Skip to content

Commit f281703

Browse files
committed
extend the Groot example to reproduce issues with arrays
1 parent 1f9389d commit f281703

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

examples/t11_groot_howto.cpp

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#include "behaviortree_cpp/loggers/groot2_publisher.h"
88
#include "behaviortree_cpp/xml_parsing.h"
99

10+
#include <cstdlib>
11+
#include <string>
12+
#include <vector>
13+
1014
/** We are using the same example in Tutorial 5,
1115
* But this time we also show how to connect
1216
*/
@@ -28,7 +32,22 @@ BT_JSON_CONVERTER(Position2D, pos)
2832
add_field("y", &pos.y);
2933
}
3034

35+
struct Waypoint
36+
{
37+
std::string name;
38+
Position2D position;
39+
double speed = 1.0;
40+
};
41+
42+
BT_JSON_CONVERTER(Waypoint, wp)
43+
{
44+
add_field("name", &wp.name);
45+
add_field("position", &wp.position);
46+
add_field("speed", &wp.speed);
47+
}
48+
3149
// Simple Action that updates an instance of Position2D in the blackboard
50+
// and also outputs vectors to reproduce Groot2 issue #55/#77
3251
class UpdatePosition : public BT::SyncActionNode
3352
{
3453
public:
@@ -41,16 +60,63 @@ class UpdatePosition : public BT::SyncActionNode
4160
_pos.x += 0.2;
4261
_pos.y += 0.1;
4362
setOutput("pos", _pos);
63+
64+
// Vectors that trigger Groot2 issue #55/#77 (crash when viewing blackboard)
65+
std::vector<double> doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
66+
setOutput("vec_double", doubles);
67+
68+
std::vector<std::string> strings = { "hello", "world", "test" };
69+
setOutput("vec_string", strings);
70+
71+
// Helper to generate random offset [-range, +range]
72+
auto randOffset = [](double range) {
73+
return (static_cast<double>(std::rand()) / RAND_MAX - 0.5) * 2.0 * range;
74+
};
75+
76+
// Vector of custom types - alternate between 2 and 3 waypoints
77+
std::vector<Waypoint> waypoints;
78+
if(_execution_count % 2 == 0)
79+
{
80+
// Even executions: 2 waypoints
81+
waypoints = {
82+
{ "start", { randOffset(5.0), randOffset(5.0) }, 1.0 + randOffset(0.3) },
83+
{ "goal",
84+
{ 100.0 + randOffset(10.0), 50.0 + randOffset(10.0) },
85+
0.5 + randOffset(0.2) },
86+
};
87+
}
88+
else
89+
{
90+
// Odd executions: 3 waypoints
91+
waypoints = {
92+
{ "start", { randOffset(5.0), randOffset(5.0) }, 1.0 + randOffset(0.3) },
93+
{ "checkpoint",
94+
{ 50.0 + randOffset(15.0), 25.0 + randOffset(15.0) },
95+
2.0 + randOffset(0.5) },
96+
{ "goal",
97+
{ 100.0 + randOffset(10.0), 50.0 + randOffset(10.0) },
98+
0.5 + randOffset(0.2) },
99+
};
100+
}
101+
setOutput("waypoints", waypoints);
102+
_execution_count++;
103+
44104
return BT::NodeStatus::SUCCESS;
45105
}
46106

47107
static BT::PortsList providedPorts()
48108
{
49-
return { BT::OutputPort<Position2D>("pos") };
109+
return {
110+
BT::OutputPort<Position2D>("pos"),
111+
BT::OutputPort<std::vector<double>>("vec_double", "Vector of doubles"),
112+
BT::OutputPort<std::vector<std::string>>("vec_string", "Vector of strings"),
113+
BT::OutputPort<std::vector<Waypoint>>("waypoints", "Vector of waypoints"),
114+
};
50115
}
51116

52117
private:
53118
Position2D _pos = { 0, 0 };
119+
int _execution_count = 0;
54120
};
55121

56122
// clang-format off
@@ -61,7 +127,7 @@ static const char* xml_text = R"(
61127
<BehaviorTree ID="MainTree">
62128
<Sequence>
63129
<Script code="door_open:=false" />
64-
<UpdatePosition pos="{pos_2D}" />
130+
<UpdatePosition pos="{pos_2D}" vec_double="{doubles}" vec_string="{strings}" waypoints="{waypoints}"/>
65131
<Fallback>
66132
<Inverter>
67133
<IsDoorClosed/>
@@ -105,6 +171,7 @@ int main()
105171

106172
// Add this to allow Groot2 to visualize your custom type
107173
BT::RegisterJsonDefinition<Position2D>();
174+
BT::RegisterJsonDefinition<Waypoint>();
108175

109176
auto tree = factory.createTree("MainTree");
110177

0 commit comments

Comments
 (0)