|Deletions are marked like this.||Additions are marked like this.|
|Line 37:||Line 37:|
|Line 57:||Line 58:|
|# Run the server||# Run the server in a background thread|
|Line 59:||Line 60:|
# Wait for control-c
|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.|
Wrapping a Container With actionlibDescription: This tutorial explains how to serve out a SMACH plan as an action over actionlib.
Tutorial Level: INTERMEDIATE
Wrapping a SMACH State
SMACH provides the top-level container called ActionServerWrapper. This class advertises an actionlib action server. Instead of being executed by a parent, it's contained state goes active when the action server receives a goal. Accordingly, this container does not inherit from the smach.State base class and cannot be put inside of another container.
The action server wrapper can inject the goal message received by the action server into the contained state, as well as extract the result message from that state when it terminates. When constructing the action server wrapper, the user specifies which state machine outcomes correspond to a succeeded, aborted, or preempted result.
Consider this example, which wraps a SMACH state machine as an action:
1 import rospy 2 3 from smach import StateMachine 4 from smach_ros import ActionServerWrapper 5 6 # Construct state machine 7 sm = StateMachine(outcomes=['did_something', 8 'did_something_else', 9 'aborted', 10 'preempted']) 11 with sm: 12 ### Add states in here... 13 14 # Construct action server wrapper 15 asw = ActionServerWrapper( 16 'my_action_server_name', MyAction, 17 wrapped_container = sm, 18 succeeded_outcomes = ['did_something','did_something_else'], 19 aborted_outcomes = ['aborted'], 20 preempted_outcomes = ['preempted'] ) 21 22 # Run the server in a background thread 23 asw.run_server() 24 25 # Wait for control-c 26 rospy.spin()
Getting The Goal/Result Messages Into/Out Of The Contained State
The above code will call sm.execute(), but it will not load the goal into the contained state machine, nor will it extract a result. In order to do these things, you need to tell the action server wrapper what it should call the goal and result messages in the context of SMACH. You can replace the action server wrapper construction call with the following:
The keyword arguments goal_key and result_key are the SMACH userdata keys in the context of the ActionServerWrapper. Like any other container, this means that the wrapper's contained state (in this case the state machine sm) will receive a reference to this userdata structure when its execute() method is called. Similarly to how userdata is passed between scopes in nested state machines, in this case, you need to set these key identifiers in the state machine sm as well.
In order to copy in the keys form the parent, you can replace the construction call for the state machine sm with this:
Once you have done this, you can access these keys from any state added to sm. For more goal/result policies, see the ActionServerWrapper API documentation.