berkeleyauv / behavior_tree

ROS2 package for managing the AUV's behavior using BTCPP behavior trees.
10 stars 2 forks source link

behavior_tree

ROS2 package for managing the AUV's behavior using BTCPP behavior trees. BTCPP documentation can be found at https://www.behaviortree.dev. The github repository which contains examples and source code can be found here. To visualize the behavior trees checkout Groot and download the latest AppImage under releases.

For a good reference implementation of BTCPP with ROS2 checkout navigation2.


Overview

This package provides abstractions that make building a extensible behavior trees with ROS2 easy. The general development flow for adding new behaviors and functionality to the AUV can be summarized in the following steps:

  1. Implement the task or process as a ROS2 service or action server completely independent of the behavior tree.
  2. Create a new behavior tree node inheriting from either BtService or BtAction
  3. Implement the virtual functions in a C++ plugin and override any other functions to get the desired behavior when the node is called in the tree.
  4. Compile the plugin and and add the node to the tree.

BtService and BtAction are both contained entirely in header files so no static linking is required to work with them.

BtEngine

This is the only executable in this repository and is responsible for loading the behavior tree xml and plugins and then executing the behavior tree. BtEngine is run as a ROS node and has the default name bt_engine not to be confused with the additional node that this process will create which is used by BtService and BtAction with the default name bt_node.

Program Flow

Parameters

Name Default Description
bt_file_path "tree.xml" File path to the xml file to load
loop_timeout 100 Time between tree ticks in milliseconds
plugins [] List of plugins names for custom tree nodes, example ['fibonacci_bt_node']
run_groot_monitoring true Rather or not to publish debugging information for Groot
publisher_port 1666 ZMQ publisher port for Groot
server_port 1667 ZMQ server port for Groot
max_msg_per_second 25 ZMQ message rate limit for Groot

Note that all plugins specified in the plugins parameter should be pointed to by the LD_LIBRARY_PATH environment variable. This should be handled automatically when sourcing the ROS2 workspace but if issues come up you can check to make sure LD_LIBRARY_PATH is set correctly by running echo $LD_LIBRARY_PATH in the terminal where you are having issues running the behavior tree.

BtService

Provides the framework for a standard ROS2 service client. Implementation is done through overriding the ServiceT::Request::SharedPtr populate_request() and BT::NodeStatus handle_response(ServiceT::Response::SharedPtr response) methods. Adding additional ports can be done by overriding BT::PortsList providedPorts().

Program Flow

On tick

Basic Ports

Name Default Description
server_timeout None timeout for wait_for_service
server_name None name of the service to call

BtAction

Provides the framework for a standard ROS2 action client. Implementation is done through overriding ActionT::Goal populate_goal(). Adding additional ports can be done by overriding BT::PortsList providedPorts(). Canceling actions is done by halting the node which can be accomplished by using something like a reactive sequence with an action or condition node preceding the BtAction node which, upon returning FAILURE, will cause the reactive sequence to halt the BtAction node which will subsequently cancel the action over ROS2.

Program Flow

On tick

send_goal

process_goal_status

Basic Ports

Name Default Description
server_timeout None timeout for accepting goal and wait_for_action_server
cancel_timeout None timeout for action cancelation to be accepted
server_name None name of the service to call

Creating a custom ROS2 action/service client node

Action Service Example

Action Client Example

  1. Create a new .cpp file for the desired node, typically this will be in plugins/action within a ROS2 package
  2. The cpp file should contain a class that inherits public BtAction<ActionType> or public BtService<ServiceType>, we will override the necessary methods to generate a fully implemented behavior tree node.
  3. For action client override the ActionType::Goal populate_goal() method, for a service client override ServiceType::Request::SharedPtr populate_request() and BT::NodeStatus handle_response(ServiceType::Response::SharedPtr response).
  4. (Optional) Override the static PortsList providedPorts() method to add additional ports, the code should look similar to the below example code segment
    static PortsList providedPorts() {
     return providedBasicPorts({InputPort<geometry_msgs::msg::Vector3>("distances")});
    }
  5. Add the following code segment, changing the Type and ClientNodeName based on your setup. The name that you set here is the name that will be used in the tree.xml.
    BT_REGISTER_NODES(factory) {
     factory.registerNodeType<Type>("ClientNodeName");
    }
  6. See the Building Nodes section

Building Nodes

Add package dependencies to the CMakeLists.txt and add the following snippet adapted to your behavior tree node

add_library(name_bt_node SHARED plugins/action/name.cpp)
list(APPEND plugin_libs name_bt_node)

The CMakeLists.txt should include the following supporting code

set(dependencies
        rclcpp
        ...
        )

<<<List of plugin specific segments resembling the above code snippet>>>

foreach(bt_plugin ${plugin_libs})
  ament_target_dependencies(${bt_plugin} ${dependencies})
  target_compile_definitions(${bt_plugin} PRIVATE BT_PLUGIN_EXPORT)
endforeach()

install(TARGETS ${plugin_libs}
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
        )