GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/dynamic-graph/signal-caster.h Lines: 30 30 100.0 %
Date: 2023-03-15 12:04:10 Branches: 46 78 59.0 %

Line Branch Exec Source
1
// -*- c++-mode -*-
2
// Copyright 2010 François Bleibel Thomas Moulard, Olivier Stasse
3
//
4
5
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HH
6
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HH
7
#include <dynamic-graph/dynamic-graph-api.h>
8
#include <dynamic-graph/eigen-io.h>
9
#include <dynamic-graph/linear-algebra.h>
10
11
#include <boost/format.hpp>
12
#include <boost/lexical_cast.hpp>
13
#include <map>
14
#include <vector>
15
16
#include "dynamic-graph/exception-signal.h"
17
18
namespace dynamicgraph {
19
20
/// Inherit from this class if you want to keep default implementation for some
21
/// functions.
22
template <typename T>
23
struct signal_io_base {
24
  /// serialize a signal value.
25
16
  inline static void disp(const T &value, std::ostream &os) { os << value; }
26
  /// deserialize a signal value.
27
48
  inline static T cast(std::istringstream &is) {
28
46
    T inst;
29
48
    is >> inst;
30

16
    if (is.fail()) {
31
      throw ExceptionSignal(ExceptionSignal::GENERIC,
32

5
                            "failed to serialize " + is.str());
33
    }
34
11
    return inst;
35
  }
36
  /// write a signal value to log file
37
2004
  inline static void trace(const T &value, std::ostream &os) { os << value; }
38
};
39
40
/// Inherit from this class if tracing is not implemented for a given type.
41
template <typename T>
42
struct signal_io_unimplemented {
43
  inline static void disp(const T &, std::ostream &) {
44
    throw std::logic_error("this disp is not implemented.");
45
  }
46
  inline static T cast(std::istringstream &) {
47
    throw std::logic_error("this cast is not implemented.");
48
  }
49
  inline static void trace(const T &, std::ostream &) {
50
    throw std::logic_error("this trace is not implemented.");
51
  }
52
};
53
54
/// Class used for I/O operations in Signal<T,Time>
55
template <typename T>
56
struct signal_io : signal_io_base<T> {};
57
58
/// Template specialization of signal_disp for Eigen objects
59
template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows,
60
          int _MaxCols>
61
struct signal_io<
62
    Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>>
63
    : signal_io_base<
64
          Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> {
65
  typedef Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
66
      matrix_type;
67
68
11
  inline static void disp(const matrix_type &value, std::ostream &os) {
69





11
    static const Eigen::IOFormat row_format(
70
        Eigen::StreamPrecision, Eigen::DontAlignCols, " ", " ", "", "", "", "");
71
11
    os << value.format(row_format);
72
11
  }
73
74
1005
  inline static void trace(const matrix_type &value, std::ostream &os) {
75





1005
    static const Eigen::IOFormat row_format(Eigen::StreamPrecision,
76
                                            Eigen::DontAlignCols, "\t", "\t",
77
                                            "", "", "", "");
78
1005
    os << value.format(row_format);
79
1005
  }
80
};
81
82
/// Template specialization of signal_io for Eigen quaternion objects
83
template <typename _Scalar, int _Options>
84
struct signal_io<Eigen::Quaternion<_Scalar, _Options>>
85
    : signal_io_base<Eigen::Quaternion<_Scalar, _Options>> {
86
  typedef Eigen::Quaternion<_Scalar, _Options> quat_type;
87
  typedef Eigen::Matrix<_Scalar, 4, 1, _Options> matrix_type;
88
89
  inline static void disp(const quat_type &value, std::ostream &os) {
90
    signal_io<matrix_type>::disp(value.coeffs(), os);
91
  }
92
93
  inline static quat_type cast(std::istringstream &is) {
94
    return quat_type(signal_io<matrix_type>::cast(is));
95
  }
96
97
  inline static void trace(const quat_type &value, std::ostream &os) {
98
    signal_io<matrix_type>::trace(value.coeffs(), os);
99
  }
100
};
101
102
/// Template specialization of signal_io for std::string.
103
/// Do not print '\n' at the end.
104
template <>
105
struct signal_io<std::string> : signal_io_base<std::string> {
106
2
  inline static std::string cast(std::istringstream &iss) { return iss.str(); }
107
};
108
109
/// Template specialization of signal_io for double
110
/// to workaround the limitations of the stream based approach.
111
///
112
/// When dealing with double: displaying a double on a stream
113
/// is *NOT* the opposite of reading a double from a stream.
114
///
115
/// In practice, it means that there is no way to read
116
/// a NaN, +inf, -inf from a stream!
117
///
118
/// To workaround this problem, parse special values manually
119
/// (the strings used are the one produces by displaying special
120
/// values on a stream).
121
template <>
122
struct signal_io<double> : signal_io_base<double> {
123
7
  inline static double cast(std::istringstream &iss) {
124
14
    std::string tmp(iss.str());
125
126
7
    if (tmp == "nan")
127
1
      return std::numeric_limits<double>::quiet_NaN();
128

6
    else if (tmp == "inf" || tmp == "+inf")
129
1
      return std::numeric_limits<double>::infinity();
130
5
    else if (tmp == "-inf")
131
1
      return -1. * std::numeric_limits<double>::infinity();
132
133
    try {
134
4
      return boost::lexical_cast<double>(tmp);
135
2
    } catch (boost::bad_lexical_cast &) {
136
2
      boost::format fmt("failed to serialize %s (to double)");
137
1
      fmt % tmp;
138

1
      throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
139
    }
140
  }
141
};
142
143
}  // end of namespace dynamicgraph.
144
145
#endif  //! DYNAMIC_GRAPH_SIGNAL_CASTER_HH