diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h
index 73eab66545543855df753984a5fb5fb55d3607d6..102cc6a180264c402355be4a48e47a99cf2d86bf 100644
--- a/include/core/problem/problem.h
+++ b/include/core/problem/problem.h
@@ -283,6 +283,16 @@ class Problem : public std::enable_shared_from_this<Problem>
      */
     void emplaceStatesToFrame(FrameBasePtr _frame_ptr, const StateKeys& _frame_keys);
 
+    /** \brief Take a frame and emplace to it the missing states
+     * \param _frame_ptr Frame to which states have to be emplaced
+     * \param _frame_states the states vectors to be added to the frame
+     *
+     * - The frame_types are taken from Problem.
+     * - Only the missing keys are emplaced.
+     * - The states are emplaced to the frame as unfixed.
+     */
+    void emplaceStatesToFrame(FrameBasePtr _frame_ptr, const VectorComposite& _frame_states);
+
     // Frame getters
     FrameBaseConstPtr getLastFrame() const;
     FrameBasePtr      getLastFrame();
diff --git a/include/core/processor/processor_motion.h b/include/core/processor/processor_motion.h
index 4d8dcee2844eafebb27865d38329c6c6eb263c7e..6464addfa1cba48b45bbeab7ecabefe43f636204 100644
--- a/include/core/processor/processor_motion.h
+++ b/include/core/processor/processor_motion.h
@@ -503,8 +503,6 @@ class ProcessorMotion : public ProcessorBase, public MotionProvider
     CaptureMotionPtr last_ptr_;
     CaptureMotionPtr incoming_ptr_;
 
-    FrameBasePtr last_frame_ptr_;
-
   protected:
     // helpers to avoid allocation
     mutable double          dt_;                     ///< Time step
diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp
index a744c222d91986ca9ba35df0cbf26314c6968998..bd9a117fac1303ae286dd64ffaff26aedfea099d 100644
--- a/src/problem/problem.cpp
+++ b/src/problem/problem.cpp
@@ -538,6 +538,20 @@ void Problem::emplaceStatesToFrame(FrameBasePtr _frame_ptr, const StateKeys& _fr
         _frame_ptr->emplaceStateBlock(vec_pair.first, frame_types_.at(vec_pair.first), vec_pair.second, false);
 }
 
