moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
gtest_with_move_group.py
Go to the documentation of this file.
1import os
2import unittest
3import launch_testing
4
5from ament_index_python.packages import get_package_share_directory
6from moveit_configs_utils import MoveItConfigsBuilder
7
8from launch import LaunchDescription
9from launch.actions import (
10 DeclareLaunchArgument,
11 ExecuteProcess,
12 RegisterEventHandler,
13 TimerAction,
14)
15from launch.event_handlers import OnProcessExit
16from launch_ros.actions import Node
17from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
18from launch_testing.actions import ReadyToTest
19
20from moveit_configs_utils import MoveItConfigsBuilder
21
22
24 moveit_config = (
25 MoveItConfigsBuilder("moveit_resources_panda")
26 .robot_description(file_path="config/panda.urdf.xacro")
27 .planning_pipelines("ompl", ["ompl"])
28 .trajectory_execution(file_path="config/gripper_moveit_controllers.yaml")
29 .to_moveit_configs()
30 )
31
32 run_move_group_node = Node(
33 package="moveit_ros_move_group",
34 executable="move_group",
35 output="log",
36 parameters=[moveit_config.to_dict()],
37 )
38
39 static_tf = Node(
40 package="tf2_ros",
41 executable="static_transform_publisher",
42 output="log",
43 arguments=["--frame-id", "world", "--child-frame-id", "panda_link0"],
44 )
45
46 robot_state_publisher = Node(
47 package="robot_state_publisher",
48 executable="robot_state_publisher",
49 name="robot_state_publisher",
50 output="log",
51 parameters=[moveit_config.robot_description],
52 )
53
54 # ros2_control using FakeSystem as hardware
55 ros2_controllers_path = os.path.join(
56 get_package_share_directory("moveit_resources_panda_moveit_config"),
57 "config",
58 "ros2_controllers.yaml",
59 )
60 ros2_control_node = Node(
61 package="controller_manager",
62 executable="ros2_control_node",
63 parameters=[moveit_config.robot_description, ros2_controllers_path],
64 output="log",
65 )
66
67 load_controllers = []
68 for controller in [
69 "panda_arm_controller",
70 "panda_hand_controller",
71 ]:
72 load_controllers += [
73 ExecuteProcess(
74 cmd=["ros2 run controller_manager spawner {}".format(controller)],
75 shell=True,
76 output="log",
77 )
78 ]
79
80 # Spawn the joint_state_broadcaster separately so the test binary can be
81 # gated on its activation. The spawner process exits 0 only once the
82 # controller is loaded, configured, and activated, at which point
83 # /joint_states is guaranteed to be publishing. Gating the test on this
84 # event (instead of a fixed wall-clock timer) avoids a startup race where
85 # the test runs before joint_states exists and
86 # MoveGroupInterface::getCurrentState() fails with
87 # "Failed to fetch current robot state".
88 joint_state_broadcaster_spawner = ExecuteProcess(
89 cmd=["ros2 run controller_manager spawner joint_state_broadcaster"],
90 shell=True,
91 output="log",
92 )
93
94 gtest_node = Node(
95 executable=PathJoinSubstitution(
96 [
97 LaunchConfiguration("test_binary_dir"),
98 LaunchConfiguration("test_executable"),
99 ]
100 ),
101 parameters=[moveit_config.to_dict()],
102 output="screen",
103 )
104
105 return LaunchDescription(
106 [
107 DeclareLaunchArgument(
108 name="test_binary_dir",
109 description="Binary directory of package "
110 "containing test executables",
111 ),
112 static_tf,
113 robot_state_publisher,
114 ros2_control_node,
115 *load_controllers,
116 joint_state_broadcaster_spawner,
117 TimerAction(period=1.0, actions=[run_move_group_node]),
118 # Launch the test binary only once joint_state_broadcaster has
119 # activated, guaranteeing /joint_states is available.
120 RegisterEventHandler(
121 OnProcessExit(
122 target_action=joint_state_broadcaster_spawner,
123 on_exit=[gtest_node],
124 )
125 ),
126 ReadyToTest(),
127 ]
128 ), {
129 "gtest_node": gtest_node,
130 }
131
132
133class TestGTestWaitForCompletion(unittest.TestCase):
134 # Waits for test to complete, then waits a bit to make sure result files are generated
135 def test_gtest_run_complete(self, gtest_node):
136 self.proc_info.assertWaitForShutdown(gtest_node, timeout=4000.0)
137
138
139@launch_testing.post_shutdown_test()
140class TestGTestProcessPostShutdown(unittest.TestCase):
141 # Checks if the test has been completed with acceptable exit codes (successful codes)
142 def test_gtest_pass(self, proc_info, gtest_node):
143 launch_testing.asserts.assertExitCodes(
144 proc_info,
145 process=gtest_node,
146 # Allow -11 since ros2_control or warehouse_ros sometimes segfaults
147 # for unrelated reasons.
148 allowable_exit_codes=[0, -11],
149 )