Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e2d1024

Browse files
committed
adding virtual TreeNode::onInit() [issue BehaviorTree#33]
1 parent fb8c965 commit e2d1024

File tree

8 files changed

+111
-81
lines changed

8 files changed

+111
-81
lines changed

gtest/gtest_factory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ TEST(BehaviorTreeFactory, VerifyLargeTree)
8787

8888
std::vector<BT::TreeNode::Ptr> nodes;
8989

90-
BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes);
90+
BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes, Blackboard::Ptr());
9191

9292
BT::printTreeRecursively(root_node.get());
9393

@@ -133,7 +133,7 @@ TEST(BehaviorTreeFactory, Subtree)
133133

134134
std::vector<BT::TreeNode::Ptr> nodes;
135135

136-
BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes);
136+
BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes, Blackboard::Ptr());
137137
BT::printTreeRecursively(root_node.get());
138138

139139
ASSERT_EQ(root_node->name(), "root_selector");

include/behaviortree_cpp/bt_factory.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ class BehaviorTreeFactory
8484
* @return new node.
8585
*/
8686
std::unique_ptr<TreeNode> instantiateTreeNode(const std::string& ID, const std::string& name,
87-
const NodeParameters& params) const;
87+
const NodeParameters& params,
88+
const Blackboard::Ptr& blackboard) const;
8889

8990
/** registerNodeType is the method to use to register your custom TreeNode.
9091
*

include/behaviortree_cpp/tree_node.h

Lines changed: 73 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ typedef std::chrono::high_resolution_clock::duration Duration;
3838
// Abstract base class for Behavior Tree Nodes
3939
class TreeNode
4040
{
41+
42+
private:
43+
44+
/// This calback will be executed only ONCE after the constructor of the node,
45+
/// before the very first tick.
46+
/// Override if necessary.
47+
virtual void onInit() {}
48+
4149
public:
4250
/**
4351
* @brief TreeNode main constructor.
@@ -103,77 +111,22 @@ class TreeNode
103111
/// creation of the TreeNode instance.
104112
const NodeParameters& initializationParameters() const;
105113

106-
/** Get a parameter from the passed NodeParameters and convert it to type T.
114+
/** Get a parameter from the NodeParameters and convert it to type T.
107115
*/
108116
template <typename T>
109117
BT::optional<T> getParam(const std::string& key) const
110118
{
111119
T out;
112-
if (getParam(key, out))
113-
{
114-
return std::move(out);
115-
}
116-
else
117-
{
118-
return BT::nullopt;
119-
}
120+
return getParam(key, out) ? std::move(out) : BT::nullopt;
120121
}
121122

122123
/** Get a parameter from the passed NodeParameters and convert it to type T.
123-
*
124-
* return false either if there is no parameter with this key or if conversion failed.
124+
* Return false either if there is no parameter with this key or if conversion failed.
125125
*/
126126
template <typename T>
127-
bool getParam(const std::string& key, T& destination) const
128-
{
129-
auto it = parameters_.find(key);
130-
if (it == parameters_.end())
131-
{
132-
return false;
133-
}
134-
const std::string& str = it->second;
127+
bool getParam(const std::string& key, T& destination) const;
135128

136-
try
137-
{
138-
bool bb_pattern = isBlackboardPattern(str);
139-
if( bb_pattern && just_constructed_)
140-
{
141-
std::cerr << "You are calling getParam inside a constructor, but this is not allowed "
142-
"when the parameter contains a blackboard.\n"
143-
"You should call getParam inside your tick() method"<< std::endl;
144-
std::logic_error("Calling getParam inside a constructor");
145-
}
146-
// check if it follows this ${pattern}, if it does, search inside the blackboard
147-
if ( bb_ && bb_pattern)
148-
{
149-
const std::string stripped_key(&str[2], str.size() - 3);
150-
const SafeAny::Any* val = bb_->getAny(stripped_key);
151-
152-
if( val )
153-
{
154-
if( std::is_same<T,std::string>::value == false &&
155-
(val->type() == typeid (std::string) ||
156-
val->type() == typeid (SafeAny::SimpleString)))
157-
{
158-
destination = convertFromString<T>(val->cast<std::string>());
159-
}
160-
else{
161-
destination = val->cast<T>();
162-
}
163-
}
164-
return val != nullptr;
165-
}
166-
else{
167-
destination = convertFromString<T>(str.c_str());
168-
return true;
169-
}
170-
}
171-
catch (std::runtime_error& err)
172-
{
173-
std::cout << "Exception at getParam(" << key << "): " << err.what() << std::endl;
174-
return false;
175-
}
176-
}
129+
static bool isBlackboardPattern(StringView str);
177130

