We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
According to the documentation https://www.behaviortree.dev/docs/guides/pre_post_conditions#example, precondition should behave exactly like the inverted condition, but in practice precondition is checked on every tick.
#include "behaviortree_cpp/bt_factory.h" void RunTest(BT::Tree& tree) { tree.rootBlackboard()->set("check", false); std::cout << toStr(tree.tickOnce()) << "\n"; tree.rootBlackboard()->set("check", true); std::cout << toStr(tree.tickOnce()) << "\n"; std::cout << toStr(tree.tickOnce()) << "\n"; tree.rootBlackboard()->set("check", false); std::cout << toStr(tree.tickOnce()) << "\n"; } static constexpr auto AlwaysCheckXML = R"( <root BTCPP_format="4"> <BehaviorTree> <KeepRunningUntilFailure _skipIf="check == true"> <AlwaysSuccess/> </KeepRunningUntilFailure> </BehaviorTree> </root> )"; void TestAlwaysCheck() { BT::BehaviorTreeFactory factory; auto tree = factory.createTreeFromText(AlwaysCheckXML); RunTest(tree); } // clang-format off static constexpr auto SimpleCondition2XML = R"( <root BTCPP_format="4"> <BehaviorTree> <Fallback> <IsCheckSet check="{check}"/> <KeepRunningUntilFailure> <AlwaysSuccess/> </KeepRunningUntilFailure> </Fallback> </BehaviorTree> </root> )"; // clang-format on void TestSimpleCondition2() { BT::BehaviorTreeFactory factory; factory.registerSimpleCondition( "IsCheckSet", [](BT::TreeNode& node) { auto check = node.getInput<bool>("check").value(); return check ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE; }, BT::PortsList{BT::InputPort("check")}); auto tree = factory.createTreeFromText(SimpleCondition2XML); RunTest(tree); } int main() { std::cout << "============= AlwaysCheck =============\n"; TestAlwaysCheck(); std::cout << "============= SimpleCondition =============\n"; TestSimpleCondition2(); return 0; } /* Expected output: ============= AlwaysCheck ============= RUNNING SKIPPED SKIPPED RUNNING ============= SimpleCondition ============= RUNNING RUNNING RUNNING RUNNING */
Also, when StatefulActionNode receives SKIPPED state on the first iteration, all subsequent ticks are skipped
#include "behaviortree_cpp/bt_factory.h" class MyTestNode : public BT::StatefulActionNode { public: MyTestNode(const std::string& name, const BT::NodeConfig& config) : BT::StatefulActionNode(name, config){}; static BT::PortsList providedPorts() { return {}; } BT::NodeStatus onStart() override { std::cout << "Node started\n"; return BT::NodeStatus::RUNNING; } BT::NodeStatus onRunning() override { std::cout << "Node running\n"; return BT::NodeStatus::RUNNING; } void onHalted() override { std::cout << "Node halted\n"; } }; void RunTest(BT::Tree& tree) { tree.rootBlackboard()->set("check", false); std::cout << toStr(tree.tickOnce()) << "\n"; tree.rootBlackboard()->set("check", true); std::cout << toStr(tree.tickOnce()) << "\n"; std::cout << toStr(tree.tickOnce()) << "\n"; tree.rootBlackboard()->set("check", false); std::cout << toStr(tree.tickOnce()) << "\n"; } // clang-format off static constexpr auto PreconditionXML = R"( <root BTCPP_format="4"> <BehaviorTree> <MyTestNode _skipIf="check!=true"/> </BehaviorTree> </root> )"; // clang-format on void TestPrecondition() { BT::BehaviorTreeFactory factory; factory.registerNodeType<MyTestNode>("MyTestNode"); auto tree = factory.createTreeFromText(PreconditionXML); RunTest(tree); } // clang-format off static constexpr auto SimpleConditionXML = R"( <root BTCPP_format="4"> <BehaviorTree> <Fallback> <Inverter> <IsCheckSet check="{check}"/> </Inverter> <MyTestNode/> </Fallback> </BehaviorTree> </root> )"; // clang-format on void TestSimpleCondition() { BT::BehaviorTreeFactory factory; factory.registerNodeType<MyTestNode>("MyTestNode"); factory.registerSimpleCondition( "IsCheckSet", [](BT::TreeNode& node) { auto check = node.getInput<bool>("check").value(); return check ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE; }, BT::PortsList{BT::InputPort("check")}); auto tree = factory.createTreeFromText(SimpleConditionXML); RunTest(tree); } int main() { std::cout << "============= Precondition =============\n"; TestPrecondition(); std::cout << "============= SimpleCondition =============\n"; TestSimpleCondition(); return 0; } /* Expected output: ============= Precondition ============= SKIPPED SKIPPED SKIPPED SKIPPED ============= SimpleCondition ============= SUCCESS Node started RUNNING Node running RUNNING Node running RUNNING Node halted */
The text was updated successfully, but these errors were encountered:
Thanks for reporting, I will investigate
Sorry, something went wrong.
fix issue #615 : don't execute preconditions if state is RUNNING
10b1227
Fixed. thanks for reporting.
You can check the added unit tests:
https://github.com/BehaviorTree/BehaviorTree.CPP/blob/master/tests/gtest_preconditions.cpp#L229-L300
No branches or pull requests
According to the documentation https://www.behaviortree.dev/docs/guides/pre_post_conditions#example, precondition should behave exactly like the inverted condition, but in practice precondition is checked on every tick.
Difference between precondition and inverted condition
Also, when StatefulActionNode receives SKIPPED state on the first iteration, all subsequent ticks are skipped
Unexpected StatefulActionNode behavior
The text was updated successfully, but these errors were encountered: