void ahrs_aligner_init(void) { ahrs_aligner.status = AHRS_ALIGNER_RUNNING;//ahrs_aligner 运行 INT_RATES_ZERO(gyro_sum);//gyro,accel,mag初始化都为0 INT_VECT3_ZERO(accel_sum); INT_VECT3_ZERO(mag_sum); samples_idx = 0; ahrs_aligner.noise = 0; ahrs_aligner.low_noise_cnt = 0; }
//进行ahrs校准器的运行, void ahrs_aligner_run(void) { RATES_ADD(gyro_sum, imu.gyro); VECT3_ADD(accel_sum, imu.accel); VECT3_ADD(mag_sum, imu.mag); ref_sensor_samples[samples_idx] = imu.accel.z;//该数组大小为60(PERIDIC FREQUENCY) samples_idx++;//samples_idx从0开始 #ifdef AHRS_ALIGNER_LED RunOnceEvery(50, {LED_TOGGLE(AHRS_ALIGNER_LED)});//如果定义了ahrs校准器的指示灯时会让该灯以固定频率闪烁 #endif if (samples_idx >= SAMPLES_NB) { int32_t avg_ref_sensor = accel_sum.z; if ( avg_ref_sensor >= 0) avg_ref_sensor += SAMPLES_NB / 2; else avg_ref_sensor -= SAMPLES_NB / 2; avg_ref_sensor /= SAMPLES_NB; //噪声的误差计算 ahrs_aligner.noise = 0; int i; for (i=0; i<SAMPLES_NB; i++) { int32_t diff = ref_sensor_samples[i] - avg_ref_sensor; ahrs_aligner.noise += abs(diff); } //存储平均值(60次)到ahrs校准的lp_xxx RATES_SDIV(ahrs_aligner.lp_gyro, gyro_sum, SAMPLES_NB); VECT3_SDIV(ahrs_aligner.lp_accel, accel_sum, SAMPLES_NB); VECT3_SDIV(ahrs_aligner.lp_mag, mag_sum, SAMPLES_NB); //清零 INT_RATES_ZERO(gyro_sum); INT_VECT3_ZERO(accel_sum); INT_VECT3_ZERO(mag_sum); samples_idx = 0; if (ahrs_aligner.noise < LOW_NOISE_THRESHOLD) ahrs_aligner.low_noise_cnt++; else if ( ahrs_aligner.low_noise_cnt > 0) ahrs_aligner.low_noise_cnt--; if (ahrs_aligner.low_noise_cnt > LOW_NOISE_TIME) { ahrs_aligner.status = AHRS_ALIGNER_LOCKED;//如果ahrs校准器的噪声(noise)值低于阈值的次数为5次,那么ahrs校准器将关闭 #ifdef AHRS_ALIGNER_LED LED_ON(AHRS_ALIGNER_LED);//ahrs校准器关闭的话,对应的led灯就会关闭 #endif } } }
void ahrs_aligner_init(void) { ahrs_aligner.status = AHRS_ALIGNER_RUNNING; INT_RATES_ZERO(gyro_sum); INT_VECT3_ZERO(accel_sum); INT_VECT3_ZERO(mag_sum); samples_idx = 0; ahrs_aligner.noise = 0; ahrs_aligner.low_noise_cnt = 0; #if PERIODIC_TELEMETRY register_periodic_telemetry(DefaultPeriodic, "FILTER_ALIGNER", send_aligner); #endif }
bool_t nav_check_wp_time(struct EnuCoor_i *wp, uint16_t stay_time) { uint16_t time_at_wp; uint32_t dist_to_point; static uint16_t wp_entry_time = 0; static bool_t wp_reached = FALSE; static struct EnuCoor_i wp_last = { 0, 0, 0 }; struct Int32Vect2 diff; if ((wp_last.x != wp->x) || (wp_last.y != wp->y)) { wp_reached = FALSE; wp_last = *wp; } VECT2_DIFF(diff, *wp, *stateGetPositionEnu_i()); INT32_VECT2_RSHIFT(diff, diff, INT32_POS_FRAC / 2); dist_to_point = int32_vect2_norm(&diff); if (dist_to_point < BFP_OF_REAL(ARRIVED_AT_WAYPOINT, INT32_POS_FRAC / 2)) { if (!wp_reached) { wp_reached = TRUE; wp_entry_time = autopilot_flight_time; time_at_wp = 0; } else { time_at_wp = autopilot_flight_time - wp_entry_time; } } else { time_at_wp = 0; wp_reached = FALSE; } if (time_at_wp > stay_time) { INT_VECT3_ZERO(wp_last); return TRUE; } return FALSE; }
void imu_init(void) { /* initialises neutrals */ RATES_ASSIGN(imu.gyro_neutral, IMU_GYRO_P_NEUTRAL, IMU_GYRO_Q_NEUTRAL, IMU_GYRO_R_NEUTRAL); VECT3_ASSIGN(imu.accel_neutral, IMU_ACCEL_X_NEUTRAL, IMU_ACCEL_Y_NEUTRAL, IMU_ACCEL_Z_NEUTRAL); #if defined IMU_MAG_X_NEUTRAL && defined IMU_MAG_Y_NEUTRAL && defined IMU_MAG_Z_NEUTRAL VECT3_ASSIGN(imu.mag_neutral, IMU_MAG_X_NEUTRAL, IMU_MAG_Y_NEUTRAL, IMU_MAG_Z_NEUTRAL); #else #if USE_MAGNETOMETER #pragma message "Info: Magnetomter neutrals are set to zero!" #endif INT_VECT3_ZERO(imu.mag_neutral); #endif /* Compute quaternion and rotation matrix for conversions between body and imu frame */ struct Int32Eulers body_to_imu_eulers = { ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_PHI), ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_THETA), ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_PSI) }; INT32_QUAT_OF_EULERS(imu.body_to_imu_quat, body_to_imu_eulers); INT32_QUAT_NORMALIZE(imu.body_to_imu_quat); INT32_RMAT_OF_EULERS(imu.body_to_imu_rmat, body_to_imu_eulers); imu_impl_init(); }
void imu_periodic(void) { // Start reading the latest gyroscope data if (!imu_krooz.mpu.config.initialized) { mpu60x0_i2c_start_configure(&imu_krooz.mpu); } if (!imu_krooz.hmc.initialized) { hmc58xx_start_configure(&imu_krooz.hmc); } uint32_t now_ts = get_sys_time_usec(); if (imu_krooz.meas_nb) { RATES_ASSIGN(imu.gyro_unscaled, -imu_krooz.rates_sum.q / imu_krooz.meas_nb, imu_krooz.rates_sum.p / imu_krooz.meas_nb, imu_krooz.rates_sum.r / imu_krooz.meas_nb); RATES_ASSIGN(imu_krooz.rates_sum, 0, 0, 0); imu_krooz.meas_nb = 0; imu_scale_gyro(&imu); AbiSendMsgIMU_GYRO_INT32(IMU_BOARD_ID, now_ts, &imu.gyro); } if (imu_krooz.meas_nb_acc.x && imu_krooz.meas_nb_acc.y && imu_krooz.meas_nb_acc.z) { imu.accel_unscaled.x = 65536 - imu_krooz.accel_sum.x / imu_krooz.meas_nb_acc.x; imu.accel_unscaled.y = 65536 - imu_krooz.accel_sum.y / imu_krooz.meas_nb_acc.y; imu.accel_unscaled.z = imu_krooz.accel_sum.z / imu_krooz.meas_nb_acc.z; #if IMU_KROOZ_USE_ACCEL_MEDIAN_FILTER UpdateMedianFilterVect3Int(median_accel, imu.accel_unscaled); #endif VECT3_SMUL(imu_krooz.accel_filtered, imu_krooz.accel_filtered, IMU_KROOZ_ACCEL_AVG_FILTER); VECT3_ADD(imu_krooz.accel_filtered, imu.accel_unscaled); VECT3_SDIV(imu_krooz.accel_filtered, imu_krooz.accel_filtered, (IMU_KROOZ_ACCEL_AVG_FILTER + 1)); VECT3_COPY(imu.accel_unscaled, imu_krooz.accel_filtered); INT_VECT3_ZERO(imu_krooz.accel_sum); INT_VECT3_ZERO(imu_krooz.meas_nb_acc); imu_scale_accel(&imu); AbiSendMsgIMU_ACCEL_INT32(IMU_BOARD_ID, now_ts, &imu.accel); } RunOnceEvery(128, {axis_nb = 5;});
void imu_init(void) { #ifdef IMU_POWER_GPIO gpio_setup_output(IMU_POWER_GPIO); IMU_POWER_GPIO_ON(IMU_POWER_GPIO); #endif /* initialises neutrals */ RATES_ASSIGN(imu.gyro_neutral, IMU_GYRO_P_NEUTRAL, IMU_GYRO_Q_NEUTRAL, IMU_GYRO_R_NEUTRAL); VECT3_ASSIGN(imu.accel_neutral, IMU_ACCEL_X_NEUTRAL, IMU_ACCEL_Y_NEUTRAL, IMU_ACCEL_Z_NEUTRAL); #if defined IMU_MAG_X_NEUTRAL && defined IMU_MAG_Y_NEUTRAL && defined IMU_MAG_Z_NEUTRAL VECT3_ASSIGN(imu.mag_neutral, IMU_MAG_X_NEUTRAL, IMU_MAG_Y_NEUTRAL, IMU_MAG_Z_NEUTRAL); #else #if USE_MAGNETOMETER INFO("Magnetometer neutrals are set to zero, you should calibrate!") #endif INT_VECT3_ZERO(imu.mag_neutral); #endif /* Compute quaternion and rotation matrix for conversions between body and imu frame */ struct Int32Eulers body_to_imu_eulers = { ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_PHI), ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_THETA), ANGLE_BFP_OF_REAL(IMU_BODY_TO_IMU_PSI) }; INT32_QUAT_OF_EULERS(imu.body_to_imu_quat, body_to_imu_eulers); INT32_QUAT_NORMALIZE(imu.body_to_imu_quat); INT32_RMAT_OF_EULERS(imu.body_to_imu_rmat, body_to_imu_eulers); #if PERIODIC_TELEMETRY register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL", send_accel); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO", send_gyro); #if USE_IMU_FLOAT #else // !USE_IMU_FLOAT register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL_RAW", send_accel_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL_SCALED", send_accel_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL", send_accel); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO_RAW", send_gyro_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO_SCALED", send_gyro_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO", send_gyro); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG_RAW", send_mag_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG_SCALED", send_mag_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG", send_mag); #endif // !USE_IMU_FLOAT #endif // DOWNLINK imu_impl_init(); }
void imu_init(void) { #ifdef IMU_POWER_GPIO gpio_setup_output(IMU_POWER_GPIO); IMU_POWER_GPIO_ON(IMU_POWER_GPIO); #endif /* initialises neutrals */ RATES_ASSIGN(imu.gyro_neutral, IMU_GYRO_P_NEUTRAL, IMU_GYRO_Q_NEUTRAL, IMU_GYRO_R_NEUTRAL); VECT3_ASSIGN(imu.accel_neutral, IMU_ACCEL_X_NEUTRAL, IMU_ACCEL_Y_NEUTRAL, IMU_ACCEL_Z_NEUTRAL); #if defined IMU_MAG_X_NEUTRAL && defined IMU_MAG_Y_NEUTRAL && defined IMU_MAG_Z_NEUTRAL VECT3_ASSIGN(imu.mag_neutral, IMU_MAG_X_NEUTRAL, IMU_MAG_Y_NEUTRAL, IMU_MAG_Z_NEUTRAL); #else #if USE_MAGNETOMETER INFO("Magnetometer neutrals are set to zero, you should calibrate!") #endif INT_VECT3_ZERO(imu.mag_neutral); #endif struct FloatEulers body_to_imu_eulers = {IMU_BODY_TO_IMU_PHI, IMU_BODY_TO_IMU_THETA, IMU_BODY_TO_IMU_PSI}; orientationSetEulers_f(&imu.body_to_imu, &body_to_imu_eulers); #if USE_IMU_FLOAT orientationSetEulers_f(&imuf.body_to_imu, &body_to_imu_eulers); #endif #if PERIODIC_TELEMETRY register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL", send_accel); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO", send_gyro); #if !USE_IMU_FLOAT register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL_RAW", send_accel_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL_SCALED", send_accel_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_ACCEL", send_accel); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO_RAW", send_gyro_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO_SCALED", send_gyro_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_GYRO", send_gyro); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG_RAW", send_mag_raw); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG_SCALED", send_mag_scaled); register_periodic_telemetry(DefaultPeriodic, "IMU_MAG", send_mag); #endif // !USE_IMU_FLOAT #endif // DOWNLINK imu_impl_init(); }
void ms2100_init(struct Ms2100 *ms, struct spi_periph *spi_p, uint8_t slave_idx) { /* set spi_peripheral */ ms->spi_p = spi_p; /* configure spi transaction for the request */ ms->req_trans.cpol = SPICpolIdleLow; ms->req_trans.cpha = SPICphaEdge1; ms->req_trans.dss = SPIDss8bit; ms->req_trans.bitorder = SPIMSBFirst; ms->req_trans.cdiv = SPIDiv64; ms->req_trans.slave_idx = slave_idx; ms->req_trans.select = SPISelectUnselect; ms->req_trans.output_buf = ms->req_buf; ms->req_trans.output_length = 1; ms->req_trans.input_buf = NULL; ms->req_trans.input_length = 0; // ms2100 has to be reset before each measurement: implemented in ms2100_arch.c ms->req_trans.before_cb = ms2100_reset_cb; ms->req_trans.status = SPITransDone; /* configure spi transaction to read the result */ ms->read_trans.cpol = SPICpolIdleLow; ms->read_trans.cpha = SPICphaEdge1; ms->read_trans.dss = SPIDss8bit; ms->read_trans.bitorder = SPIMSBFirst; ms->read_trans.cdiv = SPIDiv64; ms->read_trans.slave_idx = slave_idx; ms->read_trans.select = SPISelectUnselect; ms->read_trans.output_buf = NULL; ms->read_trans.output_length = 0; ms->read_trans.input_buf = ms->read_buf; ms->read_trans.input_length = 2; ms->read_trans.before_cb = NULL; ms->read_trans.after_cb = NULL; ms->read_trans.status = SPITransDone; ms2100_arch_init(); INT_VECT3_ZERO(ms->data.vect); ms->cur_axe = 0; ms->status = MS2100_IDLE; }
/* compute the mean of the last n accel measurements */ static inline void b2_hff_compute_accel_body_mean(uint8_t n) { struct Int32Vect3 sum; int i, j; INT_VECT3_ZERO(sum); if (n > 1) { if (n > acc_body.n) { n = acc_body.n; } for (i = 1; i <= n; i++) { j = (acc_body.w - i) > 0 ? (acc_body.w - i) : (acc_body.w - i + acc_body.size); VECT3_ADD(sum, acc_body.buf[j]); } VECT3_SDIV(acc_body_mean, sum, n); } else { VECT3_COPY(acc_body_mean, sum); } }
static inline void on_gyro_accel_event( void ) { #ifdef AHRS_CPU_LED LED_ON(AHRS_CPU_LED); #endif // Run aligner on raw data as it also makes averages. if (ahrs.status == AHRS_UNINIT) { ImuScaleGyro(imu); ImuScaleAccel(imu); ahrs_aligner_run(); if (ahrs_aligner.status == AHRS_ALIGNER_LOCKED) ahrs_align(); return; } #if PERIODIC_FREQUENCY == 60 ImuScaleGyro(imu); ImuScaleAccel(imu); ahrs_propagate(); ahrs_update_accel(); ahrs_update_fw_estimator(); #else //PERIODIC_FREQUENCY static uint8_t _reduced_propagation_rate = 0; static uint8_t _reduced_correction_rate = 0; static struct Int32Vect3 acc_avg; static struct Int32Rates gyr_avg; RATES_ADD(gyr_avg, imu.gyro_unscaled); VECT3_ADD(acc_avg, imu.accel_unscaled); _reduced_propagation_rate++; if (_reduced_propagation_rate < (PERIODIC_FREQUENCY / AHRS_PROPAGATE_FREQUENCY)) { } else { _reduced_propagation_rate = 0; RATES_SDIV(imu.gyro_unscaled, gyr_avg, (PERIODIC_FREQUENCY / AHRS_PROPAGATE_FREQUENCY) ); INT_RATES_ZERO(gyr_avg); ImuScaleGyro(imu); ahrs_propagate(); _reduced_correction_rate++; if (_reduced_correction_rate >= (AHRS_PROPAGATE_FREQUENCY / AHRS_CORRECT_FREQUENCY)) { _reduced_correction_rate = 0; VECT3_SDIV(imu.accel_unscaled, acc_avg, (PERIODIC_FREQUENCY / AHRS_CORRECT_FREQUENCY) ); INT_VECT3_ZERO(acc_avg); ImuScaleAccel(imu); ahrs_update_accel(); ahrs_update_fw_estimator(); } } #endif //PERIODIC_FREQUENCY #ifdef AHRS_CPU_LED LED_OFF(AHRS_CPU_LED); #endif #ifdef AHRS_TRIGGERED_ATTITUDE_LOOP new_ins_attitude = 1; #endif }