control-systems-ai999x — offline, verified control systems solver with step-by-step answers

Desktop app & command line · Compute in your browser · Install (Python) · Guides · Evaluation · AI999X on Hugging Face · Website · Support: Buy Me a Coffee

License: Apache-2.0 · Author: Ibnul Jaif Farabi (creator and engineer) · Organization: AI999X · Version 1.0.0

Field: Engineering · Tasks: Question Answering, Sentence Similarity, Feature Extraction

control-systems-ai999x is an offline, deterministic Python solver that answers control systems questions with verified results from 97 certified capabilities, gives 686 documented answers identically on Windows and Linux, and refuses rather than guesses when an answer cannot be verified.

control-systems-ai999x is a compact, deterministic control systems engine for Python. It reads a question in plain English (or a typed call), picks a certified control systems capability, computes the answer exactly, checks it, and returns the result with its steps, units, LaTeX and assumptions — or an honest refusal that says what is missing. It runs fully offline on any CPU, needs no GPU, no API key and no internet, and is built to give zero wrong answers: when it is not sure, it refuses instead of guessing.

Buy me a coffee License Python Offline Rust

Run it your way. control-systems-ai999x comes as the AI999X desktop app and as the command-line program control-systems for Windows and Linux, runs in your browser as WebAssembly, and installs as a Python package. The desktop app, the command line and the browser run the same compiled Rust program on your own device: offline, no Python needed.

Get it

Way to run it For Get it
AI999X Control Systems desktop app 1.2.0 Windows, Linux — this model in its own app: search, ask in words, forms, live figures, explanations, offline Windows (x86-64) · Linux (x86-64)
AI999X desktop app 1.2.0 Windows, Linux — every AI999X model in one app: search, ask in words, forms, live figures, explanations, offline Windows (x86-64) · Linux (x86-64)
Command line (control-systems) Windows, Linux — one program per model, offline, no Python Windows (x86-64) · Linux (x86-64)
In your browser any device — nothing to install Compute on the model page
Python Python 3.10+ pip install control-systems-ai999x

Checksums: SHA256SUMS · every version: https://www.ai999x.com/downloads/desktop/latest/ · install guide: desktop & command line

Rust versions

Control Systems also comes as native programs compiled from Rust, version 1.2.0 of the AI999X desktop app and command line: they run offline on your computer and need no Python. Each file is in this repository's rust/ folder, on the GitHub release v1.0.0 and on the website.

Program System File Size Download Use
Desktop app (Control Systems) Windows x86-64 ai999x-control-systems-1.2.0-windows-x86_64.zip 7.4 MB Hub · GitHub · website unzip, then double-click ai999x-control-systems.exe (no installer)
Desktop app (Control Systems) Linux x86-64 ai999x-control-systems-1.2.0-linux-x86_64.tar.gz 8.4 MB Hub · GitHub · website extract, then run ./ai999x-control-systems (X11 or Wayland desktop)
Command line (control-systems) Windows x86-64 ai999x-control-systems-cli-1.2.0-windows-x86_64.zip 3.2 MB Hub · GitHub · website (all models) unzip, then control-systems.exe ask "<question>" or control-systems.exe solve <capability> name=value
Command line (control-systems) Linux x86-64 ai999x-control-systems-cli-1.2.0-linux-x86_64.tar.gz 3.1 MB Hub · GitHub · website (all models) extract, then ./control-systems ask "<question>" or ./control-systems solve <capability> name=value

The command-line archive holds control-systems with a README of its commands and examples, the licence and the notice. Checksums: rust/SHA256SUMS (sha256sum -c SHA256SUMS).

Quick start

Desktop app

Download AI999X Control Systems for your system (above), unpack it and start it; type a question in words or pick a capability, fill in the form and press Compute. Figures and an explanation of the answer appear beside it. The AI999X desktop app has the same, with Control Systems among all AI999X models.

Linux, from a terminal:

curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/ai999x-control-systems-1.2.0-linux-x86_64.tar.gz
curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS
tar xzf ai999x-control-systems-1.2.0-linux-x86_64.tar.gz
./ai999x-control-systems-1.2.0-linux-x86_64/ai999x-control-systems

Command line

Linux:

curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/ai999x-cli-1.2.0-linux-x86_64.tar.gz
curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS
mkdir -p ~/.local/share && tar xzf ai999x-cli-1.2.0-linux-x86_64.tar.gz -C ~/.local/share
echo 'export PATH="$HOME/.local/share/ai999x-cli-1.2.0-linux-x86_64:$PATH"' >> ~/.bashrc && source ~/.bashrc
control-systems --version

Windows (PowerShell):

$F = "ai999x-cli-1.2.0-windows-x86_64.zip"
Invoke-WebRequest "https://www.ai999x.com/downloads/desktop/1.2.0/$F" -OutFile $F
Invoke-WebRequest "https://www.ai999x.com/downloads/desktop/1.2.0/SHA256SUMS" -OutFile SHA256SUMS
(Get-FileHash $F -Algorithm SHA256).Hash.ToLower() -eq ((Select-String -SimpleMatch $F SHA256SUMS).Line -split ' ')[0]
Expand-Archive $F -DestinationPath "$env:LOCALAPPDATA\AI999X" -Force
$D = "$env:LOCALAPPDATA\AI999X\ai999x-cli-1.2.0-windows-x86_64"; $env:Path += ";$D"
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";$D", "User")
control-systems --version

Every command below was run as shown; the text under it is what the program printed.

Ask in words — Write the question as you would say it: the program reads the quantities and their units, picks the capability and answers.

$ control-systems ask "stability margins: num = [10], den = [1, 3, 2, 0]"
Read as: Gain and phase margins
gm = 0.6
gm_db = -4.436974992
w_pc = 1.414213562 rad/s
pm_deg = -12.99720802
w_gc = 1.802203305 rad/s
  by: Gain and phase margins  (crossovers as positive real roots of |N|^2 - |D|^2 and Im(N(jw) conj D(jw)), Newton-polished)
  assumes: exactly one gain crossover and one phase crossover

What a capability needs — The equation or method, every input and output with its SI unit. Read this before solve: it tells you the input names.

$ control-systems info ctrl_stability_margins
Gain and phase margins
  crossovers as positive real roots of |N|^2 - |D|^2 and Im(N(jw) conj D(jw)), Newton-polished
  in   num      numerator of the open loop L(s) (vector) []
  in   den      denominator of L(s) (vector) []
  out  gm       gain margin (ratio) []
  out  gm_db    gain margin in dB []
  out  w_pc     phase-crossover frequency [rad/s]
  out  pm_deg   phase margin in degrees []
  out  w_gc     gain-crossover frequency [rad/s]

Solve — Inputs as name=value, each with any unit of the right kind. The answer lists every output, the method used, each input converted to SI, and the conditions the answer assumes.

$ control-systems solve ctrl_stability_margins "num=[10]" "den=[1, 3, 2, 0]"
gm = 0.6
gm_db = -4.436974992
w_pc = 1.414213562 rad/s
pm_deg = -12.99720802
w_gc = 1.802203305 rad/s
  by: Gain and phase margins  (crossovers as positive real roots of |N|^2 - |D|^2 and Im(N(jw) conj D(jw)), Newton-polished)
  assumes: exactly one gain crossover and one phase crossover

Many questions at once — One JSON request per line in, one JSON answer per line out, in order: for scripts, notebooks and agents (the program starts once). In PowerShell: Get-Content cases.jsonl | control-systems batch

cases.jsonl:

{"key": "ctrl_stability_margins", "inputs": {"num": "[10]", "den": "[1, 3, 2, 0]"}}
{"key": "ctrl_routh_hurwitz", "inputs": {"coefficients": "[1, 2, 3, 4, 5]"}}
$ control-systems batch < cases.jsonl
{"outcome":"SOLVED","message":"","value":-12.9972080155,"unit":"","solved_for":"pm_deg","values":[["gm",0.6,""],["gm_db",-4.43697499233,""],["w_pc",1.41421356237,"rad/s"],["pm_deg",-12.9972080155,""],["w_gc",1.80220330461,"rad/s"]],"target":"pm_deg","phrase":"gain margin (ratio)","assumptions":["exactly one gain crossover and one phase crossover"],"name":"Gain and phase margins","equation":"crossovers as positive real roots of |N|^2 - |D|^2 and Im(N(jw) conj D(jw)), Newton-polished"}
{"outcome":"SOLVED","message":"","value":2.0,"unit":"","solved_for":"rhp_roots","values":[["first_column",[1.0,2.0,1.0,-6.0,5.0],""],["rhp_roots",2,""],["stable",false,""]],"target":"rhp_roots","phrase":"first column of the Routh array","assumptions":["no zero in the first column (special cases are refused)"],"name":"Routh-Hurwitz stability test","equation":"Routh array in exact fractions; sign changes of the first column"}

In your browser

Open Control Systems on ai999x.com, choose a capability and press Compute: the model runs on your own device as WebAssembly; nothing is sent anywhere. Change any input (any unit of the right kind) and the answer, its explanation and the figures follow.

