36 #include "generated/airframe.h"
41 #define PRINT_DBG(_l, _p) { \
42 if (DBG_LEVEL >= _l) \
46 #define PRINT_DBG(_l, _p) {}
50 #ifndef AHRS_PROPAGATE_FREQUENCY
51 #define AHRS_PROPAGATE_FREQUENCY PERIODIC_FREQUENCY
55 #if AHRS_PROPAGATE_FREQUENCY == 512
56 #define HFF_PRESCALER 16
57 #elif AHRS_PROPAGATE_FREQUENCY == 500
58 #define HFF_PRESCALER 10
60 #error "HFF_PRESCALER not set, needs to be a divisor of AHRS_PROPAGATE_FREQUENCY"
65 #define HFF_FREQ ((AHRS_PROPAGATE_FREQUENCY)/HFF_PRESCALER)
66 #define DT_HFILTER (1./HFF_FREQ)
71 #ifndef HFF_ACCEL_NOISE
72 #define HFF_ACCEL_NOISE 0.5
74 #define Q HFF_ACCEL_NOISE*DT_HFILTER*DT_HFILTER/2.
75 #define Qdotdot HFF_ACCEL_NOISE*DT_HFILTER
82 #define HFF_R_POS_MIN 3.
86 #define HFF_R_SPEED 2.
88 #ifndef HFF_R_SPEED_MIN
89 #define HFF_R_SPEED_MIN 1.
92 #ifndef HFF_UPDATE_SPEED
93 #define HFF_UPDATE_SPEED TRUE
96 #ifndef HFF_LOWPASS_CUTOFF_FREQUENCY
97 #define HFF_LOWPASS_CUTOFF_FREQUENCY 14
100 #if HFF_LOWPASS_CUTOFF_FREQUENCY < 8
101 #error "It is not allowed to use a cutoff frequency lower than 8Hz due to overflow issues."
150 #define GPS_LAG_N ((int) (GPS_LAG * HFF_FREQ + 0.5))
152 #define GPS_DT_N ((int) (HFF_FREQ / 4))
154 #define GPS_LAG_TOLERANCE 0.08
155 #define GPS_LAG_TOL_N ((int) (GPS_LAG_TOLERANCE * HFF_FREQ + 0.5))
161 #define MAX_PP_STEPS 6
164 #define ACC_BUF_MAXN (GPS_LAG_N+10)
165 #define INC_ACC_IDX(idx) { idx = (idx + 1) < ACC_BUF_MAXN ? (idx + 1) : 0; }
170 static unsigned int acc_buf_r;
171 static unsigned int acc_buf_w;
172 static unsigned int acc_buf_n;
178 #define HFF_RB_MAXN ((int) (GPS_LAG * 4))
179 #define INC_RB_POINTER(ptr) { \
180 if (ptr == &b2_hff_rb[HFF_RB_MAXN-1]) \
205 #define HFF_LOST_LIMIT 1000
210 static void b2_hff_get_past_accel(
unsigned int back_n);
211 static void b2_hff_rb_put_state(
struct HfilterFloat *source);
212 static void b2_hff_rb_drop_last(
void);
229 #if PERIODIC_TELEMETRY
234 pprz_msg_send_HFF(trans, dev, AC_ID,
245 pprz_msg_send_HFF_DBG(trans, dev, AC_ID,
259 pprz_msg_send_HFF_GPS(trans, dev, AC_ID,
268 void b2_hff_init(
float init_x,
float init_xdot,
float init_y,
float init_ydot)
279 b2_hff_rb_put = b2_hff_rb;
280 b2_hff_rb_last = b2_hff_rb;
285 printf(
"GPS_LAG: %f\n", GPS_LAG);
286 printf(
"GPS_LAG_N: %d\n", GPS_LAG_N);
287 printf(
"GPS_DT_N: %d\n", GPS_DT_N);
289 printf(
"GPS_LAG_TOL_N: %i\n", GPS_LAG_TOL_N);
304 #if PERIODIC_TELEMETRY
344 static void b2_hff_store_accel_ltp(
float x,
float y)
346 past_accel[acc_buf_w].x =
x;
347 past_accel[acc_buf_w].y =
y;
348 INC_ACC_IDX(acc_buf_w);
350 if (acc_buf_n < ACC_BUF_MAXN) {
353 INC_ACC_IDX(acc_buf_r);
358 static void b2_hff_get_past_accel(
unsigned int back_n)
361 if (back_n > acc_buf_n) {
362 PRINT_DBG(1, (
"Cannot go back %d steps, going back only %d instead!\n", back_n, acc_buf_n));
364 }
else if (back_n == 0) {
365 PRINT_DBG(1, (
"Cannot go back zero steps!\n"));
368 if ((
int)(acc_buf_w - back_n) < 0) {
369 i = acc_buf_w - back_n + ACC_BUF_MAXN;
371 i = acc_buf_w - back_n;
375 PRINT_DBG(3, (
"get past accel. buf_n: %2d \tbuf_w: %2d \tback_n: %2d \ti: %2d \txdd: %f \tydd: %f\n", acc_buf_n,
379 static void b2_hff_rb_put_state(
struct HfilterFloat *source)
382 b2_hff_set_state(b2_hff_rb_put, source);
387 INC_RB_POINTER(b2_hff_rb_put);
393 INC_RB_POINTER(b2_hff_rb_last);
398 static void b2_hff_rb_drop_last(
void)
401 INC_RB_POINTER(b2_hff_rb_last);
404 PRINT_DBG(2, (
"hff ringbuffer empty!\n"));
422 dest->
xP[i][j] = source->
xP[i][j];
423 dest->
yP[i][j] = source->
yP[i][j];
428 static void b2_hff_propagate_past(
struct HfilterFloat *hff_past)
432 for (
int i = 0; i < MAX_PP_STEPS; i++) {
446 b2_hff_rb_put_state(hff_past);
450 if (hff_past == &b2_hff_rb[HFF_RB_MAXN - 1]) {
451 b2_hff_rb[0].lag_counter++;
461 b2_hff_rb_drop_last();
479 b2_hff_propagate_past(b2_hff_rb_last);
549 if (GPS_LAG_N == 0) {
577 b2_hff_propagate_past(b2_hff_rb_last);
580 PRINT_DBG(2, (
"try next saved state\n"));
581 b2_hff_rb_drop_last();
602 b2_hff_rb_drop_last();
633 hff_work->
x = hff_work->
x + dt * hff_work->
xdot + dt * dt / 2 * hff_work->
xdotdot;
636 const float FPF00 = hff_work->
xP[0][0] + dt * (hff_work->
xP[1][0] + hff_work->
xP[0][1] + dt * hff_work->
xP[1][1]);
637 const float FPF01 = hff_work->
xP[0][1] + dt * hff_work->
xP[1][1];
638 const float FPF10 = hff_work->
xP[1][0] + dt * hff_work->
xP[1][1];
639 const float FPF11 = hff_work->
xP[1][1];
641 hff_work->
xP[0][0] = FPF00 +
Q;
642 hff_work->
xP[0][1] = FPF01;
643 hff_work->
xP[1][0] = FPF10;
651 hff_work->
y = hff_work->
y + dt * hff_work->
ydot + dt * dt / 2 * hff_work->
ydotdot;
654 const float FPF00 = hff_work->
yP[0][0] + dt * (hff_work->
yP[1][0] + hff_work->
yP[0][1] + dt * hff_work->
yP[1][1]);
655 const float FPF01 = hff_work->
yP[0][1] + dt * hff_work->
yP[1][1];
656 const float FPF10 = hff_work->
yP[1][0] + dt * hff_work->
yP[1][1];
657 const float FPF11 = hff_work->
yP[1][1];
659 hff_work->
yP[0][0] = FPF00 +
Q;
660 hff_work->
yP[0][1] = FPF01;
661 hff_work->
yP[1][0] = FPF10;
695 const float y = x_meas - hff_work->
x;
696 const float S = hff_work->
xP[0][0] + Rpos;
697 const float K1 = hff_work->
xP[0][0] * 1 / S;
698 const float K2 = hff_work->
xP[1][0] * 1 / S;
700 hff_work->
x = hff_work->
x + K1 * y;
701 hff_work->
xdot = hff_work->
xdot + K2 * y;
703 const float P11 = (1. - K1) * hff_work->
xP[0][0];
704 const float P12 = (1. - K1) * hff_work->
xP[0][1];
705 const float P21 = -K2 * hff_work->
xP[0][0] + hff_work->
xP[1][0];
706 const float P22 = -K2 * hff_work->
xP[0][1] + hff_work->
xP[1][1];
708 hff_work->
xP[0][0] = P11;
709 hff_work->
xP[0][1] = P12;
710 hff_work->
xP[1][0] = P21;
711 hff_work->
xP[1][1] = P22;
718 const float y = y_meas - hff_work->
y;
719 const float S = hff_work->
yP[0][0] + Rpos;
720 const float K1 = hff_work->
yP[0][0] * 1 / S;
721 const float K2 = hff_work->
yP[1][0] * 1 / S;
723 hff_work->
y = hff_work->
y + K1 * y;
724 hff_work->
ydot = hff_work->
ydot + K2 * y;
726 const float P11 = (1. - K1) * hff_work->
yP[0][0];
727 const float P12 = (1. - K1) * hff_work->
yP[0][1];
728 const float P21 = -K2 * hff_work->
yP[0][0] + hff_work->
yP[1][0];
729 const float P22 = -K2 * hff_work->
yP[0][1] + hff_work->
yP[1][1];
731 hff_work->
yP[0][0] = P11;
732 hff_work->
yP[0][1] = P12;
733 hff_work->
yP[1][0] = P21;
734 hff_work->
yP[1][1] = P22;
767 const float yd = vel - hff_work->
xdot;
768 const float S = hff_work->
xP[1][1] + Rvel;
769 const float K1 = hff_work->
xP[0][1] * 1 / S;
770 const float K2 = hff_work->
xP[1][1] * 1 / S;
772 hff_work->
x = hff_work->
x + K1 * yd;
773 hff_work->
xdot = hff_work->
xdot + K2 * yd;
775 const float P11 = -K1 * hff_work->
xP[1][0] + hff_work->
xP[0][0];
776 const float P12 = -K1 * hff_work->
xP[1][1] + hff_work->
xP[0][1];
777 const float P21 = (1. - K2) * hff_work->
xP[1][0];
778 const float P22 = (1. - K2) * hff_work->
xP[1][1];
780 hff_work->
xP[0][0] = P11;
781 hff_work->
xP[0][1] = P12;
782 hff_work->
xP[1][0] = P21;
783 hff_work->
xP[1][1] = P22;
790 const float yd = vel - hff_work->
ydot;
791 const float S = hff_work->
yP[1][1] + Rvel;
792 const float K1 = hff_work->
yP[0][1] * 1 / S;
793 const float K2 = hff_work->
yP[1][1] * 1 / S;
795 hff_work->
y = hff_work->
y + K1 * yd;
796 hff_work->
ydot = hff_work->
ydot + K2 * yd;
798 const float P11 = -K1 * hff_work->
yP[1][0] + hff_work->
yP[0][0];
799 const float P12 = -K1 * hff_work->
yP[1][1] + hff_work->
yP[0][1];
800 const float P21 = (1. - K2) * hff_work->
yP[1][0];
801 const float P22 = (1. - K2) * hff_work->
yP[1][1];
803 hff_work->
yP[0][0] = P11;
804 hff_work->
yP[0][1] = P12;
805 hff_work->
yP[1][0] = P21;
806 hff_work->
yP[1][1] = P22;
static float b2_hff_x_meas
static struct Int32RMat * orientationGetRMat_i(struct OrientationReps *orientation)
Get vehicle body attitude rotation matrix (int).
static void b2_hff_update_ydot(struct HfilterFloat *hff_work, float vel, float Rvel)
uint32_t pacc
position accuracy in cm
Generic transmission transport header.
Horizontal filter (x,y) to estimate position and velocity.
#define AHRS_PROPAGATE_FREQUENCY
void b2_hff_realign(struct FloatVect2 pos, struct FloatVect2 vel)
Periodic telemetry system header (includes downlink utility and generated code).
static struct Int32RMat * stateGetNedToBodyRMat_i(void)
Get vehicle body attitude rotation matrix (int).
Simple first order low pass filter with bilinear transform.
static int b2_hff_rb_n
ringbuffer fill count
Butterworth2LowPass_int filter_y
#define HFF_LOWPASS_CUTOFF_FREQUENCY
static void b2_hff_init_x(float init_x, float init_xdot)
static int save_counter
counts down the propagation steps until the filter state is saved again
struct HfilterFloat * b2_hff_rb_last
ringbuffer read pointer
static void init_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, float cut_off, float sample_time, int32_t value)
Init a second order Butterworth filter.
static float b2_hff_xd_meas
static float b2_hff_y_meas
uint32_t sacc
speed accuracy in cm/s
static void b2_hff_propagate_x(struct HfilterFloat *hff_work, float dt)
#define PRINT_DBG(_l, _p)
struct Int32Vect3 accel
accelerometer measurements in m/s^2 in BFP with INT32_ACCEL_FRAC
static float b2_hff_xdd_meas
static void b2_hff_propagate_y(struct HfilterFloat *hff_work, float dt)
Device independent GPS code (interface)
#define ACCEL_FLOAT_OF_BFP(_ai)
struct Imu imu
global IMU state
#define DefaultPeriodic
Set default periodic telemetry.
void b2_hff_init(float init_x, float init_xdot, float init_y, float init_ydot)
static uint16_t b2_hff_lost_counter
static int32_t update_butterworth_2_low_pass_int(Butterworth2LowPass_int *filter, int32_t value)
Update second order Butterworth low pass filter state with a new value(fixed point version)...
static uint16_t b2_hff_lost_limit
Inertial Measurement Unit interface.
struct HfilterFloat b2_hff_state
float yP[HFF_STATE_SIZE][HFF_STATE_SIZE]
struct OrientationReps body_to_imu
rotation from body to imu frame
static const struct usb_device_descriptor dev
static int past_save_counter
API to get/set the generic vehicle states.
static void b2_hff_update_x(struct HfilterFloat *hff_work, float x_meas, float Rpos)
void b2_hff_propagate(void)
static void b2_hff_update_xdot(struct HfilterFloat *hff_work, float vel, float Rvel)
static void b2_hff_update_y(struct HfilterFloat *hff_work, float y_meas, float Rpos)
void b2_hff_update_gps(struct FloatVect2 *pos_ned, struct FloatVect2 *speed_ned)
void int32_rmat_transp_vmult(struct Int32Vect3 *vb, struct Int32RMat *m_b2a, struct Int32Vect3 *va)
rotate 3D vector by transposed rotation matrix.
Butterworth2LowPass_int filter_x
static void b2_hff_init_y(float init_y, float init_ydot)
void b2_hff_update_pos(struct FloatVect2 pos, struct FloatVect2 Rpos)
static int lag_counter_err
by how many steps the estimated GPS validity point in time differed from GPS_LAG_N ...
static int b2_hff_ps_counter
counter for hff propagation
static float b2_hff_ydd_meas
struct GpsState gps
global GPS state
static float b2_hff_yd_meas
Butterworth2LowPass_int filter_z
void b2_hff_update_vel(struct FloatVect2 vel, struct FloatVect2 Rvel)
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
float xP[HFF_STATE_SIZE][HFF_STATE_SIZE]
#define INIT_PXX
initial covariance diagonal
if(PrimarySpektrumState.SpektrumTimer)