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

【ROS1】09-ROS通信机制——参数服务器

目录

一、参数服务器概念

二、参数操作

2.1 C++实现

2.1.1 新增参数

2.1.2 修改参数

2.1.3 查询参数

2.1.4 删除参数

2.2 python实现

2.2.1 新增参数

2.2.2 修改参数

2.2.3 查询参数

2.2.4 删除参数


一、参数服务器概念

假设正在开发一个复杂的机器人应用,里面有很多需要配置的数值,比如:

  • 机器人的物理尺寸(轮子直径、轮距)

  • PID 控制器的增益参数(Kp, Ki, Kd)

  • 传感器的配置(相机分辨率、激光雷达扫描频率)

  • 导航算法的参数(避障距离、目标容忍度)

你当然可以把这些数值硬编码(hard-code)在你的 C++ 或 Python 代码里。但这样做有几个巨大的缺点:

  • 修改困难:每次想调整一个参数,都必须重新修改代码、重新编译、重新部署。

  • 复用性差:同一个算法用在不同机器人上,参数不同,就需要维护多个版本的代码。

  • 管理混乱:参数散落在各个节点的代码中,难以集中查看和管理。

参数服务器就是为了解决这些问题而生的。它是一个全局的、集中式的、运行在 ROS Master 内部的字典(dictionary),能够存储一些多节点共享的数据,类似于全局变量。

这个“字典”可以存储各种基本数据类型的键值对(Key-Value pairs),任何 ROS 节点都可以在运行时存入 (set)查询 (get) 和 删除 (delete) 这些参数。

核心特点:

  • 集中存储: 所有参数都存储在一个地方(ROS Master),方便管理和调试。

  • 全局可访问: 任何连接到同一个 ROS Master 的节点都可以访问这些参数。

  • 动态配置: 可以在节点运行时动态地修改参数,而无需重启节点(需要节点代码支持动态重配置)。

  • 与代码解耦: 将配置参数从业务逻辑代码中分离出来,提高了代码的通用性和可维护性。

  • 支持多种数据类型: 支持字符串、整数、浮点数、布尔值、列表(数组)和字典(结构体)。

注意:参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据。

二、参数操作

2.1 C++实现

2.1.1 新增参数

进入到工作空间的src目录下,输入如下指令来创建一个名为“plumbing_param_server”的功能包

在功能包的src目录下新建一个cpp文件,这里命名为“demo01_param_set.cpp”

在“demo01_param_set.cpp”中添加如下代码来实现参数的新增

#include "ros/ros.h"/*
需求:实现参数的新增
实现:ros::NodeHandle.setParam()ros::param.set()
*/int main(int argc, char *argv[])
{// 初始化ROS节点ros::init(argc, argv, "set_param_c");// 创建ROS节点句柄ros::NodeHandle nh;// 参数增加// 方式1nh.setParam("type", "type1");nh.setParam("radius", 0.15);// // 方式2// ros::param::set("type", "type1");// ros::param::set("radius", 0.15);return 0;
}

打开功能包下的“CMakeLists.txt”,添加如下部分

Ctrl+Shift+B编译一下,然后开启3个终端窗口分别用于启动ROS核心、启动ROS节点、查看参数

roscore  // 启动ROS核心source ./devel/setup.bash
rosrun plumbing_param_server demo01_param_set  //启动ROS节点rosparam list  //列出参数

如果想查询参数的值,可以使用如下命令

rosparam get 参数名

2.1.2 修改参数

如果再次设置相同参数名,就会覆盖之前参数名对应的参数值

2.1.3 查询参数

在功能包的src目录中新创建一个cpp文件,这里命名为“demo02_param_get.cpp” 

在“demo02_param_get.cpp” 添加如下代码,用于展示如何执行参数的相关查询操作

#include "ros/ros.h"/*
需求:实现参数的查询
实现:ros::NodeHandle.param(键,默认值)  存在这个键方法返回存储的值,否则返回默认值.getParam(键,变量) 存在这个键方法返回true并将存储的值赋值给变量,否则返回false,且不为变量赋值.getparamCached(键,变量)  和.getParam基本一样.getParamNames(td::vector<std::string>)  获取所有的键并存储在vector中.hasParam(键) 判断是否存在某个键,存在返回true,否则返回false.searchParam(键,变量)   能够搜索到就将“/”+键名赋值给变量,否则将空字符串赋给变量ros::param
*/int main(int argc, char *argv[])
{setlocale(LC_ALL,"");// 初始化ROS节点ros::init(argc, argv, "get_param_c");// 创建ROS节点句柄ros::NodeHandle nh;// ros::NodeHandle// 1. paramdouble radius = nh.param("radius", 0.5);  //查询参数名为“radius”对应的值,如果“radius”不存在返回0.5ROS_INFO("radius = %.2f", radius);// 2. getParamdouble radius2 = 0.0;bool result = nh.getParam("radius", radius2);if (result){ROS_INFO("radius = %.2f", radius2);}// 3.getparamCached// 4.getParamNamesstd::vector<std::string> names;nh.getParamNames(names);for (auto &&name : names){ROS_INFO("遍历的元素:%s", name.c_str());}// 5.hasParambool flag = nh.hasParam("radius");// 6.searchParamstd::string key;nh.searchParam("radius", key);ROS_INFO("搜索结果:%s", key.c_str());return 0;
}

