diff --git a/.gitignore b/.gitignore
index 94d4918bdec0d0d02df589c529d938e6c87d72d4..b690efc9b285d63727f435a9db3ee8b2039aee82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,5 @@ src/examples/map_apriltag_save.yaml
 \.vscode/
 build_release/
 .clangd
-wolf.found
+wolfcore.found
+/wolf.found
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6e7ee166720a726fc6c9178acc4119e0c4286e9..b84a4aa218a28e25b767d517f055f0c901bf8e8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,7 +10,8 @@ SET(CMAKE_MACOSX_RPATH 1)
 
 
 # The project name
-PROJECT(wolf)
+PROJECT(core)
+set(PLUGIN_NAME "wolf${PROJECT_NAME}")
 
 #string(COMPARE EQUAL "${CMAKE_BINARY_DIR}" "" result)
 #IF(result)
@@ -421,7 +422,7 @@ IF (Suitesparse_FOUND)
 ENDIF(Suitesparse_FOUND)
 
 # create the shared library
-ADD_LIBRARY(${PROJECT_NAME}
+ADD_LIBRARY(${PLUGIN_NAME}
   SHARED
   ${SRCS}
   ${SRCS_BASE}
@@ -450,24 +451,24 @@ ADD_LIBRARY(${PROJECT_NAME}
 # ====================  
 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
   message(STATUS "Using C++ compiler clang")
-  target_compile_options(${PROJECT_NAME} PRIVATE -Winconsistent-missing-override)
+  target_compile_options(${PLUGIN_NAME} PRIVATE -Winconsistent-missing-override)
   # using Clang
 elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
   message(STATUS "Using C++ compiler gnu")
-  target_compile_options(${PROJECT_NAME} PRIVATE -Wsuggest-override)
+  target_compile_options(${PLUGIN_NAME} PRIVATE -Wsuggest-override)
   # using GCC
 endif()
 
 #Link the created libraries
 #=============================================================
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT} dl)
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${YAMLCPP_LIBRARY})
+TARGET_LINK_LIBRARIES(${PLUGIN_NAME} ${CMAKE_THREAD_LIBS_INIT} dl)
+TARGET_LINK_LIBRARIES(${PLUGIN_NAME} ${YAMLCPP_LIBRARY})
 IF (Ceres_FOUND)
-    TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CERES_LIBRARIES})
+    TARGET_LINK_LIBRARIES(${PLUGIN_NAME} ${CERES_LIBRARIES})
 ENDIF(Ceres_FOUND)
 
 # IF (GLOG_FOUND)
-#     TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${GLOG_LIBRARY})
+#     TARGET_LINK_LIBRARIES(${PLUGIN_NAME} ${GLOG_LIBRARY})
 # ENDIF (GLOG_FOUND)
 #check if this is done correctly
 
@@ -486,12 +487,12 @@ ENDIF(BUILD_DEMOS)
 #install library
 
 #=============================================================
