Skip to content

Commit 0d7464c

Browse files
Fix: DelayNode ignores delay_msec when created from XML (#1097)
* Initial plan * Fix DelayNode to honor delay_msec port from XML + add test Co-authored-by: facontidavide <2822888+facontidavide@users.noreply.github.com> * Improve DelayWithXML test to accurately measure delay timing Co-authored-by: facontidavide <2822888+facontidavide@users.noreply.github.com> * Final verification: All tests passing Co-authored-by: facontidavide <2822888+facontidavide@users.noreply.github.com> * Remove accidentally committed codeql build artifacts * Apply suggestion from @facontidavide * Apply suggestion from @facontidavide * Apply suggestion from @facontidavide --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: facontidavide <2822888+facontidavide@users.noreply.github.com> Co-authored-by: Davide Faconti <davide.faconti@gmail.com>
1 parent 46fe516 commit 0d7464c

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/decorators/delay_node.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DelayNode::DelayNode(const std::string& name, unsigned milliseconds)
1212
}
1313

1414
DelayNode::DelayNode(const std::string& name, const NodeConfig& config)
15-
: DecoratorNode(name, config), timer_id_(0), msec_(0)
15+
: DecoratorNode(name, config), timer_id_(0), msec_(0), read_parameter_from_ports_(true)
1616
{}
1717

1818
void DelayNode::halt()

tests/gtest_decorator.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,46 @@ TEST(Decorator, RunOnce)
220220
// counters[1] contains the number of times TestB was ticked
221221
ASSERT_EQ(counters[1], 5);
222222
}
223+
224+
// Test for DelayNode with XML: delay_msec port should be honored
225+
TEST(Decorator, DelayWithXML)
226+
{
227+
BT::BehaviorTreeFactory factory;
228+
229+
const std::string xml_text = R"(
230+
<root BTCPP_format="4" >
231+
<BehaviorTree>
232+
<Delay delay_msec="100">
233+
<AlwaysSuccess/>
234+
</Delay>
235+
</BehaviorTree>
236+
</root>)";
237+
238+
auto tree = factory.createTreeFromText(xml_text);
239+
240+
// First tick should return RUNNING (delay not complete)
241+
auto start = std::chrono::steady_clock::now();
242+
NodeStatus status = tree.tickOnce();
243+
ASSERT_EQ(status, NodeStatus::RUNNING);
244+
245+
// Wait for a short time, still should be RUNNING
246+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
247+
status = tree.tickOnce();
248+
ASSERT_EQ(status, NodeStatus::RUNNING);
249+
250+
// Poll until the delay completes (with timeout for safety)
251+
while(status == NodeStatus::RUNNING)
252+
{
253+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
254+
status = tree.tickOnce();
255+
}
256+
auto end = std::chrono::steady_clock::now();
257+
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
258+
259+
// The child (AlwaysSuccess) should have been executed after the delay
260+
ASSERT_EQ(status, NodeStatus::SUCCESS);
261+
// Verify that at least ~200ms have passed (with small tolerance for timing jitter)
262+
ASSERT_GE(elapsed.count(), 80);
263+
// Ensure the test didn't take too long (sanity check)
264+
ASSERT_LE(elapsed.count(), 200);
265+
}

0 commit comments

Comments
 (0)