【ROS】—— ROS通信机制——参数服务器(四)

news2024/11/14 15:37:45

文章目录

  • 前言
  • 1. 参数服务器理论模型
  • 2. 参数操作(C++)
    • 2.1 增加参数
    • 2.2 参数修改
    • 2.3 参数的获取
      • 2.3.1 ros::NodeHandle
      • 2.3.2 ros::param
    • 2.4 参数的删除
  • 3. 参数操作(python)
    • 3.1 增加参数与修改参数
    • 3.2 获取参数
    • 3.3 删除参数

前言

📢本系列将依托赵虚左老师的ROS课程,写下自己的一些心得与笔记。
📢课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ
📢讲义链接:http://www.autolabor.com.cn/book/ROSTutorials/index.html
📢 文章可能存在疏漏的地方,恳请大家指出。

参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。

概念
以共享的方式实现不同节点之间数据交互的通信模式。

作用
存储一些多节点共享的数据,类似于全局变量。

1. 参数服务器理论模型

参数服务器实现是最为简单的,该模型如下图所示,该模型中涉及到三个角色:

  • ROS Master (管理者)
  • Talker (参数设置者)
  • Listener (参数调用者)

ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。


在这里插入图片描述

整个流程由以下步骤实现:
1.Talker 设置参数
Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。

2.Listener 获取参数
Listener 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。

3.ROS Master 向 Listener 发送参数值
ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Listener。

参数可使用数据类型:

  • 32-bit integers
  • booleans
  • strings
  • doubles
  • iso8601 dates
  • lists
  • base64-encoded binary data
  • 字典

2. 参数操作(C++)

在 C++ 中实现参数服务器数据的增删改查,可以通过两套 API 实现:

  • ros::NodeHandle
  • ros::param

2.1 增加参数

#include "ros/ros.h"
/* 
      实现参数的新增与修改
      需求:首先设置机器人的共享参数、类型、半径(0.15m)
      实现:
                ros::NodeHandle
                        setParam()
                ros::param
                        set()
 */

int main(int argc, char  *argv[])
{
    //初始化ros节点
    ros::init(argc,argv,"set_param");
    //创建ROS节点句柄
    ros::NodeHandle nh;
    //参数增
    //方案1:nh
    nh.setParam("type","silun");
    nh.setParam("radius",0.15);
    //方案2:ros::param
    ros::param::set("type_param","silun");
    ros::param::set("radius_param",0.15);
    //参数改

    return 0;
}

配置完后,运行如下
在这里插入图片描述
使用rosparam list可以查看参数是否已经设置进入参数服务器

rosparam list

在这里插入图片描述
使用rosparam get 参数名可以查看所设置的参数值。
在这里插入图片描述

2.2 参数修改

#include "ros/ros.h"
/* 
      实现参数的新增与修改
      需求:首先设置机器人的共享参数、类型、半径(0.15m)
      实现:
                ros::NodeHandle
                        setParam()
                ros::param
                        set()
 */

int main(int argc, char  *argv[])
{
    //初始化ros节点
    ros::init(argc,argv,"set_param");
    //创建ROS节点句柄
    ros::NodeHandle nh;
    //参数增
    //方案1:nh
    nh.setParam("type","silun");
    nh.setParam("radius",0.15);
    //方案2:ros::param
    ros::param::set("type_param","silun");
    ros::param::set("radius_param",0.15);
    //参数改
     //方案1:nh
     nh.setParam("radius",0.20);
    //方案2:ros::param
     ros::param::set("radius_param",0.25);
    return 0;
}

重新rosrun后,再查看参数:
在这里插入图片描述
参数的修改其实是一个参数覆盖的过程。

2.3 参数的获取

2.3.1 ros::NodeHandle

param(键,默认值)
存在,返回对应结果,否则返回默认值
在这里插入图片描述 getParam(键,存储结果的变量)
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
在这里插入图片描述
getParamCached(键,存储结果的变量)–提高变量获取效率
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
会判断之前是否已经查询过参数,若查询过,直接从本地返回。是底层性能上的提升。一般情况下看不出来
在这里插入图片描述

getParamNames(std::vector<std::string>)
获取所有的键,并存储在参数 vector 中
在这里插入图片描述
hasParam(键)
是否包含某个键,存在返回 true,否则返回 false
在这里插入图片描述
searchParam(参数1,参数2)
搜索键,参数1是被搜索的键,参数2存储搜索结果的变量
在这里插入图片描述

2.3.2 ros::param

在这里插入图片描述 ros::param基本与nodehandle方式一致。
在这里插入图片描述

