Skip to content
Back to Projects

Extremum-Seeking Control for Nanometer-Scale Localization

April 2, 2026Completedacademic
control-systems matlab experimental

Overview

This project was completed individually for 4CM120 — Data-Based Optimization of Control Systems (TU Eindhoven, MSc Mechanical Engineering, Feb–Apr 2026). Taught by Dr.ir. Thijs van Keulen and Dr.ir. Leroy Hazeleger, the course studies real-time, model-free optimization for high-tech mechatronic systems.

The problem — nanometer-scale localization of a moving stage with respect to a reference frame — is directly relevant to atomic force microscopes and lithography machines, where fast and accurate alignment is critical. The approach implemented here is based on the patent by Van Keulen et al. (2021, Method of controlling a position of a first object relative to a second object, PCT/EP2020/070979).

Steady-state performance mapping Q_J(x) with global maximum at x* = 120 rad

The objective function is the light intensity measured by a photodiode on the moving body as it passes under a fixed reference lens:

J=QJ(x):=0.021+0.533e3.5×104(x120)2J = Q_J(x) := 0.021 + 0.533 \cdot e^{-3.5 \times 10^{-4}(x - 120)^2}

This Gaussian has a unique maximum at x=120radx^* = 120\,\text{rad} with J=0.554J^* = 0.554. The goal of the ESC controller is to find this peak without any analytical model of QJQ_J — using only the measured intensity signal J(t)J(t).

The Assignment

The project is split into two deliverables — both embedded below:

Assignment 1 — ESC in simulation
Assignment 2 — ESC on physical hardware

The Plant Model

The moving stage uses a combination of feedforward and feedback control to follow a reference position rr. The underlying fourth-order transfer function from input force uu to position xx is:

P(s)=s2+566s+7.564×1064.396×105s4+2.399×102s3+420.1s2+1.293×104sP(s) = \frac{s^2 + 566s + 7.564 \times 10^6}{4.396 \times 10^{-5} s^4 + 2.399 \times 10^{-2} s^3 + 420.1 s^2 + 1.293 \times 10^4 s}

with a PD + second-order Low-Pass feedback controller:

Cpd(s)=(kds+kp)ωlp2s2+2ζlpωlps+ωlp2C_\text{pd}(s) = \frac{(k_d s + k_p)\omega_\text{lp}^2}{s^2 + 2\zeta_\text{lp}\omega_\text{lp} s + \omega_\text{lp}^2}

where kp=0.05k_p = 0.05, kd=0.005k_d = 0.005, ωlp=400πrad/s\omega_\text{lp} = 400\pi\,\text{rad/s}, ζlp=0.7\zeta_\text{lp} = 0.7. The full loop runs discrete-time at Fs=4kHzF_s = 4\,\text{kHz} via zero-order-hold discretization.

Part I — Classical ESC in Simulation (Assignment 1)

How Extremum Seeking Control Works

ESC estimates the gradient of the unknown objective QJQ_J by injecting a sinusoidal dither signal acos(ωt)a\cos(\omega t) onto the reference. The measured output is then demodulated (multiplied by the same cosine) and filtered to extract the gradient component ξ(t)\xi(t). An integrator uses this estimate to steer the nominal position x^\hat{x} toward the optimum.

ESC feedback loop implemented in Simulink

The loop has five elements:

  1. Dither signalacos(ωt)a\cos(\omega t) added to x^\hat{x}
  2. High-pass filter HHP(s)=s/(s+ωf)H_\text{HP}(s) = s/(s + \omega_f) — removes DC
  3. Demodulation — multiplication by 2acos(ωt)\frac{2}{a}\cos(\omega t) extracts gradient information
  4. Low-pass filter HLP(s)=ωf/(s+ωf)H_\text{LP}(s) = \omega_f/(s + \omega_f) — smooths the estimate
  5. Integrator with gain kk — drives x^\hat{x} toward increasing JJ

A critical design constraint is the timescale separation: ωfωωBW\omega_f \ll \omega \ll \omega_\text{BW}.

Three frequencies on a log axis: filter cutoff ω_f at 1.95 rad/s, dither frequency ω at 6.28 rad/s (1 Hz), closed-loop bandwidth ω_BW at 67.3 rad/s. Each separated by ≪ to indicate the hierarchy required for classical ESC.

Tuned values from Q2 placed on a log-frequency axis. The filter cutoff sits below the dither (so HP/LP can extract DC), and both sit well below the closed-loop bandwidth (so the plant looks like a static map at ω\omega).

Unimodality Assumption (Q1)

