#include namespace hlzn_slam { namespace pose_graph { template static Eigen::Matrix skewSymmetric(const Eigen::MatrixBase &q) { Eigen::Matrix ans; ans << typename Derived::Scalar(0), -q(2), q(1), q(2), typename Derived::Scalar(0), -q(0), -q(1), q(0), typename Derived::Scalar(0); return ans; } template static Eigen::Quaternion deltaQ(const Eigen::MatrixBase &theta) { typedef typename Derived::Scalar Scalar_t; Eigen::Quaternion dq; Eigen::Matrix half_theta = theta; half_theta /= static_cast(2.0); dq.w() = static_cast(1.0); dq.x() = 0; // half_theta.x(); dq.y() = 0; // half_theta.y(); dq.z() = half_theta.z(); return dq; } bool PoseLocalParameterization::Plus(const double *x, const double *delta, double *x_plus_delta) const { Eigen::Map _p(x); Eigen::Map _q(x + 3); Eigen::Map dp(delta); Eigen::Quaterniond dq = deltaQ(Eigen::Map(delta + 3)); Eigen::Map p(x_plus_delta); Eigen::Map q(x_plus_delta + 3); p = _p + dp; q = (_q * dq).normalized(); return true; } bool PoseLocalParameterization::ComputeJacobian(const double *x, double *jacobian) const { Eigen::Map> j(jacobian); j.topRows<6>().setIdentity(); j.bottomRows<1>().setZero(); return true; } PoseCostFunction::PoseCostFunction() { } bool PoseCostFunction::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const { Eigen::Vector3d T1(parameters[0][0], parameters[0][1], parameters[0][2]); Eigen::Quaterniond Q1(parameters[0][6], parameters[0][3], parameters[0][4], parameters[0][5]); Eigen::Vector3d T2(parameters[1][0], parameters[1][1], parameters[1][2]); Eigen::Quaterniond Q2(parameters[1][6], parameters[1][3], parameters[1][4], parameters[1][5]); Eigen::Vector3d T12(parameters[2][0], parameters[2][1], parameters[2][2]); Eigen::Quaterniond Q12(parameters[2][6], parameters[2][3], parameters[2][4], parameters[2][5]); Eigen::Map residual(residuals); Eigen::Matrix3d R1 = Q1.toRotationMatrix(); Eigen::Matrix3d R2 = Q2.toRotationMatrix(); Eigen::Matrix3d R12 = Q12.toRotationMatrix(); // residual = -R1 * R12 * R2.inverse() * T2 + R1 * T12 + T1; // LOG(INFO)<<"residual: \r\n"<> jacobian(jacobians[0]); // Eigen::Matrix jaco; // jaco.leftCols<3>().setIdentity(); // jaco.rightCols<3>() = R1 * skewSymmetric(R12 * R2.inverse() * T2) - R1 * skewSymmetric(T12); // jacobian.leftCols<6>() = jaco; // jacobian.rightCols<1>().setZero(); // } // // 对R2和T2求导 // if (jacobians[1]) { // Eigen::Map> jacobian(jacobians[1]); // Eigen::Matrix jaco; // jaco.leftCols<3>() = -R1 * R12 * R2.inverse(); // jaco.rightCols<3>() = -R1 * R12 * skewSymmetric(R2.inverse() * T2); // jacobian.leftCols<6>() = jaco; // jacobian.rightCols<1>().setZero(); // } // // 对R12和T12求导 // if (jacobians[2]) { // Eigen::Map> jacobian(jacobians[2]); // Eigen::Matrix jaco; // jaco.leftCols<3>() = R1; // jaco.rightCols<3>() = R1 * R12 * skewSymmetric(R2.inverse() * T2); // jacobian.leftCols<6>() = jaco; // jacobian.rightCols<1>().setZero(); // } // } Eigen::Vector3d p(1, 1, 1); residual = R2.inverse() * R1 * R12 * p + R2.inverse() * R1 * T12 + R2.inverse() * T1 - R2.inverse() * T2 - p; // LOG(INFO)<<"residual: \r\n"<> jacobian(jacobians[0]); Eigen::Matrix jaco; jaco.leftCols<3>() = R2.inverse(); jaco.rightCols<3>() = -R2.inverse() * R1 * skewSymmetric(R12 * p) - R2.inverse() * R1 * skewSymmetric(T12); // R1 * skewSymmetric(R12 * R2.inverse() * T2) - R1 * skewSymmetric(T12); jacobian.leftCols<6>() = jaco; jacobian.rightCols<1>().setZero(); } // 对R2和T2求导 if (jacobians[1]) { Eigen::Map> jacobian(jacobians[1]); Eigen::Matrix jaco; jaco.leftCols<3>() = -R2.inverse(); jaco.rightCols<3>() = skewSymmetric(R2.inverse() * R1 * R12 * p) + skewSymmetric(R2.inverse() * R1 * T12) + skewSymmetric(R2.inverse() * T1) - skewSymmetric(R2.inverse() * T2); jacobian.leftCols<6>() = jaco; jacobian.rightCols<1>().setZero(); } // 对R12和T12求导 if (jacobians[2]) { Eigen::Map> jacobian(jacobians[2]); Eigen::Matrix jaco; jaco.leftCols<3>() = R2.inverse() * R1; jaco.rightCols<3>() = -R2.inverse() * R1 * R12 * skewSymmetric(p); jacobian.leftCols<6>() = jaco; jacobian.rightCols<1>().setZero(); } } return true; } } }