GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 |
Generated by: GCOVR (Version 4.2) |