文章目录

前言

  之前的学习中,曾了解过ROS参数服务器的通信机制,如果Listenner不主动查询参数值,就无法获取Talker是否已经向Master更新了参数值。
  很多情况下,我们需要动态的更新参数,比如参数调试等,ROS提供了dynamic_reconfigure功能包,实现动态参数配置。

一、原理

  ROS的动态参数修改采用C/S架构,在运行过程中,客户端修改参数后不需要重启,而是向服务器发送请求;服务器通过回调函数确认,即可完成参数的动态配置。

二、实现

1、创建功能包

创建名为dynamic_tutorials的功能包,命令如下:

catkin_create_pkg dynamic_tutorials rospy roscpp dynamic_reconfigure

2、创建配置文件

在功能包下的cfg文件夹下,创建名为Tutorials.cfg的文件,内容如下:

#!/usr/bin/env python
PACKAGE = "dynamic_tutorials"
#导入参数生成器
from dynamic_reconfigure.parameter_generator_catkin import *
#创建参数生成器
gen = ParameterGenerator()
#定义需要动态配置的参数,参数分别代表参数名、类型、参数动态配置回调中的掩码、描述、默认值、最小值和最大值(后面两个可选,且对字符串和波尔类型无效)
gen.add("int_param",    int_t,    0, "An Integer parameter", 50,  0, 100)
gen.add("double_param", double_t, 0, "A double parameter",    .5, 0,   1)
gen.add("str_param",    str_t,    0, "A string parameter",  "Hello World")
gen.add("bool_param",   bool_t,   0, "A Boolean parameter",  True)
#定义一个枚举,参数分别代表枚举值名称、类型、值和描述
size_enum = gen.enum([ gen.const("Small",      int_t, 0, "A small constant"),
                       gen.const("Medium",     int_t, 1, "A medium constant"),
                       gen.const("Large",      int_t, 2, "A large constant"),
                       gen.const("ExtraLarge", int_t, 3, "An extra large constant")], "An enum to set size")
#定义一个整型值,可以通过枚举罗列出来
gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
#生成所有与C++和python相关的文件,并且退出程序,第二个参数表示运行时的节点名,第三个参数为生成文件所使用的前缀,需要与配置文件名相同
exit(gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials"))

真正运行时,需要去掉中文注释。配置完成后,对该文件添加可执行权限。

3、修改CMakeLists.txt文件

添加编译规则,内容如下:

generate_dynamic_reconfigure_options(
  cfg/Tutorials.cfg
)
add_dependencies(dynamic_reconfigure_node ${PROJECT_NAME}_gencfg)

4、创建dynamic_reconfigure_node节点

4、1 创建服务器节点

在src目录下,创建server.cpp文件,内容如下:

#include <ros/ros.h>

#include <dynamic_reconfigure/server.h>
//该头文件是配置文件在编译过程中生成的
#include <dynamic_tutorials/TutorialsConfig.h>
//回调函数,参数分别表示参数更新的配置值、参数修改的掩码
void callback(dynamic_tutorials::TutorialsConfig &config, uint32_t level) {
  ROS_INFO("Reconfigure Request: %d %f %s %s %d", 
            config.int_param, config.double_param, 
            config.str_param.c_str(), 
            config.bool_param?"True":"False", 
            config.size);
}

int main(int argc, char **argv) 
{
    //初始化ROS节点
    ros::init(argc, argv, "dynamic_tutorials");
    //创建服务端实例,监听客户端的参数配置请求
    dynamic_reconfigure::Server<dynamic_tutorials::TutorialsConfig> server;
    //定义回调函数
    dynamic_reconfigure::Server<dynamic_tutorials::TutorialsConfig>::CallbackType f;
    //回调函数绑定服务端,当客户端请求修改参数时,服务端跳转到回调函数进行处理
    f = boost::bind(&callback, _1, _2);
    server.setCallback(f);

    ROS_INFO("Spinning node");
    ros::spin();
    return 0;
}

4、2 修改CMakeLists.txt文件

添加编译规则,内容如下:

# for dynamic reconfigure  
add_executable(dynamic_reconfigure_node src/server.cpp) 

# make sure configure headers are built before any node using them
add_dependencies(dynamic_reconfigure_node ${PROJECT_NAME}_gencfg)

# for dynamic reconfigure  
target_link_libraries(dynamic_reconfigure_node ${catkin_LIBRARIES})  

完成上述配置后,编译功能包。

5、参数动态配置

运行roscore和dynamic_reconfigure_node节点,命令如下:

roscore
rosrun dynamic_tutorials dynamic_reconfigure_node

此时,参数动态配置的服务器就开始运行了,接下来使用ROS提供的可视化参数配置工具来修改参数,命令如下:

rosrun rqt_reconfigure rqt_reconfigure

如图:
在这里插入图片描述
  可以通过拖动、输入、下拉框等方式修改参数,值得注意的是,这里的输入方式不同与配置文件中的参数设置有关,例如设置了最大值/最小值,就会有拖动条;设置了枚举,就会出现下拉框。

 伴随着参数值的变化,在服务器节点的输出中,会看到修改后的信息,如图:
在这里插入图片描述