Skip to content

Commit 1e27f64

Browse files
committed
revert new behavior of Sequence and Fallback
1 parent 41cb606 commit 1e27f64

File tree

10 files changed

+112
-11
lines changed

10 files changed

+112
-11
lines changed

include/behaviortree_cpp/controls/fallback_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace BT
3232
class FallbackNode : public ControlNode
3333
{
3434
public:
35-
FallbackNode(const std::string& name);
35+
FallbackNode(const std::string& name, bool make_aynch = false);
3636

3737
virtual ~FallbackNode() override = default;
3838

@@ -41,6 +41,7 @@ class FallbackNode : public ControlNode
4141
private:
4242
size_t current_child_idx_;
4343
bool all_skipped_ = true;
44+
bool asynch_ = false;
4445

4546
virtual BT::NodeStatus tick() override;
4647
};

include/behaviortree_cpp/controls/reactive_sequence.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,14 @@ class ReactiveSequence : public ControlNode
3636
ReactiveSequence(const std::string& name) : ControlNode(name, {})
3737
{}
3838

39+
static void EnableException(bool enable);
40+
3941
private:
4042
virtual BT::NodeStatus tick() override;
43+
44+
int running_child_ = -1;
45+
46+
static bool throw_if_multiple_running;
4147
};
4248

4349
} // namespace BT

include/behaviortree_cpp/controls/sequence_node.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ namespace BT
3030
* Restart the loop only if (reset_on_failure == true)
3131
*
3232
*/
33+
3334
class SequenceNode : public ControlNode
3435
{
3536
public:
36-
SequenceNode(const std::string& name);
37+
SequenceNode(const std::string& name,
38+
bool make_async = false);
3739

3840
virtual ~SequenceNode() override = default;
3941

@@ -42,6 +44,7 @@ class SequenceNode : public ControlNode
4244
private:
4345
size_t current_child_idx_;
4446
bool all_skipped_ = true;
47+
bool asynch_ = false;
4548

4649
virtual BT::NodeStatus tick() override;
4750
};

include/behaviortree_cpp/tree_node.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ class TreeNode
266266
}
267267
else if constexpr (hasNodeNameCtor<DerivedT>())
268268
{
269-
auto node_ptr = new DerivedT(name);
269+
auto node_ptr = new DerivedT(name, args...);
270270
node_ptr->config_ = config;
271271
return std::unique_ptr<DerivedT>(node_ptr);
272272
}

