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

文章目录

  • 前言
  • 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 可以获取参数。


【ROS】—— ROS通信机制——参数服务器(四)_第1张图片

整个流程由以下步骤实现:
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;
}

配置完后,运行如下
【ROS】—— ROS通信机制——参数服务器(四)_第2张图片
使用rosparam list可以查看参数是否已经设置进入参数服务器

rosparam list

【ROS】—— ROS通信机制——参数服务器(四)_第3张图片
使用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(键,默认值)
存在,返回对应结果,否则返回默认值
【ROS】—— ROS通信机制——参数服务器(四)_第4张图片 getParam(键,存储结果的变量)
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
在这里插入图片描述
getParamCached(键,存储结果的变量)–提高变量获取效率
存在,返回 true,且将值赋值给参数2
若果键不存在,那么返回值为 false,且不为参数2赋值
会判断之前是否已经查询过参数,若查询过,直接从本地返回。是底层性能上的提升。一般情况下看不出来
【ROS】—— ROS通信机制——参数服务器(四)_第5张图片

getParamNames(std::vector)
获取所有的键,并存储在参数 vector 中
【ROS】—— ROS通信机制——参数服务器(四)_第6张图片
hasParam(键)
是否包含某个键,存在返回 true,否则返回 false
在这里插入图片描述
searchParam(参数1,参数2)
搜索键,参数1是被搜索的键,参数2存储搜索结果的变量
在这里插入图片描述

2.3.2 ros::param

【ROS】—— ROS通信机制——参数服务器(四)_第7张图片 ros::param基本与nodehandle方式一致。
在这里插入图片描述

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

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

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

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

            getParamNames(std::vector)
                获取所有的键,并存储在参数 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::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)

【ROS】—— ROS通信机制——参数服务器(四)_第8张图片

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)

【ROS】—— ROS通信机制——参数服务器(四)_第9张图片

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 被删除
【ROS】—— ROS通信机制——参数服务器(四)_第10张图片

你可能感兴趣的:(ROS,服务器,机器人,运维)