Skip to content

Multiple inertial support #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

wijiler
Copy link

@wijiler wijiler commented May 3, 2025

Adds support for multiple inertials, allowing for reduced noise, and more accurate heading readings. Overall a very useful feature missing from most motion libraries

image
image

Example, module and library both build

Negatives:

  • changes example to use multiple inertials
  • Untested on actual robot
  • could be expanded upon to be more generic

@wijiler
Copy link
Author

wijiler commented May 4, 2025

going to implement outlier detection

@wijiler wijiler force-pushed the multiple-inertial branch from f1a27d7 to 3bb3a25 Compare May 5, 2025 01:23
@Tropix126
Copy link
Member

Could this PR be split into two parts? I'd like to go ahead with the Gyro trait, however I need some more time to extensively test the implementation on [InertialSensor; N].

Copy link

@GamingLiamStudios GamingLiamStudios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decent concept, flawed implementation.

Comment on lines 103 to 106
let mut avg: Angle = Angle::from_radians(0.0);
// calculate initial average
drop(success_value.iter().map(|angle| avg += angle.to_owned()));
avg /= N as f64;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this just let avg = success_value.iter().reduce(|acc, angle| acc + angle);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait no, needs slightly more logic, but should be fine with a fold

/// 7.5 radian degree tolerance
const MAX_TOLERANCE_RADIANS: f64 = 7.5;
const MAX_TOLERANCE_G: f64 = 1.5;
impl<const N: usize> Gyro for [InertialSensor; N] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this potentially be extra generalized to all G: Gyro (i.e impl<G: Gyro, const N: usize> Gyro for [G; N] {...})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this should be any more general due to there being hardcoded tolerance values here.

Comment on lines 61 to 64
let mut avg: f64 = 0.0;
// calculate initial average
drop(success_value.iter().map(|vel| avg += vel.to_owned()));
avg /= N as f64;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be converted to a fold/reduce

Comment on lines 66 to 68
let mut variance: f64 = 0.0;
drop(success_value.iter().map(|vel| variance += vel.to_owned()));
variance /= N as f64 - 1.0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be converted to a fold/reduce

Comment on lines 70 to 80
let mut ignored: u8 = 0;
for (index, heading) in success_value.into_iter().enumerate() {
let z_score = (heading - avg) / standard_deviation;
if f64::abs(z_score) >= MAX_TOLERANCE_G {
success_value[index] = 0.0;
ignored += 1;
}
}
// calculate new average
drop(success_value.iter().map(|vel| avg += vel.to_owned()));
avg /= (N - ignored as usize) as f64;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also broken; avg is not set to zero, and will add to the existing avg value. Can probably benefit from a filter_map().fold()

Comment on lines 124 to 126
// calculate new average
drop(success_value.iter().map(|angle| avg += angle.to_owned()));
avg /= (N - ignored as usize) as f64;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suffers from the same bug as [InertialSensor; N]::angular_velocity

Comment on lines 108 to 114
let mut variance: f64 = 0.0;
drop(
success_value
.iter()
.map(|angle| variance += angle.to_owned().as_radians()),
);
variance /= N as f64 - 1.0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be reduced to a fold()

Comment on lines 13 to 16
/// Method of retreiving heading
fn heading(&mut self) -> Result<Angle, Self::Error>;
/// get raw angular velocity readings
fn angular_velocity(&mut self) -> Result<f64, Self::Error>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason these are required to be mutable?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like i could be just dumb and not realize that IMU functions are mutable, but it doesn't make sense imho, as state reading shouldn't be mutable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trait takes a mutable reference to self because you could want to modify some internal struct values, kinda just took the suggestion of tropical. Makes sense to me as a feature of flexibility

@wijiler wijiler force-pushed the multiple-inertial branch from 0d2cd78 to fde3afe Compare May 20, 2025 01:08
@wijiler wijiler closed this May 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants