jmagnuson / ahrs-rs

A Rust port of Madgwick's AHRS algorithm
MIT License
33 stars 19 forks source link

Ability to update filter without a fixed sample period #19

Open vincentl98 opened 3 years ago

vincentl98 commented 3 years ago

Both Madgwick and Mahony filter implementations are using a fixed sample_period. However in non real-time systems, it is more accurate to directly pass the time delta between two measurements:

fn update(
        &mut self,
        gyroscope: &Vector3<N>,
        accelerometer: &Vector3<N>,
        magnetometer: &Vector3<N>,
    ) -> Result<&Quaternion<N>, &str> {

would become in that case:

fn update(
        &mut self,
        gyroscope: &Vector3<N>,
        accelerometer: &Vector3<N>,
        magnetometer: &Vector3<N>,
        dt : N, // dt: time delta between the previous measurements and this one
    ) -> Result<&Quaternion<N>, &str> {
jmagnuson commented 3 years ago

Agree-- I originally realized this only after publishing the API, and implemented the (admittedly hacky) field_access feature flag to be able to mutate the period for each sample update without a breaking releases.

It would be nice to satisfy both fixed and dynamic sample periods, but without separate implementations I fear it might have a performance impact (e.g., passing in a Option<N> and doing the mutation check internally). So unless a more elegant solution can be determined, the best option is probably just to do like you suggest and force the caller to manage period.

Eventually, it would be nice to add implementations for Unscented, Extended, etc. Fortunately those should also be compatible with the updated Ahrs trait.

msdrigg commented 2 years ago

I am also interested in this feature. Could you have a second method update_dynamic(self, gyroscope, accelerometer, magnetometer, dt) that internally mutates the sample rate and then calls update. I know that this might not be the desired api, so I am happy to fork this and edit (just for my own personal use, I won't publish on crates.io).

sgeos commented 5 months ago

I can think of three sensible approaches for handling a dynamic time delta.

  1. A breaking change that moves dt to the Ahrs trait interface seems like the most graceful solution to me. It is easy enough for users to keep track of their own fixed time delta.
  2. Additional methods with a dt parameter are also a reasonably graceful solution- update_dynamic() and update_imu_dynamic().
  3. Finally, a dt(dt) setter seems more graceful than the field_access feature. The setter could even be set up for method chaining, although this is probably not conventional.
    attitude = ahrs.dt(dt).update(gyroscope, accelerometer, magnetometer);