For ESC to converge to the global optimum from any initial condition x0x_0, the objective function must be unimodal — i.e., have a single critical point. Since QJQ_J is Gaussian, QJ(120)<0Q_J''(120) < 0 and x120|x - 120| causes strict monotonic decrease in both directions. Only one zero of the gradient exists at x=120radx^* = 120\,\text{rad}, so the assumption is satisfied.

Optimal Parameters on the Static Map (Q2)

Starting from x0=10radx_0 = 10\,\text{rad} with ω=1Hz\omega = 1\,\text{Hz} prescribed, tuning converged on:

k=5000,a=4rad,ωf=1.95rad/sk = 5000, \quad a = 4\,\text{rad}, \quad \omega_f = 1.95\,\text{rad/s}
  • Convergence time: 17.3 s
  • Steady-state error: < 0.1 rad
  • Peak intensity reached: J=0.554J = 0.554

ESC convergence with optimal parameters

Measured vs. Analytical Objective (Q3)

The analytical QJQ_J was replaced with an experimentally measured objective function obtained by sweeping the stage slowly past the photodiode. Intensity values were binned into 0.5 rad intervals and averaged, producing a lookup table for Simulink interpolation.

Experimental sweep vs analytical Q_J

Key differences:

  • Peak offset: the experimental peak appears at x98radx \approx 98\,\text{rad} rather than 120rad120\,\text{rad} — an encoder-zero offset
  • Steeper slopes: the real lens-photodiode geometry produces sharper gradients near the peak
  • The analytical parameters caused divergence on the measured objective because the high filter cutoff created phase lag through the steeper gradient

Re-tuning for the measured case required a lower filter cutoff (ωf=1.01rad/s\omega_f = 1.01\,\text{rad/s}) and slightly adjusted gains (k=5250k = 5250, a=7rada = 7\,\text{rad}).

ESC convergence: analytical vs measured objective function

Lookup Table vs Analytical Function (Q3)

Lookup table comparison detail

Incorporating Plant Dynamics (Q5–Q7)

So far the plant was treated as a static map. In reality the moving stage has non-trivial dynamics: for ESC to work, the dynamic system G:rJG: r \to J must behave as a static map at the dither frequency — i.e., the closed-loop transfer function T(s)=x(s)/r(s)T(s) = x(s)/r(s) must satisfy:

T(jω)1andT(jω)0|T(j\omega)| \approx 1 \quad \text{and} \quad \angle T(j\omega) \approx 0^\circ

Bode plot of T(s)

The Bode plot confirms a closed-loop bandwidth of ωBW=67.3rad/s\omega_\text{BW} = 67.3\,\text{rad/s}. At the 1 Hz dither frequency (ω=6.28rad/s\omega = 6.28\,\text{rad/s}), T(jω)=0.66dB|T(j\omega)| = -0.66\,\text{dB} and T(jω)=9.3°\angle T(j\omega) = -9.3° — well within the static-map regime.

With dynamics and noise enabled (disturbances = true, dynamics = true), the ESC was re-calibrated:

k=3000,a=7.5rad,ωf=1.8rad/sk = 3000, \quad a = 7.5\,\text{rad}, \quad \omega_f = 1.8\,\text{rad/s}

ESC convergence with plant dynamics and noise

Despite the new constraints (phase lag, stage resonances, tighter filter speeds), convergence was achieved in ~20.8 s with all requirements met.

Part II — ESC on Physical Hardware (Assignment 2)

Assignment 2 took the simulation framework and deployed it on the real test setup — a motorized rotary stage with a photodiode. Three distinct ESC architectures were compared, both in simulation and on hardware:

  1. Classical ESC — sinusoidal dither with HP/LP filters
  2. Moving Average ESC — replaces the HP/LP filters with an exact moving average
  3. Sampled-Data ESC — discrete step perturbations with finite-difference gradients

Classical ESC on Hardware (C-Q1)

The Q7 simulation parameters were used as a starting point. Four experimental runs were performed on the physical setup.

All classical ESC experimental runs

The best run matched the Assignment 1 Q7 parameters exactly and converged in 9.1 s — over a second faster than the simulation (10.6 s), due to the steeper real gradient.

Encoder Offset Discovery

The physical encoder's zero position did not match the model's x=0x = 0. The system converged to r^ss6067rad\hat{r}_\text{ss} \approx 60\text{–}67\,\text{rad} rather than the model's 120 rad, but the peak intensities were identical (J0.555J \approx 0.555). Aligning the data with a ~53 rad offset confirmed the experimental shape follows the model Gaussian near the peak but with steeper slopes further out.

Model vs experimental objective function

Simulation vs. Experiment

