Crate flaw

Source
Expand description

§flaw

Control-law-inspired embedded signal filtering, no-std and no-alloc compatible.

This library provides a simple method for initializing and updating single-input, single-output infinite-impulse-response filters using 32-bit floats, as well as tabulated filter coefficients for some common filters. Filters evaluate in 4N+1 floating-point operations for a filter of order N.

The name flaw is short for filter-law, but also refers to the fact that digital IIR filtering with small floating-point types is an inherently flawed approach, in that higher-order and lower-cutoff filters produce very small coefficients that result in floating-point roundoff error. This library makes an attempt to mitigate this problem by providing filter coefficients for a tested domain of validity. The result is a limited, but useful, range of operation where these filters can achieve both accuracy and performance as well as be formulated and initialized in an embedded environment.

§Example: Second-Order Butterworth Filter

// First, choose a cutoff frequency as a fraction of sampling frequency
let cutoff_ratio = 1e-3;

// Construct a filter, interpolating coefficients to that cutoff ratio.
// Initializes internal state to zero by default.
let mut filter = flaw::butter2(cutoff_ratio).unwrap();  // Errors if extrapolating

// Initialize the internal state of the filter
// to match the steady-state associated with some input value.
let initial_steady_measurement = 1.57;  // Some number
filter.initialize(initial_steady_measurement);

// Update the filter with a new raw measurement
let measurement = 0.3145; // Some number
let estimate = filter.update(measurement);  // Latest state estimate

§Development Status: Early Days

This is in an experimental stage - it appears to work well, but is not fully-validated or fully-featured.

  • More software testing is needed to guarantee filter performance at interpolated cutoff ratios
  • More hardware/firmware testing is needed to examine performance on actual microcontrollers
  • More filter types can be added

§Coefficient Tables

Tabulated filters are tested to enforce

  • <0.01% error in converged step response at the minimum cutoff frequency
  • <1ppm error in converged step response at the maximum cutoff frequency
  • <5% error to -3dB attenuation of a sine input at the cutoff frequency at the maximum cutoff ratio
    • This error appears to be mainly an issue of discretization in test cases, and could be reduced by using a better method for testing (fit a sine curve to the result or do gradient-descent on a cubic interpolator)

Each filter with tabulated coefficients has a minimum and maximum cutoff ratio. The minimum value is determined by floating-point error in convergence of a step response, while the maximum value is determined by the accuracy of attenuation at the cutoff frequency as the cutoff ratio approaches the Nyquist frequency.

Coefficients for a given filter are interpolated on these tables using a cubic Hermite method with the log10(cutoff_ratio) as the independent variable. Tabulated values are stored and interpolated as 64-bit floats, and only converted to 32-bit floats at the final stage of calculation.

Filter coefficients are extracted from scipy’s state-space representations, which are the result of a bilinear transform of the transfer function polynomials.

FilterMin. Cutoff RatioMax. Cutoff Ratio
Butter110^-50.4
Butter210^-30.4
Butter310^-2.25 (~0.006)0.4
Butter410^-1.5 (~0.032)0.4
Butter510^-1.5 (~0.032)0.4
Butter610^-1.25 (~0.06)0.4

§Additional Filter Kinds

FilterNotes
MedianAvailable for odd numbers of taps.
Helpful for rejecting non-oscillatory noise, such as packet latency spikes.

§License

Licensed under either of

  • Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Re-exports§

pub use generated::butter::butter1::butter1;
pub use generated::butter::butter2::butter2;
pub use generated::butter::butter3::butter3;
pub use generated::butter::butter4::butter4;
pub use generated::butter::butter5::butter5;
pub use generated::butter::butter6::butter6;

Modules§

generated

Structs§

MedianFilter
Simple median filter on arbitrary ordered type. Requires an odd number of points to make the median unique.
SisoIirFilter
Single-Input-Single-Output, Infinite Impulse Response filter, normalized to a sample time interval of 1.0