36 #define SQR(X) ( std::pow(X,2) ) 37 #define CUBE(X) ( std::pow(X,3) ) 39 using namespace Eigen;
45 std::vector<VelocityMeasurement, Eigen::aligned_allocator<VelocityMeasurement> > velMeasurements;
46 for (
size_t i = 0; i < measurements.size(); ++i) {
47 const SE2& odomMotion = measurements[i].odomMotion;
48 const double& timeInterval = measurements[i].timeInterval;
51 velMeasurements.push_back(velMeas);
56 Eigen::MatrixXd A(measurements.size(), 2);
57 Eigen::VectorXd x(measurements.size());
58 for (
size_t i = 0; i < measurements.size(); ++i) {
59 const SE2& laserMotion = measurements[i].laserMotion;
60 const double& timeInterval = measurements[i].timeInterval;
62 A(i, 0) = velMeas.
vl() * timeInterval;
63 A(i, 1) = velMeas.
vr() * timeInterval;
64 x(i) = laserMotion.
rotation().angle();
67 Eigen::Vector2d
linearSolution = (A.transpose() * A).inverse() * A.transpose() * x;
74 Eigen::Matrix<double, 5, 5> M;
76 for (
size_t i = 0; i < measurements.size(); ++i) {
77 const SE2& laserMotion = measurements[i].laserMotion;
78 const double& timeInterval = measurements[i].timeInterval;
80 Eigen::Matrix<double, 2, 5> L;
81 double omega_o_k = J_21 * velMeas.
vl() + J_22 * velMeas.
vr();
82 double o_theta_k = omega_o_k * timeInterval;
85 if (fabs(o_theta_k) > std::numeric_limits<double>::epsilon()) {
86 sx = sin(o_theta_k) / o_theta_k;
87 sy = (1 - cos(o_theta_k)) / o_theta_k;
89 double c_x = 0.5 * timeInterval * (-J_21 * velMeas.
vl() + J_22 * velMeas.
vr()) * sx;
90 double c_y = 0.5 * timeInterval * (-J_21 * velMeas.
vl() + J_22 * velMeas.
vr()) * sy;
92 L(0, 1) = 1 - cos(o_theta_k);
93 L(0, 2) = sin(o_theta_k);
97 L(1, 1) = - sin(o_theta_k);
98 L(1, 2) = 1 - cos(o_theta_k);
101 M.noalias() += L.transpose() * L;
116 double a = m11 *
SQR(m22) - m22 *
SQR(m13);
117 double b = 2*m11 *
SQR(m22) * m44 -
SQR(m22) *
SQR(m14) - 2*m22 *
SQR(m13) * m44 - 2*m11 * m22 *
SQR(m34)
118 - 2*m11 * m22 *
SQR(m35) -
SQR(m22) *
SQR(m15) + 2*m13 * m22 * m34 * m14 +
SQR(m13) *
SQR(m34)
119 + 2*m13 * m22 * m35 * m15 +
SQR(m13) *
SQR(m35);
120 double c = - 2*m13 *
CUBE(m35) * m15 - m22 *
SQR(m13) *
SQR(m44) + m11 *
SQR(m22) *
SQR(m44) +
SQR(m13) *
SQR(m35) * m44
121 + 2*m13 * m22 * m34 * m14 * m44 +
SQR(m13) *
SQR(m34) * m44 - 2*m11 * m22 *
SQR(m34) * m44 - 2 * m13 *
CUBE(m34) * m14
122 - 2*m11 * m22 *
SQR(m35) * m44 + 2*m11 *
SQR(m35) *
SQR(m34) + m22 *
SQR(m14) *
SQR(m35) - 2*m13 *
SQR(m35) * m34 * m14
123 - 2*m13 *
SQR(m34) * m35 * m15 + m11 * std::pow(m34, 4) + m22 *
SQR(m15) *
SQR(m34) + m22 *
SQR(m35) *
SQR(m15)
124 + m11 * std::pow(m35, 4) -
SQR(m22) *
SQR(m14) * m44 + 2*m13 * m22 * m35 * m15 * m44 + m22 *
SQR(m34) *
SQR(m14)
125 -
SQR(m22) *
SQR(m15) * m44;
128 double lambda1, lambda2;
129 if(a < std::numeric_limits<double>::epsilon()) {
130 if(b <= std::numeric_limits<double>::epsilon())
132 lambda1 = lambda2 = -c/b;
134 double delta = b*b - 4*a*c;
137 lambda1 = 0.5 * (-b-sqrt(delta)) / a;
138 lambda2 = 0.5 * (-b+sqrt(delta)) / a;
141 Eigen::VectorXd x1 = solveLagrange(M, lambda1);
142 Eigen::VectorXd x2 = solveLagrange(M, lambda2);
143 double err1 = x1.dot(M * x1);
144 double err2 = x2.dot(M * x2);
146 const Eigen::VectorXd& calibrationResult = err1 < err2 ? x1 : x2;
147 odomParams(0) = - calibrationResult(0) * J_21;
148 odomParams(1) = calibrationResult(0) * J_22;
149 odomParams(2) = calibrationResult(0);
151 laserOffset =
SE2(calibrationResult(1), calibrationResult(2), atan2(calibrationResult(4), calibrationResult(3)));
156 Eigen::VectorXd ClosedFormCalibration::solveLagrange(
const Eigen::Matrix<double,5,5>& M,
double lambda)
159 Eigen::Matrix<double,5,5> A;
161 A(3,3) = A(4,4) = lambda;
165 Eigen::JacobiSVD< Eigen::Matrix<double,5,5> > svd(A, ComputeFullV);
166 Eigen::VectorXd result = svd.matrixV().col(4);
176 double scale = sqrt(pow(result(3), 2) + pow(result(4), 2));
static Eigen::Vector2d linearSolution
const Eigen::Rotation2Dd & rotation() const
rotational component
velocity measurement of a differential robot
A 2D odometry measurement expressed as a transformation.
std::vector< MotionInformation, Eigen::aligned_allocator< MotionInformation > > MotionInformationVector
const Vector2D & translation() const
translational component