/** * 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 "ImuTypes.h" #include "Converter.h" #include "GeometricTools.h" #include namespace ORB_SLAM3 { 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(ddT),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 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 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 ORB_SLAM2