Behavior Specialization and Usage Examples
This guide discusses advanced Behavior usage and assumes an understanding of C++ template specialization.
For preliminary reading, please refer to:
Behavior Examples
A comprehensive collection of example Behaviors can be found in the example_behaviors package.
To edit, build, test, and run them, ensure there is no COLCON_IGNORE
present in the example_behaviors
package while using the moveit_pro_example_ws.
They can then be built and added to an Objective of your choosing.
Using Custom ROS 2 Message, Service, and Action types
Behaviors that require interaction with ROS interfaces (such as Topics, Services, and Actions) must have their interface type defined at compile time. The majority of the code to interact with these interfaces can be considered boilerplate, so we provide convenience classes. The classes are templated, allowing you to specialze them with any types you have available in your workspace.
In this how to guide, we will discuss the following ROS interactions:
- Publishing a Message to a Topic
- Getting a Message from a Topic and placing it on the Blackboard
- Calling a Service and placing the response on the Blackboard
- Calling an Action
Using MoveIt Pro Behavior Templates
Publish a Message to a Topic
Publishing a message does not require any template specialization, simply add a std::shared_ptr<rclcpp::Publisher<MESSAGE_TYPE>>
class member variable to an AsyncBehaviorBase
and publish a message in the doWork()
method.
The API documentation for the AsyncBehaviorBase
class is here.
Get a Message from a Topic
The API documentation for the GetMessageFromTopicBehaviorBase
class is here.
It can be specialized to to create a custom Behavior that subscribes to a topic, waits until it receives a message on that topic, and then sets the message it received as an output data port.
The GetMessageFromTopicBehaviorBase
class itself inherits from AsyncBehaviorBase
, which has the following virtual functions that must be implemented in the new class as well.
getWaitForMessageTimeout
is an optional function used to set the timeout used when waiting for a message to be received on the topic. This is left as default in this example (no timeout).getFuture
must be implemented for all classes derived fromAsyncBehaviorBase
. It returns ashared_future
class member.
Call a Service
To create a custom Behavior that creates a service request, waits until it receives a response from the service server, and then sets the response it received as an output data port, you can specialize the ServiceClientBehaviorBase
class for the service type of your choice.
The API documentation for the ServiceClientBehaviorBase
class is here.
The ServiceClientBehaviorBase
class itself inherits from AsyncBehaviorBase
, which has the following virtual functions that must be implemented in the new class as well:
getServiceName
is used to get the name of the service when initializing the service client.createRequest
is used to to create the service request. In this example, we will make the request from data specified from input ports.getResponseTimeout
is an optional function used to set the timeout used when waiting for the service response. This is left as default in this example (no timeout).processResponse
is an optional function used to process the service response after the service has finished. In this example, we will make the response available on an output port.getFuture
must be implemented for all classes derived fromAsyncBehaviorBase
. It returns ashared_future
class member.
Call an Action
To create a custom Behavior that creates an action goal request, processes feedback, and processes results, you can specialize the ActionClientBehaviorBase
class for the action type of your choice.
The API documentation for the ActionClientBehaviorBase
class is here.
The ActionClientBehaviorBase
class itself inherits from AsyncBehaviorBase
, which has the following virtual functions that must be implemented in the new class as well.
getActionName
is used to get the name of the action when initializing the action client.createGoal
is used to function to create the action goal. In this example, we will make the goal from data specified from an input port.getResultTimeout
is an optional function used to set the timeout used when waiting for the action result. This is left as default in this example (no timeout).processResult
is used to process the result from the action server. In this example, we will log the result and make it available on an output port.processFeedback
is used to process the feedback from the action server. In this example, we will log the feedback and make it available on an output port.getFuture
must be implemented for all classes derived fromAsyncBehaviorBase
. It returns ashared_future
class member.
Conclusion
The examples above illustrate the best approach to interacting with ROS interfaces in MoveIt Pro. For a deeper dive in to the implementation details of Behaviors, please consult the API documentation. For a discussion of best practices when writing Behavior Tree Nodes, consult the Behavior Tree and Behavior Concepts page.