C++中机器人应用程序的行为树(ROS2)

马库斯·布赫霍尔茨

一、说明

         以下文章为您提供了对机器人应用程序或框架中经常使用的行为树的一般直觉:ROS,Moveit和NAV2。了解行为 Tress (BT) 框架的原理为您提供了在游戏领域应用知识的绝佳机会。BT可以与Unity或Unreal集成。

        由于 BT 是提供创建 BT 框架(C++ 年)的C++库,因此本文重点介绍 BT 的概述。 您对此领域的兴趣可以通过在线课程和实践课程来扩展,我强烈推荐。如果您对学习ROS,机器人,AI,ML,软件等更感兴趣,请查看The ConstructSim网站,并从您可以学到的内容中获得灵感。他们还有一个完美的机器人开发人员大师班,让您进入梦想中的公司。

        此外,对于在线课程,请下载免费书籍并从此YouTube频道中获得灵感。

在这里,您还可以找到BT的精彩介绍链接到在线环境,您可以在其中运行移动机器人。

二、行为树、软件架构

       BT 框架是一个C++库,使您能够在机器人或游戏应用程序中构建 BT。BT 提供了抽象方法(内置于 C++ 年)来保护应用程序中的逻辑关系。例如,如果您开发游戏,则行为树可以与游戏的性能相关,或者定义游戏角色在某些游戏情况下的行为方式等。在这方面,我们声明BT框架提供了在C++类之间启用逻辑/抽象关系的工具,这些类的方法是根据程序的逻辑树(BT)结构调用的。

        BT 可以与状态机 (SM) 相关联,但是 BT 优于 SM 存在某些差异。SM 的主要问题是状态之间的转换随着状态数量的增加而增加。
        SM 中的状态是紧密连接的,当需要重用时,通常会出现问题。诚然,设计师(软件工程师)可以轻松处理SM,但一个人无疑会发现很难理解和预测系统的整体行为。这些问题中的大多数都由行为树解决,它增强了模块化设计并且可以重用。行为树本质上是分层的。

        下图为您提供了BT的一般概述。 如您所见,BT框架可以独立运行,无需ROS(正如我在设计游戏时提到的)。稍后我将给你一个例子,说明如何构建一个简单的BT并运行你的第一个程序。请注意,官方网站上的教程非常出色,应相应地进行研究以解决所有剩余问题。

软件架构概述

        我们可以想象您的机器人执行任务。为了保证机器人(例如机器人清洁器)的任务性能,“主要”任务分为几个子任务,如路径规划、感知、空间定向和电源管理等(在 ROS 中,所有这些子任务都可以分布在节点上)。所有这些子任务都可以被视为低级任务,这些任务不是由BT构建的。
        一个任务或动作可以依赖于一个或多个先前的动作,同时,不同的条件必须为真/假才能影响机器人/应用程序动作。

        关于机器人技术,BT是一种从低级任务控制(路径规划器,电源管理等)转移到更高层次行为的抽象。

        当我们设计机器人系统时,我们仍然必须考虑基本组件(低级动作/任务)如何工作并寻找优化(例如,通过添加启发式来提高路径算法的性能)。

        然而,为了构建整个机器人应用程序的架构,我们需要转向更高层次的编程抽象,这意味着将路径规划器或电源管理等任务作为一个简单的组件进行评估。

        我们使用高度抽象的概念,因此详细说明这种抽象的位置似乎是合理的。下图概述了抽象堆栈。

抽象堆栈 

        所描绘的堆栈可以考虑如下。工程师/设计师负责机器人应用程序的需求,并构建应用程序的逻辑流程(创建行为树)。
        BT(逻辑流)的结构模仿机器人的行为(游戏中的人物)。我们可以说,设计人员在逻辑上连接了机器人基元以反映机器人应用的规范。
BT 被建模为 XML 格式化文件。C++框架(BehaviorTree.CPP)允许在您的应用程序中构建BT。机器人任务的定义(C++中的程序功能)完成以下堆栈。

        在讨论BT的概念时,我使用了逻辑流公式。在软件设计的上下文中,我们可以将所讨论的概念评估为某些软件模块(节点)之间的逻辑连接。逻辑连接可以描述为使用某个逻辑运算符,如 AND、OR 或 NOT 包装到 BT 框架中。

        BT框架的美妙之处在于,设计人员可以完全实现所有机制和其他组件,以构建复杂的逻辑结构。此外,逻辑流可以设计为多线程应用程序,而无需不必要的工作。支持线程处理的所有C++机制都合并到框架中。

