mirror of https://github.com/ArduPilot/ardupilot
AC_AutoTune: use chirp function in AP_Math for frequency sweeps
This commit is contained in:
parent
9d1c560faa
commit
f782215194
|
@ -156,11 +156,11 @@ void AC_AutoTune_Heli::test_init()
|
||||||
if (!is_equal(start_freq,stop_freq)) {
|
if (!is_equal(start_freq,stop_freq)) {
|
||||||
// initialize determine_gain function whenever test is initialized
|
// initialize determine_gain function whenever test is initialized
|
||||||
freqresp.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::RATE);
|
freqresp.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||||
dwell_test_init(start_freq, stop_freq, RATE);
|
dwell_test_init(start_freq, stop_freq, stop_freq, RATE);
|
||||||
} else {
|
} else {
|
||||||
// initialize determine_gain function whenever test is initialized
|
// initialize determine_gain function whenever test is initialized
|
||||||
freqresp.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
freqresp.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::RATE);
|
||||||
dwell_test_init(start_freq, start_freq, RATE);
|
dwell_test_init(start_freq, stop_freq, start_freq, RATE);
|
||||||
}
|
}
|
||||||
if (!is_zero(start_freq)) {
|
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.
|
// 4 seconds is added to allow aircraft to achieve start attitude. Then the time to conduct the dwells is added to it.
|
||||||
|
@ -186,11 +186,11 @@ void AC_AutoTune_Heli::test_init()
|
||||||
if (!is_equal(start_freq,stop_freq)) {
|
if (!is_equal(start_freq,stop_freq)) {
|
||||||
// initialize determine gain function
|
// initialize determine gain function
|
||||||
freqresp.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
freqresp.init(AC_AutoTune_FreqResp::InputType::SWEEP, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||||
dwell_test_init(start_freq, stop_freq, ANGLE);
|
dwell_test_init(start_freq, stop_freq, stop_freq, ANGLE);
|
||||||
} else {
|
} else {
|
||||||
// initialize determine gain function
|
// initialize determine gain function
|
||||||
freqresp.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
freqresp.init(AC_AutoTune_FreqResp::InputType::DWELL, AC_AutoTune_FreqResp::ResponseType::ANGLE);
|
||||||
dwell_test_init(start_freq, start_freq, ANGLE);
|
dwell_test_init(start_freq, stop_freq, start_freq, ANGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add time limit for sweep test
|
// TODO add time limit for sweep test
|
||||||
|
@ -910,7 +910,7 @@ void AC_AutoTune_Heli::rate_ff_test_run(float max_angle_cd, float target_rate_cd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AC_AutoTune_Heli::dwell_test_init(float start_frq, float filt_freq, DwellType dwell_type)
|
void AC_AutoTune_Heli::dwell_test_init(float start_frq, float stop_frq, float filt_freq, DwellType dwell_type)
|
||||||
{
|
{
|
||||||
dwell_start_time_ms = 0.0f;
|
dwell_start_time_ms = 0.0f;
|
||||||
settle_time = 200;
|
settle_time = 200;
|
||||||
|
@ -989,11 +989,14 @@ void AC_AutoTune_Heli::dwell_test_init(float start_frq, float filt_freq, DwellTy
|
||||||
trim_pff_out = ff_term + p_term;
|
trim_pff_out = ff_term + p_term;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_equal(start_freq, stop_freq)) {
|
if (!is_equal(start_frq, stop_frq)) {
|
||||||
reset_sweep_variables();
|
reset_sweep_variables();
|
||||||
curr_test.gain = 0.0f;
|
curr_test.gain = 0.0f;
|
||||||
curr_test.phase = 0.0f;
|
curr_test.phase = 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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq, float stop_frq, float &dwell_gain, float &dwell_phase, DwellType dwell_type)
|
void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq, float stop_frq, float &dwell_gain, float &dwell_phase, DwellType dwell_type)
|
||||||
|
@ -1005,7 +1008,6 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
||||||
const uint32_t now = AP_HAL::millis();
|
const uint32_t now = AP_HAL::millis();
|
||||||
float target_angle_cd;
|
float target_angle_cd;
|
||||||
float target_rate_cds;
|
float target_rate_cds;
|
||||||
float sweep_time_ms = 23000;
|
|
||||||
float dwell_freq = start_frq;
|
float dwell_freq = start_frq;
|
||||||
float target_rate_mag_cds;
|
float target_rate_mag_cds;
|
||||||
const float att_hold_gain = 4.5f;
|
const float att_hold_gain = 4.5f;
|
||||||
|
@ -1040,18 +1042,18 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
||||||
Vector3f attitude_cd = Vector3f((float)ahrs_view->roll_sensor, (float)ahrs_view->pitch_sensor, (float)ahrs_view->yaw_sensor);
|
Vector3f attitude_cd = Vector3f((float)ahrs_view->roll_sensor, (float)ahrs_view->pitch_sensor, (float)ahrs_view->yaw_sensor);
|
||||||
if (settle_time == 0) {
|
if (settle_time == 0) {
|
||||||
if (dwell_type == RATE) {
|
if (dwell_type == RATE) {
|
||||||
target_rate_cds = -waveform((now - dwell_start_time_ms) * 0.001, sweep_time_ms * 0.001f, target_rate_mag_cds, start_frq, stop_frq);
|
target_rate_cds = -chirp_input.update((now - dwell_start_time_ms) * 0.001, target_rate_mag_cds);
|
||||||
filt_pit_roll_cd.apply(Vector2f(attitude_cd.x,attitude_cd.y), AP::scheduler().get_loop_period_s());
|
filt_pit_roll_cd.apply(Vector2f(attitude_cd.x,attitude_cd.y), AP::scheduler().get_loop_period_s());
|
||||||
filt_heading_error_cd.apply(wrap_180_cd(trim_attitude_cd.z - attitude_cd.z), AP::scheduler().get_loop_period_s());
|
filt_heading_error_cd.apply(wrap_180_cd(trim_attitude_cd.z - attitude_cd.z), AP::scheduler().get_loop_period_s());
|
||||||
} else {
|
} else {
|
||||||
target_angle_cd = -waveform((now - dwell_start_time_ms) * 0.001, sweep_time_ms * 0.001f, tgt_attitude * 5730.0f, start_frq, stop_frq);
|
target_angle_cd = -chirp_input.update((now - dwell_start_time_ms) * 0.001, tgt_attitude * 5730.0f);
|
||||||
}
|
}
|
||||||
const Vector2f att_fdbk {
|
const Vector2f att_fdbk {
|
||||||
-5730.0f * vel_hold_gain * velocity_bf.y,
|
-5730.0f * vel_hold_gain * velocity_bf.y,
|
||||||
5730.0f * vel_hold_gain * velocity_bf.x
|
5730.0f * vel_hold_gain * velocity_bf.x
|
||||||
};
|
};
|
||||||
filt_att_fdbk_from_velxy_cd.apply(att_fdbk, AP::scheduler().get_loop_period_s());
|
filt_att_fdbk_from_velxy_cd.apply(att_fdbk, AP::scheduler().get_loop_period_s());
|
||||||
dwell_freq = waveform_freq_rads;
|
dwell_freq = chirp_input.get_frequency_rads();
|
||||||
} else {
|
} else {
|
||||||
if (dwell_type == RATE) {
|
if (dwell_type == RATE) {
|
||||||
target_rate_cds = 0.0f;
|
target_rate_cds = 0.0f;
|
||||||
|
@ -1237,45 +1239,6 @@ void AC_AutoTune_Heli::dwell_test_run(uint8_t freq_resp_input, float start_frq,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// init_test - initialises the test
|
|
||||||
float AC_AutoTune_Heli::waveform(float time, float time_record, float waveform_magnitude, float wMin, float wMax)
|
|
||||||
{
|
|
||||||
float time_fade_in = 0.0f; // Time to reach maximum amplitude of chirp
|
|
||||||
float time_fade_out = 0.1 * time_record; // Time to reach zero amplitude after chirp finishes
|
|
||||||
float time_const_freq = 0.0f;
|
|
||||||
|
|
||||||
float window;
|
|
||||||
float output;
|
|
||||||
|
|
||||||
float B = logf(wMax / wMin);
|
|
||||||
|
|
||||||
if (time <= 0.0f) {
|
|
||||||
window = 0.0f;
|
|
||||||
} else if (time <= time_fade_in) {
|
|
||||||
window = 0.5 - 0.5 * cosf(M_PI * time / time_fade_in);
|
|
||||||
} else if (time <= time_record - time_fade_out) {
|
|
||||||
window = 1.0;
|
|
||||||
} else if (time <= time_record) {
|
|
||||||
window = 0.5 - 0.5 * cosf(M_PI * (time - (time_record - time_fade_out)) / time_fade_out + M_PI);
|
|
||||||
} else {
|
|
||||||
window = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time <= 0.0f) {
|
|
||||||
waveform_freq_rads = wMin;
|
|
||||||
output = 0.0f;
|
|
||||||
} else if (time <= time_const_freq) {
|
|
||||||
waveform_freq_rads = wMin;
|
|
||||||
output = window * waveform_magnitude * sinf(wMin * time - wMin * time_const_freq);
|
|
||||||
} else if (time <= time_record) {
|
|
||||||
waveform_freq_rads = wMin * expf(B * (time - time_const_freq) / (time_record - time_const_freq));
|
|
||||||
output = window * waveform_magnitude * sinf((wMin * (time_record - time_const_freq) / B) * (expf(B * (time - time_const_freq) / (time_record - time_const_freq)) - 1));
|
|
||||||
} else {
|
|
||||||
waveform_freq_rads = wMax;
|
|
||||||
output = 0.0f;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update gains for the rate p up tune type
|
// update gains for the rate p up tune type
|
||||||
void AC_AutoTune_Heli::updating_rate_p_up_all(AxisType test_axis)
|
void AC_AutoTune_Heli::updating_rate_p_up_all(AxisType test_axis)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AC_AutoTune.h"
|
#include "AC_AutoTune.h"
|
||||||
|
#include <AP_Math/chirp.h>
|
||||||
|
|
||||||
class AC_AutoTune_Heli : public AC_AutoTune
|
class AC_AutoTune_Heli : public AC_AutoTune
|
||||||
{
|
{
|
||||||
|
@ -147,14 +148,11 @@ private:
|
||||||
void rate_ff_test_run(float max_angle_cds, float target_rate_cds, float dir_sign);
|
void rate_ff_test_run(float max_angle_cds, float target_rate_cds, float dir_sign);
|
||||||
|
|
||||||
// initialize dwell test or angle dwell test variables
|
// initialize dwell test or angle dwell test variables
|
||||||
void dwell_test_init(float start_frq, float filt_freq, DwellType dwell_type);
|
void dwell_test_init(float start_frq, float stop_frq, float filt_freq, DwellType dwell_type);
|
||||||
|
|
||||||
// dwell test used to perform frequency dwells for rate gains
|
// dwell test used to perform frequency dwells for rate gains
|
||||||
void dwell_test_run(uint8_t freq_resp_input, float start_frq, float stop_frq, float &dwell_gain, float &dwell_phase, DwellType dwell_type);
|
void dwell_test_run(uint8_t freq_resp_input, float start_frq, float stop_frq, float &dwell_gain, float &dwell_phase, DwellType dwell_type);
|
||||||
|
|
||||||
// generates waveform for frequency sweep excitations
|
|
||||||
float waveform(float time, float time_record, float waveform_magnitude, float wMin, float wMax);
|
|
||||||
|
|
||||||
// updating_rate_ff_up - adjust FF to ensure the target is reached
|
// updating_rate_ff_up - adjust FF to ensure the target is reached
|
||||||
// FF is adjusted until rate requested is acheived
|
// FF is adjusted until rate requested is acheived
|
||||||
void updating_rate_ff_up(float &tune_ff, float rate_target, float meas_rate, float meas_command);
|
void updating_rate_ff_up(float &tune_ff, float rate_target, float meas_rate, float meas_command);
|
||||||
|
@ -281,6 +279,10 @@ private:
|
||||||
};
|
};
|
||||||
sweep_data sweep;
|
sweep_data sweep;
|
||||||
|
|
||||||
|
// fix the frequency sweep time to 23 seconds
|
||||||
|
const float sweep_time_ms = 23000;
|
||||||
|
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
AP_Int8 axis_bitmask; // axes to be tuned
|
AP_Int8 axis_bitmask; // axes to be tuned
|
||||||
AP_Int8 seq_bitmask; // tuning sequence bitmask
|
AP_Int8 seq_bitmask; // tuning sequence bitmask
|
||||||
|
@ -291,4 +293,6 @@ private:
|
||||||
|
|
||||||
// freqresp object for the frequency response tests
|
// freqresp object for the frequency response tests
|
||||||
AC_AutoTune_FreqResp freqresp;
|
AC_AutoTune_FreqResp freqresp;
|
||||||
|
|
||||||
|
Chirp chirp_input;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue