The ROS2 Humble package offers a starting point for high-level task control of your robotic application. It is based on the BehaviorTree.CPP framework.
OTHER License
This package uses the BehaviorTree.IRAS framework which is a wrapper around the BehaviorTree.cpp v3.8 library and extends it for the combined use of behavior trees with ROS 2 Humble.
The IRAS Coordinator offers a starting point for high-level task control of your robotic application. Just clone this package and change the git remote and develop behaviors for your own custom project.
git clone -b humble https://github.com/AndreasZachariae/iras_coordinator.git
cd iras_coordinator
git remote remove origin
git remote add origin <your_repo_adress>
The library of actions can be arranged freely with the graphical user interface Groot.
Build and start the docker container
source build_docker.sh
source start_docker.sh
Inside the container launch the Coordinator node with parameters
ros2 launch iras_coordinator test.launch.py
To view or modify the behavior trees, attach a new shell and start Groot
docker exec -it coordinator bash
ros2 run groot Groot
Install VSCode extension:
Mount settings folder .vscode to target directory for development
# Add parameter to docker run command
-v $PWD/.vscode:/home/docker/ros2_ws/src/.vscode
source start_docker.sh
ROS
and C/C++
extension in containerTasks: Run Task
and Build
Start the docker container as normal
source start_docker.sh
If new BT nodes were added or ports changed regenerate the GrootPalette by starting a test BT.
# in ~/ros2_ws/
colcon build
ros2 launch iras_coordinator test.launch.py
Start Groot in Editor mode
ros2 run groot Groot
# Click "Editor" and "START"
Load GrootPalette with all custom nodes.
Click on -> to load palette from file.
Choose the file from: /home/docker/ros2_ws/src/iras_coordinator/behaviors/GrootPalette.xml
Build BT via drag and drop
Save tree to file.
Click on -> to save.
Choose location as: /home/docker/ros2_ws/src/iras_coordinator/behaviors/<your_folder_name>/
Modify config parameter
# in /home/docker/ros2_ws/src/iras_coordinator/config/params.yaml
main_tree_path: "/home/docker/ros2_ws/src/iras_coordinator/behaviors/<your_folder_name>/<your_tree_name>.xml"
OR create a new launch file with this parameter
# in /home/docker/ros2_ws/src/iras_coordinator/launch/<your_launch_file>.launch.py>
parameters=[{'main_tree_path': "/home/docker/ros2_ws/src/iras_coordinator/behaviors/<your_folder_name>/<your_tree_name>.xml",
'groot_palette_path': "/home/docker/ros2_ws/src/iras_coordinator/behaviors/GrootPalette.xml"}],
Launch your node
There are currently 4 different types of nodes supported:
This instructions gives an example for a ROS2 action client
iras_coordinator/include/iras_coordinator/actions
. For this, copy an existing file from that folder and rename. Use this structure as template. Copy MoveBase.h
and rename to MyCustomActionNode.h
.iras_coordinator/src/actions
. Copy MoveBase.cpp
and rename to MyCustomActionNode.cpp
.#include <iras_coordinator/actions/MoveBase.h>
// in MyCustomActionNode.cpp
#include <iras_coordinator/actions/MyCustomActionNode.h>
MyCustomActionNode.h
include the header files of your ROS2 interface you want to use. In this example it is located in the iras_interfaces
package.#include <nav2_msgs/action/navigate_to_pose.hpp>
MyCustomAction.action
(PascalCase) the generated header will be my_custom_action.hpp
(snake_case).
// in MyCustomActionNode.h
#include <iras_interfaces/action/my_custom_action.hpp>
using NavigateToPoseAction = nav2_msgs::action::NavigateToPose;
// in MyCustomActionNode.h
using MyCustomAction = iras_interfaces::action::MyCustomAction;
.ccp
and .h
file. Use VSCode find and replace (strg + f) or rename symbol (F2) shortcut.class MoveArm : public RosAction<MoveArmMoveIt>
// in MyCustomActionNode.h
class MyCustomActionNode : public RosAction<MyCustomAction>
.ccp
with new one. Use VSCode find and replace (strg + f) or rename symbol (F2) shortcut.std::string MoveBase::ros2_action_name()
// in MyCustomActionNode.cpp
// for every function
std::string MyCustomActionNode::ros2_action_name()
/* ... */
// in MyCustomActionNode.cpp
std::string MyCustomActionNode::ros2_action_name()
{
return "my_custom_action_topic";
}
// in MyCustomActionNode.cpp
/* New port:
* direction = [BT::InputPort, BT::OutputPort, BT::BidirectionalPort]
* data_type = <[float, int, std::string]>
* name = ("name") */
BT::PortsList MyCustomActionNode::providedPorts()
{
return {BT::InputPort<std::string>("string_input"),
BT::OutputPort<float>("float_output"),
BT::BidirectionalPort<int>("int_bidirectional")
/* ... */};
}
// in MyCustomActionNode.cpp
void MyCustomActionNode::on_send(MyCustomAction::Goal &goal)
{
goal.header.frame_id = "custom_frame";
goal.header.stamp = get_node_handle()->now();
/* ... */
log("Custom goal sent");
}
// in MyCustomActionNode.cpp
void MyCustomActionNode::on_feedback(const std::shared_ptr<const NavigateToPoseAction::Feedback> feedback)
{
/* ... */
log("Feedback no. " + std::to_string(feedback.counter) + " recieved");
}
// in MyCustomActionNode.cpp
void MyCustomActionNode::on_result(const rclcpp_action::ClientGoalHandle<MyCustomAction>::WrappedResult &result, const MyCustomAction::Goal &goal)
{
/* ... */
log("Action finished");
}
iras_coordinator/src/node.cpp
// in node.cpp
#include <iras_coordinator/actions/MyCustomActionNode.h>
// in node.cpp
factory.registerNodeType<MyCustomActionNode>("MyCustomActionNode");
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
this->declare_parameter("my_str", rclcpp::PARAMETER_STRING);
what(): std::future_error: No associated state
https://github.com/ros2/rclcpp/issues/1968