Struct InertialSensor

Source
pub struct InertialSensor { /* private fields */ }
Expand description

An inertial sensor (IMU) plugged into a Smart Port.

Implementations§

Source§

impl InertialSensor

Source

pub const CALIBRATION_START_TIMEOUT: Duration

The maximum time that the Inertial Sensor should take to begin its calibration process following a call to InertialSensor::calibrate.

Source

pub const CALIBRATION_END_TIMEOUT: Duration

The maximum time that the Inertial Sensor should take to end its calibration process after calibration has begun.

Source

pub const MIN_DATA_INTERVAL: Duration

The minimum data rate that you can set an IMU to run at.

Source

pub const MAX_HEADING: f64 = 360f64

The maximum value that can be returned by Self::heading.

Source

pub fn new(port: SmartPort) -> Self

Create a new inertial sensor from a SmartPort.

§Important

This sensor must be calibrated using InertialSensor::calibrate before any meaningful data can be read from it.

§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let sensor = InertialSensor::new(peripherals.port_1);
}
Source

pub fn status(&self) -> Result<InertialStatus, InertialError>

Returns the internal status code of the intertial sensor.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let sensor = InertialSensor::new(peripherals.port_1);

    if let Ok(status) = sensor.status() {
        println!("Status: {:b}", status.bits());
    }
}
Source

pub fn is_calibrating(&self) -> Result<bool, InertialError>

Returns true if the sensor is currently calibrating.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let sensor = InertialSensor::new(peripherals.port_1);

    // We haven't calibrated yet, so this is expected.
    if sensor.is_calibrating() == Ok(false) {
        println!("Sensor is not currently calibrating.");
    }
}
Source

pub fn is_auto_calibrated(&self) -> Result<bool, InertialError>

Returns true if the sensor was calibrated using auto-calibration.

In some cases (such as a loss of power), VEXos will automatically decide to recalibrate the inertial sensor.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let sensor = InertialSensor::new(peripherals.port_1);

    if sensor.is_auto_calibrated() == Ok(true) {
        println!("Sensor was automatically calibrated by VEXos.");
    }
}
Source

pub fn physical_orientation(&self) -> Result<InertialOrientation, InertialError>

Returns the physical orientation of the sensor as it was measured during calibration.

This orientation can be one of six possible orientations aligned to two cardinal directions.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    if sensor.calibrate().await.is_ok() {
        if let Ok(orientation) = sensor.physical_orientation() {
            println!("Sensor was calibrated while facing: {:?}", orientation);
        }
    }
}
Source

pub const fn calibrate(&mut self) -> InertialCalibrateFuture<'_>

Calibrates the IMU.

Returns an InertialCalibrateFuture that resolves once the calibration operation has finished or timed out.

This method MUST be called for any meaningful gyroscope readings to be obtained. Calibration requires the sensor to be sitting completely still. If the sensor is moving during the calibration process, readings will drift from reality over time.

§Errors
  • Calibration has a 1-second start timeout (when waiting for calibration to actually start on the sensor) and a 3-second end timeout (when waiting for calibration to complete after it has started) as a failsafe in the event that something goes wrong and the sensor gets stuck in a calibrating state. If either timeout is exceeded in its respective phase of calibration, InertialError::CalibrationTimedOut will be returned.
  • An InertialError::Port error is returned if there is not an inertial sensor connected to the port.
  • An InertialError::BadStatus error is returned if the inertial sensor failed to report its status.
§Examples

Calibration process with error handling and a retry:

use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    match sensor.calibrate().await {
        Ok(_) => println!("IMU calibrated successfully."),
        Err(err) => {
            println!("IMU failed to calibrate, retrying. Reason: {:?}", err);

            // Since calibration failed, let's try one more time. If that fails,
            // we just ignore the error and go on with our lives.
            _ = sensor.calibrate().await;
        }
    }
}

Calibrating in a competition enviornment:

use vexide::prelude::*;
use core::time::Duration;

struct Robot {
    imu: InertialSensor,
}

impl Compete for Robot {
    async fn autonomous(&mut self) {
        loop {
            if let Ok(heading) = self.imu.heading() {
                println!("IMU Heading: {heading}°");
            }

            sleep(Duration::from_millis(10)).await;
        }
    }
}

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut imu = InertialSensor::new(peripherals.port_1);

    if let Err(err) = imu.calibrate().await {
        // Log out a warning to terminal if calibration failed. You can also retry by
        // calling it again, although this usually only happens if the sensor was unplugged.
        println!("WARNING: IMU failed to calibrate! Readings might be inaccurate!");
    }

    Robot { imu }.compete().await;
}
Source

pub fn rotation(&self) -> Result<f64, InertialError>

Returns the total number of degrees the Inertial Sensor has spun about the z-axis.

This value is theoretically unbounded. Clockwise rotations are represented with positive degree values, while counterclockwise rotations are represented with negative ones.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    if let Ok(rotation) = sensor.rotation() {
        println!("Robot has rotated {} degrees since calibration.", rotation);
    }
}
Source

pub fn heading(&self) -> Result<f64, InertialError>

Returns the Inertial Sensor’s yaw angle bounded from [0.0, 360.0) degrees.

Clockwise rotations are represented with positive degree values, while counterclockwise rotations are represented with negative ones.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    if let Ok(heading) = sensor.heading() {
        println!("Heading is {} degrees.", rotation);
    }
}
Source

pub fn quaternion(&self) -> Result<Quaternion<f64>, InertialError>

