1010from compas_fab .backends .ros .messages import ExecuteTrajectoryFeedback
1111from compas_fab .backends .ros .messages import ExecuteTrajectoryGoal
1212from compas_fab .backends .ros .messages import ExecuteTrajectoryResult
13+ from compas_fab .backends .ros .messages import FollowJointTrajectoryFeedback
1314from compas_fab .backends .ros .messages import FollowJointTrajectoryGoal
1415from compas_fab .backends .ros .messages import FollowJointTrajectoryResult
1516from compas_fab .backends .ros .messages import Header
1617from compas_fab .backends .ros .messages import JointTrajectory as RosMsgJointTrajectory
1718from compas_fab .backends .ros .messages import JointTrajectoryPoint as RosMsgJointTrajectoryPoint
19+ from compas_fab .backends .ros .messages import MoveItErrorCodes
1820from compas_fab .backends .ros .messages import RobotTrajectory
1921from compas_fab .backends .ros .messages import Time
2022from compas_fab .backends .ros .planner_backend_moveit import MoveItPlanner
21- from compas_fab .backends .tasks import CancellableTask
23+ from compas_fab .backends .tasks import CancellableFutureResult
2224
2325__all__ = [
2426 'RosClient' ,
2931}
3032
3133
32- class CancellableRosAction ( CancellableTask ):
34+ class CancellableRosActionResult ( CancellableFutureResult ):
3335 def __init__ (self , goal ):
36+ super (CancellableRosActionResult , self ).__init__ ()
3437 self .goal = goal
3538
3639 def cancel (self ):
37- """Attempt to cancel the task .
40+ """Attempt to cancel the action .
3841
3942 If the task is currently being executed and cannot be cancelled
4043 then the method will return ``False``, otherwise the call will
4144 be cancelled and the method will return ``True``.
4245 """
46+ if self .done :
47+ raise Exception ('Already completed action cannot be cancelled' )
48+
49+ if self .goal .is_finished :
50+ return False
51+
4352 self .goal .cancel ()
4453
54+ # NOTE: Check if we can output more meaning results than just "we tried to cancel"
55+ return True
56+
4557
4658class RosClient (Ros ):
4759 """Interface to use ROS as backend via the **rosbridge**.
@@ -302,32 +314,43 @@ def follow_joint_trajectory(self, joint_trajectory, action_name='/joint_trajecto
302314 joint_trajectory = self ._convert_to_ros_trajectory (joint_trajectory )
303315 trajectory_goal = FollowJointTrajectoryGoal (trajectory = joint_trajectory )
304316
305- def handle_result (msg , client ):
317+ action_client = ActionClient (self , action_name , 'control_msgs/FollowJointTrajectoryAction' )
318+ goal = Goal (action_client , Message (trajectory_goal .msg ))
319+ action_result = CancellableRosActionResult (goal )
320+
321+ def handle_result (msg ):
306322 result = FollowJointTrajectoryResult .from_msg (msg )
307- callback (result )
323+ if result .error_code != FollowJointTrajectoryResult .SUCCESSFUL :
324+ ros_error = RosError (
325+ 'Follow trajectory failed={}' .format (result .error_string ),
326+ int (result .error_code ))
327+ action_result ._set_error_result (ros_error )
328+ if errback :
329+ errback (ros_error )
330+ else :
331+ action_result ._set_result (result )
332+ if callback :
333+ callback (result )
334+
335+ def handle_feedback (msg ):
336+ feedback = FollowJointTrajectoryFeedback .from_msg (msg )
337+ feedback_callback (feedback )
308338
309339 def handle_failure (error ):
310340 errback (error )
311341
312- action_client = ActionClient (self , action_name ,
313- 'control_msgs/FollowJointTrajectoryAction' )
314-
315- goal = Goal (action_client , Message (trajectory_goal .msg ))
316-
317- if callback :
318- goal .on ('result' , lambda result : handle_result (
319- result , action_client ))
342+ goal .on ('result' , handle_result )
320343
321344 if feedback_callback :
322- goal .on ('feedback' , feedback_callback )
345+ goal .on ('feedback' , handle_feedback )
323346
324347 if errback :
325348 goal .on ('timeout' , lambda : handle_failure (
326- RosError (" Action Goal timeout" , - 1 )))
349+ RosError (' Action Goal timeout' , - 1 )))
327350
328351 goal .send (timeout = timeout )
329352
330- return CancellableRosAction ( goal )
353+ return action_result
331354
332355 def execute_joint_trajectory (self , joint_trajectory , action_name = '/execute_trajectory' , callback = None , errback = None , feedback_callback = None , timeout = 60000 ):
333356 """Execute a joint trajectory via the MoveIt infrastructure.
@@ -355,17 +378,29 @@ def execute_joint_trajectory(self, joint_trajectory, action_name='/execute_traje
355378
356379 Returns
357380 -------
358- :class:`CancellableTask `
359- An instance of a cancellable tasks .
381+ :class:`CancellableFutureResult `
382+ An instance of a cancellable future result .
360383 """
361384
362385 joint_trajectory = self ._convert_to_ros_trajectory (joint_trajectory )
363386 trajectory = RobotTrajectory (joint_trajectory = joint_trajectory )
364387 trajectory_goal = ExecuteTrajectoryGoal (trajectory = trajectory )
365388
389+ action_client = ActionClient (self , action_name , 'moveit_msgs/ExecuteTrajectoryAction' )
390+ goal = Goal (action_client , Message (trajectory_goal .msg ))
391+ action_result = CancellableRosActionResult (goal )
392+
366393 def handle_result (msg ):
367394 result = ExecuteTrajectoryResult .from_msg (msg )
368- callback (result )
395+ if result .error_code != MoveItErrorCodes .SUCCESS :
396+ ros_error = RosError ('Execute trajectory failed. Message={}' .format (result .error_code .human_readable ), int (result .error_code ))
397+ action_result ._set_error_result (ros_error )
398+ if errback :
399+ errback (ros_error )
400+ else :
401+ action_result ._set_result (result )
402+ if callback :
403+ callback (result )
369404
370405 def handle_feedback (msg ):
371406 feedback = ExecuteTrajectoryFeedback .from_msg (msg )
@@ -374,18 +409,14 @@ def handle_feedback(msg):
374409 def handle_failure (error ):
375410 errback (error )
376411
377- action_client = ActionClient (self , action_name , 'moveit_msgs/ExecuteTrajectoryAction' )
378- goal = Goal (action_client , Message (trajectory_goal .msg ))
379-
380- if callback :
381- goal .on ('result' , handle_result )
412+ goal .on ('result' , handle_result )
382413
383414 if feedback_callback :
384415 goal .on ('feedback' , handle_feedback )
385416
386417 if errback :
387- goal .on ('timeout' , lambda : handle_failure (RosError (" Action Goal timeout" , - 1 )))
418+ goal .on ('timeout' , lambda : handle_failure (RosError (' Action Goal timeout' , - 1 )))
388419
389420 goal .send (timeout = timeout )
390421
391- return CancellableRosAction ( goal )
422+ return action_result
0 commit comments