Skip to content

Commit 66fb139

Browse files
author
wangzheng
committed
feat: add _onStart precondition for script execution
Add a new precondition type _onStart that allows executing scripts before a node starts its tick. This provides symmetry with the existing _post functionality. Resolves BehaviorTree#895
1 parent d4d8ae1 commit 66fb139

File tree

3 files changed

+52
-16
lines changed

3 files changed

+52
-16
lines changed

include/behaviortree_cpp/tree_node.h

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum class PreCond
4949
SUCCESS_IF,
5050
SKIP_IF,
5151
WHILE_TRUE,
52+
ALWAYS,
5253
COUNT_
5354
};
5455

src/tree_node.cpp

+22-16
Original file line numberDiff line numberDiff line change
@@ -208,24 +208,28 @@ Expected<NodeStatus> TreeNode::checkPreConditions()
208208
// Some preconditions are applied only when the node state is IDLE or SKIPPED
209209
if(_p->status == NodeStatus::IDLE || _p->status == NodeStatus::SKIPPED)
210210
{
211-
// what to do if the condition is true
212-
if(parse_executor(env).cast<bool>())
211+
auto execute_result = parse_executor(env);
212+
// always
213+
if(preID == PreCond::ALWAYS)
213214
{
214-
if(preID == PreCond::FAILURE_IF)
215-
{
216-
return NodeStatus::FAILURE;
217-
}
218-
else if(preID == PreCond::SUCCESS_IF)
219-
{
220-
return NodeStatus::SUCCESS;
221-
}
222-
else if(preID == PreCond::SKIP_IF)
223-
{
224-
return NodeStatus::SKIPPED;
225-
}
215+
return nonstd::make_unexpected("");
216+
}
217+
auto bool_result = execute_result.cast<bool>();
218+
// what to do if the condition is true and the precondition is xx_IF
219+
if(bool_result && preID == PreCond::FAILURE_IF)
220+
{
221+
return NodeStatus::FAILURE;
222+
}
223+
if(bool_result && preID == PreCond::SUCCESS_IF)
224+
{
225+
return NodeStatus::SUCCESS;
226+
}
227+
if(bool_result && preID == PreCond::SKIP_IF)
228+
{
229+
return NodeStatus::SKIPPED;
226230
}
227-
// if the conditions is false
228-
else if(preID == PreCond::WHILE_TRUE)
231+
// if the condition is false and the precondition is WHILE_TRUE, skip the node
232+
if(!bool_result && preID == PreCond::WHILE_TRUE)
229233
{
230234
return NodeStatus::SKIPPED;
231235
}
@@ -476,6 +480,8 @@ std::string toStr<PreCond>(const PreCond& pre)
476480
return "_skipIf";
477481
case PreCond::WHILE_TRUE:
478482
return "_while";
483+
case PreCond::ALWAYS:
484+
return "_onStart";
479485
default:
480486
return "Undefined";
481487
}

tests/gtest_preconditions.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,32 @@ TEST(Preconditions, WhileCallsOnHalt)
397397
ASSERT_EQ(status, BT::NodeStatus::SKIPPED);
398398
ASSERT_EQ(tree.rootBlackboard()->get<int>("B"), 69);
399399
}
400+
401+
TEST(Preconditions, OnStart)
402+
{
403+
BehaviorTreeFactory factory;
404+
std::array<int, 3> counters;
405+
RegisterTestTick(factory, "Test", counters);
406+
407+
static constexpr auto xml_text = R"(
408+
<root BTCPP_format="4">
409+
<BehaviorTree ID="Main">
410+
<Sequence>
411+
<AlwaysSuccess _onStart="B:=69"/>
412+
<TestA/>
413+
<TestB _successIf="B==69"/>
414+
<TestC _onStart="C:=70" _post="B=70"/>
415+
</Sequence>
416+
</BehaviorTree>
417+
</root>
418+
)";
419+
420+
auto tree = factory.createTreeFromText(xml_text);
421+
const auto status = tree.tickWhileRunning();
422+
ASSERT_EQ(status, NodeStatus::SUCCESS);
423+
ASSERT_EQ(tree.rootBlackboard()->get<int>("B"), 70);
424+
ASSERT_EQ(tree.rootBlackboard()->get<int>("C"), 70);
425+
ASSERT_EQ(counters[0], 1);
426+
ASSERT_EQ(counters[1], 0);
427+
ASSERT_EQ(counters[2], 1);
428+
}

0 commit comments

Comments
 (0)