/** * ControlLoopTrait — PID and Model-Predictive Control (MPC) in a single trait (H2). * * ## PID controller * * Classic discrete-time PID with anti-windup integral clamping and optional * derivative filtering: * * u[k] = Kp·e[k] + Ki·Σe·dt + Kd·(e[k]-e[k-1])/dt * * Anti-windup: integral is clamped to [-iMax, iMax] every step. * Derivative filter: optional first-order low-pass on the derivative term * (d_filtered = α·d_raw + (1-α)·d_prev, α = filterCoeff ∈ (0,1]). * Output saturation: optional [outputMin, outputMax] clamp on the final u. * * ## Linear MPC (receding-horizon) * * State-space: x[k+1] = A·x[k] + B·u[k] * Objective : min Σ_{i=0}^{H-1}(x[i]^T Q x[i] + u[i]^T R u[i]) + x[H]^T Qf x[H] * Constraint : u ∈ [uMin, uMax] (element-wise, applied after unconstrained solve) * * Unconstrained horizon solution via recursive Riccati descent, then project * each u_i into [uMin, uMax]. Linear MPC is returned as the optimal first * control action u[0] from the computed horizon. * * ## Domain-neutrality * * No domain nouns appear here. The controllers apply to robotics, HVAC, * process control, animation, or any closed-loop system. * * ## Trait usage * * onAttach: resets internal state. * onEvent 'control_loop.step': * - type='pid' → PID step → result on node.__control_output. * - type='mpc' → MPC horizon solve → result on node.__control_output. * onEvent 'control_loop.reset': clears integral/derivative state. */ import type { TraitHandler } from './TraitTypes'; /** Result of a single control step. */ export interface ControlOutput { /** Computed control action. */ u: number; /** Type of controller that produced this output. */ type: 'pid' | 'mpc'; /** PID-only: proportional contribution. */ proportional?: number; /** PID-only: integral contribution (post-windup). */ integral?: number; /** PID-only: derivative contribution (post-filter). */ derivative?: number; /** MPC-only: full computed horizon [u0, u1, ..., u_{H-1}]. */ horizon?: number[]; } /** PID tuning parameters. */ export interface PIDParams { /** Proportional gain. */ Kp: number; /** Integral gain. */ Ki: number; /** Derivative gain. */ Kd: number; /** Integral anti-windup clamp (magnitude). Default: Infinity. */ iMax?: number; /** Derivative low-pass filter coefficient α ∈ (0,1]. 1 = no filter. Default: 1. */ filterCoeff?: number; /** Output lower bound. Default: -Infinity. */ outputMin?: number; /** Output upper bound. Default: +Infinity. */ outputMax?: number; } /** * Input for a PID step event (`control_loop.pid_step`). * The `type` field on the event itself is the event name; this interface * carries only the step payload. */ export interface PIDStepRequest { /** PID tuning. Falls back to config.pid when omitted. */ params?: PIDParams; /** Setpoint (reference). */ setpoint: number; /** Measured process variable. */ measurement: number; /** Time step Δt (same units as Ki/Kd). Default: 1. */ dt?: number; } /** Internal PID state (stored on the trait). */ export interface PIDState { integralAccum: number; prevError: number; prevDerivative: number; } /** Linear time-invariant state-space matrices for MPC. */ export interface MPCModel { /** State transition matrix A (n×n, row-major). */ A: number[]; /** Input matrix B (n×m, row-major). */ B: number[]; /** State dimension n. */ n: number; /** Input dimension m. */ m: number; } /** MPC tuning and horizon parameters. */ export interface MPCParams { /** State-space model. */ model: MPCModel; /** Prediction horizon. Default: 10. */ horizon?: number; /** State cost matrix Q (n×n, row-major). Default: identity. */ Q?: number[]; /** Terminal state cost matrix Qf (n×n, row-major). Default: Q. */ Qf?: number[]; /** Input cost matrix R (m×m, row-major). Default: identity. */ R?: number[]; /** Element-wise input lower bound (length m). Default: -Infinity. */ uMin?: number[]; /** Element-wise input upper bound (length m). Default: +Infinity. */ uMax?: number[]; } /** * Input for an MPC step event (`control_loop.mpc_step`). * The `type` field on the event itself is the event name; this interface * carries only the step payload. */ export interface MPCStepRequest { /** MPC parameters. Falls back to config.mpc when omitted. */ params?: MPCParams; /** Current state vector x (length n). */ state: number[]; /** Reference state trajectory (H×n, row-major). Defaults to all-zero. */ reference?: number[]; } /** Trait configuration — at least one of pid or mpc must be set to use events. */ export interface ControlLoopConfig { /** Default PID parameters (used when event omits params). */ pid?: PIDParams; /** Default MPC parameters (used when event omits params). */ mpc?: MPCParams; } /** * Discrete-time PID step. Mutates `state` in place. */ export declare function stepPid(params: PIDParams, setpoint: number, measurement: number, dt: number, state: PIDState): ControlOutput; /** * Linear MPC with receding horizon. * * Uses backward Riccati recursion to compute unconstrained optimal gains, * then projects each control input into [uMin, uMax] element-wise. * Returns the first control action u[0] as `u`, with the full horizon in * `output.horizon`. */ export declare function stepMpc(params: MPCParams, state: number[]): ControlOutput; export declare const controlLoopHandler: TraitHandler;