rosparam与参数服务器

机器人的参数一般会提前设置好,这些参数都会放在yaml文件里,但有些参数是需要动态改变的,调试导航时尤其如此。于是ROS提供了rosparam命令和参数服务器这两个工具。rosparam命令的方便之处在于它可以直接读取yaml文件中的参数,而不必自己找第三方库去文件中读取。

如果参数服务器不加载yaml文件,就没有相应的参数。`nh.param`函数只是对相应的变量赋值,不会加载参数到服务器。

一般在package的文件夹里会建一个param文件夹,也就是与launchmsg同一级,yaml文件就放在这个param文件夹里。

使用rosparam load file.yaml命令将多个参数加载到参数服务器,在用到时会从服务器中获取。但实际上,这个命令直接用得不多。要将一个yaml文件中的参数在节点启动时都加载到参数服务器,一般是在launch文件中使用rosparam标签:

1
2
<rosparam file="$(find turtlebot_navigation)/param/move_base_params.yaml" command="load" />
<rosparam file="$(arg custom_param_file)" command="load" />

加载完成后,可以使用一些调试性的命令了。用rosparam list查看所有参数。可以用rosparam get param查看某参数的值,用rosparam set param value设定参数的值。另外还可以用rosparam delete param删除某个参数。

在launch文件里,如果参数paramA是在某个node之内的,那么它的全名是/node/paramA。如果希望全名是paramA,那么不应在任何node内,一般写在launch开头。

使用rosparam get时要注意,参数名称不只是yaml文件中的名称,而是一个完整名称,比如.yaml中是这样的:

1
2
3
TrajectoryPlannerROS:
int_param: 2
max_vel_x: 0.15

要获得max_vel_x的值,命令是rosparam get /move_base/TrajectoryPlannerROS/max_vel_x,也就是/node/tag/param

启动ROS节点后, 用rosparam get param可获知各个参数值,而且发现在关掉所有节点后,仍然能用rosparam get获得参数值,可见它被存到参数服务器里了

程序中的param

加载参数的方法其实有三种,除了上面说的直接用rosparam load命令和launch文件中使用load外,还可以在程序中使用paramsetParam,getParam函数,这里和yaml文件就没关系了。

1
2
3
4
5
6
7
8
9
10
std::string s;
int num;
n.getParam("string_param", s);
pn.getParam("int_param", num);
n.setParam("string_param", "hehe");
pn.setParam("int_param", 222);


n.param<std::string>("string_param", s, "haha");
pn.param<int>("int_param", num, 666)

getParam()函数可以从参数服务器获取参数值。如果成功,变量s和num的值将会被修改为参数值,函数返回true;如果不成功(譬如参数服务器没有设置这个参数),变量s和num将保持原值,函数会返回false。setParam()就是设置参数的值了。param()函数从参数服务器取参数值给变量。如果无法获取,则将默认值赋给变量,和param()函数的区别是还提供了一个默认值。

还有ros::NodeHandle::hasParam()ros::NodeHandle::deleteParam()函数,后者可以在析构函数中使用。


如果在yaml文件中定义如下

1
2
3
waypoints:
X: [38, 38, 38, 38, 38, 38, 38 , 38.21, 39.25, 42.56, 48.97, 61]
Y: [-57, -45, -32.0, -18.5, -12.0, 0.0, 12, 35, 42.89, 80.41, 131.48, 139.47]

可以直接以vector形式获取数据
1
2
vector<double> X;
nh.getParam("/frenet_planner/waypoints/X", X);

注意

使用yaml文件时,一定要注意格式的正确,但是最好不要用-符号,也就是不要用数组项,否则可能出问题,之前尝试使用一个第三方库读取yaml文件时,总是读取失败,发现只有加上-符号,也就是将参数作为数组项后才能正常读取。但再用rosparam get读取这个文件中的参数就会出错,结果获得的全是默认值,不是当前值。用rosparam list会发现加载的参数不全,原因是yaml文件中这样编辑:

1
2
3
4
TrajectoryPlannerROS:
-name: value
int_param: 2
max_vel_x: 0.15

不要加-name一行,也就是反而不能使用标准的yaml格式

参考:Using Parameters in roscpp