#include "ros/ros.h"
/* 
      实现参数的查询
      实现:
            ros::NodeHandle

            param(键,默认值) 
                存在,返回对应结果,否则返回默认值

            getParam(键,存储结果的变量)
                存在,返回 true,且将值赋值给参数2
                若果键不存在,那么返回值为 false,且不为参数2赋值

            getParamCached键,存储结果的变量)--提高变量获取效率
                存在,返回 true,且将值赋值给参数2
                若果键不存在,那么返回值为 false,且不为参数2赋值

            getParamNames(std::vector<std::string>)
                获取所有的键,并存储在参数 vector 中 

            hasParam(键)
                是否包含某个键,存在返回 true,否则返回 false

            searchParam(参数1,参数2)
                搜索键,参数1是被搜索的键,参数2存储搜索结果的变量

    ros::param ----- 与 NodeHandle 类似
 */
int main(int argc, char  *argv[])
{
    setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"get_param");
    //创建ROS节点句柄
    ros::NodeHandle nh;

    //param(键,默认值) 
    double radius = nh.param("radius",0.5);
    ROS_INFO("查询结果为: radius=%lf",radius);

    // getParam(键,存储结果的变量)
    double radius2 = 0.0;
    bool result1 = nh.getParam("radius",radius2);
    if(result1)
    {
        ROS_INFO("查询变量为:%0.2f",radius2);
    }
    else
    {
        ROS_INFO("结果不存在");
    }

    //getParamCached键,存储结果的变量)--提高变量获取效率
    double radius3= 0.0;
    bool result2 = nh.getParamCached("radius1",radius3);
        if(result2)
    {
        ROS_INFO("查询变量为:%0.3f",radius3);
    }
    else
    {
        ROS_INFO("结果不存在");
    }

    // getParamNames(std::vector<std::string>)  
    std::vector<std::string> names;
    nh.getParamNames(names);
    for(auto &&name  :  names)
    {
        ROS_INFO("遍历的元素:%s",name.c_str());
    }

    //hasParam(键)
    bool flag1 = nh.hasParam("radius");
    bool flag2 = nh.hasParam("");
    ROS_INFO("查询的元素是否存在:%d",flag1);
    ROS_INFO("查询的元素是否存在:%d",flag2);

    //searchParam(参数1,参数2)
    std::string  key;
    nh.searchParam("raduis",key);
    ROS_INFO("搜寻到的结果为:%s",key.c_str());
    nh.searchParam("radius",key);
    ROS_INFO("搜寻到的结果为:%s",key.c_str());


    //ros::param
    double radius_param = ros::param::param("radius",10);
    ROS_INFO("结果为:%lf",radius_param);

        return 0;
}

2.4 参数的删除

ros::NodeHandle
deleteParam(“键”)
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
在这里插入图片描述

ros::param
del(“键”)
根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
在这里插入图片描述

#include "ros/ros.h"/* 
    参数服务器操作之删除_C++实现:

    ros::NodeHandle
        deleteParam("键")
        根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false

    ros::param
        del("键")
        根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false


*/
int main(int argc, char *argv[])
{
        setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"get_param");
    //创建ROS节点句柄
    ros::NodeHandle nh; 

    // ros::NodeHandle
     bool flag1 = nh.deleteParam("radius");
    if(flag1){
        ROS_INFO("删除成功");
    }
    else{
        ROS_INFO("删除失败");
    }
    //ros::param
    bool flag2 =ros::param::del("radius");
     if(flag2){
        ROS_INFO("删除2成功");
    }
    else{
        ROS_INFO("删除2失败");
    }
    return 0;
}

3. 参数操作(python)

3.1 增加参数与修改参数

#! /usr/bin/env python
#-- coding:UTF-8 --

"""
    参数服务器操作之新增与修改(二者API一样)_Python实现:
"""

import rospy

if __name__ == "__main__":
    rospy.init_node("set_update_paramter_p")

    # 设置各种类型参数
    rospy.set_param("p_int",10)
    rospy.set_param("p_double",3.14)
    rospy.set_param("p_bool",True)
    rospy.set_param("p_string","hello python")
    rospy.set_param("p_list",["hello","haha","xixi"])
    rospy.set_param("p_dict",{"name":"hulu","age":8})

    # 修改
    rospy.set_param("p_int",100)

在这里插入图片描述

3.2 获取参数

#! /usr/bin/env python
#-- coding:UTF-8 --
"""
    参数服务器操作之查询_Python实现:    
        get_param(键,默认值)
            当键存在时,返回对应的值,如果不存在返回默认值
        get_param_cached
        get_param_names
        has_param
        search_param
"""

import rospy

