ROS进阶——Behaviortree行为树

SMACH

BehaviorTree

一、简述

BehaviorTree_cpp_v3版本之间api存在改动,需注意版本问题

BehaviorTree.CPP has many interesting features, when compared to other implementations:

  • It makes asynchronous Actions, i.e. non-blocking, a first-class citizen.
  • It allows the creation of trees at run-time, using a textual representation (XML).
  • You can link staticaly you custom TreeNodes or convert them into plugins which are loaded at run-time.
  • It includes a logging/profiling infrastructure that allows the user to visualize, record, replay and analyze state transitions.
    在这里插入图片描述

二、nodes基础

在这里插入图片描述

ControlNodes和DecoratorNodes主要用于控制执行节点,不会执行实际工作,一般直接在xml中调用就好

  • ControlNodes:可以有1到N个子节点的节点,一旦收到tick,该tick可以传播给一个或多个子节点。
  • DecoratorNodes:类似于ControlNode,但它只能有一个子节点。

ActionNodes和ConditionNodes都是执行节点,执行实际任务,不存在子节点,一般使用时继承ActionNodes编写功能节点

  • ActionNodes:是叶子,没有子节点,用户应该实现自己的ActionNodes来执行实际任务。
  • ConditionNodes:等效于ActionNodes,但它们始终是同步执行的子叶,即它们不能返回RUNNING,也不能改变系统的状态。

2.1 ControlNodes

Sequences
Type of ControlNodeChild returns FAILUREChild returns RUNNING
SequenceRestartTick again
ReactiveSequenceRestartRestart
SequenceStarTick againTick again
Fallback
  • Before ticking the first child, the node status becomes RUNNING.
  • If a child returns FAILURE, the fallback ticks the next child.
  • If the last child returns FAILURE too, all the children are halted and the sequence returns FAILURE.
  • If a child returns SUCCESS, it stops and returns SUCCESS. All the children are halted.

The two versions of Fallback differ in the way they react when a child returns RUNNING:

  • FallbackStar will return RUNNING and the next time it is ticked, it will tick the same child where it left off before.
  • Plain old Fallback will return RUNNING and the index of the next child to execute is reset after each execution.

2.2 DecoratorNodes

  • InverterNode

    Tick the child once and return SUCCESS if the child failed or FAILURE if the child succeeded.

If the child returns RUNNING, this node returns RUNNING too.

  • ForceSuccessNode

    If the child returns RUNNING, this node returns RUNNING too.

    Otherwise, it returns always SUCCESS.

  • ForceFailureNode

    If the child returns RUNNING, this node returns RUNNING too.

    Otherwise, it returns always FAILURE.

  • RepeatNode

    Tick the child up to N times, where N is passed as a Input Port, as long as the child returns SUCCESS.

    Interrupt the loop if the child returns FAILURE and, in that case, return FAILURE too.

    If the child returns RUNNING, this node returns RUNNING too.

  • RetryNode

    Tick the child up to N times, where N is passed as a Input Port, as long as the child returns FAILURE.

2.3 ActionNodes

Sync同步:串行执行(按顺序,一个等一个),阻塞模式。

