Skip to content
New issue

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

Precondition not checked in ReactiveSequence #917

Open
mrjogo opened this issue Jan 31, 2025 · 1 comment
Open

Precondition not checked in ReactiveSequence #917

mrjogo opened this issue Jan 31, 2025 · 1 comment

Comments

@mrjogo
Copy link

mrjogo commented Jan 31, 2025

Describe the bug

In the following behavior tree, AlwaysRunning never succeeds even when _successIf="my_var != 0" evaluates to true. (AlwaysRunning is a StatefulActionNode that always returns RUNNING; Echo just prints the variable; full repro below):

<root BTCPP_format="4">
  <BehaviorTree ID="MainTree">
    <Sequence name="root">
      <Script code="my_var := 0; loop := 0"/>
      <ReactiveSequence>
        <Script code="loop += 1; my_var = (loop &gt;= 3) ? 42 : 0"/>
        <Echo message="{my_var}"/>
        <AlwaysRunning _successIf="my_var != 0"/>
      </ReactiveSequence>
    </Sequence>
  </BehaviorTree>
</root>

I would expect AlwaysRunning to return SUCCESS on the 3rd iteration, once my_var is set to 42, but the precondition never hits:

[1738296607.060]: root                      IDLE -> RUNNING
[1738296607.060]: Script                    IDLE -> SUCCESS
[1738296607.060]: ReactiveSequence          IDLE -> RUNNING
[1738296607.060]: Script                    IDLE -> SUCCESS
ECHO: 0
[1738296607.060]: Echo                      IDLE -> SUCCESS
[1738296607.060]: AlwaysRunning             IDLE -> RUNNING
[1738296607.060]: Script                    SUCCESS -> IDLE
[1738296607.060]: Echo                      SUCCESS -> IDLE
[1738296607.070]: Script                    IDLE -> SUCCESS
ECHO: 0
[1738296607.070]: Echo                      IDLE -> SUCCESS
[1738296607.070]: Script                    SUCCESS -> IDLE
[1738296607.070]: Echo                      SUCCESS -> IDLE
[1738296607.081]: Script                    IDLE -> SUCCESS
ECHO: 42
[1738296607.081]: Echo                      IDLE -> SUCCESS
[1738296607.081]: Script                    SUCCESS -> IDLE
[1738296607.081]: Echo                      SUCCESS -> IDLE
[1738296607.091]: Script                    IDLE -> SUCCESS
ECHO: 42
[1738296607.091]: Echo                      IDLE -> SUCCESS
[1738296607.091]: Script                    SUCCESS -> IDLE
[1738296607.091]: Echo                      SUCCESS -> IDLE
ad nauseam

How to Reproduce

#include <behaviortree_cpp/action_node.h>
#include <behaviortree_cpp/bt_factory.h>
#include <behaviortree_cpp/loggers/bt_cout_logger.h>

static const char* xml_text = R"(
 <root BTCPP_format="4">
 
   <BehaviorTree ID="MainTree">
     <Sequence name="root">
       <Script code="my_var := 0; loop := 0"/>
       <ReactiveSequence>
         <Script code="loop += 1; my_var = (loop &gt;= 3) ? 42 : 0"/>
         <Echo message="{my_var}"/>
         <AlwaysRunning _successIf="my_var != 0"/>
       </ReactiveSequence>
     </Sequence>
   </BehaviorTree>
 
 </root>
 )";

class AlwaysRunning : public BT::StatefulActionNode
{
public:
  AlwaysRunning(const std::string& name) : StatefulActionNode(name, {})
  {
  }

private:
  BT::NodeStatus onStart() override
  {
    return BT::NodeStatus::RUNNING;
  }
  BT::NodeStatus onRunning() override
  {
    return BT::NodeStatus::RUNNING;
  }
  void onHalted() override
  {
  }
};

class Echo : public BT::SyncActionNode
{
public:
  Echo(const std::string& name, const BT::NodeConfig& config) : BT::SyncActionNode(name, config)
  {
  }

  static BT::PortsList providedPorts()
  {
    return { BT::InputPort<std::string>("message") };
  }

  BT::NodeStatus tick() override
  {
    auto msg = getInput<int>("message");
    if (!msg)
    {
      throw BT::RuntimeError("missing required input [message]: ", msg.error());
    }

    std::cout << "ECHO: " << msg.value() << std::endl;
    return BT::NodeStatus::SUCCESS;
  }
};

int main()
{
  BT::BehaviorTreeFactory factory;
  factory.registerNodeType<AlwaysRunning>("AlwaysRunning");
  factory.registerNodeType<Echo>("Echo");

  auto tree = factory.createTreeFromText(xml_text);
  BT::StdCoutLogger logger(tree);
  tree.tickWhileRunning();

  return 0;
}
@mrjogo
Copy link
Author

mrjogo commented Feb 7, 2025

Here is a workaround to get the same behavior:

<root BTCPP_format="4">

  <BehaviorTree ID="MainTree">
    <Sequence name="root">
      <Script code="my_var := 0; loop := 0"/>
      <ReactiveSequence>
        <Script code="loop += 1; my_var = (loop &gt;= 3) ? 42 : 0"/>
        <Echo message="{my_var}"/>
        <Precondition else="RUNNING" if="my_var != 0">
          <AlwaysSuccess/>
        </Precondition>
      </ReactiveSequence>
    </Sequence>
  </BehaviorTree>

</root>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant