sensors/vehicle_angular_velocity: properly handle filter reset on FIFO data scale changes

For the sake of efficiency (at 8 kHz) all filtering is performed on the raw data before the calibration and rotation is applied to only the final output. As a result we have to be a bit more careful when switching between sensors or in cases where the gyro scale factor changes (eg icm42688p 20 bit data rescaled to fit in int16 output).
This commit is contained in:
Daniel Agar
2021-04-25 14:20:32 -04:00
committed by GitHub
parent ed0fa99198
commit 8478d1ea37
6 changed files with 146 additions and 103 deletions
@@ -93,6 +93,22 @@ void PX4Accelerometer::set_device_type(uint8_t devtype)
_device_id = device_id.devid; _device_id = device_id.devid;
} }
void PX4Accelerometer::set_scale(float scale)
{
if (fabsf(scale - _scale) > FLT_EPSILON) {
// rescale last sample on scale change
float rescale = _scale / scale;
for (auto &s : _last_sample) {
s = roundf(s * rescale);
}
_scale = scale;
UpdateClipLimit();
}
}
void PX4Accelerometer::update(const hrt_abstime &timestamp_sample, float x, float y, float z) void PX4Accelerometer::update(const hrt_abstime &timestamp_sample, float x, float y, float z)
{ {
// Apply rotation (before scaling) // Apply rotation (before scaling)
@@ -55,7 +55,7 @@ public:
void set_error_count(uint32_t error_count) { _error_count = error_count; } void set_error_count(uint32_t error_count) { _error_count = error_count; }
void increase_error_count() { _error_count++; } void increase_error_count() { _error_count++; }
void set_range(float range) { _range = range; UpdateClipLimit(); } void set_range(float range) { _range = range; UpdateClipLimit(); }
void set_scale(float scale) { _scale = scale; UpdateClipLimit(); } void set_scale(float scale);
void set_temperature(float temperature) { _temperature = temperature; } void set_temperature(float temperature) { _temperature = temperature; }
void update(const hrt_abstime &timestamp_sample, float x, float y, float z); void update(const hrt_abstime &timestamp_sample, float x, float y, float z);
@@ -80,6 +80,20 @@ void PX4Gyroscope::set_device_type(uint8_t devtype)
_device_id = device_id.devid; _device_id = device_id.devid;
} }
void PX4Gyroscope::set_scale(float scale)
{
if (fabsf(scale - _scale) > FLT_EPSILON) {
// rescale last sample on scale change
float rescale = _scale / scale;
for (auto &s : _last_sample) {
s = roundf(s * rescale);
}
_scale = scale;
}
}
void PX4Gyroscope::update(const hrt_abstime &timestamp_sample, float x, float y, float z) void PX4Gyroscope::update(const hrt_abstime &timestamp_sample, float x, float y, float z)
{ {
// Apply rotation (before scaling) // Apply rotation (before scaling)
+1 -1
View File
@@ -55,7 +55,7 @@ public:
void set_error_count(uint32_t error_count) { _error_count = error_count; } void set_error_count(uint32_t error_count) { _error_count = error_count; }
void increase_error_count() { _error_count++; } void increase_error_count() { _error_count++; }
void set_range(float range) { _range = range; } void set_range(float range) { _range = range; }
void set_scale(float scale) { _scale = scale; } void set_scale(float scale);
void set_temperature(float temperature) { _temperature = temperature; } void set_temperature(float temperature) { _temperature = temperature; }
void update(const hrt_abstime &timestamp_sample, float x, float y, float z); void update(const hrt_abstime &timestamp_sample, float x, float y, float z);
@@ -106,10 +106,12 @@ bool VehicleAngularVelocity::UpdateSampleRate()
} }
// calculate sensor update rate // calculate sensor update rate
if (PX4_ISFINITE(sample_rate_hz) && PX4_ISFINITE(publish_rate_hz)) { if ((sample_rate_hz > 0) && PX4_ISFINITE(sample_rate_hz) && (publish_rate_hz > 0) && PX4_ISFINITE(publish_rate_hz)) {
// check if sample rate error is greater than 1% // check if sample rate error is greater than 1%
if ((fabsf(sample_rate_hz - _filter_sample_rate_hz) / sample_rate_hz) > 0.01f) { if ((_filter_sample_rate_hz <= FLT_EPSILON) || !PX4_ISFINITE(_filter_sample_rate_hz)
PX4_DEBUG("resetting filters, sample rate: %.3f Hz -> %.3f Hz", (double)_filter_sample_rate_hz, (double)sample_rate_hz); || (fabsf(sample_rate_hz - _filter_sample_rate_hz) / sample_rate_hz) > 0.01f) {
PX4_DEBUG("updating sample rate: %.3f Hz -> %.3f Hz", (double)_filter_sample_rate_hz, (double)sample_rate_hz);
_reset_filters = true; _reset_filters = true;
_filter_sample_rate_hz = sample_rate_hz; _filter_sample_rate_hz = sample_rate_hz;
@@ -137,19 +139,17 @@ bool VehicleAngularVelocity::UpdateSampleRate()
_publish_interval_min_us = 0; _publish_interval_min_us = 0;
} }
} }
if (_filter_sample_rate_hz > 0.f) {
return true;
}
} }
return false; return PX4_ISFINITE(_filter_sample_rate_hz) && (_filter_sample_rate_hz > 0);
} }
void VehicleAngularVelocity::ResetFilters() void VehicleAngularVelocity::ResetFilters(float new_scale)
{ {
const Vector3f angular_velocity{GetResetAngularVelocity()}; if ((_filter_sample_rate_hz > 0) && PX4_ISFINITE(_filter_sample_rate_hz)) {
const Vector3f angular_acceleration{GetResetAngularAcceleration()};
const Vector3f angular_velocity{GetResetAngularVelocity(new_scale)};
const Vector3f angular_acceleration{GetResetAngularAcceleration(new_scale)};
for (int axis = 0; axis < 3; axis++) { for (int axis = 0; axis < 3; axis++) {
// angular velocity low pass // angular velocity low pass
@@ -170,14 +170,16 @@ void VehicleAngularVelocity::ResetFilters()
DisableDynamicNotchEscRpm(); DisableDynamicNotchEscRpm();
DisableDynamicNotchFFT(); DisableDynamicNotchFFT();
UpdateDynamicNotchEscRpm(true); UpdateDynamicNotchEscRpm(new_scale, true);
UpdateDynamicNotchFFT(true); UpdateDynamicNotchFFT(new_scale, true);
_angular_velocity_prev = angular_velocity; _angular_velocity_prev = angular_velocity;
_last_scale = new_scale;
_reset_filters = false; _reset_filters = false;
perf_count(_filter_reset_perf); perf_count(_filter_reset_perf);
} }
}
void VehicleAngularVelocity::SensorBiasUpdate(bool force) void VehicleAngularVelocity::SensorBiasUpdate(bool force)
{ {
@@ -224,6 +226,8 @@ bool VehicleAngularVelocity::SensorSelectionUpdate(bool force)
_selected_sensor_device_id = sensor_selection.gyro_device_id; _selected_sensor_device_id = sensor_selection.gyro_device_id;
_calibration.set_device_id(sensor_gyro_fifo_sub.get().device_id); _calibration.set_device_id(sensor_gyro_fifo_sub.get().device_id);
_timestamp_sample_last = 0;
_filter_sample_rate_hz = NAN;
_reset_filters = true; _reset_filters = true;
_bias.zero(); _bias.zero();
_fifo_available = true; _fifo_available = true;
@@ -231,6 +235,8 @@ bool VehicleAngularVelocity::SensorSelectionUpdate(bool force)
perf_count(_selection_changed_perf); perf_count(_selection_changed_perf);
PX4_DEBUG("selecting gyro FIFO %d %d", i, _selected_sensor_device_id);
return true; return true;
} }
} }
@@ -249,7 +255,8 @@ bool VehicleAngularVelocity::SensorSelectionUpdate(bool force)
_calibration.set_device_id(sensor_gyro_sub.get().device_id); _calibration.set_device_id(sensor_gyro_sub.get().device_id);
_selected_sensor_device_id = sensor_selection.gyro_device_id; _selected_sensor_device_id = sensor_selection.gyro_device_id;
// clear bias and corrections _timestamp_sample_last = 0;
_filter_sample_rate_hz = NAN;
_reset_filters = true; _reset_filters = true;
_bias.zero(); _bias.zero();
_fifo_available = false; _fifo_available = false;
@@ -257,6 +264,8 @@ bool VehicleAngularVelocity::SensorSelectionUpdate(bool force)
perf_count(_selection_changed_perf); perf_count(_selection_changed_perf);
PX4_DEBUG("selecting gyro %d %d", i, _selected_sensor_device_id);
return true; return true;
} }
} }
@@ -341,29 +350,37 @@ void VehicleAngularVelocity::ParametersUpdate(bool force)
} }
} }
Vector3f VehicleAngularVelocity::GetResetAngularVelocity() const Vector3f VehicleAngularVelocity::GetResetAngularVelocity(float new_scale) const
{ {
if ((_last_publish != 0) && (_last_scale > 0.f) if ((_last_publish != 0) && (new_scale > 0.f)) {
&& PX4_ISFINITE(_angular_velocity(0))
&& PX4_ISFINITE(_angular_velocity(1))
&& PX4_ISFINITE(_angular_velocity(2))) {
// angular velocity filtering is performed on raw unscaled data // angular velocity filtering is performed on raw unscaled data
// start with last valid vehicle body frame angular velocity and compute equivalent raw data (for current sensor selection) // start with last valid vehicle body frame angular velocity and compute equivalent raw data (for current sensor selection)
return _calibration.Uncorrect(_angular_velocity + _bias) / _last_scale; Vector3f angular_velocity{_calibration.Uncorrect(_angular_velocity + _bias) / new_scale};
if (PX4_ISFINITE(angular_velocity(0))
&& PX4_ISFINITE(angular_velocity(1))
&& PX4_ISFINITE(angular_velocity(2))) {
return angular_velocity;
}
} }
return Vector3f{0.f, 0.f, 0.f}; return Vector3f{0.f, 0.f, 0.f};
} }
Vector3f VehicleAngularVelocity::GetResetAngularAcceleration() const Vector3f VehicleAngularVelocity::GetResetAngularAcceleration(float new_scale) const
{ {
if ((_last_publish != 0) && (_last_scale > 0.f) if ((_last_publish != 0) && (new_scale > 0.f)) {
&& PX4_ISFINITE(_angular_acceleration(0)) // angular acceleration filtering is performed on unscaled angular velocity data
&& PX4_ISFINITE(_angular_acceleration(1))
&& PX4_ISFINITE(_angular_acceleration(2))) {
// angular acceleration filtering is performed on raw unscaled data
// start with last valid vehicle body frame angular acceleration and compute equivalent raw data (for current sensor selection) // start with last valid vehicle body frame angular acceleration and compute equivalent raw data (for current sensor selection)
return _calibration.rotation().I() * _angular_acceleration / _last_scale; Vector3f angular_acceleration{_calibration.rotation().I() *_angular_acceleration / new_scale};
if (PX4_ISFINITE(angular_acceleration(0))
&& PX4_ISFINITE(angular_acceleration(1))
&& PX4_ISFINITE(angular_acceleration(2))) {
return angular_acceleration;
}
} }
return Vector3f{0.f, 0.f, 0.f}; return Vector3f{0.f, 0.f, 0.f};
@@ -401,7 +418,7 @@ void VehicleAngularVelocity::DisableDynamicNotchFFT()
#endif // !CONSTRAINED_FLASH #endif // !CONSTRAINED_FLASH
} }
void VehicleAngularVelocity::UpdateDynamicNotchEscRpm(bool force) void VehicleAngularVelocity::UpdateDynamicNotchEscRpm(float new_scale, bool force)
{ {
#if !defined(CONSTRAINED_FLASH) #if !defined(CONSTRAINED_FLASH)
const bool enabled = _param_imu_gyro_dyn_nf.get() & DynamicNotch::EscRpm; const bool enabled = _param_imu_gyro_dyn_nf.get() & DynamicNotch::EscRpm;
@@ -434,8 +451,8 @@ void VehicleAngularVelocity::UpdateDynamicNotchEscRpm(bool force)
} }
// only reset if there's sufficient change (> 1%) // only reset if there's sufficient change (> 1%)
if (change_percent > 0.01f) { if (force || (change_percent > 0.01f)) {
const Vector3f reset_angular_velocity{GetResetAngularVelocity()}; const Vector3f reset_angular_velocity{GetResetAngularVelocity(new_scale)};
for (int axis = 0; axis < 3; axis++) { for (int axis = 0; axis < 3; axis++) {
auto &dnf = _dynamic_notch_filter_esc_rpm[i][harmonic][axis]; auto &dnf = _dynamic_notch_filter_esc_rpm[i][harmonic][axis];
@@ -464,7 +481,7 @@ void VehicleAngularVelocity::UpdateDynamicNotchEscRpm(bool force)
#endif // !CONSTRAINED_FLASH #endif // !CONSTRAINED_FLASH
} }
void VehicleAngularVelocity::UpdateDynamicNotchFFT(bool force) void VehicleAngularVelocity::UpdateDynamicNotchFFT(float new_scale, bool force)
{ {
#if !defined(CONSTRAINED_FLASH) #if !defined(CONSTRAINED_FLASH)
const bool enabled = _param_imu_gyro_dyn_nf.get() & DynamicNotch::FFT; const bool enabled = _param_imu_gyro_dyn_nf.get() & DynamicNotch::FFT;
@@ -488,13 +505,13 @@ void VehicleAngularVelocity::UpdateDynamicNotchFFT(bool force)
const float peak_diff_abs = fabsf(dnf.getNotchFreq() - peak_freq); const float peak_diff_abs = fabsf(dnf.getNotchFreq() - peak_freq);
const float change_percent = peak_diff_abs / peak_freq; const float change_percent = peak_diff_abs / peak_freq;
if (change_percent > 0.001f) { if (force || (change_percent > 0.001f)) {
// peak frequency changed by at least 0.1% // peak frequency changed by at least 0.1%
dnf.setParameters(_filter_sample_rate_hz, peak_freq, sensor_gyro_fft.resolution_hz); dnf.setParameters(_filter_sample_rate_hz, peak_freq, sensor_gyro_fft.resolution_hz);
// only reset if there's sufficient change // only reset if there's sufficient change
if (peak_diff_abs > sensor_gyro_fft.resolution_hz) { if (peak_diff_abs > sensor_gyro_fft.resolution_hz) {
dnf.reset(GetResetAngularVelocity()(axis)); dnf.reset(GetResetAngularVelocity(new_scale)(axis));
} }
perf_count(_dynamic_notch_filter_fft_update_perf); perf_count(_dynamic_notch_filter_fft_update_perf);
@@ -566,22 +583,18 @@ float VehicleAngularVelocity::FilterAngularVelocity(int axis, float data[], int
return data[N - 1]; return data[N - 1];
} }
float VehicleAngularVelocity::FilterAngularAcceleration(int axis, float data[], int N, float dt_s) float VehicleAngularVelocity::FilterAngularAcceleration(int axis, float dt_s, float data[], int N)
{ {
if (N > 0) {
// angular acceleration: Differentiate & apply specific angular acceleration (D-term) low-pass (IMU_DGYRO_CUTOFF) // angular acceleration: Differentiate & apply specific angular acceleration (D-term) low-pass (IMU_DGYRO_CUTOFF)
float delta_velocity_filtered; float angular_acceleration_filtered = 0.f;
for (int n = 0; n < N; n++) { for (int n = 0; n < N; n++) {
const float delta_velocity = (data[n] - _angular_velocity_prev(axis)); const float angular_acceleration = (data[n] - _angular_velocity_prev(axis)) / dt_s;
delta_velocity_filtered = _lp_filter_acceleration[axis].apply(delta_velocity); angular_acceleration_filtered = _lp_filter_acceleration[axis].apply(angular_acceleration);
_angular_velocity_prev(axis) = data[n]; _angular_velocity_prev(axis) = data[n];
} }
return delta_velocity_filtered / dt_s; return angular_acceleration_filtered;
}
return 0.f;
} }
void VehicleAngularVelocity::Run() void VehicleAngularVelocity::Run()
@@ -589,12 +602,20 @@ void VehicleAngularVelocity::Run()
// backup schedule // backup schedule
ScheduleDelayed(10_ms); ScheduleDelayed(10_ms);
ParametersUpdate();
// update corrections first to set _selected_sensor // update corrections first to set _selected_sensor
const bool selection_updated = SensorSelectionUpdate(); const bool selection_updated = SensorSelectionUpdate();
_calibration.SensorCorrectionsUpdate(selection_updated); _calibration.SensorCorrectionsUpdate(selection_updated);
SensorBiasUpdate(selection_updated); SensorBiasUpdate(selection_updated);
ParametersUpdate();
if (selection_updated || !PX4_ISFINITE(_filter_sample_rate_hz) || (_filter_sample_rate_hz <= FLT_EPSILON)) {
if (!UpdateSampleRate()) {
// sensor sample rate required to run
return;
}
}
if (_fifo_available) { if (_fifo_available) {
// process all outstanding fifo messages // process all outstanding fifo messages
@@ -604,13 +625,9 @@ void VehicleAngularVelocity::Run()
const float dt_s = sensor_fifo_data.dt * 1e-6f; const float dt_s = sensor_fifo_data.dt * 1e-6f;
_timestamp_sample_last = sensor_fifo_data.timestamp_sample; _timestamp_sample_last = sensor_fifo_data.timestamp_sample;
// in FIFO mode the unscaled raw data is filtered, reset filters on any scale change
if (_reset_filters || (fabsf(sensor_fifo_data.scale - _last_scale) > FLT_EPSILON)) { if (_reset_filters || (fabsf(sensor_fifo_data.scale - _last_scale) > FLT_EPSILON)) {
if (UpdateSampleRate()) { ResetFilters(sensor_fifo_data.scale);
// in FIFO mode the unscaled raw data is filtered
_last_scale = sensor_fifo_data.scale;
ResetFilters();
}
if (_reset_filters) { if (_reset_filters) {
continue; // not safe to run until filters configured continue; // not safe to run until filters configured
@@ -639,14 +656,12 @@ void VehicleAngularVelocity::Run()
// save last filtered sample // save last filtered sample
angular_velocity_unscaled(axis) = FilterAngularVelocity(axis, data, N); angular_velocity_unscaled(axis) = FilterAngularVelocity(axis, data, N);
angular_acceleration_unscaled(axis) = FilterAngularAcceleration(axis, data, N, dt_s); angular_acceleration_unscaled(axis) = FilterAngularAcceleration(axis, dt_s, data, N);
} }
// Publish // Publish
if (!_sensor_fifo_sub.updated()) { CalibrateAndPublish(!_sensor_fifo_sub.updated(), sensor_fifo_data.timestamp_sample, angular_velocity_unscaled,
CalibrateAndPublish(sensor_fifo_data.timestamp_sample, angular_velocity_unscaled, angular_acceleration_unscaled, angular_acceleration_unscaled, sensor_fifo_data.scale);
sensor_fifo_data.scale);
}
} }
} }
@@ -655,15 +670,15 @@ void VehicleAngularVelocity::Run()
sensor_gyro_s sensor_data; sensor_gyro_s sensor_data;
while (_sensor_sub.update(&sensor_data)) { while (_sensor_sub.update(&sensor_data)) {
if (_timestamp_sample_last == 0) {
_timestamp_sample_last = sensor_data.timestamp_sample - 1e6f / _filter_sample_rate_hz;
}
const float dt_s = math::constrain(((sensor_data.timestamp_sample - _timestamp_sample_last) / 1e6f), 0.0002f, 0.02f); const float dt_s = math::constrain(((sensor_data.timestamp_sample - _timestamp_sample_last) / 1e6f), 0.0002f, 0.02f);
_timestamp_sample_last = sensor_data.timestamp_sample; _timestamp_sample_last = sensor_data.timestamp_sample;
if (_reset_filters) { if (_reset_filters) {
if (UpdateSampleRate()) {
// non-FIFO sensor data is already scaled
_last_scale = 1.f;
ResetFilters(); ResetFilters();
}
if (_reset_filters) { if (_reset_filters) {
continue; // not safe to run until filters configured continue; // not safe to run until filters configured
@@ -673,8 +688,8 @@ void VehicleAngularVelocity::Run()
UpdateDynamicNotchEscRpm(); UpdateDynamicNotchEscRpm();
UpdateDynamicNotchFFT(); UpdateDynamicNotchFFT();
Vector3f angular_velocity_unscaled; Vector3f angular_velocity;
Vector3f angular_acceleration_unscaled; Vector3f angular_acceleration;
float raw_data_array[] {sensor_data.x, sensor_data.y, sensor_data.z}; float raw_data_array[] {sensor_data.x, sensor_data.y, sensor_data.z};
@@ -683,19 +698,17 @@ void VehicleAngularVelocity::Run()
float data[1] {raw_data_array[axis]}; float data[1] {raw_data_array[axis]};
// save last filtered sample // save last filtered sample
angular_velocity_unscaled(axis) = FilterAngularVelocity(axis, data, 1); angular_velocity(axis) = FilterAngularVelocity(axis, data);
angular_acceleration_unscaled(axis) = FilterAngularAcceleration(axis, data, 1, dt_s); angular_acceleration(axis) = FilterAngularAcceleration(axis, dt_s, data);
} }
// Publish // Publish
if (!_sensor_sub.updated()) { CalibrateAndPublish(!_sensor_sub.updated(), sensor_data.timestamp_sample, angular_velocity, angular_acceleration);
CalibrateAndPublish(sensor_data.timestamp_sample, angular_velocity_unscaled, angular_acceleration_unscaled);
}
} }
} }
} }
void VehicleAngularVelocity::CalibrateAndPublish(const hrt_abstime &timestamp_sample, void VehicleAngularVelocity::CalibrateAndPublish(bool publish, const hrt_abstime &timestamp_sample,
const Vector3f &angular_velocity_unscaled, const Vector3f &angular_acceleration_unscaled, float scale) const Vector3f &angular_velocity_unscaled, const Vector3f &angular_acceleration_unscaled, float scale)
{ {
// Angular velocity: rotate sensor frame to board, scale raw data to SI, apply calibration, and remove in-run estimated bias // Angular velocity: rotate sensor frame to board, scale raw data to SI, apply calibration, and remove in-run estimated bias
@@ -704,7 +717,7 @@ void VehicleAngularVelocity::CalibrateAndPublish(const hrt_abstime &timestamp_sa
// Angular acceleration: rotate sensor frame to board, scale raw data to SI, apply any additional configured rotation // Angular acceleration: rotate sensor frame to board, scale raw data to SI, apply any additional configured rotation
_angular_acceleration = _calibration.rotation() * angular_acceleration_unscaled * scale; _angular_acceleration = _calibration.rotation() * angular_acceleration_unscaled * scale;
if (timestamp_sample >= _last_publish + _publish_interval_min_us) { if (publish && (timestamp_sample >= _last_publish + _publish_interval_min_us)) {
// Publish vehicle_angular_acceleration // Publish vehicle_angular_acceleration
vehicle_angular_acceleration_s v_angular_acceleration; vehicle_angular_acceleration_s v_angular_acceleration;
@@ -75,26 +75,26 @@ public:
private: private:
void Run() override; void Run() override;
void CalibrateAndPublish(const hrt_abstime &timestamp_sample, const matrix::Vector3f &angular_velocity, void CalibrateAndPublish(bool publish, const hrt_abstime &timestamp_sample, const matrix::Vector3f &angular_velocity,
const matrix::Vector3f &angular_acceleration, float scale = 1.f); const matrix::Vector3f &angular_acceleration, float scale = 1.f);
float FilterAngularVelocity(int axis, float data[], int N); float FilterAngularVelocity(int axis, float data[], int N = 1);
float FilterAngularAcceleration(int axis, float data[], int N, float dt_s); float FilterAngularAcceleration(int axis, float dt_s, float data[], int N = 1);
void DisableDynamicNotchEscRpm(); void DisableDynamicNotchEscRpm();
void DisableDynamicNotchFFT(); void DisableDynamicNotchFFT();
void ParametersUpdate(bool force = false); void ParametersUpdate(bool force = false);
void ResetFilters(); void ResetFilters(float new_scale = 1.f);
void SensorBiasUpdate(bool force = false); void SensorBiasUpdate(bool force = false);
bool SensorSelectionUpdate(bool force = false); bool SensorSelectionUpdate(bool force = false);
void UpdateDynamicNotchEscRpm(bool force = false); void UpdateDynamicNotchEscRpm(float new_scale = 1.f, bool force = false);
void UpdateDynamicNotchFFT(bool force = false); void UpdateDynamicNotchFFT(float new_scale = 1.f, bool force = false);
bool UpdateSampleRate(); bool UpdateSampleRate();
// scaled appropriately for current FIFO mode // scaled appropriately for current FIFO mode
matrix::Vector3f GetResetAngularVelocity() const; matrix::Vector3f GetResetAngularVelocity(float new_scale = 1.f) const;
matrix::Vector3f GetResetAngularAcceleration() const; matrix::Vector3f GetResetAngularAcceleration(float new_scale = 1.f) const;
static constexpr int MAX_SENSOR_COUNT = 4; static constexpr int MAX_SENSOR_COUNT = 4;
@@ -127,7 +127,7 @@ private:
hrt_abstime _publish_interval_min_us{0}; hrt_abstime _publish_interval_min_us{0};
hrt_abstime _last_publish{0}; hrt_abstime _last_publish{0};
float _filter_sample_rate_hz{0.f}; float _filter_sample_rate_hz{NAN};
static constexpr const float kInitialRateHz{1000.f}; /**< sensor update rate used for initialization */ static constexpr const float kInitialRateHz{1000.f}; /**< sensor update rate used for initialization */