-INSTALL(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets
+INSTALL(TARGETS ${PLUGIN_NAME} EXPORT ${PLUGIN_NAME}Targets
   RUNTIME DESTINATION bin
   LIBRARY DESTINATION lib/iri-algorithms
   ARCHIVE DESTINATION lib/iri-algorithms)
 
-install(EXPORT ${PROJECT_NAME}Targets DESTINATION lib/cmake/${PROJECT_NAME})
+install(EXPORT ${PLUGIN_NAME}Targets DESTINATION lib/cmake/${PLUGIN_NAME})
 #install headers
 INSTALL(FILES ${HDRS_CAPTURE}
    DESTINATION include/iri-algorithms/wolf/plugin_core/core/capture)
@@ -536,13 +537,13 @@ INSTALL(FILES ${HDRS_WRAPPER}
 INSTALL(FILES ${HDRS_YAML}
   DESTINATION include/iri-algorithms/wolf/plugin_core/core/yaml)
 
-FILE(WRITE ${PROJECT_NAME}.found "")
-INSTALL(FILES ${PROJECT_NAME}.found
+FILE(WRITE ${PLUGIN_NAME}.found "")
+INSTALL(FILES ${PLUGIN_NAME}.found
   DESTINATION include/iri-algorithms/wolf/plugin_core)
 
 #install Find*.cmake
-configure_file("${CMAKE_SOURCE_DIR}/cmake_modules/wolfConfig.cmake"
-               "${CMAKE_BINARY_DIR}/wolfConfig.cmake" @ONLY)
+configure_file("${CMAKE_SOURCE_DIR}/cmake_modules/${PLUGIN_NAME}Config.cmake"
+               "${CMAKE_BINARY_DIR}/${PLUGIN_NAME}Config.cmake" @ONLY)
 
 configure_file("${CMAKE_SOURCE_DIR}/cmake_modules/FindYamlCpp.cmake"
                "${CMAKE_BINARY_DIR}/FindYamlCpp.cmake" @ONLY)
@@ -550,12 +551,12 @@ configure_file("${CMAKE_SOURCE_DIR}/cmake_modules/FindYamlCpp.cmake"
 INSTALL(FILES "${WOLF_CONFIG_DIR}/config.h"
   DESTINATION include/iri-algorithms/wolf/plugin_core/core/internal)
 
-INSTALL(FILES "${CMAKE_BINARY_DIR}/wolfConfig.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}")
-INSTALL(FILES "${CMAKE_BINARY_DIR}/FindYamlCpp.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}")
+INSTALL(FILES "${CMAKE_BINARY_DIR}/${PLUGIN_NAME}Config.cmake" DESTINATION "lib/cmake/${PLUGIN_NAME}")
+INSTALL(FILES "${CMAKE_BINARY_DIR}/FindYamlCpp.cmake" DESTINATION "lib/cmake/${PLUGIN_NAME}")
 
 INSTALL(DIRECTORY ${SPDLOG_INCLUDE_DIRS} DESTINATION "include/iri-algorithms/")
 
-export(PACKAGE ${PROJECT_NAME})
+export(PACKAGE ${PLUGIN_NAME})
 
 #-END_SRC --------------------------------------------------------------------------------------------------------------------------------
 FIND_PACKAGE(Doxygen)
@@ -601,8 +602,8 @@ ELSE(UNIX)
 ENDIF(UNIX)
 
 IF (UNIX)
-  SET(CPACK_PACKAGE_FILE_NAME "iri-${PROJECT_NAME}-dev-${CPACK_PACKAGE_VERSION}${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
-  SET(CPACK_PACKAGE_NAME "iri-${PROJECT_NAME}-dev")
+  SET(CPACK_PACKAGE_FILE_NAME "iri-${PLUGIN_NAME}-dev-${CPACK_PACKAGE_VERSION}${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+  SET(CPACK_PACKAGE_NAME "iri-${PLUGIN_NAME}-dev")
   SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "...Enter something here...")
   SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
   SET(CPACK_GENERATOR "DEB")
diff --git a/cmake_modules/wolfConfig.cmake b/cmake_modules/wolfConfig.cmake
deleted file mode 100644
index 74ede89df7d20ffdfe00d7cd669bce317fc501a9..0000000000000000000000000000000000000000
--- a/cmake_modules/wolfConfig.cmake
+++ /dev/null
@@ -1,99 +0,0 @@
-#edit the following line to add the librarie's header files
-FIND_PATH(
-    wolf_INCLUDE_DIRS
-    NAMES wolf.found
-    PATHS /usr/local/include/iri-algorithms/wolf/plugin_core)
-IF(wolf_INCLUDE_DIRS)
-  MESSAGE("Found wolf include dirs: ${wolf_INCLUDE_DIRS}")
-ELSE(wolf_INCLUDE_DIRS)
-  MESSAGE("Couldn't find wolf include dirs")
-ENDIF(wolf_INCLUDE_DIRS)
-
-FIND_LIBRARY(
-    wolf_LIBRARIES
-    NAMES libwolf.so libwolf.dylib
-    PATHS /usr/local/lib/iri-algorithms)
-IF(wolf_LIBRARIES)
-  MESSAGE("Found wolf lib: ${wolf_LIBRARIES}")
-ELSE(wolf_LIBRARIES)
-  MESSAGE("Couldn't find wolf lib")
-ENDIF(wolf_LIBRARIES)
-
-IF (wolf_INCLUDE_DIRS AND wolf_LIBRARIES)
-   SET(wolf_FOUND TRUE)
- ELSE(wolf_INCLUDE_DIRS AND wolf_LIBRARIES)
-   set(wolf_FOUND FALSE)
-ENDIF (wolf_INCLUDE_DIRS AND wolf_LIBRARIES)
-
-IF (wolf_FOUND)
-   IF (NOT wolf_FIND_QUIETLY)
-      MESSAGE(STATUS "Found wolf: ${wolf_LIBRARIES}")
-   ENDIF (NOT wolf_FIND_QUIETLY)
-ELSE (wolf_FOUND)
-   IF (wolf_FIND_REQUIRED)
-      MESSAGE(FATAL_ERROR "Could not find wolf")
-   ENDIF (wolf_FIND_REQUIRED)
-ENDIF (wolf_FOUND)
-
-
-macro(wolf_report_not_found REASON_MSG)
-  set(wolf_FOUND FALSE)
-  unset(wolf_INCLUDE_DIRS)
-  unset(wolf_LIBRARIES)
-
-  # Reset the CMake module path to its state when this script was called.
-  set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
-
-  # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by
-  # FindPackage() use the camelcase library name, not uppercase.
-  if (wolf_FIND_QUIETLY)
-    message(STATUS "Failed to find wolf- " ${REASON_MSG} ${ARGN})
-  else (wolf_FIND_REQUIRED)
-    message(FATAL_ERROR "Failed to find wolf - " ${REASON_MSG} ${ARGN})
-  else()
-    # Neither QUIETLY nor REQUIRED, use SEND_ERROR which emits an error
-    # that prevents generation, but continues configuration.
-    message(SEND_ERROR "Failed to find wolf - " ${REASON_MSG} ${ARGN})
-  endif ()
-  return()
-endmacro(wolf_report_not_found)
-
-if(NOT wolf_FOUND)
-  wolf_report_not_found("Something went wrong while setting up wolf.")
-endif(NOT wolf_FOUND)
-# Set the include directories for wolf (itself).
-set(wolf_FOUND TRUE)
-
-# Now we gather all the required dependencies for Wolf
-
-get_filename_component(WOLF_CURRENT_CONFIG_DIR
-  "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-SET(BACKUP_MODULE_PATH ${CMAKE_MODULE_PATH})
-LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${WOLF_CURRENT_CONFIG_DIR})
-
-FIND_PACKAGE(Threads REQUIRED)
-list(APPEND wolf_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
-
-FIND_PACKAGE(Ceres REQUIRED)
-list(APPEND wolf_INCLUDE_DIRS ${CERES_INCLUDE_DIRS})
-list(APPEND wolf_LIBRARIES ${CERES_LIBRARIES})
-
-# YAML with yaml-cpp
-FIND_PACKAGE(YamlCpp REQUIRED)
-list(APPEND wolf_INCLUDE_DIRS ${YAMLCPP_INCLUDE_DIRS})
-list(APPEND wolf_LIBRARIES ${YAMLCPP_LIBRARY})
-
-#Eigen
-# FIND_PACKAGE(Eigen3 REQUIRED)
-# list(APPEND wolf_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
-
-if(NOT Eigen3_FOUND)
-  FIND_PACKAGE(Eigen3 REQUIRED)
-endif()
-if(${EIGEN3_VERSION_STRING} VERSION_LESS 3.3)
-  message(FATAL_ERROR "Found Eigen ${EIGEN3_VERSION_STRING}. The minimum version required is Eigen 3.3")
-endif()
-list(APPEND wolf_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
-
-SET(CMAKE_MODULE_PATH ${BACKUP_MODULE_PATH})
diff --git a/cmake_modules/wolfcoreConfig.cmake b/cmake_modules/wolfcoreConfig.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b4df7e15bab20bc8d1090ffbd5428ac7a3ab5cd6
--- /dev/null
+++ b/cmake_modules/wolfcoreConfig.cmake
@@ -0,0 +1,99 @@
+#edit the following line to add the librarie's header files
+FIND_PATH(
+    wolfcore_INCLUDE_DIRS
+    NAMES wolfcore.found
+    PATHS /usr/local/include/iri-algorithms/wolf/plugin_core)
+IF(wolfcore_INCLUDE_DIRS)
+  MESSAGE("Found wolf core include dirs: ${wolfcore_INCLUDE_DIRS}")
+ELSE(wolfcore_INCLUDE_DIRS)
+  MESSAGE("Couldn't find wolf core include dirs")
+ENDIF(wolfcore_INCLUDE_DIRS)
+
+FIND_LIBRARY(
+    wolfcore_LIBRARIES
+    NAMES libwolfcore.so libwolfcore.dylib
+    PATHS /usr/local/lib/iri-algorithms)
+IF(wolfcore_LIBRARIES)
+  MESSAGE("Found wolf core lib: ${wolfcore_LIBRARIES}")
+ELSE(wolfcore_LIBRARIES)
+  MESSAGE("Couldn't find wolf core lib")
+ENDIF(wolfcore_LIBRARIES)
+
+IF (wolfcore_INCLUDE_DIRS AND wolfcore_LIBRARIES)
+   SET(wolfcore_FOUND TRUE)
+ ELSE(wolfcore_INCLUDE_DIRS AND wolfcore_LIBRARIES)
+   set(wolfcore_FOUND FALSE)
+ENDIF (wolfcore_INCLUDE_DIRS AND wolfcore_LIBRARIES)
+
+IF (wolfcore_FOUND)
+   IF (NOT wolfcore_FIND_QUIETLY)
+      MESSAGE(STATUS "Found wolf core: ${wolfcore_LIBRARIES}")
+   ENDIF (NOT wolfcore_FIND_QUIETLY)
+ELSE (wolfcore_FOUND)
+   IF (wolfcore_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find wolf core")
+   ENDIF (wolfcore_FIND_REQUIRED)
+ENDIF (wolfcore_FOUND)
+
+
+macro(wolfcore_report_not_found REASON_MSG)
+  set(wolfcore_FOUND FALSE)
+  unset(wolfcore_INCLUDE_DIRS)
+  unset(wolfcore_LIBRARIES)
+
+  # Reset the CMake module path to its state when this script was called.
+  set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
+
+  # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by
+  # FindPackage() use the camelcase library name, not uppercase.
+  if (wolfcore_FIND_QUIETLY)
+    message(STATUS "Failed to find wolf core - " ${REASON_MSG} ${ARGN})
+  elseif (wolfcore_FIND_REQUIRED)
+    message(FATAL_ERROR "Failed to find wolf core - " ${REASON_MSG} ${ARGN})
+  else()
+    # Neither QUIETLY nor REQUIRED, use SEND_ERROR which emits an error
+    # that prevents generation, but continues configuration.
+    message(SEND_ERROR "Failed to find wolf core - " ${REASON_MSG} ${ARGN})
+  endif ()
+  return()
+endmacro(wolfcore_report_not_found)
+
+if(NOT wolfcore_FOUND)
+  wolfcore_report_not_found("Something went wrong while setting up wolf.")
+else (NOT wolfcore_FOUND)
+  # Set the include directories for wolf core (itself).
+  set(wolfcore_FOUND TRUE)
+
+  # Now we gather all the required dependencies for Wolf
+
+  get_filename_component(WOLFCORE_CURRENT_CONFIG_DIR
+    "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+  SET(BACKUP_MODULE_PATH ${CMAKE_MODULE_PATH})
+  LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${WOLFCORE_CURRENT_CONFIG_DIR})
+
+  FIND_PACKAGE(Threads REQUIRED)
+  list(APPEND wolfcore_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+
+  FIND_PACKAGE(Ceres REQUIRED)
+  list(APPEND wolfcore_INCLUDE_DIRS ${CERES_INCLUDE_DIRS})
+  list(APPEND wolfcore_LIBRARIES ${CERES_LIBRARIES})
+
+  # YAML with yaml-cpp
+  FIND_PACKAGE(YamlCpp REQUIRED)
+  list(APPEND wolfcore_INCLUDE_DIRS ${YAMLCPP_INCLUDE_DIRS})
+  list(APPEND wolfcore_LIBRARIES ${YAMLCPP_LIBRARY})
+
+  #Eigen
+  # FIND_PACKAGE(Eigen3 REQUIRED)
+  # list(APPEND wolfcore_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
+
+  if(NOT Eigen3_FOUND)
+    FIND_PACKAGE(Eigen3 REQUIRED)
+  endif()
+  if(${EIGEN3_VERSION_STRING} VERSION_LESS 3.3)
+    message(FATAL_ERROR "Found Eigen ${EIGEN3_VERSION_STRING}. The minimum version required is Eigen 3.3")
+  endif()
+  list(APPEND wolfcore_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
+endif(NOT wolfcore_FOUND)
+SET(CMAKE_MODULE_PATH ${BACKUP_MODULE_PATH})
diff --git a/demos/demo_analytic_autodiff_factor.cpp b/demos/demo_analytic_autodiff_factor.cpp
index d72f6ce2dde3025570786da0a532361c47da4d6b..0fd8d42cc5280016d7473e23cb2624615221fda7 100644
--- a/demos/demo_analytic_autodiff_factor.cpp
+++ b/demos/demo_analytic_autodiff_factor.cpp
@@ -274,8 +274,8 @@ int main(int argc, char** argv)
         printf("\nError opening file\n");
 
     // PRIOR
-    FrameBasePtr first_frame_autodiff = wolf_problem_autodiff->getTrajectory()->getFrameList().front();
-    FrameBasePtr first_frame_analytic = wolf_problem_analytic->getTrajectory()->getFrameList().front();
+    FrameBasePtr first_frame_autodiff = wolf_problem_autodiff->getTrajectory()->getFrameMap().front();
+    FrameBasePtr first_frame_analytic = wolf_problem_analytic->getTrajectory()->getFrameMap().front();
     CaptureFix* initial_covariance_autodiff = new CaptureFix(TimeStamp(0), new SensorBase("ABSOLUTE POSE", nullptr, nullptr, nullptr, 0), first_frame_autodiff->getState(), Eigen::Matrix3d::Identity() * 0.01);
     CaptureFix* initial_covariance_analytic = new CaptureFix(TimeStamp(0), new SensorBase("ABSOLUTE POSE", nullptr, nullptr, nullptr, 0), first_frame_analytic->getState(), Eigen::Matrix3d::Identity() * 0.01);
     first_frame_autodiff->addCapture(initial_covariance_autodiff);
diff --git a/demos/demo_wolf_imported_graph.cpp b/demos/demo_wolf_imported_graph.cpp
index d3be8bc31e3a1821e2ff7442f56e33e6456b2e89..c0afa76e96229181122659244a20fd1fab433354 100644
--- a/demos/demo_wolf_imported_graph.cpp
+++ b/demos/demo_wolf_imported_graph.cpp
@@ -301,8 +301,8 @@ int main(int argc, char** argv)
         printf("\nError opening file\n");
 
     // PRIOR
-    FrameBasePtr first_frame_full = wolf_problem_full->getTrajectory()->getFrameList().front();
-    FrameBasePtr first_frame_prun = wolf_problem_prun->getTrajectory()->getFrameList().front();
+    FrameBasePtr first_frame_full = wolf_problem_full->getTrajectory()->getFrameMap().front();
+    FrameBasePtr first_frame_prun = wolf_problem_prun->getTrajectory()->getFrameMap().front();
     CaptureFix* initial_covariance_full = new CaptureFix(TimeStamp(0), new SensorBase("ABSLOUTE POSE", nullptr, nullptr, nullptr, 0), first_frame_full->getState(), Eigen::Matrix3d::Identity() * 0.01);
     CaptureFix* initial_covariance_prun = new CaptureFix(TimeStamp(0), new SensorBase("ABSLOUTE POSE", nullptr, nullptr, nullptr, 0), first_frame_prun->getState(), Eigen::Matrix3d::Identity() * 0.01);
     first_frame_full->addCapture(initial_covariance_full);
diff --git a/demos/hello_wolf/CMakeLists.txt b/demos/hello_wolf/CMakeLists.txt
index bf223af61a3358cfc458d8360c1b07e7ab1aff01..81291a479cd3e524ba77b3676982ed0e140d965b 100644
--- a/demos/hello_wolf/CMakeLists.txt
+++ b/demos/hello_wolf/CMakeLists.txt
@@ -22,17 +22,17 @@ SET(HDRS_PROCESSOR ${HDRS_PROCESSOR}
     
 
 add_library(hellowolf SHARED ${SRCS_HELLOWOLF})
-TARGET_LINK_LIBRARIES(hellowolf ${PROJECT_NAME})
+TARGET_LINK_LIBRARIES(hellowolf ${PLUGIN_NAME})
 
 ADD_EXECUTABLE(hello_wolf hello_wolf.cpp)
-TARGET_LINK_LIBRARIES(hello_wolf ${PROJECT_NAME} hellowolf)
+TARGET_LINK_LIBRARIES(hello_wolf ${PLUGIN_NAME} hellowolf)
 
 ADD_EXECUTABLE(hello_wolf_autoconf hello_wolf_autoconf.cpp)
-#TARGET_LINK_LIBRARIES(hello_wolf_autoconf ${PROJECT_NAME})
-TARGET_LINK_LIBRARIES(hello_wolf_autoconf ${PROJECT_NAME} hellowolf)
+#TARGET_LINK_LIBRARIES(hello_wolf_autoconf ${PLUGIN_NAME})
+TARGET_LINK_LIBRARIES(hello_wolf_autoconf ${PLUGIN_NAME} hellowolf)
 
 #add_library(sensor_odom SHARED ../src/sensor/sensor_odom_2d.cpp ../src/processor/processor_odom_2d.cpp)
-#TARGET_LINK_LIBRARIES(sensor_odom ${PROJECT_NAME} hellowolf)
+#TARGET_LINK_LIBRARIES(sensor_odom ${PLUGIN_NAME} hellowolf)
 #
 #add_library(range_bearing SHARED sensor_range_bearing.cpp processor_range_bearing.cpp)
-#TARGET_LINK_LIBRARIES(range_bearing ${PROJECT_NAME} hellowolf)
+#TARGET_LINK_LIBRARIES(range_bearing ${PLUGIN_NAME} hellowolf)
diff --git a/demos/hello_wolf/hello_wolf.cpp b/demos/hello_wolf/hello_wolf.cpp
index b747cbee6e2939e9ee096e9241d185bbd6ca1da9..ef4f173494fbb602b2042088b065f45bf28ae43b 100644
--- a/demos/hello_wolf/hello_wolf.cpp
+++ b/demos/hello_wolf/hello_wolf.cpp
@@ -105,7 +105,7 @@ int main()
     // Wolf problem and solver
     ProblemPtr problem                      = Problem::create("PO", 2);
     SolverCeresPtr ceres                    = std::make_shared<SolverCeres>(problem);
-    ceres.getSolverOptions().max_num_iterations = 1000; // We depart far from solution, need a lot of iterations
+    ceres->getSolverOptions().max_num_iterations = 1000; // We depart far from solution, need a lot of iterations
 
     // sensor odometer 2d
     ParamsSensorOdom2dPtr intrinsics_odo    = std::make_shared<ParamsSensorOdom2d>();
@@ -232,8 +232,8 @@ int main()
     // GET COVARIANCES of all states
     WOLF_TRACE("======== COVARIANCES OF SOLVED PROBLEM =======")
     ceres->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS);
-    for (auto& kf : problem->getTrajectory()->getFrameList())
-        if (kf->isKeyOrAux())
+    for (auto& kf : *problem->getTrajectory())
+        if (kf->isKey())
         {
             Eigen::MatrixXd cov;
             kf->getCovariance(cov);
diff --git a/demos/hello_wolf/hello_wolf_autoconf.cpp b/demos/hello_wolf/hello_wolf_autoconf.cpp
index 4a12a89073ecc0b53c24f87a273fcb5621433e09..e975bb30fa55bb3cb39026a4377f7f4e62b2e58b 100644
--- a/demos/hello_wolf/hello_wolf_autoconf.cpp
+++ b/demos/hello_wolf/hello_wolf_autoconf.cpp
@@ -7,7 +7,8 @@
 
 
 // wolf core includes
-#include "../../include/core/ceres_wrapper/solver_ceres.h"
+#include "core/ceres_wrapper/solver_ceres.h"
+#include "core/solver/factory_solver.h"
 #include "core/common/wolf.h"
 #include "core/capture/capture_odom_2d.h"
 #include "core/processor/processor_motion.h"
@@ -110,9 +111,10 @@ int main()
     problem->print(4,0,1,0);
 
     // Solver. Configure a Ceres solver
-    ceres::Solver::Options options;
-    options.max_num_iterations  = 1000; // We depart far from solution, need a lot of iterations
-    SolverCeresPtr ceres       = std::make_shared<SolverCeres>(problem, options);
+    // ceres::Solver::Options options;
+    // options.max_num_iterations  = 1000; // We depart far from solution, need a lot of iterations
+    // SolverCeresPtr ceres       = std::make_shared<SolverCeres>(problem, options);
+    SolverManagerPtr ceres = FactorySolver::create("SolverCeres", problem, server);
 
     // recover sensor pointers and other stuff for later use (access by sensor name)
     SensorBasePtr sensor_odo    = problem->getSensor("sen odom");
@@ -216,8 +218,8 @@ int main()
     // GET COVARIANCES of all states
     WOLF_TRACE("======== COVARIANCES OF SOLVED PROBLEM =======")
     ceres->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS);
-    for (auto& kf : problem->getTrajectory()->getFrameList())
-        if (kf->isKeyOrAux())
+    for (auto& kf : *problem->getTrajectory())
+        if (kf->isKey())
         {
             Eigen::MatrixXd cov;
             kf->getCovariance(cov);
diff --git a/demos/hello_wolf/processor_range_bearing.cpp b/demos/hello_wolf/processor_range_bearing.cpp
index 08e77f76c8d7d2ec70c9b1ac6689e724a67e5c7c..7df38e73367b7b45aff81cdbf5f00099d64aa990 100644
--- a/demos/hello_wolf/processor_range_bearing.cpp
+++ b/demos/hello_wolf/processor_range_bearing.cpp
@@ -46,7 +46,7 @@ void ProcessorRangeBearing::processCapture(CaptureBasePtr _capture)
     if (!kf)
     {
         // No KeyFrame callback received -- we assume a KF is available to hold this _capture (checked in assert below)
-        kf = getProblem()->closestKeyFrameToTimeStamp(_capture->getTimeStamp());
+        kf = getProblem()->closestFrameToTimeStamp(_capture->getTimeStamp());
         assert( (fabs(kf->getTimeStamp() - _capture->getTimeStamp()) < params_->time_tolerance) && "Could not find a KF close enough to _capture!");
     }
 
diff --git a/demos/hello_wolf/yaml/hello_wolf_config.yaml b/demos/hello_wolf/yaml/hello_wolf_config.yaml
index f2e4f8db31f97ef8059b4d59483a747456e6d19c..a7d674d13d929cdcd260c571d9c12cde02e67658 100644
--- a/demos/hello_wolf/yaml/hello_wolf_config.yaml
+++ b/demos/hello_wolf/yaml/hello_wolf_config.yaml
@@ -1,7 +1,6 @@
 config:
 
   problem:
-  
     tree_manager:
       type: "TreeManagerSlidingWindow"
       n_key_frames: -1
@@ -20,7 +19,12 @@ config:
         P: [0.31, 0.31]
         O: [0.31]
       time_tolerance:     0.1
-    
+
+  solver:
+    max_num_iterations: 100
+    verbose: 0
+    period: 0.2
+    update_immediately: false
   sensors:
     
     - type:               "SensorOdom2d"
diff --git a/demos/solver/test_iQR_wolf2.cpp b/demos/solver/test_iQR_wolf2.cpp
index de9f6f157cc58ef2b5a542056cae7d7e32b16afd..82aab6219874c3575dc14fdb24af6d2cc0e2d07a 100644
--- a/demos/solver/test_iQR_wolf2.cpp
+++ b/demos/solver/test_iQR_wolf2.cpp
@@ -363,8 +363,8 @@ int main(int argc, char *argv[])
     // Vehicle poses
     std::cout << "Vehicle poses..." << std::endl;
     int i = 0;
-    Eigen::VectorXd state_poses(wolf_manager_QR->getProblem()->getTrajectory()->getFrameList().size() * 3);
-    for (auto frame_it = wolf_manager_QR->getProblem()->getTrajectory()->getFrameList().begin(); frame_it != wolf_manager_QR->getProblem()->getTrajectory()->getFrameList().end(); frame_it++)
+    Eigen::VectorXd state_poses(wolf_manager_QR->getProblem()->getTrajectory()->getFrameMap().size() * 3);
+    for (auto frame_it = wolf_manager_QR->getProblem()->getTrajectory()->getFrameMap().begin(); frame_it != wolf_manager_QR->getProblem()->getTrajectory()->getFrameMap().end(); frame_it++)
     {
         if (complex_angle)
             state_poses.segment(i, 3) << *(*frame_it)->getP()->get(), *((*frame_it)->getP()->get() + 1), atan2(*(*frame_it)->getO()->get(), *((*frame_it)->getO()->get() + 1));
diff --git a/include/core/capture/capture_base.h b/include/core/capture/capture_base.h
index 324b83297d987561c4a119e699ac44c2d0eb4ec5..40d3603da035205b145df7d1b7d43541a52b6a44 100644
--- a/include/core/capture/capture_base.h
+++ b/include/core/capture/capture_base.h
@@ -157,7 +157,8 @@ inline unsigned int CaptureBase::id() const
 
 inline FrameBasePtr CaptureBase::getFrame() const
 {
-    return frame_ptr_.lock();
+    if(frame_ptr_.expired()) return nullptr;
+    else return frame_ptr_.lock();
 }
 
 inline void CaptureBase::setFrame(const FrameBasePtr _frm_ptr)
diff --git a/include/core/ceres_wrapper/solver_ceres.h b/include/core/ceres_wrapper/solver_ceres.h
index e4306aa8ca126185a6343435405c1bcb5940e650..c899b7a054d6e1a9ebab5f45cca35fa0bd86c3d0 100644
--- a/include/core/ceres_wrapper/solver_ceres.h
+++ b/include/core/ceres_wrapper/solver_ceres.h
@@ -116,6 +116,10 @@ class SolverCeres : public SolverManager
 
         const Eigen::SparseMatrixd computeHessian() const;
 
+        virtual int numStateBlocksDerived() const override;
+
+        virtual int numFactorsDerived() const override;
+
     protected:
 
         bool checkDerived(std::string prefix="") const override;
@@ -138,7 +142,14 @@ class SolverCeres : public SolverManager
 
         bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override;
 
-        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) override;
+        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const override;
+
+        bool isStateBlockFixedDerived(const StateBlockPtr& st) override;
+
+        bool hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                const LocalParametrizationBasePtr& local_param) override;
+
+        bool hasLocalParametrizationDerived(const StateBlockPtr& st)  const override;
 };
 
 inline ceres::Solver::Summary SolverCeres::getSummary()
@@ -158,16 +169,35 @@ inline ceres::Solver::Options& SolverCeres::getSolverOptions()
 
 inline bool SolverCeres::isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const
 {
-    return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end()
-            && fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
+    return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end() and
+           fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
 }
 
-inline bool SolverCeres::isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr)
+inline bool SolverCeres::isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const
 {
-    return state_blocks_local_param_.find(state_ptr) != state_blocks_local_param_.end()
-            && ceres_problem_->HasParameterBlock(getAssociatedMemBlockPtr(state_ptr));
+    return ceres_problem_->HasParameterBlock(getAssociatedMemBlockPtr(state_ptr));
 }
 
+inline bool SolverCeres::isStateBlockFixedDerived(const StateBlockPtr& st)
+{
+    return ceres_problem_->IsParameterBlockConstant(SolverManager::getAssociatedMemBlockPtr(st));
+};
+
+inline bool SolverCeres::hasLocalParametrizationDerived(const StateBlockPtr& st) const
+{
+    return state_blocks_local_param_.count(st) == 1;
+};
+
+inline int SolverCeres::numStateBlocksDerived() const
+{
+    return ceres_problem_->NumParameterBlocks();
+}
+
+inline int SolverCeres::numFactorsDerived() const
+{
+    return ceres_problem_->NumResidualBlocks();
+};
+
 } // namespace wolf
 
 #endif
diff --git a/include/core/common/wolf.h b/include/core/common/wolf.h
index 229e10f95dd8f7506846fe75536a85c6604ae521..97f9a50ff1eb1b0a345461af2fbdce2b81b32491 100644
--- a/include/core/common/wolf.h
+++ b/include/core/common/wolf.h
@@ -23,6 +23,7 @@
 #include <list>
 #include <map>
 #include <memory> // shared_ptr and weak_ptr
+#include <set>
 
 // System specifics
 #include <sys/stat.h>
@@ -230,10 +231,14 @@ WOLF_STRUCT_PTR_TYPEDEFS(ParamsProcessorBase);
 // Trajectory
 WOLF_PTR_TYPEDEFS(TrajectoryBase);
 
+
 // - Frame
 WOLF_PTR_TYPEDEFS(FrameBase);
 WOLF_LIST_TYPEDEFS(FrameBase);
 
+class TimeStamp;
+typedef std::map<TimeStamp, FrameBasePtr> FrameMap;
+
 // - Capture
 WOLF_PTR_TYPEDEFS(CaptureBase);
 WOLF_LIST_TYPEDEFS(CaptureBase);
diff --git a/include/core/factor/factor_base.h b/include/core/factor/factor_base.h
index 1d4f01a35e5a1541ec6b147ab3155d268a7f9a9c..c600f8a2433a024f63d2af21fe39105c761e7300 100644
--- a/include/core/factor/factor_base.h
+++ b/include/core/factor/factor_base.h
@@ -4,6 +4,8 @@
 // Forward declarations for node templates
 namespace wolf{
 class FeatureBase;
+class TrajectoryIter;
+class TrajectoryRevIter;
 }
 
 //Wolf includes
diff --git a/include/core/frame/frame_base.h b/include/core/frame/frame_base.h
index a28e13e1e73c089f717a43dcf23ed8d2cc486fe3..1b368bf02df6a89567d90455edba72cf02f54bf0 100644
--- a/include/core/frame/frame_base.h
+++ b/include/core/frame/frame_base.h
@@ -1,4 +1,5 @@
 
+
 #ifndef FRAME_BASE_H_
 #define FRAME_BASE_H_
 
@@ -12,8 +13,8 @@ class StateBlock;
  */
 typedef enum
 {
-    KEY = 2,          ///< key frame. It plays at optimizations (estimated).
-    AUXILIARY = 1,    ///< auxiliary frame. It plays at optimizations (estimated).
+    KEY = 1,          ///< key frame. It plays at optimizations (estimated).
+    // AUXILIARY = 1,    ///< auxiliary frame. It plays at optimizations (estimated).
     NON_ESTIMATED = 0 ///< regular frame. It does not play at optimization.
 } FrameType;
 }
@@ -82,13 +83,10 @@ class FrameBase : public NodeBase, public HasStateBlocks, public std::enable_sha
 
         // get type
         bool isKey() const;
-        bool isAux() const;
-        bool isKeyOrAux() const;
 
         // set type
         void setNonEstimated();
-        void setKey();
-        void setAux();
+        void setKey(ProblemPtr _prb);
 
         // Frame values ------------------------------------------------
     public:
@@ -131,7 +129,9 @@ class FrameBase : public NodeBase, public HasStateBlocks, public std::enable_sha
         bool isConstrainedBy(const FactorBasePtr& _factor) const;
         void link(TrajectoryBasePtr);
         template<typename classType, typename... T>
-        static std::shared_ptr<classType> emplace(TrajectoryBasePtr _ptr, T&&... all);
+        static std::shared_ptr<classType> emplaceKeyFrame(TrajectoryBasePtr _ptr, T&&... all);
+        template<typename classType, typename... T>
+        static std::shared_ptr<classType> createNonKeyFrame(T&&... all);
 
         virtual void printHeader(int depth, //
                                  bool constr_by, //
@@ -172,13 +172,20 @@ class FrameBase : public NodeBase, public HasStateBlocks, public std::enable_sha
 namespace wolf {
 
 template<typename classType, typename... T>
-std::shared_ptr<classType> FrameBase::emplace(TrajectoryBasePtr _ptr, T&&... all)
+std::shared_ptr<classType> FrameBase::emplaceKeyFrame(TrajectoryBasePtr _ptr, T&&... all)
 {
-    std::shared_ptr<classType> frm = std::make_shared<classType>(std::forward<T>(all)...);
+    std::shared_ptr<classType> frm = std::make_shared<classType>(FrameType::KEY, std::forward<T>(all)...);
     frm->link(_ptr);
     return frm;
 }
 
+template<typename classType, typename... T>
+std::shared_ptr<classType> FrameBase::createNonKeyFrame(T&&... all)
+{
+    std::shared_ptr<classType> frm = std::make_shared<classType>(FrameType::NON_ESTIMATED, std::forward<T>(all)...);
+    return frm;
+}
+
 inline unsigned int FrameBase::id() const
 {
     return frame_id_;
@@ -189,16 +196,6 @@ inline bool FrameBase::isKey() const
     return (type_ == KEY);
 }
 
-inline bool FrameBase::isAux() const
-{
-    return (type_ == AUXILIARY);
-}
-
-inline bool FrameBase::isKeyOrAux() const
-{
-    return (type_ == KEY || type_ == AUXILIARY);
-}
-
 inline void FrameBase::getTimeStamp(TimeStamp& _ts) const
 {
     _ts = time_stamp_;
@@ -237,7 +234,7 @@ inline const FactorBasePtrList& FrameBase::getConstrainedByList() const
 inline StateBlockPtr FrameBase::addStateBlock(const char& _sb_type,
                                               const StateBlockPtr& _sb)
 {
-    if (isKeyOrAux())
+    if (isKey())
         HasStateBlocks::addStateBlock(_sb_type, _sb, getProblem());
     else
         HasStateBlocks::addStateBlock(_sb_type, _sb, nullptr);
diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h
index 63512663b68076b6c7da86285a548691889b37f4..002015f83efac35a081aa24873f9c684cb1b36b7 100644
--- a/include/core/problem/problem.h
+++ b/include/core/problem/problem.h
@@ -217,11 +217,10 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp, //
-                                  const StateStructure& _frame_structure, //
-                                  const SizeEigen _dim, //
-                                  const Eigen::VectorXd& _frame_state);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                     const StateStructure& _frame_structure, //
+                                     const SizeEigen _dim, //
+                                     const Eigen::VectorXd& _frame_state);
 
         /** \brief Emplace frame from string frame_structure and state
          * \param _frame_key_type Either KEY, AUXILIARY or NON_ESTIMATED
@@ -236,10 +235,9 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp, //
-                                  const StateStructure& _frame_structure, //
-                                  const VectorComposite& _frame_state);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                     const StateStructure& _frame_structure, //
+                                     const VectorComposite& _frame_state);
 
         /** \brief Emplace frame from state
          * \param _frame_key_type Either KEY, AUXILIARY or NON_ESTIMATED
@@ -254,9 +252,8 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp, //
-                                  const VectorComposite& _frame_state);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                     const VectorComposite& _frame_state);
 
         /** \brief Emplace frame from string frame_structure and dimension
          * \param _frame_key_type Either KEY, AUXILIARY or NON_ESTIMATED
@@ -272,10 +269,9 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp, //
-                                  const StateStructure& _frame_structure, //
-                                  const SizeEigen _dim);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                     const StateStructure& _frame_structure, //
+                                     const SizeEigen _dim);
 
         /** \brief Emplace frame from state vector
          * \param _frame_key_type Either KEY, AUXILIARY or NON_ESTIMATED
@@ -290,9 +286,8 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp, //
-                                  const Eigen::VectorXd& _frame_state);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                     const Eigen::VectorXd& _frame_state);
 
         /** \brief Emplace frame, guess all values
          * \param _frame_key_type Either KEY, AUXILIARY or NON_ESTIMATED
@@ -307,15 +302,12 @@ class Problem : public std::enable_shared_from_this<Problem>
          *   - Add it to Trajectory
          *   - If it is key-frame, update state-block lists in Problem
          */
-        FrameBasePtr emplaceFrame(FrameType _frame_key_type, //
-                                  const TimeStamp& _time_stamp);
+        FrameBasePtr emplaceKeyFrame(const TimeStamp& _time_stamp);
 
         // Frame getters
         FrameBasePtr getLastFrame( ) const;
-        FrameBasePtr getLastKeyFrame( ) const;
         FrameBasePtr getLastKeyOrAuxFrame( ) const;
-        FrameBasePtr closestKeyFrameToTimeStamp(const TimeStamp& _ts) const;
-        FrameBasePtr closestKeyOrAuxFrameToTimeStamp(const TimeStamp& _ts) const;
+        FrameBasePtr closestFrameToTimeStamp(const TimeStamp& _ts) const;
 
         /** \brief Give the permission to a processor to create a new key Frame
          *
@@ -380,7 +372,7 @@ class Problem : public std::enable_shared_from_this<Problem>
         bool getCovarianceBlock(std::map<StateBlockPtr, unsigned int> _sb_2_idx, Eigen::MatrixXd& _cov) const;
         bool getCovarianceBlock(StateBlockPtr _state, Eigen::MatrixXd& _cov, const int _row_and_col = 0) const;
         bool getFrameCovariance(FrameBaseConstPtr _frame_ptr, Eigen::MatrixXd& _covariance) const;
-        bool getLastKeyFrameCovariance(Eigen::MatrixXd& _covariance) const;
+        bool getLastFrameCovariance(Eigen::MatrixXd& _covariance) const;
         bool getLastKeyOrAuxFrameCovariance(Eigen::MatrixXd& _covariance) const;
         bool getLandmarkCovariance(LandmarkBaseConstPtr _landmark_ptr, Eigen::MatrixXd& _covariance) const;
 
diff --git a/include/core/processor/processor_motion.h b/include/core/processor/processor_motion.h
index e1caf715503a64568df40611c49f5b11a35f3e84..1f62a82a39dfcf5ae2de6183d341051d5785b45c 100644
--- a/include/core/processor/processor_motion.h
+++ b/include/core/processor/processor_motion.h
@@ -486,7 +486,9 @@ class ProcessorMotion : public ProcessorBase, public IsMotion
         CaptureMotionPtr origin_ptr_;
         CaptureMotionPtr last_ptr_;
         CaptureMotionPtr incoming_ptr_;
-        
+
+        FrameBasePtr last_frame_ptr_;
+
     protected:
         // helpers to avoid allocation
         double dt_;                             ///< Time step
diff --git a/include/core/processor/processor_tracker.h b/include/core/processor/processor_tracker.h
index 0f4c3180003140544f251113583e0184e630d9b8..1a05397319a431fc04a8b33642d90ad09edb524f 100644
--- a/include/core/processor/processor_tracker.h
+++ b/include/core/processor/processor_tracker.h
@@ -101,6 +101,7 @@ class ProcessorTracker : public ProcessorBase
         CaptureBasePtr origin_ptr_;             ///< Pointer to the origin of the tracker.
         CaptureBasePtr last_ptr_;               ///< Pointer to the last tracked capture.
         CaptureBasePtr incoming_ptr_;           ///< Pointer to the incoming capture being processed.
+        FrameBasePtr last_frame_ptr_;
         FeatureBasePtrList new_features_last_;     ///< List of new features in \b last for landmark initialization and new key-frame creation.
         FeatureBasePtrList new_features_incoming_; ///< list of the new features of \b last successfully tracked in \b incoming
         FeatureBasePtrList known_features_last_; ///< list of the known features in previous captures successfully tracked in \b last
diff --git a/include/core/solver/solver_manager.h b/include/core/solver/solver_manager.h
index 17341101c0d2ee4ee7074d220fda006e42fd0b31..bdd8a37aaa817b36609cc672402161f60a5fdba2 100644
--- a/include/core/solver/solver_manager.h
+++ b/include/core/solver/solver_manager.h
@@ -119,31 +119,47 @@ class SolverManager
 
         ReportVerbosity getVerbosity() const;
 
-        virtual bool isStateBlockRegistered(const StateBlockPtr& state_ptr);
+        virtual bool isStateBlockRegistered(const StateBlockPtr& state_ptr) const final;
 
-        virtual bool isFactorRegistered(const FactorBasePtr& fac_ptr) const;
+        virtual bool isStateBlockFloating(const StateBlockPtr& state_ptr) const final;
 
-        bool check(std::string prefix="") const;
+        virtual bool isFactorRegistered(const FactorBasePtr& fac_ptr) const final;
+        virtual bool isStateBlockFixed(const StateBlockPtr& st) final;
+
+        virtual bool hasThisLocalParametrization(const StateBlockPtr& st,
+                                                 const LocalParametrizationBasePtr& local_param) final;
+
+        virtual bool hasLocalParametrization(const StateBlockPtr& st) const final;
+
+        virtual int numFactors() const final;
+        virtual int numStateBlocks() const final;
+        virtual int numStateBlocksFloating() const final;
+
+        virtual int numFactorsDerived() const = 0;
+        virtual int numStateBlocksDerived() const = 0;
+
+        virtual bool check(std::string prefix="") const final;
 
     protected:
 
         std::map<StateBlockPtr, Eigen::VectorXd> state_blocks_;
         std::map<StateBlockPtr, FactorBasePtrList> state_blocks_2_factors_;
         std::set<FactorBasePtr> factors_;
+        std::set<StateBlockPtr> floating_state_blocks_;
 
         virtual Eigen::VectorXd& getAssociatedMemBlock(const StateBlockPtr& state_ptr);
         const double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr) const;
-        virtual double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr);
+        double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr);
 
     private:
         // SolverManager functions
-        void addFactor(const FactorBasePtr& fac_ptr);
-        void removeFactor(const FactorBasePtr& fac_ptr);
-        void addStateBlock(const StateBlockPtr& state_ptr);
-        void removeStateBlock(const StateBlockPtr& state_ptr);
-        void updateStateBlockState(const StateBlockPtr& state_ptr);
-        void updateStateBlockStatus(const StateBlockPtr& state_ptr);
-        void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr);
+        virtual void addFactor(const FactorBasePtr& fac_ptr) final;
+        virtual void removeFactor(const FactorBasePtr& fac_ptr) final;
+        virtual void addStateBlock(const StateBlockPtr& state_ptr) final;
+        virtual void removeStateBlock(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockState(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockStatus(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr) final;
 
     protected:
         // Derived virtual functions
@@ -154,9 +170,13 @@ class SolverManager
         virtual void removeStateBlockDerived(const StateBlockPtr& state_ptr) = 0;
         virtual void updateStateBlockStatusDerived(const StateBlockPtr& state_ptr) = 0;
         virtual void updateStateBlockLocalParametrizationDerived(const StateBlockPtr& state_ptr) = 0;
-        virtual bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) = 0;
+        virtual bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const = 0;
         virtual bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const = 0;
         virtual bool checkDerived(std::string prefix="") const = 0;
+        virtual bool isStateBlockFixedDerived(const StateBlockPtr& st) = 0;
+        virtual bool hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                        const LocalParametrizationBasePtr& local_param) = 0;
+        virtual bool hasLocalParametrizationDerived(const StateBlockPtr& st) const = 0;
 };
 
 // Params (here becaure it needs of declaration of SolverManager::ReportVerbosity)
diff --git a/include/core/trajectory/trajectory_base.h b/include/core/trajectory/trajectory_base.h
index 152a7b40e8d154f0b251d8fd322c5f0473126972..cb89fa517f981153b84812b3382e852989d3f8a1 100644
--- a/include/core/trajectory/trajectory_base.h
+++ b/include/core/trajectory/trajectory_base.h
@@ -6,42 +6,76 @@
 namespace wolf{
 class Problem;
 class FrameBase;
-class TimeStamp;
 }
 
 //Wolf includes
 #include "core/common/wolf.h"
 #include "core/common/node_base.h"
+#include "core/common/time_stamp.h"
 
 //std includes
 
 namespace wolf {
 
+class TrajectoryIter : public std::map<TimeStamp, FrameBasePtr>::const_iterator
+{
+    public:
+        TrajectoryIter(std::map<TimeStamp, FrameBasePtr>::const_iterator src)
+            : std::map<TimeStamp, FrameBasePtr>::const_iterator(std::move(src))
+        {
+
+        }
+
+        // override the indirection operator
+        const FrameBasePtr& operator*() const {
+            return std::map<TimeStamp, FrameBasePtr>::const_iterator::operator*().second;
+        }
+};
+
+class TrajectoryRevIter : public std::map<TimeStamp, FrameBasePtr>::const_reverse_iterator
+{
+    public:
+        TrajectoryRevIter(std::map<TimeStamp, FrameBasePtr>::const_reverse_iterator src)
+            : std::map<TimeStamp, FrameBasePtr>::const_reverse_iterator(std::move(src))
+        {
+
+        }
+
+        // override the indirection operator
+        const FrameBasePtr& operator*() const {
+            return std::map<TimeStamp, FrameBasePtr>::const_reverse_iterator::operator*().second;
+        }
+};
+// typedef std::map<TimeStamp, FrameBasePtr> FrameMap;
+// typedef std::map<TimeStamp, FrameBasePtr>::const_iterator TrajectoryIter;
+// typedef std::map<TimeStamp, FrameBasePtr>::const_reverse_iterator TrajectoryRevIter;
+
 //class TrajectoryBase
 class TrajectoryBase : public NodeBase, public std::enable_shared_from_this<TrajectoryBase>
 {
     friend FrameBase;
 
     private:
-        std::list<FrameBasePtr> frame_list_;
+         FrameMap frame_map_;
 
     protected:
-        FrameBasePtr last_key_frame_ptr_; // keeps pointer to the last key frame
-        FrameBasePtr last_key_or_aux_frame_ptr_; // keeps pointer to the last estimated frame
+        std::string frame_structure_;  // Defines the structure of the Frames in the Trajectory.
+        // FrameBasePtr last_key_frame_ptr_; // keeps pointer to the last key frame
+        // FrameBasePtr last_key_or_aux_frame_ptr_; // keeps pointer to the last estimated frame
         
     public:
         TrajectoryBase();
         ~TrajectoryBase() override;
         
         // Frames
-        const FrameBasePtrList& getFrameList() const;
+        const FrameMap& getFrameMap() const;
         FrameBasePtr getLastFrame() const;
-        FrameBasePtr getLastKeyFrame() const;
-        FrameBasePtr getLastKeyOrAuxFrame() const;
-        FrameBasePtr closestKeyFrameToTimeStamp(const TimeStamp& _ts) const;
-        FrameBasePtr closestKeyOrAuxFrameToTimeStamp(const TimeStamp& _ts) const;
-        void sortFrame(FrameBasePtr _frm_ptr);
-        void updateLastFrames();
+        FrameBasePtr getFirstFrame() const;
+        FrameBasePtr closestFrameToTimeStamp(const TimeStamp& _ts) const;
+        TrajectoryIter begin() const;
+        TrajectoryIter end() const;
+        TrajectoryRevIter rbegin() const;
+        TrajectoryRevIter rend() const;
 
         virtual void printHeader(int depth, //
                                  bool constr_by, //
@@ -65,30 +99,47 @@ class TrajectoryBase : public NodeBase, public std::enable_shared_from_this<Traj
     public:
         // factors
         void getFactorList(FactorBasePtrList & _fac_list) const;
-
-    protected:
-        FrameBaseConstIter computeFrameOrder(FrameBasePtr _frame_ptr);
-        void moveFrame(FrameBasePtr _frm_ptr, FrameBaseConstIter _place);
 };
 
-inline const FrameBasePtrList& TrajectoryBase::getFrameList() const
+inline const FrameMap& TrajectoryBase::getFrameMap() const
 {
-    return frame_list_;
+    return frame_map_;
+    // return frame_map_;
 }
 
-inline FrameBasePtr TrajectoryBase::getLastFrame() const
+// inline FrameBasePtr TrajectoryBase::getLastFrame() const
+// {
+//     auto it = static_cast<TrajectoryRevIter>(frame_map_.rbegin());
+//     return *it;
+// }
+inline FrameBasePtr TrajectoryBase::getFirstFrame() const
 {
-    return frame_list_.back();
+    auto it = static_cast<TrajectoryIter>(frame_map_.begin());
+    return *it;
 }
-
-inline FrameBasePtr TrajectoryBase::getLastKeyFrame() const
+inline TrajectoryIter TrajectoryBase::begin() const
+{
+    return static_cast<TrajectoryIter>(frame_map_.begin());
+}
+inline TrajectoryIter TrajectoryBase::end() const
 {
-    return last_key_frame_ptr_;
+    return static_cast<TrajectoryIter>(frame_map_.end());
+}
+inline TrajectoryRevIter TrajectoryBase::rbegin() const
+{
+    return static_cast<TrajectoryRevIter>(frame_map_.rbegin());
+}
+inline TrajectoryRevIter TrajectoryBase::rend() const
+{
+    return static_cast<TrajectoryRevIter>(frame_map_.rend());
 }
 
-inline FrameBasePtr TrajectoryBase::getLastKeyOrAuxFrame() const
+inline FrameBasePtr TrajectoryBase::getLastFrame() const
 {
-    return last_key_or_aux_frame_ptr_;
+    // return last_key_frame_ptr_;
+    auto last = this->rbegin();
+    if(last != this->rend()) return *(this->rbegin());
+    else return nullptr;
 }
 
 } // namespace wolf
diff --git a/include/core/utils/converter.h b/include/core/utils/converter.h
index 76e710f75d4aeb31589e27aa819304ec0b8d9cec..0c9502c4ec0cc12ce041611d3a86d5c035af9d09 100644
--- a/include/core/utils/converter.h
+++ b/include/core/utils/converter.h
@@ -20,9 +20,35 @@
 
 /**
    @file
+   converter.h
+   @brief This file implements a set of simple functions that deal with the correspondence between
+   classes and their string representation. The YAML autosetup framework makes heavy use of this file.
+ */
+
+//Note: In order to deal with string representations we make heavy use of regexps.
+//      We use the standard C++11 regular expressions capabilities.
+
+/*
+** This file is structured essentially in two parts:
+** in the first part (which starts after the CONVERTERS ~~~~ STRING ----> TYPE line)
+** we have functions to convert from string to C++ class. For example:
+     string v1 = "[3,4,5,6,7,8,9,10,11]";
+     vector<int> v = converter<vector<int>>::convert(v1);
+   This code snippet transforms the string v1 which represents an std::vector into an actual std::vector value.
+   The second part (which starts after the TYPES ----> ToSTRING line) has the functions to
+   transform from C++ classes to strings. For instance, if we wanted to convert from a C++ class
+   to a string we would do something like this:
+     vector<int> vect{ 10, 20, 30 };
+     string str = converter<std::string>::convert(vect);
+     //str == "[10,20,30]"
  */
 namespace wolf{
 
+    //This definition is a bit of a "hack". The reason of redefining the pair class is to be able
+    //to have two string representations of a pair, namely
+    //"(·,·)" -> typical pair/tuple representation
+    //"{·,·}" -> key-value pair representation used to represent maps.
+    //This is purely an aesthetic reason and could be removed without problems.
 template<class A, class B>
 struct Wpair : std::pair<A,B>
 {
diff --git a/src/ceres_wrapper/solver_ceres.cpp b/src/ceres_wrapper/solver_ceres.cpp
index 74802c255736656930cd348158f62d339bd0b86a..1d9cc7dd2e8f43c76820974caa473ad876b0a97c 100644
--- a/src/ceres_wrapper/solver_ceres.cpp
+++ b/src/ceres_wrapper/solver_ceres.cpp
@@ -99,8 +99,8 @@ void SolverCeres::computeCovariances(const CovarianceBlocksToBeComputed _blocks)
             // first create a vector containing all state blocks
             std::vector<StateBlockPtr> all_state_blocks, landmark_state_blocks;
             //frame state blocks
-            for(auto fr_ptr : wolf_problem_->getTrajectory()->getFrameList())
-                if (fr_ptr->isKeyOrAux())
+            for(auto fr_ptr : *wolf_problem_->getTrajectory())
+                if (fr_ptr->isKey())
                     for (const auto& key : fr_ptr->getStructure())
                     {
                         const auto& sb = fr_ptr->getStateBlock(key);
@@ -126,8 +126,8 @@ void SolverCeres::computeCovariances(const CovarianceBlocksToBeComputed _blocks)
         case CovarianceBlocksToBeComputed::ALL_MARGINALS:
         {
             // first create a vector containing all state blocks
-            for(auto fr_ptr : wolf_problem_->getTrajectory()->getFrameList())
-                if (fr_ptr->isKeyOrAux())
+            for(auto fr_ptr : *wolf_problem_->getTrajectory())
+                if (fr_ptr->isKey())
                     for (const auto& key1 : wolf_problem_->getFrameStructure())
                         for (const auto& key2 : wolf_problem_->getFrameStructure())
                         {
@@ -165,7 +165,7 @@ void SolverCeres::computeCovariances(const CovarianceBlocksToBeComputed _blocks)
         case CovarianceBlocksToBeComputed::ROBOT_LANDMARKS:
         {
             //robot-robot
-            auto last_key_frame = wolf_problem_->getLastKeyFrame();
+            auto last_key_frame = wolf_problem_->getLastFrame();
 
             state_block_pairs.emplace_back(last_key_frame->getP(), last_key_frame->getP());
             state_block_pairs.emplace_back(last_key_frame->getP(), last_key_frame->getO());
@@ -579,6 +579,14 @@ const Eigen::SparseMatrixd SolverCeres::computeHessian() const
     return H;
 }
 
+bool SolverCeres::hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                     const LocalParametrizationBasePtr& local_param)
+{
+    return state_blocks_local_param_.count(st) == 1
+            && state_blocks_local_param_.at(st)->getLocalParametrization() == local_param
+            && ceres_problem_->GetParameterization(getAssociatedMemBlockPtr(st))
+                    == state_blocks_local_param_.at(st).get();
+}
 
 } // namespace wolf
 #include "core/solver/factory_solver.h"
diff --git a/src/factor/factor_base.cpp b/src/factor/factor_base.cpp
index 4e18cb47d8485a7b9ee83853e863ddf20bb7e78a..a0b4bc90005cb0ffa48c7ef21d87c758a7a52a36 100644
--- a/src/factor/factor_base.cpp
+++ b/src/factor/factor_base.cpp
@@ -151,20 +151,23 @@ void FactorBase::remove(bool viral_remove_empty_parent)
 
 CaptureBasePtr FactorBase::getCapture() const
 {
-    assert(getFeature() != nullptr && "calling getCapture before linking with a feature");
-    return getFeature()->getCapture();
+    auto ftr = getFeature();
+    if (ftr != nullptr) return ftr->getCapture();
+    else return nullptr;
 }
 
 FrameBasePtr FactorBase::getFrame() const
 {
-    assert(getCapture() != nullptr && "calling getFrame before linking with a capture");
-    return getCapture()->getFrame();
+    auto cpt = getCapture();
+    if(cpt != nullptr) return cpt->getFrame();
+    else return nullptr;
 }
 
 SensorBasePtr FactorBase::getSensor() const
 {
-    assert(getCapture() != nullptr && "calling getSensor before linking with a capture");
-    return getCapture()->getSensor();
+    auto cpt = getCapture();
+    if(cpt != nullptr) return cpt->getSensor();
+    else return nullptr;
 }
 
 void FactorBase::setStatus(FactorStatus _status)
diff --git a/src/frame/frame_base.cpp b/src/frame/frame_base.cpp
index a8f56d1a20302504ae0acad701a9fce7c86e91d9..f7c7ce6ea257a48f73c68003b8c1efbfeb4f6a6b 100644
--- a/src/frame/frame_base.cpp
+++ b/src/frame/frame_base.cpp
@@ -116,7 +116,7 @@ void FrameBase::remove(bool viral_remove_empty_parent)
         }
 
         // Remove Frame State Blocks
-        if ( isKeyOrAux() )
+        if ( isKey() )
             removeStateBlocks(getProblem());
 
         // remove from upstream
@@ -131,52 +131,23 @@ void FrameBase::remove(bool viral_remove_empty_parent)
 void FrameBase::setTimeStamp(const TimeStamp& _ts)
 {
     time_stamp_ = _ts;
-    if (isKeyOrAux() && getTrajectory() != nullptr)
-        getTrajectory()->sortFrame(shared_from_this());
 }
 
 void FrameBase::setNonEstimated()
 {
     // unregister if previously estimated
-    if (isKeyOrAux())
+    if (isKey())
         for (const auto& sb : getStateBlockVec())
             getProblem()->notifyStateBlock(sb, REMOVE);
 
     type_ = NON_ESTIMATED;
-    if (getTrajectory())
-    {
-        getTrajectory()->sortFrame(shared_from_this());
-        getTrajectory()->updateLastFrames();
-    }
 }
 
-void FrameBase::setKey()
+void FrameBase::setKey(ProblemPtr _prb)
 {
-    // register if previously not estimated
-    if (!isKeyOrAux())
-        registerNewStateBlocks(getProblem());
-
+    assert(_prb != nullptr && "setting Key fram with a null problem pointer");
     type_ = KEY;
-
-    if (getTrajectory())
-    {
-        getTrajectory()->sortFrame(shared_from_this());
-        getTrajectory()->updateLastFrames();
-    }
-}
-
-void FrameBase::setAux()
-{
-    if (!isKeyOrAux())
-        registerNewStateBlocks(getProblem());
-
-    type_ = AUXILIARY;
-
-    if (getTrajectory())
-    {
-        getTrajectory()->sortFrame(shared_from_this());
-        getTrajectory()->updateLastFrames();
-    }
+    this->link(_prb->getTrajectory());
 }
 
 bool FrameBase::getCovariance(Eigen::MatrixXd& _cov) const
@@ -189,12 +160,12 @@ FrameBasePtr FrameBase::getPreviousFrame() const
     assert(getTrajectory() != nullptr && "This Frame is not linked to any trajectory");
 
     //look for the position of this node in the upper list (frame list of trajectory)
-    for (auto f_it = getTrajectory()->getFrameList().rbegin(); f_it != getTrajectory()->getFrameList().rend(); f_it++ )
+    for (auto f_it = getTrajectory()->rbegin(); f_it != getTrajectory()->rend(); f_it++ )
     {
         if ( this->frame_id_ == (*f_it)->id() )
         {
         	f_it++;
-        	if (f_it != getTrajectory()->getFrameList().rend())
+        	if (f_it != getTrajectory()->rend())
             {
                 return *f_it;
             }
@@ -210,11 +181,11 @@ FrameBasePtr FrameBase::getPreviousFrame() const
 FrameBasePtr FrameBase::getNextFrame() const
 {
     //std::cout << "finding next frame of " << this->frame_id_ << std::endl;
-	auto f_it = getTrajectory()->getFrameList().rbegin();
+	auto f_it = getTrajectory()->rbegin();
 	f_it++; //starting from second last frame
 
     //look for the position of this node in the frame list of trajectory
-    while (f_it != getTrajectory()->getFrameList().rend())
+    while (f_it != getTrajectory()->rend())
     {
         if ( this->frame_id_ == (*f_it)->id())
         {
@@ -316,6 +287,7 @@ void FrameBase::link(TrajectoryBasePtr _trj_ptr)
 {
     assert(!is_removing_ && "linking a removed frame");
     assert(this->getTrajectory() == nullptr && "linking an already linked frame");
+    assert(isKey() && "Trying to link a non keyframe");
 
     if(_trj_ptr)
     {
@@ -344,7 +316,7 @@ void FrameBase::setProblem(ProblemPtr _problem)
 
 void FrameBase::printHeader(int _depth, bool _constr_by, bool _metric, bool _state_blocks, std::ostream& _stream, std::string _tabs) const
 {
-    _stream << _tabs << (isKeyOrAux() ? (isKey() ? "KFrm" : "AFrm") : "Frm") << id()
+    _stream << _tabs << (isKey() ? "KFrm" : "Frm") << id()
             << " " << getStructure()
             << " ts = " << std::setprecision(3) << getTimeStamp()
             << ((_depth < 2) ? " -- " + std::to_string(getCaptureList().size()) + "C  " : "");
@@ -399,7 +371,7 @@ CheckLog FrameBase::localCheck(bool _verbose, FrameBasePtr _frm_ptr, std::ostrea
     std::stringstream inconsistency_explanation;
 
     if (_verbose) {
-        _stream << _tabs << (isKeyOrAux() ? (isKey() ? "KFrm" : "EFrm") : "Frm")
+        _stream << _tabs << (isKey() ? "KFrm" : "Frm")
                 << id() << " @ " << _frm_ptr.get() << std::endl;
         _stream << _tabs << "  " << "-> Prb @ " << getProblem().get() << std::endl;
         _stream << _tabs << "  " << "-> Trj @ " << getTrajectory().get() << std::endl;
@@ -472,9 +444,8 @@ CheckLog FrameBase::localCheck(bool _verbose, FrameBasePtr _frm_ptr, std::ostrea
     inconsistency_explanation << "Frm" << id() << " @ " << _frm_ptr
                               << " ---> Trj" << " @ " << trj_ptr
                               << " -X-> Frm" << id();
-    auto trj_frm_list = trj_ptr->getFrameList();
-    auto trj_has_frm = std::find_if(trj_frm_list.begin(), trj_frm_list.end(), [&_frm_ptr](FrameBasePtr frm){ return frm == _frm_ptr;});
-    log.assertTrue(trj_has_frm != trj_frm_list.end(), inconsistency_explanation);
+    auto trj_has_frm = std::find_if(trj_ptr->begin(), trj_ptr->end(), [&_frm_ptr](FrameBasePtr frm){ return frm == _frm_ptr;});
+    log.assertTrue(trj_has_frm != trj_ptr->end(), inconsistency_explanation);
 
     for(auto C : getCaptureList())
     {
diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp
index 9e84a825a30ffacf0ffb2e66fbb3670697901cd9..b151a6929ed93ecb4c231ffcd409df89ee3c36d1 100644
--- a/src/problem/problem.cpp
+++ b/src/problem/problem.cpp
@@ -325,11 +325,10 @@ SensorBasePtr Problem::getSensor(const std::string& _sensor_name) const
     return (*sen_it);
 }
 
-FrameBasePtr Problem::emplaceFrame(FrameType _frame_key_type, //
-                                   const TimeStamp& _time_stamp, //
-                                   const StateStructure& _frame_structure, //
-                                   const SizeEigen _dim, //
-                                   const Eigen::VectorXd& _frame_state)
+FrameBasePtr Problem::emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                      const StateStructure& _frame_structure, //
+                                      const SizeEigen _dim, //
+                                      const Eigen::VectorXd& _frame_state)
 {
     VectorComposite state;
     SizeEigen index = 0;
@@ -353,66 +352,55 @@ FrameBasePtr Problem::emplaceFrame(FrameType _frame_key_type, //
 
     assert (_frame_state.size() == index && "State vector incompatible with given structure and dimension! Vector too large.");
 
-    auto frm = FrameBase::emplace<FrameBase>(trajectory_ptr_,
-                                             _frame_key_type,
-                                             _time_stamp,
-                                             _frame_structure,
-                                             state);
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(trajectory_ptr_,
+                                                     _time_stamp,
+                                                     _frame_structure,
+                                                     state);
     return frm;
 }
 
-FrameBasePtr Problem::emplaceFrame(FrameType _frame_key_type, //
-                                   const TimeStamp& _time_stamp, //
-                                   const StateStructure& _frame_structure, //
-                                   const SizeEigen _dim)
+FrameBasePtr Problem::emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                      const StateStructure& _frame_structure, //
+                                      const SizeEigen _dim)
 {
-    return emplaceFrame(_frame_key_type,
-                        _time_stamp,
-                        _frame_structure,
-                        getState(_time_stamp));
+    return emplaceKeyFrame(_time_stamp,
+                           _frame_structure,
+                           getState(_time_stamp));
 }
 
-FrameBasePtr Problem::emplaceFrame (FrameType _frame_key_type, //
-                                    const TimeStamp& _time_stamp, //
-                                    const StateStructure& _frame_structure, //
-                                    const VectorComposite& _frame_state)
+FrameBasePtr Problem::emplaceKeyFrame (const TimeStamp& _time_stamp, //
+                                       const StateStructure& _frame_structure, //
+                                       const VectorComposite& _frame_state)
 {
-    return FrameBase::emplace<FrameBase>(getTrajectory(),
-                                         _frame_key_type,
-                                         _time_stamp,
-                                         _frame_structure,
-                                         _frame_state);
+    return FrameBase::emplaceKeyFrame<FrameBase>(getTrajectory(),
+                                                 _time_stamp,
+                                                 _frame_structure,
+                                                 _frame_state);
 }
 
-FrameBasePtr Problem::emplaceFrame (FrameType _frame_key_type, //
-                                    const TimeStamp& _time_stamp, //
-                                    const VectorComposite& _frame_state)
+FrameBasePtr Problem::emplaceKeyFrame (const TimeStamp& _time_stamp, //
+                                       const VectorComposite& _frame_state)
 {
-    return FrameBase::emplace<FrameBase>(getTrajectory(),
-                                         _frame_key_type,
-                                         _time_stamp,
-                                         getFrameStructure(),
-                                         _frame_state);
+    return FrameBase::emplaceKeyFrame<FrameBase>(getTrajectory(),
+                                                 _time_stamp,
+                                                 getFrameStructure(),
+                                                 _frame_state);
 }
 
-FrameBasePtr Problem::emplaceFrame(FrameType _frame_key_type, //
-                                   const TimeStamp& _time_stamp, //
-                                   const Eigen::VectorXd& _frame_state)
+FrameBasePtr Problem::emplaceKeyFrame(const TimeStamp& _time_stamp, //
+                                      const Eigen::VectorXd& _frame_state)
 {
-    return emplaceFrame(_frame_key_type,
-                        _time_stamp,
-                        this->getFrameStructure(),
-                        this->getDim(),
-                        _frame_state);
+    return emplaceKeyFrame(_time_stamp,
+                           this->getFrameStructure(),
+                           this->getDim(),
+                           _frame_state);
 }
 
-FrameBasePtr Problem::emplaceFrame(FrameType _frame_key_type, //
-                                   const TimeStamp& _time_stamp)
+FrameBasePtr Problem::emplaceKeyFrame(const TimeStamp& _time_stamp)
 {
-    return emplaceFrame(_frame_key_type,
-                        _time_stamp,
-                        this->getFrameStructure(),
-                        this->getDim());
+    return emplaceKeyFrame(_time_stamp,
+                           this->getFrameStructure(),
+                           this->getDim());
 }
 
 TimeStamp Problem::getTimeStamp ( ) const
@@ -427,7 +415,7 @@ TimeStamp Problem::getTimeStamp ( ) const
 
     if (not ts.ok())
     {
-        const auto& last_kf_or_aux = trajectory_ptr_->getLastKeyOrAuxFrame();
+        const auto& last_kf_or_aux = trajectory_ptr_->getLastFrame();
 
         if (last_kf_or_aux)
             ts = last_kf_or_aux->getTimeStamp(); // Use last estimated frame's state
@@ -461,7 +449,7 @@ VectorComposite Problem::getState(const StateStructure& _structure) const
 
     VectorComposite state_last;
 
-    const auto& last_kf_or_aux = trajectory_ptr_->getLastKeyOrAuxFrame();
+    const auto& last_kf_or_aux = trajectory_ptr_->getLastFrame();
 
     if (last_kf_or_aux)
         state_last = last_kf_or_aux->getState(structure);
@@ -510,7 +498,7 @@ VectorComposite Problem::getState (const TimeStamp& _ts, const StateStructure& _
 
     VectorComposite state_last;
 
-    const auto& last_kf_or_aux = trajectory_ptr_->closestKeyOrAuxFrameToTimeStamp(_ts);
+    const auto& last_kf_or_aux = trajectory_ptr_->closestFrameToTimeStamp(_ts);
 
     if (last_kf_or_aux)
         state_last = last_kf_or_aux->getState(structure);
@@ -871,15 +859,9 @@ bool Problem::getFrameCovariance(FrameBaseConstPtr _frame_ptr, Eigen::MatrixXd&
     return success;
 }
 
-bool Problem::getLastKeyFrameCovariance(Eigen::MatrixXd& cov) const
+bool Problem::getLastFrameCovariance(Eigen::MatrixXd& cov) const
 {
-    FrameBasePtr frm = getLastKeyFrame();
-    return getFrameCovariance(frm, cov);
-}
-
-bool Problem::getLastKeyOrAuxFrameCovariance(Eigen::MatrixXd& cov) const
-{
-    FrameBasePtr frm = getLastKeyOrAuxFrame();
+    FrameBasePtr frm = getLastFrame();
     return getFrameCovariance(frm, cov);
 }
 
@@ -963,24 +945,9 @@ FrameBasePtr Problem::getLastFrame() const
     return trajectory_ptr_->getLastFrame();
 }
 
-FrameBasePtr Problem::getLastKeyFrame() const
-{
-    return trajectory_ptr_->getLastKeyFrame();
-}
-
-FrameBasePtr Problem::getLastKeyOrAuxFrame() const
-{
-    return trajectory_ptr_->getLastKeyOrAuxFrame();
-}
-
-FrameBasePtr Problem::closestKeyFrameToTimeStamp(const TimeStamp& _ts) const
-{
-    return trajectory_ptr_->closestKeyFrameToTimeStamp(_ts);
-}
-
-FrameBasePtr Problem::closestKeyOrAuxFrameToTimeStamp(const TimeStamp& _ts) const
+FrameBasePtr Problem::closestFrameToTimeStamp(const TimeStamp& _ts) const
 {
-    return trajectory_ptr_->closestKeyOrAuxFrameToTimeStamp(_ts);
+    return trajectory_ptr_->closestFrameToTimeStamp(_ts);
 }
 
 void Problem::setPriorOptions(const std::string& _mode,
@@ -1036,9 +1003,8 @@ FrameBasePtr Problem::applyPriorOptions(const TimeStamp& _ts)
 
     if (prior_options_->mode != "nothing" and prior_options_->mode != "")
     {
-        prior_keyframe = emplaceFrame(KEY,
-                                      _ts,
-                                      prior_options_->state);
+        prior_keyframe = emplaceKeyFrame(_ts,
+                                         prior_options_->state);
 
         if (prior_options_->mode == "fix")
             prior_keyframe->fix();
@@ -1198,9 +1164,9 @@ void Problem::perturb(double amplitude)
         S->perturb(amplitude);
 
     // Frames and Captures
-    for (auto& F : getTrajectory()->getFrameList())
+    for (auto& F : *(getTrajectory()))
     {
-        if (F->isKeyOrAux())
+        if (F->isKey())
         {
             F->perturb(amplitude);
             for (auto& C : F->getCaptureList())
diff --git a/src/processor/processor_motion.cpp b/src/processor/processor_motion.cpp
index f831e077a2b1ea698b24438a8c29fe3d7982dbc6..f56b8c80a344e864f16be3ca2f8f006a0996052f 100644
--- a/src/processor/processor_motion.cpp
+++ b/src/processor/processor_motion.cpp
@@ -34,7 +34,8 @@ ProcessorMotion::ProcessorMotion(const std::string& _type,
         origin_ptr_(),
         last_ptr_(),
         incoming_ptr_(),
-        dt_(0.0), 
+        last_frame_ptr_(),
+        dt_(0.0),
         x_(_state_size),
         delta_(_delta_size),
         delta_cov_(_delta_cov_size, _delta_cov_size),
@@ -385,7 +386,7 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
         // Set the frame of last_ptr as key
         auto key_frame      = last_ptr_->getFrame();
-        key_frame           ->setKey();
+        key_frame           ->setKey(getProblem());
 
         // create motion feature and add it to the key_capture
         auto key_feature    = emplaceFeature(last_ptr_);
@@ -394,10 +395,9 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         auto factor         = emplaceFactor(key_feature, origin_ptr_);
 
         // create a new frame
-        auto frame_new      = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                         getTimeStamp(),
-                                                         getStateStructure(),
-                                                         getProblem()->getState());
+        auto frame_new      = FrameBase::createNonKeyFrame<FrameBase>(getTimeStamp(),
+                                                                      getStateStructure(),
+                                                                      getProblem()->getState());
         // create a new capture
         auto capture_new    = emplaceCapture(frame_new,
                                              getSensor(),
@@ -416,15 +416,18 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         // Reset pointers
         origin_ptr_     = last_ptr_;
         last_ptr_       = capture_new;
+        last_frame_ptr_ = frame_new;
 
         // callback to other processors
         getProblem()->keyFrameCallback(key_frame, shared_from_this(), params_motion_->time_tolerance);
+
     }
 
     // clear incoming just in case
     incoming_ptr_ = nullptr; // This line is not really needed, but it makes things clearer.
 
     postProcess();
+
 }
 
 VectorComposite ProcessorMotion::getState(const StateStructure& _structure) const
@@ -622,10 +625,10 @@ VectorComposite ProcessorMotion::getState(const TimeStamp& _ts, const StateStruc
 
 FrameBasePtr ProcessorMotion::setOrigin(const VectorComposite& _x_origin, const TimeStamp& _ts_origin)
 {
-    FrameBasePtr key_frame_ptr = getProblem()->emplaceFrame(KEY,
-                                                            _ts_origin,
-                                                            getStateStructure(),
-                                                            _x_origin);
+    FrameBasePtr key_frame_ptr = FrameBase::emplaceKeyFrame<FrameBase>(getProblem()->getTrajectory(),
+                                                                       _ts_origin,
+                                                                       getStateStructure(),
+                                                                       _x_origin);
     setOrigin(key_frame_ptr);
 
     return key_frame_ptr;
@@ -653,13 +656,12 @@ void ProcessorMotion::setOrigin(FrameBasePtr _origin_frame)
 
     // ---------- LAST ----------
     // Make non-key-frame for last Capture
-    auto new_frame_ptr  = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                     origin_ts,
-                                                     getProblem()->getFrameStructure(),
-                                                     _origin_frame->getState());
+    last_frame_ptr_  = FrameBase::createNonKeyFrame<FrameBase>(origin_ts,
+                                                               getStateStructure(),
+                                                               _origin_frame->getState());
                                         
     // emplace (emtpy) last Capture
-    last_ptr_ = emplaceCapture(new_frame_ptr,
+    last_ptr_ = emplaceCapture(last_frame_ptr_,
                                getSensor(),
                                origin_ts,
                                Eigen::VectorXd::Zero(data_size_),
@@ -793,6 +795,19 @@ void ProcessorMotion::reintegrateBuffer(CaptureMotionPtr _capture_ptr)
 CaptureMotionPtr ProcessorMotion::findCaptureContainingTimeStamp(const TimeStamp& _ts) const
 {
     assert(_ts.ok());
+    // assert(last_ptr_ != nullptr);
+
+    //Need to uncomment this line so that wolf_ros_apriltag doesn't crash
+    if(last_ptr_ == nullptr) return nullptr;
+
+    // First check if last_ptr is the one we are looking for
+    if (last_ptr_->containsTimeStamp(_ts, this->params_->time_tolerance))
+        return last_ptr_;
+
+
+    // Then look in the Wolf tree...
+    // -----------------------------
+    //
 
     // We need to search in previous keyframes for the capture containing a motion buffer with the queried time stamp
     // Note: since the buffer goes from a KF in the past until the next KF, we need to:
@@ -802,8 +817,8 @@ CaptureMotionPtr ProcessorMotion::findCaptureContainingTimeStamp(const TimeStamp
     FrameBasePtr     frame          = nullptr;
     CaptureBasePtr   capture        = nullptr;
     CaptureMotionPtr capture_motion = nullptr;
-    for (auto frame_rev_iter = getProblem()->getTrajectory()->getFrameList().rbegin();
-            frame_rev_iter != getProblem()->getTrajectory()->getFrameList().rend();
+    for (auto frame_rev_iter = getProblem()->getTrajectory()->rbegin();
+            frame_rev_iter != getProblem()->getTrajectory()->rend();
             ++frame_rev_iter)
     {
         frame   = *frame_rev_iter;
@@ -921,10 +936,10 @@ void ProcessorMotion::printHeader(int _depth, bool _constr_by, bool _metric, boo
 {
     _stream << _tabs << "PrcM" << id() << " " << getType() << " \"" << getName() << "\"" << std::endl;
     if (getOrigin())
-        _stream << _tabs << "  " << "o: Cap" << getOrigin()->id() << " - " << (getOrigin()->getFrame()->isKeyOrAux() ? (getOrigin()->getFrame()->isKey() ? "  KFrm" : "  AFrm" ) : "  Frm")
+        _stream << _tabs << "  " << "o: Cap" << getOrigin()->id() << " - " << (getOrigin()->getFrame()->isKey() ? "  KFrm" : "  Frm" )
                 << getOrigin()->getFrame()->id() << std::endl;
     if (getLast())
-        _stream << _tabs << "  " << "l: Cap" << getLast()->id() << " - " << (getLast()->getFrame()->isKeyOrAux() ? (getLast()->getFrame()->isKey() ? "  KFrm" : " AFrm") : "  Frm")
+        _stream << _tabs << "  " << "l: Cap" << getLast()->id() << " - " << (getLast()->getFrame()->isKey() ? "  KFrm" : " Frm")
                 << getLast()->getFrame()->id() << std::endl;
     if (getIncoming())
         _stream << _tabs << "  " << "i: Cap" << getIncoming()->id() << std::endl;
diff --git a/src/processor/processor_odom_3d.cpp b/src/processor/processor_odom_3d.cpp
index d6f7e77a9562e8762f9ab99c9ac525b8fe592c54..c7be4d48c4d086d5d4f594dfa7849419d8cc5c30 100644
--- a/src/processor/processor_odom_3d.cpp
+++ b/src/processor/processor_odom_3d.cpp
@@ -13,7 +13,11 @@ ProcessorOdom3d::ProcessorOdom3d(ParamsProcessorOdom3dPtr _params) :
                         min_disp_var_   (0.1),          // around 10cm error
                         min_rot_var_    (0.1)           // around 6 degrees error
 {
-    //
+     // Set constant parts of Jacobians
+    jacobian_delta_preint_.setIdentity(6,6);
+    jacobian_delta_.setIdentity(6,6);
+    jacobian_calib_.setZero(6,0);
+    unmeasured_perturbation_cov_ = pow(params_odom_3d_->unmeasured_perturbation_std, 2.0) * Eigen::Matrix6d::Identity();   
 }
 
 ProcessorOdom3d::~ProcessorOdom3d()
diff --git a/src/processor/processor_tracker.cpp b/src/processor/processor_tracker.cpp
index 14db03bed63e3ee272f450a15838758108778a4d..91867f39528b54cc7335fcca91e7fcc108757576 100644
--- a/src/processor/processor_tracker.cpp
+++ b/src/processor/processor_tracker.cpp
@@ -24,6 +24,7 @@ ProcessorTracker::ProcessorTracker(const std::string& _type,
         origin_ptr_(nullptr),
         last_ptr_(nullptr),
         incoming_ptr_(nullptr),
+        last_frame_ptr_(nullptr),
         state_structure_(_structure)
 {
     //
@@ -80,10 +81,10 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
         {
             WOLF_DEBUG( "PT ", getName(), " FIRST_TIME_WITHOUT_PACK" );
 
-            FrameBasePtr kfrm = getProblem()->emplaceFrame(KEY,
-                                                           incoming_ptr_->getTimeStamp());//,
-                                                           //getStateStructure(),
-                                                           //getProblem()->getState(getStateStructure()));
+            FrameBasePtr kfrm = FrameBase::emplaceKeyFrame<FrameBase>(getProblem()->getTrajectory(),
+                                                                      incoming_ptr_->getTimeStamp(),
+                                                                      getStateStructure(),
+                                                                      getProblem()->getState(getStateStructure()));
             incoming_ptr_->link(kfrm);
 
             // Process info
@@ -113,10 +114,10 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
         {
             WOLF_DEBUG( "PT ", getName(), " SECOND_TIME_WITHOUT_PACK" );
 
-            FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                          incoming_ptr_->getTimeStamp());
+            FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp(),
+                                                                       getProblem()->getFrameStructure(),
+                                                                       getProblem()->getState());
             incoming_ptr_->link(frm);
-
             // We have a last_ Capture with no features, so we do not process known features, and we do not vote for KF.
 
             // Process info
@@ -130,6 +131,7 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
             resetDerived();
             origin_ptr_ = last_ptr_;
             last_ptr_   = incoming_ptr_;
+            last_frame_ptr_ = frm;
             incoming_ptr_ = nullptr;
 
             break;
@@ -149,8 +151,9 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
             last_old_frame->remove();
 
             // Create new frame
-            FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                          incoming_ptr_->getTimeStamp());
+            FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp(),
+                                                                       getProblem()->getFrameStructure(),
+                                                                       getProblem()->getState());
             incoming_ptr_->link(frm);
 
             // Detect new Features, initialize Landmarks, create Factors, ...
@@ -163,6 +166,7 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
             resetDerived();
             origin_ptr_ = last_ptr_;
             last_ptr_   = incoming_ptr_;
+            last_frame_ptr_ = frm;
             incoming_ptr_ = nullptr;
 
             break;
@@ -183,10 +187,10 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
                 // We create a KF
                 // set KF on last
                 last_ptr_->getFrame()->setState(getProblem()->getState(last_ptr_->getTimeStamp()));
-                last_ptr_->getFrame()->setKey();
+                last_ptr_->getFrame()->setKey(getProblem());
 
                 // // make F; append incoming to new F
-                // FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED, incoming_ptr_->getTimeStamp());
+                // FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp());
                 // incoming_ptr_->link(frm);
 
                 // Establish factors
@@ -199,13 +203,13 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
                 resetDerived();
 
                 // make F; append incoming to new F
-                FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                              incoming_ptr_->getTimeStamp(),
-                                                              last_ptr_->getFrame()->getState());
+                FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp(),
+                                                                           getProblem()->getFrameStructure(),
+                                                                           last_ptr_->getFrame()->getState());
                 incoming_ptr_->link(frm);
-
                 origin_ptr_ = last_ptr_;
                 last_ptr_   = incoming_ptr_;
+                last_frame_ptr_ = frm;
                 incoming_ptr_ = nullptr;
 
             }
@@ -219,7 +223,7 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
                 last_ptr_->getFrame()->setAuxiliary();
 
                 // make F; append incoming to new F
-                FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED, incoming_ptr_->getTimeStamp());
+                FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp());
                 incoming_ptr_->link(frm);
 
                 // Establish factors
@@ -248,14 +252,15 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
                 advanceDerived();
 
                 // Replace last frame for a new one in incoming
-                FrameBasePtr frm = getProblem()->emplaceFrame(NON_ESTIMATED,
-                                                              incoming_ptr_->getTimeStamp(),
-                                                              last_ptr_->getFrame()->getState());
+                FrameBasePtr frm = FrameBase::createNonKeyFrame<FrameBase>(incoming_ptr_->getTimeStamp(),
+                                                                           getProblem()->getFrameStructure(),
+                                                                           last_ptr_->getFrame()->getState());
                 incoming_ptr_->link(frm);
                 last_ptr_->getFrame()->remove(); // implicitly calling last_ptr_->remove();
 
                 // Update pointers
                 last_ptr_       = incoming_ptr_;
+                last_frame_ptr_ = frm;
                 incoming_ptr_   = nullptr;
             }
             break;
@@ -337,10 +342,10 @@ void ProcessorTracker::printHeader(int _depth, bool _constr_by, bool _metric, bo
 {
     _stream << _tabs << "PrcT" << id() << " " << getType() << " \"" << getName() << "\"" << std::endl;
     if (getOrigin())
-        _stream << _tabs << "  " << "o: Cap" << getOrigin()->id() << " - " << (getOrigin()->getFrame()->isKeyOrAux() ? (getOrigin()->getFrame()->isKey() ? "  KFrm" : " AFrm") : "  Frm")
+        _stream << _tabs << "  " << "o: Cap" << getOrigin()->id() << " - " << (getOrigin()->getFrame()->isKey() ? "  KFrm" : " Frm")
                 << getOrigin()->getFrame()->id() << std::endl;
     if (getLast())
-        _stream << _tabs << "  " << "l: Cap" << getLast()->id() << " - " << (getLast()->getFrame()->isKeyOrAux() ? (getLast()->getFrame()->isKey() ? "  KFrm" : " AFrm") : "  Frm")
+        _stream << _tabs << "  " << "l: Cap" << getLast()->id() << " - " << (getLast()->getFrame()->isKey() ? "  KFrm" : " Frm")
                 << getLast()->getFrame()->id() << std::endl;
     if (getIncoming())
         _stream << _tabs << "  " << "i: Cap" << getIncoming()->id() << std::endl;
diff --git a/src/sensor/sensor_base.cpp b/src/sensor/sensor_base.cpp
index b32f02f3dca55c584567b8d84e220a2f2604114b..fefc4d332eca061b041585bf42c6248fb985d992 100644
--- a/src/sensor/sensor_base.cpp
+++ b/src/sensor/sensor_base.cpp
@@ -220,9 +220,10 @@ CaptureBasePtr SensorBase::lastCapture(void) const
     CaptureBasePtr capture = nullptr;
     if (getProblem())
     {
-        FrameBasePtrList frame_list = getProblem()->getTrajectory()->getFrameList();
-        FrameBaseRevIter frame_rev_it = frame_list.rbegin();
-        while (frame_rev_it != frame_list.rend())
+        // auto frame_list = getProblem()->getTrajectory()->getFrameMap();
+        auto trajectory = getProblem()->getTrajectory();
+        TrajectoryRevIter frame_rev_it = trajectory->rbegin();
+        while (frame_rev_it != trajectory->rend())
         {
             capture = (*frame_rev_it)->getCaptureOf(shared_from_this());
             if (capture)
@@ -240,9 +241,9 @@ CaptureBasePtr SensorBase::lastKeyCapture(void) const
     CaptureBasePtr capture = nullptr;
     if (getProblem())
     {
-        FrameBasePtrList frame_list = getProblem()->getTrajectory()->getFrameList();
-        FrameBaseRevIter frame_rev_it = frame_list.rbegin();
-        while (frame_rev_it != frame_list.rend())
+        auto trajectory = getProblem()->getTrajectory();
+        TrajectoryRevIter frame_rev_it = trajectory->rbegin();
+        while (frame_rev_it != trajectory->rend())
         {
             if ((*frame_rev_it)->isKey())
             {
@@ -263,11 +264,12 @@ CaptureBasePtr SensorBase::lastCapture(const TimeStamp& _ts) const
     CaptureBasePtr capture = nullptr;
     if (getProblem())
     {
-        FrameBasePtrList frame_list = getProblem()->getTrajectory()->getFrameList();
+        // auto frame_list = getProblem()->getTrajectory()->getFrameMap();
+        auto trajectory = getProblem()->getTrajectory();
 
         // We iterate in reverse since we're likely to find it close to the rbegin() place.
-        FrameBaseRevIter frame_rev_it = frame_list.rbegin();
-        while (frame_rev_it != frame_list.rend())
+        TrajectoryRevIter frame_rev_it = trajectory->rbegin();
+        while (frame_rev_it != trajectory->rend())
         {
             if ((*frame_rev_it)->getTimeStamp() <= _ts)
             {
diff --git a/src/solver/solver_manager.cpp b/src/solver/solver_manager.cpp
index 4a74ca8194f9b2b6111fb69d4c97bb7a4875b60e..60b06fd1f7b0744f8c8a293ff4f35e0e265c9f60 100644
--- a/src/solver/solver_manager.cpp
+++ b/src/solver/solver_manager.cpp
@@ -56,12 +56,24 @@ void SolverManager::update()
 
         // remove
         else
-            removeStateBlock(sb_notification_map.begin()->first);
+        {
+            if (floating_state_blocks_.count(sb_notification_map.begin()->first) == 1)
+                floating_state_blocks_.erase(sb_notification_map.begin()->first);
+            else
+                removeStateBlock(sb_notification_map.begin()->first);
+        }
 
         // remove notification
         sb_notification_map.erase(sb_notification_map.begin());
     }
 
+    // ADD "floating" STATE BLOCKS (last update they weren't involved in any factor)
+    while (!floating_state_blocks_.empty())
+    {
+        addStateBlock(*floating_state_blocks_.begin());
+        floating_state_blocks_.erase(floating_state_blocks_.begin());
+    }
+
     // ADD FACTORS
     while (!fac_notification_map.empty())
     {
@@ -79,6 +91,14 @@ void SolverManager::update()
     {
         auto state_ptr = state_pair.first;
 
+        // Check for "floating" state blocks (estimated but not involved in any factor -> not observable problem)
+        if (state_blocks_2_factors_.at(state_ptr).empty())
+        {
+            WOLF_INFO("SolverManager::update(): 'Floating' StateBlock ", state_ptr, " (not involved in any factor) Storing it apart.");
+            floating_state_blocks_.insert(state_ptr);
+            continue;
+        }
+
         // state update
         if (state_ptr->stateUpdated())
             updateStateBlockState(state_ptr);
@@ -92,6 +112,16 @@ void SolverManager::update()
             updateStateBlockLocalParametrization(state_ptr);
     }
 
+    // REMOVE "floating" STATE BLOCKS (will be added next update() call)
+    for (auto state_ptr : floating_state_blocks_)
+    {
+        removeStateBlock(state_ptr);
+        // reset flags meaning "solver will handle this change" (state, fix and local param will be set in addStateBlock)
+        state_ptr->resetStateUpdated();
+        state_ptr->resetFixUpdated();
+        state_ptr->resetLocalParamUpdated();
+    }
+
     #ifdef _WOLF_DEBUG
         assert(check("after update()"));
     #endif
@@ -321,14 +351,67 @@ SolverManager::ReportVerbosity SolverManager::getVerbosity() const
     return params_->verbose;
 }
 
-bool SolverManager::isStateBlockRegistered(const StateBlockPtr& state_ptr)
+bool SolverManager::isStateBlockRegistered(const StateBlockPtr& state_ptr) const
+{
+    return isStateBlockFloating(state_ptr) or (state_blocks_.count(state_ptr) == 1 and isStateBlockRegisteredDerived(state_ptr));
+}
+
+bool SolverManager::isStateBlockFloating(const StateBlockPtr& state_ptr) const
 {
-    return state_blocks_.count(state_ptr) ==1 && isStateBlockRegisteredDerived(state_ptr);
+    return floating_state_blocks_.count(state_ptr) == 1;
 }
 
 bool SolverManager::isFactorRegistered(const FactorBasePtr& fac_ptr) const
 {
-    return isFactorRegisteredDerived(fac_ptr);
+    return factors_.count(fac_ptr) and isFactorRegisteredDerived(fac_ptr);
+}
+
+bool SolverManager::isStateBlockFixed(const StateBlockPtr& st)
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->isFixed();
+
+    return isStateBlockFixedDerived(st);
+}
+
+bool SolverManager::hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param)
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->getLocalParametrization() == local_param;
+
+    return hasThisLocalParametrizationDerived(st, local_param);
+};
+
+bool SolverManager::hasLocalParametrization(const StateBlockPtr& st) const
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->hasLocalParametrization();
+
+    return hasLocalParametrizationDerived(st);
+};
+
+int SolverManager::numFactors() const
+{
+    return factors_.size();
+}
+
+int SolverManager::numStateBlocks() const
+{
+    return state_blocks_.size() + floating_state_blocks_.size();
+}
+
+int SolverManager::numStateBlocksFloating() const
+{
+    return floating_state_blocks_.size();
 }
 
 double SolverManager::getPeriod() const
@@ -357,15 +440,32 @@ bool SolverManager::check(std::string prefix) const
             ok = false;
         }
 
-        // factor involving state block in factors_
-        for (auto fac : sb_fac_it->second)
+        // no factors involving state block
+        if (sb_fac_it->second.empty())
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb_fac_it->first, " is in state_blocks_ but not involved in any factor - in ", prefix);
+            ok = false;
+        }
+        else
         {
-            if (factors_.count(fac) == 0)
+            // factor involving state block in factors_
+            for (auto fac : sb_fac_it->second)
             {
-                WOLF_ERROR("SolverManager::check: factor ", fac->id(), " (involved in sb ", sb_fac_it->first, ") missing in factors_ map - in ", prefix);
-                ok = false;
+                if (factors_.count(fac) == 0)
+                {
+                    WOLF_ERROR("SolverManager::check: factor ", fac->id(), " (involved in sb ", sb_fac_it->first, ") missing in factors_ map - in ", prefix);
+                    ok = false;
+                }
             }
         }
+
+        // can't be in both state_blocks_ and floating_state_blocks_
+        if (floating_state_blocks_.count(sb_fac_it->first) == 1)
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb_fac_it->first, " is both in state_blocks_ and floating_state_blocks_ - in ", prefix);
+            ok = false;
+        }
+
         sb_vec_it++;
         sb_fac_it++;
     }
@@ -384,9 +484,38 @@ bool SolverManager::check(std::string prefix) const
         }
     }
 
-    // checkDerived
+    // CHECK DERIVED ----------------------
     ok &= checkDerived(prefix);
 
+    // CHECK IF DERIVED IS UP TO DATE ----------------------
+    // state blocks registered in derived solver
+    for (auto sb : state_blocks_)
+        if (!isStateBlockRegisteredDerived(sb.first))
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb.first, " is in state_blocks_ but not registered in derived solver - in ", prefix);
+            ok = false;
+        }
+
+    // factors registered in derived solver
+    for (auto fac : factors_)
+        if (!isFactorRegisteredDerived(fac))
+        {
+            WOLF_ERROR("SolverManager::check: factor ", fac->id(), " is in factors_ but not registered in derived solver - in ", prefix);
+            ok = false;
+        }
+
+    // numbers
+    if (numStateBlocksDerived() != state_blocks_.size())
+    {
+        WOLF_ERROR("SolverManager::check: numStateBlocksDerived() = ", numStateBlocksDerived(), " DIFFERENT THAN state_blocks_.size() = ", state_blocks_.size(), " - in ", prefix);
+        ok = false;
+    }
+    if (numFactorsDerived() != numFactors())
+    {
+        WOLF_ERROR("SolverManager::check: numFactorsDerived() = ", numFactorsDerived(), " DIFFERENT THAN numFactors() = ", numFactors(), " - in ", prefix);
+        ok = false;
+    }
+
     return ok;
 }
 
diff --git a/src/trajectory/trajectory_base.cpp b/src/trajectory/trajectory_base.cpp
index ad760c8c3ccf2942f734c256e7b04ed3d59aecf7..8ab61006c9e46acfdeee6ad735257bdf9d776ff7 100644
--- a/src/trajectory/trajectory_base.cpp
+++ b/src/trajectory/trajectory_base.cpp
@@ -4,11 +4,10 @@
 namespace wolf {
 
 TrajectoryBase::TrajectoryBase() :
-    NodeBase("TRAJECTORY", "TrajectoryBase"),
-    last_key_frame_ptr_(nullptr),
-    last_key_or_aux_frame_ptr_(nullptr)
+    NodeBase("TRAJECTORY", "TrajectoryBase")
 {
 //    WOLF_DEBUG("constructed T");
+    frame_map_ = FrameMap();
 }
 
 TrajectoryBase::~TrajectoryBase()
@@ -19,16 +18,9 @@ TrajectoryBase::~TrajectoryBase()
 FrameBasePtr TrajectoryBase::addFrame(FrameBasePtr _frame_ptr)
 {
     // add to list
-    frame_list_.push_back(_frame_ptr);
+    assert(frame_map_.count(_frame_ptr->getTimeStamp()) == 0 && "Trying to add a keyframe with the same timestamp of an existing one");
 
-    if (_frame_ptr->isKeyOrAux())
-    {
-        // sort
-        sortFrame(_frame_ptr);
-
-        // update last_estimated and last_key
-        updateLastFrames();
-    }
+    frame_map_.emplace(_frame_ptr->getTimeStamp(), _frame_ptr);
 
     return _frame_ptr;
 }
@@ -36,114 +28,69 @@ FrameBasePtr TrajectoryBase::addFrame(FrameBasePtr _frame_ptr)
 void TrajectoryBase::removeFrame(FrameBasePtr _frame_ptr)
 {
     // add to list
-    frame_list_.remove(_frame_ptr);
-
-    // update last_estimated and last_key
-    if (_frame_ptr->isKeyOrAux())
-        updateLastFrames();
+    // frame_map_.erase(_frame_ptr);
+    frame_map_.erase(_frame_ptr->getTimeStamp());
 }
 
 void TrajectoryBase::getFactorList(FactorBasePtrList & _fac_list) const
 {
-	for(auto fr_ptr : getFrameList())
+	for(auto fr_ptr : *this)
 		fr_ptr->getFactorList(_fac_list);
 }
 
-void TrajectoryBase::sortFrame(FrameBasePtr _frame_ptr)
-{
-    moveFrame(_frame_ptr, computeFrameOrder(_frame_ptr));
-}
-
-void TrajectoryBase::moveFrame(FrameBasePtr _frm_ptr, FrameBaseConstIter _place)
-{
-    if (*_place != _frm_ptr)
-    {
-        frame_list_.remove(_frm_ptr);
-        frame_list_.insert(_place, _frm_ptr);
-        updateLastFrames();
-    }
-}
-
-FrameBaseConstIter TrajectoryBase::computeFrameOrder(FrameBasePtr _frame_ptr)
-{
-    for (auto frm_rit = getFrameList().rbegin(); frm_rit != getFrameList().rend(); frm_rit++)
-        if ((*frm_rit)!= _frame_ptr && (*frm_rit)->isKeyOrAux() && (*frm_rit)->getTimeStamp() <= _frame_ptr->getTimeStamp())
-            return frm_rit.base();
-    return getFrameList().begin();
-}
-
-void TrajectoryBase::updateLastFrames()
-{
-    bool last_estimated_set = false;
-
-    // NOTE: Assumes estimated (key or auxiliary) frames are sorted by timestamp
-    for (auto frm_rit = getFrameList().rbegin(); frm_rit != getFrameList().rend(); ++frm_rit)
-        if ((*frm_rit)->isKeyOrAux())
-        {
-            if (!last_estimated_set)
-            {
-                last_key_or_aux_frame_ptr_ = (*frm_rit);
-                last_estimated_set = true;
-            }
-            if ((*frm_rit)->isKey())
-            {
-                last_key_frame_ptr_ = (*frm_rit);
-                break;
-            }
-        }
-}
 
-FrameBasePtr TrajectoryBase::closestKeyFrameToTimeStamp(const TimeStamp& _ts) const
+FrameBasePtr TrajectoryBase::closestFrameToTimeStamp(const TimeStamp& _ts) const
 {
-    // NOTE: Assumes estimated (key or auxiliary) frames are sorted by timestamp
     FrameBasePtr closest_kf = nullptr;
-    double min_dt = 1e9;
-
-    for (auto frm_rit = frame_list_.rbegin(); frm_rit != frame_list_.rend(); frm_rit++)
-        if ((*frm_rit)->isKey())
+    //If frame_map_ is empty then closestFrameToTimeStamp is meaningless
+    if(not frame_map_.empty())
+    {
+        //Let me use shorter names for this explanation: lower_bound -> lb & upper_bound -> ub
+        //In the std they fulfill the following property:
+        //        lb is the first element such that ts <= lb, alternatively the smallest element that is NOT less than ts.
+        // lb definition is NOT the ACTUAL lower bound but the following position so, lb = lb_true + 1.
+
+        auto lower_bound = frame_map_.lower_bound(_ts);
+        if((lower_bound != this->end() and lower_bound->first == _ts) or lower_bound == this->begin() ) closest_kf = lower_bound->second;
+        else
         {
-            double dt = std::fabs((*frm_rit)->getTimeStamp() - _ts);
-            if (dt < min_dt)
-            {
-                min_dt = dt;
-                closest_kf = *frm_rit;
-            }
+            auto upper_bound = lower_bound;
+            //I find it easier to reason if lb < ts < ub. Remember that we have got rid of the
+            //equality case and the out of bounds cases so this inequality is complete (it is not misssing cases).
+            //Therefore, we need to decrease the lower_bound to the previous element
+            lower_bound = std::prev(lower_bound);
+
+            //If ub points to end() it means that the last frame is still less than _ts, therefore certainly
+            //it will be the closest one
+            if(upper_bound == this->end()) closest_kf = lower_bound->second;
             else
-                break;
-        }
-    return closest_kf;
-}
-
-FrameBasePtr TrajectoryBase::closestKeyOrAuxFrameToTimeStamp(const TimeStamp& _ts) const
-{
-    // NOTE: Assumes estimated (key or auxiliary) frames are sorted by timestamp
-    FrameBasePtr closest_kf = nullptr;
-    double min_dt = 1e9;
-
-    for (auto frm_rit = frame_list_.rbegin(); frm_rit != frame_list_.rend(); frm_rit++)
-        if ((*frm_rit)->isKeyOrAux())
-        {
-            double dt = std::fabs((*frm_rit)->getTimeStamp() - _ts);
-            if (dt < min_dt)
             {
-                min_dt = dt;
-                closest_kf = *frm_rit;
+                //Easy stuff just calculate the distance return minimum
+                auto lb_diff = fabs(lower_bound->first - _ts);
+                auto ub_diff = fabs(upper_bound->first - _ts);
+                if(lb_diff < ub_diff)
+                {
+                    closest_kf = lower_bound->second;
+                }
+                else
+                {
+                    closest_kf = upper_bound->second;
+                }
             }
-            else
-                break;
         }
+    }
     return closest_kf;
 }
 
 void TrajectoryBase::printHeader(int _depth, bool _metric, bool _state_blocks, bool _constr_by, std::ostream& _stream, std::string _tabs) const
 {
-    _stream << _tabs << "Trajectory" << ((_depth < 1) ? (" -- " + std::to_string(getFrameList().size()) + "F") : "")  << std::endl;
+    _stream << _tabs << "Trajectory" << ((_depth < 1) ? (" -- " + std::to_string(getFrameMap().size()) + "F") : "")  << std::endl;
 }
 void TrajectoryBase::print(int _depth, bool _constr_by, bool _metric, bool _state_blocks, std::ostream& _stream, std::string _tabs) const
 {
     printHeader(_depth, _constr_by, _metric, _state_blocks, _stream, _tabs);
     if (_depth >= 1)
-        for (auto F : getFrameList())
+        for (auto F : *this)
             F->print(_depth, _constr_by, _metric, _state_blocks, _stream, _tabs + "  ");
 
 }
@@ -169,7 +116,7 @@ bool TrajectoryBase::check(CheckLog& _log, std::shared_ptr<NodeBase> _node_ptr,
     auto trj_ptr = std::static_pointer_cast<TrajectoryBase>(_node_ptr);
     auto local_log = localCheck(_verbose, trj_ptr, _stream, _tabs);
     _log.compose(local_log);
-    for (auto F : getFrameList())
+    for (auto F : *this)
         F->check(_log, F, _verbose, _stream, _tabs + "  ");
     return _log.is_consistent_;
 }
diff --git a/src/tree_manager/tree_manager_sliding_window.cpp b/src/tree_manager/tree_manager_sliding_window.cpp
index 5816567557bdd2ca5779615834a3f48a418bbabe..623c7bec91214b55f7d2d8f2034dbba3e01c5ccb 100644
--- a/src/tree_manager/tree_manager_sliding_window.cpp
+++ b/src/tree_manager/tree_manager_sliding_window.cpp
@@ -7,7 +7,7 @@ void TreeManagerSlidingWindow::keyFrameCallback(FrameBasePtr _key_frame)
 {
     int n_kf(0);
     FrameBasePtr first_KF(nullptr), second_KF(nullptr);
-    for (auto frm : getProblem()->getTrajectory()->getFrameList())
+    for (auto frm : *getProblem()->getTrajectory())
     {
         if (frm->isKey())
         {
diff --git a/src/yaml/parser_yaml.cpp b/src/yaml/parser_yaml.cpp
index d50e1b53096e248e5b5776243ad1aa831b41b50c..6efc250f44ed45f4da571bb747f8cc9fb875f4f6 100644
--- a/src/yaml/parser_yaml.cpp
+++ b/src/yaml/parser_yaml.cpp
@@ -345,6 +345,12 @@ void ParserYaml::updateActiveName(std::string _tag)
 {
     active_name_ = _tag;
 }
+/*
+** @brief This function is responsible for parsing the first level of the YAML file.
+** The first level here can be thought as the entry point of the YAML file. Since we impose a certain structure
+** this function is responsible for enforcing said structure.
+**
+ */
 void ParserYaml::parseFirstLevel(YAML::Node _n, std::string _file)
 {
 
@@ -550,6 +556,9 @@ void ParserYaml::parse()
     }
     parsing_file_.pop();
 }
+/*
+** @brief This function gives the ability to run the parser without enforcing the wolf YAML structure.
+ */
 void ParserYaml::parse_freely()
 {
     parsing_file_.push(generatePath(file_));
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 96656415449da2d8b229f67d11e76529c34764d3..88bcfc88a48286994ec38aee96c3cb44eb25a200 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -28,7 +28,7 @@ include_directories(${GTEST_INCLUDE_DIRS})
 #                                                         #
 # Create a specific test executable for gtest_example     #
 wolf_add_gtest(gtest_example gtest_example.cpp)           #
-target_link_libraries(gtest_example ${PROJECT_NAME})      #
+target_link_libraries(gtest_example ${PLUGIN_NAME})      #
 #                                                         #
 ###########################################################
 set(SRC_DUMMY
@@ -36,7 +36,7 @@ set(SRC_DUMMY
   dummy/processor_tracker_landmark_dummy.cpp
   )
 add_library(dummy SHARED ${SRC_DUMMY})
-target_link_libraries(dummy ${PROJECT_NAME})
+target_link_libraries(dummy ${PLUGIN_NAME})
 ################# ADD YOUR TESTS BELOW ####################
 #                                                         #
 #           ==== IN ALPHABETICAL ORDER! ====              #
@@ -46,221 +46,219 @@ target_link_libraries(dummy ${PROJECT_NAME})
 
 # CaptureBase class test
 wolf_add_gtest(gtest_capture_base gtest_capture_base.cpp)
-target_link_libraries(gtest_capture_base ${PROJECT_NAME})
+target_link_libraries(gtest_capture_base ${PLUGIN_NAME})
 
 # Converter from String to various types used by the parameters server
 wolf_add_gtest(gtest_converter gtest_converter.cpp)
-target_link_libraries(gtest_converter ${PROJECT_NAME})
+target_link_libraries(gtest_converter ${PLUGIN_NAME})
 
 # FactorBase class test
 wolf_add_gtest(gtest_factor_base gtest_factor_base.cpp)
-target_link_libraries(gtest_factor_base ${PROJECT_NAME})
+target_link_libraries(gtest_factor_base ${PLUGIN_NAME})
 
 # FactorAutodiff class test
 wolf_add_gtest(gtest_factor_autodiff gtest_factor_autodiff.cpp)
-target_link_libraries(gtest_factor_autodiff ${PROJECT_NAME})
+target_link_libraries(gtest_factor_autodiff ${PLUGIN_NAME})
 
 # FactoryStateBlock factory test
 wolf_add_gtest(gtest_factory_state_block gtest_factory_state_block.cpp)
-target_link_libraries(gtest_factory_state_block ${PROJECT_NAME})
+target_link_libraries(gtest_factory_state_block ${PLUGIN_NAME})
 
 # FeatureBase classes test
 wolf_add_gtest(gtest_eigen_predicates gtest_eigen_predicates.cpp)
-target_link_libraries(gtest_eigen_predicates ${PROJECT_NAME})
+target_link_libraries(gtest_eigen_predicates ${PLUGIN_NAME})
 
 # Node Emplace test
 wolf_add_gtest(gtest_emplace gtest_emplace.cpp)
-target_link_libraries(gtest_emplace ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_emplace ${PLUGIN_NAME} dummy)
 
 # FeatureBase classes test
 wolf_add_gtest(gtest_feature_base gtest_feature_base.cpp)
-target_link_libraries(gtest_feature_base ${PROJECT_NAME})
+target_link_libraries(gtest_feature_base ${PLUGIN_NAME})
 
 # FrameBase classes test
 wolf_add_gtest(gtest_frame_base gtest_frame_base.cpp)
-target_link_libraries(gtest_frame_base ${PROJECT_NAME})
+target_link_libraries(gtest_frame_base ${PLUGIN_NAME})
 
 # HasStateBlocks classes test
 wolf_add_gtest(gtest_has_state_blocks gtest_has_state_blocks.cpp)
-target_link_libraries(gtest_has_state_blocks ${PROJECT_NAME})
+target_link_libraries(gtest_has_state_blocks ${PLUGIN_NAME})
 
 # LocalParametrizationXxx classes test
 wolf_add_gtest(gtest_local_param gtest_local_param.cpp)
-target_link_libraries(gtest_local_param ${PROJECT_NAME})
+target_link_libraries(gtest_local_param ${PLUGIN_NAME})
 
 # Logging test
 wolf_add_gtest(gtest_logging gtest_logging.cpp)
-target_link_libraries(gtest_logging ${PROJECT_NAME})
+target_link_libraries(gtest_logging ${PLUGIN_NAME})
 
 # MotionBuffer class test
 wolf_add_gtest(gtest_motion_buffer gtest_motion_buffer.cpp)
-target_link_libraries(gtest_motion_buffer ${PROJECT_NAME})
+target_link_libraries(gtest_motion_buffer ${PLUGIN_NAME})
 
 # PackKFBuffer
 wolf_add_gtest(gtest_pack_KF_buffer gtest_pack_KF_buffer.cpp)
-target_link_libraries(gtest_pack_KF_buffer ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_pack_KF_buffer ${PLUGIN_NAME} dummy)
 
 # Parameters server
 wolf_add_gtest(gtest_param_server gtest_param_server.cpp ${CMAKE_CURRENT_LIST_DIR})
-target_link_libraries(gtest_param_server ${PROJECT_NAME})
+target_link_libraries(gtest_param_server ${PLUGIN_NAME})
 
 # YAML parser
 wolf_add_gtest(gtest_parser_yaml gtest_parser_yaml.cpp)
-target_link_libraries(gtest_parser_yaml ${PROJECT_NAME})
+target_link_libraries(gtest_parser_yaml ${PLUGIN_NAME})
 
 # Problem class test
 wolf_add_gtest(gtest_problem gtest_problem.cpp)
-target_link_libraries(gtest_problem ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_problem ${PLUGIN_NAME} dummy)
 
 # ProcessorBase class test
 wolf_add_gtest(gtest_processor_base gtest_processor_base.cpp)
-target_link_libraries(gtest_processor_base ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_processor_base ${PLUGIN_NAME} dummy)
 
 # ProcessorMotion class test
 wolf_add_gtest(gtest_processor_motion gtest_processor_motion.cpp)
-target_link_libraries(gtest_processor_motion ${PROJECT_NAME})
+target_link_libraries(gtest_processor_motion ${PLUGIN_NAME})
   
 # Rotation test
 wolf_add_gtest(gtest_rotation gtest_rotation.cpp)
 
 # SE3 test
 wolf_add_gtest(gtest_SE3 gtest_SE3.cpp)
-target_link_libraries(gtest_SE3 ${PROJECT_NAME})
+target_link_libraries(gtest_SE3 ${PLUGIN_NAME})
 
 # SensorBase test
 wolf_add_gtest(gtest_sensor_base gtest_sensor_base.cpp)
-target_link_libraries(gtest_sensor_base ${PROJECT_NAME})
+target_link_libraries(gtest_sensor_base ${PLUGIN_NAME})
 
 # shared_from_this test
 wolf_add_gtest(gtest_shared_from_this gtest_shared_from_this.cpp)
-target_link_libraries(gtest_shared_from_this ${PROJECT_NAME})
+target_link_libraries(gtest_shared_from_this ${PLUGIN_NAME})
 
 # SolverManager test
 wolf_add_gtest(gtest_solver_manager gtest_solver_manager.cpp)
-target_link_libraries(gtest_solver_manager ${PROJECT_NAME})
+target_link_libraries(gtest_solver_manager ${PLUGIN_NAME})
 
 # StateBlock class test
 wolf_add_gtest(gtest_state_block gtest_state_block.cpp)
-target_link_libraries(gtest_state_block ${PROJECT_NAME})
+target_link_libraries(gtest_state_block ${PLUGIN_NAME})
 
 # StateBlock class test
 wolf_add_gtest(gtest_state_composite gtest_state_composite.cpp)
-target_link_libraries(gtest_state_composite ${PROJECT_NAME})
+target_link_libraries(gtest_state_composite ${PLUGIN_NAME})
 
 # TimeStamp class test
 wolf_add_gtest(gtest_time_stamp gtest_time_stamp.cpp)
-target_link_libraries(gtest_time_stamp ${PROJECT_NAME})
+target_link_libraries(gtest_time_stamp ${PLUGIN_NAME})
 
 # TrackMatrix class test
 wolf_add_gtest(gtest_track_matrix gtest_track_matrix.cpp)
-target_link_libraries(gtest_track_matrix ${PROJECT_NAME})
+target_link_libraries(gtest_track_matrix ${PLUGIN_NAME})
 
 # TrajectoryBase class test
 wolf_add_gtest(gtest_trajectory gtest_trajectory.cpp)
-target_link_libraries(gtest_trajectory ${PROJECT_NAME})
+target_link_libraries(gtest_trajectory ${PLUGIN_NAME})
 
 # TreeManager class test
 wolf_add_gtest(gtest_tree_manager gtest_tree_manager.cpp)
-target_link_libraries(gtest_tree_manager ${PROJECT_NAME})
+target_link_libraries(gtest_tree_manager ${PLUGIN_NAME})
 
 # ------- Now Derived classes ----------
 
 # FactorAbs(P/O/V) classes test
 wolf_add_gtest(gtest_factor_absolute gtest_factor_absolute.cpp)
-target_link_libraries(gtest_factor_absolute ${PROJECT_NAME})
+target_link_libraries(gtest_factor_absolute ${PLUGIN_NAME})
 
 # FactorAutodiffDistance3d test
 wolf_add_gtest(gtest_factor_autodiff_distance_3d gtest_factor_autodiff_distance_3d.cpp)
-target_link_libraries(gtest_factor_autodiff_distance_3d ${PROJECT_NAME})
+target_link_libraries(gtest_factor_autodiff_distance_3d ${PLUGIN_NAME})
 
 # FactorBlockDifference class test
 wolf_add_gtest(gtest_factor_block_difference gtest_factor_block_difference.cpp)
-target_link_libraries(gtest_factor_block_difference ${PROJECT_NAME})
+target_link_libraries(gtest_factor_block_difference ${PLUGIN_NAME})
 
 # FactorOdom3d class test
 wolf_add_gtest(gtest_factor_diff_drive gtest_factor_diff_drive.cpp)
-target_link_libraries(gtest_factor_diff_drive ${PROJECT_NAME})
+target_link_libraries(gtest_factor_diff_drive ${PLUGIN_NAME})
 
 # FactorOdom2d class test
 wolf_add_gtest(gtest_factor_odom_2d gtest_factor_odom_2d.cpp)
-target_link_libraries(gtest_factor_odom_2d ${PROJECT_NAME})
+target_link_libraries(gtest_factor_odom_2d ${PLUGIN_NAME})
 
 # FactorOdom3d class test
 wolf_add_gtest(gtest_factor_odom_3d gtest_factor_odom_3d.cpp)
-target_link_libraries(gtest_factor_odom_3d ${PROJECT_NAME})
+target_link_libraries(gtest_factor_odom_3d ${PLUGIN_NAME})
 
 # FactorPose2d class test
 wolf_add_gtest(gtest_factor_pose_2d gtest_factor_pose_2d.cpp)
-target_link_libraries(gtest_factor_pose_2d ${PROJECT_NAME})
+target_link_libraries(gtest_factor_pose_2d ${PLUGIN_NAME})
 
 # FactorPose3d class test
 wolf_add_gtest(gtest_factor_pose_3d gtest_factor_pose_3d.cpp)
-target_link_libraries(gtest_factor_pose_3d ${PROJECT_NAME})
+target_link_libraries(gtest_factor_pose_3d ${PLUGIN_NAME})
 
 # FactorRelativePose2dWithExtrinsics class test
 wolf_add_gtest(gtest_factor_relative_pose_2d_with_extrinsics gtest_factor_relative_pose_2d_with_extrinsics.cpp)
-target_link_libraries(gtest_factor_relative_pose_2d_with_extrinsics ${PROJECT_NAME})
+target_link_libraries(gtest_factor_relative_pose_2d_with_extrinsics ${PLUGIN_NAME})
 
 # FactorRelative2dAnalytic class test
 wolf_add_gtest(gtest_factor_relative_2d_analytic gtest_factor_relative_2d_analytic.cpp)
-target_link_libraries(gtest_factor_relative_2d_analytic ${PROJECT_NAME})
+target_link_libraries(gtest_factor_relative_2d_analytic ${PLUGIN_NAME})
 
 # MakePosDef function test
 wolf_add_gtest(gtest_make_posdef gtest_make_posdef.cpp)
-target_link_libraries(gtest_make_posdef ${PROJECT_NAME})
+target_link_libraries(gtest_make_posdef ${PLUGIN_NAME})
 
 # Map yaml save/load test
 wolf_add_gtest(gtest_map_yaml gtest_map_yaml.cpp)
-target_link_libraries(gtest_map_yaml ${PROJECT_NAME})
+target_link_libraries(gtest_map_yaml ${PLUGIN_NAME})
 
 # Parameter prior test
 wolf_add_gtest(gtest_param_prior gtest_param_prior.cpp)
-target_link_libraries(gtest_param_prior ${PROJECT_NAME})
+target_link_libraries(gtest_param_prior ${PLUGIN_NAME})
 
 # ProcessorDiffDriveSelfcalib class test
 wolf_add_gtest(gtest_processor_diff_drive gtest_processor_diff_drive.cpp)
-target_link_libraries(gtest_processor_diff_drive ${PROJECT_NAME})
+target_link_libraries(gtest_processor_diff_drive ${PLUGIN_NAME})
 
 # ProcessorLoopClosureBase class test
 wolf_add_gtest(gtest_processor_loopclosure gtest_processor_loopclosure.cpp)
-target_link_libraries(gtest_processor_loopclosure ${PROJECT_NAME})
+target_link_libraries(gtest_processor_loopclosure ${PLUGIN_NAME})
 
 # ProcessorFrameNearestNeighborFilter class test
 # wolf_add_gtest(gtest_processor_frame_nearest_neighbor_filter_2d gtest_processor_frame_nearest_neighbor_filter_2d.cpp)
-# target_link_libraries(gtest_processor_frame_nearest_neighbor_filter_2d ${PROJECT_NAME})
+# target_link_libraries(gtest_processor_frame_nearest_neighbor_filter_2d ${PLUGIN_NAME})
 
 # ProcessorMotion in 2d
 wolf_add_gtest(gtest_odom_2d gtest_odom_2d.cpp)
-target_link_libraries(gtest_odom_2d ${PROJECT_NAME})
+target_link_libraries(gtest_odom_2d ${PLUGIN_NAME})
 
 # ProcessorOdom3d class test
 wolf_add_gtest(gtest_processor_odom_3d gtest_processor_odom_3d.cpp)
-target_link_libraries(gtest_processor_odom_3d ${PROJECT_NAME})
+target_link_libraries(gtest_processor_odom_3d ${PLUGIN_NAME})
 
 # ProcessorTrackerFeatureDummy class test
 wolf_add_gtest(gtest_processor_tracker_feature_dummy gtest_processor_tracker_feature_dummy.cpp)
-target_link_libraries(gtest_processor_tracker_feature_dummy ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_processor_tracker_feature_dummy ${PLUGIN_NAME} dummy)
 
 # ProcessorTrackerLandmarkDummy class test
 wolf_add_gtest(gtest_processor_tracker_landmark_dummy gtest_processor_tracker_landmark_dummy.cpp)
-target_link_libraries(gtest_processor_tracker_landmark_dummy ${PROJECT_NAME} dummy)
+target_link_libraries(gtest_processor_tracker_landmark_dummy ${PLUGIN_NAME} dummy)
 
 # SensorDiffDriveSelfcalib class test
 wolf_add_gtest(gtest_sensor_diff_drive gtest_sensor_diff_drive.cpp)
-target_link_libraries(gtest_sensor_diff_drive ${PROJECT_NAME})
+target_link_libraries(gtest_sensor_diff_drive ${PLUGIN_NAME})
 
 IF (Ceres_FOUND)
 # SolverCeres test
 wolf_add_gtest(gtest_solver_ceres gtest_solver_ceres.cpp)
-target_link_libraries(gtest_solver_ceres ${PROJECT_NAME})
+target_link_libraries(gtest_solver_ceres ${PLUGIN_NAME})
 ENDIF(Ceres_FOUND)
 
 # TreeManagerSlidingWindow class test
 wolf_add_gtest(gtest_tree_manager_sliding_window gtest_tree_manager_sliding_window.cpp)
-target_link_libraries(gtest_tree_manager_sliding_window ${PROJECT_NAME})
+target_link_libraries(gtest_tree_manager_sliding_window ${PLUGIN_NAME})
 
 # yaml conversions
 wolf_add_gtest(gtest_yaml_conversions gtest_yaml_conversions.cpp)
-target_link_libraries(gtest_yaml_conversions ${PROJECT_NAME})
-
-
+target_link_libraries(gtest_yaml_conversions ${PLUGIN_NAME})
diff --git a/test/dummy/solver_manager_dummy.h b/test/dummy/solver_manager_dummy.h
index 15db720a3c42f8151dd8745dc35d0232fc0fe885..5faef11f35874747a5f0b98f8d99b42911d116e1 100644
--- a/test/dummy/solver_manager_dummy.h
+++ b/test/dummy/solver_manager_dummy.h
@@ -17,7 +17,7 @@ WOLF_PTR_TYPEDEFS(SolverManagerDummy);
 class SolverManagerDummy : public SolverManager
 {
     public:
-        std::list<FactorBasePtr> factors_;
+        std::set<FactorBasePtr> factors_derived_;
         std::map<StateBlockPtr,bool> state_block_fixed_;
         std::map<StateBlockPtr,LocalParametrizationBasePtr> state_block_local_param_;
 
@@ -26,35 +26,34 @@ class SolverManagerDummy : public SolverManager
         {
         };
 
-        bool isStateBlockRegistered(const StateBlockPtr& st) override
+        bool isStateBlockFixedDerived(const StateBlockPtr& st) override
         {
-            return state_blocks_.find(st)!=state_blocks_.end();
+            return state_block_fixed_.at(st);
         };
 
-        bool isStateBlockFixed(const StateBlockPtr& st) const
+        bool hasThisLocalParametrizationDerived(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param) override
         {
-            return state_block_fixed_.at(st);
+            return state_block_local_param_.at(st) == local_param;
         };
 
-        bool isFactorRegistered(const FactorBasePtr& fac_ptr) const override
+        bool hasLocalParametrizationDerived(const StateBlockPtr& st) const override
         {
-            return std::find(factors_.begin(), factors_.end(), fac_ptr) != factors_.end();
+            return state_block_local_param_.at(st) != nullptr;
         };
 
-        bool hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param) const
+        virtual int numStateBlocksDerived() const override
         {
-            return state_block_local_param_.find(st) != state_block_local_param_.end() && state_block_local_param_.at(st) == local_param;
-        };
+            return state_block_fixed_.size();
+        }
 
-        bool hasLocalParametrization(const StateBlockPtr& st) const
+        virtual int numFactorsDerived() const override
         {
-            return state_block_local_param_.find(st) != state_block_local_param_.end();
+            return factors_derived_.size();
         };
 
         void computeCovariances(const CovarianceBlocksToBeComputed blocks) override {};
         void computeCovariances(const std::vector<StateBlockPtr>& st_list) override {};
-        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) override {return true;};
-        bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override {return true;};
+
 
         // The following are dummy implementations
         bool    hasConverged() override  { return true;      }
@@ -62,19 +61,17 @@ class SolverManagerDummy : public SolverManager
         double  initialCost() override   { return double(1); }
         double  finalCost() override     { return double(0); }
 
-
-
     protected:
 
         bool checkDerived(std::string prefix="") const override {return true;}
         std::string solveDerived(const ReportVerbosity report_level) override { return std::string("");};
         void addFactorDerived(const FactorBasePtr& fac_ptr) override
         {
-            factors_.push_back(fac_ptr);
+            factors_derived_.insert(fac_ptr);
         };
         void removeFactorDerived(const FactorBasePtr& fac_ptr) override
         {
-            factors_.remove(fac_ptr);
+            factors_derived_.erase(fac_ptr);
         };
         void addStateBlockDerived(const StateBlockPtr& state_ptr) override
         {
@@ -92,10 +89,16 @@ class SolverManagerDummy : public SolverManager
         };
         void updateStateBlockLocalParametrizationDerived(const StateBlockPtr& state_ptr) override
         {
-            if (state_ptr->getLocalParametrization() == nullptr)
-                state_block_local_param_.erase(state_ptr);
-            else
-                state_block_local_param_[state_ptr] = state_ptr->getLocalParametrization();
+            state_block_local_param_[state_ptr] = state_ptr->getLocalParametrization();
+        };
+        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const override
+        {
+            return state_block_fixed_.count(state_ptr) == 1 and state_block_local_param_.count(state_ptr) == 1;
+        };
+
+        bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override
+        {
+            return factors_derived_.count(fac_ptr) == 1;
         };
 };
 
diff --git a/test/gtest_emplace.cpp b/test/gtest_emplace.cpp
index 2c28c2bd442bc8675bf5e71fb82d97141cac8390..ebca6bb09bf463ed022aa81a1629e0accc877ff8 100644
--- a/test/gtest_emplace.cpp
+++ b/test/gtest_emplace.cpp
@@ -42,8 +42,8 @@ TEST(Emplace, Frame)
     ProblemPtr P = Problem::create("POV", 3);
 
     ASSERT_NE(P->getTrajectory(), nullptr);
-    FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getTrajectory()->getProblem());
+    FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getTrajectory()->getProblem());
 }
 
 TEST(Emplace, Processor)
@@ -67,12 +67,12 @@ TEST(Emplace, Capture)
     ProblemPtr P = Problem::create("POV", 3);
 
     ASSERT_NE(P->getTrajectory(), nullptr);
-    auto frm = FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getTrajectory()->getProblem());
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getTrajectory()->getProblem());
 
     auto cpt = CaptureBase::emplace<CaptureBase>(frm, "Dummy", TimeStamp(0), nullptr, nullptr, nullptr, nullptr);
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getProblem());
     ASSERT_EQ(frm, frm->getCaptureList().front()->getFrame());
 }
 
@@ -81,17 +81,17 @@ TEST(Emplace, Feature)
     ProblemPtr P = Problem::create("POV", 3);
 
     ASSERT_NE(P->getTrajectory(), nullptr);
-    auto frm = FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getTrajectory()->getProblem());
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getTrajectory()->getProblem());
 
     auto cpt = CaptureBase::emplace<CaptureBase>(frm, "Dummy", TimeStamp(0), nullptr, nullptr, nullptr, nullptr);
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getProblem());
     ASSERT_EQ(frm, frm->getCaptureList().front()->getFrame());
     auto cov = Eigen::MatrixXd::Identity(2,2);
     FeatureBase::emplace<FeatureBase>(cpt, "Dummy", Eigen::VectorXd(2), cov);
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFeatureList().front()->getCapture()->getFrame()->getTrajectory()->getProblem());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFeatureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFeatureList().front()->getCapture()->getFrame()->getTrajectory()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFeatureList().front()->getProblem());
     ASSERT_EQ(cpt, cpt->getFeatureList().front()->getCapture());
 }
 TEST(Emplace, Factor)
@@ -99,17 +99,17 @@ TEST(Emplace, Factor)
     ProblemPtr P = Problem::create("POV", 3);
 
     ASSERT_NE(P->getTrajectory(), nullptr);
-    auto frm = FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getTrajectory()->getProblem());
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getTrajectory()->getProblem());
 
     auto cpt = CaptureBase::emplace<CaptureBase>(frm, "Dummy", TimeStamp(0), nullptr, nullptr, nullptr, nullptr);
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFrame()->getTrajectory()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getProblem());
     ASSERT_EQ(frm, frm->getCaptureList().front()->getFrame());
     auto cov = Eigen::MatrixXd::Identity(2,2);
     auto ftr = FeatureBase::emplace<FeatureOdom2d>(cpt, Eigen::VectorXd(2), cov);
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFeatureList().front()->getCapture()->getFrame()->getTrajectory()->getProblem());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFeatureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFeatureList().front()->getCapture()->getFrame()->getTrajectory()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFeatureList().front()->getProblem());
     ASSERT_EQ(cpt, cpt->getFeatureList().front()->getCapture());
     auto cnt = FactorBase::emplace<FactorOdom2d>(ftr, ftr, frm, nullptr, false);
     ASSERT_NE(nullptr, ftr->getFactorList().front().get());
@@ -119,7 +119,7 @@ TEST(Emplace, EmplaceDerived)
 {
     ProblemPtr P = Problem::create("POV", 3);
 
-    auto frm = FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
     auto sen = SensorBase::emplace<SensorOdom2d>(P->getHardware(), Eigen::VectorXd(3), ParamsSensorOdom2d());
     auto cov = Eigen::MatrixXd::Identity(2,2);
     auto cpt = CaptureBase::emplace<CaptureOdom2d>(frm, TimeStamp(0), sen, Eigen::VectorXd(2), cov, nullptr);
@@ -130,7 +130,7 @@ TEST(Emplace, EmplaceDerived)
 
     auto ftr = FeatureBase::emplace<FeatureOdom2d>(cpt, Eigen::VectorXd(2), cov);
     ASSERT_EQ(sen, P->getHardware()->getSensorList().front());
-    ASSERT_EQ(P, P->getTrajectory()->getFrameList().front()->getCaptureList().front()->getFeatureList().front()->getProblem());
+    ASSERT_EQ(P, P->getTrajectory()->getFirstFrame()->getCaptureList().front()->getFeatureList().front()->getProblem());
 }
 TEST(Emplace, Nullpointer)
 {
@@ -141,7 +141,7 @@ TEST(Emplace, ReturnDerived)
     ProblemPtr P = Problem::create("POV", 3);
 
     ASSERT_NE(P->getTrajectory(), nullptr);
-    auto frm = FrameBase::emplace<FrameBase>(P->getTrajectory(),  KEY, TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
+    auto frm = FrameBase::emplaceKeyFrame<FrameBase>(P->getTrajectory(),  TimeStamp(0), std::make_shared<StateBlock>(2,true), std::make_shared<StateBlock>(2,true));
     auto cpt = CaptureBase::emplace<CaptureBase>(frm, "Dummy", TimeStamp(0), nullptr, nullptr, nullptr, nullptr);
     auto cov = Eigen::MatrixXd::Identity(2,2);
     auto ftr = FeatureBase::emplace<FeatureOdom2d>(cpt, Eigen::VectorXd(2), cov);
diff --git a/test/gtest_factor_absolute.cpp b/test/gtest_factor_absolute.cpp
index 9e19dce8b5fad3d950461a74f13d4226036c704f..8c3b353ccb9493be57f2d38a6ffe257a6375f3b8 100644
--- a/test/gtest_factor_absolute.cpp
+++ b/test/gtest_factor_absolute.cpp
@@ -35,7 +35,7 @@ ProblemPtr problem_ptr = Problem::create("POV", 3);
 SolverCeres solver(problem_ptr);
 
 // Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY, 0, problem_ptr->stateZero() );
+FrameBasePtr frm0 = problem_ptr->emplaceKeyFrame(0, problem_ptr->stateZero() );
 
 // Capture
 // auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "IMU ABS", 0, nullptr, pose10, 10, 9, nullptr);
diff --git a/test/gtest_factor_autodiff_distance_3d.cpp b/test/gtest_factor_autodiff_distance_3d.cpp
index c8f33528b9320d01e281add3bcaf0a74420ec35d..3e6974cb91303c8f864db2816d801207eba309ad 100644
--- a/test/gtest_factor_autodiff_distance_3d.cpp
+++ b/test/gtest_factor_autodiff_distance_3d.cpp
@@ -55,9 +55,9 @@ class FactorAutodiffDistance3d_Test : public testing::Test
             problem = Problem::create("PO", 3);
             solver = std::make_shared<SolverCeres>(problem);
 
-            F1 = problem->emplaceFrame        (KEY, 1.0, pose1);
+            F1 = problem->emplaceKeyFrame        (1.0, pose1);
 
-            F2 = problem->emplaceFrame        (KEY, 2.0, pose2);
+            F2 = problem->emplaceKeyFrame        (2.0, pose2);
             C2 = CaptureBase::emplace<CaptureBase>(F2, "Base", 1.0);
         }
 
diff --git a/test/gtest_factor_block_difference.cpp b/test/gtest_factor_block_difference.cpp
index 2b7c9cb0c3ff6deb8ae9ec0b2279963d46a6a090..9b572504fa686bd555ba3b5ec25f39d1a4fb7afd 100644
--- a/test/gtest_factor_block_difference.cpp
+++ b/test/gtest_factor_block_difference.cpp
@@ -58,7 +58,7 @@ class FixtureFactorBlockDifference : public testing::Test
             //FeatureBasePtr featV0 = FeatureBase::emplace<FeatureBase>(capV0, "Vel0", x_origin.tail(3), cov_prior.bottomRightCorner<3,3>());
             //FactorBasePtr facV0 = FactorBase::emplace<FactorBlockAbsolute>(featV0, KF0_->getV(), nullptr, false);
 
-            KF1_ = problem_->emplaceFrame(KEY, t1, problem_->stateZero());
+            KF1_ = problem_->emplaceKeyFrame(t1, problem_->stateZero());
 
             Cap_ = CaptureBase::emplace<CaptureBase>(KF1_, "BlockDifference", t1);
         }
diff --git a/test/gtest_factor_diff_drive.cpp b/test/gtest_factor_diff_drive.cpp
index c8338be45a4388c282da32037a27e5b4530e3f02..51661f8ab26d1257f43dd4d4cbcc8dd5237b80d8 100644
--- a/test/gtest_factor_diff_drive.cpp
+++ b/test/gtest_factor_diff_drive.cpp
@@ -159,13 +159,11 @@ class FactorDiffDriveTest : public testing::Test
             processor = std::static_pointer_cast<ProcessorDiffDrivePublic>(prc);
 
             // frames
-            F0 = FrameBase::emplace<FrameBase>(trajectory,
-                                               KEY,
+            F0 = FrameBase::emplaceKeyFrame<FrameBase>(trajectory,
                                                0.0,
                                                "PO",
                                                std::list<VectorXd>{Vector2d(0,0), Vector1d(0)});
-            F1 = FrameBase::emplace<FrameBase>(trajectory,
-                                               KEY,
+            F1 = FrameBase::emplaceKeyFrame<FrameBase>(trajectory,
                                                1.0,
                                                "PO",
                                                std::list<VectorXd>{Vector2d(1,0), Vector1d(0)});
@@ -500,7 +498,7 @@ TEST(FactorDiffDrive, preintegrate_and_solve_sensor_intrinsics_gt)
         C->process();
     }
 
-    auto F2 = problem->getLastKeyFrame();
+    auto F2 = problem->getLastFrame();
 
     // Fix boundaries
     F0->fix();
@@ -636,7 +634,7 @@ TEST(FactorDiffDrive, preintegrate_and_solve_sensor_intrinsics)
         C->process();
     }
 
-    auto F2 = problem->getLastKeyFrame();
+    auto F2 = problem->getLastFrame();
 
 //    VectorComposite x2c(x2, "PO", {2,1});
     F2->setState(x2, "PO"); // Impose known final state regardless of integrated value.
diff --git a/test/gtest_factor_odom_2d.cpp b/test/gtest_factor_odom_2d.cpp
index 6230881af471e41fc187ddab8757845471311b50..baee1dddcaf2c1fb998e3ae551f29a39a335fd5b 100644
--- a/test/gtest_factor_odom_2d.cpp
+++ b/test/gtest_factor_odom_2d.cpp
@@ -19,8 +19,8 @@ ProblemPtr problem_ptr = Problem::create("PO", 2);
 SolverCeres solver(problem_ptr);
 
 // Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY, TimeStamp(0), Vector3d::Zero());
-FrameBasePtr frm1 = problem_ptr->emplaceFrame(KEY, TimeStamp(1), Vector3d::Zero());
+FrameBasePtr frm0 = problem_ptr->emplaceKeyFrame(TimeStamp(0), Vector3d::Zero());
+FrameBasePtr frm1 = problem_ptr->emplaceKeyFrame(TimeStamp(1), Vector3d::Zero());
 
 // Capture from frm1 to frm0
 auto cap1 = CaptureBase::emplace<CaptureOdom2d>(frm1, 1, nullptr, Vector3d::Zero(), data_cov);
diff --git a/test/gtest_factor_odom_3d.cpp b/test/gtest_factor_odom_3d.cpp
index 3ac18c88700d5d4169b6b9c6f59b607780b897a1..24daac332094bb8e65964eb0acdd9346341eb3f9 100644
--- a/test/gtest_factor_odom_3d.cpp
+++ b/test/gtest_factor_odom_3d.cpp
@@ -37,8 +37,8 @@ ProblemPtr problem_ptr = Problem::create("PO", 3);
 SolverCeres solver(problem_ptr);
 
 // Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY, TimeStamp(0), problem_ptr->stateZero());
-FrameBasePtr frm1 = problem_ptr->emplaceFrame(KEY, TimeStamp(1), delta);
+FrameBasePtr frm0 = problem_ptr->emplaceKeyFrame(TimeStamp(0), problem_ptr->stateZero());
+FrameBasePtr frm1 = problem_ptr->emplaceKeyFrame(TimeStamp(1), delta);
 
 // Capture, feature and factor from frm1 to frm0
 auto cap1 = CaptureBase::emplace<CaptureMotion>(frm1, "CaptureOdom3d", 1, nullptr, delta, nullptr);
diff --git a/test/gtest_factor_pose_2d.cpp b/test/gtest_factor_pose_2d.cpp
index 6f9804f9d16518d1eaa349a1359a1f4da153cf3f..749d514d8cc4c0479cfdf5092dca6e5face76ea8 100644
--- a/test/gtest_factor_pose_2d.cpp
+++ b/test/gtest_factor_pose_2d.cpp
@@ -30,7 +30,7 @@ ProblemPtr problem = Problem::create("PO", 2);
 SolverCeres solver(problem);
 
 // Two frames
-FrameBasePtr frm0 = problem->emplaceFrame(KEY, TimeStamp(0), problem->stateZero());
+FrameBasePtr frm0 = problem->emplaceKeyFrame(TimeStamp(0), problem->stateZero());
 
 // Capture, feature and factor from frm1 to frm0
 auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "CaptureOdom2d", 0, nullptr, pose, nullptr);
diff --git a/test/gtest_factor_pose_3d.cpp b/test/gtest_factor_pose_3d.cpp
index d50660e2f0515aa5589d8fb0146e7ca75f8cfa84..88433b4b4433ce7e5290c81b34766d13fb2f9831 100644
--- a/test/gtest_factor_pose_3d.cpp
+++ b/test/gtest_factor_pose_3d.cpp
@@ -36,7 +36,7 @@ ProblemPtr problem = Problem::create("PO", 3);
 SolverCeres solver(problem);
 
 // Two frames
-FrameBasePtr frm0 = problem->emplaceFrame(KEY, 0, problem->stateZero() );
+FrameBasePtr frm0 = problem->emplaceKeyFrame(0, problem->stateZero() );
 
 // Capture, feature and factor
 auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "CaptureOdom3d", 0, nullptr, pose7, nullptr);
diff --git a/test/gtest_factor_relative_2d_analytic.cpp b/test/gtest_factor_relative_2d_analytic.cpp
index 5650f90618f6e556cd80a0f5cd423e7ac3b722b2..93581a6ac63b18da056f84ea5caed95ca009ebd4 100644
--- a/test/gtest_factor_relative_2d_analytic.cpp
+++ b/test/gtest_factor_relative_2d_analytic.cpp
@@ -19,8 +19,8 @@ ProblemPtr problem_ptr = Problem::create("PO", 2);
 SolverCeres solver(problem_ptr);
 
 // Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY, 0.0, Vector3d::Zero());
-FrameBasePtr frm1 = problem_ptr->emplaceFrame(KEY, 1.0, Vector3d::Zero());
+FrameBasePtr frm0 = problem_ptr->emplaceKeyFrame(0.0, Vector3d::Zero());
+FrameBasePtr frm1 = problem_ptr->emplaceKeyFrame(1.0, Vector3d::Zero());
 
 // Capture from frm1 to frm0
 auto cap1 = CaptureBase::emplace<CaptureOdom2d>(frm1, 1, nullptr, Vector3d::Zero(), data_cov);
diff --git a/test/gtest_factor_relative_pose_2d_with_extrinsics.cpp b/test/gtest_factor_relative_pose_2d_with_extrinsics.cpp
index feee02d63ca843c9f89fd8efc3443fedc40567b1..78321478cc5126e419ca4fc8fea53c5ed79caa71 100644
--- a/test/gtest_factor_relative_pose_2d_with_extrinsics.cpp
+++ b/test/gtest_factor_relative_pose_2d_with_extrinsics.cpp
@@ -27,8 +27,8 @@ auto sensor_odom2d = problem_ptr->installSensor("SensorOdom2d", "odom", Vector3d
 auto processor_odom2d = problem_ptr->installProcessor("ProcessorOdom2d", "odom", sensor_odom2d, std::make_shared<ParamsProcessorOdom2d>());
 
 // Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY, 0, Vector3d::Zero() );
-FrameBasePtr frm1 = problem_ptr->emplaceFrame(KEY, 1, Vector3d::Zero() );
+FrameBasePtr frm0 = problem_ptr->emplaceKeyFrame(0, Vector3d::Zero() );
+FrameBasePtr frm1 = problem_ptr->emplaceKeyFrame(1, Vector3d::Zero() );
 
 // Capture from frm1 to frm0
 auto cap1 = CaptureBase::emplace<CaptureOdom2d>(frm1, 1, sensor_odom2d, Vector3d::Zero(), data_cov);
diff --git a/test/gtest_frame_base.cpp b/test/gtest_frame_base.cpp
index 8f73d96ac2560d6366410b48da41e2a3ef3fe00b..7167566535827fa6281057903e6f11dafdf3810d 100644
--- a/test/gtest_frame_base.cpp
+++ b/test/gtest_frame_base.cpp
@@ -32,7 +32,7 @@ TEST(FrameBase, GettersAndSetters)
     ASSERT_EQ(t, 1);
     ASSERT_FALSE(F->isFixed());
     ASSERT_EQ(F->isKey(), false);
-    ASSERT_EQ(F->isKeyOrAux(), false);
+    ASSERT_EQ(F->isKey(), false);
 }
 
 TEST(FrameBase, StateBlocks)
@@ -69,8 +69,8 @@ TEST(FrameBase, LinksToTree)
     intrinsics_odo.k_disp_to_disp = 1;
     intrinsics_odo.k_rot_to_rot = 1;
     auto S = SensorBase::emplace<SensorOdom2d>(P->getHardware(), Vector3d::Zero(), intrinsics_odo);
-    auto F1 = FrameBase::emplace<FrameBase>(T, KEY, 1, make_shared<StateBlock>(2), make_shared<StateBlock>(1));
-    auto F2 = FrameBase::emplace<FrameBase>(T, KEY, 1, make_shared<StateBlock>(2), make_shared<StateBlock>(1));
+    auto F1 = FrameBase::emplaceKeyFrame<FrameBase>(T, 1, make_shared<StateBlock>(2), make_shared<StateBlock>(1));
+    auto F2 = FrameBase::emplaceKeyFrame<FrameBase>(T, 2, make_shared<StateBlock>(2), make_shared<StateBlock>(1));
     auto C = CaptureBase::emplace<CaptureMotion>(F1, "CaptureMotion", 1, S, Vector3d::Zero(), nullptr);
     WOLF_INFO("F2->getCaptureList().size() ", F2->getCaptureList().size());
     auto p = std::make_shared<ProcessorOdom2d>(std::make_shared<ParamsProcessorOdom2d>());
@@ -116,10 +116,7 @@ TEST(FrameBase, LinksToTree)
     F1->getO()->fix();
     ASSERT_TRUE(F1->isFixed());
 
-    // set key
-    F1->setKey();
     ASSERT_TRUE(F1->isKey());
-    ASSERT_TRUE(F1->isKeyOrAux());
 }
 
 #include "core/state_block/state_quaternion.h"
diff --git a/test/gtest_has_state_blocks.cpp b/test/gtest_has_state_blocks.cpp
index e17124a2d56687d8fe8de4c8d1144e49285e1f86..646dd602e619b0c2d2fadd70eb6c6f94e7f79a5f 100644
--- a/test/gtest_has_state_blocks.cpp
+++ b/test/gtest_has_state_blocks.cpp
@@ -55,11 +55,11 @@ TEST_F(HasStateBlocksTest, Notifications_setKey_add)
     Notification n;
     ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
 
-    F0->link(problem->getTrajectory());
+    ASSERT_DEATH(F0->link(problem->getTrajectory()), "");
 
-    ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
+    // ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
 
-    F0->setKey();
+    F0->setKey(problem);
 
     ASSERT_TRUE(problem->getStateBlockNotification(sbp0, n));
     ASSERT_EQ(n, ADD);
@@ -69,21 +69,21 @@ TEST_F(HasStateBlocksTest, Notifications_add_makeKF)
 {
     Notification n;
 
-    // First add SB, than make KF
+    // First add SB, then make KF
 
     ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
 
-    F0->link(problem->getTrajectory());
+    // F0->link(problem->getTrajectory());
 
-    ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
+    // ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
 
-    ASSERT_FALSE(problem->getStateBlockNotification(sbv0, n));
+    // ASSERT_FALSE(problem->getStateBlockNotification(sbv0, n));
 
     F0->addStateBlock('V', sbv0);
 
     ASSERT_FALSE(problem->getStateBlockNotification(sbv0, n));
 
-    F0->setKey();
+    F0->setKey(problem);
 
     ASSERT_TRUE(problem->getStateBlockNotification(sbp0, n));
     ASSERT_EQ(n, ADD);
@@ -99,8 +99,8 @@ TEST_F(HasStateBlocksTest, Notifications_makeKF_add)
 
     // first make KF, then add SB
 
-    F1->link(problem->getTrajectory());
-    F1->setKey();
+    // F1->link(problem->getTrajectory());
+    F1->setKey(problem);
 
     F1->addStateBlock('P', sbp1);
 
@@ -130,9 +130,8 @@ TEST_F(HasStateBlocksTest, Add_solve_notify_solve_add)
 
     ASSERT_FALSE(problem->getStateBlockNotification(sbp0, n));
 
-    F0->link(problem->getTrajectory());
     F0->addStateBlock('V', sbv0);
-    F0->setKey();
+    F0->setKey(problem);
 
     ASSERT_TRUE(problem->getStateBlockNotification(sbv0, n));
     ASSERT_EQ(n, ADD);
@@ -213,9 +212,6 @@ TEST_F(HasStateBlocksTest, getState_structure)
     ASSERT_FALSE(state0.count('V'));
     ASSERT_FALSE(state0.count('W'));
 
-
-
-
 }
 
 
diff --git a/test/gtest_odom_2d.cpp b/test/gtest_odom_2d.cpp
index 62109f6323593cada613758a05e762618d33bd84..3b525a12e5210de4eeb54ef213d8446bd24b8329 100644
--- a/test/gtest_odom_2d.cpp
+++ b/test/gtest_odom_2d.cpp
@@ -74,7 +74,7 @@ void show(const ProblemPtr& problem)
     using std::endl;
     cout << std::setprecision(4);
 
-    for (FrameBasePtr F : problem->getTrajectory()->getFrameList())
+    for (FrameBasePtr F : *problem->getTrajectory())
     {
         if (F->isKey())
         {
@@ -132,14 +132,14 @@ TEST(Odom2d, FactorFix_and_FactorOdom2d)
 
     // KF1 and motion from KF0
     t += dt;
-    FrameBasePtr        F1 = Pr->emplaceFrame(KEY, t, Vector3d::Zero());
+    FrameBasePtr        F1 = Pr->emplaceKeyFrame(t, Vector3d::Zero());
     auto C1 = CaptureBase::emplace<CaptureBase>(F1, "CaptureOdom2d", t);
     auto f1 = FeatureBase::emplace<FeatureBase>(C1, "FeatureOdom2d", delta, delta_cov);
     auto c1 = FactorBase::emplace<FactorOdom2d>(f1, f1, F0, nullptr, false);
 
     // KF2 and motion from KF1
     t += dt;
-    FrameBasePtr        F2 = Pr->emplaceFrame(KEY, t, Vector3d::Zero());
+    FrameBasePtr        F2 = Pr->emplaceKeyFrame(t, Vector3d::Zero());
     auto C2 = CaptureBase::emplace<CaptureBase>(F2, "CaptureOdom2d", t);
     auto f2 = FeatureBase::emplace<FeatureBase>(C2, "FeatureOdom2d", delta, delta_cov);
     auto c2 = FactorBase::emplace<FactorOdom2d>(f2, f2, F1, nullptr, false);
@@ -228,7 +228,7 @@ TEST(Odom2d, VoteForKfAndSolve)
     solver.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS);
 
     //    std::cout << "Initial pose : " << problem->getCurrentState().transpose() << std::endl;
-    //    std::cout << "Initial covariance : " << std::endl << problem->getLastKeyFrameCovariance() << std::endl;
+    //    std::cout << "Initial covariance : " << std::endl << problem->getLastFrameCovariance() << std::endl;
     //    std::cout << "Motion data  : " << data.transpose() << std::endl;
 
     // Check covariance values
@@ -306,7 +306,7 @@ TEST(Odom2d, VoteForKfAndSolve)
     // Check the 3 KFs' states and covariances
     MatrixXd computed_cov;
     int n = 0;
-    for (auto F : problem->getTrajectory()->getFrameList())
+    for (auto F : *problem->getTrajectory())
     {
         if (!F->isKey()) break;
 
@@ -423,12 +423,12 @@ TEST(Odom2d, KF_callback)
     std::cout << "-----------------------------\nSplit after last KF; time: " << t_split << std::endl;
 
     Vector3d x_split = processor_odom2d->getState(t_split).vector("PO");
-    FrameBasePtr keyframe_2 = problem->emplaceFrame(KEY, t_split, x_split);
+    FrameBasePtr keyframe_2 = problem->emplaceKeyFrame(t_split, x_split);
 
     // there must be 2KF and one F
-    ASSERT_EQ(problem->getTrajectory()->getFrameList().size(), 3);
+    ASSERT_EQ(problem->getTrajectory()->getFrameMap().size(), 2);
     // The last KF must have TS = 0.08
-    ASSERT_EQ(problem->getLastKeyFrame()->getTimeStamp().getNanoSeconds(), 80000000);
+    ASSERT_EQ(problem->getLastFrame()->getTimeStamp().getNanoSeconds(), 80000000);
 
     ASSERT_TRUE(problem->check(0));
     processor_odom2d->keyFrameCallback(keyframe_2, dt/2);
@@ -446,9 +446,9 @@ TEST(Odom2d, KF_callback)
 //    std::cout << report << std::endl;
     solver.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS);
 
-    ASSERT_POSE2d_APPROX(problem->getLastKeyFrame()->getStateVector() , integrated_pose_vector[n_split], 1e-6);
+    ASSERT_POSE2d_APPROX(problem->getLastFrame()->getStateVector() , integrated_pose_vector[n_split], 1e-6);
     MatrixXd computed_cov;
-    ASSERT_TRUE(problem->getLastKeyFrameCovariance(computed_cov));
+    ASSERT_TRUE(problem->getLastFrameCovariance(computed_cov));
     ASSERT_MATRIX_APPROX(computed_cov, integrated_cov_vector [n_split], 1e-6);
 
     ////////////////////////////////////////////////////////////////
@@ -460,7 +460,7 @@ TEST(Odom2d, KF_callback)
     problem->print(4,1,1,1);
 
     x_split = processor_odom2d->getState(t_split).vector("PO");
-    FrameBasePtr keyframe_1 = problem->emplaceFrame(KEY, t_split, x_split);
+    FrameBasePtr keyframe_1 = problem->emplaceKeyFrame(t_split, x_split);
 
     ASSERT_TRUE(problem->check(0));
     processor_odom2d->keyFrameCallback(keyframe_1, dt/2);
@@ -493,7 +493,7 @@ TEST(Odom2d, KF_callback)
     // check other KF in the future of the split KF
     MatrixXd KF2_cov;
     ASSERT_TRUE(problem->getFrameCovariance(keyframe_2, KF2_cov));
-    ASSERT_POSE2d_APPROX(problem->getLastKeyFrame()->getStateVector(), integrated_pose_vector[n_split], 1e-6);
+    ASSERT_POSE2d_APPROX(problem->getLastFrame()->getStateVector(), integrated_pose_vector[n_split], 1e-6);
     ASSERT_MATRIX_APPROX(KF2_cov,                                integrated_cov_vector [n_split], 1e-6);
 
     // Check full trajectory
diff --git a/test/gtest_problem.cpp b/test/gtest_problem.cpp
index 210fdbee0df5a8e4b6f3e189a28b4fe6e841b9fd..657ddc48a3ee49d8aefa709379415e780641aeec 100644
--- a/test/gtest_problem.cpp
+++ b/test/gtest_problem.cpp
@@ -132,7 +132,7 @@ TEST(Problem, SetOrigin_PO_2d)
     F->getFactorList(fac_list);
 
     // check that we have one frame (prior)
-    ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1);
+    ASSERT_EQ(T->getFrameMap().size(), (SizeStd) 1);
     // check that we have one capture (prior)
     ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1);
     // check that we have two features (prior: one per state block)
@@ -191,7 +191,7 @@ TEST(Problem, SetOrigin_PO_3d)
     F->getFactorList(fac_list);
 
     // check that we have one frame (prior)
-    ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1);
+    ASSERT_EQ(T->getFrameMap().size(), (SizeStd) 1);
     // check that we have one capture (prior)
     ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1);
     // check that we have two features (prior: one per state block)