三、逻辑基元

        由于本文的想法是对BT的唯一介绍,我将重点介绍基本的逻辑组件,我将在后面的实际C++示例中使用这些组件。ROS2(银河)的例子,你可以在这里或课程中找到。

        在简单的原理中(仅出于本文的目的),我们可以区分两个逻辑节点(BT 机制)。回退实现逻辑OR和序列节点,实现AND逻辑。

        两者都可以描述如下,

回退节点(OR 运算符)。(作者)

序列节点(AND 运算符)

  

        BT 的体系结构在应用程序读取的 XML 文件中指定。BehaviorTree.CPP框架根据XML规范(我们说调用回调)管理逻辑流(勾选BT节点)。基于状态的节点(此处为任务)将返回信号发送到“根”(应用程序的主节点)。信号可以是成功、失败或正在运行

        下面的示例结合了上述机制,并显示了上述信号如何在BT上分布。

英国电信在行动

 

        我们可以这样描述上面的BT,

        推导出这种BT哲学,我们可以通过考虑以下示例来描述以下BT的工作原理。

        1. 呈现的BT由4个任务组成,落回和序列节点。

        2. 将刻度发送到该回退的根。我们沿着左侧走。回退向任务 1 发送一个时钟周期,这是一个失败(当然这只是模拟)。通常,成功或失败的决定是由正在运行的程序做出的。在我们的例子中,回调返回失败。
请注意,现在我们运行回退节点(OR),它至少需要一个成功才能返回成功,因此可以检查所有节点。对于序列节点 (AND),第一个 FAILURE 终止“节点调查”。

        3. 与任务 1 类似,任务 2 回调返回失败。由于我们仍然运行回退机制(OR),因此我们继续。

        4. 现在,即时报价被发送到序列节点 (AND)。序列将时钟周期发送到任务 3 并接收成功,但序列是逻辑 AND 操作,因此我们继续检查是否全部成功。
任务 4 是成功,因此根也收到成功。

        描述上述 BT 描述的逻辑的 XML 可以表述为:

 <root main_tree_to_execute = "MainTree" >

     <BehaviorTree ID="MainTree">
        <Fallback name="root">
            <Task1 name="task_1"/>
            <Task2 name="task_2"/>
            <Sequence>
                <Task3 name="task_3"/>
                <Task4  name="task_4"/>
            </Sequence>
        </Fallback>
     </BehaviorTree>

 </root>
 )";

下面您将找到可以在 ROSject 中运行的代码。(ROS2银河)

#include "behaviortree_cpp_v3/bt_factory.h"

using namespace BT;

class Task1 : public BT::SyncActionNode
{
  public:
    Task1(const std::string& name) : BT::SyncActionNode(name, {})
    {
    }

    // You must override the virtual function tick()
    NodeStatus tick() override
    {
        std::cout << "Task1: " << this->name() << std::endl;
        return BT::NodeStatus::FAILURE;
    }
};

class Task2 : public BT::SyncActionNode
{
  public:
    Task2(const std::string& name) : BT::SyncActionNode(name, {})
    {
    }

    // You must override the virtual function tick()
    NodeStatus tick() override
    {
        std::cout << "Task2: " << this->name() << std::endl;
        return BT::NodeStatus::FAILURE;
    }
};

class Task3 : public BT::SyncActionNode
{
  public:
    Task3(const std::string& name) : BT::SyncActionNode(name, {})
    {
    }

    // You must override the virtual function tick()
    NodeStatus tick() override
    {
        std::cout << "Task3: " << this->name() << std::endl;
        return BT::NodeStatus::SUCCESS;
    }
};

class Task4 : public BT::SyncActionNode
{
  public:
    Task4(const std::string& name) : BT::SyncActionNode(name, {})
    {
    }

    // You must override the virtual function tick()
    NodeStatus tick() override
    {
        std::cout << "Task4: " << this->name() << std::endl;
        return BT::NodeStatus::SUCCESS;
    }
};

static const char* xml_text_medium = R"(

 <root main_tree_to_execute = "MainTree" >

     <BehaviorTree ID="MainTree">
        <Fallback name="root">
            <Task1 name="task_1"/>
            <Task2 name="task_2"/>
            <Sequence>
                <Task3 name="task_3"/>
                <Task4  name="task_4"/>
            </Sequence>
        </Fallback>
     </BehaviorTree>

 </root>
 )";

int main()
{
    BehaviorTreeFactory factory;

    factory.registerNodeType<Task1>("Task1");
    factory.registerNodeType<Task2>("Task2");
    factory.registerNodeType<Task3>("Task3");
    factory.registerNodeType<Task4>("Task4");

    std::cout << "\n------------ BUILDING A NEW TREE ------------" << std::endl;

    auto tree = factory.createTreeFromText(xml_text_medium);

    tree.tickRoot();

    std::cout << std::endl;

    // }

    return 0;
}

In the ROSject (on a Linux terminal) perform the following actions,

cd /ros2_ws/src/bt_course_files/BehaviorTree.CPP/course_bt

touch bt_medium.cpp

// go to VSC  to the same folder where you created bt_medium.cpp

// paste above code

// in the same folder modify the CMakeList.txt by adding:
// CompileExample("bt_medium")

cd ros2_ws/src/bt_course_files/BehaviorTree.CPP/build
cmake ..
make

// after building is finish
 
cd course_bt
./bt_medium

预期产出

感谢您的阅读。

四、结论

        关于BT的概念,需要更多的文档介绍;BT 可以与状态机 (SM) 相关联,但是 BT 优于 SM 存在某些差异。SM 的主要问题是状态之间的转换随着状态数量的增加而增加,而BT没有类似难点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/83666.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

操作符详解(1)

1. 操作符分类&#xff1a; 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 1. 除了 % 操作符之外&#xff0c;其他的几个操作符可以作用于整数和浮点数。 2. 对…

springboot 项目日志配置文件详解

spring boot 项目指定 日志配置文件 在Spring Boot项目中&#xff0c;可以通过在application.properties或application.yml文件中指定日志配置文件来配置日志。 1. 使用application.properties文件&#xff1a; 在application.properties中&#xff0c;您可以使用以下属性来…

元核云私募双录助力私募基金业务高效合规

近年来&#xff0c;私募基金监管政策不断收紧&#xff0c;今年7月发布的《私募投资基金监督管理条例》更是把私募投资基金业务活动纳入法治化、规范化轨道进行监管。 作为保障私募基金业务透明合规的重要手段&#xff0c;“双录”一直是私募流程中非常重要的一环&#xff0c;多…

三、SQL注入之报错注入

文章目录 1、 xpath语法&#xff08;1&#xff09;extractvalue&#xff08;2&#xff09;updatexml 2、concatrand()group by()导致主键重复 报错注入就是利用了数据库的某些机制&#xff0c;人为地制造错误条件&#xff0c;使得查询结果能够出现在错误信息中。这里主要介绍报…

动漫3D虚拟人物制作为企业数字化转型提供强大动力

一个 3D 虚拟数字人角色的制作流程&#xff0c;可以分为概念设定-3D 建模-贴图-蒙皮-动画-引擎测试六个步骤&#xff0c;涉及到的岗位有原画师、模型师、动画师等。角色概念设定、贴图绘制一般是由视觉设计师来完成;而建模、装配(骨骼绑定)、渲染动画是由三维设计师来制作完成。…

⛳ TCP 协议面试题

目录 ⛳ TCP 协议面试题&#x1f43e; 一、为什么关闭连接的需要四次挥⼿&#xff0c;⽽建⽴连接却只要三次握⼿呢&#xff1f;&#x1f3ed; 二、为什么连接建⽴的时候是三次握⼿&#xff0c;可以改成两次握⼿吗&#xff1f;&#x1f463; 三、为什么主动断开⽅在TIME-WAIT状态…

wustojc3001求三角形面积

#include <stdio.h> #include <math.h> int main() {float a,b,c,d;double s;scanf("%f%f%f",&a,&b,&c);if(ab>c&&ac>b&&cb>a){d(abc)/2;ssqrt(d*(d-a)*(d-b)*(d-c));//数学公式printf("%.2f",s);}retur…

(成功踩坑)electron-builder打包过程中报错

目录 注意&#xff1a;文中的解决方法2&#xff0c;一定全部看完&#xff0c;再进行操作&#xff0c;有坑 背景 报错1&#xff1a; 报错2&#xff1a; 1.原因&#xff1a;网络连接失败 2.解决方法1&#xff1a; 3.解决方法2&#xff1a; 3.1查看缺少什么资源文件 3.2去淘…

软件开发bug问题跟踪与管理

一、Redmine 项目管理和缺陷跟踪工具 官网&#xff1a;https://www.redmine.org/ Redmine 是一个开源的、基于 Web 的项目管理和缺陷跟踪工具。它用日历和甘特图辅助项目及进度可视化显示&#xff0c;同时它又支持多项目管理。Redmine 是一个自由开源软件解决方案&#xff0c;…

如何将图片应用于所有的PPT页面?

问题&#xff1a;如何快速将图片应用到所有PPT页面&#xff1f; 解答&#xff1a;有两种方法可以解决这个问题。第一种用母板。第二种用PPT背景功能。 解决有时候汇报的时候&#xff0c;ppt中背景图片修改不了以及不知道如何查找&#xff0c;今天按照逆向过程进行操作 方法1…

详解C#-static void Main(string[] args)

目录 简介: 举例: 输出结果:​编辑 总结&#xff1a; 简介: 在C#中static void Main(string[] args)这个句话有什么作用&#xff0c;分别代表什么意思&#xff01;&#xff01; 这句话是入口函数的声明&#xff0c;指定了C#程序的入口点&#xff0c;并定义了一个名为”Mai…

Go语言GIN框架安装与入门

Go语言GIN框架安装与入门 文章目录 Go语言GIN框架安装与入门1. 创建配置环境2. 配置环境3. 下载最新版本Gin4. 编写第一个接口5. 静态页面和资源文件加载6. 各种传参方式6.1 URL传参6.2 路由形式传参6.3 前端给后端传递JSON格式6.4 表单形式传参 7. 路由和路由组8. 项目代码mai…

wustojc3006水果店收款

#include <stdio.h> int main() {double a,b,c,d,sum;scanf("%lf%lf%lf%lf",&a,&b,&c,&d);suma*2.5b*1.7c*2.0d*1.2;printf("%.2lf",sum);//注意保留几位小数return 0;}

图数据库_Neo4j学习cypher语言_常用函数_关系函数_字符串函数_聚合函数_数据库备份_数据库恢复---Neo4j图数据库工作笔记0008

然后再来看一些常用函数,和字符串函数,这里举个例子,然后其他的 类似 可以看到substring字符串截取函数 可以看到截取成功 聚合函数 这里用了一个count(n) 统计函数,可以看到效果 关系函数,我们用过就是id(r) 可以取出对应的r的id来这样..

Scratch 游戏 之 随机大地图生成教程

在很多生存 / 沙盒类游戏中&#xff0c;地图往往是随机生成的&#xff0c;例如&#xff1a;饥荒、我的世界等。那我们该如何在scratch中实现这一点呢&#xff1f; 在scratch中有两种办法可以实现——画笔和克隆体。我们这次先聊克隆体。 我们可以先将克隆体设置为方形的&#x…

python AI绘图教程

前提 1.安装python 2.安装git 步骤 下载stable-diffusion-webui项目&#xff08;链接&#xff1a;GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI&#xff09; git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git 安装st…

.netcore grpc客户端工厂及依赖注入使用

一、客户端工厂概述 gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。可以通过依赖包Grpc.Net.ClientFactory中的AddGrpcClient进行gRPC客户端依赖注入AddGrpcClient函数提供了许多配置项用于处理一些其他事项&#xff1b;例如AOP、重试策略等 二、案…

azure VM完全复制

创建虚拟机&#xff0c;并创建linux服务&#xff0c;可以参考 https://blog.csdn.net/m0_48468018/article/details/132267096 &#xff0c; https://blog.csdn.net/m0_48468018/article/details/132267315在虚拟机中点击磁盘快照&#xff0c;创建磁盘快照 通过磁盘快照创建磁盘…

我的编程语言学习笔记

前言 作为一名编程初学者&#xff0c;我深知学习编程需要不断积累和记录。在这篇博客文章中&#xff0c;我将分享一些我在学习C/C编程语言过程中记录的常用代码、特定函数、复杂概念以及特定功能。希望能与大家一起切磋进步&#xff01; 常用代码&#xff1a; 1. 输入输出操作…

vscode如何关闭受限模式

受限模式旨在实现安全地浏览代码 第一步&#xff1a; 第二步&#xff1a;输入trust,找到Security.workspace.trust,取消勾选 第三步&#xff1a; 重启vscode.