Sequences and AsyncActionNode
下面例子将展示SequenceNode和ReactiveSequence的不同
一个异步行为有它自己的线程;允许用户使用阻塞函数,但是要将执行流返回给到树;
//Custom type struct Pose2D { double x, y, theta; }; class MoveBaseAction : public AsyncActionNode { public: MoveBaseAction(const std::string& name, const NodeConfiguration& config) : AsyncActionNode(name, config) { } static PortsList providedPorts() { return{ InputPort<Pose2D>("goal") }; } NodeStatus tick() override; // This overloaded method is used to stop the execution of this node. void halt() override { _halt_requested.store(true); } private: std::atomic_bool_halt_requested; }; //------------------------- NodeStatus MoveBaseAction::tick() { Pose2D goal; if ( !getInput<Pose2D>("goal", goal)) { throw RuntimeError("missing required input [goal]"); } printf("[ MoveBase: STARTED ]. goal: x=%.f y=%.1f theta=%.2f\n", goal.x, goal.y, goal.theta); _halt_requested.store(false); int count = 0; // Pretend that "computing" takes 250 milliseconds. // It is up to you to check periodicall _halt_requested and interrupt // this tick() if it is true. while (!_halt_requested && count++ < 25) { SleepMS(10); } std::cout << "[ MoveBase: FINISHED ]" << std::endl; return _halt_requested ? NodeStatus::FAILURE : NodeStatus::SUCCESS; }
方法MoveBaseAction::tick()
在不主线程不同的线程中执行,主线程唤醒的MoveBaseAction::executeTick()
.
自己需要实现一个有效的halt()函数;
也需要实现一个函数convertFromString<Pose2D>(StringView)
;
Sequence与ReactiveSequence比较
下面是一个简单的SequenceNode
<root> <BehaviorTree> <Sequence> <BatteryOK/> <SaySomething message="mission started..." /> <MoveBase goal="1;2;3"/> <SaySomething message="mission completed!" /> </Sequence> </BehaviorTree> </root>
int main() { using namespace DummyNodes; BehaviorTreeFactory factory; factory.registerSimpleCondition("BatteryOK", std::bind(CheckBattery)); factory.registerNodeType<MoveBaseAction>("MoveBase"); factory.registerNodeType<SaySomething>("SaySomething"); auto tree = factory.createTreeFromText(xml_text); NodeStatus status; std::cout << "\n--- 1st executeTick() ---" << std::endl; status = tree.tickRoot(); SleepMS(150); std::cout << "\n--- 2nd executeTick() ---" << std::endl; status = tree.tickRoot(); SleepMS(150); std::cout << "\n--- 3rd executeTick() ---" << std::endl; status = tree.tickRoot(); std::cout << std::endl; return 0; }
Expected output: --- 1st executeTick() --- [ Battery: OK ] Robot says: "mission started..." [ MoveBase: STARTED ]. goal: x=1 y=2.0 theta=3.00 --- 2nd executeTick() --- [ MoveBase: FINISHED ] --- 3rd executeTick() --- Robot says: "mission completed!"
注意到当executeTick()被执行的时候,MoveBase返回RUNNING,在第一次和第二次,第三次最后成功;
BatteryOK只执行了一次;
如果使用ReactiveSequence,MoveBase返回RUNNING,序列sequence重新开始从BatteryOK开始执行,这样比较合理
<root> <BehaviorTree> <ReactiveSequence> <BatteryOK/> <Sequence> <SaySomething message="mission started..." /> <MoveBase goal="1;2;3"/> <SaySomething message="mission completed!" /> </Sequence> </ReactiveSequence> </BehaviorTree> </root>
Expected output: --- 1st executeTick() --- [ Battery: OK ] Robot says: "mission started..." [ MoveBase: STARTED ]. goal: x=1 y=2.0 theta=3.00 --- 2nd executeTick() --- [ Battery: OK ] [ MoveBase: FINISHED ] --- 3rd executeTick() --- [ Battery: OK ] Robot says: "mission completed!"
分类:
状态机
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2017-04-25 第十一课,ROS与传感器
2017-04-25 第十课,ROS仿真2
2017-04-25 第九课,ROS仿真1