当前位置: 首页 > news >正文

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_bttouch 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 finishcd course_bt
./bt_medium

预期产出

感谢您的阅读。

四、结论

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

相关文章:

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

马库斯布赫霍尔茨 一、说明 以下文章为您提供了对机器人应用程序或框架中经常使用的行为树的一般直觉&#xff1a;ROS&#xff0c;Moveit和NAV2。了解行为 Tress &#xff08;BT&#xff09; 框架的原理为您提供了在游戏领域应用知识的绝佳机会。BT可以与Unity或Unreal集成。 由…...

像Vuex一样使用redux

redux基础知识 本篇文章主要介绍redux的基本使用方法&#xff0c;并简单封装&#xff0c;像vuex一样写redux 学习文档 英文文档: https://redux.js.org/ 中文文档: http://www.redux.org.cn/ Github: https://github.com/reactjs/redux redux是什么 redux和vuex几乎是一…...

关于模板的大致认识【C++】

文章目录 函数模板函数模板的原理函数模板的实例化模板参数的匹配原则 类模板类模板的定义格式类模板的实例化 非类型模板参数typename 与class模板的特化函数模板特化类模板特化全特化偏特化 模板的分离编译 函数模板 函数模板的原理 template <typename T> //模板参数…...

C#如何遍历类的属性,并获取描述/注释

要获取属性的描述/注释&#xff0c;需要使用System.ComponentModel命名空间中的DescriptionAttribute。可以通过反射获取属性上的DescriptionAttribute&#xff0c;并获取其Description属性值。 首先&#xff0c;需要引入System.ComponentModel命名空间&#xff1a; using Sy…...

ffmpeg 子进程从内存读取文件、提取图片到内存

除了网络、文件io&#xff0c;由python或java或go或c等语言开启的ffmpeg子进程还支持pipe&#xff0c;可以从stdin读入数据&#xff0c;输出转化后的图像到stdout。无需编译 ffmpeg&#xff0c;直接调用 ffmpeg.exe不香么&#xff01; “从内存读”可用于边下载边转码&#xf…...

Springboot+Netty+WebSocket搭建简单的消息通知

SpringbootNettyWebSocket搭建简单的消息通知 一、快速开始 1、添加依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.36.Final</version> </dependency> <dependency>…...

@RefreshScope静态变量注入

RefreshScope注解通常用于注入实例变量&#xff0c;而不是静态变量。由于静态变量与类直接关联&#xff0c;刷新操作无法直接影响它们。 如果你需要动态刷新静态变量的值&#xff0c;一种可行的方案是使用一个通过Value注解注入的实例变量&#xff0c;并在该实例变量的getter方…...

多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测

多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现SABO-CNN-GRU-Attention多变量时间序列预测。 模型描…...

SAP 凭证项目文本 增强 demo2

SAP 凭证项目文本 增强 demo2 增强点 AC_DOCUMENT METHOD if_ex_ac_document~change_initial. DATA: ls_item TYPE accit, ls_exitem TYPE accit_sub, lv_sgtxt TYPE bseg-sgtxt, lv_bktxt TYPE bkpf-bktxt, lv_zuonr TYPE bseg-zuonr, lv_blart TYPE bkpf-blart, lv_zprono TY…...

一套基于C#语言开发的LIMS实验室信息管理系统源码

实验室信息管理系统&#xff08;LIMS)是指帮助实验室组织和管理实验数据的计算机软件系统&#xff0c;它将实验室操作有机地组织在一起&#xff0c;以满足实验室工作流程的所有要求。它能以不同的方式支持实验室的工作&#xff0c;从简单的过程(如样品采集和入库)到复杂的流程(…...

kubesphere部署rocketmq5.x,并对外暴露端口

