sensors: move gyro filtering to sensors/vehicle_angular_velocity

- gyro filtering (low-pass and notch) only performed on primary gyro in `sensors/vehicle_angular_velocity` instead of every gyro in `PX4Gyroscope`
 - sample rate is calculated from actual updates (the fixed value was slightly wrong in many cases, and very wrong in a few)
 - In the FIFO case the array is now averaged and published in `sensor_gyro` for filtering downstream. I'll update this in the future to use the full FIFO array (if available), but right now it should be fine.
This commit is contained in:
Daniel Agar
2020-01-27 10:05:33 -05:00
committed by GitHub
parent 0d2e5f1c50
commit 24f0c2d72a
22 changed files with 355 additions and 258 deletions
@@ -43,11 +43,15 @@ VehicleAngularVelocity::VehicleAngularVelocity() :
ModuleParams(nullptr),
WorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl)
{
_lowpass_filter.set_cutoff_frequency(kInitialRateHz, _param_imu_gyro_cutoff.get());
_notch_filter.setParameters(kInitialRateHz, _param_imu_gyro_nf_freq.get(), _param_imu_gyro_nf_bw.get());
}
VehicleAngularVelocity::~VehicleAngularVelocity()
{
Stop();
perf_free(_interval_perf);
}
bool VehicleAngularVelocity::Start()
@@ -77,6 +81,50 @@ void VehicleAngularVelocity::Stop()
_sensor_selection_sub.unregisterCallback();
}
void VehicleAngularVelocity::CheckFilters(const Vector3f &rates)
{
if ((hrt_elapsed_time(&_filter_check_last) > 100_ms)) {
_filter_check_last = hrt_absolute_time();
// calculate sensor update rate
const float sample_interval_avg = perf_mean(_interval_perf);
if (PX4_ISFINITE(sample_interval_avg) && (sample_interval_avg > 0.0f)) {
const float update_rate_hz = 1.0f / sample_interval_avg;
if ((fabsf(update_rate_hz) > 0.0f) && PX4_ISFINITE(update_rate_hz)) {
_update_rate_hz = update_rate_hz;
// check if sample rate error is greater than 1%
if ((fabsf(_update_rate_hz - _filter_sample_rate) / _filter_sample_rate) > 0.01f) {
++_sample_rate_incorrect_count;
}
}
}
const bool sample_rate_updated = (_sample_rate_incorrect_count > 50);
const bool lowpass_updated = (fabsf(_lowpass_filter.get_cutoff_freq() - _param_imu_gyro_cutoff.get()) > 0.01f);
const bool notch_updated = ((fabsf(_notch_filter.getNotchFreq() - _param_imu_gyro_nf_freq.get()) > 0.01f)
|| (fabsf(_notch_filter.getBandwidth() - _param_imu_gyro_nf_bw.get()) > 0.01f));
if (sample_rate_updated || lowpass_updated || notch_updated) {
PX4_INFO("updating filter, sample rate: %.3f Hz -> %.3f Hz", (double)_filter_sample_rate, (double)_update_rate_hz);
_filter_sample_rate = _update_rate_hz;
// update software low pass filters
_lowpass_filter.set_cutoff_frequency(_filter_sample_rate, _param_imu_gyro_cutoff.get());
_lowpass_filter.reset(rates);
_notch_filter.setParameters(_filter_sample_rate, _param_imu_gyro_nf_freq.get(), _param_imu_gyro_nf_bw.get());
_notch_filter.reset(rates);
// reset state
_sample_rate_incorrect_count = 0;
}
}
}
void VehicleAngularVelocity::SensorBiasUpdate(bool force)
{
if (_estimator_sensor_bias_sub.updated() || force) {
@@ -165,6 +213,9 @@ bool VehicleAngularVelocity::SensorSelectionUpdate(bool force)
// force corrections reselection
_corrections_selected_instance = -1;
// reset sample rate monitor
_sample_rate_incorrect_count = 0;
return true;
}
}
@@ -205,15 +256,23 @@ void VehicleAngularVelocity::ParametersUpdate(bool force)
void VehicleAngularVelocity::Run()
{
// update corrections first to set _selected_sensor
bool sensor_select_update = SensorSelectionUpdate();
SensorCorrectionsUpdate(sensor_select_update);
SensorBiasUpdate(sensor_select_update);
bool selection_updated = SensorSelectionUpdate();
SensorCorrectionsUpdate(selection_updated);
SensorBiasUpdate(selection_updated);
ParametersUpdate();
if (_sensor_sub[_selected_sensor_sub_index].updated() || sensor_select_update) {
bool sensor_updated = _sensor_sub[_selected_sensor_sub_index].updated();
if (sensor_updated || selection_updated) {
sensor_gyro_s sensor_data;
if (_sensor_sub[_selected_sensor_sub_index].copy(&sensor_data)) {
if (sensor_updated) {
perf_count_interval(_interval_perf, sensor_data.timestamp_sample);
}
// get the sensor data and correct for thermal errors (apply offsets and scale)
const Vector3f val{sensor_data.x, sensor_data.y, sensor_data.z};
@@ -226,14 +285,32 @@ void VehicleAngularVelocity::Run()
// correct for in-run bias errors
rates -= _bias;
// publish
vehicle_angular_velocity_s out;
// Filter: apply notch and then low-pass
CheckFilters(rates);
const Vector3f rates_filtered = _lowpass_filter.apply(_notch_filter.apply(rates));
out.timestamp_sample = sensor_data.timestamp_sample;
rates.copyTo(out.xyz);
out.timestamp = hrt_absolute_time();
_vehicle_angular_velocity_pub.publish(out);
bool publish = true;
if (_param_imu_gyro_rate_max.get() > 0) {
const uint64_t interval = 1e6f / _param_imu_gyro_rate_max.get();
if (hrt_elapsed_time(&_last_publish) < interval) {
publish = false;
}
}
if (publish) {
vehicle_angular_velocity_s out;
out.timestamp_sample = sensor_data.timestamp_sample;
rates_filtered.copyTo(out.xyz);
out.timestamp = hrt_absolute_time();
_vehicle_angular_velocity_pub.publish(out);
_last_publish = out.timestamp_sample;
}
}
}
}
@@ -244,4 +321,12 @@ void VehicleAngularVelocity::PrintStatus()
PX4_INFO("bias: [%.3f %.3f %.3f]", (double)_bias(0), (double)_bias(1), (double)_bias(2));
PX4_INFO("offset: [%.3f %.3f %.3f]", (double)_offset(0), (double)_offset(1), (double)_offset(2));
PX4_INFO("scale: [%.3f %.3f %.3f]", (double)_scale(0), (double)_scale(1), (double)_scale(2));
PX4_INFO("sample rate: %.3f Hz", (double)_update_rate_hz);
PX4_INFO("low-pass filter cutoff: %.3f Hz", (double)_lowpass_filter.get_cutoff_freq());
if (_notch_filter.getNotchFreq() > 0.0f) {
PX4_INFO("notch filter freq: %.3f Hz\tbandwidth: %.3f Hz", (double)_notch_filter.getNotchFreq(),
(double)_notch_filter.getBandwidth());
}
}