Learned Narrowband Angle-of-Arrival Estimation#
Goal#
Train a portable single-source AoA estimator for an eight-element half-wavelength uniform linear array. The returned model receives noisy complex snapshots only. Source angles are offline labels and are unavailable at runtime.
The paired comparison holds angles, array snapshots, and AWGN seeds fixed across Bartlett, MUSIC, and the returned learned estimator.
CLI training summary#
(
set -euo pipefail
ROOT="$(git rev-parse --show-toplevel)"
BUNDLE="$ROOT/.noema/training_exports/aoa_estimation"
cd "$ROOT"
uv sync --extra onnx
uv run --project "$ROOT" --extra onnx noema differentiable export \
"$ROOT/recipes/aoa_adapter_ula_baseline.yaml" \
--training-plan "$ROOT/demo_trainings/aoa_estimation_covariance_mlp/training_plan.yaml" \
--out "$BUNDLE" --force
uv run --project "$ROOT" --extra onnx python \
"$ROOT/demo_trainings/prepare_example.py" aoa-estimation "$BUNDLE" \
--project-root "$ROOT"
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_train_recipe.yaml" --out "$BUNDLE/data/train" --force
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_validation_recipe.yaml" --out "$BUNDLE/data/validation" --force
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_test_recipe.yaml" --out "$BUNDLE/data/test" --force
cd "$BUNDLE"
uv run --project "$ROOT" --extra onnx python validate_contract.py
uv run --project "$ROOT" --extra onnx python train_demo.py
uv run --project "$ROOT" --extra onnx python evaluate_demo.py
cd "$BUNDLE/reference_training"
uv run --project "$ROOT" --extra onnx python build_benchmark.py
cd "$ROOT"
uv run --project "$ROOT" --extra onnx noema benchmark validate \
"$BUNDLE/reference_training/benchmark_pack.yaml"
uv run --project "$ROOT" --extra onnx noema benchmark run \
"$BUNDLE/reference_training/benchmark_pack.yaml"
)
1. Export and capture from Workbench#
Open Localization / Sensing > ULA angle-of-arrival estimation, then select Train/replace for Estimator. Keep:
snapshotsfromarray_observation.observation;angles_degfromarray_observation.truth.
Use 4,096 records, the default three-way split, and the training plan’s 0, 5, 10, 15, 20 dB
capture sweep. The captured snapshot tensor preserves the complex array and time axes; the
exporter presents it to ONNX as a final real/imaginary axis.
2. Train and return the estimator#
The starter converts each frame to a normalized complex sample covariance, obtains a 0.25°-grid
Bartlett estimate, and trains a bounded residual head for sub-grid and noise corrections. The last
layer starts at zero, so training starts from the physical estimator rather than an arbitrary MLP.
Validation angle MSE selects the checkpoint; held-out angles remain sealed until
evaluate_demo.py.
The returned aoa_estimator.onnx implements:
input
snapshots_ri:[batch, antenna, snapshot, 2];output
angles_deg:[batch].
The schema-v2 artifact records the exact trained antenna and snapshot sizes and binds the model to
model.aoa_estimator_adapter.
3. Compare estimators#
The post-training pack compares Bartlett, MUSIC, and the learned estimator at 0 and 15 dB over
three fresh paired seeds. Use aoa.rmse_deg as the primary metric and inspect aoa.mae_deg as a
companion measure.
Completed benchmark result#
The completed paired campaign contains 18 runs: Bartlett, MUSIC, and the learned estimator at two held-out SNRs over three fresh seeds. Points are means over the three seeds; bands are two-sided Student-t 95% confidence intervals.
Note
Three paired seeds make this a compact workflow result, not a publication-strength population claim.
The physics-informed learned estimator reaches 0.345° mean RMSE at 0 dB, compared with 0.356° for Bartlett and 0.364° for MUSIC. At 15 dB all three are effectively tied near 0.093°. This is a small low-SNR point-estimate improvement, and the three-seed confidence intervals overlap. It is not a claim that learning generally dominates classical single-source array processing.
SNR (dB) |
Method |
Role |
Mean RMSE (degree) |
Primary 95% CI low |
Primary 95% CI high |
|---|---|---|---|---|---|
0 |
Bartlett reference |
baseline |
0.355609497958 |
0.112940089193 |
0.598278906723 |
0 |
MUSIC |
baseline |
0.363952401628 |
0.132107910709 |
0.595796892548 |
0 |
Learned Bartlett-residual estimator |
candidate |
0.345006895503 |
0.0744081549881 |
0.615605636017 |
15 |
Bartlett reference |
baseline |
0.0933945370652 |
0.085953806086 |
0.100835268044 |
15 |
MUSIC |
baseline |
0.0933945370652 |
0.085953806086 |
0.100835268044 |
15 |
Learned Bartlett-residual estimator |
candidate |
0.0934483725855 |
0.0788052559106 |
0.10809148926 |
Download the run-level projection, chart data, or provenance manifest.
This is deliberately a far-field, single-source, narrowband, calibrated-array protocol. Multiple sources, coherent multipath, calibration error, near-field propagation, and wideband beam squint need separate contracts and should not be inferred from this demo.