diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index 09cffcf..1e2fabd 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -1,3 +1,7 @@
+add_library(backend
+ sensor_fusion/imu/imu_types.cc
+)
+
add_executable(gauss_newton_method example/gauss_newton_method.cpp)
target_link_libraries(gauss_newton_method tiny_ceres)
diff --git a/backend/sensor_fusion/imu/imu_types.cc b/backend/sensor_fusion/imu/imu_types.cc
new file mode 100644
index 0000000..3dd4cb8
--- /dev/null
+++ b/backend/sensor_fusion/imu/imu_types.cc
@@ -0,0 +1,393 @@
+/**
+ * This file is part of ORB-SLAM3
+ *
+ * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel
+ * and Juan D. Tardós, University of Zaragoza. Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M.
+ * Montiel and Juan D. Tardós, University of Zaragoza.
+ *
+ * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
+ * If not, see .
+ */
+
+#include "backend/sensor_fusion/imu/imu_types.h"
+
+#include
+
+namespace backend {
+
+namespace IMU {
+
+const float eps = 1e-4;
+
+Eigen::Matrix3f NormalizeRotation( const Eigen::Matrix3f &R ) {
+ Eigen::JacobiSVD svd( R, Eigen::ComputeFullU | Eigen::ComputeFullV );
+ return svd.matrixU() * svd.matrixV().transpose();
+}
+
+Eigen::Matrix3f RightJacobianSO3( const float &x, const float &y, const float &z ) {
+ Eigen::Matrix3f I;
+ I.setIdentity();
+ const float d2 = x * x + y * y + z * z;
+ const float d = sqrt( d2 );
+ Eigen::Vector3f v;
+ v << x, y, z;
+ Eigen::Matrix3f W = Sophus::SO3f::hat( v );
+ if ( d < eps ) {
+ return I;
+ } else {
+ return I - W * ( 1.0f - cos( d ) ) / d2 + W * W * ( d - sin( d ) ) / ( d2 * d );
+ }
+}
+
+Eigen::Matrix3f RightJacobianSO3( const Eigen::Vector3f &v ) {
+ return RightJacobianSO3( v( 0 ), v( 1 ), v( 2 ) );
+}
+
+Eigen::Matrix3f InverseRightJacobianSO3( const float &x, const float &y, const float &z ) {
+ Eigen::Matrix3f I;
+ I.setIdentity();
+ const float d2 = x * x + y * y + z * z;
+ const float d = sqrt( d2 );
+ Eigen::Vector3f v;
+ v << x, y, z;
+ Eigen::Matrix3f W = Sophus::SO3f::hat( v );
+
+ if ( d < eps ) {
+ return I;
+ } else {
+ return I + W / 2 + W * W * ( 1.0f / d2 - ( 1.0f + cos( d ) ) / ( 2.0f * d * sin( d ) ) );
+ }
+}
+
+Eigen::Matrix3f InverseRightJacobianSO3( const Eigen::Vector3f &v ) {
+ return InverseRightJacobianSO3( v( 0 ), v( 1 ), v( 2 ) );
+}
+
+IntegratedRotation::IntegratedRotation( const Eigen::Vector3f &angVel, const Bias &imuBias,
+ const float &time ) {
+ const float x = ( angVel( 0 ) - imuBias.bwx ) * time;
+ const float y = ( angVel( 1 ) - imuBias.bwy ) * time;
+ const float z = ( angVel( 2 ) - imuBias.bwz ) * time;
+
+ const float d2 = x * x + y * y + z * z;
+ const float d = sqrt( d2 );
+
+ Eigen::Vector3f v;
+ v << x, y, z;
+ Eigen::Matrix3f W = Sophus::SO3f::hat( v );
+ if ( d < eps ) {
+ deltaR = Eigen::Matrix3f::Identity() + W;
+ rightJ = Eigen::Matrix3f::Identity();
+ } else {
+ deltaR = Eigen::Matrix3f::Identity() + W * sin( d ) / d + W * W * ( 1.0f - cos( d ) ) / d2;
+ rightJ = Eigen::Matrix3f::Identity() - W * ( 1.0f - cos( d ) ) / d2 +
+ W * W * ( d - sin( d ) ) / ( d2 * d );
+ }
+}
+
+Preintegrated::Preintegrated( const Bias &b_, const Calib &calib ) {
+ Nga = calib.Cov;
+ NgaWalk = calib.CovWalk;
+ Initialize( b_ );
+}
+
+// Copy constructor
+Preintegrated::Preintegrated( Preintegrated *pImuPre )
+ : dT( pImuPre->dT ),
+ C( pImuPre->C ),
+ Info( pImuPre->Info ),
+ Nga( pImuPre->Nga ),
+ NgaWalk( pImuPre->NgaWalk ),
+ b( pImuPre->b ),
+ dR( pImuPre->dR ),
+ dV( pImuPre->dV ),
+ dP( pImuPre->dP ),
+ JRg( pImuPre->JRg ),
+ JVg( pImuPre->JVg ),
+ JVa( pImuPre->JVa ),
+ JPg( pImuPre->JPg ),
+ JPa( pImuPre->JPa ),
+ avgA( pImuPre->avgA ),
+ avgW( pImuPre->avgW ),
+ bu( pImuPre->bu ),
+ db( pImuPre->db ),
+ mvMeasurements( pImuPre->mvMeasurements ) {}
+
+void Preintegrated::CopyFrom( Preintegrated *pImuPre ) {
+ dT = pImuPre->dT;
+ C = pImuPre->C;
+ Info = pImuPre->Info;
+ Nga = pImuPre->Nga;
+ NgaWalk = pImuPre->NgaWalk;
+ b.CopyFrom( pImuPre->b );
+ dR = pImuPre->dR;
+ dV = pImuPre->dV;
+ dP = pImuPre->dP;
+ JRg = pImuPre->JRg;
+ JVg = pImuPre->JVg;
+ JVa = pImuPre->JVa;
+ JPg = pImuPre->JPg;
+ JPa = pImuPre->JPa;
+ avgA = pImuPre->avgA;
+ avgW = pImuPre->avgW;
+ bu.CopyFrom( pImuPre->bu );
+ db = pImuPre->db;
+ mvMeasurements = pImuPre->mvMeasurements;
+}
+
+void Preintegrated::Initialize( const Bias &b_ ) {
+ dR.setIdentity();
+ dV.setZero();
+ dP.setZero();
+ JRg.setZero();
+ JVg.setZero();
+ JVa.setZero();
+ JPg.setZero();
+ JPa.setZero();
+ C.setZero();
+ Info.setZero();
+ db.setZero();
+ b = b_;
+ bu = b_;
+ avgA.setZero();
+ avgW.setZero();
+ dT = 0.0f;
+ mvMeasurements.clear();
+}
+
+void Preintegrated::Reintegrate() {
+ std::unique_lock lock( mMutex );
+ const std::vector aux = mvMeasurements;
+ Initialize( bu );
+ for ( size_t i = 0; i < aux.size(); i++ ) IntegrateNewMeasurement( aux[i].a, aux[i].w, aux[i].t );
+}
+
+void Preintegrated::IntegrateNewMeasurement( const Eigen::Vector3f &acceleration,
+ const Eigen::Vector3f &angVel, const float &dt ) {
+ mvMeasurements.push_back( integrable( acceleration, angVel, dt ) );
+
+ // Position is updated firstly, as it depends on previously computed velocity and rotation.
+ // Velocity is updated secondly, as it depends on previously computed rotation.
+ // Rotation is the last to be updated.
+
+ // Matrices to compute covariance
+ Eigen::Matrix A;
+ A.setIdentity();
+ Eigen::Matrix B;
+ B.setZero();
+
+ Eigen::Vector3f acc, accW;
+ acc << acceleration( 0 ) - b.bax, acceleration( 1 ) - b.bay, acceleration( 2 ) - b.baz;
+ accW << angVel( 0 ) - b.bwx, angVel( 1 ) - b.bwy, angVel( 2 ) - b.bwz;
+
+ avgA = ( dT * avgA + dR * acc * dt ) / ( dT + dt );
+ avgW = ( dT * avgW + accW * dt ) / ( dT + dt );
+
+ // Update delta position dP and velocity dV (rely on no-updated delta rotation)
+ dP = dP + dV * dt + 0.5f * dR * acc * dt * dt;
+ dV = dV + dR * acc * dt;
+
+ // Compute velocity and position parts of matrices A and B (rely on non-updated delta rotation)
+ Eigen::Matrix Wacc = Sophus::SO3f::hat( acc );
+
+ A.block<3, 3>( 3, 0 ) = -dR * dt * Wacc;
+ A.block<3, 3>( 6, 0 ) = -0.5f * dR * dt * dt * Wacc;
+ A.block<3, 3>( 6, 3 ) = Eigen::DiagonalMatrix( dt, dt, dt );
+ B.block<3, 3>( 3, 3 ) = dR * dt;
+ B.block<3, 3>( 6, 3 ) = 0.5f * dR * dt * dt;
+
+ // Update position and velocity jacobians wrt bias correction
+ JPa = JPa + JVa * dt - 0.5f * dR * dt * dt;
+ JPg = JPg + JVg * dt - 0.5f * dR * dt * dt * Wacc * JRg;
+ JVa = JVa - dR * dt;
+ JVg = JVg - dR * dt * Wacc * JRg;
+
+ // Update delta rotation
+ IntegratedRotation dRi( angVel, b, dt );
+ dR = NormalizeRotation( dR * dRi.deltaR );
+
+ // Compute rotation parts of matrices A and B
+ A.block<3, 3>( 0, 0 ) = dRi.deltaR.transpose();
+ B.block<3, 3>( 0, 0 ) = dRi.rightJ * dt;
+
+ // Update covariance
+ C.block<9, 9>( 0, 0 ) = A * C.block<9, 9>( 0, 0 ) * A.transpose() + B * Nga * B.transpose();
+ C.block<6, 6>( 9, 9 ) += NgaWalk;
+
+ // Update rotation jacobian wrt bias correction
+ JRg = dRi.deltaR.transpose() * JRg - dRi.rightJ * dt;
+
+ // Total integrated time
+ dT += dt;
+}
+
+void Preintegrated::MergePrevious( Preintegrated *pPrev ) {
+ if ( pPrev == this ) return;
+
+ std::unique_lock lock1( mMutex );
+ std::unique_lock lock2( pPrev->mMutex );
+ Bias bav;
+ bav.bwx = bu.bwx;
+ bav.bwy = bu.bwy;
+ bav.bwz = bu.bwz;
+ bav.bax = bu.bax;
+ bav.bay = bu.bay;
+ bav.baz = bu.baz;
+
+ const std::vector aux1 = pPrev->mvMeasurements;
+ const std::vector aux2 = mvMeasurements;
+
+ Initialize( bav );
+ for ( size_t i = 0; i < aux1.size(); i++ )
+ IntegrateNewMeasurement( aux1[i].a, aux1[i].w, aux1[i].t );
+ for ( size_t i = 0; i < aux2.size(); i++ )
+ IntegrateNewMeasurement( aux2[i].a, aux2[i].w, aux2[i].t );
+}
+
+void Preintegrated::SetNewBias( const Bias &bu_ ) {
+ std::unique_lock lock( mMutex );
+ bu = bu_;
+
+ db( 0 ) = bu_.bwx - b.bwx;
+ db( 1 ) = bu_.bwy - b.bwy;
+ db( 2 ) = bu_.bwz - b.bwz;
+ db( 3 ) = bu_.bax - b.bax;
+ db( 4 ) = bu_.bay - b.bay;
+ db( 5 ) = bu_.baz - b.baz;
+}
+
+IMU::Bias Preintegrated::GetDeltaBias( const Bias &b_ ) {
+ std::unique_lock lock( mMutex );
+ return IMU::Bias( b_.bax - b.bax, b_.bay - b.bay, b_.baz - b.baz, b_.bwx - b.bwx, b_.bwy - b.bwy,
+ b_.bwz - b.bwz );
+}
+
+Eigen::Matrix3f Preintegrated::GetDeltaRotation( const Bias &b_ ) {
+ std::unique_lock lock( mMutex );
+ Eigen::Vector3f dbg;
+ dbg << b_.bwx - b.bwx, b_.bwy - b.bwy, b_.bwz - b.bwz;
+ return NormalizeRotation( dR * Sophus::SO3f::exp( JRg * dbg ).matrix() );
+}
+
+Eigen::Vector3f Preintegrated::GetDeltaVelocity( const Bias &b_ ) {
+ std::unique_lock lock( mMutex );
+ Eigen::Vector3f dbg, dba;
+ dbg << b_.bwx - b.bwx, b_.bwy - b.bwy, b_.bwz - b.bwz;
+ dba << b_.bax - b.bax, b_.bay - b.bay, b_.baz - b.baz;
+ return dV + JVg * dbg + JVa * dba;
+}
+
+Eigen::Vector3f Preintegrated::GetDeltaPosition( const Bias &b_ ) {
+ std::unique_lock lock( mMutex );
+ Eigen::Vector3f dbg, dba;
+ dbg << b_.bwx - b.bwx, b_.bwy - b.bwy, b_.bwz - b.bwz;
+ dba << b_.bax - b.bax, b_.bay - b.bay, b_.baz - b.baz;
+ return dP + JPg * dbg + JPa * dba;
+}
+
+Eigen::Matrix3f Preintegrated::GetUpdatedDeltaRotation() {
+ std::unique_lock lock( mMutex );
+ return NormalizeRotation( dR * Sophus::SO3f::exp( JRg * db.head( 3 ) ).matrix() );
+}
+
+Eigen::Vector3f Preintegrated::GetUpdatedDeltaVelocity() {
+ std::unique_lock lock( mMutex );
+ return dV + JVg * db.head( 3 ) + JVa * db.tail( 3 );
+}
+
+Eigen::Vector3f Preintegrated::GetUpdatedDeltaPosition() {
+ std::unique_lock lock( mMutex );
+ return dP + JPg * db.head( 3 ) + JPa * db.tail( 3 );
+}
+
+Eigen::Matrix3f Preintegrated::GetOriginalDeltaRotation() {
+ std::unique_lock lock( mMutex );
+ return dR;
+}
+
+Eigen::Vector3f Preintegrated::GetOriginalDeltaVelocity() {
+ std::unique_lock lock( mMutex );
+ return dV;
+}
+
+Eigen::Vector3f Preintegrated::GetOriginalDeltaPosition() {
+ std::unique_lock lock( mMutex );
+ return dP;
+}
+
+Bias Preintegrated::GetOriginalBias() {
+ std::unique_lock lock( mMutex );
+ return b;
+}
+
+Bias Preintegrated::GetUpdatedBias() {
+ std::unique_lock lock( mMutex );
+ return bu;
+}
+
+Eigen::Matrix Preintegrated::GetDeltaBias() {
+ std::unique_lock lock( mMutex );
+ return db;
+}
+
+void Bias::CopyFrom( Bias &b ) {
+ bax = b.bax;
+ bay = b.bay;
+ baz = b.baz;
+ bwx = b.bwx;
+ bwy = b.bwy;
+ bwz = b.bwz;
+}
+
+std::ostream &operator<<( std::ostream &out, const Bias &b ) {
+ if ( b.bwx > 0 ) out << " ";
+ out << b.bwx << ",";
+ if ( b.bwy > 0 ) out << " ";
+ out << b.bwy << ",";
+ if ( b.bwz > 0 ) out << " ";
+ out << b.bwz << ",";
+ if ( b.bax > 0 ) out << " ";
+ out << b.bax << ",";
+ if ( b.bay > 0 ) out << " ";
+ out << b.bay << ",";
+ if ( b.baz > 0 ) out << " ";
+ out << b.baz;
+
+ return out;
+}
+
+void Calib::Set( const Sophus::SE3 &sophTbc, const float &ng, const float &na,
+ const float &ngw, const float &naw ) {
+ mbIsSet = true;
+ const float ng2 = ng * ng;
+ const float na2 = na * na;
+ const float ngw2 = ngw * ngw;
+ const float naw2 = naw * naw;
+
+ // Sophus/Eigen
+ mTbc = sophTbc;
+ mTcb = mTbc.inverse();
+ Cov.diagonal() << ng2, ng2, ng2, na2, na2, na2;
+ CovWalk.diagonal() << ngw2, ngw2, ngw2, naw2, naw2, naw2;
+}
+
+Calib::Calib( const Calib &calib ) {
+ mbIsSet = calib.mbIsSet;
+ // Sophus/Eigen parameters
+ mTbc = calib.mTbc;
+ mTcb = calib.mTcb;
+ Cov = calib.Cov;
+ CovWalk = calib.CovWalk;
+}
+
+} // namespace IMU
+
+} // namespace backend
diff --git a/backend/sensor_fusion/imu/imu_types.h b/backend/sensor_fusion/imu/imu_types.h
new file mode 100644
index 0000000..5d08e61
--- /dev/null
+++ b/backend/sensor_fusion/imu/imu_types.h
@@ -0,0 +1,268 @@
+/**
+ * This file is part of ORB-SLAM3
+ *
+ * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel
+ * and Juan D. Tardós, University of Zaragoza. Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M.
+ * Montiel and Juan D. Tardós, University of Zaragoza.
+ *
+ * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
+ * If not, see .
+ */
+
+#ifndef IMUTYPES_H
+#define IMUTYPES_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "backend/sensor_fusion/imu/serialization_utils.h"
+
+namespace backend {
+
+namespace IMU {
+
+// TODO
+const float GRAVITY_VALUE = 9.81;
+
+// IMU measurement (gyro, accelerometer and timestamp)
+class Point
+{
+public:
+ Point( const float &acc_x, const float &acc_y, const float &acc_z, const float &ang_vel_x,
+ const float &ang_vel_y, const float &ang_vel_z, const double ×tamp )
+ : a( acc_x, acc_y, acc_z ), w( ang_vel_x, ang_vel_y, ang_vel_z ), t( timestamp ) {}
+ Point( const cv::Point3f Acc, const cv::Point3f Gyro, const double ×tamp )
+ : a( Acc.x, Acc.y, Acc.z ), w( Gyro.x, Gyro.y, Gyro.z ), t( timestamp ) {}
+
+public:
+ Eigen::Vector3f a;
+ Eigen::Vector3f w;
+ double t;
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// IMU biases (gyro and accelerometer)
+class Bias
+{
+ friend class boost::serialization::access;
+ template
+ void serialize( Archive &ar, const unsigned int version ) {
+ ar & bax;
+ ar & bay;
+ ar & baz;
+
+ ar & bwx;
+ ar & bwy;
+ ar & bwz;
+ }
+
+public:
+ Bias() : bax( 0 ), bay( 0 ), baz( 0 ), bwx( 0 ), bwy( 0 ), bwz( 0 ) {}
+ Bias( const float &b_acc_x, const float &b_acc_y, const float &b_acc_z, const float &b_ang_vel_x,
+ const float &b_ang_vel_y, const float &b_ang_vel_z )
+ : bax( b_acc_x ),
+ bay( b_acc_y ),
+ baz( b_acc_z ),
+ bwx( b_ang_vel_x ),
+ bwy( b_ang_vel_y ),
+ bwz( b_ang_vel_z ) {}
+ void CopyFrom( Bias &b );
+ friend std::ostream &operator<<( std::ostream &out, const Bias &b );
+
+public:
+ float bax, bay, baz;
+ float bwx, bwy, bwz;
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// IMU calibration (Tbc, Tcb, noise)
+class Calib
+{
+ friend class boost::serialization::access;
+ template
+ void serialize( Archive &ar, const unsigned int version ) {
+ serializeSophusSE3( ar, mTcb, version );
+ serializeSophusSE3( ar, mTbc, version );
+
+ ar &boost::serialization::make_array( Cov.diagonal().data(), Cov.diagonal().size() );
+ ar &boost::serialization::make_array( CovWalk.diagonal().data(), CovWalk.diagonal().size() );
+
+ ar & mbIsSet;
+ }
+
+public:
+ Calib( const Sophus::SE3 &Tbc, const float &ng, const float &na, const float &ngw,
+ const float &naw ) {
+ Set( Tbc, ng, na, ngw, naw );
+ }
+
+ Calib( const Calib &calib );
+ Calib() { mbIsSet = false; }
+
+ // void Set(const cv::Mat &cvTbc, const float &ng, const float &na, const float &ngw, const float
+ // &naw);
+ void Set( const Sophus::SE3 &sophTbc, const float &ng, const float &na, const float &ngw,
+ const float &naw );
+
+public:
+ // Sophus/Eigen implementation
+ Sophus::SE3 mTcb;
+ Sophus::SE3 mTbc;
+ Eigen::DiagonalMatrix Cov, CovWalk;
+ bool mbIsSet;
+};
+
+// Integration of 1 gyro measurement
+class IntegratedRotation
+{
+public:
+ IntegratedRotation() {}
+ IntegratedRotation( const Eigen::Vector3f &angVel, const Bias &imuBias, const float &time );
+
+public:
+ float deltaT; // integration time
+ Eigen::Matrix3f deltaR;
+ Eigen::Matrix3f rightJ; // right jacobian
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+// Preintegration of Imu Measurements
+class Preintegrated
+{
+ friend class boost::serialization::access;
+ template
+ void serialize( Archive &ar, const unsigned int version ) {
+ ar & dT;
+ ar &boost::serialization::make_array( C.data(), C.size() );
+ ar &boost::serialization::make_array( Info.data(), Info.size() );
+ ar &boost::serialization::make_array( Nga.diagonal().data(), Nga.diagonal().size() );
+ ar &boost::serialization::make_array( NgaWalk.diagonal().data(), NgaWalk.diagonal().size() );
+ ar & b;
+ ar &boost::serialization::make_array( dR.data(), dR.size() );
+ ar &boost::serialization::make_array( dV.data(), dV.size() );
+ ar &boost::serialization::make_array( dP.data(), dP.size() );
+ ar &boost::serialization::make_array( JRg.data(), JRg.size() );
+ ar &boost::serialization::make_array( JVg.data(), JVg.size() );
+ ar &boost::serialization::make_array( JVa.data(), JVa.size() );
+ ar &boost::serialization::make_array( JPg.data(), JPg.size() );
+ ar &boost::serialization::make_array( JPa.data(), JPa.size() );
+ ar &boost::serialization::make_array( avgA.data(), avgA.size() );
+ ar &boost::serialization::make_array( avgW.data(), avgW.size() );
+
+ ar & bu;
+ ar &boost::serialization::make_array( db.data(), db.size() );
+ ar & mvMeasurements;
+ }
+
+public:
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+ Preintegrated( const Bias &b_, const Calib &calib );
+ Preintegrated( Preintegrated *pImuPre );
+ Preintegrated() {}
+ ~Preintegrated() {}
+ void CopyFrom( Preintegrated *pImuPre );
+ void Initialize( const Bias &b_ );
+ void IntegrateNewMeasurement( const Eigen::Vector3f &acceleration, const Eigen::Vector3f &angVel,
+ const float &dt );
+ void Reintegrate();
+ void MergePrevious( Preintegrated *pPrev );
+ void SetNewBias( const Bias &bu_ );
+ IMU::Bias GetDeltaBias( const Bias &b_ );
+
+ Eigen::Matrix3f GetDeltaRotation( const Bias &b_ );
+ Eigen::Vector3f GetDeltaVelocity( const Bias &b_ );
+ Eigen::Vector3f GetDeltaPosition( const Bias &b_ );
+
+ Eigen::Matrix3f GetUpdatedDeltaRotation();
+ Eigen::Vector3f GetUpdatedDeltaVelocity();
+ Eigen::Vector3f GetUpdatedDeltaPosition();
+
+ Eigen::Matrix3f GetOriginalDeltaRotation();
+ Eigen::Vector3f GetOriginalDeltaVelocity();
+ Eigen::Vector3f GetOriginalDeltaPosition();
+
+ Eigen::Matrix GetDeltaBias();
+
+ Bias GetOriginalBias();
+ Bias GetUpdatedBias();
+
+ void printMeasurements() const {
+ std::cout << "pint meas:\n";
+ for ( int i = 0; i < mvMeasurements.size(); i++ ) {
+ std::cout << "meas " << mvMeasurements[i].t << std::endl;
+ }
+ std::cout << "end pint meas:\n";
+ }
+
+public:
+ float dT;
+ Eigen::Matrix C;
+ Eigen::Matrix Info;
+ Eigen::DiagonalMatrix Nga, NgaWalk;
+
+ // Values for the original bias (when integration was computed)
+ Bias b;
+ Eigen::Matrix3f dR;
+ Eigen::Vector3f dV, dP;
+ Eigen::Matrix3f JRg, JVg, JVa, JPg, JPa;
+ Eigen::Vector3f avgA, avgW;
+
+private:
+ // Updated bias
+ Bias bu;
+ // Dif between original and updated bias
+ // This is used to compute the updated values of the preintegration
+ Eigen::Matrix db;
+
+ struct integrable
+ {
+ template
+ void serialize( Archive &ar, const unsigned int version ) {
+ ar &boost::serialization::make_array( a.data(), a.size() );
+ ar &boost::serialization::make_array( w.data(), w.size() );
+ ar & t;
+ }
+
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+ integrable() {}
+ integrable( const Eigen::Vector3f &a_, const Eigen::Vector3f &w_, const float &t_ )
+ : a( a_ ), w( w_ ), t( t_ ) {}
+ Eigen::Vector3f a, w;
+ float t;
+ };
+
+ std::vector mvMeasurements;
+
+ std::mutex mMutex;
+};
+
+// Lie Algebra Functions
+Eigen::Matrix3f RightJacobianSO3( const float &x, const float &y, const float &z );
+Eigen::Matrix3f RightJacobianSO3( const Eigen::Vector3f &v );
+
+Eigen::Matrix3f InverseRightJacobianSO3( const float &x, const float &y, const float &z );
+Eigen::Matrix3f InverseRightJacobianSO3( const Eigen::Vector3f &v );
+
+Eigen::Matrix3f NormalizeRotation( const Eigen::Matrix3f &R );
+
+} // namespace IMU
+
+} // namespace backend
+
+#endif // IMUTYPES_H
diff --git a/backend/sensor_fusion/imu/serialization_utils.h b/backend/sensor_fusion/imu/serialization_utils.h
new file mode 100644
index 0000000..ac30983
--- /dev/null
+++ b/backend/sensor_fusion/imu/serialization_utils.h
@@ -0,0 +1,134 @@
+/**
+ * This file is part of ORB-SLAM3
+ *
+ * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel
+ * and Juan D. Tardós, University of Zaragoza. Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M.
+ * Montiel and Juan D. Tardós, University of Zaragoza.
+ *
+ * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
+ * If not, see .
+ */
+
+#ifndef SERIALIZATION_UTILS_H
+#define SERIALIZATION_UTILS_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ORB_SLAM3 {
+
+template
+void serializeSophusSE3( Archive& ar, Sophus::SE3f& T, const unsigned int version ) {
+ Eigen::Vector4f quat;
+ Eigen::Vector3f transl;
+
+ if ( Archive::is_saving::value ) {
+ Eigen::Quaternionf q = T.unit_quaternion();
+ quat << q.w(), q.x(), q.y(), q.z();
+ transl = T.translation();
+ }
+
+ ar& boost::serialization::make_array( quat.data(), quat.size() );
+ ar& boost::serialization::make_array( transl.data(), transl.size() );
+
+ if ( Archive::is_loading::value ) {
+ Eigen::Quaternionf q( quat[0], quat[1], quat[2], quat[3] );
+ T = Sophus::SE3f( q, transl );
+ }
+}
+
+template
+void serializeMatrix( Archive& ar, cv::Mat& mat, const unsigned int version ) {
+ int cols, rows, type;
+ bool continuous;
+
+ if ( Archive::is_saving::value ) {
+ cols = mat.cols;
+ rows = mat.rows;
+ type = mat.type();
+ continuous = mat.isContinuous();
+ }
+
+ ar & cols & rows & type & continuous;
+
+ if ( Archive::is_loading::value ) mat.create( rows, cols, type );
+
+ if ( continuous ) {
+ const unsigned int data_size = rows * cols * mat.elemSize();
+ ar& boost::serialization::make_array( mat.ptr(), data_size );
+ } else {
+ const unsigned int row_size = cols * mat.elemSize();
+ for ( int i = 0; i < rows; i++ ) {
+ ar& boost::serialization::make_array( mat.ptr( i ), row_size );
+ }
+ }
+}
+
+template
+void serializeMatrix( Archive& ar, const cv::Mat& mat, const unsigned int version ) {
+ cv::Mat matAux = mat;
+
+ serializeMatrix( ar, matAux, version );
+
+ if ( Archive::is_loading::value ) {
+ cv::Mat* ptr;
+ ptr = (cv::Mat*)( &mat );
+ *ptr = matAux;
+ }
+}
+
+template
+void serializeVectorKeyPoints( Archive& ar, const std::vector& vKP,
+ const unsigned int version ) {
+ int NumEl;
+
+ if ( Archive::is_saving::value ) {
+ NumEl = vKP.size();
+ }
+
+ ar & NumEl;
+
+ std::vector vKPaux = vKP;
+ if ( Archive::is_loading::value ) vKPaux.reserve( NumEl );
+
+ for ( int i = 0; i < NumEl; ++i ) {
+ cv::KeyPoint KPi;
+
+ if ( Archive::is_loading::value ) KPi = cv::KeyPoint();
+
+ if ( Archive::is_saving::value ) KPi = vKPaux[i];
+
+ ar & KPi.angle;
+ ar & KPi.response;
+ ar & KPi.size;
+ ar & KPi.pt.x;
+ ar & KPi.pt.y;
+ ar & KPi.class_id;
+ ar & KPi.octave;
+
+ if ( Archive::is_loading::value ) vKPaux.push_back( KPi );
+ }
+
+ if ( Archive::is_loading::value ) {
+ std::vector* ptr;
+ ptr = (std::vector*)( &vKP );
+ *ptr = vKPaux;
+ }
+}
+
+} // namespace ORB_SLAM3
+
+#endif // SERIALIZATION_UTILS_H