evian_tracking/lib.rs
1//! Robot localization and tracking.
2//!
3//! This crate provides traits and systems for tracking and localizing the position, orientation,
4//! velocity, and forward travel of a mobile robot in a 2D environment. The goal is to measure
5//! accurate data about the robot and provide it to motion algorithms.
6//!
7//! The traits provided in this crate allow for motion algorithms to operate generically over any
8//! tracking system implementation, provided that the implementation measures the necessary data.
9//!
10//! Tracking systems may choose to implement the following traits for motion algorithms to use:
11//!
12//! - [`TracksPosition`], for tracking the robot's 2D position (odometry).
13//! - [`TracksHeading`], for tracking the robot's absolute orientation (heading).
14//! - [`TracksVelocity`], for tracking the robot's linear and angular velocity.
15//! - [`TracksForwardTravel`], for tracking the robot's signed forward wheel travel.
16//!
17//! Below is an example of a motion algorithm function that is generic across all differential
18//! drivetrains with tracking systems that measure a robot's forward wheel travel:
19//!
20//! ```
21//! async fn motion(drivetrain: &mut Drivetrain<Differential, impl TracksForwardTravel>) {
22//! // Motion goes here...
23//! }
24//! ```
25//!
26//! Additionally, a reference implementation of a tracking system that performs wheeled odometry is
27//! provided by the [`wheeled`] module.
28//!
29//! # A quick note about units!
30//!
31//! `evian` made the intentional choice to be primarily unitless, mainly because stable Rust
32//! currently lacks many of the features needed to provide a good developer experience using
33//! typed units. Although several widely-used libraries exist in stable Rust (such as
34//! [`uom`](http://crates.io/crates/uom)), there is no single obvious choice to be made here and
35//! this region of the Rust ecosystem seems to be in a fairly volatile state that would make it
36//! dangerous to fully commit to a single library this early on.
37//!
38//! As such, evian made the decision to forego requiring specific units of measure where possible,
39//! particular in measures of *length*. Instead, length is typically provided in **wheel units**,
40//! which is defined as "whatever the user measured their wheels with". This gives users a choice
41//! of what units to use and keeps everything generally stable while the Rust ecosystem tries to
42//! figure out what typed units library to go with.
43
44#![no_std]
45
46extern crate alloc;
47
48mod sensor;
49pub mod wheeled;
50
51pub use sensor::RotarySensor;
52
53use evian_math::{Angle, Vec2};
54
55/// A tracking system that localizes a robot's 2D position.
56///
57/// This trait defines a system for tracking and reporting the position of a mobile robot in a
58/// 2D environment. The process of localizing a mobile robot's position is also commonly known
59/// as odometry.
60///
61/// # Coordinate System
62///
63/// Implementors of this trait MUST provide their position estimate in the [*cartesian coordinate
64/// system*](https://en.wikipedia.org/wiki/Cartesian_coordinate_system). Units are expected to be
65/// in *wheel units* — the same units that were used to measure the robot's wheel diameter.
66pub trait TracksPosition {
67 /// Return's the robot's position on a 2D cartesian coordinate plane measured
68 /// in wheel units.
69 fn position(&self) -> Vec2<f64>;
70}
71
72/// A tracking system that tracks a robot's absolute orientation.
73///
74/// This trait defines a system for tracking and reporting the orientation (heading) of a mobile
75/// robot in a 2D environment. The robot's orientation refers to its direction of travel relative
76/// to a fixed reference frame.
77///
78/// # Angle System
79///
80/// Implementors of this trait MUST provide their angles in a system compatible with cartesian
81/// coordinates in *standard position*. This means that anticlockwise motion is considered a
82/// positive rotation, and a rotation of zero degrees is inline with the x-axis.
83pub trait TracksHeading {
84 /// Returns the robot's orientation bounded from [0, 2π] radians.
85 fn heading(&self) -> Angle;
86}
87
88/// A tracking system that tracks a robot's linear and angular velocity.
89///
90/// # Units
91///
92/// - Linear velocity is measured in *wheel units per second*. In this instance, *wheel units*
93/// refer to whatever units the user measured their wheel diameter with.
94///
95/// - Angular velocity is measured in *radians per second*.
96pub trait TracksVelocity {
97 /// Returns the robot's estimated linear velocity in wheel units per second.
98 fn linear_velocity(&self) -> f64;
99
100 /// Returns the robot's estimated angular velocity in radians per second.
101 fn angular_velocity(&self) -> f64;
102}
103
104/// A tracking system that tracks a robot's signed forward wheel travel.
105///
106/// # Units
107///
108/// Units are expected to be returned in *wheel units* — the same units that were used to measure the
109/// robot's wheel diameter.
110pub trait TracksForwardTravel {
111 /// Returns the signed forward wheel travel of the robot in wheel units.
112 ///
113 /// Positive values indicate forward movement from the origin of tracking, while negative
114 /// values indicate backwards movement from the origin.
115 fn forward_travel(&self) -> f64;
116}