Skip to content

Commit af5d5f7

Browse files
authored
Converted io_test and switch_on_test to ROS2 (#124)
* Converted io_test and switch_on_test to ROS2 and configured pipeline to start ursim
1 parent 799cdee commit af5d5f7

File tree

7 files changed

+204
-136
lines changed

7 files changed

+204
-136
lines changed

.github/workflows/ci-build-binary.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ jobs:
2020
- {ROS_DISTRO: foxy, ROS_REPO: testing}
2121
env:
2222
UPSTREAM_WORKSPACE: Universal_Robots_ROS2_Driver.repos
23+
DOCKER_RUN_OPTS: --network static_test_net
24+
BEFORE_INIT: 'apt-get update -qq && apt-get install -y iproute2 iputils-ping && ip addr && ping -c5 192.168.56.101'
25+
IMMEDIATE_TEST_OUTPUT: true
2326
steps:
2427
- uses: actions/checkout@v1
28+
- name: start ursim
29+
run: |
30+
.github/dockerursim/build_and_run_docker_ursim.sh
2531
- uses: 'ros-industrial/industrial_ci@master'
2632
env: ${{matrix.env}}

.github/workflows/ci-build-coverage.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ jobs:
1919
- uses: ros-tooling/[email protected]
2020
with:
2121
required-ros-distributions: foxy
22+
- uses: actions/checkout@v1
23+
- name: start ursim
24+
run: |
25+
.github/dockerursim/build_and_run_docker_ursim.sh
2226
- uses: ros-tooling/[email protected]
2327
with:
2428
target-ros2-distro: foxy

ur_robot_driver/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,12 @@ ament_export_dependencies(
107107
)
108108

109109
ament_package()
110+
111+
if(BUILD_TESTING)
112+
find_package(ur_controllers REQUIRED)
113+
find_package(ur_description REQUIRED)
114+
find_package(ur_bringup REQUIRED)
115+
find_package(ur_msgs REQUIRED)
116+
find_package(launch_testing_ament_cmake)
117+
add_launch_test(test/integration_test.py)
118+
endif()

ur_robot_driver/package.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
<!-- TODO: rosdep cannot find ur_client_library -->
3131
<depend>ur_client_library</depend>
3232
<depend>ur_dashboard_msgs</depend>
33+
<depend>launch_testing_ament_cmake</depend>
34+
<depend>ur_msgs</depend>
35+
<depend>ur_description</depend>
36+
<depend>ur_bringup</depend>
37+
<depend>ur_controllers</depend>
3338

3439
<exec_depend>controller_manager</exec_depend>
3540

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env python
2+
# Copyright 2019, FZI Forschungszentrum Informatik
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import unittest
17+
import os
18+
import time
19+
import pytest
20+
21+
import launch_testing
22+
from launch import LaunchDescription
23+
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
24+
from launch.substitutions import LaunchConfiguration
25+
from launch.launch_description_sources import PythonLaunchDescriptionSource
26+
27+
import rclpy
28+
from rclpy.node import Node
29+
30+
from ur_msgs.srv import SetIO
31+
from ur_msgs.msg import IOStates
32+
from ur_dashboard_msgs.srv import GetRobotMode
33+
from ur_dashboard_msgs.msg import RobotMode
34+
from std_srvs.srv import Trigger
35+
36+
37+
@pytest.mark.launch_test
38+
def generate_test_description():
39+
declared_arguments = []
40+
41+
declared_arguments.append(
42+
DeclareLaunchArgument(
43+
"robot_ip",
44+
default_value="192.168.56.101",
45+
description="IP address by which the robot can be reached.",
46+
)
47+
)
48+
49+
declared_arguments.append(
50+
DeclareLaunchArgument(
51+
"ur_type", default_value="ur5e", description="Type/series of used UR robot."
52+
)
53+
)
54+
55+
ur_type = LaunchConfiguration("ur_type")
56+
robot_ip = LaunchConfiguration("robot_ip")
57+
dir_path = os.path.dirname(os.path.realpath(__file__))
58+
59+
launch_file = IncludeLaunchDescription(
60+
PythonLaunchDescriptionSource([dir_path, "/../../ur_bringup/launch/ur_control.launch.py"]),
61+
launch_arguments={"robot_ip": robot_ip, "ur_type": ur_type, "launch_rviz": "false"}.items(),
62+
)
63+
64+
return LaunchDescription(
65+
declared_arguments + [launch_testing.actions.ReadyToTest(), launch_file]
66+
)
67+
68+
69+
class IOTest(unittest.TestCase):
70+
@classmethod
71+
def setUpClass(cls):
72+
# Initialize the ROS context
73+
rclpy.init()
74+
cls.node = Node("ur_robot_driver_integrations_test")
75+
cls.init_robot(cls)
76+
77+
@classmethod
78+
def tearDownClass(cls):
79+
# Shutdown the ROS context
80+
cls.node.destroy_node()
81+
rclpy.shutdown()
82+
83+
def init_robot(self):
84+
# Initialize clients
85+
self.set_io_client = self.node.create_client(SetIO, "/io_and_status_controller/set_io")
86+
if self.set_io_client.wait_for_service(10) is False:
87+
raise Exception(
88+
"Could not reach set IO service, make sure that the driver is actually running"
89+
)
90+
91+
self.power_on_client = self.node.create_client(Trigger, "/dashboard_client/power_on")
92+
if self.power_on_client.wait_for_service(10) is False:
93+
raise Exception(
94+
"Could not reach power on service, make sure that the driver is actually running"
95+
)
96+
97+
self.brake_release_client = self.node.create_client(
98+
Trigger, "/dashboard_client/brake_release"
99+
)
100+
if self.brake_release_client.wait_for_service(10) is False:
101+
raise Exception(
102+
"Could not reach brake release service, make sure that the driver is actually running"
103+
)
104+
105+
self.get_robot_mode_client = self.node.create_client(
106+
GetRobotMode, "/dashboard_client/get_robot_mode"
107+
)
108+
if self.get_robot_mode_client.wait_for_service(10) is False:
109+
raise Exception(
110+
"Could not reach get robot mode service, make sure that the driver is actually running"
111+
)
112+
113+
def test_switch_on(self):
114+
"""Test power on a robot."""
115+
empty_req = Trigger.Request()
116+
get_robot_mode_req = GetRobotMode.Request()
117+
118+
self.power_on_client.call_async(empty_req)
119+
end_time = time.time() + 10
120+
mode = RobotMode.DISCONNECTED
121+
while mode not in (RobotMode.IDLE, RobotMode.RUNNING) and time.time() < end_time:
122+
future = self.get_robot_mode_client.call_async(get_robot_mode_req)
123+
while future.done() is False:
124+
rclpy.spin_once(self.node, timeout_sec=0.1)
125+
mode = future.result().robot_mode.mode
126+
127+
self.assertIn(mode, (RobotMode.IDLE, RobotMode.RUNNING))
128+
129+
self.brake_release_client.call_async(empty_req)
130+
end_time = time.time() + 10
131+
while mode != RobotMode.RUNNING and time.time() < end_time:
132+
future = self.get_robot_mode_client.call_async(get_robot_mode_req)
133+
while future.done() is False:
134+
rclpy.spin_once(self.node, timeout_sec=0.1)
135+
mode = future.result().robot_mode.mode
136+
137+
self.assertEqual(mode, RobotMode.RUNNING)
138+
139+
def test_set_io(self):
140+
"""Test to set an IO and check whether it has been set."""
141+
self.io_msg = None
142+
io_states_sub = self.node.create_subscription(
143+
IOStates,
144+
"/io_and_status_controller/io_states",
145+
self.io_msg_cb,
146+
rclpy.qos.qos_profile_system_default,
147+
)
148+
149+
pin = 0
150+
set_io_req = SetIO.Request()
151+
set_io_req.fun = 1
152+
set_io_req.pin = pin
153+
set_io_req.state = 1.0
154+
155+
self.set_io_client.call_async(set_io_req)
156+
pin_state = False
157+
158+
end_time = time.time() + 5
159+
while not pin_state and time.time() < end_time:
160+
rclpy.spin_once(self.node, timeout_sec=0.1)
161+
if self.io_msg is not None:
162+
pin_state = self.io_msg.digital_out_states[pin].state
163+
164+
self.assertEqual(pin_state, 1)
165+
166+
set_io_req.state = 0.0
167+
self.set_io_client.call_async(set_io_req)
168+
169+
end_time = time.time() + 5
170+
while pin_state and time.time() < end_time:
171+
rclpy.spin_once(self.node, timeout_sec=0.1)
172+
if self.io_msg is not None:
173+
pin_state = self.io_msg.digital_out_states[pin].state
174+
175+
self.assertEqual(pin_state, 0)
176+
177+
self.node.destroy_subscription(io_states_sub)
178+
179+
def io_msg_cb(self, msg):
180+
self.io_msg = msg

ur_robot_driver/test/io_test.py

Lines changed: 0 additions & 78 deletions
This file was deleted.

ur_robot_driver/test/switch_on_test.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)