diff --git a/src/tree_node.cpp b/src/tree_node.cpp index 16171a135..b14ab5020 100644 --- a/src/tree_node.cpp +++ b/src/tree_node.cpp @@ -222,13 +222,29 @@ Expected TreeNode::checkPreConditions() return NodeStatus::SKIPPED; } } - else if(_p->status == NodeStatus::RUNNING && preID == PreCond::WHILE_TRUE) + else if(_p->status == NodeStatus::RUNNING) { - // what to do if the condition is false - if(!parse_executor(env).cast()) + // Check WHILE_TRUE when running - halt if condition becomes false + if(preID == PreCond::WHILE_TRUE) + { + // what to do if the condition is false + if(!parse_executor(env).cast()) + { + haltNode(); + return NodeStatus::SKIPPED; + } + } + // Issue #917: Also check SUCCESS_IF and FAILURE_IF when running + // This allows reactive sequences to respond to condition changes + else if(preID == PreCond::SUCCESS_IF && parse_executor(env).cast()) { haltNode(); - return NodeStatus::SKIPPED; + return NodeStatus::SUCCESS; + } + else if(preID == PreCond::FAILURE_IF && parse_executor(env).cast()) + { + haltNode(); + return NodeStatus::FAILURE; } } } diff --git a/tests/gtest_preconditions.cpp b/tests/gtest_preconditions.cpp index f0dee8a32..3c78b6a19 100644 --- a/tests/gtest_preconditions.cpp +++ b/tests/gtest_preconditions.cpp @@ -508,3 +508,88 @@ TEST(Preconditions, SkippedSequence) status = tree.tickWhileRunning(); ASSERT_EQ(status, BT::NodeStatus::SUCCESS); } + +// Test for Issue #917: _successIf and _failureIf not re-evaluated when node is RUNNING +// in a ReactiveSequence +TEST(Preconditions, Issue917_SuccessIfWhenRunning) +{ + // The issue is that _successIf is only checked when a node is IDLE or SKIPPED. + // In a ReactiveSequence, when a variable changes to make _successIf true, + // the running node should return SUCCESS (after being halted). + + BehaviorTreeFactory factory; + factory.registerNodeType("KeepRunning"); + + static constexpr auto xml_text = R"( + + + +