| 72 | // where I is the information matrix which is the inverse of the covariance. |
| 73 | |
| 74 | struct Pose3d { |
| 75 | Eigen::Vector3d p; |
| 76 | Eigen::Quaterniond q; |
| 77 | |
| 78 | Pose3d() { |
| 79 | p << 0, 0, 0; |
| 80 | q = Eigen::Quaterniond::Identity(); |
| 81 | } |
| 82 | |
| 83 | Pose3d(Eigen::Vector3d& p, Eigen::Quaterniond& q) : p(p), q(q) {} |
| 84 | // The name of the data type in the g2o file format. |
| 85 | static std::string name() { return "VERTEX_SE3:QUAT"; } |
| 86 | |
| 87 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW |
| 88 | }; |
| 89 | |
| 90 | std::istream& operator>>(std::istream& input, Pose3d& pose) { |
| 91 | input >> pose.p.x() >> pose.p.y() >> pose.p.z() >> pose.q.x() >> pose.q.y() >> pose.q.z() >> pose.q.w(); |
| 92 | // Normalize the quaternion to account for precision loss due to |
| 93 | // serialization. |
| 94 | pose.q.normalize(); |
| 95 | return input; |
| 96 | } |
| 97 | |
| 98 | typedef std::map<int, Pose3d, std::less<int>, Eigen::aligned_allocator<std::pair<const int, Pose3d> > > MapOfPoses; |
| 99 | |
| 100 | class PoseGraph3dErrorTerm { |
| 101 | public: |
| 102 | PoseGraph3dErrorTerm(const Pose3d& t_ab_measured, const Eigen::Matrix<double, 6, 6>& sqrt_information) |
| 103 | : t_ab_measured_(t_ab_measured), sqrt_information_(sqrt_information) {} |
| 104 | |
| 105 | template <typename T> |
| 106 | bool operator()(const T* const p_a_ptr, |
| 107 | const T* const q_a_ptr, |
| 108 | const T* const p_b_ptr, |
| 109 | const T* const q_b_ptr, |
| 110 | T* residuals_ptr) const { |
| 111 | Eigen::Map<const Eigen::Matrix<T, 3, 1> > p_a(p_a_ptr); |
| 112 | Eigen::Map<const Eigen::Quaternion<T> > q_a(q_a_ptr); |
| 113 | |
| 114 | Eigen::Map<const Eigen::Matrix<T, 3, 1> > p_b(p_b_ptr); |
| 115 | Eigen::Map<const Eigen::Quaternion<T> > q_b(q_b_ptr); |
| 116 | |
| 117 | // Compute the relative transformation between the two frames. |
| 118 | Eigen::Quaternion<T> q_a_inverse = q_a.conjugate(); |
| 119 | Eigen::Quaternion<T> q_ab_estimated = q_a_inverse * q_b; |
| 120 | |
| 121 | // Represent the displacement between the two frames in the A frame. |
| 122 | Eigen::Matrix<T, 3, 1> p_ab_estimated = q_a_inverse * (p_b - p_a); |
| 123 | |
| 124 | // Compute the error between the two orientation estimates. |
| 125 | Eigen::Quaternion<T> delta_q = t_ab_measured_.q.template cast<T>() * q_ab_estimated.conjugate(); |
| 126 | |
| 127 | // Compute the residuals. |
| 128 | // [ position ] [ delta_p ] |
| 129 | // [ orientation (3x1)] = [ 2 * delta_q(0:2) ] |
| 130 | Eigen::Map<Eigen::Matrix<T, 6, 1> > residuals(residuals_ptr); |
| 131 | residuals.template block<3, 1>(0, 0) = p_ab_estimated - t_ab_measured_.p.template cast<T>(); |