Copter: systemid mode formatting and name changes

This commit is contained in:
Randy Mackay 2019-10-15 14:38:24 +09:00
parent c11f2247eb
commit 2cb3e446ab
5 changed files with 91 additions and 99 deletions

View File

@ -330,7 +330,7 @@ void Copter::update_batt_compass(void)
// should be run at 400hz // should be run at 400hz
void Copter::fourhundred_hz_logging() void Copter::fourhundred_hz_logging()
{ {
if (should_log(MASK_LOG_ATTITUDE_FAST) && !copter.flightmode->stop_attitude_logging()) { if (should_log(MASK_LOG_ATTITUDE_FAST) && !copter.flightmode->logs_attitude()) {
Log_Write_Attitude(); Log_Write_Attitude();
} }
} }
@ -340,7 +340,7 @@ void Copter::fourhundred_hz_logging()
void Copter::ten_hz_logging_loop() void Copter::ten_hz_logging_loop()
{ {
// log attitude data if we're not already logging at the higher rate // log attitude data if we're not already logging at the higher rate
if (should_log(MASK_LOG_ATTITUDE_MED) && !should_log(MASK_LOG_ATTITUDE_FAST) && !copter.flightmode->stop_attitude_logging()) { if (should_log(MASK_LOG_ATTITUDE_MED) && !should_log(MASK_LOG_ATTITUDE_FAST) && !copter.flightmode->logs_attitude()) {
Log_Write_Attitude(); Log_Write_Attitude();
} }
// log EKF attitude data // log EKF attitude data

View File

@ -95,7 +95,7 @@ enum tuning_func {
TUNING_RATE_MOT_YAW_HEADROOM = 55, // motors yaw headroom minimum TUNING_RATE_MOT_YAW_HEADROOM = 55, // motors yaw headroom minimum
TUNING_RATE_YAW_FILT = 56, // yaw rate input filter TUNING_RATE_YAW_FILT = 56, // yaw rate input filter
TUNING_WINCH = 57, // winch control (not actually a value to be tuned) TUNING_WINCH = 57, // winch control (not actually a value to be tuned)
SYSTEM_ID_MAGNITUDE = 58 // magnitude of the system ID signal TUNING_SYSTEM_ID_MAGNITUDE = 58 // magnitude of the system ID signal
}; };
// Acro Trainer types // Acro Trainer types

View File

@ -56,7 +56,7 @@ public:
virtual bool is_autopilot() const { return false; } virtual bool is_autopilot() const { return false; }
virtual bool has_user_takeoff(bool must_navigate) const { return false; } virtual bool has_user_takeoff(bool must_navigate) const { return false; }
virtual bool in_guided_mode() const { return false; } virtual bool in_guided_mode() const { return false; }
virtual bool stop_attitude_logging() const { return false; } virtual bool logs_attitude() const { return false; }
// return a string for this flightmode // return a string for this flightmode
virtual const char *name() const = 0; virtual const char *name() const = 0;
@ -1185,8 +1185,8 @@ public:
bool has_manual_throttle() const override { return false; } bool has_manual_throttle() const override { return false; }
bool allows_arming(bool from_gcs) const override { return true; }; bool allows_arming(bool from_gcs) const override { return true; };
bool is_autopilot() const override { return false; } bool is_autopilot() const override { return false; }
bool stop_attitude_logging() const override { return true; } bool logs_attitude() const override { return true; }
void set_magnitude(float input) {waveform_magnitude = input;} void set_magnitude(float input) { waveform_magnitude = input; }
static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info[];
@ -1196,48 +1196,47 @@ protected:
const char *name4() const override { return "SYSI"; } const char *name4() const override { return "SYSI"; }
private: private:
void log_data();
float waveform(float time);
enum AxisType { void log_data();
NONE = 0, // none float waveform(float time);
INPUT_ROLL = 1, // angle input roll axis is being excited
INPUT_PITCH = 2, // angle pitch axis is being excited enum class AxisType {
INPUT_YAW = 3, // angle yaw axis is being excited NONE = 0, // none
RECOVER_ROLL = 4, // angle roll axis is being excited INPUT_ROLL = 1, // angle input roll axis is being excited
RECOVER_PITCH = 5, // angle pitch axis is being excited INPUT_PITCH = 2, // angle pitch axis is being excited
RECOVER_YAW = 6, // angle yaw axis is being excited INPUT_YAW = 3, // angle yaw axis is being excited
RATE_ROLL = 7, // rate roll axis is being excited RECOVER_ROLL = 4, // angle roll axis is being excited
RATE_PITCH = 8, // rate pitch axis is being excited RECOVER_PITCH = 5, // angle pitch axis is being excited
RATE_YAW = 9, // rate yaw axis is being excited RECOVER_YAW = 6, // angle yaw axis is being excited
MIX_ROLL = 10, // mixer roll axis is being excited RATE_ROLL = 7, // rate roll axis is being excited
MIX_PITCH = 11, // mixer pitch axis is being excited RATE_PITCH = 8, // rate pitch axis is being excited
MIX_YAW = 12, // mixer pitch axis is being excited RATE_YAW = 9, // rate yaw axis is being excited
MIX_THROTTLE = 13, // mixer throttle axis is being excited MIX_ROLL = 10, // mixer roll axis is being excited
MIX_PITCH = 11, // mixer pitch axis is being excited
MIX_YAW = 12, // mixer pitch axis is being excited
MIX_THROTTLE = 13, // mixer throttle axis is being excited
}; };
AP_Int8 systemID_axis; // Controls which axis are being excited AP_Int8 axis; // Controls which axis are being excited
AP_Float waveform_magnitude; // Magnitude of chirp waveform AP_Float waveform_magnitude;// Magnitude of chirp waveform
AP_Float frequency_start; // Frequency at the start of the chirp AP_Float frequency_start; // Frequency at the start of the chirp
AP_Float frequency_stop; // Frequency at the end of the chirp AP_Float frequency_stop; // Frequency at the end of the chirp
AP_Float time_fade_in; // Time to reach maximum amplitude of chirp AP_Float time_fade_in; // Time to reach maximum amplitude of chirp
AP_Float time_record; // Time taken to complete the chirp waveform AP_Float time_record; // Time taken to complete the chirp waveform
AP_Float time_fade_out; // Time to reach zero amplitude after chirp finishes AP_Float time_fade_out; // Time to reach zero amplitude after chirp finishes
bool att_bf_feedforward; // Setting of attitude_control->get_bf_feedforward bool att_bf_feedforward; // Setting of attitude_control->get_bf_feedforward
float waveform_time; // Time reference for waveform float waveform_time; // Time reference for waveform
float waveform_sample; // Current waveform sample float waveform_sample; // Current waveform sample
float waveform_freq_rads; // Instantaneous waveform frequency float waveform_freq_rads; // Instantaneous waveform frequency
float time_const_freq; // Time at constant frequency before chirp starts float time_const_freq; // Time at constant frequency before chirp starts
int8_t log_subsample; // Subsample multiple for logging. int8_t log_subsample; // Subsample multiple for logging.
// System ID states // System ID states
enum SystemIDModeState { enum class SystemIDModeState {
SystemID_Stopped, SYSTEMID_STATE_STOPPED,
SystemID_Testing SYSTEMID_STATE_TESTING
}; } systemid_state;
SystemIDModeState systemIDState;
}; };
class ModeThrow : public Mode { class ModeThrow : public Mode {

View File

@ -13,16 +13,16 @@ const AP_Param::GroupInfo ModeSystemId::var_info[] = {
// @Description: Controls which axis are being excited // @Description: Controls which axis are being excited
// @User: Standard // @User: Standard
// @Values: 0:None, 1:Input Roll Angle, 2:Input Pitch Angle, 3:Input Yaw Angle, 4:Recovery Roll Angle, 5:Recovery Pitch Angle, 6:Recovery Yaw Angle, 7:Rate Roll, 8:Rate Pitch, 9:Rate Yaw, 10:Mixer Roll, 11:Mixer Pitch, 12:Mixer Yaw, 13:Mixer Thrust // @Values: 0:None, 1:Input Roll Angle, 2:Input Pitch Angle, 3:Input Yaw Angle, 4:Recovery Roll Angle, 5:Recovery Pitch Angle, 6:Recovery Yaw Angle, 7:Rate Roll, 8:Rate Pitch, 9:Rate Yaw, 10:Mixer Roll, 11:Mixer Pitch, 12:Mixer Yaw, 13:Mixer Thrust
AP_GROUPINFO("_AXIS", 1, ModeSystemId, systemID_axis, 0), AP_GROUPINFO("_AXIS", 1, ModeSystemId, axis, 0),
// @Param: _MAG // @Param: _MAGNITUDE
// @DisplayName: Chirp Magnitude // @DisplayName: System identification Chirp Magnitude
// @Description: Magnitude of sweep in deg, deg/s and 0-1 for mixer outputs. // @Description: Magnitude of sweep in deg, deg/s and 0-1 for mixer outputs.
// @User: Standard // @User: Standard
AP_GROUPINFO("_MAG", 2, ModeSystemId, waveform_magnitude, 15), AP_GROUPINFO("_MAGNITUDE", 2, ModeSystemId, waveform_magnitude, 15),
// @Param: _F_START_HZ // @Param: _F_START_HZ
// @DisplayName: Start Frequency // @DisplayName: System identification Start Frequency
// @Description: Frequency at the start of the sweep // @Description: Frequency at the start of the sweep
// @Range: 0.01 100 // @Range: 0.01 100
// @Units: Hz // @Units: Hz
@ -30,7 +30,7 @@ const AP_Param::GroupInfo ModeSystemId::var_info[] = {
AP_GROUPINFO("_F_START_HZ", 3, ModeSystemId, frequency_start, 0.5f), AP_GROUPINFO("_F_START_HZ", 3, ModeSystemId, frequency_start, 0.5f),
// @Param: _F_STOP_HZ // @Param: _F_STOP_HZ
// @DisplayName: Stop Frequency // @DisplayName: System identification Stop Frequency
// @Description: Frequency at the end of the sweep // @Description: Frequency at the end of the sweep
// @Range: 0.01 100 // @Range: 0.01 100
// @Units: Hz // @Units: Hz
@ -38,7 +38,7 @@ const AP_Param::GroupInfo ModeSystemId::var_info[] = {
AP_GROUPINFO("_F_STOP_HZ", 4, ModeSystemId, frequency_stop, 40), AP_GROUPINFO("_F_STOP_HZ", 4, ModeSystemId, frequency_stop, 40),
// @Param: _T_FADE_IN // @Param: _T_FADE_IN
// @DisplayName: Fade in time // @DisplayName: System identification Fade in time
// @Description: Time to reach maximum amplitude of sweep // @Description: Time to reach maximum amplitude of sweep
// @Range: 0 20 // @Range: 0 20
// @Units: s // @Units: s
@ -46,7 +46,7 @@ const AP_Param::GroupInfo ModeSystemId::var_info[] = {
AP_GROUPINFO("_T_FADE_IN", 5, ModeSystemId, time_fade_in, 15), AP_GROUPINFO("_T_FADE_IN", 5, ModeSystemId, time_fade_in, 15),
// @Param: _T_REC // @Param: _T_REC
// @DisplayName: Total Sweep length // @DisplayName: System identification Total Sweep length
// @Description: Time taken to complete the sweep // @Description: Time taken to complete the sweep
// @Range: 0 255 // @Range: 0 255
// @Units: s // @Units: s
@ -54,7 +54,7 @@ const AP_Param::GroupInfo ModeSystemId::var_info[] = {
AP_GROUPINFO("_T_REC", 6, ModeSystemId, time_record, 70), AP_GROUPINFO("_T_REC", 6, ModeSystemId, time_record, 70),
// @Param: _T_FADE_OUT // @Param: _T_FADE_OUT
// @DisplayName: Fade out time // @DisplayName: System identification Fade out time
// @Description: Time to reach zero amplitude at the end of the sweep // @Description: Time to reach zero amplitude at the end of the sweep
// @Range: 0 5 // @Range: 0 5
// @Units: s // @Units: s
@ -86,12 +86,12 @@ bool ModeSystemId::init(bool ignore_checks)
att_bf_feedforward = attitude_control->get_bf_feedforward(); att_bf_feedforward = attitude_control->get_bf_feedforward();
waveform_time = 0.0f; waveform_time = 0.0f;
time_const_freq = 2.0f / frequency_start; // Two full cycles at the starting frequency time_const_freq = 2.0f / frequency_start; // Two full cycles at the starting frequency
systemIDState = SystemID_Testing; systemid_state = SystemIDModeState::SYSTEMID_STATE_TESTING;
log_subsample = 0; log_subsample = 0;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Starting: axis=%d", (unsigned)systemID_axis); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Starting: axis=%d", (unsigned)axis);
copter.Log_Write_SysID_Setup(systemID_axis, waveform_magnitude, frequency_start, frequency_stop, time_fade_in, time_const_freq, time_record, time_fade_out); copter.Log_Write_SysID_Setup(axis, waveform_magnitude, frequency_start, frequency_stop, time_fade_in, time_const_freq, time_record, time_fade_out);
return true; return true;
} }
@ -156,81 +156,82 @@ void ModeSystemId::run()
float pilot_throttle_scaled = get_pilot_desired_throttle(); float pilot_throttle_scaled = get_pilot_desired_throttle();
#endif #endif
if((systemIDState == SystemID_Testing) && (!is_positive(frequency_start) || !is_positive(frequency_stop) || is_negative(time_fade_in) || !is_positive(time_record) || is_negative(time_fade_out) || (time_record <= time_const_freq))) { if ((systemid_state == SystemIDModeState::SYSTEMID_STATE_TESTING) &&
systemIDState = SystemID_Stopped; (!is_positive(frequency_start) || !is_positive(frequency_stop) || is_negative(time_fade_in) || !is_positive(time_record) || is_negative(time_fade_out) || (time_record <= time_const_freq))) {
systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Parameter Error"); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Parameter Error");
} }
waveform_time += G_Dt; waveform_time += G_Dt;
waveform_sample = waveform(waveform_time - SYSTEM_ID_DELAY); waveform_sample = waveform(waveform_time - SYSTEM_ID_DELAY);
switch (systemIDState) { switch (systemid_state) {
case SystemID_Stopped: case SystemIDModeState::SYSTEMID_STATE_STOPPED:
break; break;
case SystemID_Testing: case SystemIDModeState::SYSTEMID_STATE_TESTING:
attitude_control->bf_feedforward(att_bf_feedforward); attitude_control->bf_feedforward(att_bf_feedforward);
if(copter.ap.land_complete) { if (copter.ap.land_complete) {
systemIDState = SystemID_Stopped; systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: Landed"); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: Landed");
break; break;
} }
if(attitude_control->lean_angle()*100 > attitude_control->lean_angle_max()) { if (attitude_control->lean_angle()*100 > attitude_control->lean_angle_max()) {
systemIDState = SystemID_Stopped; systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: lean=%f max=%f", (double)attitude_control->lean_angle(), (double)attitude_control->lean_angle_max()); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: lean=%f max=%f", (double)attitude_control->lean_angle(), (double)attitude_control->lean_angle_max());
break; break;
} }
if(waveform_time > SYSTEM_ID_DELAY + time_fade_in + time_const_freq + time_record + time_fade_out) { if (waveform_time > SYSTEM_ID_DELAY + time_fade_in + time_const_freq + time_record + time_fade_out) {
systemIDState = SystemID_Stopped; systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Finished"); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Finished");
break; break;
} }
switch (systemID_axis) { switch ((AxisType)axis.get()) {
case NONE: case AxisType::NONE:
systemIDState = SystemID_Stopped; systemid_state = SystemIDModeState::SYSTEMID_STATE_STOPPED;
gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: axis = 0"); gcs().send_text(MAV_SEVERITY_INFO, "SystemID Stopped: axis = 0");
break; break;
case INPUT_ROLL: case AxisType::INPUT_ROLL:
target_roll += waveform_sample*100.0f; target_roll += waveform_sample*100.0f;
break; break;
case INPUT_PITCH: case AxisType::INPUT_PITCH:
target_pitch += waveform_sample*100.0f; target_pitch += waveform_sample*100.0f;
break; break;
case INPUT_YAW: case AxisType::INPUT_YAW:
target_yaw_rate += waveform_sample*100.0f; target_yaw_rate += waveform_sample*100.0f;
break; break;
case RECOVER_ROLL: case AxisType::RECOVER_ROLL:
target_roll += waveform_sample*100.0f; target_roll += waveform_sample*100.0f;
attitude_control->bf_feedforward(false); attitude_control->bf_feedforward(false);
break; break;
case RECOVER_PITCH: case AxisType::RECOVER_PITCH:
target_pitch += waveform_sample*100.0f; target_pitch += waveform_sample*100.0f;
attitude_control->bf_feedforward(false); attitude_control->bf_feedforward(false);
break; break;
case RECOVER_YAW: case AxisType::RECOVER_YAW:
target_yaw_rate += waveform_sample*100.0f; target_yaw_rate += waveform_sample*100.0f;
attitude_control->bf_feedforward(false); attitude_control->bf_feedforward(false);
break; break;
case RATE_ROLL: case AxisType::RATE_ROLL:
attitude_control->rate_bf_roll_sysid(radians(waveform_sample)); attitude_control->rate_bf_roll_sysid(radians(waveform_sample));
break; break;
case RATE_PITCH: case AxisType::RATE_PITCH:
attitude_control->rate_bf_pitch_sysid(radians(waveform_sample)); attitude_control->rate_bf_pitch_sysid(radians(waveform_sample));
break; break;
case RATE_YAW: case AxisType::RATE_YAW:
attitude_control->rate_bf_yaw_sysid(radians(waveform_sample)); attitude_control->rate_bf_yaw_sysid(radians(waveform_sample));
break; break;
case MIX_ROLL: case AxisType::MIX_ROLL:
attitude_control->actuator_roll_sysid(waveform_sample); attitude_control->actuator_roll_sysid(waveform_sample);
break; break;
case MIX_PITCH: case AxisType::MIX_PITCH:
attitude_control->actuator_pitch_sysid(waveform_sample); attitude_control->actuator_pitch_sysid(waveform_sample);
break; break;
case MIX_YAW: case AxisType::MIX_YAW:
attitude_control->actuator_yaw_sysid(waveform_sample); attitude_control->actuator_yaw_sysid(waveform_sample);
break; break;
case MIX_THROTTLE: case AxisType::MIX_THROTTLE:
pilot_throttle_scaled += waveform_sample; pilot_throttle_scaled += waveform_sample;
break; break;
} }
@ -240,8 +241,6 @@ void ModeSystemId::run()
// call attitude controller // call attitude controller
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate); attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
// body-frame rate controller is run directly from 100hz loop
// output pilot's throttle // output pilot's throttle
if (copter.is_tradheli()) { if (copter.is_tradheli()) {
attitude_control->set_throttle_out(pilot_throttle_scaled, false, g.throttle_filt); attitude_control->set_throttle_out(pilot_throttle_scaled, false, g.throttle_filt);
@ -249,13 +248,13 @@ void ModeSystemId::run()
attitude_control->set_throttle_out(pilot_throttle_scaled, true, g.throttle_filt); attitude_control->set_throttle_out(pilot_throttle_scaled, true, g.throttle_filt);
} }
if(log_subsample <= 0){ if (log_subsample <= 0) {
log_data(); log_data();
if(copter.should_log(MASK_LOG_ATTITUDE_FAST) && copter.should_log(MASK_LOG_ATTITUDE_MED)) { if (copter.should_log(MASK_LOG_ATTITUDE_FAST) && copter.should_log(MASK_LOG_ATTITUDE_MED)) {
log_subsample = 1; log_subsample = 1;
} else if(copter.should_log(MASK_LOG_ATTITUDE_FAST)){ } else if (copter.should_log(MASK_LOG_ATTITUDE_FAST)) {
log_subsample = 2; log_subsample = 2;
} else if(copter.should_log(MASK_LOG_ATTITUDE_MED)){ } else if (copter.should_log(MASK_LOG_ATTITUDE_MED)) {
log_subsample = 4; log_subsample = 4;
} else { } else {
log_subsample = 8; log_subsample = 8;
@ -264,26 +263,20 @@ void ModeSystemId::run()
log_subsample -= 1; log_subsample -= 1;
} }
// init_test - initialises the test // log system id and attitude
void ModeSystemId::log_data() void ModeSystemId::log_data()
{ {
int8_t index = copter.ahrs.get_primary_gyro_index(); uint8_t index = copter.ahrs.get_primary_gyro_index();
if(index < 0){
index = 0;
}
Vector3f delta_angle; Vector3f delta_angle;
copter.ins.get_delta_angle(index, delta_angle); copter.ins.get_delta_angle(index, delta_angle);
float delta_angle_dt = copter.ins.get_delta_angle_dt(index); float delta_angle_dt = copter.ins.get_delta_angle_dt(index);
index = copter.ahrs.get_primary_accel_index(); index = copter.ahrs.get_primary_accel_index();
if(index < 0){
index = 0;
}
Vector3f delta_velocity; Vector3f delta_velocity;
copter.ins.get_delta_velocity(index, delta_velocity); copter.ins.get_delta_velocity(index, delta_velocity);
float delta_velocity_dt = copter.ins.get_delta_velocity_dt(index); float delta_velocity_dt = copter.ins.get_delta_velocity_dt(index);
if(is_positive(delta_angle_dt) && is_positive(delta_velocity_dt)){ if (is_positive(delta_angle_dt) && is_positive(delta_velocity_dt)) {
copter.Log_Write_SysID_Data(waveform_time, waveform_sample, waveform_freq_rads / (2 * M_PI), degrees(delta_angle.x / delta_angle_dt), degrees(delta_angle.y / delta_angle_dt), degrees(delta_angle.z / delta_angle_dt), delta_velocity.x / delta_velocity_dt, delta_velocity.y / delta_velocity_dt, delta_velocity.z / delta_velocity_dt); copter.Log_Write_SysID_Data(waveform_time, waveform_sample, waveform_freq_rads / (2 * M_PI), degrees(delta_angle.x / delta_angle_dt), degrees(delta_angle.y / delta_angle_dt), degrees(delta_angle.z / delta_angle_dt), delta_velocity.x / delta_velocity_dt, delta_velocity.y / delta_velocity_dt, delta_velocity.z / delta_velocity_dt);
} }
@ -302,7 +295,7 @@ float ModeSystemId::waveform(float time)
float B = logf(wMax / wMin); float B = logf(wMax / wMin);
if(time <= 0.0f) { if (time <= 0.0f) {
window = 0.0f; window = 0.0f;
} else if (time <= time_fade_in) { } else if (time <= time_fade_in) {
window = 0.5 - 0.5 * cosf(M_PI * time / time_fade_in); window = 0.5 - 0.5 * cosf(M_PI * time / time_fade_in);
@ -314,7 +307,7 @@ float ModeSystemId::waveform(float time)
window = 0.0; window = 0.0;
} }
if(time <= 0.0f) { if (time <= 0.0f) {
waveform_freq_rads = wMin; waveform_freq_rads = wMin;
output = 0.0f; output = 0.0f;
} else if (time <= time_const_freq) { } else if (time <= time_const_freq) {

View File

@ -229,7 +229,7 @@ void Copter::tuning()
#endif #endif
#if MODE_SYSTEMID_ENABLED == ENABLED #if MODE_SYSTEMID_ENABLED == ENABLED
case SYSTEM_ID_MAGNITUDE: case TUNING_SYSTEM_ID_MAGNITUDE:
copter.mode_systemid.set_magnitude(tuning_value); copter.mode_systemid.set_magnitude(tuning_value);
break; break;
} }