diff --git a/include/behaviortree_cpp/decorators/script_precondition.h b/include/behaviortree_cpp/decorators/script_precondition.h index a39624ae2..f9ca18f0d 100644 --- a/include/behaviortree_cpp/decorators/script_precondition.h +++ b/include/behaviortree_cpp/decorators/script_precondition.h @@ -60,6 +60,12 @@ class PreconditionNode : public DecoratorNode } private: + void halt() override + { + _children_running = false; + DecoratorNode::halt(); + } + virtual BT::NodeStatus tick() override { loadExecutor(); @@ -72,8 +78,7 @@ class PreconditionNode : public DecoratorNode // Only check the 'if' script if we haven't started ticking the children yet. Ast::Environment env = { config().blackboard, config().enums }; - bool tick_children = - _children_running || (_children_running = _executor(env).cast()); + bool tick_children = _children_running || _executor(env).cast(); if(!tick_children) { @@ -81,10 +86,10 @@ class PreconditionNode : public DecoratorNode } auto const child_status = child_node_->executeTick(); + _children_running = (child_status == NodeStatus::RUNNING); if(isStatusCompleted(child_status)) { resetChild(); - _children_running = false; } return child_status; } diff --git a/tests/gtest_preconditions.cpp b/tests/gtest_preconditions.cpp index c9b87797a..b33daee8e 100644 --- a/tests/gtest_preconditions.cpp +++ b/tests/gtest_preconditions.cpp @@ -168,6 +168,53 @@ TEST(PreconditionsDecorator, ChecksConditionOnce) EXPECT_EQ(tree.tickOnce(), NodeStatus::SUCCESS); } +TEST(PreconditionsDecorator, ChecksConditionAfterHalt) +{ + BehaviorTreeFactory factory; + factory.registerNodeType("KeepRunning"); + + const std::string xml_text = R"( + + + + + + + )"; + + auto tree = factory.createTreeFromText(xml_text); + tree.rootBlackboard()->set("A", 0); + EXPECT_EQ(tree.tickOnce(), NodeStatus::RUNNING); + + tree.haltTree(); + tree.rootBlackboard()->set("A", 1); + EXPECT_EQ(tree.tickOnce(), NodeStatus::FAILURE); +} + +TEST(PreconditionsDecorator, ChecksConditionAfterSkippedChild) +{ + BehaviorTreeFactory factory; + factory.registerNodeType("KeepRunning"); + + const std::string xml_text = R"( + + + + + + + )"; + + auto tree = factory.createTreeFromText(xml_text); + tree.rootBlackboard()->set("A", 0); + tree.rootBlackboard()->set("skip", true); + EXPECT_EQ(tree.tickOnce(), NodeStatus::SKIPPED); + + tree.rootBlackboard()->set("A", 1); + tree.rootBlackboard()->set("skip", false); + EXPECT_EQ(tree.tickOnce(), NodeStatus::FAILURE); +} + TEST(PreconditionsDecorator, CanRunChildrenMultipleTimes) { BehaviorTreeFactory factory;