ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
ekf_imu13states Class Reference

This class is used to process and calculate attitude from imu sensors. More...

#include <ekf_imu13states.h>

Inheritance diagram for ekf_imu13states:
[legend]
Collaboration diagram for ekf_imu13states:
[legend]

Public Member Functions

 ekf_imu13states ()
virtual ~ekf_imu13states ()
virtual void Init ()
virtual dspm::Mat StateXdot (dspm::Mat &x, float *u)
virtual void LinearizeFG (dspm::Mat &x, float *u)
void Test ()
void TestFull (bool enable_att)
void UpdateRefMeasurement (float *accel_data, float *magn_data, float R[6])
void UpdateRefMeasurementMagn (float *accel_data, float *magn_data, float R[6])
void UpdateRefMeasurement (float *accel_data, float *magn_data, float *attitude, float R[10])
Public Member Functions inherited from ekf
 ekf (int x, int w)
virtual ~ekf ()
virtual void Process (float *u, float dt)
void RungeKutta (dspm::Mat &x, float *u, float dt)
virtual void CovariancePrediction (float dt)
virtual void Update (dspm::Mat &H, float *measured, float *expected, float *R)
virtual void UpdateRef (dspm::Mat &H, float *measured, float *expected, float *R)

Data Fields

dspm::Mat mag0
dspm::Mat accel0
int NUMU
Data Fields inherited from ekf
int NUMX
int NUMW
dspm::MatX
dspm::MatF
dspm::MatG
dspm::MatP
dspm::MatQ
float * HP
float * Km

Additional Inherited Members

Static Public Member Functions inherited from ekf
static dspm::Mat quat2rotm (float q[4])
static dspm::Mat rotm2quat (dspm::Mat &R)
static dspm::Mat quat2eul (const float q[4])
static dspm::Mat eul2rotm (float xyz[3])
static dspm::Mat rotm2eul (dspm::Mat &rotm)
static dspm::Mat dFdq (dspm::Mat &vector, dspm::Mat &quat)
static dspm::Mat dFdq_inv (dspm::Mat &vector, dspm::Mat &quat)
static dspm::Mat SkewSym4x4 (float *w)
static dspm::Mat qProduct (float *q)

Detailed Description

This class is used to process and calculate attitude from imu sensors.

The class use state vector with 13 follows values X[0..3] - attitude quaternion X[4..6] - gyroscope bias error, rad/sec X[7..9] - magnetometer vector value - magn_ampl X[10..12] - magnetometer offset value - magn_offset

where, reference magnetometer value = magn_ampl*rotation_matrix' + magn_offset

Definition at line 31 of file ekf_imu13states.h.

Constructor & Destructor Documentation

◆ ekf_imu13states()

ekf_imu13states::ekf_imu13states ( )

Definition at line 18 of file ekf_imu13states.cpp.

18 : ekf(13, 18),
19 mag0(3, 1),
20 accel0(3, 1)
21{
22 this->NUMU = 3;
23}
ekf(int x, int w)
Definition ekf.cpp:19

References accel0, ekf::ekf(), mag0, and NUMU.

Here is the call graph for this function:

◆ ~ekf_imu13states()

ekf_imu13states::~ekf_imu13states ( )
virtual

Definition at line 25 of file ekf_imu13states.cpp.

26{
27}

Member Function Documentation

◆ Init()

void ekf_imu13states::Init ( )
virtual

Initialization of EKF. The method should be called befare the first use of the filter.

Implements ekf.

Definition at line 29 of file ekf_imu13states.cpp.

30{
31 mag0.data[0] = 1;
32 mag0.data[1] = 0;
33 mag0.data[2] = 0;
34
35 mag0 /= mag0.norm();
36
37 accel0.data[0] = 0;
38 accel0.data[1] = 0;
39 accel0.data[2] = 1;
40
41 accel0 /= accel0.norm();
42
43 this->Q.Copy(0.1 * dspm::Mat::eye(3), 0, 0);
44 this->Q.Copy(0.0001 * dspm::Mat::eye(3), 3, 3);
45 this->Q.Copy(0.0001 * dspm::Mat::eye(3), 6, 6);
46 this->Q.Copy(0.0001 * dspm::Mat::eye(3), 9, 9);
47 this->Q.Copy(0.00001 * dspm::Mat::eye(3), 12, 12);
48 this->Q.Copy(0.00001 * dspm::Mat::eye(3), 15, 15);
49
50 this->X.data[0] = 1; // Init quaternion
51 this->X.data[7] = 1; // Initial magnetometer vector
52}
static Mat eye(int size)
Definition mat.cpp:394
dspm::Mat & X
Definition ekf.h:73
dspm::Mat & Q
Definition ekf.h:92

