其他分享
首页 > 其他分享> > ROS参数服务器深度解剖(二)

ROS参数服务器深度解剖(二)

作者:互联网

ROS参数服务器中使用的命令

rosparam 命令行工具:

rosparam 命令参数选项有(set, get, load, dump, delete, list),其中load, dump, delete选项同时可在luanch文件运行有效, 向set,get,load,list 选项应用前提是ros参数服务器中有参数,否则不能使用,当然参数一定要加上命名空间,下面是详解:

在终端,我们运行roscore 启动ros master,那么对应的参数服务器也就启动起来了。我们可以使用rosparam list 查看当服务器中的参数列表,默认ros参数服务器会自动添加这样的类似参数:

/rosdistro
/roslaunch/uris/host_honghu__37429
/rosversion
/run_id

我们可以通过rosparam load xxx.yaml,如果没有报错,说明yaml语法没错,此时可以通过rosparam list查看我们刚刚加载的参数列表,并且可以通过rosparam get xxx查看 xxx 参数的数值。至于其他参数delete,dump就很简单了。

ROS 参数服务器在launch文件中

下面重点讲下load,dump,delete 在launch文件中使用,因为load, dump都是针对yaml文件的,所有后续讲yaml文件时还会回顾这节内容。前面所讲的阐述传递都是单个元素的参数变量,如果需要传递数据结构体型的变量参数,就是要使用yaml文件,当然launch文件也可以通过rosparam传递list结构数据。如下:

在launch文件中<node>的元素内加上:
<rosparam param="list">[1,23,4,5]</rosparam>  <!--一维数组的使用 -->
然后在C++文件中获取:
std::vector<int> v;
nh.param(“list”,v,v);  //说着使用nh.getParam() ,ros::param::get() 或者需要使用参数的完整名称

luanch 文件中使用二维或者多维数组,邻接矩阵、list等完整代码

<launch>
    <arg name ="topic_name_arg" default="aaa"/>
    <!-- <param name="topic_name" type = "str" value = "$(arg topic_name_arg)"/> -->
    <node pkg = "param_pkg" type = "param_node" name = "param_node" output="screen">
       <param name="topic_name" type = "str" value = "/$(arg topic_name_arg)"/>
       <rosparam param="list">[1,23,4,5,456,6,7,9,222]</rosparam>
       <rosparam param="v">
       [[1,2]
       [1,23,45,67],
       [11,22,33,44,55]]
       </rosparam>  <!-- 此处同一个维度内内存不对齐的邻接矩阵 ,可以定义常见矩阵-->
       <rosparam param="alpha">0.03</rosparam>
       <rosparam file= "$(find param_pkg)/config/p.yaml" command="load"/>
    </node>
</launch>

C++代码

  std::vector<int> vec;
  nh.param("list", vec, vec);    //对于一维的数组或者链表可以使用直接读的方式
  for(size_t i = 0; i < vec.size(); ++i)
  {
    ROS_INFO("vec[%d] = %d", i, vec[i]);
  }
  
//二维以上的数组、或者邻接矩阵之类需要借助与XmlRpc::XmlRpcVlaue 类
  std::vector<std::vector<int>> v;
  nh.param("v", xml_v, xml_v);
  v.resize(xml_v.size());
  for(int i = 0; i < xml_v.size(); ++i)
  {
    for(int j = 0; j < xml_v[i].size(); ++j)
    {
      if(XmlRpc::XmlRpcValue::TypeInt == xml_v[i][j].getType())  //此处判断必不可少
      {
        v[i].push_back(static_cast<int>(xml_v[i][j]));
        std::cout << v[i][j] << ",";
      }
    }
    std::cout << std::endl;
  }

ROS参数服务器加载yaml文件

下面是一个yaml示列,简单讲下yaml语法规则
语法规则:
YAML文件
-简单说明:YAML(YAML Ain’t a Markup Language)一种非标记语言,通用的数据串行化格式,方便人类的读写。
**基本语法规则: **

%YAML 1.2  #yaml语法格式 定义版本
---  #yaml语法格式,必须要有
#所有冒号之后必须要空格,冒号后换行的情况例外。
object: animal  # 单个键对的词典C++可以直接使用nh.param()等读取参数,不需要借助XmlRpc::XmlRpcValue
Position: {longitude: -2147483648, latitude: 2342, x: 234.9, y: 23.35} #两层的词典需要使用XmlRpc::XmlRpcValue读取参数,可以是直接使用std::map 在nh.param()中使用
factor:   #与上述luanch代码中二维数组一样的使用方法
    [[1,2],
    [3,4,5],
    [11,22,33,44,55,66,77,88,9],
    [123,234,345,45,6,567,678]]
