Moved two very large methods from ImuFactorBase to PreintegrationBase
							parent
							
								
									8bfe4d75fb
								
							
						
					
					
						commit
						aa93475b3d
					
				|  | @ -209,7 +209,9 @@ Vector CombinedImuFactor::evaluateError(const Pose3& pose_i, const Vector3& vel_ | |||
|     Matrix H1_pvR, H2_pvR, H3_pvR, H4_pvR, H5_pvR, Hbias_i, Hbias_j; // pvR = mnemonic: position (p), velocity (v), rotation (R)
 | ||||
| 
 | ||||
|     // error wrt preintegrated measurements
 | ||||
|     Vector r_pvR(9); r_pvR << ImuFactorBase::computeErrorAndJacobians(_PIM_, pose_i, vel_i, pose_j, vel_j, bias_i, | ||||
|     Vector r_pvR(9); | ||||
|     r_pvR = _PIM_.computeErrorAndJacobians(pose_i, vel_i, pose_j, vel_j, bias_i, | ||||
|         gravity_, omegaCoriolis_, use2ndOrderCoriolis_, //
 | ||||
|         H1_pvR, H2_pvR, H3_pvR, H4_pvR, H5_pvR); | ||||
| 
 | ||||
|     // error wrt bias evolution model (random walk)
 | ||||
|  | @ -256,7 +258,9 @@ Vector CombinedImuFactor::evaluateError(const Pose3& pose_i, const Vector3& vel_ | |||
|   } | ||||
|   // else, only compute the error vector:
 | ||||
|   // error wrt preintegrated measurements
 | ||||
|   Vector r_pvR(9); r_pvR << ImuFactorBase::computeErrorAndJacobians(_PIM_, pose_i, vel_i, pose_j, vel_j, bias_i, | ||||
|   Vector r_pvR(9); | ||||
|   r_pvR = _PIM_.computeErrorAndJacobians(pose_i, vel_i, pose_j, vel_j, bias_i, | ||||
|       gravity_, omegaCoriolis_, use2ndOrderCoriolis_, //
 | ||||
|       boost::none, boost::none, boost::none, boost::none, boost::none); | ||||
|   // error wrt bias evolution model (random walk)
 | ||||
|   Vector6 fbias = bias_j.between(bias_i).vector(); // [bias_j.acc - bias_i.acc; bias_j.gyr - bias_i.gyr]
 | ||||
|  |  | |||
|  | @ -212,14 +212,6 @@ public: | |||
|       boost::optional<Matrix&> H5 = boost::none, | ||||
|       boost::optional<Matrix&> H6 = boost::none) const; | ||||
| 
 | ||||
|   /// predicted states from IMU
 | ||||
|   static PoseVelocityBias predict(const Pose3& pose_i, const Vector3& vel_i, | ||||
|       const imuBias::ConstantBias& bias_i, | ||||
|       const PreintegrationBase& preintegratedMeasurements, | ||||
|       const Vector3& gravity, const Vector3& omegaCoriolis, const bool use2ndOrderCoriolis = false){ | ||||
|     return ImuFactorBase::predict(pose_i, vel_i, bias_i, preintegratedMeasurements, gravity, omegaCoriolis, use2ndOrderCoriolis); | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|   /** Serialization function */ | ||||
|  |  | |||
|  | @ -148,7 +148,8 @@ ImuFactor::ImuFactor( | |||
|     const Vector3& gravity, const Vector3& omegaCoriolis, | ||||
|     boost::optional<const Pose3&> body_P_sensor, | ||||
|     const bool use2ndOrderCoriolis) : | ||||
|         Base(noiseModel::Gaussian::Covariance(preintegratedMeasurements.preintMeasCov_), pose_i, vel_i, pose_j, vel_j, bias), | ||||
|         Base(noiseModel::Gaussian::Covariance(preintegratedMeasurements.preintMeasCov_), | ||||
|             pose_i, vel_i, pose_j, vel_j, bias), | ||||
|         ImuFactorBase(gravity, omegaCoriolis, body_P_sensor, use2ndOrderCoriolis), | ||||
|         _PIM_(preintegratedMeasurements) {} | ||||
| 
 | ||||
|  | @ -180,13 +181,14 @@ bool ImuFactor::equals(const NonlinearFactor& expected, double tol) const { | |||
| } | ||||
| 
 | ||||
| //------------------------------------------------------------------------------
 | ||||
| Vector ImuFactor::evaluateError(const Pose3& pose_i, const Vector3& vel_i, const Pose3& pose_j, const Vector3& vel_j, | ||||
|     const imuBias::ConstantBias& bias_i, | ||||
|     boost::optional<Matrix&> H1,  boost::optional<Matrix&> H2, | ||||
|     boost::optional<Matrix&> H3,  boost::optional<Matrix&> H4, | ||||
|     boost::optional<Matrix&> H5) const{ | ||||
| Vector ImuFactor::evaluateError(const Pose3& pose_i, const Vector3& vel_i, | ||||
|     const Pose3& pose_j, const Vector3& vel_j, | ||||
|     const imuBias::ConstantBias& bias_i, boost::optional<Matrix&> H1, | ||||
|     boost::optional<Matrix&> H2, boost::optional<Matrix&> H3, | ||||
|     boost::optional<Matrix&> H4, boost::optional<Matrix&> H5) const { | ||||
| 
 | ||||
|   return ImuFactorBase::computeErrorAndJacobians(_PIM_, pose_i, vel_i, pose_j, vel_j, bias_i, H1, H2, H3, H4, H5); | ||||
|   return _PIM_.computeErrorAndJacobians(pose_i, vel_i, pose_j, vel_j, bias_i, | ||||
|       gravity_, omegaCoriolis_, use2ndOrderCoriolis_, H1, H2, H3, H4, H5); | ||||
| } | ||||
| 
 | ||||
| } /// namespace gtsam
 | ||||
|  |  | |||
|  | @ -197,13 +197,6 @@ public: | |||
|       boost::optional<Matrix&> H4 = boost::none, | ||||
|       boost::optional<Matrix&> H5 = boost::none) const; | ||||
| 
 | ||||
|   /// predicted states from IMU
 | ||||
|   static PoseVelocityBias predict(const Pose3& pose_i, const Vector3& vel_i, | ||||
|       const imuBias::ConstantBias& bias_i, const PreintegrationBase& preintegratedMeasurements, | ||||
|       const Vector3& gravity, const Vector3& omegaCoriolis, const bool use2ndOrderCoriolis = false){ | ||||
|     return ImuFactorBase::predict(pose_i, vel_i, bias_i, preintegratedMeasurements, gravity, omegaCoriolis, use2ndOrderCoriolis); | ||||
|   } | ||||
| 
 | ||||
|   private: | ||||
| 
 | ||||
|   /** Serialization function */ | ||||
|  |  | |||
|  | @ -27,20 +27,6 @@ | |||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
| /**
 | ||||
|  * Struct to hold all state variables of returned by Predict function | ||||
|  */ | ||||
| struct PoseVelocityBias { | ||||
|   Pose3 pose; | ||||
|   Vector3 velocity; | ||||
|   imuBias::ConstantBias bias; | ||||
| 
 | ||||
|   PoseVelocityBias(const Pose3& _pose, const Vector3& _velocity, | ||||
|       const imuBias::ConstantBias _bias) : | ||||
|         pose(_pose), velocity(_velocity), bias(_bias) { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| class ImuFactorBase { | ||||
| 
 | ||||
| protected: | ||||
|  | @ -93,184 +79,6 @@ public: | |||
|         (body_P_sensor_ && expected.body_P_sensor_ && body_P_sensor_->equals(*expected.body_P_sensor_))); | ||||
|   } | ||||
| 
 | ||||
|   /// Compute errors w.r.t. preintegrated measurements and jacobians wrt pose_i, vel_i, bias_i, pose_j, bias_j
 | ||||
|   //------------------------------------------------------------------------------
 | ||||
|   Vector computeErrorAndJacobians(const PreintegrationBase& _PIM, const Pose3& pose_i, const Vector3& vel_i, const Pose3& pose_j, const Vector3& vel_j, | ||||
|       const imuBias::ConstantBias& bias_i, boost::optional<Matrix&> H1,  boost::optional<Matrix&> H2, | ||||
|       boost::optional<Matrix&> H3,  boost::optional<Matrix&> H4, boost::optional<Matrix&> H5) const{ | ||||
| 
 | ||||
|     const double& deltaTij = _PIM.deltaTij(); | ||||
|     // We need the mistmatch w.r.t. the biases used for preintegration
 | ||||
|     const Vector3 biasAccIncr = bias_i.accelerometer() - _PIM.biasHat().accelerometer(); | ||||
|     const Vector3 biasOmegaIncr = bias_i.gyroscope() - _PIM.biasHat().gyroscope(); | ||||
| 
 | ||||
|     // we give some shorter name to rotations and translations
 | ||||
|     const Rot3& Rot_i = pose_i.rotation(); | ||||
|     const Rot3& Rot_j = pose_j.rotation(); | ||||
|     const Vector3& pos_j = pose_j.translation().vector(); | ||||
| 
 | ||||
|     // Jacobian computation
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     // Get Get so<3> version of bias corrected rotation
 | ||||
|     // If H5 is asked for, we will need the Jacobian, which we store in H5
 | ||||
|     // H5 will then be corrected below to take into account the Coriolis effect
 | ||||
|     Vector3 theta_biascorrected = | ||||
|         _PIM.biascorrectedThetaRij(biasOmegaIncr, H5); | ||||
| 
 | ||||
|     Vector3 theta_biascorrected_corioliscorrected = theta_biascorrected  - | ||||
|         Rot_i.inverse().matrix() * omegaCoriolis_ * deltaTij; // Coriolis term
 | ||||
| 
 | ||||
|     const Rot3 deltaRij_biascorrected_corioliscorrected = | ||||
|         Rot3::Expmap( theta_biascorrected_corioliscorrected ); | ||||
| 
 | ||||
|     // TODO: these are not always needed
 | ||||
|     const Rot3 fRhat = deltaRij_biascorrected_corioliscorrected.between(Rot_i.between(Rot_j)); | ||||
|     const Matrix3 Jr_theta_bcc = Rot3::rightJacobianExpMapSO3(theta_biascorrected_corioliscorrected); | ||||
|     const Matrix3 Jtheta = -Jr_theta_bcc  * skewSymmetric(Rot_i.inverse().matrix() * omegaCoriolis_ * deltaTij); | ||||
|     const Matrix3 Jrinv_fRhat = Rot3::rightJacobianExpMapSO3inverse(Rot3::Logmap(fRhat)); | ||||
| 
 | ||||
|     if(H1) { | ||||
|       H1->resize(9,6); | ||||
| 
 | ||||
|       Matrix3 dfPdPi; | ||||
|       Matrix3 dfVdPi; | ||||
|       if(use2ndOrderCoriolis_){ | ||||
|         dfPdPi = - Rot_i.matrix() + 0.5 * skewSymmetric(omegaCoriolis_) * skewSymmetric(omegaCoriolis_) * Rot_i.matrix() * deltaTij*deltaTij; | ||||
|         dfVdPi = skewSymmetric(omegaCoriolis_) * skewSymmetric(omegaCoriolis_) * Rot_i.matrix() * deltaTij; | ||||
|       } | ||||
|       else{ | ||||
|         dfPdPi = - Rot_i.matrix(); | ||||
|         dfVdPi = Z_3x3; | ||||
|       } | ||||
|       (*H1) << | ||||
|           // dfP/dRi
 | ||||
|           Rot_i.matrix() * skewSymmetric(_PIM.deltaPij() | ||||
|           + _PIM.delPdelBiasOmega() * biasOmegaIncr + _PIM.delPdelBiasAcc() * biasAccIncr), | ||||
|           // dfP/dPi
 | ||||
|           dfPdPi, | ||||
|           // dfV/dRi
 | ||||
|           Rot_i.matrix() * skewSymmetric(_PIM.deltaVij() | ||||
|           + _PIM.delVdelBiasOmega() * biasOmegaIncr + _PIM.delVdelBiasAcc() * biasAccIncr), | ||||
|           // dfV/dPi
 | ||||
|           dfVdPi, | ||||
|           // dfR/dRi
 | ||||
|           Jrinv_fRhat *  (- Rot_j.between(Rot_i).matrix() - fRhat.inverse().matrix() * Jtheta), | ||||
|           // dfR/dPi
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H2) { | ||||
|       H2->resize(9,3); | ||||
|       (*H2) << | ||||
|           // dfP/dVi
 | ||||
|           - I_3x3 * deltaTij | ||||
|           + skewSymmetric(omegaCoriolis_) * deltaTij * deltaTij,  // Coriolis term - we got rid of the 2 wrt ins paper
 | ||||
|           // dfV/dVi
 | ||||
|           - I_3x3 | ||||
|           + 2 * skewSymmetric(omegaCoriolis_) * deltaTij, // Coriolis term
 | ||||
|           // dfR/dVi
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H3) { | ||||
|       H3->resize(9,6); | ||||
|       (*H3) << | ||||
|           // dfP/dPosej
 | ||||
|           Z_3x3, Rot_j.matrix(), | ||||
|           // dfV/dPosej
 | ||||
|           Matrix::Zero(3,6), | ||||
|           // dfR/dPosej
 | ||||
|           Jrinv_fRhat *  ( I_3x3 ), Z_3x3; | ||||
|     } | ||||
|     if(H4) { | ||||
|       H4->resize(9,3); | ||||
|       (*H4) << | ||||
|           // dfP/dVj
 | ||||
|           Z_3x3, | ||||
|           // dfV/dVj
 | ||||
|           I_3x3, | ||||
|           // dfR/dVj
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H5) { | ||||
|       // H5 by this point already contains 3*3 biascorrectedThetaRij derivative
 | ||||
|       const Matrix3 JbiasOmega = Jr_theta_bcc * (*H5); | ||||
|       H5->resize(9,6); | ||||
|       (*H5) << | ||||
|           // dfP/dBias
 | ||||
|           - Rot_i.matrix() * _PIM.delPdelBiasAcc(), | ||||
|           - Rot_i.matrix() * _PIM.delPdelBiasOmega(), | ||||
|           // dfV/dBias
 | ||||
|           - Rot_i.matrix() * _PIM.delVdelBiasAcc(), | ||||
|           - Rot_i.matrix() * _PIM.delVdelBiasOmega(), | ||||
|           // dfR/dBias
 | ||||
|           Matrix::Zero(3,3), | ||||
|           Jrinv_fRhat * ( - fRhat.inverse().matrix() * JbiasOmega); | ||||
|     } | ||||
| 
 | ||||
|     // Evaluate residual error, according to [3]
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     PoseVelocityBias predictedState_j = ImuFactorBase::predict(pose_i, vel_i, bias_i, _PIM, | ||||
|         gravity_, omegaCoriolis_, use2ndOrderCoriolis_); | ||||
| 
 | ||||
|     const Vector3 fp = pos_j - predictedState_j.pose.translation().vector(); | ||||
| 
 | ||||
|     const Vector3 fv = vel_j - predictedState_j.velocity; | ||||
| 
 | ||||
|     // This is the same as: dR = (predictedState_j.pose.translation()).between(Rot_j)
 | ||||
|     const Vector3 fR = Rot3::Logmap(fRhat); | ||||
| 
 | ||||
|     Vector r(9); r << fp, fv, fR; | ||||
|     return r; | ||||
|   } | ||||
| 
 | ||||
|   /// Predict state at time j
 | ||||
|   //------------------------------------------------------------------------------
 | ||||
|   static PoseVelocityBias predict(const Pose3& pose_i, const Vector3& vel_i, | ||||
|       const imuBias::ConstantBias& bias_i, | ||||
|       const PreintegrationBase& _PIM, | ||||
|       const Vector3& gravity, const Vector3& omegaCoriolis, const bool use2ndOrderCoriolis){ | ||||
| 
 | ||||
|     const double& deltaTij = _PIM.deltaTij(); | ||||
|     const Vector3 biasAccIncr = bias_i.accelerometer() - _PIM.biasHat().accelerometer(); | ||||
|     const Vector3 biasOmegaIncr = bias_i.gyroscope() - _PIM.biasHat().gyroscope(); | ||||
| 
 | ||||
|     const Rot3& Rot_i = pose_i.rotation(); | ||||
|     const Vector3& pos_i = pose_i.translation().vector(); | ||||
| 
 | ||||
|     // Predict state at time j
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     Vector3 pos_j =  pos_i + Rot_i.matrix() * (_PIM.deltaPij() | ||||
|         + _PIM.delPdelBiasAcc() * biasAccIncr | ||||
|         + _PIM.delPdelBiasOmega() * biasOmegaIncr) | ||||
|         + vel_i * deltaTij | ||||
|         - skewSymmetric(omegaCoriolis) * vel_i * deltaTij*deltaTij  // Coriolis term - we got rid of the 2 wrt ins paper
 | ||||
|         + 0.5 * gravity * deltaTij*deltaTij; | ||||
| 
 | ||||
|     Vector3 vel_j = Vector3(vel_i + Rot_i.matrix() * (_PIM.deltaVij() | ||||
|         + _PIM.delVdelBiasAcc() * biasAccIncr | ||||
|         + _PIM.delVdelBiasOmega() * biasOmegaIncr) | ||||
|         - 2 * skewSymmetric(omegaCoriolis) * vel_i * deltaTij  // Coriolis term
 | ||||
|         + gravity * deltaTij); | ||||
| 
 | ||||
|     if(use2ndOrderCoriolis){ | ||||
|       pos_j += - 0.5 * skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * pos_i * deltaTij*deltaTij;  // 2nd order coriolis term for position
 | ||||
|       vel_j += - skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * pos_i * deltaTij; // 2nd order term for velocity
 | ||||
|     } | ||||
| 
 | ||||
|     const Rot3 deltaRij_biascorrected = _PIM.biascorrectedDeltaRij(biasOmegaIncr); | ||||
|     // TODO Frank says comment below does not reflect what was in code
 | ||||
|     // deltaRij_biascorrected is expmap(deltaRij) * expmap(delRdelBiasOmega * biasOmegaIncr)
 | ||||
| 
 | ||||
|     Vector3 theta_biascorrected = Rot3::Logmap(deltaRij_biascorrected); | ||||
|     Vector3 theta_biascorrected_corioliscorrected = theta_biascorrected  - | ||||
|         Rot_i.inverse().matrix() * omegaCoriolis * deltaTij; // Coriolis term
 | ||||
|     const Rot3 deltaRij_biascorrected_corioliscorrected = | ||||
|         Rot3::Expmap( theta_biascorrected_corioliscorrected ); | ||||
|     const Rot3 Rot_j = Rot_i.compose( deltaRij_biascorrected_corioliscorrected  ); | ||||
| 
 | ||||
|     Pose3 pose_j = Pose3( Rot_j, Point3(pos_j) ); | ||||
|     return PoseVelocityBias(pose_j, vel_j, bias_i); // bias is predicted as a constant
 | ||||
|   } | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } /// namespace gtsam
 | ||||
|  |  | |||
|  | @ -26,6 +26,20 @@ | |||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
| /**
 | ||||
|  * Struct to hold all state variables of returned by Predict function | ||||
|  */ | ||||
| struct PoseVelocityBias { | ||||
|   Pose3 pose; | ||||
|   Vector3 velocity; | ||||
|   imuBias::ConstantBias bias; | ||||
| 
 | ||||
|   PoseVelocityBias(const Pose3& _pose, const Vector3& _velocity, | ||||
|       const imuBias::ConstantBias _bias) : | ||||
|         pose(_pose), velocity(_velocity), bias(_bias) { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * PreintegrationBase is the base class for PreintegratedMeasurements | ||||
|  * (in ImuFactor) and CombinedPreintegratedMeasurements (in CombinedImuFactor). | ||||
|  | @ -150,6 +164,185 @@ public: | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Predict state at time j
 | ||||
|   //------------------------------------------------------------------------------
 | ||||
|   PoseVelocityBias predict(const Pose3& pose_i, const Vector3& vel_i, | ||||
|       const imuBias::ConstantBias& bias_i, const Vector3& gravity, | ||||
|       const Vector3& omegaCoriolis, const bool use2ndOrderCoriolis = false) const { | ||||
| 
 | ||||
|     const Vector3 biasAccIncr = bias_i.accelerometer() - biasHat().accelerometer(); | ||||
|     const Vector3 biasOmegaIncr = bias_i.gyroscope() - biasHat().gyroscope(); | ||||
| 
 | ||||
|     const Rot3& Rot_i = pose_i.rotation(); | ||||
|     const Vector3& pos_i = pose_i.translation().vector(); | ||||
| 
 | ||||
|     // Predict state at time j
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     Vector3 pos_j =  pos_i + Rot_i.matrix() * (deltaPij() | ||||
|         + delPdelBiasAcc() * biasAccIncr | ||||
|         + delPdelBiasOmega() * biasOmegaIncr) | ||||
|         + vel_i * deltaTij() | ||||
|         - skewSymmetric(omegaCoriolis) * vel_i * deltaTij()*deltaTij()  // Coriolis term - we got rid of the 2 wrt ins paper
 | ||||
|         + 0.5 * gravity * deltaTij()*deltaTij(); | ||||
| 
 | ||||
|     Vector3 vel_j = Vector3(vel_i + Rot_i.matrix() * (deltaVij() | ||||
|         + delVdelBiasAcc() * biasAccIncr | ||||
|         + delVdelBiasOmega() * biasOmegaIncr) | ||||
|         - 2 * skewSymmetric(omegaCoriolis) * vel_i * deltaTij()  // Coriolis term
 | ||||
|         + gravity * deltaTij()); | ||||
| 
 | ||||
|     if(use2ndOrderCoriolis){ | ||||
|       pos_j += - 0.5 * skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * pos_i * deltaTij()*deltaTij();  // 2nd order coriolis term for position
 | ||||
|       vel_j += - skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * pos_i * deltaTij(); // 2nd order term for velocity
 | ||||
|     } | ||||
| 
 | ||||
|     const Rot3 deltaRij_biascorrected = biascorrectedDeltaRij(biasOmegaIncr); | ||||
|     // TODO Frank says comment below does not reflect what was in code
 | ||||
|     // deltaRij_biascorrected is expmap(deltaRij) * expmap(delRdelBiasOmega * biasOmegaIncr)
 | ||||
| 
 | ||||
|     Vector3 theta_biascorrected = Rot3::Logmap(deltaRij_biascorrected); | ||||
|     Vector3 theta_biascorrected_corioliscorrected = theta_biascorrected  - | ||||
|         Rot_i.inverse().matrix() * omegaCoriolis * deltaTij(); // Coriolis term
 | ||||
|     const Rot3 deltaRij_biascorrected_corioliscorrected = | ||||
|         Rot3::Expmap( theta_biascorrected_corioliscorrected ); | ||||
|     const Rot3 Rot_j = Rot_i.compose( deltaRij_biascorrected_corioliscorrected  ); | ||||
| 
 | ||||
|     Pose3 pose_j = Pose3( Rot_j, Point3(pos_j) ); | ||||
|     return PoseVelocityBias(pose_j, vel_j, bias_i); // bias is predicted as a constant
 | ||||
|   } | ||||
| 
 | ||||
|   /// Compute errors w.r.t. preintegrated measurements and jacobians wrt pose_i, vel_i, bias_i, pose_j, bias_j
 | ||||
|   //------------------------------------------------------------------------------
 | ||||
|   Vector computeErrorAndJacobians(const Pose3& pose_i, const Vector3& vel_i, | ||||
|       const Pose3& pose_j, const Vector3& vel_j, | ||||
|       const imuBias::ConstantBias& bias_i, const Vector3& gravity, | ||||
|       const Vector3& omegaCoriolis, const bool use2ndOrderCoriolis, | ||||
|       boost::optional<Matrix&> H1, boost::optional<Matrix&> H2, | ||||
|       boost::optional<Matrix&> H3, boost::optional<Matrix&> H4, | ||||
|       boost::optional<Matrix&> H5) const { | ||||
| 
 | ||||
|     // We need the mistmatch w.r.t. the biases used for preintegration
 | ||||
|     const Vector3 biasAccIncr = bias_i.accelerometer() - biasHat().accelerometer(); | ||||
|     const Vector3 biasOmegaIncr = bias_i.gyroscope() - biasHat().gyroscope(); | ||||
| 
 | ||||
|     // we give some shorter name to rotations and translations
 | ||||
|     const Rot3& Rot_i = pose_i.rotation(); | ||||
|     const Rot3& Rot_j = pose_j.rotation(); | ||||
|     const Vector3& pos_j = pose_j.translation().vector(); | ||||
| 
 | ||||
|     // Jacobian computation
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     // Get Get so<3> version of bias corrected rotation
 | ||||
|     // If H5 is asked for, we will need the Jacobian, which we store in H5
 | ||||
|     // H5 will then be corrected below to take into account the Coriolis effect
 | ||||
|     Vector3 theta_biascorrected = | ||||
|         biascorrectedThetaRij(biasOmegaIncr, H5); | ||||
| 
 | ||||
|     Vector3 theta_biascorrected_corioliscorrected = theta_biascorrected  - | ||||
|         Rot_i.inverse().matrix() * omegaCoriolis * deltaTij(); // Coriolis term
 | ||||
| 
 | ||||
|     const Rot3 deltaRij_biascorrected_corioliscorrected = | ||||
|         Rot3::Expmap( theta_biascorrected_corioliscorrected ); | ||||
| 
 | ||||
|     // TODO: these are not always needed
 | ||||
|     const Rot3 fRhat = deltaRij_biascorrected_corioliscorrected.between(Rot_i.between(Rot_j)); | ||||
|     const Matrix3 Jr_theta_bcc = Rot3::rightJacobianExpMapSO3(theta_biascorrected_corioliscorrected); | ||||
|     const Matrix3 Jtheta = -Jr_theta_bcc  * skewSymmetric(Rot_i.inverse().matrix() * omegaCoriolis * deltaTij()); | ||||
|     const Matrix3 Jrinv_fRhat = Rot3::rightJacobianExpMapSO3inverse(Rot3::Logmap(fRhat)); | ||||
| 
 | ||||
|     if(H1) { | ||||
|       H1->resize(9,6); | ||||
| 
 | ||||
|       Matrix3 dfPdPi; | ||||
|       Matrix3 dfVdPi; | ||||
|       if(use2ndOrderCoriolis){ | ||||
|         dfPdPi = - Rot_i.matrix() + 0.5 * skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * Rot_i.matrix() * deltaTij()*deltaTij(); | ||||
|         dfVdPi = skewSymmetric(omegaCoriolis) * skewSymmetric(omegaCoriolis) * Rot_i.matrix() * deltaTij(); | ||||
|       } | ||||
|       else{ | ||||
|         dfPdPi = - Rot_i.matrix(); | ||||
|         dfVdPi = Z_3x3; | ||||
|       } | ||||
|       (*H1) << | ||||
|           // dfP/dRi
 | ||||
|           Rot_i.matrix() * skewSymmetric(deltaPij() | ||||
|           + delPdelBiasOmega() * biasOmegaIncr + delPdelBiasAcc() * biasAccIncr), | ||||
|           // dfP/dPi
 | ||||
|           dfPdPi, | ||||
|           // dfV/dRi
 | ||||
|           Rot_i.matrix() * skewSymmetric(deltaVij() | ||||
|           + delVdelBiasOmega() * biasOmegaIncr + delVdelBiasAcc() * biasAccIncr), | ||||
|           // dfV/dPi
 | ||||
|           dfVdPi, | ||||
|           // dfR/dRi
 | ||||
|           Jrinv_fRhat *  (- Rot_j.between(Rot_i).matrix() - fRhat.inverse().matrix() * Jtheta), | ||||
|           // dfR/dPi
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H2) { | ||||
|       H2->resize(9,3); | ||||
|       (*H2) << | ||||
|           // dfP/dVi
 | ||||
|           - I_3x3 * deltaTij() | ||||
|           + skewSymmetric(omegaCoriolis) * deltaTij() * deltaTij(),  // Coriolis term - we got rid of the 2 wrt ins paper
 | ||||
|           // dfV/dVi
 | ||||
|           - I_3x3 | ||||
|           + 2 * skewSymmetric(omegaCoriolis) * deltaTij(), // Coriolis term
 | ||||
|           // dfR/dVi
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H3) { | ||||
|       H3->resize(9,6); | ||||
|       (*H3) << | ||||
|           // dfP/dPosej
 | ||||
|           Z_3x3, Rot_j.matrix(), | ||||
|           // dfV/dPosej
 | ||||
|           Matrix::Zero(3,6), | ||||
|           // dfR/dPosej
 | ||||
|           Jrinv_fRhat *  ( I_3x3 ), Z_3x3; | ||||
|     } | ||||
|     if(H4) { | ||||
|       H4->resize(9,3); | ||||
|       (*H4) << | ||||
|           // dfP/dVj
 | ||||
|           Z_3x3, | ||||
|           // dfV/dVj
 | ||||
|           I_3x3, | ||||
|           // dfR/dVj
 | ||||
|           Z_3x3; | ||||
|     } | ||||
|     if(H5) { | ||||
|       // H5 by this point already contains 3*3 biascorrectedThetaRij derivative
 | ||||
|       const Matrix3 JbiasOmega = Jr_theta_bcc * (*H5); | ||||
|       H5->resize(9,6); | ||||
|       (*H5) << | ||||
|           // dfP/dBias
 | ||||
|           - Rot_i.matrix() * delPdelBiasAcc(), | ||||
|           - Rot_i.matrix() * delPdelBiasOmega(), | ||||
|           // dfV/dBias
 | ||||
|           - Rot_i.matrix() * delVdelBiasAcc(), | ||||
|           - Rot_i.matrix() * delVdelBiasOmega(), | ||||
|           // dfR/dBias
 | ||||
|           Matrix::Zero(3,3), | ||||
|           Jrinv_fRhat * ( - fRhat.inverse().matrix() * JbiasOmega); | ||||
|     } | ||||
| 
 | ||||
|     // Evaluate residual error, according to [3]
 | ||||
|     /* ---------------------------------------------------------------------------------------------------- */ | ||||
|     PoseVelocityBias predictedState_j = predict(pose_i, vel_i, bias_i, gravity, | ||||
|         omegaCoriolis, use2ndOrderCoriolis); | ||||
| 
 | ||||
|     const Vector3 fp = pos_j - predictedState_j.pose.translation().vector(); | ||||
| 
 | ||||
|     const Vector3 fv = vel_j - predictedState_j.velocity; | ||||
| 
 | ||||
|     // This is the same as: dR = (predictedState_j.pose.translation()).between(Rot_j)
 | ||||
|     const Vector3 fR = Rot3::Logmap(fRhat); | ||||
| 
 | ||||
|     Vector r(9); r << fp, fv, fR; | ||||
|     return r; | ||||
|   } | ||||
| 
 | ||||
|   /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
|   // This function is only used for test purposes (compare numerical derivatives wrt analytic ones)
 | ||||
|   static inline Vector PreIntegrateIMUObservations_delta_vel(const Vector& msr_gyro_t, const Vector& msr_acc_t, const double msr_dt, | ||||
|  |  | |||
|  | @ -290,7 +290,7 @@ TEST(CombinedImuFactor, PredictPositionAndVelocity){ | |||
|     // Predict
 | ||||
|     Pose3 x1; | ||||
|     Vector3 v1(0, 0.0, 0.0); | ||||
|     PoseVelocityBias poseVelocityBias = Combinedfactor.predict(x1, v1, bias, Combined_pre_int_data, gravity, omegaCoriolis); | ||||
|     PoseVelocityBias poseVelocityBias = Combined_pre_int_data.predict(x1, v1, bias, gravity, omegaCoriolis); | ||||
|     Pose3 expectedPose(Rot3(), Point3(0, 0.5, 0)); | ||||
|     Vector3 expectedVelocity; expectedVelocity<<0,1,0; | ||||
|     EXPECT(assert_equal(expectedPose, poseVelocityBias.pose)); | ||||
|  | @ -319,7 +319,7 @@ TEST(CombinedImuFactor, PredictRotation) { | |||
|   // Predict
 | ||||
|   Pose3 x(Rot3().ypr(0,0, 0), Point3(0,0,0)); | ||||
|   Vector3 v(0,0,0); | ||||
|   PoseVelocityBias poseVelocityBias = Combinedfactor.predict(x,v,bias, Combined_pre_int_data, gravity, omegaCoriolis); | ||||
|   PoseVelocityBias poseVelocityBias = Combined_pre_int_data.predict(x,v,bias, gravity, omegaCoriolis); | ||||
|   Pose3 expectedPose(Rot3().ypr(M_PI/10, 0,0), Point3(0,0,0)); | ||||
|   EXPECT(assert_equal(expectedPose, poseVelocityBias.pose, tol)); | ||||
| } | ||||
|  |  | |||
|  | @ -561,7 +561,7 @@ TEST(ImuFactor, PredictPositionAndVelocity){ | |||
|     // Predict
 | ||||
|     Pose3 x1; | ||||
|     Vector3 v1(0, 0.0, 0.0); | ||||
|     PoseVelocityBias poseVelocity = factor.predict(x1, v1, bias, pre_int_data, gravity, omegaCoriolis); | ||||
|     PoseVelocityBias poseVelocity = pre_int_data.predict(x1, v1, bias, gravity, omegaCoriolis); | ||||
|     Pose3 expectedPose(Rot3(), Point3(0, 0.5, 0)); | ||||
|     Vector3 expectedVelocity; expectedVelocity<<0,1,0; | ||||
|     EXPECT(assert_equal(expectedPose, poseVelocity.pose)); | ||||
|  | @ -593,7 +593,7 @@ TEST(ImuFactor, PredictRotation) { | |||
|     // Predict
 | ||||
|     Pose3 x1; | ||||
|     Vector3 v1(0, 0.0, 0.0); | ||||
|     PoseVelocityBias poseVelocity = factor.predict(x1, v1, bias, pre_int_data, gravity, omegaCoriolis); | ||||
|     PoseVelocityBias poseVelocity = pre_int_data.predict(x1, v1, bias, gravity, omegaCoriolis); | ||||
|     Pose3 expectedPose(Rot3().ypr(M_PI/10, 0, 0), Point3(0, 0, 0)); | ||||
|     Vector3 expectedVelocity; expectedVelocity<<0,0,0; | ||||
|     EXPECT(assert_equal(expectedPose, poseVelocity.pose)); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue