Skip to main content

wls_alloc/
lib.rs

1//! Weighted least-squares (WLS) constrained control allocator.
2//!
3//! Solves `min ‖Au − b‖²` subject to `umin ≤ u ≤ umax` using an active-set
4//! method with incremental QR updates. Designed for real-time motor mixing on
5//! flight controllers: `no_std`, fully stack-allocated, const-generic over
6//! problem dimensions.
7//!
8//! # Encapsulated API (recommended)
9//!
10//! [`wls::ControlAllocator`] owns the static problem (effectiveness matrix,
11//! weights, `γ`) and the warm-start solver state. Build once, then call
12//! [`solve`](wls::ControlAllocator::solve) on every control tick.
13//!
14//! ```no_run
15//! use wls_alloc::wls::ControlAllocator;
16//! use wls_alloc::{ExitCode, VecN, MatA};
17//!
18//! // Effectiveness matrix G (6 pseudo-controls × 4 motors)
19//! let g: MatA<6, 4> = MatA::zeros(); // replace with real data
20//! let wv: VecN<6> = VecN::from_column_slice(&[10.0, 10.0, 10.0, 1.0, 0.5, 0.5]);
21//! let wu: VecN<4> = VecN::from_column_slice(&[1.0; 4]);
22//!
23//! let mut alloc = ControlAllocator::<4, 6, 10>::new(&g, &wv, wu, 2e-9, 4e5);
24//!
25//! // Per-tick solve
26//! let v: VecN<6> = VecN::zeros();
27//! let ud: VecN<4> = VecN::from_column_slice(&[0.5; 4]);
28//! let umin: VecN<4> = VecN::from_column_slice(&[0.0; 4]);
29//! let umax: VecN<4> = VecN::from_column_slice(&[1.0; 4]);
30//!
31//! let stats = alloc.solve(&v, &ud, &umin, &umax, 100);
32//! assert_eq!(stats.exit_code, ExitCode::Success);
33//! let u = alloc.solution();
34//! ```
35//!
36//! # Raw building blocks
37//!
38//! The [`raw`] module exposes the underlying free functions
39//! (`setup_a` / `setup_b` / `solve` / `solve_cls`) for advanced use: custom
40//! `A` matrices, the unregularised CLS variant, or composing pieces of the
41//! pipeline differently.
42//!
43//! ```no_run
44//! use wls_alloc::raw::{setup_a_unreg, setup_b_unreg, solve_cls};
45//! use wls_alloc::{ExitCode, VecN, MatA};
46//!
47//! let g: MatA<4, 4> = MatA::zeros();
48//! let wv: VecN<4> = VecN::from_column_slice(&[1.0; 4]);
49//!
50//! let a = setup_a_unreg::<4, 4>(&g, &wv);
51//! let v: VecN<4> = VecN::zeros();
52//! let b = setup_b_unreg(&v, &wv);
53//!
54//! let umin: VecN<4> = VecN::from_column_slice(&[0.0; 4]);
55//! let umax: VecN<4> = VecN::from_column_slice(&[1.0; 4]);
56//! let mut us: VecN<4> = VecN::from_column_slice(&[0.5; 4]);
57//! let mut ws = [0i8; 4];
58//! let stats = solve_cls::<4, 4>(&a, &b, &umin, &umax, &mut us, &mut ws, 100);
59//! assert_eq!(stats.exit_code, ExitCode::Success);
60//! ```
61
62#![no_std]
63#![warn(missing_docs)]
64
65/// Low-level linear algebra: Householder QR, back-substitution, constraint checking.
66pub mod linalg;
67/// Problem setup: convert WLS control-allocation parameters into LS form.
68pub mod setup;
69/// Active-set constrained least-squares solver.
70pub mod solver;
71/// Core types, constants, and nalgebra type aliases.
72pub mod types;
73/// High-level encapsulated WLS control allocator.
74pub mod wls;
75
76pub use types::{ExitCode, MatA, SolverStats, VecN};
77
78/// Low-level free-function building blocks. Use [`wls::ControlAllocator`] for
79/// typical flight-controller workloads; reach for `raw` when you need a custom
80/// `A`, the unregularised CLS solver, or non-standard pipeline composition.
81pub mod raw {
82    pub use crate::setup::{setup_a, setup_a_unreg, setup_b, setup_b_unreg};
83    pub use crate::solver::{solve, solve_cls};
84}
85
86pub use setup::{setup_a, setup_a_unreg, setup_b, setup_b_unreg};
87pub use solver::{solve, solve_cls};