so2nostd 0.1.1

A robust Second-Order (SO2) controller implementation for no_std environments, protected by GPL.
Documentation

so2nostd

License: GPL-2.0-or-later No Std Maintenance

Second-Order no_std Controller for Embedded Systems

so2nostd is a lightweight, high-performance no_std Rust crate implementing a discrete-time second-order (SO2) control system. Designed for embedded environments like MCUs (e.g., RP2040), it provides stable, physics-based dynamics using Euler integration.

GPL-2.0-or-later licensed to ensure community protection against privatization. Optimized for minimal footprint and maximal reliability.

Table of Contents

πŸš€ Features

  • βœ… Pure no_std: Zero standard library dependencies, perfect for bare-metal/RTOS.
  • ⚑ Flexible Floating-Point: f64 (default) or f32 feature for memory-constrained devices.
  • πŸ”§ Size-Optimized: Compatible with opt-level="z" and LTO for tiny binary footprints.
  • πŸ›‘οΈ Numerical Safety: Robust handling of dt <= 0 to prevent system divergence.
  • πŸ“ˆ Physics-Based: Models natural frequency (Ο‰_n), damping ratio (ΞΆ), and static gain.

πŸ› οΈ Installation

Add to your Cargo.toml:

[dependencies]
so2nostd = { git = "[https://github.com/jorgeandrecastro/so2nostd.git](https://github.com/jorgeandrecastro/so2nostd.git)" }
For f32 support (Cortex-M optimization):Ini, TOMLso2nostd = { git = "[https://github.com/jorgeandrecastro/so2nostd.git](https://github.com/jorgeandrecastro/so2nostd.git)", features = ["f32"] }
πŸš€ QuickstartRustuse so2nostd::So2Controller;

fn main() {
    // w_n=10 rad/s, zeta=0.7 (underdamped), initial=0.0, gain=1.0
    let mut controller = So2Controller::new(10.0, 0.7, 0.0, 1.0);

    let dt = 0.01; // 10ms timestep
    let target = 1.0;

    // Simulate convergence
    for _ in 0..100 {
        let output = controller.update(target, dt);
        // output smoothly approaches 1.0 following SO2 dynamics
    }
}
πŸ“š API ReferenceMethodSignatureDescriptionnewnew(w_n: Float, zeta: Float, initial: Float, gain: Float)Creates a new controller. w_n: rad/s, zeta: damping.updateupdate(input: Float, dt: Float) -> FloatAdvances system state. Safe for dt <= 0.set_targetset_target(target: Float)Updates the internal setpoint.resetreset(value: Float)Hard reset of internal states to value.Note: Float is an alias for f64 (default) or f32 (with feature).

⚑ Performance & OptimizationZero Allocation: No heap usage, strictly stack-based.Predictable CPU: Constant time O(1) update cycles.Binary Size: Minimal footprint when compiled with panic = "abort" and strip = true.πŸ§ͺ TestingThe crate includes tests for:Step response stability and convergence.Zero/Negative delta time safety.Run tests with:Bashcargo test

βš–οΈ LicenseGPL-2.0-or-later Β© 2026 Jorge Andre Castro.Free to use, modify, and distribute. In accordance with the GPL, any derivative works or larger projects incorporating this code must also be released under the GPL-2.0-or-later.