文章目录

  • 一、通用端口功能实现
    • 1. 功能实现
      • 1.1 头文件定义
      • 1.2 源文件实现
      • 1.3 main文件实现
      • 1.4 tree.xml 实现
    • 2. 执行结果

使用行为树控制机器人(一) —— 节点
使用行为树控制机器人(二) —— 黑板
使用行为树控制机器人(三) —— 通用端口

有了上述前两节我们已经可以实现节点间的通信,BehaviorTree.CPP支持将字符串自动转换为常见类型(如int、long、double、bool、NodeStatus等),但作为导航,我们希望节点间实现自定义数据的传递,如:导航点的数据传递:

// 自定义二维位姿类型
struct Pose2D 
{ double x;double y; double yaw; 
};

接下来,我们将展示如何将通用的 C++ 类型作为端口。

一、通用端口功能实现

1. 功能实现

1.1 头文件定义

为了让XML加载器能从字符串中实例化Pose2D,需提供convertFromString(BT::StringView str) 的模板类实现。如何将Pose2D序列化为字符串参考如下:

// 在BT命名空间中特化字符串转换
namespace BT
{template <> inline Pose2D convertFromString(BT::StringView str){// 使用字符串流替代 splitStringstd::string input(str.data(), str.size());std::istringstream ss(input);Pose2D output;char delimiter;// 解析格式: "x;y;yaw"if (!(ss >> output.x >> delimiter >> output.y >> delimiter >> output.yaw) || delimiter != ';'){throw BT::RuntimeError("invalid input for Pose2D: " + input);}return output;}
} // end namespace BT

接着按照惯例,就是头文件定义操作了。

#ifndef BEHAVIOR_TREE_NODES_H
#define BEHAVIOR_TREE_NODES_H#include "behaviortree_cpp/bt_factory.h"
#include <iostream>
#include <sstream> // 添加 sstream 头文件// 自定义二维位姿类型
struct Pose2D 
{ double x;double y; double yaw; 
};// 在BT命名空间中特化字符串转换
namespace BT
{template <> inline Pose2D convertFromString(BT::StringView str){// 使用字符串流替代 splitStringstd::string input(str.data(), str.size());std::istringstream ss(input);Pose2D output;char delimiter;// 解析格式: "x;y;yaw"if (!(ss >> output.x >> delimiter >> output.y >> delimiter >> output.yaw) || delimiter != ';'){throw BT::RuntimeError("invalid input for Pose2D: " + input);}return output;}
} // end namespace BTnamespace BTNodes
{// 写入端口 "goal"
class CalculateGoal : public BT::SyncActionNode
{
public:CalculateGoal(const std::string& name, const BT::NodeConfig& config);static BT::PortsList providedPorts();BT::NodeStatus tick() override;
};// 读取端口
class PrintTarget : public BT::SyncActionNode
{
public:PrintTarget(const std::string& name, const BT::NodeConfig& config);static BT::PortsList providedPorts();BT::NodeStatus tick() override;
};} // namespace BTNodes#endif // BEHAVIOR_TREE_NODES_H

1.2 源文件实现

#include "behavior_tree_nodes.h"using namespace BTNodes;// CalculateGoal 实现
CalculateGoal::CalculateGoal(const std::string& name, const BT::NodeConfig& config) : BT::SyncActionNode(name, config)
{}BT::PortsList CalculateGoal::providedPorts()
{return { BT::OutputPort<Pose2D>("goal") };
}BT::NodeStatus CalculateGoal::tick()
{// 设置目标位置Pose2D mygoal = {1.1, 2.3, 0.0};setOutput<Pose2D>("goal", mygoal);return BT::NodeStatus::SUCCESS;
}// PrintTarget 实现
PrintTarget::PrintTarget(const std::string& name, const BT::NodeConfig& config) : BT::SyncActionNode(name, config)
{}BT::PortsList PrintTarget::providedPorts()
{// 可选:添加人类可读的描述const char* description = "打印目标位置到控制台";return { BT::InputPort<Pose2D>("target", description) };
}BT::NodeStatus PrintTarget::tick()
{auto res = getInput<Pose2D>("target");if (!res){throw BT::RuntimeError("error reading port [target]: " + res.error());}Pose2D target = res.value();printf("目标位置: [%.1f, %.1f, %.1f]\n", target.x, target.y, target.yaw);return BT::NodeStatus::SUCCESS;
}

1.3 main文件实现

#include "behavior_tree_nodes.h"
#include "behaviortree_cpp/bt_factory.h"
#include "behaviortree_cpp/loggers/bt_cout_logger.h"int main()
{BT::BehaviorTreeFactory factory;// 注册自定义节点factory.registerNodeType<BTNodes::CalculateGoal>("CalculateGoal");factory.registerNodeType<BTNodes::PrintTarget>("PrintTarget");// 内联 XML 定义const std::string xml_text = R"(
<root BTCPP_format="4" main_tree_to_execute="MainTree"><BehaviorTree ID="MainTree"><Sequence name="root"><CalculateGoal goal="{GoalPosition}" /><PrintTarget   target="{GoalPosition}" /><Script        code=" OtherGoal:='-1;3' " /><PrintTarget   target="{OtherGoal}" /></Sequence></BehaviorTree>
</root>
)";try {
#if 0// 从文本创建行为树const std::string tree_xml_path = xml_text;auto tree = factory.createTreeFromText(tree_xml_path);#else// 从XML文件 创建行为树const std::string tree_xml_path = "../trees/tree.xml";auto tree = factory.createTreeFromFile(tree_xml_path);
#endif// 添加日志记录器(可选)BT::StdCoutLogger logger(tree);// 打印树结构std::cout << "------ Behavior Tree Structure ------" << std::endl;BT::printTreeRecursively(tree.rootNode());std::cout << "------------------------------------" << std::endl;// 执行行为树tree.tickWhileRunning();} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;return 1;}return 0;
}

1.4 tree.xml 实现

在这里插入图片描述
行为树实现逻辑如上,xml文件定义如下:

<root BTCPP_format="4" main_tree_to_execute="MainTree"><BehaviorTree ID="MainTree"><Sequence name="root"><CalculateGoal goal="{GoalPosition}" /><PrintTarget   target="{GoalPosition}" /><Script        code=" OtherGoal:='-1;3;3.14' " /><PrintTarget   target="{OtherGoal}" /></Sequence></BehaviorTree>
</root>

2. 执行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93072.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93072.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93072.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DataDome反爬虫验证技术深度解析:无感、滑块与设备验证全攻略

DataDome反爬虫验证技术深度解析&#xff1a;无感、滑块与设备验证全攻略 随着网络安全威胁的不断演进&#xff0c;企业对数据保护的需求日益增强。DataDome作为业界领先的反爬虫解决方案&#xff0c;以其三层防护机制在众多知名网站中得到广泛应用。本文将深入解析DataDome的…

RabbitMQ 消息转换器详解

RabbitMQ 消息转换器详解 一、为什么需要消息转换器&#xff1f; RabbitMQ 的消息传输协议只识别字节流&#xff1a; 发送对象时&#xff0c;需要序列化成字节数组接收消息时&#xff0c;需要将字节数组反序列化成对象 如果不使用消息转换器&#xff1a; 需要手动序列化和反序列…

内网穿透的应用-告别“现场救火”!用 cpolar远程调试让内网故障排查进入“云时代”

文章目录前言**常见困境与解决方案****实际应用价值**1. Remote JVM Debug2. 系统要求与环境准备2.1 服务器环境2.2 本地开发环境3. 内网服务器准备及开始3.1 安装cpolar配置支持远程ssh登录3.1.1 什么是cpolar&#xff1f;3.1.2 安装cpolar3.1.3 注册及配置cpolar系统服务3.1.…

Cherryusb UAC例程对接STM32内置ADC和PWM播放音乐和录音(下)=>UAC+STM32 ADC+PWM实现录音和播放

1. 程序基本框架整个程序框架, 与之前的一篇文章《Cherryusb UAC例程对接STM32内置ADC和DAC播放音乐和录音(中)>UACSTM32 ADCDAC实现录音和播放》基本一致, 只是这次将DAC替换成了PWM。因此这里不再赘述了。 2. audio_v1_mic_speaker_multichan_template.c的修改说明(略) 参…

1 JQ6500语音播报模块详解(STM32)

系列文章目录 文章目录系列文章目录前言1 JQ6500简介2 基本参数说明2.1 硬件参数2.2 模块管脚说明3 控制方式3.1 通信格式3.2 通信指令4 硬件设计5 软件设计5.1 main.c5.2 board_config5.2.1board_config.h5.2.2 board_config.c5.3 module_config5.3.1 module_config.h5.3.2 mo…

常用数据分析工具

Tableau丨Power BI丨FineBI丨SQL丨影刀丨Excel丨Python丨 参考视频&#xff1a;【戴师兄】数据分析有哪些必学工具&#xff1f;2023最新版&#xff01;Tableau丨Power BI丨FineBI丨SQL丨影刀丨Excel丨Python丨课程教程自学攻略_哔哩哔哩_bilibili 文档资料&#xff1a; 【戴师兄…

OBOO鸥柏丨智能会议平板教学查询一体机交互式触摸终端招标投标核心标底参数要求

整机参数要求&#xff1a;55寸/65寸/75寸/85-86寸/98寸/100寸/110寸/115寸智能会议平板教学触控一体机/智慧黑板触摸屏招标投标核心标底参数要求1、整机屏幕采用≥采用超高清原厂原包原装工业LCD液晶屏面板&#xff1b;具有高色域&#xff0c;显示动态视频、web及3D动画时&…

无人机在环保监测中的应用:低空经济发展的智能监测与高效治理

一、行业背景与技术革新 随着全球环境问题日益严峻&#xff0c;传统环保监测手段已难以满足现代环境管理的需求。固定监测站点建设成本高、覆盖范围有限&#xff0c;地面巡查效率低下且存在安全风险。在此背景下&#xff0c;无人机技术凭借其独特的空间优势和技术特性&#xff…

PO、BO、VO、DTO、POJO、DAO、DO基本概念

一、图解二、相关概念 1、PO&#xff08;Persistant Object - 持久化对象&#xff09; 核心定位&#xff1a; 直接与数据库表结构一一映射的对象&#xff0c;通常用于 ORM&#xff08;对象关系映射&#xff09;框架&#xff08;如 MyBatis、Hibernate&#xff09;中。 特点&…

todoList清单(HTML+CSS+JavaScript)

&#x1f30f;个人博客主页&#xff1a; 前言&#xff1a; 前段时间学习了JavaScript&#xff0c;然后写了一个todoList小项目&#xff0c;现在和大家分享一下我的清单以及如何实现的&#xff0c;希望对大家有所帮助 &#x1f525;&#x1f525;&#x1f525;文章专题&#xff…

Mac M1探索AnythingLLM+Ollama+知识库问答

AnythingLLM内置 RAG、AI Agent、可视化/无代码的 Agent 编排&#xff0c;支持多家模型与本地/云端向量库&#xff0c;并提供多用户与可嵌入的聊天组件&#xff0c;用来快速验证“知识 模型 工具”拼成的 AI 应用。 1 AnythingLLM、Ollama准备 1&#xff09;AnythingLLM 打…

【 Navicat Premium 17 完全图形化新手指南(从零开始)】

Navicat Premium 17 完全图形化新手指南&#xff08;从零开始&#xff09; 一、准备阶段&#xff1a;清理现有环境 1. 删除已创建的测试数据库&#xff08;如需重新开始&#xff09;打开Navicat Premium 17 双击桌面图标启动程序在左侧连接面板中找到你的MySQL连接&#xff08;…

Web学习笔记5

Javascript概述1、JS简介JS是运行在浏览器的脚本编程语言&#xff0c;最初用于Web表单的校验。现在的作用主要有三个&#xff1a;网页特效、表单验证、数据交互JS由三部分组成&#xff0c;分别是ECMAscript、DOM、BOM&#xff0c;其中ECMAscript规定了JS的基本语法和规则&#…

部署一个开源的证件照系统

以下数据来自官方网站,记录下来,方便自己 项目简介 &#x1f680; 谢谢你对我们的工作感兴趣。您可能还想查看我们在图像领域的其他成果&#xff0c;欢迎来信:zeyi.linswanhub.co. HivisionIDPhoto 旨在开发一种实用、系统性的证件照智能制作算法。 它利用一套完善的AI模型工作…

Linux客户端利用MinIO对服务器数据进行同步

接上篇 Windows客户端利用MinIO对服务器数据进行同步 本篇为Linux下 操作&#xff0c;先看下我本地的系统版本 所以我这里下载的话&#xff0c;是AMD64 文档在这 因为我这里只是需要用到客户端&#xff0c;获取数据而已&#xff0c;所以我只需要下载个MC工具用来数据获取就可以…

Docker 中部署 MySQL 5.7 并远程连接 Navicat 的完整指南

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

自己动手造个球平衡机器人

你是否曾对那些能够精妙地保持平衡的机器设备感到好奇&#xff1f; 从无人机到独轮平衡车&#xff0c;背后都蕴藏着复杂的控制系统。 今天&#xff0c;我们来介绍一个充满挑战与乐趣的项目——制作一个球平衡机器人。这不仅是一个酷炫的摆件&#xff0c;更是一次深入学习机器…

21.Linux HTTPS服务

Linux : HTTPS服务协议传输方式端口安全性HTTP明文传输80无加密&#xff0c;可被窃听HTTPS加密传输443HTTP SSL/TLS 数据加密&#xff08;防窃听&#xff09;身份认证&#xff08;防伪装&#xff09;完整性校验&#xff08;防篡改&#xff09;OpenSSL 证书操作核心命令命令选项…

SqlSugar 跨方法 操作临时表

.net项目中时长会有用到临时表的操作结果如下所示但是在SqlSugar中可能因为会话问题导致临时表访问受限 搜索到的方式var conn (SqlConnection)sugarClient.Ado.Connection;if (conn.State ! System.Data.ConnectionState.Open) {conn.Open();}using (var cmd new SqlCommand…

怎么用飞算javaAI实现视频逐帧截图并保存

相信很多朋友都遇到过这样的需求&#xff1a;想从视频中截取特定帧作为素材&#xff0c;却苦于没有简单易用的工具&#xff0c;要么操作复杂难以精准定位&#xff0c;要么导出的图片质量不佳。市面上的视频处理软件要么功能冗余&#xff0c;要么需要付费才能使用逐帧截取功能&a…