Skip to content

grvc-robotics-lab/grvc-bt

Repository files navigation


GRVC Behavior Trees ROS

Behavior Tree wrapper for UAVs in ROS

Overview

This package provides a wrapper for ROS and UAVs.

Support ROS version

  • melodic
  • noetic

Build up environment

  1. git clone the repo.
mkdir -p ~/bt_ros1_ws/src
cd ~/bt_ros1_ws/src
git clone https://github.com/miggilcas/grvc-bt.git
  1. Install dependencies
cd ~/bt_ros1_ws
cd src/grvc-bt 
./configure.sh # and follow the steps
  1. Build
cd ~/bt_ros1_ws
catkin build

Tutorial: Creating Custom Behavior Tree Nodes in UBT Library

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.


1. Understand Node Types

  • Condition Nodes: Evaluate a state and return SUCCESS or FAILURE.
    • 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.

2. Create a Custom Node

Step 1: Define the Node Class

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

Step 2: Implement Node Logic

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;
  }
}

Step 3: Register the Node

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;
}

3. Example Tree Design in XML

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>

4. Debugging Tips

  1. Logging: Add detailed logs using ROS_INFO, ROS_WARN, or std::cout:
    ROS_INFO("[LowBatteryCondition] Tick completed.");
  2. Testing: Use test nodes to validate each node independently.
  3. Visual Debugging: Use BehaviorTree.CPP loggers (e.g., BT::StdCoutLogger) to visualize execution.

5. Checklist for Creating Nodes

  • Define the class and inherit from the appropriate node type.
  • Implement required methods:
    • tick() for SyncActionNode and AsyncActionNode.
    • onStart, onRunning, and onHalted for StatefulActionNode.
  • Register the node in the factory.
  • Integrate the node in XML or programmatically.

Help / Contribution

  • Contact: Miguel Gil Castilla (mgil8@us.es)

  • Found a bug? Create an ISSUE!

  • Do you want to contribute? Create a PULL-REQUEST!


Acknowledgments

Finally I want to thank the following packages or URLs that inspired us to create the tool.



About

Behavior Tree wrapper for UAVs in ROS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published