Skip to content
Snippets Groups Projects
Commit 5452c703 authored by Guilhem Saurel's avatar Guilhem Saurel
Browse files

Merge branch 'cpp11' into release/4.3.0

parents 53a7bbf8 590bb017
No related branches found
No related tags found
No related merge requests found
...@@ -74,6 +74,7 @@ SET(${PROJECT_NAME}_HEADERS ...@@ -74,6 +74,7 @@ SET(${PROJECT_NAME}_HEADERS
include/${CUSTOM_HEADER_DIR}/signal.t.cpp include/${CUSTOM_HEADER_DIR}/signal.t.cpp
include/${CUSTOM_HEADER_DIR}/time-dependency.h include/${CUSTOM_HEADER_DIR}/time-dependency.h
include/${CUSTOM_HEADER_DIR}/time-dependency.t.cpp include/${CUSTOM_HEADER_DIR}/time-dependency.t.cpp
# Kept for a brittle backward compatiblity.
include/${CUSTOM_HEADER_DIR}/signal-caster.h include/${CUSTOM_HEADER_DIR}/signal-caster.h
include/${CUSTOM_HEADER_DIR}/signal-cast-helper.h include/${CUSTOM_HEADER_DIR}/signal-cast-helper.h
include/${CUSTOM_HEADER_DIR}/all-signals.h include/${CUSTOM_HEADER_DIR}/all-signals.h
...@@ -117,8 +118,6 @@ SET(${PROJECT_NAME}_SOURCES ...@@ -117,8 +118,6 @@ SET(${PROJECT_NAME}_SOURCES
src/mt/process-list.cpp src/mt/process-list.cpp
src/signal/signal-array.cpp src/signal/signal-array.cpp
src/signal/signal-caster.cpp
src/signal/signal-cast-helper.cpp
src/command/value.cpp src/command/value.cpp
src/command/command.cpp src/command/command.cpp
......
...@@ -23,14 +23,9 @@ class OutStringStream; ...@@ -23,14 +23,9 @@ class OutStringStream;
class PluginLoader; class PluginLoader;
class PoolStorage; class PoolStorage;
class SignalCaster;
class SignalCastRegisterer;
class Tracer; class Tracer;
class TracerRealTime; class TracerRealTime;
template <typename T> class DefaultCastRegisterer;
template <typename T, typename Time> class Signal; template <typename T, typename Time> class Signal;
template <typename Time> class SignalArray; template <typename Time> class SignalArray;
......
...@@ -5,191 +5,7 @@ ...@@ -5,191 +5,7 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH #define DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
#include <map>
#include <typeinfo>
#include <vector>
#include <boost/any.hpp> #pragma warning "This file is now useless"
#include <boost/format.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <dynamic-graph/eigen-io.h>
#include "dynamic-graph/exception-signal.h"
#include "dynamic-graph/signal-caster.h"
#include <dynamic-graph/dynamic-graph-api.h>
namespace dynamicgraph {
/* --- NON GENERIC CASTER ------------------------------------------------- */
/// This class can be used to register default casts, i.e. casts
/// already supported by the object to an std::iostream through the
/// operators >> and << .
template <typename T>
class DefaultCastRegisterer : public SignalCastRegisterer {
public:
DefaultCastRegisterer()
: SignalCastRegisterer(typeid(T), disp, cast, trace) {}
static boost::any cast(std::istringstream &iss);
static void disp(const boost::any &object, std::ostream &os) {
os << boost::any_cast<T>(object) << std::endl;
}
static void trace(const boost::any &object, std::ostream &os) {
disp(object, os);
}
};
/// A default version of the caster, to serialize directly from
/// std::in.
template <typename T>
boost::any DefaultCastRegisterer<T>::cast(std::istringstream &iss) {
T inst;
iss >> inst;
if (iss.fail()) {
boost::format fmt("failed to serialize %s ");
fmt % iss.str();
throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
}
return inst;
}
/* --- GENERIC CASTER ----------------------------------------------------- */
/*!
* This class is only used to group together static functions who differ by
* a template parameter. It is never actually instanced
* (the private constructor
* makes sure of that).
* Typical use of this class is to add the caster in the dg graph:
* dynamicgraph::SignalCastRegisterer sotCastRegisterer_TYPE
* (typeid(TYPE),
* SignalCast<TYPE>::disp_,
* SignalCast<TYPE>::cast_,
* SignalCast<TYPE>::trace_);
* NMSD: I don't really understand the use of this additional class. IMHO
* (comme on dit), it should be possible to rewrite the same-spec macros
* using specialization of the template class DefaultCastRegisterer. No?
*/
template <class T> class SignalCast {
public:
static T cast(std::istringstream &) { throw 1; }
static void disp(const T &, std::ostream &) { throw 1; }
static void trace(const T &t, std::ostream &os) { disp(t, os); }
public:
// adapter functions for SignalCast
static boost::any cast_(std::istringstream &stringValue) {
return boost::any_cast<T>(cast(stringValue));
}
static void disp_(const boost::any &t, std::ostream &os) {
disp(boost::any_cast<T>(t), os);
}
static void trace_(const boost::any &t, std::ostream &os) {
trace(boost::any_cast<T>(t), os);
}
private:
SignalCast() {}
};
} // namespace dynamicgraph
/* -------------------------------------------------------------------------- */
/* --- MACROS --------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* Declaration macro: one instance of each class needs to be present in
* order for casts to be registered.
*/
#define DG_SIGNAL_CAST_DECLARATION(TYPE) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##TYPE( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
#define DG_SIGNAL_CAST_DECLARATION_NAMED(TYPE, NAME) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##NAME( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
/* Standard definition macros: the three functions can be specified
* in the macros. To define then in the cpp, just put ';' in the args.
*/
#define DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, CAST, DISP, TRACE) \
template <> class SignalCast<TYPE> { \
public: \
static TYPE cast(std::istringstream &iss) CAST \
static void disp(TYPE const &t, std::ostream &os) DISP \
static void trace(TYPE const &t, std::ostream &os) TRACE public \
: static boost::any cast_(std::istringstream &stringValue) { \
return boost::any_cast<TYPE>(cast(stringValue)); \
} \
static void disp_(const boost::any &t, std::ostream &os) { \
disp(boost::any_cast<TYPE>(t), os); \
} \
static void trace_(const boost::any &t, std::ostream &os) { \
trace(boost::any_cast<TYPE>(t), os); \
} \
}
/* Standard definition macros: the functions <cast> and <disp> have
* to be implemented in the cpp files. The function <trace> is
* implemented as a proxy on <disp>.
*/
#define DG_SIGNAL_CAST_DEFINITION_HPP(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, ;, ;, { disp(t, os); })
/* Lazy definition: <cast> and <disp> are to proxys on the standard
* std input (>>) and output (<<). The function <trace> has to be
* implemented in the cpp.
*/
#define DG_SIGNAL_CAST_DEFINITION_TRACE_HPP(TYPE, TRACE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, TRACE)
/* Lazy lazy definition: the three functions are implemented as
* proxys on std::io operation.
*/
#define DG_SIGNAL_CAST_DEFINITION(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, { disp(t, os); })
/* Lazy definition of <cast> and <disp> with implementation of
* <trace> in the cpp.
*/
#define DG_SIGNAL_CAST_DEFINITION_TRACE(TYPE) \
DG_SIGNAL_CAST_FULL_DEFINITION(TYPE, \
{ \
TYPE res; \
iss >> res; \
return res; \
}, \
{ os << t << std::endl; }, \
;)
/* Macro to add the define SignalCast in the dg graph. Typical use is:
* DG_ADD_CASTER( Matrix,matrix )
*/
#define DG_ADD_CASTER(TYPE, ID) \
::dynamicgraph::SignalCastRegisterer sotCastRegisterer_##ID( \
typeid(TYPE), SignalCast<TYPE>::disp_, SignalCast<TYPE>::cast_, \
SignalCast<TYPE>::trace_)
#endif // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH #endif // #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HELPER_HH
...@@ -5,113 +5,134 @@ ...@@ -5,113 +5,134 @@
#ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HH #ifndef DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#define DYNAMIC_GRAPH_SIGNAL_CASTER_HH #define DYNAMIC_GRAPH_SIGNAL_CASTER_HH
#include <map> #include <map>
#include <typeinfo>
#include <vector> #include <vector>
#include <boost/any.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include "dynamic-graph/exception-signal.h" #include "dynamic-graph/exception-signal.h"
#include <dynamic-graph/dynamic-graph-api.h> #include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/eigen-io.h>
namespace dynamicgraph { namespace dynamicgraph {
/// This singleton class allows serialization of a number of objects into
/// (disp) and from (cast) std i/o streams.
///
/// The transformation is done at run-time, i.e. SignalCaster
/// doesn't know about the type of objects it casts to.
///
/// It also allows registering of user-defined casts. A cast is
/// identified by the compiler. The mapping from a type to a
/// serialization function is dynamic, hence it is more complex than
/// a typical template-based compile-time resolve. So disp, cast and
/// trace are costly functions and should be used as such.
class DYNAMIC_GRAPH_DLLAPI SignalCaster {
public:
virtual ~SignalCaster();
/// Destroy the unique instance.
static void destroy();
/// Typedef of displayer functions that take an encapsulated 'any'
/// object and displays, cast, or trace it on an output stream
/// (serialization).
typedef boost::function2<void, const boost::any &, std::ostream &>
displayer_type;
typedef boost::function1<boost::any, std::istringstream &> caster_type;
typedef boost::function2<void, const boost::any &, std::ostream &>
tracer_type;
/// Get a reference to the unique object of the class.
static SignalCaster *getInstance(void);
/// Displays an object using a registered displayer function.
void disp(const boost::any &object, std::ostream &os);
/// Traces an object using a registered trace function.
void trace(const boost::any &object, std::ostream &os);
/// Casts an object using a registered cast function.
boost::any cast(const std::type_info &, std::istringstream &iss);
/// Registers a cast.
void registerCast(const std::type_info &type, displayer_type displayer,
caster_type caster, tracer_type tracer);
/// Unregister a cast.
void unregisterCast(const std::type_info &type);
/// Checks if there is a displayer registered with type_name.
bool existsCast(const std::type_info &type) const;
/// Return the list of type names registered.
std::vector<std::string> listTypenames() const;
private:
/// Container for the three cast functions.
typedef boost::tuple<displayer_type, caster_type, tracer_type>
cast_functions_type;
/// \brief Retrieve cast structure from its name.
cast_functions_type &getCast(const std::string &type_name);
/// This map associates the typename of objects and the corresponding
/// using boost::function with 'compatible' syntax
std::map<std::string, cast_functions_type> functions_;
std::map<std::string, const std::type_info *> type_info_;
private:
explicit SignalCaster();
/// Pointer to the unique instance of the class.
static SignalCaster *instance_;
};
/// The SignalCast registerer class. Can be used to automatically /// Inherit from this class if you want to keep default implementation for some
/// register a cast when instanced somewhere in a cpp file. Pass the /// functions.
/// typeid () of the type you want to register a cast to as the first template <typename T> struct signal_io_base {
/// argument. The code is provided here so the class does not need /// serialize a signal value.
/// to be exported. inline static void disp (const T &value, std::ostream &os) { os << value; }
class DYNAMIC_GRAPH_DLLAPI SignalCastRegisterer { /// deserialize a signal value.
public: inline static T cast (std::istringstream &is) {
inline SignalCastRegisterer(const std::type_info &type, T inst;
SignalCaster::displayer_type displayer, is >> inst;
SignalCaster::caster_type caster, if (is.fail()) {
SignalCaster::tracer_type tracer) { throw ExceptionSignal(ExceptionSignal::GENERIC,
SignalCaster::getInstance()->registerCast(type, displayer, caster, tracer); "failed to serialize " + is.str());
} }
return inst;
}
/// write a signal value to log file
inline static void trace(const T &value, std::ostream &os) { os << value; }
}; };
/// Global signal cast template (helper) functions /// Inherit from this class if tracing is not implemented for a given type.
/// template <typename T> struct signal_io_unimplemented {
/// Using these avoid using the typeid () operator and keeps the inline static void disp (const T &, std::ostream &) {
/// implementation details hidden. throw std::logic_error("this disp is not implemented.");
template <typename T> void signal_disp(const T &value, std::ostream &os) { }
SignalCaster::getInstance()->disp(value, os); inline static T cast (std::istringstream &) {
throw std::logic_error("this cast is not implemented.");
}
inline static void trace(const T &, std::ostream &) {
throw std::logic_error("this trace is not implemented.");
}
};
/// Class used for I/O operations in Signal<T,Time>
template <typename T> struct signal_io : signal_io_base<T> {};
/// Template specialization of signal_disp for Eigen objects
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
struct signal_io<Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > >
: signal_io_base <Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > >
{
typedef Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > matrix_type;
inline static void disp(const matrix_type &value, std::ostream &os) {
static const Eigen::IOFormat row_format (Eigen::StreamPrecision,
Eigen::DontAlignCols, " ", " ", "", "", "", "");
os << value.format(row_format);
} }
template <typename T> T signal_cast(std::istringstream &iss) { inline static void trace(const matrix_type &value, std::ostream &os) {
return boost::any_cast<T>(SignalCaster::getInstance()->cast(typeid(T), iss)); static const Eigen::IOFormat row_format (Eigen::StreamPrecision,
Eigen::DontAlignCols, "\t", "\t", "", "", "", "");
os << value.format(row_format);
}
};
/// Template specialization of signal_io for Eigen quaternion objects
template<typename _Scalar, int _Options>
struct signal_io<Eigen::Quaternion< _Scalar, _Options> >
: signal_io_base<Eigen::Quaternion< _Scalar, _Options> >
{
typedef Eigen::Quaternion< _Scalar, _Options> quat_type;
typedef Eigen::Matrix< _Scalar, 4, 1, _Options> matrix_type;
inline static void disp(const quat_type &value, std::ostream &os) {
signal_io<matrix_type>::disp(value.coeffs(), os);
} }
template <typename T> void signal_trace(const T &value, std::ostream &os) { inline static quat_type cast (std::istringstream &is) {
SignalCaster::getInstance()->trace(value, os); return quat_type(signal_io<matrix_type>::cast(is));
} }
inline static void trace(const quat_type &value, std::ostream &os) {
signal_io<matrix_type>::trace(value.coeffs(), os);
}
};
/// Template specialization of signal_io for std::string.
/// Do not print '\n' at the end.
template <> struct signal_io<std::string> : signal_io_base<std::string>
{
inline static std::string cast (std::istringstream &iss) { return iss.str(); }
};
/// Template specialization of signal_io for double
/// to workaround the limitations of the stream based approach.
///
/// When dealing with double: displaying a double on a stream
/// is *NOT* the opposite of reading a double from a stream.
///
/// In practice, it means that there is no way to read
/// a NaN, +inf, -inf from a stream!
///
/// To workaround this problem, parse special values manually
/// (the strings used are the one produces by displaying special
/// values on a stream).
template <> struct signal_io<double> : signal_io_base<double> {
inline static double cast (std::istringstream &iss) {
std::string tmp (iss.str());
if (tmp == "nan")
return std::numeric_limits<double>::quiet_NaN();
else if (tmp == "inf" || tmp == "+inf")
return std::numeric_limits<double>::infinity();
else if (tmp == "-inf")
return -1. * std::numeric_limits<double>::infinity();
try {
return boost::lexical_cast<double>(tmp);
} catch (boost::bad_lexical_cast &) {
boost::format fmt("failed to serialize %s (to double)");
fmt % tmp;
throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
}
}
};
} // end of namespace dynamicgraph. } // end of namespace dynamicgraph.
#endif //! DYNAMIC_GRAPH_SIGNAL_CASTER_HH #endif //! DYNAMIC_GRAPH_SIGNAL_CASTER_HH
...@@ -30,18 +30,18 @@ Signal<T, Time>::Signal(std::string name) ...@@ -30,18 +30,18 @@ Signal<T, Time>::Signal(std::string name)
template <class T, class Time> template <class T, class Time>
void Signal<T, Time>::set(std::istringstream &stringValue) { void Signal<T, Time>::set(std::istringstream &stringValue) {
(*this) = signal_cast<T>(stringValue); (*this) = signal_io<T>::cast(stringValue);
} }
template <class T, class Time> template <class T, class Time>
void Signal<T, Time>::get(std::ostream &os) const { void Signal<T, Time>::get(std::ostream &os) const {
signal_disp<T>(this->accessCopy(), os); signal_io<T>::disp(this->accessCopy(), os);
} }
template <class T, class Time> template <class T, class Time>
void Signal<T, Time>::trace(std::ostream &os) const { void Signal<T, Time>::trace(std::ostream &os) const {
try { try {
signal_trace<T>(this->accessCopy(), os); signal_io<T>::trace(this->accessCopy(), os);
} catch DG_RETHROW catch (...) { } catch DG_RETHROW catch (...) {
DG_THROW ExceptionSignal(ExceptionSignal::SET_IMPOSSIBLE, DG_THROW ExceptionSignal(ExceptionSignal::SET_IMPOSSIBLE,
"TRACE operation not possible with this signal. ", "TRACE operation not possible with this signal. ",
......
// -*- c++-mode -*-
// Copyright 2010 François Bleibel
// Thomas Moulard,
// Olivier Stasse,
// Nicolas Mansard
//
#include <algorithm>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lambda/bind.hpp>
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/signal-cast-helper.h>
#include <dynamic-graph/signal-caster.h>
#include <exception>
#include <sstream>
#include <string>
namespace dynamicgraph {
// Define a custom implementation of the DefaultCastRegisterer
// to workaround the limitations of the stream based approach.
// When dealing with double: displaying a double on a stream
// is *NOT* the opposite of reading a double from a stream.
//
// In practice, it means that there is no way to read
// a NaN, +inf, -inf from a stream!
//
// To workaround this problem, parse special values manually
// (the strings used are the one produces by displaying special
// values on a stream).
template <>
inline boost::any DefaultCastRegisterer<double>::cast(std::istringstream &iss) {
std::string tmp;
iss >> tmp;
if (tmp == "nan")
return std::numeric_limits<double>::quiet_NaN();
else if (tmp == "inf" || tmp == "+inf")
return std::numeric_limits<double>::infinity();
else if (tmp == "-inf")
return -1. * std::numeric_limits<double>::infinity();
try {
return boost::lexical_cast<double>(tmp);
} catch (boost::bad_lexical_cast &) {
boost::format fmt("failed to serialize %s (to double)");
fmt % tmp;
throw ExceptionSignal(ExceptionSignal::GENERIC, fmt.str());
}
}
// for std::string, do not check failure. If input stream contains an
// empty string, iss.fail() returns true and an exception is thrown
template <>
inline boost::any
DefaultCastRegisterer<std::string>::cast(std::istringstream &iss) {
std::string inst(iss.str());
return inst;
}
// for std::string, do not add std::endl at the end of the stream.
template <>
inline void DefaultCastRegisterer<std::string>::disp(const boost::any &object,
std::ostream &os) {
os << boost::any_cast<std::string>(object);
}
/// Registers useful casts
namespace {
DefaultCastRegisterer<double> double_reg;
DefaultCastRegisterer<int> int_reg;
DefaultCastRegisterer<unsigned int> uint_reg;
DefaultCastRegisterer<bool> bool_reg;
DefaultCastRegisterer<dynamicgraph::Vector> vectorCastRegisterer;
DefaultCastRegisterer<dynamicgraph::Matrix> matrixCastRegisterer;
DefaultCastRegisterer<boost::posix_time::ptime> ptimeCastRegisterer;
DefaultCastRegisterer<std::string> stringCastRegisterer;
} // end of anonymous namespace.
} // namespace dynamicgraph
// -*- c++-mode -*-
// Copyright 2010 François Bleibel
// Thomas Moulard,
// Olivier Stasse
//
#include <algorithm>
#include <boost/lambda/bind.hpp>
#include <dynamic-graph/dynamic-graph-api.h>
#include <dynamic-graph/exception-signal.h>
#include <dynamic-graph/signal-caster.h>
#include <exception>
#include <sstream>
#include <string>
#include <dynamic-graph/linear-algebra.h>
namespace dynamicgraph {
SignalCaster::SignalCaster() {}
SignalCaster::~SignalCaster() {}
void SignalCaster::destroy() {
delete instance_;
instance_ = 0;
}
void SignalCaster::registerCast(const std::type_info &type,
SignalCaster::displayer_type displayer,
SignalCaster::caster_type caster,
SignalCaster::tracer_type tracer) {
if (existsCast(type)) {
// If type name has already been registered for same type, do not throw.
if (type_info_[type.name()] != &type) {
std::string typeName(type.name());
std::ostringstream os;
os << "cast already registered for typename " << typeName << "\n"
<< "and types differ: " << &type << " != " << type_info_[type.name()]
<< ".\n"
<< "A possible reason is that the dynamic"
<< " library defining this type\n"
<< "has been loaded several times, defining different symbols"
<< " for the same type.";
throw ExceptionSignal(ExceptionSignal::GENERIC, os.str());
}
}
functions_[type.name()] = cast_functions_type(displayer, caster, tracer);
type_info_[type.name()] = &type;
}
void SignalCaster::unregisterCast(const std::type_info &type) {
size_t n = functions_.erase(type.name());
if (0 == n) // erase did not find element
// TODO: throw Cast not registered exception
throw ExceptionSignal(ExceptionSignal::GENERIC);
}
bool SignalCaster::existsCast(const std::type_info &type) const {
return functions_.find(type.name()) != functions_.end();
}
SignalCaster::cast_functions_type &
SignalCaster::getCast(const std::string &type_name) {
std::map<std::string, cast_functions_type>::iterator it =
functions_.find(type_name);
if (it == functions_.end())
// TODO: throw "cast not registered" exception
throw ExceptionSignal(ExceptionSignal::BAD_CAST, "Cast not registered");
return it->second;
}
void SignalCaster::disp(const boost::any &object, std::ostream &os) {
getCast(object.type().name()).get<0>()(object, os);
}
void SignalCaster::trace(const boost::any &object, std::ostream &os) {
getCast(object.type().name()).get<2>()(object, os);
}
std::vector<std::string> SignalCaster::listTypenames() const {
std::vector<std::string> typeList;
for (std::map<std::string, cast_functions_type>::const_iterator iter =
functions_.begin();
iter != functions_.end(); ++iter)
typeList.push_back(iter->first);
return typeList;
}
boost::any SignalCaster::cast(const std::type_info &type,
std::istringstream &iss) {
return getCast(type.name()).get<1>()(iss);
}
/// Singleton on the library-wide instance of SignalCaster
SignalCaster *SignalCaster::getInstance(void) {
if (instance_ == 0) {
instance_ = new SignalCaster;
}
return instance_;
}
SignalCaster *SignalCaster::instance_ = 0;
} // namespace dynamicgraph
...@@ -112,5 +112,5 @@ BOOST_AUTO_TEST_CASE(test_tracer) { ...@@ -112,5 +112,5 @@ BOOST_AUTO_TEST_CASE(test_tracer) {
"TracerRealTime my-tracer [mode=play] : \n" "TracerRealTime my-tracer [mode=play] : \n"
" - Dep list: \n" " - Dep list: \n"
" -> MyEntity(my-entity)::input(double)::out_double (in output)" " -> MyEntity(my-entity)::input(double)::out_double (in output)"
" [9Ko/16Ko] \n")); " [8Ko/16Ko] \n"));
} }
...@@ -25,6 +25,7 @@ struct MyEntity : public dynamicgraph::Entity { ...@@ -25,6 +25,7 @@ struct MyEntity : public dynamicgraph::Entity {
dynamicgraph::Signal<double, int> m_sigdSIN; dynamicgraph::Signal<double, int> m_sigdSIN;
dynamicgraph::SignalTimeDependent<double, int> m_sigdTimeDepSOUT; dynamicgraph::SignalTimeDependent<double, int> m_sigdTimeDepSOUT;
dynamicgraph::SignalTimeDependent<Vector, int> m_sigVTimeDepSOUT;
dynamicgraph::SignalTimeDependent<double, int> m_sigdTwoTimeDepSOUT; dynamicgraph::SignalTimeDependent<double, int> m_sigdTwoTimeDepSOUT;
explicit MyEntity(const std::string &name) explicit MyEntity(const std::string &name)
...@@ -33,12 +34,15 @@ struct MyEntity : public dynamicgraph::Entity { ...@@ -33,12 +34,15 @@ struct MyEntity : public dynamicgraph::Entity {
m_sigdTimeDepSOUT(boost::bind(&MyEntity::update, this, _1, _2), m_sigdTimeDepSOUT(boost::bind(&MyEntity::update, this, _1, _2),
m_sigdSIN, m_sigdSIN,
"MyEntity(" + name + ")::input(double)::out_double"), "MyEntity(" + name + ")::input(double)::out_double"),
m_sigVTimeDepSOUT(boost::bind(&MyEntity::updateVector, this, _1, _2),
m_sigdSIN,
"MyEntity(" + name + ")::input(vector)::out_vector"),
m_sigdTwoTimeDepSOUT( m_sigdTwoTimeDepSOUT(
boost::bind(&MyEntity::update, this, _1, _2), m_sigdSIN, boost::bind(&MyEntity::update, this, _1, _2), m_sigdSIN,
"MyEntity(" + name + ")::input(double)::out2double") "MyEntity(" + name + ")::input(double)::out2double")
{ {
signalRegistration(m_sigdSIN << m_sigdTimeDepSOUT << m_sigdTwoTimeDepSOUT); signalRegistration(m_sigdSIN << m_sigdTimeDepSOUT << m_sigVTimeDepSOUT << m_sigdTwoTimeDepSOUT);
} }
virtual void display(std::ostream &os) const { virtual void display(std::ostream &os) const {
...@@ -52,11 +56,20 @@ struct MyEntity : public dynamicgraph::Entity { ...@@ -52,11 +56,20 @@ struct MyEntity : public dynamicgraph::Entity {
res = aDouble; res = aDouble;
return res; return res;
} }
Vector &updateVector(Vector &res, const int &inTime) {
const double &aDouble = m_sigdSIN(inTime);
res.resize(2);
res << aDouble, 2*aDouble;
return res;
}
}; };
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(MyEntity, "MyEntity"); DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(MyEntity, "MyEntity");
} // namespace dynamicgraph } // namespace dynamicgraph
BOOST_AUTO_TEST_CASE(test_tracer) { BOOST_AUTO_TEST_CASE(test_tracer) {
using dynamicgraph::Vector;
// Creates a tracer. // Creates a tracer.
dynamicgraph::Tracer &atracer = *dynamic_cast<dynamicgraph::Tracer *>( dynamicgraph::Tracer &atracer = *dynamic_cast<dynamicgraph::Tracer *>(
dynamicgraph::FactoryStorage::getInstance()->newEntity("Tracer", dynamicgraph::FactoryStorage::getInstance()->newEntity("Tracer",
...@@ -75,6 +88,8 @@ BOOST_AUTO_TEST_CASE(test_tracer) { ...@@ -75,6 +88,8 @@ BOOST_AUTO_TEST_CASE(test_tracer) {
/// Add trace by name /// Add trace by name
atracer.addSignalToTraceByName("my-entity.out_double", "output"); atracer.addSignalToTraceByName("my-entity.out_double", "output");
/// Add trace by name
atracer.addSignalToTraceByName("my-entity.out_vector", "output-vector");
dynamicgraph::SignalBase<int> &aSignal = entity.getSignal("out2double"); dynamicgraph::SignalBase<int> &aSignal = entity.getSignal("out2double");
...@@ -82,6 +97,10 @@ BOOST_AUTO_TEST_CASE(test_tracer) { ...@@ -82,6 +97,10 @@ BOOST_AUTO_TEST_CASE(test_tracer) {
*(dynamic_cast<dynamicgraph::Signal<double, int> *>( *(dynamic_cast<dynamicgraph::Signal<double, int> *>(
&entity.getSignal("in_double"))); &entity.getSignal("in_double")));
dynamicgraph::Signal<Vector, int> &aSignalVector =
*(dynamic_cast<dynamicgraph::Signal<Vector, int> *>(
&entity.getSignal("out_vector")));
/// Add trace by signal object /// Add trace by signal object
atracer.addSignalToTrace(aSignal, "output2"); atracer.addSignalToTrace(aSignal, "output2");
...@@ -91,7 +110,10 @@ BOOST_AUTO_TEST_CASE(test_tracer) { ...@@ -91,7 +110,10 @@ BOOST_AUTO_TEST_CASE(test_tracer) {
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
aSignal.setTime(i); aSignal.setTime(i);
aSignalInt.access(i);
aSignalInt.setTime(i); aSignalInt.setTime(i);
aSignalVector.recompute(i);
aSignalVector.setTime(i);
atracer.recordTrigger(i, i); atracer.recordTrigger(i, i);
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include <dynamic-graph/debug.h> #include <dynamic-graph/debug.h>
#include <dynamic-graph/factory.h> #include <dynamic-graph/factory.h>
#include <dynamic-graph/signal-array.h> #include <dynamic-graph/signal-array.h>
#include <dynamic-graph/signal-cast-helper.h> #include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/tracer.h> #include <dynamic-graph/tracer.h>
#include <assert.h> #include <assert.h>
...@@ -140,96 +140,35 @@ BOOST_AUTO_TEST_CASE(test_base) { ...@@ -140,96 +140,35 @@ BOOST_AUTO_TEST_CASE(test_base) {
} }
BOOST_AUTO_TEST_CASE(test_cast_helper) { BOOST_AUTO_TEST_CASE(test_cast_helper) {
DefaultCastRegisterer<int> defaultCR;
std::istringstream iss; std::istringstream iss;
iss.str("1"); iss.str("1");
defaultCR.cast(iss); signal_io<int>::cast(iss);
bool res = false; {
try {
std::istringstream iss_fail; std::istringstream iss_fail;
iss.str("test"); iss.str("test");
defaultCR.cast(iss_fail); BOOST_CHECK_THROW(signal_io<int>::cast(iss_fail), ExceptionSignal);
} catch (ExceptionSignal &e) {
// Take int, not string
res = true;
} }
BOOST_CHECK(res);
/// Test cast register with Vector /// Test cast register with Vector
output_test_stream output; output_test_stream output;
dynamicgraph::Vector avec; dynamicgraph::Vector avec;
DefaultCastRegisterer<dynamicgraph::Vector> defaultVR;
avec.resize(4); avec.resize(4);
avec[0] = 1.0; avec[0] = 1.0;
avec[1] = 2.0; avec[1] = 2.0;
avec[2] = 3.0; avec[2] = 3.0;
avec[3] = 4.0; avec[3] = 4.0;
res = true; BOOST_CHECK_NO_THROW(signal_io<Vector>::trace(avec, output));
try {
defaultVR.trace(avec, output);
} catch (ExceptionSignal &e) {
/// Exception in case of wrong cast.
/// This should not happen.
res = false;
}
BOOST_CHECK(res);
/// Test cast register with Matrix /// Test cast register with Matrix
dynamicgraph::Matrix amatrix; dynamicgraph::Matrix amatrix;
DefaultCastRegisterer<dynamicgraph::Matrix> defaultMR;
amatrix.resize(2, 2); amatrix.resize(2, 2);
amatrix(0, 0) = 0.0; amatrix(0, 0) = 0.0;
amatrix(0, 1) = 1.0; amatrix(0, 1) = 1.0;
amatrix(1, 0) = 2.0; amatrix(1, 0) = 2.0;
amatrix(1, 1) = 3.0; amatrix(1, 1) = 3.0;
res = true; BOOST_CHECK_NO_THROW(signal_io<Matrix>::trace(amatrix, output));
try {
defaultMR.trace(amatrix, output);
} catch (ExceptionSignal &e) {
/// Exception in case of wrong cast.
/// This should happen
res = false;
}
BOOST_CHECK(res);
std::istringstream aiss("test"); std::istringstream aiss("test");
DefaultCastRegisterer<std::string> defaultSR; signal_io<std::string>::cast(aiss);
boost::any aTest = defaultSR.cast(aiss);
}
BOOST_AUTO_TEST_CASE(signal_caster_basics) {
/// Get the singleton on registered types.
SignalCaster *asig_caster = SignalCaster::getInstance();
/// List the registered types.
std::vector<std::string> amap = asig_caster->listTypenames();
for (std::vector<std::string>::iterator it = amap.begin(); it != amap.end();
++it)
std::cout << "signal_caster:listTypename: " << *it << std::endl;
/// Unregister a type
asig_caster->unregisterCast(typeid(double));
/// Unregister the type a second time to generate exception
bool res = false;
try {
asig_caster->unregisterCast(typeid(double));
} catch (ExceptionSignal &aes) {
res = (aes.getCode() == ExceptionSignal::GENERIC);
}
BOOST_CHECK(res);
/// Get the type cast to generate exception
res = false;
double ad = 2.0;
output_test_stream output;
try {
asig_caster->disp(ad, output);
} catch (ExceptionSignal &aes) {
res = (aes.getCode() == ExceptionSignal::BAD_CAST);
}
BOOST_CHECK(res);
asig_caster->destroy();
BOOST_CHECK(true);
} }
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include <dynamic-graph/factory.h> #include <dynamic-graph/factory.h>
#include <dynamic-graph/linear-algebra.h> #include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/pool.h> #include <dynamic-graph/pool.h>
#include <dynamic-graph/signal-cast-helper.h>
#include <dynamic-graph/signal-caster.h>
#include <dynamic-graph/signal.h> #include <dynamic-graph/signal.h>
#include "signal-cast-registerer-libA.hh" #include "signal-cast-registerer-libA.hh"
...@@ -31,67 +29,6 @@ using boost::test_tools::output_test_stream; ...@@ -31,67 +29,6 @@ using boost::test_tools::output_test_stream;
typedef Eigen::VectorXd Vector; typedef Eigen::VectorXd Vector;
typedef Eigen::MatrixXd Matrix; typedef Eigen::MatrixXd Matrix;
struct EigenCastRegisterer_V : public dynamicgraph::SignalCastRegisterer {
typedef Vector bnuVector;
EigenCastRegisterer_V()
: SignalCastRegisterer(typeid(bnuVector), dispVector, castVector,
traceVector) {}
static boost::any castVector(std::istringstream &iss) {
bnuVector res;
iss >> res;
return res;
}
static void dispVector(const boost::any &object, std::ostream &os) {
const bnuVector &v = boost::any_cast<bnuVector>(object);
os << "[ ";
for (int i = 0; i < v.size(); ++i)
os << v(i) << " ";
os << " ];" << std::endl;
}
static void traceVector(const boost::any &object, std::ostream &os) {
const bnuVector &v = boost::any_cast<bnuVector>(object);
for (int i = 0; i < v.size(); ++i)
os << v(i) << " ";
os << std::endl;
}
};
template <typename Derived>
struct EigenCastRegisterer_M : public dynamicgraph::SignalCastRegisterer {
typedef Matrix bnuMatrix;
EigenCastRegisterer_M()
: SignalCastRegisterer(typeid(bnuMatrix), dispMatrix, castMatrix,
traceMatrix) {}
static boost::any castMatrix(std::istringstream &iss) {
bnuMatrix res;
iss >> res;
return res;
}
static void dispMatrix(const boost::any &object, std::ostream &os) {
const bnuMatrix &m = boost::any_cast<bnuMatrix>(object);
os << m << std::endl;
}
static void traceMatrix(const boost::any &object, std::ostream &os) {
const bnuMatrix &m = boost::any_cast<bnuMatrix>(object);
os << m << std::endl;
}
};
EigenCastRegisterer_V myVectorCast;
EigenCastRegisterer_M<int> myMatrixCast;
// Define a new cast with a type that supports streaming operators to
// and from it (this could be automated with macros).
dynamicgraph::DefaultCastRegisterer<bool> myBooleanCast;
// Check standard double cast registerer. // Check standard double cast registerer.
BOOST_AUTO_TEST_CASE(standard_double_registerer) { BOOST_AUTO_TEST_CASE(standard_double_registerer) {
dynamicgraph::Signal<double, int> mySignal("out"); dynamicgraph::Signal<double, int> mySignal("out");
...@@ -99,15 +36,15 @@ BOOST_AUTO_TEST_CASE(standard_double_registerer) { ...@@ -99,15 +36,15 @@ BOOST_AUTO_TEST_CASE(standard_double_registerer) {
typedef std::pair<std::string, std::string> test_t; typedef std::pair<std::string, std::string> test_t;
std::vector<test_t> values; std::vector<test_t> values;
values.push_back(std::make_pair("42.0", "42\n")); values.push_back(std::make_pair("42.0", "42"));
values.push_back(std::make_pair("42.5", "42.5\n")); values.push_back(std::make_pair("42.5", "42.5"));
values.push_back(std::make_pair("-12.", "-12\n")); values.push_back(std::make_pair("-12.", "-12"));
// Double special values. // Double special values.
// FIXME: these tests are failing :( // FIXME: these tests are failing :(
values.push_back(std::make_pair("inf", "inf\n")); values.push_back(std::make_pair("inf", "inf"));
values.push_back(std::make_pair("-inf", "-inf\n")); values.push_back(std::make_pair("-inf", "-inf"));
values.push_back(std::make_pair("nan", "nan\n")); values.push_back(std::make_pair("nan", "nan"));
BOOST_FOREACH (const test_t &test, values) { BOOST_FOREACH (const test_t &test, values) {
// Set // Set
...@@ -118,14 +55,14 @@ BOOST_AUTO_TEST_CASE(standard_double_registerer) { ...@@ -118,14 +55,14 @@ BOOST_AUTO_TEST_CASE(standard_double_registerer) {
{ {
output_test_stream output; output_test_stream output;
mySignal.get(output); mySignal.get(output);
BOOST_CHECK(output.is_equal(test.second)); BOOST_CHECK_EQUAL(output.str(), test.second);
} }
// Trace // Trace
{ {
output_test_stream output; output_test_stream output;
mySignal.trace(output); mySignal.trace(output);
BOOST_CHECK(output.is_equal(test.second)); BOOST_CHECK_EQUAL(output.str(), test.second);
} }
} }
...@@ -159,7 +96,7 @@ BOOST_AUTO_TEST_CASE(custom_vector_registerer) { ...@@ -159,7 +96,7 @@ BOOST_AUTO_TEST_CASE(custom_vector_registerer) {
output_test_stream output; output_test_stream output;
myVectorSignal.get(output); myVectorSignal.get(output);
boost::format fmt("[ %d %d %d %d %d ];\n"); boost::format fmt("%d %d %d %d %d");
fmt % (i == 0) % (i == 1) % (i == 2) % (i == 3) % (i == 4); fmt % (i == 0) % (i == 1) % (i == 2) % (i == 3) % (i == 4);
BOOST_CHECK(output.is_equal(fmt.str())); BOOST_CHECK(output.is_equal(fmt.str()));
...@@ -204,7 +141,7 @@ BOOST_AUTO_TEST_CASE(custom_vector_registerer) { ...@@ -204,7 +141,7 @@ BOOST_AUTO_TEST_CASE(custom_vector_registerer) {
std::istringstream ss("[5](1, "); std::istringstream ss("[5](1, ");
myVectorSignal.set(ss); myVectorSignal.set(ss);
} catch (ExceptionSignal &e) { } catch (ExceptionSignal &e) {
BOOST_ERROR("Can't happened"); std::cout << "Test passed : ss[4] != \" \" || \",\"";
} }
// ss[-1] != ")" // ss[-1] != ")"
...@@ -296,7 +233,7 @@ BOOST_AUTO_TEST_CASE(custom_matrix_registerer) { ...@@ -296,7 +233,7 @@ BOOST_AUTO_TEST_CASE(custom_matrix_registerer) {
std::istringstream ss("[5,3]((1,"); std::istringstream ss("[5,3]((1,");
myMatrixSignal.set(ss); myMatrixSignal.set(ss);
} catch (ExceptionSignal &e) { } catch (ExceptionSignal &e) {
BOOST_ERROR("Can't happened"); std::cout << "Test passed : ss[8] != \" \" || \",\"";
} }
// ss[6+n] != ")" // ss[6+n] != ")"
......
...@@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(plug_signal_string) { ...@@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(plug_signal_string) {
inSigVec.recompute(1); inSigVec.recompute(1);
output_test_stream output; output_test_stream output;
inSigVec.get(output); inSigVec.get(output);
BOOST_CHECK(output.is_equal("1\n2\n3\n4\n5\n")); BOOST_CHECK(output.is_equal("1 2 3 4 5"));
Signal<std::string, int> s("signal"); Signal<std::string, int> s("signal");
std::ostringstream os2; std::ostringstream os2;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment