classic-controlling 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 classic_controlling contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: classic-controlling
3
+ Version: 0.1.0
4
+ Summary: Self-tuning ADRC, vectorized UKF, and dependency-free linear MPC — classic control algorithms in pure NumPy, with benchmarks
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 classic_controlling contributors
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+
27
+ Keywords: control,adrc,pid,mpc,kalman-filter,ukf,self-tuning
28
+ Classifier: Development Status :: 4 - Beta
29
+ Classifier: Intended Audience :: Science/Research
30
+ Classifier: License :: OSI Approved :: MIT License
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: Programming Language :: Python :: 3.9
33
+ Classifier: Programming Language :: Python :: 3.10
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Programming Language :: Python :: 3.13
37
+ Classifier: Topic :: Scientific/Engineering
38
+ Requires-Python: >=3.9
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: numpy
42
+ Requires-Dist: scipy
43
+ Provides-Extra: dev
44
+ Requires-Dist: pytest; extra == "dev"
45
+ Requires-Dist: matplotlib; extra == "dev"
46
+ Dynamic: license-file
47
+
48
+ # classic_controlling
49
+
50
+ **Self-tuning ADRC, vectorized UKF, and dependency-free MPC — classic control algorithms in pure NumPy, with benchmarks.**
51
+
52
+ ![tests](https://img.shields.io/badge/pytest-21%20passed-brightgreen)
53
+ ![python](https://img.shields.io/badge/python-%3E%3D3.9-blue)
54
+ ![license](https://img.shields.io/badge/license-MIT-green)
55
+
56
+ ![ADRC vs PID](docs/figures/adrc_vs_pid.png)
57
+
58
+ > **Zero manual tuning:** `ADRC.auto_tune()` identifies the plant and reaches steady-state <5% error on first-order, second-order and nonlinear plants — blind-tested. Above: model-tuned PID vs zero-touch ADRC on three plants, with a step load disturbance at t=20s. On the open-loop-unstable nonlinear plant the Z-N tuned PID diverges into growing oscillation; the auto-tuned ADRC just locks on.
59
+
60
+ ## Features
61
+
62
+ - **Self-tuning ADRC** (`ADRC.auto_tune`) — one step-response experiment → FOPDT identification → bandwidth selection under delay phase-margin/sampling hard-constraints. Steady-state error **0.9% / 3.2% / 1.0%** on the three blind-test plants, zero human parameters. Optional online RLS correction of b0 (experimental, off by default): rate-limited two-timescale updates, [0.3, 3.0]× rails, and automatic rollback-and-freeze if the estimate hugs a rail while tracking stagnates.
63
+ - **Vectorized UKF** — every sigma-point operation (generation, batch propagation, weighted mean/covariance rebuild) is one NumPy broadcast/einsum, no per-point Python loop: **2.2× / 6.0× / 11.2×** faster than a mathematically equivalent point-loop reference at dim_x = 2 / 8 / 32.
64
+ - **Dependency-free LinearMPC** — condensed QP compiled once, built-in OSQP-style ADMM solver with pre-factored KKT matrix, warm start over (z, s, y) cutting total iterations **1.9×** (3687 → 1935) on a constrained double integrator. No external solver (no OSQP/CVXPY) needed.
65
+
66
+ ## Quick Start
67
+
68
+ ```bash
69
+ pip install classic-controlling # or: pip install -e . from source
70
+ python -m pytest tests/ -v # 21 tests
71
+ ```
72
+
73
+ ### ADRC — 5 lines to a self-tuned loop
74
+
75
+ ```python
76
+ from classic_controlling import ADRC, FOPDTPlant
77
+
78
+ plant = FOPDTPlant(gain=1.0, time_constant=0.5, dt=0.05)
79
+ ctl = ADRC.auto_tune(plant, dt=0.05) # identify + tune, zero knobs
80
+ # (online RLS: opt-in via adaptive=True)
81
+ for _ in range(300):
82
+ u = ctl.step(r=1.0, y=plant.y)
83
+ plant.step(u)
84
+ ```
85
+
86
+ The full auto-tuning pipeline (step test → FOPDT fit → tracking → b0 adapting to a mid-run gain change), from `examples/demo_autotune.py`:
87
+
88
+ ![auto_tune process](docs/figures/autotune_process.png)
89
+
90
+ ### UKF — vectorized sigma points
91
+
92
+ ```python
93
+ import numpy as np
94
+ from classic_controlling import UKF
95
+
96
+ def fx(sigmas, dt): # (2n+1, 4) batch in, batch out
97
+ out = sigmas.copy()
98
+ out[:, 0] += dt * sigmas[:, 2]; out[:, 1] += dt * sigmas[:, 3]
99
+ return out
100
+
101
+ ukf = UKF(4, 2, 0.1, fx, hx=lambda s: s[:, :2], Q=np.eye(4)*0.01, R=np.eye(2))
102
+ ests = ukf.batch_filter(zs) # zs: (N, 2) position measurements
103
+ ```
104
+
105
+ From `examples/demo_ukf.py` — coordinated-turn tracking, RMSE 0.30 m under 0.5 m observation noise:
106
+
107
+ ![UKF tracking](docs/figures/ukf_tracking.png)
108
+
109
+ ### LinearMPC — constrained MPC without a solver dependency
110
+
111
+ ```python
112
+ import numpy as np
113
+ from classic_controlling import LinearMPC
114
+
115
+ A = np.array([[1.0, 0.1], [0.0, 1.0]]); B = np.array([[0.005], [0.1]])
116
+ mpc = LinearMPC(A, B, Q=np.eye(2), R=[[0.1]], horizon=40, u_min=-1.0, u_max=1.0)
117
+ x = np.array([3.0, 0.0])
118
+ for _ in range(120):
119
+ x = A @ x + B @ mpc.solve(x, warm_start=True)
120
+ ```
121
+
122
+ From `examples/demo_mpc.py`:
123
+
124
+ ![MPC demo](docs/figures/mpc_demo.png)
125
+
126
+ ## Benchmarks
127
+
128
+ ### Vectorized UKF vs point-loop reference
129
+
130
+ `python benchmarks/bench_ukf.py` — 1000 predict+update steps each, mathematically equivalent implementations (Python 3.13.5 / NumPy 2.3.3, Windows):
131
+
132
+ | dim_x | vectorized (s) | point-loop (s) | speedup |
133
+ |------:|---------------:|---------------:|--------:|
134
+ | 2 | 0.0392 | 0.0855 | 2.2× |
135
+ | 8 | 0.0439 | 0.2623 | 6.0× |
136
+ | 32 | 0.1079 | 1.2066 | 11.2× |
137
+
138
+ The point-loop overhead grows linearly with `2n+1` sigma points; the vectorized path is eaten by BLAS.
139
+
140
+ ### `auto_tune` blind test
141
+
142
+ Zero human parameters; the plants' true parameters are used only for assertions (`tests/test_autotune.py`, 300 closed-loop steps at dt=0.05):
143
+
144
+ | plant | model | steady-state error |
145
+ |---|---|---:|
146
+ | FOPDT | `0.5·ẏ + y = u` | 0.89% |
147
+ | second-order underdamped | `ζ=0.5, ωn=3` | 3.21% |
148
+ | nonlinear, open-loop unstable | `ÿ = -ẏ + u + 0.5y²` | 1.03% |
149
+
150
+ ### MPC warm start
151
+
152
+ Constrained double integrator, horizon 40, 120 closed-loop steps (`examples/demo_mpc.py`):
153
+
154
+ | | total ADMM iters | mean iters/step |
155
+ |---|---:|---:|
156
+ | cold start | 3687 | 30.7 |
157
+ | warm start | 1935 | 16.1 |
158
+ | **speedup** | **1.9×** | **1.9×** |
159
+
160
+ ### ADRC.auto_tune vs model-tuned PID
161
+
162
+ Step tracking `r=1` with a step load disturbance at t=20s (`examples/demo_adrc_vs_pid.py`; PID tuned from the *same* step-test data via Ziegler-Nichols reaction-curve rules, IMC-PI fallback when the identified delay ≈ 0):
163
+
164
+ | plant | controller | overshoot | settling (s) | disturbance recovery (s) | IAE |
165
+ |---|---|---:|---:|---:|---:|
166
+ | FOPDT | PID (IMC-PI) | 0.0% | 0.40 | 0.55 | 0.15 |
167
+ | FOPDT | ADRC | 0.0% | 12.45 | 6.25 | 4.12 |
168
+ | 2nd-order | PID (Z-N) | 6.7% | 2.05 | 1.05 | 0.51 |
169
+ | 2nd-order | ADRC | 0.0% | 17.05 | 6.35 | 5.06 |
170
+ | nonlinear | PID (Z-N) | 757% | — | ∞ | 170.86 |
171
+ | nonlinear | ADRC | 20.1% | 13.20 | 3.55 | 2.89 |
172
+
173
+ Honest read: on well-behaved LTI plants a model-tuned PID is faster — ADRC's auto-bandwidth trades speed for guarantees (the delay phase-margin cap is calibrated against measured divergence, not folklore). The trade: ADRC never rings, needs zero expertise, and is the only one left standing on the open-loop-unstable nonlinear plant.
174
+
175
+ ## Examples
176
+
177
+ ```bash
178
+ python examples/demo_adrc_vs_pid.py # hero comparison + metrics table
179
+ python examples/demo_autotune.py # auto_tune pipeline end-to-end
180
+ python examples/demo_mpc.py # constrained MPC + warm-start speedup
181
+ python examples/demo_ukf.py # coordinated-turn tracking
182
+ ```
183
+
184
+ All figures are written to `docs/figures/`.
185
+
186
+ ## Project layout
187
+
188
+ ```
189
+ classic_controlling/ # the package
190
+ ├── adrc.py # linear ADRC (bandwidth tuning + auto_tune + RLS b0 adaptation)
191
+ ├── autotune.py # step-response FOPDT identification + automatic bandwidth selection
192
+ ├── sim.py # virtual plants (FOPDT / 2nd-order / nonlinear), reset()/step(u) protocol
193
+ ├── ukf.py # vectorized UKF
194
+ └── mpc.py # LinearMPC (condensed QP + built-in ADMM + warm start)
195
+ tests/ # 21 pytest tests (blind auto-tune assertions, SLSQP cross-check, ...)
196
+ benchmarks/bench_ukf.py # UKF vectorized vs point-loop benchmark
197
+ examples/ # runnable demos -> docs/figures/*.png
198
+ research/ # background research notes (Chinese)
199
+ ```
200
+
201
+ ## 中文简介
202
+
203
+ 三个经典控制/估计算法的高质量纯 NumPy 实现:
204
+
205
+ - **自整定 ADRC**:`ADRC.auto_tune(plant, dt)` 一键完成阶跃辨识 → FOPDT 拟合 → 带宽自动选择(时滞相位裕量帽 + 采样硬约束),全程零人工调参;一阶/二阶/非线性三个对象盲测稳态误差 0.9% / 3.2% / 1.0%。在线 RLS 修正 b0 为 experimental 可选项(默认关闭):限速双时间尺度更新 + [0.3, 3.0]× 护栏 + 贴护栏停滞自动回退冻结;
206
+ - **向量化 UKF**:sigma 点操作全部 NumPy 广播一次完成,无逐点循环,相比等价逐点实现加速 2.2× / 6.0× / 11.2×(dim 2/8/32);
207
+ - **轻量线性 MPC**:稠密式 QP 编译一次 + 内置 OSQP 风格 ADMM 求解器 + (z, s, y) 热启动(总迭代数减 1.9×),零外部求解器依赖。
208
+
209
+ 快速开始:
210
+
211
+ ```bash
212
+ pip install -e .
213
+ python -m pytest tests/ -v # 21 项测试
214
+ python examples/demo_adrc_vs_pid.py # 核心对比演示,出图到 docs/figures/
215
+ ```
216
+
217
+ ## Roadmap
218
+
219
+ - Upstream the vectorized UKF sigma-point path as a PR to `filterpy`
220
+ - Optional Numba backend for the MPC ADMM iterations (per-iteration cost → microseconds)
221
+ - More virtual plant types (integrating, oscillatory, MIMO) and ADRC tracking of time-varying references
222
+
223
+ ## License
224
+
225
+ MIT — see [LICENSE](LICENSE). Contributions welcome: [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -0,0 +1,178 @@
1
+ # classic_controlling
2
+
3
+ **Self-tuning ADRC, vectorized UKF, and dependency-free MPC — classic control algorithms in pure NumPy, with benchmarks.**
4
+
5
+ ![tests](https://img.shields.io/badge/pytest-21%20passed-brightgreen)
6
+ ![python](https://img.shields.io/badge/python-%3E%3D3.9-blue)
7
+ ![license](https://img.shields.io/badge/license-MIT-green)
8
+
9
+ ![ADRC vs PID](docs/figures/adrc_vs_pid.png)
10
+
11
+ > **Zero manual tuning:** `ADRC.auto_tune()` identifies the plant and reaches steady-state <5% error on first-order, second-order and nonlinear plants — blind-tested. Above: model-tuned PID vs zero-touch ADRC on three plants, with a step load disturbance at t=20s. On the open-loop-unstable nonlinear plant the Z-N tuned PID diverges into growing oscillation; the auto-tuned ADRC just locks on.
12
+
13
+ ## Features
14
+
15
+ - **Self-tuning ADRC** (`ADRC.auto_tune`) — one step-response experiment → FOPDT identification → bandwidth selection under delay phase-margin/sampling hard-constraints. Steady-state error **0.9% / 3.2% / 1.0%** on the three blind-test plants, zero human parameters. Optional online RLS correction of b0 (experimental, off by default): rate-limited two-timescale updates, [0.3, 3.0]× rails, and automatic rollback-and-freeze if the estimate hugs a rail while tracking stagnates.
16
+ - **Vectorized UKF** — every sigma-point operation (generation, batch propagation, weighted mean/covariance rebuild) is one NumPy broadcast/einsum, no per-point Python loop: **2.2× / 6.0× / 11.2×** faster than a mathematically equivalent point-loop reference at dim_x = 2 / 8 / 32.
17
+ - **Dependency-free LinearMPC** — condensed QP compiled once, built-in OSQP-style ADMM solver with pre-factored KKT matrix, warm start over (z, s, y) cutting total iterations **1.9×** (3687 → 1935) on a constrained double integrator. No external solver (no OSQP/CVXPY) needed.
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ pip install classic-controlling # or: pip install -e . from source
23
+ python -m pytest tests/ -v # 21 tests
24
+ ```
25
+
26
+ ### ADRC — 5 lines to a self-tuned loop
27
+
28
+ ```python
29
+ from classic_controlling import ADRC, FOPDTPlant
30
+
31
+ plant = FOPDTPlant(gain=1.0, time_constant=0.5, dt=0.05)
32
+ ctl = ADRC.auto_tune(plant, dt=0.05) # identify + tune, zero knobs
33
+ # (online RLS: opt-in via adaptive=True)
34
+ for _ in range(300):
35
+ u = ctl.step(r=1.0, y=plant.y)
36
+ plant.step(u)
37
+ ```
38
+
39
+ The full auto-tuning pipeline (step test → FOPDT fit → tracking → b0 adapting to a mid-run gain change), from `examples/demo_autotune.py`:
40
+
41
+ ![auto_tune process](docs/figures/autotune_process.png)
42
+
43
+ ### UKF — vectorized sigma points
44
+
45
+ ```python
46
+ import numpy as np
47
+ from classic_controlling import UKF
48
+
49
+ def fx(sigmas, dt): # (2n+1, 4) batch in, batch out
50
+ out = sigmas.copy()
51
+ out[:, 0] += dt * sigmas[:, 2]; out[:, 1] += dt * sigmas[:, 3]
52
+ return out
53
+
54
+ ukf = UKF(4, 2, 0.1, fx, hx=lambda s: s[:, :2], Q=np.eye(4)*0.01, R=np.eye(2))
55
+ ests = ukf.batch_filter(zs) # zs: (N, 2) position measurements
56
+ ```
57
+
58
+ From `examples/demo_ukf.py` — coordinated-turn tracking, RMSE 0.30 m under 0.5 m observation noise:
59
+
60
+ ![UKF tracking](docs/figures/ukf_tracking.png)
61
+
62
+ ### LinearMPC — constrained MPC without a solver dependency
63
+
64
+ ```python
65
+ import numpy as np
66
+ from classic_controlling import LinearMPC
67
+
68
+ A = np.array([[1.0, 0.1], [0.0, 1.0]]); B = np.array([[0.005], [0.1]])
69
+ mpc = LinearMPC(A, B, Q=np.eye(2), R=[[0.1]], horizon=40, u_min=-1.0, u_max=1.0)
70
+ x = np.array([3.0, 0.0])
71
+ for _ in range(120):
72
+ x = A @ x + B @ mpc.solve(x, warm_start=True)
73
+ ```
74
+
75
+ From `examples/demo_mpc.py`:
76
+
77
+ ![MPC demo](docs/figures/mpc_demo.png)
78
+
79
+ ## Benchmarks
80
+
81
+ ### Vectorized UKF vs point-loop reference
82
+
83
+ `python benchmarks/bench_ukf.py` — 1000 predict+update steps each, mathematically equivalent implementations (Python 3.13.5 / NumPy 2.3.3, Windows):
84
+
85
+ | dim_x | vectorized (s) | point-loop (s) | speedup |
86
+ |------:|---------------:|---------------:|--------:|
87
+ | 2 | 0.0392 | 0.0855 | 2.2× |
88
+ | 8 | 0.0439 | 0.2623 | 6.0× |
89
+ | 32 | 0.1079 | 1.2066 | 11.2× |
90
+
91
+ The point-loop overhead grows linearly with `2n+1` sigma points; the vectorized path is eaten by BLAS.
92
+
93
+ ### `auto_tune` blind test
94
+
95
+ Zero human parameters; the plants' true parameters are used only for assertions (`tests/test_autotune.py`, 300 closed-loop steps at dt=0.05):
96
+
97
+ | plant | model | steady-state error |
98
+ |---|---|---:|
99
+ | FOPDT | `0.5·ẏ + y = u` | 0.89% |
100
+ | second-order underdamped | `ζ=0.5, ωn=3` | 3.21% |
101
+ | nonlinear, open-loop unstable | `ÿ = -ẏ + u + 0.5y²` | 1.03% |
102
+
103
+ ### MPC warm start
104
+
105
+ Constrained double integrator, horizon 40, 120 closed-loop steps (`examples/demo_mpc.py`):
106
+
107
+ | | total ADMM iters | mean iters/step |
108
+ |---|---:|---:|
109
+ | cold start | 3687 | 30.7 |
110
+ | warm start | 1935 | 16.1 |
111
+ | **speedup** | **1.9×** | **1.9×** |
112
+
113
+ ### ADRC.auto_tune vs model-tuned PID
114
+
115
+ Step tracking `r=1` with a step load disturbance at t=20s (`examples/demo_adrc_vs_pid.py`; PID tuned from the *same* step-test data via Ziegler-Nichols reaction-curve rules, IMC-PI fallback when the identified delay ≈ 0):
116
+
117
+ | plant | controller | overshoot | settling (s) | disturbance recovery (s) | IAE |
118
+ |---|---|---:|---:|---:|---:|
119
+ | FOPDT | PID (IMC-PI) | 0.0% | 0.40 | 0.55 | 0.15 |
120
+ | FOPDT | ADRC | 0.0% | 12.45 | 6.25 | 4.12 |
121
+ | 2nd-order | PID (Z-N) | 6.7% | 2.05 | 1.05 | 0.51 |
122
+ | 2nd-order | ADRC | 0.0% | 17.05 | 6.35 | 5.06 |
123
+ | nonlinear | PID (Z-N) | 757% | — | ∞ | 170.86 |
124
+ | nonlinear | ADRC | 20.1% | 13.20 | 3.55 | 2.89 |
125
+
126
+ Honest read: on well-behaved LTI plants a model-tuned PID is faster — ADRC's auto-bandwidth trades speed for guarantees (the delay phase-margin cap is calibrated against measured divergence, not folklore). The trade: ADRC never rings, needs zero expertise, and is the only one left standing on the open-loop-unstable nonlinear plant.
127
+
128
+ ## Examples
129
+
130
+ ```bash
131
+ python examples/demo_adrc_vs_pid.py # hero comparison + metrics table
132
+ python examples/demo_autotune.py # auto_tune pipeline end-to-end
133
+ python examples/demo_mpc.py # constrained MPC + warm-start speedup
134
+ python examples/demo_ukf.py # coordinated-turn tracking
135
+ ```
136
+
137
+ All figures are written to `docs/figures/`.
138
+
139
+ ## Project layout
140
+
141
+ ```
142
+ classic_controlling/ # the package
143
+ ├── adrc.py # linear ADRC (bandwidth tuning + auto_tune + RLS b0 adaptation)
144
+ ├── autotune.py # step-response FOPDT identification + automatic bandwidth selection
145
+ ├── sim.py # virtual plants (FOPDT / 2nd-order / nonlinear), reset()/step(u) protocol
146
+ ├── ukf.py # vectorized UKF
147
+ └── mpc.py # LinearMPC (condensed QP + built-in ADMM + warm start)
148
+ tests/ # 21 pytest tests (blind auto-tune assertions, SLSQP cross-check, ...)
149
+ benchmarks/bench_ukf.py # UKF vectorized vs point-loop benchmark
150
+ examples/ # runnable demos -> docs/figures/*.png
151
+ research/ # background research notes (Chinese)
152
+ ```
153
+
154
+ ## 中文简介
155
+
156
+ 三个经典控制/估计算法的高质量纯 NumPy 实现:
157
+
158
+ - **自整定 ADRC**:`ADRC.auto_tune(plant, dt)` 一键完成阶跃辨识 → FOPDT 拟合 → 带宽自动选择(时滞相位裕量帽 + 采样硬约束),全程零人工调参;一阶/二阶/非线性三个对象盲测稳态误差 0.9% / 3.2% / 1.0%。在线 RLS 修正 b0 为 experimental 可选项(默认关闭):限速双时间尺度更新 + [0.3, 3.0]× 护栏 + 贴护栏停滞自动回退冻结;
159
+ - **向量化 UKF**:sigma 点操作全部 NumPy 广播一次完成,无逐点循环,相比等价逐点实现加速 2.2× / 6.0× / 11.2×(dim 2/8/32);
160
+ - **轻量线性 MPC**:稠密式 QP 编译一次 + 内置 OSQP 风格 ADMM 求解器 + (z, s, y) 热启动(总迭代数减 1.9×),零外部求解器依赖。
161
+
162
+ 快速开始:
163
+
164
+ ```bash
165
+ pip install -e .
166
+ python -m pytest tests/ -v # 21 项测试
167
+ python examples/demo_adrc_vs_pid.py # 核心对比演示,出图到 docs/figures/
168
+ ```
169
+
170
+ ## Roadmap
171
+
172
+ - Upstream the vectorized UKF sigma-point path as a PR to `filterpy`
173
+ - Optional Numba backend for the MPC ADMM iterations (per-iteration cost → microseconds)
174
+ - More virtual plant types (integrating, oscillatory, MIMO) and ADRC tracking of time-varying references
175
+
176
+ ## License
177
+
178
+ MIT — see [LICENSE](LICENSE). Contributions welcome: [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -0,0 +1,17 @@
1
+ """classic_controlling: 三个经典控制/估计算法的高质量实现。
2
+
3
+ - ADRC : 线性自抗扰控制(带宽法 LADRC)
4
+ - UKF : 向量化无迹卡尔曼滤波
5
+ - LinearMPC : 轻量线性模型预测控制(稠密式 QP + 内置 ADMM 求解器 + 热启动)
6
+ """
7
+
8
+ from .adrc import ADRC
9
+ from .ukf import UKF
10
+ from .mpc import LinearMPC
11
+ from .sim import FOPDTPlant, SecondOrderPlant, NonlinearPlant
12
+ from .autotune import fit_fopdt, auto_bandwidth
13
+
14
+ __all__ = ["ADRC", "UKF", "LinearMPC",
15
+ "FOPDTPlant", "SecondOrderPlant", "NonlinearPlant",
16
+ "fit_fopdt", "auto_bandwidth"]
17
+ __version__ = "0.1.0"