diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3d3536f6c7eefa65e3a0f8176719c9de2727800f..0a8ee503ae3be46996ba8003b6865bdfbcbae57b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -69,6 +69,12 @@ else(OpenCV_FOUND)
     message("[WARN] OpenCV not found. Related sources will NOT be built.")
 endif(OpenCV_FOUND)
 
+# Cereal
+FIND_PACKAGE(cereal QUIET)
+IF(cereal_FOUND)
+    MESSAGE("cereal Library FOUND: cereal related sources will be built.")
+ENDIF(cereal_FOUND)
+
 # YAML with yaml-cpp
 INCLUDE (${PROJECT_SOURCE_DIR}/cmake_modules/FindYamlCpp.cmake)
 IF(YAMLCPP_FOUND)
@@ -161,6 +167,11 @@ IF(OpenCV_FOUND)
     INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
 ENDIF(OpenCV_FOUND)
 
+# cereal
+IF(cereal_FOUND)
+    INCLUDE_DIRECTORIES(${cereal_INCLUDE_DIRS})
+ENDIF(cereal_FOUND)
+
 IF(Suitesparse_FOUND)
     INCLUDE_DIRECTORIES(${Suitesparse_INCLUDE_DIRS})
 ENDIF(Suitesparse_FOUND)
@@ -417,6 +428,10 @@ IF (OpenCV_FOUND)
         )
 ENDIF(OpenCV_FOUND)
 
+IF (cereal_FOUND)
+  ADD_SUBDIRECTORY(serialization/cereal)
+ENDIF(cereal_FOUND)
+
 IF (Suitesparse_FOUND)
     ADD_SUBDIRECTORY(solver)
 ENDIF(Suitesparse_FOUND)
@@ -506,6 +521,8 @@ INSTALL(FILES ${HDRS_WRAPPER}
     DESTINATION include/iri-algorithms/wolf/ceres_wrapper)
 INSTALL(FILES ${HDRS_SOLVER}
     DESTINATION include/iri-algorithms/wolf/solver)
+INSTALL(FILES ${HDRS_SERIALIZATION}
+    DESTINATION include/iri-algorithms/wolf/serialization)
 
 INSTALL(FILES "${CMAKE_SOURCE_DIR}/cmake_modules/Findwolf.cmake"
     DESTINATION "lib/cmake/${PROJECT_NAME}")
