RMVL  2.5.0-dev
Robotic Manipulation and Vision Library
载入中...
搜索中...
未找到
YAML 数据读写

上一篇教程:聚合类反射及其相关 API
下一篇教程:基于异步 I/O 的协程设施


1. 概述

core 模块提供了基于 rapidyaml 的 YAML 树模型,接口位于 rm::yaml 命名空间中。它适合读取配置、机器人描述和其他结构化数据,不会向用户暴露 rapidyaml 的节点或字符串视图类型。

rm::yaml::Node 是共享底层 YAML 树所有权的轻量句柄。保存子节点时无需同时保存根节点,但同一棵树上的并发写入或读写并发需要由调用方同步。

直接包含对应头文件即可使用:

#include <rmvl/core/yaml.hpp>

也可以包含 core 模块汇总头文件:

#include <rmvl/core.hpp>

2. 解析与读取

rm::yaml::parse() 从内存文本解析 YAML,rm::yaml::load() 从文件加载。两者都返回 rm::yaml::Result,解析或文件错误不会导致进程终止。

auto result = rm::yaml::parse(R"(
camera:
name: front
width: 1280
enabled: true
labels: [robot, armor]
)");
if (!result) {
fmt::print("YAML error at {}:{}: {}\n",
result.error.line,
result.error.column,
result.error.message);
return;
}
auto name = (*result)["camera"]["name"].as<std::string>();
auto width = (*result)["camera"]["width"].valueOr(640);
auto labels = (*result)["labels"].as<std::vector<std::string>>();
Result parse(std::string_view source)
从内存解析 YAML

operator[] 查找失败时返回无效节点。as<T>() 转换失败时返回 std::nulloptvalueOr() 可直接提供默认值。整数转换会检查格式和目标类型的取值范围。

3. 构建与保存

可以从映射、序列或标量根节点开始构建 YAML:

root.set("name", "demo");
root.set("ports", std::vector<int>{8000, 8001});
auto network = root.ensure("network");
network.set("host", "127.0.0.1");
network.set("enabled", true);
const auto text = rm::yaml::dump(root);
if (!rm::yaml::save("config.yml", root, error))
fmt::print("failed to save YAML: {}\n", error.message);
static Node createMap()
创建空映射根节点
std::string dump(const Node &node)
将节点及其后代序列化为 YAML
bool save(std::string_view path, const Node &node, Error &err)
将节点保存为 YAML 文件并返回错误信息
YAML 操作错误
定义 yaml.hpp:60

映射节点保持 YAML 树中的展示顺序。类型转换同时支持以 std::string 为键的 std::mapstd::unordered_map:前者适合需要稳定排序输出的配置,后者适合不关心顺序的运行时查找。

4. OpenCV 类型兼容

启用 OpenCV 后,rm::yaml 可直接转换 OpenCV FileStorage 使用的类型,包括 cv::Pointcv::Point3cv::Sizecv::Rectcv::Veccv::Scalarcv::Rangecv::KeyPointcv::DMatchcv::Matxcv::Mat,上述类型组成的 std::vector 同样受支持。

解析器兼容 OpenCV 使用的 YAML:1.0 文件头以及 !!opencv-matrix!!opencv-nd-matrix 标签。矩阵中的 rowscolssizesdtdata 字段会自动转换为对应深度与通道数的矩阵:

auto result = rm::yaml::load("camera.yml");
auto camera_matrix = (*result)["camera_matrix"].as<cv::Matx33d>();
auto points = (*result)["points"].as<std::vector<cv::Point2f>>();
Result load(std::string_view path)
从文件加载 YAML

普通 dump()save() 输出标准 YAML。需要让 OpenCV FileStorage 继续读取输出文件时,使用 dumpOpenCv()saveOpenCv() 生成带 OpenCV 文件头和矩阵标签的兼容格式。

5. 自定义类型

为用户类型提供 yaml_encode()yaml_decode() 即可通过 ADL 接入,无需继承基类或注册运行时类型:

struct Point {
double x{};
double y{};
};
bool yaml_encode(rm::yaml::Node &node, const Point &point) {
node.makeMap();
return node.set("x", point.x) && node.set("y", point.y);
}
bool yaml_decode(const rm::yaml::Node &node, Point &point) {
return node["x"].read(point.x) && node["y"].read(point.y);
}
YAML 树节点句柄
定义 yaml.hpp:80
bool read(T &value) const
读取并转换节点值
void makeMap()
将节点替换为空映射
bool set(std::string_view name, const T &value)
设置映射字段
bool yaml_decode(const Node &node, cv::Point_< T > &value)
定义 yaml.hpp:434

之后自定义类型可以与内置类型一样使用:

root.set("origin", Point{1.5, 2.0});
auto origin = root["origin"].as<Point>();

当前支持字符串、布尔值、整数、浮点数、枚举、std::optionalstd::vectorstd::array 以及字符串键映射。Node::tag()Node::setTag() 可用于访问 YAML 标签;需要 anchor 或样式等其他 rapidyaml 底层特性时,应直接使用 rapidyaml。