array: [1,2,3,4,5,6]  #上述launch文件中一维数组一样的使用方法
Wheel:  #词典可以一行定义,也可以分行定义,缩进必要使用空格,并对其
    Car:
        Radius: 0.6
    Bicycle:
        Radius: 0.3
    Airplane:
        Radius: 0.5
Class:  #横杠‘-’表示数组定义,这里使用数组和词典组合定义
-   Car:
        Radius: 0.1
-   Bicycle:
        Radius: 0.3
-   Airplane:
        Radius: 0.5

以上yaml文件加载之后,使用rosparam list 查看ros参数服务器就可以看到以下参数列表:

/Class
/Position/latitude
/Position/longitude
/Position/x
/Position/y
/Wheel/Airplane/Radius
/Wheel/Bicycle/Radius
/Wheel/Car/Radius
/array
/factor
/object
/rosdistro
/roslaunch/uris/host_honghu__37429
/rosversion
/run_id

下面贴出C++代码

std::string                   obj;
  std::map<std::string, double> pos;  //可以直接使用map数据结构读取yaml中的二维词典
  std::vector<std::vector<int>> factor;
  std::vector<int>              array;
  XmlRpc::XmlRpcValue           factor_xml;
  XmlRpc::XmlRpcValue           wheel_xml;
  XmlRpc::XmlRpcValue           class_xml;

  double wheel_car_r      = 0;
  double wheel_bicycle_r  = 0;
  float  wheel_airplane_r = 0;

  double class_car_r      = 0;
  float  class_bicycle_r  = 0;
  float  class_airplane_r = 0;

  nh.param("object", obj, obj);
  ROS_INFO("object: %s", obj.c_str());
  nh.param("array", array, array);
  for(int i = 0; i < array.size(); ++i)
  {
    std::cout << array[i] << ",";
  }
  std::cout << std::endl;

  nh.param("Postion", pos, pos);

  for(auto it = pos.begin(); it != pos.end(); ++it)
  {
    std::cout << it->first << "," << it->second << std::endl;
  }

  nh.param("factor", factor_xml, factor_xml);
  factor.resize(factor_xml.size());
  for(int i = 0; i < factor.size(); ++i)
  {
    for(int j = 0; j < factor_xml[i].size(); ++j)
    {
      if(XmlRpc::XmlRpcValue::TypeInt == factor_xml[i][j].getType())
      {
        factor[i].push_back(static_cast<int>(factor_xml[i][j]));
        std::cout << factor[i][j] << ",";
      }
    }
    std::cout << std::endl;
  }

  nh.param("Wheel", wheel_xml, wheel_xml);
  //  wheel_car_r = float(atof(wheel_xml["Car"]["Radius"].toXml().c_str()));
  if(XmlRpc::XmlRpcValue::TypeDouble == wheel_xml["Car"]["Radius"].getType())
  {
    wheel_car_r = double(wheel_xml["Car"]["Radius"]);
  }
  std::cout << " wheel_car_r: " << wheel_car_r << std::endl;
  nh.param("Class", class_xml, class_xml);
  //  class_car_r = float(atof(class_xml[0]["Radius"].toXml().c_str()));
  if(XmlRpc::XmlRpcValue::TypeDouble == class_xml[0]["Car"]["Radius"].getType())
  {
    class_car_r = double(class_xml[0]["Car"]["Radius"]);
  }
  std::cout << " class_car_r: " << class_car_r << std::endl;

  float r = 0.f;
  nh.param("/param_node/Wheel/Car/Radius", r, r);
  std::cout << " radius " << r << std::endl;
  ros::Rate loop_rate(10);

总结:
我们写好yaml文件后,可以先使用rosparam load xxx.yaml命令检验yaml文件有没有存在语法错误。另外,在C++代码中使用XmlRpcVlaue 加载参数 ,词典参数需要用[name]名字访问,数组使用[]下表访问,可以看C++代码,同时需要注意由于ros 参数服务器只支持32位的数字参数,那么除去符号位,有效位只有31位因此,数值范围在 [ − 2 31 , 2 31 − 1 ] [-2^{31} , 2^{31}-1] [−231,231−1] 即[-2147483648,2147383647],因此需要留意这个问题,可以使用yaml-cpp 库读取yaml文件绕开或者避免这个问题

有问题联系QQ(451800861)持续更新中…

标签:xml,std,rosparam,list,yaml,参数,服务器,ROS,解剖
来源: https://blog.csdn.net/HongHu_fly/article/details/117002739