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

ros::NodeHandle nh_private(“~“)讲解

假设我们现在要写一个控制“智能风扇”的 ROS 程序。

这个风扇需要知道两个参数:最大转速风扇名字

第一步:写一份 YAML 配置文件(准备数据)

新建一个文件叫fan_config.yaml。里面的内容非常简单:

YAML

max_speed: 3000 fan_name: "LivingRoomFan"

这就是你风扇的“出厂说明书”。


第二步:写一个 Launch 文件(把数据塞进私有空间)

新建一个文件叫start_fan.launch。它的作用是启动程序,并把上面的说明书“塞”给程序。

<launch> <node name="my_fan_node" pkg="my_pkg" type="fan_program" output="screen"> <rosparam file="$(find my_pkg)/config/fan_config.yaml" command="load" /> </node> </launch>

这一步做完后,ROS 系统里就偷偷多出了两个专属变量:/my_fan_node/max_speed/my_fan_node/fan_name


第三步:写 C++ 代码(用 nh_private 把数据掏出来!)

这就是你一直想学的部分。新建你的main.cpp,照着下面这样写:

#include <ros/ros.h> #include <string> int main(int argc, char** argv) { // 1. 初始化 ROS 节点,名字叫 my_fan_node ros::init(argc, argv, "my_fan_node"); // ========================================== // ★ 核心 1:打造一把私密空间的钥匙 // ========================================== ros::NodeHandle nh_private("~"); // 2. 准备两个空变量,用来接住马上要取出来的数据 int speed_from_yaml = 0; std::string name_from_yaml = ""; // ========================================== // ★ 核心 2:用钥匙开箱取物! // 语法:nh_private.getParam("yaml里的变量名", 存入哪个C++变量); // ========================================== // 取出最大转速 if (nh_private.getParam("max_speed", speed_from_yaml)) { ROS_INFO("成功!我读到的最大转速是: %d", speed_from_yaml); } else { ROS_WARN("没找到 max_speed 这个参数!"); } // 取出风扇名字 if (nh_private.getParam("fan_name", name_from_yaml)) { ROS_INFO("成功!我读到的风扇名字是: %s", name_from_yaml.c_str()); } return 0; }

💡 核心原理解析:这段代码到底发生了什么?

  1. 为什么不写全名?注意看getParam("max_speed", ...)。你并没有写/my_fan_node/max_speed,你只写了"max_speed"这就是~的厉害之处!因为你是用nh_private调用的,ROS 会自动帮你把节点名字拼在前面(/my_fan_node/max_speed)准确无误地去你的私密空间里找到了3000这个数字。

如果在这个风扇项目中,你把ros::NodeHandle nh_private("~");换成了普通的ros::NodeHandle nh;,程序的运行结果会非常直接:

你会读不到任何数据!程序会直接打印出警告:“没找到 max_speed 这个参数!”

1. 为什么普通nh读不到?(找错房间了)

  • 参数的实际存放位置: 在你的start_fan.launch文件中,<rosparam ... />是写在<node ...>里面的。这意味着,ROS 把max_speed这个参数,锁进了my_fan_node的私有金库里。 它在 ROS 系统里的真实全名是:/my_fan_node/max_speed

  • 普通nh的寻找路径: 如果你在 C++ 里写了ros::NodeHandle nh;,然后调用nh.getParam("max_speed", speed_from_yaml);。 普通nh代表的是“公共大厅”。它会去 ROS 系统的最顶层全局目录下寻找这个参数。 它搜索的路径是:/max_speed

结果显而易见:普通nh在大厅里找/max_speed,但参数实际上藏在/my_fan_node/max_speed房间里。找错了地方,当然什么都读不到!


2. 如果非要用普通nh,该怎么改?

如果你就是想用普通的nh把参数读出来,你必须修改.launch文件,把参数“搬到公共大厅”里去。

你需要把<rosparam><node>内部,挪到它的外面

<launch> <rosparam file="$(find my_pkg)/config/fan_config.yaml" command="load" /> <node name="my_fan_node" pkg="my_pkg" type="fan_program" output="screen"> </node> </launch>

当你这样写了之后,参数就会被存为/max_speed。此时,你的 C++ 代码里用普通的nh.getParam("max_speed", ...)就能成功读到3000了!


3. 既然普通nh也能搞定,为什么全世界都在用nh_private("~")

