moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
servo_ros_integration.test.py
Go to the documentation of this file.
1import os
2import launch
3from launch.event_handlers import OnProcessExit
4import unittest
5import launch_ros
6import launch_testing
7from ament_index_python.packages import get_package_share_directory
8from moveit_configs_utils import MoveItConfigsBuilder
9from launch_param_builder import ParameterBuilder
10from launch.conditions import IfCondition, UnlessCondition
11from launch.substitutions import LaunchConfiguration
12
13
15 moveit_config = (
16 MoveItConfigsBuilder("moveit_resources_panda")
17 .robot_description(file_path="config/panda.urdf.xacro")
18 .to_moveit_configs()
19 )
20
21 # Launch Servo as a standalone node or as a "node component" for better latency/efficiency
22 launch_as_standalone_node = LaunchConfiguration(
23 "launch_as_standalone_node", default="true"
24 )
25
26 # Get parameters for the Servo node
27 servo_params = {
28 "moveit_servo": ParameterBuilder("moveit_servo")
29 .yaml("config/test_config_panda.yaml")
30 .to_dict()
31 }
32
33 # This sets the update rate and planning group name for the acceleration limiting filter.
34 acceleration_filter_update_period = {"update_period": 0.01}
35 planning_group_name = {"planning_group_name": "panda_arm"}
36
37 # ros2_control using FakeSystem as hardware
38 ros2_controllers_path = os.path.join(
39 get_package_share_directory("moveit_resources_panda_moveit_config"),
40 "config",
41 "ros2_controllers.yaml",
42 )
43 ros2_control_node = launch_ros.actions.Node(
44 package="controller_manager",
45 executable="ros2_control_node",
46 parameters=[ros2_controllers_path],
47 remappings=[
48 ("/controller_manager/robot_description", "/robot_description"),
49 ],
50 output="screen",
51 )
52
53 joint_state_broadcaster_spawner = launch_ros.actions.Node(
54 package="controller_manager",
55 executable="spawner",
56 arguments=[
57 "joint_state_broadcaster",
58 "--controller-manager-timeout",
59 "300",
60 "--controller-manager",
61 "/controller_manager",
62 ],
63 output="screen",
64 )
65
66 panda_arm_controller_spawner = launch_ros.actions.Node(
67 package="controller_manager",
68 executable="spawner",
69 arguments=["panda_arm_controller", "-c", "/controller_manager"],
70 )
71
72 # Launch as much as possible in components
73 container = launch_ros.actions.ComposableNodeContainer(
74 name="moveit_servo_demo_container",
75 namespace="/",
76 package="rclcpp_components",
77 executable="component_container_mt",
78 composable_node_descriptions=[
79 # Example of launching Servo as a node component
80 # Launching as a node component makes ROS 2 intraprocess communication more efficient.
81 launch_ros.descriptions.ComposableNode(
82 package="moveit_servo",
83 plugin="moveit_servo::ServoNode",
84 name="servo_node",
85 parameters=[
86 servo_params,
87 acceleration_filter_update_period,
88 planning_group_name,
89 moveit_config.robot_description,
90 moveit_config.robot_description_semantic,
91 moveit_config.robot_description_kinematics,
92 ],
93 condition=UnlessCondition(launch_as_standalone_node),
94 ),
95 launch_ros.descriptions.ComposableNode(
96 package="robot_state_publisher",
97 plugin="robot_state_publisher::RobotStatePublisher",
98 name="robot_state_publisher",
99 parameters=[moveit_config.robot_description],
100 ),
101 launch_ros.descriptions.ComposableNode(
102 package="tf2_ros",
103 plugin="tf2_ros::StaticTransformBroadcasterNode",
104 name="static_tf2_broadcaster",
105 parameters=[{"child_frame_id": "/panda_link0", "frame_id": "/world"}],
106 ),
107 ],
108 output="screen",
109 )
110 # Launch a standalone Servo node.
111 # As opposed to a node component, this may be necessary (for example) if Servo is running on a different PC
112 servo_node = launch_ros.actions.Node(
113 package="moveit_servo",
114 executable="servo_node",
115 name="servo_node",
116 parameters=[
117 servo_params,
118 acceleration_filter_update_period,
119 planning_group_name,
120 moveit_config.robot_description,
121 moveit_config.robot_description_semantic,
122 moveit_config.robot_description_kinematics,
123 ],
124 output="screen",
125 condition=IfCondition(launch_as_standalone_node),
126 )
127
128 servo_gtest = launch_ros.actions.Node(
129 executable=launch.substitutions.PathJoinSubstitution(
130 [
131 launch.substitutions.LaunchConfiguration("test_binary_dir"),
132 "moveit_servo_ros_integration_test",
133 ]
134 ),
135 output="screen",
136 )
137
138 return launch.LaunchDescription(
139 [
140 servo_node,
141 container,
142 launch.actions.TimerAction(period=3.0, actions=[ros2_control_node]),
143 launch.actions.TimerAction(
144 period=5.0, actions=[joint_state_broadcaster_spawner]
145 ),
146 launch.actions.TimerAction(
147 period=7.0, actions=[panda_arm_controller_spawner]
148 ),
149 # Gate the gtest launch on the last-in-chain spawner completing so the
150 # test does not race controller activation. Prior fixed 9s timer flaked
151 # under load (ServoRosFixture.testJointJog).
152 launch.actions.RegisterEventHandler(
153 OnProcessExit(
154 target_action=panda_arm_controller_spawner,
155 on_exit=[servo_gtest],
156 )
157 ),
158 launch_testing.actions.ReadyToTest(),
159 ]
160 ), {
161 "servo_gtest": servo_gtest,
162 }
163
164
165class TestGTestWaitForCompletion(unittest.TestCase):
166 # Waits for test to complete, then waits a bit to make sure result files are generated
167 def test_gtest_run_complete(self, servo_gtest):
168 self.proc_info.assertWaitForShutdown(servo_gtest, timeout=4000.0)
169
170
171@launch_testing.post_shutdown_test()
172class TestGTestProcessPostShutdown(unittest.TestCase):
173 # Checks if the test has been completed with acceptable exit codes (successful codes)
174 def test_gtest_pass(self, proc_info, servo_gtest):
175 launch_testing.asserts.assertExitCodes(proc_info, process=servo_gtest)