From fab8909c52ba2f78bbd3ab676ba1c9343d5be1fd Mon Sep 17 00:00:00 2001
From: fbailly <fbailly@laas.fr>
Date: Mon, 28 Jan 2019 19:52:12 +0100
Subject: [PATCH] [topic/logger_sigHelper] added logger.h and modified
 signal-helper.h from sot-torque-control

---
 include/dynamic-graph/CMakeLists.txt  |   4 +-
 include/dynamic-graph/logger.h        | 216 ++++++++++++++++++++++++++
 include/dynamic-graph/signal-helper.h |  38 ++++-
 src/CMakeLists.txt                    |   1 +
 src/debug/logger.cpp                  | 108 +++++++++++++
 5 files changed, 365 insertions(+), 2 deletions(-)
 create mode 100644 include/dynamic-graph/logger.h
 create mode 100644 src/debug/logger.cpp

diff --git a/include/dynamic-graph/CMakeLists.txt b/include/dynamic-graph/CMakeLists.txt
index a8a7ae5..efec6a1 100644
--- a/include/dynamic-graph/CMakeLists.txt
+++ b/include/dynamic-graph/CMakeLists.txt
@@ -47,7 +47,9 @@ SET(${PROJECT_NAME}_HEADERS
   command-direct-setter.h
   command-bind.h
   all-commands.h
-  )
+
+  logger.h
+    )
 
 INSTALL(FILES ${${PROJECT_NAME}_HEADERS}
   DESTINATION include/${PROJECT_NAME}
diff --git a/include/dynamic-graph/logger.h b/include/dynamic-graph/logger.h
new file mode 100644
index 0000000..f40a0ec
--- /dev/null
+++ b/include/dynamic-graph/logger.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2015, 2019
+ * LAAS-CNRS
+ * Andrea Del Prete, François Bailly,
+ *
+ * This file is part of dynamic-graph.
+ * See license file.
+ */
+
+#ifndef __dynamic_graph_logger_H__
+#define __dynamic_graph_logger_H__
+
+/* --------------------------------------------------------------------- */
+/* --- API ------------------------------------------------------------- */
+/* --------------------------------------------------------------------- */
+
+#if defined (WIN32)
+#  if defined (logger_EXPORTS)
+#    define LOGGER_EXPORT __declspec(dllexport)
+#  else
+#    define LOGGER_EXPORT __declspec(dllimport)
+#  endif
+#else
+#  define LOGGER_EXPORT
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* --- INCLUDE --------------------------------------------------------- */
+/* --------------------------------------------------------------------- */
+
+#include <dynamic-graph/signal-helper.h>
+#include <map>
+#include <iomanip> // std::setprecision
+#include "boost/assign.hpp"
+
+
+namespace dynamicgraph {
+
+//#define LOGGER_VERBOSITY_INFO_WARNING_ERROR
+#define LOGGER_VERBOSITY_ALL
+
+#define SEND_MSG(msg,type)         sendMsg(msg,type,__FILE__,__LINE__)
+
+#ifdef LOGGER_VERBOSITY_ERROR
+  #define SEND_DEBUG_STREAM_MSG(msg)
+  #define SEND_INFO_STREAM_MSG(msg)
+  #define SEND_WARNING_STREAM_MSG(msg)
+  #define SEND_ERROR_STREAM_MSG(msg)    SEND_MSG(msg,MSG_TYPE_ERROR_STREAM)
+#endif
+
+#ifdef LOGGER_VERBOSITY_WARNING_ERROR
+  #define SEND_DEBUG_STREAM_MSG(msg)
+  #define SEND_INFO_STREAM_MSG(msg)\
+  #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)
+#endif
+
+#ifdef LOGGER_VERBOSITY_INFO_WARNING_ERROR
+  #define SEND_DEBUG_STREAM_MSG(msg)
+  #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_ERROR_STREAM_MSG(msg)    SEND_MSG(msg,MSG_TYPE_ERROR_STREAM)
+#endif
+
+#ifdef LOGGER_VERBOSITY_ALL
+  #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_WARNING_STREAM_MSG(msg)  SEND_MSG(msg,MSG_TYPE_WARNING_STREAM)
+  #define SEND_ERROR_STREAM_MSG(msg)    SEND_MSG(msg,MSG_TYPE_ERROR_STREAM)
+#endif
+
+  /** Enum representing the different kind of messages.
+   */
+  enum MsgType
+  {
+    MSG_TYPE_DEBUG          =0,
+    MSG_TYPE_INFO           =1,
+    MSG_TYPE_WARNING        =2,
+    MSG_TYPE_ERROR          =3,
+    MSG_TYPE_DEBUG_STREAM   =4,
+    MSG_TYPE_INFO_STREAM    =5,
+    MSG_TYPE_WARNING_STREAM =6,
+    MSG_TYPE_ERROR_STREAM   =7
+  };
+
+  template<typename T>
+  std::string toString(const T& v, const int precision=3, const int width=-1)
+  {
+    std::stringstream ss;
+    if(width>precision)
+      ss<<std::fixed<<std::setw(width)<<std::setprecision(precision)<<v;
+    else
+      ss<<std::fixed<<std::setprecision(precision)<<v;
+    return ss.str();
+  }
+
+  template<typename T>
+  std::string toString(const std::vector<T>& v, const int precision=3, const int width=-1,
+                       const std::string separator=", ")
+  {
+    std::stringstream ss;
+    if(width>precision)
+    {
+      for(int i=0; i<v.size()-1; i++)
+        ss<<std::fixed<<std::setw(width)<<std::setprecision(precision)<<v[i]<<separator;
+      ss<<std::fixed<<std::setw(width)<<std::setprecision(precision)<<v[v.size()-1];
+    }
+    else
+    {
+      for(int i=0; i<v.size()-1; i++)
+        ss<<std::fixed<<std::setprecision(precision)<<v[i]<<separator;
+      ss<<std::fixed<<std::setprecision(precision)<<v[v.size()-1];
+    }
+
+    return ss.str();
+  }
+
+//      template<typename T, int N>
+//      std::string toString(const Eigen::Matrix<T, N, 1, 0, N, 1>& v, const std::string separator=", ",
+//                           const int precision=3, const int width=-1)
+  template<typename T>
+  std::string toString(const Eigen::MatrixBase<T>& v,
+                       const int precision=3, const int width=-1, const std::string separator=", ")
+  {
+    std::stringstream ss;
+    if(width>precision)
+    {
+      for(int i=0; i<v.size()-1; i++)
+        ss<<std::fixed<<std::setw(width)<<std::setprecision(precision)<<v[i]<<separator;
+      ss<<std::fixed<<std::setw(width)<<std::setprecision(precision)<<v[v.size()-1];
+    }
+    else
+    {
+      for(int i=0; i<v.size()-1; i++)
+        ss<<std::fixed<<std::setprecision(precision)<<v[i]<<separator;
+      ss<<std::setprecision(precision)<<v[v.size()-1];
+    }
+
+    return ss.str();
+  }
+
+  enum LoggerVerbosity
+  {
+    VERBOSITY_ALL,
+    VERBOSITY_INFO_WARNING_ERROR,
+    VERBOSITY_WARNING_ERROR,
+    VERBOSITY_ERROR,
+    VERBOSITY_NONE
+  };
+
+  /** A simple class for logging messages
+  */
+  class Logger
+  {
+  public:
+
+    /** Constructor */
+    Logger(double timeSample=0.001, double streamPrintPeriod=1.0);
+
+    /** Destructor */
+    ~Logger(){}
+
+    /** Method to be called at every control iteration
+       * to decrement the internal Logger's counter. */
+    void countdown();
+
+    /** Print the specified message on standard output if the verbosity level
+     * allows it. The file name and the line number are used to identify
+     * the point where sendMsg is called so that streaming messages are
+     * printed only every streamPrintPeriod iterations.
+     */
+    void sendMsg(std::string msg, MsgType type, const char* file="", int line=0);
+
+    /** Set the sampling time at which the method countdown()
+       * is going to be called. */
+    bool setTimeSample(double t);
+
+    /** Set the time period for printing of streaming messages. */
+    bool setStreamPrintPeriod(double s);
+
+    /** Set the verbosity level of the logger. */
+    void setVerbosity(LoggerVerbosity lv);
+
+  protected:
+    LoggerVerbosity m_lv;                /// verbosity of the logger
+    double          m_timeSample;        /// specify the period of call of the countdown method
+    double          m_streamPrintPeriod; /// specify the time period of the stream prints
+    double          m_printCountdown;    /// every time this is < 0 (i.e. every _streamPrintPeriod sec) print stuff
+
+    /** Pointer to the dynamic structure which holds the collection of streaming messages */
+    std::map<std::string, double> m_stream_msg_counters;
+
+    bool isStreamMsg(MsgType m)
+    { return m==MSG_TYPE_ERROR_STREAM || m==MSG_TYPE_DEBUG_STREAM || m==MSG_TYPE_INFO_STREAM || m==MSG_TYPE_WARNING_STREAM; }
+
+    bool isDebugMsg(MsgType m)
+    { return m==MSG_TYPE_DEBUG_STREAM || m==MSG_TYPE_DEBUG; }
+
+    bool isInfoMsg(MsgType m)
+    { return m==MSG_TYPE_INFO_STREAM || m==MSG_TYPE_INFO; }
+
+    bool isWarningMsg(MsgType m)
+    { return m==MSG_TYPE_WARNING_STREAM || m==MSG_TYPE_WARNING; }
+
+    bool isErrorMsg(MsgType m)
+    { return m==MSG_TYPE_ERROR_STREAM || m==MSG_TYPE_ERROR; }
+  };
+
+  /** Method to get the logger (singleton). */
+  Logger& getLogger();
+}        // namespace dynamicgraph
+
+
+
+#endif // #ifndef __sot_torque_control_logger_H__
diff --git a/include/dynamic-graph/signal-helper.h b/include/dynamic-graph/signal-helper.h
index 87bbec3..0282e34 100644
--- a/include/dynamic-graph/signal-helper.h
+++ b/include/dynamic-graph/signal-helper.h
@@ -1,5 +1,7 @@
 /*
- * Copyright 2011, Nicolas Mansard, LAAS-CNRS
+ * Copyright 2011, 2019 
+ * LAAS-CNRS
+ * Nicolas Mansard, François Bailly 
  *
  * This file is part of dynamic-graph.
  * dynamic-graph is free software: you can redistribute it and/or
@@ -23,26 +25,60 @@
 #include <dynamic-graph/entity.h>
 #include <dynamic-graph/signal-ptr.h>
 #include <dynamic-graph/signal-time-dependent.h>
+#include <dynamic-graph/linear-algebra.h> 
 
 /* --- MACROS ---------------------------------------------------------- */
+#define SIGNAL_OUT_FUNCTION_NAME(name) name##SOUT_function
 
 #define DECLARE_SIGNAL( name,IO,type )    ::dynamicgraph::Signal<type,int> name##S##IO
 #define CONSTRUCT_SIGNAL( name,IO,type )  name##S##IO( getClassName()+"("+getName()+")::"+#IO+"put("+#type+")::"+#name )
+#define BIND_SIGNAL_TO_FUNCTION(name,IO,type) m_##name##S##IO.setFunction(boost::bind(&EntityClassName::SIGNAL_OUT_FUNCTION_NAME(name),this,_1,_2));
+
+/**/
 
 #define DECLARE_SIGNAL_IN( name,type )    ::dynamicgraph::SignalPtr<type,int> name##SIN
 #define CONSTRUCT_SIGNAL_IN( name,type )  name##SIN( NULL,getClassName()+"("+getName()+")::input("+#type+")::"+#name )
 
+/**/
+
+#define DECLARE_SIGNAL_OUT_FUNCTION(name,type) \
+  type& SIGNAL_OUT_FUNCTION_NAME(name)(type&,int)
+
+#define DEFINE_SIGNAL_OUT_FUNCTION(name,type) \
+  type& EntityClassName::SIGNAL_OUT_FUNCTION_NAME(name)(type& s,int iter)
+
 #define SIGNAL_OUT_FUNCTION( name )  name##SOUT_function
+
 #define DECLARE_SIGNAL_OUT( name,type )                         \
   public:                                                       \
     ::dynamicgraph::SignalTimeDependent<type,int> name##SOUT;	\
   protected:                                                    \
   type& SIGNAL_OUT_FUNCTION(name)( type&,int )
+
 #define CONSTRUCT_SIGNAL_OUT( name,type,dep )		\
   name##SOUT( boost::bind(&  EntityClassName::name##SOUT_function,this,_1,_2), \
 	      dep,getClassName()+"("+getName()+")::output("+#type+")::"+#name )
 
 
 
+/**************** INNER SIGNALS *******************/
+#define SIGNAL_INNER_FUNCTION_NAME(name) name##SINNER_function
+
+#define DECLARE_SIGNAL_INNER_FUNCTION(name,type) \
+  type& SIGNAL_INNER_FUNCTION_NAME(name)(type&,int)
+
+#define DEFINE_SIGNAL_INNER_FUNCTION(name,type) \
+  type& EntityClassName::SIGNAL_INNER_FUNCTION_NAME(name)(type& s,int iter)
+
+#define DECLARE_SIGNAL_INNER(name,type)                           \
+  public:                                                       \
+    ::dynamicgraph::SignalTimeDependent<type,int> m_##name##SINNER;\
+  protected:                                                    \
+    DECLARE_SIGNAL_INNER_FUNCTION(name,type)
+
+#define CONSTRUCT_SIGNAL_INNER( name,type,dep )		        \
+  m_##name##SINNER( boost::bind(&EntityClassName::name##SINNER_function,this,_1,_2), \
+              dep,getClassName()+"("+getName()+")::inner("+#type+")::"+#name )
+
 
 #endif // __dynamic_graph_signal_helper_H__
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3e16737..738a664 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -41,6 +41,7 @@ ADD_LIBRARY(${LIBRARY_NAME}
   SHARED
   debug/debug.cpp
   debug/real-time-logger.cpp
+  debug/logger.cpp
 
   dgraph/entity.cpp
   dgraph/factory.cpp
diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp
new file mode 100644
index 0000000..412de96
--- /dev/null
+++ b/src/debug/logger.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015, 2019 
+ * LAAS-CNRS
+ * Andrea Del Prete, François Bailly 
+ * 
+ * This file is part of dynamic-graph.
+ * See license file.
+ */
+
+#ifndef WIN32
+  #include <sys/time.h>
+#else
+  #include <Windows.h>
+#endif
+
+#include <stdio.h>
+#include <iostream>
+#include <iomanip>      // std::setprecision
+#include <dynamic-graph/logger.h>
+
+namespace dynamicgraph
+{
+
+    using namespace std;
+
+    Logger& getLogger()
+    {
+      static Logger l(0.001, 1.0);
+      return l;
+    }
+
+    Logger::Logger(double timeSample, double streamPrintPeriod)
+      : m_timeSample(timeSample),
+        m_streamPrintPeriod(streamPrintPeriod),
+        m_printCountdown(0.0)
+    {
+#ifdef LOGGER_VERBOSITY_ERROR
+        m_lv = VERBOSITY_ERROR;
+#endif
+#ifdef LOGGER_VERBOSITY_WARNING_ERROR
+        m_lv = VERBOSITY_WARNING_ERROR;
+#endif
+#ifdef LOGGER_VERBOSITY_INFO_WARNING_ERROR
+        m_lv = VERBOSITY_INFO_WARNING_ERROR;
+#endif
+#ifdef LOGGER_VERBOSITY_ALL
+        m_lv = VERBOSITY_ALL;
+#endif
+    }
+
+    void Logger::countdown()
+    {
+      if(m_printCountdown<0.0)
+        m_printCountdown = m_streamPrintPeriod;
+      m_printCountdown -= m_timeSample;
+    }
+
+    void Logger::sendMsg(string msg, MsgType type, const char* file, int line)
+    {
+      if(m_lv==VERBOSITY_NONE ||
+        (m_lv==VERBOSITY_ERROR && !isErrorMsg(type)) ||
+        (m_lv==VERBOSITY_WARNING_ERROR && !(isWarningMsg(type) || isErrorMsg(type))) ||
+        (m_lv==VERBOSITY_INFO_WARNING_ERROR && isDebugMsg(type)))
+        return;
+
+      // if print is allowed by current verbosity level
+      if(isStreamMsg(type))
+      {
+        // check whether counter already exists
+        string id = file+toString(line);
+        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;
+          return;
+        }
+        else  // otherwise reset counter and print
+          it->second = m_streamPrintPeriod;
+      }
+      printf("%s\n", msg.c_str());
+      fflush(stdout); // Prints to screen or whatever your standard out is
+    }
+
+    bool Logger::setTimeSample(double t)
+    {
+      if(t<=0.0)
+        return false;
+      m_timeSample = t;
+      return true;
+    }
+
+    bool Logger::setStreamPrintPeriod(double s)
+    {
+      if(s<=0.0)
+        return false;
+      m_streamPrintPeriod = s;
+      return true;
+    }
+} // namespace dynamicgraph
+
-- 
GitLab