178131
protected:
179132
/// Method to be implemented by the user
@@ -184,9 +137,12 @@ class TreeNode
184137

185138
friend class BehaviorTreeFactory;
186139

187-
bool just_constructed_;
140+
void initialize();
188141

189142
private:
143+
144+
bool not_initialized_;
145+
190146
const std::string name_;
191147

192148
NodeStatus status_;
@@ -205,10 +161,63 @@ class TreeNode
205161

206162
Blackboard::Ptr bb_;
207163

208-
209-
protected:
210-
static bool isBlackboardPattern(const std::string& str );
211164
};
165+
166+
//-------------------------------------------------------
167+
168+
169+
template <typename T> inline
170+
bool TreeNode::getParam(const std::string& key, T& destination) const
171+
{
172+
auto it = parameters_.find(key);
173+
if (it == parameters_.end())
174+
{
175+
return false;
176+
}
177+
const std::string& str = it->second;
178+
179+
try
180+
{
181+
bool bb_pattern = isBlackboardPattern(str);
182+
if( bb_pattern && not_initialized_)
183+
{
184+
std::cerr << "you are calling getParam inside a constructor, but this is not allowed "
185+
"when the parameter contains a blackboard.\n"
186+
"You should call getParam inside your tick() method"<< std::endl;
187+
std::logic_error("Calling getParam inside a constructor");
188+
}
189+
// check if it follows this ${pattern}, if it does, search inside the blackboard
190+
if ( bb_pattern && blackboard() )
191+
{
192+
const std::string stripped_key(&str[2], str.size() - 3);
193+
const SafeAny::Any* val = blackboard()->getAny(stripped_key);
194+
if( val )
195+
{
196+
if( std::is_same<T,std::string>::value == false &&
197+
(val->type() == typeid (std::string) ||
198+
val->type() == typeid (SafeAny::SimpleString)))
199+
{
200+
destination = convertFromString<T>(val->cast<std::string>());
201+
}
202+
else{
203+
destination = val->cast<T>();
204+
}
205+
}
206+
return val != nullptr;
207+
}
208+
else{
209+
destination = convertFromString<T>(str.c_str());
210+
return true;
211+
}
212+
}
213+
catch (std::runtime_error& err)
214+
{
215+
std::cout << "Exception at getParam(" << key << "): " << err.what() << std::endl;
216+
return false;
217+
}
218+
}
219+
220+
212221
}
213222

214223
#endif

include/behaviortree_cpp/xml_parsing.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class XMLParser
2222
using NodeBuilder = std::function<TreeNode::Ptr(const std::string&, const std::string&,
2323
const NodeParameters&, TreeNode::Ptr)>;
2424

25-
TreeNode::Ptr instantiateTree(std::vector<TreeNode::Ptr>& nodes);
25+
TreeNode::Ptr instantiateTree(std::vector<TreeNode::Ptr>& nodes, const Blackboard::Ptr &blackboard);
2626

2727
private:
2828

src/action_node.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ActionNodeBase::ActionNodeBase(const std::string& name, const NodeParameters& pa
2323

2424
NodeStatus ActionNodeBase::executeTick()
2525
{
26-
just_constructed_ = false;
26+
initialize();
2727
NodeStatus prev_status = status();
2828

2929
if (prev_status == NodeStatus::IDLE || prev_status == NodeStatus::RUNNING)
@@ -94,8 +94,7 @@ void AsyncActionNode::waitForTick()
9494

9595
NodeStatus AsyncActionNode::executeTick()
9696
{
97-
just_constructed_ = false;
98-
97+
initialize();
9998
//send signal to other thread.
10099
// The other thread is in charge for changing the status
101100
if (status() == NodeStatus::IDLE)
@@ -146,6 +145,7 @@ void CoroActionNode::setStatusRunningAndYield()
146145

147146
NodeStatus CoroActionNode::executeTick()
148147
{
148+
initialize();
149149
if (status() == NodeStatus::IDLE)
150150
{
151151
_p->coro = coroutine::create( [this]() { setStatus(tick()); } );

src/bt_factory.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ void BehaviorTreeFactory::registerFromPlugin(const std::string file_path)
123123
}
124124

125125
std::unique_ptr<TreeNode> BehaviorTreeFactory::instantiateTreeNode(
126-
const std::string& ID, const std::string& name, const NodeParameters& params) const
126+
const std::string& ID, const std::string& name,
127+
const NodeParameters& params,
128+
const Blackboard::Ptr& blackboard) const
127129
{
128130
auto it = builders_.find(ID);
129131
if (it == builders_.end())
@@ -137,6 +139,9 @@ std::unique_ptr<TreeNode> BehaviorTreeFactory::instantiateTreeNode(
137139
}
138140
std::unique_ptr<TreeNode> node = it->second(name, params);
139141
node->setRegistrationName(ID);
142+
node->setBlackboard(blackboard);
143+
node->initialize();
144+
140145
return node;
141146
}
142147

src/tree_node.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static uint8_t getUID()
2323
}
2424

2525
TreeNode::TreeNode(const std::string& name, const NodeParameters& parameters)
26-
: just_constructed_(true),
26+
: not_initialized_(true),
2727
name_(name),
2828
status_(NodeStatus::IDLE),
2929
uid_(getUID()),
@@ -34,7 +34,7 @@ TreeNode::TreeNode(const std::string& name, const NodeParameters& parameters)
3434

3535
NodeStatus TreeNode::executeTick()
3636
{
37-
just_constructed_ = false;
37+
3838
const NodeStatus status = tick();
3939
setStatus(status);
4040
return status;
@@ -63,6 +63,12 @@ void TreeNode::setBlackboard(const Blackboard::Ptr& bb)
6363

6464
const Blackboard::Ptr& TreeNode::blackboard() const
6565
{
66+
if( not_initialized_ )
67+
{
68+
throw std::logic_error("You can NOT access the blackboard in the constructor."
69+
" If you need to access the blackboard before the very first tick(), "
70+
" you should override the virtual method TreeNode::onInit()");
71+
}
6672
return bb_;
6773
}
6874

@@ -109,7 +115,16 @@ void TreeNode::setRegistrationName(const std::string& registration_name)
109115
registration_name_ = registration_name;
110116
}
111117

112-
bool TreeNode::isBlackboardPattern(const std::string &str)
118+
void TreeNode::initialize()
119+
{
120+
if( not_initialized_ )
121+
{
122+
onInit();
123+
not_initialized_ = false;
124+
}
125+
}
126+
127+
bool TreeNode::isBlackboardPattern(StringView str)
113128
{
114129
return str.size() >= 4 && str[0] == '$' && str[1] == '{' && str.back() == '}';
115130
}

src/xml_parsing.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,8 @@ void XMLParser::Pimpl::verifyXML(const tinyxml2::XMLDocument* doc) const
347347
}
348348
}
349349

350-
TreeNode::Ptr XMLParser::instantiateTree(std::vector<TreeNode::Ptr>& nodes)
350+
TreeNode::Ptr XMLParser::instantiateTree(std::vector<TreeNode::Ptr>& nodes,
351+
const Blackboard::Ptr& blackboard)
351352
{
352353
nodes.clear();
353354

@@ -377,7 +378,7 @@ TreeNode::Ptr XMLParser::instantiateTree(std::vector<TreeNode::Ptr>& nodes)
377378

378379
if( _p->factory.builders().count(ID) != 0)
379380
{
380-
child_node = _p->factory.instantiateTreeNode(ID, name, params);
381+
child_node = _p->factory.instantiateTreeNode(ID, name, params, blackboard);
381382
}
382383
else if( _p->tree_roots.count(ID) != 0) {
383384
child_node = std::unique_ptr<TreeNode>( new DecoratorSubtreeNode(name) );
@@ -599,8 +600,8 @@ Tree buildTreeFromText(const BehaviorTreeFactory& factory, const std::string& te
599600
parser.loadFromText(text);
600601

601602
std::vector<TreeNode::Ptr> nodes;
602-
auto root = parser.instantiateTree(nodes);
603-
assignBlackboardToEntireTree(root.get(), blackboard);
603+
auto root = parser.instantiateTree(nodes, blackboard);
604+
604605
return Tree(root.get(), nodes);
605606
}
606607

@@ -611,8 +612,7 @@ Tree buildTreeFromFile(const BehaviorTreeFactory& factory, const std::string& fi
611612
parser.loadFromFile(filename);
612613

613614
std::vector<TreeNode::Ptr> nodes;
614-
auto root = parser.instantiateTree(nodes);
615-
assignBlackboardToEntireTree(root.get(), blackboard);
615+
auto root = parser.instantiateTree(nodes, blackboard);
616616
return Tree(root.get(), nodes);
617617
}
618618

0 commit comments

Comments
 (0)