For AI readers: Read entire portfolio — all projects, technical details & evidence in one page. Plain text · GitHub fallback

← Flagship work
04 / Control engineering2025–2026

Measured C++ control

Built a C++20 control core with explicit actuator limits and state-consistent controller switching.

SystemC++ control runtime
My contributionControl-library design & implementation
AccessPublic implementation
Engineering & evidence

Arena-backed controller state, bumpless transfer and timing sweeps over 1–64 channels.

Recorded position response settles within ±2% at 342 ms in a simulated integrator plant. Response plots, percentiles and source CSVs are public.

Recorded measurements

Control response.
Execution cost.

Position tracking, cascade response and controller-update timing from the toolkit’s recorded CSV artifacts.

Step response

Position response and applied command across 1000 samples, including the setpoint and 2 percent settling band
Position-control example · 1 ms model step · 1,000 samples. Recorded response enters and stays in the ±2% band at 342 ms. This is a simulated integrator plant.
Cascade position and velocity response with the applied actuator command
Cascade example · 1 ms model step · 1,000 samples. Position overshoot 0.0904%; ±2% settling at 420 ms.

Latency

Recorded p50 p95 and p99 nanoseconds per update for 1 4 8 16 32 and 64 channels, showing both recorded sweeps
Raw PID + loop + timer measurements from both recorded sweeps. Each record summarises 200,000 timing batches, with 64 updates per batch after 10,000 warm-up updates.

This is an amortised update microbenchmark, not scheduler jitter or end-to-end robot latency. Hardware identity and run flags are absent from the CSV. The two recorded sweeps are shown separately; neither is labelled as a safety-on/off comparison.

Exact recorded percentiles
SweepChannelsp50 nsp95 nsp99 nsp99.9 ns
A151.18852.46965.39176.453
A4161.922196.578224.828262.828
A8294.859330.453356.469426.766
A16578.672638.422698.125823.578
A321130.0941267.7031332.9221566.734
A642297.4842576.2032643.0473201.656
B156.48463.20374.12592.547
B4173.578191.141210.203251.016
B8318.266424.547471.344491.781
B16629.359705.469830.547941.734
B321259.1091411.2661486.0621839.609
B642508.8442809.5622860.5473436.656
Technical deep dive Architecture, implementation & tradeoffs
System architecture
C++20 / fixed-period control

The actuator limit feeds back into state.

  1. 01

    Compute

    u_raw = P + I + D + FF

    Setpoint weighting, gain scheduling and Tustin-discretised derivative filtering.

  2. 02

    Constrain

    saturate → rate → jerk

    Preserve each stage’s effect and the final applied command.

  3. 03

    Reconcile

    u_applied − u_raw

    Feed constraint error into anti-windup; align internal state on transfer.

  4. 04

    Supervise

    health + watchdog

    Track timing, limiting hits and fallback state with the output.

Lifecycle
Initialise → start → update → stop / reset
Memory
Arena-allocated workspaces reused on the update path
Recording
JSONL · MCAP · FlatBuffers · integrity checks
01 / Implementation

Execution architecture

  • Allocated working buffers from a memory arena during initialisation and reused them on the update path.
  • Defined controller dimensions, start/stop/reset lifecycle, measurement-validity masks, fixed-tick timing and runtime health.
  • Preserved the unconstrained and constrained commands separately so each limiting stage can report its effect.
02 / Implementation

Control and constraints

  • Implemented setpoint weighting, feedforward bias and a filtered derivative with Tustin discretisation.
  • Added gain scheduling over configured breakpoints, with interpolation of gains and weights.
  • Composed saturation, slew-rate and jerk constraints before anti-windup, plus bumpless state alignment and watchdog/fallback components.
03 / Implementation

Inspectability

  • Included checks for derivative kick, bumpless transfer, saturation, rate and jerk behaviour, scheduling and deterministic execution.
  • Built JSONL and MCAP evidence-recorder paths, a FlatBuffers schema, hash/round-trip checks and example traces.
  • Kept runtime health attached to the output: deadline misses, clamp magnitudes, limiting hits and anti-windup correction magnitude.
Engineering note

The integrator must see the command that survives the constraints.

A controller can request far more than an actuator is allowed to deliver. Updating its internal state as though the raw request was executed creates a mismatch. The core preserves both values and feeds their difference into the anti-windup path after saturation, rate and jerk limiting.

Project context

The implemented controller family is PID/IMC-PID. Broader controllers described in the repository roadmap are ongoing work.

Keep exploring

One world. Multiple robots.

Multi-robot autonomy runtime