This package provides a wrapper for ROS and UAVs.
- melodic
- noetic
- git clone the repo.
mkdir -p ~/bt_ros1_ws/src
cd ~/bt_ros1_ws/src
git clone https://github.com/miggilcas/grvc-bt.git
- Install dependencies
cd ~/bt_ros1_ws
cd src/grvc-bt
./configure.sh # and follow the steps
- Build
cd ~/bt_ros1_ws
catkin build
This tutorial demonstrates how to extend the UBT library by creating your own Behavior Tree (BT) nodes. We'll cover Condition Nodes, Action Nodes, and Stateful Nodes, focusing on their integration into the system and practical implementation. Below are the steps, enriched with examples from your ubt.cpp
file.
- Condition Nodes: Evaluate a state and return
SUCCESS
orFAILURE
.- Example: Detecting a low battery or geofence violation.
- Action Nodes: Perform actions with potential intermediate states (
RUNNING
).- Example: Takeoff or landing actions.
- Stateful Nodes: Maintain internal state and implement lifecycle hooks (
onStart
,onRunning
,onHalted
).- Example: Mission configuration or emergency handling.
The node must inherit from the appropriate base class:
BT::SyncActionNode
: For synchronous tasks or conditions.BT::AsyncActionNode
: For asynchronous actions.BT::StatefulActionNode
: For stateful operations.
Example: LowBatteryCondition Node
#include <uav_behavior_trees/backend.h>
#include <behaviortree_cpp_v3/bt_factory.h>
namespace grvc {
namespace ubt {
class LowBatteryCondition : public BT::SyncActionNode {
public:
LowBatteryCondition(const std::string &name,
const BT::NodeConfiguration &config,
Backend *backend)
: BT::SyncActionNode(name, config), _backend(backend) {}
// Define the tick function logic
BT::NodeStatus tick() override {
ros::spinOnce();
ROS_INFO("[LowBatteryCondition] Evaluating...");
if (_backend->detectLowBattery()) {
ROS_WARN("Low battery detected!");
return BT::NodeStatus::FAILURE;
}
return BT::NodeStatus::SUCCESS;
}
static BT::PortsList providedPorts() { return {}; }
private:
Backend *_backend; // Access to shared backend functionality
};
} // namespace ubt
} // namespace grvc
Customize your node to perform a specific action or evaluate a condition. For example, TakeOffAction from your implementation:
BT::NodeStatus TakeOffAction::tick() {
ros::spinOnce();
auto height = getInput<std::string>("height");
if (!height) {
throw BT::RuntimeError("Missing required input: height", height.error());
}
double takeoff_height = convertFromString<double>(height.value());
int status = _backend->takeOff(takeoff_height);
switch (status) {
case 0:
return BT::NodeStatus::FAILURE;
case 1:
return BT::NodeStatus::SUCCESS;
default:
return BT::NodeStatus::RUNNING;
}
}
To use your custom node, register it with the BT::BehaviorTreeFactory
in your ROS node:
int main(int argc, char **argv) {
ros::init(argc, argv, "ubt_server");
BT::BehaviorTreeFactory factory;
grvc::ubt::Backend *backend = new grvc::ubt::Backend();
// Register custom nodes
factory.registerNodeType<grvc::ubt::TakeOffAction>("TakeOffAction", backend);
factory.registerNodeType<grvc::ubt::LowBatteryCondition>("LowBatteryCondition", backend);
// Load and execute tree
auto tree = factory.createTreeFromFile("path/to/tree.xml");
tree.tickRootWhileRunning();
delete backend;
return 0;
}
Design the Behavior Tree using XML to define task flow:
<root main_tree_to_execute="MainTree">
<ReactiveSequence>
<LowBatteryCondition/>
<TakeOffAction height="5.0"/>
<LandAction/>
</ReactiveSequence>
</root>
- Logging: Add detailed logs using
ROS_INFO
,ROS_WARN
, orstd::cout
:ROS_INFO("[LowBatteryCondition] Tick completed.");
- Testing: Use test nodes to validate each node independently.
- Visual Debugging: Use BehaviorTree.CPP loggers (e.g.,
BT::StdCoutLogger
) to visualize execution.
- Define the class and inherit from the appropriate node type.
- Implement required methods:
tick()
forSyncActionNode
andAsyncActionNode
.onStart
,onRunning
, andonHalted
forStatefulActionNode
.
- Register the node in the factory.
- Integrate the node in XML or programmatically.
-
Contact: Miguel Gil Castilla (mgil8@us.es)
-
Found a bug? Create an ISSUE!
-
Do you want to contribute? Create a PULL-REQUEST!
Finally I want to thank the following packages or URLs that inspired us to create the tool.