@@ -224,12 +224,12 @@ TEST(Problem, emplaceFrame_factory)
 {
     ProblemPtr P = Problem::create("PO", 2);
 
-    FrameBasePtr f0 = P->emplaceFrame(KEY, 0, "PO" , 2,  VectorXd(3)  );
-    FrameBasePtr f1 = P->emplaceFrame(KEY, 1, "PO" , 3,  VectorXd(7)  );
-    FrameBasePtr f2 = P->emplaceFrame(KEY, 2, "POV", 3,  VectorXd(10) );
+    FrameBasePtr f0 = P->emplaceKeyFrame(0, "PO" , 2,  VectorXd(3)  );
+    FrameBasePtr f1 = P->emplaceKeyFrame(1, "PO" , 3,  VectorXd(7)  );
+    FrameBasePtr f2 = P->emplaceKeyFrame(2, "POV", 3,  VectorXd(10) );
 
     // check that all frames are effectively in the trajectory
-    ASSERT_EQ(P->getTrajectory()->getFrameList().size(), (SizeStd) 3);
+    ASSERT_EQ(P->getTrajectory()->getFrameMap().size(), (SizeStd) 3);
 
     ASSERT_EQ(f0->getStateVector().size(), 3 );
     ASSERT_EQ(f1->getStateVector().size(), 7 );
@@ -261,7 +261,7 @@ TEST(Problem, StateBlocks)
     auto pm = P->installProcessor("ProcessorOdom3d",                "odom integrator",  "odometer", wolf_root + "/test/yaml/processor_odom_3d.yaml");
 
     // 2 state blocks, estimated
-    auto KF = P->emplaceFrame(KEY, 0, "PO", 3, xs3d );
+    auto KF = P->emplaceKeyFrame(0, "PO", 3, xs3d );
     ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd)(2 + 2));
 
     // Notifications
