Sequences and AsyncActionNode
原创
©著作权归作者所有:来自51CTO博客作者wx62fc501145180的原创作品,请联系作者获取转载授权,否则将追究法律责任
下面例子将展示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
"mission started..." />
<MoveBase goal="1;2;3"/>
<SaySomething message="mission completed!"
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开始执行,这样比较合理
"mission started..." />
<MoveBase goal="1;2;3"/>
<SaySomething message="mission completed!"
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!"