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.
Files changed (124) hide show
  1. aimct-0.1.0/CHANGELOG.md +94 -0
  2. aimct-0.1.0/LICENSE +21 -0
  3. aimct-0.1.0/MANIFEST.in +18 -0
  4. aimct-0.1.0/PKG-INFO +210 -0
  5. aimct-0.1.0/README.md +165 -0
  6. aimct-0.1.0/pyproject.toml +84 -0
  7. aimct-0.1.0/setup.cfg +4 -0
  8. aimct-0.1.0/src/aimct/__init__.py +13 -0
  9. aimct-0.1.0/src/aimct/__main__.py +203 -0
  10. aimct-0.1.0/src/aimct/benchmarks/__init__.py +96 -0
  11. aimct-0.1.0/src/aimct/benchmarks/capstone_scoring.py +174 -0
  12. aimct-0.1.0/src/aimct/benchmarks/challenge.py +748 -0
  13. aimct-0.1.0/src/aimct/benchmarks/challenge_scoring.py +222 -0
  14. aimct-0.1.0/src/aimct/benchmarks/challenge_wrappers.py +289 -0
  15. aimct-0.1.0/src/aimct/benchmarks/harness.py +391 -0
  16. aimct-0.1.0/src/aimct/benchmarks/metrics.py +272 -0
  17. aimct-0.1.0/src/aimct/benchmarks/sweep.py +325 -0
  18. aimct-0.1.0/src/aimct/benchmarks/tracking.py +164 -0
  19. aimct-0.1.0/src/aimct/controllers/__init__.py +52 -0
  20. aimct-0.1.0/src/aimct/controllers/_qp.py +163 -0
  21. aimct-0.1.0/src/aimct/controllers/adaptive.py +178 -0
  22. aimct-0.1.0/src/aimct/controllers/base.py +57 -0
  23. aimct-0.1.0/src/aimct/controllers/ilqr.py +480 -0
  24. aimct-0.1.0/src/aimct/controllers/lqr.py +168 -0
  25. aimct-0.1.0/src/aimct/controllers/mpc.py +315 -0
  26. aimct-0.1.0/src/aimct/controllers/observer_feedback.py +127 -0
  27. aimct-0.1.0/src/aimct/controllers/pid.py +240 -0
  28. aimct-0.1.0/src/aimct/controllers/sampling_mpc.py +125 -0
  29. aimct-0.1.0/src/aimct/controllers/state_feedback.py +196 -0
  30. aimct-0.1.0/src/aimct/controllers/swingup.py +218 -0
  31. aimct-0.1.0/src/aimct/dev/__init__.py +14 -0
  32. aimct-0.1.0/src/aimct/dev/__main__.py +46 -0
  33. aimct-0.1.0/src/aimct/dev/preview.py +331 -0
  34. aimct-0.1.0/src/aimct/estimation/__init__.py +29 -0
  35. aimct-0.1.0/src/aimct/estimation/ekf.py +180 -0
  36. aimct-0.1.0/src/aimct/estimation/kalman.py +110 -0
  37. aimct-0.1.0/src/aimct/estimation/luenberger.py +94 -0
  38. aimct-0.1.0/src/aimct/estimation/observability.py +38 -0
  39. aimct-0.1.0/src/aimct/estimation/ukf.py +153 -0
  40. aimct-0.1.0/src/aimct/hybrid/__init__.py +9 -0
  41. aimct-0.1.0/src/aimct/hybrid/shield.py +174 -0
  42. aimct-0.1.0/src/aimct/ml/__init__.py +14 -0
  43. aimct-0.1.0/src/aimct/ml/dynamics.py +120 -0
  44. aimct-0.1.0/src/aimct/ml/mlp.py +125 -0
  45. aimct-0.1.0/src/aimct/ml/planning.py +119 -0
  46. aimct-0.1.0/src/aimct/plot_style.py +257 -0
  47. aimct-0.1.0/src/aimct/rl/__init__.py +38 -0
  48. aimct-0.1.0/src/aimct/rl/dqn.py +209 -0
  49. aimct-0.1.0/src/aimct/rl/env.py +343 -0
  50. aimct-0.1.0/src/aimct/rl/policy_gradient.py +186 -0
  51. aimct-0.1.0/src/aimct/rl/ppo.py +189 -0
  52. aimct-0.1.0/src/aimct/rl/tabular.py +257 -0
  53. aimct-0.1.0/src/aimct/simulate.py +132 -0
  54. aimct-0.1.0/src/aimct/study.py +108 -0
  55. aimct-0.1.0/src/aimct/sysid/__init__.py +23 -0
  56. aimct-0.1.0/src/aimct/sysid/linear.py +145 -0
  57. aimct-0.1.0/src/aimct/systems/__init__.py +31 -0
  58. aimct-0.1.0/src/aimct/systems/base.py +81 -0
  59. aimct-0.1.0/src/aimct/systems/bicycle.py +122 -0
  60. aimct-0.1.0/src/aimct/systems/cartpole.py +64 -0
  61. aimct-0.1.0/src/aimct/systems/dc_motor.py +91 -0
  62. aimct-0.1.0/src/aimct/systems/diffdrive.py +113 -0
  63. aimct-0.1.0/src/aimct/systems/furuta_pendulum.py +193 -0
  64. aimct-0.1.0/src/aimct/systems/linear.py +46 -0
  65. aimct-0.1.0/src/aimct/systems/mass_spring_damper.py +28 -0
  66. aimct-0.1.0/src/aimct/systems/pendulum.py +53 -0
  67. aimct-0.1.0/src/aimct/systems/quadrotor.py +83 -0
  68. aimct-0.1.0/src/aimct/systems/quadrotor3d.py +112 -0
  69. aimct-0.1.0/src/aimct/systems/twolink_arm.py +126 -0
  70. aimct-0.1.0/src/aimct/trajectories.py +297 -0
  71. aimct-0.1.0/src/aimct/viz/__init__.py +41 -0
  72. aimct-0.1.0/src/aimct/viz/artists.py +585 -0
  73. aimct-0.1.0/src/aimct/viz/hud.py +55 -0
  74. aimct-0.1.0/src/aimct/viz/pv_arm.py +219 -0
  75. aimct-0.1.0/src/aimct/viz/replay.py +205 -0
  76. aimct-0.1.0/src/aimct/viz/sandbox.py +335 -0
  77. aimct-0.1.0/src/aimct.egg-info/PKG-INFO +210 -0
  78. aimct-0.1.0/src/aimct.egg-info/SOURCES.txt +122 -0
  79. aimct-0.1.0/src/aimct.egg-info/dependency_links.txt +1 -0
  80. aimct-0.1.0/src/aimct.egg-info/entry_points.txt +2 -0
  81. aimct-0.1.0/src/aimct.egg-info/requires.txt +20 -0
  82. aimct-0.1.0/src/aimct.egg-info/top_level.txt +1 -0
  83. aimct-0.1.0/tests/test_adaptive.py +112 -0
  84. aimct-0.1.0/tests/test_benchmark_harness.py +236 -0
  85. aimct-0.1.0/tests/test_benchmark_metrics.py +259 -0
  86. aimct-0.1.0/tests/test_benchmark_sweep.py +198 -0
  87. aimct-0.1.0/tests/test_bicycle.py +110 -0
  88. aimct-0.1.0/tests/test_capstone_scoring.py +103 -0
  89. aimct-0.1.0/tests/test_challenge.py +166 -0
  90. aimct-0.1.0/tests/test_challenge_scoring_and_wrappers.py +171 -0
  91. aimct-0.1.0/tests/test_dc_motor.py +64 -0
  92. aimct-0.1.0/tests/test_dev_preview.py +241 -0
  93. aimct-0.1.0/tests/test_diffdrive.py +101 -0
  94. aimct-0.1.0/tests/test_dqn.py +55 -0
  95. aimct-0.1.0/tests/test_ekf.py +230 -0
  96. aimct-0.1.0/tests/test_estimation.py +133 -0
  97. aimct-0.1.0/tests/test_furuta_pendulum.py +114 -0
  98. aimct-0.1.0/tests/test_ilqr.py +137 -0
  99. aimct-0.1.0/tests/test_live_drone.py +64 -0
  100. aimct-0.1.0/tests/test_live_drone_3d.py +102 -0
  101. aimct-0.1.0/tests/test_live_sandboxes.py +164 -0
  102. aimct-0.1.0/tests/test_lqr.py +160 -0
  103. aimct-0.1.0/tests/test_ml.py +170 -0
  104. aimct-0.1.0/tests/test_mpc.py +244 -0
  105. aimct-0.1.0/tests/test_observer_feedback.py +186 -0
  106. aimct-0.1.0/tests/test_pid.py +301 -0
  107. aimct-0.1.0/tests/test_policy_gradient.py +114 -0
  108. aimct-0.1.0/tests/test_ppo.py +67 -0
  109. aimct-0.1.0/tests/test_pv_arm.py +107 -0
  110. aimct-0.1.0/tests/test_qp.py +101 -0
  111. aimct-0.1.0/tests/test_quadrotor.py +68 -0
  112. aimct-0.1.0/tests/test_quadrotor3d.py +60 -0
  113. aimct-0.1.0/tests/test_rl_env.py +199 -0
  114. aimct-0.1.0/tests/test_rl_tabular.py +96 -0
  115. aimct-0.1.0/tests/test_shield.py +182 -0
  116. aimct-0.1.0/tests/test_state_feedback.py +164 -0
  117. aimct-0.1.0/tests/test_study.py +64 -0
  118. aimct-0.1.0/tests/test_swingup.py +154 -0
  119. aimct-0.1.0/tests/test_sysid.py +117 -0
  120. aimct-0.1.0/tests/test_systems_simulate.py +72 -0
  121. aimct-0.1.0/tests/test_trajectories.py +113 -0
  122. aimct-0.1.0/tests/test_twolink_arm.py +110 -0
  123. aimct-0.1.0/tests/test_ukf.py +181 -0
  124. aimct-0.1.0/tests/test_viz.py +249 -0
