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

使用行为树控制机器人(三) ——通用端口

文章目录

  • 一、通用端口功能实现
    • 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.dtcms.com/a/325885.html

相关文章:

  • Python面试题及详细答案150道(41-55) -- 面向对象编程篇
  • 《基于Redis实现高效消息队列的完整指南》
  • 在 RHEL9 上搭建企业级 Web 服务(Tomcat)
  • Java Selenium 自动打开浏览器保存截图
  • Spring Cloud系列—Gateway统一服务入口
  • 案例分析2:上层应用不稳定提示注册失败
  • Python(9)-- 异常模块与包
  • CLIP,BLIP,SigLIP技术详解【二】
  • Flink + Hologres构建实时数仓
  • 机器学习:基于OpenCV和Python的智能图像处理 实战
  • 【05】昊一源科技——昊一源科技 嵌入式笔试, 校招,题目记录及解析
  • 提示词注入攻防全解析——从攻击原理到防御浅谈
  • gophis钓鱼
  • 深入解析 resolv.conf 文件:DNS 配置的核心
  • 区间修改 - 差分
  • 在Linux中使用docker-compose快速搭建Prometheus监控系统
  • foreach 块并行加速
  • 澳洲增高营养品排行榜
  • 小波卷积YYDS!小波变换+CNN创新结合
  • 无人机航拍数据集|第11期 无人机人员行为目标检测YOLO数据集1868张yolov11/yolov8/yolov5可训练
  • 【bug】diff-gaussian-rasterization Windows下编译 bug 解决
  • STM32 HAL库驱动0.96寸OLED屏幕
  • 【学习】DCMM认证从“跟风“到“生存法则“的进化
  • EI检索-学术会议 | 人工智能、虚拟现实、可视化
  • react中父子数据流动和事件互相调用(和vue做比较)
  • 小杰python高级(three day)——matplotlib库
  • 关于微信小程序的笔记
  • 告别“焊武帝”时代!30-65W零外围A+C快充协议正式上线
  • Cherryusb UAC例程对接STM32内置ADC和PWM播放音乐和录音(下)=>UAC+STM32 ADC+PWM实现录音和播放
  • TradingAgents-CN: 基于多智能体的中文金融交易决策框架