From dadaeddbb9f1c0161eb4898a432e8f4e035e277f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 10 Dec 2024 20:58:34 +0100 Subject: [PATCH 1/3] Use humble branch for rt tools (#657) --- ros2_control_demos.humble.repos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ros2_control_demos.humble.repos b/ros2_control_demos.humble.repos index 235d4ba4b..0293269ad 100644 --- a/ros2_control_demos.humble.repos +++ b/ros2_control_demos.humble.repos @@ -6,7 +6,7 @@ repositories: realtime_tools: type: git url: https://github.com/ros-controls/realtime_tools.git - version: master + version: humble ros2_control: type: git url: https://github.com/ros-controls/ros2_control.git From 01a9261abfa0ed44ef2edb1c76eb0edbeefa9f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 15 Dec 2024 13:19:26 +0100 Subject: [PATCH 2/3] Use class methods for rclpy.init/shutdown (#664) --- example_1/test/test_rrbot_launch.py | 23 +++++++++++------ .../test/test_rrbot_launch_cli_direct.py | 12 ++++++--- example_10/test/test_rrbot_launch.py | 12 ++++++--- example_11/test/test_carlikebot_launch.py | 12 ++++++--- example_12/test/test_rrbot_launch.py | 25 +++++++++++++------ example_13/test/test_three_robots_launch.py | 12 ++++++--- ...ck_sensors_for_position_feedback_launch.py | 12 ++++++--- .../test_multi_controller_manager_launch.py | 12 ++++++--- .../test/test_rrbot_namespace_launch.py | 12 ++++++--- example_2/test/test_diffbot_launch.py | 12 ++++++--- ...est_rrbot_system_multi_interface_launch.py | 12 ++++++--- .../test_rrbot_system_with_sensor_launch.py | 12 ++++++--- ...rbot_system_with_external_sensor_launch.py | 12 ++++++--- .../test_rrbot_modular_actuators_launch.py | 12 ++++++--- .../test/test_r6bot_controller_launch.py | 12 ++++++--- ...ansmissions_system_position_only_launch.py | 12 ++++++--- example_9/test/test_rrbot_launch.py | 12 ++++++--- 17 files changed, 153 insertions(+), 75 deletions(-) diff --git a/example_1/test/test_rrbot_launch.py b/example_1/test/test_rrbot_launch.py index ecc66ecf7..30fa7467e 100644 --- a/example_1/test/test_rrbot_launch.py +++ b/example_1/test/test_rrbot_launch.py @@ -41,7 +41,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -68,14 +67,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") @@ -91,14 +95,19 @@ def test_check_if_msgs_published(self): class TestFixtureCLI(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_main(self, proc_output): diff --git a/example_1/test/test_rrbot_launch_cli_direct.py b/example_1/test/test_rrbot_launch_cli_direct.py index cab04cfa8..0aa14fabb 100644 --- a/example_1/test/test_rrbot_launch_cli_direct.py +++ b/example_1/test/test_rrbot_launch_cli_direct.py @@ -41,7 +41,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import check_controllers_running @@ -62,14 +61,19 @@ def generate_test_description(): class TestFixtureCliDirect(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_main(self, proc_output): diff --git a/example_10/test/test_rrbot_launch.py b/example_10/test/test_rrbot_launch.py index 005ee36e8..e9df25da7 100644 --- a/example_10/test/test_rrbot_launch.py +++ b/example_10/test/test_rrbot_launch.py @@ -39,7 +39,6 @@ from launch_testing.actions import ReadyToTest import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -68,14 +67,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_11/test/test_carlikebot_launch.py b/example_11/test/test_carlikebot_launch.py index 5636eda21..1afb4ff33 100644 --- a/example_11/test/test_carlikebot_launch.py +++ b/example_11/test/test_carlikebot_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_12/test/test_rrbot_launch.py b/example_12/test/test_rrbot_launch.py index 5f716c906..5abbec91a 100644 --- a/example_12/test/test_rrbot_launch.py +++ b/example_12/test/test_rrbot_launch.py @@ -41,7 +41,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -68,14 +67,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") @@ -97,10 +101,9 @@ def test_check_if_msgs_published(self): # This is our second test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixtureChained(unittest.TestCase): - - def setUp(self): + @classmethod + def setUpClass(cls): rclpy.init() - self.node = Node("test_node") # Command to run the launch file command = [ "ros2", @@ -111,9 +114,15 @@ def setUp(self): # Execute the command subprocess.run(command) + @classmethod + def tearDownClass(cls): + rclpy.shutdown() + + def setUp(self): + self.node = rclpy.create_node("test_node") + def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_13/test/test_three_robots_launch.py b/example_13/test/test_three_robots_launch.py index 0937f3de6..9e0fed689 100644 --- a/example_13/test/test_three_robots_launch.py +++ b/example_13/test/test_three_robots_launch.py @@ -41,7 +41,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -68,14 +67,19 @@ def generate_test_description(): # This is our first test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_14/test/test_rrbot_modular_actuators_without_feedback_sensors_for_position_feedback_launch.py b/example_14/test/test_rrbot_modular_actuators_without_feedback_sensors_for_position_feedback_launch.py index 9f8158944..b26ee3a40 100644 --- a/example_14/test/test_rrbot_modular_actuators_without_feedback_sensors_for_position_feedback_launch.py +++ b/example_14/test/test_rrbot_modular_actuators_without_feedback_sensors_for_position_feedback_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_15/test/test_multi_controller_manager_launch.py b/example_15/test/test_multi_controller_manager_launch.py index a927fdb6d..a78cfdc78 100644 --- a/example_15/test/test_multi_controller_manager_launch.py +++ b/example_15/test/test_multi_controller_manager_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_15/test/test_rrbot_namespace_launch.py b/example_15/test/test_rrbot_namespace_launch.py index a4e5dfb97..702be9d52 100644 --- a/example_15/test/test_rrbot_namespace_launch.py +++ b/example_15/test/test_rrbot_namespace_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_2/test/test_diffbot_launch.py b/example_2/test/test_diffbot_launch.py index 5f762872b..d84de296a 100644 --- a/example_2/test/test_diffbot_launch.py +++ b/example_2/test/test_diffbot_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_3/test/test_rrbot_system_multi_interface_launch.py b/example_3/test/test_rrbot_system_multi_interface_launch.py index 8f6394df2..9b5529654 100644 --- a/example_3/test/test_rrbot_system_multi_interface_launch.py +++ b/example_3/test/test_rrbot_system_multi_interface_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_4/test/test_rrbot_system_with_sensor_launch.py b/example_4/test/test_rrbot_system_with_sensor_launch.py index d9238acf2..9e5001654 100644 --- a/example_4/test/test_rrbot_system_with_sensor_launch.py +++ b/example_4/test/test_rrbot_system_with_sensor_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_5/test/test_rrbot_system_with_external_sensor_launch.py b/example_5/test/test_rrbot_system_with_external_sensor_launch.py index cce21b560..e965d5ace 100644 --- a/example_5/test/test_rrbot_system_with_external_sensor_launch.py +++ b/example_5/test/test_rrbot_system_with_external_sensor_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_6/test/test_rrbot_modular_actuators_launch.py b/example_6/test/test_rrbot_modular_actuators_launch.py index b48389713..3e8a5e9d4 100644 --- a/example_6/test/test_rrbot_modular_actuators_launch.py +++ b/example_6/test/test_rrbot_modular_actuators_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_7/test/test_r6bot_controller_launch.py b/example_7/test/test_r6bot_controller_launch.py index 42a731020..968f789f1 100644 --- a/example_7/test/test_r6bot_controller_launch.py +++ b/example_7/test/test_r6bot_controller_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_8/test/test_rrbot_transmissions_system_position_only_launch.py b/example_8/test/test_rrbot_transmissions_system_position_only_launch.py index 96ba7d3c9..a16f4d7a7 100644 --- a/example_8/test/test_rrbot_transmissions_system_position_only_launch.py +++ b/example_8/test/test_rrbot_transmissions_system_position_only_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") diff --git a/example_9/test/test_rrbot_launch.py b/example_9/test/test_rrbot_launch.py index fb2211e1e..6817f0e03 100644 --- a/example_9/test/test_rrbot_launch.py +++ b/example_9/test/test_rrbot_launch.py @@ -40,7 +40,6 @@ # import launch_testing.markers import rclpy -from rclpy.node import Node from ros2_control_demo_testing.test_utils import ( check_controllers_running, check_if_js_published, @@ -67,14 +66,19 @@ def generate_test_description(): # This is our test fixture. Each method is a test case. # These run alongside the processes specified in generate_test_description() class TestFixture(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() def setUp(self): - rclpy.init() - self.node = Node("test_node") + self.node = rclpy.create_node("test_node") def tearDown(self): self.node.destroy_node() - rclpy.shutdown() def test_node_start(self, proc_output): check_node_running(self.node, "robot_state_publisher") From ceed8cfc458e60a695f68411077728fa5d41a01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 16 Dec 2024 14:10:28 +0100 Subject: [PATCH 3/3] Use launch_utils instead of a spawner per controller (#666) --- example_13/CMakeLists.txt | 9 +- .../bringup/launch/three_robots.launch.py | 108 +++++------------- example_13/package.xml | 7 +- example_13/test/test_three_robots_launch.py | 4 +- 4 files changed, 46 insertions(+), 82 deletions(-) diff --git a/example_13/CMakeLists.txt b/example_13/CMakeLists.txt index 06aec8e9d..e63aa68a5 100644 --- a/example_13/CMakeLists.txt +++ b/example_13/CMakeLists.txt @@ -34,11 +34,18 @@ install( ) if(BUILD_TESTING) + find_package(ament_cmake_ros REQUIRED) + find_package(launch_testing_ament_cmake REQUIRED) find_package(ament_cmake_pytest REQUIRED) ament_add_pytest_test(example_13_urdf_xacro test/test_urdf_xacro.py) ament_add_pytest_test(view_example_13_launch test/test_view_robot_launch.py) - ament_add_pytest_test(run_example_13_launch test/test_three_robots_launch.py) + + function(add_ros_isolated_launch_test path) + set(RUNNER "${ament_cmake_ros_DIR}/run_test_isolated.py") + add_launch_test("${path}" RUNNER "${RUNNER}" ${ARGN}) + endfunction() + add_ros_isolated_launch_test(test/test_three_robots_launch.py) endif() ## EXPORTS diff --git a/example_13/bringup/launch/three_robots.launch.py b/example_13/bringup/launch/three_robots.launch.py index 8a2aa2b53..e9a1679cc 100644 --- a/example_13/bringup/launch/three_robots.launch.py +++ b/example_13/bringup/launch/three_robots.launch.py @@ -22,6 +22,7 @@ from launch_ros.actions import Node from launch_ros.substitutions import FindPackageShare +from controller_manager.launch_utils import generate_controllers_spawner_launch_description def generate_launch_description(): @@ -104,85 +105,44 @@ def generate_launch_description(): condition=IfCondition(gui), ) - # Separate robot state publishers for each robot - - # Global joint state broadcaster - joint_state_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["joint_state_broadcaster"], + # global broadcaster and initially active controllers from RRBot + general_ctrl_spawner = generate_controllers_spawner_launch_description( + [ + # Global joint state broadcaster + "joint_state_broadcaster", + # RRBot controllers + "rrbot_joint_state_broadcaster", + "rrbot_position_controller", + # External FTS broadcaster + "rrbot_external_fts_broadcaster", + ], + controller_params_files=[robot_controllers], ) - # RRBot controllers - rrbot_joint_state_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["rrbot_joint_state_broadcaster", "--param-file", robot_controllers], - ) - rrbot_position_controller_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["rrbot_position_controller", "--param-file", robot_controllers], - ) - # External FTS broadcaster - rrbot_external_fts_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["rrbot_external_fts_broadcaster", "--param-file", robot_controllers], + # RRBot with sensors controllers, initially active + rrbot_sensor_ctrl_spawner_active = generate_controllers_spawner_launch_description( + ["rrbot_with_sensor_joint_state_broadcaster", "rrbot_with_sensor_fts_broadcaster"], + controller_params_files=[robot_controllers], ) - # RRBot controllers - rrbot_with_sensor_joint_state_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["rrbot_with_sensor_joint_state_broadcaster", "--param-file", robot_controllers], - ) - rrbot_with_sensor_position_controller_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=[ + # RRBot with sensors controllers, initially inactive + rrbot_sensor_ctrl_spawner_inactive = generate_controllers_spawner_launch_description( + [ "rrbot_with_sensor_position_controller", - "--inactive", - "--param-file", - robot_controllers, ], - ) - rrbot_with_sensor_fts_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=["rrbot_with_sensor_fts_broadcaster", "--param-file", robot_controllers], + controller_params_files=[robot_controllers], + extra_spawner_args=["--inactive"], ) - # ThreeDofBot controllers - threedofbot_joint_state_broadcaster_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=[ + # ThreeDofBot controllers, initially inactive + threedofbot_ctrl_spawner = generate_controllers_spawner_launch_description( + [ "threedofbot_joint_state_broadcaster", - "--inactive", - "--param-file", - robot_controllers, - ], - ) - threedofbot_position_controller_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=[ "threedofbot_position_controller", - "--inactive", - "--param-file", - robot_controllers, - ], - ) - threedofbot_pid_gain_controller_spawner = Node( - package="controller_manager", - executable="spawner", - arguments=[ "threedofbot_pid_gain_controller", - "--inactive", - "--param-file", - robot_controllers, ], + controller_params_files=[robot_controllers], + extra_spawner_args=["--inactive"], ) # Command publishers @@ -209,16 +169,10 @@ def generate_launch_description(): control_node, robot_state_pub_node, rviz_node, - joint_state_broadcaster_spawner, - rrbot_joint_state_broadcaster_spawner, - rrbot_position_controller_spawner, - rrbot_external_fts_broadcaster_spawner, - rrbot_with_sensor_joint_state_broadcaster_spawner, - rrbot_with_sensor_position_controller_spawner, - rrbot_with_sensor_fts_broadcaster_spawner, - threedofbot_joint_state_broadcaster_spawner, - threedofbot_position_controller_spawner, - threedofbot_pid_gain_controller_spawner, + general_ctrl_spawner, + rrbot_sensor_ctrl_spawner_active, + rrbot_sensor_ctrl_spawner_inactive, + threedofbot_ctrl_spawner, rrbot_position_command_publisher, rrbot_with_sensor_position_command_publisher, threedofbot_position_command_publisher, diff --git a/example_13/package.xml b/example_13/package.xml index 0cc8f4a59..9e0af6f60 100644 --- a/example_13/package.xml +++ b/example_13/package.xml @@ -31,8 +31,13 @@ xacro ament_cmake_pytest - launch_testing_ros + ament_cmake_ros + launch_ros + launch_testing_ament_cmake + launch_testing + launch liburdfdom-tools + rclpy ros2_control_demo_testing xacro diff --git a/example_13/test/test_three_robots_launch.py b/example_13/test/test_three_robots_launch.py index 9e0fed689..eaaa12ac1 100644 --- a/example_13/test/test_three_robots_launch.py +++ b/example_13/test/test_three_robots_launch.py @@ -29,7 +29,6 @@ # Author: Christoph Froehlich import os -import pytest import unittest import subprocess @@ -48,8 +47,7 @@ ) -# Executes the given launch file and checks if all nodes can be started -@pytest.mark.rostest +# Executes the given launch file def generate_test_description(): launch_include = IncludeLaunchDescription( PythonLaunchDescriptionSource(