2626# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2727# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2828# POSSIBILITY OF SUCH DAMAGE.
29-
30-
29+ import os
30+ import sys
3131import time
3232import unittest
3333
3434import pytest
3535import rclpy
36- from launch import LaunchDescription
37- from launch .actions import DeclareLaunchArgument , ExecuteProcess , IncludeLaunchDescription
38- from launch .launch_description_sources import PythonLaunchDescriptionSource
39- from launch .substitutions import LaunchConfiguration , PathJoinSubstitution
40- from launch_ros .substitutions import FindPackagePrefix , FindPackageShare
41- from launch_testing .actions import ReadyToTest
4236from rclpy .node import Node
43- from std_srvs .srv import Trigger
4437from ur_dashboard_msgs .msg import RobotMode
45- from ur_dashboard_msgs .srv import (
46- GetLoadedProgram ,
47- GetProgramState ,
48- GetRobotMode ,
49- IsProgramRunning ,
50- Load ,
51- )
5238
53- TIMEOUT_WAIT_SERVICE = 10
54- # If we download the docker image simultaneously to the tests, it can take quite some time until the
55- # dashboard server is reachable and usable.
56- TIMEOUT_WAIT_SERVICE_INITIAL = 120
39+ sys .path .append (os .path .dirname (__file__ ))
40+ from test_common import DashboardInterface , generate_dashboard_test_description # noqa: E402
5741
5842
5943@pytest .mark .launch_test
6044def generate_test_description ():
61- declared_arguments = []
62-
63- declared_arguments .append (
64- DeclareLaunchArgument (
65- "ur_type" ,
66- default_value = "ur5e" ,
67- description = "Type/series of used UR robot." ,
68- choices = ["ur3" , "ur3e" , "ur5" , "ur5e" , "ur10" , "ur10e" , "ur16e" , "ur20" , "ur30" ],
69- )
70- )
71-
72- ur_type = LaunchConfiguration ("ur_type" )
73-
74- dashboard_client = IncludeLaunchDescription (
75- PythonLaunchDescriptionSource (
76- PathJoinSubstitution (
77- [
78- FindPackageShare ("ur_robot_driver" ),
79- "launch" ,
80- "ur_dashboard_client.launch.py" ,
81- ]
82- )
83- ),
84- launch_arguments = {
85- "robot_ip" : "192.168.56.101" ,
86- }.items (),
87- )
88- ursim = ExecuteProcess (
89- cmd = [
90- PathJoinSubstitution (
91- [
92- FindPackagePrefix ("ur_robot_driver" ),
93- "lib" ,
94- "ur_robot_driver" ,
95- "start_ursim.sh" ,
96- ]
97- ),
98- " " ,
99- "-m " ,
100- ur_type ,
101- ],
102- name = "start_ursim" ,
103- output = "screen" ,
104- )
105-
106- return LaunchDescription (declared_arguments + [ReadyToTest (), dashboard_client , ursim ])
45+ return generate_dashboard_test_description ()
10746
10847
10948class DashboardClientTest (unittest .TestCase ):
@@ -121,38 +60,7 @@ def tearDownClass(cls):
12160 rclpy .shutdown ()
12261
12362 def init_robot (self ):
124- # We wait longer for the first client, as the robot is still starting up
125- power_on_client = waitForService (
126- self .node , "/dashboard_client/power_on" , Trigger , timeout = TIMEOUT_WAIT_SERVICE_INITIAL
127- )
128-
129- # Connect to all other expected services
130- dashboard_interfaces = {
131- "power_off" : Trigger ,
132- "brake_release" : Trigger ,
133- "unlock_protective_stop" : Trigger ,
134- "restart_safety" : Trigger ,
135- "get_robot_mode" : GetRobotMode ,
136- "load_installation" : Load ,
137- "load_program" : Load ,
138- "close_popup" : Trigger ,
139- "get_loaded_program" : GetLoadedProgram ,
140- "program_state" : GetProgramState ,
141- "program_running" : IsProgramRunning ,
142- "play" : Trigger ,
143- "stop" : Trigger ,
144- }
145- self .dashboard_clients = {
146- srv_name : waitForService (self .node , f"/dashboard_client/{ srv_name } " , srv_type )
147- for (srv_name , srv_type ) in dashboard_interfaces .items ()
148- }
149-
150- # Add first client to dict
151- self .dashboard_clients ["power_on" ] = power_on_client
152-
153- #
154- # Test functions
155- #
63+ self ._dashboard_interface = DashboardInterface (self .node )
15664
15765 def test_switch_on (self ):
15866 """Test power on a robot."""
@@ -161,59 +69,34 @@ def test_switch_on(self):
16169 mode = RobotMode .DISCONNECTED
16270 while mode != RobotMode .POWER_OFF and time .time () < end_time :
16371 time .sleep (0.1 )
164- result = self .call_dashboard_service ( "get_robot_mode" , GetRobotMode . Request () )
72+ result = self ._dashboard_interface . get_robot_mode ( )
16573 self .assertTrue (result .success )
16674 mode = result .robot_mode .mode
16775
16876 # Power on robot
169- self .assertTrue (self .call_dashboard_service ( "power_on" , Trigger . Request () ).success )
77+ self .assertTrue (self ._dashboard_interface . power_on ( ).success )
17078
17179 # Wait until robot mode changes
17280 end_time = time .time () + 10
17381 mode = RobotMode .DISCONNECTED
17482 while mode not in (RobotMode .IDLE , RobotMode .RUNNING ) and time .time () < end_time :
17583 time .sleep (0.1 )
176- result = self .call_dashboard_service ( "get_robot_mode" , GetRobotMode . Request () )
84+ result = self ._dashboard_interface . get_robot_mode ( )
17785 self .assertTrue (result .success )
17886 mode = result .robot_mode .mode
17987
18088 self .assertIn (mode , (RobotMode .IDLE , RobotMode .RUNNING ))
18189
18290 # Release robot brakes
183- self .assertTrue (self .call_dashboard_service ( "brake_release" , Trigger . Request () ).success )
91+ self .assertTrue (self ._dashboard_interface . brake_release ( ).success )
18492
18593 # Wait until robot mode is RUNNING
18694 end_time = time .time () + 10
18795 mode = RobotMode .DISCONNECTED
18896 while mode != RobotMode .RUNNING and time .time () < end_time :
18997 time .sleep (0.1 )
190- result = self .call_dashboard_service ( "get_robot_mode" , GetRobotMode . Request () )
98+ result = self ._dashboard_interface . get_robot_mode ( )
19199 self .assertTrue (result .success )
192100 mode = result .robot_mode .mode
193101
194102 self .assertEqual (mode , RobotMode .RUNNING )
195-
196- #
197- # Utility functions
198- #
199-
200- def call_dashboard_service (self , srv_name , request ):
201- self .node .get_logger ().info (
202- f"Calling dashboard service '{ srv_name } ' with request { request } "
203- )
204- future = self .dashboard_clients [srv_name ].call_async (request )
205- rclpy .spin_until_future_complete (self .node , future )
206- if future .result () is not None :
207- self .node .get_logger ().info (f"Received result { future .result ()} " )
208- return future .result ()
209- else :
210- raise Exception (f"Exception while calling service: { future .exception ()} " )
211-
212-
213- def waitForService (node , srv_name , srv_type , timeout = TIMEOUT_WAIT_SERVICE ):
214- client = node .create_client (srv_type , srv_name )
215- if client .wait_for_service (timeout ) is False :
216- raise Exception (f"Could not reach service '{ srv_name } ' within timeout of { timeout } " )
217-
218- node .get_logger ().info (f"Successfully connected to service '{ srv_name } '" )
219- return client
0 commit comments