Expand description
§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.
Macros§
- Helper macro that implements everything needed to do +,-,+=,-= operations with the unit itself
- Implements the basics for a unit
- Implements everything required to form a “derive over time like”-connection between the given units
Structs§
- Represents a change in velocity over time
- The delta distance represents a relative distance traveled by the
- Represents a certain factor between 0 and 1
- Represents a force, slowing down movement processes, eventually even overloading the component
- Represents a change in distance over time
- The gamma distance represents the actual distance traveled by the component
- Represents an inertia, slowing down movement processes
- Represents a change in acceleration over time
- The phi distance represents the mathematical distance used for calculations
- Represents a time
- Represents a change in distance over time
Enums§
- Direction of movement
- Helper error for String-Parsing
Traits§
- General marker trait for all units
Functions§
- Add two arrays of units
- Compare two unit arrays
- Helper functions to foce convert an array of phis to gammas
- Helper functions to force convert an array of gammas to phis
- Subtract two arrays of units