@@ -320,7 +320,7 @@ TEST(Problem, Covariances)
 
     // 4 state blocks, estimated
     St->unfixExtrinsics();
-    FrameBasePtr F = P->emplaceFrame(KEY, 0, "PO", 3, xs3d );
+    FrameBasePtr F = P->emplaceKeyFrame(0, "PO", 3, xs3d );
 
     // set covariance (they are not computed without a solver)
     P->addCovarianceBlock(F->getP(), Eigen::Matrix3d::Identity());
@@ -356,7 +356,7 @@ TEST(Problem, perturb)
     int i = 0;
     for (TimeStamp t = 0.0; t < 2.0; t += 1.0)
     {
-        auto F = problem->emplaceFrame(KEY, t, pose );
+        auto F = problem->emplaceKeyFrame(t, pose );
         if (i==0) F->fix();
 
         for (int j = 0; j< 2 ; j++)
@@ -394,7 +394,7 @@ TEST(Problem, perturb)
         ASSERT_FALSE(S->getIntrinsic()->getState().isApprox(Vector3d(1,1,1), prec) );
     }
 
-    for (auto F : problem->getTrajectory()->getFrameList())
+    for (auto F : *problem->getTrajectory())
     {
         if (F->isFixed()) // fixed
         {
@@ -446,7 +446,7 @@ TEST(Problem, check)
     int i = 0;
     for (TimeStamp t = 0.0; t < 2.0; t += 1.0)
     {
-        auto F = problem->emplaceFrame(KEY, t, pose);
+        auto F = problem->emplaceKeyFrame(t, pose);
         if (i==0) F->fix();
 
         for (int j = 0; j< 2 ; j++)
@@ -477,7 +477,7 @@ TEST(Problem, check)
 
     // remove stuff from problem, and re-check
 
-    auto F = problem->getLastKeyFrame();
+    auto F = problem->getLastFrame();
 
     auto cby = F->getConstrainedByList().front();
 
diff --git a/test/gtest_processor_base.cpp b/test/gtest_processor_base.cpp
index ed01245b29c903a7584e932196fb93a2c01c5c20..c3277078df9300439a6dee3721f0084df9751522 100644
--- a/test/gtest_processor_base.cpp
+++ b/test/gtest_processor_base.cpp
@@ -117,12 +117,16 @@ TEST(ProcessorBase, KeyFrameCallback)
 
         capt_odo->setTimeStamp(t);
         std::cout << "2\n";
+//        auto proc_odo_motion = std::static_pointer_cast<ProcessorMotion>(proc_odo);
+//        auto last_ptr = proc_odo_motion->last_ptr_;
+//        auto last_ptr_frame = last_ptr->getFrame();
         proc_odo->captureCallback(capt_odo);
         std::cout << "3\n";
 
         // Track
         capt_trk = make_shared<CaptureVoid>(t, sens_trk);
         std::cout << "4\n";
+        problem->print(4,1,1,1, std::cout);
         proc_trk->captureCallback(capt_trk);
         std::cout << "5\n";
 
@@ -130,7 +134,7 @@ TEST(ProcessorBase, KeyFrameCallback)
         std::cout << "6\n";
 
         // Only odom creating KFs
-        ASSERT_TRUE( problem->getLastKeyFrame()->getStructure().compare("PO")==0 );
+        ASSERT_TRUE( problem->getLastFrame()->getStructure().compare("PO")==0 );
     }
 }
 
diff --git a/test/gtest_processor_diff_drive.cpp b/test/gtest_processor_diff_drive.cpp
index b13061e657badbd2ed81e9ea82b0f6078f3803f0..fc30487fe96765f36caea276defddc7abee9a6ac 100644
--- a/test/gtest_processor_diff_drive.cpp
+++ b/test/gtest_processor_diff_drive.cpp
@@ -352,9 +352,11 @@ TEST_F(ProcessorDiffDriveTest, linear)
     data(0) = 100.0 ; // one turn of the wheels
     data(1) = 100.0 ;
 
+    t += 1.0;
     auto C = std::make_shared<CaptureDiffDrive>(t, sensor, data, data_cov, F0->getCaptureList().front());
 
     C->process();
+
     WOLF_TRACE("t = ", t, "; x = ", processor->getState().vector("PO").transpose());
 
     // radius is 1.0m, 100 ticks per revolution, so advanced distance is
@@ -377,6 +379,7 @@ TEST_F(ProcessorDiffDriveTest, angular)
     processor->setOrigin(F0);
 
     // Straight one turn of the wheels, in one go
+    t += 1.0;
     data(0) = -20.0 ; // one fifth of a turn of the left wheel, in reverse
     data(1) =  20.0 ; // one fifth of a turn of the right wheel, forward --> we'll turn left --> positive angle
 
diff --git a/test/gtest_processor_loopclosure.cpp b/test/gtest_processor_loopclosure.cpp
index 90d55137f88921c61c2e79bee1ea19d0f9047111..6a4b40d32c0908484e31b576310657aba5d11fb4 100644
--- a/test/gtest_processor_loopclosure.cpp
+++ b/test/gtest_processor_loopclosure.cpp
@@ -34,7 +34,7 @@ protected:
     bool detectFeatures(CaptureBasePtr cap) override     { return true;};
     CaptureBasePtr findLoopCandidate(CaptureBasePtr _capture) override
     {
-        for (FrameBasePtr kf : getProblem()->getTrajectory()->getFrameList())
+        for (FrameBasePtr kf : *getProblem()->getTrajectory())
             if (kf->isKey())
                 for (CaptureBasePtr cap : kf->getCaptureList())
                     if (cap != _capture)
@@ -87,7 +87,7 @@ TEST(ProcessorLoopClosure, installProcessor)
 
     // new KF
     t += dt;
-    auto kf = problem->emplaceFrame(KEY, t, x); //KF2
+    auto kf = problem->emplaceKeyFrame(t, x); //KF2
     // emplace a capture in KF
     auto capt_lc = CaptureBase::emplace<CaptureVoid>(kf, t, sens_lc);
     proc_lc->captureCallback(capt_lc);
diff --git a/test/gtest_processor_motion.cpp b/test/gtest_processor_motion.cpp
index a977672d0230aff9786590d10724d544036f7224..743b0fcc56a4088ceb87073a6941200fd74ccd33 100644
--- a/test/gtest_processor_motion.cpp
+++ b/test/gtest_processor_motion.cpp
@@ -50,11 +50,6 @@ class ProcessorMotion_test : public testing::Test{
         Vector2d                    data;
         Matrix2d                    data_cov;
 
-//        ProcessorMotion_test() :
-//            ProcessorOdom2d(std::make_shared<ProcessorParamsOdom2d>()),
-//            dt(0)
-//        { }
-
         void SetUp() override
         {
             std::string wolf_root = _WOLF_ROOT_DIR;
@@ -63,7 +58,7 @@ class ProcessorMotion_test : public testing::Test{
             problem = Problem::create("PO", 2);
             sensor = static_pointer_cast<SensorOdom2d>(problem->installSensor("SensorOdom2d", "odom", Vector3d(0,0,0), wolf_root + "/test/yaml/sensor_odom_2d.yaml"));
             ParamsProcessorOdom2dPtr params(std::make_shared<ParamsProcessorOdom2d>());
-            params->time_tolerance  = 0.25;
+            params->time_tolerance  = 0.5;
             params->dist_traveled   = 100;
             params->angle_turned    = 6.28;
             params->max_time_span   = 2.5*dt; // force KF at every third process()
@@ -146,10 +141,12 @@ TEST_F(ProcessorMotion_test, getState_time_structure)
         capture->setTimeStamp(t);
         capture->setData(data);
         capture->setDataCovariance(data_cov);
-        processor->captureCallback(capture);
+        capture->process();
         WOLF_DEBUG("t: ", t, "  x: ", problem->getState().vector("PO").transpose());
     }
 
+    problem->print(2,1,1,1);
+
     ASSERT_TRUE (processor->getState(7, "P").count('P'));
     ASSERT_FALSE(processor->getState(7, "P").count('O'));
     ASSERT_FALSE(processor->getState(7, "O").count('P'));
@@ -315,7 +312,7 @@ TEST_F(ProcessorMotion_test, splitBufferAutoPrior)
     SensorBasePtr    S = processor->getSensor();
 
     TimeStamp        t_target = 8.5;
-    FrameBasePtr     F_target = problem->emplaceFrame(KEY, t_target);
+    FrameBasePtr     F_target = problem->emplaceKeyFrame(t_target);
     CaptureMotionPtr C_source = std::dynamic_pointer_cast<CaptureMotion>(processor->getLast());
     CaptureMotionPtr C_target = CaptureBase::emplace<CaptureMotion>(F_target,
                                                                     "ODOM 2d",
@@ -360,7 +357,7 @@ TEST_F(ProcessorMotion_test, splitBufferFactorPrior)
     SensorBasePtr    S = processor->getSensor();
 
     TimeStamp        t_target = 8.5;
-    FrameBasePtr     F_target = problem->emplaceFrame(KEY, t_target);
+    FrameBasePtr     F_target = problem->emplaceKeyFrame(t_target);
     CaptureMotionPtr C_source = std::dynamic_pointer_cast<CaptureMotion>(processor->getLast());
     CaptureMotionPtr C_target = CaptureBase::emplace<CaptureMotion>(F_target,
                                                                     "ODOM 2d",
@@ -405,7 +402,7 @@ TEST_F(ProcessorMotion_test, splitBufferFixPrior)
     SensorBasePtr    S = processor->getSensor();
 
     TimeStamp        t_target = 8.5;
-    FrameBasePtr     F_target = problem->emplaceFrame(KEY, t_target);
+    FrameBasePtr     F_target = problem->emplaceKeyFrame(t_target);
     CaptureMotionPtr C_source = std::dynamic_pointer_cast<CaptureMotion>(processor->getLast());
     CaptureMotionPtr C_target = CaptureBase::emplace<CaptureMotion>(F_target,
                                                                     "ODOM 2d",
diff --git a/test/gtest_processor_tracker_feature_dummy.cpp b/test/gtest_processor_tracker_feature_dummy.cpp
index 6238a5786533fc89df682364305db55661921e92..7b6dc1c40fe5a4eabcdeae278cd823fa01403fbb 100644
--- a/test/gtest_processor_tracker_feature_dummy.cpp
+++ b/test/gtest_processor_tracker_feature_dummy.cpp
@@ -287,8 +287,8 @@ TEST_F(ProcessorTrackerFeatureDummyTest, process)
     CaptureBasePtr cap1 = std::make_shared<CaptureVoid>(0, sensor);
     cap1->process();
 
-    ASSERT_TRUE(problem->getTrajectory()->getLastKeyFrame() != nullptr);
-    ASSERT_EQ(problem->getTrajectory()->getLastKeyFrame()->id(), cap1->getFrame()->id());
+    ASSERT_TRUE(problem->getTrajectory()->getLastFrame() != nullptr);
+    ASSERT_EQ(problem->getTrajectory()->getLastFrame()->id(), cap1->getFrame()->id());
     ASSERT_TRUE(problem->check(0));
 
     //2ND TIME
@@ -322,7 +322,7 @@ TEST_F(ProcessorTrackerFeatureDummyTest, process)
     cap5->process();
 
     ASSERT_TRUE(cap4->getFrame()->isKey());
-    ASSERT_EQ(problem->getTrajectory()->getLastKeyFrame()->id(), cap4->getFrame()->id());
+    ASSERT_EQ(problem->getTrajectory()->getLastFrame()->id(), cap4->getFrame()->id());
     ASSERT_TRUE(problem->check(0));
 
     // check factors
diff --git a/test/gtest_processor_tracker_landmark_dummy.cpp b/test/gtest_processor_tracker_landmark_dummy.cpp
index 44dfbdf14cc1f53ea4962cc7f2517d37ef5210b2..d0fe1b1d8a748df603db674cf7604720c69e4d71 100644
--- a/test/gtest_processor_tracker_landmark_dummy.cpp
+++ b/test/gtest_processor_tracker_landmark_dummy.cpp
@@ -321,8 +321,8 @@ TEST_F(ProcessorTrackerLandmarkDummyTest, process)
     CaptureBasePtr cap1 = std::make_shared<CaptureVoid>(0, sensor);
     cap1->process();
 
-    ASSERT_TRUE(problem->getTrajectory()->getLastKeyFrame() != nullptr);
-    ASSERT_EQ(problem->getTrajectory()->getLastKeyFrame(), cap1->getFrame());
+    ASSERT_TRUE(problem->getTrajectory()->getLastFrame() != nullptr);
+    ASSERT_EQ(problem->getTrajectory()->getLastFrame(), cap1->getFrame());
 
     //2ND TIME
     WOLF_DEBUG("Second time...");
@@ -351,7 +351,7 @@ TEST_F(ProcessorTrackerLandmarkDummyTest, process)
     CaptureBasePtr cap5 = std::make_shared<CaptureVoid>(4, sensor);
     cap5->process();
 
-    ASSERT_EQ(problem->getTrajectory()->getLastKeyFrame(), cap4->getFrame());
+    ASSERT_EQ(problem->getTrajectory()->getLastFrame(), cap4->getFrame());
     ASSERT_EQ(processor->getOrigin(), cap4);
     ASSERT_EQ(processor->getLast(), cap5);
 
diff --git a/test/gtest_solver_ceres.cpp b/test/gtest_solver_ceres.cpp
index 42b2f1c825fe7cfc79bbe44e8f577eed7ec1dfd8..9fe0e4306704919bcd7ab234716a3acf107e0227 100644
--- a/test/gtest_solver_ceres.cpp
+++ b/test/gtest_solver_ceres.cpp
@@ -1,5 +1,5 @@
 /*
- * gtest_solver_ceres.cpp
+ * gtest_solver_ptr.cpp
  *
  *  Created on: Jun, 2018
  *      Author: jvallve
@@ -13,6 +13,7 @@
 #include "core/capture/capture_void.h"
 #include "core/factor/factor_pose_2d.h"
 #include "core/factor/factor_quaternion_absolute.h"
+#include "core/factor/factor_block_absolute.h"
 #include "core/state_block/local_parametrization_angle.h"
 #include "core/state_block/local_parametrization_quaternion.h"
 
@@ -27,604 +28,1533 @@
 using namespace wolf;
 using namespace Eigen;
 
-WOLF_PTR_TYPEDEFS(SolverCeresWrapper);
-class SolverCeresWrapper : public SolverCeres
-{
-    public:
-        SolverCeresWrapper(const ProblemPtr& wolf_problem) :
-            SolverCeres(wolf_problem)
-        {
-        };
-
-        bool isStateBlockRegisteredSolverCeres(const StateBlockPtr& st)
-        {
-            return ceres_problem_->HasParameterBlock(SolverManager::getAssociatedMemBlockPtr(st));
-        };
-
-        bool isStateBlockRegisteredSolverManager(const StateBlockPtr& st)
-        {
-            return state_blocks_.find(st)!=state_blocks_.end();
-        };
-
-        bool isStateBlockFixed(const StateBlockPtr& st)
-        {
-            return ceres_problem_->IsParameterBlockConstant(SolverManager::getAssociatedMemBlockPtr(st));
-        };
-
-        int numStateBlocks()
-        {
-            return ceres_problem_->NumParameterBlocks();
-        };
-
-        int numFactors()
-        {
-            return ceres_problem_->NumResidualBlocks();
-        };
-
-        bool isFactorRegistered(const FactorBasePtr& fac_ptr) const override
-        {
-            return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end() && fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
-        };
-
-        bool hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param)
-        {
-            return state_blocks_local_param_.find(st) != state_blocks_local_param_.end() &&
-                   state_blocks_local_param_.at(st)->getLocalParametrization() == local_param &&
-                   ceres_problem_->GetParameterization(getAssociatedMemBlockPtr(st)) == state_blocks_local_param_.at(st).get();
-        };
+/*
+ * Following tests are the same as in gtest_solver_manager.cpp
+ * (modifications should be applied to both tests)
+ */
 
-        bool hasLocalParametrization(const StateBlockPtr& st) const
-        {
-            return state_blocks_local_param_.find(st) != state_blocks_local_param_.end();
-        };
+StateBlockPtr createStateBlock()
+{
+    Vector4d state; state << 1, 0, 0, 0;
+    return std::make_shared<StateBlock>(state);
+}
 
-};
+FactorBasePtr createFactor(StateBlockPtr sb_ptr)
+{
+    return std::make_shared<FactorBlockAbsolute>(std::make_shared<FeatureBase>("Dummy",
+                                                                               VectorXd::Zero(sb_ptr->getSize()),
+                                                                               MatrixXd::Identity(sb_ptr->getSize(),sb_ptr->getSize())),
+                                                 sb_ptr,
+                                                 nullptr,
+                                                 false);
+}
 
 TEST(SolverCeres, Create)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // check double ointers to branches
-    ASSERT_EQ(P, solver_ceres->getProblem());
+    // check pointers
+    EXPECT_EQ(P, solver_ptr->getProblem());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // run solver check
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddStateBlock)
+////////////////////////////////////////////////////////
+// FLOATING STATE BLOCKS
+TEST(SolverCeres, FloatingStateBlock_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleAddStateBlock)
+TEST(SolverCeres, FloatingStateBlock_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // add stateblock again
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, UpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddFix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock unfixed
-    ASSERT_FALSE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 
     // Fix frame
     sb_ptr->fix();
 
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, FloatingStateBlock_AddFixed)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddUpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddUpdateLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
     // Fix state block
     sb_ptr->fix();
 
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, FloatingStateBlock_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock localparam
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check stateblock localparam
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_Remove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_EQ(solver_ceres->numStateBlocks(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddRemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check no stateblocks
-    ASSERT_FALSE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_EQ(solver_ceres->numStateBlocks(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveUpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddRemoveAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
-    // update solver
-    solver_ceres->update();
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD); // again ADD in notification list
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleRemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_DoubleRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // update solver
+    solver_ptr->update();
+
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddFactor)
+TEST(SolverCeres, FloatingStateBlock_AddUpdated)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Fix
+    sb_ptr->fix();
+
+    // Set State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, ADD);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY,  0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 1);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverCeres, DoubleAddFactor)
+////////////////////////////////////////////////////////
+// STATE BLOCKS AND FACTOR
+TEST(SolverCeres, StateBlockAndFactor_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
 
-    // add factor again
-    P->notifyFactor(c,ADD);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock (floating for the moment)
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update();
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+
+    // notify factor (state block now not floating)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 1);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+    solver_ptr->update();
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddRemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_Fix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    ASSERT_TRUE(P->getFactorNotificationMapSize() == 0); // add+remove = empty
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock unfixed
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // Fix frame
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleRemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_UpdateLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_RemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // there is a factor involved, removal posponed (REMOVE in notification list)
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+TEST(SolverCeres, StateBlockAndFactor_RemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddStateBlockLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_AddRemoveStateBlock)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD notification is not executed since state block involved is missing (ADD notification added)
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(sb_ptr));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(sb_ptr,local_param_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_AddRemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // state block should be automatically stored as floating
 
-    // Remove local param
-    sb_ptr->removeLocalParametrization();
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_DoubleRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD is posponed
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_DoubleRemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // state block should be automatically stored as floating
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // repeated REMOVE should be ignored
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(sb_ptr));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(sb_ptr,local_param_ptr));
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_AddUpdatedStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Fix
+    sb_ptr->fix();
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // Change State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // update solver
+    solver_ptr->update();
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverCeres, FactorsRemoveLocalParam)
+////////////////////////////////////////////////////////
+// ONLY FACTOR
+TEST(SolverCeres, OnlyFactor_Add)
 {
     ProblemPtr P = Problem::create("PO", 3);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) 2 factors quaternion
-    FrameBasePtr                    F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorQuaternionAbsolutePtr c1 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
-    FactorQuaternionAbsolutePtr c2 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD should be posponed (in the notification list again)
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),F->getO()->getLocalParametrization()));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
 
-    // remove local param
-    F->getO()->removeLocalParametrization();
+TEST(SolverCeres, OnlyFactor_Remove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // ADD factor should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check local param
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(F->getO()));
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // update solver
+    solver_ptr->update(); // nothing to update
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, FactorsUpdateLocalParam)
+TEST(SolverCeres, OnlyFactor_AddRemove)
 {
     ProblemPtr P = Problem::create("PO", 3);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) 2 factors quaternion
-    FrameBasePtr                    F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorQuaternionAbsolutePtr c1 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
-    FactorQuaternionAbsolutePtr c2 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
 
-    // update solver
-    solver_ceres->update();
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),F->getO()->getLocalParametrization()));
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
 