想象一下这个终极场景: 夏天到了,你买了两个风扇,一个放在客厅(LivingRoom),一个放在卧室(Bedroom)。客厅比较大,风扇最大转速需要配 3000;卧室比较小,风扇最大转速配 1500 就够了。

这两个风扇运行的都是你写的这同一个 C++ 程序

灾难现场(使用普通nh: 如果把参数放在全局(/max_speed),两个风扇的 C++ 程序都会去读同一个地方。结果就是,你要么让两个风扇都转 3000,要么都转 1500,它们之间无法区分!它们打架了!

完美解决(使用带~的私有nh: 如果你在 C++ 里乖乖使用了ros::NodeHandle nh_private("~");,在启动时,你只需要写一个这样的 launch 文件:

<launch> <node name="living_room_fan" pkg="my_pkg" type="fan_program"> <rosparam file="客厅的配置.yaml" command="load" /> </node> <node name="bedroom_fan" pkg="my_pkg" type="fan_program"> <rosparam file="卧室的配置.yaml" command="load" /> </node> </launch>

你看!完全相同的 C++ 代码:

  • 客厅风扇的nh_private自动去读了/living_room_fan/max_speed(拿到 3000)。

  • 卧室风扇的nh_private自动去读了/bedroom_fan/max_speed(拿到 1500)。

http://www.jsqmd.com/news/435565/

相关文章:

  • 想选冲孔铝方通不知哪家好?2026十家高口碑品牌实地评测与排名解析 - 速递信息
  • 京东商品列表接口实战手记:十一年踩坑与避坑指南
  • 2026喷涂设备品牌排行榜,广东靠谱生产商霞晖自动化实力解读 - 工业设备
  • 2026年3月注塑件加工厂家权威推荐,技术实力与市场口碑深度解析 - 品牌鉴赏师
  • 2025 年 AI 毕业论文写作工具深度测评:9 款工具谁才是本科毕业生的 “救命稻草”?
  • ASE10N04A-ASEMI中低压MOS的极致适配之选
  • JPG转PNG用哪个网站更方便?几款在线工具简单对比
  • 2026年3月建筑木方厂家权威推荐,技术实力与市场口碑深度解析 - 品牌鉴赏师
  • 大型地产企业 BPM 平台年度运营实践:高并发、高集成场景下的流程优化
  • LangGraph之图模型
  • 微信立减金这样回收更便捷靠谱 - 抖抖收
  • 总结2026年广东小型喷油机生产企业哪家好,性价比之选在这里 - mypinpai
  • 论文提交前一周紧急降AI率攻略:时间紧也能搞定 - 我要发一区
  • 2026年海外仓代发服务性价比排名,海云汇优势凸显 - 工业品牌热点
  • 2026年全国海外仓货物代发服务费用多少,十大公司分析 - myqiye
  • 2026陕西泡沫雕塑、景观雕塑、玻璃钢雕塑厂家五大推荐:雕塑厂家哪家好?重点关注 - 深度智识库
  • Flutter 三方库 http_cache_hive_store 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、工业级的 HTTP 二级缓存与 Hive 数据库持久化联动引擎
  • Java 大视界 -- Java 大材料在智能教育在线考试系统中的考试结果分析与教学反馈优化中的应用
  • C# 使用FFmpeg 命令 水印以及水印位置 录音录像时设置分辨率-分辨率一般是宽高比是 4:3 和16:9 少数是 5:4
  • 2026年怀孕APP推荐:基于多维度长期测试评价,针对个性化需求与数据安全痛点 - 品牌推荐
  • GEO服务商优选指南:抓词GEO领衔,垂直领域标杆各展所长
  • Go - infinite loop
  • 竞赛和实习经历,秋招里哪个更有含金量?
  • 老板看利润、施工看顺手:这份“工程项目管理软件排名”让上下级都满意
  • go的内存逃逸
  • 2026年怀孕APP推荐:基于多场景实测评价,针对个性化需求与数据安全痛点精准指南 - 品牌推荐
  • 经典蓝牙与低功耗蓝牙 (BLE) 核心技术对比
  • 从本体论、认识论和方法论三个维度对比贾子思想、系统论和复杂科学的异同
  • FFmpeg 命令 水印以及水印位置 FFmpeg 命令录音录像时分辨率 FFmpeg 查看分辨率以及指定分辨率
  • MBR 分区重定义在线扩容根目录(/)实战步骤