matlab-simulate-radar-detections
GitHub基于radarDataGenerator构建雷达检测统计仿真,支持从硬件规格生成场景、诊断配置错误、分析覆盖范围及验证性能。
Trigger Scenarios
Install
npx skills add matlab/matlab-agentic-toolkit --skill matlab-simulate-radar-detections -g -y
SKILL.md
Frontmatter
{
"name": "matlab-simulate-radar-detections",
"license": "https:\/\/www.mathworks.com\/content\/dam\/mathworks\/license\/pmrl\/license.md",
"metadata": {
"author": "MathWorks",
"version": "1.0"
},
"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.\n"
}
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
radarDataGeneratorcode 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
radarDataGeneratorstandalone (withoutradarScenario) 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 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 — 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:
ReferenceRCSis 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 § Step 4 for the full decision table.
Step 5: Present Coupled-Parameter Table
Show the parameter-relationship table from 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 for patterns. Default platform RCS is 10 dBsm (Swerling0).
Sanity checks before proceeding:
-
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. -
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). 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 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.
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
radarDataGeneratorprovides 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
waypointTrajectoryhas'ReferenceFrame'property:'NED'or'ENU'— use withIsEarthCentered = falsekinematicTrajectoryhas NOReferenceFrame— inherits from scenario — use withIsEarthCentered = falsegeoTrajectoryuses geodetic waypoints [lat, lon, alt] in [deg, deg, m] — requiresIsEarthCentered = true- Has
'ReferenceFrame'('NED'/'ENU') for velocity/orientation interpretation - Also supports
Course,GroundSpeed,ClimbRateas alternatives toVelocities DetectionCoordinates = 'Scenario'reports in ECEF (meters), not lat/lon- Single waypoint = stationary platform (TimeOfArrival is ignored)
- Has
- Constraint: trajectory type and
IsEarthCenteredare 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. |
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:
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 >= 18Hz
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 fromReferenceRange+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/Bandwidthaffect 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
marcumqfor Swerling0,Pfa^(1/(1+SNR))for Swerling1. Using the wrong formula gives ~40% Pd error. See 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:
% 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):
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 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:
- Release the sensor, then go omnidirectional:
origFoV = radar.FieldOfView;
origScan = radar.ScanMode;
release(radar);
radar.FieldOfView = [360; 180];
radar.ScanMode = 'No scanning';
- Restart and re-run the scenario (
restart(scenario)+ advance loop) - 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)
- Release and restore original config before continuing:
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
- Omnidirectional isolation (above) — rules out beam pointing in one test
- Inspect systematic causes — RangeLimits gate, scan sector bounds, UpdateRate aliasing. These produce deterministic failures (0% Pd) and are identifiable from a single run.
- 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 negativeel. - 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 for full conversion recipes and verification patterns.
Output Requirements
- Requirements sheet — standalone document (see template in references)
- MATLAB script — runnable, with design-rationale comments and coupled-parameter table
- 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 | Configuring radar properties, debugging property names, understanding detection pathway |
| FoV & Scan | Setting FieldOfView, scan mode config, UpdateRate/scan rate derivation |
| Coordinates & Transforms | Interpreting detections, converting frames, NED elevation/azimuth, plotting |
| Trajectories | Target motion, stationary platforms, scenario duration, body frame orientation |
| Terrain, Clutter & Atmosphere | Adding surfaces, clutter generator, atmosphere models, occlusion |
| Radar Equation Tools | Bottom-up derivation, hardware-to-ReferenceRange bridge, Pd vs range |
| Visualization | theaterPlot, coverage plots, radarmetricplot |
| Coupled Parameters | Step 5: parameter-relationship table, datasheet ingestion |
| Interaction Flow | Full 9-step workflow with suggested phrasings |
| Requirements Sheet Template | Step 9: three-section output artifact structure |
Copyright 2026 The MathWorks, Inc.
Version History
- 2026.08.13 Current 2026-08-16 07:20
- 2026.07.16 2026-07-24 16:20


