4444 IncludeLaunchDescription ,
4545 RegisterEventHandler ,
4646)
47+ from launch .conditions import IfCondition , UnlessCondition
4748from launch .event_handlers import OnProcessExit
4849from launch .launch_description_sources import PythonLaunchDescriptionSource
4950from launch .substitutions import LaunchConfiguration , PathJoinSubstitution
5758from ur_dashboard_msgs .srv import GetRobotMode
5859from ur_msgs .msg import IOStates
5960from ur_msgs .srv import SetIO
61+ from controller_manager_msgs .srv import ListControllers
6062
6163TIMEOUT_WAIT_SERVICE = 10
6264TIMEOUT_WAIT_SERVICE_INITIAL = 60
@@ -90,7 +92,25 @@ def generate_test_description(tf_prefix):
9092 )
9193 )
9294
95+ declared_arguments .append (
96+ DeclareLaunchArgument (
97+ "robot_ip" ,
98+ default_value = "192.168.56.101" ,
99+ description = "IP address of used UR robot." ,
100+ )
101+ )
102+
103+ declared_arguments .append (
104+ DeclareLaunchArgument (
105+ "launch_ursim" ,
106+ default_value = "true" ,
107+ description = "Launches the ursim when running the test if True" ,
108+ )
109+ )
110+
93111 ur_type = LaunchConfiguration ("ur_type" )
112+ robot_ip = LaunchConfiguration ("robot_ip" )
113+ launch_ursim = LaunchConfiguration ("launch_ursim" )
94114
95115 robot_driver = IncludeLaunchDescription (
96116 PythonLaunchDescriptionSource (
@@ -109,7 +129,9 @@ def generate_test_description(tf_prefix):
109129 "start_joint_controller" : "false" ,
110130 "tf_prefix" : tf_prefix ,
111131 }.items (),
132+ condition = IfCondition (launch_ursim ),
112133 )
134+
113135 ursim = ExecuteProcess (
114136 cmd = [
115137 PathJoinSubstitution (
@@ -126,22 +148,48 @@ def generate_test_description(tf_prefix):
126148 ],
127149 name = "start_ursim" ,
128150 output = "screen" ,
151+ condition = IfCondition (launch_ursim ),
129152 )
153+
130154 wait_dashboard_server = ExecuteProcess (
131155 cmd = [
132156 PathJoinSubstitution (
133157 [FindPackagePrefix ("ur_robot_driver" ), "bin" , "wait_dashboard_server.sh" ]
134- )
158+ ),
135159 ],
136160 name = "wait_dashboard_server" ,
137161 output = "screen" ,
162+ condition = IfCondition (launch_ursim ),
138163 )
164+
139165 driver_starter = RegisterEventHandler (
140- OnProcessExit (target_action = wait_dashboard_server , on_exit = robot_driver )
166+ OnProcessExit (target_action = wait_dashboard_server , on_exit = robot_driver ),
167+ condition = IfCondition (launch_ursim ),
168+ )
169+
170+ robot_driver_no_wait = IncludeLaunchDescription (
171+ PythonLaunchDescriptionSource (
172+ PathJoinSubstitution (
173+ [FindPackageShare ("ur_robot_driver" ), "launch" , "ur_control.launch.py" ]
174+ )
175+ ),
176+ launch_arguments = {
177+ "robot_ip" : robot_ip ,
178+ "ur_type" : ur_type ,
179+ "launch_rviz" : "false" ,
180+ "controller_spawner_timeout" : str (TIMEOUT_WAIT_SERVICE_INITIAL ),
181+ "initial_joint_controller" : "scaled_joint_trajectory_controller" ,
182+ "headless_mode" : "true" ,
183+ "launch_dashboard_client" : "false" ,
184+ "start_joint_controller" : "false" ,
185+ "tf_prefix" : tf_prefix ,
186+ }.items (),
187+ condition = UnlessCondition (launch_ursim ),
141188 )
142189
143190 return LaunchDescription (
144- declared_arguments + [ReadyToTest (), wait_dashboard_server , ursim , driver_starter ]
191+ declared_arguments
192+ + [ReadyToTest (), wait_dashboard_server , ursim , driver_starter , robot_driver_no_wait ]
145193 )
146194
147195
@@ -184,6 +232,7 @@ def init_robot(self):
184232 "/dashboard_client/get_robot_mode" : GetRobotMode ,
185233 "/controller_manager/switch_controller" : SwitchController ,
186234 "/io_and_status_controller/resend_robot_program" : Trigger ,
235+ "/controller_manager/list_controllers" : ListControllers ,
187236 }
188237 self .service_clients .update (
189238 {
@@ -282,6 +331,9 @@ def io_msg_cb(msg):
282331
283332 def test_trajectory (self , tf_prefix ):
284333 """Test robot movement."""
334+ # Wait for controller to be active
335+ self .waitForController ("scaled_joint_trajectory_controller" )
336+
285337 # Construct test trajectory
286338 test_trajectory = [
287339 (Duration (sec = 6 , nanosec = 0 ), [0.0 for j in ROBOT_JOINTS ]),
@@ -320,6 +372,9 @@ def test_illegal_trajectory(self, tf_prefix):
320372
321373 This is more of a validation test that the testing suite does the right thing
322374 """
375+ # Wait for controller to be active
376+ self .waitForController ("scaled_joint_trajectory_controller" )
377+
323378 # Construct test trajectory, the second point wrongly starts before the first
324379 test_trajectory = [
325380 (Duration (sec = 6 , nanosec = 0 ), [0.0 for j in ROBOT_JOINTS ]),
@@ -347,6 +402,9 @@ def test_illegal_trajectory(self, tf_prefix):
347402
348403 def test_trajectory_scaled (self , tf_prefix ):
349404 """Test robot movement."""
405+ # Wait for controller to be active
406+ self .waitForController ("scaled_joint_trajectory_controller" )
407+
350408 # Construct test trajectory
351409 test_trajectory = [
352410 (Duration (sec = 6 , nanosec = 0 ), [0.0 for j in ROBOT_JOINTS ]),
@@ -442,6 +500,25 @@ def get_result(self, action_name, goal_response, timeout):
442500 else :
443501 raise Exception (f"Exception while calling action: { future_res .exception ()} " )
444502
503+ def waitForController (
504+ self , controller_name , controller_status = "active" , timeout = TIMEOUT_WAIT_SERVICE
505+ ):
506+ controller_running = False
507+ end_time = time .time () + timeout
508+ while controller_running is False and time .time () < end_time :
509+ time .sleep (1 )
510+ response = self .call_service (
511+ "/controller_manager/list_controllers" , ListControllers .Request ()
512+ )
513+ for controller in response .controller :
514+ if controller .name == controller_name :
515+ controller_running = controller .state == controller_status
516+
517+ if controller_running is False :
518+ raise Exception (
519+ f"Controller { controller_name } did not reach controller state { controller_status } within timeout of { timeout } "
520+ )
521+
445522
446523def waitForService (node , srv_name , srv_type , timeout = TIMEOUT_WAIT_SERVICE ):
447524 client = node .create_client (srv_type , srv_name )
0 commit comments