diff --git a/src/imu_tools.h b/src/imu_tools.h
index a1831bde54104c142533510dbb64afca79f37a01..95241fe1142f9438308e37b566eaa077ec3ae5a1 100644
--- a/src/imu_tools.h
+++ b/src/imu_tools.h
@@ -153,27 +153,16 @@ inline void compose(const MatrixBase<D1>& d1,
     MatrixSizeCheck< 9, 9>::check(J_sum_d1);
     MatrixSizeCheck< 9, 9>::check(J_sum_d2);
 
-    // Maps over provided data
-    Map<const Matrix<typename D1::Scalar, 3, 1> >   dp1    ( & d1( 0 ) );
-    Map<const Quaternion<typename D1::Scalar> >     dq1    ( & d1( 3 ) );
-    Map<const Matrix<typename D1::Scalar, 3, 1> >   dv1    ( & d1( 7 ) );
-    Map<const Matrix<typename D2::Scalar, 3, 1> >   dp2    ( & d2( 0 ) );
-    Map<const Quaternion<typename D2::Scalar> >     dq2    ( & d2( 3 ) );
-    Map<const Matrix<typename D2::Scalar, 3, 1> >   dv2    ( & d2( 7 ) );
-    Map<Matrix<typename D3::Scalar, 3, 1> >         sum_p  ( & sum( 0 ) );
-    Map<Quaternion<typename D3::Scalar> >           sum_q  ( & sum( 3 ) );
-    Map<Matrix<typename D3::Scalar, 3, 1> >         sum_v  ( & sum( 7 ) );
-
     // Some useful temporaries
-    Matrix<typename D1::Scalar, 3, 3> dR1 = dq1.matrix(); // First  Delta, DR
-    Matrix<typename D2::Scalar, 3, 3> dR2 = dq2.matrix(); // Second delta, dR
+    Matrix<typename D1::Scalar, 3, 3> dR1 = q2R(d1.segment(3,4)); //dq1.matrix(); // First  Delta, DR
+    Matrix<typename D2::Scalar, 3, 3> dR2 = q2R(d2.segment(3,4)); //dq2.matrix(); // Second delta, dR
 
     // Jac wrt first delta
     J_sum_d1.setIdentity();                                     // dDp'/dDp = dDv'/dDv = I
-    J_sum_d1.block(0,3,3,3).noalias() = - dR1 * skew(dp2) ;     // dDp'/dDo
+    J_sum_d1.block(0,3,3,3).noalias() = - dR1 * skew(d2.head(3)) ;     // dDp'/dDo
     J_sum_d1.block(0,6,3,3) = Matrix3s::Identity() * dt;        // dDp'/dDv = I*dt
     J_sum_d1.block(3,3,3,3) = dR2.transpose();                  // dDo'/dDo
-    J_sum_d1.block(6,3,3,3).noalias() = - dR1 * skew(dv2) ;     // dDv'/dDo
+    J_sum_d1.block(6,3,3,3).noalias() = - dR1 * skew(d2.tail(3)) ;     // dDv'/dDo
 
     // Jac wrt second delta
     J_sum_d2.setIdentity();                                     //
diff --git a/src/logging.h b/src/logging.h
index acfb00fa76096447ba92fce8b07196633a31cf94..eea75fcc522654ab8d302634c432e267249be632 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -19,6 +19,9 @@
 
 namespace wolf {
 namespace internal {
+namespace do_not_enter_where_the_wolf_lives {
+
+#define __INTERNAL_WOLF_MAIN_LOGGER_NAME_ "wolf_main_console"
 
 static const auto repeated_brace = std::make_tuple("{}",
                                                    "{}{}",
@@ -44,49 +47,51 @@ static const auto repeated_brace = std::make_tuple("{}",
                                                    "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                    "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                                                    "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
-                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}"); // up to 25 args.
-
-class Logger : public Singleton<Logger>
+                                                   "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}"); // up to 25 args. Should be fine
+class Logger
 {
-  friend class Singleton<Logger>;
+public:
 
-protected:
+  Logger(const std::string& name);
 
-  Logger();
-  ~Logger();
+  Logger(std::string&& name);
 
-// It is counter intuitive to have those functions
-// public but that for the sake of the macros below
-public:
+  ~Logger();
 
-  Logger(Logger&)         = delete;
-  void operator=(Logger&) = delete;
+  // Not copyable/movable
+  Logger(Logger&)          = delete;
+  void operator=(Logger&)  = delete;
+  Logger(Logger&&)         = delete;
+  void operator=(Logger&&) = delete;
 
   template<typename... Args>
-  void info(Args&&... args);
+  void info(Args&&... args) const;
 
   template<typename... Args>
-  void warn(Args&&... args);
+  void warn(Args&&... args) const;
 
   template<typename... Args>
-  void error(Args&&... args);
+  void error(Args&&... args) const;
 
   template<typename... Args>
-  void debug(Args&&... args);
+  void debug(Args&&... args) const;
 
   template<typename... Args>
-  void trace(Args&&... args);
+  void trace(Args&&... args) const;
 
   bool set_async_queue(const std::size_t q_size);
 
+  void set_pattern(const std::string& p);
+
 protected:
 
-  const std::string log_name_ = "wolf_main_console";
+  const std::string log_name_;
 
   std::shared_ptr<spdlog::logger> console_;
 };
 
-inline Logger::Logger()
+inline Logger::Logger(const std::string& name) :
+  log_name_(name)
 {
   // Create main logger
   console_ = spdlog::stdout_color_mt(log_name_);
@@ -99,9 +104,46 @@ inline Logger::Logger()
   // Queue size must be a power of 2
   spdlog::set_async_mode(4096);
 
-  // Logging pattern is :
-  // [thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
-  console_->set_pattern("[%t][%H:%M:%S.%F][%l] %v");
+  if (log_name_ == __INTERNAL_WOLF_MAIN_LOGGER_NAME_)
+    // Logging pattern is :
+    // [thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
+    //set_pattern("[%t][%H:%M:%S.%F][%l] %v");
+    // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds] #log-content
+    set_pattern("[%l][%x - %H:%M:%S.%F] %v");
+  else
+    // Logging pattern is :
+    // [logger name][thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
+    //set_pattern("[" + log_name_ + "]" +"[%t][%H:%M:%S.%F][%l] %v");
+    // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds][logger name] #log-content
+    set_pattern("[%l][%x - %H:%M:%S.%F][" + log_name_ + "] %v");
+}
+
+inline Logger::Logger(std::string&& name) :
+  log_name_(std::forward<std::string>(name))
+{
+  // Create main logger
+  console_ = spdlog::stdout_color_mt(log_name_);
+
+#ifdef _WOLF_TRACE
+  console_->set_level(spdlog::level::trace);
+#endif
+
+  // Enable asynchronous logging
+  // Queue size must be a power of 2
+  spdlog::set_async_mode(4096);
+
+  if (log_name_ == __INTERNAL_WOLF_MAIN_LOGGER_NAME_)
+    // Logging pattern is :
+    // [thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
+    //set_pattern("[%t][%H:%M:%S.%F][%l] %v");
+    // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds] #log-content
+    set_pattern("[%l][%x - %H:%M:%S.%F] %v");
+  else
+    // Logging pattern is :
+    // [logger name][thread num][hour:minutes:seconds.nanoseconds][log type] #log-content
+    //set_pattern("[" + log_name_ + "]" +"[%t][%H:%M:%S.%F][%l] %v");
+    // [log type][MM/DD/YY - hour:minutes:seconds.nanoseconds][logger name] #log-content
+    set_pattern("[%l][%x - %H:%M:%S.%F][" + log_name_ + "] %v");
 }
 
 inline Logger::~Logger()
@@ -110,31 +152,31 @@ inline Logger::~Logger()
 }
 
 template<typename... Args>
-void Logger::info(Args&&... args)
+void Logger::info(Args&&... args) const
 {
   console_->info(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
 }
 
 template<typename... Args>
-void Logger::warn(Args&&... args)
+void Logger::warn(Args&&... args) const
 {
   console_->warn(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
 }
 
 template<typename... Args>
-void Logger::error(Args&&... args)
+void Logger::error(Args&&... args) const
 {
   console_->error(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
 }
 
 template<typename... Args>
-void Logger::debug(Args&&... args)
+void Logger::debug(Args&&... args) const
 {
   console_->debug(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
 }
 
 template<typename... Args>
-void Logger::trace(Args&&... args)
+void Logger::trace(Args&&... args) const
 {
   console_->trace(std::get<sizeof...(args)-1>(repeated_brace), std::forward<Args>(args)...);
 }
@@ -148,38 +190,140 @@ inline bool Logger::set_async_queue(const std::size_t q_size)
   return q_size;
 }
 
+inline void Logger::set_pattern(const std::string& p)
+{
+  console_->set_pattern(p);
+}
+
+using LoggerPtr = std::unique_ptr<Logger>;
+
+/// dummy namespace to avoid colision with c++14
+/// @todo use std version once we move to cxx14
+namespace not_std {
+template <typename T, typename... Args>
+std::unique_ptr<T> make_unique(Args&&... args)
+{
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+} /* namespace not_std */
+
+class LoggerManager
+{
+public:
+
+  LoggerManager()  = default;
+  ~LoggerManager() = default;
+
+  bool exists(const std::string& name) const
+  {
+    std::lock_guard<std::mutex> lock(mut_);
+    return existsImpl(name);
+  }
+
+  const Logger& getLogger(const std::string& name) /*const*/
+  {
+    std::lock_guard<std::mutex> lock(mut_);
+
+    if (!existsImpl(name)) addLogger(name);
+
+    return *(logger_map_.at(name));
+  }
+
+protected:
+
+  mutable std::mutex mut_;
+
+  std::map<const std::string, const LoggerPtr> logger_map_;
+
+  bool addLogger(const std::string& name)
+  {
+    /// @note would be easier with cpp17 map.try_emplace...
+    const bool created = existsImpl(name) ?
+                          false :
+                          logger_map_.emplace(name, not_std::make_unique<Logger>(name)).second;
+    return created;
+  }
+
+  bool existsImpl(const std::string& name) const
+  {
+    return (logger_map_.find(name) != logger_map_.end());
+    //return (spdlog::get(name) != nullptr);
+  }
+};
+
+} /* namespace do_not_enter_where_the_wolf_lives */
+
+using WolfLogger = Singleton<do_not_enter_where_the_wolf_lives::Logger>;
+using WolfLoggerManager = Singleton<do_not_enter_where_the_wolf_lives::LoggerManager>;
+
+} /* namespace internal */
+} /* namespace wolf */
+
 #define WOLF_STRINGIFY(x) #x
 #define WOLF_STR_HELPER(x) WOLF_STRINGIFY(x)
 
-#define WOLF_INFO(...) \
-  wolf::internal::Logger::get().info(__VA_ARGS__);
+/// @brief NAMED LOGGING
+
+#define WOLF_ASYNC_QUEUE_LOG_NAMED(name, ...) wolf::internal::WolfLoggerManager::get().getLogger(name).set_async_queue(x);
 
-#define WOLF_WARN(...) \
-  wolf::internal::Logger::get().warn(__VA_ARGS__);
+#define WOLF_INFO_NAMED(name, ...) wolf::internal::WolfLoggerManager::get().getLogger(name).info(__VA_ARGS__);
+#define WOLF_INFO_NAMED_COND(name, cond, ...) if (cond) WOLF_INFO_NAMED(name, __VA_ARGS__);
 
-#define WOLF_ERROR(...) \
-  wolf::internal::Logger::get().error(__VA_ARGS__);
+#define WOLF_WARN_NAMED(name, ...) wolf::internal::WolfLoggerManager::get().getLogger(name).warn(__VA_ARGS__);
+#define WOLF_WARN_NAMED_COND(name, cond, ...) if (cond) WOLF_WARN_NAMED(name, __VA_ARGS__);
+
+#define WOLF_ERROR_NAMED(name, ...) wolf::internal::WolfLoggerManager::get().getLogger(name).error(__VA_ARGS__);
+#define WOLF_ERROR_NAMED_COND(name, cond, ...) if (cond) WOLF_ERROR_NAMED(name, __VA_ARGS__);
 
 #ifdef _WOLF_DEBUG
-  #define WOLF_DEBUG(...) \
-    wolf::internal::Logger::get().debug(__VA_ARGS__);
+  #define WOLF_DEBUG_NAMED(name, ...) wolf::internal::WolfLoggerManager::get().getLogger(name).debug(__VA_ARGS__);
+  #define WOLF_DEBUG_NAMED_COND(name, cond, ...) if (cond) WOLF_DEBUG_NAMED(name, __VA_ARGS__);
 #else
-  #define WOLF_DEBUG(...)
+  #define WOLF_DEBUG_NAMED(name, ...)
+  #define WOLF_DEBUG_NAMED_COND(cond, name, ...)
 #endif
 
-#define WOLF_ASYNC_QUEUE_LOG(x) \
-  wolf::internal::Logger::get().set_async_queue(x);
+#ifdef _WOLF_TRACE
+  #define WOLF_TRACE_NAMED(name, ...) \
+    {char this_file[] = __FILE__;\
+    wolf::internal::WolfLoggerManager::get().getLogger(name).trace("[", basename(this_file), " L", __LINE__, \
+              " : ", __FUNCTION__, "] ", __VA_ARGS__);}
+  #define WOLF_TRACE_NAMED_COND(name, cond, ...) if (cond) WOLF_TRACE_NAMED_COND(name, __VA_ARGS__);
+#else
+  #define WOLF_TRACE_NAMED(...)
+  #define WOLF_TRACE_NAMED_cond(name, cond, ...)
+#endif
+
+/// @brief MAIN LOGGING
+
+#define WOLF_ASYNC_QUEUE_LOG(x) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).set_async_queue(x);
+
+#define WOLF_INFO(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).info(__VA_ARGS__);
+#define WOLF_INFO_COND(cond, ...) if (cond) WOLF_INFO(__VA_ARGS__);
+
+#define WOLF_WARN(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).warn(__VA_ARGS__);
+#define WOLF_WARN_COND(cond, ...) if (cond) WOLF_WARN(__VA_ARGS__);
+
+#define WOLF_ERROR(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).error(__VA_ARGS__);
+#define WOLF_ERROR_COND(cond, ...) if (cond) WOLF_ERROR(__VA_ARGS__);
+
+#ifdef _WOLF_DEBUG
+  #define WOLF_DEBUG(...) wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).debug(__VA_ARGS__);
+  #define WOLF_DEBUG_COND(cond, ...) if (cond) WOLF_DEBUG(__VA_ARGS__);
+#else
+  #define WOLF_DEBUG(...)
+  #define WOLF_DEBUG_COND(cond, ...)
+#endif
 
 #ifdef _WOLF_TRACE
   #define WOLF_TRACE(...) \
     {char this_file[] = __FILE__;\
-    wolf::internal::Logger::get().trace("[", basename(this_file), " L", __LINE__, \
+    wolf::internal::WolfLogger::get(__INTERNAL_WOLF_MAIN_LOGGER_NAME_).trace("[", basename(this_file), " L", __LINE__, \
               " : ", __FUNCTION__, "] ", __VA_ARGS__);}
+  #define WOLF_TRACE_COND(cond, ...) if (cond) WOLF_TRACE(__VA_ARGS__);
 #else
   #define WOLF_TRACE(...)
+  #define WOLF_TRACE_COND(cond, ...)
 #endif
 
-} // namespace internal
-} // namespace wolf
-
 #endif /* WOLF_LOGGING_H_ */
diff --git a/src/processor_logging.h b/src/processor_logging.h
new file mode 100644
index 0000000000000000000000000000000000000000..167beb892bb2dfe777426d14d535daf7e28cd1ac
--- /dev/null
+++ b/src/processor_logging.h
@@ -0,0 +1,31 @@
+/**
+ * \file processor_logging.h
+ *
+ *  Created on: Oct 5, 2017
+ *  \author: Jeremie Deray
+ */
+
+#ifndef _WOLF_PROCESSOR_LOGGING_H_
+#define _WOLF_PROCESSOR_LOGGING_H_
+
+/// @brief un-comment for IDE highlights.
+//#include "logging.h"
+
+#define __INTERNAL_WOLF_ASSERT_PROCESSOR \
+  static_assert(std::is_base_of<ProcessorBase, \
+   typename std::remove_pointer<decltype(this)>::type>::value, \
+    "This macro can be used only within the body of a " \
+    "non-static " \
+    "ProcessorBase (and derived) function !");
+
+#define WOLF_PROCESSOR_INFO(...)  __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_INFO_NAMED(getType(),  __VA_ARGS__);
+#define WOLF_PROCESSOR_WARN(...)  __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_WARN_NAMED(getType(),  __VA_ARGS__);
+#define WOLF_PROCESSOR_ERROR(...) __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_ERROR_NAMED(getType(), __VA_ARGS__);
+#define WOLF_PROCESSOR_DEBUG(...) __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_DEBUG_NAMED(getType(), __VA_ARGS__);
+
+#define WOLF_PROCESSOR_INFO_COND(cond, ...)  __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_INFO_NAMED_COND(getType(),  cond, __VA_ARGS__);
+#define WOLF_PROCESSOR_WARN_COND(cond, ...)  __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_WARN_NAMED_COND(getType(),  cond, __VA_ARGS__);
+#define WOLF_PROCESSOR_ERROR_COND(cond, ...) __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_ERROR_NAMED_COND(getType(), cond, __VA_ARGS__);
+#define WOLF_PROCESSOR_DEBUG_COND(cond, ...) __INTERNAL_WOLF_ASSERT_PROCESSOR WOLF_DEBUG_NAMED_COND(getType(), cond, __VA_ARGS__);
+
+#endif /* _WOLF_PROCESSOR_LOGGING_H_ */
diff --git a/src/rotations.h b/src/rotations.h
index 1e2426985dc45b3fbaffdb03c54bd4cf266529f1..a5fc57e566d1bec2b0077a37fb35dfb67f026515 100644
--- a/src/rotations.h
+++ b/src/rotations.h
@@ -245,6 +245,19 @@ inline Eigen::Matrix<typename Derived::Scalar, 3, 3> q2R(const Eigen::Quaternion
     return _q.matrix();
 }
 
+/** \brief quaternion to rotation matrix conversion
+ *
+ * @param _q a right-handed unit quaternion
+ * @return the equivalent rotation matrix
+ */
+template<typename Derived>
+inline Eigen::Matrix<typename Derived::Scalar, 3, 3> q2R(const Eigen::MatrixBase<Derived>& _q)
+{
+    MatrixSizeCheck<4,1>::check(_q);
+    Eigen::Quaternion<typename Derived::Scalar> q(_q(3),_q(0),_q(1),_q(2));
+    return q2R( q );
+}
+
 /** \brief rotation matrix to quaternion conversion
  *
  * @param _R a rotation matrix
diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a853ba8ec5158727fcd4bfd9752d6de398c5aefa
--- /dev/null
+++ b/src/serialization/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(cereal)
diff --git a/src/serialization/cereal/CMakeLists.txt b/src/serialization/cereal/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c526b9f2171f61cf1dbb5d06af48865c3863d814
--- /dev/null
+++ b/src/serialization/cereal/CMakeLists.txt
@@ -0,0 +1,20 @@
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(HDRS_SERIALIZATION ${HDRS_SERIALIZATION}
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_base.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_homogeneous.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_local_parametrization_quaternion.h
+
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_node_base.h
+
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_sensor_intrinsic_base.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_sensor_odom2d_intrinsic.h
+
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_processor_params_base.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_processor_odom2d_params.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/serialization_processor_odom3d_params.h
+
+    ${CMAKE_CURRENT_SOURCE_DIR}/archives.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/io.h
+
+    PARENT_SCOPE)
diff --git a/src/serialization/cereal/archives.h b/src/serialization/cereal/archives.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8c16fd180ef04049ceedaf268fa33782790d27a
--- /dev/null
+++ b/src/serialization/cereal/archives.h
@@ -0,0 +1,9 @@
+#ifndef _WOLF_IO_CEREAL_ARCHIVE_H_
+#define _WOLF_IO_CEREAL_ARCHIVE_H_
+
+#include <cereal/archives/binary.hpp>
+#include <cereal/archives/json.hpp>
+#include <cereal/archives/portable_binary.hpp>
+#include <cereal/archives/xml.hpp>
+
+#endif /* _WOLF_IO_CEREAL_ARCHIVE_H_ */
diff --git a/src/serialization/cereal/io.h b/src/serialization/cereal/io.h
new file mode 100644
index 0000000000000000000000000000000000000000..afd32843878e43a66674970a69df37dbf6429fe2
--- /dev/null
+++ b/src/serialization/cereal/io.h
@@ -0,0 +1,216 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_IO_H_
+#define _WOLF_SERIALIZATION_CEREAL_IO_H_
+
+#include <stdexcept>
+#include "archives.h"
+
+//#include <cereal/types/tuple.hpp>
+
+namespace wolf {
+namespace serialization {
+
+inline std::string extension(const std::string& file)
+{
+  const std::size_t p = file.find_last_of(".");
+  return (p != std::string::npos) ? file.substr(p) : "";
+}
+
+//struct Extensions
+//{
+//  constexpr static const char* bin  = ".bin";
+//  constexpr static const char* json = ".json";
+//  constexpr static const char* xml  = ".xml";
+
+//  constexpr static const char* fall_back = json;
+//};
+
+//enum class Extensions2 : std::size_t
+//{
+//  BIN = 0,
+////  CBIN,
+//  JSON,
+////  TEXT,
+//  XML,
+//};
+
+//template <char... Chars>
+//struct constexp_str
+//{
+//  using type = constexp_str<Chars...>;
+
+//  virtual ~constexp_str() = default;
+
+//  constexpr static const char value[sizeof...(Chars)+1] = {Chars..., '\0'};
+
+//  constexpr static std::size_t size() { return sizeof...(Chars); }
+
+//  constexpr static const char* c_str() { return &value[0]; }
+
+////  constexpr static bool comp(const std::string& s) { return s == value; }
+
+//  /*constexpr*/ bool operator == (const std::string& s) { return s == value; }
+
+//  constexpr /*static*/ operator const char* ()  { return c_str(); }
+//  constexpr /*static*/ operator std::string& () { return c_str(); }
+//};
+
+struct Extensions
+{
+//  template <char... Chars>
+//  struct EXT : constexp_str<Chars...>
+//  {
+//    //
+//  };
+
+//  struct BIN  : EXT<'.','b','i','n'> { };
+//  struct XML  : EXT<'.','x','m','l'> { };
+//  struct JSON : EXT<'.','j','s','o','n'> { };
+
+  struct EXT { virtual ~EXT() = default; };
+
+  struct BIN : EXT
+  {
+    constexpr static const char* value  = ".bin";
+    bool operator == (const std::string& s) { return value == s; }
+  };
+
+  struct XML : EXT
+  {
+    constexpr static const char* value  = ".xml";
+    bool operator == (const std::string& s) { return value == s; }
+  };
+
+  struct JSON : EXT
+  {
+    constexpr static const char* value  = ".json";
+    bool operator == (const std::string& s) { return value == s; }
+  };
+};
+
+template <typename Ar, typename S, typename T, typename... Args>
+void serialize(S& stream, T&& object, Args&&... args)
+{
+  Ar archive(stream);
+
+  archive( cereal::make_nvp("object", std::forward<T>(object)) );
+  archive( cereal::make_nvp("object", std::forward<Args>(args))... );
+}
+
+template <typename Ar, typename S, typename T>
+void serialize(S& stream, T&& object)
+{
+  Ar archive(stream);
+  archive( cereal::make_nvp("object", std::forward<T>(object)) );
+}
+
+template <typename EXT, typename InAr, typename OutAr>
+struct Serializer
+{
+  template <typename S, typename... T>
+  static void serialize_in(S& stream, T&... object)
+  {
+    serialize<InAr>(stream, object...);
+  }
+
+  template <typename S, typename... T>
+  static void serialize_out(S& stream, T&&... object)
+  {
+    serialize<OutAr>(stream, std::forward<T>(object)...);
+  }
+
+  template <typename... T>
+  static void save(std::string filename, T&&... o)
+  {
+    const std::string ext = serialization::extension(filename);
+
+    if (ext != EXT::value) filename += EXT::value;
+
+    std::ofstream os(filename);
+    serialize_out(os, std::forward<T>(o)...);
+  }
+
+  template <typename... T>
+  static void load(std::string filename, T&... o)
+  {
+    const std::string ext = serialization::extension(filename);
+
+    if (ext != EXT::value) filename += EXT::value;
+
+    std::ifstream is(filename);
+    serialize_in(is, o...);
+  }
+};
+
+using SerializerBin = Serializer<Extensions::BIN,
+                                 cereal::BinaryInputArchive,
+                                 cereal::BinaryOutputArchive>;
+
+using SerializerXML = Serializer<Extensions::XML,
+                                 cereal::XMLInputArchive,
+                                 cereal::XMLOutputArchive>;
+
+using SerializerJSON = Serializer<Extensions::JSON,
+                                  cereal::JSONInputArchive,
+                                  cereal::JSONOutputArchive>;
+
+
+} /* namespace serialization */
+
+template <typename... T>
+void save(const std::string& filename, T&&... o)
+throw(std::runtime_error)
+{
+  const std::string ext = serialization::extension(filename);
+
+  if (ext == serialization::Extensions::BIN::value)
+  {
+    serialization::SerializerBin::save(filename, std::forward<T>(o)...);
+  }
+  else if (ext == serialization::Extensions::JSON::value)
+  {
+    serialization::SerializerJSON::save(filename, std::forward<T>(o)...);
+  }
+  else if (ext == serialization::Extensions::XML::value)
+  {
+    serialization::SerializerXML::save(filename, std::forward<T>(o)...);
+  }
+  else if (ext == "") // falback is json
+  {
+    serialization::SerializerJSON::save(filename, std::forward<T>(o)...);
+  }
+  else
+  {
+    throw std::runtime_error("Unknown file extension : " + filename);
+  }
+}
+
+template <typename... T>
+void load(const std::string& filename, T&... o)
+{
+  const std::string ext = serialization::extension(filename);
+
+  if (ext == serialization::Extensions::BIN::value)
+  {
+    serialization::SerializerBin::load(filename, o...);
+  }
+  else if (ext == serialization::Extensions::XML::value)
+  {
+    serialization::SerializerXML::load(filename, o...);
+  }
+  else if (ext == serialization::Extensions::JSON::value)
+  {
+    serialization::SerializerJSON::load(filename, o...);
+  }
+  else if (ext == "") // falback is json
+  {
+    serialization::SerializerJSON::load(filename, o...);
+  }
+  else
+  {
+    throw std::runtime_error("Unknown file extension : " + filename);
+  }
+}
+
+} /* namespace wolf */
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_IO_H_ */
diff --git a/src/serialization/cereal/serialization_local_parametrization_base.h b/src/serialization/cereal/serialization_local_parametrization_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..b57b9f5649556cf89684810aa162d1495e1258d0
--- /dev/null
+++ b/src/serialization/cereal/serialization_local_parametrization_base.h
@@ -0,0 +1,27 @@
+#ifndef _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_H_
+#define _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_H_
+
+#include "../../local_parametrization_base.h"
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/polymorphic.hpp>
+
+namespace cereal {
+
+// Since classes deriving from LocalParametrizationBase
+// have default constructor calling the non-default
+// LocalParametrizationBase constructor with pre-defined
+// arguments, there is nothing to save here.
+template<class Archive>
+inline void serialize(
+    Archive& /*ar*/,
+    wolf::LocalParametrizationBase& /*lpb*/,
+    std::uint32_t const /*file_version*/)
+{
+  //
+}
+
+
+} //namespace cereal
+
+#endif /* _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_H_ */
diff --git a/src/serialization/cereal/serialization_local_parametrization_homogeneous.h b/src/serialization/cereal/serialization_local_parametrization_homogeneous.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa04a9904eafc13e70d5a68515cf1ae356a18d58
--- /dev/null
+++ b/src/serialization/cereal/serialization_local_parametrization_homogeneous.h
@@ -0,0 +1,27 @@
+#ifndef _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_HOMOGENEOUS_H_
+#define _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_HOMOGENEOUS_H_
+
+#include "../../local_parametrization_homogeneous.h"
+
+#include "serialization_local_parametrization_base.h"
+
+#include <cereal/cereal.hpp>
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::LocalParametrizationHomogeneous,
+                               "LocalParametrizationHomogeneous");
+
+namespace cereal {
+
+template<class Archive>
+inline void serialize(
+    Archive& ar,
+    wolf::LocalParametrizationHomogeneous& lp,
+    std::uint32_t const /*file_version*/)
+{
+  ar( cereal::make_nvp("LocalParametrizationBase",
+                       cereal::base_class<wolf::LocalParametrizationBase>(&lp)) );
+}
+
+} //namespace cereal
+
+#endif /* _WOLF_IO_CEREAL_LOCAL_PARAMETRIZATION_BASE_HOMOGENEOUS_H_ */
diff --git a/src/serialization/cereal/serialization_local_parametrization_quaternion.h b/src/serialization/cereal/serialization_local_parametrization_quaternion.h
new file mode 100644
index 0000000000000000000000000000000000000000..10b04f67cd9de48610f5fc40c0711413d37410a6
--- /dev/null
+++ b/src/serialization/cereal/serialization_local_parametrization_quaternion.h
@@ -0,0 +1,30 @@
+#ifndef WOLF_IO_SERIALIZATION_LOCAL_PARAMETRIZATION_QUATERNION_H_
+#define WOLF_IO_SERIALIZATION_LOCAL_PARAMETRIZATION_QUATERNION_H_
+
+#include "../../local_parametrization_quaternion.h"
+
+#include "serialization_local_parametrization_base.h"
+
+#include <cereal/cereal.hpp>
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::LocalParametrizationQuaternion<wolf::DQ_LOCAL>,
+                               "wolf_LocalParametrizationQuaternion_DQ_LOCAL")
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::LocalParametrizationQuaternion<wolf::DQ_GLOBAL>,
+                               "wolf_LocalParametrizationQuaternion_DQ_GLOBAL")
+
+namespace cereal {
+
+template<class Archive, unsigned int DeltaReference>
+inline void serialize(
+    Archive &ar,
+    wolf::LocalParametrizationQuaternion<DeltaReference> &lp,
+    const unsigned int /*file_version*/)
+{
+  ar( cereal::make_nvp("LocalParametrizationBase",
+                       cereal::base_class<wolf::LocalParametrizationBase>(&lp)) );
+}
+
+} //namespace boost
+
+#endif /* WOLF_IO_SERIALIZATION_LOCAL_PARAMETRIZATION_QUATERNION_H_ */
diff --git a/src/serialization/cereal/serialization_processor_odom2d_params.h b/src/serialization/cereal/serialization_processor_odom2d_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..109fa6c54f8ab5a4f583fb3c3e360124a967dc40
--- /dev/null
+++ b/src/serialization/cereal/serialization_processor_odom2d_params.h
@@ -0,0 +1,29 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM2D_PARAMS_H_
+#define _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM2D_PARAMS_H_
+
+// Wolf includes
+#include "../../processor_odom_2D.h"
+#include "serialization_processor_params_base.h"
+
+namespace cereal {
+
+template <class Archive>
+void serialize(Archive& ar, wolf::ProcessorParamsOdom2D& o,
+               std::uint32_t const /*version*/)
+{
+  ar( cereal::make_nvp("ProcessorParamsBase",
+        cereal::base_class<wolf::ProcessorParamsBase>(&o)) );
+
+  ar( cereal::make_nvp("cov_det_th_",        o.cov_det_th_)        );
+  ar( cereal::make_nvp("dist_traveled_th_",  o.dist_traveled_th_)  );
+  ar( cereal::make_nvp("elapsed_time_th_",   o.elapsed_time_th_)   );
+  ar( cereal::make_nvp("theta_traveled_th_", o.theta_traveled_th_) );
+  ar( cereal::make_nvp("unmeasured_perturbation_std_",
+                       o.unmeasured_perturbation_std_)   );
+}
+
+} // namespace cereal
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::ProcessorParamsOdom2D, "ProcessorParamsOdom2D")
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM3D_PARAMS_H_ */
diff --git a/src/serialization/cereal/serialization_processor_odom3d_params.h b/src/serialization/cereal/serialization_processor_odom3d_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..06770f759cbcf96ca77faf3d83a2a16f0822db04
--- /dev/null
+++ b/src/serialization/cereal/serialization_processor_odom3d_params.h
@@ -0,0 +1,27 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM3D_PARAMS_H_
+#define _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM3D_PARAMS_H_
+
+// Wolf includes
+#include "../../processor_odom_3D.h"
+#include "serialization_processor_params_base.h"
+
+namespace cereal {
+
+template <class Archive>
+void serialize(Archive& ar, wolf::ProcessorOdom3DParams& o,
+               std::uint32_t const /*version*/)
+{
+  ar( cereal::make_nvp("ProcessorParamsBase",
+        cereal::base_class<wolf::ProcessorParamsBase>(&o)) );
+
+  ar( cereal::make_nvp("angle_turned",    o.angle_turned)    );
+  ar( cereal::make_nvp("dist_traveled",   o.dist_traveled)   );
+  ar( cereal::make_nvp("max_buff_length", o.max_buff_length) );
+  ar( cereal::make_nvp("max_time_span",   o.max_time_span)   );
+}
+
+} // namespace cereal
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::ProcessorOdom3DParams, "ProcessorOdom3DParams")
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_PROCESSOR_ODOM3D_PARAMS_H_ */
diff --git a/src/serialization/cereal/serialization_processor_params_base.h b/src/serialization/cereal/serialization_processor_params_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..03cbce7825047da46621a4f3bdf9bb5f8bcb2148
--- /dev/null
+++ b/src/serialization/cereal/serialization_processor_params_base.h
@@ -0,0 +1,22 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_PROCESSOR_PARAM_BASE_H_
+#define _WOLF_SERIALIZATION_CEREAL_PROCESSOR_PARAM_BASE_H_
+
+// Wolf includes
+#include "../../processor_base.h"
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/polymorphic.hpp>
+
+namespace cereal {
+
+template <class Archive>
+void serialize(Archive& ar, wolf::ProcessorParamsBase& o,
+               std::uint32_t const /*version*/)
+{
+  ar( cereal::make_nvp("type", o.type) );
+  ar( cereal::make_nvp("name", o.name) );
+}
+
+} // namespace cereal
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_SENSOR_INTRINSIC_BASE_H_ */
diff --git a/src/serialization/cereal/serialization_sensor_intrinsic_base.h b/src/serialization/cereal/serialization_sensor_intrinsic_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..2398fbad04a33b4934638c0e37d9a9c72588f905
--- /dev/null
+++ b/src/serialization/cereal/serialization_sensor_intrinsic_base.h
@@ -0,0 +1,25 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_SENSOR_INTRINSIC_BASE_H_
+#define _WOLF_SERIALIZATION_CEREAL_SENSOR_INTRINSIC_BASE_H_
+
+// Wolf includes
+#include "../../sensor_base.h"
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/polymorphic.hpp>
+
+namespace cereal {
+
+template <class Archive>
+void serialize(Archive& ar, wolf::IntrinsicsBase& o,
+               std::uint32_t const /*version*/)
+{
+  ar( cereal::make_nvp("type", o.type) );
+  ar( cereal::make_nvp("name", o.name) );
+}
+
+} // namespace cereal
+
+// No need to register base
+//CEREAL_REGISTER_TYPE_WITH_NAME(wolf::IntrinsicsBase, "IntrinsicsBase");
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_SENSOR_INTRINSIC_BASE_H_ */
diff --git a/src/serialization/cereal/serialization_sensor_odom2d_intrinsic.h b/src/serialization/cereal/serialization_sensor_odom2d_intrinsic.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4bf370448af5d4b72ef5d7132b51d5e891647f3
--- /dev/null
+++ b/src/serialization/cereal/serialization_sensor_odom2d_intrinsic.h
@@ -0,0 +1,26 @@
+#ifndef _WOLF_SERIALIZATION_CEREAL_SENSOR_ODOM2D_INTRINSIC_H_
+#define _WOLF_SERIALIZATION_CEREAL_SENSOR_ODOM2D_INTRINSIC_H_
+
+// Wolf includes
+#include "../../sensor_odom_2D.h"
+
+#include "serialization_sensor_intrinsic_base.h"
+
+namespace cereal {
+
+template <class Archive>
+void serialize(Archive& ar, wolf::IntrinsicsOdom2D& o,
+               std::uint32_t const /*version*/)
+{
+  ar( cereal::make_nvp("IntrinsicsBase",
+        cereal::base_class<wolf::IntrinsicsBase>(&o)) );
+
+  ar( cereal::make_nvp("k_disp_to_disp", o.k_disp_to_disp) );
+  ar( cereal::make_nvp("k_rot_to_rot",   o.k_rot_to_rot)   );
+}
+
+} // namespace cereal
+
+CEREAL_REGISTER_TYPE_WITH_NAME(wolf::IntrinsicsOdom2D, "IntrinsicsOdom2D")
+
+#endif /* _WOLF_SERIALIZATION_CEREAL_SENSOR_ODOM2D_INTRINSIC_H_ */
diff --git a/src/singleton.h b/src/singleton.h
index 56450acaf4a738890eb3c98a9aca5d7c0e5dddb5..c50a8da39306e521c11caa3d098a524184b63a75 100644
--- a/src/singleton.h
+++ b/src/singleton.h
@@ -14,49 +14,34 @@ namespace wolf {
 namespace internal {
 
 /**
- * \brief A thread-safer Singleton implementation with
+ * \brief A thread-safer (?) Singleton implementation with
  * argument forwarding.
  **/
 template <class T>
 class Singleton
 {
-  /**
-   * \brief Custom deleter to by-pass private destructor issue.
-   **/
-  struct Deleter;
-
-  using SingletonOPtr = std::unique_ptr<T, Deleter>;
+  using SingletonOPtr = std::unique_ptr<T>;
 
 public:
 
   template <typename... Args>
   static T& get(Args&&... args)
   {
-    static SingletonOPtr instance_(new T(args...));
+    static SingletonOPtr instance_(new T(std::forward<Args>(args)...));
 
     return *instance_;
   }
 
-  constexpr Singleton(const Singleton&)       = delete;
-  //constexpr Singleton(const Singleton&&)      = delete;
+  constexpr Singleton(const Singleton&)  = delete;
+  constexpr Singleton(const Singleton&&) = delete;
 
   constexpr Singleton& operator=(const Singleton&) const = delete;
-  //constexpr Singleton& operator=(const Singleton&&) = delete;
+  constexpr Singleton& operator=(const Singleton&&) = delete;
 
 protected:
 
-  Singleton() = default;
-
-  virtual ~Singleton() = default;
-};
-
-template <class T>
-struct Singleton<T>::Deleter
-{
-  void operator()( const T* const p )
-  {
-    delete p;
-  }
+  constexpr Singleton() = default;
+  virtual ~Singleton()  = default;
 };
 
 } // namespace internal
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 8bd7628d1bf8b7fc4964d53e143b0672c6b5396b..6200ebc3af36d86dea01c639f926007a20728982 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -151,3 +151,7 @@ IF(OpenCV_FOUND)
   wolf_add_gtest(gtest_roi_ORB gtest_roi_ORB.cpp)
   target_link_libraries(gtest_roi_ORB ${PROJECT_NAME})
 ENDIF(OpenCV_FOUND)
+
+# ------- Now Core classes Serialization ----------
+
+add_subdirectory(serialization)
diff --git a/src/test/serialization/CMakeLists.txt b/src/test/serialization/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6902132bd458245e2e45012662fdcf0b348b7d4a
--- /dev/null
+++ b/src/test/serialization/CMakeLists.txt
@@ -0,0 +1,4 @@
+# cereal
+IF(cereal_FOUND)
+  add_subdirectory(cereal)
+ENDIF(cereal_FOUND)
diff --git a/src/test/serialization/cereal/CMakeLists.txt b/src/test/serialization/cereal/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..eb9055fa5c85a252adc5eaef80f1894fb885b09d
--- /dev/null
+++ b/src/test/serialization/cereal/CMakeLists.txt
@@ -0,0 +1,27 @@
+# NodeBase serialization class test
+wolf_add_gtest(gtest_cereal_serialization_node_base gtest_serialization_node_base.cpp)
+target_link_libraries(gtest_cereal_serialization_node_base ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_local_parametrization
+  gtest_serialization_local_parametrization.cpp)
+target_link_libraries(gtest_cereal_serialization_local_parametrization ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_sensor_intrinsic_base
+  gtest_serialization_sensor_intrinsic_base.cpp)
+target_link_libraries(gtest_cereal_serialization_sensor_intrinsic_base ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_sensor_odom2d_intrinsic
+  gtest_serialization_sensor_odom2d_intrinsic.cpp)
+target_link_libraries(gtest_cereal_serialization_sensor_odom2d_intrinsic ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_save_load
+  gtest_serialization_save_load.cpp)
+target_link_libraries(gtest_cereal_serialization_save_load ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_processor_odom3d_params
+  gtest_serialization_processor_odom3d_params.cpp)
+target_link_libraries(gtest_cereal_serialization_processor_odom3d_params ${PROJECT_NAME})
+
+wolf_add_gtest(gtest_cereal_serialization_processor_odom2d_params
+  gtest_serialization_processor_odom2d_params.cpp)
+target_link_libraries(gtest_cereal_serialization_processor_odom2d_params ${PROJECT_NAME})
diff --git a/src/test/serialization/cereal/gtest_serialization_local_parametrization.cpp b/src/test/serialization/cereal/gtest_serialization_local_parametrization.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..667c5d8443ec7ff0e7ecdf9d0ada0f04200db6b8
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_local_parametrization.cpp
@@ -0,0 +1,572 @@
+/*
+ * gtest_node_base_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/serialization_local_parametrization_quaternion.h"
+#include "../../../serialization/cereal/serialization_local_parametrization_homogeneous.h"
+
+#include "../../../serialization/cereal/archives.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+///////////////////////////////////////
+/// LocalParametrizationHomogeneous ///
+///////////////////////////////////////
+
+const std::string path_to_io = "/tmp/";
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousXML)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousPtrXML)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_ptr_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationHomogeneous>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_ptr_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationHomogeneous>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousPtrXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousJSON)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousPtrJSON)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_ptr_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationHomogeneous>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_ptr_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationHomogeneous>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousPtrJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousBIN)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    wolf::LocalParametrizationHomogeneous local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousBIN !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationHomogeneousPtrBIN)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_ptr_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationHomogeneous>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_ptr_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationHomogeneous>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationHomogeneousPtrBIN !\n");
+}
+
+
+//////////////////////////////////////
+/// LocalParametrizationQuaternion ///
+//////////////////////////////////////
+
+//////////////////////////////////////
+///           LOCAL                ///
+//////////////////////////////////////
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionXML)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionPtrXML)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_ptr_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionLocal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_ptr_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionLocal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionPtrXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionJSON)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionPtrJSON)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_ptr_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionLocal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_ptr_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionLocal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionPtrJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionBIN)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionLocal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionBIN !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionPtrBIN)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quat_ptr_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionLocal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quat_ptr_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionLocal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionPtrBIN !\n");
+}
+
+//////////////////////////////////////
+///           GLOBAL               ///
+//////////////////////////////////////
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalXML)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalPtrXML)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_ptr_serialization.xml");
+    cereal::XMLOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionGlobal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_ptr_serialization.xml");
+    cereal::XMLInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionGlobal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalPtrXML !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalJSON)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalPtrJSON)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_ptr_serialization.json");
+    cereal::JSONOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionGlobal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_ptr_serialization.json");
+    cereal::JSONInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionGlobal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalPtrJSON !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalBIN)
+{
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    wolf::LocalParametrizationQuaternionGlobal local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h.getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h.getLocalSize(),  3);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalBIN !\n");
+}
+
+TEST(TestSerialization, SerializationLocalParametrizationQuaternionGlobalPtrBIN)
+{
+  using LocalParametrizationPtr = std::shared_ptr<wolf::LocalParametrizationBase> ;
+
+  {
+    std::ofstream os(path_to_io + "local_parametrization_quatg_ptr_serialization.bin");
+    cereal::BinaryOutputArchive archive(os);
+
+    LocalParametrizationPtr local_param_h =
+        std::make_shared<wolf::LocalParametrizationQuaternionGlobal>();
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "local_parametrization_quatg_ptr_serialization.bin");
+    cereal::BinaryInputArchive archive(is);
+
+    LocalParametrizationPtr local_param_h;
+
+    ASSERT_NO_THROW( archive( local_param_h ) );
+
+    ASSERT_EQ(local_param_h->getGlobalSize(), 4);
+    ASSERT_EQ(local_param_h->getLocalSize(),  3);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::LocalParametrizationQuaternionGlobal>(local_param_h) != nullptr);
+  }
+
+  PRINTF("All good at TestSerialization::SerializationLocalParametrizationQuaternionGlobalPtrBIN !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/serialization/cereal/gtest_serialization_processor_odom2d_params.cpp b/src/test/serialization/cereal/gtest_serialization_processor_odom2d_params.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ca83b3d32366ac7b84b048a2c5d80aa1a474564
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_processor_odom2d_params.cpp
@@ -0,0 +1,108 @@
+/*
+ * gtest_intrinsics_odom2d_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/serialization_processor_odom2d_params.h"
+
+#include "../../../serialization/cereal/io.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+class WolfTestCerealSerializationProcessorParamsOdom2D : public testing::Test
+{
+public:
+
+  WolfTestCerealSerializationProcessorParamsOdom2D()
+  {
+    nb_.name = "NAME";
+    nb_.type = "ODOM 2D";
+
+    nb_.dist_traveled_th_            = 0.17;
+    nb_.theta_traveled_th_           = 0.3;
+    nb_.cov_det_th_                  = 0.4;
+    nb_.elapsed_time_th_             = 1.5;
+    nb_.unmeasured_perturbation_std_ = 1e-5;
+  }
+
+  const std::string path_to_io = "/tmp/";
+  const std::string filename   = "serialization_processor_odom2d_params";
+  const std::string ptr_ext    = "_ptr";
+
+  const std::vector<std::string> exts = {".bin", ".xml", ".json"};
+
+  wolf::ProcessorParamsOdom2D nb_;
+};
+
+TEST_F(WolfTestCerealSerializationProcessorParamsOdom2D,
+       CerealSerializationProcessorParamsOdom2D)
+{
+  for (const auto ext : exts)
+  {
+    const std::string full_path = path_to_io + filename + ext;
+
+    ASSERT_NO_THROW( wolf::save( full_path, nb_ ) )
+        << "Failed on saving " << full_path;
+
+    wolf::ProcessorParamsOdom2D nb_load;
+
+    ASSERT_NO_THROW( wolf::load( full_path, nb_load ) )
+        << "Failed on loading " << full_path;
+
+    ASSERT_EQ(nb_load.type,               nb_.type)               << full_path;
+    ASSERT_EQ(nb_load.name,               nb_.name)               << full_path;
+    ASSERT_EQ(nb_load.dist_traveled_th_,  nb_.dist_traveled_th_)  << full_path;
+    ASSERT_EQ(nb_load.theta_traveled_th_, nb_.theta_traveled_th_) << full_path;
+    ASSERT_EQ(nb_load.cov_det_th_,        nb_.cov_det_th_)        << full_path;
+    ASSERT_EQ(nb_load.unmeasured_perturbation_std_,
+              nb_.unmeasured_perturbation_std_)                   << full_path;
+
+    /// Testing BasePtr
+
+    const std::string ptr_full_path = path_to_io + filename + ptr_ext + ext;
+
+    {
+      wolf::ProcessorParamsBasePtr nb =
+          std::make_shared<wolf::ProcessorParamsOdom2D>(nb_);
+
+      ASSERT_NO_THROW( wolf::save( ptr_full_path, nb ) )
+          << "Failed on saving " << ptr_full_path;
+    }
+
+    {
+      wolf::ProcessorParamsBasePtr nb;
+
+      ASSERT_NO_THROW( wolf::load( ptr_full_path, nb ) )
+          << "Failed on loading " << ptr_full_path;
+
+      wolf::ProcessorParamsOdom2DPtr nb_cast =
+          std::dynamic_pointer_cast<wolf::ProcessorParamsOdom2D>(nb);
+
+      ASSERT_TRUE(nb_cast != nullptr)
+          << "Failed on casting " << ptr_full_path;
+
+      ASSERT_EQ(nb_cast->type,               nb_.type)               << full_path;
+      ASSERT_EQ(nb_cast->name,               nb_.name)               << full_path;
+      ASSERT_EQ(nb_cast->dist_traveled_th_,  nb_.dist_traveled_th_)  << full_path;
+      ASSERT_EQ(nb_cast->theta_traveled_th_, nb_.theta_traveled_th_) << full_path;
+      ASSERT_EQ(nb_cast->cov_det_th_,        nb_.cov_det_th_)        << full_path;
+      ASSERT_EQ(nb_cast->unmeasured_perturbation_std_,
+                nb_.unmeasured_perturbation_std_)                    << full_path;
+    }
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorParamsOdom2D::"
+         "CerealSerializationProcessorParamsOdom2D !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/serialization/cereal/gtest_serialization_processor_odom3d_params.cpp b/src/test/serialization/cereal/gtest_serialization_processor_odom3d_params.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed2aaab3b9b257a708b680db2e38d7b6eb51d592
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_processor_odom3d_params.cpp
@@ -0,0 +1,246 @@
+/*
+ * gtest_intrinsics_odom2d_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/serialization_processor_odom3d_params.h"
+
+#include "../../../serialization/cereal/io.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+class WolfTestCerealSerializationProcessorOdom3DParams : public testing::Test
+{
+public:
+
+  WolfTestCerealSerializationProcessorOdom3DParams()
+  {
+    nb_.name = "NAME";
+    //nb_.type = "ODOM 3D";
+
+    nb_.max_time_span   = 1.5;
+    nb_.max_buff_length = 55.;
+    nb_.dist_traveled   = .25;
+    nb_.angle_turned    = .17;
+  }
+
+  const std::string path_to_io = "/tmp/";
+
+  wolf::ProcessorOdom3DParams nb_;
+};
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsXML)
+{
+  const std::string filename(path_to_io + "params_odom3d_serialization.xml");
+
+  wolf::ProcessorOdom3DParams nb_save;
+  nb_save.name = "NAME2";
+  //nb_.type = "ODOM 3D";
+
+  nb_save.max_time_span   = 2.5;
+  nb_save.max_buff_length = 52.;
+  nb_save.dist_traveled   = .24;
+  nb_save.angle_turned    = .18;
+
+  ASSERT_NO_THROW( wolf::save( filename, nb_, nb_save, 10 ) );
+
+  {
+    wolf::ProcessorOdom3DParams nb_load;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb_load ) );
+
+    ASSERT_EQ(nb_load.type, nb_.type);
+    ASSERT_EQ(nb_load.name, nb_.name);
+    ASSERT_EQ(nb_load.max_time_span,   nb_.max_time_span);
+    ASSERT_EQ(nb_load.max_buff_length, nb_.max_buff_length);
+    ASSERT_EQ(nb_load.dist_traveled,   nb_.dist_traveled);
+    ASSERT_EQ(nb_load.angle_turned,    nb_.angle_turned);
+
+    wolf::ProcessorOdom3DParams nb_load0, nb_load1;
+    int myint;
+    ASSERT_NO_THROW( wolf::load( filename, nb_load0, nb_load1, myint ) );
+
+    ASSERT_EQ(nb_load0.type, nb_.type);
+    ASSERT_EQ(nb_load0.name, nb_.name);
+    ASSERT_EQ(nb_load0.max_time_span,   nb_.max_time_span);
+    ASSERT_EQ(nb_load0.max_buff_length, nb_.max_buff_length);
+    ASSERT_EQ(nb_load0.dist_traveled,   nb_.dist_traveled);
+    ASSERT_EQ(nb_load0.angle_turned,    nb_.angle_turned);
+
+    ASSERT_EQ(nb_load1.type, nb_save.type);
+    ASSERT_EQ(nb_load1.name, nb_save.name);
+    ASSERT_EQ(nb_load1.max_time_span,   nb_save.max_time_span);
+    ASSERT_EQ(nb_load1.max_buff_length, nb_save.max_buff_length);
+    ASSERT_EQ(nb_load1.dist_traveled,   nb_save.dist_traveled);
+    ASSERT_EQ(nb_load1.angle_turned,    nb_save.angle_turned);
+
+    ASSERT_EQ(myint, 10);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsPtrXML)
+{
+  const std::string filename(path_to_io + "params_odom3d_ptr_serialization.xml");
+
+  {
+    wolf::ProcessorParamsBasePtr nb =
+        std::make_shared<wolf::ProcessorOdom3DParams>(nb_);
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::ProcessorParamsBasePtr nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    wolf::ProcessorOdom3DParamsPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::ProcessorOdom3DParams>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->max_time_span,   nb_.max_time_span);
+    ASSERT_EQ(nb_cast->max_buff_length, nb_.max_buff_length);
+    ASSERT_EQ(nb_cast->dist_traveled,   nb_.dist_traveled);
+    ASSERT_EQ(nb_cast->angle_turned,    nb_.angle_turned);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsPtrXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsJSON)
+{
+  const std::string filename(path_to_io + "params_odom3d_serialization.json");
+
+  ASSERT_NO_THROW( wolf::save( filename, nb_ ) );
+
+  wolf::ProcessorOdom3DParams nb_load;
+
+  ASSERT_NO_THROW( wolf::load( filename, nb_load ) );
+
+  ASSERT_EQ(nb_load.type, nb_.type);
+  ASSERT_EQ(nb_load.name, nb_.name);
+  ASSERT_EQ(nb_load.max_time_span,   nb_.max_time_span);
+  ASSERT_EQ(nb_load.max_buff_length, nb_.max_buff_length);
+  ASSERT_EQ(nb_load.dist_traveled,   nb_.dist_traveled);
+  ASSERT_EQ(nb_load.angle_turned,    nb_.angle_turned);
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsPtrJSON)
+{
+  const std::string filename(path_to_io + "params_odom3d_ptr_serialization.json");
+
+  {
+    wolf::ProcessorParamsBasePtr nb =
+        std::make_shared<wolf::ProcessorOdom3DParams>(nb_);
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::ProcessorParamsBasePtr nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    wolf::ProcessorOdom3DParamsPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::ProcessorOdom3DParams>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->max_time_span,   nb_.max_time_span);
+    ASSERT_EQ(nb_cast->max_buff_length, nb_.max_buff_length);
+    ASSERT_EQ(nb_cast->dist_traveled,   nb_.dist_traveled);
+    ASSERT_EQ(nb_cast->angle_turned,    nb_.angle_turned);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsPtrJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsBinary)
+{
+  const std::string filename(path_to_io + "params_odom3d_serialization.bin");
+
+  ASSERT_NO_THROW( wolf::save( filename, nb_ ) );
+
+  wolf::ProcessorOdom3DParams nb_load;
+
+  ASSERT_NO_THROW( wolf::load( filename, nb_load ) );
+
+  ASSERT_EQ(nb_load.type, nb_.type);
+  ASSERT_EQ(nb_load.name, nb_.name);
+  ASSERT_EQ(nb_load.max_time_span,   nb_.max_time_span);
+  ASSERT_EQ(nb_load.max_buff_length, nb_.max_buff_length);
+  ASSERT_EQ(nb_load.dist_traveled,   nb_.dist_traveled);
+  ASSERT_EQ(nb_load.angle_turned,    nb_.angle_turned);
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsBinary !\n");
+}
+
+TEST_F(WolfTestCerealSerializationProcessorOdom3DParams,
+       CerealSerializationProcessorOdom3DParamsPtrBinary)
+{
+  const std::string filename(path_to_io + "params_odom3d_ptr_serialization.bin");
+
+  {
+    wolf::ProcessorParamsBasePtr nb =
+        std::make_shared<wolf::ProcessorOdom3DParams>(nb_);
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::ProcessorParamsBasePtr nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    wolf::ProcessorOdom3DParamsPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::ProcessorOdom3DParams>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->max_time_span,   nb_.max_time_span);
+    ASSERT_EQ(nb_cast->max_buff_length, nb_.max_buff_length);
+    ASSERT_EQ(nb_cast->dist_traveled,   nb_.dist_traveled);
+    ASSERT_EQ(nb_cast->angle_turned,    nb_.angle_turned);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationProcessorOdom3DParams::"
+         "CerealSerializationProcessorOdom3DParamsPtrBinary !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/serialization/cereal/gtest_serialization_save_load.cpp b/src/test/serialization/cereal/gtest_serialization_save_load.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..23241af4887a43db6d48f027b30481e3408ade49
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_save_load.cpp
@@ -0,0 +1,202 @@
+/*
+ * gtest_intrinsics_odom2d_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/io.h"
+#include "../../../serialization/cereal/serialization_sensor_odom2d_intrinsic.h"
+
+#include "../../../serialization/cereal/archives.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+namespace wolf {
+
+using IntrinsicsOdom2DPtr = std::shared_ptr<IntrinsicsOdom2D>;
+
+}
+
+class WolfTestCerealSerializationSaveLoad : public testing::Test
+{
+public:
+
+  WolfTestCerealSerializationSaveLoad()
+  {
+    //
+  }
+
+  const std::string path_to_io = "/tmp/";
+
+  decltype(std::declval<wolf::IntrinsicsOdom2D>().type) nb_type = "TYPE";
+  decltype(std::declval<wolf::IntrinsicsOdom2D>().name) nb_name = "NAME";
+  decltype(std::declval<wolf::IntrinsicsOdom2D>().k_disp_to_disp) nb_k_disp_to_disp = 0.54;
+  decltype(std::declval<wolf::IntrinsicsOdom2D>().k_rot_to_rot) nb_k_rot_to_rot   = 0.18;
+};
+
+TEST_F(WolfTestCerealSerializationSaveLoad, CerealSerializationSaveLoadExtension)
+{
+  const std::string xml  = "/test/filename.xml";
+  const std::string bin  = "/test/filename.bin";
+  const std::string json = "/test/filename.json";
+
+  ASSERT_EQ(wolf::serialization::extension(xml),  ".xml");
+  ASSERT_EQ(wolf::serialization::extension(bin),  ".bin");
+  ASSERT_EQ(wolf::serialization::extension(json), ".json");
+}
+
+TEST_F(WolfTestCerealSerializationSaveLoad,
+       CerealSerializationSaveLoadXML)
+{
+  const std::string filename = path_to_io + "save_load_serialization.xml";
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+    nb.k_disp_to_disp = nb_k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_k_rot_to_rot;
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationSaveLoad::"
+         "CerealSerializationSaveLoadXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationSaveLoad,
+       CerealSerializationSaveLoadJSON)
+{
+  const std::string filename = path_to_io + "save_load_serialization.json";
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+    nb.k_disp_to_disp = nb_k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_k_rot_to_rot;
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationSaveLoad::"
+         "CerealSerializationSaveLoadJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationSaveLoad,
+       CerealSerializationSaveLoadBinary)
+{
+  const std::string filename = path_to_io + "save_load_serialization.bin";
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+    nb.k_disp_to_disp = nb_k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_k_rot_to_rot;
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationSaveLoad::"
+         "CerealSerializationSaveLoadBinary !\n");
+}
+
+TEST_F(WolfTestCerealSerializationSaveLoad,
+       CerealSerializationSaveLoadNoExt)
+{
+  const std::string filename = path_to_io + "save_load_serialization_no_ext";
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+    nb.k_disp_to_disp = nb_k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_k_rot_to_rot;
+
+    ASSERT_NO_THROW( wolf::save( filename, nb ) );
+  }
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( wolf::load( filename, nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationSaveLoad::"
+         "CerealSerializationSaveLoadNoExt !\n");
+}
+
+TEST_F(WolfTestCerealSerializationSaveLoad,
+       CerealSerializationSaveLoadUnknownExt)
+{
+  const std::string filename = path_to_io + "save_load_serialization.foo";
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_THROW( wolf::save( filename, nb ), std::runtime_error );
+  }
+
+  {
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_THROW( wolf::load( filename, nb ), std::runtime_error );
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationSaveLoad::"
+         "CerealSerializationSaveLoadUnknownExt !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/serialization/cereal/gtest_serialization_sensor_intrinsic_base.cpp b/src/test/serialization/cereal/gtest_serialization_sensor_intrinsic_base.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a8a67dc1977d184a91a26cae2420f1a04ef5a0ee
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_sensor_intrinsic_base.cpp
@@ -0,0 +1,233 @@
+/*
+ * gtest_intrinsics_base_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/serialization_sensor_intrinsic_base.h"
+
+#include "../../../serialization/cereal/archives.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+class WolfTestCerealSerializationIntrinsicsBase : public testing::Test
+{
+public:
+
+  WolfTestCerealSerializationIntrinsicsBase()
+  {
+    //
+  }
+
+  const std::string path_to_io = "/tmp/";
+
+  decltype(std::declval<wolf::IntrinsicsBase>().type) nb_type = "TYPE";
+  decltype(std::declval<wolf::IntrinsicsBase>().name) nb_name = "NAME";
+};
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase,
+       CerealSerializationIntrinsicsBaseXML)
+{
+  {
+    wolf::IntrinsicsBase nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+
+    std::ofstream os(path_to_io + "intrinsics_base_serialization.xml");
+    cereal::XMLOutputArchive xml_archive(os);
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_serialization.xml");
+    cereal::XMLInputArchive xml_archive(is);
+
+    wolf::IntrinsicsBase nb;
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBaseXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase,
+       CerealSerializationIntrinsicsBasePtrXML)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsBase>();
+    nb->name = nb_name;
+    nb->type = nb_type;
+
+    std::ofstream os(path_to_io + "intrinsics_base_ptr_serialization.xml");
+    cereal::XMLOutputArchive xml_archive(os);
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_ptr_serialization.xml");
+    cereal::XMLInputArchive xml_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+
+    ASSERT_EQ(nb->type, nb_type);
+    ASSERT_EQ(nb->name, nb_name);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::IntrinsicsBase>(nb) != nullptr);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBasePtrXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase,
+       CerealSerializationIntrinsicsBaseJSON)
+{
+  {
+    wolf::IntrinsicsBase nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+
+    std::ofstream os(path_to_io + "intrinsics_base_serialization.json");
+    cereal::JSONOutputArchive json_archive(os);
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_serialization.json");
+    cereal::JSONInputArchive json_archive(is);
+
+    wolf::IntrinsicsBase nb;
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBaseJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase,
+       CerealSerializationIntrinsicsBasePtrJSON)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsBase>();
+    nb->name = nb_name;
+    nb->type = nb_type;
+
+    std::ofstream os(path_to_io + "intrinsics_base_ptr_serialization.json");
+    cereal::JSONOutputArchive json_archive(os);
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_ptr_serialization.json");
+    cereal::JSONInputArchive json_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+
+    ASSERT_EQ(nb->type, nb_type);
+    ASSERT_EQ(nb->name, nb_name);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::IntrinsicsBase>(nb) != nullptr);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBasePtrJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase,
+       CerealSerializationIntrinsicsBaseBinary)
+{
+  {
+    wolf::IntrinsicsBase nb;
+    nb.type = nb_type;
+    nb.name = nb_name;
+
+    std::ofstream os(path_to_io + "intrinsics_base_serialization.bin");
+    cereal::BinaryOutputArchive bin_archive(os);
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_serialization.bin");
+    cereal::BinaryInputArchive bin_archive(is);
+
+    wolf::IntrinsicsBase nb;
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_type);
+    ASSERT_EQ(nb.name, nb_name);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBaseBinary !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsBase, CerealSerializationIntrinsicsBasePtrBinary)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsBase>();
+    nb->name = nb_name;
+    nb->type = nb_type;
+
+    std::ofstream os(path_to_io + "intrinsics_base_ptr_serialization.bin");
+    cereal::BinaryOutputArchive bin_archive(os);
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_base_ptr_serialization.bin");
+    cereal::BinaryInputArchive bin_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+
+    ASSERT_EQ(nb->type, nb_type);
+    ASSERT_EQ(nb->name, nb_name);
+
+    ASSERT_TRUE(
+          std::dynamic_pointer_cast<
+          wolf::IntrinsicsBase>(nb) != nullptr);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsBase::"
+         "CerealSerializationIntrinsicsBasePtrBinary !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/serialization/cereal/gtest_serialization_sensor_odom2d_intrinsic.cpp b/src/test/serialization/cereal/gtest_serialization_sensor_odom2d_intrinsic.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c5891c3d91d020293937236e582535ddd2e2beaf
--- /dev/null
+++ b/src/test/serialization/cereal/gtest_serialization_sensor_odom2d_intrinsic.cpp
@@ -0,0 +1,256 @@
+/*
+ * gtest_intrinsics_odom2d_serialization.cpp
+ *
+ *  Created on: Jul 16, 2017
+ *      Author: Jeremie Deray
+ */
+
+#include "../../utils_gtest.h"
+
+#include "../../../serialization/cereal/serialization_sensor_odom2d_intrinsic.h"
+
+#include "../../../serialization/cereal/archives.h"
+
+#include <cereal/types/memory.hpp>
+#include <fstream>
+
+namespace wolf {
+
+using IntrinsicsOdom2DPtr = std::shared_ptr<IntrinsicsOdom2D>;
+
+}
+
+class WolfTestCerealSerializationIntrinsicsOdom2D : public testing::Test
+{
+public:
+
+  WolfTestCerealSerializationIntrinsicsOdom2D()
+  {
+    nb_.k_disp_to_disp = 0.54;
+    nb_.k_rot_to_rot = 0.18;
+    nb_.name = "NAME";
+    nb_.type = "TYPE";
+  }
+
+  const std::string path_to_io = "/tmp/";
+
+  wolf::IntrinsicsOdom2D nb_;
+};
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D,
+       CerealSerializationIntrinsicsOdom2DXML)
+{
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_.type;
+    nb.name = nb_.name;
+    nb.k_disp_to_disp = nb_.k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_.k_rot_to_rot;
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_serialization.xml");
+    cereal::XMLOutputArchive xml_archive(os);
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_serialization.xml");
+    cereal::XMLInputArchive xml_archive(is);
+
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_.type);
+    ASSERT_EQ(nb.name, nb_.name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D,
+       CerealSerializationIntrinsicsOdom2DPtrXML)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsOdom2D>(nb_);
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_ptr_serialization.xml");
+    cereal::XMLOutputArchive xml_archive(os);
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_ptr_serialization.xml");
+    cereal::XMLInputArchive xml_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( xml_archive( nb ) );
+
+    wolf::IntrinsicsOdom2DPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::IntrinsicsOdom2D>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb_cast->k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DPtrXML !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D,
+       CerealSerializationIntrinsicsOdom2DJSON)
+{
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_.type;
+    nb.name = nb_.name;
+    nb.k_disp_to_disp = nb_.k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_.k_rot_to_rot;
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_serialization.json");
+    cereal::JSONOutputArchive json_archive(os);
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_serialization.json");
+    cereal::JSONInputArchive json_archive(is);
+
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_.type);
+    ASSERT_EQ(nb.name, nb_.name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D,
+       CerealSerializationIntrinsicsOdom2DPtrJSON)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsOdom2D>(nb_);
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_ptr_serialization.json");
+    cereal::JSONOutputArchive json_archive(os);
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_ptr_serialization.json");
+    cereal::JSONInputArchive json_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( json_archive( nb ) );
+
+    wolf::IntrinsicsOdom2DPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::IntrinsicsOdom2D>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb_cast->k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DPtrJSON !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D,
+       CerealSerializationIntrinsicsOdom2DBinary)
+{
+  {
+    wolf::IntrinsicsOdom2D nb;
+    nb.type = nb_.type;
+    nb.name = nb_.name;
+    nb.k_disp_to_disp = nb_.k_disp_to_disp;
+    nb.k_rot_to_rot   = nb_.k_rot_to_rot;
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_serialization.bin");
+    cereal::BinaryOutputArchive bin_archive(os);
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_serialization.bin");
+    cereal::BinaryInputArchive bin_archive(is);
+
+    wolf::IntrinsicsOdom2D nb;
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+
+    ASSERT_EQ(nb.type, nb_.type);
+    ASSERT_EQ(nb.name, nb_.name);
+    ASSERT_EQ(nb.k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb.k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DBinary !\n");
+}
+
+TEST_F(WolfTestCerealSerializationIntrinsicsOdom2D, CerealSerializationIntrinsicsOdom2DPtrBinary)
+{
+  {
+    wolf::IntrinsicsBasePtr nb = std::make_shared<wolf::IntrinsicsOdom2D>(nb_);
+
+    std::ofstream os(path_to_io + "intrinsics_odom2d_ptr_serialization.bin");
+    cereal::BinaryOutputArchive bin_archive(os);
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+  }
+
+  {
+    std::ifstream is(path_to_io + "intrinsics_odom2d_ptr_serialization.bin");
+    cereal::BinaryInputArchive bin_archive(is);
+
+    wolf::IntrinsicsBasePtr nb;
+
+    ASSERT_NO_THROW( bin_archive( nb ) );
+
+    wolf::IntrinsicsOdom2DPtr nb_cast =
+        std::dynamic_pointer_cast<wolf::IntrinsicsOdom2D>(nb);
+
+    ASSERT_TRUE(nb_cast != nullptr);
+
+    ASSERT_EQ(nb_cast->type, nb_.type);
+    ASSERT_EQ(nb_cast->name, nb_.name);
+    ASSERT_EQ(nb_cast->k_disp_to_disp, nb_.k_disp_to_disp);
+    ASSERT_EQ(nb_cast->k_rot_to_rot,   nb_.k_rot_to_rot);
+  }
+
+  PRINTF("All good at "
+         "WolfTestCerealSerializationIntrinsicsOdom2D::"
+         "CerealSerializationIntrinsicsOdom2DPtrBinary !\n");
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}