ezconfig
Create C++ Objects from Yaml and Json
Loading...
Searching...
No Matches
eigen.hpp
1// Copyright (c) 2023 Petter Nilsson. MIT License. https://github.com/pettni/ezconfig
2
3#pragma once
4
5#include <yaml-cpp/yaml.h>
6
7#include "eigen_fwd.hpp"
8
9namespace YAML {
10
11template<typename T, int Rows, int Cols, int Opts>
12bool convert<Eigen::Matrix<T, Rows, Cols, Opts>>::decode(const Node & yaml, Eigen::Matrix<T, Rows, Cols, Opts> & obj)
13{
14 if constexpr (Cols == 1) {
15 if (yaml.IsSequence()) {
16 if (Rows > 0 && yaml.size() != static_cast<std::size_t>(Rows)) {
17 throw YAML::ParserException{
18 yaml.Mark(),
19 "Invalid size of numeric yaml vector: expected '" + std::to_string(Rows) + "' but got '"
20 + std::to_string(yaml.size()) + "'",
21 };
22 }
23 // compile-time vector
24 const auto data = yaml.as<std::vector<T>>();
25 obj = Eigen::Map<const Eigen::Matrix<T, Rows, Cols>>(data.data(), static_cast<Eigen::Index>(data.size()));
26 } else if (yaml.IsMap()) {
27 // count x,y,z keys
28 auto counter = [](const auto & item) {
29 const auto k = item.first.template as<std::string>();
30 return k == "x" || k == "y" || k == "z";
31 };
32 Eigen::Index N = std::count_if(std::begin(yaml), std::end(yaml), counter);
33 obj.resize(N);
34 for (auto i = 0u; i < N; ++i) { obj(i) = yaml[char('x' + i)].as<T>(); }
35 } else {
36 throw YAML::ParserException{yaml.Mark(), "Expected sequence or map"};
37 }
38 } else {
39 // compile-time matrix
40 const auto data = yaml.as<std::vector<std::vector<T>>>();
41 if (data.empty()) { throw YAML::ParserException{yaml.Mark(), "Can not parse empty matrix"}; }
42 obj.resize(static_cast<Eigen::Index>(data.size()), static_cast<Eigen::Index>(data[0].size()));
43 for (auto i = 0u; const auto & data_row : data) {
44 if (static_cast<Eigen::Index>(data_row.size()) != obj.cols()) {
45 throw YAML::ParserException{yaml.Mark(), "Not all rows have the same length"};
46 }
47 obj.row(i++) =
48 Eigen::Map<const Eigen::Matrix<T, Cols, 1>>(data_row.data(), static_cast<Eigen::Index>(data_row.size()));
49 }
50 }
51 return true;
52}
53
54template<typename T, int Opts>
55bool convert<Eigen::Quaternion<T, Opts>>::decode(const Node & yaml, Eigen::Quaternion<T, Opts> & obj)
56{
57 if (yaml["w"]) {
58 obj.w() = yaml["w"].as<T>();
59 obj.x() = yaml["x"].as<T>();
60 obj.y() = yaml["y"].as<T>();
61 obj.z() = yaml["z"].as<T>();
62 } else if (yaml["qw"]) {
63 obj.w() = yaml["qw"].as<T>();
64 obj.x() = yaml["qx"].as<T>();
65 obj.y() = yaml["qy"].as<T>();
66 obj.z() = yaml["qz"].as<T>();
67 } else {
68 throw YAML::ParserException{yaml.Mark(), "Expected key 'w' or 'qw'"};
69 }
70 return true;
71}
72
73} // namespace YAML
YAML forward declarations.
Definition yaml_fwd.hpp:16