Note: This tutorial assumes that you have completed the previous tutorials: Preparing a new script (python), Using the move command (python).
(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Specify execution behaviour (python)

Description: This tutorial shows how to execute synchronous and asynchronous behaviour.

Tutorial Level: INTERMEDIATE

Next Tutorial: Using other commands (python)

Synchronizing motion

Wouldn't it be nice if you could start opening the hand for grasping while the arm is still moving? To do that you need to call functions non-blocking so that they run in the background. To make a function non-blocking set the optional third parameter of move to False.

   1         # move arm while opening gripper
   2         self.sss.move("arm_left","arm_to_tray",False)
   3         self.sss.move("gripper_left","open")

Now the gripper will start to move right after the arm has begun to move. As the arm trajectory is rather long, the gripper will reach its target position even before the arm.

Waiting for motion to finish

In the example above the components move at the same time. But how will you know, that the arm has finally arrived? You need to know that because otherwise you might open the hand to early and the object will drop! The solution is to assign a handle to the non-blocking function. You can call <handle>.wait() afterwards to ensure that the function call is finished.

So you should modify the code above and add the <handle>.wait() functionality to the arm movement.

   1         # move arm while opening gripper
   2         handle01 = self.sss.move("arm_left","arm_to_tray",False)
   3         self.sss.move("gripper","open")
   4 
   5         #wait for arm movement to be finished
   6         handle01.wait()

The wait function provides even more functionality. You can set a timeout, after which you stop waiting and go on with your script. Note that this timeout doesn't terminate the action running in the background. The wait function also returns the status code or exit code of the associated Move function, which allows you to check if the action had any errors.

Getting current state and error_code

If you assigned a handle to a move action you can ask for the current state and get an error_code, which indictes what kind of failure occoured. So let's modify the code above again to

   1         # move arm while opening gripper
   2         handle01 = self.sss.move("arm_left","arm_to_tray",False)
   3         self.sss.move("gripper","open")
   4 
   5         # print current state
   6         print handle01.get_state()
   7 
   8         #wait for arm movement to be finished
   9         handle01.wait()
  10 
  11         # print again current state and error_code
  12         print handle01.get_state()
  13         handle01.get_error_code()

If the movements are executed without error you should get state 1 for the first get_state() which means active. For the second get_state() the action should be finished so you get the state 2 for failed or 3 for succeeded. The return states of the get_state() function are the same as the return codes of the actionlib, see http://www.ros.org/doc/api/actionlib_msgs/html/msg/GoalStatus.html.

To know what went wrong you can have a look at the error_code from get_error_code(). The error_code is 0 if all was successfully or otherwise an integer value indicating the reason for the failure.

Wiki: cob_script_server/Tutorials/Specify execution behaviour (python) (last edited 2019-09-24 11:25:57 by HannesBachter)