Async异步:并行执行(没有顺序,同时做),非阻塞模式。

  • BT::ActionNodeBase: 基类

  • BT::AsyncActionNode: The AsyncActionNode a different thread where the action will be executed. 当节点处于运行状态时,默认返回running,当使用Sequence时,再次被tick时,会再次调用running节点。

  • BT::CoroActionNode: The CoroActionNode class is an ideal candidate for asynchronous actions which need to communicate with a service provider using an asynch request/reply interface (being a notable example ActionLib in ROS, MoveIt clients or move_base clients).

  • BT::SimpleActionNode: The[SimpleActionNode provides an easy to use ActionNode. The user should simply provide a callback with this signature.

  • BT::SyncActionNode: is an helper derived class that explicitly forbids the status RUNNING and doesn’t require an implementation of halt(). 该节点不存在running状态,执行会一直等待直到返回状态。

三、数据交互(dataflow)

Behaviortree的数据交互形式为key/value键值对,数据的写入与读出都可以使用键或者数值。

3.1 数据写入与读出

  1. 在ActionNode类中定义static PortsList providedPorts()
// It is mandatory to define this static method.
static PortsList providedPorts()
{
    // Any port must have a name. The type is optional.
    return { BT::InputPort<std::string>("input_1"),
             BT::InputPort<Pose2D>("input_2"),
             BT::OutputPort<std::string>("output_1"),
             BT::OutputPort<std::string>("output_1")};
}
  1. tick()函数中写入和读出数据,基础数据默认都是std::string
// 写入数据
Optional<std::string> msg = getInput<std::string>("input_1");
// Check if optional is valid. If not, throw its error
if (!msg)
    throw BT::RuntimeError("missing required input [message]: ", 
                           msg.error());

// use the method value() to extract the valid message.
std::cout << "Robot says: " << msg.value() << std::endl;

// 读出数据
// the output may change at each tick(). Here we keep it simple.
setOutput("output_1", "The answer is 42" );
  1. xml中进行数据的交互
  • 直接进行数据交互
 <root>
     <BehaviorTree>
        <Sequence name="root">
            <get_data    input_1="start thinking..." />
            <send_data   output_1="{the_answer}"/>
            <get_data    input_1="{the_answer}" />
        </Sequence>
     </BehaviorTree>
 </root>
  • 使用Blackboard

A Blackboard is a key/value storage shared by all the Nodes of a Tree.

 <root main_tree_to_execute = "MainTree" >
     <BehaviorTree ID="MainTree">
        <SequenceStar name="root">
            <SetBlackboard   output_key="input_text" value="start thinking..." />
            <get_data    input_1="{input_text}" />
            <send_data   output_1="{the_answer}"/>
            <get_data    input_1="{the_answer}" />
        </SequenceStar>
     </BehaviorTree>
 </root>

3.2 数据的预处理

若需要写入其他类型数据,需对数据进行解析,通过模板函数BT::convertFromString<Position2D>(StringView),对数据进行分割(splitString(str, ';')),然后再调用convertFromString<double>转换到double类型。

struct Position2D 
{ 
  double x;
  double y; 
};

// Template specialization to converts a string to Position2D.
namespace BT
{
    template <> inline Position2D convertFromString(StringView str)
    {
        // The next line should be removed...
        printf("Converting string: \"%s\"\n", str.data() );

        // We expect real numbers separated by semicolons
        auto parts = splitString(str, ';');
        if (parts.size() != 2)
        {
            throw RuntimeError("invalid input)");
        }
        else{
            Position2D output;
            output.x     = convertFromString<double>(parts[0]);
            output.y     = convertFromString<double>(parts[1]);
            return output;
        }
    }
} // end namespace BT

参考

行为树(BT)笔记(一):BehaviorTree.CPP库简介

behaviortree

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
串口通信在ROS中是非常常见和重要的功能。下面是一些关于ROS串口通信的进阶知识: 1. 安装serial包:首先,你需要安装ROS的serial包。在终端中运行以下命令来安装:`sudo apt-get install ros-<your_ros_version>-serial` 2. 创建ROS节点:使用ROS中的串口通信,你需要创建一个ROS节点来处理串口数据。你可以使用C++或者Python编写节点。 3. 打开串口:在ROS节点中,你需要打开串口并进行配置。你可以使用serial包提供的函数来打开和配置串口。例如,在C++中,你可以使用`serial::Serial::open()`函数来打开串口,并使用`serial::Serial::setBaudrate()`函数来设置波特率。 4. 发送和接收数据:一旦打开了串口,你就可以通过串口发送和接收数据了。你可以使用serial包提供的函数来发送和接收字节流。例如,在C++中,你可以使用`serial::Serial::write()`函数来发送数据,并使用`serial::Serial::read()`函数来接收数据。 5. ROS消息和串口数据转换:通常,你可能还需要将串口数据转换为ROS消息,以便在ROS系统中进行处理。你可以根据你的需求创建自定义的ROS消息类型,并编写转换代码将串口数据转换为ROS消息。例如,在Python中,你可以使用`rospy.Publisher`来发布ROS消息。 6. ROS参数配置:为了方便地配置串口参数,你可以使用ROS参数服务器。你可以使用`rosparam`命令或者在launch文件中设置参数。这样,你就可以在运行节点时动态地配置串口参数。 这些是ROS中串口通信的一些进阶知识。希望对你有帮助!如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值