打开功能包中的“CMakeLists.txt”,添加如下部分

编译一下,该节点执行效果如下:

2.1.4 删除参数

 删除参数主要通过如下两种方式实现

#include "ros/ros.h"/*
删除参数:实现:ros::NodeHandle.delParam()ros::param.del()*/int main(int argc, char *argv[])
{setlocale(LC_ALL,"");ros::init(argc, argv, "param_del_c");ros::NodeHandle nh;bool flag = nh.deleteParam("radius");if (flag){ROS_INFO("删除成功!");}else{ROS_INFO("删除失败!");}// ros::param::del("radius");return 0;
}

运行效果如下,可以看到成功删除了“radius”参数

2.2 python实现

2.2.1 新增参数

在功能包中添加一个“scripts”目录 

在“scripts”目录添加一个python文件,用于新增参数

#! /usr/bin/env python
# -*- coding: utf-8 -*-import rospyif __name__ == "__main__":rospy.init_node("param_set_py")rospy.set_param("name", "czc")rospy.set_param("age", 18)

在“CMakeLists.txt”中添加如下部分

为python文件添加可执行权限

chmod +x *.py

可以看到成功添加了两个参数

2.2.2 修改参数

只需重新设置一下相同键名的参数,那么参数值就会被重新覆盖 

2.2.3 查询参数

参数查询可通过如下方法实现

1. get_param

2. get_param_cached

3. get_param names

4. has_param

5. search param

示例:

import rospyif __name__ == "__main__":rospy.init_node('param_example_node')# 1. get_param - 获取参数值,支持默认值name1 = rospy.get_param('name', 'default_name')print(f"Name1: {name1}")# 2. get_param_cached - 缓存参数值,减少RPC调用name2 = rospy.get_param_cached('name', 'default_name')print(f"Name2: {name2}")# 3. get_param_names - 获取所有参数名称all_params = rospy.get_param_names()for param in all_params:print(f"param: - {param}")# 4. has_param - 检查参数是否存在has_name = rospy.has_param('name')print(f"Has Param: {has_name}")# 5. search_param key = rospy.search_param('name')rospy.loginfo("key = %s", key)rospy.spin()

执行效果如下:

2.2.4 删除参数

rospy.delete_param("Key")
http://www.dtcms.com/a/295253.html

相关文章:

  • JavaSE:学习输入输出编写简单的程序
  • 从java到vue3:第二天
  • 字符串和对象的深拷贝和浅拷贝
  • 教务管理系统学员管理系统模块设计
  • Ubuntu-安装Epics教程
  • 从零构建 Node20+pnpm+pm2 环境镜像:基于 Dockerfile 的两种方案及持久化配置指南
  • NPM/Yarn完全指南:前端开发的“基石“与“加速器“
  • 用LangChain重构客服系统:腾讯云向量数据库+GPT-4o实战
  • AI风险治理“实战”落地:CISO如何将GenAI纳入GRC管控体系
  • 前端面试专栏-前沿技术:30.跨端开发技术(React Native、Flutter)
  • 从零构建:Jenkins与Kubernetes集成的完整指南
  • 借助 VR 消防技术开展应急演练,检验完善应急预案​
  • 血液样本的分类与应用
  • 论文阅读--《Besting the Black-Box: Barrier Zones for Adversarial Example Defense》
  • Elasticsearch 高级查询语法 Query DSL 实战指南
  • 2025年“创新杯”(原钉钉杯) A题 建模思路
  • Java 实现 C/S 架构详解:从基础到实战,彻底掌握客户端/服务端编程
  • Socket编程入门:从IP到端口全解析
  • OSPF路由协议单区域
  • MSOP/DIFOP端口 vs. IP地址的关系以及每个IP下面有什么自己的东西
  • 征服 Linux 网络:核心服务与实战解析
  • RWA与DeFi(去中心化金融)的关系是什么?RWA在DeFi中扮演什么角色?
  • 香草社游戏系列原声大碟OST合集全无损 FLAC格式 30GB
  • 详细介绍AI在金融、医疗、教育、制造四大领域的落地案例,每个案例均包含实际应用场景、技术实现方案、可视化图表和核心代码示例
  • 【每天一个知识点】生成对抗聚类(Generative Adversarial Clustering, GAC)
  • 【Unity开发】数据存储——XML
  • C++11+ 原子操作 `std::atomic`,现代并发编程的核心
  • Delegate、Action 与 Func 委托的全面解析
  • GitHub Actions打包容器,推送 AWS ECR 并使 EKS 自动拉取以完成发版部署
  • 【Java基础06】ArrayList