[module] wind estimation from quadrotor motion (#2800)

- add a generic linear kalman filter lib
- add a quad model with linear drag and simplified for recent jsbsim
- add example frame and noisy NPS sensor config

see "Estimating wind using a quadrotor" in IMAV2021 proceedings
This commit is contained in:
Gautier Hattenberger
2021-11-28 22:24:44 +01:00
committed by GitHub
parent fb0a7a0eb1
commit e075daf06f
14 changed files with 1412 additions and 8 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,50 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="wind_estimation_quadrotor" dir="meteo">
<doc>
<description>
Wind estimation from quadrotor motion
Estimation using a linear Kalman filter
For details, see:
G. Hattenberger, M. Bronz, and J. Condomines, “Estimating wind using a quadrotor,”
in 12th international micro air vehicle conference, Puebla, México, 2021, p. 124–130.
</description>
<section name="WE_QUAD" prefix="WE_QUAD_">
<define name="MASS" value="required" description="mass of the airframe" unit="kg"/>
<define name="DRAG" value="required" description="linear drag coefficient modeling the relation between drag and bank angle"/>
<define name="P0_VA" value="1." description="initial covariance on airspeed estimate"/>
<define name="P0_W" value="1." description="initial covariance on wind estimate"/>
<define name="Q_VA" value="0.05" description="process noise on airspeed"/>
<define name="Q_W" value="0.001" description="process noise on wind estimate"/>
<define name="R" value="0.5" description="measurement noise on ground speed"/>
<define name="UPDATE_STATE" value="FALSE|TRUE" description="update directly wind estimation in state interface (default: TRUE)"/>
</section>
</doc>
<settings>
<dl_settings>
<dl_settings name="Wind quad">
<dl_setting MIN="0.001" MAX="1" STEP="0.01" VAR="we_quad_params.Q_va" shortname="Q_va" module="meteo/wind_estimation_quadrotor" handler="SetQva"/>
<dl_setting MIN="0.001" MAX="0.1" STEP="0.001" VAR="we_quad_params.Q_w" shortname="Q_w" module="meteo/wind_estimation_quadrotor" handler="SetQw"/>
<dl_setting MIN="0.01" MAX="3" STEP="0.01" VAR="we_quad_params.R" shortname="R" module="meteo/wind_estimation_quadrotor" handler="SetR"/>
</dl_settings>
</dl_settings>
</settings>
<header>
<file name="wind_estimation_quadrotor.h"/>
</header>
<init fun="wind_estimation_quadrotor_init()"/>
<periodic fun="wind_estimation_quadrotor_periodic()" freq="10.0" start="wind_estimation_quadrotor_stop()" stop="wind_estimation_quadrotor_start()" autorun="FALSE"/>
<periodic fun="wind_estimation_quadrotor_report()" freq="10.0" autorun="FALSE"/>
<makefile>
<file name="wind_estimation_quadrotor.c"/>
<file name="linear_kalman_filter.c" dir="filters"/>
<test>
<define name="WE_QUAD_MASS" value="1."/>
<define name="WE_QUAD_DRAG" value="1."/>
<define name="DOWNLINK_TRANSPORT" value="pprz_tp"/>
<define name="DOWNLINK_DEVICE" value="uart0"/>
<define name="USE_UART0"/>
<define name="WIND_ESTIMATION_QUADROTOR_PERIODIC_PERIOD" value="0.1"/>
</test>
</makefile>
</module>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,194 @@
/*
* Copyright (C) 2012 Felix Ruess <felix.ruess@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef NPS_SENSORS_PARAMS_H
#define NPS_SENSORS_PARAMS_H
#include "generated/airframe.h"
#include "modules/imu/imu.h"
#define NPS_BODY_TO_IMU_PHI IMU_BODY_TO_IMU_PHI
#define NPS_BODY_TO_IMU_THETA IMU_BODY_TO_IMU_THETA
#define NPS_BODY_TO_IMU_PSI IMU_BODY_TO_IMU_PSI
// try to determine propagate frequency
#if defined AHRS_PROPAGATE_FREQUENCY
#define NPS_PROPAGATE AHRS_PROPAGATE_FREQUENCY
#elif defined INS_PROPAGATE_FREQUENCY
#define NPS_PROPAGATE INS_PROPAGATE_FREQUENCY
#elif defined PERIODIC_FREQUENCY
#define NPS_PROPAGATE PERIODIC_FREQUENCY
#else
#define 512. // historical magic number
#endif
/*
* Accelerometer
*/
/* assume resolution is less than 16 bits, so saturation will not occur */
#ifndef NPS_ACCEL_MIN
#define NPS_ACCEL_MIN -65536
#endif
#ifndef NPS_ACCEL_MAX
#define NPS_ACCEL_MAX 65536
#endif
/* ms-2 */
/* aka 2^10/ACCEL_X_SENS */
#define NPS_ACCEL_SENSITIVITY_XX (IMU_ACCEL_X_SIGN * ACCEL_BFP_OF_REAL(1./IMU_ACCEL_X_SENS))
#define NPS_ACCEL_SENSITIVITY_YY (IMU_ACCEL_Y_SIGN * ACCEL_BFP_OF_REAL(1./IMU_ACCEL_Y_SENS))
#define NPS_ACCEL_SENSITIVITY_ZZ (IMU_ACCEL_Z_SIGN * ACCEL_BFP_OF_REAL(1./IMU_ACCEL_Z_SENS))
#define NPS_ACCEL_NEUTRAL_X IMU_ACCEL_X_NEUTRAL
#define NPS_ACCEL_NEUTRAL_Y IMU_ACCEL_Y_NEUTRAL
#define NPS_ACCEL_NEUTRAL_Z IMU_ACCEL_Z_NEUTRAL
/* m2s-4 */
#define NPS_ACCEL_NOISE_STD_DEV_X .5
#define NPS_ACCEL_NOISE_STD_DEV_Y .5
#define NPS_ACCEL_NOISE_STD_DEV_Z .5
/* ms-2 */
#define NPS_ACCEL_BIAS_X 0
#define NPS_ACCEL_BIAS_Y 0
#define NPS_ACCEL_BIAS_Z 0
/* s */
#ifndef NPS_ACCEL_DT
#define NPS_ACCEL_DT (1./NPS_PROPAGATE)
#endif
/*
* Gyrometer
*/
/* assume resolution is less than 16 bits, so saturation will not occur */
#ifndef NPS_GYRO_MIN
#define NPS_GYRO_MIN -65536
#endif
#ifndef NPS_GYRO_MAX
#define NPS_GYRO_MAX 65536
#endif
/* 2^12/GYRO_X_SENS */
#define NPS_GYRO_SENSITIVITY_PP (IMU_GYRO_P_SIGN * RATE_BFP_OF_REAL(1./IMU_GYRO_P_SENS))
#define NPS_GYRO_SENSITIVITY_QQ (IMU_GYRO_Q_SIGN * RATE_BFP_OF_REAL(1./IMU_GYRO_Q_SENS))
#define NPS_GYRO_SENSITIVITY_RR (IMU_GYRO_R_SIGN * RATE_BFP_OF_REAL(1./IMU_GYRO_R_SENS))
#define NPS_GYRO_NEUTRAL_P IMU_GYRO_P_NEUTRAL
#define NPS_GYRO_NEUTRAL_Q IMU_GYRO_Q_NEUTRAL
#define NPS_GYRO_NEUTRAL_R IMU_GYRO_R_NEUTRAL
#define NPS_GYRO_NOISE_STD_DEV_P RadOfDeg(9.)
#define NPS_GYRO_NOISE_STD_DEV_Q RadOfDeg(9.)
#define NPS_GYRO_NOISE_STD_DEV_R RadOfDeg(9.)
#define NPS_GYRO_BIAS_INITIAL_P RadOfDeg( 0.0)
#define NPS_GYRO_BIAS_INITIAL_Q RadOfDeg( 0.0)
#define NPS_GYRO_BIAS_INITIAL_R RadOfDeg( 0.0)
#define NPS_GYRO_BIAS_RANDOM_WALK_STD_DEV_P RadOfDeg(0.5)
#define NPS_GYRO_BIAS_RANDOM_WALK_STD_DEV_Q RadOfDeg(0.5)
#define NPS_GYRO_BIAS_RANDOM_WALK_STD_DEV_R RadOfDeg(0.5)
/* s */
#ifndef NPS_GYRO_DT
#define NPS_GYRO_DT (1./NPS_PROPAGATE)
#endif
/*
* Magnetometer
*/
/* assume resolution is less than 16 bits, so saturation will not occur */
#ifndef NPS_MAG_MIN
#define NPS_MAG_MIN -65536
#endif
#ifndef NPS_MAG_MAX
#define NPS_MAG_MAX 65536
#endif
#define NPS_MAG_IMU_TO_SENSOR_PHI 0.
#define NPS_MAG_IMU_TO_SENSOR_THETA 0.
#define NPS_MAG_IMU_TO_SENSOR_PSI 0.
#define NPS_MAG_SENSITIVITY_XX (IMU_MAG_X_SIGN * MAG_BFP_OF_REAL(1./IMU_MAG_X_SENS))
#define NPS_MAG_SENSITIVITY_YY (IMU_MAG_Y_SIGN * MAG_BFP_OF_REAL(1./IMU_MAG_Y_SENS))
#define NPS_MAG_SENSITIVITY_ZZ (IMU_MAG_Z_SIGN * MAG_BFP_OF_REAL(1./IMU_MAG_Z_SENS))
#define NPS_MAG_NEUTRAL_X IMU_MAG_X_NEUTRAL
#define NPS_MAG_NEUTRAL_Y IMU_MAG_Y_NEUTRAL
#define NPS_MAG_NEUTRAL_Z IMU_MAG_Z_NEUTRAL
#define NPS_MAG_NOISE_STD_DEV_X 2e-1
#define NPS_MAG_NOISE_STD_DEV_Y 2e-1
#define NPS_MAG_NOISE_STD_DEV_Z 2e-1
#ifndef NPS_MAG_DT
#define NPS_MAG_DT (1./100.)
#endif
/*
* Barometer (pressure and std dev in Pascal)
*/
#define NPS_BARO_DT (1./50.)
#define NPS_BARO_NOISE_STD_DEV 2
/*
* GPS
*/
#ifndef GPS_PERFECT
#define GPS_PERFECT 0
#endif
#if GPS_PERFECT
#define NPS_GPS_SPEED_NOISE_STD_DEV 0.
#define NPS_GPS_SPEED_LATENCY 0.
#define NPS_GPS_POS_NOISE_STD_DEV 0.001
#define NPS_GPS_POS_BIAS_INITIAL_X 0.
#define NPS_GPS_POS_BIAS_INITIAL_Y 0.
#define NPS_GPS_POS_BIAS_INITIAL_Z 0.
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_X 0.
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_Y 0.
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_Z 0.
#define NPS_GPS_POS_LATENCY 0.
#else
#define NPS_GPS_SPEED_NOISE_STD_DEV 0.5
#define NPS_GPS_SPEED_LATENCY 0.2
#define NPS_GPS_POS_NOISE_STD_DEV 2
#define NPS_GPS_POS_BIAS_INITIAL_X 0e-1
#define NPS_GPS_POS_BIAS_INITIAL_Y -0e-1
#define NPS_GPS_POS_BIAS_INITIAL_Z -0e-1
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_X 1e-3
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_Y 1e-3
#define NPS_GPS_POS_BIAS_RANDOM_WALK_STD_DEV_Z 1e-3
#define NPS_GPS_POS_LATENCY 0.2
#endif /* GPS_PERFECT */
#ifndef NPS_GPS_DT
#define NPS_GPS_DT (1./10.)
#endif
#endif /* NPS_SENSORS_PARAMS_H */
+1
View File
@@ -35,6 +35,7 @@
<message name="LOGGER_STATUS" period="5.1"/>
<message name="LIDAR" period="1.2"/>
<message name="INS_EKF2" period=".25"/>
<message name="WIND_INFO_RET" period="1."/>
</mode>
<mode name="ppm">
+149
View File
@@ -0,0 +1,149 @@
/*
* Copyright (C) 2021 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file "filters/linear_kalman_filter.c"
*
* Generic discrete Linear Kalman Filter
*/
#include "filters/linear_kalman_filter.h"
#include "math/pprz_algebra_float.h"
/** Init all matrix and vectors to zero
*
* @param filter pointer to a filter structure
* @param n size of the state vector
* @param c size of the command vector
* @param m size of the measurement vector
* @return false if n, c or m are larger than the maximum value
*/
bool linear_kalman_filter_init(struct linear_kalman_filter *filter, uint8_t n, uint8_t c, uint8_t m)
{
if (n > KF_MAX_STATE_SIZE || c > KF_MAX_CMD_SIZE || m > KF_MAX_MEAS_SIZE) {
filter->n = 0;
filter->c = 0;
filter->m = 0;
return false; // invalide sizes;
}
filter->n = n;
filter->c = c;
filter->m = m;
// Matrix
MAKE_MATRIX_PTR(_A, filter->A, n);
float_mat_zero(_A, n, n);
MAKE_MATRIX_PTR(_B, filter->B, n);
float_mat_zero(_B, n, c);
MAKE_MATRIX_PTR(_C, filter->C, m);
float_mat_zero(_C, m, n);
MAKE_MATRIX_PTR(_P, filter->P, n);
float_mat_zero(_P, n, n);
MAKE_MATRIX_PTR(_Q, filter->Q, n);
float_mat_zero(_Q, n, n);
MAKE_MATRIX_PTR(_R, filter->R, m);
float_mat_zero(_R, m, m);
// Vector
float_vect_zero(filter->X, n);
return true;
}
/** Prediction step
*
* X = Ad * X + Bd * U
* P = Ad * P * Ad' + Q
*
* @param filter pointer to the filter structure
* @param U command vector
*/
void linear_kalman_filter_predict(struct linear_kalman_filter *filter, float *U)
{
float AX[filter->n];
float BU[filter->n];
float tmp[filter->n][filter->n];
MAKE_MATRIX_PTR(_A, filter->A, filter->n);
MAKE_MATRIX_PTR(_B, filter->B, filter->n);
MAKE_MATRIX_PTR(_P, filter->P, filter->n);
MAKE_MATRIX_PTR(_Q, filter->Q, filter->n);
MAKE_MATRIX_PTR(_tmp, tmp, filter->n);
// X = A * X + B * U
float_mat_vect_mul(AX, _A, filter->X, filter->n, filter->n);
float_mat_vect_mul(BU, _B, U, filter->n, filter->c);
float_vect_sum(filter->X, AX, BU, filter->n);
// P = A * P * A' + Q
float_mat_mul(_tmp, _A, _P, filter->n, filter->n, filter->n); // A * P
float_mat_mul_transpose(_P, _tmp, _A, filter->n, filter->n, filter->n); // * A'
float_mat_sum(_P, _P, _Q, filter->n, filter->n); // + Q
}
/** Update step
*
* S = Cd * P * Cd' + R
* K = P * Cd' / S
* X = X + K * (Y - Cd * X)
* P = P - K * Cd * P
*
* @param filter pointer to the filter structure
* @param Y measurement vector
*/
extern void linear_kalman_filter_update(struct linear_kalman_filter *filter, float *Y)
{
float S[filter->m][filter->m];
float K[filter->n][filter->m];
float tmp1[filter->n][filter->m];
float tmp2[filter->n][filter->n];
MAKE_MATRIX_PTR(_P, filter->P, filter->n);
MAKE_MATRIX_PTR(_C, filter->C, filter->m);
MAKE_MATRIX_PTR(_R, filter->R, filter->m);
MAKE_MATRIX_PTR(_S, S, filter->m);
MAKE_MATRIX_PTR(_K, K, filter->n);
MAKE_MATRIX_PTR(_tmp1, tmp1, filter->n);
MAKE_MATRIX_PTR(_tmp2, tmp2, filter->n);
// S = Cd * P * Cd' + R
float_mat_mul_transpose(_tmp1, _P, _C, filter->n, filter->n, filter->m); // P * C'
float_mat_mul(_S, _C, _tmp1, filter->m, filter->n, filter->m); // C *
float_mat_sum(_S, _S, _R, filter->m, filter->m); // + R
// K = P * Cd' * inv(S)
float_mat_invert(_S, _S, filter->m); // inv(S) in place
float_mat_mul(_K, _tmp1, _S, filter->n, filter->m, filter->m); // tmp1 {P*C'} * inv(S)
// P = P - K * C * P
float_mat_mul(_tmp2, _K, _C, filter->n, filter->m, filter->n); // K * C
float_mat_mul_copy(_tmp2, _tmp2, _P, filter->n, filter->n, filter->n); // * P
float_mat_diff(_P, _P, _tmp2, filter->n, filter->n); // P - K*H*P
// X = X + K * err
float err[filter->n];
float dx_err[filter->n];
float_mat_vect_mul(err, _C, filter->X, filter->m, filter->n); // C * X
float_vect_diff(err, Y, err, filter->m); // err = Y - C * X
float_mat_vect_mul(dx_err, _K, err, filter->n, filter->m); // K * err
float_vect_sum(filter->X, filter->X, dx_err, filter->n); // X + dx_err
}
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2021 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file "filters/linear_kalman_filter.c"
*
* Generic discrete Linear Kalman Filter
*/
#ifndef LINEAR_KALMAN_FILTER_H
#define LINEAR_KALMAN_FILTER_H
#include "std.h"
// maximum size for the state vector
#ifndef KF_MAX_STATE_SIZE
#define KF_MAX_STATE_SIZE 6
#endif
// maximum size for the command vector
#ifndef KF_MAX_CMD_SIZE
#define KF_MAX_CMD_SIZE 2
#endif
// maximum size for the measurement vector
#ifndef KF_MAX_MEAS_SIZE
#define KF_MAX_MEAS_SIZE 6
#endif
struct linear_kalman_filter {
// filled by user after calling init function
float A[KF_MAX_STATE_SIZE][KF_MAX_STATE_SIZE]; ///< dynamic matrix
float B[KF_MAX_STATE_SIZE][KF_MAX_CMD_SIZE]; ///< command matrix
float C[KF_MAX_MEAS_SIZE][KF_MAX_STATE_SIZE]; ///< observation matrix
float P[KF_MAX_STATE_SIZE][KF_MAX_STATE_SIZE]; ///< state covariance matrix
float Q[KF_MAX_STATE_SIZE][KF_MAX_STATE_SIZE]; ///< proces covariance noise
float R[KF_MAX_MEAS_SIZE][KF_MAX_MEAS_SIZE]; ///< measurement covariance noise
float X[KF_MAX_STATE_SIZE]; ///< estimated state X
uint8_t n; ///< state vector size (<= KF_MAX_STATE_SIZE)
uint8_t c; ///< command vector size (<= KF_MAX_CMD_SIZE)
uint8_t m; ///< measurement vector size (<= KF_MAX_MEAS_SIZE)
};
/** Init all matrix and vectors to zero
*
* @param filter pointer to a filter structure
* @param n size of the state vector
* @param c size of the command vector
* @param m size of the measurement vector
* @return false if n, c or m are larger than the maximum value
*/
extern bool linear_kalman_filter_init(struct linear_kalman_filter *filter, uint8_t n, uint8_t c, uint8_t m);
/** Prediction step
*
* X = Ad * X + Bd * U
* P = Ad * P * Ad' + Q
*
* @param filter pointer to the filter structure
* @param U command vector
*/
extern void linear_kalman_filter_predict(struct linear_kalman_filter *filter, float *U);
/** Update step
*
* S = Cd * P * Cd' + R
* K = P * Cd' / S
* X = X + K * (Y - Cd * X)
* P = P - K * Cd * P
*
* @param filter pointer to the filter structure
* @param Y measurement vector
*/
extern void linear_kalman_filter_update(struct linear_kalman_filter *filter, float *Y);
#endif /* DISCRETE_EKF_H */
+19
View File
@@ -728,6 +728,25 @@ static inline void float_mat_mul(float **o, float **a, float **b, int m, int n,
}
}
/** o = a * b'
*
* a: [m x n]
* b: [l x n]
* o: [m x l]
*/
static inline void float_mat_mul_transpose(float **o, float **a, float **b, int m, int n, int l)
{
int i, j, k;
for (i = 0; i < m; i++) {
for (j = 0; j < l; j++) {
o[i][j] = 0.;
for (k = 0; k < n; k++) {
o[i][j] += a[i][k] * b[j][k];
}
}
}
}
/** o = a * b
*
* a: [m x n]
+31 -8
View File
@@ -327,15 +327,9 @@ float get_tas_factor(float p, float t)
}
/**
* Calculate true airspeed from equivalent airspeed.
*
* True airspeed (TAS) from EAS:
* TAS = air_data.tas_factor * EAS
*
* @param eas equivalent airspeed (EAS) in m/s
* @return true airspeed in m/s
* Internal utility function to compute current tas factor if needed
*/
float tas_from_eas(float eas)
static void compute_tas_factor(void)
{
// update tas factor if requested
if (air_data.calc_tas_factor) {
@@ -351,9 +345,38 @@ float tas_from_eas(float eas)
air_data.tas_factor = get_tas_factor(p, CelsiusOfKelvin(t));
}
}
}
/**
* Calculate true airspeed from equivalent airspeed.
*
* True airspeed (TAS) from EAS:
* TAS = air_data.tas_factor * EAS
*
* @param eas equivalent airspeed (EAS) in m/s
* @return true airspeed in m/s
*/
float tas_from_eas(float eas)
{
compute_tas_factor();
return air_data.tas_factor * eas;
}
/**
* Calculate equivalent airspeed from true airspeed.
*
* EAS from True airspeed (TAS):
* EAS = TAS / air_data.tas_factor
*
* @param tas true airspeed (TAS) in m/s
* @return equivalent airspeed in m/s
*/
float eas_from_tas(float tas)
{
compute_tas_factor();
return tas / air_data.tas_factor;
}
/**
* Calculate true airspeed from dynamic pressure.
* Dynamic pressure @f$q@f$ (also called impact pressure) is the
+8
View File
@@ -101,6 +101,14 @@ extern float get_tas_factor(float p, float t);
*/
extern float tas_from_eas(float eas);
/**
* Calculate equivalent airspeed from true airspeed.
*
* @param tas true airspeed (TAS) in m/s
* @return equivalent airspeed in m/s
*/
extern float eas_from_tas(float tas);
/**
* Calculate true airspeed from dynamic pressure.
* Dynamic pressure @f$q@f$ (also called impact pressure) is the
@@ -111,6 +111,10 @@
#define AIRSPEED_ETS_ID 4
#endif
#ifndef AIRSPEED_WE_QUAD_ID
#define AIRSPEED_WE_QUAD_ID 5
#endif
/*
* IDs of Incidence angles (message 24)
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 Gautier Hattenberger <gautier.hattenberger@enac.fr>
*
* This file is part of paparazzi
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/** @file "modules/meteo/wind_estimation_quadrotor.h"
* @author Gautier Hattenberger <gautier.hattenberger@enac.fr>
* Wind estimation from quadrotor motion
*/
#ifndef WIND_ESTIMATION_QUADROTOR_H
#define WIND_ESTIMATION_QUADROTOR_H
struct wind_estimation_quadrotor_params {
float Q_va; ///< model noise on airspeed
float Q_w; ///< model noise on wind
float R; ///< measurement noise (ground speed)
};
extern struct wind_estimation_quadrotor_params we_quad_params;
extern void wind_estimation_quadrotor_init(void);
extern void wind_estimation_quadrotor_periodic(void);
extern void wind_estimation_quadrotor_stop(void);
extern void wind_estimation_quadrotor_start(void);
extern void wind_estimation_quadrotor_report(void);
extern float wind_estimation_quadrotor_SetQva(float Q_va);
extern float wind_estimation_quadrotor_SetQw(float Q_w);
extern float wind_estimation_quadrotor_SetR(float R);
#endif // WIND_ESTIMATION_QUADROTOR_H
+1
View File
@@ -576,6 +576,7 @@ static void init_jsbsim(double dt)
delete FDMExec;
exit(-1);
}
cout << "JSBSim model loaded from " << NPS_JSBSIM_MODEL << endl;
#ifdef DEBUG
cerr << "NumEngines: " << FDMExec->GetPropulsion()->GetNumEngines() << endl;