CPP解析YAML

 

Node

Node 是 yaml-cpp 的核心概念,是最重要的数据结构,用于存储解析后的yaml信息

在源码中通过 Nodetype 定义了 Node的可能类型

namespace YAML {
  struct NodeType {
    enum value {Undifined, Null, Scalar, Sequence, Map};
  };
}

可以通过 Type() 方法获取其类型

YAML::Node test1 = YAML::Load("[1,2,3,4]");
std::cout << "Type: " << test1.Type() << std::endl;
// 3 意味着 Sequence

YAML::Node test2 = YAML::Load("{'id': '1', 'degree', 'senior'}");
std::cout << "Type: " << test2.Type() << std::endl;
// 4 意味着 Map

生成的方法有两种常见的

YAML::Node test = YAML::LoadFile("xxx/xxx/xxx/test.yaml")
YAML::Node tt = YAML::Load("[1,2,3,4]");

解析

以下均假设 YAML::Node config 为存储解析后的 yaml 信息的 Node

纯量

name: frank
YAML::Node config;
std::string name = config["name"].as<string>();

// 其中 as<string> 指定将此纯量解释为 什么类型的信息。如此例 string
// 还支持 int float 等等

数组

tanway_cls:
  - Car
  - Cyclist
  - Tricyclist
  - Pedestrain
YAML::Node config;
std::vector<std::string> cls = config["tanway_cls"].as<std::vector<std::string> >;

对象

class2RGB:
  '0':
    - 255
    - 0
    - 0
  '1':
    - 0
    - 255
    - 0
  '2':
    - 0
    - 0
    - 255
#include <utility> //for std::pair

YAML::Node config;
// 一方面可以通过逐层剥开 dic 索引
std::vector<int> red = config["class2RGB"]["0"].as<std::vector<int> >;

// 另一方面对于这种情况应使用迭代的方法保存这些信息
std::unordered_map<int, std::vector<int> > class2RGB;
for (YAML::const_iterator it = config["class2RGB"].begin(), it != config["class2RGB"].end(); it++) {
  int cls_idx = it->first.as<int>();
  std::vector<int> RGB = it->second.as<std::vector<int> >();
  class2RGB.insert(std::pair<int, std::vector<int> >(cls_idx, RGB));
}

多层级对象

class2RGB:
  '0':
    r: 255
    g: 0
    b: 0
  '1':
    r: 0
    g: 255
    b: 0
  '2':
    r: 0
    g: 0
    b: 255
// 法一:
config["class2RGB"]["0"]["r"].as<int>();  //多层级!!!

// 法二:
#include <utility>

YAML::Node config;
std::unordered_map<int, std::unordered_map<std::string, int> > class2RGB;
for (YAML::const_iterator it_0 = config["class2RGB"].begin(); it_0 != config["class2RGB"].end(); it_0++) {
  int cls_idx = it_0->first.as<int>();
  std::unordered_map<std::string, int> single_cls;
  for (YAML::const_iterator it_1 = it_0->second.begin(); it_1 != it_0->second.end(); it_1++) {
    std::string color = it_1->firsr.as<std::string>();
    int value = it_1->second.as<int>();
    single_cls.insert(std::pair<std::string, int>(color,value));
  }
  class2RGB.insert(std::pair<int, std::unordered_map<std::string, int> >(cls_idx, single_cls));
}

对于ROS来说,参数服务器需要获取很多参数,目前笔者知道的可以直接读取的参数类型为:

  1. c++基本类型
  2. std::string
  3. vector容器,容器里面是基本数据类型

更多类型留待以后验证补充,但实际上最好的方法应该是查看技术文档,查看原型。一遍遍的尝试是愚蠢的。

关于ROS如何读取yaml文件中的参数,参见此文档

参考资料

  1. 原博主整理的实在是太好了,可惜链接失效了,只能贴上这种转载网站