The blackboard is the main data storage component of the behavior tree in mr_bt which contains ROS messages, and other variables vital to the function of your program. The variables in the blackboard will be defined in your tree JSON or throughout multiple tree JSONs in your project.
The blackboard is, at its core, just a referece to a python dictionary that gets passed down through each node recursively in your tree. All nodes called in your tree have access to the same python dictionary so they can share information.
Let's start off with defining a blackboard that has two input variables: max_speed
and goal_position
. You want to define these two variables yourself at the root of your tree, so your tree JSON root.json
should look something like this:
You can see that the blackboard is defined within the node with the keyword "blackboard"
and the value being another JSON dictionary containing the key, value pairs of the blackboard variables.
Let's say you want a few variables in your blackboard to keep track of where your robot is, and whether it has reached a certain position. You want your variables to be called current_position
and reached_position
.
The various nodes within your tree will update these variables with the correct information when the tree is executed, however you don't want to populate them yourself. In this case, you can simply define the blackboard as so:
Since your other nodes will populate these values upon execution of the tree, you can initialize them as null
.
You'll likely need to subscribe to ROS messages coming from either your robot, or other ros programs in your behavior tree. In order to program your behavior tree to subscribe to these messages, you must define them in the blackboard as a special case.
For example, let's say you need want to use the GetPosition
node to populate the current_position
variable from the previous example. The GetPosition
node uses an Odometry
message to get the current positionof the robot, so your blackboard should look like this:
You'll notice that in the special case of subscribing to a ROS topic in the blackboard, the name of the variable is preceded with a /
, and the value is the name of the ROS message type. This will be the case for any ROS topic subscription in your behavior tree.
Likely you will split your project up into multiple different files, and it will be difficult to consolidate all of the required blackboard variables and ROS topic subscriptions into one blackboard definition. Luckily, you don't need to do that.
You can define different sections of the blackboard in different JSON files, and all of the different blackboard definitions will be combined into one upon compilation of your tree.
For example, if you have two files in your tree each with a different blackboard definition such as:
And then
The final functional blackboard will be
The mr_bt project allows users to define behavior trees as JSON files. Each node in the behavior tree is a JSON dictionary object, for example:
When building a new project create a new folder with the name of your project in mr_bt/src/tree_jsons
.
Each behavior tree project must have a root JSON file named root.json
. This file will define the root node of your behavior tree and must be unique in your project folder. For example if you want to make a new project named my_new_bt_project
, your folder structure should look something like this:
The usage of the included nodes can be generalized to a few rules.
All of the included nodes exist within python files inside the folder mr_bt/src/nodes/
. The files themselves are using the snake naming convention, for example: my_bt_node
. The classes inside each file uses the CapWords naming convention conversion of the file name, for example: class MyBtNode:
. When calling the node in a JSON tree, use reference the "type"
with the CapWords name of the node class, i.e.
The arguments passed into the node definition in the tree JSON should exactly match the names of the arguments defined in the python class __init__
function, for example if the class definition looks like this:
Your tree JSON should look like this:
The usage of parent nodes follows the same rules as the usage of the leaf nodes, however all parent nodes require their children to be defined in the tree JSON as well. The children are defined as a list of nodes within the "children"
agument of the parent node. Here is an example parent node with two children:
Due to the recursively defined nature of the behavior tree, the JSON definitions can get messy and unreadable for larger trees. The solution for splitting up different parts of your tree is using a reference to another JSON within your workspace instead of an entire node or tree definition.
Anywhere you could include a node or tree definition, you could instead reference another JSON using the "ref"
keyword. The root directory of the tree parser is set to mr_bt/src/tree_jsons/
, so your reference provided must be relative to that root directory.
For example, let's say that you are creating a new behavior tree in the folder mr_bt/src/tree_jsons/my_new_tree/
and your folder contains the following:
You want to include move.json
and calculate_dist.json
as children for a parent node in root.json
. This is what that would look like
You can also make references to other behavior tree JSONs as long as they are in the directory mr_bt/src/tree_jsons
by providing their path within that directory.