Skip to content

Commit c6c7ecd

Browse files
Felix Exnerfmauch
authored andcommitted
Added a test that sjtc correctly aborts on violation of constraints
(cherry picked from commit e98d271)
1 parent 0eb1b82 commit c6c7ecd

File tree

1 file changed

+72
-5
lines changed

1 file changed

+72
-5
lines changed

ur_robot_driver/test/robot_driver.py

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
from launch_testing.actions import ReadyToTest
5252
from rclpy.action import ActionClient
5353
from rclpy.node import Node
54+
from sensor_msgs.msg import JointState
5455
from std_srvs.srv import Trigger
5556
from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
5657
from ur_dashboard_msgs.msg import RobotMode
@@ -376,15 +377,81 @@ def test_trajectory_scaled(self, tf_prefix):
376377
)
377378
self.assertIn(
378379
result.error_code,
379-
(
380-
FollowJointTrajectory.Result.PATH_TOLERANCE_VIOLATED,
381-
FollowJointTrajectory.Result.GOAL_TOLERANCE_VIOLATED,
382-
FollowJointTrajectory.Result.SUCCESSFUL,
383-
),
380+
(FollowJointTrajectory.Result.SUCCESSFUL,),
384381
)
385382

386383
self.node.get_logger().info("Received result")
387384

385+
def test_trajectory_scaled_aborts_on_violation(self, tf_prefix):
386+
"""Test that the robot correctly aborts the trajectory when the constraints are violated."""
387+
# Construct test trajectory
388+
test_trajectory = [
389+
(Duration(sec=6, nanosec=0), [0.0 for j in ROBOT_JOINTS]),
390+
(
391+
Duration(sec=6, nanosec=50000000),
392+
[-1.0 for j in ROBOT_JOINTS],
393+
), # physically unfeasible
394+
(Duration(sec=8, nanosec=0), [-1.5 for j in ROBOT_JOINTS]), # physically unfeasible
395+
]
396+
397+
trajectory = JointTrajectory(
398+
joint_names=[tf_prefix + joint for joint in ROBOT_JOINTS],
399+
points=[
400+
JointTrajectoryPoint(positions=test_pos, time_from_start=test_time)
401+
for (test_time, test_pos) in test_trajectory
402+
],
403+
)
404+
405+
last_joint_state = None
406+
407+
def js_cb(msg):
408+
nonlocal last_joint_state
409+
last_joint_state = msg
410+
411+
joint_state_sub = self.node.create_subscription(JointState, "/joint_states", js_cb, 1)
412+
joint_state_sub # prevent warning about unused variable
413+
414+
goal = FollowJointTrajectory.Goal(trajectory=trajectory)
415+
416+
self.node.get_logger().info("Sending goal for robot to follow")
417+
goal_response = self.call_action(
418+
"/scaled_joint_trajectory_controller/follow_joint_trajectory", goal
419+
)
420+
421+
self.assertEqual(goal_response.accepted, True)
422+
423+
if goal_response.accepted:
424+
result = self.get_result(
425+
"/scaled_joint_trajectory_controller/follow_joint_trajectory",
426+
goal_response,
427+
TIMEOUT_EXECUTE_TRAJECTORY,
428+
)
429+
self.assertIn(
430+
result.error_code,
431+
(FollowJointTrajectory.Result.PATH_TOLERANCE_VIOLATED,),
432+
)
433+
self.node.get_logger().info("Received result")
434+
435+
# self.node.get_logger().info(f"Joint state before sleep {last_joint_state.position}")
436+
state_when_aborted = last_joint_state
437+
438+
# This section is to make sure the robot stopped moving once the trajectory was aborted
439+
time.sleep(2.0)
440+
# Ugly workaround since we want to wait for a joint state in the same thread
441+
while last_joint_state == state_when_aborted:
442+
rclpy.spin_once(self.node)
443+
state_after_sleep = last_joint_state
444+
self.node.get_logger().info(f"before: {state_when_aborted.position.tolist()}")
445+
self.node.get_logger().info(f"after: {state_after_sleep.position.tolist()}")
446+
self.assertTrue(
447+
all(
448+
[
449+
abs(a - b) < 0.01
450+
for a, b in zip(state_after_sleep.position, state_when_aborted.position)
451+
]
452+
)
453+
)
454+
388455
# TODO: uncomment when JTC starts taking into account goal_time_tolerance from goal message
389456
# see https://github.com/ros-controls/ros2_controllers/issues/249
390457
# Now do the same again, but with a goal time constraint

0 commit comments

Comments
 (0)