From ebf514e90c21abd3d2acc352ca4b91a59a7108e2 Mon Sep 17 00:00:00 2001 From: rafal-gorecki Date: Tue, 10 Oct 2023 18:23:06 +0200 Subject: [PATCH 01/10] rafal-sugestions --- rosbot_gazebo/test/simulation_test_node.py | 62 +++++++------------ .../test/test_diff_drive_simulation.py | 12 ++-- rosbot_gazebo/test/test_mecanum_simulation.py | 16 ++--- 3 files changed, 38 insertions(+), 52 deletions(-) diff --git a/rosbot_gazebo/test/simulation_test_node.py b/rosbot_gazebo/test/simulation_test_node.py index 40a2d133..37fde0d7 100644 --- a/rosbot_gazebo/test/simulation_test_node.py +++ b/rosbot_gazebo/test/simulation_test_node.py @@ -27,34 +27,29 @@ class SimulationTestNode(Node): __test__ = False - DISTANCE_TO_LINEAR_VELOCITY_SCALE = 1.0 - DISTANCE_TO_ANGULAR_VELOCITY_SCALE = 6.0 + XY_TOLERANCE = 0.05 + YAW_TOLERANCE = 0.1 def __init__(self, name="test_node"): super().__init__(name) - self.goal_x_distance = 0.0 - self.goal_y_distance = 0.0 - self.goal_theta_angle = 0.0 - - self.velocity_x = 0.0 - self.velocity_y = 0.0 - self.velocity_theta = 0.0 + self.v_x = 0.0 + self.v_y = 0.0 + self.v_yaw = 0.0 self.goal_x_event = Event() self.goal_y_event = Event() - self.goal_theta_event = Event() + self.goal_yaw_event = Event() - def set_and_publish_destination_goal( - self, goal_x_distance, goal_y_distance, goal_yaw_angle - ): - self.goal_x_distance = goal_x_distance - self.goal_y_distance = goal_y_distance - self.goal_theta_angle = goal_yaw_angle + def clear_events(self): + self.goal_x_event.clear() + self.goal_y_event.clear() + self.goal_yaw_event.clear() - self.velocity_x = self.DISTANCE_TO_LINEAR_VELOCITY_SCALE * goal_x_distance - self.velocity_y = self.DISTANCE_TO_LINEAR_VELOCITY_SCALE * goal_y_distance - self.velocity_theta = self.DISTANCE_TO_ANGULAR_VELOCITY_SCALE * goal_yaw_angle - self.publish_cmd_vel_messages() + def set_destination_speed(self, v_x, v_y, v_yaw): + self.clear_events() + self.v_x = v_x + self.v_y = v_y + self.v_yaw = v_yaw def create_test_subscribers_and_publishers(self): self.cmd_vel_publisher = self.create_publisher(Twist, "cmd_vel", 10) @@ -72,31 +67,22 @@ def start_node_thread(self): self.timer = self.create_timer(1.0 / 10.0, self.publish_cmd_vel_messages) def odometry_callback(self, data: Odometry): - pose = data.pose.pose - q = ( - pose.orientation.x, - pose.orientation.y, - pose.orientation.z, - pose.orientation.w, - ) - roll, pitch, yaw = tf_transformations.euler_from_quaternion(q) + twist = data.twist.twist - print(f"x: {pose.position.x}, y: {pose.position.y}, yaw: {yaw}") - print(f"roll: {roll}, pitch: {pitch}, yaw: {yaw}") - - if pose.position.x > self.goal_x_distance and self.goal_x_distance != 0.0: + if abs(twist.linear.x - self.v_x) < self.XY_TOLERANCE: self.goal_x_event.set() - if pose.position.y > self.goal_y_distance and self.goal_y_distance != 0.0: + if abs(twist.linear.y - self.v_y) < self.XY_TOLERANCE: self.goal_y_event.set() - if yaw > self.goal_theta_angle and self.goal_theta_angle != 0.0: - self.goal_theta_event.set() + if abs(twist.angular.z - self.v_yaw) < self.YAW_TOLERANCE: + self.goal_yaw_event.set() def publish_cmd_vel_messages(self): twist_msg = Twist() - twist_msg.linear.x = self.velocity_x - twist_msg.linear.y = self.velocity_y - twist_msg.angular.z = self.velocity_theta + + twist_msg.linear.x = self.v_x + twist_msg.linear.y = self.v_y + twist_msg.angular.z = self.v_yaw self.cmd_vel_publisher.publish(twist_msg) diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index 53fd472e..acf127ac 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -42,7 +42,7 @@ def generate_test_description(): ) ), launch_arguments={ - "headless": "True", + "headless": "False", }.items(), ) @@ -57,13 +57,13 @@ def test_diff_drive_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - node.set_and_publish_destination_goal(0.6, 0.0, 0.0) + node.set_destination_speed(0.2, 0.0, 0.0) msgs_received_flag = node.goal_x_event.wait(timeout=60.0) - assert msgs_received_flag, "ROSbot can't move by x axis!" + assert msgs_received_flag, "ROSbot does not move properly in x direction!" - node.set_and_publish_destination_goal(0.0, 0.0, 1.57) - msgs_received_flag = node.goal_theta_event.wait(timeout=60.0) - assert msgs_received_flag, "ROSbot can't rotate!" + node.set_destination_speed(0.0, 0.0, 1.57) + msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) + assert msgs_received_flag, "ROSbot does not rotate properly!" finally: # The pytest cannot kill properly the Gazebo Ignition's tasks what blocks launching diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index ee46f652..bf3ce4e6 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -43,7 +43,7 @@ def generate_test_description(): ), launch_arguments={ "mecanum": "True", - "headless": "True", + "headless": "False", }.items(), ) @@ -58,17 +58,17 @@ def test_mecanum_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - node.set_and_publish_destination_goal(0.6, 0.0, 0.0) + node.set_destination_speed(0.2, 0.0, 0.0) msgs_received_flag = node.goal_x_event.wait(timeout=60.0) - assert msgs_received_flag, "ROSbot can't move by x axis!" + assert msgs_received_flag, "ROSbot does not move properly in x direction!" - node.set_and_publish_destination_goal(0.0, 0.6, 0.0) + node.set_destination_speed(0.0, 0.2, 0.0) msgs_received_flag = node.goal_y_event.wait(timeout=60.0) - assert msgs_received_flag, "ROSbot can't move by y axis!" + assert msgs_received_flag, "ROSbot does not move properly in y direction!" - node.set_and_publish_destination_goal(0.0, 0.0, 1.57) - msgs_received_flag = node.goal_theta_event.wait(timeout=60.0) - assert msgs_received_flag, "ROSbot can't rotate!" + node.set_destination_speed(0.0, 0.0, 1.00) + msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) + assert msgs_received_flag, "ROSbot does not rotate properly!" finally: # The pytest cannot kill properly the Gazebo Ignition's tasks what blocks launching From 9dde480c75098752d6b7ade8b2cde0ee3b9cf33a Mon Sep 17 00:00:00 2001 From: Jakub Delicat Date: Wed, 11 Oct 2023 09:56:44 +0200 Subject: [PATCH 02/10] changed max vel wheel joint | changed testing velocities to the maximum velocity Signed-off-by: Jakub Delicat --- rosbot_bringup/config/ekf.yaml | 4 ++-- rosbot_description/urdf/wheel.urdf.xacro | 2 +- rosbot_gazebo/test/simulation_test_node.py | 1 - rosbot_gazebo/test/test_diff_drive_simulation.py | 6 ++++-- rosbot_gazebo/test/test_mecanum_simulation.py | 8 +++++--- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/rosbot_bringup/config/ekf.yaml b/rosbot_bringup/config/ekf.yaml index 5a22e85d..e042a542 100644 --- a/rosbot_bringup/config/ekf.yaml +++ b/rosbot_bringup/config/ekf.yaml @@ -36,7 +36,7 @@ ekf_filter_node: imu0_differential: false imu0_relative: true imu0_remove_gravitational_acceleration: true - + # [ADVANCED] The process noise covariance matrix can be difficult to tune, and can vary for each application, so it is # exposed as a configuration parameter. This matrix represents the noise we add to the total error after each # prediction step. The better the omnidirectional motion model matches your system, the smaller these values can be. @@ -73,7 +73,7 @@ ekf_filter_node: 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 1e-8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, diff --git a/rosbot_description/urdf/wheel.urdf.xacro b/rosbot_description/urdf/wheel.urdf.xacro index ecfe572d..167468d0 100644 --- a/rosbot_description/urdf/wheel.urdf.xacro +++ b/rosbot_description/urdf/wheel.urdf.xacro @@ -63,7 +63,7 @@ - + diff --git a/rosbot_gazebo/test/simulation_test_node.py b/rosbot_gazebo/test/simulation_test_node.py index 37fde0d7..01a1f0bd 100644 --- a/rosbot_gazebo/test/simulation_test_node.py +++ b/rosbot_gazebo/test/simulation_test_node.py @@ -22,7 +22,6 @@ from geometry_msgs.msg import Twist from nav_msgs.msg import Odometry -import tf_transformations class SimulationTestNode(Node): diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index acf127ac..10f97d91 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -57,11 +57,13 @@ def test_diff_drive_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - node.set_destination_speed(0.2, 0.0, 0.0) + # 0.9 m/s and 3.0 rad/s are controller's limits defined in + # rosbot_controller/config/diff_drive_controller.yaml + node.set_destination_speed(0.9, 0.0, 0.0) msgs_received_flag = node.goal_x_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not move properly in x direction!" - node.set_destination_speed(0.0, 0.0, 1.57) + node.set_destination_speed(0.0, 0.0, 3.0) msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not rotate properly!" diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index bf3ce4e6..9cc3d7f7 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -58,15 +58,17 @@ def test_mecanum_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - node.set_destination_speed(0.2, 0.0, 0.0) + # 0.9 m/s and 3.0 rad/s are controller's limits defined in + # rosbot_controller/config/mecanum_drive_controller.yaml + node.set_destination_speed(0.9, 0.0, 0.0) msgs_received_flag = node.goal_x_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not move properly in x direction!" - node.set_destination_speed(0.0, 0.2, 0.0) + node.set_destination_speed(0.0, 0.9, 0.0) msgs_received_flag = node.goal_y_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not move properly in y direction!" - node.set_destination_speed(0.0, 0.0, 1.00) + node.set_destination_speed(0.0, 0.0, 3.0) msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not rotate properly!" From 1d9e7dfdd9fa1efd66933b08e2c9579cc0c9f6f0 Mon Sep 17 00:00:00 2001 From: Jakub Delicat Date: Wed, 11 Oct 2023 09:57:30 +0200 Subject: [PATCH 03/10] changed to headless mode Signed-off-by: Jakub Delicat --- rosbot_gazebo/test/test_diff_drive_simulation.py | 2 +- rosbot_gazebo/test/test_mecanum_simulation.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index 10f97d91..58c8a0c2 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -42,7 +42,7 @@ def generate_test_description(): ) ), launch_arguments={ - "headless": "False", + "headless": "True", }.items(), ) diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index 9cc3d7f7..d1d43b60 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -43,7 +43,7 @@ def generate_test_description(): ), launch_arguments={ "mecanum": "True", - "headless": "False", + "headless": "True", }.items(), ) From 3b441ae50b4aa9e426e272f8d1744b03bbded34a Mon Sep 17 00:00:00 2001 From: Jakub Delicat Date: Wed, 11 Oct 2023 10:45:55 +0200 Subject: [PATCH 04/10] changed odom topic to tf Signed-off-by: Jakub Delicat --- rosbot_bringup/test/bringup_test_node.py | 28 +++++++++++++------ rosbot_bringup/test/test_diff_drive_ekf.py | 4 +-- rosbot_bringup/test/test_mecanum_ekf.py | 5 ++-- rosbot_gazebo/test/simulation_test_node.py | 22 ++++++++++++++- .../test/test_diff_drive_simulation.py | 5 ++++ rosbot_gazebo/test/test_mecanum_simulation.py | 5 ++++ 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/rosbot_bringup/test/bringup_test_node.py b/rosbot_bringup/test/bringup_test_node.py index 6da192ad..d40cb4a1 100644 --- a/rosbot_bringup/test/bringup_test_node.py +++ b/rosbot_bringup/test/bringup_test_node.py @@ -21,7 +21,9 @@ from rclpy.node import Node from sensor_msgs.msg import JointState, Imu -from nav_msgs.msg import Odometry +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener class BringupTestNode(Node): @@ -31,7 +33,7 @@ class BringupTestNode(Node): def __init__(self, name="test_node"): super().__init__(name) - self.odom_msg_event = Event() + self.odom_tf_event = Event() def create_test_subscribers_and_publishers(self): self.imu_publisher = self.create_publisher(Imu, "_imu/data_raw", 10) @@ -40,26 +42,34 @@ def create_test_subscribers_and_publishers(self): JointState, "_motors_response", 10 ) - self.odom_sub = self.create_subscription( - Odometry, "/odometry/filtered", self.odometry_callback, 10 - ) + self.tf_buffer = Buffer() + self.tf_listener = TransformListener(self.tf_buffer, self) + self.timer = None + def lookup_transform_odom(self): + try: + self.tf_buffer.lookup_transform("odom", "base_link", rclpy.time.Time()) + self.odom_tf_event.set() + except TransformException as ex: + self.get_logger().error(f"Could not transform odom to base_link: {ex}") + def start_node_thread(self): self.ros_spin_thread = Thread( target=lambda node: rclpy.spin(node), args=(self,) ) self.ros_spin_thread.start() - def odometry_callback(self, data): - self.odom_msg_event.set() - def start_publishing_fake_hardware(self): self.timer = self.create_timer( 1.0 / self.ROSBOT_HARDWARE_PUBLISHERS_RATE, - self.publish_fake_hardware_messages, + self.timer_callback, ) + def timer_callback(self): + self.publish_fake_hardware_messages() + self.lookup_transform_odom() + def publish_fake_hardware_messages(self): imu_msg = Imu() imu_msg.header.stamp = self.get_clock().now().to_msg() diff --git a/rosbot_bringup/test/test_diff_drive_ekf.py b/rosbot_bringup/test/test_diff_drive_ekf.py index 3c0a6fc4..aef6d8e7 100644 --- a/rosbot_bringup/test/test_diff_drive_ekf.py +++ b/rosbot_bringup/test/test_diff_drive_ekf.py @@ -58,10 +58,10 @@ def test_bringup_startup_success(): node.start_publishing_fake_hardware() node.start_node_thread() - msgs_received_flag = node.odom_msg_event.wait(timeout=10.0) + msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) assert ( msgs_received_flag - ), "Expected Odom message but it was not received. Check robot_localization!" + ), "Expected odom to base_link tf but it was not received. Check robot_localization!" finally: rclpy.shutdown() diff --git a/rosbot_bringup/test/test_mecanum_ekf.py b/rosbot_bringup/test/test_mecanum_ekf.py index 584c4a34..ab473e08 100644 --- a/rosbot_bringup/test/test_mecanum_ekf.py +++ b/rosbot_bringup/test/test_mecanum_ekf.py @@ -58,9 +58,10 @@ def test_bringup_startup_success(): node.start_publishing_fake_hardware() node.start_node_thread() - msgs_received_flag = node.odom_msg_event.wait(timeout=10.0) + msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) assert ( msgs_received_flag - ), "Expected Odom message but it was not received. Check robot_localization!" + ), "Expected odom to base_link tf but it was not received. Check robot_localization!" + finally: rclpy.shutdown() diff --git a/rosbot_gazebo/test/simulation_test_node.py b/rosbot_gazebo/test/simulation_test_node.py index 01a1f0bd..58561597 100644 --- a/rosbot_gazebo/test/simulation_test_node.py +++ b/rosbot_gazebo/test/simulation_test_node.py @@ -23,6 +23,10 @@ from geometry_msgs.msg import Twist from nav_msgs.msg import Odometry +from tf2_ros import TransformException +from tf2_ros.buffer import Buffer +from tf2_ros.transform_listener import TransformListener + class SimulationTestNode(Node): __test__ = False @@ -38,6 +42,7 @@ def __init__(self, name="test_node"): self.goal_x_event = Event() self.goal_y_event = Event() self.goal_yaw_event = Event() + self.odom_tf_event = Event() def clear_events(self): self.goal_x_event.clear() @@ -56,6 +61,10 @@ def create_test_subscribers_and_publishers(self): self.odom_sub = self.create_subscription( Odometry, "/odometry/filtered", self.odometry_callback, 10 ) + + self.tf_buffer = Buffer() + self.tf_listener = TransformListener(self.tf_buffer, self) + self.timer = None def start_node_thread(self): @@ -63,7 +72,7 @@ def start_node_thread(self): target=lambda node: rclpy.spin(node), args=(self,) ) self.ros_spin_thread.start() - self.timer = self.create_timer(1.0 / 10.0, self.publish_cmd_vel_messages) + self.timer = self.create_timer(1.0 / 10.0, self.timer_callback) def odometry_callback(self, data: Odometry): twist = data.twist.twist @@ -77,6 +86,17 @@ def odometry_callback(self, data: Odometry): if abs(twist.angular.z - self.v_yaw) < self.YAW_TOLERANCE: self.goal_yaw_event.set() + def lookup_transform_odom(self): + try: + self.tf_buffer.lookup_transform("odom", "base_link", rclpy.time.Time()) + self.odom_tf_event.set() + except TransformException as ex: + self.get_logger().error(f"Could not transform odom to base_link: {ex}") + + def timer_callback(self): + self.publish_cmd_vel_messages() + self.lookup_transform_odom() + def publish_cmd_vel_messages(self): twist_msg = Twist() diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index 58c8a0c2..9deea744 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -57,6 +57,11 @@ def test_diff_drive_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() + msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) + assert ( + msgs_received_flag + ), "Expected odom to base_link tf but it was not received. Check robot_localization!" + # 0.9 m/s and 3.0 rad/s are controller's limits defined in # rosbot_controller/config/diff_drive_controller.yaml node.set_destination_speed(0.9, 0.0, 0.0) diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index d1d43b60..8162352a 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -58,6 +58,11 @@ def test_mecanum_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() + msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) + assert ( + msgs_received_flag + ), "Expected odom to base_link tf but it was not received. Check robot_localization!" + # 0.9 m/s and 3.0 rad/s are controller's limits defined in # rosbot_controller/config/mecanum_drive_controller.yaml node.set_destination_speed(0.9, 0.0, 0.0) From e109f9e54f9df62e72153fbc5510e8f00f26b6ce Mon Sep 17 00:00:00 2001 From: Jakub Delicat Date: Wed, 11 Oct 2023 11:00:37 +0200 Subject: [PATCH 05/10] changed rosbot_gazebo tf timeout Signed-off-by: Jakub Delicat --- rosbot_gazebo/test/test_diff_drive_simulation.py | 2 +- rosbot_gazebo/test/test_mecanum_simulation.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index 9deea744..318587eb 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -57,7 +57,7 @@ def test_diff_drive_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) + msgs_received_flag = node.odom_tf_event.wait(timeout=60.0) assert ( msgs_received_flag ), "Expected odom to base_link tf but it was not received. Check robot_localization!" diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index 8162352a..3db98f6a 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -58,7 +58,7 @@ def test_mecanum_simulation(): node.create_test_subscribers_and_publishers() node.start_node_thread() - msgs_received_flag = node.odom_tf_event.wait(timeout=10.0) + msgs_received_flag = node.odom_tf_event.wait(timeout=60.0) assert ( msgs_received_flag ), "Expected odom to base_link tf but it was not received. Check robot_localization!" From 6ef71e84f569aa69b570e75e81caab4d62158c4f Mon Sep 17 00:00:00 2001 From: action-bot Date: Wed, 11 Oct 2023 09:20:06 +0000 Subject: [PATCH 06/10] Update changelog --- rosbot/CHANGELOG.rst | 6 ++++++ rosbot_bringup/CHANGELOG.rst | 8 ++++++++ rosbot_controller/CHANGELOG.rst | 6 ++++++ rosbot_description/CHANGELOG.rst | 8 ++++++++ rosbot_gazebo/CHANGELOG.rst | 10 ++++++++++ 5 files changed, 38 insertions(+) diff --git a/rosbot/CHANGELOG.rst b/rosbot/CHANGELOG.rst index 7dee547e..1b224dcd 100644 --- a/rosbot/CHANGELOG.rst +++ b/rosbot/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package rosbot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo +* Merge branch 'humble' into test-gazebo +* Contributors: Jakub Delicat, rafal-gorecki + 0.8.4 (2023-09-21) ------------------ * Merge branch 'humble' into test-ekf diff --git a/rosbot_bringup/CHANGELOG.rst b/rosbot_bringup/CHANGELOG.rst index b6a0216a..31b6133e 100644 --- a/rosbot_bringup/CHANGELOG.rst +++ b/rosbot_bringup/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package rosbot_bringup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Merge pull request `#70 `_ from husarion/test-gazebo + Test gazebo +* Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo +* Merge branch 'humble' into test-gazebo +* Contributors: Jakub Delicat, rafal-gorecki + 0.8.4 (2023-09-21) ------------------ * Merge pull request `#69 `_ from husarion/test-ekf diff --git a/rosbot_controller/CHANGELOG.rst b/rosbot_controller/CHANGELOG.rst index 459acb73..ace09f2c 100644 --- a/rosbot_controller/CHANGELOG.rst +++ b/rosbot_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package rosbot_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo +* Merge branch 'humble' into test-gazebo +* Contributors: Jakub Delicat, rafal-gorecki + 0.8.4 (2023-09-21) ------------------ * Merge pull request `#69 `_ from husarion/test-ekf diff --git a/rosbot_description/CHANGELOG.rst b/rosbot_description/CHANGELOG.rst index 943c9da9..07406828 100644 --- a/rosbot_description/CHANGELOG.rst +++ b/rosbot_description/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package rosbot_description ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Merge pull request `#70 `_ from husarion/test-gazebo + Test gazebo +* Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo +* Merge branch 'humble' into test-gazebo +* Contributors: Jakub Delicat, rafal-gorecki + 0.8.4 (2023-09-21) ------------------ * Merge branch 'humble' into test-ekf diff --git a/rosbot_gazebo/CHANGELOG.rst b/rosbot_gazebo/CHANGELOG.rst index dfc88957..decd7e17 100644 --- a/rosbot_gazebo/CHANGELOG.rst +++ b/rosbot_gazebo/CHANGELOG.rst @@ -2,6 +2,16 @@ Changelog for package rosbot_gazebo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Merge pull request `#70 `_ from husarion/test-gazebo + Test gazebo +* Merge pull request `#74 `_ from husarion/rafal-suggestions + rafal-sugestions +* Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo +* Merge branch 'humble' into test-gazebo +* Contributors: Jakub Delicat, rafal-gorecki + 0.8.4 (2023-09-21) ------------------ * Merge branch 'humble' into test-ekf From 7c40386cf31ebd27efd5e612785a9a3743f098af Mon Sep 17 00:00:00 2001 From: action-bot Date: Wed, 11 Oct 2023 09:20:07 +0000 Subject: [PATCH 07/10] 0.8.5 --- rosbot/CHANGELOG.rst | 4 ++-- rosbot/package.xml | 2 +- rosbot_bringup/CHANGELOG.rst | 4 ++-- rosbot_bringup/package.xml | 2 +- rosbot_controller/CHANGELOG.rst | 4 ++-- rosbot_controller/package.xml | 2 +- rosbot_description/CHANGELOG.rst | 4 ++-- rosbot_description/package.xml | 2 +- rosbot_gazebo/CHANGELOG.rst | 4 ++-- rosbot_gazebo/package.xml | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/rosbot/CHANGELOG.rst b/rosbot/CHANGELOG.rst index 1b224dcd..35237bd1 100644 --- a/rosbot/CHANGELOG.rst +++ b/rosbot/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.8.5 (2023-10-11) +------------------ * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo * Merge branch 'humble' into test-gazebo * Contributors: Jakub Delicat, rafal-gorecki diff --git a/rosbot/package.xml b/rosbot/package.xml index 884072c4..8047af85 100644 --- a/rosbot/package.xml +++ b/rosbot/package.xml @@ -2,7 +2,7 @@ rosbot - 0.8.4 + 0.8.5 Meta package that contains all packages of Rosbot 2 2R PRO Apache License 2.0 diff --git a/rosbot_bringup/CHANGELOG.rst b/rosbot_bringup/CHANGELOG.rst index 31b6133e..3ef10b79 100644 --- a/rosbot_bringup/CHANGELOG.rst +++ b/rosbot_bringup/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_bringup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.8.5 (2023-10-11) +------------------ * Merge pull request `#70 `_ from husarion/test-gazebo Test gazebo * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo diff --git a/rosbot_bringup/package.xml b/rosbot_bringup/package.xml index 3dc3f53e..89e012f3 100644 --- a/rosbot_bringup/package.xml +++ b/rosbot_bringup/package.xml @@ -2,7 +2,7 @@ rosbot_bringup - 0.8.4 + 0.8.5 ROSbot 2, 2R, PRO bringup package Apache License 2.0 diff --git a/rosbot_controller/CHANGELOG.rst b/rosbot_controller/CHANGELOG.rst index ace09f2c..093655a7 100644 --- a/rosbot_controller/CHANGELOG.rst +++ b/rosbot_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.8.5 (2023-10-11) +------------------ * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo * Merge branch 'humble' into test-gazebo * Contributors: Jakub Delicat, rafal-gorecki diff --git a/rosbot_controller/package.xml b/rosbot_controller/package.xml index f63fade1..60eba10d 100644 --- a/rosbot_controller/package.xml +++ b/rosbot_controller/package.xml @@ -2,7 +2,7 @@ rosbot_controller - 0.8.4 + 0.8.5 Hardware configuration for ROSbot 2, 2R, PRO Apache License 2.0 diff --git a/rosbot_description/CHANGELOG.rst b/rosbot_description/CHANGELOG.rst index 07406828..9bad716e 100644 --- a/rosbot_description/CHANGELOG.rst +++ b/rosbot_description/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_description ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.8.5 (2023-10-11) +------------------ * Merge pull request `#70 `_ from husarion/test-gazebo Test gazebo * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo diff --git a/rosbot_description/package.xml b/rosbot_description/package.xml index 61d5a8dc..2051343e 100644 --- a/rosbot_description/package.xml +++ b/rosbot_description/package.xml @@ -2,7 +2,7 @@ rosbot_description - 0.8.4 + 0.8.5 ROSbot 2, 2R, PRO description package Apache License 2.0 diff --git a/rosbot_gazebo/CHANGELOG.rst b/rosbot_gazebo/CHANGELOG.rst index decd7e17..79243813 100644 --- a/rosbot_gazebo/CHANGELOG.rst +++ b/rosbot_gazebo/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_gazebo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.8.5 (2023-10-11) +------------------ * Merge pull request `#70 `_ from husarion/test-gazebo Test gazebo * Merge pull request `#74 `_ from husarion/rafal-suggestions diff --git a/rosbot_gazebo/package.xml b/rosbot_gazebo/package.xml index 1628bf1b..6a18559c 100644 --- a/rosbot_gazebo/package.xml +++ b/rosbot_gazebo/package.xml @@ -2,7 +2,7 @@ rosbot_gazebo - 0.8.4 + 0.8.5 Gazebo Ignition simulation for ROSbot 2, 2R, PRO Apache License 2.0 From 186d98c54b417f76564534c070fb91e2303420ab Mon Sep 17 00:00:00 2001 From: Jakub Delicat <109142865+delihus@users.noreply.github.com> Date: Mon, 16 Oct 2023 07:59:52 +0200 Subject: [PATCH 08/10] Test gazebo scan (#71) * added scan test Signed-off-by: Jakub Delicat * updated gazebo scan test Signed-off-by: Jakub Delicat * Added tests to readme Signed-off-by: Jakub Delicat * Update rosbot_gazebo/test/simulation_test_node.py Co-authored-by: rafal-gorecki <126687345+rafal-gorecki@users.noreply.github.com> * Update README.md Co-authored-by: rafal-gorecki <126687345+rafal-gorecki@users.noreply.github.com> --------- Signed-off-by: Jakub Delicat Co-authored-by: rafal-gorecki <126687345+rafal-gorecki@users.noreply.github.com> --- README.md | 21 +++++++++++++++++++ rosbot_gazebo/test/simulation_test_node.py | 9 ++++++++ .../test/test_diff_drive_simulation.py | 3 +++ rosbot_gazebo/test/test_mecanum_simulation.py | 3 +++ 4 files changed, 36 insertions(+) diff --git a/README.md b/README.md index 80927f12..b9ed442e 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,27 @@ source install/setup.bash ros2 launch rosbot_gazebo simulation.launch.py ``` +## Testing package + +### Industrial CI +``` +colcon test +``` + +> [!NOTE] +> Command `colcon test` does not build the code. Remember to build your code after changes. + +If tests finish with errors print logs: +``` +colcon test-result --verbose +``` + +### Format python code with [Black](https://github.com/psf/black) +``` +cd src/ +black rosbot* +``` + ## Demo Bellow you can find demos with ROSbots: - in [rosbot-docker](https://github.com/husarion/rosbot-docker/tree/ros2) you will find a simple example how to drive ROSbot with `teleop_twist_keyboard`. diff --git a/rosbot_gazebo/test/simulation_test_node.py b/rosbot_gazebo/test/simulation_test_node.py index 58561597..7fb5a4ac 100644 --- a/rosbot_gazebo/test/simulation_test_node.py +++ b/rosbot_gazebo/test/simulation_test_node.py @@ -22,6 +22,7 @@ from geometry_msgs.msg import Twist from nav_msgs.msg import Odometry +from sensor_msgs.msg import LaserScan from tf2_ros import TransformException from tf2_ros.buffer import Buffer @@ -43,6 +44,7 @@ def __init__(self, name="test_node"): self.goal_y_event = Event() self.goal_yaw_event = Event() self.odom_tf_event = Event() + self.scan_event = Event() def clear_events(self): self.goal_x_event.clear() @@ -62,6 +64,9 @@ def create_test_subscribers_and_publishers(self): Odometry, "/odometry/filtered", self.odometry_callback, 10 ) + self.scan_sub = self.create_subscription( + LaserScan, "/scan", self.scan_callback, 10 + ) self.tf_buffer = Buffer() self.tf_listener = TransformListener(self.tf_buffer, self) @@ -97,6 +102,10 @@ def timer_callback(self): self.publish_cmd_vel_messages() self.lookup_transform_odom() + def scan_callback(self, data: LaserScan): + if data.ranges: + self.scan_event.set() + def publish_cmd_vel_messages(self): twist_msg = Twist() diff --git a/rosbot_gazebo/test/test_diff_drive_simulation.py b/rosbot_gazebo/test/test_diff_drive_simulation.py index 318587eb..25dc7ed7 100644 --- a/rosbot_gazebo/test/test_diff_drive_simulation.py +++ b/rosbot_gazebo/test/test_diff_drive_simulation.py @@ -72,6 +72,9 @@ def test_diff_drive_simulation(): msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not rotate properly!" + msgs_received_flag = node.scan_event.wait(timeout=60.0) + assert msgs_received_flag, "ROSbot's lidar does not work properly!" + finally: # The pytest cannot kill properly the Gazebo Ignition's tasks what blocks launching # several tests in a row. diff --git a/rosbot_gazebo/test/test_mecanum_simulation.py b/rosbot_gazebo/test/test_mecanum_simulation.py index 3db98f6a..f4c425ea 100644 --- a/rosbot_gazebo/test/test_mecanum_simulation.py +++ b/rosbot_gazebo/test/test_mecanum_simulation.py @@ -77,6 +77,9 @@ def test_mecanum_simulation(): msgs_received_flag = node.goal_yaw_event.wait(timeout=60.0) assert msgs_received_flag, "ROSbot does not rotate properly!" + msgs_received_flag = node.scan_event.wait(timeout=60.0) + assert msgs_received_flag, "ROSbot's lidar does not work properly!" + finally: # The pytest cannot kill properly the Gazebo Ignition's tasks what blocks launching # several tests in a row. From 437a7fc73d7c16ce2d39de21167f19c282b6f13f Mon Sep 17 00:00:00 2001 From: action-bot Date: Mon, 16 Oct 2023 06:00:38 +0000 Subject: [PATCH 09/10] Update changelog --- rosbot/CHANGELOG.rst | 3 +++ rosbot_bringup/CHANGELOG.rst | 3 +++ rosbot_controller/CHANGELOG.rst | 3 +++ rosbot_description/CHANGELOG.rst | 3 +++ rosbot_gazebo/CHANGELOG.rst | 3 +++ 5 files changed, 15 insertions(+) diff --git a/rosbot/CHANGELOG.rst b/rosbot/CHANGELOG.rst index 35237bd1..501f4b4b 100644 --- a/rosbot/CHANGELOG.rst +++ b/rosbot/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rosbot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 0.8.5 (2023-10-11) ------------------ * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo diff --git a/rosbot_bringup/CHANGELOG.rst b/rosbot_bringup/CHANGELOG.rst index 3ef10b79..ad4bffc8 100644 --- a/rosbot_bringup/CHANGELOG.rst +++ b/rosbot_bringup/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rosbot_bringup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 0.8.5 (2023-10-11) ------------------ * Merge pull request `#70 `_ from husarion/test-gazebo diff --git a/rosbot_controller/CHANGELOG.rst b/rosbot_controller/CHANGELOG.rst index 093655a7..d43d4be2 100644 --- a/rosbot_controller/CHANGELOG.rst +++ b/rosbot_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rosbot_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 0.8.5 (2023-10-11) ------------------ * Merge remote-tracking branch 'origin/test-gazebo' into test-gazebo diff --git a/rosbot_description/CHANGELOG.rst b/rosbot_description/CHANGELOG.rst index 9bad716e..4fa990c4 100644 --- a/rosbot_description/CHANGELOG.rst +++ b/rosbot_description/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rosbot_description ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 0.8.5 (2023-10-11) ------------------ * Merge pull request `#70 `_ from husarion/test-gazebo diff --git a/rosbot_gazebo/CHANGELOG.rst b/rosbot_gazebo/CHANGELOG.rst index 79243813..b079dc4b 100644 --- a/rosbot_gazebo/CHANGELOG.rst +++ b/rosbot_gazebo/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rosbot_gazebo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 0.8.5 (2023-10-11) ------------------ * Merge pull request `#70 `_ from husarion/test-gazebo From c92fb130a6b8e576d8e4a4d6e97f9fd11908d01b Mon Sep 17 00:00:00 2001 From: action-bot Date: Mon, 16 Oct 2023 06:00:38 +0000 Subject: [PATCH 10/10] 0.9.0 --- rosbot/CHANGELOG.rst | 4 ++-- rosbot/package.xml | 2 +- rosbot_bringup/CHANGELOG.rst | 4 ++-- rosbot_bringup/package.xml | 2 +- rosbot_controller/CHANGELOG.rst | 4 ++-- rosbot_controller/package.xml | 2 +- rosbot_description/CHANGELOG.rst | 4 ++-- rosbot_description/package.xml | 2 +- rosbot_gazebo/CHANGELOG.rst | 4 ++-- rosbot_gazebo/package.xml | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/rosbot/CHANGELOG.rst b/rosbot/CHANGELOG.rst index 501f4b4b..73310264 100644 --- a/rosbot/CHANGELOG.rst +++ b/rosbot/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.9.0 (2023-10-16) +------------------ 0.8.5 (2023-10-11) ------------------ diff --git a/rosbot/package.xml b/rosbot/package.xml index 8047af85..918b90e2 100644 --- a/rosbot/package.xml +++ b/rosbot/package.xml @@ -2,7 +2,7 @@ rosbot - 0.8.5 + 0.9.0 Meta package that contains all packages of Rosbot 2 2R PRO Apache License 2.0 diff --git a/rosbot_bringup/CHANGELOG.rst b/rosbot_bringup/CHANGELOG.rst index ad4bffc8..de297c5b 100644 --- a/rosbot_bringup/CHANGELOG.rst +++ b/rosbot_bringup/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_bringup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.9.0 (2023-10-16) +------------------ 0.8.5 (2023-10-11) ------------------ diff --git a/rosbot_bringup/package.xml b/rosbot_bringup/package.xml index 89e012f3..7a052e0b 100644 --- a/rosbot_bringup/package.xml +++ b/rosbot_bringup/package.xml @@ -2,7 +2,7 @@ rosbot_bringup - 0.8.5 + 0.9.0 ROSbot 2, 2R, PRO bringup package Apache License 2.0 diff --git a/rosbot_controller/CHANGELOG.rst b/rosbot_controller/CHANGELOG.rst index d43d4be2..654c6122 100644 --- a/rosbot_controller/CHANGELOG.rst +++ b/rosbot_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.9.0 (2023-10-16) +------------------ 0.8.5 (2023-10-11) ------------------ diff --git a/rosbot_controller/package.xml b/rosbot_controller/package.xml index 60eba10d..218e6df7 100644 --- a/rosbot_controller/package.xml +++ b/rosbot_controller/package.xml @@ -2,7 +2,7 @@ rosbot_controller - 0.8.5 + 0.9.0 Hardware configuration for ROSbot 2, 2R, PRO Apache License 2.0 diff --git a/rosbot_description/CHANGELOG.rst b/rosbot_description/CHANGELOG.rst index 4fa990c4..76ee75fe 100644 --- a/rosbot_description/CHANGELOG.rst +++ b/rosbot_description/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_description ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.9.0 (2023-10-16) +------------------ 0.8.5 (2023-10-11) ------------------ diff --git a/rosbot_description/package.xml b/rosbot_description/package.xml index 2051343e..4c0cbfa8 100644 --- a/rosbot_description/package.xml +++ b/rosbot_description/package.xml @@ -2,7 +2,7 @@ rosbot_description - 0.8.5 + 0.9.0 ROSbot 2, 2R, PRO description package Apache License 2.0 diff --git a/rosbot_gazebo/CHANGELOG.rst b/rosbot_gazebo/CHANGELOG.rst index b079dc4b..7c19977d 100644 --- a/rosbot_gazebo/CHANGELOG.rst +++ b/rosbot_gazebo/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rosbot_gazebo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +0.9.0 (2023-10-16) +------------------ 0.8.5 (2023-10-11) ------------------ diff --git a/rosbot_gazebo/package.xml b/rosbot_gazebo/package.xml index 6a18559c..307c4bd9 100644 --- a/rosbot_gazebo/package.xml +++ b/rosbot_gazebo/package.xml @@ -2,7 +2,7 @@ rosbot_gazebo - 0.8.5 + 0.9.0 Gazebo Ignition simulation for ROSbot 2, 2R, PRO Apache License 2.0