dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
gyro-calibration.cpp
Go to the documentation of this file.
1 
2 #include <old_calibrationn.h>
3 #include <Eigen/Cholesky>
4 #include <Eigen/SVD>
5 #include <Eigen/QR>
6 
7 /*
8  * Compute basic calibration parameters for a three axis gyroscope.
9  * The measurement equation is
10  * gyro_k = accelSensitivity * \tilde{accel}_k + bias + omega
11  *
12  * where, omega is the true angular rate (assumed to be zero)
13  * bias is the sensor bias
14  * accelSensitivity is the 3x3 matrix of sensitivity scale factors
15  * \tilde{accel}_k is the calibrated measurement of the accelerometer
16  * at time k
17  *
18  * After calibration, the optimized gyro measurement is given by
19  * \tilde{gyro}_k = gyro_k - bias - accelSensitivity * \tilde{accel}_k
20  */
21 void gyroscope_calibration(Vector3f &bias, Matrix3f &accelSensitivity, Vector3f gyroSamples[],
22  Vector3f accelSamples[], size_t n_samples)
23 {
24  // Assume the following measurement model:
25  // y = H*x
26  // where x is the vector of unknowns, and y is the measurement vector.
27  // the vector of unknowns is
28  // [a_x a_y a_z b_x]
29  // The measurement vector is
30  // [gyro_x]
31  // and the measurement matrix H is
32  // [accelSample_x accelSample_y accelSample_z 1]
33 
34  // Note that the individual solutions for x are given by
35  // (H^T \times H)^-1 \times H^T y
36  // Everything is identical except for y and x. So, transform it
37  // into block form X = (H^T \times H)^-1 \times H^T Y
38  // where each column of X contains the partial solution for each
39  // column of y.
40 
41  // Construct the matrix of accelerometer samples. Intermediate results
42  // are computed in "twice the precision that the source provides and the
43  // result deserves" by Kahan's thumbrule to prevent numerical problems.
44  Matrix<double, Dynamic, 4> H(n_samples, 4);
45  // And the matrix of gyro samples.
46  Matrix<double, Dynamic, 3> Y(n_samples, 3);
47  for (unsigned i = 0; i < n_samples; ++i) {
48  H.row(i) << accelSamples[i].transpose().cast<double>(), 1.0;
49  Y.row(i) << gyroSamples[i].transpose().cast<double>();
50  }
51 
52 #if 1
53  Matrix<double, 4, 3> result;
54  // Use the cholesky-based Penrose pseudoinverse method.
55  (H.transpose() * H).ldlt().solve(H.transpose() * Y, &result);
56 
57  // Transpose the result and return it to the caller. Cast back to float
58  // since there really isn't that much accuracy in the result.
59  bias = result.row(3).transpose().cast<float>();
60  accelSensitivity = result.block<3, 3>(0, 0).transpose().cast<float>();
61 #else
62  // TODO: Compare this result with a total-least-squares model.
63  size_t n = 4;
64  Matrix<double, Dynamic, 7> C;
65  C << H, Y;
66  SVD<Matrix<double, Dynamic, 7>> usv(C);
67  Matrix<double, 4, 3> V_ab = usv.matrixV().block<4, 3>(0, n);
68  Matrix<double, Dynamic, 3> V_bb = usv.matrixV().corner(BottomRight, n_samples - 4, 3);
69  // X = -V_ab/V_bb;
70  // X^T = (A * B^-1)^T
71  // X^T = (B^-1^T * A^T)
72  // X^T = (B^T^-1 * A^T)
73  // V_bb is orthgonal but not orthonormal. QR decomposition
74  // should be very fast in this case.
75  Matrix<double, 3, 4> result;
76  V_bb.transpose().qr().solve(-V_ab.transpose(), &result);
77 
78  // Results only deserve single precision.
79  bias = result.col(3).cast<float>();
80  accelSensitivity = result.block<3, 3>(0, 0).cast<float>();
81 
82 #endif
83 }
for i
Definition: OPPlots.m:140
void gyroscope_calibration(Vector3f &bias, Matrix3f &accelSensitivity, Vector3f gyroSamples[], Vector3f accelSamples[], size_t n_samples)
Eccentricity n
Definition: OPPlots.m:137