/** Read attitude setpoint from RC as euler angles * @param[in] coordinated_turn true if in horizontal mode forward * @param[in] in_carefree true if in carefree mode * @param[in] in_flight true if in flight * @param[out] sp attitude setpoint as euler angles */ void stabilization_attitude_read_rc_setpoint_eulers(struct Int32Eulers *sp, bool_t in_flight, bool_t in_carefree, bool_t coordinated_turn) { sp->phi = get_rc_roll(); sp->theta = get_rc_pitch(); if (in_flight) { /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */ if (YAW_DEADBAND_EXCEEDED() && !THROTTLE_STICK_DOWN()) { sp->psi += get_rc_yaw() / RC_UPDATE_FREQ; INT32_ANGLE_NORMALIZE(sp->psi); } if (coordinated_turn) { //Coordinated turn //feedforward estimate angular rotation omega = g*tan(phi)/v //Take v = 9.81/1.3 m/s int32_t omega; const int32_t max_phi = ANGLE_BFP_OF_REAL(RadOfDeg(85.0)); if (abs(sp->phi) < max_phi) { omega = ANGLE_BFP_OF_REAL(1.3 * tanf(ANGLE_FLOAT_OF_BFP(sp->phi))); } else { //max 60 degrees roll, then take constant omega omega = ANGLE_BFP_OF_REAL(1.3 * 1.72305 * ((sp->phi > 0) - (sp->phi < 0))); } sp->psi += omega / RC_UPDATE_FREQ; } #ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT // Make sure the yaw setpoint does not differ too much from the real yaw // to prevent a sudden switch at 180 deg const int32_t delta_limit = ANGLE_BFP_OF_REAL(STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT); int32_t heading = stabilization_attitude_get_heading_i(); int32_t delta_psi = sp->psi - heading; INT32_ANGLE_NORMALIZE(delta_psi); if (delta_psi > delta_limit) { sp->psi = heading + delta_limit; } else if (delta_psi < -delta_limit) { sp->psi = heading - delta_limit; } INT32_ANGLE_NORMALIZE(sp->psi); #endif //Care Free mode if (in_carefree) { //care_free_heading has been set to current psi when entering care free mode. int32_t cos_psi; int32_t sin_psi; int32_t temp_theta; int32_t care_free_delta_psi_i; care_free_delta_psi_i = sp->psi - ANGLE_BFP_OF_REAL(care_free_heading); INT32_ANGLE_NORMALIZE(care_free_delta_psi_i); PPRZ_ITRIG_SIN(sin_psi, care_free_delta_psi_i); PPRZ_ITRIG_COS(cos_psi, care_free_delta_psi_i); temp_theta = INT_MULT_RSHIFT(cos_psi, sp->theta, INT32_ANGLE_FRAC) - INT_MULT_RSHIFT(sin_psi, sp->phi, INT32_ANGLE_FRAC); sp->phi = INT_MULT_RSHIFT(cos_psi, sp->phi, INT32_ANGLE_FRAC) - INT_MULT_RSHIFT(sin_psi, sp->theta, INT32_ANGLE_FRAC); sp->theta = temp_theta; } } else { /* if not flying, use current yaw as setpoint */ sp->psi = stateGetNedToBodyEulers_i()->psi; } }
/** Read attitude setpoint from RC as euler angles * @param[in] coordinated_turn true if in horizontal mode forward * @param[in] in_carefree true if in carefree mode * @param[in] in_flight true if in flight * @param[out] sp attitude setpoint as euler angles */ void stabilization_attitude_read_rc_setpoint_eulers(struct Int32Eulers *sp, bool in_flight, bool in_carefree, bool coordinated_turn) { /* last time this function was called, used to calculate yaw setpoint update */ static float last_ts = 0.f; sp->phi = get_rc_roll(); sp->theta = get_rc_pitch(); if (in_flight) { /* calculate dt for yaw integration */ float dt = get_sys_time_float() - last_ts; /* make sure nothing drastically weird happens, bound dt to 0.5sec */ Bound(dt, 0, 0.5); /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */ if (YAW_DEADBAND_EXCEEDED() && !THROTTLE_STICK_DOWN()) { sp->psi += get_rc_yaw() * dt; INT32_ANGLE_NORMALIZE(sp->psi); } if (coordinated_turn) { //Coordinated turn //feedforward estimate angular rotation omega = g*tan(phi)/v int32_t omega; const int32_t max_phi = ANGLE_BFP_OF_REAL(RadOfDeg(60.0)); if (abs(sp->phi) < max_phi) { omega = ANGLE_BFP_OF_REAL(9.81 / COORDINATED_TURN_AIRSPEED * tanf(ANGLE_FLOAT_OF_BFP(sp->phi))); } else { //max 60 degrees roll omega = ANGLE_BFP_OF_REAL(9.81 / COORDINATED_TURN_AIRSPEED * 1.72305 * ((sp->phi > 0) - (sp->phi < 0))); } sp->psi += omega * dt; } #ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT // Make sure the yaw setpoint does not differ too much from the real yaw // to prevent a sudden switch at 180 deg const int32_t delta_limit = ANGLE_BFP_OF_REAL(STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT); int32_t heading = stabilization_attitude_get_heading_i(); int32_t delta_psi = sp->psi - heading; INT32_ANGLE_NORMALIZE(delta_psi); if (delta_psi > delta_limit) { sp->psi = heading + delta_limit; } else if (delta_psi < -delta_limit) { sp->psi = heading - delta_limit; } INT32_ANGLE_NORMALIZE(sp->psi); #endif //Care Free mode if (in_carefree) { //care_free_heading has been set to current psi when entering care free mode. int32_t cos_psi; int32_t sin_psi; int32_t temp_theta; int32_t care_free_delta_psi_i; care_free_delta_psi_i = sp->psi - ANGLE_BFP_OF_REAL(care_free_heading); INT32_ANGLE_NORMALIZE(care_free_delta_psi_i); PPRZ_ITRIG_SIN(sin_psi, care_free_delta_psi_i); PPRZ_ITRIG_COS(cos_psi, care_free_delta_psi_i); temp_theta = INT_MULT_RSHIFT(cos_psi, sp->theta, INT32_ANGLE_FRAC) - INT_MULT_RSHIFT(sin_psi, sp->phi, INT32_ANGLE_FRAC); sp->phi = INT_MULT_RSHIFT(cos_psi, sp->phi, INT32_ANGLE_FRAC) - INT_MULT_RSHIFT(sin_psi, sp->theta, INT32_ANGLE_FRAC); sp->theta = temp_theta; } } else { /* if not flying, use current yaw as setpoint */ sp->psi = stateGetNedToBodyEulers_i()->psi; } /* update timestamp for dt calculation */ last_ts = get_sys_time_float(); }