pub struct InertialSensor { /* private fields */ }devices only.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 fn new(port: SmartPort) -> InertialSensor
pub fn new(port: SmartPort) -> InertialSensor
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 const fn calibrate(&mut self) -> CalibrateFuture<'_> ⓘ
pub const fn calibrate(&mut self) -> CalibrateFuture<'_> ⓘ
Calibrates the IMU.
Returns an CalibrateFuture 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,
CalibrateError::Timeoutwill be returned. - A
CalibrateError::Porterror is returned if there is not an Inertial Sensor connected to the port.
§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 environment:
use std::time::Duration;
use vexide::prelude::*;
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.as_degrees());
}
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 heading(&self) -> Result<Angle, InertialError>
pub fn heading(&self) -> Result<Angle, 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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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.", heading.as_degrees());
}
}Sourcepub fn set_heading(&mut self, heading: Angle) -> Result<(), InertialError>
pub fn set_heading(&mut self, heading: Angle) -> 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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use vexide::{math::Angle, 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(Angle::from_degrees(90.0));
}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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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 rotation(&self) -> Result<Angle, InertialError>
pub fn rotation(&self) -> Result<Angle, 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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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.as_degrees()
);
}
}Sourcepub fn set_rotation(&mut self, rotation: Angle) -> Result<(), InertialError>
pub fn set_rotation(&mut self, rotation: Angle) -> 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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use vexide::{math::Angle, 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(Angle::from_degrees(90.0));
}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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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 euler(&self) -> Result<EulerAngles<Angle, IntraZYX>, InertialError>
pub fn euler(&self) -> Result<EulerAngles<Angle, IntraZYX>, InertialError>
Returns the Euler angles (pitch, yaw, roll) in radians representing the Inertial Sensor’s orientation.
Euler angles are normalized to Angle::HALF_TURN, meaning they range from (-180°, 180°].
§Errors
- An
InertialError::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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!(
"pitch: {}°, yaw: {}°, roll: {}°",
angles.a.as_degrees(),
angles.b.as_degrees(),
angles.c.as_degrees(),
);
}
}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::Porterror is returned if there is not an Inertial Sensor connected to the port. - An
InertialError::Calibratingerror is returned if the Inertial Sensor is currently calibrating and cannot yet be used.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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 gyro_rate(&self) -> Result<Vector3<f64>, PortError>
pub fn gyro_rate(&self) -> Result<Vector3<f64>, PortError>
Returns the Inertial Sensor’s raw gyroscope readings in dps (degrees per second).
§Errors
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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>, PortError>
pub fn acceleration(&self) -> Result<Vector3<f64>, PortError>
Returns the sensor’s raw acceleration readings in g (multiples of ~9.8 m/s/s).
§Errors
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§Examples
use std::time::Duration;
use vexide::prelude::*;
#[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 acceleration 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 status(&self) -> Result<InertialStatus, PortError>
pub fn status(&self) -> Result<InertialStatus, PortError>
Returns the internal status code of the inertial sensor.
§Errors
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§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, PortError>
pub fn is_calibrating(&self) -> Result<bool, PortError>
Returns true if the sensor is currently calibrating.
§Errors
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§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, PortError>
pub fn is_auto_calibrated(&self) -> Result<bool, PortError>
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
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§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, PortError>
pub fn physical_orientation(&self) -> Result<InertialOrientation, PortError>
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
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§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 fn set_data_interval(&mut self, interval: Duration) -> Result<(), PortError>
pub fn set_data_interval(&mut self, interval: Duration) -> Result<(), PortError>
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).
§Precision
The internal data rate of the IMU has a precision of 5 milliseconds.
§Errors
- A
PortError::Disconnectederror is returned if no device was connected to the port. - A
PortError::IncorrectDeviceerror is returned if the wrong type of device was connected to the port.
§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) -> SmartPort
fn from(device: InertialSensor) -> SmartPort
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