59 F_lin = Matrix<float, 6, 6>::Identity();
60 F_lin.block<3, 3>(0, 3) = config.
T * Matrix3f::Identity();
61 F_lin_tr = F_lin.transpose();
63 F_quat << -Matrix3f::Identity(), -Matrix3f::Identity() * config.
T,
64 Matrix3f::Zero(3, 3), Matrix3f::Identity();
65 F_quat_tr = F_quat.transpose();
67 G_quat << -Matrix3f::Identity(), Matrix3f::Zero(3, 3),
68 Matrix3f::Zero(3, 3), Matrix3f::Identity();
69 G_quat_tr = G_quat.transpose();
76 Vector3f pos = x.block<3, 1>(
IDX_POS, 0);
77 Vector3f vel = x.block<3, 1>(
IDX_VEL, 0);
80 pos = pos + vel * config.
T;
83 Vector3f a = A * acceleration - gravityNed;
86 vel = vel + a * config.
T;
89 x.block<3, 1>(
IDX_POS, 0) = pos;
90 x.block<3, 1>(
IDX_VEL, 0) = vel;
93 Matrix<float, 6, 6> Pl = P.block<6, 6>(0, 0);
94 P.block<6, 6>(0, 0) = F_lin * Pl * F_lin_tr + Q_lin;
105 Vector3f bias = x.block<3, 1>(
IDX_BIAS, 0);
106 Vector4f q = x.block<4, 1>(
IDX_QUAT, 0);
108 Vector3f omega = angularSpeed - bias;
111 { 0.0f, omega(2), -omega(1), omega(0)},
112 {-omega(2), 0.0f, omega(0), omega(1)},
113 { omega(1), -omega(0), 0.0f, omega(2)},
114 {-omega(0), -omega(1), -omega(2), 0.0f}
119 q = (Matrix4f::Identity() + 0.5F * omega_mat * config.
T) * q;
128 Pq = F_quat * Pq * F_quat_tr + G_quat * Q_quat * G_quat_tr;
145 Matrix<float, 1, 6> H = Matrix<float, 1, 6>::Zero();
149 H[2] = Constants::a * Constants::n * reference.
refPressure *
150 powf(1 + Constants::a * d / temp, Constants::n - 1) / temp;
152 Matrix<float, 6, 6> Pl = P.block<6, 6>(0, 0);
153 float S = H * Pl * H.transpose() + R;
162 Matrix<float, 1, 1> e = Matrix<float, 1, 1>(pressure - y_hat);
163 Matrix<float, 6, 1> K = Pl * H.transpose() / S;
164 P.block<6, 6>(0, 0) = (Matrix<float, 6, 6>::Identity() - K * H) * Pl;
167 x.head<6>() = x.head<6>() + K * e;
173 H_gps = Matrix<float, 4, 6>::Zero();
176 float angle_rad = (reference.
refLatitude + x(0) / Constants::gpsLatConst) *
177 Constants::DEGREES_TO_RADIANS;
179 float H11 = 1 / Constants::gpsLatConst;
181 float H21 = (x(1) * sin(angle_rad)) /
182 (Constants::gpsLatConst * Constants::gpsLonConst *
183 pow(cos(angle_rad), 2));
184 float H22 = 1 / (Constants::gpsLonConst * cos(angle_rad));
187 H_gps.coeffRef(0, 0) = H11 * 1000;
188 H_gps.coeffRef(0, 1) = H12 * 1000;
189 H_gps.coeffRef(1, 0) = H21 * 1000;
190 H_gps.coeffRef(1, 1) = H22 * 1000;
192 H_gps.coeffRef(2, 3) = 1;
193 H_gps.coeffRef(3, 4) = 1;
195 H_gps_tr = H_gps.transpose();
197 Matrix<float, 1, 4> R_molt = {1, 1, std::max(std::abs(gps(2)), 30.0f),
198 std::max(std::abs(gps(3)), 30.0f)};
199 Matrix<float, 4, 4> R_gps = config.
SIGMA_GPS.asDiagonal().toDenseMatrix() *
200 config.
SIGMA_GPS.asDiagonal().toDenseMatrix() *
201 R_molt.asDiagonal().toDenseMatrix();
204 float lat = x(0) / Constants::gpsLatConst + reference.
refLatitude;
205 float lon = x(1) / (Constants::gpsLonConst *
206 cos(lat * Constants::DEGREES_TO_RADIANS)) +
208 Matrix<float, 4, 1> z{lat, lon, x(3), x(4)};
209 Vector4f e{(gps(0) - z(0)) * 1000.0f, (gps(1) - z(1)) * 1000.0f,
210 gps(2) - z(2), gps(3) - z(3)};
212 Matrix<float, 6, 6> Pl = P.block<6, 6>(0, 0);
214 Matrix<float, 4, 4> S = H_gps * Pl * H_gps_tr + R_gps;
217 if (S.determinant() < 1e-6)
220 Matrix<float, 6, 4> K = Pl * H_gps_tr * S.inverse();
223 x.head<6>() = x.head<6>() + K * e;
225 P.block<6, 6>(0, 0) = (Matrix<float, 6, 6>::Identity() - K * H_gps) * Pl;
239 Vector4f q = x.block<4, 1>(
IDX_QUAT, 0);
243 Vector3f mEst = A * config.
NED_MAG;
247 { 0, -mEst(2), mEst(1)},
248 { mEst(2), 0, -mEst(0)},
249 {-mEst(1), mEst(0), 0}
253 Matrix<float, 3, 6> H;
254 H << M, Matrix3f::Zero(3, 3);
256 Matrix<float, 3, 3> S = H * Pq * H.transpose() + R_mag;
258 Matrix<float, 6, 3> K = Pq * H.transpose() * S.inverse();
259 Matrix<float, 6, 1> dx = K * (mag - mEst);
260 Vector4f r{0.5f * dx(0), 0.5f * dx(1), 0.5f * dx(2),
261 sqrtf(1.0f - 0.25f * dx.head<3>().squaredNorm())};
264 x.block<3, 1>(
IDX_BIAS, 0) += dx.tail<3>();
265 Matrix<float, 6, 6> tmp = Matrix<float, 6, 6>::Identity() - K * H;
266 Pq = tmp * Pq * tmp.transpose() + K * R_mag * K.transpose();
279 Vector4f q = x.block<4, 1>(
IDX_QUAT, 0);
283 Vector3f aEst = A * gravityNed;
289 { 0, -aEst(2), aEst(1)},
290 { aEst(2), 0, -aEst(0)},
291 {-aEst(1), aEst(0), 0}
295 Matrix<float, 3, 6> H;
296 H << M, Matrix3f::Zero(3, 3);
298 Matrix<float, 3, 3> S = H * Pq * H.transpose() + R_acc;
300 Matrix<float, 6, 3> K = Pq * H.transpose() * S.inverse();
301 Matrix<float, 6, 1> dx = K * (acc - aEst);
302 Vector4f r{0.5f * dx(0), 0.5f * dx(1), 0.5f * dx(2),
303 sqrtf(1.0f - 0.25f * dx.head<3>().squaredNorm())};
306 x.block<3, 1>(
IDX_BIAS, 0) += dx.tail<3>();
307 Matrix<float, 6, 6> tmp = Matrix<float, 6, 6>::Identity() - K * H;
308 Pq = tmp * Pq * tmp.transpose() + K * R_mag * K.transpose();
320 using namespace Constants;
327 const float qx = x(6);
328 const float qy = x(7);
329 const float qz = x(8);
330 const float qw = x(9);
331 Vector3f vel = x.block<
IDX_VEL, 1>(3, 0);
334 const float T = T0 + a * d;
339 rot_NB << qw * qw + qx * qx - qy * qy - qz * qz,
341 2 * (qx * qy + qw * qz),
342 2 * (qx * qz - qw * qy);
346 const float vbody_x = rot_NB * vel;
349 Matrix<float, 1, 12> dT = Matrix<float, 1, 12>::Zero();
350 dT(2) = -a / powf(T0 + a * d, 2);
353 Matrix<float, 1, 12> dPstat = Matrix<float, 1, 12>::Zero();
354 dPstat(2) = g * P0 / (R * T0) * powf(1 - a * d / T0, -g / (a * R) - 1);
358 Matrix<float, 4, 3> dQuat;
359 dQuat << qw, -qz, qy, qz,
365 Matrix<float, 3, 4> dRot_dQuat;
366 dRot_dQuat << qx, -qy, -qz, qw,
373 Matrix<float, 12, 3> dRot = Matrix<float, 12, 3>::Zero();
374 dRot.block<3, 3>(
IDX_QUAT, 0) = dRot_dQuat * dQuat;
377 Matrix<float, 3, 12> dVel = Matrix<float, 3, 12>::Zero();
378 dVel.block<3, 3>(
IDX_VEL, 0) = Matrix3f::Identity();
381 Vector<float, 12> dVbody =
382 dRot * vel + dVel.transpose() * rot_NB.transpose();
385 const float Ps_est = P0 * powf(1 + a * d / T0, g / (a * R));
388 const float M2 = vbody_x * vbody_x / (GAMMA_AIR * R * T);
393 (powf(1 + (GAMMA_AIR - 1) / 2 * M2, GAMMA_AIR / (GAMMA_AIR - 1)) - 1);
397 (1 + (GAMMA_AIR - 1) / 2 * vbody_x * vbody_x / (GAMMA_AIR * R * T));
400 Matrix<float, 1, 12> dalpha_vel = 2 * vbody_x * (GAMMA_AIR - 1) /
401 (2 * GAMMA_AIR * R * T) *
405 Matrix<float, 1, 12> dalpha_temp =
406 (GAMMA_AIR - 1) * vbody_x * vbody_x / (2 * GAMMA_AIR * R) * dT;
409 Matrix<float, 1, 12> dalpha = dalpha_vel + dalpha_temp;
412 const float beta = powf(alpha, GAMMA_AIR / (GAMMA_AIR - 1));
415 Matrix<float, 1, 12> dbeta = GAMMA_AIR / (GAMMA_AIR - 1) *
416 powf(alpha, GAMMA_AIR / (GAMMA_AIR - 1) - 1) *
420 Matrix<float, 1, 12> dPtot = beta * dPstat + Ps_est * dbeta;
423 Matrix<float, 1, 12> dPdyn = dPtot - dPstat;
426 Matrix<float, 2, 12> H;
431 if (H.array().isNaN().any())
435 Matrix2f R_mat = Matrix2f::Zero();
439 Matrix2f S = H * P * H.transpose() + R_mat;
442 if (S.determinant() < 1e-3)
447 (Vector2f() << staticPressure - Ps_est, dynamicPressure - Pd_est)
451 Matrix<float, 12, 2> K = P * H.transpose() * S.inverse();
454 Matrix<float, 13, 1> correction = Matrix<float, 13, 1>::Zero();
455 correction.block<6, 1>(
IDX_POS, 0) = (K * e).block<6, 1>(
IDX_POS, 0);
461 P = (Matrix<float, 12, 12>::Identity() - K * H) * P;
473void NAS::setX(
const Matrix<float, 13, 1>& x) { this->x = x; }
477 this->reference = reference;
486 {config.
P_POS, 0, 0},
487 {0, config.
P_POS, 0},
491 {config.
P_VEL, 0, 0},
492 {0, config.
P_VEL, 0},
495 Matrix3f P_att = Matrix3f::Identity() * config.
P_ATT;
496 Matrix3f P_bias = Matrix3f::Identity() * config.
P_BIAS;
497 P << P_pos, MatrixXf::Zero(3, 9),
498 MatrixXf::Zero(3, 3), P_vel, MatrixXf::Zero(3, 6),
499 MatrixXf::Zero(3, 6), P_att, MatrixXf::Zero(3, 3),
500 MatrixXf::Zero(3, 9), P_bias;
void predictGyro(const Eigen::Vector3f &angularSpeed)
Prediction with gyroscope data.
void correctPitot(const float staticPressure, const float dynamicPressure)
Correction with pitot pressures.
Eigen::Matrix< float, 13, 1 > getX() const
void resetCovariance()
Resets the covariance matrix to the initial state based on the configuration.
void predictAcc(const Eigen::Vector3f &acceleration)
Prediction with accelerometer data.
static constexpr uint16_t IDX_BIAS
NASState getState() const
void correctAcc(const Eigen::Vector3f &acc)
Correction with accelerometer data.
void correctMag(const Eigen::Vector3f &mag)
Correction with magnetometer data.
void setState(const NASState &state)
NAS(const NASConfig &config)
static constexpr uint16_t IDX_POS
< Index of position elements in the state.
void correctGPS(const Eigen::Vector4f &gps)
Correction with gps data.
void setReferenceValues(const ReferenceValues &reference)
Changes the reference values.
void correctBaro(const float pressure)
Correction with barometer data.
static constexpr uint16_t IDX_VEL
Index of quaternions elements in the state.
ReferenceValues getReferenceValues()
Returns the current reference values.
static constexpr uint16_t IDX_QUAT
Index of bias elements in the state.
void setX(const Eigen::Matrix< float, 13, 1 > &x)
float relPressure(float altitude, float pressureRef, float temperatureRef)
Returns the pressure given the altitude with respect to a reference pressure and temperature,...
float relTemperature(float altitude, float temperatureRef)
Returns the temperature at the given altitude with respect to the reference temperature.
Matrix3f quat2rotationMatrix(const Vector4f &q)
Vector4f quatProd(const Vector4f &q1, const Vector4f &q2)
uint64_t getTimestamp()
Returns the current timer value in microseconds.
Driver for the VN100S IMU.
Structure to handle accelerometer data.
Structure to handle GPS data.
Structure to handle gyroscope data.
Structure to handle magnetometer data.
float SIGMA_ACC
[m/s^2] Estimated accelerometer variance
Eigen::Vector4f SIGMA_GPS
float SIGMA_POS
[m] Estimated variance of the position noise
float P_ATT
Attitude prediction covariance.
float P_POS
Position prediction covariance horizontal.
float SIGMA_PITOT_DYNAMIC
float SIGMA_BETA
[rad/s^2] Estimated gyroscope bias variance
float P_BIAS
Bias prediction covariance.
Eigen::Vector3f NED_MAG
Normalized magnetic field vector in NED frame.
float SIGMA_W
[rad] Estimated gyroscope variance
float P_POS_VERTICAL
Position prediction covariance vertical.
float SIGMA_VEL
[m/s] Estimated variance of the velocity noise
float SIGMA_MAG
[uT] Estimated magnetometer variance
float P_VEL
Velocity prediction covariance horizontal.
float SIGMA_BAR
[Pa] Estimated altitude variance
float P_VEL_VERTICAL
Velocity prediction covariance vertical.
Eigen::Matrix< float, 13, 1 > getX() const
Reference values for the Apogee Detection Algorithm.