mirror of https://github.com/ArduPilot/ardupilot
AC_AutoTune: general cleanup to make code more efficient
This commit is contained in:
parent
9e4d118cc9
commit
528b7eb438
|
@ -71,7 +71,7 @@ void AC_AutoTune_FreqResp::update(float command, float tgt_resp, float meas_resp
|
|||
}
|
||||
|
||||
// cycles are complete! determine gain and phase and exit
|
||||
if (max_meas_cnt > AUTOTUNE_DWELL_CYCLES + 1 && max_target_cnt > AUTOTUNE_DWELL_CYCLES + 1 && excitation == DWELL) {
|
||||
if (max_meas_cnt > dwell_cycles + 1 && max_target_cnt > dwell_cycles + 1 && excitation == DWELL) {
|
||||
float delta_time = 0.0f;
|
||||
float sum_gain = 0.0f;
|
||||
uint8_t cnt = 0;
|
||||
|
@ -81,7 +81,7 @@ void AC_AutoTune_FreqResp::update(float command, float tgt_resp, float meas_resp
|
|||
float tgt_ampl = 0.0f;
|
||||
uint32_t meas_time = 0;
|
||||
uint32_t tgt_time = 0;
|
||||
for (uint8_t i = 0; i < AUTOTUNE_DWELL_CYCLES; i++) {
|
||||
for (uint8_t i = 0; i < dwell_cycles; i++) {
|
||||
meas_cnt=0;
|
||||
tgt_cnt=0;
|
||||
pull_from_meas_buffer(meas_cnt, meas_ampl, meas_time);
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <AP_Math/AP_Math.h>
|
||||
|
||||
#define AUTOTUNE_DWELL_CYCLES 6
|
||||
|
||||
class AC_AutoTune_FreqResp {
|
||||
public:
|
||||
// Constructor
|
||||
|
@ -40,6 +38,10 @@ public:
|
|||
// Reset cycle_complete flag
|
||||
void reset_cycle_complete() { cycle_complete = false; }
|
||||
|
||||
void set_dwell_cycles(uint8_t cycles) { dwell_cycles = cycles; }
|
||||
|
||||
uint8_t get_dwell_cycles() { return dwell_cycles;}
|
||||
|
||||
// Frequency response data accessors
|
||||
float get_freq() { return curr_test_freq; }
|
||||
float get_gain() { return curr_test_gain; }
|
||||
|
@ -137,6 +139,9 @@ private:
|
|||
// flag indicating when one oscillation cycle is complete
|
||||
bool cycle_complete = false;
|
||||
|
||||
// number of dwell cycles to complete for dwell excitation
|
||||
uint8_t dwell_cycles;
|
||||
|
||||
// current test frequency, gain, and phase
|
||||
float curr_test_freq;
|
||||
float curr_test_gain;
|
||||
|
@ -179,10 +184,10 @@ private:
|
|||
};
|
||||
|
||||
// Buffer object for measured peak data
|
||||
ObjectBuffer<peak_info> meas_peak_info_buffer{AUTOTUNE_DWELL_CYCLES};
|
||||
ObjectBuffer<peak_info> meas_peak_info_buffer{6};
|
||||
|
||||
// Buffer object for target peak data
|
||||
ObjectBuffer<peak_info> tgt_peak_info_buffer{AUTOTUNE_DWELL_CYCLES};
|
||||
ObjectBuffer<peak_info> tgt_peak_info_buffer{6};
|
||||
|
||||
// Push data into measured peak data buffer object
|
||||
void push_to_meas_buffer(uint16_t count, float amplitude, uint32_t time_ms);
|
||||
|
|
|
@ -139,6 +139,11 @@ AC_AutoTune_Heli::AC_AutoTune_Heli()
|
|||
// initialize tests for each tune type
|
||||
void AC_AutoTune_Heli::test_init()
|
||||
{
|
||||
|
||||
AC_AutoTune_FreqResp::InputType input_type = AC_AutoTune_FreqResp::InputType::DWELL;
|
||||
AC_AutoTune_FreqResp::ResponseType resp_type = AC_AutoTune_FreqResp::ResponseType::RATE;
|
||||
uint8_t num_dwell_cycles = 6;
|
||||
DwellType dwell_test_type = RATE;
|
||||
switch (tune_type) {
|
||||
case RFF_UP:
|
||||
freq_cnt = 12;
|
||||
|
@ -146,73 +151,72 @@ void AC_AutoTune_Heli::test_init()
|
|||
curr_test.freq = test_freq[freq_cnt];
|
||||
start_freq = curr_test.freq;
|
||||
stop_freq = curr_test.freq;
|
||||
|
||||
attitude_control->bf_feedforward(false);
|
||||
attitude_control->use_sqrt_controller(false);
|
||||
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
dwell_test_init(start_freq, stop_freq, start_freq, RATE);
|
||||
|
||||
step_time_limit_ms = (uint32_t) 23000;
|
||||
// variables needed to initialize frequency response object and dwell test method
|
||||
resp_type = AC_AutoTune_FreqResp::ResponseType::RATE;
|
||||
pre_calc_cycles = 1.0f;
|
||||
num_dwell_cycles = 3;
|
||||
dwell_test_type = RATE;
|
||||
|
||||
break;
|
||||
case MAX_GAINS:
|
||||
case RP_UP:
|
||||
case RD_UP:
|
||||
// initialize start frequency
|
||||
if (is_zero(start_freq)) {
|
||||
if (tune_type == RP_UP || tune_type == RD_UP) {
|
||||
// continue using frequency where testing left off or RD_UP completed
|
||||
if (test_phase[12] > 0.0f && test_phase[12] < 180.0f) {
|
||||
freq_cnt = 12;
|
||||
// start with freq found for sweep where phase was 180 deg
|
||||
} else if (!is_zero(sweep_tgt.ph180.freq)) {
|
||||
freq_cnt = 12;
|
||||
test_freq[freq_cnt] = sweep_tgt.ph180.freq - 0.25f * 3.14159f * 2.0f;
|
||||
// otherwise start at min freq to step up in dwell frequency until phase > 160 deg
|
||||
} else {
|
||||
freq_cnt = 0;
|
||||
test_freq[freq_cnt] = min_sweep_freq;
|
||||
}
|
||||
if (!is_zero(sweep_mtr.ph180.freq)) {
|
||||
freq_cnt = 12;
|
||||
test_freq[freq_cnt] = sweep_mtr.ph180.freq - 0.25f * 3.14159f * 2.0f;
|
||||
curr_test.freq = test_freq[freq_cnt];
|
||||
start_freq = curr_test.freq;
|
||||
stop_freq = curr_test.freq;
|
||||
|
||||
// MAX_GAINS starts with a sweep initially but if it has been completed then start dwells at the freq for 180 deg phase
|
||||
} else {
|
||||
if (!is_zero(sweep_mtr.ph180.freq)) {
|
||||
freq_cnt = 12;
|
||||
test_freq[freq_cnt] = sweep_mtr.ph180.freq - 0.25f * 3.14159f * 2.0f;
|
||||
curr_test.freq = test_freq[freq_cnt];
|
||||
start_freq = curr_test.freq;
|
||||
stop_freq = curr_test.freq;
|
||||
if (tune_type == MAX_GAINS) {
|
||||
reset_maxgains_update_gain_variables();
|
||||
}
|
||||
} else {
|
||||
start_freq = min_sweep_freq;
|
||||
stop_freq = max_sweep_freq;
|
||||
if (tune_type == MAX_GAINS) {
|
||||
reset_maxgains_update_gain_variables();
|
||||
}
|
||||
} else {
|
||||
start_freq = min_sweep_freq;
|
||||
stop_freq = max_sweep_freq;
|
||||
}
|
||||
}
|
||||
attitude_control->bf_feedforward(false);
|
||||
attitude_control->use_sqrt_controller(false);
|
||||
|
||||
if (!is_equal(start_freq,stop_freq)) {
|
||||
// initialize determine_gain function whenever test is initialized
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
dwell_test_init(start_freq, stop_freq, stop_freq, RATE);
|
||||
} else {
|
||||
// initialize determine_gain function whenever test is initialized
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||
dwell_test_init(start_freq, stop_freq, start_freq, RATE);
|
||||
}
|
||||
if (!is_zero(start_freq)) {
|
||||
// 4 seconds is added to allow aircraft to achieve start attitude. Then the time to conduct the dwells is added to it.
|
||||
step_time_limit_ms = (uint32_t)(4000 + (float)(AUTOTUNE_DWELL_CYCLES + 2) * 1000.0f * M_2PI / start_freq);
|
||||
// variables needed to initialize frequency response object and dwell test method
|
||||
resp_type = AC_AutoTune_FreqResp::ResponseType::RATE;
|
||||
dwell_test_type = RATE;
|
||||
pre_calc_cycles = 6.25f;
|
||||
num_dwell_cycles = 6;
|
||||
|
||||
break;
|
||||
case RP_UP:
|
||||
case RD_UP:
|
||||
// initialize start frequency
|
||||
if (is_zero(start_freq)) {
|
||||
// continue using frequency where testing left off or RD_UP completed
|
||||
if (test_phase[12] > 0.0f && test_phase[12] < 180.0f) {
|
||||
freq_cnt = 12;
|
||||
// start with freq found for sweep where phase was 180 deg
|
||||
} else if (!is_zero(sweep_tgt.ph180.freq)) {
|
||||
freq_cnt = 12;
|
||||
test_freq[freq_cnt] = sweep_tgt.ph180.freq - 0.25f * 3.14159f * 2.0f;
|
||||
// otherwise start at min freq to step up in dwell frequency until phase > 160 deg
|
||||
} else {
|
||||
freq_cnt = 0;
|
||||
test_freq[freq_cnt] = min_sweep_freq;
|
||||
}
|
||||
curr_test.freq = test_freq[freq_cnt];
|
||||
start_freq = curr_test.freq;
|
||||
stop_freq = curr_test.freq;
|
||||
}
|
||||
attitude_control->bf_feedforward(false);
|
||||
attitude_control->use_sqrt_controller(false);
|
||||
|
||||
// variables needed to initialize frequency response object and dwell test method
|
||||
resp_type = AC_AutoTune_FreqResp::ResponseType::RATE;
|
||||
dwell_test_type = RATE;
|
||||
pre_calc_cycles = 6.25f;
|
||||
num_dwell_cycles = 6;
|
||||
|
||||
break;
|
||||
case SP_UP:
|
||||
// initialize start frequency
|
||||
|
@ -232,23 +236,12 @@ void AC_AutoTune_Heli::test_init()
|
|||
attitude_control->bf_feedforward(false);
|
||||
attitude_control->use_sqrt_controller(false);
|
||||
|
||||
if (!is_equal(start_freq,stop_freq)) {
|
||||
// initialize determine gain function
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
dwell_test_init(start_freq, stop_freq, stop_freq, DRB);
|
||||
} else {
|
||||
// initialize determine gain function
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
dwell_test_init(start_freq, stop_freq, start_freq, DRB);
|
||||
}
|
||||
// variables needed to initialize frequency response object and dwell test method
|
||||
resp_type = AC_AutoTune_FreqResp::ResponseType::ANGLE;
|
||||
dwell_test_type = DRB;
|
||||
pre_calc_cycles = 6.25f;
|
||||
num_dwell_cycles = 6;
|
||||
|
||||
// TODO add time limit for sweep test
|
||||
if (!is_zero(start_freq)) {
|
||||
// 1 seconds is added for a little buffer. Then the time to conduct the dwells is added to it.
|
||||
step_time_limit_ms = (uint32_t)(2000 + (float)(AUTOTUNE_DWELL_CYCLES + 7) * 1000.0f * M_2PI / start_freq);
|
||||
}
|
||||
break;
|
||||
case TUNE_CHECK:
|
||||
// initialize start frequency
|
||||
|
@ -256,20 +249,34 @@ void AC_AutoTune_Heli::test_init()
|
|||
start_freq = min_sweep_freq;
|
||||
stop_freq = max_sweep_freq;
|
||||
}
|
||||
// initialize determine gain function
|
||||
freqresp_tgt.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
freqresp_mtr.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||
dwell_test_init(start_freq, stop_freq, stop_freq, ANGLE);
|
||||
// TODO add time limit for sweep test
|
||||
if (!is_zero(start_freq)) {
|
||||
// 1 seconds is added for a little buffer. Then the time to conduct the dwells is added to it.
|
||||
step_time_limit_ms = (uint32_t)(2000 + (float)(AUTOTUNE_DWELL_CYCLES + 7) * 1000.0f * M_2PI / start_freq);
|
||||
}
|
||||
// variables needed to initialize frequency response object and dwell test method
|
||||
resp_type = AC_AutoTune_FreqResp::ResponseType::ANGLE;
|
||||
dwell_test_type = ANGLE;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize frequency response object
|
||||
if (!is_equal(start_freq,stop_freq)) {
|
||||
input_type = AC_AutoTune_FreqResp::InputType::SWEEP;
|
||||
step_time_limit_ms = sweep_time_ms + 500;
|
||||
} else {
|
||||
input_type = AC_AutoTune_FreqResp::InputType::DWELL;
|
||||
freqresp_tgt.set_dwell_cycles(num_dwell_cycles);
|
||||
freqresp_mtr.set_dwell_cycles(num_dwell_cycles);
|
||||
if (!is_zero(start_freq)) {
|
||||
// time limit set by adding the pre calc cycles with the dwell cycles. 500 ms added to account for settling with buffer.
|
||||
step_time_limit_ms = (uint32_t) (500 + ((float) freqresp_tgt.get_dwell_cycles() + pre_calc_cycles + 2.0f) * 1000.0f * M_2PI / start_freq);
|
||||
}
|
||||
}
|
||||
freqresp_tgt.init(input_type, resp_type);
|
||||
freqresp_mtr.init(input_type, resp_type);
|
||||
|
||||
// initialize dwell test method
|
||||
dwell_test_init(start_freq, stop_freq, start_freq, dwell_test_type);
|
||||
|
||||
start_angles = Vector3f(roll_cd, pitch_cd, desired_yaw_cd); // heli specific
|
||||
}
|
||||
|
||||
|
@ -759,9 +766,14 @@ void AC_AutoTune_Heli::dwell_test_init(float start_frq, float stop_frq, float fi
|
|||
reset_sweep_variables();
|
||||
curr_test.gain = 0.0f;
|
||||
curr_test.phase = 0.0f;
|
||||
chirp_input.init(0.001f * sweep_time_ms, start_frq / M_2PI, stop_frq / M_2PI, 0.0f, 0.0001f * sweep_time_ms, 0.0f);
|
||||
} else {
|
||||
chirp_input.init(0.001f * step_time_limit_ms, start_frq / M_2PI, stop_frq / M_2PI, 0.0f, 0.0001f * step_time_limit_ms, 0.0f);
|
||||
}
|
||||
|
||||
chirp_input.init(sweep_time_ms * 0.001f, start_frq / M_2PI, stop_frq / M_2PI, 0.0f, 0.0001f * sweep_time_ms, 0.0f);
|
||||
cycle_complete_tgt = false;
|
||||
cycle_complete_mtr = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -881,7 +893,7 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
|||
float dwell_gain_tgt = 0.0f;
|
||||
float dwell_phase_tgt = 0.0f;
|
||||
// wait for dwell to start before determining gain and phase
|
||||
if ((float)(now - dwell_start_time_ms) > 6.25f * cycle_time_ms || (!is_equal(start_frq,stop_frq) && settle_time == 0)) {
|
||||
if ((float)(now - dwell_start_time_ms) > pre_calc_cycles * cycle_time_ms || (!is_equal(start_frq,stop_frq) && settle_time == 0)) {
|
||||
freqresp_mtr.update(command_out,command_out,rotation_rate, dwell_freq);
|
||||
freqresp_tgt.update(command_out,filt_target_rate,rotation_rate, dwell_freq);
|
||||
|
||||
|
@ -899,6 +911,7 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
|||
} else {
|
||||
dwell_gain_mtr = freqresp_mtr.get_gain();
|
||||
dwell_phase_mtr = freqresp_mtr.get_phase();
|
||||
cycle_complete_mtr = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,6 +931,7 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
|||
dwell_gain_tgt = freqresp_tgt.get_gain();
|
||||
dwell_phase_tgt = freqresp_tgt.get_phase();
|
||||
if (dwell_type == DRB) {test_accel_max = freqresp_tgt.get_accel_max();}
|
||||
cycle_complete_tgt = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,6 +991,11 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
|||
}
|
||||
} else {
|
||||
if (now - step_start_time_ms >= step_time_limit_ms || (freqresp_tgt.is_cycle_complete() && freqresp_mtr.is_cycle_complete())) {
|
||||
if (now - step_start_time_ms >= step_time_limit_ms) {
|
||||
gcs().send_text(MAV_SEVERITY_INFO, "AutoTune: Step time limit exceeded");
|
||||
}
|
||||
cycle_complete_tgt = false;
|
||||
cycle_complete_tgt = false;
|
||||
// we have passed the maximum stop time
|
||||
step = UPDATE_GAINS;
|
||||
}
|
||||
|
@ -1147,13 +1166,18 @@ void AC_AutoTune_Heli::updating_rate_ff_up(float &tune_ff, float *freq, float *g
|
|||
curr_test.freq = curr_test.freq + test_freq_incr;
|
||||
freq[frq_cnt] = curr_test.freq;
|
||||
} else {
|
||||
if ((gain[frq_cnt] > 0.1 && gain[frq_cnt] < 0.95) || gain[frq_cnt] > 1.0) {
|
||||
tune_ff = tune_ff / gain[frq_cnt] ;
|
||||
} else if (gain[frq_cnt] >= 0.95 && gain[frq_cnt] <= 1.0) {
|
||||
if ((gain[frq_cnt] > 0.1 && gain[frq_cnt] < 0.93) || gain[frq_cnt] > 0.98) {
|
||||
if (tune_ff > 0.0f) {
|
||||
tune_ff = tune_ff / gain[frq_cnt];
|
||||
} else {
|
||||
tune_ff = 0.03f;
|
||||
}
|
||||
} else if (gain[frq_cnt] >= 0.93 && gain[frq_cnt] <= 0.98) {
|
||||
counter = AUTOTUNE_SUCCESS_COUNT;
|
||||
// reset curr_test.freq and frq_cnt for next test
|
||||
curr_test.freq = freq[0];
|
||||
frq_cnt = 0;
|
||||
tune_ff = constrain_float(tune_ff,0.0f,1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,10 +168,6 @@ private:
|
|||
|
||||
float angle_lim_neg_rpy_cd() const override;
|
||||
|
||||
// Feedforward test used to determine Rate FF gain
|
||||
void rate_ff_test_init();
|
||||
void rate_ff_test_run(float max_angle_cds, float target_rate_cds, float dir_sign);
|
||||
|
||||
// initialize dwell test or angle dwell test variables
|
||||
void dwell_test_init(float start_frq, float stop_frq, float filt_freq, DwellType dwell_type);
|
||||
|
||||
|
@ -255,6 +251,7 @@ private:
|
|||
sweep_info curr_test;
|
||||
sweep_info curr_test_mtr;
|
||||
sweep_info curr_test_tgt;
|
||||
sweep_info test[20];
|
||||
|
||||
Vector3f start_angles; // aircraft attitude at the start of test
|
||||
uint32_t settle_time; // time in ms for allowing aircraft to stabilize before initiating test
|
||||
|
@ -293,6 +290,8 @@ private:
|
|||
// fix the frequency sweep time to 23 seconds
|
||||
const float sweep_time_ms = 23000;
|
||||
|
||||
// number of cycles to complete before running frequency response calculations
|
||||
float pre_calc_cycles;
|
||||
|
||||
// parameters
|
||||
AP_Int8 axis_bitmask; // axes to be tuned
|
||||
|
@ -308,6 +307,10 @@ private:
|
|||
AC_AutoTune_FreqResp freqresp_mtr; // frequency response of output to motor mixer input
|
||||
AC_AutoTune_FreqResp freqresp_tgt; // frequency response of output to target input
|
||||
|
||||
// allow tracking of cycles complete for frequency response object
|
||||
bool cycle_complete_tgt;
|
||||
bool cycle_complete_mtr;
|
||||
|
||||
Chirp chirp_input;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue