ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Unable to use nav2 Behavior Tree Condition Node

asked 2022-10-05 02:35:23 -0500

I tried to include nav2 behavior tree to check whether battery is low.

Here is my main code:

#include <behaviortree_cpp_v3/loggers/bt_zmq_publisher.h>
#include "behaviortree_cpp_v3/bt_factory.h"
#include "behaviortree_cpp_v3/utils/shared_library.h"

#include <iostream>
#include "rclcpp/rclcpp.hpp"
#include "nav2_behavior_tree/plugins/condition/is_battery_low_condition.hpp"
#include "nav2_behavior_tree/behavior_tree_engine.hpp"


#define My_BT_XML "/home/robot/bt_ws/src/bt_test_pkg/bt_xml/example_bt.xml"

/* main class where you will initialize the behavior tree */
int main(int argc, char **argv)
{

  /* Initialize your tree */
  /* Pass the initialized tree to the ZMQ publisher */
  /* By adding following line you will be able to
     create a link between Groot and ROS */

  rclcpp::init(argc,argv);
  auto nh = rclcpp::Node::make_shared("BT_test");
  nh->declare_parameter("bt_xml",rclcpp::ParameterValue(std::string(My_BT_XML)));
  std::string bt_xml;
  nh->get_parameter("bt_xml",bt_xml);

  BT::BehaviorTreeFactory factory;
  BT::SharedLibrary loader;


  factory.registerNodeType<nav2_behavior_tree::IsBatteryLowCondition>("IsBatteryLow");


  //Tree is destoried when it goes out of scope

  //factory.registerFromPlugin(loader.getOSName("nav2_is_battery_low_condition_bt_node"));
  auto tree = factory.createTreeFromFile(bt_xml);

  BT::NodeStatus status = BT::NodeStatus::RUNNING;
  while (rclcpp::ok() && status == BT::NodeStatus::RUNNING) {
        status = tree.tickRoot();
        // Sleep 100 milliseconds
        std::cout<<status<<"\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }


  BT::PublisherZMQ publisher_zmq(tree);

  return 0;
}

I have written a fake battery level publisher:

#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/sensor_msgs/msg/battery_state.hpp"

using namespace std::chrono_literals;


class MinimalPublisher : public rclcpp::Node
{
  public:
    MinimalPublisher()
    : Node("battery_pub"), count_(0)
    {
      publisher_ = this->create_publisher<sensor_msgs::msg::BatteryState>("/battery_status",10);
      timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    void timer_callback()
    {
      auto batteryState_ = std::make_shared<sensor_msgs::msg::BatteryState>();
      batteryState_->percentage = 0.7;
      batteryState_->voltage = 8.5;
      publisher_->publish(*batteryState_);
    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<sensor_msgs::msg::BatteryState>::SharedPtr publisher_;
    size_t count_;
};



int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  rclcpp::shutdown();
  return 0;
}

The behavior tree is simply

<BehaviorTree ID="BehaviorTree">
        <Sequence>
            <Condition ID="IsBatteryLow" battery_topic="/battery_status" is_voltage="false" min_battery="0.5"/>
            <AlwaysSuccess/>
        </Sequence>
    </BehaviorTree>

However, when I run the publisher and BT tree code, I got the following error

terminate called after throwing an instance of 'BT::RuntimeError'
  what():  Blackboard::get() error. Missing key [node]
[ros2run]: Aborted
edit retag flag offensive close merge delete

Comments

The error message, i.e., Blackboard::get() error. Missing key [node] is quite useful in this case. If you run the node inside gdb, this exception can be captured. BTW, I found [1] and [2] questions reporting a similar problem.

ravijoshi gravatar image ravijoshi  ( 2022-10-05 04:50:43 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2022-10-05 13:59:05 -0500

You didn't include some of the elements that are required to be on the BT's blackboard for use. One such example of centralized assets we make available to all BT nodes is a node object so that they can create their own subscriptions or clients as required. All of that is taken care of for you if you use our provided BT factory in Nav2. Else, you'll need to make sure you have all the assets on the blackboard you give to the BT on initialization that they require in their implementations.

edit flag offensive delete link more

Comments

Thanks for the reply and I am really new to this. May I ask what are the elements that are missing in my case? I want to learn the implementation of both Nav2 and BehaviorTree CPP. I also wrote my own condition node by inherit BT::ConditionNode according to is_battery_low_condition.cpp.

Lastly, is there a boilerplate code using Nav2's custom nodes? I have been checking behavior_tree_engine.cpp and it looks like it automatically register all the nodes for you, but what is the proper way to use it?

Guang gravatar image Guang  ( 2022-10-06 01:02:22 -0500 )edit

You'd had to look at the BT nodes that you want to use and see what's missing, I can't know what all BT nodes you are using that require certain shared resources.

See the implementations of the BT nodes, there are dozens for you to reference :-)

stevemacenski gravatar image stevemacenski  ( 2022-10-06 12:16:49 -0500 )edit

Thanks! I will look into it.

Guang gravatar image Guang  ( 2022-10-07 01:15:27 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2022-10-05 02:35:23 -0500

Seen: 508 times

Last updated: Oct 05 '22