Compare commits
4
Commits
ca5607ec25
...
d4809beee7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4809beee7 | ||
|
|
69deda596e | ||
|
|
3703ca664e | ||
|
|
4b06468ff4 |
Generated
+237
-17
@@ -3,35 +3,193 @@
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"hash32 0.2.1",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"spin",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4"
|
||||
dependencies = [
|
||||
"hash32 0.3.1",
|
||||
"serde_core",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"heapless 0.7.17",
|
||||
"postcard-derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard-derive"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rnavp"
|
||||
version = "0.3.0"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"heapless 0.9.3",
|
||||
"postcard",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"uom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
name = "rnavp_communication"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "rnavp_logic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rnavp",
|
||||
"serde",
|
||||
"uom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
@@ -39,37 +197,99 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
name = "spin"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "uom"
|
||||
version = "0.38.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a739f83872836c82a4f2527d4e54b37007b3de68cafe7edde95fd695968bf4b9"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
+4
-19
@@ -1,19 +1,4 @@
|
||||
[package]
|
||||
name = "rnavp"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
publish = ["gitea"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[features]
|
||||
default= ["embassy"]
|
||||
std = []
|
||||
embassy = ["core_full"]
|
||||
core = []
|
||||
core_full = ["core_communication", "core_logic"]
|
||||
core_communication = ["core"]
|
||||
core_logic = ["core"]
|
||||
host = ["std", "core_full"]
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.228", features = ["derive"], default-features = false }
|
||||
[workspace]
|
||||
members = ["rnavp"
|
||||
, "rnavp_communication", "rnavp_controller"]
|
||||
resolver = "3"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "rnavp"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
heapless = { version = "0.9.3", features = ["serde"] }
|
||||
postcard = { version = "1.1.3", features = ["postcard-derive"] }
|
||||
serde = { version = "1.0.229", default-features = false, features = ["derive"] }
|
||||
thiserror = { version = "2.0.19", default-features = false }
|
||||
uom = { version = "0.38.0", default-features = false, features = ["autoconvert", "f32", "si"] }
|
||||
@@ -0,0 +1,69 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
///A simple enum for Counterclockwise or Clockwise direction semantics. Makes it easier much clear than a true/false bool
|
||||
/// IF you use this to convert to a signed number note that CW is negative and CCW is positive
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum Direction {
|
||||
///CounterClockWise
|
||||
CCW,
|
||||
///ClockWise
|
||||
CW,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
///Inverts the direction currently stored in this.
|
||||
/// Helps with a simple direction change without knowing the current direction.
|
||||
pub fn inv_dir(&mut self) {
|
||||
match *self {
|
||||
Self::CCW => {
|
||||
*self = Self::CW;
|
||||
}
|
||||
Self::CW => {
|
||||
*self = Self::CCW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Changes the current direction based on the sign of the float.
|
||||
///Recommended to use this over the "From" impl for directions that already exist, to prevent werid 0.0 case and NaN problems
|
||||
/// This handles 0.0 and NaN by just doing nothing. The "From" impl defualts to CCW for both
|
||||
pub fn dir_from_f32(&mut self, value: f32) {
|
||||
if value == 0.0 || value.is_nan() {
|
||||
return;
|
||||
}
|
||||
*self = value.into();
|
||||
}
|
||||
|
||||
///Changes the current direction based on the sign of the int.
|
||||
///Recommended to use this over the "From" impl for directions that already exist, to prevent weird 0 case problems
|
||||
///This handles 0 by just doing nothing. The "From" impl defaults to CCW
|
||||
pub fn dir_from_i32(&mut self, value: i32) {
|
||||
if value == 0 {
|
||||
return;
|
||||
}
|
||||
*self = value.into();
|
||||
}
|
||||
}
|
||||
|
||||
///Converts F32 to direction using the number's sign.
|
||||
/// This defaults to CCW for 0.0 and NaN.
|
||||
impl From<f32> for Direction {
|
||||
fn from(value: f32) -> Self {
|
||||
if value < 0.0 {
|
||||
Direction::CW
|
||||
} else {
|
||||
Direction::CCW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts i32 to direction using the number's sign.
|
||||
/// This defaults to CCW for 0.
|
||||
impl From<i32> for Direction {
|
||||
fn from(value: i32) -> Self {
|
||||
if value < 0 {
|
||||
Direction::CW
|
||||
} else {
|
||||
Direction::CCW
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mod direction;
|
||||
pub mod error;
|
||||
pub mod motor;
|
||||
pub mod pid;
|
||||
pub mod positional;
|
||||
@@ -1,115 +1,6 @@
|
||||
use core::fmt::Display;
|
||||
use uom::si::f32::{Angle, AngularVelocity, ElectricCurrent, ElectricPotential};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::core::{
|
||||
motor::Direction::{CCW, CW},
|
||||
units::{Angle, Current, Voltage},
|
||||
};
|
||||
|
||||
///A simple enum for Counterclockwise or Clockwise direction semantics. Makes it easier much clear than a true/false bool
|
||||
/// IF you use this to convert to a signed number note that CW is negative and CCW is positive
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum Direction {
|
||||
///CounterClockWise
|
||||
CCW,
|
||||
///ClockWise
|
||||
CW,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
///Inverts the direction currently stored in this.
|
||||
/// Helps with a simple direction change without knowing the current direction.
|
||||
pub fn inv_dir(&mut self) {
|
||||
match *self {
|
||||
Self::CCW => {
|
||||
*self = Self::CW;
|
||||
}
|
||||
Self::CW => {
|
||||
*self = Self::CCW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Changes the current direction based on the sign of the float.
|
||||
///Recommended to use this over the "From" impl for directions that already exist, to prevent werid 0.0 case and NaN problems
|
||||
/// This handles 0.0 and NaN by just doing nothing. The "From" impl defualts to CCW for both
|
||||
pub fn dir_from_f32(&mut self, value: f32) {
|
||||
if value == 0.0 || value.is_nan() {
|
||||
return;
|
||||
}
|
||||
*self = value.into();
|
||||
}
|
||||
|
||||
///Changes the current direction based on the sign of the int.
|
||||
///Recommended to use this over the "From" impl for directions that already exist, to prevent weird 0 case problems
|
||||
///This handles 0 by just doing nothing. The "From" impl defaults to CCW
|
||||
pub fn dir_from_i32(&mut self, value: i32) {
|
||||
if value == 0 {
|
||||
return;
|
||||
}
|
||||
*self = value.into();
|
||||
}
|
||||
}
|
||||
|
||||
///Converts F32 to direction using the number's sign.
|
||||
/// This defaults to CCW for 0.0 and NaN.
|
||||
impl From<f32> for Direction {
|
||||
fn from(value: f32) -> Self {
|
||||
if value < 0.0 { CW } else { CCW }
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts i32 to direction using the number's sign.
|
||||
/// This defaults to CCW for 0.
|
||||
impl From<i32> for Direction {
|
||||
fn from(value: i32) -> Self {
|
||||
if value < 0 { CW } else { CCW }
|
||||
}
|
||||
}
|
||||
|
||||
///A enum for containerizing speeds easily
|
||||
/// Lets the backend take in a Rotations per minute value from a user Sensor implementation and convert it to a Radians per second value
|
||||
///Pay attention to the units of each term
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum Speed {
|
||||
///Rotations per minute
|
||||
RPM(f32),
|
||||
///Radians per second
|
||||
RADS(f32),
|
||||
}
|
||||
///Used to convert from Rotations per minute to radians per second
|
||||
const RPM_TO_RADS: f32 = core::f32::consts::TAU / 60.0;
|
||||
///Used to convert from Radians per second to Rotations per minute
|
||||
const RADS_TO_RPM: f32 = 60.0 / core::f32::consts::TAU;
|
||||
|
||||
impl Speed {
|
||||
///Returns the value as Radians Per Second regardless of what the enum contains
|
||||
/// Uses no runtime division
|
||||
#[inline]
|
||||
pub fn rads(&self) -> f32 {
|
||||
match *self {
|
||||
Self::RPM(rpm) => rpm * RADS_TO_RPM,
|
||||
Self::RADS(rps) => rps,
|
||||
}
|
||||
}
|
||||
|
||||
///Returns the value as Rotations Per minute regardles of what the enum contains
|
||||
/// Uses no runtime division
|
||||
#[inline]
|
||||
pub fn rpm(&self) -> f32 {
|
||||
match *self {
|
||||
Self::RPM(rpm) => rpm,
|
||||
Self::RADS(rps) => rps * RPM_TO_RADS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Speed {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
pub use crate::direction::Direction;
|
||||
|
||||
/// # Motor Driver
|
||||
///
|
||||
@@ -160,15 +51,15 @@ pub trait Sensor {
|
||||
///Returns the speed struct value from the motors sensor.
|
||||
///
|
||||
/// IF properly returned in the correct Enum Data field, all other systems will use the value propely, being unit agnostic later.
|
||||
async fn get_speed(&self) -> Speed;
|
||||
async fn get_speed(&self) -> AngularVelocity;
|
||||
|
||||
///Returns the current from the sensor, if it capable.
|
||||
/// This should be non-blocking. Keep a cached value ready.
|
||||
async fn get_current(&self) -> Option<Current>;
|
||||
async fn get_current(&self) -> Option<ElectricCurrent>;
|
||||
|
||||
///Returns the current voltage from the sensro, if it is capable.
|
||||
/// This should be non-blocking. Keep a cached value ready.
|
||||
async fn get_voltage(&self) -> Option<Voltage>;
|
||||
async fn get_voltage(&self) -> Option<ElectricPotential>;
|
||||
|
||||
///Returns the current angle from the sensor if it is capable.
|
||||
/// This should be non-blocking. Keep a cached value ready.
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "rnavp_communication"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,14 @@
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "rnavp_logic"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
rnavp = {path = "../rnavp"}
|
||||
serde = { version = "1.0.229", default-features = false, features = ["derive"] }
|
||||
uom = { version = "0.38.0", default-features = false, features = ["si", "f32"] }
|
||||
@@ -0,0 +1 @@
|
||||
pub mod motor;
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::core::motor;
|
||||
use crate::core::motor::{Direction, Speed};
|
||||
|
||||
use crate::core::logic::pid;
|
||||
use rnavp::motor::{self, Direction};
|
||||
use rnavp::pid;
|
||||
use uom::si::f32::AngularVelocity;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
/// # Motor Controller
|
||||
@@ -17,7 +16,7 @@ where
|
||||
T: motor::Driver + motor::Sensor,
|
||||
{
|
||||
motor: T,
|
||||
max_speed: Speed,
|
||||
max_speed: AngularVelocity,
|
||||
pid: pid::PID,
|
||||
current_direction: Direction,
|
||||
}
|
||||
@@ -25,12 +24,12 @@ where
|
||||
///Controller Impl for the adding the PID logic for handling the motor compiston
|
||||
impl<T: motor::Driver + motor::Sensor> Controller<T> {
|
||||
///Uses the given set_speed and then will handle the rest of the control logic to accurately* hit the requested speed
|
||||
pub async fn control(&mut self, set_speed: Speed) {
|
||||
let max_speed_rads = self.max_speed.rads();
|
||||
let set_speed_rads = set_speed.rads().clamp(-max_speed_rads, max_speed_rads);
|
||||
pub async fn control(&mut self, set_speed: AngularVelocity) {
|
||||
let max_speed_rads = self.max_speed.value;
|
||||
let set_speed_rads = set_speed.value.clamp(-max_speed_rads, max_speed_rads);
|
||||
|
||||
self.pid.set_point(set_speed_rads).await;
|
||||
let pid_output = self.pid.pid_step(self.motor.get_speed().await.rads()).await;
|
||||
let pid_output = self.pid.pid_step(self.motor.get_speed().await.value).await;
|
||||
|
||||
self.current_direction.dir_from_f32(pid_output);
|
||||
|
||||
@@ -43,13 +42,13 @@ impl<T: motor::Driver + motor::Sensor> Controller<T> {
|
||||
|
||||
///Retrieve the speed from the motor inside the controller.
|
||||
/// This allows you to get a speed value from behind the move.
|
||||
pub async fn retrieve(&self) -> motor::Speed {
|
||||
pub async fn retrieve(&self) -> AngularVelocity {
|
||||
self.motor.get_speed().await
|
||||
}
|
||||
|
||||
///Creates a new Controller with a motor (of type T), a max speed and a pid::Config
|
||||
/// This then allows for you to use the controller with the provided types
|
||||
pub fn new(motor: T, max_speed: Speed, config: pid::Config) -> Self {
|
||||
pub fn new(motor: T, max_speed: AngularVelocity, config: pid::Config) -> Self {
|
||||
Controller {
|
||||
motor: motor,
|
||||
max_speed: max_speed,
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod drivetrain;
|
||||
pub mod motor;
|
||||
pub mod sensing;
|
||||
pub mod wheel;
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod kinematics;
|
||||
pub mod motor;
|
||||
pub mod pid;
|
||||
@@ -1,10 +0,0 @@
|
||||
#[cfg(feature = "core_communication")]
|
||||
pub mod communication;
|
||||
|
||||
#[cfg(feature = "core_logic")]
|
||||
pub mod logic;
|
||||
|
||||
pub mod error;
|
||||
pub mod motor;
|
||||
pub mod positional;
|
||||
pub mod units;
|
||||
@@ -1,250 +0,0 @@
|
||||
use core::fmt::Display;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
///Generic Positional Data Struct, This can contain XYZ positions in meters or Radians
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Debug)]
|
||||
pub struct XYZPos {
|
||||
x: Option<f32>,
|
||||
y: Option<f32>,
|
||||
z: Option<f32>,
|
||||
unit: Unit,
|
||||
}
|
||||
|
||||
///Generic Velocity Data Struct, This can contain XYZ velocities in Meters Per Second or Radians Per Second
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Debug)]
|
||||
pub struct XYZVel {
|
||||
x: Option<f32>,
|
||||
y: Option<f32>,
|
||||
z: Option<f32>,
|
||||
unit: Unit,
|
||||
}
|
||||
|
||||
///Generic Acceleration Data Struct, This can contain XYZ accelerations in Meters Per Second Squared or Radians Per Second
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Debug)]
|
||||
pub struct XYZAccel {
|
||||
x: Option<f32>,
|
||||
y: Option<f32>,
|
||||
z: Option<f32>,
|
||||
unit: Unit,
|
||||
}
|
||||
|
||||
impl XYZData for XYZPos {
|
||||
fn x(&self) -> Option<f32> {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(&self) -> Option<f32> {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn z(&self) -> Option<f32> {
|
||||
self.z
|
||||
}
|
||||
|
||||
fn unit(&self) -> Unit {
|
||||
self.unit
|
||||
}
|
||||
|
||||
fn is_pos(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl XYZData for XYZVel {
|
||||
fn x(&self) -> Option<f32> {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(&self) -> Option<f32> {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn z(&self) -> Option<f32> {
|
||||
self.z
|
||||
}
|
||||
|
||||
fn unit(&self) -> Unit {
|
||||
self.unit
|
||||
}
|
||||
|
||||
fn is_vel(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl XYZData for XYZAccel {
|
||||
fn x(&self) -> Option<f32> {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(&self) -> Option<f32> {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn z(&self) -> Option<f32> {
|
||||
self.z
|
||||
}
|
||||
|
||||
fn unit(&self) -> Unit {
|
||||
self.unit
|
||||
}
|
||||
|
||||
fn is_accel(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Position for XYZPos {}
|
||||
|
||||
impl Velocity for XYZVel {}
|
||||
|
||||
impl Acceleration for XYZAccel {}
|
||||
|
||||
impl Display for XYZPos {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let unit_str = match self.unit {
|
||||
Unit::Meters => "m",
|
||||
Unit::Radians => "rad",
|
||||
Unit::Custom => "custom",
|
||||
};
|
||||
|
||||
write!(
|
||||
f,
|
||||
"[X: {:?}{unit_str} | Y: {:?}{unit_str} | Z: {:?}{unit_str}]",
|
||||
self.x, self.y, self.z
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for XYZVel {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let unit_str = match self.unit {
|
||||
Unit::Meters => "m",
|
||||
Unit::Radians => "rad",
|
||||
Unit::Custom => "custom",
|
||||
};
|
||||
|
||||
write!(
|
||||
f,
|
||||
"[X: {:?}{unit_str}/s | Y: {:?}{unit_str}/s | Z: {:?}{unit_str}/s]",
|
||||
self.x, self.y, self.z
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for XYZAccel {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let unit_str = match self.unit {
|
||||
Unit::Meters => "m",
|
||||
Unit::Radians => "rad",
|
||||
Unit::Custom => "custom",
|
||||
};
|
||||
|
||||
write!(
|
||||
f,
|
||||
"[X: {:?}{unit_str}/s^2 | Y: {:?}{unit_str}/s^2 | Z: {:?}{unit_str}/s^2]",
|
||||
self.x, self.y, self.z
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
///Structs that impl this trait, mean they are positions. Determine what type of position by reading the unit.
|
||||
pub trait Position: XYZData {}
|
||||
|
||||
///Structs that impl this trait mean they are Velocities. Determine what type of velocity by reading the unit.
|
||||
pub trait Velocity: XYZData {}
|
||||
|
||||
///Structs that impl this trait mean they are Accelerations. Determine what type of Acceleration by reading the unit.
|
||||
pub trait Acceleration: XYZData {}
|
||||
|
||||
///This is the data backbone for the XYZ Position, Velocity, and Acceleration Data structs.
|
||||
///They MUST implmenent this so it possible to easily and quickly get the data from the struct.
|
||||
///Provides methods to check what type this is
|
||||
pub trait XYZData {
|
||||
fn x(&self) -> Option<f32>;
|
||||
fn y(&self) -> Option<f32>;
|
||||
fn z(&self) -> Option<f32>;
|
||||
fn unit(&self) -> Unit;
|
||||
|
||||
///Returns an array of f32s that are the XYZ position, velocity or accel, based on the implemented traits.
|
||||
///Any option field in the array that are None are returned as 0.0 here.
|
||||
///Do not forget to check the unit, this may be in radians or meters.
|
||||
fn xyz_array(&self) -> [f32; 3] {
|
||||
[
|
||||
self.x().unwrap_or(0.0),
|
||||
self.y().unwrap_or(0.0),
|
||||
self.z().unwrap_or(0.0),
|
||||
]
|
||||
}
|
||||
|
||||
fn is_pos(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_vel(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_accel(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum XYZDataBucket {
|
||||
Pos(XYZPos),
|
||||
Vel(XYZVel),
|
||||
Accel(XYZAccel),
|
||||
}
|
||||
|
||||
impl XYZData for XYZDataBucket {
|
||||
fn is_pos(&self) -> bool {
|
||||
matches!(self, Self::Pos(_))
|
||||
}
|
||||
fn is_vel(&self) -> bool {
|
||||
matches!(self, Self::Vel(_))
|
||||
}
|
||||
fn is_accel(&self) -> bool {
|
||||
matches!(self, Self::Accel(_))
|
||||
}
|
||||
|
||||
fn x(&self) -> Option<f32> {
|
||||
match self {
|
||||
Self::Pos(p) => p.x(),
|
||||
Self::Vel(v) => v.x(),
|
||||
Self::Accel(a) => a.x(),
|
||||
}
|
||||
}
|
||||
|
||||
fn y(&self) -> Option<f32> {
|
||||
match self {
|
||||
Self::Pos(p) => p.y(),
|
||||
Self::Vel(v) => v.y(),
|
||||
Self::Accel(a) => a.y(),
|
||||
}
|
||||
}
|
||||
|
||||
fn z(&self) -> Option<f32> {
|
||||
match self {
|
||||
Self::Pos(p) => p.z(),
|
||||
Self::Vel(v) => v.z(),
|
||||
Self::Accel(a) => a.z(),
|
||||
}
|
||||
}
|
||||
|
||||
fn unit(&self) -> Unit {
|
||||
match self {
|
||||
Self::Pos(p) => p.unit(),
|
||||
Self::Vel(v) => v.unit(),
|
||||
Self::Accel(a) => a.unit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Represents the unit this position struct is carrying. Combining the Unit + Trait it impls lets you determine what this message contains
|
||||
/// If you need to send a unit not listed here please use Unit::Custom
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Unit {
|
||||
Meters,
|
||||
Radians,
|
||||
Custom,
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
///Standard conversion constant to convert to micro from base unit
|
||||
pub const TO_MICRO: f32 = 1_000_000.0;
|
||||
///Standard conversion constant to convert from micro to base unit;
|
||||
pub const FROM_MICRO: f32 = 1.0 / 1_000_000.0;
|
||||
///Standard conversion constant to convert to milli from base unit;
|
||||
pub const TO_MILLI: f32 = 1_000.0;
|
||||
///Standard conversion constant to convert from milli to base unit;
|
||||
pub const FROM_MILLI: f32 = 1.0 / 1_000.0;
|
||||
|
||||
///Standard way for the RNavP system to transfer around Current measurements.
|
||||
/// This system by default uses Amps as f32.
|
||||
/// Offers MilliAmps and MicroAmps for utilizing higher precision raw data for when needed.
|
||||
/// Implements all needed conversions for handling f32 into and from this data type.
|
||||
/// Uses Amps by default, please use MicroAmps and MilliVolts when needed for higher precision.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Current {
|
||||
Amps(f32),
|
||||
MilliAmps(i32),
|
||||
MicroAmps(i32),
|
||||
}
|
||||
|
||||
impl From<f32> for Current {
|
||||
fn from(value: f32) -> Self {
|
||||
Self::Amps(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<f32> for Current {
|
||||
fn into(self) -> f32 {
|
||||
match self {
|
||||
Self::MicroAmps(micro) => micro as f32 * FROM_MICRO,
|
||||
Self::MilliAmps(milli) => milli as f32 * FROM_MILLI,
|
||||
Self::Amps(amps) => amps,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Standard way for the RNavP system to transfer around voltage measurements.
|
||||
/// This system by default uses Volts as f32.
|
||||
/// Offers MilliVolts and MicroVolts for utilizing higher precison raw data for when needed.
|
||||
/// Implements all needed conversions for handling f32 into and from this dataType.
|
||||
/// Uses Volts by default, please use MicroVolts and MilliVolts when needed for higher precision.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Voltage {
|
||||
Volts(f32),
|
||||
MilliVolts(i32),
|
||||
MicroVolts(i32),
|
||||
}
|
||||
|
||||
impl From<f32> for Voltage {
|
||||
fn from(value: f32) -> Self {
|
||||
Self::Volts(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<f32> for Voltage {
|
||||
fn into(self) -> f32 {
|
||||
match self {
|
||||
Self::MicroVolts(micro) => micro as f32 * FROM_MICRO,
|
||||
Self::MilliVolts(milli) => milli as f32 * FROM_MILLI,
|
||||
Self::Volts(volts) => volts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Standard way for the RnavP system for handling angles.
|
||||
/// The system does use a f32, so no conversions needed.
|
||||
/// Has methods for returning the wanted unit type regardless of what is stored.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Angle {
|
||||
Degrees(f32),
|
||||
Radians(f32),
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#[cfg(feature = "std")]
|
||||
compile_error!(
|
||||
"The 'std' feature is enabled, which is incompatible with 'embassy'. \n\
|
||||
The 'host' feature (enabled by default) turns on 'std'. \n\
|
||||
Please use '--no-default-features --features embassy' to build for MCU\n\
|
||||
or verify that you have not included a different feature that requires'std'"
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
pub mod core;
|
||||
|
||||
#[cfg(feature = "embassy")]
|
||||
pub mod embassy;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub mod host;
|
||||
Reference in New Issue
Block a user