BehaviorTree
Core Library to create and execute Behavior Trees
Loading...
Searching...
No Matches
bt_flatbuffer_helper.h
1#pragma once
2
3#include "behaviortree_cpp/bt_factory.h"
4#include "behaviortree_cpp/flatbuffers/BT_logger_generated.h"
5
6namespace BT
7{
8
9using SerializedTransition = std::array<uint8_t, 12>;
10
11inline Serialization::NodeType convertToFlatbuffers(BT::NodeType type)
12{
13 switch(type)
14 {
15 case BT::NodeType::ACTION:
16 return Serialization::NodeType::ACTION;
17 case BT::NodeType::DECORATOR:
18 return Serialization::NodeType::DECORATOR;
19 case BT::NodeType::CONTROL:
20 return Serialization::NodeType::CONTROL;
21 case BT::NodeType::CONDITION:
22 return Serialization::NodeType::CONDITION;
23 case BT::NodeType::SUBTREE:
24 return Serialization::NodeType::SUBTREE;
25 case BT::NodeType::UNDEFINED:
26 return Serialization::NodeType::UNDEFINED;
27 }
28 return Serialization::NodeType::UNDEFINED;
29}
30
31inline Serialization::NodeStatus convertToFlatbuffers(BT::NodeStatus type)
32{
33 switch(type)
34 {
35 case BT::NodeStatus::SKIPPED:
36 case BT::NodeStatus::IDLE:
37 return Serialization::NodeStatus::IDLE;
38 case BT::NodeStatus::SUCCESS:
39 return Serialization::NodeStatus::SUCCESS;
40 case BT::NodeStatus::RUNNING:
41 return Serialization::NodeStatus::RUNNING;
42 case BT::NodeStatus::FAILURE:
43 return Serialization::NodeStatus::FAILURE;
44 }
45 return Serialization::NodeStatus::IDLE;
46}
47
48inline Serialization::PortDirection convertToFlatbuffers(BT::PortDirection direction)
49{
50 switch(direction)
51 {
52 case BT::PortDirection::INPUT:
53 return Serialization::PortDirection::INPUT;
54 case BT::PortDirection::OUTPUT:
55 return Serialization::PortDirection::OUTPUT;
56 case BT::PortDirection::INOUT:
57 return Serialization::PortDirection::INOUT;
58 }
59 return Serialization::PortDirection::INOUT;
60}
61
62inline void CreateFlatbuffersBehaviorTree(flatbuffers::FlatBufferBuilder& builder,
63 const BT::Tree& tree)
64{
65 std::vector<flatbuffers::Offset<Serialization::TreeNode>> fb_nodes;
66
67 applyRecursiveVisitor(tree.rootNode(), [&](BT::TreeNode* node) {
68 std::vector<uint16_t> children_uid;
69 if(auto control = dynamic_cast<BT::ControlNode*>(node))
70 {
71 children_uid.reserve(control->children().size());
72 for(const auto& child : control->children())
73 {
74 children_uid.push_back(child->UID());
75 }
76 }
77 else if(auto decorator = dynamic_cast<BT::DecoratorNode*>(node))
78 {
79 const auto& child = decorator->child();
80 children_uid.push_back(child->UID());
81 }
82
83 // Const cast to ensure public access to config() overload
84 const auto& node_config = const_cast<BT::TreeNode const&>(*node).config();
85 std::vector<flatbuffers::Offset<Serialization::PortConfig>> ports;
86 for(const auto& it : node_config.input_ports)
87 {
88 ports.push_back(Serialization::CreatePortConfigDirect(builder, it.first.c_str(),
89 it.second.c_str()));
90 }
91 for(const auto& it : node_config.output_ports)
92 {
93 ports.push_back(Serialization::CreatePortConfigDirect(builder, it.first.c_str(),
94 it.second.c_str()));
95 }
96
97 auto tn = Serialization::CreateTreeNode(
98 builder, node->UID(), builder.CreateVector(children_uid),
99 convertToFlatbuffers(node->status()), builder.CreateString(node->name().c_str()),
100 builder.CreateString(node->registrationName().c_str()),
101 builder.CreateVector(ports));
102
103 fb_nodes.push_back(tn);
104 });
105
106 std::vector<flatbuffers::Offset<Serialization::NodeModel>> node_models;
107
108 for(const auto& node_it : tree.manifests)
109 {
110 const auto& manifest = node_it.second;
111 std::vector<flatbuffers::Offset<Serialization::PortModel>> port_models;
112
113 for(const auto& port_it : manifest.ports)
114 {
115 const auto& port_name = port_it.first;
116 const auto& port = port_it.second;
117 auto port_model = Serialization::CreatePortModel(
118 builder, builder.CreateString(port_name.c_str()),
119 convertToFlatbuffers(port.direction()),
120 builder.CreateString(demangle(port.type()).c_str()),
121 builder.CreateString(port.description().c_str()));
122 port_models.push_back(port_model);
123 }
124
125 auto node_model = Serialization::CreateNodeModel(
126 builder, builder.CreateString(manifest.registration_ID.c_str()),
127 convertToFlatbuffers(manifest.type), builder.CreateVector(port_models));
128
129 node_models.push_back(node_model);
130 }
131
132 auto behavior_tree = Serialization::CreateBehaviorTree(
133 builder, tree.rootNode()->UID(), builder.CreateVector(fb_nodes),
134 builder.CreateVector(node_models));
135
136 builder.Finish(behavior_tree);
137}
138
139/** Serialize manually the information about state transition
140 * No flatbuffer serialization here
141 */
142inline SerializedTransition SerializeTransition(uint16_t UID, Duration timestamp,
143 NodeStatus prev_status, NodeStatus status)
144{
145 using namespace std::chrono;
146 SerializedTransition buffer;
147 int64_t usec = duration_cast<microseconds>(timestamp).count();
148 int64_t t_sec = usec / 1000000;
149 int64_t t_usec = usec % 1000000;
150
151 flatbuffers::WriteScalar(&buffer[0], t_sec);
152 flatbuffers::WriteScalar(&buffer[4], t_usec);
153 flatbuffers::WriteScalar(&buffer[8], UID);
154
155 flatbuffers::WriteScalar(&buffer[10],
156 static_cast<int8_t>(convertToFlatbuffers(prev_status)));
157 flatbuffers::WriteScalar(&buffer[11],
158 static_cast<int8_t>(convertToFlatbuffers(status)));
159
160 return buffer;
161}
162
163} // namespace BT
The ControlNode is the base class for nodes that can have multiple children.
Definition: control_node.h:32
The DecoratorNode is the base class for nodes that have exactly one child.
Definition: decorator_node.h:19
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:96
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:154
const NodeConfig & config() const
Definition: action_node.h:24
NodeStatus
Definition: basic_types.h:34
SerializedTransition SerializeTransition(uint16_t UID, Duration timestamp, NodeStatus prev_status, NodeStatus status)
Definition: bt_flatbuffer_helper.h:142