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_