pub struct InertialSensor { /* private fields */ }
Expand description
An inertial sensor (IMU) plugged into a Smart Port.
Implementations§
Source§impl InertialSensor
impl InertialSensor
Sourcepub const CALIBRATION_START_TIMEOUT: Duration
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
.
Sourcepub const CALIBRATION_END_TIMEOUT: Duration
pub const CALIBRATION_END_TIMEOUT: Duration
The maximum time that the Inertial Sensor should take to end its calibration process after calibration has begun.
Sourcepub const MIN_DATA_INTERVAL: Duration
pub const MIN_DATA_INTERVAL: Duration
The minimum data rate that you can set an IMU to run at.
Sourcepub const MAX_HEADING: f64 = 360f64
pub const MAX_HEADING: f64 = 360f64
The maximum value that can be returned by Self::heading
.
Sourcepub fn new(port: SmartPort) -> Self
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);
}
Sourcepub fn status(&self) -> Result<InertialStatus, InertialError>
pub fn status(&self) -> Result<InertialStatus, InertialError>
Returns the internal status code of the intertial sensor.
§Errors
- 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
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());
}
}
Sourcepub fn is_calibrating(&self) -> Result<bool, InertialError>
pub fn is_calibrating(&self) -> Result<bool, InertialError>
Returns true
if the sensor is currently calibrating.
§Errors
- 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
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.");
}
}
Sourcepub fn is_auto_calibrated(&self) -> Result<bool, InertialError>
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
- 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
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.");
}
}
Sourcepub fn physical_orientation(&self) -> Result<InertialOrientation, InertialError>
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
- 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
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);
}
}
}
Sourcepub const fn calibrate(&mut self) -> InertialCalibrateFuture<'_> ⓘ
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;
}
Sourcepub fn rotation(&self) -> Result<f64, InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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);
}
}
Sourcepub fn heading(&self) -> Result<f64, InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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);
}
}
Sourcepub fn quaternion(&self) -> Result<Quaternion<f64>, InertialError>
pub fn quaternion(&self) -> Result<Quaternion<f64>, InertialError>
Returns a quaternion representing the Inertial Sensor’s current orientation.
§Errors
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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,
);
}
}
Sourcepub fn euler(&self) -> Result<EulerAngles<f64, f64>, InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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(),
);
}
}
Sourcepub fn gyro_rate(&self) -> Result<Vector3<f64>, InertialError>
pub fn gyro_rate(&self) -> Result<Vector3<f64>, InertialError>
Returns the Inertial Sensor’s raw gyroscope readings in dps (degrees per second).
§Errors
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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;
}
}
Sourcepub fn acceleration(&self) -> Result<Vector3<f64>, InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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;
}
}
Sourcepub fn reset_heading(&mut self) -> Result<(), InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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();
}
Sourcepub fn reset_rotation(&mut self) -> Result<(), InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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();
}
Sourcepub fn set_rotation(&mut self, rotation: f64) -> Result<(), InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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);
}
Sourcepub fn set_heading(&mut self, heading: f64) -> Result<(), InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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);
}
Sourcepub fn set_data_interval(
&mut self,
interval: Duration,
) -> Result<(), InertialError>
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
- 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. - An
InertialError::StillCalibrating
error is returned if the sensor is currently calibrating and cannot yet be used.
§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
impl Debug for InertialSensor
Source§impl From<InertialSensor> for SmartPort
impl From<InertialSensor> for SmartPort
Source§fn from(device: InertialSensor) -> Self
fn from(device: InertialSensor) -> Self
Source§impl PartialEq for InertialSensor
impl PartialEq for InertialSensor
Source§impl SmartDevice for InertialSensor
impl SmartDevice for InertialSensor
Source§fn port_number(&self) -> u8
fn port_number(&self) -> u8
Source§fn device_type(&self) -> SmartDeviceType
fn device_type(&self) -> SmartDeviceType
SmartDeviceType
that this device is associated with. Read more