3 releases
new 0.1.2 | Apr 26, 2024 |
---|---|
0.1.1 | Feb 24, 2024 |
0.1.0 | Feb 8, 2024 |
#28 in Robotics
31KB
569 lines
syunit
A small library that contains some basic units to help structuring kinematics and robotic programming in rust. The library uses rusts tuple structs to create a zero-overhead and compile-time checking of correct unit, variable and function usage.
Quick introduction
In many functions for kinematics and robotics, it sometimes becomes unclear which type of unit is desired to be used, especially when it comes to distances.
/// Relative movement
fn move_distance(dist : f32, speed : f32) {
// ...
}
/// Absolute movement
fn move_to_distance(dist : f32, speed : f32) {
// ...
}
Even if most code is not as horribly documented and uses such terrible names, nothing stops a developer from accidently plugging in an absolute distance into a function that takes a relative one. Here comes this library into play:
use syunit::*;
/// Relative movement
fn move_distance(dist : Delta, speed : Velocity) {
// ...
}
/// Absolute movement
fn move_to_distance(dist : Gamma, speed : Velocity) {
// ...
}
// Delta => Relative distance
// Gamma => Absolute distance
//
// Naming choice will be explained later
Each unit is represented by a 32bit float enclosed into a tuple struct. Why these units are helpful not only for documentation is explained in the flowing chapters:
Creation and conversion
As rust always prefers implicit syntax, so does this library. The unit types cannot be converted back to a f32
without calling into()
.
use syunit::*;
fn requires_f32(value : f32) {
// ...
}
fn requires_velocity(value : Velocity) {
// ...
}
// Every unit is created by the tuple struct constructor using a `f32` value
let gamma = Gamma(10.0);
requires_f32(gamma);
// error[E0308]: mismatched types
// | requires_f32(gamma) // ERROR! => Type `Gamma` cannot be used as `f32`
// | ------------ ^^^^^ expected `f32`, found `Gamma`
// | |
// | arguments to this function are incorrect
// |
requires_velocity(gamma);
// error[E0308]: mismatched types
// |
// | requires_f32(gamma);
// | ------------ ^^^^^ expected `Velocity`, found `Gamma`
// | |
// | arguments to this function are incorrect
// |
Naming
As the units are all named after their purpose, the context of functions, their parameters and other variables becomes clear easier. However the library does not differentiate between linear and rotary movement in terms of naming.
However there are three units for distances with different names:
Gamma
: Represents an absolute distance in the actuators "perspective", often refered to as component angle/distancePhi
: Represents an absolute distance in the machines "perspective", often refered to as mathematical angle/distance in a lot of documentations. This angle is for example used to describe the rotation of a robot joint, where theGamma
angle has an offset compared to thePhi
angle.Delta
: Represents a relative distance
Operations and automatic type evaluation
Especially with distances, a lot of operations between them are restricted, as they would fail to make any sense. For example a Gamma
distance cannot be added with either a Phi
or another Gamma
distance, as it does not make any sense to add two absolute distances. However a Delta
distance can be added to a Gamma
or Phi
distance to extend/shorten said Gamma
or Phi
distance.
use syunit::*;
let gamma = Gamma(2.0);
let phi = Phi(4.0);
let delta = Delta(1.0);
assert_eq!(gamma + delta, Gamma(3.0));
assert_eq!(phi + delta, Phi(5.0));
Also it is for example possible to subtract two absolute distances, which gives the relative Delta
distance between them.
use syunit::*;
assert_eq!(Gamma(5.0) - Gamma(3.0), Delta(2.0));
A very special unit is Time
, dividing or multipling by it often changes units.
use syunit::*;
// Travelling a distance of 6mm in 2 seconds gives a velocity of 3mm/s
assert_eq!(Delta(6.0) / Time(2.0), Velocity(3.0));
// Accelerating to a velocity of 3mm/s in 2 seconds gives an acceleration of 1.5mm/s^2
assert_eq!(Velocity(3.0) / Time(2.0), Acceleration(1.5));
// Travelling with 3mm/s for 3 seconds gives a total distance of 9mm
assert_eq!(Velocity(3.0) * Time(3.0), Delta(9.0));
Physical background
Each unit of course represents a physical unit, in almost all cases their standardized values. Only difference is distance, it is represented by millimeters. Meaning velocity becomes millimeters per second, acceleration becomes millimeters per second squared ...
serde
implementation
All the units implement serde::Serialize
and serde::Deserialize
if the "serde" feature is enabled, which is the case by default.
Issues and improvements
Please feel free to create issues on the github repo or contact me directly.
Dependencies
~0.4–1MB
~23K SLoC