-    // remove local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationQuaternionGlobal>();
-    F->getO()->setLocalParametrization(local_param_ptr);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // nothing to update
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),local_param_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+////////////////////////////////////////////////////////
+// MULTITHREADING
+
+TEST(SolverCeres, MultiThreadingTruncatedNotifications)
+{
+    double Dt = 5.0;
+    ProblemPtr P = Problem::create("PO", 2);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // loop updating (without sleep)
+    std::thread t([&](){
+        auto start_t = std::chrono::high_resolution_clock::now();
+        while (true)
+        {
+            solver_ptr->update();
+            ASSERT_TRUE(solver_ptr->check());
+            if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_t).count() > Dt)
+                break;
+        }});
+
+    // loop emplacing and removing frames (window of 10 KF)
+    auto start = std::chrono::high_resolution_clock::now();
+    TimeStamp ts(0);
+    while (true)
+    {
+        // Emplace Frame, Capture, feature and factor pose 2d
+        FrameBasePtr        F = P->emplaceKeyFrame(ts, P->stateZero());
+        auto C = CaptureBase::emplace<CaptureVoid>(F, ts, nullptr);
+        auto f = FeatureBase::emplace<FeatureBase>(C, "FeaturePose2d", Vector3d::Zero(), Matrix3d::Identity());
+        auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+
+        ts += 1.0;
+
+        if (P->getTrajectory()->getFrameMap().size() > 10)
+            (*P->getTrajectory()->begin())->remove();
+
+        if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start).count() > Dt)
+            break;
+    }
+
+    t.join();
 }
 
 int main(int argc, char **argv)
