ImuFactor.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #pragma once
  2. #include <ros/assert.h>
  3. #include <iostream>
  4. #include <eigen3/Eigen/Dense>
  5. #include "utils/math_tools.h"
  6. #include "factors/Preintegration.h"
  7. #include <ceres/ceres.h>
  8. class ImuFactor : public ceres::SizedCostFunction<15, 3, 4, 9, 3, 4, 9> {
  9. public:
  10. EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  11. ImuFactor() = delete;
  12. ImuFactor(Preintegration *pre_integration) : pre_integration_{pre_integration} {
  13. g_vec_ = pre_integration_->g_vec_;
  14. }
  15. virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const {
  16. Eigen::Vector3d Pi(parameters[0][0], parameters[0][1], parameters[0][2]);
  17. Eigen::Quaterniond Qi(parameters[1][0], parameters[1][1], parameters[1][2], parameters[1][3]);
  18. Qi.normalize();
  19. Eigen::Vector3d Vi(parameters[2][0], parameters[2][1], parameters[2][2]);
  20. Eigen::Vector3d Bai(parameters[2][3], parameters[2][4], parameters[2][5]);
  21. Eigen::Vector3d Bgi(parameters[2][6], parameters[2][7], parameters[2][8]);
  22. Eigen::Vector3d Pj(parameters[3][0], parameters[3][1], parameters[3][2]);
  23. Eigen::Quaterniond Qj(parameters[4][0], parameters[4][1], parameters[4][2], parameters[4][3]);
  24. Qj.normalize();
  25. Eigen::Vector3d Vj(parameters[5][0], parameters[5][1], parameters[5][2]);
  26. Eigen::Vector3d Baj(parameters[5][3], parameters[5][4], parameters[5][5]);
  27. Eigen::Vector3d Bgj(parameters[5][6], parameters[5][7], parameters[5][8]);
  28. Eigen::Map<Eigen::Matrix<double, 15, 1>> residual(residuals);
  29. residual = pre_integration_->evaluate(Pi, Qi, Vi, Bai, Bgi,
  30. Pj, Qj, Vj, Baj, Bgj);
  31. Eigen::Matrix<double, 15, 15> sqrt_info = Eigen::LLT<Eigen::Matrix<double, 15, 15>>(pre_integration_->covariance_.inverse()).matrixL().transpose();
  32. residual = sqrt_info * residual;
  33. if(jacobians) {
  34. double sum_dt = pre_integration_->sum_dt_;
  35. Eigen::Matrix3d dp_dba = pre_integration_->jacobian_.template block<3, 3>(O_P, O_BA);
  36. Eigen::Matrix3d dp_dbg = pre_integration_->jacobian_.template block<3, 3>(O_P, O_BG);
  37. Eigen::Matrix3d dq_dbg = pre_integration_->jacobian_.template block<3, 3>(O_R, O_BG);
  38. Eigen::Matrix3d dv_dba = pre_integration_->jacobian_.template block<3, 3>(O_V, O_BA);
  39. Eigen::Matrix3d dv_dbg = pre_integration_->jacobian_.template block<3, 3>(O_V, O_BG);
  40. if (pre_integration_->jacobian_.maxCoeff() > 1e8 || pre_integration_->jacobian_.minCoeff() < -1e8)
  41. ROS_WARN("numerical unstable in preintegration");
  42. if (jacobians[0]) {
  43. Eigen::Map<Eigen::Matrix<double, 15, 3, Eigen::RowMajor>> jacobian_pose_i(jacobians[0]);
  44. jacobian_pose_i.setZero();
  45. jacobian_pose_i.block<3, 3>(O_P, O_P) = -Qi.inverse().toRotationMatrix();
  46. jacobian_pose_i = sqrt_info * jacobian_pose_i;
  47. if (jacobian_pose_i.maxCoeff() > 1e8 || jacobian_pose_i.minCoeff() < -1e8)
  48. ROS_WARN("numerical unstable in preintegration");
  49. }
  50. if (jacobians[1]) {
  51. Eigen::Map<Eigen::Matrix<double, 15, 4, Eigen::RowMajor>> jacobian_pose_qi(jacobians[1]);
  52. jacobian_pose_qi.setZero();
  53. Eigen::Vector3d tmp = -0.5 * g_vec_ * sum_dt * sum_dt + Pj - Pi - Vi * sum_dt;
  54. jacobian_pose_qi.block<3, 1>(O_P, 0) = 2 * (Qi.w() * tmp + skewSymmetric(Qi.vec()) * tmp);
  55. jacobian_pose_qi.block<3, 3>(O_P, 1) = 2 * (Qi.vec().dot(tmp) * Eigen::Matrix3d::Identity() + Qi.vec() * tmp.transpose() - tmp * Qi.vec().transpose() - Qi.w() * skewSymmetric(tmp));
  56. Eigen::Quaterniond corrected_delta_q = pre_integration_->delta_q_ * deltaQ(dq_dbg * (Bgi - pre_integration_->linearized_bg_));
  57. jacobian_pose_qi.block<3, 4>(O_R, 0) = -2 * (Qleft(Qj.inverse()) * Qright(corrected_delta_q)).bottomRightCorner<3, 4>();
  58. Eigen::Vector3d tmp1 = -g_vec_ * sum_dt + Vj - Vi;
  59. jacobian_pose_qi.block<3, 1>(O_V, 0) = 2 * (Qi.w() * tmp1 + skewSymmetric(Qi.vec()) * tmp1);
  60. jacobian_pose_qi.block<3, 3>(O_V, 1) = 2 * (Qi.vec().dot(tmp1) * Eigen::Matrix3d::Identity() + Qi.vec() * tmp1.transpose() - tmp1 * Qi.vec().transpose() - Qi.w() * skewSymmetric(tmp1));
  61. jacobian_pose_qi = sqrt_info * jacobian_pose_qi;
  62. }
  63. if (jacobians[2]) {
  64. Eigen::Map<Eigen::Matrix<double, 15, 9, Eigen::RowMajor>> jacobian_speedbias_i(jacobians[2]);
  65. jacobian_speedbias_i.setZero();
  66. jacobian_speedbias_i.block<3, 3>(O_P, O_V - O_V) = -Qi.inverse().toRotationMatrix() * sum_dt;
  67. jacobian_speedbias_i.block<3, 3>(O_P, O_BA - O_V) = -dp_dba;
  68. jacobian_speedbias_i.block<3, 3>(O_P, O_BG - O_V) = -dp_dbg;
  69. Eigen::Quaterniond corrected_delta_q = pre_integration_->delta_q_ * deltaQ(dq_dbg * (Bgi - pre_integration_->linearized_bg_));
  70. jacobian_speedbias_i.block<3, 3>(O_R, O_BG - O_V) = -LeftQuatMatrix(Qj.inverse() * Qi * corrected_delta_q).topLeftCorner<3, 3>() * dq_dbg;
  71. jacobian_speedbias_i.block<3, 3>(O_V, O_V - O_V) = -Qi.inverse().toRotationMatrix();
  72. jacobian_speedbias_i.block<3, 3>(O_V, O_BA - O_V) = -dv_dba;
  73. jacobian_speedbias_i.block<3, 3>(O_V, O_BG - O_V) = -dv_dbg;
  74. jacobian_speedbias_i.block<3, 3>(O_BA, O_BA - O_V) = -Eigen::Matrix3d::Identity();
  75. jacobian_speedbias_i.block<3, 3>(O_BG, O_BG - O_V) = -Eigen::Matrix3d::Identity();
  76. jacobian_speedbias_i = sqrt_info * jacobian_speedbias_i;
  77. }
  78. if (jacobians[3]) {
  79. Eigen::Map<Eigen::Matrix<double, 15, 3, Eigen::RowMajor>> jacobian_pose_j(jacobians[3]);
  80. jacobian_pose_j.setZero();
  81. jacobian_pose_j.block<3, 3>(O_P, O_P) = Qi.inverse().toRotationMatrix();
  82. jacobian_pose_j = sqrt_info * jacobian_pose_j;
  83. }
  84. if (jacobians[4]) {
  85. Eigen::Map<Eigen::Matrix<double, 15, 4, Eigen::RowMajor>> jacobian_pose_qj(jacobians[4]);
  86. jacobian_pose_qj.setZero();
  87. Eigen::Quaterniond corrected_delta_q =
  88. pre_integration_->delta_q_ * deltaQ(dq_dbg * (Bgi - pre_integration_->linearized_bg_));
  89. jacobian_pose_qj.block<3, 4>(O_R, 0) =
  90. 2 * Qleft(corrected_delta_q.inverse() * Qi.inverse()).bottomRightCorner<3, 4>();
  91. jacobian_pose_qj = sqrt_info * jacobian_pose_qj;
  92. }
  93. if (jacobians[5]) {
  94. Eigen::Map<Eigen::Matrix<double, 15, 9, Eigen::RowMajor>> jacobian_speedbias_j(jacobians[5]);
  95. jacobian_speedbias_j.setZero();
  96. jacobian_speedbias_j.block<3, 3>(O_V, O_V - O_V) = Qi.inverse().toRotationMatrix();
  97. jacobian_speedbias_j.block<3, 3>(O_BA, O_BA - O_V) = Eigen::Matrix3d::Identity();
  98. jacobian_speedbias_j.block<3, 3>(O_BG, O_BG - O_V) = Eigen::Matrix3d::Identity();
  99. jacobian_speedbias_j = sqrt_info * jacobian_speedbias_j;
  100. }
  101. }
  102. return true;
  103. }
  104. Preintegration *pre_integration_;
  105. Eigen::Vector3d g_vec_;
  106. };