use core::f64::consts::PI;
use libm::{atan2, sqrt};
fn to_degrees(radians: f64) -> f64 {
radians * (180.0 / PI)
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Tilt {
pub roll: f64,
pub pitch: f64,
}
pub fn tilt_from_accel(ax: f64, ay: f64, az: f64) -> Tilt {
let roll = to_degrees(atan2(ay, az));
let pitch = to_degrees(atan2(-ax, sqrt(ay * ay + az * az)));
Tilt { roll, pitch }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_level_board_has_no_tilt() {
let tilt = tilt_from_accel(0.0, 0.0, 1.0);
assert!(tilt.roll.abs() < 1e-9);
assert!(tilt.pitch.abs() < 1e-9);
}
#[test]
fn rolled_onto_the_y_axis_is_ninety_degrees_of_roll() {
let tilt = tilt_from_accel(0.0, 1.0, 0.0);
assert!((tilt.roll - 90.0).abs() < 1e-9);
assert!(tilt.pitch.abs() < 1e-9);
}
#[test]
fn pitched_onto_the_x_axis_is_minus_ninety_pitch() {
let tilt = tilt_from_accel(1.0, 0.0, 0.0);
assert!((tilt.pitch + 90.0).abs() < 1e-9);
}
#[test]
fn equal_y_and_z_is_forty_five_degrees_of_roll() {
let tilt = tilt_from_accel(0.0, 1.0, 1.0);
assert!((tilt.roll - 45.0).abs() < 1e-9);
}
#[test]
fn the_scale_of_the_reading_does_not_change_the_angle() {
let g = tilt_from_accel(0.0, 1.0, 1.0);
let counts = tilt_from_accel(0.0, 1000.0, 1000.0);
assert!((g.roll - counts.roll).abs() < 1e-9);
}
}