Skip to content

Blackboard

A context can be any struct. When you want shared values without writing one, bt::Blackboard is a typed bag with one tag per value. A key's type is the only name it has, so a wrong key or a wrong value type is a compile error, and nothing is looked up at runtime or allocated.

#include <behavior_tree_lite/blackboard.hpp>

struct Battery : bt::Key<int> {};
struct Callsign : bt::Key<std::string> {};

using Board = bt::Blackboard<Battery, Callsign>;

Board board;
board.set<Battery>(80);
board.get<Callsign>() = "falcon";
int level = board.get<Battery>();

Values start value-initialised. get returns a reference, so it writes through. A key that is not in the board's list does not compile.

Use the board as the tree's context:

struct BatteryOk : bt::NodeBase {
    using EventType = Tick;
    using ContextType = Board;

    bt::Status process(const Tick&, Board& board) {
        return board.get<Battery>() > 20 ? bt::Status::Success : bt::Status::Failure;
    }
};

Two keys may hold the same value type; they do not share storage. Each key may appear once in a board.

Why tags and not string keys

ctx.get<int>("battery") needs a runtime map from strings to values, which means allocation and a lookup per access, and a typo fails when the robot runs. Tags move all of that to compile time. The price is that the set of keys is fixed when you write the board type.