if __name__ == "__main__":
    rospy.init_node("get_param_p")

    #获取参数
    int_value = rospy.get_param("p_int",10000)
    double_value = rospy.get_param("p_double")
    bool_value = rospy.get_param("p_bool")
    string_value = rospy.get_param("p_string")
    p_list = rospy.get_param("p_list")
    p_dict = rospy.get_param("p_dict")

    rospy.loginfo("获取的数据:%d,%.2f,%d,%s",
                int_value,
                double_value,
                bool_value,
                string_value)
    for ele in p_list:
        rospy.loginfo("ele = %s", ele)

    rospy.loginfo("name = %s, age = %d",p_dict["name"],p_dict["age"])

    # get_param_cached
    int_cached = rospy.get_param_cached("p_int")
    rospy.loginfo("缓存数据:%d",int_cached)

    # get_param_names
    names = rospy.get_param_names()
    for name in names:
        rospy.loginfo("name = %s",name)

    rospy.loginfo("-"*80)

    # has_param
    flag = rospy.has_param("p_int")
    rospy.loginfo("包含p_int吗?%d",flag)

    # search_param
    key = rospy.search_param("p_int")
    rospy.loginfo("搜索的键 = %s",key)

在这里插入图片描述

3.3 删除参数

#! /usr/bin/env python
#-- coding:UTF-8 --
"""
    参数服务器操作之删除_Python实现:
    rospy.delete_param("键")
    键存在时,可以删除成功,键不存在时,会抛出异常
"""
import rospy

if __name__ == "__main__":
    rospy.init_node("delete_param_p")

    try:
        rospy.delete_param("p_int")
    except Exception as e:
        rospy.loginfo("删除失败")

/p_int 被删除
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

九联UNT403G/UNT413G_国科GK6323芯片_5621ds无线wifi_免拆卡刷固件

九联UNT403G&#xff0f;UNT413G_国科GK6323芯片_5621ds无线wifi_免拆卡刷固件。 固件特点&#xff1a; 1、修改dns&#xff0c;三网通用&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、无开机广告&#xff0c;无系统更新&#xff0c;不在被强制升…

判断成绩-C语言实现

任务描述 本关任务&#xff1a;判定学生成绩。 相关知识 if-else 分支语句基本用法 C 语言提供了 if-else 分支语句用于实现程序的选择结构。 基本格式如下&#xff1a; if ( 表达式 ) 语句A else 语句B 基本流程图如下&#xff1a; 图1 if-else 分支语句流程图 从上面的…

单相全桥逆变原理及仿真实验

前言 一、单相全桥逆变器组成原理 1.全桥逆变电路拓扑结构 2.单相逆变器的SPWM调制方式 二、单相全桥逆变器仿真 1.SPWM调制波仿真 2.全桥逆变仿真 三、SPWM单片机程序实现 1.CubeMX配置 2.SPWM正弦表数据生成 3.Keil5代码 4.protues仿真观测波形 前言 通常把直流电变成…

力扣 # 1323. 6 和 9 组成的最大数字 JAVA实现

力扣 1323. 6 和 9 组成的最大数字 给你一个仅由数字 6 和 9 组成的正整数 num。 你最多只能翻转一位数字&#xff0c;将 6 变成 9&#xff0c;或者把 9 变成 6 。 请返回你可以得到的最大数字。 难度&#xff1a;简单 示例 1&#xff1a; 输入&#xff1a;num 9669 输出&a…

基于采样的规划算法之动态规划方法

经过前面对RRT的介绍,我们发现基于采样的规划算法与基于图搜索的规划算法都是通过对路径树进行拓展新节点,来找到起点到终点的路径解。RRT家族通过随机采样来生成这棵路径树,随机采样会面临采样低效的问题——大部分采样的新节点都无益于提升路径解的最优性。动态规划基于特…

JS对数组的操作详解

目录 shift 方法 unshift 方法 reverse方法 sort方法 reduce方法 concat方法 join方法 push方法 pop方法 slice方法 splice方法 forEach方法 map方法 filter方法 every方法 some方法 indexOf方法 find方法 includes方法 在这里总结一下JS的数组方法&#xf…

JDBC基本使用

文章目录一、JDBC技术1.1、JDBC概念1.2、JDBC作用1.3、JDBC工作原理1.4、JDBC工作流程二、使用JDBC访问数据库2.1、创建Maven项目2.2、添加数据库依赖2.2.1、mysql依赖2.2.2、oracle依赖2.3、编写代码2.3.1、加载驱动2.3.2、通过DriverManager获取connection连接2.3.3、执行SQL…

java中线程安全问题及解决方法、线程状态、线程间通信(线程等待唤醒机制)

线程安全 概述&#xff1a; 多线程访问了共享数据&#xff0c;此时会产生冲突&#xff08;如&#xff1a;在多个线程中执行售卖货物的业务&#xff0c;要求是某个货被某个线程售卖后&#xff0c;其他线程应该不再可以售卖此个货&#xff0c;但是默认被某个线程售卖后&#xf…

JVM 教程

