Skip to content

Commit 81a2282

Browse files
committed
Make test use an arbitraty orientation
This should avoid a coincitental overlap if the transformation is wrong.
1 parent 47a18f7 commit 81a2282

File tree

1 file changed

+76
-13
lines changed

1 file changed

+76
-13
lines changed

ur_robot_driver/test/integration_test_force_mode.py

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@
4141
from tf2_ros import TransformException
4242
from tf2_ros.buffer import Buffer
4343
from tf2_ros.transform_listener import TransformListener
44+
import tf2_geometry_msgs # noqa: F401 # pylint: disable=unused-import
4445

46+
from builtin_interfaces.msg import Duration
47+
from control_msgs.action import FollowJointTrajectory
48+
from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
4549
import std_msgs
4650
from controller_manager_msgs.srv import SwitchController
4751
from geometry_msgs.msg import (
@@ -52,16 +56,19 @@
5256
Twist,
5357
Wrench,
5458
Vector3,
59+
Vector3Stamped,
5560
)
5661

5762
sys.path.append(os.path.dirname(__file__))
5863
from test_common import ( # noqa: E402
64+
ActionInterface,
5965
ControllerManagerInterface,
6066
DashboardInterface,
6167
ForceModeInterface,
6268
IoStatusInterface,
6369
ConfigurationInterface,
6470
generate_driver_test_description,
71+
ROBOT_JOINTS,
6572
)
6673

6774
TIMEOUT_EXECUTE_TRAJECTORY = 30
@@ -101,6 +108,11 @@ def init_robot(self):
101108
self._controller_manager_interface = ControllerManagerInterface(self.node)
102109
self._io_status_controller_interface = IoStatusInterface(self.node)
103110
self._configuration_controller_interface = ConfigurationInterface(self.node)
111+
self._passthrough_forward_joint_trajectory = ActionInterface(
112+
self.node,
113+
"/passthrough_trajectory_controller/follow_joint_trajectory",
114+
FollowJointTrajectory,
115+
)
104116

105117
def setUp(self):
106118
self._dashboard_interface.start_robot()
@@ -127,14 +139,12 @@ def run_force_mode(self, tf_prefix):
127139
self._force_mode_controller_interface = ForceModeInterface(self.node)
128140

129141
# Create task frame for force mode
130-
point = Point(x=0.8, y=0.8, z=0.8)
142+
point = Point(x=0.0, y=0.0, z=0.0)
131143
orientation = Quaternion(x=0.7071, y=0.0, z=0.0, w=0.7071)
132144
task_frame_pose = Pose()
133145
task_frame_pose.position = point
134146
task_frame_pose.orientation = orientation
135-
header = std_msgs.msg.Header(seq=1, frame_id=tf_prefix + "base")
136-
header.stamp.sec = int(time.time()) + 1
137-
header.stamp.nanosec = 0
147+
header = std_msgs.msg.Header(seq=1, frame_id=tf_prefix + "tool0_controller")
138148
frame_stamp = PoseStamped()
139149
frame_stamp.header = header
140150
frame_stamp.pose = task_frame_pose
@@ -144,7 +154,7 @@ def run_force_mode(self, tf_prefix):
144154

145155
# Create Wrench message for force mode
146156
wrench = Wrench()
147-
wrench.force = Vector3(x=0.0, y=0.0, z=5.0)
157+
wrench.force = Vector3(x=0.0, y=0.0, z=10.0)
148158
wrench.torque = Vector3(x=0.0, y=0.0, z=0.0)
149159

150160
# Specify interpretation of task frame (no transform)
@@ -183,27 +193,46 @@ def run_force_mode(self, tf_prefix):
183193
time.sleep(5.0)
184194

