From 66fb1397c92de9f91a9f81228895ae45cb2e6774 Mon Sep 17 00:00:00 2001 From: wangzheng Date: Tue, 17 Dec 2024 11:55:00 +0800 Subject: [PATCH 1/5] 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 #895 --- include/behaviortree_cpp/tree_node.h | 1 + src/tree_node.cpp | 38 ++++++++++++++++------------ tests/gtest_preconditions.cpp | 29 +++++++++++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/behaviortree_cpp/tree_node.h b/include/behaviortree_cpp/tree_node.h index 537176519..899a32acb 100644 --- a/include/behaviortree_cpp/tree_node.h +++ b/include/behaviortree_cpp/tree_node.h @@ -49,6 +49,7 @@ enum class PreCond SUCCESS_IF, SKIP_IF, WHILE_TRUE, + ALWAYS, COUNT_ }; diff --git a/src/tree_node.cpp b/src/tree_node.cpp index 7b7a4ac88..28767f8c6 100644 --- a/src/tree_node.cpp +++ b/src/tree_node.cpp @@ -208,24 +208,28 @@ Expected TreeNode::checkPreConditions() // Some preconditions are applied only when the node state is IDLE or SKIPPED if(_p->status == NodeStatus::IDLE || _p->status == NodeStatus::SKIPPED) { - // what to do if the condition is true - if(parse_executor(env).cast()) + auto execute_result = parse_executor(env); + // always + if(preID == PreCond::ALWAYS) { - if(preID == PreCond::FAILURE_IF) - { - return NodeStatus::FAILURE; - } - else if(preID == PreCond::SUCCESS_IF) - { - return NodeStatus::SUCCESS; - } - else if(preID == PreCond::SKIP_IF) - { - return NodeStatus::SKIPPED; - } + return nonstd::make_unexpected(""); + } + auto bool_result = execute_result.cast(); + // what to do if the condition is true and the precondition is xx_IF + if(bool_result && preID == PreCond::FAILURE_IF) + { + return NodeStatus::FAILURE; + } + if(bool_result && preID == PreCond::SUCCESS_IF) + { + return NodeStatus::SUCCESS; + } + if(bool_result && preID == PreCond::SKIP_IF) + { + return NodeStatus::SKIPPED; } - // if the conditions is false - else if(preID == PreCond::WHILE_TRUE) + // if the condition is false and the precondition is WHILE_TRUE, skip the node + if(!bool_result && preID == PreCond::WHILE_TRUE) { return NodeStatus::SKIPPED; } @@ -476,6 +480,8 @@ std::string toStr(const PreCond& pre) return "_skipIf"; case PreCond::WHILE_TRUE: return "_while"; + case PreCond::ALWAYS: + return "_onStart"; default: return "Undefined"; } diff --git a/tests/gtest_preconditions.cpp b/tests/gtest_preconditions.cpp index 7a3df89f7..be1b030d3 100644 --- a/tests/gtest_preconditions.cpp +++ b/tests/gtest_preconditions.cpp @@ -397,3 +397,32 @@ TEST(Preconditions, WhileCallsOnHalt) ASSERT_EQ(status, BT::NodeStatus::SKIPPED); ASSERT_EQ(tree.rootBlackboard()->get("B"), 69); } + +TEST(Preconditions, OnStart) +{ + BehaviorTreeFactory factory; + std::array counters; + RegisterTestTick(factory, "Test", counters); + + static constexpr auto xml_text = R"( + + + + + + + + + + + )"; + + auto tree = factory.createTreeFromText(xml_text); + const auto status = tree.tickWhileRunning(); + ASSERT_EQ(status, NodeStatus::SUCCESS); + ASSERT_EQ(tree.rootBlackboard()->get("B"), 70); + ASSERT_EQ(tree.rootBlackboard()->get("C"), 70); + ASSERT_EQ(counters[0], 1); + ASSERT_EQ(counters[1], 0); + ASSERT_EQ(counters[2], 1); +} From c9b61ac5f4cd89dc1cbcad3e3310e32a081c939f Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Fri, 10 Jan 2025 12:10:58 +0100 Subject: [PATCH 2/5] Update include/behaviortree_cpp/tree_node.h --- include/behaviortree_cpp/tree_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/behaviortree_cpp/tree_node.h b/include/behaviortree_cpp/tree_node.h index 899a32acb..edb580dfc 100644 --- a/include/behaviortree_cpp/tree_node.h +++ b/include/behaviortree_cpp/tree_node.h @@ -49,7 +49,7 @@ enum class PreCond SUCCESS_IF, SKIP_IF, WHILE_TRUE, - ALWAYS, + ON_START, COUNT_ }; From af09eac300cd498df5d55ae4b7614cd169dec13f Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Fri, 10 Jan 2025 12:11:03 +0100 Subject: [PATCH 3/5] Update src/tree_node.cpp --- src/tree_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree_node.cpp b/src/tree_node.cpp index 28767f8c6..0cc45bff0 100644 --- a/src/tree_node.cpp +++ b/src/tree_node.cpp @@ -480,7 +480,7 @@ std::string toStr(const PreCond& pre) return "_skipIf"; case PreCond::WHILE_TRUE: return "_while"; - case PreCond::ALWAYS: + case PreCond::ON_START: return "_onStart"; default: return "Undefined"; From 9dc3e8aface3b852bb0dcfae72ccc7e7f71d18d4 Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Fri, 10 Jan 2025 12:11:08 +0100 Subject: [PATCH 4/5] Update src/tree_node.cpp --- src/tree_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree_node.cpp b/src/tree_node.cpp index 0cc45bff0..d009fb131 100644 --- a/src/tree_node.cpp +++ b/src/tree_node.cpp @@ -210,7 +210,7 @@ Expected TreeNode::checkPreConditions() { auto execute_result = parse_executor(env); // always - if(preID == PreCond::ALWAYS) + if(preID == PreCond::ON_START) { return nonstd::make_unexpected(""); } From 3416d82d463f1ab4e0bfb555e672efb26f20f804 Mon Sep 17 00:00:00 2001 From: Aglargil <1252223935@qq.com> Date: Fri, 10 Jan 2025 21:52:11 +0800 Subject: [PATCH 5/5] Update src/tree_node.h PreCondNames --- include/behaviortree_cpp/tree_node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/behaviortree_cpp/tree_node.h b/include/behaviortree_cpp/tree_node.h index 323c8d393..7689d3a17 100644 --- a/include/behaviortree_cpp/tree_node.h +++ b/include/behaviortree_cpp/tree_node.h @@ -54,8 +54,8 @@ enum class PreCond COUNT_ }; -static const std::array PreCondNames = { // - "_failureIf", "_successIf", "_skipIf", "_while" +static const std::array PreCondNames = { // + "_failureIf", "_successIf", "_skipIf", "_while", "_onStart" }; enum class PostCond