In your own page: control_systems_ai999x.wasm and the loader ax-wasm.js (https://www.ai999x.com/compute/rust/ax-wasm.js).

Python

pip install control-systems-ai999x

Worked examples in every form

The same worked example from the command line, from Python and in the browser. Each command-line output is what the program printed.

Lag compensator placement

C(s) = (s + z)/(s + p) with z = w_c/ratio (default a decade below the crossover) and p = z/beta: zero, pole, DC gain beta, and the phase lag and gain it adds at w_c.

Command line:

$ control-systems solve ctrl_lag_design beta=10 w_c=1
zero = 0.1
pole = 0.01
dc_gain = 10
phase_deg = -5.13765444
magnitude_db = 0.04277946506
  by: Lag compensator placement  (zero a decade below crossover, pole beta times lower)
  beta = 10
  w_c = 1
  assumes: beta > 1; ratio >= 2

Python:

import control_systems_ai999x as m

a = m.solve("ctrl_lag_design", beta="10", w_c="1")
print(a.values or (a.value, a.unit))

Browser: open this capability on the model page and press Compute in your browser.

Lead compensator design for a required phase lead

alpha = (1 - sin phi)/(1 + sin phi) and T = 1/(w_m sqrt(alpha)) so that C(s) = (T s + 1)/(alpha T s + 1) adds the phase lead phi at w_m; its zero, pole and gain at w_m.

Command line:

$ control-systems solve ctrl_lead_design phi_max_deg=30 w_m=1
alpha = 0.3333333333
T = 1.732050808 s
zero = 0.5773502692
pole = 1.732050808
gain_db = 4.771212547
  by: Lead compensator design for a required phase lead  (sin phi_max = (1 - alpha)/(1 + alpha), w_m = 1/(T sqrt(alpha)))
  phi_max_deg = 30
  w_m = 1
  assumes: 0 < phi < 90 degrees; w_m > 0

Python:

import control_systems_ai999x as m

a = m.solve("ctrl_lead_design", phi_max_deg="30", w_m="1")
print(a.values or (a.value, a.unit))

Browser: open this capability on the model page and press Compute in your browser.

Maximum phase lead of a lead compensator

For C(s) = (s + z)/(s + p) with z < p: the maximum phase lead asin((p - z)/(p + z)), the frequency sqrt(z p) where it occurs, alpha = z/p and the gain there, 10 log10(z/p) dB.

Command line:

$ control-systems solve ctrl_lead_max_phase z=1 p=9
phi_max_deg = 53.13010235
w_max = 3 rad/s
alpha = 0.1111111111
magnitude_db = -9.542425094
  by: Maximum phase lead of a lead compensator  (stationary point of the phase)
  z = 1
  p = 9
  assumes: 0 < z < p

Python:

import control_systems_ai999x as m

a = m.solve("ctrl_lead_max_phase", z="1", p="9")
print(a.values or (a.value, a.unit))

Browser: open this capability on the model page and press Compute in your browser.

Desired closed-loop poles from overshoot and settling time

zeta from the overshoot, sigma = 4/Ts from the 2 % settling time, wn = sigma/zeta, the poles -sigma +/- j wd and the desired characteristic polynomial.

Command line:

$ control-systems solve ctrl_specs_to_poles OS=0.1630335348 Ts=2
zeta = 0.5
wn = 4 rad/s
sigma = 2
wd = 3.464101615 rad/s
char_poly = [1.0,4.0,15.9999999982]
  by: Desired closed-loop poles from overshoot and settling time  (zeta from the overshoot formula; sigma = 4/Ts)
  OS = 0.1630335348
  Ts = 2
  assumes: 0 < OS < 100 %; Ts > 0

Python:

import control_systems_ai999x as m

a = m.solve("ctrl_specs_to_poles", OS="0.1630335348", Ts="2")
print(a.values or (a.value, a.unit))

Browser: open this capability on the model page and press Compute in your browser.

Documentation

Highlights

  • Verified, not generated. Every answer is computed by a certified control systems capability and checked (substituted back, dimension-checked or compared with an independent computation) before it is returned.
  • Zero wrong answers by design. Seven explicit outcomes — SOLVED, NEEDS_INPUT, AMBIGUOUS, INVALID_INPUT, OUT_OF_SCOPE, UNRECOGNIZED_FORMAT, INTERNAL_ERROR — never a silent guess. Every one of its 686 documented answers is reproduced exactly on every tested platform.
  • Plain-English questions and a guaranteed typed interface. ask() reads documented question forms; solve(capability_id, **inputs) always solves a supported task with valid inputs.
  • Explains itself. Steps, formulas in LaTeX, units, assumptions and the model used, ready for notebooks, tutoring apps and homework checkers.
  • Native and in the browser. Every capability also computes natively in Rust: the desktop app and the control-systems command line for Windows and Linux, and WebAssembly on the model page — no Python, no network.
  • Small and portable. Pure Python (sympy, mpmath); identical answers on Windows and Linux (Python 3.10, 3.11, 3.12, 3.13, 3.14).
  • Coverage: transfer functions, time and frequency response, stability margins, root locus, state space, LQR, Kalman filters, discretization and PID tuning.

Model overview

Property Value
Package control-systems-ai999x 1.0.0 (import control_systems_ai999x)
Type Deterministic neuro-symbolic control systems engine (rule-based reading + certified symbolic capabilities)
Capabilities 97 certified procedures
Knowledge pack version 1.0.0
Golden answers 686 documented answers, identical on every tested platform
Platforms tested Windows (Python 3.13), Linux x86-64 (Python 3.10, 3.11, 3.12, 3.13, 3.14)
Runtime CPU only, offline; no GPU, no network, no API key
License Apache-2.0
Creator / engineer Ibnul Jaif Farabi
Organization AI999X

Python quick start

pip install control-systems-ai999x
# or straight from this repository:
pip install https://huggingface.co/AI999X/control-systems-ai999x/resolve/main/dist/control_systems_ai999x-1.0.0-py3-none-any.whl
import control_systems_ai999x as control_systems

control_systems.ask("stability margins: num = [10], den = [1, 3, 2, 0]").show()
# -> SOLVED — gm = 0.6, gm_db = -4.43697, w_pc = 1.41421, pm_deg = -12.9972  (ctrl_stability_margins)
control_systems.ask("Routh-Hurwitz: coefficients = [1, 2, 3, 4, 5]").show()
# -> SOLVED — first_column = [1.0, 2.0, 1.0, -6.0, 5.0], rhp_roots = 2, stable = 0  (ctrl_routh_hurwitz)
control_systems.solve("ctrl_percent_overshoot", zeta=0.5).show()
# -> SOLVED — PO = 16.3034, Mp = 0.163034, pole_angle_deg = 60  (ctrl_percent_overshoot)
control_systems.solve("ctrl_lqr", A=[[0, 1], [0, 0]], B=[0, 1], Q=[[1, 0], [0, 1]], R=1).show()
# -> SOLVED — K = [1.0, 1.73205080757], P = [[1.73205080757, 1.0], [1.0, 1.73205080757]], poles = [(-0.866025403784-0.5j), (-0.866025403784+0.5j)]  (ctrl_lqr)
control_systems.ask("Tustin discretization: num = [1], den = [1, 1], T = 0.1").show()
# -> SOLVED — numz = [0.047619047619, 0.047619047619], denz = [1.0, -0.904761904762]  (ctrl_tustin)
control_systems.ask("Who created you?").message
# -> control-systems-ai999x was created and engineered by Ibnul Jaif Farabi at AI999X.

The Python package also installs a Python command, control-systems-ai999x "<question>"; for the native program use control-systems (above). The outputs above were produced by running this exact code on control-systems-ai999x 1.0.0.

How every answer is verified

  1. Reading — the question is turned into typed quantities (value, unit, kind, role) and one asked quantity; every stated number must be used or the question is refused.
  2. Planning — only certified capabilities may answer; a capability applies only under the conditions the wording states (for example a pendulum, a liquid at rest, boiling).
  3. Computing — exact symbolic or high-precision numeric evaluation.
  4. Checking — dimensions, substitution back into the defining equation, and agreement between independent readings; any disagreement becomes a refusal, never a number.

Capabilities are certified before they ship: each must reproduce hand-worked reference cases, reject a deliberately wrong variant (a control), and leave every benchmark answer unchanged.

Python worked examples, with their steps

Each question was put to control-systems-ai999x; the answer is the one it returned, with the steps it took.

Gain and phase margins · Stability

stability margins: num = [10], den = [1, 3, 2, 0]

→ gm = 0.6, gm_db = -4.436974992, w_pc = 1.414213562 rad/s, pm_deg = -12.99720802, w_gc = 1.802203305 rad/s

Steps
  • Gain and phase margins: num = [10], den = [1, 3, 2, 0] → gm = 0.6, gm_db = -4.436974992, w_pc = 1.414213562 rad/s, pm_deg = -12.99720802, w_gc = 1.802203305 rad/s

Routh-Hurwitz stability test · Stability

Routh-Hurwitz: coefficients = [1, 2, 3, 4, 5]

→ first_column = [1, 2, 1, -6, 5], rhp_roots = 2, stable = False

Steps
  • Routh-Hurwitz stability test: coefficients = [1, 2, 3, 4, 5] → first_column = [1, 2, 1, -6, 5], rhp_roots = 2, stable = False

Percent overshoot from the damping ratio · Time response

m.solve("ctrl_percent_overshoot", zeta=0.5)

→ PO = 16.30335348, Mp = 0.1630335348, pole_angle_deg = 60

Steps
  • Percent overshoot from the damping ratio: zeta = 0.5 → PO = 16.30335348, Mp = 0.1630335348, pole_angle_deg = 60

Continuous-time LQR gain (Riccati equation) · Optimal control

m.solve("ctrl_lqr", A=[[0, 1], [0, 0]], B=[0, 1], Q=[[1, 0], [0, 1]], R=1)

→ K = [1, 1.732050808], P = [[1.732050808, 1], [1, 1.732050808]], poles = [-0.8660254038-0.5i, -0.8660254038+0.5i]

Steps
  • Continuous-time LQR gain (Riccati equation): A = [0 1; 0 0], B = [0, 1], Q = [1 0; 0 1], R = 1 → K = [1, 1.732050808], P = [[1.732050808, 1], [1, 1.732050808]], poles = [-0.8660254038-0.5i, -0.8660254038+0.5i]

Tustin (bilinear) discretization · Discretization

Tustin discretization: num = [1], den = [1, 1], T = 0.1

→ numz = [0.04761904762, 0.04761904762], denz = [1, -0.9047619048]

Steps
  • Tustin (bilinear) discretization: num = [1], den = [1, 1], T = 0.1 → numz = [0.04761904762, 0.04761904762], denz = [1, -0.9047619048]

Lag compensator placement · Compensators

lag compensator design: beta = 10, w_c = 1

→ zero = 0.1, pole = 0.01, dc_gain = 10, phase_deg = -5.13765444, magnitude_db = 0.04277946506

Steps
  • Lag compensator placement: beta = 10, w_c = 1 → zero = 0.1, pole = 0.01, dc_gain = 10, phase_deg = -5.13765444, magnitude_db = 0.04277946506

Figures

Every point was computed by control-systems-ai999x.

Lag compensator placement

Lag compensator placement — computed by control-systems-ai999x

phase_deg (phase added at w_c in degrees (negative)) against beta (required low-frequency gain increase (> 1)), with w_c = 1. 31 points computed by control-systems-ai999x; marked: beta = 10, phase_deg = -5.13765.

Desired closed-loop poles from overshoot and settling time

Desired closed-loop poles from overshoot and settling time — computed by control-systems-ai999x

wn (natural frequency) against OS (maximum overshoot (write 10% or 0.1)), with Ts = 2. 31 points computed by control-systems-ai999x; marked: OS = 0.163034, wn = 4 rad/s.

Percent overshoot from the damping ratio

Percent overshoot from the damping ratio — computed by control-systems-ai999x

PO (percent overshoot (%)) against zeta (damping ratio (0 <= zeta < 1)). 31 points computed by control-systems-ai999x; marked: zeta = 0.5, PO = 16.3034.

Mapping an s-plane pole to the z-plane (z = e^{sT})

Mapping an s-plane pole to the z-plane (z = e^{sT}) — computed by control-systems-ai999x

z_mag (|z| = e^{s_re T}) against s_re (real part of the s-plane pole (1/s)), with T = 0.1, s_im = 0. 31 points computed by control-systems-ai999x; marked: s_re = -2, z_mag = 0.818731.

Capabilities

97 certified procedures. A few of them:

  • Procedures: -3 dB bandwidth of a transfer function; Backward Euler (backward difference) discretization; Bandwidth of a standard second-order system; Bode magnitude and phase at one frequency; Closed-loop poles of a PID loop; Closed-loop poles under state feedback u = -K x; Closed-loop transfer function of a feedback loop; Cohen-Coon tuning of a first-order-plus-dead-time process; Continuous Lyapunov equation; Continuous equivalent of a discrete pole (s = ln z / T); Continuous-time LQR gain (Riccati equation); Controllability Gramian; Controllability matrix and rank; Controllable canonical form of a transfer function; DC gain and final value of a discrete transfer function; DC gain and final value of a step response; DC gain of a state-space model; Damping ratio from percent overshoot; Damping ratio from the logarithmic decrement; Deadbeat state feedback (discrete time); Desired closed-loop poles from overshoot and settling time; Discrete Lyapunov equation; Discrete PID in velocity (incremental) form; Discrete-time LQR gain (discrete Riccati equation) …

control_systems_ai999x.templates() lists every question form ask() reads; the capability guide (PDF, every example executed) is included in this repository.

All 97 formulas

Show every formula, by topic

PID tuning / Cohen-Coon

Cohen-Coon tuning of a first-order-plus-dead-time process

PID: Kp=τKθ(43+θ4τ),  Ti=θ32+6θ/τ13+8θ/τ,  Td=4θ11+2θ/τ \text{PID: } K_p = \frac{\tau}{K\theta}\left(\frac{4}{3} + \frac{\theta}{4\tau}\right),\; T_i = \theta\frac{32+6\theta/\tau}{13+8\theta/\tau},\; T_d = \frac{4\theta}{11+2\theta/\tau}

PID tuning / SIMC

SIMC (Skogestad) PI tuning

Kp=τK(τc+θ),  Ti=min⁡(τ,4(τc+θ)) K_p = \frac{\tau}{K(\tau_c+\theta)},\; T_i = \min(\tau, 4(\tau_c+\theta))

PID tuning / Ziegler-Nichols

Ziegler-Nichols tuning from a plant model

Ku=1∣G(jω180)∣,Pu=2πω180 K_u = \frac{1}{\vert G(j\omega_{180})\vert },\quad P_u = \frac{2\pi}{\omega_{180}}

Ziegler-Nichols tuning from the process reaction curve

PID: Kp=1.2 TKL,  Ti=2L,  Td=0.5L \text{PID: } K_p = \frac{1.2\,T}{KL},\; T_i = 2L,\; T_d = 0.5L

Ziegler-Nichols tuning from the ultimate gain and period

PID: Kp=0.6Ku,  Ti=Pu/2,  Td=Pu/8 \text{PID: } K_p = 0.6K_u,\; T_i = P_u/2,\; T_d = P_u/8

PID tuning / closed loop

Closed-loop poles of a PID loop

sD(s)+(Kds2+Kps+Ki)N(s)=0 sD(s) + (K_ds^2 + K_ps + K_i)N(s) = 0

PID tuning / forms

PID: parallel gains to standard form

Ti=Kp/Ki,Td=Kd/Kp T_i = K_p/K_i,\quad T_d = K_d/K_p

PID: standard form to parallel gains

Ki=Kp/Ti,Kd=KpTd K_i = K_p/T_i,\quad K_d = K_pT_d

PID tuning / pole placement

PI gains placing the closed-loop poles of a first-order plant

Kp=2ζωnτ−1K,Ki=ωn2τK K_p = \frac{2\zeta\omega_n\tau - 1}{K},\quad K_i = \frac{\omega_n^2\tau}{K}

Compensators / lag

Lag compensator placement

C(s)=s+zs+z/β,z=ωc/10 C(s) = \frac{s + z}{s + z/\beta},\quad z = \omega_c/10

Compensators / lead

Lead compensator design for a required phase lead

α=1−sin⁡ϕm1+sin⁡ϕm,T=1ωmα \alpha = \frac{1-\sin\phi_m}{1+\sin\phi_m},\quad T = \frac{1}{\omega_m\sqrt\alpha}

Maximum phase lead of a lead compensator

sin⁡ϕmax=p−zp+z=1−α1+α,ωm=zp \sin\phi_{max} = \frac{p-z}{p+z} = \frac{1-\alpha}{1+\alpha},\quad \omega_m = \sqrt{zp}

Design / specifications

Desired closed-loop poles from overshoot and settling time

ζ=−ln⁡OSπ2+ln⁡2OS,σ=4Ts,ωn=σζ \zeta = \frac{-\ln OS}{\sqrt{\pi^2+\ln^2 OS}},\quad \sigma = \frac{4}{T_s},\quad \omega_n = \frac{\sigma}{\zeta}

Discretization / Euler

Backward Euler (backward difference) discretization

s←z−1Tz s \leftarrow \frac{z-1}{Tz}

Forward Euler (forward difference) discretization

s←z−1T s \leftarrow \frac{z-1}{T}

Discretization / FOH

First-order-hold (triangle-hold) discretization

Bd=Γ1−Γ2+ΦΓ2,Dd=D+CΓ2 B_d = \Gamma_1 - \Gamma_2 + \Phi\Gamma_2,\quad D_d = D + C\Gamma_2

Discretization / Tustin

Tustin (bilinear) discretization

s←2T z−1z+1 s \leftarrow \frac{2}{T}\,\frac{z-1}{z+1}

Tustin discretization with frequency prewarping

s←ωtan⁡(ωT/2) z−1z+1 s \leftarrow \frac{\omega}{\tan(\omega T/2)}\,\frac{z-1}{z+1}

Discretization / ZOH

Zero-order-hold discretization of a first-order system

G(z)=K(1−e−T/τ)z−e−T/τ G(z) = \frac{K(1 - e^{-T/\tau})}{z - e^{-T/\tau}}

Zero-order-hold discretization of a transfer function

Ad=eAT,  Bd=∫0TeAτdτ B A_d = e^{AT},\; B_d = \int_0^T e^{A\tau}d\tau\,B

Discretization / digital PID

Discrete PID in velocity (incremental) form

Δuk=(Kp+KiT+KdT)ek−(Kp+2KdT)ek−1+KdTek−2 \Delta u_k = (K_p + K_iT + \tfrac{K_d}{T})e_k - (K_p + \tfrac{2K_d}{T})e_{k-1} + \tfrac{K_d}{T}e_{k-2}

Discretization / discrete systems

DC gain and final value of a discrete transfer function

y(∞)=A G(1) y(\infty) = A\,G(1)

Step response of a discrete transfer function at sample k

y[k]=∑ibiu[k−i]−∑i≥1aiy[k−i] y[k] = \sum_{i} b_i u[k-i] - \sum_{i\ge 1} a_i y[k-i]

Discretization / pole mapping

Continuous equivalent of a discrete pole (s = ln z / T)

s=ln⁡zT s = \frac{\ln z}{T}

Mapping an s-plane pole to the z-plane (z = e^{sT})

z=esT=eσT∠ ωT z = e^{sT} = e^{\sigma T}\angle\,\omega T

Estimation / Kalman filter

One step of a scalar Kalman filter

K=P−P−+r,x^=x^−+K(z−x^−),P=(1−K)P− K = \frac{P^-}{P^- + r},\quad \hat x = \hat x^- + K(z - \hat x^-),\quad P = (1-K)P^-

Steady-state Kalman-Bucy filter gain

AP+PAT−PCTV−1CP+W=0,L=PCTV−1 AP + PA^T - PC^TV^{-1}CP + W = 0,\quad L = PC^TV^{-1}

Steady-state discrete Kalman filter gain

P=APAT−APCT(CPCT+R)−1CPAT+Q,K=PCT(CPCT+R)−1 P = APA^T - APC^T(CPC^T + R)^{-1}CPA^T + Q,\quad K = PC^T(CPC^T + R)^{-1}

Steady-state gain of a scalar Kalman filter

P=a2P−a2c2P2c2P+r+q,K=Pcc2P+r P = a^2P - \frac{a^2c^2P^2}{c^2P + r} + q,\quad K = \frac{Pc}{c^2P + r}

Frequency response / Bode

Bode magnitude and phase at one frequency

∣G(jω)∣dB=20log⁡10∣G(jω)∣ \vert G(j\omega)\vert _{dB} = 20\log_{10}\vert G(j\omega)\vert

Frequency response of a first-order lag

∣G(jω)∣=K1+ω2τ2,∠G=−arctan⁡(ωτ) \vert G(j\omega)\vert = \frac{K}{\sqrt{1+\omega^2\tau^2}},\quad \angle G = -\arctan(\omega\tau)

Frequency response of a standard second-order system

∣G∣=ωn2(ωn2−ω2)2+(2ζωnω)2 \vert G\vert = \frac{\omega_n^2}{\sqrt{(\omega_n^2-\omega^2)^2 + (2\zeta\omega_n\omega)^2}}

Frequency response / bandwidth

-3 dB bandwidth of a transfer function

∣G(jωB)∣=∣G(0)∣2 \vert G(j\omega_B)\vert = \frac{\vert G(0)\vert }{\sqrt 2}

Bandwidth of a standard second-order system

ωB=ωn1−2ζ2+4ζ4−4ζ2+2 \omega_B = \omega_n\sqrt{1-2\zeta^2+\sqrt{4\zeta^4-4\zeta^2+2}}

Frequency response / norms

H-infinity norm (peak gain) of a stable transfer function

vertGvert∞=sup⁡ω∣G(jω)∣ \\vert G\\vert _\infty = \sup_\omega \vert G(j\omega)\vert

H2 norm of a stable transfer function

vertGvert22=12π∫−∞∞∣G(jω)∣2dω=BTWoB \\vert G\\vert _2^2 = \frac{1}{2\pi}\int_{-\infty}^{\infty}\vert G(j\omega)\vert ^2d\omega = B^TW_oB

Frequency response / resonance

Resonant peak and resonant frequency

Mr=12ζ1−ζ2,ωr=ωn1−2ζ2 M_r = \frac{1}{2\zeta\sqrt{1-\zeta^2}},\quad \omega_r = \omega_n\sqrt{1-2\zeta^2}

Identification / FOPDT

First-order-plus-dead-time fit by Smith's two-point method

τ=1.5(t63−t28),θ=t63−τ \tau = 1.5(t_{63} - t_{28}),\quad \theta = t_{63} - \tau

Identification / second order

Damping ratio from the logarithmic decrement

δ=1nln⁡x1xn+1,ζ=δ4π2+δ2 \delta = \frac{1}{n}\ln\frac{x_1}{x_{n+1}},\quad \zeta = \frac{\delta}{\sqrt{4\pi^2+\delta^2}}

Second-order model from a step response

ωn=πTp1−ζ2 \omega_n = \frac{\pi}{T_p\sqrt{1-\zeta^2}}

Modelling / DC motor

Speed transfer function of a DC motor

Ω(s)V(s)=Kt(Js+b)(Ls+R)+Kt2 \frac{\Omega(s)}{V(s)} = \frac{K_t}{(Js+b)(Ls+R)+K_t^2}

Optimal control / LQR

Continuous-time LQR gain (Riccati equation)

ATP+PA−PBR−1BTP+Q=0,K=R−1BTP A^TP + PA - PBR^{-1}B^TP + Q = 0,\quad K = R^{-1}B^TP

Discrete-time LQR gain (discrete Riccati equation)

P=ATPA−ATPB(R+BTPB)−1BTPA+Q P = A^TPA - A^TPB(R + B^TPB)^{-1}B^TPA + Q

LQR for a first-order system

2aP−b2P2r+q=0,K=bPr 2aP - \frac{b^2P^2}{r} + q = 0,\quad K = \frac{bP}{r}

Root locus / asymptotes

Root-locus asymptotes (centroid and angles)

σa=∑pi−∑zjn−m,θk=(2k+1)180∘n−m \sigma_a = \frac{\sum p_i - \sum z_j}{n-m},\quad \theta_k = \frac{(2k+1)180^\circ}{n-m}

Root locus / breakaway points

Root-locus breakaway and break-in points

dKds=0  ⟺  ND′−N′D=0 \frac{dK}{ds} = 0 \iff N D' - N' D = 0

Root locus / departure and arrival angles

Root-locus angle of arrival at a complex zero

θa=180∘+∑∠(z−pj)−∑i≠∠(z−zi) \theta_a = 180^\circ + \sum\angle(z - p_j) - \sum_{i\ne}\angle(z - z_i)

Root-locus angle of departure from a complex pole

θd=180∘+∑∠(p−zi)−∑j≠∠(p−pj) \theta_d = 180^\circ + \sum\angle(p - z_i) - \sum_{j\ne}\angle(p - p_j)

Root locus / magnitude and angle criteria

Root-locus gain and angle at a test point

K=1∣G(s0)∣,∠G(s0)=±180∘ K = \frac{1}{\vert G(s_0)\vert },\quad \angle G(s_0) = \pm 180^\circ

Stability / Lyapunov

Continuous Lyapunov equation

ATP+PA+Q=0 A^TP + PA + Q = 0

Discrete Lyapunov equation

ATPA−P+Q=0 A^TPA - P + Q = 0

Stability / Nyquist

Nyquist criterion: encirclements of -1

Z=N+P Z = N + P

Stability / Routh-Hurwitz

Range of gain for closed-loop stability (Routh, j-omega crossing)

D(jω)+KN(jω)=0 D(j\omega) + K N(j\omega) = 0

Routh-Hurwitz stability test

bi=a1a0,i+1−a0a1,i+1a1 b_i = \frac{a_1a_{0,i+1} - a_0a_{1,i+1}}{a_1}

Stability / discrete

Jury (Schur-Cohn) stability test for a discrete polynomial

∣an∣<a0,  P(1)>0,  (−1)nP(−1)>0 \vert a_n\vert < a_0,\; P(1) > 0,\; (-1)^nP(-1) > 0

Stability / margins

Gain and phase margins

GM=1∣L(jωpc)∣,PM=180∘+∠L(jωgc) GM = \frac{1}{\vert L(j\omega_{pc})\vert },\quad PM = 180^\circ + \angle L(j\omega_{gc})

Stability / poles

Poles and stability of a characteristic polynomial

stable  ⟺  Re⁡pi<0  ∀i \text{stable} \iff \operatorname{Re} p_i < 0 \;\forall i

Stability / robustness

Peak sensitivity Ms and modulus margin

Ms=max⁡ω1∣1+L(jω)∣ M_s = \max_\omega \frac{1}{\vert 1 + L(j\omega)\vert }

State space / DC gain

DC gain of a state-space model

G(0)=D−CA−1B G(0) = D - CA^{-1}B

State space / Gramians

Controllability Gramian

AWc+WcAT+BBT=0 AW_c + W_cA^T + BB^T = 0

Observability Gramian

ATWo+WoA+CTC=0 A^TW_o + W_oA + C^TC = 0

State space / controllability

Controllability matrix and rank

C=[B  AB  ⋯  An−1B] \mathcal{C} = [B\;AB\;\cdots\;A^{n-1}B]

State space / conversions

Controllable canonical form of a transfer function

A=[−a1⋯−an10⋱],  B=e1 A = \begin{bmatrix}-a_1 & \cdots & -a_n\\ 1 & & 0\\ & \ddots & \end{bmatrix},\; B = e_1

Transfer function of a state-space model

G(s)=C(sI−A)−1B+D=C adj(sI−A) Bdet⁡(sI−A)+D G(s) = C(sI-A)^{-1}B + D = \frac{C\,\mathrm{adj}(sI-A)\,B}{\det(sI-A)} + D

State space / observability

Observability matrix and rank

O=[CCA⋮CAn−1] \mathcal{O} = \begin{bmatrix}C\\ CA\\ \vdots\\ CA^{n-1}\end{bmatrix}

State space / observers

Observer (estimator) gain by pole placement

L=α(A) O−1[0⋮1] L = \alpha(A)\,\mathcal{O}^{-1}\begin{bmatrix}0\\ \vdots\\ 1\end{bmatrix}

State space / pole placement

Deadbeat state feedback (discrete time)

K=[0⋯1] C−1An K = [0\cdots 1]\,\mathcal{C}^{-1}A^n

Pole placement by Ackermann's formula

K=[0⋯01]C−1α(A) K = \begin{bmatrix}0 & \cdots & 0 & 1\end{bmatrix}\mathcal{C}^{-1}\alpha(A)

State space / stability

Eigenvalues (poles) of a state matrix

det⁡(sI−A)=0 \det(sI - A) = 0

State space / state feedback

Closed-loop poles under state feedback u = -K x

det⁡(sI−A+BK)=0 \det(sI - A + BK) = 0

State space / time response

State response to an initial state and a constant input

x(t)=eAtx0+∫0teAτdτ Bu x(t) = e^{At}x_0 + \int_0^t e^{A\tau}d\tau\,Bu

State-transition matrix e^{At}

Φ(t)=eAt=∑k(At)kk! \Phi(t) = e^{At} = \sum_k \frac{(At)^k}{k!}

Steady-state error

System type, static error constant and steady-state error

ess=A1+Kp,  AKv,  AKa e_{ss} = \frac{A}{1+K_p},\; \frac{A}{K_v},\; \frac{A}{K_a}

Time delay / Pade

Pade approximation of a time delay

e−θs≈∑kck(−θs)k∑kck(θs)k e^{-\theta s} \approx \frac{\sum_k c_k(-\theta s)^k}{\sum_k c_k(\theta s)^k}

Time response / closed loop

Proportional control of a first-order plant

T(s)=KKpτs+1+KKp T(s) = \frac{KK_p}{\tau s + 1 + KK_p}

Time response / dead time

Step response of a first-order-plus-dead-time process

y(t)=KA(1−e−(t−θ)/τ) u(t−θ) y(t) = KA\left(1 - e^{-(t-\theta)/\tau}\right)\,u(t-\theta)

Time response / final and initial values

Final value theorem

y(∞)=lim⁡s→0sY(s) y(\infty) = \lim_{s\to 0} sY(s)

Initial value theorem (value and slope at t = 0+)

y(0+)=lim⁡s→∞sY(s) y(0^+) = \lim_{s\to\infty} sY(s)

Time response / first order

Step response of a first-order system

y(t)=KA(1−e−t/τ) y(t) = K A\left(1 - e^{-t/\tau}\right)

Time and frequency specifications of a first-order system

tr=τln⁡9,ts,2%=τln⁡50,ωB=1/τ t_r = \tau\ln 9,\quad t_{s,2\%} = \tau\ln 50,\quad \omega_B = 1/\tau

Time response / general

Step response of a transfer function at a given time

y(t)=C∫0teAτdτ B Au+DAu y(t) = C\int_0^t e^{A\tau}d\tau\,B\,A_u + D A_u

Time response / second order

Damping ratio from percent overshoot

ζ=−ln⁡(%OS/100)π2+ln⁡2(%OS/100) \zeta = \frac{-\ln(\%OS/100)}{\sqrt{\pi^2 + \ln^2(\%OS/100)}}

Exact settling time of a second-order step response

Ts=max⁡{t:∣y(t)−1∣=band} T_s = \max\{t : \vert y(t) - 1\vert = \text{band}\}

Mass-spring-damper natural frequency and damping ratio

ωn=k/m,ζ=c2km \omega_n = \sqrt{k/m},\quad \zeta = \frac{c}{2\sqrt{km}}

Natural frequency and damping ratio of a second-order denominator

s2+2ζωns+ωn2 s^2 + 2\zeta\omega_n s + \omega_n^2

Peak time of a second-order step response

Tp=πωn1−ζ2 T_p = \frac{\pi}{\omega_n\sqrt{1-\zeta^2}}

Percent overshoot from the damping ratio

%OS=100 e−ζπ/1−ζ2 \%OS = 100\,e^{-\zeta\pi/\sqrt{1-\zeta^2}}

Rise time of an underdamped second-order system

Tr,0−100=π−cos⁡−1ζωd T_{r,0-100} = \frac{\pi - \cos^{-1}\zeta}{\omega_d}

Second-order specifications from the pole location

ωn=σ2+ωd2,ζ=σ/ωn,%OS=100e−σπ/ωd \omega_n = \sqrt{\sigma^2+\omega_d^2},\quad \zeta = \sigma/\omega_n,\quad \%OS = 100e^{-\sigma\pi/\omega_d}

Settling time of a second-order system (rule and envelope)

Ts≈4ζωn  (2%),Ts≈3ζωn  (5%) T_s \approx \frac{4}{\zeta\omega_n}\;(2\%),\qquad T_s \approx \frac{3}{\zeta\omega_n}\;(5\%)

Step response of a standard second-order system

y(t)=1−e−ζωnt(cos⁡ωdt+ζ1−ζ2sin⁡ωdt) y(t) = 1 - e^{-\zeta\omega_n t}\left(\cos\omega_d t + \frac{\zeta}{\sqrt{1-\zeta^2}}\sin\omega_d t\right)

Transfer functions / DC gain

DC gain and final value of a step response

y(∞)=A G(0) y(\infty) = A\,G(0)

Transfer functions / block diagrams

Closed-loop transfer function of a feedback loop

T(s)=G1+GH=NGDHDGDH+NGNH T(s) = \frac{G}{1 + GH} = \frac{N_GD_H}{D_GD_H + N_GN_H}

Parallel connection of two transfer functions

G1+G2=N1D2+N2D1D1D2 G_1 + G_2 = \frac{N_1D_2 + N_2D_1}{D_1D_2}

Series (cascade) connection of two transfer functions

G(s)=G1(s)G2(s)=N1N2D1D2 G(s) = G_1(s)G_2(s) = \frac{N_1N_2}{D_1D_2}

Transfer functions / evaluation

Value of a transfer function at a complex point

G(s0)=N(s0)D(s0) G(s_0) = \frac{N(s_0)}{D(s_0)}

Transfer functions / poles and zeros

Poles, zeros and gain of a transfer function

G(s)=k ∏(s−zi)∏(s−pj) G(s) = k\,\frac{\prod (s - z_i)}{\prod (s - p_j)}

Out of scope

  • Open-ended explanation, essay writing or tutoring dialogue: it is a solver, not a chatbot.
  • Questions outside its certified control systems capabilities, and any question whose stated numbers it cannot all use — it refuses with the reason instead.
  • High-stakes engineering, medical or legal decisions without independent review.

Limitations

  • It answers what its certified capabilities cover (transfer functions, time and frequency response, stability margins, root locus, state space, LQR, Kalman filters, discretization and PID tuning); anything else is refused with a reason.
  • ask() reads documented question forms and common phrasings; unusual wording may be refused — use solve() for guaranteed results.
  • Results are as correct as the certified relations and their stated conditions; a certified relation is a checked model, not a claim about every physical situation.

Citation

@software{control_systems_ai999x_1_0_0,
  title  = {control-systems-ai999x: an offline, verified control systems solver},
  author = {Farabi, Ibnul Jaif}, organization = {AI999X},
  year   = {2026}, version = {1.0.0},
  url    = {https://huggingface.co/AI999X/control-systems-ai999x}
}

Contact

Questions, bug reports and requests: open a discussion on https://huggingface.co/AI999X/control-systems-ai999x/discussions or visit https://ai999x.com.

Support the project

control-systems-ai999x is free and open source. If it helps you, you can support further development on Buy Me a Coffee.

Created and engineered by Ibnul Jaif Farabi · AI999X · ai999x.com

Downloads last month
-
Safetensors
Model size
4.72M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Evaluation results

  • identical on every platform on Golden answers (686 documented questions, Windows + Linux Python 3.10-3.14)
    self-reported
    1.000