diff --git a/test/gtest_solver_manager.cpp b/test/gtest_solver_manager.cpp
index 7e212b9971b5bf8fb1a46f94141ce61a1a5aab08..5226e125d79e059b29fbbfc3a432ce72452ef43c 100644
--- a/test/gtest_solver_manager.cpp
+++ b/test/gtest_solver_manager.cpp
@@ -13,8 +13,8 @@
 #include "core/state_block/state_block.h"
 #include "core/capture/capture_void.h"
 #include "core/factor/factor_pose_2d.h"
-#include "core/state_block/local_parametrization_base.h"
-#include "core/state_block/local_parametrization_angle.h"
+#include "core/factor/factor_block_absolute.h"
+#include "core/state_block/local_parametrization_quaternion.h"
 #include "dummy/solver_manager_dummy.h"
 
 #include <iostream>
@@ -23,562 +23,1527 @@
 using namespace wolf;
 using namespace Eigen;
 
+/*
+ * Following tests are the same as in gtest_solver_ceres.cpp
+ * (modifications should be applied to both tests)
+ */
+
+StateBlockPtr createStateBlock()
+{
+    Vector4d state; state << 1, 0, 0, 0;
+    return std::make_shared<StateBlock>(state);
+}
+
+FactorBasePtr createFactor(StateBlockPtr sb_ptr)
+{
+    return std::make_shared<FactorBlockAbsolute>(std::make_shared<FeatureBase>("Dummy",
+                                                                               VectorXd::Zero(sb_ptr->getSize()),
+                                                                               MatrixXd::Identity(sb_ptr->getSize(),sb_ptr->getSize())),
+                                                 sb_ptr,
+                                                 nullptr,
+                                                 false);
+}
+
 TEST(SolverManager, Create)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
