Skip to content

Commit 9045993

Browse files
committed
fix issue #525 when ReactiveSequence contains skipped children
1 parent c71b2aa commit 9045993

File tree

6 files changed

+57
-30
lines changed

6 files changed

+57
-30
lines changed

src/controls/reactive_fallback.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ NodeStatus ReactiveFallback::tick()
5050
}
5151

5252
case NodeStatus::SKIPPED: {
53-
// node skipped
53+
// to allow it to be skipped again, we must reset the node
54+
haltChild(index);
5455
}
5556
break;
5657

src/controls/reactive_sequence.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ NodeStatus ReactiveSequence::tick()
4343
resetChildren();
4444
return NodeStatus::FAILURE;
4545
}
46-
// do nothing if SUCCESS or SKIPPED
47-
case NodeStatus::SUCCESS:
48-
case NodeStatus::SKIPPED:
46+
// do nothing if SUCCESS
47+
case NodeStatus::SUCCESS: break;
48+
49+
case NodeStatus::SKIPPED:{
50+
// to allow it to be skipped again, we must reset the node
51+
haltChild(index);
52+
}
4953
break;
5054

5155
case NodeStatus::IDLE: {

src/decorators/repeat_node.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ NodeStatus RepeatNode::tick()
8686
}
8787

8888
case NodeStatus::SKIPPED: {
89+
// to allow it to be skipped again, we must reset the node
90+
resetChild();
8991
// the child has been skipped. Skip the decorator too.
9092
// Don't reset the counter, though !
91-
return NodeStatus::IDLE;
93+
return NodeStatus::SKIPPED;
9294
}
9395
case NodeStatus::IDLE: {
9496
throw LogicError("[", name(), "]: A children should not return IDLE");

src/decorators/retry_node.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ NodeStatus RetryNode::tick()
9494
}
9595

9696
case NodeStatus::SKIPPED: {
97+
// to allow it to be skipped again, we must reset the node
98+
resetChild();
9799
// the child has been skipped. Slip this too
98100
return NodeStatus::SKIPPED;
99101
}

tests/gtest_skipping.cpp

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "behaviortree_cpp/basic_types.h"
44
#include "behaviortree_cpp/bt_factory.h"
55
#include "test_helper.hpp"
6+
#include "action_test_node.h"
67

78
using namespace BT;
89

@@ -121,39 +122,56 @@ TEST(SkippingLogic, SkippingReactiveSequence)
121122
std::array<int, 2> counters;
122123
RegisterTestTick(factory, "Test", counters);
123124

124-
const std::string xml_text = R"(
125+
const std::string xml_text_noskip = R"(
125126
<root BTCPP_format="4" >
126127
<BehaviorTree>
127-
<Sequence>
128-
<ReactiveSequence>
129-
<Script code=" value:=50 "/>
130-
<TestA _skipIf="value < 25"/>
131-
</ReactiveSequence>
132-
133-
<ReactiveSequence>
134-
<Script code=" value:=10 "/>
135-
<TestB _skipIf="value < 25"/>
136-
</ReactiveSequence>
137-
</Sequence>
128+
<ReactiveSequence>
129+
<Script code=" value:=50 "/>
130+
<TestA _skipIf="value < 25"/>
131+
<AsyncActionTest/>
132+
</ReactiveSequence>
138133
</BehaviorTree>
139134
</root>)";
140135

141-
auto tree = factory.createTreeFromText(xml_text);
136+
const std::string xml_text_skip = R"(
137+
<root BTCPP_format="4" >
138+
<BehaviorTree>
139+
<ReactiveSequence>
140+
<Script code=" value:=10 "/>
141+
<TestB _skipIf="value < 25"/>
142+
<AsyncActionTest/>
143+
</ReactiveSequence>
144+
</BehaviorTree>
145+
</root>)";
146+
147+
factory.registerNodeType<AsyncActionTest>("AsyncActionTest");
148+
149+
int expected_test_A_ticks = 0;
142150

143-
BT::NodeStatus status;
144-
try {
145-
int runs = 0;
146-
while(runs < 5)
151+
for(auto const* xml_text: {&xml_text_noskip, &xml_text_skip})
152+
{
153+
auto tree = factory.createTreeFromText(*xml_text);
154+
155+
for(int repeat=0; repeat<3; repeat++)
147156
{
148-
status = tree.tickOnce();
149-
tree.sleep(std::chrono::milliseconds(10));
150-
runs++;
157+
NodeStatus status = NodeStatus::IDLE;
158+
while(!StatusCompleted(status))
159+
{
160+
status = tree.tickOnce();
161+
162+
if(xml_text == &xml_text_noskip)
163+
{
164+
expected_test_A_ticks++;
165+
}
166+
167+
tree.sleep(std::chrono::milliseconds{15});
168+
}
169+
ASSERT_EQ(status, NodeStatus::SUCCESS);
151170
}
152-
} catch (BT::LogicError err) {
153-
std::cout << err.what() << std::endl;
154171
}
172+
// counters[0] contains the number ot times TestA was ticked
173+
ASSERT_EQ(counters[0], expected_test_A_ticks);
155174

156-
ASSERT_EQ(status, NodeStatus::SUCCESS);
157-
ASSERT_EQ(counters[0], 5);
175+
// counters[1] contains the number ot times TestB was ticked
158176
ASSERT_EQ(counters[1], 0);
159177
}

tests/test_helper.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ inline BT::NodeStatus TestTick(int* tick_counter)
1111

1212
template <size_t N> inline
1313
void RegisterTestTick(BT::BehaviorTreeFactory& factory, const std::string& name_prefix,
14-
std::array<int, N>& tick_counters)
14+
std::array<int, N>& tick_counters)
1515
{
1616
for(size_t i=0; i<tick_counters.size(); i++)
1717
{

0 commit comments

Comments
 (0)