...
 
Commits (11)
...@@ -98,6 +98,7 @@ SET(${PROJECT_NAME}_HEADERS ...@@ -98,6 +98,7 @@ SET(${PROJECT_NAME}_HEADERS
include/dynamic-graph/fwd.hh include/dynamic-graph/fwd.hh
include/dynamic-graph/debug.h include/dynamic-graph/debug.h
include/dynamic-graph/real-time-logger.h include/dynamic-graph/real-time-logger.h
include/dynamic-graph/real-time-logger-def.h
include/dynamic-graph/dynamic-graph-api.h include/dynamic-graph/dynamic-graph-api.h
......
...@@ -83,12 +83,16 @@ public: ...@@ -83,12 +83,16 @@ public:
SignalMap getSignalMap() const; SignalMap getSignalMap() const;
/** \name Logger related methods */ /// \name Logger related methods
/** \{*/ /// \{
Logger &logger() { return logger_; };
Logger const &logger() const { return logger_; };
/// \brief Send messages \c msg with level \c t. /// \brief Send messages \c msg with level \c t.
/// Add string file and line to message. /// Add string file and line to message.
void sendMsg(const std::string &msg, MsgType t = MSG_TYPE_INFO, void sendMsg(const std::string &msg, MsgType t = MSG_TYPE_INFO,
const char *file = "", int line = 0); const std::string &lineId = "");
/// \brief Specify the verbosity level of the logger. /// \brief Specify the verbosity level of the logger.
void setLoggerVerbosityLevel(LoggerVerbosity lv) { logger_.setVerbosity(lv); } void setLoggerVerbosityLevel(LoggerVerbosity lv) { logger_.setVerbosity(lv); }
...@@ -110,6 +114,8 @@ public: ...@@ -110,6 +114,8 @@ public:
/// \brief Get the period of the stream period /// \brief Get the period of the stream period
double getStreamPrintPeriod() { return logger_.getStreamPrintPeriod(); } double getStreamPrintPeriod() { return logger_.getStreamPrintPeriod(); }
/// \}
protected: protected:
void addCommand(const std::string &name, command::Command *command); void addCommand(const std::string &name, command::Command *command);
......
...@@ -27,14 +27,17 @@ namespace dynamicgraph { ...@@ -27,14 +27,17 @@ namespace dynamicgraph {
/** Enum representing the different kind of messages. /** Enum representing the different kind of messages.
*/ */
enum MsgType { enum MsgType {
MSG_TYPE_DEBUG = 0, MSG_TYPE_TYPE_BITS = 1<<0 | 1<<1 | 1<<2 | 1<<3, // 15
MSG_TYPE_INFO = 1, MSG_TYPE_STREAM_BIT = 1<<4, // 16
MSG_TYPE_WARNING = 2,
MSG_TYPE_ERROR = 3, MSG_TYPE_DEBUG = 1<<3, // 1
MSG_TYPE_DEBUG_STREAM = 4, MSG_TYPE_INFO = 1<<2, // 2
MSG_TYPE_INFO_STREAM = 5, MSG_TYPE_WARNING = 1<<1, // 4
MSG_TYPE_WARNING_STREAM = 6, MSG_TYPE_ERROR = 1<<0, // 8
MSG_TYPE_ERROR_STREAM = 7 MSG_TYPE_DEBUG_STREAM = MSG_TYPE_DEBUG | MSG_TYPE_STREAM_BIT, // 17
MSG_TYPE_INFO_STREAM = MSG_TYPE_INFO | MSG_TYPE_STREAM_BIT, // 18
MSG_TYPE_WARNING_STREAM = MSG_TYPE_WARNING | MSG_TYPE_STREAM_BIT, // 20
MSG_TYPE_ERROR_STREAM = MSG_TYPE_ERROR | MSG_TYPE_STREAM_BIT // 24
}; };
} // namespace dynamicgraph } // namespace dynamicgraph
...@@ -42,25 +45,54 @@ enum MsgType { ...@@ -42,25 +45,54 @@ enum MsgType {
/* --- INCLUDE --------------------------------------------------------- */ /* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
#include "boost/assign.hpp" #include <map>
#include <dynamic-graph/linear-algebra.h> /// \todo These 3 headers should be removed.
#include <fstream> #include <fstream>
#include <iomanip> // std::setprecision #include <iomanip> // std::setprecision
#include <map>
#include <sstream> #include <sstream>
#include <boost/assign.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <dynamic-graph/deprecated.hh>
#include <dynamic-graph/linear-algebra.h>
#include <dynamic-graph/real-time-logger-def.h>
namespace dynamicgraph { namespace dynamicgraph {
//#define LOGGER_VERBOSITY_INFO_WARNING_ERROR //#define LOGGER_VERBOSITY_INFO_WARNING_ERROR
#define LOGGER_VERBOSITY_ALL #define LOGGER_VERBOSITY_ALL
#define SEND_MSG(msg, type) sendMsg(msg, type, __FILE__, __LINE__) #define SEND_MSG(msg, type) \
sendMsg(msg, type, __FILE__ ":" BOOST_PP_STRINGIZE(__LINE__))
#define SEND_DEBUG_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_DEBUG_STREAM) #define SEND_DEBUG_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_DEBUG_STREAM)
#define SEND_INFO_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_INFO_STREAM) #define SEND_INFO_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_INFO_STREAM)
#define SEND_WARNING_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_WARNING_STREAM) #define SEND_WARNING_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_WARNING_STREAM)
#define SEND_ERROR_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_ERROR_STREAM) #define SEND_ERROR_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_ERROR_STREAM)
#define _DYNAMIC_GRAPH_ENTITY_MSG(entity, type) \
(entity).logger().stream(type, __FILE__ BOOST_PP_STRINGIZE(__LINE__))
#define DYNAMIC_GRAPH_ENTITY_DEBUG(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_DEBUG)
#define DYNAMIC_GRAPH_ENTITY_INFO(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_INFO)
#define DYNAMIC_GRAPH_ENTITY_WARNING(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_WARNING)
#define DYNAMIC_GRAPH_ENTITY_ERROR(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_ERROR)
#define DYNAMIC_GRAPH_ENTITY_DEBUG_STREAM(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_DEBUG_STREAM)
#define DYNAMIC_GRAPH_ENTITY_INFO_STREAM(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_INFO_STREAM)
#define DYNAMIC_GRAPH_ENTITY_WARNING_STREAM(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_WARNING_STREAM)
#define DYNAMIC_GRAPH_ENTITY_ERROR_STREAM(entity) \
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_ERROR_STREAM)
template <typename T> template <typename T>
std::string toString(const T &v, const int precision = 3, std::string toString(const T &v, const int precision = 3,
const int width = -1) { const int width = -1) {
...@@ -111,11 +143,11 @@ std::string toString(const Eigen::MatrixBase<T> &v, const int precision = 3, ...@@ -111,11 +143,11 @@ std::string toString(const Eigen::MatrixBase<T> &v, const int precision = 3,
} }
enum LoggerVerbosity { enum LoggerVerbosity {
VERBOSITY_ALL, VERBOSITY_ALL = MSG_TYPE_DEBUG,
VERBOSITY_INFO_WARNING_ERROR, VERBOSITY_INFO_WARNING_ERROR = MSG_TYPE_INFO,
VERBOSITY_WARNING_ERROR, VERBOSITY_WARNING_ERROR = MSG_TYPE_WARNING,
VERBOSITY_ERROR, VERBOSITY_ERROR = MSG_TYPE_ERROR,
VERBOSITY_NONE VERBOSITY_NONE = 0
}; };
/// \ingroup debug /// \ingroup debug
...@@ -139,12 +171,20 @@ enum LoggerVerbosity { ...@@ -139,12 +171,20 @@ enum LoggerVerbosity {
/// VERBOSITY_WARNING_ERROR; /// VERBOSITY_WARNING_ERROR;
/// entity.setLoggerVerbosityLevel(aLoggerVerbosityLevel); /// entity.setLoggerVerbosityLevel(aLoggerVerbosityLevel);
/// ... /// ...
/// std::string aMsg=aBaseMsg+" WARNING"; /// // using macros
/// entity.sendMsg(aMsg,dynamicgraph::MSG_TYPE_WARNING, __FILE__,__LINE__); /// DYNAMIC_GRAPH_ENTITY_WARNING(entity) << "your message\n";
/// ///
/// \endcode /// // or the equivalent code without macros:
/// // Please use '\n' instead of std::endl and flushing will have no effect
/// entity.logger.stream(dynamicgraph::MSG_TYPE_WARNING,
/// __FILE__ BOOST_PP_STRINGIZE(__LINE__))
/// << your message << '\n';
/// ///
/// \endcode
/// ///
/// \todo remove m_timeSample and streamPrintPeriod to rather use a simple
/// integer counting the number of calls. This will achieve exactly the
/// same behaviour without rouding numerical errors.
class Logger { class Logger {
public: public:
/** Constructor */ /** Constructor */
...@@ -157,13 +197,39 @@ public: ...@@ -157,13 +197,39 @@ public:
* to decrement the internal Logger's counter. */ * to decrement the internal Logger's counter. */
void countdown(); void countdown();
/** Get an output stream independently of the debug level.
*/
RTLoggerStream stream() {
return ::dynamicgraph::RealTimeLogger::instance().front();
}
/** Print the specified message on standard output if the verbosity level /** Print the specified message on standard output if the verbosity level
* allows it. The file name and the line number are used to identify * allows it. The lineId is used to identify the point where sendMsg is
* the point where sendMsg is called so that streaming messages are * called so that streaming messages are printed only every streamPrintPeriod
* printed only every streamPrintPeriod iterations. * iterations.
* \param lineId typically __FILE__ ":" BOOST_PP_STRINGIZE(__LINE__)
*/
RTLoggerStream stream(MsgType type, const std::string& lineId = "") {
RealTimeLogger &rtlogger = ::dynamicgraph::RealTimeLogger::instance();
if (acceptMsg(type, lineId))
return rtlogger.front();
return rtlogger.emptyStream();
}
/** \deprecated instead, use
* \code
* stream(type, lineId) << msg << '\n';
* \endcode
*/ */
void sendMsg(std::string msg, MsgType type, const char *file = "", void sendMsg(std::string msg, MsgType type, const std::string& lineId = "");
int line = 0);
/** \deprecated instead, use
* \code
* stream(type, lineId) << msg << '\n';
* \endcode
*/
void sendMsg(std::string msg, MsgType type, const std::string& file,
int line) DYNAMIC_GRAPH_DEPRECATED;
/** Set the sampling time at which the method countdown() /** Set the sampling time at which the method countdown()
* is going to be called. */ * is going to be called. */
...@@ -193,30 +259,33 @@ protected: ...@@ -193,30 +259,33 @@ protected:
double m_printCountdown; double m_printCountdown;
/// every time this is < 0 (i.e. every _streamPrintPeriod sec) print stuff /// every time this is < 0 (i.e. every _streamPrintPeriod sec) print stuff
typedef std::map<std::string, double> StreamCounterMap_t;
/** Pointer to the dynamic structure which holds /** Pointer to the dynamic structure which holds
the collection of streaming messages */ the collection of streaming messages */
std::map<std::string, double> m_stream_msg_counters; StreamCounterMap_t m_stream_msg_counters;
bool isStreamMsg(MsgType m) { inline bool isStreamMsg(MsgType m) {
return m == MSG_TYPE_ERROR_STREAM || m == MSG_TYPE_DEBUG_STREAM || return (m & MSG_TYPE_STREAM_BIT);
m == MSG_TYPE_INFO_STREAM || m == MSG_TYPE_WARNING_STREAM;
} }
bool isDebugMsg(MsgType m) { /** Check whether a message of type \m and from \c lineId should be accepted.
return m == MSG_TYPE_DEBUG_STREAM || m == MSG_TYPE_DEBUG; * \note If \c is a stream type, the internal counter associated to \c lineId
} * is updated.
*/
bool isInfoMsg(MsgType m) { bool acceptMsg (MsgType m, const std::string& lineId) {
return m == MSG_TYPE_INFO_STREAM || m == MSG_TYPE_INFO; // If more verbose than the current verbosity level
} if ((m & MSG_TYPE_TYPE_BITS) > m_lv)
return false;
bool isWarningMsg(MsgType m) {
return m == MSG_TYPE_WARNING_STREAM || m == MSG_TYPE_WARNING; // if print is allowed by current verbosity level
if (isStreamMsg(m)) return checkStreamPeriod(lineId);
return true;
} }
bool isErrorMsg(MsgType m) { /** Check whether a message from \c lineId should be accepted.
return m == MSG_TYPE_ERROR_STREAM || m == MSG_TYPE_ERROR; * \note The internal counter associated to \c lineId is updated.
} */
bool checkStreamPeriod (const std::string& lineId);
}; };
} // namespace dynamicgraph } // namespace dynamicgraph
......
// -*- mode: c++ -*-
// Copyright 2018, Joseph Mirabel LAAS-CNRS
//
#ifndef DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
#define DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
#include <sstream>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <dynamic-graph/config.hh>
namespace dynamicgraph {
/// \ingroup debug
///
/// \brief Stream for the real-time logger.
///
/// You should inherit from this class in order to redirect the logs where you
/// want.
/// \sa LoggerIOStream
class LoggerStream {
public:
virtual void write(const char *c) = 0;
};
/// Write to an ostream object.
///
/// The easieast is to use the macro \ref dgADD_OSTREAM_TO_RTLOG(ostr) where
/// `ostr` can be `std::cout` or an std::ofstream...
class LoggerIOStream : public LoggerStream {
public:
LoggerIOStream(std::ostream &os) : os_(os) {}
virtual void write(const char *c) { os_ << c; }
private:
std::ostream &os_;
};
typedef boost::shared_ptr<LoggerStream> LoggerStreamPtr_t;
class RealTimeLogger;
/// \cond DEVEL
/// \brief write entries to intenal buffer.
///
/// The entry starts when an instance is created and ends when is is deleted.
/// This class is only used by RealTimeLogger.
class RTLoggerStream {
public:
inline RTLoggerStream(RealTimeLogger *logger, std::ostream &os)
: ok_(logger != NULL), logger_(logger), os_(os) {}
template <typename T> inline RTLoggerStream &operator<<(T t) {
if (ok_)
os_ << t;
return *this;
}
inline RTLoggerStream &operator<<(std::ostream &(*pf)(std::ostream &)) {
if (ok_)
os_ << pf;
return *this;
}
inline ~RTLoggerStream();
inline bool isNull() { return !ok_; }
private:
const bool ok_;
RealTimeLogger *logger_;
std::ostream &os_;
};
/// \endcond DEVEL
/// \ingroup debug
///
/// \brief Main class of the real-time logger.
///
/// It is intended to be used like this:
/// \code
/// #define ENABLE_RT_LOG
/// #include <dynamic-graph/real-time-logger.h>
///
/// // Somewhere in the main function of your executable
/// int main (int argc, char** argv) {
/// dgADD_OSTREAM_TO_RTLOG (std::cout);
/// }
///
/// // Somewhere in your library
/// dgRTLOG() << "your message. Prefer to use \n than std::endl."
/// \endcode
///
/// \note Thread safety. This class expects to have:
/// - only one reader: the one who take the log entries and write them
/// somewhere.
/// - one writer at a time. Writing to the logs is **never** a blocking
/// operation. If the resource is busy, the log entry is discarded.
class DYNAMIC_GRAPH_DLLAPI RealTimeLogger {
public:
static RealTimeLogger &instance();
static void destroy();
/// \todo add an argument to preallocate the internal string
/// to a given size.
RealTimeLogger(const std::size_t &bufferSize);
inline void clearOutputStreams() { outputs_.clear(); }
inline void addOutputStream(const LoggerStreamPtr_t &os) {
outputs_.push_back(os);
}
/// Write next message to output.
/// It does nothing if the buffer is empty.
/// \return true if it wrote something
bool spinOnce();
/// Return an object onto which a real-time thread can write.
/// The message is considered finished when the object is destroyed.
RTLoggerStream front();
/// Return an empty stream object.
RTLoggerStream emptyStream() { return RTLoggerStream(NULL, oss_); }
inline void frontReady() {
backIdx_ = (backIdx_ + 1) % buffer_.size();
wmutex.unlock();
}
inline bool empty() const { return frontIdx_ == backIdx_; }
inline bool full() const {
return ((backIdx_ + 1) % buffer_.size()) == frontIdx_;
}
inline std::size_t size() const {
if (frontIdx_ <= backIdx_)
return backIdx_ - frontIdx_;
else
return backIdx_ + buffer_.size() - frontIdx_;
}
inline std::size_t getBufferSize() { return buffer_.size(); }
~RealTimeLogger();
private:
struct Data {
std::stringbuf buf;
};
std::vector<LoggerStreamPtr_t> outputs_;
std::vector<Data *> buffer_;
/// Index of the next value to be read.
std::size_t frontIdx_;
/// Index of the slot where to write next value
/// (does not contain valid data).
std::size_t backIdx_;
std::ostream oss_;
/// The writer mutex.
boost::mutex wmutex;
std::size_t nbDiscarded_;
struct thread;
static RealTimeLogger *instance_;
static thread *thread_;
};
RTLoggerStream::~RTLoggerStream() {
if (ok_) {
os_ << std::ends;
logger_->frontReady();
}
}
} // end of namespace dynamicgraph
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_DEF_H
...@@ -4,167 +4,6 @@ ...@@ -4,167 +4,6 @@
#ifndef DYNAMIC_GRAPH_LOGGER_REAL_TIME_H #ifndef DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
#define DYNAMIC_GRAPH_LOGGER_REAL_TIME_H #define DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
#include <sstream>
#include <vector>
#include <boost/circular_buffer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <dynamic-graph/config.hh>
#include <dynamic-graph/debug.h>
namespace dynamicgraph {
/// \ingroup debug
///
/// \brief Stream for the real-time logger.
///
/// You should inherit from this class in order to redirect the logs where you
/// want.
/// \sa LoggerIOStream
class LoggerStream {
public:
virtual void write(const char *c) = 0;
};
/// Write to an ostream object.
///
/// The easieast is to use the macro \ref dgADD_OSTREAM_TO_RTLOG(ostr) where
/// `ostr` can be `std::cout` or an std::ofstream...
class LoggerIOStream : public LoggerStream {
public:
LoggerIOStream(std::ostream &os) : os_(os) {}
virtual void write(const char *c) { os_ << c; }
private:
std::ostream &os_;
};
typedef boost::shared_ptr<LoggerStream> LoggerStreamPtr_t;
class RealTimeLogger;
/// \cond DEVEL
/// \brief write entries to intenal buffer.
///
/// The entry starts when an instance is created and ends when is is deleted.
/// This class is only used by RealTimeLogger.
class RTLoggerStream {
public:
RTLoggerStream(RealTimeLogger *logger, std::ostream &os)
: logger_(logger), os_(os) {}
template <typename T> inline RTLoggerStream &operator<<(T t) {
if (logger_ != NULL)
os_ << t;
return *this;
}
inline RTLoggerStream &operator<<(std::ostream &(*pf)(std::ostream &)) {
if (logger_ != NULL)
os_ << pf;
return *this;
}
~RTLoggerStream();
private:
RealTimeLogger *logger_;
std::ostream &os_;
};
/// \endcond DEVEL
/// \ingroup debug
///
/// \brief Main class of the real-time logger.
///
/// It is intended to be used like this:
/// \code
/// #define ENABLE_RT_LOG
/// #include <dynamic-graph/real-time-logger.h>
///
/// // Somewhere in the main function of your executable
/// int main (int argc, char** argv) {
/// dgADD_OSTREAM_TO_RTLOG (std::cout);
/// }
///
/// // Somewhere in your library
/// dgRTLOG() << "your message. Prefer to use \n than std::endl."
/// \endcode
///
/// \note Thread safety. This class expects to have:
/// - only one reader: the one who take the log entries and write them
/// somewhere.
/// - one writer at a time. Writing to the logs is **never** a blocking
/// operation. If the resource is busy, the log entry is discarded.
class DYNAMIC_GRAPH_DLLAPI RealTimeLogger {
public:
static RealTimeLogger &instance();
static void destroy();
/// \todo add an argument to preallocate the internal string
/// to a given size.
RealTimeLogger(const std::size_t &bufferSize);
inline void clearOutputStreams() { outputs_.clear(); }
inline void addOutputStream(const LoggerStreamPtr_t &os) {
outputs_.push_back(os);
}
/// Write next message to output.
/// It does nothing if the buffer is empty.
/// \return true if it wrote something
bool spinOnce();
/// Return an object onto which a real-time thread can write.
/// The message is considered finished when the object is destroyed.
RTLoggerStream front();
inline void frontReady() {
backIdx_ = (backIdx_ + 1) % buffer_.size();
wmutex.unlock();
}
inline bool empty() const { return frontIdx_ == backIdx_; }
inline bool full() const {
return ((backIdx_ + 1) % buffer_.size()) == frontIdx_;
}
inline std::size_t size() const {
if (frontIdx_ <= backIdx_)
return backIdx_ - frontIdx_;
else
return backIdx_ + buffer_.size() - frontIdx_;
}
inline std::size_t getBufferSize() { return buffer_.size(); }
~RealTimeLogger();
private:
struct Data {
std::stringbuf buf;
};
std::vector<LoggerStreamPtr_t> outputs_;
std::vector<Data *> buffer_;
/// Index of the next value to be read.
std::size_t frontIdx_;
/// Index of the slot where to write next value
/// (does not contain valid data).
std::size_t backIdx_;
std::ostream oss_;
/// The writer mutex.
boost::mutex wmutex;
std::size_t nbDiscarded_;
struct thread;
static RealTimeLogger *instance_;
static thread *thread_;
};
} // end of namespace dynamicgraph
#ifdef ENABLE_RT_LOG #ifdef ENABLE_RT_LOG
#define dgADD_OSTREAM_TO_RTLOG(ostr) \ #define dgADD_OSTREAM_TO_RTLOG(ostr) \
...@@ -182,4 +21,6 @@ private: ...@@ -182,4 +21,6 @@ private:
__null_stream() __null_stream()
#endif #endif
#include <dynamic-graph/real-time-logger-def.h>
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_H #endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
...@@ -12,10 +12,13 @@ ...@@ -12,10 +12,13 @@
#include <dynamic-graph/linear-algebra.h> #include <dynamic-graph/linear-algebra.h>
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#include <vector>
namespace dynamicgraph { namespace dynamicgraph {
namespace command { namespace command {
class Value; class Value;
typedef std::vector<Value> Values;
class DYNAMIC_GRAPH_DLLAPI EitherType { class DYNAMIC_GRAPH_DLLAPI EitherType {
public: public:
EitherType(const Value &value); EitherType(const Value &value);
...@@ -29,6 +32,7 @@ public: ...@@ -29,6 +32,7 @@ public:
operator Vector() const; operator Vector() const;
operator Eigen::MatrixXd() const; operator Eigen::MatrixXd() const;
operator Eigen::Matrix4d() const; operator Eigen::Matrix4d() const;
operator Values() const;
private: private:
const Value *value_; const Value *value_;
...@@ -47,6 +51,7 @@ public: ...@@ -47,6 +51,7 @@ public:
VECTOR, VECTOR,
MATRIX, MATRIX,
MATRIX4D, MATRIX4D,
VALUES,
NB_TYPES NB_TYPES
}; };
~Value(); ~Value();
...@@ -60,12 +65,15 @@ public: ...@@ -60,12 +65,15 @@ public:
explicit Value(const Vector &value); explicit Value(const Vector &value);
explicit Value(const Eigen::MatrixXd &value); explicit Value(const Eigen::MatrixXd &value);
explicit Value(const Eigen::Matrix4d &value); explicit Value(const Eigen::Matrix4d &value);
explicit Value(const Values &value);
/// Copy constructor /// Copy constructor
Value(const Value &value); Value(const Value &value);
// Construct an empty value (None) // Construct an empty value (None)
explicit Value(); explicit Value();
// operator assignement // operator assignement
Value operator=(const Value &value); Value operator=(const Value &value);
// Equality operator
bool operator==(const Value &other) const;
/// Return the type of the value /// Return the type of the value
Type type() const; Type type() const;
...@@ -99,6 +107,8 @@ public: ...@@ -99,6 +107,8 @@ public:
Vector vectorValue() const; Vector vectorValue() const;
Eigen::MatrixXd matrixXdValue() const; Eigen::MatrixXd matrixXdValue() const;
Eigen::Matrix4d matrix4dValue() const; Eigen::Matrix4d matrix4dValue() const;
Values valuesValue () const;
const Values &constValuesValue () const;
Type type_; Type type_;
const void *const value_; const void *const value_;
}; };
......
# Copyright 2010, Olivier Stasse, JRL, CNRS/AIST
#
####################################
### Main Library
####################################
SET(LIBRARY_NAME ${PROJECT_NAME})
# Verbosity level
IF (NOT (\"${CMAKE_VERBOSITY_LEVEL}\" STREQUAL \"\"))
ADD_DEFINITIONS(-DVP_DEBUG_MODE=${CMAKE_VERBOSITY_LEVEL} -DVP_DEBUG)
ENDIF (NOT (\"${CMAKE_VERBOSITY_LEVEL}\" STREQUAL \"\"))
# Declare boost include directories
#include_directories(${Boost_INCLUDE_DIRS})
#link_directories(${Boost_LIBRARY_DIRS})
ADD_LIBRARY(${LIBRARY_NAME}
SHARED
debug/debug.cpp
debug/real-time-logger.cpp
debug/logger.cpp
dgraph/entity.cpp
dgraph/factory.cpp
dgraph/pool.cpp
exception/exception-abstract.cpp
exception/exception-factory.cpp
exception/exception-signal.cpp
exception/exception-traces.cpp
mt/process-list.cpp
signal/signal-array.cpp
signal/signal-caster.cpp
signal/signal-cast-helper.cpp
command/value.cpp
command/command.cpp
)
# INSTALL(TARGETS ${PROJECT_NAME}
# EXPORT ${TARGETS_EXPORT_NAME}
# PUBLIC_HEADER
# INCLUDES DESTINATION include/${PROJECT_NAME}
# )
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:include>
)
SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
IF (UNIX)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${CMAKE_DL_LIBS} pthread)
ENDIF (UNIX)
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${Boost_LIBRARIES})
TARGET_LINK_LIBRARIES(${LIBRARY_NAME} Eigen3::Eigen)
#IF (UNIX AND NOT APPLE)
# TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${JRL_MAL_LDFLAGS_OTHER})
#ENDIF (UNIX AND NOT APPLE)
INSTALL(TARGETS ${LIBRARY_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
DESTINATION ${CMAKE_INSTALL_LIBDIR})
####################################
### Plugins
####################################
SET(plugins_list
traces/tracer
traces/tracer-real-time
)
SET(tracer-real-time_dependency tracer)
FOREACH(plugin_file ${plugins_list})
GET_FILENAME_COMPONENT(plugin ${plugin_file} NAME)
ADD_LIBRARY(${plugin} SHARED "${plugin_file}.cpp")
TARGET_LINK_LIBRARIES(${plugin}
${PROJECT_NAME} ${${plugin}_dependency}
${Boost_LIBRARIES})
SET_TARGET_PROPERTIES(${plugin}
PROPERTIES
PREFIX ""
)
INSTALL(TARGETS ${plugin} EXPORT ${TARGET_NAME} DESTINATION ${PLUGINDIR})
ENDFOREACH(plugin_file)
...@@ -29,6 +29,7 @@ EitherType::operator Vector() const { return value_->vectorValue(); } ...@@ -29,6 +29,7 @@ EitherType::operator Vector() const { return value_->vectorValue(); }
EitherType::operator Eigen::MatrixXd() const { return value_->matrixXdValue(); } EitherType::operator Eigen::MatrixXd() const { return value_->matrixXdValue(); }
EitherType::operator Eigen::Matrix4d() const { return value_->matrix4dValue(); } EitherType::operator Eigen::Matrix4d() const { return value_->matrix4dValue(); }
EitherType::operator Values() const { return value_->valuesValue(); }
void Value::deleteValue() { void Value::deleteValue() {
switch (type_) { switch (type_) {
...@@ -59,6 +60,9 @@ void Value::deleteValue() { ...@@ -59,6 +60,9 @@ void Value::deleteValue() {
case MATRIX4D: case MATRIX4D:
delete (const Eigen::Matrix4d *)value_; delete (const Eigen::Matrix4d *)value_;
break; break;
case VALUES:
delete (const Values *)value_;
break;
default:; default:;
} }
} }
...@@ -78,6 +82,8 @@ Value::Value(const Eigen::MatrixXd &value) ...@@ -78,6 +82,8 @@ Value::Value(const Eigen::MatrixXd &value)
: type_(MATRIX), value_(new Eigen::MatrixXd(value)) {} : type_(MATRIX), value_(new Eigen::MatrixXd(value)) {}
Value::Value(const Eigen::Matrix4d &value) Value::Value(const Eigen::Matrix4d &value)
: type_(MATRIX4D), value_(new Eigen::Matrix4d(value)) {} : type_(MATRIX4D), value_(new Eigen::Matrix4d(value)) {}
Value::Value(const Values &value)
: type_(VALUES), value_(new Values(value)) {}
Value::Value(const Value &value) Value::Value(const Value &value)
: type_(value.type_), value_(copyValue(value)) {} : type_(value.type_), value_(copyValue(value)) {}
...@@ -116,6 +122,9 @@ void *copyValue(const Value &value) { ...@@ -116,6 +122,9 @@ void *copyValue(const Value &value) {
case Value::MATRIX4D: case Value::MATRIX4D:
copy = new Eigen::Matrix4d(value.matrix4dValue()); copy = new Eigen::Matrix4d(value.matrix4dValue());
break; break;
case Value::VALUES:
copy = new Values(value.valuesValue());
break;
default: default:
abort(); abort();
} }
...@@ -135,6 +144,25 @@ Value Value::operator=(const Value &value) { ...@@ -135,6 +144,25 @@ Value Value::operator=(const Value &value) {
return *this; return *this;
} }
bool Value::operator==(const Value &other) const {
if (type_ != other.type_) return false;
switch (type_) {
case Value::BOOL: return boolValue() == other.boolValue();
case Value::UNSIGNED: return unsignedValue() == other.unsignedValue();
case Value::INT: return intValue() == other.intValue();
case Value::DOUBLE: return doubleValue() == other.doubleValue();
case Value::FLOAT: return floatValue() == other.floatValue();
case Value::STRING: return stringValue() == other.stringValue();
case Value::VECTOR: return vectorValue() == other.vectorValue();
case Value::MATRIX: return matrixXdValue() == other.matrixXdValue();
case Value::MATRIX4D: return matrix4dValue() == other.matrix4dValue();
case Value::VALUES: return constValuesValue() == other.constValuesValue();
case Value::NONE: break;
default: break;
}
return false;
}
const EitherType Value::value() const { return EitherType(*this); } const EitherType Value::value() const { return EitherType(*this); }
Value::Type Value::type() const { return type_; } Value::Type Value::type() const { return type_; }
...@@ -200,6 +228,20 @@ Eigen::Matrix4d Value::matrix4dValue() const { ...@@ -200,6 +228,20 @@ Eigen::Matrix4d Value::matrix4dValue() const {
"value is not a Eigen matrix4d"); "value is not a Eigen matrix4d");
} }
Values Value::valuesValue() const {
if (type_ == VALUES)
return *((const Values *)value_);
throw ExceptionAbstract(ExceptionAbstract::TOOLS,
"value is not a vector of Value");
}
const Values &Value::constValuesValue() const {
if (type_ == VALUES)
return *((const Values *)value_);
throw ExceptionAbstract(ExceptionAbstract::TOOLS,
"value is not a vector of Value");
}
std::string Value::typeName(Type type) { std::string Value::typeName(Type type) {
switch (type) { switch (type) {
case BOOL: case BOOL:
...@@ -220,6 +262,8 @@ std::string Value::typeName(Type type) { ...@@ -220,6 +262,8 @@ std::string Value::typeName(Type type) {
return std::string("matrixXd"); return std::string("matrixXd");
case MATRIX4D: case MATRIX4D:
return std::string("matrix4d"); return std::string("matrix4d");
case VALUES:
return std::string("values");
default: default:
return std::string("unknown"); return std::string("unknown");
} }
...@@ -255,6 +299,15 @@ std::ostream &operator<<(std::ostream &os, const Value &value) { ...@@ -255,6 +299,15 @@ std::ostream &operator<<(std::ostream &os, const Value &value) {
case Value::MATRIX4D: case Value::MATRIX4D:
os << value.matrix4dValue(); os << value.matrix4dValue();
break; break;
case Value::VALUES:
{
const std::vector<Value>& vals = value.constValuesValue();
os << "[ ";
for (std::size_t i = 0; i < vals.size(); ++i)
os << "Value(" << vals[i] << "), ";
os << "]";
}
break;
default: default:
return os; return os;
} }
...@@ -272,6 +325,7 @@ template <> ...@@ -272,6 +325,7 @@ template <>
const Value::Type ValueHelper<Eigen::MatrixXd>::TypeID = Value::MATRIX; const Value::Type ValueHelper<Eigen::MatrixXd>::TypeID = Value::MATRIX;
template <> template <>
const Value::Type ValueHelper<Eigen::Matrix4d>::TypeID = Value::MATRIX4D; const Value::Type ValueHelper<Eigen::Matrix4d>::TypeID = Value::MATRIX4D;
template <> const Value::Type ValueHelper<Values>::TypeID = Value::VALUES;
} // namespace command } // namespace command
} // namespace dynamicgraph } // namespace dynamicgraph
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
namespace dynamicgraph { namespace dynamicgraph {
using namespace std;
Logger::Logger(double timeSample, double streamPrintPeriod) Logger::Logger(double timeSample, double streamPrintPeriod)
: m_timeSample(timeSample), m_streamPrintPeriod(streamPrintPeriod), : m_timeSample(timeSample), m_streamPrintPeriod(streamPrintPeriod),
m_printCountdown(0.0) { m_printCountdown(0.0) {
...@@ -41,38 +39,15 @@ void Logger::countdown() { ...@@ -41,38 +39,15 @@ void Logger::countdown() {
m_printCountdown -= m_timeSample; m_printCountdown -= m_timeSample;
} }
void Logger::sendMsg(string msg, MsgType type, const char *file, int line) { void Logger::sendMsg(std::string msg, MsgType type, const std::string &lineId) {
if (m_lv == VERBOSITY_NONE || stream(type, lineId) << msg << '\n';
(m_lv == VERBOSITY_ERROR && !isErrorMsg(type)) || }
(m_lv == VERBOSITY_WARNING_ERROR &&
!(isWarningMsg(type) || isErrorMsg(type))) || void Logger::sendMsg(std::string msg, MsgType type, const std::string &file,
(m_lv == VERBOSITY_INFO_WARNING_ERROR && isDebugMsg(type))) int line) {
return; std::ostringstream oss;
oss << file << line;
// if print is allowed by current verbosity level stream(type, oss.str()) << msg << '\n';
if (isStreamMsg(type)) {
// check whether counter already exists
std::ostringstream oss;
oss << file << line;
std::string id(oss.str());
map<string, double>::iterator it = m_stream_msg_counters.find(id);
if (it == m_stream_msg_counters.end()) {
// if counter doesn't exist then add one
m_stream_msg_counters.insert(make_pair(id, 0.0));
it = m_stream_msg_counters.find(id);
}
// if counter is greater than 0 then decrement it and do not print
if (it->second > 0.0) {
it->second -= m_timeSample;
if (it->second <= 0.0)
it->second = m_streamPrintPeriod;
else
return;
} else // otherwise reset counter and print
it->second = m_streamPrintPeriod;
}
dgRTLOG() << msg.c_str() << "\n";
} }
bool Logger::setTimeSample(double t) { bool Logger::setTimeSample(double t) {
...@@ -92,4 +67,21 @@ bool Logger::setStreamPrintPeriod(double s) { ...@@ -92,4 +67,21 @@ bool Logger::setStreamPrintPeriod(double s) {
double Logger::getTimeSample() { return m_timeSample; } double Logger::getTimeSample() { return m_timeSample; }
double Logger::getStreamPrintPeriod() { return m_streamPrintPeriod; } double Logger::getStreamPrintPeriod() { return m_streamPrintPeriod; }
bool Logger::checkStreamPeriod(const std::string &lineId) {
// insert element with value 0 if it does not exist.
// otherwise, return a counter to the existing one.
std::pair<StreamCounterMap_t::iterator, bool> result =
m_stream_msg_counters.insert(std::make_pair(lineId, 0.));
// if counter is greater than 0 then decrement it and do not print
double &counter = result.first->second;
counter -= m_timeSample;
if (counter > 0.0) {
return false;
} else // otherwise reset counter and print
counter = m_streamPrintPeriod;
return true;
}
} // namespace dynamicgraph } // namespace dynamicgraph
...@@ -59,12 +59,6 @@ RTLoggerStream RealTimeLogger::front() { ...@@ -59,12 +59,6 @@ RTLoggerStream RealTimeLogger::front() {
return RTLoggerStream(this, oss_); return RTLoggerStream(this, oss_);
} }
RTLoggerStream::~RTLoggerStream() {
os_ << std::ends;
if (logger_ != NULL)
logger_->frontReady();
}
struct RealTimeLogger::thread { struct RealTimeLogger::thread {
bool requestShutdown_; bool requestShutdown_;
int threadPolicy_; int threadPolicy_;
......
...@@ -207,7 +207,7 @@ Command *Entity::getNewStyleCommand(const std::string &commandName) { ...@@ -207,7 +207,7 @@ Command *Entity::getNewStyleCommand(const std::string &commandName) {
return commandMap[commandName]; return commandMap[commandName];
} }
void Entity::sendMsg(const std::string &msg, MsgType t, const char *file, void Entity::sendMsg(const std::string &msg, MsgType t,
int line) { const std::string &lineId) {
logger_.sendMsg("[" + name + "]" + msg, t, file, line); logger_.sendMsg("[" + name + "]" + msg, t, lineId);
} }
...@@ -31,38 +31,86 @@ public: ...@@ -31,38 +31,86 @@ public:
explicit CustomEntity(const std::string &n) : Entity(n) { explicit CustomEntity(const std::string &n) : Entity(n) {
logger_.setTimeSample(0.001); logger_.setTimeSample(0.001);
logger_.setStreamPrintPeriod(0.005); logger_.setStreamPrintPeriod(0.005);
logger_.setVerbosity(VERBOSITY_NONE);
BOOST_CHECK_EQUAL(logger_.getVerbosity(), VERBOSITY_NONE);
BOOST_CHECK( logger_.stream(MSG_TYPE_DEBUG ).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_INFO ).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_WARNING).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_ERROR ).isNull());
logger_.setVerbosity(VERBOSITY_ERROR);
BOOST_CHECK_EQUAL(logger_.getVerbosity(), VERBOSITY_ERROR);
BOOST_CHECK( logger_.stream(MSG_TYPE_DEBUG ).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_INFO ).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_WARNING).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_ERROR ).isNull());
logger_.setVerbosity(VERBOSITY_WARNING_ERROR);
BOOST_CHECK_EQUAL(logger_.getVerbosity(), VERBOSITY_WARNING_ERROR);
BOOST_CHECK( logger_.stream(MSG_TYPE_DEBUG ).isNull());
BOOST_CHECK( logger_.stream(MSG_TYPE_INFO ).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_WARNING).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_ERROR ).isNull());
logger_.setVerbosity(VERBOSITY_INFO_WARNING_ERROR);
BOOST_CHECK_EQUAL(logger_.getVerbosity(), VERBOSITY_INFO_WARNING_ERROR);
BOOST_CHECK( logger_.stream(MSG_TYPE_DEBUG ).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_INFO ).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_WARNING).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_ERROR ).isNull());
logger_.setVerbosity(VERBOSITY_ALL); logger_.setVerbosity(VERBOSITY_ALL);
LoggerVerbosity alv = logger_.getVerbosity(); BOOST_CHECK_EQUAL(logger_.getVerbosity(), VERBOSITY_ALL);
BOOST_CHECK(alv == VERBOSITY_ALL); BOOST_CHECK(!logger_.stream(MSG_TYPE_DEBUG ).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_INFO ).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_WARNING).isNull());
BOOST_CHECK(!logger_.stream(MSG_TYPE_ERROR ).isNull());
} }
~CustomEntity() {} ~CustomEntity() {}
void testDebugTrace() { void testDebugTrace() {
sendMsg("This is a message of level MSG_TYPE_DEBUG", MSG_TYPE_DEBUG); logger_.stream(MSG_TYPE_DEBUG)
sendMsg("This is a message of level MSG_TYPE_INFO", MSG_TYPE_INFO); << "This is a message of level MSG_TYPE_DEBUG\n";
sendMsg("This is a message of level MSG_TYPE_WARNING", MSG_TYPE_WARNING); dynamicgraph::RealTimeLogger::instance().spinOnce();
sendMsg("This is a message of level MSG_TYPE_ERROR", MSG_TYPE_ERROR); logger_.stream(MSG_TYPE_INFO)
sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM", << "This is a message of level MSG_TYPE_INFO\n";
MSG_TYPE_DEBUG_STREAM); dynamicgraph::RealTimeLogger::instance().spinOnce();
sendMsg("This is a message of level MSG_TYPE_INFO_STREAM", logger_.stream(MSG_TYPE_WARNING)
MSG_TYPE_INFO_STREAM); << "This is a message of level MSG_TYPE_WARNING\n";
sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM", dynamicgraph::RealTimeLogger::instance().spinOnce();
MSG_TYPE_WARNING_STREAM); logger_.stream(MSG_TYPE_ERROR)
sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM", << "This is a message of level MSG_TYPE_ERROR\n";
MSG_TYPE_ERROR_STREAM); dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.stream(MSG_TYPE_DEBUG_STREAM)
<< "This is a message of level MSG_TYPE_DEBUG_STREAM\n";
dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.stream(MSG_TYPE_INFO_STREAM)
<< "This is a message of level MSG_TYPE_INFO_STREAM\n";
dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.stream(MSG_TYPE_WARNING_STREAM)
<< "This is a message of level MSG_TYPE_WARNING_STREAM\n";
dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.stream(MSG_TYPE_ERROR_STREAM)
<< "This is a message of level MSG_TYPE_ERROR_STREAM\n";
/* Add test toString */ /* Add test toString */
dynamicgraph::RealTimeLogger::instance().spinOnce();
double q = 1.0; double q = 1.0;
sendMsg("Value to display: " + toString(q)); logger_.stream() << "Value to display: " + toString(q) << '\n';
dynamicgraph::RealTimeLogger::instance().spinOnce();
std::vector<double> vq; std::vector<double> vq;
vq.resize(3); vq.resize(3);
vq[0] = 1.0; vq[0] = 1.0;
vq[1] = 2.0; vq[1] = 2.0;
vq[2] = 3.0; vq[2] = 3.0;
sendMsg("Value to display: " + toString(vq)); logger_.stream(MSG_TYPE_INFO) << "Value to display: " << toString(vq) << '\n';
sendMsg("Value to display: " + toString(vq, 3, 10)); dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.stream(MSG_TYPE_INFO) << "Value to display: " << toString(vq, 3, 10) << '\n';
dynamicgraph::RealTimeLogger::instance().spinOnce();
Eigen::Matrix<double, 3, 3> an_eig_m; Eigen::Matrix<double, 3, 3> an_eig_m;
an_eig_m.Ones(); an_eig_m.setOnes();
sendMsg("Value to display: " + toString(an_eig_m)); logger_.stream(MSG_TYPE_INFO) << "Value to display: " << toString(an_eig_m) << '\n';
dynamicgraph::RealTimeLogger::instance().spinOnce();
logger_.countdown(); logger_.countdown();
} }
}; };
...@@ -84,8 +132,8 @@ BOOST_AUTO_TEST_CASE(debug_logger) { ...@@ -84,8 +132,8 @@ BOOST_AUTO_TEST_CASE(debug_logger) {
entity.setTimeSample(0.002); entity.setTimeSample(0.002);
BOOST_CHECK_EQUAL(entity.getTimeSample(), 0.002); BOOST_CHECK_EQUAL(entity.getTimeSample(), 0.002);
entity.setStreamPrintPeriod(0.004); entity.setStreamPrintPeriod(0.002);
BOOST_CHECK_EQUAL(entity.getStreamPrintPeriod(), 0.004); BOOST_CHECK_EQUAL(entity.getStreamPrintPeriod(), 0.002);
for (unsigned int i = 0; i < 10000; i++) { for (unsigned int i = 0; i < 10000; i++) {
entity.testDebugTrace(); entity.testDebugTrace();
......
...@@ -216,15 +216,16 @@ BOOST_AUTO_TEST_CASE(sendMsg) { ...@@ -216,15 +216,16 @@ BOOST_AUTO_TEST_CASE(sendMsg) {
if (entity.getLoggerVerbosityLevel() != aLoggerVerbosityLevel) if (entity.getLoggerVerbosityLevel() != aLoggerVerbosityLevel)
output << "Mismatch output"; output << "Mismatch output";
std::string aBaseMsg = "Auto Test Case"; #define __FILELINE__ __FILE__ BOOST_PP_STRINGIZE(__LINE__)
std::string aMsg = aBaseMsg + " DEBUG"; entity.logger().stream(dynamicgraph::MSG_TYPE_DEBUG, __FILELINE__)
entity.sendMsg(aMsg, dynamicgraph::MSG_TYPE_DEBUG, __FILE__, __LINE__); << "Auto Test Case" << " DEBUG" << '\n';
aMsg = aBaseMsg + " INFO"; entity.logger().stream(dynamicgraph::MSG_TYPE_INFO, __FILELINE__)
entity.sendMsg(aMsg, dynamicgraph::MSG_TYPE_INFO, __FILE__, __LINE__); << "Auto Test Case" << " INFO" << '\n';
aMsg = aBaseMsg + " WARNING"; entity.logger().stream(dynamicgraph::MSG_TYPE_WARNING, __FILELINE__)
entity.sendMsg(aMsg, dynamicgraph::MSG_TYPE_WARNING, __FILE__, __LINE__); << "Auto Test Case" << " WARNING" << '\n';
aMsg = aBaseMsg + " DEBUG"; entity.logger().stream(dynamicgraph::MSG_TYPE_ERROR, __FILELINE__)
entity.sendMsg(aMsg, dynamicgraph::MSG_TYPE_ERROR, __FILE__, __LINE__); << "Auto Test Case" << " ERROR" << '\n';
#undef __FILELINE__
}; };
}; };
......
...@@ -19,6 +19,10 @@ BOOST_AUTO_TEST_CASE(value_none) { ...@@ -19,6 +19,10 @@ BOOST_AUTO_TEST_CASE(value_none) {
Value value1; Value value1;
Value value(value1); Value value(value1);
// Similar to NaN != NaN
BOOST_CHECK(!(value1 == value));
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -33,6 +37,8 @@ BOOST_AUTO_TEST_CASE(value_bool) { ...@@ -33,6 +37,8 @@ BOOST_AUTO_TEST_CASE(value_bool) {
Value value1(abool1); Value value1(abool1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -166,6 +172,8 @@ BOOST_AUTO_TEST_CASE(value_unsigned_int) { ...@@ -166,6 +172,8 @@ BOOST_AUTO_TEST_CASE(value_unsigned_int) {
Value value1(aint1); Value value1(aint1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -186,6 +194,8 @@ BOOST_AUTO_TEST_CASE(value_int) { ...@@ -186,6 +194,8 @@ BOOST_AUTO_TEST_CASE(value_int) {
Value value1(aint1); Value value1(aint1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -206,6 +216,8 @@ BOOST_AUTO_TEST_CASE(value_float) { ...@@ -206,6 +216,8 @@ BOOST_AUTO_TEST_CASE(value_float) {
Value value1(afloat1); Value value1(afloat1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -226,6 +238,8 @@ BOOST_AUTO_TEST_CASE(value_double) { ...@@ -226,6 +238,8 @@ BOOST_AUTO_TEST_CASE(value_double) {
Value value1(adouble1); Value value1(adouble1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -249,6 +263,8 @@ BOOST_AUTO_TEST_CASE(value_vector) { ...@@ -249,6 +263,8 @@ BOOST_AUTO_TEST_CASE(value_vector) {
Value value1(avector1); Value value1(avector1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -269,6 +285,8 @@ BOOST_AUTO_TEST_CASE(value_string) { ...@@ -269,6 +285,8 @@ BOOST_AUTO_TEST_CASE(value_string) {
Value value1(str1); Value value1(str1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -310,6 +328,8 @@ BOOST_AUTO_TEST_CASE(value_matrixXd) { ...@@ -310,6 +328,8 @@ BOOST_AUTO_TEST_CASE(value_matrixXd) {
Value value1(avector1); Value value1(avector1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -335,6 +355,8 @@ BOOST_AUTO_TEST_CASE(value_matrix4d) { ...@@ -335,6 +355,8 @@ BOOST_AUTO_TEST_CASE(value_matrix4d) {
Value value1(avector1); Value value1(avector1);
Value value = value1; Value value = value1;
BOOST_CHECK(value1 == value);
{ {
output_test_stream output; output_test_stream output;
output << value1; output << value1;
...@@ -351,3 +373,46 @@ BOOST_AUTO_TEST_CASE(value_matrix4d) { ...@@ -351,3 +373,46 @@ BOOST_AUTO_TEST_CASE(value_matrix4d) {
" 0 0 0 0")); " 0 0 0 0"));
} }
} }
BOOST_AUTO_TEST_CASE(value_values) {
using namespace dynamicgraph::command;
std::string s1("value #1");
double d1 = 0.3;
Value vs1(s1);
Value vd1(d1);
Values values;
values.push_back (vs1);
values.push_back (vd1);
Value vvalues (values);
BOOST_CHECK_EQUAL(vvalues.type(), Value::VALUES);
{ // Const ref
const Values& vs = vvalues.constValuesValue();
BOOST_CHECK_EQUAL(vs.size(), values.size());
BOOST_CHECK(vs == values);
}
{ // Cast does not work.
//dg::command::EitherType eitherType (vvalues);
//Values vs = static_cast<Values>(eitherType);
//BOOST_CHECK_EQUAL(vs.size(), values.size());
//BOOST_CHECK(vs == values);
}
{ // Constructor
Value vvs (vvalues);
BOOST_CHECK(vvs == vvalues);
}
{
output_test_stream output;
output << vvalues;
BOOST_CHECK(output.is_equal("Type=values, value=[ "
"Value(Type=string, value=value #1), "
"Value(Type=double, value=0.3), "
"]"));
}
}