-    // check double pointers to branches
-    ASSERT_EQ(P, solver_manager_ptr->getProblem());
+    // check pointers
+    EXPECT_EQ(P, solver_ptr->getProblem());
+
+    // run solver check
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddStateBlock)
+////////////////////////////////////////////////////////
+// FLOATING STATE BLOCKS
+TEST(SolverManager, FloatingStateBlock_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleAddStateBlock)
+TEST(SolverManager, FloatingStateBlock_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // add stateblock again
+    // notify stateblock again
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, UpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddFix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock unfixed
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 
     // Fix frame
     sb_ptr->fix();
 
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Fix state block
     sb_ptr->fix();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdateLocalParamStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddUpdateLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Local param
-    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationAngle>();
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
     sb_ptr->setLocalParametrization(local_ptr);
 
     // Fix state block
     sb_ptr->fix();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddLocalParamRemoveLocalParamStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddLocalParamRemoveLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
     // Local param
-    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationAngle>();
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
     sb_ptr->setLocalParametrization(local_ptr);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock localparam
-    ASSERT_TRUE(solver_manager_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Remove local param
     sb_ptr->removeLocalParametrization();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock localparam
-    ASSERT_FALSE(solver_manager_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_Remove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddRemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancel out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check state block
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveUpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddRemoveAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add state_block
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD); // again ADD in notification list
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check state block
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleRemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_DoubleRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // update solver
+    solver_ptr->update();
+
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdatedStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddUpdated)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
     // Fix
     sb_ptr->fix();
 
     // Set State
-    Vector2d state_2 = 2*state;
-    sb_ptr->setState(state_2);
+    sb_ptr->setState(2*sb_ptr->getState());
 
     // Check flags have been set true
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
 
     // == When an ADD is notified: a ADD notification should be stored ==
 
-    // add state_block
+    // notify state block
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    // check notifications
     Notification notif;
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
-    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, ADD);
 
     // == Insert OTHER notifications ==
 
     // Set State --> FLAG
