1 #ifndef AIKIDO_IO_DETAIL_YAMLEIGENEXTENSION_HPP_
2 #define AIKIDO_IO_DETAIL_YAMLEIGENEXTENSION_HPP_
5 #include <unordered_map>
8 #include <yaml-cpp/yaml.h>
17 template <
typename MatrixType,
bool IsVectorAtCompileTime>
31 template <
typename MatrixType>
34 static YAML::Node
encode(
const MatrixType& matrix)
36 using Index =
typename MatrixType::Index;
39 for (Index i = 0; i < matrix.size(); ++i)
40 node.push_back(YAML::Node(matrix[i]));
48 template <
typename MatrixType>
51 static YAML::Node
encode(
const MatrixType& matrix)
53 using Index =
typename MatrixType::Index;
56 for (Index r = 0; r < matrix.rows(); ++r)
58 YAML::Node row(YAML::NodeType::Sequence);
60 for (Index c = 0; c < matrix.cols(); ++c)
61 row.push_back(matrix(r, c));
70 inline YAML::Mark
getMark(
const YAML::Node& node)
72 #ifdef YAMLCPP_NODE_HAS_MARK
76 return YAML::Mark::null_mark();
101 Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>>
104 = Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>;
105 using Index =
typename MatrixType::Index;
110 return encode_impl<MatrixType, MatrixType::IsVectorAtCompileTime>::encode(
121 if (node.Type() != YAML::NodeType::Sequence)
123 throw YAML::RepresentationException(
124 getMark(node),
"Matrix or vector must be a sequence.");
127 const Index rows = node.size();
128 if (MatrixType::RowsAtCompileTime != Eigen::Dynamic
129 && rows != MatrixType::RowsAtCompileTime)
131 std::stringstream ss;
132 ss <<
"Matrix has incorrect number of rows: expected "
133 << MatrixType::RowsAtCompileTime <<
"; got " << rows <<
".";
134 throw YAML::RepresentationException(
getMark(node), ss.str());
137 if (node.size() > 0 && node[0].Type() == YAML::NodeType::Sequence)
141 const auto cols = node[0].size();
143 if (MatrixType::ColsAtCompileTime != Eigen::Dynamic
144 && cols !=
static_cast<std::size_t
>(MatrixType::ColsAtCompileTime))
146 std::stringstream ss;
147 ss <<
"Matrix has incorrect number of cols: expected "
148 << MatrixType::ColsAtCompileTime <<
"; got " << cols <<
".";
149 throw YAML::RepresentationException(
getMark(node), ss.str());
155 matrix.resize(rows, cols);
157 for (
auto r = 0u; r < node.size(); ++r)
159 if (node[r].Type() != YAML::NodeType::Sequence)
161 std::stringstream ss;
162 ss <<
"Row " << r <<
" of the matrix must be a sequence.";
163 throw YAML::RepresentationException(
getMark(node), ss.str());
165 else if (node[r].size() != cols)
167 std::stringstream ss;
168 ss <<
"Expected row " << r <<
" to have " << cols <<
" columns; got "
169 << node[r].size() <<
".";
170 throw YAML::RepresentationException(
getMark(node), ss.str());
173 for (
auto c = 0u; c < cols; ++c)
175 if (node[r][c].Type() != YAML::NodeType::Scalar)
177 std::stringstream ss;
178 ss <<
"Matrix has a non-scalar element at (" << r <<
", " << c
179 <<
") component (1-based numbering).";
180 throw YAML::RepresentationException(
getMark(node), ss.str());
183 matrix(r, c) = node[r][c].template as<_Scalar>();
191 if (MatrixType::ColsAtCompileTime != Eigen::Dynamic
192 && 1 != MatrixType::ColsAtCompileTime)
194 std::stringstream ss;
195 ss <<
"Matrix has incorrect number of cols: expected "
196 << MatrixType::ColsAtCompileTime <<
"; got " << 1 <<
".";
197 throw YAML::RepresentationException(
getMark(node), ss.str());
200 matrix.resize(rows, 1);
201 for (
Index i = 0; i < rows; ++i)
203 if (node[i].Type() != YAML::NodeType::Scalar)
205 std::stringstream ss;
206 ss <<
"Vector has a non-scalar element at the " << i + 1
207 <<
"-th component (1-based numbering).";
208 throw YAML::RepresentationException(
getMark(node), ss.str());
211 matrix(i, 0) = node[i].template as<_Scalar>();
223 template <
typename _Scalar,
int _Dim,
int _Mode,
int _Options>
224 struct convert<Eigen::Transform<_Scalar, _Dim, _Mode, _Options>>
231 return convert<MatrixType>::encode(transform.matrix());
236 return convert<MatrixType>::decode(node, transform.matrix());
250 struct convert<std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>>
252 using UnorderedMap = std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>;
256 Node node(NodeType::Map);
258 for (
const auto& it : map)
259 node.force_insert(it.first, it.second);
270 map.reserve(node.size());
272 for (
const auto& it : node)
273 map[it.first.as<_Key>()] = it.second.as<_Tp>();
281 #endif // AIKIDO_IO_YAMLUTILS_HPP_