+void Problem::emplaceStatesToFrame(FrameBasePtr _frame_ptr, const VectorComposite& _frame_states)
+{
+    if (not _frame_ptr) throw std::runtime_error("Problem::emplaceStatesToFrame: the provided frame is nullptr");
+
+    if (not frame_types_.has(_frame_states.getKeys()))
+        throw std::runtime_error("Problem::emplaceStatesToFrame: any unknown type. Asked for key " + _frame_states.getKeys() +
+                                 " but problem only know the types of " + frame_types_.getKeys());
+
+    // emplace missing keys
+    for (auto key : _frame_states.getKeys())
+        if (not _frame_ptr->getState().has(key))
+            _frame_ptr->emplaceStateBlock(key, frame_types_.at(key), _frame_states.at(key), false);
+}
+
 TimeStamp Problem::getTimeStamp() const
 {
     TimeStamp ts = TimeStamp::Invalid();
diff --git a/src/processor/processor_diff_drive.cpp b/src/processor/processor_diff_drive.cpp
index 824af2cb3f399782f9d33c0158b8b4fa7c047442..eb49aa5815913b06f6b7a8e70838f5e96db113db 100644
--- a/src/processor/processor_diff_drive.cpp
+++ b/src/processor/processor_diff_drive.cpp
@@ -130,13 +130,13 @@ void ProcessorDiffDrive::computeCurrentDelta(const Eigen::VectorXd& _data,
 }
 
 CaptureMotionPtr ProcessorDiffDrive::emplaceCapture(const FrameBasePtr&   _frame_own,
-                                                    const SensorBasePtr&  _sensor,
-                                                    const TimeStamp&      _ts,
-                                                    const VectorXd&       _data,
-                                                    const MatrixXd&       _data_cov,
-                                                    const VectorXd&       _calib,
-                                                    const VectorXd&       _calib_preint,
-                                                    const CaptureBasePtr& _capture_origin)
+                                                   const SensorBasePtr&  _sensor,
+                                                   const TimeStamp&      _ts,
+                                                   const VectorXd&       _data,
+                                                   const MatrixXd&       _data_cov,
+                                                   const VectorXd&       _calib,
+                                                   const VectorXd&       _calib_preint,
+                                                   const CaptureBasePtr& _capture_origin)
 {
     auto cap_motion =
         CaptureBase::emplace<CaptureDiffDrive>(_frame_own, _ts, _sensor, _data, _data_cov, _capture_origin);
diff --git a/src/processor/processor_motion.cpp b/src/processor/processor_motion.cpp
index abad4de30d6f6eb0b01839040e69216825dcfaf6..4bba66a5327b652977914b736bc779c593b384cd 100644
--- a/src/processor/processor_motion.cpp
+++ b/src/processor/processor_motion.cpp
@@ -41,7 +41,6 @@ ProcessorMotion::ProcessorMotion(const std::string& _type,
       origin_ptr_(),
       last_ptr_(),
       incoming_ptr_(),
-      last_frame_ptr_(),
       dt_(0.0),
       x_(_state_size),
       delta_(_delta_size),
@@ -208,6 +207,7 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
     preProcess();  // Derived class operations
 
+    FrameBasePtr new_keyframe           = nullptr;
     FrameBasePtr keyframe_from_callback = computeProcessingStep();
     if (keyframe_from_callback) buffer_frame_.removeUpTo(keyframe_from_callback->getTimeStamp());
 
@@ -215,12 +215,12 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
     {
         case FIRST_TIME_WITHOUT_KF: {
             // There is no KF: create own origin
-            setOrigin(getProblem()->stateZero(getStateKeys()), _incoming_ptr->getTimeStamp());
+            new_keyframe = setOrigin(getProblem()->stateZero(getStateKeys()), _incoming_ptr->getTimeStamp());
             break;
         }
         case FIRST_TIME_WITH_KF_BEFORE_INCOMING: {
             // cannot join to the KF: create own origin
-            setOrigin(getProblem()->getState(getStateKeys()), _incoming_ptr->getTimeStamp());
+            new_keyframe = setOrigin(getProblem()->getState(getStateKeys()), _incoming_ptr->getTimeStamp());
             break;
         }
         case FIRST_TIME_WITH_KF_ON_INCOMING: {
@@ -230,17 +230,16 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         }
         case FIRST_TIME_WITH_KF_AFTER_INCOMING: {
             // cannot join to the KF: create own origin
-            setOrigin(getProblem()->getState(getStateKeys()), _incoming_ptr->getTimeStamp());
+            new_keyframe = setOrigin(getProblem()->getState(getStateKeys()), _incoming_ptr->getTimeStamp());
             break;
         }
-        case RUNNING_WITHOUT_KF:
-        case RUNNING_WITH_KF_ON_ORIGIN:
-            break;
-
         default:
             break;
     }
 
+    // callback new keyframe to other processors
+    if (new_keyframe) getProblem()->keyFrameCallback(new_keyframe, shared_from_this());
+
     // integrate motion data
     // Done at this place because emplaceFirstFrame() needs
     integrateOneStep();
@@ -295,12 +294,7 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
             // update KF state (adding missing StateBlocks)
             auto proc_state = getState(timestamp_from_callback);
-            for (auto pair_key_vec : proc_state)
-                if (not keyframe_from_callback->has(pair_key_vec.first))
-                    keyframe_from_callback->emplaceStateBlock(
-                        pair_key_vec.first, getStateTypes().at(pair_key_vec.first), pair_key_vec.second, false);
-                else
-                    keyframe_from_callback->getStateBlock(pair_key_vec.first)->setState(pair_key_vec.second);
+            getProblem()->emplaceStatesToFrame(keyframe_from_callback, proc_state);
 
             // Find the capture acting as the buffer's origin
             auto capture_origin = capture_existing->getOriginCapture();
@@ -318,7 +312,7 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
             // emplace a new motion capture to the new keyframe
             auto capture_for_keyframe_callback =
-                emplaceCapture(keyframe_from_callback,  // j
+                emplaceCapture(keyframe_from_callback,
                                getSensor(),
                                timestamp_from_callback,
                                Eigen::VectorXd::Zero(data_size_),
@@ -331,18 +325,16 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
             // and give the part of the buffer before the new keyframe to the capture for the KF callback
             splitBuffer(capture_existing, timestamp_from_callback, capture_for_keyframe_callback);
 
-            // // create motion feature and add it to the capture
-            // // create motion factor and add it to the feature, and constrain to the other capture (origin)
+            // emplace motion features and factors
             emplaceFeaturesAndFactors(capture_origin, capture_for_keyframe_callback);
 
             // modify existing feature and factor (if they exist in the existing capture)
             if (!capture_existing->getFeatureList().empty())
             {
-                // setMeasurement is not allowed: feature (and factor) will be removed and a new feature and factor
-                // will be emplaced
+                // feature (and factor) will be removed and new ones will be emplaced
                 capture_existing->getFeatureList().back()->remove();  // factor is removed automatically
 
-                assert(capture_existing->getFeatureList().empty());  // there was only one feature!
+                assert(capture_existing->getFeatureList().empty());  // ensure that there was only one feature
 
                 emplaceFeaturesAndFactors(capture_for_keyframe_callback, capture_existing);
             }
@@ -389,14 +381,7 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
             // update KF state (adding missing StateBlocks)
             auto proc_state = this->getState(timestamp_from_callback);
-            for (auto pair_key_vec : proc_state)
-                if (not keyframe_from_callback->has(pair_key_vec.first))
-                    keyframe_from_callback->emplaceStateBlock(
-                        pair_key_vec.first, getStateTypes().at(pair_key_vec.first), pair_key_vec.second, false);
-                else
-                    keyframe_from_callback->getStateBlock(pair_key_vec.first)->setState(pair_key_vec.second);
-
-            auto& capture_existing = last_ptr_;
+            getProblem()->emplaceStatesToFrame(keyframe_from_callback, proc_state);
 
             // Find the capture acting as the buffer's origin
             auto& capture_origin = origin_ptr_;
@@ -417,10 +402,9 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
             // split the buffer
             // and give the part of the buffer before the new keyframe to the capture for the KF callback
-            splitBuffer(capture_existing, timestamp_from_callback, capture_for_keyframe_callback);
+            splitBuffer(last_ptr_, timestamp_from_callback, capture_for_keyframe_callback);
 
-            // create motion feature and add it to the capture
-            // create motion factor and add it to the feature, and constrain to the other capture (origin)
+            // emplace motion features and factors
             emplaceFeaturesAndFactors(capture_origin, capture_for_keyframe_callback);
 
             // reset processor origin
@@ -433,24 +417,15 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
             break;
     }
 
-    // Update state and time stamps
+    // Update time stamp
     auto ts = getTimeStamp();
     last_ptr_->setTimeStamp(ts);
-    last_ptr_->getFrame()->setTimeStamp(ts);
-    VectorComposite state_propa = getState(ts);
-    for (auto pair_key_vec : state_propa)
-        if (not last_ptr_->getFrame()->has(pair_key_vec.first))
-            last_ptr_->getFrame()->emplaceStateBlock(
-                pair_key_vec.first, getStateTypes().at(pair_key_vec.first), pair_key_vec.second, false);
-        else
-            last_ptr_->getFrame()->getStateBlock(pair_key_vec.first)->setState(pair_key_vec.second);
 
     if (permittedKeyFrame() && voteForKeyFrame())
     {
         /*
          * Legend:
          *    * : any keyframe
-         *    + : last frame
          *    x : any capture
          *    o : origin capture
          *    l : last capture      -> we'll make a KF here
@@ -460,19 +435,19 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
          *
          * Trajectory before the KF
          *
-         *    * ========= * ========= +
+         *    * ========= *
          *    x ----------o ----------l   i
          *     \____f____/
          *
          * Trajectory after creating KF at last
          *
-         *    * ========= * ========= * = +
+         *    * ========= * ========= *
          *    x ----------o ----------l --n
          *     \____f____/ \____f____/
          *
          * Trajectory after creating KF at last and reset
          *
-         *    * ========= * ========= * = +
+         *    * ========= * ========= *
          *    x ----------x ----------o --l
          *     \____f____/ \____f____/
          *
@@ -481,19 +456,18 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         // Set the capture's calibration with best results available (in case origin_ptr_ received a solve())
         setCalibration(last_ptr_, getCalibration(origin_ptr_));
 
-        // Set the frame of last_ptr as key
-        auto keyframe = last_ptr_->getFrame();
-        keyframe->link(getProblem());
+        // Create a keyframe at last_ptr
+        auto keyframe =
+            getProblem()->emplaceFrame(last_ptr_->getTimeStamp(), this->getState(last_ptr_->getTimeStamp()));
 
-        // create motion feature and add it to the key_capture
-        // create motion factor and link it to parent feature and other frame (which is origin's frame)
+        // link last_ptr_ to the keyframe
+        last_ptr_->link(keyframe);
+
+        // emplace features and factors
         emplaceFeaturesAndFactors(origin_ptr_, last_ptr_);
 
-        // create a new frame
-        auto frame_new =
-            std::make_shared<FrameBase>(getTimeStamp(), getStateTypes(), getProblem()->getState(getStateKeys()));
         // create a new capture
-        auto capture_new = emplaceCapture(frame_new,
+        auto capture_new = emplaceCapture(nullptr,  // no linked to any frame yet
                                           getSensor(),
                                           keyframe->getTimeStamp(),
                                           Eigen::VectorXd::Zero(data_size_),
@@ -508,11 +482,10 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         resetDerived();
 
         // Reset pointers
-        origin_ptr_     = last_ptr_;
-        last_ptr_       = capture_new;
-        last_frame_ptr_ = frame_new;
+        origin_ptr_ = last_ptr_;
+        last_ptr_   = capture_new;
 
-        // callback to other processors
+        // callback keyframe to other processors
         getProblem()->keyFrameCallback(keyframe, shared_from_this());
     }
 
@@ -546,8 +519,7 @@ VectorComposite ProcessorMotion::getState(StateKeys _keys) const
 
     // We do not have any info of where to find a valid state
     // Further checking here for origin_ptr is redundant: if last=null, then origin=null too.
-    if (origin_ptr_ == nullptr or origin_ptr_->isRemoving() or last_ptr_ == nullptr or
-        last_ptr_->getFrame() == nullptr)
+    if (origin_ptr_ == nullptr or origin_ptr_->isRemoving() or last_ptr_ == nullptr)
     {
         WOLF_DEBUG("Processor has no state. Returning an empty VectorComposite with no blocks");
         return VectorComposite();  // return empty state
@@ -559,7 +531,7 @@ VectorComposite ProcessorMotion::getState(StateKeys _keys) const
     // this may happen when in the very first frame where the capture has no motion info --> empty buffer
     if (last_ptr_->getBuffer().empty())
     {
-        return last_ptr_->getFrame()->getState(_keys);
+        return origin_ptr_->getFrame()->getState(_keys);
     }
 
     /* Doing this:
@@ -787,11 +759,8 @@ void ProcessorMotion::setOrigin(FrameBasePtr _origin_frame)
     origin_ptr_->getBuffer().push_back(motionZero(_origin_frame->getTimeStamp()));
 
     // ---------- LAST ----------
-    // Make non-key-frame for last Capture
-    last_frame_ptr_ = std::make_shared<FrameBase>(origin_ts, getStateTypes(), _origin_frame->getState(getStateKeys()));
-
-    // emplace (emtpy) last Capture
-    last_ptr_ = emplaceCapture(last_frame_ptr_,
+    // create last capture
+    last_ptr_ = emplaceCapture(nullptr,  // no linked to any frame yet
                                getSensor(),
                                origin_ts,
                                Eigen::VectorXd::Zero(data_size_),
@@ -1131,8 +1100,7 @@ void ProcessorMotion::printHeader(int           _depth,
                 << " Frm" << getOrigin()->getFrame()->id() << std::endl;
     if (getLast())
         _stream << _tabs << "  "
-                << "l: Cap" << getLast()->id() << " - "
-                << " Frm" << getLast()->getFrame()->id() << std::endl;
+                << "l: Cap" << getLast()->id() << std::endl;
     if (getIncoming())
         _stream << _tabs << "  "
                 << "i: Cap" << getIncoming()->id() << std::endl;
diff --git a/test/gtest_processor_loop_closure.cpp b/test/gtest_processor_loop_closure.cpp
index d4b585dcd3a949b3ac831672118c53600ac5a988..b57fe809d014062ca5bf7edfd171b22c699bfe01 100644
--- a/test/gtest_processor_loop_closure.cpp
+++ b/test/gtest_processor_loop_closure.cpp
@@ -64,7 +64,7 @@ class ProcessorLoopClosureTest : public testing::Test
         return CaptureBase::emplace<CaptureBase>(frame, "CaptureBase", frame->getTimeStamp(), sensor);
     }
 
-    CaptureBasePtr createCapture(TimeStamp ts)
+    CaptureBasePtr emplaceCapture(TimeStamp ts)
     {
         // new capture
         return std::make_shared<CaptureBase>("CaptureBase", ts, sensor);
@@ -92,7 +92,7 @@ TEST_F(ProcessorLoopClosureTest, frame_stored)
 TEST_F(ProcessorLoopClosureTest, capture_stored)
 {
     // new capture
-    auto cap1 = createCapture(1);
+    auto cap1 = emplaceCapture(1);
 
     // captureCallback
     processor->captureCallback(cap1);
@@ -121,7 +121,7 @@ TEST_F(ProcessorLoopClosureTest, captureCallbackCase2)
     auto frm1 = emplaceFrame(1, Vector3d::Zero());
 
     // new capture
-    auto cap1 = createCapture(1);
+    auto cap1 = emplaceCapture(1);
 
     // keyframecallback
     problem->keyFrameCallback(frm1, nullptr);
@@ -140,7 +140,7 @@ TEST_F(ProcessorLoopClosureTest, captureCallbackCase3)
     // new frame
     auto frm1 = emplaceFrame(1, Vector3d::Zero());
     // new capture
-    auto cap1 = createCapture(2);
+    auto cap1 = emplaceCapture(2);
 
     // keyframecallback
     problem->keyFrameCallback(frm1, nullptr);
@@ -173,7 +173,7 @@ TEST_F(ProcessorLoopClosureTest, keyFrameCallbackCase2)
     // new frame
     auto frm1 = emplaceFrame(1, Vector3d::Zero());
     // new capture
-    auto cap1 = createCapture(1);
+    auto cap1 = emplaceCapture(1);
 
     // captureCallback
     processor->captureCallback(cap1);
@@ -192,7 +192,7 @@ TEST_F(ProcessorLoopClosureTest, keyFrameCallbackCase3)
     // new frame
     auto frm1 = emplaceFrame(2, Vector3d::Zero());
     // new capture
-    auto cap1 = createCapture(1);
+    auto cap1 = emplaceCapture(1);
 
     // captureCallback
     processor->captureCallback(cap1);
@@ -211,7 +211,7 @@ TEST_F(ProcessorLoopClosureTest, keyFrameCallbackCase4)
     // new frame
     auto frm1 = emplaceFrame(1, Vector3d::Zero());
     // new capture
-    auto cap1 = createCapture(2);
+    auto cap1 = emplaceCapture(2);
 
     // captureCallback
     processor->captureCallback(cap1);
@@ -234,7 +234,7 @@ TEST_F(ProcessorLoopClosureTest, captureCallbackMatch)
     auto frm4 = emplaceFrame(4, Vector3d::Zero());
     auto frm5 = emplaceFrame(5, Vector3d::Zero());
     // new captures
-    auto cap4 = createCapture(4);
+    auto cap4 = emplaceCapture(4);
 
     // keyframecallback
     problem->keyFrameCallback(frm1, nullptr);
@@ -264,11 +264,11 @@ TEST_F(ProcessorLoopClosureTest, keyFrameCallbackMatch)
     // new frame
     auto frm2 = emplaceFrame(2, Vector3d::Zero());
     // new captures
-    auto cap1 = createCapture(1);
-    auto cap2 = createCapture(2);
-    auto cap3 = createCapture(3);
-    auto cap4 = createCapture(4);
-    auto cap5 = createCapture(5);
+    auto cap1 = emplaceCapture(1);
+    auto cap2 = emplaceCapture(2);
+    auto cap3 = emplaceCapture(3);
+    auto cap4 = emplaceCapture(4);
+    auto cap5 = emplaceCapture(5);
 
     // captureCallback
     processor->captureCallback(cap1);