在上一篇文章中,实现了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