Single-tone narrowband

Adaptive notch control targets one sinusoidal component with a quadrature pair.

The controller synthesizes cosine and sine references at the tracked frequency, then adapts two weights to cancel the measured component after accounting for secondary-path delay or compensation filtering. It is the narrowband choice for a dominant rotating-order or single-frequency disturbance.

Core Equations

The synthesized references are:

\[x_0(n) = A \cos(k \omega_0 n)\] \[x_1(n) = A \sin(k \omega_0 n)\]

The canceling signal is the weighted combination:

\[y(n) = w_0(n) x_0(n) + w_1(n) x_1(n)\]

and the update follows the same ANC sign convention used elsewhere:

\[w_i(n+1) = w_i(n) - \mu e(n) x'_i(n)\]

where $x’_i(n)$ is either delay-compensated or filtered through the secondary-path estimate.

Benchmark Interpretation

The primary benchmark shows the notch controller converging quickly in the single-tone scenario and delivering a solid narrowband attenuation result. The scenario comparison also shows the limit of the method: once the disturbance drifts or stops being a single stable tone, a fixed-frequency notch section is no longer well matched.

Use the right model class

Adaptive notch is excellent when the disturbance really is one tracked sinusoid. It is not a broadband controller and should not be evaluated as if it were one.

Tuning Notes

Using It From C++

#include "anc/adaptive_notch_controller.h"

anc::AdaptiveNotchConfig config;
config.frequencyRadians = 2.0 * 3.14159265358979323846 / 64.0;
config.amplitude = 1.0;
config.stepSize = 0.02;
config.delaySamples = 1;
config.secondaryEstimate = {0.0, 0.12, 0.38, 0.21, -0.05};

anc::AdaptiveNotchController controller(config);

for (double error : errorSignal) {
  const double control = controller.synthesize();
  sendToActuator(control);
  controller.adapt(error);
}

CLI Reproduction

build\Debug\anc_cli.exe `
  --algorithm notch `
  --summary analysis_output\raw\notch_single_tone_summary.csv `
  --timeseries analysis_output\raw\notch_single_tone_timeseries.csv `
  --period-samples 64 `
  --delay-samples 1 `
  --step-size 0.02