- ROS机器人编程实战
- (印度)库马尔·比平
- 1680字
- 2020-08-27 13:21:46
3.2 掌握参数服务器和动态参数
在前一章中,我们了解到参数服务器是节点管理器(Master)的一部分,并且允许ROS系统将数据或配置信息保存在关键位置。所有的节点可以获取这些数据来配置、改变自己的状态。
我们之前已经有过使用rosparam工具的经验,所以现在使用参数服务器也不成问题了。在节点执行期间,我们可以使用dynamic_reconfigure功能包来动态地改变它所使用的参数。在下一节中,我们将详细了解ROS中的动态参数工具。
3.2.1 准备工作
通常我们所编写节点程序的变量值是在初始化的时候就确定好了,之后这些值只能在节点的内部进行修改。如果我们需要从运行节点外部来动态地修改这些值,就需要用到参数服务器、服务或者话题。
举例来说,如果我们正在操作一个节点,这个节点可以通过PID控制器来控制电动机的最佳运动速度,这通常需要调整PID的3个参数,即k1、k2和k3。不过,ROS中提供了一个效率更高的工具“Dynamic Reconfigure”(动态配置)来完成这些功能。
在接下来的一节中,我们将学习如何在一个基本实例节点中启用这个工具。首先必须在CMakeLists.txt和package.xml文件中添加几行代码。
3.2.2 如何完成
1.如果你希望使用“Dynamic Reconfigure”工具,首先要编写一个配置文件,并将其保存在预期功能包的cfg文件夹中。
2.在parameter_server_tutorials功能包中创建一个cfg文件夹,然后在其中再创建一个parameter_server_tutorials.cfg文件。这个过程如下所示:
$ roscd parameter_server_tutorials $ mkdir cfg $ vim parameter_server_tutorials
3.将如下所示的代码添加到parameter_server_tutorials.cfg文件中:
#!/usr/bin/env python PACKAGE = "parameter_server_tutorials" from dynamic_reconfigure.parameter_generator_catkin import * gen = ParameterGenerator() gen.add("BOOL_PARAM", bool_t, 0,"A Boolean parameter", True) gen.add("INT_PARAM", int_t, 0, "An Integer Parameter", 1, 0, 100) gen.add("DOUBLE_PARAM", double_t, 0, "A Double Parameter", 0.01, 0, 1) gen.add("STR_PARAM", str_t, 0, "A String parameter", "Dynamic Reconfigure") size_enum = gen.enum([ gen.const("Low", int_t, 0, "Low : 0"), gen.const("Medium", int_t, 1,"Medium : 1"), gen.const("High", int_t, 2, "Hight :2")], "Selection List") gen.add("SIZE", int_t, 0, "Selection List", 1, 0, 3, edit_method=size_enum) exit(gen.generate(PACKAGE, "parameter_server_tutorials", "parameter_server_"))
4.要完成参数生成器的初始化并定义需要动态配置的参数,我们需要添加以下代码:
gen = ParameterGenerator() gen.add("BOOL_PARAM", bool_t, 0,"A Boolean parameter", True) gen.add("INT_PARAM", int_t, 0, "An Integer Parameter", 1, 0, 100) gen.add("DOUBLE_PARAM", double_t, 0, "A Double Parameter", 0.01, 0, 1) gen.add("STR_PARAM", str_t, 0, "A String parameter", "Dynamic Reconfigure") size_enum = gen.enum([gen.const("Low", int_t, 0, "Low : 0"), gen.const("Medium", int_t, 1, "Medium : 1"), gen.const("High", int_t, 2, "Hight :2")],"Selection List") gen.add("SIZE", int_t, 0, "Selection List", 1, 0, 3, edit_method=size_enum)
5.这些行中添加了不同的参数类型并且设置默认值(default)、描述(description)和取值范围等。生成参数生成器add()的格式如下所示:
gen.add(name, type, level, description, default, min, max)
参数生成器add()中每个参数的含义如下所示。
•name:参数的名称。
•type:定义存储值的类型。
•level:需要传入参数动态配置回调函数中的掩码。
•description:描述参数作用的字符串。
•default:设置节点启动时参数的默认值。
•min:设置参数的最小值。
•max:设置参数的最大值。
上面程序中的最后一行代码用于生成所需的文件并退出程序。我们可以看到这个.cfg文件是使用Python语言编写的。虽然本书是针对C++语言的,但是在某些特定的场合,或者需要解释某个概念的时候,还是会使用到Python语言。
exit(gen.generate(PACKAGE, "parameter_server_tutorials", "parameter_server_"))
然后,我们必须修改parameter_server_tutorials.cfg文件的权限(为其添加可执行权限),这是因为需要ROS系统将其作为一个Python脚本来执行。
$ chmod a+x cfg/ parameter_server_tutorials.cfg
6.为了调用编译,我们需要将下面这些行的内容添加到CMakeLists.txt文件中。
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation dynamic_reconfigure ) generate_dynamic_reconfigure_options( cfg/parameter_server_tutorials.cfg ) add_dependencies(parameter_server_tutorials parameter_server_tutorials_gencfg)
7.接下来我们需要在“Dynamic Reconfigure”的帮助下来创建一个示例节点。
$ roscd parameter_server_tutorials $ vim src/ parameter_server_tutorials.cpp
我们需要将下面的代码片段添加到node文件中:
#include <ros/ros.h> #include <dynamic_reconfigure/server.h> #include <parameter_server_tutorials/parameter_server_Config.h> void callback(parameter_server_tutorials::parameter_server_Config &config, uint32_t level) { ROS_INFO("Reconfigure Request: %s %d %f %s %d", config.BOOL_PARAM?"True":"False", config.INT_PARAM, config.DOUBLE_PARAM, config.STR_PARAM.c_str(), config.SIZE); } int main(int argc, char **argv) { ros::init(argc, argv, "parameter_server_tutorials"); dynamic_reconfigure::Server<parameter_server_tutorials::paramet er_server_Config> server; dynamic_reconfigure::Server<parameter_server_tutorials::paramet er_server_Config>::CallbackType f; f = boost::bind(&callback, _1, _2); server.setCallback(f); ROS_INFO("Spinning"); ros::spin(); return 0; }
像往常一样,这几行代码引入了ROS的头文件、参数服务器以及我们之前创建的配置文件:
#include <ros/ros.h> #include <dynamic_reconfigure/server.h> #include <parameter_server_tutorials/parameter_server_Config.h>
下面的代码中显示了函数callback()的内容,当客户端请求修改参数时,它就会将修改之后的参数值打印输出。需要注意的是,参数的名字必须和parameter_server_tutorials.cfg文件中配置的相一致。
void callback(parameter_server_tutorials::parameter_server_Config &config, uint32_t level) { ROS_INFO("Reconfigure Request: %s %d %f %s %d", config.BOOL_PARAM?"True":"False", config.INT_PARAM, config.DOUBLE_PARAM, config.STR_PARAM.c_str(), config.SIZE); }
另外,在主函数中是使用parameter_server_Config configuration文件来初始化服务器的。当服务器收到重新配置的请求时,就会跳转到callback函数进行处理。
dynamic_reconfigure::Server<parameter_server_tutorials::paramet er_server_Config> server; dynamic_reconfigure::Server<parameter_server_tutorials::paramet er_server_Config>::CallbackType f; f = boost::bind(&callback, _1, _2); server.setCallback(f);
8.最后,我们需要将下面的代码添加到ROS构建系统的文件CMakeLists.txt中来完成编译。
add_executable(parameter_server_tutorials src/parameter_server_tutorials.cpp) add_dependencies(parameter_server_tutorials parameter_server_tutorials_gencfg) target_link_libraries(parameter_server_tutorials ${catkin_LIBRARIES}
现在我们已经完成代码部分的开发了,接下来需要编译并运行这个节点,同时启动ROS提供的可视化参数动态配置工具(Dynamic ReconfigureGUI),执行的命令如下所示:
$ roscore $ rosrun parameter_server_tutorials parameter_server_tutorials $ rosrun rqt_reconfigure rqt_reconfigure
9.在图3-1所示的可视化界面中,可以动态地修改节点参数。
图3-1 可视化参数动态配置工具
当用户通过滑块、复选框等修改参数时,我们可以在节点运行的命令行(shell)中看到修改的信息(见图3-2)。
图3-2 可视化参数动态配置工具的回显
ROS中提供的“Dynamic Reconfigure”工具非常有用,我们通过它可以更快、更有效地完成对与硬件连接节点的调整与验证。我们将在接下来的章节中了解这方面的更多内容。