References accel0, dspm::Mat::eye(), mag0, ekf::Q, and ekf::X.

Here is the call graph for this function:

◆ LinearizeFG()

void ekf_imu13states::LinearizeFG ( dspm::Mat & x,
float * u )
virtual

Calculation of system state matrices F and G

Parameters
[in]xstate vector
[in]ucontrol measurement

Implements ekf.

Definition at line 75 of file ekf_imu13states.cpp.

76{
77 float w[3] = {(u[0] - x(4, 0)), (u[1] - x(5, 0)), (u[2] - x(6, 0))}; // subtract the biases on gyros
78 // float w[3] = {u[0], u[1], u[2]}; // subtract the biases on gyros
79
80 this->F *= 0; // Initialize F and G matrixes.
81 this->G *= 0;
82
83 // dqdot / dq - skey matrix
84 F.Copy(0.5 * ekf::SkewSym4x4(w), 0, 0);
85
86 // dqdot/dvector
87 dspm::Mat dq = -0.5 * qProduct(x.data);
88 dspm::Mat dq_q = dq.Get(0, 4, 1, 3);
89
90 // dqdot / dnw
91 G.Copy(dq_q, 0, 0);
92 // dqdot / dwbias
93 F.Copy(dq_q, 0, 4);
94
95 dspm::Mat rotm = -1 * this->quat2rotm(x.data); // Convert quat to rotation matrix
96
97 G.Copy(rotm, 7, 6);
98 G.Copy(dspm::Mat::eye(3), 4, 3); // random noise wbias
99 G.Copy(dspm::Mat::eye(3), 7, 12); // random noise magnetometer amplitude
100 G.Copy(dspm::Mat::eye(3), 10, 9); // magnetometer offset constant
101 G.Copy(dspm::Mat::eye(3), 10, 15); // random noise offset constant
102}
Mat Get(int row_start, int row_size, int col_start, int col_size)
Definition mat.cpp:209
dspm::Mat & F
Definition ekf.h:78
static dspm::Mat quat2rotm(float q[4])
Definition ekf.cpp:209
dspm::Mat & G
Definition ekf.h:82
static dspm::Mat qProduct(float *q)
Definition ekf.cpp:112
static dspm::Mat SkewSym4x4(float *w)
Definition ekf.cpp:81
float x[1024]
Definition test_fir.c:10

References dspm::Mat::data, dspm::Mat::eye(), ekf::F, ekf::G, dspm::Mat::Get(), ekf::qProduct(), ekf::quat2rotm(), ekf::SkewSym4x4(), and x.

Here is the call graph for this function:

◆ StateXdot()

dspm::Mat ekf_imu13states::StateXdot ( dspm::Mat & x,
float * u )
virtual

Derivative of state vector X The default calculation: xDot = F*x + G*u It's possible to implement optimized version

Parameters
[in]xstate vector
[in]ucontrol measurement
Returns
xDot - derivative of input vector x and u

Reimplemented from ekf.

Definition at line 54 of file ekf_imu13states.cpp.

55{
56 float wx = u[0] - x(4, 0); // subtract the biases on gyros
57 float wy = u[1] - x(5, 0);
58 float wz = u[2] - x(6, 0);
59
60 float w[] = {wx, wy, wz};
61 dspm::Mat q = dspm::Mat(x.data, 4, 1);
62
63 // qdot = Q * w
64 dspm::Mat Omega = 0.5 * SkewSym4x4(w);
65 dspm::Mat qdot = Omega * q;
66 dspm::Mat Xdot(this->NUMX, 1);
67 Xdot *= 0;
68 Xdot.Copy(qdot, 0, 0);
69 // dwbias = 0
70 // dMang_Ampl = 0
71 // dMang_offset = 0
72 return Xdot;
73}
int NUMX
Definition ekf.h:63

References dspm::Mat::Copy(), ekf::NUMX, ekf::SkewSym4x4(), and x.

Referenced by Test().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Test()

void ekf_imu13states::Test ( )

Method for development and tests only.

