Skip to main content
Version: 7

Behavior Specialization and Usage Examples

note

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:

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 from AsyncBehaviorBase. It returns a shared_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 from AsyncBehaviorBase. It returns a shared_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 from AsyncBehaviorBase. It returns a shared_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.