Skip to main content

pamoja_kit/
lib.rs

1#![cfg_attr(not(test), no_std)]
2
3//! Goal-named helper math for the pamoja SDK.
4//!
5//! The hardest part of building something real on a cheap sensor is rarely reading
6//! the sensor; it is turning that reading into a decision that holds up in the
7//! field. `pamoja-kit` is the layer that closes that gap for people who are not
8//! signal-processing engineers. Each helper is named for the goal rather than the
9//! technique, ships with correct defaults, and documents the real algorithm one
10//! layer down, so it teaches as it abstracts.
11//!
12//! The first helpers cover the jobs the cookbook leans on most:
13//!
14//! - [`Smoother`] - smooth a noisy reading (exponential moving average).
15//! - [`Kalman`] - settle to a steady value from a noisy sensor (one-dimensional Kalman).
16//! - [`Complementary`] - fuse a fast rate with a slow absolute reading (complementary filter).
17//! - [`Median`] - reject spikes with a rolling median (robust to a lone bad reading).
18//! - [`Debounce`] - clean a chattering on/off signal into one event (counter debounce).
19//! - [`Calibration`] - turn a raw reading into real units (two-point linear map).
20//! - [`deadband`] - ignore small wiggle around a setpoint so an actuator does not chatter.
21//! - [`Thermostat`] - keep a reading near a setpoint (on/off control with
22//!   hysteresis).
23//! - [`Pid`] - hold a value at a target with a smooth, proportional command (PID control).
24//! - [`Ramp`] - ease a command toward a target at a limited rate (slew-rate limiter).
25//! - [`Depletion`] - warn before a falling level runs out (linear extrapolation).
26//! - [`Surge`] - warn when a reading changes dangerously fast (first difference).
27//! - [`Trend`] - tell whether a value is rising or falling and how fast (least-squares slope).
28//! - [`Anomaly`] - flag a reading that departs from its recent history (three-sigma rule).
29//! - [`Window`] - keep a rolling window of recent readings and read their spread
30//!   (min, max, range, mean, population variance).
31//! - [`units`] - convert a reading to the unit a person reads (Celsius and Fahrenheit,
32//!   pascals to hPa/kPa/psi, ratio and percent).
33//! - [`DiffDrive`], [`Ackermann`], [`SkidSteer`], [`Mecanum`] - wheel kinematics for the common
34//!   differential, car-like, skid-steer, and omnidirectional chassis (behind `robotics`).
35//! - [`TwoLinkArm`] / [`forward_kinematics`] - manipulator kinematics: the planar two-link inverse,
36//!   and Denavit-Hartenberg forward kinematics for any serial arm.
37//! - [`Odometry`] - dead-reckon a [`Pose`] from a body motion or wheel deltas, exact-arc.
38//! - [`WaypointFollower`] / [`obstacle_stop`] - steer toward a waypoint and stop for an obstacle
39//!   (behind `robotics` and `geo`).
40//! - [`SafetyGate`] - the gate every motion command passes through: emergency [`EStop`], deadman
41//!   [`Watchdog`], and bounded motion ([`Limits`]).
42//! - [`ServoMap`] / [`Esc`] / [`Quadrature`] / [`QuadratureScale`] - servo and ESC pulse widths
43//!   and quadrature-encoder decoding.
44//! - [`Twist`] / [`Pose`] - the shared body-velocity and world-pose types the robotics helpers use.
45//! - [`Coordinate`] / [`Geofence`] - great-circle distance and bearing, and leaving a safe
46//!   area (behind the default `geo` feature).
47//! - [`imu`] - roll and pitch from a three-axis accelerometer (behind the `imu` feature).
48//! - [`weather`] - the dew point from temperature and humidity (behind the `weather` feature).
49//!
50//! The `geo`, `imu`, `weather`, and `robotics` features each pull in `libm` for `no_std` float
51//! math and can be turned off on the most constrained targets; the waypoint guidance needs both
52//! `robotics` and `geo`.
53//!
54//! The crate is `no_std` and allocation-free, so the same helpers run on a
55//! microcontroller and on a server.
56//!
57//! # Examples
58//!
59//! Compose two helpers to hold a noisy fridge probe near 4 C:
60//!
61//! ```
62//! use pamoja_kit::{Smoother, Thermostat};
63//!
64//! let mut probe = Smoother::new(0.5);
65//! let mut fridge = Thermostat::cooling(4.0, 0.5);
66//!
67//! // A warm, noisy reading is smoothed, then drives the cooler on.
68//! let cooler_on = fridge.update(probe.update(7.8));
69//! assert!(cooler_on);
70//! ```
71
72mod anomaly;
73mod calibration;
74mod complementary;
75mod debounce;
76mod depletion;
77mod drive;
78mod kalman;
79mod median;
80mod pid;
81mod ramp;
82mod shape;
83mod smoothing;
84mod surge;
85mod thermostat;
86mod trend;
87mod window;
88
89pub mod units;
90
91#[cfg(feature = "geo")]
92mod geo;
93
94#[cfg(feature = "imu")]
95pub mod imu;
96
97#[cfg(feature = "weather")]
98pub mod weather;
99
100#[cfg(feature = "robotics")]
101mod arm;
102#[cfg(feature = "robotics")]
103mod chassis;
104#[cfg(feature = "robotics")]
105mod drivers;
106#[cfg(feature = "robotics")]
107mod motion;
108#[cfg(all(feature = "robotics", feature = "geo"))]
109mod navigate;
110#[cfg(feature = "robotics")]
111mod odometry;
112#[cfg(feature = "robotics")]
113mod safety;
114
115pub use anomaly::Anomaly;
116pub use calibration::Calibration;
117pub use complementary::Complementary;
118pub use debounce::Debounce;
119pub use depletion::Depletion;
120pub use drive::DiffDrive;
121pub use kalman::Kalman;
122pub use median::Median;
123pub use pid::Pid;
124pub use ramp::Ramp;
125pub use shape::deadband;
126pub use smoothing::Smoother;
127pub use surge::Surge;
128pub use thermostat::Thermostat;
129pub use trend::Trend;
130pub use window::Window;
131
132#[cfg(feature = "geo")]
133pub use geo::{Boundary, Coordinate, Geofence};
134
135#[cfg(feature = "robotics")]
136pub use arm::{forward_kinematics, DhParameters, Elbow, Transform, TwoLinkArm};
137#[cfg(feature = "robotics")]
138pub use chassis::{Ackermann, Mecanum, SkidSteer, WheelSpeeds};
139#[cfg(feature = "robotics")]
140pub use drivers::{Esc, Quadrature, QuadratureScale, ServoMap};
141#[cfg(feature = "robotics")]
142pub use motion::{Pose, Twist};
143#[cfg(all(feature = "robotics", feature = "geo"))]
144pub use navigate::{obstacle_stop, Guidance, WaypointFollower};
145#[cfg(feature = "robotics")]
146pub use odometry::Odometry;
147#[cfg(feature = "robotics")]
148pub use safety::{EStop, Limits, SafetyGate, Watchdog};