Definition at line 104 of file ekf_imu13states.cpp.

105{
106 dspm::Mat test_x(7, 1);
107 for (size_t i = 0; i < 7; i++) {
108 test_x(i, 0) = i;
109 }
110 printf("Allocate data = %i\n", this->NUMU);
111 float *test_u = new float[this->NUMU];
112 for (size_t i = 0; i < this->NUMU; i++) {
113 test_u[i] = i;
114 }
115 dspm::Mat result_StateXdot = StateXdot(test_x, test_u);
116 delete[] test_u;
117}
virtual dspm::Mat StateXdot(dspm::Mat &x, float *u)

References NUMU, and StateXdot().

Here is the call graph for this function:

◆ TestFull()

void ekf_imu13states::TestFull ( bool enable_att)
Method for development and tests only.
Parameters
[in]enable_att- enable attitude as input reference value

Definition at line 119 of file ekf_imu13states.cpp.

120{
121 int total_N = 2048;
122 float pi = std::atan(1) * 4;
123 float gyro_err_data[] = {0.1, 0.2, 0.3}; // static constatnt error
124 dspm::Mat gyro_err(gyro_err_data, 3, 1);
125 float R[10];
126 for (size_t i = 0; i < 10; i++) {
127 R[i] = 0.01;
128 }
129
130 float accel0_data[] = {0, 0, 1};
131 float magn0_data[] = {1, 0, 0};
132
133 dspm::Mat accel0(accel0_data, 3, 1);
134 dspm::Mat magn0(magn0_data, 3, 1);
135
136 float dt = 0.01;
137
138 dspm::Mat gyro_data(3, 1);
139 int count = 0;
140
141 // Initial rotation matrix
142 dspm::Mat Rm = dspm::Mat::eye(3);
143 dspm::Mat Re = dspm::Mat::eye(3);
144
145 gyro_err *= 1;
146
147 std::cout << "Gyro error: " << gyro_err.t() << std::endl;
148 for (size_t n = 1; n < total_N * 3; n++) {
149 if ((n % 1000) == 0) {
150 std::cout << "Loop " << n << " from " << total_N * 16;
151 std::cout << ", State data : " << this->X.t();
152 }
153 gyro_data *= 0; // reset gyro value
154 if ((n >= (total_N / 2)) && (n < total_N * 12)) {
155 gyro_data(0, 0) = 1 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
156 gyro_data(1, 0) = 2 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
157 gyro_data(2, 0) = 3 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
158 count++;
159 }
160 dspm::Mat gyro_sample = gyro_data + gyro_err;
161
162 gyro_data *= dt;
163 Re = this->eul2rotm(gyro_data.data); // Calculate rotation to gyro angel
164 Rm = Rm * Re; // Rotate original matrix
165 dspm::Mat attitude = ekf::rotm2quat(Rm);
166 // We have to rotate accel and magn to the opposite direction
167 dspm::Mat accel_data = Rm.t() * accel0;
168 dspm::Mat magn_data = Rm.t() * magn0;
169
170 dspm::Mat accel_norm = accel_data / accel_data.norm();
171 dspm::Mat magn_norm = magn_data / magn_data.norm();
172
173 float input_u[] = {gyro_sample(0, 0), gyro_sample(1, 0), gyro_sample(2, 0)};
174 // Process input values to new state
175 this->Process(input_u, dt);
176 dspm::Mat q_norm(this->X.data, 4, 1);
177 q_norm /= q_norm.norm();
178
179 if (true == enable_att) {
180 this->UpdateRefMeasurement(accel_norm.data, magn_norm.data, attitude.data, R);
181 } else {
182 this->UpdateRefMeasurement(accel_norm.data, magn_norm.data, R);
183 }
184 }
185 std::cout << "Final State data : " << this->X.t() << std::endl;
186}
float * data
Definition mat.h:37
float norm(void)
Definition mat.cpp:456
Mat t()
Definition mat.cpp:383
void UpdateRefMeasurement(float *accel_data, float *magn_data, float R[6])
static dspm::Mat rotm2quat(dspm::Mat &R)
Definition ekf.cpp:305
virtual void Process(float *u, float dt)
Definition ekf.cpp:53
static dspm::Mat eul2rotm(float xyz[3])
Definition ekf.cpp:251
const int n
Definition test_mmult.c:17

