# Design Document 06 — Contributor-Facing Roadmap Status: Accepted (Milestone 1) This roadmap translates the design (docs 01–05) into ordered, independently shippable milestones. Each milestone lists its scope, acceptance criteria, and the design sections it implements. Dependencies flow strictly downward — a contributor can pick up any milestone whose predecessors are merged. --- ## Milestone overview | # | Title | Depends on | Outcome | |---|---|---|---| | 1 | Architecture & API design | — | This document set + API stubs (**done**) | | 2 | Core data models & PID controller | 1 | `models/`, `controllers/` fully implemented + tested | | 3 | Classical rule-based tuners | 2 | ZN (both forms), Cohen-Coon, AMIGO, IMC/SIMC | | 4 | Simulation engine & metrics | 2 | Plant/loop/signals, IAE/ISE/ITAE/etc., plotting helpers | | 5 | Relay autotuning & step-response identification | 3, 4 | Relay experiment runner, FOPDT/SOPDT fitting | | 6 | Optimization-based tuning | 4 | Constrained gain optimization (Ms, margins) | | 7 | Documentation site, CLI & 1.0 release | 3–6 | Sphinx docs, `pidtune` CLI, PyPI 1.0.0 | --- ## Milestone 2 — Core data models & PID controller Implements: doc 02 §all, doc 04 §controllers. * Implement `FOPDT`, `SOPDT`, `TransferFunction`: step response (analytic where closed forms exist, `scipy.signal` otherwise), frequency response, Padé-approximated dead time for state-space export, serialization (`to_dict`/`from_dict`). * Implement `PIDController`: positional/velocity forms, derivative filtering (N coefficient), anti-windup (back-calculation and clamping), bumpless parameter changes, setpoint weighting (b, c), ideal↔parallel↔series gain conversions in `gains.py`. * **Acceptance:** ≥95% branch coverage on `models/` and `controllers/`; property-based tests (Hypothesis) for gain-form round-trips; step responses validated against `scipy.signal.lsim` references to 1e-6 relative tolerance. ## Milestone 3 — Classical rule-based tuners Implements: doc 03 §2–5, doc 04 §tuners. * Implement the formula tables for ZN step & ultimate, Tyreus-Luyben, Cohen-Coon, AMIGO (PI and PID, stable + integrating cases), IMC/lambda and SIMC. * Applicability-range warnings per doc 05 §2.1; ultimate-point computation from model frequency response for `ZieglerNicholsUltimateTuner.tune(model)`. * **Acceptance:** every published table row reproduced by a unit test against the cited reference values (Åström & Hägglund 2006; O'Dwyer's handbook); all tuners registered and resolvable by name. ## Milestone 4 — Simulation engine & metrics Implements: doc 01 §simulation layer, doc 04 §simulation/§metrics. * `Plant` adapters for every `ProcessModel` (discretized with configurable hold and ring buffer for dead time); `simulate_closed_loop()` returning a `SimulationResult` with time, setpoint, output, control, and error arrays. * Signals: step, ramp, pulse, PRBS, sine, composite; load-disturbance and measurement noise injection points. * Metrics: IAE, ISE, ITAE, ITSE, overshoot, rise/settling time, control effort & total variation; metric registry per doc 05 §5.3. * Optional `matplotlib` plotting helpers behind the `[plot]` extra. * **Acceptance:** closed-loop simulation of FOPDT + PI matches an analytically derivable case to 1e-4; PRBS spectral flatness test; metrics validated on hand-computed traces. ## Milestone 5 — Relay autotuning & identification Implements: doc 03 §6, doc 04 §relay/§identification. * Relay experiment runner working against any `Plant` (simulated or user-supplied hardware adapter): hysteresis relay, oscillation detection (zero-crossing + amplitude convergence criterion), describing-function extraction of (Ku, Pu), asymmetric-relay extension yielding a FOPDT estimate. * Step-response identification: tangent, two-point (28.3/63.2%), and area methods for FOPDT; least-squares refinement via `scipy.optimize.least_squares`; fit-quality report (`ModelFitWarning` thresholds). * **Acceptance:** relay on simulated FOPDT recovers Ku, Pu within 5% of frequency-domain truth across a θ/τ grid; identification round-trips synthetic noisy data. ## Milestone 6 — Optimization-based tuning Implements: doc 03 §7, doc 04 §optimization. * Objective evaluation by closed-loop simulation (IAE/ISE/ITAE/ITSE on setpoint and/or load-disturbance scenarios), constraints on maximum sensitivity Ms, gain/phase margins via frequency response. * Backends: `scipy.optimize.minimize` (Nelder-Mead default) and `differential_evolution`; warm starts from a rule-based tuner; `ConvergenceError` with partial results per doc 05. * **Acceptance:** optimizer beats AMIGO's IAE on a benchmark batch of 20 FOPDT models while respecting Ms ≤ 1.4; deterministic with fixed seeds. ## Milestone 7 — Docs, CLI & 1.0 * Sphinx site (API reference from docstrings, tutorial notebooks: "tune from a step test", "relay autotune a simulated plant", "optimize with constraints"). * `pidtune` CLI: `pidtune fit step.csv`, `pidtune tune --method amigo --model ...`, `pidtune simulate ...` emitting JSON/CSV. * Packaging hardening: wheels, `py.typed` marker, CI matrix (CPython 3.9–3.13, Linux/ macOS/Windows), 1.0.0 release with the doc-05 stability promise activated. --- ## Engineering conventions (all milestones) * **Testing:** pytest + Hypothesis; numerical comparisons via `numpy.testing`; every bug fix lands with a regression test. * **Style/static checks:** ruff (lint + format), mypy `--strict` on `src/`; full type hints are mandatory in public modules. * **CI:** GitHub Actions — lint, type-check, test matrix, coverage gate (≥90% project wide from Milestone 3 onward), docs build. * **Branching:** trunk-based; PRs require one maintainer review; squash merges with Conventional Commits messages feeding an auto-generated changelog. * **Governance:** design changes amend docs 01–05 in the same PR as the code; ADR-style "Status/Depends on" headers as used in this set. ## How to contribute right now 1. Read docs 01–04, then pick an unclaimed task from the milestone matching the current project phase (tracked as GitHub milestone labels `M2`…`M7`). 2. Comment on the issue to claim it; small PRs (< 500 lines) merge fastest. 3. Stub files in `src/pidtune/` carry complete docstrings describing exact expected behavior — implementing a stub means making its docstring true and its tests pass.