ROS 八、参数的使用


ROS 8: 参数的使用与编程

在ROS Master中有一个参数服务器,它是一个全局字典,用来保存各个节点的配置参数的,这些参数是各个节点都可以全局访问的

可以简单理解为,这是一个用来存放全局变量的空间

有关参数的使用,有如下命令行工具

一、参数的命令行工具

我们在命令行会使用rosparam,用于从ROS参数服务器获取、设置和删除参数。

rosparam is a command-line tool for getting, setting, and deleting parameters from the ROS Parameter Server.

Commands:
        rosparam set    set parameter
        rosparam get    get parameter
        rosparam load   load parameters from file
        rosparam dump   dump parameters to file
        rosparam delete delete parameter
        rosparam list   list parameter names

如果参数比较多的时候,我们会用*.yaml文件来存参数。

以下是rosparam在命令行的工具使用介绍

  • 列出参数rosparam list

    • 如果此时你运行turtlesim,你可以使用rosparam list看到参数名:
    /rosversion
    /run_id
    /turtlesim/background_b
    /turtlesim/background_g
    /turtlesim/background_r
    • 如果你设置了命名空间,还需要在后面加上命名空间的名字,如:rosparam list /namespace

      这里的命名空间可以类比为c++中的using namespace xxx中的xxx

      具体内容放在第三Part介绍

  • 显示某个参数值rosparam get <param_key>

  • 设置某个参数值rosparam set <param_key> <param_value>

    比如要修改turtlesim的background对应的RGB值,输入:

    rosparam set /turtlesim/background_g 255

    然后turtlesim需要收到一次/clear请求,才会重新读取背景值

    rosservice call /clear "{}"

    如果此时你正在运行上述代码,你就可以看到,海龟仿真器的背景颜色已经修改了。

    -v:显示详细输出。

    -t <text_file>, --textfile <text_file> :将参数设置为文本文件的内容。

    -b <binary_file>, --binfile <binary_file> :将参数设置为二进制文件的内容。参数服务器将值存储为XML-RPC二进制类型(基64编码)。

  • 保存参数到文件rosparam dump <file_name>

  • 从文件读取参数rosparam load <file_name>

    此时,在工作空间使用rosparam dump param.yaml指令,ros就会把当前的参数配置保存到该yaml文件中。

    使用rosparam load param.yaml就可以加载以前保存好的参数

    yaml文件会存储类似于以下的内容,

    rosdistro: 'melodic
    
      '
    roslaunch:
      uris:
        xxx: http://xxx:44429/
    rosversion: '1.14.10
    
      '
    run_id: 80cf1b56-0e4b-11ed-9d12-000c29d50405
    turtlesim:
      background_b: 255
      background_g: 255
      background_r: 255
  • 删除参数rosparam delete <param_key>

    删除当前系统载入的参数。

二、参数在编程上的使用

c++代码实现

1、设置参数

ros::NodeHandle::setParam()

ros::param::set()

在c++中,在代码中获取参数时,除了上述代码使用的ros::param::get方法之外,还可以使用句柄来获取参数:ros::NodeHandle::getParam() 。需要的参数是一样的:

//ros::NodeHandle::setParam()
ros::NodeHandle nh;
nh.setParam("/global_param", 5);
nh.setParam("relative_param", "my_string");
nh.setParam("bool_param", false);

都是需要输入参数名和存放的变量名

//ros::param::set()
ros::param::set("/global_param", 5);
ros::param::set("relative_param", "my_string");
ros::param::set("bool_param", false);

需要注意的是,如果使用NodeHandle,还需要注意他对应的命名空间。

对于命名空间来说,节点名前面直接加个/号,代表着这个节点是放在全局的,比如/turltesim。如果需要使用对应命名空间里的节点,需要写上空间名,如:/my/turtlesim

2、检查参数是否存在

  • ros::NodeHandle::hasParam()
ros::NodeHandle nh;
if (nh.hasParam("my_param")){...}
  • ros::param::has()
if (ros::param::has("my_param")){...}

3、删除参数

  • ros::NodeHandle::deleteParam()
ros::NodeHandle nh;
nh.deleteParam("my_param");
  • ros::param::del()
ros::param::del("my_param");

4、访问私有参数

根据使用的是“句柄”接口还是“裸”接口,访问私有参数的方式是不一样的。在句柄接口中,您必须创建一个新的ros::NodeHandle以私有命名空间作为其命名空间:

ros::NodeHandle nh("~");
std::string param;
nh.getParam("private_name", param);

在裸界面中,可以使用描述私有参数的相同符号来访问它们,例如:

std::string param;
ros::param::get("~private_name", param);

5、搜索参数键

  • ros::NodeHandle::searchParam()
std::string key;
if (nh.searchParam("bar", key))
{
  std::string val;
  nh.getParam(key, val);
}
  • ros::param::search()
std::string key;
if (ros::param::search("bar", key))
{
  std::string val;
  ros::param::get(key, val);
}

6、demo

