YAML解析自定义结构

 

yaml解析自定义结构

直接看官方例程1

struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
// 实际使用来看并不需要重载 operator==

namespace YAML {
template<>
struct convert<Vec3> {
  static Node encode(const Vec3& rhs) {
    Node node;
    node.push_back(rhs.x);
    node.push_back(rhs.y);
    node.push_back(rhs.z);
    return node;
  }

  static bool decode(const Node& node, Vec3& rhs) {
    if(!node.IsSequence() || node.size() != 3) {
      return false;
    }

    rhs.x = node[0].as<double>();
    rhs.y = node[1].as<double>();
    rhs.z = node[2].as<double>();
    return true;
  }
};
}

YAML::Node node = YAML::Load("start: [1, 3, 0]");
Vec3 v = node["start"].as<Vec3>();
node["end"] = Vec3(2, -1, 0);

个人认为最值得注意的部分是:

    if(!node.IsSequence() || node.size() != 3) {
      return false;
    }

用来校验node的合法性。

个人使用样例:

YAML文件

topics_config:
        - is_record: false
          wildcard_path: ["/perception/users/qiuzhongyuan/datasets/at128/xingyueL/demo_shanqi/*.pcd"]
          topic_name: /at128
          begin_msg_idx: 0
          msg_count: 2000
          msg_config:
            type: sensor_msgs/msg/PointCloud2
            encoding: bgr8
            scale: 1
            padding_top: 0
            padding_bottom: 0
            padding_left: 0
            padding_right: 0
            lidar_type: at128
            viewed_scale: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        - is_record: false
          wildcard_path: ["/perception/custom_datasets/nova_pilot/mod/train/image/highway/cam9/0727/*.jpg"]
          topic_name: /vis_topic_image
          begin_msg_idx: 2000
          msg_count: 2000
          msg_config:
            type: sensor_msgs/msg/CompressedImage
            encoding: rgb8
            scale: 1
            padding_top: 0
            padding_bottom: 0
            padding_left: 0
            padding_right: 0
            lidar_type: at128
            viewed_scale: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

结构体定义和自定义编解码

struct TopicConfig {
    bool                            isRecord;
    std::vector<std::string>        wildcardPath;
    std::string                     topicName;
    int                             beginMsgIdx;
    int                             msgCount;
    std::string                     msgType;
    std::string                     imgEncoding;
    int                             scale;
    int                             paddingTop;
    int                             paddingBottom;
    int                             paddingLeft;
    int                             paddingRight;
    std::string                     lidarType;
    std::vector<double>             viewedScale;

    TopicConfig() :
        isRecord(false),
        wildcardPath({}),
        topicName(""),
        beginMsgIdx(0),
        msgCount(0),
        msgType(""),
        imgEncoding(""),
        scale(1),
        paddingTop(0),
        paddingBottom(0),
        paddingLeft(0),
        paddingRight(0),
        lidarType(""),
        viewedScale({0.0, 0.0, 0.0, 0.0, 0.0, 0.0})
    {};
};

namespace YAML {
    template<>
    struct convert<TopicConfig> {
        static Node encode(const TopicConfig& config) {
            Node node;
            node["is_record"] = config.isRecord;
            node["wildcard_path"] = config.wildcardPath;
            node["topic_name"] = config.topicName;
            node["begin_msg_idx"] = config.beginMsgIdx;
            node["msg_count"] = config.msgCount;
            node["msg_config"]["type"] = config.msgType;
            node["msg_config"]["encoding"] = config.imgEncoding;
            node["msg_config"]["scale"] = config.scale;
            node["msg_config"]["padding_top"] = config.paddingTop;
            node["msg_config"]["padding_bottom"] = config.paddingBottom;
            node["msg_config"]["padding_left"] = config.paddingLeft;
            node["msg_config"]["padding_right"] = config.paddingRight;
            node["msg_config"]["lidar_type"] = config.lidarType;
            node["msg_config"]["viewed_scale"] = config.viewedScale;
            return node;
        }

        static bool decode(const Node& node, TopicConfig& config) {
          	// 使用如下的方式来校验每一个key的有效性
            if (!node["is_record"] || !node["wildcard_path"] || 
                !node["topic_name"] || !node["begin_msg_idx"] || 
                !node["msg_count"] || !node["msg_config"]["type"] || !node["msg_config"]["encoding"] ||
                !node["msg_config"]["scale"] || !node["msg_config"]["padding_top"] || 
                !node["msg_config"]["padding_bottom"] || !node["msg_config"]["padding_left"] || 
                !node["msg_config"]["padding_right"] || 
                !node["msg_config"]["lidar_type"] || !node["msg_config"]["viewed_scale"]) {
                return false;
            }

            config.isRecord         = node["is_record"].as<bool>();
            config.wildcardPath     = node["wildcard_path"].as<std::vector<std::string>>();
            config.topicName        = node["topic_name"].as<std::string>();
            config.beginMsgIdx      = node["begin_msg_idx"].as<int>();
            config.msgCount         = node["msg_count"].as<int>();
            config.msgType          = node["msg_config"]["type"].as<std::string>();
            config.imgEncoding      = node["msg_config"]["encoding"].as<std::string>();
            config.scale            = node["msg_config"]["scale"].as<int>();
            config.paddingTop       = node["msg_config"]["padding_top"].as<int>();
            config.paddingBottom    = node["msg_config"]["padding_bottom"].as<int>();
            config.paddingLeft      = node["msg_config"]["padding_left"].as<int>();
            config.paddingRight     = node["msg_config"]["padding_right"].as<int>();
            config.lidarType        = node["msg_config"]["lidar_type"].as<std::string>();
            config.viewedScale      = node["msg_config"]["viewed_scale"].as<std::vector<double>>();
            return true;
        }
    };
}

使用

YAML::Node config = YAML::LoadFile("file.yaml");
std::vector<TopicConfig> = config["topics_config"].as<std::vector<TopicConfig>>();

参考资料

  1. 官方例程
  2. yaml-cpp通用encode/decode重载宏
  3. github–使用样例