Configure, simulate, debug, and analyze radarDataGenerator within radarScenario. Use for: interactively building radar detection scenarios from datasheets or performance requirements; diagnosing missed detections and configuration errors; interpreting sensor spherical, body, and scenario-frame outputs; deriving ReferenceRange from hardware specs via link budget; scan mode configuration (mechanical, electronic/AESA, hybrid); and validating simulation results against analytical predictions.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add matlab/matlab-agentic-toolkit --skill matlab-simulate-radar-detections --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Matlab Simulate Radar Detections?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/matlab-matlab-simulate-radar-detections)More formats (shields.io, HTML) on the badges page.
---
name: matlab-simulate-radar-detections
description: >
Configure, simulate, debug, and analyze radarDataGenerator within radarScenario.
Use for: interactively building radar detection scenarios from datasheets or
performance requirements; diagnosing missed detections and configuration errors;
interpreting sensor spherical, body, and scenario-frame outputs; deriving
ReferenceRange from hardware specs via link budget; scan mode configuration
(mechanical, electronic/AESA, hybrid); and validating simulation results against
analytical predictions.
license: https://www.mathworks.com/content/dam/mathworks/license/pmrl/license.md
metadata:
author: MathWorks
version: "1.0"
---
# Radar Data Generator — Statistical Detection Simulation
Build detection-level radar simulations using `radarDataGenerator` within `radarScenario`. This skill bridges user hardware specs and performance requirements to the Radar Toolbox statistical simulation API.
## When to Use
- User wants to simulate radar detections on moving targets
- User has radar hardware specs (datasheet) or performance requirements and wants to build a simulation
- User mentions surveillance radar, scanning, revisit time, detection probability, or radar coverage
- User wants to compare scan strategies (mechanical vs electronic vs hybrid)
- User wants to generate detections to feed a tracker (trackerGNN, trackerJPDA) or do sensor fusion
- User wants Monte Carlo analysis, trade studies, or validation against link budget predictions
- User is studying radar placement or geometry to maximize coverage
- User has existing `radarDataGenerator` code that isn't working — missed detections, configuration errors
- User wants to validate simulation results against expected performance
## When NOT to Use
- User needs I/Q-level waveform simulation (use `radarTransceiver` + pulse-Doppler chain)
- User needs CFAR detector design or beamforming
- User needs waveform design (ambiguity functions, chirp optimization)
- User already has detections and wants to process them
- User needs bistatic or multistatic radar configurations
- User needs interference or jamming modeling (EW scenarios)
- User wants to call `radarDataGenerator` standalone (without `radarScenario`) in a custom simulation loop
If the user needs signal-level fidelity, explain the tradeoff and hand off.
## Detection Pathways
`radarDataGenerator` supports two detection pathways. This skill uses the **target-pose pathway** exclusively:
| Pathway | Call Signature | Detection Governed By | When Used |
|---------|---------------|----------------------|-----------|
| **Target-pose** (this skill) | `detect(scenario)` | `DetectionProbability`, `FalseAlarmRate`, `ReferenceRange`, `ReferenceRCS` | Standard radar simulation — targets defined as platforms with trajectories |
| **Emissions** | `detect(scenario, propagatedEmissions)` | `Sensitivity`, `DetectionThreshold` | ESM receivers, bistatic with explicit emission propagation |
Properties from one pathway have **zero effect** on the other. Setting `Sensitivity` or `DetectionThreshold` in the target-pose pathway produces a "not relevant" warning.
**Standalone mode:** `radarDataGenerator` can also be called outside a scenario: `[dets, numDets, config] = rdg(targetPoses, simTime)`. Use for integration into custom loops (Simulink, event-driven). Loses `advance()`, trajectory automation, multi-sensor aggregation, and coverage visualization. See [references/detection-model.md](references/detection-model.md) for the full standalone API and pose struct requirements.
## Workflow
Follow these 9 steps interactively. Do NOT silently choose parameters — engage the user at each decision point.
### Step 1: Recommend Approach
Recommend statistical-level simulation using `radarDataGenerator` within `radarScenario`. Explain the tradeoff: fast iteration on scenario design vs less control over signal processing. If user needs I/Q-level fidelity, name the alternative path (`radarTransceiver` + pulse-Doppler + CFAR) and stop the structured 9-step flow.
When they confirm statistical-level, state the approach and name the APIs: `radarScenario`, `radarDataGenerator`, `platform`, `waypointTrajectory`/`kinematicTrajectory`/`geoTrajectory`.
### Step 2: Confirm Use Case
Suggest a use case (e.g., ground-based surveillance scanning a sector). Confirm:
- **Scan type:** Propose mechanical, offer electronic or both
- **Coordinate frame:** NED (default), ENU, or Earth-centered. State implications.
- **Configuration:** Confirm monostatic
- **Propagation environment:** Default is FreeSpace (no refraction). If user mentions long range, low-elevation targets, or over-the-horizon, offer atmosphere models: `atmosphere(scenario, model)` — `'EffectiveEarth'` (4/3 radius), `'RefractivityGradient'`, or `'CRPL'`. These add refraction bias to propagation paths (ray bending), affecting reported target positions — they do NOT add atmospheric attenuation to the link budget. Weather/precipitation is NOT modeled at statistical level.
### Step 3: Ask Parameter Sourcing Direction
> "Which direction are you working? Top-down (specify requirements, derive hardware)? Bottom-up (specify hardware, derive performance)? Or a mix?"
If user provides a **datasheet**: follow the datasheet ingestion procedure in [references/coupled-parameters.md](references/coupled-parameters.md) — extract parameters, map to groups, identify gaps, close link budgets, flag conflicts.
**The flow branches here:**
**Top-down path** (Steps 4 → 5): User specifies performance requirements first, then derive hardware.
- Step 4: Propose reference performance (range, RCS, Pd, Pfa)
- Step 5: Present coupled-parameter table, derive hardware needed to meet requirements
**Bottom-up path** (Steps 5 → 4): User specifies hardware first, then derive performance.
- Step 5: Present coupled-parameter table, collect hardware specs (power, gain, NF, bandwidth, etc.)
- Step 4: Derive and present reference performance from hardware via `radareqrng`
**Mixed/Datasheet**: Collect what they have, fill gaps from both directions, flag inconsistencies.
Both paths converge at Step 6 (Target Set Design).
### Step 4: Propose Reference Performance
Present as a reference target specification:
- Reference range, reference RCS (note: `ReferenceRCS` is in **dBsm**)
- Detection probability, false alarm rate (valid: [1e-7, 1e-3])
- Integration type and number of pulses (assume coherent; ask for N or CPI)
- Monostatic, clear sky
**Top-down:** Present concrete defaults. Let user react/modify.
**Bottom-up:** Present values *derived from their hardware*. Show the derivation (which function, which inputs). For integration: assume coherent, ask number of pulses or CPI duration. Use `detectability(Pd, Pfa, 1, 'SwerlingN') - 10*log10(N)` for required SNR. The Swerling argument is a **string**: `'Swerling0'`, `'Swerling1'`, ..., `'Swerling4'`. Never pass N to `detectability` for coherent systems — that applies non-coherent loss. See [references/interaction-flow.md](references/interaction-flow.md) § Step 4 for the full decision table.
### Step 5: Present Coupled-Parameter Table
Show the parameter-relationship table from [references/coupled-parameters.md](references/coupled-parameters.md). This builds confidence, shows traceability, invites correction.
**Top-down:** Use the table to derive what hardware is needed to meet the agreed reference performance.
**Bottom-up:** Use the table to collect the user's hardware specs and identify which groups are constrained.
### Step 6: Target Set Design
Confirm geometry (radar placement, scan sector, airborne targets). Propose physically representative targets varying:
- RCS (UAV ~0.01 m², fighter ~1 m², commercial ~10 m²)
- Speed (50 m/s rotary, 250 m/s jet, 300+ m/s fast mover)
- Altitude (500 m nap, 5 km mid, 10 km high)
Offer Swerling models (I = slow-fluctuating, III = dominant scatterer). Configure per-target RCS via `rcsSignature` on each platform's `Signatures` property — see [references/detection-model.md](references/detection-model.md) for patterns. Default platform RCS is 10 dBsm (Swerling0).
**Sanity checks before proceeding:**
1. Verify target geometry is within radar horizon using `horizonrange(antennaHeight)`. If any target is beyond LOS at its specified altitude, flag this to the user.
2. Compute the expected 0.9 Pd reference range for each target. Report a table like:
| Target | RCS (dBsm) | Swerling | Range (km) | Expected Pd |
|--------|-----------|----------|-----------|-------------|
| UAV | -20 | 1 | 15 | 0.72 |
| Fighter | 0 | 1 | 40 | 0.95 |
Use: `SNR_at_R = RadarLoopGain + RCS_dBsm - 40*log10(range)`, then map SNR to Pd with the correct Swerling formula (see [references/radar-equation-tools.md](references/radar-equation-tools.md#pd-vs-range-prediction-fluctuationmodel-dependent)). Flag any target where expected Pd < 0.5 — the user should know which targets will have unreliable detection before running the sim.
Ask: "Do you need terrain or ground returns, or is free-space sufficient?"
### Step 7: Terrain / Occlusion
If applicable — see [references/terrain-clutter-atmosphere.md](references/terrain-clutter-atmosphere.md) for terrain options. Terrain and occlusion are additive after validating detections in free-space. `landSurface` for height maps, `seaSurface` for sea state, `customSurface` for user-defined. `landSurface` has `occlusion()` for LOS blocking. `HasOcclusion` on `radarDataGenerator` is target-to-target occlusion.
### Step 8: Simulation Duration
Ask in user's terms: seconds, number of scans, number of target illuminations, or event-based. Convert between these once scan parameters are locked.
### Step 9: Produce Requirements Sheet
Generate a standalone document with three sections — see [references/requirements-sheet-template.md](references/requirements-sheet-template.md).
## Key Functions
| Function | Purpose | Toolbox |
|----------|---------|---------|
| `radarScenario` | Scenario container (platforms, time, detect) | Radar |
| `radarDataGenerator` | Statistical detection sensor | Radar |
| `platform` | Add platform to scenario | Radar |
| `waypointTrajectory` | Waypoint-based motion in local coords (has `ReferenceFrame`) | Radar |
| `kinematicTrajectory` | State-based motion in local coords (NO `ReferenceFrame`) | Radar |
| `geoTrajectory` | Waypoint-based motion in geodetic coords (lat/lon/alt) — requires `IsEarthCentered = true` | Radar |
| `radareqrng` | Max detection range from radar equation | Radar |
| `radareqpow` | Required Tx power | Radar |
| `radareqsnr` | Received SNR at range | Radar |
| `detectability` | Required SNR (detectability factor) for Pd/Pfa/N/Swerling | Radar |
| `albersheim` | Required SNR for Pd/Pfa/N (Swerling 0 only) | Phased Array |
| `shnidman` | Required SNR for Pd/Pfa/N/Swerling 0–4 | Phased Array |
| `horizonrange` | Radar horizon from antenna height | Radar |
| `height2el` | Elevation angle from target height/range | Radar |
| `freq2wavelen` | Wavelength from frequency | Phased Array |
| `rangeres2bw` | Bandwidth from range resolution | Phased Array |
| `bw2rangeres` | Range resolution from bandwidth | Phased Array |
| `speed2dop` | Doppler shift from speed. **One-way convention** — for monostatic two-way: `fd = 2*speed2dop(v, lambda)` | Phased Array |
| `dop2speed` | Speed from Doppler shift. **One-way convention** — for monostatic two-way: `v = dop2speed(fd, lambda)/2` or use `lambda*fd/2` directly | Phased Array |
| `beamwidth2gain` | Antenna gain from half-power beamwidth. **Must pass [azBW; elBW] column vector** — scalar assumes symmetric beam. | Phased Array |
| `aperture2gain` | Antenna gain from effective aperture | Phased Array |
| `gain2aperture` | Effective aperture from antenna gain | Phased Array |
| `ap2beamwidth` | Beamwidth from aperture length and wavelength | Phased Array |
| `beamwidth2ap` | Aperture length from beamwidth and wavelength | Phased Array |
| `effbeamwidth` | Two-way effective beamwidth (Tx+Rx) → maps to `AzimuthResolution`/`ElevationResolution` | Phased Array |
| `systemp` | System noise temperature | Phased Array |
| `noisepow` | Noise power from temperature + bandwidth | Phased Array |
| `theaterplot` | Scenario visualization | Radar |
| `coverageConfig` | Coverage diagram | Radar |
| `radarmetricplot` | Plot metric vs range with objective/threshold lines and stoplight | Radar |
| `orientationPlotter` | Visualize beam pointing direction (theaterPlot plotter) | Radar |
| `detectionPlotter` | Visualize detections on theater plot | Radar |
| `landSurface` | Static terrain (height matrix or DTED) — occlusion only with `IsEarthCentered=true` | Radar |
| `seaSurface` | Dynamic ocean surface (spectral model, wind, fetch) | Radar |
| `customSurface` | Polarization scattering matrix surface for clutter | Radar |
| `surfaceReflectivityLand` | Land clutter reflectivity model (Barton, GIT, etc.) | Radar |
| `surfaceReflectivitySea` | Sea clutter reflectivity model | Radar |
| `clutterGenerator` | Add clutter to scenario (1:1 with radar sensor, requires a surface) | Radar |
| `ringClutterRegion` | Define explicit clutter region (required when `UseBeam=false`) | Radar |
| `getClutterGenerator` | Retrieve existing clutter generator for a radar | Radar |
## Conventions
### Traceability
- Every stochastic quantity traces to a configured parameter
- `radarDataGenerator` provides built-in traceability — property names ARE the documentation
- If hand-rolling any computation, comment the model, its parameters, and how it connects to system design
### Coordinate Frames
- Pick ONE frame and use it consistently throughout
- `waypointTrajectory` has `'ReferenceFrame'` property: `'NED'` or `'ENU'` — use with `IsEarthCentered = false`
- `kinematicTrajectory` has NO `ReferenceFrame` — inherits from scenario — use with `IsEarthCentered = false`
- `geoTrajectory` uses geodetic waypoints [lat, lon, alt] in [deg, deg, m] — **requires** `IsEarthCentered = true`
- Has `'ReferenceFrame'` (`'NED'`/`'ENU'`) for velocity/orientation interpretation
- Also supports `Course`, `GroundSpeed`, `ClimbRate` as alternatives to `Velocities`
- `DetectionCoordinates = 'Scenario'` reports in ECEF (meters), not lat/lon
- Single waypoint = stationary platform (TimeOfArrival is ignored)
- **Constraint:** trajectory type and `IsEarthCentered` are strictly coupled — mixing produces an error
- NED: elevation is **negative** above horizon. ENU: elevation is **positive** above.
- Always validate: compute expected elevation analytically, compare to measured
### Parameter Source Tags
Every parameter in the requirements sheet gets a tag:
- **User-provided** — they told us
- **Domain assumption** — reasonable default, justified
- **Derived** — computed from other params (show which function)
### System Parameters vs Simulation Parameters
Once the user's requirements and use case are confirmed (Steps 2–6), distinguish between:
- **System parameters** (user's design): FieldOfView, CenterFrequency, Bandwidth, MaxAzimuthScanRate, ReferenceRange, antenna height, etc. Never change these to fix a simulation issue.
- **Simulation parameters** (our configuration): UpdateRate, RangeLimits, scenario UpdateRate, DetectionCoordinates, simulation duration. These can be tuned freely.
If a simulation artifact occurs (e.g., missed detections due to beam stepping), fix it by adjusting simulation parameters. If the fix requires changing a system parameter, surface it to the user with physical intuition — it's a design insight, not a sim fix.
### Self-Consistency
After deriving all parameters, validate the loop closes:
- Compute Rmax from hardware via `radareqrng`
- Configure `ReferenceRange` = Rmax
- Run simulation, confirm ~Pd at reference range
- If mismatch, diagnose and flag
## Common Mistakes
| Mistake | Why It's Wrong | Correct Approach |
|---------|---------------|-----------------|
| Changing non-tunable properties without `release()` | `radarDataGenerator` is a System object — non-tunable properties (`FieldOfView`, `ScanMode`, `AzimuthResolution`, scan limits) are locked after first call to `detect()` | Call `release(radar)` before modifying non-tunable properties, then `restart(scenario)` before re-running |
| `ReferenceRCS` in linear m² | Property expects **dBsm** | Convert: `10*log10(rcs_linear)` |
| `range2bw` / `bw2range` | Deprecated | Use `rangeres2bw` / `bw2rangeres` |
| `MechanicalScanLimits` | Does not exist | Use `MechanicalAzimuthLimits`, `MechanicalElevationLimits` |
| Setting `MaxAzimuthScanRate` for electronic scan | Ignored (warning issued) | Beam steps by `FieldOfView(1)` per update in electronic mode |
| Confusing `detect(scenario)` with `detect(platform, time)` | Different signatures — scenario-level returns all sensors' detections combined | `dets = detect(scenario)` or `[dets, configs] = detect(scenario)` — both valid. Per-platform: `[dets, ~, configs] = detect(platform, time)` |
| Forgetting elevation sign in NED | Targets above horizon have negative elevation | Check sign: `el = -asind(alt/range)` in NED |
| `HasScanLoss` with non-Custom scan | Only applies when `ScanMode='Custom'` | Omit for Mechanical/Electronic modes |
| Mixing trajectory reference frames | Causes silent position errors | Set all `waypointTrajectory` objects to same `'ReferenceFrame'` |
| `waypointTrajectory` shorter than `StopTime` | Scenario stops at max trajectory endpoint, NOT at `StopTime`. Platform goes to NaN position after trajectory ends — silently stops being detected. | Extend all `waypointTrajectory` endpoints to >= `StopTime` (add hold waypoint). Or use `kinematicTrajectory` for constant-velocity platforms. |
| Confusing `radar/waypointTrajectory` with `drivingScenario` trajectories | Different API — `drivingScenario` uses actor waypoints, not this class | In `radarScenario`, always use `waypointTrajectory`, `kinematicTrajectory`, or `geoTrajectory` |
| Using `kinematicTrajectory` for a moving platform with a forward-looking sensor | Body frame orientation is FIXED (default: identity = scenario axes). Does NOT rotate with velocity — a forward-looking sensor will not track the flight path. | Use `waypointTrajectory` or `geoTrajectory` for moving platforms with sensors. Their body frame rotates with heading. |
| Hardcoded noise (e.g., `0.2*randn`) | Not traceable, breaks self-consistency | Use `radarDataGenerator` built-in noise model or comment the source |
| Not setting sensor `UpdateRate` | Default is 1 Hz — scan rate = `FoV(1)*1` = crawl | Always set `'UpdateRate'` explicitly on `radarDataGenerator` |
| Scenario `UpdateRate` < sensor `UpdateRate` | Aliasing: only a fraction of FoV dwell positions are sampled. Targets between sampled positions get **zero detections silently**. | Set scenario `UpdateRate` = sensor `UpdateRate` for detection-complete sims. |
| Comparing sensor rectangular measurements directly to scenario-frame truth | Sensor rectangular is a **beam-rotating frame** — each detection's coordinate system depends on where the beam was pointing at detection time. Raw measurements will differ from truth by tens of km. | Use per-detection `MeasurementParameters(1)`: `scenarioPos = Orientation * Measurement + OriginPosition`. The Orientation matrix encodes mounting + current scan angle. |
| Assuming spherical measurement order is [range, az, el] | Actual order is **[az, el, range]** for `'Sensor spherical'` | Check `DetectionCoordinates` setting; default is `'Body'` (Cartesian) |
| Not setting `RangeLimits` | Default is [0, 100 km] — targets beyond 100 km silently produce no detections | Set `'RangeLimits', [0, R]` where R = max(maxTargetRange, ReferenceRange * 1.2) |
| Using `'Sector'` with `MechanicalElevationLimits` | 'Sector' sets `HasElevation=false` — elevation limits are ignored (warning issued) | Use explicit `'ScanMode','Mechanical'` with `HasElevation=true` if elevation scanning is needed |
| Setting or investigating `HasElevation` for detection issues | `HasElevation` does NOT affect whether targets are detected. It only controls whether elevation angle is measured and whether the beam scans in elevation. Default is `false` (azimuth-only). | Never set `HasElevation=false` (it's already the default). Never investigate `HasElevation` when debugging missing detections — it cannot cause them. Missing detections are caused by: `RangeLimits`, target outside scan sector, insufficient `ReferenceRange`/`ReferenceRCS`, or `UpdateRate` too low. |
| Calling `atmosphere(scene, model)` with `IsEarthCentered=false` | Errors: "The IsEarthCentered property must be true to modify the atmosphere model" | All atmosphere/refraction models require `IsEarthCentered=true`. Flat-earth scenarios are always free-space. |
| Expecting terrain to block targets with `IsEarthCentered=false` | Terrain occlusion in `detect()` only works with `IsEarthCentered=true` | If terrain masking matters, use earth-centered scenario with `geoTrajectory` |
| Confusing `HasOcclusion` with terrain occlusion | `HasOcclusion` is target-to-target (extended objects); terrain LOS is via `SurfaceManager` | For terrain masking: `IsEarthCentered=true` + `landSurface`. For target-to-target: `HasOcclusion=true` |
| `clutterGenerator` without any surface | Produces 0 clutter detections silently | Add `landSurface(scene)` or `seaSurface(scene)` before creating clutter generator |
| `ScattererDistribution='RangeDopplerCells'` with `radarDataGenerator` | Error at `detect()` | Only works with `radarTransceiver`; use `'Uniform'` (default) for radarDataGenerator |
| `UseBeam=false` without `ringClutterRegion` | 0 clutter detections | Add explicit regions: `ringClutterRegion(cg, minR, maxR, azSpan, azCenter)` |
| Setting `Sensitivity` or `DetectionThreshold` in target-pose mode | "Not relevant" — these are emissions-pathway only | In the target-pose pathway (`detect(scenario)`), detection is governed solely by `Pd`/`Pfa`/`ReferenceRange`/`ReferenceRCS` |
| Increasing `FalseAlarmRate` to simulate surface clutter | `FalseAlarmRate` produces uniformly distributed false detections (white noise); it does not model spatially correlated surface clutter with realistic sigma-zero, geometry, or Doppler | Use `clutterGenerator` with a surface (`landSurface`/`seaSurface`) and reflectivity model. See [terrain-clutter-atmosphere.md](references/terrain-clutter-atmosphere.md). |
| Expecting `radarDataGenerator` to model signal processing losses (MTI, STAP, CFAR) | The statistical model does not simulate clutter-rejection filter losses, STAP adaptive weight losses, or detectability degradation near the clutter ridge in range-Doppler space | These effects require I/Q-level simulation (Phased Array System Toolbox waveform + receiver chain). For statistical-level approximation, add expected processing losses via the `Loss` parameter in the link budget (`radareqsnr`), or reduce `DetectionProbability` in clutter-affected regions. |
| `dop2speed(1/CPI, lambda)` for monostatic velocity resolution | Gives 2× correct value (3.0 m/s instead of 1.5 m/s) | `dop2speed` uses one-way convention. Monostatic velocity resolution = `lambda/(2*CPI)`. Either use manual formula or `dop2speed(fd,lambda)/2`. |
| `radareqrng(SNR, lambda, ...)` — wrong arg order | Silent wrong answer (no error) | Correct: `radareqrng(lambda, SNR, Pt, tau, ...)` — lambda first |
| Passing `Gain` in linear to `radareqrng` | Absurd range (10^49 km) | `Gain` is **dBi**, not linear. Pass `30`, not `1000`. |
| Passing `RCS` in dBsm to `radareqrng` | Wrong by 3× or errors on negative | `RCS` is **linear m²**. Convert: `db2pow(rcs_dBsm)` |
| Passing average power to `radareqrng` as Pt | Underestimates range | Pt is **peak** power (Watts). Derive: `Ppeak = Pavg / (tau * PRF)` |
| Using `FieldOfView` for antenna gain derivation | Wrong gain when FoV ≠ beamwidth | Gain comes from `beamwidth2gain([AzimuthResolution; ElevationResolution])`. Both beamwidths required — scalar input assumes symmetric beam (up to 10 dB error for fan beams). FoV is the angular coverage per scan position; it is not necessarily equal to the receive beamwidth. |
| Assuming `FieldOfView` must equal `AzimuthResolution` | Incorrect scan step for AESA or wide-Tx configurations | FoV and resolution are independent. FoV = Tx beamwidth (typical). For shared aperture, FoV = AzRes. For wide Tx + narrow Rx, FoV > AzRes. |
| Applying Swerling I Pd formula to a default (Swerling0) target | Underpredicts Pd by ~40% at reference range (0.52 vs 0.89) | Check `target.Signatures{1}.FluctuationModel`. Default is Swerling0 — use `marcumq`. For Swerling1 targets: `Pfa^(1/(1+SNR_lin))`. |
## Scan Mode Quick Reference
| Mode | Key Behavior |
|------|-------------|
| `'Mechanical'` | `actualRate = min(FieldOfView(1) * sensorUpdateRate, MaxAzimuthScanRate)`. See scan rate model below. |
| `'Electronic'` | Beam steps by `FieldOfView(1)` per update. `MaxAzimuthScanRate` irrelevant. |
| `'Mechanical and electronic'` | Mechanical provides coarse pointing, electronic refines. |
| `'No scanning'` | Fixed staring beam. |
Convenience constructors: `radarDataGenerator(id, 'Raster')`, `'Rotator'`, `'Sector'`, `'Custom'`.
### Mechanical Scan Rate Model (Critical)
The actual scan rate for mechanical mode is:
```
actualScanRate = min(FieldOfView(1) * sensorUpdateRate, MaxAzimuthScanRate) [deg/s]
stepPerScenarioUpdate = actualScanRate / scenarioUpdateRate [deg]
```
**Default sensor `UpdateRate` is 1 Hz.** If not set explicitly, a 2-deg beam scans at only 2 deg/s regardless of `MaxAzimuthScanRate`. Always set sensor `UpdateRate` explicitly:
```matlab
radar = radarDataGenerator(1, 'Sector', ...
'UpdateRate', 20, ... % MUST set — default 1 Hz causes very slow scan
'FieldOfView', [2; 20], ...
'MaxAzimuthScanRate', 36, ...
...);
% actualRate = min(2*20, 36) = 36 deg/s ✓
```
To achieve a desired scan rate with a narrow beam:
- `sensorUpdateRate >= desiredRate / FieldOfView(1)`
- Example: 36 deg/s with 2-deg beam needs `UpdateRate >= 18` Hz
### Scenario vs Sensor UpdateRate
The sensor fires at its own `UpdateRate`; the scenario `UpdateRate` controls how often `advance()`/`detect()` execute. If scenario rate < sensor rate, only a fraction of dwell positions are sampled — targets between sampled positions produce **zero detections silently**.
**Rule:** Always set scenario `UpdateRate` = sensor `UpdateRate` unless you specifically want sparse detection cadence.
## Detection Model
```
SNR = RadarLoopGain + RCS_dBsm - 40*log10(Range)
```
- `RadarLoopGain`: read-only, derived from `ReferenceRange` + `ReferenceRCS` + `DetectionProbability` + `FalseAlarmRate`. The reference SNR uses Swerling0 (non-fluctuating) internally — target fluctuation models are applied separately at detection time.
- No hardware knobs (Pt, Gain, NF) — all lumped into reference performance
- `CenterFrequency`/`Bandwidth` affect resolution only, not detection range
- Measurement accuracy: `σ² = (Δ/√(2·SNR))² + (BiasFraction·Δ)²` — Cramér-Rao plus bias floor. Defaults: `AzimuthBiasFraction=0.1`, `RangeBiasFraction=0.05`, `ElevationBiasFraction=0.1`. At high SNR the bias floor dominates (0.3° azimuth, 3.75m range).
- **Pd vs range depends on target FluctuationModel** — default platforms are Swerling0 (non-fluctuating). Use `marcumq` for Swerling0, `Pfa^(1/(1+SNR))` for Swerling1. Using the wrong formula gives ~40% Pd error. See [references/radar-equation-tools.md](references/radar-equation-tools.md) for the full recipe.
The agent's job is to **bridge** between user hardware specs and this statistical interface using radar equation tools as the translation layer.
## Troubleshooting
| Symptom | Likely Cause | Diagnostic / Fix |
|---------|-------------|-----------------|
| No detections at all | `RangeLimits` too short | Check `radar.RangeLimits(2)` >= max target range |
| No detections at all | Sensor `UpdateRate` = 1 Hz (default) | Beam scanning too slowly — set `UpdateRate` explicitly |
| No detections at all (UpdateRate is set) | Scenario `UpdateRate` < sensor `UpdateRate` | FoV dwell aliasing — only sampled positions produce detections. Set scenario `UpdateRate` = sensor `UpdateRate`. |
| No detections at all | Target outside beam FoV | Use `coverageConfig(radar)` to get current beam direction; compare to target bearing |
| Detections only on some scans | Target near beam step boundary | Normal for mechanical scan — fast targets at bearings aligned with beam step positions may be missed on some sweeps. Increase sensor/scenario `UpdateRate` to reduce step size (never change system parameters like `FieldOfView` to fix a simulation artifact). |
| Too many detections | Self-detection (radar platform) | Filter: ignore detections where `TargetIndex == radar platform ID` (usually 1) |
| Pd much lower than configured | Target beyond `ReferenceRange` | SNR drops as 40·log10(R) — expected; Pd is specified AT reference range only |
| Pd higher than expected | Target RCS > `ReferenceRCS` | Higher RCS increases SNR — check `rcsSignature` on target platform |
| Empirical Pd > 1.0 | Dividing detections by scans, not illuminations | Mechanical scan is bidirectional: illuminations = 2 × scans for sector scan. Count beam passes from `IsScanDone` or compute from scan timing: `nIlluminations = StopTime / (sector / scanRate)`. |
| Measured position far from truth | Plotting raw `.Measurement` against scenario-frame truth | **Must convert to scenario frame first.** Use `MeasurementParameters.Orientation` and `.OriginPosition` to transform. "0 azimuth" = sensor boresight, not north. See API Answer Key for conversion recipes. |
| Range-limited vs LOS-limited | Targets beyond radar horizon | Use `horizonrange(antennaHeight)` to check. Comment in code where missed detections are expected due to LOS. This should also be caught as a sanity check before writing code (Step 6 — verify target geometry is within radar horizon). |
| Self-consistency check fails | Hardware-derived Rmax ≠ configured ReferenceRange | Recheck `radareqrng` inputs match the hardware specs fed to the derivation |
### Programmatic Verification
**Detection accuracy check** — verify measurement errors are within expected bounds. **This must account for DetectionCoordinates mode** — raw `.Measurement` values cannot be compared to scenario-frame truth unless using `'Scenario'` mode:
```matlab
% Convert detection to scenario frame FIRST (required for all non-Scenario modes)
mp = dets{k}.MeasurementParameters(1); % first element = position transform
meas = dets{k}.Measurement;
switch mp.Frame
case 'Spherical'
az = meas(1); el = meas(2); R = meas(3);
posSensor = [R*cosd(el)*cosd(az); R*cosd(el)*sind(az); R*sind(el)];
measScenario = mp.Orientation * posSensor + mp.OriginPosition(:);
case 'Rectangular'
measScenario = mp.Orientation * meas(1:3)' + mp.OriginPosition(:);
end
posError = norm(measScenario - truthPos);
expectedSigma = sqrt(trace(dets{k}.MeasurementNoise(1:3,1:3)));
assert(posError < 5*expectedSigma, 'Position error exceeds 5-sigma');
```
**SNR check** — verify reported SNR matches link budget prediction (within ~1 dB):
```matlab
expectedSNR = radar.RadarLoopGain + rcs_dBsm - 40*log10(slantRange);
reportedSNR = dets{k}.ObjectAttributes{1}.SNR;
assert(abs(reportedSNR - expectedSNR) < 1.0, 'SNR mismatch > 1 dB');
```
See [Coordinates & Transforms — Verification](references/coordinates-and-transforms.md#verification-spot-check-detections-against-truth) for full mode-aware verification patterns.
### Debugging: Isolate Beam Pointing
When diagnosing "no detections" or unexpected detection gaps, isolate whether the problem is beam pointing vs. something else:
1. **Release the sensor, then go omnidirectional:**
```matlab
origFoV = radar.FieldOfView;
origScan = radar.ScanMode;
release(radar);
radar.FieldOfView = [360; 180];
radar.ScanMode = 'No scanning';
```
2. **Restart and re-run the scenario** (`restart(scenario)` + advance loop)
3. **Interpret:**
- Detections appear → problem is beam pointing (scan limits, MountingAngles, FoV, scan stepping over target)
- Still no detections → problem is elsewhere (RangeLimits, UpdateRate aliasing, ReferenceRange, horizon, target RCS)
4. **Release and restore original config before continuing:**
```matlab
release(radar);
radar.FieldOfView = origFoV;
radar.ScanMode = origScan;
```
**Note:** `radarDataGenerator` is a System object. Non-tunable properties (`FieldOfView`, `ScanMode`, `AzimuthResolution`, scan limits, etc.) cannot be changed after `detect()` has been called without first calling `release(radar)`. Always `release()` before modifying non-tunable properties.
Do this BEFORE drilling into individual parameters — it splits the problem space in half with one test.
### Debugging Order
1. **Omnidirectional isolation** (above) — rules out beam pointing in one test
2. **Inspect systematic causes** — RangeLimits gate, scan sector bounds, UpdateRate aliasing. These produce deterministic failures (0% Pd) and are identifiable from a single run.
3. **Monte Carlo trials (last)** — only after systematic causes are ruled out. Use repeated runs to characterize *stochastic* behavior: Swerling fluctuation, intermittent detections near the detection boundary, empirical Pd vs analytical Pd. Never run Monte Carlo to diagnose a target that gets 0 detections — that is always a systematic cause.
### Fix Forward: Step Hierarchy
When validation fails, fix the latest step that could be wrong. Never change a system parameter (Steps 1–5) to accommodate a scenario choice (Steps 6–7). If the radar's FoV doesn't cover a target, the target is out of coverage — don't widen FoV to "fix" it. Only revisit earlier steps when there is a genuine design error.
## Analyzing Simulation Outputs
Critical NED traps that cause silent errors:
- **Geometric elevation (positive up):** `atand(-dx(3) ./ horizRange)` — negate D-axis so airborne targets get positive angle. **Sensor spherical elevation has opposite sign** for NED (sensor +z = Down): airborne targets get negative `el`.
- **Azimuth:** `atan2d(East, North)` — swapping arguments gives azimuth from East (90° error)
- **Empirical Pd:** `platformID = targetIndex + 1` (radar is platform 1) — off-by-one is common
- **Analytical Pd:** Default is **Swerling0** (`marcumq`), not Swerling I — using wrong formula gives 40% error
- **SNR:** `RadarLoopGain + RCS_dBsm - 40*log10(R)` — do NOT add integration gain (already in RLG)
See [Coordinates & Transforms](references/coordinates-and-transforms.md) for full conversion recipes and verification patterns.
## Output Requirements
1. **Requirements sheet** — standalone document (see template in references)
2. **MATLAB script** — runnable, with design-rationale comments and coupled-parameter table
3. **Validation** — compare simulation detections to analytical predictions
### Code Generation Rules
- **Never rely on defaults for `radarDataGenerator`.** Set every relevant property explicitly in the constructor, even when using the default value. This makes the code self-documenting — a reader should see every parameter choice without consulting documentation. Hidden defaults are hidden assumptions. **Exception — property gating:** Do NOT set properties that are irrelevant to the current configuration. Setting gated properties produces warnings ("not relevant in this configuration"). See the property-gating table below.
- Tag each parameter value with its source: user-provided, derived (from which inputs), or domain assumption (with justification).
### Property-Gating Rules
Properties gated by `Has*` flags — do NOT set these when the flag is `false`:
| Gate (when `false`) | Do NOT set |
|---------------------|-----------|
| `HasElevation` | `ElevationResolution`, `ElevationBiasFraction`, `MaxElevationScanRate`, `MechanicalElevationLimits`, `ElectronicElevationLimits` |
| `HasRangeRate` | `RangeRateResolution`, `RangeRateBiasFraction`, `RangeRateLimits`, `HasRangeRateAmbiguities` |
| `HasRangeAmbiguities` | `MaxUnambiguousRange` |
| `HasRangeRateAmbiguities` | `MaxUnambiguousRadialSpeed` |
Properties gated by `ScanMode`:
| ScanMode | Do NOT set |
|----------|-----------|
| `'No scanning'` | `MaxAzimuthScanRate`, `MaxElevationScanRate`, `MechanicalAzimuthLimits`, `MechanicalElevationLimits`, `ElectronicAzimuthLimits`, `ElectronicElevationLimits` |
| `'Mechanical'` | `ElectronicAzimuthLimits`, `ElectronicElevationLimits` |
| `'Electronic'` | `MechanicalAzimuthLimits`, `MechanicalElevationLimits`, `MaxAzimuthScanRate`, `MaxElevationScanRate` |
| `'Mechanical and electronic'` | (all scan properties valid) |
Never set `HasScanLoss` — it warns in all scan modes (not valid in any current configuration).
When `EmissionsInputPort=true`: do NOT set `ScanMode`, `FieldOfView`, or any scan-limit/rate properties (scan is driven by emissions).
Properties gated by `TargetReportFormat`:
| Format | Do NOT set |
|--------|-----------|
| `'Clustered detections'` or `'Detections'` | `FilterInitializationFcn`, `ConfirmationThreshold`, `DeletionThreshold`, `TrackCoordinates` |
| `'Tracks'` | `DetectionCoordinates` |
Properties gated by `DetectionMode`:
| Mode | Do NOT set |
|------|-----------|
| `'ESM'` | `ReferenceRange`, `ReferenceRCS`, `DetectionProbability` |
## References
Load only what the task requires — do not read all references for every prompt.
| Reference | When to Read |
|-----------|-------------|
| [Detection Model](references/detection-model.md) | Configuring radar properties, debugging property names, understanding detection pathway |
| [FoV & Scan](references/fov-and-scan.md) | Setting FieldOfView, scan mode config, UpdateRate/scan rate derivation |
| [Coordinates & Transforms](references/coordinates-and-transforms.md) | Interpreting detections, converting frames, NED elevation/azimuth, plotting |
| [Trajectories](references/trajectories.md) | Target motion, stationary platforms, scenario duration, body frame orientation |
| [Terrain, Clutter & Atmosphere](references/terrain-clutter-atmosphere.md) | Adding surfaces, clutter generator, atmosphere models, occlusion |
| [Radar Equation Tools](references/radar-equation-tools.md) | Bottom-up derivation, hardware-to-ReferenceRange bridge, Pd vs range |
| [Visualization](references/visualization.md) | theaterPlot, coverage plots, radarmetricplot |
| [Coupled Parameters](references/coupled-parameters.md) | Step 5: parameter-relationship table, datasheet ingestion |
| [Interaction Flow](references/interaction-flow.md) | Full 9-step workflow with suggested phrasings |
| [Requirements Sheet Template](references/requirements-sheet-template.md) | Step 9: three-section output artifact structure |
----
Copyright 2026 The MathWorks, Inc.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!