References accel0, dspm::Mat::data, ekf::eul2rotm(), dspm::Mat::eye(), n, dspm::Mat::norm(), ekf::Process(), ekf::rotm2quat(), dspm::Mat::t(), UpdateRefMeasurement(), and ekf::X.

Here is the call graph for this function:

◆ UpdateRefMeasurement() [1/2]

void ekf_imu13states::UpdateRefMeasurement ( float * accel_data,
float * magn_data,
float * attitude,
float R[10] )

Update system state by reference measurements accelerometer, magnetometer and attitude quaternion. This method could be used when system on constant state or in initialization phase.

Parameters
[in]accel_dataaccelerometer measurement vector XYZ in g, where 1 g ~ 9.81 m/s^2
[in]magn_datamagnetometer measurement vector XYZ
[in]attitudeattitude quaternion
[in]Rmeasurement noise covariance values for diagonal covariance matrix. Then smaller value, then more you trust them.

Definition at line 256 of file ekf_imu13states.cpp.

257{
258 dspm::Mat quat(this->X.data, 4, 1);
259 dspm::Mat H = 0 * dspm::Mat(10, this->NUMX);
260 dspm::Mat Re = this->quat2rotm(quat.data).t();
261
262 H.Copy(Re, 0, 7);
263 H.Copy(dspm::Mat::eye(3), 0, 10);
264 // dAccel/dq
265 dspm::Mat dAccel_dq = ekf::dFdq_inv(this->accel0, quat);
266 H.Copy(dAccel_dq, 3, 0);
267 // dMagn/dq
268 dspm::Mat magn(&this->X.data[7], 3, 1);
269 dspm::Mat magn_offset(&this->X.data[10], 3, 1);
270 dspm::Mat dMagn_dq = ekf::dFdq_inv(magn, quat);
271 H.Copy(dMagn_dq, 0, 0);
272
273 // dq/dq
274 H.Copy(dspm::Mat::eye(4), 6, 1);
275
276 dspm::Mat expected_magn = Re * magn + magn_offset;
277 dspm::Mat expected_accel = Re * this->accel0;
278
279 float measured_data[10];
280 float expected_data[10];
281 for (size_t i = 0; i < 3; i++) {
282 measured_data[i] = magn_data[i];
283 expected_data[i] = expected_magn.data[i];
284 measured_data[i + 3] = accel_data[i];
285 expected_data[i + 3] = expected_accel.data[i];
286 }
287 for (size_t i = 0; i < 4; i++) {
288 measured_data[i + 6] = attitude[i];
289 expected_data[i + 6] = this->X.data[i];
290 }
291
292 this->Update(H, measured_data, expected_data, R);
293 quat /= quat.norm();
294}
void Copy(const Mat &src, int row_pos, int col_pos)
Definition mat.cpp:168
static dspm::Mat dFdq_inv(dspm::Mat &vector, dspm::Mat &quat)
Definition ekf.cpp:389
virtual void Update(dspm::Mat &H, float *measured, float *expected, float *R)
Definition ekf.cpp:149

References accel0, dspm::Mat::Copy(), dspm::Mat::data, ekf::dFdq_inv(), dspm::Mat::eye(), dspm::Mat::norm(), ekf::NUMX, ekf::quat2rotm(), dspm::Mat::t(), ekf::Update(), and ekf::X.

Here is the call graph for this function:

◆ UpdateRefMeasurement() [2/2]

void ekf_imu13states::UpdateRefMeasurement ( float * accel_data,
float * magn_data,
float R[6] )

Update part of system state by reference measurements accelerometer and magnetometer. Only attitude and gyro bias will be updated. This method should be used as main method after calibration.

Parameters
[in]accel_dataaccelerometer measurement vector XYZ in g, where 1 g ~ 9.81 m/s^2
[in]magn_datamagnetometer measurement vector XYZ
[in]Rmeasurement noise covariance values for diagonal covariance matrix. Then smaller value, then more you trust them.

Definition at line 188 of file ekf_imu13states.cpp.

