理解ROS:参数服务器&动态参数

一、程序中的getparam与param

1. getparam(无默认值)

bool getParam (const std::string& key, parameter_type& output_value)//返回值判断是否获取参数成功

其中:

  • key是参数名(相当于接口,和话题类似),命名方法参考:ros命名(这个参考后续学习)
  • output_value用来保持参数的值
    parameter_type类型包含bool, int, double, string, 或 特定的 XmlRpcValue 类型,XmlRpcValue类型包含所有类型,甚至是lists/maps

举例:

std::string s;
n.getParam("my_param", s);

2. param(有默认值)

int i;
n.param("my_num", i, 42);//默认参数为42

3. 删除参数

n.deleteParam("my_param");

4.程序中设置参数

n.setParam("my_param", "hello there");

5. 检查参数

这个步骤不是必需的

 if (!n.hasParam("my_param"))
 {
    
    
    ROS_INFO("No param named 'my_param'");
 }

6. 搜索参数

例如:如果参数服务器存在/a/b的参数,你的NodeHandle在/a/c工作空间,searchParam()搜索b会得到/a/b. 如果/a/c/b参数增加,搜索就会得到/a/c/b参数。举例如下:

 std::string param_name;
 if (n.searchParam("b", param_name))   {
    
         
 // Found parameter, can now query it using param_name     
 int i = 0;     
 n.getParam(param_name, i);   
 }   
 else   {
    
         
 ROS_INFO("No param 'b' found in an upward search");   
 }

二. launch中参数设置方式

总共三种:param,rosparam,arg

Param

launch文件中设置参数:

节点内:
< node name=“node_keyboard_control” pkg=“keyboardControl” type=“node_keyboard_control” output=“screen”>
< param name=“linear_min” value=“0.3” />
< /node>

全局:
< param name=“use_gui” value="$(arg gui)" />

rosparam

launch文件中设置参数:

< rosparam file=“param.yaml” command=“load”/>

arg

由launch内部使用,类似于launch里面的语法。

launch文件中设置参数:

< arg name=“gui” default=“false” />
< param name=“use_gui” value="$(arg gui)" />
//一起使用

三、动态参数

仅仅使用ros的参数有时候不能满足我们的工作需求,比如在调试机器人的参数时,我们希望能够动态改变参数,从而观察机器人的相应的反应。所以我们接下来介绍ros中的动态参数。
ros中的动态参数类似于话题的发布和订阅形式,一旦配置好动态参数文件,我们只需要在程序中订阅相应的参数即可。

创建配置参数

  • 创建ros包

catkin_create_pkg dynamic_tutorials rospy roscpp dynamic_reconfigure

如果自己已经有功能包了,只需要在CmakeList.txt和package.xml中自行添加dynamic_reconfigure。

  • 创建cfg配置文件
    在功能包的src同一级目录下创建文件夹cfg,并在cfg中添加一个文件命名为my_cfg.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)

exit(gen.generate(PACKAGE, "dynamic_tutorials", "my_cfg"))

可以看出它是由python形式实现的,下面简要介绍配置的内容。

创建参数生成器:

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)

动态参数的实现形式:add(name, type, level,description, default, min,max)。

  • name:参数名,使用字符串描述;
  • type:定义参数的类型,可以是int_t, double_t, str_t, 或者bool_t;
  • level:需要传入参数动态配置回调函数中的掩码,在回调函数中会修改所有参数的掩码,表示参数已经进行修改;
  • description:描述参数作用的字符串;
  • default:设置参数的默认值;
  • min:可选,设置参数的最小值,对于字符串和布尔类型值不生效;
  • max:可选,设置参数的最大值,对于字符串和布尔类型值不生效;

枚举类型的动态参数实现形式: 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", "my_cfg"))
  • dynamic_tutorials:包的名字
  • my_cfg:创建的配置文件名(也可以不是配置文件名,但是它必须和程序中保持一致),也就是程序中需要包含的头文件

创建服务端节点

服务端节点,也就是订阅节点,代码实现如下,详情看注释:

#include <ros/ros.h>
#include <dynamic_reconfigure/server.h>//实现动态参数的头文件
#include <dynamic_tutorials/TutorialsConfig.h>//cfg生成的头文件

/****回调函数****/
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::init(argc, argv, "node_dy_param");

    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;
}

增加CmakeList.txt内容:

add_executable(node_dy_param src/main.cpp)
target_link_libraries(node_dy_param ${
    
    catkin_LIBRARIES})
add_dependencies(node_dy_param ${
    
    ${
    
    PROJECT_NAME}_EXPORTED_TARGETS} ${
    
    catkin_EXPORTED_TARGETS})
add_dependencies(node_dy_param ${
    
    PROJECT_NAME}_gencfg)

运行

启动订阅端节点:

$ roscore
$ rosrun dynamic_tutorials node_dy_param

运行发布端节点:

 rosrun rqt_reconfigure rqt_reconfigure

猜你喜欢

转载自blog.csdn.net/QLeelq/article/details/111060091