kubesphere是青云开源的k8s管理工具&#xff0c;用户可以方便的通过页面进行k8s部署的部署&#xff0c;rocketmq则是阿里开源的一款mq平台&#xff0c;现在版本为5.1.3版本&#xff0c;较比4.x版本的rocketmq有比较大的调整&#xff1a;比如客户端的轻量化&#xff08;统一通过…...

5.8 汇编语言:汇编高效除法运算

通常情况下计算除法会使用div/idiv这两条指令&#xff0c;该指令分别用于计算无符号和有符号除法运算&#xff0c;但除法运算所需要耗费的时间非常多&#xff0c;大概需要比乘法运算多消耗10倍的CPU时钟&#xff0c;在Debug模式下&#xff0c;除法运算不会被优化&#xff0c;但…...

如何通过python来给手机发送一条短信?

要通过Python发送短信到手机,您可以使用不同的短信服务提供商的API。以下是一个使用Twilio和Sinch服务提供商的示例,您可以根据自己的选择来决定使用哪个。 使用Twilio发送短信: 首先,注册一个Twilio账户并获取您的账户SID、认证令牌和Twilio号码。 安装 twilio 包,如果您…...

无涯教程-PHP - IntlChar类

在PHP7中&#xff0c;添加了一个新的 IntlChar 类&#xff0c;该类试图公开其他ICU函数。此类定义了许多静态方法和常量&#xff0c;可用于操作unicode字符。使用此类之前&#xff0c;您需要先安装 Intl 扩展名。 <?phpprintf(%x, IntlChar::CODEPOINT_MAX);print (IntlCh…...

【Linux操作系统】Linux系统编程中信号捕捉的实现

在Linux系统编程中&#xff0c;信号是一种重要的机制&#xff0c;用于实现进程间通信和控制。当某个事件发生时&#xff0c;如用户按下CtrlC键&#xff0c;操作系统会向进程发送一个信号&#xff0c;进程可以捕获并相应地处理该信号。本篇博客将介绍信号的分类、捕获与处理方式…...

【PHP】基础语法变量常量

文章目录 PHP简介前置知识了解静态网站的特点动态网站特点 PHP基础语法代码标记注释语句分隔(结束)符变量变量的基本概念变量的使用变量命名规则预定义变量可变变量变量传值内存分区 常量基本概念常量定义形式命名规则使用形式系统常量魔术常量 PHP简介 PHP定义&#xff1a;一…...

Failed to resolve: com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0

在allprojects下的repositories闭包里面添加jcenter()和maven {url https://jitpack.io}&#xff0c;具体可以看你的第三方框架需要添加什么仓库&#xff0c;大多数都只需要上面两个。 我的build.gradle&#xff08;Project&#xff09;完整内容如下&#xff1a; buildscript …...

常用 Python IDE 汇总(非常详细)从零基础入门到精通,看完这一篇就够了

写 Python 代码最好的方式莫过于使用集成开发环境&#xff08;IDE&#xff09;了。它们不仅能使你的工作更加简单、更具逻辑性&#xff0c;还能够提升编程体验和效率。 每个人都知道这一点。而问题在于&#xff0c;如何从众多选项中选择最好的 Python 开发环境。初级开发者往往…...

【Hive】HQL Map 『CRUD | 相关函数』

文章目录 1. Map 增删改查1.1 声明 Map 数据类型1.2 增1.3 删1.4 改1.5 查 2. Map 相关函数2.1 单个Map 3. Map 与 String3.1 Map 转 string3.2 string 转 Map 1. Map 增删改查 1.1 声明 Map 数据类型 语法&#xff1a;map<基本数据类型, 基本数据类型> 注意是<>…...

ELF修复基本工作原理

ELF修复基本工作原理 ELF(Executable and Linkable Format)是一种常见的可执行文件和可链接文件的格式,广泛用于Linux和UNIX系统中。ELF修复是指对ELF文件进行修改或修复,以确保其正确加载和执行。 ELF修复的基本工作原理如下: 识别ELF文件:首先,需要识别和验证目标文…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...