189{
190 dspm::Mat quat(this->X.data, 4, 1);
191 dspm::Mat H = 0 * dspm::Mat(6, this->NUMX);
192 dspm::Mat Re = this->quat2rotm(quat.data).t();
193
194 // dAccel/dq
195 dspm::Mat dAccel_dq = ekf::dFdq_inv(this->accel0, quat);
196 H.Copy(dAccel_dq, 3, 0);
197
198 // dMagn/dq
199 dspm::Mat magn(&this->X.data[7], 3, 1);
200 dspm::Mat magn_offset(&this->X.data[10], 3, 1);
201 dspm::Mat dMagn_dq = ekf::dFdq_inv(magn, quat);
202 H.Copy(dMagn_dq, 0, 0);
203
204 dspm::Mat expected_magn = Re * magn + magn_offset;
205 dspm::Mat expected_accel = Re * this->accel0;
206
207 float measured_data[6];
208 float expected_data[6];
209 for (size_t i = 0; i < 3; i++) {
210 measured_data[i] = magn_data[i];
211 expected_data[i] = expected_magn.data[i];
212 measured_data[i + 3] = accel_data[i];
213 expected_data[i + 3] = expected_accel.data[i];
214 }
215
216 this->Update(H, measured_data, expected_data, R);
217 quat /= quat.norm();
218}

References accel0, dspm::Mat::Copy(), dspm::Mat::data, ekf::dFdq_inv(), dspm::Mat::norm(), ekf::NUMX, ekf::quat2rotm(), dspm::Mat::t(), ekf::Update(), and ekf::X.

Referenced by TestFull().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateRefMeasurementMagn()

void ekf_imu13states::UpdateRefMeasurementMagn ( float * accel_data,
float * magn_data,
float R[6] )

Update full system state by reference measurements accelerometer and magnetometer. This method should be used at calibration phase.

Parameters
[in]accel_dataaccelerometer measurement vector XYZ in g, where 1 g ~ 9.81 m/s^2
[in]magn_datamagnetometer measurement vector XYZ
[in]Rmeasurement noise covariance values for diagonal covariance matrix. Then smaller value, then more you trust them.

Definition at line 220 of file ekf_imu13states.cpp.

221{
222 dspm::Mat quat(this->X.data, 4, 1);
223 dspm::Mat H = 0 * dspm::Mat(6, this->NUMX);
224 dspm::Mat Re = this->quat2rotm(quat.data).t();
225
226 // We include these two line to update magnetometer initial state
227 H.Copy(Re, 0, 7);
228 H.Copy(dspm::Mat::eye(3), 0, 10);
229
230 // dAccel/dq
231 dspm::Mat dAccel_dq = ekf::dFdq_inv(this->accel0, quat);
232 H.Copy(dAccel_dq, 3, 0);
233
234 // dMagn/dq
235 dspm::Mat magn(&this->X.data[7], 3, 1);
236 dspm::Mat magn_offset(&this->X.data[10], 3, 1);
237 dspm::Mat dMagn_dq = ekf::dFdq_inv(magn, quat);
238 H.Copy(dMagn_dq, 0, 0);
239
240 dspm::Mat expected_magn = Re * magn + magn_offset;
241 dspm::Mat expected_accel = Re * this->accel0;
242
243 float measured_data[6];
244 float expected_data[6];
245 for (size_t i = 0; i < 3; i++) {
246 measured_data[i] = magn_data[i];
247 expected_data[i] = expected_magn.data[i];
248 measured_data[i + 3] = accel_data[i];
249 expected_data[i + 3] = expected_accel.data[i];
250 }
251
252 this->Update(H, measured_data, expected_data, R);
253 quat /= quat.norm();
254}

References accel0, dspm::Mat::Copy(), dspm::Mat::data, ekf::dFdq_inv(), dspm::Mat::eye(), dspm::Mat::norm(), ekf::NUMX, ekf::quat2rotm(), dspm::Mat::t(), ekf::Update(), and ekf::X.

Here is the call graph for this function:

Field Documentation

◆ accel0

dspm::Mat ekf_imu13states::accel0

Initial reference valie for accelerometer.

Definition at line 60 of file ekf_imu13states.h.

Referenced by ekf_imu13states(), Init(), TestFull(), UpdateRefMeasurement(), UpdateRefMeasurement(), and UpdateRefMeasurementMagn().

◆ mag0

dspm::Mat ekf_imu13states::mag0

Initial reference valie for magnetometer.

Definition at line 56 of file ekf_imu13states.h.

Referenced by ekf_imu13states(), and Init().

◆ NUMU

int ekf_imu13states::NUMU

number of control measurements

Definition at line 65 of file ekf_imu13states.h.

Referenced by ekf_imu13states(), and Test().


The documentation for this class was generated from the following files: