最近开始ROS的学习及应用。
背景:车辆控制算法在实际车上调试,一定需要经常调整参数,包括PID系数,MPC权重矩阵,LQR权重矩阵,在仿真或者实车上调参数实际上真的真的非常麻烦,每次修改参数,还需要编译,一个大的工程,编译一次真的需要很多时间。
结果:经查找发现了动态调参。
ROS 动态调参官方文档 :http://wiki.ros.org/dynamic_reconfigure/Tutorials
How to Write Your First .cfg File
catkin_create_pkg --rosdistro ROSDISTRO dynamic_tutorials rospy roscpp dynamic_reconfigure
实际上这句里面--rosdistro ROSDISTRO ,对于ROS版本的描述至今没用过,也就是说可以省略。然后创建文件夹cfg
mkdir cfg
在文件夹下创建 xxxx.cfg文件,其中xxx.cfg文件内容如下:
1 #!/usr/bin/env python
2 PACKAGE = "dynamic_tutorials"
3
4 from dynamic_reconfigure.parameter_generator_catkin import *
5
6 gen = ParameterGenerator()
7
8 gen.add("int_param", int_t, 0, "An Integer parameter", 50, 0, 100)
9 gen.add("double_param", double_t, 0, "A double parameter", .5, 0, 1)
10 gen.add("str_param", str_t, 0, "A string parameter", "Hello World")
11 gen.add("bool_param", bool_t, 0, "A Boolean parameter", True)
12
13 size_enum = gen.enum([ gen.const("Small", int_t, 0, "A small constant"),
14 gen.const("Medium", int_t, 1, "A medium constant"),
15 gen.const("Large", int_t, 2, "A large constant"),
16 gen.const("ExtraLarge", int_t, 3, "An extra large constant")],
17 "An enum to set size")
18
19 gen.add("size", int_t, 0, "A size parameter which is edited via an enum", 1, 0, 3, edit_method=size_enum)
20
21 exit(gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials"))
从代码可知,这里面可以定义动态参数类型包括:int_t , double_t , str_t , bool_t ,enum 共5种类型。对于13 ~19行,意思为声明与定义enum变量。
最后
gen.generate(PACKAGE, "dynamic_tutorials", "Tutorials")
表示在PACKAGE b包下面的,"dynamic_tutorials"节点下的,"Tutorials"表示该cfg的文件名。这里面需要详细说明这里的原因是,后面ROS将其变换成头文件,需要被加载,类似与msg文件,这里面名称为:#include<dynamic_tutorials/tutorialsConfig.h> .可认为节点名/cfg文件名+Config.h 。
创建完cfg文件后,还需要设置文件伪可执行文件文件
chmod a+x cfg/Tutorials.cfg
然后添加文件至cmakelists
#find_package(catkin REQUIRED dynamic_reconfigure)
generate_dynamic_reconfigure_options(
cfg/Tutorials.cfg
#...
)
# make sure configure headers are built before any node using them
add_dependencies(example_node ${PROJECT_NAME}_gencfg)
这里需要注意:
add_dependencies(example_node ${PROJECT_NAME}_gencfg)
如果你的package 是新建的,并包含了 dynamic_reconfigure ,就无需添加下面这条命令,否则需要添加至xml文件内
<build_depend>dynamic_reconfigure</build_depend>
Setting up Dynamic Reconfigure for a Node(cpp)
#include <ros/ros.h>
2
3 #include <dynamic_reconfigure/server.h>
4 #include <dynamic_tutorials/TutorialsConfig.h>
5
6 void callback(dynamic_tutorials::TutorialsConfig &config, uint32_t level) {
7 ROS_INFO("Reconfigure Request: %d %f %s %s %d",
8 config.int_param, config.double_param,
9 config.str_param.c_str(),
10 config.bool_param?"True":"False",
11 config.size);
12 }
13
14 int main(int argc, char **argv) {
15 ros::init(argc, argv, "dynamic_tutorials");
16
17 dynamic_reconfigure::Server<dynamic_tutorials::TutorialsConfig> server;
18 dynamic_reconfigure::Server<dynamic_tutorials::TutorialsConfig>::CallbackType f;
19
20 f = boost::bind(&callback, _1, _2);
21 server.setCallback(f);
22
23 ROS_INFO("Spinning node");
24 ros::spin();
25 return 0;
26 }
这里需要注意的是server 以及 boost::bind 。
创建一个server ,与一个回调函数,boost::bind 是个函数绑定器。
使用boost::bind给回调函数传递动态参数
boost::bind(f,x,y) = f(x,y)
_1,_2表示占位符
https://www.jianshu.com/p/30e79d2a8f7d该帖子较详细说明该函数,因为毕竟不是程序员,并不想在这里下功夫。
ok至此完毕。