jvm教程jvm概述前言JVM 定义JVM 的作用查看自己的 JVMJVM&#xff0c;JRE 和 JDK 联系小结JVM 整体架构目标JVM 整体架构类加载子系统运行时数据区执行引擎小结JVM 常用参数配置IntelliJ IDEA 添加运行参数JVM 参数&#xff1a;跟踪垃圾回收JVM 参数&#xff1a;跟踪类的加载与…

手把手代码实现五级流水线CPU——第二篇:分支预测流水线

系列文章目录 第三篇&#xff1a;流水线控制逻辑 第一篇&#xff1a;初级顺序流水线 文章目录系列文章目录一、流水线硬件结构二、流水线各阶段的实现实现原理一、流水线硬件结构 取指阶段 PC增加器&#xff1a;用来计算下一条指令的地址valP 译码阶段 一次译码操作读出俩个寄…

学习vue的准备工作

一、前提&#xff1a; 1、vscode安装&#xff1a; https://blog.csdn.net/m0_55400356/article/details/1260267332、node.js安装&#xff1a; 已安装 16.0 或更高版本的 Node.js&#xff1b; https://www.runoob.com/nodejs/nodejs-install-setup.html3、安装vue&#xff…

hadoop之ranger权限配置(二)

文章目录一、编译ranger&#xff08;node12&#xff09;二、安装前环境准备&#xff08;node12&#xff09;三、安装RangerAdmin&#xff08;node12&#xff09;(root)五、Ranger Hive-plugin&#xff08;node10&#xff09;六、Ranger Hdfs-plugin&#xff08;node10、11&…

ansible远程控制及其相关操作

1.控制主机和受控主机通过root用户通过免密验证方式远程控住受控主机实施对应&#xff08;普通命令&#xff0c;特权命令&#xff09;任务&#xff08;以下所有结果均见截图&#xff09; (1)控住主机--server通过主机名匹配对应连接的受控主机 [rootserver ~]#vim /etc/hosts …

一本通 1267:【例9.11】01背包问题(详细代码+严谨思路+清晰图片)

经典01背包问题 这里给你3种方法 目录 DFS 思路&#xff1a; 代码&#xff1a; DFS记忆化 思路&#xff1a; 代码&#xff1a; 动态规划 思路&#xff1a; 代码&#xff1a; DFS 时间复杂度 &#xff1a;O(2^n) 思路&#xff1a; DFS求出所有选法&#xff0c;再用…

Git Stash、Git Merge、Git Rebase、Git Revert

GIT 日常使用总结git stashgit mergegit rebase将多个commit合并成一个commitgit revert撤销修改撤销commit 但是不撤销add 的内容撤销addGIT Rebase 补充说明&#xff1a;git stash git stash&#xff1a;将修改后的代码存储到本地的一个栈结构&#xff0c;将工作区和暂存区恢…

37-Vue之ECharts高级-交互API

交互API前言全局ECharts对象echartsInstance对象前言 本篇来学习下ECharts中交互API的使用 全局ECharts对象 全局 echarts 对象是引入 echarts.js 文件之后就可以直接使用的 init &#xff1a;初始化ECharts实例对象&#xff0c;使用主题 registerTheme&#xff1a;注册主题…

Avatar和虚拟场景如何影响用户VR社交行为

对于VR社交来讲&#xff0c;虚拟场景&#xff08;社交环境&#xff09;、Avatar&#xff08;虚拟化身&#xff09;是两个重要的元素&#xff0c;一个代表了人们在VR中互动的空间&#xff0c;而另一个则代表他们在这个空间中所扮演的角色。现阶段&#xff0c;Avatar有多种形态&a…

已解决import tensorflow.contrib.layers as layers导包错误

已解决W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library ‘cudart64_110.dll’; dlerror: cudart64_110.dll not found I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not ha…

opencv-python常用函数解析及参数介绍(八)——轮廓与轮廓特征

轮廓与轮廓特征前言1.获取轮廓通过膨胀与腐蚀获得轮廓通过梯度获取轮廓通过边缘检测获取轮廓2.寻找轮廓参数及作用对比3.轮廓特征前言 在前面的文章中我们已经学会了使用膨胀与腐蚀、使用梯度、使用边缘检测的方式获得图像的轮廓&#xff0c;那么在获得轮廓后我们可以对图像进…

​赛分科技冲刺科创板上市:拟募资8亿元,复星、高瓴为股东​

近日&#xff0c;苏州赛分科技股份有限公司&#xff08;下称“赛分科技”&#xff09;在上海证券交易所递交招股书&#xff0c;准备在科创板上市。本次冲刺上市&#xff0c;赛分科技计划募资8亿元&#xff0c;将用于20万升/年生物医药分离纯化用辅料、研发中心建设项目&#xf…