void stateCalcAccelNed_i(void) { if (bit_is_set(state.accel_status, ACCEL_NED_I)) return; int errno = 0; if (state.ned_initialized_i) { if (bit_is_set(state.accel_status, ACCEL_NED_F)) { ACCELS_BFP_OF_REAL(state.ned_accel_i, state.ned_accel_f); } else if (bit_is_set(state.accel_status, ACCEL_ECEF_I)) { ned_of_ecef_vect_i(&state.ned_accel_i, &state.ned_origin_i, &state.ecef_accel_i); } else if (bit_is_set(state.accel_status, ACCEL_ECEF_F)) { /* transform ecef_f -> ecef_i -> ned_i , set status bits */ ACCELS_BFP_OF_REAL(state.ecef_accel_i, state.ecef_accel_f); SetBit(state.accel_status, ACCEL_ECEF_I); ned_of_ecef_vect_i(&state.ned_accel_i, &state.ned_origin_i, &state.ecef_accel_i); } else { /* could not get this representation, set errno */ errno = 1; } } else { /* ned coordinate system not initialized, set errno */ errno = 2; } if (errno) { //struct NedCoor_i _ned_zero = {0}; //return _ned_zero; } /* set bit to indicate this representation is computed */ SetBit(state.accel_status, ACCEL_NED_I); }
void stateCalcSpeedNed_i(void) { if (bit_is_set(state.speed_status, SPEED_NED_I)) return; int errno = 0; if (state.ned_initialized_i) { if (bit_is_set(state.speed_status, SPEED_NED_F)) { SPEEDS_BFP_OF_REAL(state.ned_speed_i, state.ned_speed_f); } else if (bit_is_set(state.speed_status, SPEED_ENU_I)) { INT32_VECT3_NED_OF_ENU(state.ned_speed_i, state.enu_speed_i); } else if (bit_is_set(state.speed_status, SPEED_ENU_F)) { SPEEDS_BFP_OF_REAL(state.enu_speed_i, state.enu_speed_f); SetBit(state.speed_status, SPEED_ENU_I); INT32_VECT3_NED_OF_ENU(state.ned_speed_i, state.enu_speed_i); } else if (bit_is_set(state.speed_status, SPEED_ECEF_I)) { ned_of_ecef_vect_i(&state.ned_speed_i, &state.ned_origin_i, &state.ecef_speed_i); } else if (bit_is_set(state.speed_status, SPEED_ECEF_F)) { /* transform ecef_f -> ecef_i -> ned_i , set status bits */ SPEEDS_BFP_OF_REAL(state.ecef_speed_i, state.ecef_speed_f); SetBit(state.speed_status, SPEED_ECEF_I); ned_of_ecef_vect_i(&state.ned_speed_i, &state.ned_origin_i, &state.ecef_speed_i); } else { /* could not get this representation, set errno */ errno = 1; } } else if (state.utm_initialized_f) { if (bit_is_set(state.speed_status, SPEED_NED_F)) { SPEEDS_BFP_OF_REAL(state.ned_speed_i, state.ned_speed_f); } else if (bit_is_set(state.speed_status, SPEED_ENU_I)) { INT32_VECT3_NED_OF_ENU(state.ned_speed_i, state.enu_speed_i); } else if (bit_is_set(state.speed_status, SPEED_ENU_F)) { SPEEDS_BFP_OF_REAL(state.enu_speed_i, state.enu_speed_f); SetBit(state.speed_status, SPEED_ENU_I); INT32_VECT3_NED_OF_ENU(state.ned_speed_i, state.enu_speed_i); } else { /* could not get this representation, set errno */ errno = 2; } } else { /* ned coordinate system not initialized, set errno */ errno = 3; } if (errno) { //struct NedCoor_i _ned_zero = {0}; //return _ned_zero; } /* set bit to indicate this representation is computed */ SetBit(state.speed_status, SPEED_NED_I); }
void ins_update_gps(void) { if (gps_state.fix == GPS_FIX_3D) { if (!ins.ltp_initialised) { ltp_def_from_ecef_i(&ins.ltp_def, &gps_state.ecef_pos); ins.ltp_initialised = TRUE; } ned_of_ecef_point_i(&ins.gps_pos_cm_ned, &ins.ltp_def, &gps_state.ecef_pos); ned_of_ecef_vect_i(&ins.gps_speed_cm_s_ned, &ins.ltp_def, &gps_state.ecef_speed); #ifdef USE_HFF b2ins_update_gps(); VECT2_SDIV(ins.ltp_pos, (1<<(B2INS_POS_LTP_FRAC-INT32_POS_FRAC)), b2ins_pos_ltp); VECT2_SDIV(ins.ltp_speed, (1<<(B2INS_SPEED_LTP_FRAC-INT32_SPEED_FRAC)), b2ins_speed_ltp); #else INT32_VECT3_SCALE_2(b2ins_meas_gps_pos_ned, ins.gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT3_SCALE_2(b2ins_meas_gps_speed_ned, ins.gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); VECT3_COPY(ins.ltp_pos, b2ins_meas_gps_pos_ned); VECT3_COPY(ins.ltp_speed, b2ins_meas_gps_speed_ned); #endif INT32_VECT3_ENU_OF_NED(ins.enu_pos, ins.ltp_pos); INT32_VECT3_ENU_OF_NED(ins.enu_speed, ins.ltp_speed); INT32_VECT3_ENU_OF_NED(ins.enu_accel, ins.ltp_accel); } }
void WEAK ins_module_update_gps(struct GpsState *gps_s, float dt __attribute__((unused))) { /* copy velocity from GPS */ if (bit_is_set(gps_s->valid_fields, GPS_VALID_VEL_NED_BIT)) { /* convert speed from cm/s to m/s in BFP with INT32_SPEED_FRAC */ INT32_VECT3_SCALE_2(ins_module.ltp_speed, gps_s->ned_vel, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); } else if (bit_is_set(gps_s->valid_fields, GPS_VALID_VEL_ECEF_BIT)) { /* convert ECEF to NED */ struct NedCoor_i gps_speed_cm_s_ned; ned_of_ecef_vect_i(&gps_speed_cm_s_ned, &ins_module.ltp_def, &gps_s->ecef_vel); /* convert speed from cm/s to m/s in BFP with INT32_SPEED_FRAC */ INT32_VECT3_SCALE_2(ins_module.ltp_speed, gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); } /* copy position from GPS */ if (bit_is_set(gps_s->valid_fields, GPS_VALID_POS_ECEF_BIT)) { /* convert ECEF to NED */ struct NedCoor_i gps_pos_cm_ned; ned_of_ecef_point_i(&gps_pos_cm_ned, &ins_module.ltp_def, &gps_s->ecef_pos); /* convert pos from cm to m in BFP with INT32_POS_FRAC */ INT32_VECT3_SCALE_2(ins_module.ltp_pos, gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); } }
void ins_update_gps(void) { #ifdef USE_GPS if (booz_gps_state.fix == BOOZ2_GPS_FIX_3D) { if (!ins_ltp_initialised) { ltp_def_from_ecef_i(&ins_ltp_def, &booz_gps_state.ecef_pos); ins_ltp_def.lla.alt = booz_gps_state.lla_pos.alt; ins_ltp_def.hmsl = booz_gps_state.hmsl; ins_ltp_initialised = TRUE; } ned_of_ecef_point_i(&ins_gps_pos_cm_ned, &ins_ltp_def, &booz_gps_state.ecef_pos); ned_of_ecef_vect_i(&ins_gps_speed_cm_s_ned, &ins_ltp_def, &booz_gps_state.ecef_vel); #ifdef USE_HFF VECT2_ASSIGN(ins_gps_pos_m_ned, ins_gps_pos_cm_ned.x, ins_gps_pos_cm_ned.y); VECT2_SDIV(ins_gps_pos_m_ned, ins_gps_pos_m_ned, 100.); VECT2_ASSIGN(ins_gps_speed_m_s_ned, ins_gps_speed_cm_s_ned.x, ins_gps_speed_cm_s_ned.y); VECT2_SDIV(ins_gps_speed_m_s_ned, ins_gps_speed_m_s_ned, 100.); if (ins_hf_realign) { ins_hf_realign = FALSE; #ifdef SITL struct FloatVect2 true_pos, true_speed; VECT2_COPY(true_pos, fdm.ltpprz_pos); VECT2_COPY(true_speed, fdm.ltpprz_ecef_vel); b2_hff_realign(true_pos, true_speed); #else const struct FloatVect2 zero = {0.0, 0.0}; b2_hff_realign(ins_gps_pos_m_ned, zero); #endif } b2_hff_update_gps(); #ifndef USE_VFF /* vff not used */ ins_ltp_pos.z = (ins_gps_pos_cm_ned.z * INT32_POS_OF_CM_NUM) / INT32_POS_OF_CM_DEN; ins_ltp_speed.z = (ins_gps_speed_cm_s_ned.z * INT32_SPEED_OF_CM_S_NUM) INT32_SPEED_OF_CM_S_DEN; #endif /* vff not used */ #endif /* hff used */ #ifndef USE_HFF /* hff not used */ #ifndef USE_VFF /* neither hf nor vf used */ INT32_VECT3_SCALE_3(ins_ltp_pos, ins_gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT3_SCALE_3(ins_ltp_speed, ins_gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); #else /* only vff used */ INT32_VECT2_SCALE_2(ins_ltp_pos, ins_gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT2_SCALE_2(ins_ltp_speed, ins_gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); #endif #ifdef USE_GPS_LAG_HACK VECT2_COPY(d_pos, ins_ltp_speed); INT32_VECT2_RSHIFT(d_pos, d_pos, 11); VECT2_ADD(ins_ltp_pos, d_pos); #endif #endif /* hff not used */ INT32_VECT3_ENU_OF_NED(ins_enu_pos, ins_ltp_pos); INT32_VECT3_ENU_OF_NED(ins_enu_speed, ins_ltp_speed); INT32_VECT3_ENU_OF_NED(ins_enu_accel, ins_ltp_accel); } #endif /* USE_GPS */ }
void ins_reset_altitude_ref(void) { struct LlaCoor_i lla = { .lat = state.ned_origin_i.lla.lat, .lon = state.ned_origin_i.lla.lon, .alt = gps.lla_pos.alt }; ltp_def_from_lla_i(&ins_gp.ltp_def, &lla); ins_gp.ltp_def.hmsl = gps.hmsl; stateSetLocalOrigin_i(&ins_gp.ltp_def); } #include "subsystems/abi.h" static abi_event gps_ev; static void gps_cb(uint8_t sender_id __attribute__((unused)), uint32_t stamp __attribute__((unused)), struct GpsState *gps_s) { if (gps_s->fix == GPS_FIX_3D) { if (!ins_gp.ltp_initialized) { ins_reset_local_origin(); } /* simply scale and copy pos/speed from gps */ struct NedCoor_i gps_pos_cm_ned; ned_of_ecef_point_i(&gps_pos_cm_ned, &ins_gp.ltp_def, &gps_s->ecef_pos); INT32_VECT3_SCALE_2(ins_gp.ltp_pos, gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); stateSetPositionNed_i(&ins_gp.ltp_pos); struct NedCoor_i gps_speed_cm_s_ned; ned_of_ecef_vect_i(&gps_speed_cm_s_ned, &ins_gp.ltp_def, &gps_s->ecef_vel); INT32_VECT3_SCALE_2(ins_gp.ltp_speed, gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); stateSetSpeedNed_i(&ins_gp.ltp_speed); } } void ins_gps_passthrough_register(void); { ins_register_impl(ins_gps_passthrough_init); AbiBindMsgGPS(ABI_BROADCAST, &gps_ev, gps_cb); }
void ins_update_gps(void) { if (gps.fix == GPS_FIX_3D) { if (!ins_impl.ltp_initialized) { ins_reset_local_origin(); } /* simply scale and copy pos/speed from gps */ struct NedCoor_i gps_pos_cm_ned; ned_of_ecef_point_i(&gps_pos_cm_ned, &ins_impl.ltp_def, &gps.ecef_pos); INT32_VECT3_SCALE_2(ins_impl.ltp_pos, gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); stateSetPositionNed_i(&ins_impl.ltp_pos); struct NedCoor_i gps_speed_cm_s_ned; ned_of_ecef_vect_i(&gps_speed_cm_s_ned, &ins_impl.ltp_def, &gps.ecef_vel); INT32_VECT3_SCALE_2(ins_impl.ltp_speed, gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); stateSetSpeedNed_i(&ins_impl.ltp_speed); } }
void ins_update_gps(void) { #if USE_GPS if (gps.fix == GPS_FIX_3D) { if (!ins_ltp_initialised) { ltp_def_from_ecef_i(&ins_ltp_def, &gps.ecef_pos); ins_ltp_def.lla.alt = gps.lla_pos.alt; ins_ltp_def.hmsl = gps.hmsl; ins_ltp_initialised = TRUE; stateSetLocalOrigin_i(&ins_ltp_def); } ned_of_ecef_point_i(&ins_gps_pos_cm_ned, &ins_ltp_def, &gps.ecef_pos); ned_of_ecef_vect_i(&ins_gps_speed_cm_s_ned, &ins_ltp_def, &gps.ecef_vel); #if USE_HFF VECT2_ASSIGN(ins_gps_pos_m_ned, ins_gps_pos_cm_ned.x, ins_gps_pos_cm_ned.y); VECT2_SDIV(ins_gps_pos_m_ned, ins_gps_pos_m_ned, 100.); VECT2_ASSIGN(ins_gps_speed_m_s_ned, ins_gps_speed_cm_s_ned.x, ins_gps_speed_cm_s_ned.y); VECT2_SDIV(ins_gps_speed_m_s_ned, ins_gps_speed_m_s_ned, 100.); if (ins.hf_realign) { ins.hf_realign = FALSE; #ifdef SITL struct FloatVect2 true_pos, true_speed; VECT2_COPY(true_pos, fdm.ltpprz_pos); VECT2_COPY(true_speed, fdm.ltpprz_ecef_vel); b2_hff_realign(true_pos, true_speed); #else const struct FloatVect2 zero = {0.0, 0.0}; b2_hff_realign(ins_gps_pos_m_ned, zero); #endif } b2_hff_update_gps(); #endif /* hff used */ #if !USE_HFF /* hff not used */ INT32_VECT2_SCALE_2(ins_ltp_pos, ins_gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT2_SCALE_2(ins_ltp_speed, ins_gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); #endif /* hff not used */ } #endif /* USE_GPS */ }
void ned_of_lla_vect_i(struct NedCoor_i* ned, struct LtpDef_i* def, struct LlaCoor_i* lla) { struct EcefCoor_i ecef; ecef_of_lla_i(&ecef,lla); ned_of_ecef_vect_i(ned,def,&ecef); }
void ins_reset_altitude_ref(void) { #if USE_GPS struct LlaCoor_i lla = { .lat = state.ned_origin_i.lla.lat, .lon = state.ned_origin_i.lla.lon, .alt = gps.lla_pos.alt }; ltp_def_from_lla_i(&ins_impl.ltp_def, &lla); ins_impl.ltp_def.hmsl = gps.hmsl; stateSetLocalOrigin_i(&ins_impl.ltp_def); #endif ins_impl.vf_reset = TRUE; } void ins_propagate(float dt) { /* untilt accels */ struct Int32Vect3 accel_meas_body; struct Int32RMat *body_to_imu_rmat = orientationGetRMat_i(&imu.body_to_imu); int32_rmat_transp_vmult(&accel_meas_body, body_to_imu_rmat, &imu.accel); struct Int32Vect3 accel_meas_ltp; int32_rmat_transp_vmult(&accel_meas_ltp, stateGetNedToBodyRMat_i(), &accel_meas_body); float z_accel_meas_float = ACCEL_FLOAT_OF_BFP(accel_meas_ltp.z); if (ins_impl.baro_initialized) { vff_propagate(z_accel_meas_float, dt); ins_update_from_vff(); } else { // feed accel from the sensors // subtract -9.81m/s2 (acceleration measured due to gravity, // but vehicle not accelerating in ltp) ins_impl.ltp_accel.z = accel_meas_ltp.z + ACCEL_BFP_OF_REAL(9.81); } #if USE_HFF /* propagate horizontal filter */ b2_hff_propagate(); /* convert and copy result to ins_impl */ ins_update_from_hff(); #else ins_impl.ltp_accel.x = accel_meas_ltp.x; ins_impl.ltp_accel.y = accel_meas_ltp.y; #endif /* USE_HFF */ ins_ned_to_state(); } static void baro_cb(uint8_t __attribute__((unused)) sender_id, const float *pressure) { if (!ins_impl.baro_initialized && *pressure > 1e-7) { // wait for a first positive value ins_impl.qfe = *pressure; ins_impl.baro_initialized = TRUE; } if (ins_impl.baro_initialized) { if (ins_impl.vf_reset) { ins_impl.vf_reset = FALSE; ins_impl.qfe = *pressure; vff_realign(0.); ins_update_from_vff(); } else { ins_impl.baro_z = -pprz_isa_height_of_pressure(*pressure, ins_impl.qfe); #if USE_VFF_EXTENDED vff_update_baro(ins_impl.baro_z); #else vff_update(ins_impl.baro_z); #endif } ins_ned_to_state(); } } #if USE_GPS void ins_update_gps(void) { if (gps.fix == GPS_FIX_3D) { if (!ins_impl.ltp_initialized) { ltp_def_from_ecef_i(&ins_impl.ltp_def, &gps.ecef_pos); ins_impl.ltp_def.lla.alt = gps.lla_pos.alt; ins_impl.ltp_def.hmsl = gps.hmsl; ins_impl.ltp_initialized = TRUE; stateSetLocalOrigin_i(&ins_impl.ltp_def); } struct NedCoor_i gps_pos_cm_ned; ned_of_ecef_point_i(&gps_pos_cm_ned, &ins_impl.ltp_def, &gps.ecef_pos); /// @todo maybe use gps.ned_vel directly?? struct NedCoor_i gps_speed_cm_s_ned; ned_of_ecef_vect_i(&gps_speed_cm_s_ned, &ins_impl.ltp_def, &gps.ecef_vel); #if INS_USE_GPS_ALT vff_update_z_conf((float)gps_pos_cm_ned.z / 100.0, INS_VFF_R_GPS); #endif #if USE_HFF /* horizontal gps transformed to NED in meters as float */ struct FloatVect2 gps_pos_m_ned; VECT2_ASSIGN(gps_pos_m_ned, gps_pos_cm_ned.x, gps_pos_cm_ned.y); VECT2_SDIV(gps_pos_m_ned, gps_pos_m_ned, 100.0f); struct FloatVect2 gps_speed_m_s_ned; VECT2_ASSIGN(gps_speed_m_s_ned, gps_speed_cm_s_ned.x, gps_speed_cm_s_ned.y); VECT2_SDIV(gps_speed_m_s_ned, gps_speed_m_s_ned, 100.); if (ins_impl.hf_realign) { ins_impl.hf_realign = FALSE; const struct FloatVect2 zero = {0.0f, 0.0f}; b2_hff_realign(gps_pos_m_ned, zero); } // run horizontal filter b2_hff_update_gps(&gps_pos_m_ned, &gps_speed_m_s_ned); // convert and copy result to ins_impl ins_update_from_hff(); #else /* hff not used */ /* simply copy horizontal pos/speed from gps */ INT32_VECT2_SCALE_2(ins_impl.ltp_pos, gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT2_SCALE_2(ins_impl.ltp_speed, gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); #endif /* USE_HFF */ ins_ned_to_state(); } } #endif /* USE_GPS */ #if USE_SONAR static void sonar_cb(uint8_t __attribute__((unused)) sender_id, const float *distance) { static float last_offset = 0.; /* update filter assuming a flat ground */ if (*distance < INS_SONAR_MAX_RANGE && *distance > INS_SONAR_MIN_RANGE #ifdef INS_SONAR_THROTTLE_THRESHOLD && stabilization_cmd[COMMAND_THRUST] < INS_SONAR_THROTTLE_THRESHOLD #endif #ifdef INS_SONAR_BARO_THRESHOLD && ins_impl.baro_z > -INS_SONAR_BARO_THRESHOLD /* z down */ #endif && ins_impl.update_on_agl && ins_impl.baro_initialized) { vff_update_z_conf(-(*distance), VFF_R_SONAR_0 + VFF_R_SONAR_OF_M * fabsf(*distance)); last_offset = vff.offset; } else { /* update offset with last value to avoid divergence */ vff_update_offset(last_offset); } } #endif // USE_SONAR /** initialize the local origin (ltp_def) from flight plan position */ static void ins_init_origin_from_flightplan(void) { struct LlaCoor_i llh_nav0; /* Height above the ellipsoid */ llh_nav0.lat = NAV_LAT0; llh_nav0.lon = NAV_LON0; /* NAV_ALT0 = ground alt above msl, NAV_MSL0 = geoid-height (msl) over ellipsoid */ llh_nav0.alt = NAV_ALT0 + NAV_MSL0; struct EcefCoor_i ecef_nav0; ecef_of_lla_i(&ecef_nav0, &llh_nav0); ltp_def_from_ecef_i(&ins_impl.ltp_def, &ecef_nav0); ins_impl.ltp_def.hmsl = NAV_ALT0; stateSetLocalOrigin_i(&ins_impl.ltp_def); } /** copy position and speed to state interface */ static void ins_ned_to_state(void) { stateSetPositionNed_i(&ins_impl.ltp_pos); stateSetSpeedNed_i(&ins_impl.ltp_speed); stateSetAccelNed_i(&ins_impl.ltp_accel); #if defined SITL && USE_NPS if (nps_bypass_ins) { sim_overwrite_ins(); } #endif }
void ins_reset_altitude_ref(void) { #if USE_GPS struct LlaCoor_i lla = { .lat = state.ned_origin_i.lla.lat, .lon = state.ned_origin_i.lla.lon, .alt = gps.lla_pos.alt }; ltp_def_from_lla_i(&ins_int.ltp_def, &lla); ins_int.ltp_def.hmsl = gps.hmsl; stateSetLocalOrigin_i(&ins_int.ltp_def); #endif ins_int.vf_reset = TRUE; } void ins_int_propagate(struct Int32Vect3 *accel, float dt) { /* untilt accels */ struct Int32Vect3 accel_meas_body; struct Int32RMat *body_to_imu_rmat = orientationGetRMat_i(&imu.body_to_imu); int32_rmat_transp_vmult(&accel_meas_body, body_to_imu_rmat, accel); struct Int32Vect3 accel_meas_ltp; int32_rmat_transp_vmult(&accel_meas_ltp, stateGetNedToBodyRMat_i(), &accel_meas_body); float z_accel_meas_float = ACCEL_FLOAT_OF_BFP(accel_meas_ltp.z); /* Propagate only if we got any measurement during the last INS_MAX_PROPAGATION_STEPS. * Otherwise halt the propagation to not diverge and only set the acceleration. * This should only be relevant in the startup phase when the baro is not yet initialized * and there is no gps fix yet... */ if (ins_int.propagation_cnt < INS_MAX_PROPAGATION_STEPS) { vff_propagate(z_accel_meas_float, dt); ins_update_from_vff(); } else { // feed accel from the sensors // subtract -9.81m/s2 (acceleration measured due to gravity, // but vehicle not accelerating in ltp) ins_int.ltp_accel.z = accel_meas_ltp.z + ACCEL_BFP_OF_REAL(9.81); } #if USE_HFF /* propagate horizontal filter */ b2_hff_propagate(); /* convert and copy result to ins_int */ ins_update_from_hff(); #else ins_int.ltp_accel.x = accel_meas_ltp.x; ins_int.ltp_accel.y = accel_meas_ltp.y; #endif /* USE_HFF */ ins_ned_to_state(); /* increment the propagation counter, while making sure it doesn't overflow */ if (ins_int.propagation_cnt < 100 * INS_MAX_PROPAGATION_STEPS) { ins_int.propagation_cnt++; } } static void baro_cb(uint8_t __attribute__((unused)) sender_id, float pressure) { if (!ins_int.baro_initialized && pressure > 1e-7) { // wait for a first positive value ins_int.qfe = pressure; ins_int.baro_initialized = TRUE; } if (ins_int.baro_initialized) { if (ins_int.vf_reset) { ins_int.vf_reset = FALSE; ins_int.qfe = pressure; vff_realign(0.); ins_update_from_vff(); } else { ins_int.baro_z = -pprz_isa_height_of_pressure(pressure, ins_int.qfe); #if USE_VFF_EXTENDED vff_update_baro(ins_int.baro_z); #else vff_update(ins_int.baro_z); #endif } ins_ned_to_state(); /* reset the counter to indicate we just had a measurement update */ ins_int.propagation_cnt = 0; } } #if USE_GPS void ins_int_update_gps(struct GpsState *gps_s) { if (gps_s->fix < GPS_FIX_3D) { return; } if (!ins_int.ltp_initialized) { ins_reset_local_origin(); } struct NedCoor_i gps_pos_cm_ned; ned_of_ecef_point_i(&gps_pos_cm_ned, &ins_int.ltp_def, &gps_s->ecef_pos); /* calculate body frame position taking BODY_TO_GPS translation (in cm) into account */ #ifdef INS_BODY_TO_GPS_X /* body2gps translation in body frame */ struct Int32Vect3 b2g_b = { .x = INS_BODY_TO_GPS_X, .y = INS_BODY_TO_GPS_Y, .z = INS_BODY_TO_GPS_Z }; /* rotate offset given in body frame to navigation/ltp frame using current attitude */ struct Int32Quat q_b2n = *stateGetNedToBodyQuat_i(); QUAT_INVERT(q_b2n, q_b2n); struct Int32Vect3 b2g_n; int32_quat_vmult(&b2g_n, &q_b2n, &b2g_b); /* subtract body2gps translation in ltp from gps position */ VECT3_SUB(gps_pos_cm_ned, b2g_n); #endif /// @todo maybe use gps_s->ned_vel directly?? struct NedCoor_i gps_speed_cm_s_ned; ned_of_ecef_vect_i(&gps_speed_cm_s_ned, &ins_int.ltp_def, &gps_s->ecef_vel); #if INS_USE_GPS_ALT vff_update_z_conf(((float)gps_pos_cm_ned.z) / 100.0, INS_VFF_R_GPS); #endif #if INS_USE_GPS_ALT_SPEED vff_update_vz_conf(((float)gps_speed_cm_s_ned.z) / 100.0, INS_VFF_VZ_R_GPS); #endif #if USE_HFF /* horizontal gps transformed to NED in meters as float */ struct FloatVect2 gps_pos_m_ned; VECT2_ASSIGN(gps_pos_m_ned, gps_pos_cm_ned.x, gps_pos_cm_ned.y); VECT2_SDIV(gps_pos_m_ned, gps_pos_m_ned, 100.0f); struct FloatVect2 gps_speed_m_s_ned; VECT2_ASSIGN(gps_speed_m_s_ned, gps_speed_cm_s_ned.x, gps_speed_cm_s_ned.y); VECT2_SDIV(gps_speed_m_s_ned, gps_speed_m_s_ned, 100.); if (ins_int.hf_realign) { ins_int.hf_realign = FALSE; const struct FloatVect2 zero = {0.0f, 0.0f}; b2_hff_realign(gps_pos_m_ned, zero); } // run horizontal filter b2_hff_update_gps(&gps_pos_m_ned, &gps_speed_m_s_ned); // convert and copy result to ins_int ins_update_from_hff(); #else /* hff not used */ /* simply copy horizontal pos/speed from gps */ INT32_VECT2_SCALE_2(ins_int.ltp_pos, gps_pos_cm_ned, INT32_POS_OF_CM_NUM, INT32_POS_OF_CM_DEN); INT32_VECT2_SCALE_2(ins_int.ltp_speed, gps_speed_cm_s_ned, INT32_SPEED_OF_CM_S_NUM, INT32_SPEED_OF_CM_S_DEN); #endif /* USE_HFF */ ins_ned_to_state(); /* reset the counter to indicate we just had a measurement update */ ins_int.propagation_cnt = 0; } #else void ins_int_update_gps(struct GpsState *gps_s __attribute__((unused))) {} #endif /* USE_GPS */ #if USE_SONAR static void sonar_cb(uint8_t __attribute__((unused)) sender_id, float distance) { static float last_offset = 0.; /* update filter assuming a flat ground */ if (distance < INS_SONAR_MAX_RANGE && distance > INS_SONAR_MIN_RANGE #ifdef INS_SONAR_THROTTLE_THRESHOLD && stabilization_cmd[COMMAND_THRUST] < INS_SONAR_THROTTLE_THRESHOLD #endif #ifdef INS_SONAR_BARO_THRESHOLD && ins_int.baro_z > -INS_SONAR_BARO_THRESHOLD /* z down */ #endif && ins_int.update_on_agl && ins_int.baro_initialized) { vff_update_z_conf(-(distance), VFF_R_SONAR_0 + VFF_R_SONAR_OF_M * fabsf(distance)); last_offset = vff.offset; } else { /* update offset with last value to avoid divergence */ vff_update_offset(last_offset); } /* reset the counter to indicate we just had a measurement update */ ins_int.propagation_cnt = 0; } #endif // USE_SONAR /** initialize the local origin (ltp_def) from flight plan position */ static void ins_init_origin_from_flightplan(void) { struct LlaCoor_i llh_nav0; /* Height above the ellipsoid */ llh_nav0.lat = NAV_LAT0; llh_nav0.lon = NAV_LON0; /* NAV_ALT0 = ground alt above msl, NAV_MSL0 = geoid-height (msl) over ellipsoid */ llh_nav0.alt = NAV_ALT0 + NAV_MSL0; struct EcefCoor_i ecef_nav0; ecef_of_lla_i(&ecef_nav0, &llh_nav0); ltp_def_from_ecef_i(&ins_int.ltp_def, &ecef_nav0); ins_int.ltp_def.hmsl = NAV_ALT0; stateSetLocalOrigin_i(&ins_int.ltp_def); } /** copy position and speed to state interface */ static void ins_ned_to_state(void) { stateSetPositionNed_i(&ins_int.ltp_pos); stateSetSpeedNed_i(&ins_int.ltp_speed); stateSetAccelNed_i(&ins_int.ltp_accel); #if defined SITL && USE_NPS if (nps_bypass_ins) { sim_overwrite_ins(); } #endif }
void gps_skytraq_read_message(void) { //DEBUG_S1_ON(); if (gps_skytraq.msg_id == SKYTRAQ_ID_NAVIGATION_DATA) { gps.ecef_pos.x = SKYTRAQ_NAVIGATION_DATA_ECEFX(gps_skytraq.msg_buf); gps.ecef_pos.y = SKYTRAQ_NAVIGATION_DATA_ECEFY(gps_skytraq.msg_buf); gps.ecef_pos.z = SKYTRAQ_NAVIGATION_DATA_ECEFZ(gps_skytraq.msg_buf); gps.ecef_vel.x = SKYTRAQ_NAVIGATION_DATA_ECEFVX(gps_skytraq.msg_buf); gps.ecef_vel.y = SKYTRAQ_NAVIGATION_DATA_ECEFVY(gps_skytraq.msg_buf); gps.ecef_vel.z = SKYTRAQ_NAVIGATION_DATA_ECEFVZ(gps_skytraq.msg_buf); gps.lla_pos.lat = RadOfDeg(SKYTRAQ_NAVIGATION_DATA_LAT(gps_skytraq.msg_buf)); gps.lla_pos.lon = RadOfDeg(SKYTRAQ_NAVIGATION_DATA_LON(gps_skytraq.msg_buf)); gps.lla_pos.alt = SKYTRAQ_NAVIGATION_DATA_AEL(gps_skytraq.msg_buf)/10; gps.hmsl = SKYTRAQ_NAVIGATION_DATA_ASL(gps_skytraq.msg_buf)/10; // pacc; // sacc; // gps.pdop = SKYTRAQ_NAVIGATION_DATA_PDOP(gps_skytraq.msg_buf); gps.num_sv = SKYTRAQ_NAVIGATION_DATA_NumSV(gps_skytraq.msg_buf); gps.tow = SKYTRAQ_NAVIGATION_DATA_TOW(gps_skytraq.msg_buf)/10; switch (SKYTRAQ_NAVIGATION_DATA_FixMode(gps_skytraq.msg_buf)) { case SKYTRAQ_FIX_3D_DGPS: case SKYTRAQ_FIX_3D: gps.fix = GPS_FIX_3D; break; case SKYTRAQ_FIX_2D: gps.fix = GPS_FIX_2D; break; default: gps.fix = GPS_FIX_NONE; } #if GPS_USE_LATLONG /* Computes from (lat, long) in the referenced UTM zone */ struct LlaCoor_f lla_f; lla_f.lat = ((float) gps.lla_pos.lat) / 1e7; lla_f.lon = ((float) gps.lla_pos.lon) / 1e7; struct UtmCoor_f utm_f; utm_f.zone = nav_utm_zone0; /* convert to utm */ utm_of_lla_f(&utm_f, &lla_f); /* copy results of utm conversion */ gps.utm_pos.east = utm_f.east*100; gps.utm_pos.north = utm_f.north*100; gps.utm_pos.alt = gps.lla_pos.alt; gps.utm_pos.zone = nav_utm_zone0; #endif if ( gps.fix == GPS_FIX_3D ) { if ( distance_too_great( &ref_ltp.ecef, &gps.ecef_pos ) ) { // just grab current ecef_pos as reference. ltp_def_from_ecef_i( &ref_ltp, &gps.ecef_pos ); } // convert ecef velocity vector to NED vector. ned_of_ecef_vect_i( &gps.ned_vel, &ref_ltp, &gps.ecef_vel ); // ground course in radians gps.course = ( M_PI_4 + atan2( -gps.ned_vel.y, gps.ned_vel.x )) * 1e7; // GT: gps.cacc = ... ? what should course accuracy be? // ground speed gps.gspeed = sqrt( gps.ned_vel.x * gps.ned_vel.x + gps.ned_vel.y * gps.ned_vel.y ); gps.speed_3d = sqrt( gps.ned_vel.x * gps.ned_vel.x + gps.ned_vel.y * gps.ned_vel.y + gps.ned_vel.z * gps.ned_vel.z ); // vertical speed (climb) // solved by gps.ned.z? } //DEBUG_S2_TOGGLE(); #ifdef GPS_LED if (gps.fix == GPS_FIX_3D) { LED_ON(GPS_LED); } else { LED_TOGGLE(GPS_LED); } #endif } //DEBUG_S1_OFF(); }