@@ -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.
@@ -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
+ [![CI](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml/badge.svg)](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml)
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
52
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](pyproject.toml)
53
+ [![Report: Living PDF](https://img.shields.io/badge/Report-Living%20PDF-brightgreen)](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)** &nbsp;|&nbsp; 📖 **[User Guide & API Recipes](docs/USAGE.md)** &nbsp;|&nbsp; 🎨 **[Unified Visualization](docs/VISUALIZATION.md)** &nbsp;|&nbsp; 📊 **[Master Results & Verdicts Table](docs/RESULTS.md)** &nbsp;|&nbsp; 🧭 **[Engineering Decision Guide](docs/DECISION-GUIDE.md)** &nbsp;|&nbsp; 🚁 **[Live 3D WebGL Sandbox](https://claude.ai/code/artifact/69b12b78-d7b2-4732-a7af-2af14930139b)** &nbsp;|&nbsp; 🎯 **[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
+ [![CI](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml/badge.svg)](https://github.com/zalihthomas-ui/ai-meets-control-theory/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](pyproject.toml)
8
+ [![Report: Living PDF](https://img.shields.io/badge/Report-Living%20PDF-brightgreen)](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)** &nbsp;|&nbsp; 📖 **[User Guide & API Recipes](docs/USAGE.md)** &nbsp;|&nbsp; 🎨 **[Unified Visualization](docs/VISUALIZATION.md)** &nbsp;|&nbsp; 📊 **[Master Results & Verdicts Table](docs/RESULTS.md)** &nbsp;|&nbsp; 🧭 **[Engineering Decision Guide](docs/DECISION-GUIDE.md)** &nbsp;|&nbsp; 🚁 **[Live 3D WebGL Sandbox](https://claude.ai/code/artifact/69b12b78-d7b2-4732-a7af-2af14930139b)** &nbsp;|&nbsp; 🎯 **[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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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"