Simulation vs experiment comparison

  • Convergence speed: within 1.5 s of each other, validating the model
  • Steady-state oscillations: smaller on the experiment (±0.03rad\pm 0.03\,\text{rad} vs. ±0.09rad\pm 0.09\,\text{rad}), suggesting additional unmodeled HF attenuation
  • Gradient estimate ξ(t)\xi(t): less volatile in simulation, hinting at unmodeled plant dynamics

Positioning-Accuracy Trade-off (C-Q2)

A subtle but important effect: the actual position is r(t)=r^(t)+acos(ωt)r(t) = \hat{r}(t) + a\cos(\omega t), so even when r^\hat{r} has converged exactly to xx^*, the position still oscillates by ±a\pm a around the optimum. If a>0.1rada > 0.1\,\text{rad}, the 0.1 rad positioning requirement is not met just by the nominal position alone.

Three levers affect accuracy:

  • Reduce aa — smaller dither reduces oscillation but weakens the gradient signal (noisier ξ\xi, slower convergence)
  • Reduce kk — less overshoot but slower convergence
  • Reduce ωf\omega_f — better noise rejection but slower gradient extraction

This creates a fundamental convergence-speed vs. positioning-accuracy trade-off. For the dither-based accuracy requirement r^x+a<0.1rad|\hat{r} - x^*| + a < 0.1\,\text{rad}, both a<0.1a < 0.1 and r^\hat{r} must converge tightly to xx^*.

Moving Average ESC (C-Q3 & C-Q4)

The moving average (MA) filter replaces the HP → demodulation → LP chain with a single operation: averaging the demodulated signal over exactly one dither period T=2π/ωT = 2\pi/\omega.

Moving average ESC Simulink implementation

The theoretical benefits are significant:

  • Exact gradient extraction — the MA over one cosine period is exactly zero, perfectly canceling the dither component and all harmonics
  • No phase lag — the classical HP/LP filters introduce phase lag arctan(ω/ωf)-\arctan(\omega/\omega_f); the MA has only a fixed T/2T/2 delay that is frequency-independent
  • Simpler tuning — only the window length TT needs to match the dither period
  • Higher dither frequencies possible — no strict ωfω\omega_f \ll \omega timescale separation required

MA Simulation Results

By exploiting the relaxed timescale constraint, the dither frequency was increased from ω=2π\omega = 2\pi to ω=24.5rad/s\omega = 24.5\,\text{rad/s}. The MA window shortened from T=1.0sT = 1.0\,\text{s} to T=0.26sT = 0.26\,\text{s}, enabling more aggressive tuning: k=24000k = 24000, a=15rada = 15\,\text{rad}. Simulation convergence: 3.9 s — a 5× improvement over the classical approach.

MA ESC simulation convergence

MA Experimental Results

Seven runs on the physical setup. The best run (MA2: k=35000k = 35000, a=5.8a = 5.8, f=10Hzf = 10\,\text{Hz}) converged in 1.3 s — a 7× speedup over the classical experiment (9.1 s).

Best MA experimental run (MA2) — detailed view

The MA approach proved sensitive to aggressive gain tuning: MA1 at k=45000k = 45000 went immediately unstable, showing the test setup has a lower maximum stable gain than simulation. Lower dither frequencies (2–5 Hz) converged significantly slower.

Classical vs. MA Head-to-Head

Classical vs MA on the test setup

SimulationExperiment
VariableClassicalMAClassicalMA
Convergence time [s]10.63.99.11.3
JssJ_\text{ss}0.5490.5400.5550.556
r^\hat{r} oscillation [rad]0.090.030.030.06

Sampled-Data ESC (SD-Q1 → SD-Q4)

The sampled-data approach replaces the continuous sinusoidal dither with discrete step perturbations of amplitude ±cv\pm c_v and estimates the gradient via central differences:

ξk=J+J2cv\xi_k = \frac{J^+ - J^-}{2 c_v}

where J±J^\pm are steady-state intensity measurements at positions r^±cv\hat{r} \pm c_v. A discrete-time integrator then updates: r^k+1=r^k+λξk\hat{r}_{k+1} = \hat{r}_k + \lambda \cdot \xi_k.

Sampled-data ESC Simulink implementation

Three parameters govern SD performance:

  • Step amplitude cvc_v — finite-difference accuracy vs. signal-to-noise ratio
  • Waiting time TT — must exceed the plant's settling time for unbiased measurements
  • Step size λ\lambda — analogous to the integrator gain kk in classical ESC

Dither-Amplitude Analysis (SD-Q1)

Gradient estimate quality vs dither amplitude c_v

  • Small cvc_v (< 0.5 rad): accurate finite difference, but ΔJ\Delta J is small relative to sensor noise → noisy estimates
  • Medium cvc_v (0.5–2 rad): good tracking, strong gradient signal
  • Large cvc_v (> 5 rad): overshoot + higher-order Taylor terms (cv2\propto c_v^2) degrade the approximation