-    state_2 = 2*state;
-    sb_ptr->setState(state_2);
+    sb_ptr->setState(2*sb_ptr->getState());
 
     // Fix --> FLAG
     sb_ptr->unfix();
     // Check flag has been set true
-    ASSERT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
 
     // == consume empties the notification map ==
-    solver_manager_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
     // Check flags have been reset
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
 
     // == When an REMOVE is notified: a REMOVE notification should be stored ==
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
-    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
-    ASSERT_EQ(notif, REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
 
     // == REMOVE + ADD: notification map should be empty ==
     P->notifyStateBlock(sb_ptr,ADD);
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 
     // == UPDATES should clear the list of notifications ==
-    // add state_block
+    // notify state block
     P->notifyStateBlock(sb_ptr,ADD);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // == ADD + REMOVE: notification map should be empty ==
     P->notifyStateBlock(sb_ptr,ADD);
     P->notifyStateBlock(sb_ptr,REMOVE);
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverManager, AddFactor)
+////////////////////////////////////////////////////////
+// STATE BLOCKS AND FACTOR
+TEST(SolverManager, StateBlockAndFactor_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify stateblock (floating for the moment)
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    // notification
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+
+    // notify factor (state block now not floating)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
-    // check factor
-    ASSERT_TRUE(solver_manager_ptr->isFactorRegistered(c));
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    // add factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // notification
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_Fix)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, REMOVE);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock unfixed
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // Fix frame
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddRemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, 0, P->stateZero() );
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    // notification
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // add factor
-    P->notifyFactor(c,REMOVE);
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // notification
-    ASSERT_EQ(P->getFactorNotificationMapSize(), 0); // ADD+REMOVE cancels out
-    ASSERT_FALSE(P->getFactorNotification(c, notif)); // ADD+REMOVE cancels out
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_UpdateLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_RemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update(); // there is a factor involved, removal posponed (REMOVE in notification list)
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleRemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_RemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD notification is not executed since state block involved is missing (ADD notification added)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddRemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_DoubleRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD is posponed
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_DoubleRemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+
+    // update solver
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddUpdatedStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceFrame(KEY, TimeStamp(0), P->stateZero() );
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // Fix
+    sb_ptr->fix();
+
+    // Change State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // update solver
+    solver_ptr->update();
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+}
+
+////////////////////////////////////////////////////////
+// ONLY FACTOR
+TEST(SolverManager, OnlyFactor_Add)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, OnlyFactor_Remove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // ADD factor should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // nothing to update
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, OnlyFactor_AddRemove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // nothing to update
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
+////////////////////////////////////////////////////////
+// MULTITHREADING
+
 TEST(SolverManager, MultiThreadingTruncatedNotifications)
 {
     double Dt = 5.0;
     ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // loop updating (without sleep)
     std::thread t([&](){
         auto start_t = std::chrono::high_resolution_clock::now();
         while (true)
         {
-            solver_manager_ptr->update();
+            solver_ptr->update();
+            ASSERT_TRUE(solver_ptr->check());
             if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_t).count() > Dt)
                 break;
         }});
 
     // loop emplacing and removing frames (window of 10 KF)
     auto start = std::chrono::high_resolution_clock::now();
+    TimeStamp ts(0);
     while (true)
     {
         // Emplace Frame, Capture, feature and factor pose 2d
-        FrameBasePtr        F = P->emplaceFrame(KEY, TimeStamp(0), P->stateZero());
-        auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
+        FrameBasePtr        F = P->emplaceKeyFrame(ts, P->stateZero());
+        auto C = CaptureBase::emplace<CaptureVoid>(F, ts, nullptr);
         auto f = FeatureBase::emplace<FeatureBase>(C, "FeaturePose2d", Vector3d::Zero(), Matrix3d::Identity());
         auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
 
-        if (P->getTrajectory()->getFrameList().size() > 10)
-            P->getTrajectory()->getFrameList().front()->remove();
+        ts += 1.0;
+
+        if (P->getTrajectory()->getFrameMap().size() > 10)
+            (*P->getTrajectory()->begin())->remove();
 
         if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start).count() > Dt)
             break;
diff --git a/test/gtest_track_matrix.cpp b/test/gtest_track_matrix.cpp
index 4e539e24b7554a7a2e5cfe88096cc4c861de4018..72bf3f7d8ce8124c4005daf4a9a82ba119504d5e 100644
--- a/test/gtest_track_matrix.cpp
+++ b/test/gtest_track_matrix.cpp
@@ -22,9 +22,11 @@ class TrackMatrixTest : public testing::Test
         FrameBasePtr   F0, F1, F2, F3, F4;
         CaptureBasePtr C0, C1, C2, C3, C4;
         FeatureBasePtr f0, f1, f2, f3, f4;
+        ProblemPtr problem;
 
         void SetUp() override
         {
+            problem = Problem::create("PO", 2);
             // unlinked captures
             // Some warnings will be thrown "linking with nullptr" for emplacing without providing frame pointer
             C0 = CaptureBase::emplace<CaptureBase>(nullptr, "CaptureBase", 0.0);
@@ -35,11 +37,11 @@ class TrackMatrixTest : public testing::Test
 
             // unlinked frames
             // Some warnings will be thrown "linking with nullptr" for emplacing without providing frame pointer
-            F0 = FrameBase::emplace<FrameBase>(nullptr, NON_ESTIMATED, 0.0, nullptr);
-            F1 = FrameBase::emplace<FrameBase>(nullptr, NON_ESTIMATED, 1.0, nullptr);
-            F2 = FrameBase::emplace<FrameBase>(nullptr, NON_ESTIMATED, 2.0, nullptr);
-            F3 = FrameBase::emplace<FrameBase>(nullptr, NON_ESTIMATED, 3.0, nullptr);
-            F4 = FrameBase::emplace<FrameBase>(nullptr, NON_ESTIMATED, 4.0, nullptr);
+            F0 = FrameBase::createNonKeyFrame<FrameBase>(0.0, nullptr);
+            F1 = FrameBase::createNonKeyFrame<FrameBase>(1.0, nullptr);
+            F2 = FrameBase::createNonKeyFrame<FrameBase>(2.0, nullptr);
+            F3 = FrameBase::createNonKeyFrame<FrameBase>(3.0, nullptr);
+            F4 = FrameBase::createNonKeyFrame<FrameBase>(4.0, nullptr);
 
             // unlinked features
             // Some warnings will be thrown "linking with nullptr" for emplacing without providing capture pointer
@@ -50,8 +52,8 @@ class TrackMatrixTest : public testing::Test
             f4 = FeatureBase::emplace<FeatureBase>(nullptr, "FeatureBase", m, m_cov);
 
             // F0 and F4 are keyframes
-            F0->setKey();
-            F4->setKey();
+            F0->setKey(problem);
+            F4->setKey(problem);
 
             // link captures
             C0->link(F0);
diff --git a/test/gtest_trajectory.cpp b/test/gtest_trajectory.cpp
index 00f7d83fff99ff39b16fc8a67c2eee9b767cfbe1..ff103bc097ba9d166ef76a97fcde20b15199507a 100644
--- a/test/gtest_trajectory.cpp
+++ b/test/gtest_trajectory.cpp
@@ -32,62 +32,34 @@ TEST(TrajectoryBase, ClosestKeyFrame)
     //   1     2     3     4       time stamps
     // --+-----+-----+-----+--->   time
 
-    FrameBasePtr F1 = P->emplaceFrame(KEY,           1, Eigen::Vector3d::Zero() );
-    FrameBasePtr F2 = P->emplaceFrame(KEY,           2, Eigen::Vector3d::Zero() );
-    FrameBasePtr F3 = P->emplaceFrame(AUXILIARY,     3, Eigen::Vector3d::Zero() );
-    FrameBasePtr F4 = P->emplaceFrame(NON_ESTIMATED, 4, Eigen::Vector3d::Zero() );
+    FrameBasePtr F1 = P->emplaceKeyFrame(          1, Eigen::Vector3d::Zero() );
+    FrameBasePtr F2 = P->emplaceKeyFrame(          2, Eigen::Vector3d::Zero() );
+    // FrameBasePtr F3 = P->emplaceFrame(AUXILIARY,     3, Eigen::Vector3d::Zero() );
+    FrameBasePtr F3 = FrameBase::createNonKeyFrame<FrameBase>(3, P->getFrameStructure(),
+//                                                              P->getDim(),
+                                                              std::list<VectorXd>({Eigen::Vector2d::Zero(),Eigen::Vector1d::Zero()}) );
+    FrameBasePtr F4 = FrameBase::createNonKeyFrame<FrameBase>(4, P->getFrameStructure(),
+//                                                              P->getDim(),
+                                                              std::list<VectorXd>({Eigen::Vector2d::Zero(),Eigen::Vector1d::Zero()}) );
 
     FrameBasePtr KF; // closest key-frame queried
 
-    KF = T->closestKeyFrameToTimeStamp(-0.8);                // before all keyframes    --> return F1
+    KF = T->closestFrameToTimeStamp(-0.8);                // before all keyframes    --> return F1
     ASSERT_EQ(KF->id(), F1->id());                           // same id!
 
-    KF = T->closestKeyFrameToTimeStamp(1.1);                 // between keyframes       --> return F1
+    KF = T->closestFrameToTimeStamp(1.1);                 // between keyframes       --> return F1
     ASSERT_EQ(KF->id(), F1->id());                           // same id!
 
-    KF = T->closestKeyFrameToTimeStamp(1.9);                 // between keyframes       --> return F2
+    KF = T->closestFrameToTimeStamp(1.9);                 // between keyframes       --> return F2
     ASSERT_EQ(KF->id(), F2->id());                           // same id!
 
-    KF = T->closestKeyFrameToTimeStamp(2.6);                 // between keyframe and auxiliary frame, but closer to auxiliary frame --> return F2
+    KF = T->closestFrameToTimeStamp(2.6);                 // between keyframe and auxiliary frame, but closer to auxiliary frame --> return F2
     ASSERT_EQ(KF->id(), F2->id());                           // same id!
 
-    KF = T->closestKeyFrameToTimeStamp(3.2);                 // after the auxiliary frame, between closer to frame --> return F2
+    KF = T->closestFrameToTimeStamp(3.2);                 // after the auxiliary frame, between closer to frame --> return F2
     ASSERT_EQ(KF->id(), F2->id());                           // same id!
 
-    KF = T->closestKeyFrameToTimeStamp(4.2);                 // after the last frame --> return F2
-    ASSERT_EQ(KF->id(), F2->id());                           // same id!
-}
-
-TEST(TrajectoryBase, ClosestKeyOrAuxFrame)
-{
-
-    ProblemPtr P = Problem::create("PO", 2);
-    TrajectoryBasePtr T = P->getTrajectory();
-
-    // Trajectory status:
-    //  KF1   KF2    F3      frames
-    //   1     2     3       time stamps
-    // --+-----+-----+--->   time
-
-    FrameBasePtr F1 = P->emplaceFrame(KEY,           1, Eigen::Vector3d::Zero() );
-    FrameBasePtr F2 = P->emplaceFrame(AUXILIARY,     2, Eigen::Vector3d::Zero() );
-    FrameBasePtr F3 = P->emplaceFrame(NON_ESTIMATED, 3, Eigen::Vector3d::Zero() );
-
-    FrameBasePtr KF; // closest key-frame queried
-
-    KF = T->closestKeyOrAuxFrameToTimeStamp(-0.8);          // before all keyframes    --> return f0
-    ASSERT_EQ(KF->id(), F1->id());                           // same id!
-
-    KF = T->closestKeyOrAuxFrameToTimeStamp(1.1);           // between keyframes       --> return F1
-    ASSERT_EQ(KF->id(), F1->id());                           // same id!
-
-    KF = T->closestKeyOrAuxFrameToTimeStamp(1.9);           // between keyframes       --> return F2
-    ASSERT_EQ(KF->id(), F2->id());                           // same id!
-
-    KF = T->closestKeyOrAuxFrameToTimeStamp(2.6);           // between keyframe and frame, but closer to frame --> return F2
-    ASSERT_EQ(KF->id(), F2->id());                           // same id!
-
-    KF = T->closestKeyOrAuxFrameToTimeStamp(3.2);           // after the last frame    --> return F2
+    KF = T->closestFrameToTimeStamp(4.2);                 // after the last frame --> return F2
     ASSERT_EQ(KF->id(), F2->id());                           // same id!
 }
 
@@ -108,28 +80,29 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     std::cout << __LINE__ << std::endl;
 
     // add F1
-    FrameBasePtr F1 = P->emplaceFrame(KEY, 1, Eigen::Vector3d::Zero()); // 2 non-fixed
+    FrameBasePtr F1 = P->emplaceKeyFrame(1, Eigen::Vector3d::Zero()); // 2 non-fixed
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 1);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 1);
     ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 2);
     std::cout << __LINE__ << std::endl;
 
     // add F2
-    FrameBasePtr F2 = P->emplaceFrame(KEY, 2, Eigen::Vector3d::Zero()); // 1 fixed, 1 not
+    FrameBasePtr F2 = P->emplaceKeyFrame(2, Eigen::Vector3d::Zero()); // 1 fixed, 1 not
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 2);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 2);
     ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 4);
     std::cout << __LINE__ << std::endl;
 
     // add F3
-    FrameBasePtr F3 = P->emplaceFrame(NON_ESTIMATED, 3, Eigen::Vector3d::Zero());
+    FrameBasePtr F3 = FrameBase::createNonKeyFrame<FrameBase>(3, P->getFrameStructure(),
+//                                                              P->getDim(),
+                                                              std::list<VectorXd>({Eigen::Vector2d::Zero(),Eigen::Vector1d::Zero()}));
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 3);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 2);
     ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 4);
     std::cout << __LINE__ << std::endl;
 
-    ASSERT_EQ(T->getLastFrame()->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyFrame()->id(), F2->id());
+    ASSERT_EQ(T->getLastFrame()->id(), F2->id());
     std::cout << __LINE__ << std::endl;
 
     N.update();
@@ -139,24 +112,23 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     // remove frames and keyframes
     F2->remove(); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 2);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 1);
     ASSERT_EQ(P->getStateBlockNotificationMapSize(), (SizeStd) 2);
     std::cout << __LINE__ << std::endl;
 
-    ASSERT_EQ(T->getLastFrame()->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyFrame()->id(), F1->id());
+    ASSERT_EQ(T->getLastFrame()->id(), F1->id());
     std::cout << __LINE__ << std::endl;
 
     F3->remove(); // F
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 1);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 1);
     std::cout << __LINE__ << std::endl;
 
-    ASSERT_EQ(T->getLastKeyFrame()->id(), F1->id());
+    ASSERT_EQ(T->getLastFrame()->id(), F1->id());
 
     F1->remove(); // KF
     if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getFrameList().             size(), (SizeStd) 0);
+    ASSERT_EQ(T->getFrameMap().             size(), (SizeStd) 0);
     std::cout << __LINE__ << std::endl;
 
     N.update();
@@ -165,123 +137,6 @@ TEST(TrajectoryBase, Add_Remove_Frame)
     std::cout << __LINE__ << std::endl;
 }
 
-TEST(TrajectoryBase, KeyFramesAreSorted)
-{
-    using std::make_shared;
-
-    ProblemPtr P = Problem::create("PO", 2);
-    TrajectoryBasePtr T = P->getTrajectory();
-
-    // Trajectory status:
-    //  KF1   KF2    F3      frames
-    //   1     2     3       time stamps
-    // --+-----+-----+--->   time
-
-    // add frames and keyframes in random order --> keyframes must be sorted after that
-    FrameBasePtr F2 = P->emplaceFrame(KEY, 2, Eigen::Vector3d::Zero());
-    if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    FrameBasePtr F3 = P->emplaceFrame(NON_ESTIMATED, 3, Eigen::Vector3d::Zero()); // non-key-frame
-    if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    FrameBasePtr F1 = P->emplaceFrame(KEY, 1, Eigen::Vector3d::Zero());
-    if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    F3->setKey(); // set KF3
-    if (debug) P->print(2,0,0,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F3->id());
-
-    auto F4 = P->emplaceFrame(NON_ESTIMATED, 1.5, Eigen::Vector3d::Zero());
-    // Trajectory status:
-    //  KF1   KF2   KF3     F4       frames
-    //   1     2     3     1.5       time stamps
-    // --+-----+-----+------+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F4->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F3->id());
-
-    F4->setKey();
-    // Trajectory status:
-    //  KF1   KF4   KF2    KF3       frames
-    //   1    1.5    2      3        time stamps
-    // --+-----+-----+------+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F3->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F3->id());
-
-    F2->setTimeStamp(4);
-    // Trajectory status:
-    //  KF1   KF4   KF3    KF2       frames
-    //   1    1.5    3      4        time stamps
-    // --+-----+-----+------+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    F4->setTimeStamp(0.5);
-    // Trajectory status:
-    //  KF4   KF2   KF3    KF2       frames
-    //  0.5    1     3      4        time stamps
-    // --+-----+-----+------+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getFrameList().front()->id(), F4->id());
-
-    auto F5 = P->emplaceFrame(AUXILIARY, 1.5, Eigen::Vector3d::Zero());
-    // Trajectory status:
-    //  KF4   KF2  AuxF5  KF3   KF2       frames
-    //  0.5    1    1.5    3     4        time stamps
-    // --+-----+-----+-----+-----+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F2->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    F5->setTimeStamp(5);
-    // Trajectory status:
-    //  KF4   KF2   KF3   KF2   AuxF5     frames
-    //  0.5    1     3     4     5        time stamps
-    // --+-----+-----+-----+-----+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F5->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F5->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    auto F6 = P->emplaceFrame(NON_ESTIMATED, 6, Eigen::Vector3d::Zero());
-    // Trajectory status:
-    //  KF4   KF2   KF3   KF2   AuxF5  F6       frames
-    //  0.5    1     3     4     5     6        time stamps
-    // --+-----+-----+-----+-----+-----+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F6->id());
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F5->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-    auto F7 = P->emplaceFrame(NON_ESTIMATED, 5.5, Eigen::Vector3d::Zero());
-    // Trajectory status:
-    //  KF4   KF2   KF3   KF2   AuxF5  F7   F6       frames
-    //  0.5    1     3     4     5     5.5   6        time stamps
-    // --+-----+-----+-----+-----+-----+-----+--->    time
-    if (debug) P->print(2,0,1,0);
-    ASSERT_EQ(T->getLastFrame()         ->id(), F7->id()); //Only auxiliary and key-frames are sorted
-    ASSERT_EQ(T->getLastKeyOrAuxFrame()->id(), F5->id());
-    ASSERT_EQ(T->getLastKeyFrame()      ->id(), F2->id());
-
-}
-
 int main(int argc, char **argv)
 {
   testing::InitGoogleTest(&argc, argv);
diff --git a/test/gtest_tree_manager.cpp b/test/gtest_tree_manager.cpp
index 1d97e2925487f9e363e1292b6ef2c2a82c29fc96..15bb1778940d6e2d1e80ad05e195caba66b6417d 100644
--- a/test/gtest_tree_manager.cpp
+++ b/test/gtest_tree_manager.cpp
@@ -94,7 +94,7 @@ TEST(TreeManager, keyFrameCallback)
 
     ASSERT_EQ(GM->n_KF_, 0);
 
-    auto F0 = P->emplaceFrame(KEY, 0, "PO", 3, VectorXd(7) );
+    auto F0 = P->emplaceKeyFrame(0, "PO", 3, VectorXd(7) );
     P->keyFrameCallback(F0, nullptr, 0);
 
     ASSERT_EQ(GM->n_KF_, 1);
diff --git a/test/gtest_tree_manager_sliding_window.cpp b/test/gtest_tree_manager_sliding_window.cpp
index 5cbc9550cc9a751a57046807f236486f4d5cbb92..b8ff8240e7e2c7e97fb4f56aeadb72d2b51a0027 100644
--- a/test/gtest_tree_manager_sliding_window.cpp
+++ b/test/gtest_tree_manager_sliding_window.cpp
@@ -79,7 +79,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowFixViral)
     P->applyPriorOptions(0);
 
     // FRAME 1 ----------------------------------------------------------
-    auto F1 = P->getTrajectory()->getLastKeyFrame();
+    auto F1 = P->getTrajectory()->getLastFrame();
     ASSERT_TRUE(F1 != nullptr);
 
     Vector7d state = F1->getStateVector();
@@ -87,7 +87,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowFixViral)
     Matrix6d cov = Matrix6d::Identity();
 
     // FRAME 2 ----------------------------------------------------------
-    auto F2 = P->emplaceFrame(KEY, TimeStamp(2), "PO", 3, state);
+    auto F2 = P->emplaceKeyFrame(TimeStamp(2), "PO", 3, state);
     P->keyFrameCallback(F2, nullptr, 0);
 
     // absolute factor
@@ -103,7 +103,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowFixViral)
     ASSERT_FALSE(F1->isRemoving());
 
     // FRAME 3 ----------------------------------------------------------
-    auto F3 = P->emplaceFrame(KEY, TimeStamp(3), "PO", 3,    state);
+    auto F3 = P->emplaceKeyFrame(TimeStamp(3), "PO", 3,    state);
     P->keyFrameCallback(F3, nullptr, 0);
 
     // absolute factor
@@ -119,7 +119,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowFixViral)
     ASSERT_FALSE(F1->isRemoving());
 
     // FRAME 4 ----------------------------------------------------------
-    auto F4 = P->emplaceFrame(KEY, TimeStamp(4), "PO", 3,    state);
+    auto F4 = P->emplaceKeyFrame(TimeStamp(4), "PO", 3,    state);
     P->keyFrameCallback(F4, nullptr, 0);
 
     // absolute factor
@@ -139,7 +139,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowFixViral)
     ASSERT_TRUE(F2->isFixed()); //Fixed
 
     // FRAME 5 ----------------------------------------------------------
-    auto F5 = P->emplaceFrame(KEY, TimeStamp(5), "PO", 3,    state);
+    auto F5 = P->emplaceKeyFrame(TimeStamp(5), "PO", 3,    state);
     P->keyFrameCallback(F5, nullptr, 0);
 
     // absolute factor
@@ -175,7 +175,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral)
     P->applyPriorOptions(0);
 
     // FRAME 1 (prior) ----------------------------------------------------------
-    auto F1 = P->getTrajectory()->getLastKeyFrame();
+    auto F1 = P->getTrajectory()->getLastFrame();
     ASSERT_TRUE(F1 != nullptr);
 
     Vector7d state = F1->getStateVector();
@@ -183,7 +183,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral)
     Matrix6d cov = Matrix6d::Identity();
 
     // FRAME 2 ----------------------------------------------------------
-    auto F2 = P->emplaceFrame(KEY, TimeStamp(2), "PO", 3,    state);
+    auto F2 = P->emplaceKeyFrame(TimeStamp(2), "PO", 3,    state);
     P->keyFrameCallback(F2, nullptr, 0);
 
     // absolute factor
@@ -199,7 +199,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral)
     ASSERT_FALSE(F1->isRemoving());
 
     // FRAME 3 ----------------------------------------------------------
-    auto F3 = P->emplaceFrame(KEY, TimeStamp(3), "PO", 3,    state);
+    auto F3 = P->emplaceKeyFrame(TimeStamp(3), "PO", 3,    state);
     P->keyFrameCallback(F3, nullptr, 0);
 
     // absolute factor
@@ -215,7 +215,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral)
     ASSERT_FALSE(F1->isRemoving());
 
     // FRAME 4 ----------------------------------------------------------
-    auto F4 = P->emplaceFrame(KEY, TimeStamp(4), "PO", 3,    state);
+    auto F4 = P->emplaceKeyFrame(TimeStamp(4), "PO", 3,    state);
     P->keyFrameCallback(F4, nullptr, 0);
 
     // absolute factor
@@ -235,7 +235,7 @@ TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral)
     ASSERT_FALSE(F2->isFixed()); //Not fixed
 
     // FRAME 5 ----------------------------------------------------------
-    auto F5 = P->emplaceFrame(KEY, TimeStamp(5), "PO", 3,    state);
+    auto F5 = P->emplaceKeyFrame(TimeStamp(5), "PO", 3,    state);
     P->keyFrameCallback(F5, nullptr, 0);
 
     // absolute factor
diff --git a/wolf_scripts/wolf_uninstall.sh b/wolf_scripts/wolf_uninstall.sh
index b381616ecf9c37423d5cd11e18bb3f5502cec641..ff022e0b25ebc31bc0d7d0e50124569896c8f6ba 100755
--- a/wolf_scripts/wolf_uninstall.sh
+++ b/wolf_scripts/wolf_uninstall.sh
@@ -1,20 +1,42 @@
 #!/bin/bash
 
-echo “=”
-echo “====================== UNINSTALLING WOLF ======================”
-echo “=”
+if [ -z "$1" ]
+then
+    echo “=”
+    echo “====================== UNINSTALLING WOLF ======================”
+    echo “=”
 
-echo "cd /usr/local/include/iri-algorithms/"
-cd /usr/local/include/iri-algorithms/
-echo "sudo rm -rf wolf"
-sudo rm -rf wolf
+    echo "cd /usr/local/include/iri-algorithms/"
+    cd /usr/local/include/iri-algorithms/
+    echo "sudo rm -rf wolf"
+    sudo rm -rf wolf
 
-echo "cd /usr/local/lib/iri-algorithms/"
-echo "sudo rm libwolf*.*"
-cd /usr/local/lib/iri-algorithms/
-sudo rm libwolf*.*
+    echo "cd /usr/local/lib/iri-algorithms/"
+    echo "sudo rm libwolf*.*"
+    cd /usr/local/lib/iri-algorithms/
+    sudo rm libwolf*.*
 
-echo "cd /usr/local/lib/cmake/"
-echo "sudo rm -rf wolf*"
-cd /usr/local/lib/cmake/
-sudo rm -rf wolf*
\ No newline at end of file
+    echo "cd /usr/local/lib/cmake/"
+    echo "sudo rm -rf wolf*"
+    cd /usr/local/lib/cmake/
+    sudo rm -rf wolf*
+else
+    echo “=”
+    echo “====================== UNINSTALLING PLUGIN $1 ======================”
+    echo “=”
+
+    echo "cd /usr/local/include/iri-algorithms/wolf"
+    cd /usr/local/include/iri-algorithms/wolf/
+    echo "sudo rm -rf plugin_$1"
+    sudo rm -rf plugin_$1
+
+    echo "cd /usr/local/lib/iri-algorithms/"
+    echo "sudo rm libwolf$1.*"
+    cd /usr/local/lib/iri-algorithms/
+    sudo rm libwolf$1.*
+
+    echo "cd /usr/local/lib/cmake/"
+    echo "sudo rm -rf wolf$1"
+    cd /usr/local/lib/cmake/
+    sudo rm -rf wolf$1
+fi