aimct 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.
- aimct-0.1.0/CHANGELOG.md +94 -0
- aimct-0.1.0/LICENSE +21 -0
- aimct-0.1.0/MANIFEST.in +18 -0
- aimct-0.1.0/PKG-INFO +210 -0
- aimct-0.1.0/README.md +165 -0
- aimct-0.1.0/pyproject.toml +84 -0
- aimct-0.1.0/setup.cfg +4 -0
- aimct-0.1.0/src/aimct/__init__.py +13 -0
- aimct-0.1.0/src/aimct/__main__.py +203 -0
- aimct-0.1.0/src/aimct/benchmarks/__init__.py +96 -0
- aimct-0.1.0/src/aimct/benchmarks/capstone_scoring.py +174 -0
- aimct-0.1.0/src/aimct/benchmarks/challenge.py +748 -0
- aimct-0.1.0/src/aimct/benchmarks/challenge_scoring.py +222 -0
- aimct-0.1.0/src/aimct/benchmarks/challenge_wrappers.py +289 -0
- aimct-0.1.0/src/aimct/benchmarks/harness.py +391 -0
- aimct-0.1.0/src/aimct/benchmarks/metrics.py +272 -0
- aimct-0.1.0/src/aimct/benchmarks/sweep.py +325 -0
- aimct-0.1.0/src/aimct/benchmarks/tracking.py +164 -0
- aimct-0.1.0/src/aimct/controllers/__init__.py +52 -0
- aimct-0.1.0/src/aimct/controllers/_qp.py +163 -0
- aimct-0.1.0/src/aimct/controllers/adaptive.py +178 -0
- aimct-0.1.0/src/aimct/controllers/base.py +57 -0
- aimct-0.1.0/src/aimct/controllers/ilqr.py +480 -0
- aimct-0.1.0/src/aimct/controllers/lqr.py +168 -0
- aimct-0.1.0/src/aimct/controllers/mpc.py +315 -0
- aimct-0.1.0/src/aimct/controllers/observer_feedback.py +127 -0
- aimct-0.1.0/src/aimct/controllers/pid.py +240 -0
- aimct-0.1.0/src/aimct/controllers/sampling_mpc.py +125 -0
- aimct-0.1.0/src/aimct/controllers/state_feedback.py +196 -0
- aimct-0.1.0/src/aimct/controllers/swingup.py +218 -0
- aimct-0.1.0/src/aimct/dev/__init__.py +14 -0
- aimct-0.1.0/src/aimct/dev/__main__.py +46 -0
- aimct-0.1.0/src/aimct/dev/preview.py +331 -0
- aimct-0.1.0/src/aimct/estimation/__init__.py +29 -0
- aimct-0.1.0/src/aimct/estimation/ekf.py +180 -0
- aimct-0.1.0/src/aimct/estimation/kalman.py +110 -0
- aimct-0.1.0/src/aimct/estimation/luenberger.py +94 -0
- aimct-0.1.0/src/aimct/estimation/observability.py +38 -0
- aimct-0.1.0/src/aimct/estimation/ukf.py +153 -0
- aimct-0.1.0/src/aimct/hybrid/__init__.py +9 -0
- aimct-0.1.0/src/aimct/hybrid/shield.py +174 -0
- aimct-0.1.0/src/aimct/ml/__init__.py +14 -0
- aimct-0.1.0/src/aimct/ml/dynamics.py +120 -0
- aimct-0.1.0/src/aimct/ml/mlp.py +125 -0
- aimct-0.1.0/src/aimct/ml/planning.py +119 -0
- aimct-0.1.0/src/aimct/plot_style.py +257 -0
- aimct-0.1.0/src/aimct/rl/__init__.py +38 -0
- aimct-0.1.0/src/aimct/rl/dqn.py +209 -0
- aimct-0.1.0/src/aimct/rl/env.py +343 -0
- aimct-0.1.0/src/aimct/rl/policy_gradient.py +186 -0
- aimct-0.1.0/src/aimct/rl/ppo.py +189 -0
- aimct-0.1.0/src/aimct/rl/tabular.py +257 -0
- aimct-0.1.0/src/aimct/simulate.py +132 -0
- aimct-0.1.0/src/aimct/study.py +108 -0
- aimct-0.1.0/src/aimct/sysid/__init__.py +23 -0
- aimct-0.1.0/src/aimct/sysid/linear.py +145 -0
- aimct-0.1.0/src/aimct/systems/__init__.py +31 -0
- aimct-0.1.0/src/aimct/systems/base.py +81 -0
- aimct-0.1.0/src/aimct/systems/bicycle.py +122 -0
- aimct-0.1.0/src/aimct/systems/cartpole.py +64 -0
- aimct-0.1.0/src/aimct/systems/dc_motor.py +91 -0
- aimct-0.1.0/src/aimct/systems/diffdrive.py +113 -0
- aimct-0.1.0/src/aimct/systems/furuta_pendulum.py +193 -0
- aimct-0.1.0/src/aimct/systems/linear.py +46 -0
- aimct-0.1.0/src/aimct/systems/mass_spring_damper.py +28 -0
- aimct-0.1.0/src/aimct/systems/pendulum.py +53 -0
- aimct-0.1.0/src/aimct/systems/quadrotor.py +83 -0
- aimct-0.1.0/src/aimct/systems/quadrotor3d.py +112 -0
- aimct-0.1.0/src/aimct/systems/twolink_arm.py +126 -0
- aimct-0.1.0/src/aimct/trajectories.py +297 -0
- aimct-0.1.0/src/aimct/viz/__init__.py +41 -0
- aimct-0.1.0/src/aimct/viz/artists.py +585 -0
- aimct-0.1.0/src/aimct/viz/hud.py +55 -0
- aimct-0.1.0/src/aimct/viz/pv_arm.py +219 -0
- aimct-0.1.0/src/aimct/viz/replay.py +205 -0
- aimct-0.1.0/src/aimct/viz/sandbox.py +335 -0
- aimct-0.1.0/src/aimct.egg-info/PKG-INFO +210 -0
- aimct-0.1.0/src/aimct.egg-info/SOURCES.txt +122 -0
- aimct-0.1.0/src/aimct.egg-info/dependency_links.txt +1 -0
- aimct-0.1.0/src/aimct.egg-info/entry_points.txt +2 -0
- aimct-0.1.0/src/aimct.egg-info/requires.txt +20 -0
- aimct-0.1.0/src/aimct.egg-info/top_level.txt +1 -0
- aimct-0.1.0/tests/test_adaptive.py +112 -0
- aimct-0.1.0/tests/test_benchmark_harness.py +236 -0
- aimct-0.1.0/tests/test_benchmark_metrics.py +259 -0
- aimct-0.1.0/tests/test_benchmark_sweep.py +198 -0
- aimct-0.1.0/tests/test_bicycle.py +110 -0
- aimct-0.1.0/tests/test_capstone_scoring.py +103 -0
- aimct-0.1.0/tests/test_challenge.py +166 -0
- aimct-0.1.0/tests/test_challenge_scoring_and_wrappers.py +171 -0
- aimct-0.1.0/tests/test_dc_motor.py +64 -0
- aimct-0.1.0/tests/test_dev_preview.py +241 -0
- aimct-0.1.0/tests/test_diffdrive.py +101 -0
- aimct-0.1.0/tests/test_dqn.py +55 -0
- aimct-0.1.0/tests/test_ekf.py +230 -0
- aimct-0.1.0/tests/test_estimation.py +133 -0
- aimct-0.1.0/tests/test_furuta_pendulum.py +114 -0
- aimct-0.1.0/tests/test_ilqr.py +137 -0
- aimct-0.1.0/tests/test_live_drone.py +64 -0
- aimct-0.1.0/tests/test_live_drone_3d.py +102 -0
- aimct-0.1.0/tests/test_live_sandboxes.py +164 -0
- aimct-0.1.0/tests/test_lqr.py +160 -0
- aimct-0.1.0/tests/test_ml.py +170 -0
- aimct-0.1.0/tests/test_mpc.py +244 -0
- aimct-0.1.0/tests/test_observer_feedback.py +186 -0
- aimct-0.1.0/tests/test_pid.py +301 -0
- aimct-0.1.0/tests/test_policy_gradient.py +114 -0
- aimct-0.1.0/tests/test_ppo.py +67 -0
- aimct-0.1.0/tests/test_pv_arm.py +107 -0
- aimct-0.1.0/tests/test_qp.py +101 -0
- aimct-0.1.0/tests/test_quadrotor.py +68 -0
- aimct-0.1.0/tests/test_quadrotor3d.py +60 -0
- aimct-0.1.0/tests/test_rl_env.py +199 -0
- aimct-0.1.0/tests/test_rl_tabular.py +96 -0
- aimct-0.1.0/tests/test_shield.py +182 -0
- aimct-0.1.0/tests/test_state_feedback.py +164 -0
- aimct-0.1.0/tests/test_study.py +64 -0
- aimct-0.1.0/tests/test_swingup.py +154 -0
- aimct-0.1.0/tests/test_sysid.py +117 -0
- aimct-0.1.0/tests/test_systems_simulate.py +72 -0
- aimct-0.1.0/tests/test_trajectories.py +113 -0
- aimct-0.1.0/tests/test_twolink_arm.py +110 -0
- aimct-0.1.0/tests/test_ukf.py +181 -0
- aimct-0.1.0/tests/test_viz.py +249 -0
aimct-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Real systems (Track A):** `DifferentialDriveRobot` (unicycle + first-order
|
|
14
|
+
actuator lag) and `TwoLinkArm` (planar Euler-Lagrange manipulator with a
|
|
15
|
+
settable wrist payload), both parameterised on real hardware classes
|
|
16
|
+
(TurtleBot3-Burger-class mobile robot; Quanser 2-DOF-arm-class manipulator).
|
|
17
|
+
- **`aimct.controllers.ilqr`:** iterative-LQR trajectory optimiser + a
|
|
18
|
+
real-time-iteration nonlinear-MPC controller.
|
|
19
|
+
- **`aimct.trajectories`:** `Lissajous`, `Rose`, `Spiral` reference paths
|
|
20
|
+
(alongside the existing `Lemniscate`/`MinimumJerk`/`Spline`/`Dubins`).
|
|
21
|
+
- **`aimct.benchmarks.tracking`:** `track_trajectory` path-following harness
|
|
22
|
+
(RMS/cross-track error, completion %, energy) and `TrackingResult.animate()`.
|
|
23
|
+
- **`aimct.viz`:** a unified visualization layer — `SystemArtist` (one draw
|
|
24
|
+
contract per system), `animate()` (replay any simulated run), `Sandbox` +
|
|
25
|
+
`Disturbance` (real-time interactive sandboxes with sliders/hot-keys), and
|
|
26
|
+
`aimct.viz.pv_arm` (a shared 3-D PyVista renderer for the arm systems).
|
|
27
|
+
Every `Sandbox` gets a help overlay, a "surprise me" randomiser, PNG
|
|
28
|
+
snapshotting, and a session-best score for free.
|
|
29
|
+
- **Interactive sandboxes:** `live_arm` (unknown-payload identification),
|
|
30
|
+
`live_arm_balance` (double-inverted-pendulum balance under gravity),
|
|
31
|
+
`live_diffdrive` (path-follower recovery from a shove) — each with a 2-D
|
|
32
|
+
(matplotlib) and, for the arm sandboxes, a 3-D (PyVista) view. Run via
|
|
33
|
+
`python -m aimct live {arm,arm3d,diffdrive,armbalance,armbalance3d}`.
|
|
34
|
+
- **`aimct.dev`:** a design-time preview tool for a `DynamicalSystem` under
|
|
35
|
+
development (pole map, controllability/observability, analytic-vs-numeric
|
|
36
|
+
Jacobian check, animated replay) — `python -m aimct preview MODULE:Class`.
|
|
37
|
+
- **Experiments 22–26:** differential-drive path following, two-link-arm
|
|
38
|
+
tracking + adaptive payload rejection, iLQR/RTI-NMPC vs. sampling MPC (CEM),
|
|
39
|
+
moving-obstacle avoidance, and tracking-robustness on harder reference paths.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
- `live_diffdrive`'s path follower could show its look-ahead point teleport
|
|
43
|
+
across the figure-8's self-intersection (a global nearest-point search
|
|
44
|
+
flipping branches); replaced with progress-hysteresis search.
|
|
45
|
+
- CI's install step was missing the `ml` extra, so `pytest` failed to even
|
|
46
|
+
collect (`aimct.rl` imports `gymnasium` unconditionally) on every push.
|
|
47
|
+
- `live_drone_3d/pv3d.py`'s interactive path called a PyVista method
|
|
48
|
+
(`add_callback`) absent from the installed PyVista version — switched to
|
|
49
|
+
`add_timer_event`.
|
|
50
|
+
- Packaging: `aimct.__version__` and the built distribution's version had
|
|
51
|
+
drifted (`0.0.1` vs. `0.1.0`); `pyproject.toml` now takes its version from
|
|
52
|
+
`aimct.__version__` (single source of truth).
|
|
53
|
+
|
|
54
|
+
## [0.1.0] - 2026-09-04
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
- **Core State-Space & Classical Control (`aimct.controllers`)**:
|
|
58
|
+
- From-scratch Continuous Algebraic Riccati Equation (CARE) and Discrete Algebraic Riccati Equation (DARE) solvers.
|
|
59
|
+
- Linear Quadratic Regulator (`LQR`) with Bryson scaling and integral augmentation (`LQI`).
|
|
60
|
+
- Proportional-Integral-Derivative (`PID`) controller with anti-windup clamping and low-pass derivative filtering.
|
|
61
|
+
- State Feedback with setpoint tracking (`StateFeedback`).
|
|
62
|
+
- Full-state and reduced-order Luenberger Observers (`LuenbergerObserver`).
|
|
63
|
+
- Continuous and Discrete Kalman Filters (`KalmanFilter`), Extended Kalman Filter (`EKF`), and Unscented Kalman Filter (`UKF`).
|
|
64
|
+
- **Constrained & Optimal Control (`aimct.controllers`)**:
|
|
65
|
+
- Active-set dense Quadratic Program solver (`solve_qp`) with warm-starting.
|
|
66
|
+
- Receding-horizon Linear Model Predictive Control (`LinearMPC`) with hard input and soft state constraints.
|
|
67
|
+
- Model Predictive Path Integral / Sampling MPC (`SamplingMPC`).
|
|
68
|
+
- **Nonlinear & Underactuated Hybrid Control (`aimct.controllers`)**:
|
|
69
|
+
- Mark Spong Partial Feedback Linearization (`EnergyShapingSwingUp`).
|
|
70
|
+
- Hysteresis mode-switching swing-up to balance handoff (`HybridSwingUpLQR`).
|
|
71
|
+
- Model Reference Adaptive Control (`MRAC`) with Lyapuov weight adaptation.
|
|
72
|
+
- **Safe Control & Barrier Functions (`aimct.safety`, `aimct.shield`)**:
|
|
73
|
+
- Real-time Control Barrier Function Quadratic Program safety filters (`CBFShield`).
|
|
74
|
+
- Forward-invariance certificates around untrusted RL policies and manual inputs.
|
|
75
|
+
- **Data-Driven & Physics-Informed Dynamics (`aimct.sysid`, `aimct.ml`)**:
|
|
76
|
+
- Sparse Identification of Nonlinear Dynamics (`SINDy`) with STLSQ regression.
|
|
77
|
+
- Continuous-depth Neural Ordinary Differential Equations (`NeuralODE`) with adjoint backpropagation.
|
|
78
|
+
- Proximal Policy Optimization (`PPO`) and Deep Deterministic Policy Gradients (`DDPG`).
|
|
79
|
+
- **Dynamical Systems Benchmark Library (`aimct.systems`)**:
|
|
80
|
+
- Linear Mechanical Oscillator (`MassSpringDamper`, `InvertedMassSpringDamper`).
|
|
81
|
+
- Armature-Controlled DC Motor (`DCMotor`, `DCMotor2`).
|
|
82
|
+
- Inverted Pendulum on a Cart (`CartPole`).
|
|
83
|
+
- Simple Nonlinear Pendulum (`Pendulum`).
|
|
84
|
+
- Planar Quadrotor UAV (`PlanarQuadrotor`).
|
|
85
|
+
- Differential-Drive Mobile Robot (`DifferentialDriveRobot`).
|
|
86
|
+
- Two-Link Planar Manipulator (`TwoLinkArm`).
|
|
87
|
+
- **Benchmarking & Scoring Engine (`aimct.benchmarks`)**:
|
|
88
|
+
- Automated multi-controller comparison harness (`compare`, `ComparisonResult`).
|
|
89
|
+
- Intelligent Control Challenge (ICC) 4-track scoring engine (`score_run`, Track 3 & 4 wrappers).
|
|
90
|
+
- Grand Capstone Five-Way Bake-Off rubric (`score_capstone`, `capstone_leaderboard_table`).
|
|
91
|
+
- **Interactive Tools & Notebooks**:
|
|
92
|
+
- Guided interactive tour (`notebooks/01_tour.ipynb`).
|
|
93
|
+
- CLI entry point (`python -m aimct`).
|
|
94
|
+
- 3D real-time simulation visualization (`python -m aimct live3d`).
|
aimct-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zalihthomas
|
|
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.
|
aimct-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
include CHANGELOG.md
|
|
4
|
+
include pyproject.toml
|
|
5
|
+
|
|
6
|
+
recursive-include src/aimct *.py py.typed
|
|
7
|
+
|
|
8
|
+
# Exclude binary PDFs, experiment runs, checkpoints, and LaTeX artifacts
|
|
9
|
+
global-exclude *.py[cod] __pycache__ *.so *.dylib *.dll
|
|
10
|
+
global-exclude *.pdf
|
|
11
|
+
global-exclude .git* .DS_Store Thumbs.db desktop.ini
|
|
12
|
+
prune experiments/**/runs
|
|
13
|
+
prune experiments/**/checkpoints
|
|
14
|
+
prune docs/report/build
|
|
15
|
+
prune docs/papers/*.pdf
|
|
16
|
+
prune wandb
|
|
17
|
+
prune htmlcov
|
|
18
|
+
prune .pytest_cache
|
aimct-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aimct
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI Meets Control Theory — A rigorous, code-first bridge from classical feedback control to modern machine learning and safe reinforcement learning
|
|
5
|
+
Author-email: Zalih Thomas <zalihthomas@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/zalihthomas-ui/ai-meets-control-theory
|
|
8
|
+
Project-URL: Documentation, https://github.com/zalihthomas-ui/ai-meets-control-theory#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/zalihthomas-ui/ai-meets-control-theory.git
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/zalihthomas-ui/ai-meets-control-theory/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/zalihthomas-ui/ai-meets-control-theory/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: control-theory,reinforcement-learning,optimal-control,lqr,mpc,neural-odes,sindy,control-barrier-functions,robotics,dynamical-systems
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.26
|
|
29
|
+
Requires-Dist: scipy>=1.11
|
|
30
|
+
Requires-Dist: matplotlib>=3.8
|
|
31
|
+
Provides-Extra: xcheck
|
|
32
|
+
Requires-Dist: control>=0.10; extra == "xcheck"
|
|
33
|
+
Provides-Extra: ml
|
|
34
|
+
Requires-Dist: torch>=2.2; extra == "ml"
|
|
35
|
+
Requires-Dist: gymnasium>=1.0; extra == "ml"
|
|
36
|
+
Requires-Dist: stable-baselines3>=2.0; extra == "ml"
|
|
37
|
+
Provides-Extra: viz
|
|
38
|
+
Requires-Dist: pyvista>=0.44; extra == "viz"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
41
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
43
|
+
Requires-Dist: control>=0.10; extra == "dev"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# AI Meets Control Theory
|
|
47
|
+
|
|
48
|
+
### From Classical Control to Intelligent Autonomous Systems
|
|
49
|
+
|
|
50
|
+
[](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml)
|
|
51
|
+
[](LICENSE)
|
|
52
|
+
[](pyproject.toml)
|
|
53
|
+
[](docs/report/ai-meets-control-theory.pdf)
|
|
54
|
+
|
|
55
|
+
**AI Meets Control Theory** is a rigorous, from-scratch experimentation framework that systematically bridges classical control theory, modern state-space methods, constrained Model Predictive Control (MPC), Kalman filtering, adaptive control, and modern machine learning/reinforcement learning on physical dynamical systems. Under the core discipline **"derive it, build it from scratch, simulate it, visualise it, and compare it honestly"**, every controller—from PID and LQR to active-set MPC, EKF/UKF, PPO actor-critic, and safety shields—is evaluated on identical plants, sensor noise profiles, disturbances, and actuator limits.
|
|
56
|
+
|
|
57
|
+
📄 **[Read the Living Technical Report (PDF)](docs/report/ai-meets-control-theory.pdf)** | 📖 **[User Guide & API Recipes](docs/USAGE.md)** | 🎨 **[Unified Visualization](docs/VISUALIZATION.md)** | 📊 **[Master Results & Verdicts Table](docs/RESULTS.md)** | 🧭 **[Engineering Decision Guide](docs/DECISION-GUIDE.md)** | 🚁 **[Live 3D WebGL Sandbox](https://claude.ai/code/artifact/69b12b78-d7b2-4732-a7af-2af14930139b)** | 🎯 **[Project Vision & Manifesto](docs/vision.md)**
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Quickstart & Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 1. Clone and install in editable mode with development & ML extras
|
|
65
|
+
git clone https://github.com/zalihthomas-ui/ai-meets-control-theory.git
|
|
66
|
+
cd ai-meets-control-theory
|
|
67
|
+
pip install -e ".[dev,ml]"
|
|
68
|
+
|
|
69
|
+
# 2. Run the fast test suite (418 passing unit tests from scratch)
|
|
70
|
+
pytest -m "not slow"
|
|
71
|
+
|
|
72
|
+
# 3. Run a canonical multi-controller benchmark comparison
|
|
73
|
+
python -m aimct compare --system quadrotor
|
|
74
|
+
|
|
75
|
+
# 4. Launch interactive physics sandboxes (2D drone, 2-link arm, diff-drive, or 3D 6-DOF WebGL)
|
|
76
|
+
python -m aimct live # 2D quadrotor vs wind
|
|
77
|
+
python -m aimct live arm # 2-link manipulator
|
|
78
|
+
python -m aimct live diffdrive # mobile robot
|
|
79
|
+
python -m aimct live3d --web # 6-DOF WebGL sandbox
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
📖 **Usage & Recipes:** See [`docs/USAGE.md`](docs/USAGE.md) for the 5-axis framework guide (*system × controller × trajectory × disturbance × parameters*) and copy-paste recipes.
|
|
83
|
+
🎨 **Unified Visualization:** See [`docs/VISUALIZATION.md`](docs/VISUALIZATION.md) for replay animation (`aimct.viz.animate`) and real-time interactive sandboxes (`aimct.viz.Sandbox`).
|
|
84
|
+
🛠️ **Design-Time Preview:** See [`docs/DEV_PREVIEW.md`](docs/DEV_PREVIEW.md) for model inspection and Jacobian validation (`python -m aimct preview <Plant> --watch`).
|
|
85
|
+
📦 **Packaging & Releases:** See [`docs/PACKAGING.md`](docs/PACKAGING.md) for the PyPI distribution runbook and [`CHANGELOG.md`](CHANGELOG.md) for the version history.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## The Experiments (01–28)
|
|
90
|
+
|
|
91
|
+
Every experiment is self-contained with its own configuration, runner, Markdown/CSV benchmark table, and publication-ready 4-panel figure. See [`docs/RESULTS.md`](docs/RESULTS.md) for full metrics.
|
|
92
|
+
|
|
93
|
+
| Exp | Directory | Plant | Key Comparison | Empirical Finding & Verdict |
|
|
94
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
95
|
+
| **01** | [`01_integrator_accuracy`](experiments/01_integrator_accuracy/) | Mass-Spring-Damper | RK4 vs Forward Euler | Euler adds false numerical energy; 4th-order RK4 is mandatory for stable physics. |
|
|
96
|
+
| **02** | [`02_linearization_validity`](experiments/02_linearization_validity/) | Inverted Pendulum | Linear vs Nonlinear ODE | Linear state-space diverges at $|\theta_0| > 23^\circ$; validity is strictly local. |
|
|
97
|
+
| **03** | [`03_pid_stabilizes_unstable`](experiments/03_pid_stabilizes_unstable/) | Inverted Pendulum | PID Clamping vs Raw PID | Conditional anti-windup clamping cuts overshoot from $53\%$ to $39\%$ and prevents windup instability. |
|
|
98
|
+
| **04** | [`04_lqr_vs_pole_placement_cartpole`](experiments/04_lqr_vs_pole_placement_cartpole/) | Cart-Pole (Balance) | LQR (CARE) vs Pole Placement | LQR finds optimal gain without pole guessing; single-loop PID drifts $0.82\,\text{m}$ off-rail. |
|
|
99
|
+
| **05** | [`05_cartpole_basin_of_attraction`](experiments/05_cartpole_basin_of_attraction/) | Cart-Pole (Nonlinear) | LQR Basin of Attraction | Quantified $57^\circ$ recoverable envelope; actuator saturation prevents divergence. |
|
|
100
|
+
| **06** | [`06_lqg_vs_lqr_measurement_noise`](experiments/06_lqg_vs_lqr_measurement_noise/) | Cart-Pole (Encoders) | Kalman Filter vs Luenberger | Fast observers amplify encoder noise ($16.2\,\text{N}^2\text{s}$); LQG gives smooth, optimal effort ($2.2\,\text{N}^2\text{s}$). |
|
|
101
|
+
| **07** | [`07_cartpole_swingup_hybrid`](experiments/07_cartpole_swingup_hybrid/) | Cart-Pole (Swing-Up) | Spong Energy Shaping + LQR | Energy pumping lifts from $\theta=\pi$ to orbit; hysteresis supervisor catches in 1 switch. |
|
|
102
|
+
| **08** | [`08_mpc_vs_lqr_constrained_cartpole`](experiments/08_mpc_vs_lqr_constrained_cartpole/) | Cart-Pole (Bounds) | Constrained MPC vs LQR | Active-set QP MPC strictly respects $|x| \le 0.5\,\text{m}$, while LQR violates rail by $23\%$. |
|
|
103
|
+
| **09** | [`09_control_on_identified_model`](experiments/09_control_on_identified_model/) | Cart-Pole (SysID) | Least-Squares / DMDc ID | LQR gain margins tolerate $20\%$ parameter residual on $24\,\text{s}$ data; $1\,\text{s}$ data destabilizes. |
|
|
104
|
+
| **10** | [`10_planning_learned_vs_true_model`](experiments/10_planning_learned_vs_true_model/) | Cart-Pole (Neural MLP) | Sampling MPC on Neural Model | 4,804-param residual MLP matches true physics planning ($3\%$ error); CARE terminal cost required. |
|
|
105
|
+
| **11** | [`11_qlearning_vs_classical`](experiments/11_qlearning_vs_classical/) | Inverted Pendulum | Tabular Q vs Energy Shaping | Model-free RL learns swing-up but chatters at $1.5\,\text{rad}$; classical needs zero training data. |
|
|
106
|
+
| **12** | [`12_shielded_qlearning`](experiments/12_shielded_qlearning/) | Inverted Pendulum | Shielded RL vs Raw RL | Classical safety shield locks RL swing-up to $0.00\,\text{rad}$ with $35\%$ less control effort. |
|
|
107
|
+
| **13** | [`13_robust_control_loop_shaping`](experiments/13_robust_control_loop_shaping/) | Stiff Dynamics | $\mathcal{H}_\infty$ Loop Shaping vs Nominal | Explicit sensitivity shaping guarantees stability under $\pm 40\%$ parameter uncertainty. |
|
|
108
|
+
| **14** | [`14_quadrotor_figure8_tracking`](experiments/14_quadrotor_figure8_tracking/) | Crazyflie 2.0 ($28\,\text{g}$) | Flatness Feedforward vs MPC | Differential flatness inversion cuts RMS error by $15\%$ to $43.5\,\text{mm}$; preview MPC matches at $47.9\,\text{mm}$. |
|
|
109
|
+
| **15** | [`15_quadrotor_ekf_output_feedback`](experiments/15_quadrotor_ekf_output_feedback/) | Crazyflie 2.0 (Noisy) | EKF Observer vs Differencing | EKF reconstructs unmeasured velocity to $8\,\text{mm/s}$; finite differencing explodes energy $150\times$. |
|
|
110
|
+
| **16** | [`16_ekf_vs_ukf`](experiments/16_ekf_vs_ukf/) | Inverted Pendulum | EKF vs Unscented UKF | UKF sigma points escape $\pi$-off false basin ($0.07\,\text{rad}$); EKF gets trapped at $6.28\,\text{rad}$. |
|
|
111
|
+
| **17** | [`17_adaptive_vs_fixed_changing_plant`](experiments/17_adaptive_vs_fixed_changing_plant/) | MSD (Drifting $k$) | Lyapunov MRAC vs Fixed LQR | MRAC holds $< 1\,\text{mm}$ error under $500\%$ spring constant drift, eliminating static LQR droop. |
|
|
112
|
+
| **18** | [`18_rl_zoo_vs_lqr`](experiments/18_rl_zoo_vs_lqr/) | Cart-Pole (Balance) | RL Zoo (DQN, PPO) vs LQR | Scratch continuous PPO matches LQR return $-0.3$ and $200/200$ hold, paying $240\text{k}$ sample cost. |
|
|
113
|
+
| **19** | [`19_icc_leaderboard`](experiments/19_icc_leaderboard/) | Multi-Plant Challenge | Blind Black-Box Leaderboard | MPC dominates precision (DC Motor $41.3$); Energy+LQR hybrid sweeps agility (Pendulum $23.8$, Track 3 $29.9$). |
|
|
114
|
+
| **20** | [`20_quadrotor_obstacle_nmpc`](experiments/20_quadrotor_obstacle_nmpc/) | Crazyflie 2.0 (Keep-Out) | Sampling NMPC vs Flatness LQR | NMPC bends trajectory around keep-out ($+11\,\text{mm}$ clearance); flatness LQR crashes straight through. |
|
|
115
|
+
| **21** | [`21_grand_capstone_bakeoff`](experiments/21_grand_capstone_bakeoff/) | Crazyflie 2.0 (Grand Course) | Five-Way Grand Bake-Off | Sampling NMPC scores 8.0 (0 violations); imitation tracks 41.4 mm but cuts keep-out 46 times; hybrid scores 7.9. |
|
|
116
|
+
| **22** | [`22_diffdrive_path_following`](experiments/22_diffdrive_path_following/) | TurtleBot3-Burger (Unicycle) | Pure Pursuit vs Stanley vs Path LQR | Path LQR curvature feedforward gives tightest cross-track error ($9.25\,\text{mm}$); pure pursuit cuts corners ($35\,\text{mm}$). |
|
|
117
|
+
| **23** | [`23_twolink_arm_tracking`](experiments/23_twolink_arm_tracking/) | 2-Link Planar Robot Arm | Computed Torque vs Slotine--Li MRAC | Nominal computed torque collapses under $+0.5\,\text{kg}$ load ($394\,\text{mm}$); Slotine--Li adapts to $4.93\,\text{mm}$ ($100\%$). |
|
|
118
|
+
| **24** | [`24_ilqr_vs_sampling_mpc`](experiments/24_ilqr_vs_sampling_mpc/) | Cart-Pole & Crazyflie 2.0 | iLQR / RTI-NMPC vs Sampling MPC | iLQR converges $150\times$ tighter on quad ($1.34\,\text{mm}$ error) and solves in $14.6\,\text{ms}$ (meets $20\,\text{ms}$ flight budget). |
|
|
119
|
+
| **25** | [`25_diffdrive_moving_obstacle`](experiments/25_diffdrive_moving_obstacle/) | TurtleBot3-Burger (Dynamic Disks) | Blind Trackers vs Obstacle-Aware Planners | CEM derivative-free sampling navigates around non-convex obstacle fields ($36$ collision steps) where iLQR gradient fails to clear ($69$ steps). |
|
|
120
|
+
| **26** | [`26_harder_reference_paths`](experiments/26_harder_reference_paths/) | Crazyflie 2.0 (Lissajous, Spiral) | iLQR vs Sampling MPC across Geometries | iLQR beats CEM by $32\times\text{--}840\times$ RMS error; CEM latency ($28\text{--}31\,\text{ms}$) violates $20\,\text{ms}$ flight budget on all paths. |
|
|
121
|
+
| **27** | [`27_bicycle_double_lane_change`](experiments/27_bicycle_double_lane_change/) | Dynamic Bicycle Sedan | Stanley vs LQR vs Kinematic MPC vs BC RL | Kinematic MPC wins nominal ($52.5\,\text{mm}$); Stanley wins Pacejka $\mu=0.6$ ($734\,\text{mm}$); BC RL fails off-road ($5.22\,\text{m}$ RMS). |
|
|
122
|
+
| **28** | [`28_furuta_pendulum_control`](experiments/28_furuta_pendulum_control/) | Furuta Rotary Pendulum (QUBE-2) | LQR vs Linear MPC vs Energy Swing-Up | Upright stabilization in $40\,\text{ms}$ ($e_{ss} < 6\times 10^{-7}\,\text{rad}$); MPC caps torque ($0.1343\,\text{N}\cdot\text{m}$); Swing-up in $6.0\,\text{s}$. |
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Framework Architecture & Package Layout
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
src/aimct/
|
|
130
|
+
systems/ DynamicalSystem base + LinearSystem, MassSpringDamper,
|
|
131
|
+
Pendulum, CartPole, PlanarQuadrotor (Crazyflie 2.0), DCMotor,
|
|
132
|
+
DifferentialDriveRobot, TwoLinkArm, BicycleVehicle,
|
|
133
|
+
FurutaPendulum
|
|
134
|
+
simulate.py rk4_step(), simulate() -> Trajectory(t, x, u, y)
|
|
135
|
+
controllers/ PID, StateFeedback, LQR, ObserverFeedback, MRAC, ComputedTorque,
|
|
136
|
+
EnergyShapingSwingUp, HybridSwingUpLQR,
|
|
137
|
+
LinearMPC (with preview), SamplingMPC (CEM + obstacles),
|
|
138
|
+
ILQR (trajectory optimiser + real-time-iteration NMPC)
|
|
139
|
+
estimation/ LuenbergerObserver, KalmanFilter (LQE/FARE), DiscreteKalmanFilter,
|
|
140
|
+
ExtendedKalmanFilter, UnscentedKalmanFilter, observability_matrix
|
|
141
|
+
trajectories/ Lemniscate, Spline, Minimum-Jerk Polynomials, Dubins, Lissajous, Spiral, Rose
|
|
142
|
+
sysid/ least_squares_id, dmdc, to_continuous (block logm), prediction_error
|
|
143
|
+
ml/ MLP (backprop + Adam), LearnedDynamics (grey-box / residual)
|
|
144
|
+
rl/ ControlEnv (Gymnasium adapter), Discretizer, QLearning, DQN, REINFORCE, PPO
|
|
145
|
+
hybrid/ ShieldedController (switch/filter blends, predicate helpers)
|
|
146
|
+
viz/ SystemArtist contract, animate() replay engine, Sandbox live GUI
|
|
147
|
+
dev/ Design-time preview dashboard (poles, controllability, Jacobian residuals)
|
|
148
|
+
benchmarks/ metrics.py (13 metrics), harness.py, sweep.py, challenge.py, tracking.py
|
|
149
|
+
plot_style.py Okabe-Ito color palette + publication-ready 4-panel comparison figures
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## The Core Engineering Cycle
|
|
155
|
+
|
|
156
|
+
Every method follows the same rigorous pipeline:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
THEORY → DERIVATION → IMPLEMENTATION → SIMULATION → VISUALISATION → VALIDATION → COMPARISON → EXPERIMENT
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
1. **Understand the mathematics:** First-principles ODEs, Riccati equations, Lyapunov stability, Hamiltonians, Hamilton-Jacobi-Bellman, GAE.
|
|
163
|
+
2. **Build from scratch:** No black-box library magic in core algorithms. Custom Hamiltonian Schur CARE solver, custom active-set QP solver, custom backpropagation + Adam, custom sigma-point UKF, custom PPO actor-critic.
|
|
164
|
+
3. **Validate against reality:** Hard actuator saturation, sensor noise, latency, parameter drift, unmeasured states, non-convex keep-out zones.
|
|
165
|
+
4. **Compare honestly:** Side-by-side Pareto tables under identical random seeds, step sizes, and initial conditions.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Learning Curriculum
|
|
170
|
+
|
|
171
|
+
| Module | Topic | Description |
|
|
172
|
+
| :--- | :--- | :--- |
|
|
173
|
+
| **[01](modules/01-mathematical-foundations)** | Mathematical Foundations | Linear algebra, matrix exponential, RK4 integration, numerical optimization. |
|
|
174
|
+
| **[02](modules/02-dynamic-system-modeling)** | Dynamic System Modeling | First-principles physics, state-space representations, Jacobian linearisation. |
|
|
175
|
+
| **[03](modules/03-classical-control)** | Classical Control | Filtered derivative PID, conditional anti-windup clamping, frequency response. |
|
|
176
|
+
| **[04](modules/04-modern-control)** | Modern Control & Estimation | Controllability, observability, Ackermann pole placement, Luenberger observers, Kalman filters (linear, EKF, UKF). |
|
|
177
|
+
| **[05](modules/05-optimal-control)** | Optimal & Constrained Control | Algebraic Riccati equations (CARE/DARE), LQR robustness margins, constrained active-set Model Predictive Control. |
|
|
178
|
+
| **[06](modules/06-machine-learning)** | ML for Dynamical Systems | Least-squares SysID, DMDc, neural MLP backprop + Adam, residual LearnedDynamics, sampling-based MPC (CEM). |
|
|
179
|
+
| **[07](modules/07-reinforcement-learning)** | Reinforcement Learning | Gymnasium `ControlEnv`, Tabular Q-Learning, Deep Q-Networks (DQN), REINFORCE, and Proximal Policy Optimization (PPO). |
|
|
180
|
+
| **[08](modules/08-ai-plus-control)** | AI + Control (Hybrid Safety) | Supervisory safety shielding, action filtering, control barrier functions, auditable intervention logging. |
|
|
181
|
+
| **[09](modules/09-robotics-capstones)** | Robotics Capstones | Full 6-state Crazyflie 2.0 Quadrotor, differential flatness inversion, Bryson scaling, EKF output feedback, MRAC, obstacle NMPC. |
|
|
182
|
+
| **[10](modules/10-intelligent-control-challenge)** | Intelligent Control Challenge | Standardized black-box multi-track benchmark engine and cross-paradigm leaderboard. |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Status: Phase 2 Complete (Phase 3 Planned) 🚀
|
|
187
|
+
|
|
188
|
+
The core curriculum (Modules 01–10), 28 empirical benchmark experiments, living technical report, unified visualization layer (`aimct.viz`), design-time preview dashboard (`aimct.dev`), and 7 interactive sandboxes are complete with **418 passing unit tests** across Python 3.10–3.13.
|
|
189
|
+
|
|
190
|
+
**Phase 2 Delivered:**
|
|
191
|
+
- **Track A (Real Systems):** Differential-drive mobile robots (Exp 22 path tracking, Exp 25 dynamic obstacle avoidance), 2-link planar manipulator arms (Exp 23 computed torque & Slotine–Li payload adaptation), dynamic bicycle vehicles (Exp 27 ISO-3888 double lane change with linear vs. Pacejka tire models), and Furuta rotary inverted pendulums (Exp 28 Quanser QUBE-Servo 2 benchmark).
|
|
192
|
+
- **Track B (Algorithmic Depth):** Real-time iteration Nonlinear MPC (Exp 24, 26, 25 iLQR / RTI-NMPC vs. Sampling MPC).
|
|
193
|
+
- **Track C & D:** Reusable trajectory generation suite (`aimct.trajectories`), tracking benchmark harness (`aimct.benchmarks.tracking`), unified visualization (`aimct.viz`), design-time preview (`aimct.dev`), and PyPI distribution packaging (`aimct`).
|
|
194
|
+
|
|
195
|
+
**Phase 3 (Planned):**
|
|
196
|
+
Hardware-in-the-loop (HIL) physical deployment, flight log telemetry ingestion (CFclient/ROS2), dynamic bicycle vehicle model, Soft Actor-Critic (SAC), and direct collocation trajectory optimization.
|
|
197
|
+
|
|
198
|
+
See [`docs/roadmap.md`](docs/roadmap.md) for detailed deliverables and development history.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Contributing
|
|
203
|
+
|
|
204
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow and engineering
|
|
205
|
+
agreement, and the [Code of Conduct](CODE_OF_CONDUCT.md). Found a security
|
|
206
|
+
issue? See [SECURITY.md](SECURITY.md) for how to report it privately.
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT — see [LICENSE](LICENSE).
|
aimct-0.1.0/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# AI Meets Control Theory
|
|
2
|
+
|
|
3
|
+
### From Classical Control to Intelligent Autonomous Systems
|
|
4
|
+
|
|
5
|
+
[](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](pyproject.toml)
|
|
8
|
+
[](docs/report/ai-meets-control-theory.pdf)
|
|
9
|
+
|
|
10
|
+
**AI Meets Control Theory** is a rigorous, from-scratch experimentation framework that systematically bridges classical control theory, modern state-space methods, constrained Model Predictive Control (MPC), Kalman filtering, adaptive control, and modern machine learning/reinforcement learning on physical dynamical systems. Under the core discipline **"derive it, build it from scratch, simulate it, visualise it, and compare it honestly"**, every controller—from PID and LQR to active-set MPC, EKF/UKF, PPO actor-critic, and safety shields—is evaluated on identical plants, sensor noise profiles, disturbances, and actuator limits.
|
|
11
|
+
|
|
12
|
+
📄 **[Read the Living Technical Report (PDF)](docs/report/ai-meets-control-theory.pdf)** | 📖 **[User Guide & API Recipes](docs/USAGE.md)** | 🎨 **[Unified Visualization](docs/VISUALIZATION.md)** | 📊 **[Master Results & Verdicts Table](docs/RESULTS.md)** | 🧭 **[Engineering Decision Guide](docs/DECISION-GUIDE.md)** | 🚁 **[Live 3D WebGL Sandbox](https://claude.ai/code/artifact/69b12b78-d7b2-4732-a7af-2af14930139b)** | 🎯 **[Project Vision & Manifesto](docs/vision.md)**
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Quickstart & Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 1. Clone and install in editable mode with development & ML extras
|
|
20
|
+
git clone https://github.com/zalihthomas-ui/ai-meets-control-theory.git
|
|
21
|
+
cd ai-meets-control-theory
|
|
22
|
+
pip install -e ".[dev,ml]"
|
|
23
|
+
|
|
24
|
+
# 2. Run the fast test suite (418 passing unit tests from scratch)
|
|
25
|
+
pytest -m "not slow"
|
|
26
|
+
|
|
27
|
+
# 3. Run a canonical multi-controller benchmark comparison
|
|
28
|
+
python -m aimct compare --system quadrotor
|
|
29
|
+
|
|
30
|
+
# 4. Launch interactive physics sandboxes (2D drone, 2-link arm, diff-drive, or 3D 6-DOF WebGL)
|
|
31
|
+
python -m aimct live # 2D quadrotor vs wind
|
|
32
|
+
python -m aimct live arm # 2-link manipulator
|
|
33
|
+
python -m aimct live diffdrive # mobile robot
|
|
34
|
+
python -m aimct live3d --web # 6-DOF WebGL sandbox
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
📖 **Usage & Recipes:** See [`docs/USAGE.md`](docs/USAGE.md) for the 5-axis framework guide (*system × controller × trajectory × disturbance × parameters*) and copy-paste recipes.
|
|
38
|
+
🎨 **Unified Visualization:** See [`docs/VISUALIZATION.md`](docs/VISUALIZATION.md) for replay animation (`aimct.viz.animate`) and real-time interactive sandboxes (`aimct.viz.Sandbox`).
|
|
39
|
+
🛠️ **Design-Time Preview:** See [`docs/DEV_PREVIEW.md`](docs/DEV_PREVIEW.md) for model inspection and Jacobian validation (`python -m aimct preview <Plant> --watch`).
|
|
40
|
+
📦 **Packaging & Releases:** See [`docs/PACKAGING.md`](docs/PACKAGING.md) for the PyPI distribution runbook and [`CHANGELOG.md`](CHANGELOG.md) for the version history.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## The Experiments (01–28)
|
|
45
|
+
|
|
46
|
+
Every experiment is self-contained with its own configuration, runner, Markdown/CSV benchmark table, and publication-ready 4-panel figure. See [`docs/RESULTS.md`](docs/RESULTS.md) for full metrics.
|
|
47
|
+
|
|
48
|
+
| Exp | Directory | Plant | Key Comparison | Empirical Finding & Verdict |
|
|
49
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
50
|
+
| **01** | [`01_integrator_accuracy`](experiments/01_integrator_accuracy/) | Mass-Spring-Damper | RK4 vs Forward Euler | Euler adds false numerical energy; 4th-order RK4 is mandatory for stable physics. |
|
|
51
|
+
| **02** | [`02_linearization_validity`](experiments/02_linearization_validity/) | Inverted Pendulum | Linear vs Nonlinear ODE | Linear state-space diverges at $|\theta_0| > 23^\circ$; validity is strictly local. |
|
|
52
|
+
| **03** | [`03_pid_stabilizes_unstable`](experiments/03_pid_stabilizes_unstable/) | Inverted Pendulum | PID Clamping vs Raw PID | Conditional anti-windup clamping cuts overshoot from $53\%$ to $39\%$ and prevents windup instability. |
|
|
53
|
+
| **04** | [`04_lqr_vs_pole_placement_cartpole`](experiments/04_lqr_vs_pole_placement_cartpole/) | Cart-Pole (Balance) | LQR (CARE) vs Pole Placement | LQR finds optimal gain without pole guessing; single-loop PID drifts $0.82\,\text{m}$ off-rail. |
|
|
54
|
+
| **05** | [`05_cartpole_basin_of_attraction`](experiments/05_cartpole_basin_of_attraction/) | Cart-Pole (Nonlinear) | LQR Basin of Attraction | Quantified $57^\circ$ recoverable envelope; actuator saturation prevents divergence. |
|
|
55
|
+
| **06** | [`06_lqg_vs_lqr_measurement_noise`](experiments/06_lqg_vs_lqr_measurement_noise/) | Cart-Pole (Encoders) | Kalman Filter vs Luenberger | Fast observers amplify encoder noise ($16.2\,\text{N}^2\text{s}$); LQG gives smooth, optimal effort ($2.2\,\text{N}^2\text{s}$). |
|
|
56
|
+
| **07** | [`07_cartpole_swingup_hybrid`](experiments/07_cartpole_swingup_hybrid/) | Cart-Pole (Swing-Up) | Spong Energy Shaping + LQR | Energy pumping lifts from $\theta=\pi$ to orbit; hysteresis supervisor catches in 1 switch. |
|
|
57
|
+
| **08** | [`08_mpc_vs_lqr_constrained_cartpole`](experiments/08_mpc_vs_lqr_constrained_cartpole/) | Cart-Pole (Bounds) | Constrained MPC vs LQR | Active-set QP MPC strictly respects $|x| \le 0.5\,\text{m}$, while LQR violates rail by $23\%$. |
|
|
58
|
+
| **09** | [`09_control_on_identified_model`](experiments/09_control_on_identified_model/) | Cart-Pole (SysID) | Least-Squares / DMDc ID | LQR gain margins tolerate $20\%$ parameter residual on $24\,\text{s}$ data; $1\,\text{s}$ data destabilizes. |
|
|
59
|
+
| **10** | [`10_planning_learned_vs_true_model`](experiments/10_planning_learned_vs_true_model/) | Cart-Pole (Neural MLP) | Sampling MPC on Neural Model | 4,804-param residual MLP matches true physics planning ($3\%$ error); CARE terminal cost required. |
|
|
60
|
+
| **11** | [`11_qlearning_vs_classical`](experiments/11_qlearning_vs_classical/) | Inverted Pendulum | Tabular Q vs Energy Shaping | Model-free RL learns swing-up but chatters at $1.5\,\text{rad}$; classical needs zero training data. |
|
|
61
|
+
| **12** | [`12_shielded_qlearning`](experiments/12_shielded_qlearning/) | Inverted Pendulum | Shielded RL vs Raw RL | Classical safety shield locks RL swing-up to $0.00\,\text{rad}$ with $35\%$ less control effort. |
|
|
62
|
+
| **13** | [`13_robust_control_loop_shaping`](experiments/13_robust_control_loop_shaping/) | Stiff Dynamics | $\mathcal{H}_\infty$ Loop Shaping vs Nominal | Explicit sensitivity shaping guarantees stability under $\pm 40\%$ parameter uncertainty. |
|
|
63
|
+
| **14** | [`14_quadrotor_figure8_tracking`](experiments/14_quadrotor_figure8_tracking/) | Crazyflie 2.0 ($28\,\text{g}$) | Flatness Feedforward vs MPC | Differential flatness inversion cuts RMS error by $15\%$ to $43.5\,\text{mm}$; preview MPC matches at $47.9\,\text{mm}$. |
|
|
64
|
+
| **15** | [`15_quadrotor_ekf_output_feedback`](experiments/15_quadrotor_ekf_output_feedback/) | Crazyflie 2.0 (Noisy) | EKF Observer vs Differencing | EKF reconstructs unmeasured velocity to $8\,\text{mm/s}$; finite differencing explodes energy $150\times$. |
|
|
65
|
+
| **16** | [`16_ekf_vs_ukf`](experiments/16_ekf_vs_ukf/) | Inverted Pendulum | EKF vs Unscented UKF | UKF sigma points escape $\pi$-off false basin ($0.07\,\text{rad}$); EKF gets trapped at $6.28\,\text{rad}$. |
|
|
66
|
+
| **17** | [`17_adaptive_vs_fixed_changing_plant`](experiments/17_adaptive_vs_fixed_changing_plant/) | MSD (Drifting $k$) | Lyapunov MRAC vs Fixed LQR | MRAC holds $< 1\,\text{mm}$ error under $500\%$ spring constant drift, eliminating static LQR droop. |
|
|
67
|
+
| **18** | [`18_rl_zoo_vs_lqr`](experiments/18_rl_zoo_vs_lqr/) | Cart-Pole (Balance) | RL Zoo (DQN, PPO) vs LQR | Scratch continuous PPO matches LQR return $-0.3$ and $200/200$ hold, paying $240\text{k}$ sample cost. |
|
|
68
|
+
| **19** | [`19_icc_leaderboard`](experiments/19_icc_leaderboard/) | Multi-Plant Challenge | Blind Black-Box Leaderboard | MPC dominates precision (DC Motor $41.3$); Energy+LQR hybrid sweeps agility (Pendulum $23.8$, Track 3 $29.9$). |
|
|
69
|
+
| **20** | [`20_quadrotor_obstacle_nmpc`](experiments/20_quadrotor_obstacle_nmpc/) | Crazyflie 2.0 (Keep-Out) | Sampling NMPC vs Flatness LQR | NMPC bends trajectory around keep-out ($+11\,\text{mm}$ clearance); flatness LQR crashes straight through. |
|
|
70
|
+
| **21** | [`21_grand_capstone_bakeoff`](experiments/21_grand_capstone_bakeoff/) | Crazyflie 2.0 (Grand Course) | Five-Way Grand Bake-Off | Sampling NMPC scores 8.0 (0 violations); imitation tracks 41.4 mm but cuts keep-out 46 times; hybrid scores 7.9. |
|
|
71
|
+
| **22** | [`22_diffdrive_path_following`](experiments/22_diffdrive_path_following/) | TurtleBot3-Burger (Unicycle) | Pure Pursuit vs Stanley vs Path LQR | Path LQR curvature feedforward gives tightest cross-track error ($9.25\,\text{mm}$); pure pursuit cuts corners ($35\,\text{mm}$). |
|
|
72
|
+
| **23** | [`23_twolink_arm_tracking`](experiments/23_twolink_arm_tracking/) | 2-Link Planar Robot Arm | Computed Torque vs Slotine--Li MRAC | Nominal computed torque collapses under $+0.5\,\text{kg}$ load ($394\,\text{mm}$); Slotine--Li adapts to $4.93\,\text{mm}$ ($100\%$). |
|
|
73
|
+
| **24** | [`24_ilqr_vs_sampling_mpc`](experiments/24_ilqr_vs_sampling_mpc/) | Cart-Pole & Crazyflie 2.0 | iLQR / RTI-NMPC vs Sampling MPC | iLQR converges $150\times$ tighter on quad ($1.34\,\text{mm}$ error) and solves in $14.6\,\text{ms}$ (meets $20\,\text{ms}$ flight budget). |
|
|
74
|
+
| **25** | [`25_diffdrive_moving_obstacle`](experiments/25_diffdrive_moving_obstacle/) | TurtleBot3-Burger (Dynamic Disks) | Blind Trackers vs Obstacle-Aware Planners | CEM derivative-free sampling navigates around non-convex obstacle fields ($36$ collision steps) where iLQR gradient fails to clear ($69$ steps). |
|
|
75
|
+
| **26** | [`26_harder_reference_paths`](experiments/26_harder_reference_paths/) | Crazyflie 2.0 (Lissajous, Spiral) | iLQR vs Sampling MPC across Geometries | iLQR beats CEM by $32\times\text{--}840\times$ RMS error; CEM latency ($28\text{--}31\,\text{ms}$) violates $20\,\text{ms}$ flight budget on all paths. |
|
|
76
|
+
| **27** | [`27_bicycle_double_lane_change`](experiments/27_bicycle_double_lane_change/) | Dynamic Bicycle Sedan | Stanley vs LQR vs Kinematic MPC vs BC RL | Kinematic MPC wins nominal ($52.5\,\text{mm}$); Stanley wins Pacejka $\mu=0.6$ ($734\,\text{mm}$); BC RL fails off-road ($5.22\,\text{m}$ RMS). |
|
|
77
|
+
| **28** | [`28_furuta_pendulum_control`](experiments/28_furuta_pendulum_control/) | Furuta Rotary Pendulum (QUBE-2) | LQR vs Linear MPC vs Energy Swing-Up | Upright stabilization in $40\,\text{ms}$ ($e_{ss} < 6\times 10^{-7}\,\text{rad}$); MPC caps torque ($0.1343\,\text{N}\cdot\text{m}$); Swing-up in $6.0\,\text{s}$. |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Framework Architecture & Package Layout
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
src/aimct/
|
|
85
|
+
systems/ DynamicalSystem base + LinearSystem, MassSpringDamper,
|
|
86
|
+
Pendulum, CartPole, PlanarQuadrotor (Crazyflie 2.0), DCMotor,
|
|
87
|
+
DifferentialDriveRobot, TwoLinkArm, BicycleVehicle,
|
|
88
|
+
FurutaPendulum
|
|
89
|
+
simulate.py rk4_step(), simulate() -> Trajectory(t, x, u, y)
|
|
90
|
+
controllers/ PID, StateFeedback, LQR, ObserverFeedback, MRAC, ComputedTorque,
|
|
91
|
+
EnergyShapingSwingUp, HybridSwingUpLQR,
|
|
92
|
+
LinearMPC (with preview), SamplingMPC (CEM + obstacles),
|
|
93
|
+
ILQR (trajectory optimiser + real-time-iteration NMPC)
|
|
94
|
+
estimation/ LuenbergerObserver, KalmanFilter (LQE/FARE), DiscreteKalmanFilter,
|
|
95
|
+
ExtendedKalmanFilter, UnscentedKalmanFilter, observability_matrix
|
|
96
|
+
trajectories/ Lemniscate, Spline, Minimum-Jerk Polynomials, Dubins, Lissajous, Spiral, Rose
|
|
97
|
+
sysid/ least_squares_id, dmdc, to_continuous (block logm), prediction_error
|
|
98
|
+
ml/ MLP (backprop + Adam), LearnedDynamics (grey-box / residual)
|
|
99
|
+
rl/ ControlEnv (Gymnasium adapter), Discretizer, QLearning, DQN, REINFORCE, PPO
|
|
100
|
+
hybrid/ ShieldedController (switch/filter blends, predicate helpers)
|
|
101
|
+
viz/ SystemArtist contract, animate() replay engine, Sandbox live GUI
|
|
102
|
+
dev/ Design-time preview dashboard (poles, controllability, Jacobian residuals)
|
|
103
|
+
benchmarks/ metrics.py (13 metrics), harness.py, sweep.py, challenge.py, tracking.py
|
|
104
|
+
plot_style.py Okabe-Ito color palette + publication-ready 4-panel comparison figures
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## The Core Engineering Cycle
|
|
110
|
+
|
|
111
|
+
Every method follows the same rigorous pipeline:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
THEORY → DERIVATION → IMPLEMENTATION → SIMULATION → VISUALISATION → VALIDATION → COMPARISON → EXPERIMENT
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
1. **Understand the mathematics:** First-principles ODEs, Riccati equations, Lyapunov stability, Hamiltonians, Hamilton-Jacobi-Bellman, GAE.
|
|
118
|
+
2. **Build from scratch:** No black-box library magic in core algorithms. Custom Hamiltonian Schur CARE solver, custom active-set QP solver, custom backpropagation + Adam, custom sigma-point UKF, custom PPO actor-critic.
|
|
119
|
+
3. **Validate against reality:** Hard actuator saturation, sensor noise, latency, parameter drift, unmeasured states, non-convex keep-out zones.
|
|
120
|
+
4. **Compare honestly:** Side-by-side Pareto tables under identical random seeds, step sizes, and initial conditions.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Learning Curriculum
|
|
125
|
+
|
|
126
|
+
| Module | Topic | Description |
|
|
127
|
+
| :--- | :--- | :--- |
|
|
128
|
+
| **[01](modules/01-mathematical-foundations)** | Mathematical Foundations | Linear algebra, matrix exponential, RK4 integration, numerical optimization. |
|
|
129
|
+
| **[02](modules/02-dynamic-system-modeling)** | Dynamic System Modeling | First-principles physics, state-space representations, Jacobian linearisation. |
|
|
130
|
+
| **[03](modules/03-classical-control)** | Classical Control | Filtered derivative PID, conditional anti-windup clamping, frequency response. |
|
|
131
|
+
| **[04](modules/04-modern-control)** | Modern Control & Estimation | Controllability, observability, Ackermann pole placement, Luenberger observers, Kalman filters (linear, EKF, UKF). |
|
|
132
|
+
| **[05](modules/05-optimal-control)** | Optimal & Constrained Control | Algebraic Riccati equations (CARE/DARE), LQR robustness margins, constrained active-set Model Predictive Control. |
|
|
133
|
+
| **[06](modules/06-machine-learning)** | ML for Dynamical Systems | Least-squares SysID, DMDc, neural MLP backprop + Adam, residual LearnedDynamics, sampling-based MPC (CEM). |
|
|
134
|
+
| **[07](modules/07-reinforcement-learning)** | Reinforcement Learning | Gymnasium `ControlEnv`, Tabular Q-Learning, Deep Q-Networks (DQN), REINFORCE, and Proximal Policy Optimization (PPO). |
|
|
135
|
+
| **[08](modules/08-ai-plus-control)** | AI + Control (Hybrid Safety) | Supervisory safety shielding, action filtering, control barrier functions, auditable intervention logging. |
|
|
136
|
+
| **[09](modules/09-robotics-capstones)** | Robotics Capstones | Full 6-state Crazyflie 2.0 Quadrotor, differential flatness inversion, Bryson scaling, EKF output feedback, MRAC, obstacle NMPC. |
|
|
137
|
+
| **[10](modules/10-intelligent-control-challenge)** | Intelligent Control Challenge | Standardized black-box multi-track benchmark engine and cross-paradigm leaderboard. |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Status: Phase 2 Complete (Phase 3 Planned) 🚀
|
|
142
|
+
|
|
143
|
+
The core curriculum (Modules 01–10), 28 empirical benchmark experiments, living technical report, unified visualization layer (`aimct.viz`), design-time preview dashboard (`aimct.dev`), and 7 interactive sandboxes are complete with **418 passing unit tests** across Python 3.10–3.13.
|
|
144
|
+
|
|
145
|
+
**Phase 2 Delivered:**
|
|
146
|
+
- **Track A (Real Systems):** Differential-drive mobile robots (Exp 22 path tracking, Exp 25 dynamic obstacle avoidance), 2-link planar manipulator arms (Exp 23 computed torque & Slotine–Li payload adaptation), dynamic bicycle vehicles (Exp 27 ISO-3888 double lane change with linear vs. Pacejka tire models), and Furuta rotary inverted pendulums (Exp 28 Quanser QUBE-Servo 2 benchmark).
|
|
147
|
+
- **Track B (Algorithmic Depth):** Real-time iteration Nonlinear MPC (Exp 24, 26, 25 iLQR / RTI-NMPC vs. Sampling MPC).
|
|
148
|
+
- **Track C & D:** Reusable trajectory generation suite (`aimct.trajectories`), tracking benchmark harness (`aimct.benchmarks.tracking`), unified visualization (`aimct.viz`), design-time preview (`aimct.dev`), and PyPI distribution packaging (`aimct`).
|
|
149
|
+
|
|
150
|
+
**Phase 3 (Planned):**
|
|
151
|
+
Hardware-in-the-loop (HIL) physical deployment, flight log telemetry ingestion (CFclient/ROS2), dynamic bicycle vehicle model, Soft Actor-Critic (SAC), and direct collocation trajectory optimization.
|
|
152
|
+
|
|
153
|
+
See [`docs/roadmap.md`](docs/roadmap.md) for detailed deliverables and development history.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Contributing
|
|
158
|
+
|
|
159
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow and engineering
|
|
160
|
+
agreement, and the [Code of Conduct](CODE_OF_CONDUCT.md). Found a security
|
|
161
|
+
issue? See [SECURITY.md](SECURITY.md) for how to report it privately.
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aimct"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "AI Meets Control Theory — A rigorous, code-first bridge from classical feedback control to modern machine learning and safe reinforcement learning"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Zalih Thomas", email = "zalihthomas@gmail.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"control-theory",
|
|
17
|
+
"reinforcement-learning",
|
|
18
|
+
"optimal-control",
|
|
19
|
+
"lqr",
|
|
20
|
+
"mpc",
|
|
21
|
+
"neural-odes",
|
|
22
|
+
"sindy",
|
|
23
|
+
"control-barrier-functions",
|
|
24
|
+
"robotics",
|
|
25
|
+
"dynamical-systems",
|
|
26
|
+
]
|
|
27
|
+
classifiers = [
|
|
28
|
+
"Development Status :: 4 - Beta",
|
|
29
|
+
"Intended Audience :: Science/Research",
|
|
30
|
+
"Intended Audience :: Developers",
|
|
31
|
+
"License :: OSI Approved :: MIT License",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
38
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
39
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
40
|
+
]
|
|
41
|
+
dependencies = [
|
|
42
|
+
"numpy>=1.26",
|
|
43
|
+
"scipy>=1.11",
|
|
44
|
+
"matplotlib>=3.8",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
# python-control: used to cross-check from-scratch implementations. The core
|
|
49
|
+
# library still must not import it at runtime — keep it test-only.
|
|
50
|
+
xcheck = ["control>=0.10"]
|
|
51
|
+
ml = [
|
|
52
|
+
"torch>=2.2",
|
|
53
|
+
"gymnasium>=1.0",
|
|
54
|
+
"stable-baselines3>=2.0",
|
|
55
|
+
]
|
|
56
|
+
viz = ["pyvista>=0.44"]
|
|
57
|
+
dev = [
|
|
58
|
+
"pytest>=8.0",
|
|
59
|
+
"build>=1.0",
|
|
60
|
+
"twine>=5.0",
|
|
61
|
+
"control>=0.10",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[project.scripts]
|
|
65
|
+
aimct = "aimct.__main__:main"
|
|
66
|
+
|
|
67
|
+
[project.urls]
|
|
68
|
+
Homepage = "https://github.com/zalihthomas-ui/ai-meets-control-theory"
|
|
69
|
+
Documentation = "https://github.com/zalihthomas-ui/ai-meets-control-theory#readme"
|
|
70
|
+
Repository = "https://github.com/zalihthomas-ui/ai-meets-control-theory.git"
|
|
71
|
+
"Bug Tracker" = "https://github.com/zalihthomas-ui/ai-meets-control-theory/issues"
|
|
72
|
+
Changelog = "https://github.com/zalihthomas-ui/ai-meets-control-theory/blob/main/CHANGELOG.md"
|
|
73
|
+
|
|
74
|
+
[tool.setuptools.dynamic]
|
|
75
|
+
version = { attr = "aimct.__version__" }
|
|
76
|
+
|
|
77
|
+
[tool.setuptools.packages.find]
|
|
78
|
+
where = ["src"]
|
|
79
|
+
|
|
80
|
+
[tool.pytest.ini_options]
|
|
81
|
+
testpaths = ["tests"]
|
|
82
|
+
markers = [
|
|
83
|
+
"slow: heavy RL / learned-model training tests (minutes). Skip with -m 'not slow'.",
|
|
84
|
+
]
|
aimct-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""AI Meets Control Theory — reusable library.
|
|
2
|
+
|
|
3
|
+
Subpackages
|
|
4
|
+
-----------
|
|
5
|
+
systems : dynamical-system models with a common interface
|
|
6
|
+
controllers : PID, state feedback, LQR, MPC, neural, RL policies
|
|
7
|
+
estimation : observers, Kalman filters
|
|
8
|
+
ml : learned dynamics, surrogate models
|
|
9
|
+
rl : agents and environments
|
|
10
|
+
benchmarks : standardized systems + controller comparison harness
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|