SD Simulation Results (SD-Q3)

Tuned parameters achieved convergence in 8.7 s:

λ=4600,cv=9.75rad,T=0.050s\lambda = 4600, \quad c_v = 9.75\,\text{rad}, \quad T = 0.050\,\text{s}

Sampled-data simulation convergence

SD Experimental Results (SD-Q4)

Twelve runs were performed on the physical setup. None converged within the 0.1 rad bound due to a discovered implementation bug: the discrete-time integrator gain was set to λ\lambda instead of λ/(2T)\lambda/(2T). The best run (Run 8) still settled to within 3.1 rad of the optimum.

Best sampled-data run — detailed view

Three-Way Comparison

ApproachBest Experimental ConvergenceSteady-State AccuracyTuning ComplexityMIMO Scalability
Classical9.1 s< 0.1 radModerate (kk, aa, ωf\omega_f)Poor (harmonic beating with NN dithers)
Moving Average1.3 s< 0.1 radModerate (kk, aa, ω\omega, TmaT_\text{ma})Good (exact harmonic cancellation)
Sampled-Data~3 radNot met (bug in λ\lambda)Low (λ\lambda, cvc_v, TT)Best (linear scaling with NN)

Key architectural differences:

  • Classical: robust to noise (LP filter averages over many periods), but bound by ωfωωBW\omega_f \ll \omega \ll \omega_\text{BW}
  • Moving Average: exact dither cancellation enables higher frequencies and faster convergence, but sensitive to high gains and requires precise window matching
  • Sampled-Data: simplest gradient estimation (only two measurements), naturally handles constraints via barrier functions, scales linearly to MIMO (2N2N evaluations per iteration), but vulnerable to noise spikes on individual measurements

Engineering Takeaways

  • Timescale separation (ωfωωBW\omega_f \ll \omega \ll \omega_\text{BW}) is the fundamental design constraint for classical ESC — it limits the achievable convergence speed but ensures filter stability. The MA filter relaxes this constraint and delivers order-of-magnitude speedups.
  • Dither amplitude creates a fundamental trade-off: larger aa means better gradient SNR but more steady-state oscillation around the optimum. For the 0.1 rad accuracy requirement, aa itself must be < 0.1 rad.
  • Simulation-to-hardware transfer is non-trivial: encoder offsets, unmodeled dynamics, and lower stability margins all required parameter re-tuning between simulation and the physical test rig.
  • Implementation details matter: the sampled-data integrator gain normalization λ/(2T)\lambda/(2T) vs. λ\lambda was a subtle bug that made the difference between stable and unstable behavior on hardware.

Implementation Details

All three ESC approaches were deployed on the physical setup through MATLAB scripts that programmatically configure Simulink model parameters. The system sampling rate is Fs=4kHzF_s = 4\,\text{kHz}.

Classical / MA (ESC_CT.m)

The script toggles between classical and moving-average modes using gain switches, and discretizes the HP/LP filter prototypes before deployment:

% Classical ESC filter discretization
HPc = tf([1 0], [1 DE.highpass_filter_pole * 2 * pi]);
HPd = c2d(HPc, 1/Fs);
LPc = tf(1, [1 / (DE.highpass_filter_pole * 2 * pi) 1]);
LPd = c2d(LPc, 1/Fs);
 
% Toggle classical vs MA via gain switches
if DE.moving_average
    set_param(ModelName + "/DE/Gain_classic", "gain", "0")
    set_param(ModelName + "/DE/Gain_MA", "gain", "1")
end

For the MA filter, the FIR window length is N=Fs2π/ωN = F_s \cdot 2\pi/\omega samples.

Sampled-Data (ESC_DT.m)

The discrete-time implementation uses a pulse generator with period 2T2T (one +cv+c_v phase and one cv-c_v phase), triggered subsystems sample JJ at the end of each phase, and a discrete-time integrator updates via forward Euler:

% Critical: integrator gain must account for sample time
set_param(ModelName + "/optimizer/Gain", "gain", ...
    num2str(optimizer.gain / (2 * dither.time)))

Objective-Function Measurement (linear_motion.m)

A linear sweep script ramps the stage position at constant velocity while recording encoder position and photodiode intensity. This produces a scatter plot of (x,J)(x, J) pairs that maps the lens-photodiode geometry — the source for the Q3 lookup table.

Technologies Used

MATLAB, Simulink, real-time hardware control, extremum seeking control, moving average filtering, sampled-data optimization, finite-difference gradient estimation, frequency-domain analysis (Bode plots, bandwidth), system identification, experimental parameter tuning