185195
trans_after = self.lookup_tcp_in_base(tf_prefix, self.node.get_clock().now())
196+
diff = Vector3Stamped(
197+
vector=Vector3(
198+
x=(trans_after.transform.translation.x - trans_before.transform.translation.x),
199+
y=(trans_after.transform.translation.y - trans_before.transform.translation.y),
200+
z=(trans_after.transform.translation.z - trans_before.transform.translation.z),
201+
),
202+
header=trans_after.header,
203+
)
204+
diff_in_tool0_controller = self.tf_buffer.transform(
205+
diff,
206+
tf_prefix + "tool0_controller",
207+
timeout=rclpy.time.Duration(seconds=1.0),
208+
)
186209

187210
# task frame and wrench determines the expected motion
188211
# In the example we used
189-
# - a task frame rotated pi/2 deg around the base frame's x axis
212+
# - a task frame rotated pi/2 deg around the tcp frame's x axis
190213
# - a wrench with a positive z component for the force
191-
# => we should expect a motion in negative y of the base frame
192-
self.assertTrue(trans_after.transform.translation.y < trans_before.transform.translation.y)
214+
# => we should expect a motion in negative y of the tcp frame, since we didn't to any
215+
# rotation
216+
self.assertTrue(
217+
diff_in_tool0_controller.vector.y < -0.03,
218+
)
193219
self.assertAlmostEqual(
194-
trans_after.transform.translation.x,
195-
trans_before.transform.translation.x,
220+
diff_in_tool0_controller.vector.x,
221+
0.0,
196222
delta=0.001,
223+
msg="X translation should not change",
197224
)
198225
self.assertAlmostEqual(
199-
trans_after.transform.translation.z,
200-
trans_before.transform.translation.z,
226+
diff_in_tool0_controller.vector.z,
227+
0.0,
201228
delta=0.001,
229+
msg="Z translation should not change",
202230
)
203231
self.assertTrue(
204232
are_quaternions_same(
205233
trans_after.transform.rotation, trans_before.transform.rotation, 0.001
206-
)
234+
),
235+
msg="Rotation should not change",
207236
)
208237

209238
res = self._force_mode_controller_interface.stop_force_mode()
@@ -218,6 +247,39 @@ def run_force_mode(self, tf_prefix):
218247
)
219248

220249
def test_force_mode_controller(self, tf_prefix):
250+
self.assertTrue(
251+
self._controller_manager_interface.switch_controller(
252+
strictness=SwitchController.Request.BEST_EFFORT,
253+
activate_controllers=[
254+
"passthrough_trajectory_controller",
255+
],
256+
deactivate_controllers=[
257+
"scaled_joint_trajectory_controller",
258+
"joint_trajectory_controller",
259+
"force_mode_controller",
260+
],
261+
).ok
262+
)
263+
waypts = [[-1.6, -1.55, -1.7, -1.0, 2.05, 0.5]]
264+
time_vec = [Duration(sec=5, nanosec=0)]
265+
test_trajectory = zip(time_vec, waypts)
266+
trajectory = JointTrajectory(
267+
points=[
268+
JointTrajectoryPoint(positions=pos, time_from_start=times)
269+
for (times, pos) in test_trajectory
270+
],
271+
joint_names=[tf_prefix + ROBOT_JOINTS[i] for i in range(len(ROBOT_JOINTS))],
272+
)
273+
goal_handle = self._passthrough_forward_joint_trajectory.send_goal(
274+
trajectory=trajectory,
275+
)
276+
self.assertTrue(goal_handle.accepted)
277+
if goal_handle.accepted:
278+
result = self._passthrough_forward_joint_trajectory.get_result(
279+
goal_handle, TIMEOUT_EXECUTE_TRAJECTORY
280+
)
281+
self.assertEqual(result.error_code, FollowJointTrajectory.Result.SUCCESSFUL)
282+
221283
self.assertTrue(
222284
self._controller_manager_interface.switch_controller(
223285
strictness=SwitchController.Request.BEST_EFFORT,
@@ -227,6 +289,7 @@ def test_force_mode_controller(self, tf_prefix):
227289
deactivate_controllers=[
228290
"scaled_joint_trajectory_controller",
229291
"joint_trajectory_controller",
292+
"passthrough_trajectory_controller",
230293
],
231294
).ok
232295
)

0 commit comments

Comments
 (0)