src/bt_factory.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ BehaviorTreeFactory::BehaviorTreeFactory()
2828
{
2929
parser_ = std::make_shared<XMLParser>(*this);
3030
registerNodeType<FallbackNode>("Fallback");
31+
registerNodeType<FallbackNode>("AsyncFallback", true);
3132
registerNodeType<SequenceNode>("Sequence");
33+
registerNodeType<SequenceNode>("AsyncSequence", true);
3234
registerNodeType<SequenceWithMemory>("SequenceWithMemory");
3335

3436
#ifdef USE_BTCPP3_OLD_NAMES

src/controls/fallback_node.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515

1616
namespace BT
1717
{
18-
FallbackNode::FallbackNode(const std::string& name) :
19-
ControlNode::ControlNode(name, {}), current_child_idx_(0), all_skipped_(true)
18+
FallbackNode::FallbackNode(const std::string& name, bool make_aynch) :
19+
ControlNode::ControlNode(name, {}),
20+
current_child_idx_(0),
21+
all_skipped_(true),
22+
asynch_(make_aynch)
2023
{
21-
setRegistrationID("Fallback");
24+
if(asynch_)
25+
setRegistrationID("AsyncFallback");
26+
else
27+
setRegistrationID("Fallback");
2228
}
2329

2430
NodeStatus FallbackNode::tick()
@@ -56,7 +62,8 @@ NodeStatus FallbackNode::tick()
5662
current_child_idx_++;
5763
// Return the execution flow if the child is async,
5864
// to make this interruptable.
59-
if (requiresWakeUp() && prev_status == NodeStatus::IDLE &&
65+
if (asynch_ && requiresWakeUp() &&
66+
prev_status == NodeStatus::IDLE &&
6067
current_child_idx_ < children_count)
6168
{
6269
emitWakeUpSignal();

src/controls/reactive_sequence.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
namespace BT
1616
{
17+
18+
bool ReactiveSequence::throw_if_multiple_running = true;
19+
20+
void ReactiveSequence::EnableException(bool enable)
21+
{
22+
ReactiveSequence::throw_if_multiple_running = enable;
23+
}
24+
1725
NodeStatus ReactiveSequence::tick()
1826
{
1927
bool all_skipped = true;
@@ -36,6 +44,14 @@ NodeStatus ReactiveSequence::tick()
3644
{
3745
haltChild(i);
3846
}
47+
if(running_child_ == -1)
48+
{
49+
running_child_ = int(index);
50+
}
51+
else if(throw_if_multiple_running && running_child_ != int(index))
52+
{
53+
throw LogicError("[ReactiveSequence]: only a single child can return RUNNING");
54+
}
3955
return NodeStatus::RUNNING;
4056
}
4157

src/controls/sequence_node.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515

1616
namespace BT
1717
{
18-
SequenceNode::SequenceNode(const std::string& name) :
19-
ControlNode::ControlNode(name, {}), current_child_idx_(0), all_skipped_(true)
18+
SequenceNode::SequenceNode(const std::string& name, bool make_async) :
19+
ControlNode::ControlNode(name, {}),
20+
current_child_idx_(0),
21+
all_skipped_(true),
22+
asynch_(make_async)
2023
{
21-
setRegistrationID("Sequence");
24+
if(asynch_)
25+
setRegistrationID("AsyncSequence");
26+
else
27+
setRegistrationID("Sequence");
2228
}
2329

2430
void SequenceNode::halt()
@@ -63,7 +69,8 @@ NodeStatus SequenceNode::tick()
6369
current_child_idx_++;
6470
// Return the execution flow if the child is async,
6571
// to make this interruptable.
66-
if (requiresWakeUp() && prev_status == NodeStatus::IDLE &&
72+
if (asynch_ && requiresWakeUp() &&
73+
prev_status == NodeStatus::IDLE &&
6774
current_child_idx_ < children_count)
6875
{
6976
emitWakeUpSignal();

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ set(BT_TESTS
1616
gtest_match.cpp
1717
gtest_ports.cpp
1818
gtest_json.cpp
19+
gtest_reactive.cpp
1920
gtest_sequence.cpp
2021
gtest_skipping.cpp
2122
gtest_substitution.cpp

tests/gtest_reactive.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <gtest/gtest.h>
2+
#include "behaviortree_cpp/bt_factory.h"
3+
#include "test_helper.hpp"
4+
5+
using BT::NodeStatus;
6+
using std::chrono::milliseconds;
7+
8+
static const char* reactive_xml_text = R"(
9+
<root BTCPP_format="4" >
10+
<BehaviorTree ID="MainTree">
11+
<ReactiveSequence>
12+
<Sequence name="first">
13+
<TestA/>
14+
<TestB/>
15+
<TestC/>
16+
</Sequence>
17+
<AsyncSequence name="second">
18+
<TestD/>
19+
<TestE/>
20+
<TestF/>
21+
</AsyncSequence>
22+
</ReactiveSequence>
23+
</BehaviorTree>
24+
</root>
25+
)";
26+
27+
28+
TEST(Reactive, RunningChildren)
29+
{
30+
BT::BehaviorTreeFactory factory;
31+
std::array<int, 6> counters;
32+
RegisterTestTick(factory, "Test", counters);
33+
34+
auto tree = factory.createTreeFromText(reactive_xml_text);
35+
36+
NodeStatus status = NodeStatus::IDLE;
37+
38+
int count=0;
39+
while(!BT::isStatusCompleted(status) && count<100)
40+
{
41+
count++;
42+
status = tree.tickExactlyOnce();
43+
}
44+
45+
ASSERT_NE(100, count);
46+
47+
ASSERT_EQ(status, NodeStatus::SUCCESS);
48+
49+
ASSERT_EQ(counters[0], 3);
50+
ASSERT_EQ(counters[1], 3);
51+
ASSERT_EQ(counters[2], 3);
52+
53+
ASSERT_EQ(counters[3], 1);
54+
ASSERT_EQ(counters[4], 1);
55+
ASSERT_EQ(counters[5], 1);
56+
}
57+
58+

0 commit comments

Comments
 (0)