AHRS.cpp
Go to the documentation of this file.
1 /*
2  * @file AHRS.cpp
3  * @brief Attitude and Heading Reference System implementation
4  * Created on: Jan 26, 2012
5  * Author: cbeall3
6  */
7 
8 #include "AHRS.h"
9 #include <cmath>
10 
11 using namespace std;
12 
13 namespace gtsam {
14 
15 /* ************************************************************************* */
16 Matrix3 AHRS::Cov(const Vector3s& m) {
17  const double num_observations = m.cols();
18  const Vector3 mean = m.rowwise().sum() / num_observations;
19  Vector3s D = m.colwise() - mean;
20  return D * trans(D) / (num_observations - 1);
21 }
22 
23 /* ************************************************************************* */
24 AHRS::AHRS(const Matrix& stationaryU, const Matrix& stationaryF, double g_e,
25  bool flat) :
26  KF_(9) {
27 
28  // Initial state
30 
31  size_t T = stationaryU.cols();
32 
33  // estimate standard deviation on gyroscope readings
34  Pg_ = Cov(stationaryU);
35  Vector3 sigmas_v_g = (Pg_.diagonal() * T).cwiseSqrt();
36 
37  // estimate standard deviation on accelerometer readings
38  Pa_ = Cov(stationaryF);
39 
40  // Quantities needed for integration
41 
42  // dynamics, Chris' email September 23, 2011 3:38:05 PM EDT
43  double tau_g = 730; // correlation time for gyroscope
44  double tau_a = 730; // correlation time for accelerometer
45 
46  F_g_ = -I_3x3 / tau_g;
47  F_a_ = -I_3x3 / tau_a;
48  Vector3 var_omega_w = 0 * Vector::Ones(3); // TODO
49  Vector3 var_omega_g = (0.0034 * 0.0034) * Vector::Ones(3);
50  Vector3 var_omega_a = (0.034 * 0.034) * Vector::Ones(3);
51  Vector3 sigmas_v_g_sq = sigmas_v_g.array().square();
52  var_w_ << var_omega_w, var_omega_g, sigmas_v_g_sq, var_omega_a;
53 
54  // Quantities needed for aiding
55  sigmas_v_a_ = (T * Pa_.diagonal()).cwiseSqrt();
56 
57  // gravity in nav frame
58  n_g_ = (Vector(3) << 0.0, 0.0, g_e).finished();
59  n_g_cross_ = skewSymmetric(n_g_); // nav frame has Z down !!!
60 }
61 
62 /* ************************************************************************* */
63 std::pair<Mechanization_bRn2, KalmanFilter::State> AHRS::initialize(double g_e) {
64 
65  // Calculate Omega_T, formula 2.80 in Farrell08book
66  double cp = cos(mech0_.bRn().inverse().pitch());
67  double sp = sin(mech0_.bRn().inverse().pitch());
68  double cy = cos(0.0);
69  double sy = sin(0.0);
70  Matrix Omega_T = (Matrix(3, 3) << cy * cp, -sy, 0.0, sy * cp, cy, 0.0, -sp, 0.0, 1.0).finished();
71 
72  // Calculate Jacobian of roll/pitch/yaw wrpt (g1,g2,g3), see doc/ypr.nb
73  Vector b_g = mech0_.b_g(g_e);
74  double g1 = b_g(0);
75  double g2 = b_g(1);
76  double g3 = b_g(2);
77  double g23 = g2 * g2 + g3 * g3;
78  double g123 = g1 * g1 + g23;
79  double f = 1 / (std::sqrt(g23) * g123);
80  Matrix H_g = (Matrix(3, 3) <<
81  0.0, g3 / g23, -(g2 / g23), // roll
82  std::sqrt(g23) / g123, -f * (g1 * g2), -f * (g1 * g3), // pitch
83  0.0, 0.0, 0.0).finished(); // we don't know anything on yaw
84 
85  // Calculate the initial covariance matrix for the error state dx, Farrell08book eq. 10.66
86  Matrix Pa = 0.025 * 0.025 * I_3x3;
87  Matrix P11 = Omega_T * (H_g * (Pa + Pa_) * trans(H_g)) * trans(Omega_T);
88  P11(2, 2) = 0.0001;
89  Matrix P12 = -Omega_T * H_g * Pa;
90 
91  Matrix P_plus_k2 = Matrix(9, 9);
92  P_plus_k2.block<3,3>(0, 0) = P11;
93  P_plus_k2.block<3,3>(0, 3) = Z_3x3;
94  P_plus_k2.block<3,3>(0, 6) = P12;
95 
96  P_plus_k2.block<3,3>(3, 0) = Z_3x3;
97  P_plus_k2.block<3,3>(3, 3) = Pg_;
98  P_plus_k2.block<3,3>(3, 6) = Z_3x3;
99 
100  P_plus_k2.block<3,3>(6, 0) = trans(P12);
101  P_plus_k2.block<3,3>(6, 3) = Z_3x3;
102  P_plus_k2.block<3,3>(6, 6) = Pa;
103 
104  Vector dx = Z_9x1;
105  KalmanFilter::State state = KF_.init(dx, P_plus_k2);
106  return std::make_pair(mech0_, state);
107 }
108 
109 /* ************************************************************************* */
110 std::pair<Mechanization_bRn2, KalmanFilter::State> AHRS::integrate(
112  const Vector& u, double dt) {
113 
114  // Integrate full state
115  Mechanization_bRn2 newMech = mech.integrate(u, dt);
116 
117  // Integrate error state Kalman filter
118  // FIXME:
119  //if nargout>1
120  Matrix bRn = mech.bRn().matrix();
121 
122  Matrix9 F_k; F_k.setZero();
123  F_k.block<3,3>(0, 3) = -bRn;
124  F_k.block<3,3>(3, 3) = F_g_;
125  F_k.block<3,3>(6, 6) = F_a_;
126 
127  typedef Eigen::Matrix<double,9,12> Matrix9_12;
128  Matrix9_12 G_k; G_k.setZero();
129  G_k.block<3,3>(0, 0) = -bRn;
130  G_k.block<3,3>(0, 6) = -bRn;
131  G_k.block<3,3>(3, 3) = I_3x3;
132  G_k.block<3,3>(6, 9) = I_3x3;
133 
134  Matrix9 Q_k = G_k * var_w_.asDiagonal() * G_k.transpose();
135  Matrix9 Psi_k = I_9x9 + dt * F_k; // +dt*dt*F_k*F_k/2; // transition matrix
136 
137  // This implements update in section 10.6
138  Matrix9 B; B.setZero();
139  Vector9 u2; u2.setZero();
140  // TODO predictQ should be templated to also take fixed size matrices.
141  KalmanFilter::State newState = KF_.predictQ(state, Psi_k,B,u2,dt*Q_k);
142  return make_pair(newMech, newState);
143 }
144 
145 /* ************************************************************************* */
147  const gtsam::Vector& f, const gtsam::Vector& u, double ge) const {
148 
149  // Subtract the biases
150  Vector f_ = f - mech.x_a();
151  Vector u_ = u - mech.x_g();
152 
153  double mu_f = f_.norm() - ge; // accelerometer same magnitude as local gravity ?
154  double mu_u = u_.norm(); // gyro says we are not maneuvering ?
155  return (std::abs(mu_f)<0.5 && mu_u < 5.0 / 180.0 * M_PI);
156 }
157 
158 /* ************************************************************************* */
159 std::pair<Mechanization_bRn2, KalmanFilter::State> AHRS::aid(
161  const Vector& f, bool Farrell) const {
162 
163  Matrix bRn = mech.bRn().matrix();
164 
165  // get gravity in body from accelerometer
166  Vector measured_b_g = mech.x_a() - f;
167 
168  Matrix R, H;
169  Vector z;
170  if (Farrell) {
171  // calculate residual gravity measurement
172  z = n_g_ - trans(bRn) * measured_b_g;
173  H = collect(3, &n_g_cross_, &Z_3x3, &bRn);
174  R = trans(bRn) * ((Vector3) sigmas_v_a_.array().square()).asDiagonal() * bRn;
175  } else {
176  // my measurement prediction (in body frame):
177  // F(:,k) = bias - b_g
178  // F(:,k) = mech.x_a + dx_a - bRn*n_g;
179  // F(:,k) = mech.x_a + dx_a - bRn*(I+P)*n_g;
180  // F(:,k) = mech.x_a + dx_a - b_g - bRn*(rho x n_g); // P = [rho]_x
181  // Hence, the measurement z = b_g - (mech.x_a - F(:,k)) is predicted
182  // from the filter state (dx_a, rho) as dx_a + bRn*(n_g x rho)
183  // z = b_g - (mech.x_a - F(:,k)) = dx_a + bRn*(n_g x rho)
184  z = bRn * n_g_ - measured_b_g;
185  // Now the Jacobian H
186  Matrix b_g = bRn * n_g_cross_;
187  H = collect(3, &b_g, &Z_3x3, &I_3x3);
188  // And the measurement noise, TODO: should be created once where sigmas_v_a is given
189  R = ((Vector3) sigmas_v_a_.array().square()).asDiagonal();
190  }
191 
192 // update the Kalman filter
193  KalmanFilter::State updatedState = KF_.updateQ(state, H, z, R);
194 
195 // update full state (rotation and accelerometer bias)
196  Mechanization_bRn2 newMech = mech.correct(updatedState->mean());
197 
198 // reset KF state
199  Vector dx = Z_9x1;
200  updatedState = KF_.init(dx, updatedState->covariance());
201 
202  return make_pair(newMech, updatedState);
203 }
204 
205 /* ************************************************************************* */
206 std::pair<Mechanization_bRn2, KalmanFilter::State> AHRS::aidGeneral(
208  const Vector& f, const Vector& f_previous,
209  const Rot3& R_previous) const {
210 
211  Matrix increment = R_previous.between(mech.bRn()).matrix();
212 
213  // expected - measured
214  Vector z = f - increment * f_previous;
215  //Vector z = increment * f_previous - f;
216  Matrix b_g = skewSymmetric(increment* f_previous);
217  Matrix H = collect(3, &b_g, &I_3x3, &Z_3x3);
218 // Matrix R = diag(emul(sigmas_v_a_, sigmas_v_a_));
219 // Matrix R = diag(Vector3(1.0, 0.2, 1.0)); // good for L_twice
220  Matrix R = Vector3(0.01, 0.0001, 0.01).asDiagonal();
221 
222 // update the Kalman filter
223  KalmanFilter::State updatedState = KF_.updateQ(state, H, z, R);
224 
225 // update full state (rotation and gyro bias)
226  Mechanization_bRn2 newMech = mech.correct(updatedState->mean());
227 
228 // reset KF state
229  Vector dx = Z_9x1;
230  updatedState = KF_.init(dx, updatedState->covariance());
231 
232  return make_pair(newMech, updatedState);
233 }
234 
235 /* ************************************************************************* */
236 void AHRS::print(const std::string& s) const {
237  mech0_.print(s + ".mech0_");
238  gtsam::print((Matrix)F_g_, s + ".F_g");
239  gtsam::print((Matrix)F_a_, s + ".F_a");
240  gtsam::print((Vector)var_w_, s + ".var_w");
241 
242  gtsam::print((Vector)sigmas_v_a_, s + ".sigmas_v_a");
243  gtsam::print((Vector)n_g_, s + ".n_g");
244  gtsam::print((Matrix)n_g_cross_, s + ".n_g_cross");
245 
246  gtsam::print((Matrix)Pg_, s + ".P_g");
247  gtsam::print((Matrix)Pa_, s + ".P_a");
248 
249 }
250 
251 /* ************************************************************************* */
253 }
254 
255 /* ************************************************************************* */
256 
257 } /* namespace gtsam */
gtsam::LieGroup::between
Class between(const Class &g) const
Definition: Lie.h:52
g_e
double g_e
Definition: testAHRS.cpp:21
H
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate set rrange[*:*] noreverse nowriteback set trange[*:*] noreverse nowriteback set urange[*:*] noreverse nowriteback set vrange[*:*] noreverse nowriteback set xlabel matrix size set x2label set timefmt d m y n H
Definition: gnuplot_common_settings.hh:74
gtsam::AHRS::n_g_cross_
Matrix3 n_g_cross_
and its skew-symmetric matrix
Definition: AHRS.h:34
B
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:49
cy
const double cy
Definition: testSmartStereoFactor_iSAM2.cpp:50
D
MatrixXcd D
Definition: EigenSolver_EigenSolver_MatrixType.cpp:14
gtsam::AHRS::sigmas_v_a_
Vector3 sigmas_v_a_
measurement sigma
Definition: AHRS.h:32
gtsam::AHRS::initialize
std::pair< Mechanization_bRn2, KalmanFilter::State > initialize(double g_e)
Definition: AHRS.cpp:63
gtsam::AHRS::Pa_
Matrix3 Pa_
Definition: AHRS.h:36
s
RealScalar s
Definition: level1_cplx_impl.h:126
ceres::sin
Jet< T, N > sin(const Jet< T, N > &f)
Definition: jet.h:439
g1
Pose3 g1(Rot3(), Point3(100.0, 0.0, 300.0))
gtsam::Mechanization_bRn2::print
void print(const std::string &s="") const
print
Definition: Mechanization_bRn2.h:82
gtsam::KalmanFilter::State
GaussianDensity::shared_ptr State
The Kalman filter state, represented as a shared pointer to a GaussianDensity.
Definition: KalmanFilter.h:55
gtsam::AHRS::KF_
KalmanFilter KF_
initial Kalman filter
Definition: AHRS.h:22
trans
static char trans
Definition: blas_interface.hh:58
dt
const double dt
Definition: testVelocityConstraint.cpp:15
gtsam::AHRS::var_w_
Variances var_w_
dynamic noise variances
Definition: AHRS.h:29
gtsam::AHRS::isAidingAvailable
bool isAidingAvailable(const Mechanization_bRn2 &mech, const Vector &f, const Vector &u, double ge) const
Definition: AHRS.cpp:146
T
Eigen::Triplet< double > T
Definition: Tutorial_sparse_example.cpp:6
gtsam::Matrix
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
gtsam::AHRS::~AHRS
virtual ~AHRS()
Definition: AHRS.cpp:252
gtsam::Mechanization_bRn2::integrate
Mechanization_bRn2 integrate(const Vector3 &u, const double dt) const
Definition: Mechanization_bRn2.cpp:81
gtsam::AHRS::F_g_
Matrix3 F_g_
gyro bias dynamics
Definition: AHRS.h:25
gtsam::Vector3
Eigen::Vector3d Vector3
Definition: Vector.h:44
gtsam::Mechanization_bRn2::correct
Mechanization_bRn2 correct(const Vector9 &dx) const
Definition: Mechanization_bRn2.cpp:68
gtsam::Vector
Eigen::VectorXd Vector
Definition: Vector.h:39
gtsam::skewSymmetric
Matrix3 skewSymmetric(double wx, double wy, double wz)
Definition: base/Matrix.h:400
ceres::cos
Jet< T, N > cos(const Jet< T, N > &f)
Definition: jet.h:426
gtsam::Mechanization_bRn2::b_g
Vector3 b_g(double g_e) const
gravity in the body frame
Definition: Mechanization_bRn2.h:43
gtsam::AHRS::n_g_
Vector3 n_g_
gravity in nav frame
Definition: AHRS.h:33
gtsam::AHRS::print
void print(const std::string &s="") const
print
Definition: AHRS.cpp:236
gtsam::print
void print(const Matrix &A, const string &s, ostream &stream)
Definition: Matrix.cpp:156
gtsam::Mechanization_bRn2::bRn
const Rot3 & bRn() const
Definition: Mechanization_bRn2.h:48
gtsam::AHRS::F_a_
Matrix3 F_a_
acc bias dynamics
Definition: AHRS.h:26
gtsam::AHRS::aid
std::pair< Mechanization_bRn2, KalmanFilter::State > aid(const Mechanization_bRn2 &mech, KalmanFilter::State state, const Vector &f, bool Farrell=0) const
Definition: AHRS.cpp:159
gtsam::Mechanization_bRn2
Definition: Mechanization_bRn2.h:17
gtsam::Rot3
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition: Rot3.h:58
g2
Pose3 g2(g1.expmap(h *V1_g1))
u2
Vector u2
Definition: testSimpleHelicopter.cpp:32
pybind_wrapper_test_script.z
z
Definition: pybind_wrapper_test_script.py:61
m
Matrix3f m
Definition: AngleAxis_mimic_euler.cpp:1
Eigen::Triplet< double >
gtsam::Rot3::inverse
Rot3 inverse() const
inverse of a rotation
Definition: Rot3.h:312
gtsam::KalmanFilter::predictQ
State predictQ(const State &p, const Matrix &F, const Matrix &B, const Vector &u, const Matrix &Q) const
Definition: KalmanFilter.cpp:125
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
gtsam::AHRS::Pg_
Matrix3 Pg_
Definition: AHRS.h:36
gtsam::AHRS::aidGeneral
std::pair< Mechanization_bRn2, KalmanFilter::State > aidGeneral(const Mechanization_bRn2 &mech, KalmanFilter::State state, const Vector &f, const Vector &f_expected, const Rot3 &R_previous) const
Definition: AHRS.cpp:206
gtsam
traits
Definition: SFMdata.h:40
cwiseSqrt
const EIGEN_DEVICE_FUNC CwiseSqrtReturnType cwiseSqrt() const
Definition: MatrixCwiseUnaryOps.h:59
gtsam::trans
Matrix trans(const Matrix &A)
Definition: base/Matrix.h:241
std
Definition: BFloat16.h:88
gtsam::AHRS::Cov
static Matrix3 Cov(const Vector3s &m)
Definition: AHRS.cpp:16
gtsam::AHRS::mech0_
Mechanization_bRn2 mech0_
Initial mechanization state.
Definition: AHRS.h:21
gtsam::Mechanization_bRn2::x_a
const Vector3 & x_a() const
Definition: Mechanization_bRn2.h:50
gtsam::KalmanFilter::updateQ
State updateQ(const State &p, const Matrix &H, const Vector &z, const Matrix &R) const
Definition: KalmanFilter.cpp:170
gtsam::Mechanization_bRn2::x_g
const Vector3 & x_g() const
Definition: Mechanization_bRn2.h:49
gtsam::Rot3::matrix
Matrix3 matrix() const
Definition: Rot3M.cpp:218
Eigen::Matrix< double, 3, Eigen::Dynamic >
abs
#define abs(x)
Definition: datatypes.h:17
Eigen::PlainObjectBase::setZero
EIGEN_DEVICE_FUNC Derived & setZero(Index size)
Definition: CwiseNullaryOp.h:562
AHRS.h
M_PI
#define M_PI
Definition: mconf.h:117
gtsam::collect
Matrix collect(const std::vector< const Matrix * > &matrices, size_t m, size_t n)
Definition: Matrix.cpp:442
stationaryU
Matrix stationaryU
Definition: testAHRS.cpp:19
sampling::mean
static const Vector2 mean(20, 40)
stationaryF
Matrix stationaryF
Definition: testAHRS.cpp:20
gtsam::KalmanFilter::init
State init(const Vector &x0, const SharedDiagonal &P0) const
Definition: KalmanFilter.cpp:82
gtsam::AHRS::integrate
std::pair< Mechanization_bRn2, KalmanFilter::State > integrate(const Mechanization_bRn2 &mech, KalmanFilter::State state, const Vector &u, double dt)
Definition: AHRS.cpp:110
gtsam::Rot3::pitch
double pitch(OptionalJacobian< 1, 3 > H={}) const
Definition: Rot3.cpp:207
ceres::sqrt
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
R
Rot2 R(Rot2::fromAngle(0.1))
gtsam::Mechanization_bRn2::initialize
static Mechanization_bRn2 initialize(const Matrix &U, const Matrix &F, const double g_e=0, bool flat=false)
Matrix version of initialize.
Definition: Mechanization_bRn2.cpp:23
make_changelog.state
state
Definition: make_changelog.py:29


gtsam
Author(s):
autogenerated on Sun Dec 22 2024 04:11:05