Returns a quaternion representing the Inertial Sensor’s current orientation.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    if let Ok(quaternion) = sensor.quaternion() {
        println!(
            "x: {}, y: {}, z: {}, scalar: {}",
            quaternion.v.x,
            quaternion.v.y,
            quaternion.v.z,
            quaternion.s,
        );
    }
}
Source

pub fn euler(&self) -> Result<EulerAngles<f64, f64>, InertialError>

Returns the Euler angles (pitch, yaw, roll) in radians representing the Inertial Sensor’s orientation.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    if let Ok(angles) = sensor.euler() {
        println!(
            "yaw: {}°, pitch: {}°, roll: {}°",
            angles.a.to_degrees(),
            angles.b.to_degrees(),
            angles.c.to_degrees(),
        );
    }
}
Source

pub fn gyro_rate(&self) -> Result<Vector3<f64>, InertialError>

Returns the Inertial Sensor’s raw gyroscope readings in dps (degrees per second).

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Read out angular velocity values every 10mS
    loop {
        if let Ok(rates) = sensor.gyro_rate() {
            println!(
                "x: {}°/s, y: {}°/s, z: {}°/s",
                rates.x,
                rates.y,
                rates.z,
            );
        }

        sleep(Duration::from_millis(10)).await;
    }
}
Source

pub fn acceleration(&self) -> Result<Vector3<f64>, InertialError>

Returns the sensor’s raw acceleration readings in g (multiples of ~9.8 m/s/s).

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Read out accleration values every 10mS
    loop {
        if let Ok(acceleration) = sensor.acceleration() {
            println!(
                "x: {}G, y: {}G, z: {}G",
                acceleration.x,
                acceleration.y,
                acceleration.z,
            );
        }

        sleep(Duration::from_millis(10)).await;
    }
}
Source

pub fn reset_heading(&mut self) -> Result<(), InertialError>

Resets the current reading of the sensor’s heading to zero.

This only affects the value returned by InertialSensor::heading and does not effect InertialSensor::rotation or InertialSensor::euler/InertialSensor::quaternion.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    // Store heading before reset.
    let heading = sensor.heading().unwrap_or_default();

    // Reset heading back to zero.
    _ = sensor.reset_heading();
}
Source

pub fn reset_rotation(&mut self) -> Result<(), InertialError>

Resets the current reading of the sensor’s rotation to zero.

This only affects the value returned by InertialSensor::rotation and does not effect InertialSensor::heading or InertialSensor::euler/InertialSensor::quaternion.

§Errors
§Examples
use vexide::prelude::*;
use core::time::Duration;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Calibrate sensor, panic if calibration fails.
    sensor.calibrate().await.unwrap();

    // Sleep for two seconds to allow the robot to be moved.
    sleep(Duration::from_secs(2)).await;

    // Store rotation before reset.
    let rotation = sensor.rotation().unwrap_or_default();

    // Reset heading back to zero.
    _ = sensor.reset_rotation();
}
Source

pub fn set_rotation(&mut self, rotation: f64) -> Result<(), InertialError>

Sets the current reading of the sensor’s rotation to a given value.

This only affects the value returned by InertialSensor::rotation and does not effect InertialSensor::heading or InertialSensor::euler/InertialSensor::quaternion.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Set rotation to 90 degrees clockwise.
    _ = sensor.set_rotation(90.0);
}
Source

pub fn set_heading(&mut self, heading: f64) -> Result<(), InertialError>

Sets the current reading of the sensor’s heading to a given value.

This only affects the value returned by InertialSensor::heading and does not effect InertialSensor::rotation or InertialSensor::euler/InertialSensor::quaternion.

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Set heading to 90 degrees clockwise.
    _ = sensor.set_heading(90.0);
}
Source

pub fn set_data_interval( &mut self, interval: Duration, ) -> Result<(), InertialError>

Sets the internal computation speed of the IMU.

This method does NOT change the rate at which user code can read data off the IMU, as the brain will only talk to the device every 10mS regardless of how fast data is being sent or computed. See InertialSensor::UPDATE_INTERVAL.

This duration should be above Self::MIN_DATA_INTERVAL (5 milliseconds).

§Errors
§Examples
use vexide::prelude::*;

#[vexide::main]
async fn main(peripherals: Peripherals) {
    let mut sensor = InertialSensor::new(peripherals.port_1);

    // Set to minimum interval.
    _ = sensor.set_data_interval(InertialSensor::MIN_DATA_INTERVAL);
}

Trait Implementations§

Source§

impl Debug for InertialSensor

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<InertialSensor> for SmartPort

Source§

fn from(device: InertialSensor) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for InertialSensor

Source§

fn eq(&self, other: &InertialSensor) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

const fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl SmartDevice for InertialSensor

Source§

fn port_number(&self) -> u8

Returns the port number of the SmartPort this device is registered on. Read more
Source§

fn device_type(&self) -> SmartDeviceType

Returns the variant of SmartDeviceType that this device is associated with. Read more
Source§

const UPDATE_INTERVAL: Duration = _

The interval at which the V5 brain reads packets from Smart devices.
Source§

fn is_connected(&self) -> bool

Determine if this device type is currently connected to the SmartPort that it’s registered to. Read more
Source§

fn timestamp(&self) -> Result<SmartDeviceTimestamp, PortError>

Returns the timestamp recorded by this device’s internal clock. Read more
Source§

fn validate_port(&self) -> Result<(), PortError>

Verify that the device type is currently plugged into this port, returning an appropriate PortError if not available. Read more
Source§

impl Send for InertialSensor

Source§

impl StructuralPartialEq for InertialSensor

Source§

impl Sync for InertialSensor

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.