[转] rosparam和ROS参数服务

 

机器人工作时,我们有需要对机器人的参数(如传感器参数、算法的参数)进行设置。

有些参数(如机器人的轮廓、传感器的高度)在机器人启动时就设定好就行了;

有些参数则需要动态改变(特别是在调试的时候)。

ROS提供了参数服务器来满足这一需求。我们可以将参数设置在参数服务器,在需要用到参数的时候再从参数服务器中获取。


rosparam命令可对ROS参数服务器上的参数进行操作。通过rosparam -h命令,可以看到有下面的一些方法:

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 load [文件路径\文件名] 命令一次性将多个参数加载到参数服务器。

(yaml文件的格式和使用方法:https://www.ibm.com/developerworks/cn/xml/x-1103linrr/)

举个例子,一个名称为param.yaml的参数文件,内容为:

    #There are some params which will be loaded
    yaml_param_string1: abcd123
    yaml_param_string2: 567efg
     
    yaml_param_num1: 123.123
    yaml_param_num2: 1234567
     
    yaml_param_set:
      param_set_string1: zzzzz
      param_set_num1: 999
      param_set_string2: a6666
      param_set_num2: 2333
     
      param_subset:
        param_set_string1: qwer
        param_set_num1: 5432
        param_set_string2: a12s3
        param_set_num2: 1111

现在,我们要其中的参数加载到ROS的参数服务器中。


启动roscore,输入:

$ rosparam load param.yaml

然后,输入命令:

$ rosparam list

可以看到,参数已经被全部加载了:

/rosdistro
/roslaunch/uris/host_clp_virtual_machine__46453
/rosversion
/run_id
/yaml_param_num1
/yaml_param_num2
/yaml_param_set/param_set_num1
/yaml_param_set/param_set_num2
/yaml_param_set/param_set_string1
/yaml_param_set/param_set_string2
/yaml_param_set/param_subset/param_set_num1
/yaml_param_set/param_subset/param_set_num2
/yaml_param_set/param_subset/param_set_string1
/yaml_param_set/param_subset/param_set_string2
/yaml_param_string1
/yaml_param_string2

通过rosparam set [参数名] [参数值] 可以设置参数值;
通过rosparam get [参数名] 可以查看参数值;
大家可以多多尝试。

另外,还可以参考turtlebot的navigation启动move_base节点的过程,保存在yaml文件中的参数是通过rosparam标签被加载到参数服务器中的。

<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
    <rosparam file="$(find turtlebot_navigation)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find turtlebot_navigation)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />   
    <rosparam file="$(find turtlebot_navigation)/param/local_costmap_params.yaml" command="load" />   
    <rosparam file="$(find turtlebot_navigation)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find turtlebot_navigation)/param/dwa_local_planner_params.yaml" command="load" />
    <rosparam file="$(find turtlebot_navigation)/param/move_base_params.yaml" command="load" />
    <rosparam file="$(find turtlebot_navigation)/param/global_planner_params.yaml" command="load" />
    <rosparam file="$(find turtlebot_navigation)/param/navfn_global_planner_params.yaml" command="load" />
    <!-- external params file that could be loaded into the move_base namespace -->
    <rosparam file="$(arg custom_param_file)" command="load" />
    
    <!-- reset frame_id parameters using user input data -->
    <param name="global_costmap/global_frame" value="$(arg global_frame_id)"/>
    <param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
    <param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/>
    <param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
    <param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/>

    <remap from="cmd_vel" to="navigation_velocity_smoother/raw_cmd_vel"/>
    <remap from="odom" to="$(arg odom_topic)"/>
    <remap from="scan" to="$(arg laser_topic)"/>
  </node>


当然,在ROS的代码中,我们也可以进行一些参数的操作:

    #include <ros/ros.h>
     
    int main(int argc, char** argv)
    {
        ros::init(argc, argv, "param_demo");
        ros::NodeHandle n;
        ros::NodeHandle pn("~my_namespce");
     
        std::string s;
        int num;
        
        n.param<std::string>("string_param", s, "haha");
        pn.param<int>("int_param", num, 666);
        
        //输出被初始化后的变量值
        ROS_INFO("string_param_init: %s", s.c_str());
        ROS_INFO("int_param_init: %d", num);
     
        //设置参数的值
        n.setParam("string_param", "hehe");
        pn.setParam("int_param", 222);
     
     
        //设置循环的频率为1Hz
        ros::Rate loop_rate(1);    
     
        while(ros::ok())
        {    
            //获取参数的值
            n.getParam("string_param", s);
            pn.getParam("int_param", num);
            
            //输出参数
            ROS_INFO("string_param: %s", s.c_str());
            ROS_INFO("int_param: %d", num);
            
            ros::spinOnce();
            loop_rate.sleep();
        }
        
        return 0;
    }


编译后,先使用roscore启动ros,然后用rosrun运行节点。运行的结果为:

[ INFO] [1508962647.123025215]: string_param_init: haha
[ INFO] [1508962647.123388114]: int_param_init: 666
[ INFO] [1508962647.126034003]: string_param: hehe
[ INFO] [1508962647.126118085]: int_param: 222
[ INFO] [1508962648.127348007]: string_param: hehe
[ INFO] [1508962648.127499096]: int_param: 222
[ INFO] [1508962649.129554752]: string_param: hehe
[ INFO] [1508962649.130092222]: int_param: 222
[ INFO] [1508962650.128275652]: string_param: hehe
[ INFO] [1508962650.128455601]: int_param: 222
[ INFO] [1508962651.127771182]: string_param: hehe
[ INFO] [1508962651.128003505]: int_param: 222
[ INFO] [1508962652.128101292]: string_param: hehe
[ INFO] [1508962652.128249473]: int_param: 222
[ INFO] [1508962653.127405633]: string_param: hehe
[ INFO] [1508962653.127529541]: int_param: 222
[ INFO] [1508962654.126999255]: string_param: hehe
[ INFO] [1508962654.127161917]: int_param: 222
[ INFO] [1508962655.129154583]: string_param: hehe
[ INFO] [1508962655.129287685]: int_param: 222
……

此时,输入命令:

$ rosparam list

可以看到,参数已经存在参数服务器中了。结果如下:

/param_demo/my_namespce/int_param
/rosdistro
/roslaunch/uris/host_clp_virtual_machine__33415
/rosversion
/run_id
/string_param


代码解释:

定义NodeHandle对象n时用默认的全局命名空间,定义NodeHandle对象pn的时候使用了私有的命名空间:

    ros::init(argc, argv, "param_demo");
    ros::NodeHandle n;
    ros::NodeHandle pn("~my_namespce");

因此“string_param”是全局的参数,“int_param”是在命名空间my_namespace下的参数。


接下来有两行代码:

    n.param<std::string>("string_param", s, "haha");
    pn.param<int>("int_param", num, 666)

官方文档对ros::NodeHandle::param()函数的描述如下:

(参考自:http://docs.ros.org/kinetic/api/roscpp/html/classros_1_1NodeHandle.html#a05941572641a453fd416c6603b91d39f)


param()函数从参数服务器取参数值给变量。如果无法获取,则将默认值赋给变量。这个函数的功能和getParam()函数类似,而区别是param()函数还提供了一个默认值。


    //设置参数的值
    n.setParam("string_param", "hehe");
    pn.setParam("int_param", 222);

设置参数的值。如果注释这两行代码,rosparam list命令将看不到“string_param”和“int_param”,这是因为参数服务器没有设置这两个参数。


    n.getParam("string_param", s);
    pn.getParam("int_param", num);

getParam()函数可以从参数服务器获取参数值。如果成功,变量s和num的值将会被修改为参数值,函数返回true;如果不成功(譬如参数服务器没有设置这个参数),变量s和num将保持原值,函数会返回false。我在上面的代码中没有接收返回值和判断,大家可以动手试试。


到了这里,大家应该知道为什么输出的前两行结果是“haha”和“666”了吧?


关闭第一次运行的节点(不关闭roscore),然后第二次运行该节点。结果为:

    [ INFO] [1508962846.716579651]: string_param_init: hehe
    [ INFO] [1508962846.716882790]: int_param_init: 222
    [ INFO] [1508962846.719913219]: string_param: hehe
    [ INFO] [1508962846.720229965]: int_param: 222
    [ INFO] [1508962847.721341491]: string_param: hehe
    [ INFO] [1508962847.721696804]: int_param: 222
    [ INFO] [1508962848.724312549]: string_param: hehe
    [ INFO] [1508962848.724606197]: int_param: 222
    [ INFO] [1508962849.723765176]: string_param: hehe
    [ INFO] [1508962849.724541585]: int_param: 222
    [ INFO] [1508962850.721549217]: string_param: hehe
    [ INFO] [1508962850.722647030]: int_param: 222
    [ INFO] [1508962851.722353260]: string_param: hehe
    [ INFO] [1508962851.722608120]: int_param: 222
    [ INFO] [1508962852.725476354]: string_param: hehe
    [ INFO] [1508962852.726797059]: int_param: 222
    [ INFO] [1508962853.723994285]: string_param: hehe
    [ INFO] [1508962853.724691083]: int_param: 222
    ……

将第二次运行结果和第一次运行结果对比,string_param_init和int_param_init的值发生了变化。这是因为在第一次运行节点后,参数string_param和num_param已经存在于参数服务器中,所以第二次运行节点时,默认值“haha”和“666”将不被使用,因此输出结果为“hehe”和222。


另外,在节点运行的过程中,我们用rosparam set 命令修改参数的值,可以观察到输出值的变化。
————————————————
版权声明:本文为优快云博主「培培哥」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/u014695839/article/details/78348600

<think>好的,我需要帮助用户了解ROS参数服务器的使用方法相关配置。首先,我应该回顾用户提供的引用资料,从中提取关键信息。 用户提供的引用1提到参数服务器用于动态设置获取参数,启动ROS主节点使用roscore,设置参数rosparam set命令。引用3说明参数服务器是全局的,支持动态调整,方便节点间共享参数。引用24提到了C++实操,包括增删改查参数的方法。 接下来,我需要组织这些信息,按照用户要求的格式,分步骤说明参数服务器的用法。需要包括启动主节点、设置参数、获取参数、删除参数,并给出示例代码。同时,要确保所有数学表达式用$...$,独立公式用$$...$$,但这里可能涉及代码较多,数学公式可能较少。 然后,生成相关问题,参考示例中的结构,例如询问参数服务器的工作原理、如何动态调整参数、在C++中的实现等。 需要检查LaTeX语法是否正确,使用中文回答,结构清晰。最后,确认引用的标注是否正确,每个引用来源的末尾加上对应的标识符,如[^1]、[^2]等。</think>### ROS参数服务器使用说明 #### 1. 参数服务器概述 ROS参数服务器是一个集中存储管理全局配置参数的组件,支持动态增删改查操作,适用于节点间共享配置(如传感器阈值、控制参数等)[^3]。 #### 2. 基本配置步骤 **步骤1:启动ROS主节点** ```bash $ roscore ``` **步骤2:设置参数** 通过命令行设置参数: ```bash $ rosparam set /my_param_name 42 # 设置整型参数[^1] $ rosparam set /robot_speed 0.5 # 设置浮点型参数 ``` **步骤3:获取参数** ```bash $ rosparam get /my_param_name # 输出:42[^1] ``` **步骤4:删除参数** ```bash $ rosparam delete /my_param_name # 删除指定参数[^4] ``` #### 3. C++节点操作示例 **新增/修改参数** ```cpp #include <ros/ros.h> int main(int argc, char **argv) { ros::init(argc, argv, "param_demo"); ros::NodeHandle nh; // 设置参数 nh.setParam("/control_gain", 1.2); // 浮点型参数 } ``` **获取参数** ```cpp double gain; if (nh.getParam("/control_gain", gain)) { ROS_INFO("Gain value: %.2f", gain); // 输出:1.20 } ``` **删除参数** ```cpp nh.deleteParam("/control_gain"); // 删除参数[^4] ``` #### 4. 动态调整参数示例 通过`ros::param::set`实现运行时动态修改: ```cpp ros::param::set("/sensor_threshold", 75); // 更新传感器阈值 ``` #### 5. YAML文件批量加载 将参数存储在YAML文件中并批量导入: ```bash $ rosparam load config.yaml # 加载文件中的所有参数 ``` 示例`config.yaml`内容: ```yaml camera_fps: 30 max_velocity: 2.0 ``` ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值