【ROS学习】(八)ROS参数服务(2)

在上一篇文章中,实现了ROS程序中的参数初始化,并且用一个while循环检测参数服务器中的参数变化,实现了参数的动态修改。显然这样实现动态修改参数并不是最优,要浪费许多系统资源来检测参数修改,还有一个更优更方便,动态修改参数的方法,那就是使用dynamic_reconfigure参数服务。先贴代码

#include 

// Dynamic reconfigure includes.
#include 
// Auto-generated from cfg/ directory.
#include 

using namespace  std;

string s;
int num;

void paramConfigCallback(param_demo::dynamic_paramConfig &config, uint32_t level)
{
    s = config.s;
    num = config.num;
    printf("\nstring_param:  %s\n", s.c_str());
    printf("int_param:  %d\n\n", num);
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "dynamic_param_demo");
    ros::NodeHandle pnh("~");

    dynamic_reconfigure::Server dr_srv;
    dynamic_reconfigure::Server::CallbackType cb;

    cb = boost::bind(¶mConfigCallback, _1, _2);
    dr_srv.setCallback(cb);


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

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

    ros::spin();  
}

片段分析

dynamic_reconfigure::Server::dynamic_paramConfig> dr_srv;
dynamic_reconfigure::Server::dynamic_paramConfig>::CallbackType cb;

留意<>中的参数,param_demo是package名称,dynamic_paramConfig我们添加的参数配置服务,添加方式下文详述。

cb = boost::bind(¶mConfigCallback, _1, _2);
dr_srv.setCallback(cb);

paramConfigCallback是回调函数的名称,在回调函数中获取变更后的参数值。

#include 
#include 

要使用动态参数配置服务,要包含配置文件,第一个是ros中dynamic_reconfigure程序包中的头文件,第二个则是我们添加的配置文件,并通过编译后产生的,要编译产生这个文件,我们需要对package.xml和CMakeList.txt做一些改动。
package.xml

  <build_depend>dynamic_reconfigurebuild_depend>
  <run_depend>dynamic_reconfigurerun_depend>

加入dynamic_reconfigure程序包作为依赖项

CMakeList.txt

find_package(catkin REQUIRED COMPONENTS
 ...
 dynamic_reconfigure
)

generate_dynamic_reconfigure_options(
   cfg/dynamic_param.cfg
 )

catkin_package(
  ...
  CATKIN_DEPENDS ... dynamic_reconfigure
)

在上面几个地方加入对应的依赖项,其中cfg/dynamic_param.cfg是我们编写的配置文件,通过这个编译选项生成dynamic_paramConfig.h,dynamic_param.cfg位于cfg文件夹中,我们看下其中的内容

#! /usr/bin/env python

PACKAGE='param_demo'
import roslib
roslib.load_manifest(PACKAGE)

from dynamic_reconfigure.parameter_generator_catkin import *

gen = ParameterGenerator()
#       Name       Type      Level Description     Default Min   Max
gen.add("s",       str_t,    0,    "string_param.", "hello")
gen.add("num",     int_t,    0,    "int_param.",     1,    -100, 100)

exit(gen.generate(PACKAGE, "param_demo", "param_demo"))

其中,名字s和num和我们参数表中的变量名称对应,虽然只要在回调函数中赋值的时候进行正确的匹配,名字不同也可以,但是保持相同的名称有利于我们程序的编写和对参数的管理,如何编写cfg文件,可以参考下面的网页
http://wiki.ros.org/dynamic_reconfigure/Tutorials/HowToWriteYourFirstCfgFile

void paramConfigCallback(param_demo::dynamic_paramConfig &config, uint32_t level)
{
    s = config.s;
    num = config.num;
    ...
}

完成这些工作后,编译并运行这个节点,当然现在我们尽量选择用launch文件来启动并初始化参数,会在终端看到以下信息

string_param:  hello
int_param:  1

string_param:  initialize from launch file
int_param:  999

这个信息有什么意义呢,也就是说,我们运行节点的时候,参数配置的回调函数会在初始化时被调用一次,改变了参数的值,这些初始化值可能与launch文件里给定的默认值不同,因此,我们要注意的是,将下面这个代码段

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

放在初始化参数服务回调函数之后,这两句代码虽然对参数进行了初始化,但是如果从launch文件启动的话,其默认值由launcn文件中的参数值给定,这样,保证了我们运行节点初始化的参数值是确定的,这个对于一些对程序影响较大的参数的初始化很有意义。

现在,还剩下的问题是如何去改变我们希望动态配置的参数呢,有两种选择
1.使用命令行
具体参考下面网页
http://wiki.ros.org/dynamic_reconfigure
2.使用rqt_reconfigure
参考页面
http://wiki.ros.org/rqt_reconfigure
我们在终端输入命令

rosrun rqt_reconfigure rqt_reconfigure

可以看到一个参数更改页面,我们也可以将这个命令放到launch文件中和节点一起启动,在调试的时候十分方便。

完整工程代码查看
https://github.com/wenglihong/wlh_ros_demo/tree/master/param_demo

你可能感兴趣的:(ROS学习)