模仿本案例开头的修改turtlesim背景案例,我们所需要的头文件有:

#include <ros/ros.h>
#include <string>
#include <std_srvs/Empty.h>

主函数:

int main(int argc,char **argv){
    // 初始化ros
    ros::init(argc,argv,"param_code");
    ros::NodeHandle param_node;
    int red,green,blue;

    //参数获取,类比命令行rosparam的get
    ros::param::get("/turtlesim/background_r",red);
    ros::param::get("/turtlesim/background_g",green);
    ros::param::get("/turtlesim/background_b",blue);

    ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);

    //参数设置,类比命令行rosparam的set
    ros::param::set("/turtlesim/background_r",255);
    ros::param::set("/turtlesim/background_g",255);
    ros::param::set("/turtlesim/background_b",255);

    ROS_INFO("Set Backgroud Color[255, 255, 255]");

    //参数获取,类比命令行rosparam的get
    ros::param::get("/turtlesim/background_r",red);
    ros::param::get("/turtlesim/background_g",green);
    ros::param::get("/turtlesim/background_b",blue);

    ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);

    // 参考我们上面讨论的参数使用方法,我们知道turtlesim需要接受/clear请求才会更新turtlesim的参数。
    //调用/clear服务,用来刷新背景颜色
    ros::service::waitForService("/clear");
    ros::ServiceClient clear_background = param_node.serviceClient<std_srvs::Empty>("/clear");
    std_srvs::Empty srv;
    clear_background.call(srv);

    sleep(1);

    return 0;
}

程序编译:

打开功能包的CMakeLists,使用如下语句即可使用catkin_make

add_executable(learn_param src/learn_param.cpp)
target_link_libraries(learn_param ${catkin_LIBRARIES})

python代码实现

1、获取参数

rospy.get_param(参数名称)

如果使用get_param()来获取名称空间,则会返回一个字典,其中的键等于该名称空间中的参数值。

global_name = rospy.get_param("/global_name")
relative_name = rospy.get_param("relative_name")
private_param = rospy.get_param('~private_name')
default_param = rospy.get_param('default_param', 'default_value')

# fetch a group (dictionary) of parameters
gains = rospy.get_param('gains')
p, i, d = gains['p'], gains['i'], gains['d']

2、设置参数

rospy.set_param(参数名称,参数值)

# 使用rospy和原始python对象
rospy.set_param('a_string', 'baz')
rospy.set_param('~private_int', 2)
rospy.set_param('list_of_floats', [1., 2., 3., 4.])
rospy.set_param('bool_True', True)
rospy.set_param('gains', {'p': 1, 'i': 2, 'd': 3})

# 使用rosparam和yaml字符串
rosparam.set_param('a_string', 'baz')
rosparam.set_param('~private_int', '2')
rosparam.set_param('list_of_floats', "[1., 2., 3., 4.]")
rosparam.set_param('bool_True', "true")
rosparam.set_param('gains', "{'p': 1, 'i': 2, 'd': 3}")

rospy.get_param('gains/p') #should return 1

3、参数存在

rospy.has_param(param_name)

如果存在该参数,返回True,否则False。

if rospy.has_param('to_delete'):
	rospy.delete_param('to_delete')

4、删除参数

rospy.delete_param(参数名称)

其实就是从参数服务器删除参数

try:
	rospy.delete_param('to_delete')
except KeyError:
	print("value not set")

5、搜索参数键

rospy.search_param(参数名称)

查找最接近的参数名,从私有名称空间开始,向上一直搜索到全局名称空间。

param_name = rospy.search_param('global_example')
v = rospy.get_param(param_name)

如果上面的代码出现在/foo/bar节点中, rospy.search_param会试着按照以下顺序找到参数

  1. /foo/bar/global _example
  2. /foo/global _example
  3. /global _example

6、获取参数名

rospy.get_param_names()

7、demo

以下demo和c++的功能完全一样。

# -*- coding: utf-8 -*-
import rospy
from std_srvs.srv import Empty
import sys

def param_set():
    rospy.init_node('param_py')
    # 读取背景颜色参数
    red   = rospy.get_param('/background_r')
    green = rospy.get_param('/background_g')
    blue  = rospy.get_param('/background_b')

    rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)

    # 设置背景颜色参数
    ros.set_param('/background_r',100)
    ros.set_param('/background_g',100)
    ros.set_param('/background_b',100)

    rospy.loginfo("Set Backgroud Color[100, 100, 100]")

    # 读取背景颜色参数
    red   = rospy.get_param('/background_r')
    green = rospy.get_param('/background_g')
    blue  = rospy.get_param('/background_b')

    rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)

    rospy.wait_for_service('/clear')
    try:
        clear_background = rospy.ServiceProxy('/clear', Empty)

        # 请求服务调用,输入请求数据
        response = clear_background()
        return response
    except rospy.ServiceException, e:
        print "Service call failed: %s"%e


if __name__ == '__main__':
    param_set()

文章作者: 拓佑豪
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 拓佑豪 !
评论
  目录