【ROS学习】(七)ROS参数服务(1)

在任何机器人系统中,参数传递都是一个十分重要的功能,不论是传感器的设置,还是控制参数的调整,都需要留出方便的参数调试接口,有的参数只在启动程序启动时更改,有的参数却希望在运行时能够被动态修改,在ROS中,可以通过参数服务来实现上面的想法。

首先熟悉一下rosparam指令,用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

用上面几个指令可以方便地用命令行获得或更改参数。

下面通过一段简单的代码片段来熟悉一下如何向ROS程序传递参数

#include <ros/ros.h>

using namespace  std;

int main(int argc, char** argv)
{
    ros::init(argc, argv, "param_demo");
    ros::NodeHandle n;
    ros::NodeHandle pn("~my_namespace");

    string s;
    int num;

    n.param<string>("string_param", s, "default_string");
    pn.param<int>("int_param", num, 2333);

//    n.setParam("string_param","default_string"); 
//    pn.setParam("int_param",2333);   

    printf("\nstring_param:  %s\n", s.c_str());//输出初始化值
    printf("int_param:  %d\n\n", num);//输出初始化值

    ros::Rate loop_rate(0.5);

    while (ros::ok())
    {
        n.getParam("string_param",s);   
        printf("string_param:  %s\n", s.c_str());
        pn.getParam("int_param",num);
        printf("int_param:  %d\n\n", num);

        ros::spinOnce();
        loop_rate.sleep();
    }
}

我们来分析一下上面的代码片段,首先是参数的初始化

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

上面的代码表示名称为”string_param”,值为”default_string”的参数初始化化std::string 类型变量s,用名称为”int_param”,值为666的参数初始化std::int类型变量num。

//    n.setParam("string_param","default_string"); 
//    pn.setParam("int_param",2333);

这两句代码是设置参数的值,如果程序中注释掉这两句代码,会产生这样的后果:

每次新开启机器时,第一次运行这个节点,s和num的值为我们设置的默认值,但是如果我们用rosparam set指令修改对应参数的值时,参数的值会保存在参数服务器中,默认的初始化值就不在有效,也就是说重新启动这个节点,参数值一直都是修改后的值。

另外注释掉这两句代码,运行节点时用rosparam list是查看不到”string_param”和”int_param”两个参数的,并且对这两个参数用rosparam get是无效的,但rosparam set仍然有效,可能会带来一些不方便。

如果不注释这两句代码,则运行节点时用rosparam list可以在参数列表中看到”string_param”和”int_param”两个参数,同样可以使用get和set指令。但会带来一个问题,就是不管用rosparam set指令将参数设为何值,重新运行节点时参数都被初始化位以上两句代码中给定的值。

所以两种方法各有优缺点,分场合使用,或者可以使用更方便的launch文件来配置参数,下文将会提到。

    while (ros::ok())
    {
        n.getParam("string_param",s);   
        printf("string_param:  %s\n", s.c_str());
        pn.getParam("int_param",num);
        printf("int_param:  %d\n\n", num);

        ros::spinOnce();
        loop_rate.sleep();
    }

从参数服务器中读取参数值并显示,可以用rosparam set指令更改参数值。

现在留意一下这个定义

ros::NodeHandle pn("~my_namespace");

私有节点的定义可以参考http://wiki.ros.org/roscpp/Overview/NodeHandles

私有节点在参数传递中十分有用,通常我们定义的普通节点是全局的,这样在多个节点具有相同名称的参数时将会产生问题,设想这样一种情况,两个不同的传感器但是都具有一个名为”frequerncy”的参数,当我们用rosparam set将它设置为10hz时,可能会影响到我们并不想配置的那个传感器。所以,我们用私有节点来解决这个问题。私有节点实际上就是给节点指定了它所在的命名空间。例如,我们可以用rosparam list指令查看这个节点中的参数,可以看到

/param_demo/my_namespace/int_param
/string_param

如果私有节点定义为

ros::NodeHandle pn("~");

则会看到

/param_demo/int_param
/string_param

在上文提到的参数初始化方式中,如果在程序中给定默认值,则想要改变默认值将需要重新编译程序,如果要频繁更改参数的话这种方式就十分不方便,我们还可以在launch文件中对参数进行设置,避免这个麻烦,参考以下示例

<launch>
  <node name="param_demo" pkg="param_demo" type="param_demo" output="screen"> 
     <param name="string_param" value="from launch file" />
     <param name="int_param" value="999" />
  </node>
</launch>

不过在使用中要注意的是,似乎不能对全局节点和私有节点的参数同时初始化,所有尽量都使用私有节点来传递参数。
用launch文件初始化参数的优势是明显的,可以不查看源程序就可以知道节点用到的参数以及给定的初始值,并且找到一个合适的参数后,可以将它保存到launch文件而不必修改和重新编译源程序。

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值