Summary
Add a synthetic detection mode to adsb2dd that generates realistic radar detection data with configurable noise/imperfections for testing downstream components like retina-tracker and 3lips.
Motivation
Currently, adsb2dd provides perfect delay-Doppler truth data. To test tracking and geolocator algorithms, we need realistic synthetic radar detections that include:
Measurement noise (Gaussian on delay/Doppler)
Variable SNR
Missed detections (detection probability < 1.0)
False alarms (clutter detections with no ADS-B match)
This synthetic data will enable:
Testing retina-tracker ADS-B-assisted tracking (Doppler from ADS-B speed #1 )
Validating 3lips geolocation algorithms
Benchmarking algorithm performance under various noise conditions
Repeatability (same input → same output with fixed seed)
Proposed Solution
New API Endpoint: /api/synthetic-detections
Add a new endpoint that converts adsb2dd's per-aircraft output into frame-based detection arrays with realistic imperfections:
Query Parameters:
/api/synthetic-detections?server=...&rx=...&tx=...&fc=...
&noise_delay=0.5 # Delay noise std (km)
&noise_doppler=2.0 # Doppler noise std (Hz)
&snr_min=8 # Minimum SNR (dB)
&snr_max=20 # Maximum SNR (dB)
&detection_prob=0.95 # Probability of detecting aircraft [0-1]
&false_alarm_rate=0.5 # False alarms per frame
&frame_interval=500 # Frame interval (ms)
&duration=10 # Total duration (seconds)
&seed=42 # Random seed (optional, for repeatability)
Output Format
Extended .detection format compatible with blah2-arm#14 and retina-tracker:
{
"timestamp" : 1718747745000 ,
"delay" : [16.1 , 22.3 , 15.8 ],
"doppler" : [134.5 , -50.2 , 88.3 ],
"snr" : [15.2 , 12.8 , 18.5 ],
"adsb" : [
{
"hex" : " a12345" ,
"lat" : 37.7749 ,
"lon" : -122.4194 ,
"alt_baro" : 5000 ,
"gs" : 250 ,
"track" : 45
},
{
"hex" : " b67890" ,
"lat" : 37.8123 ,
"lon" : -122.3456 ,
"alt_baro" : 8500 ,
"gs" : 300 ,
"track" : 120
},
null // False alarm (clutter)
]
}
Key differences from current output:
Frame-based arrays (not per-aircraft dict)
Multiple aircraft per frame
Parallel arrays: delay, doppler, snr, adsb
adsb[i] corresponds to delay[i], or null for clutter
Sequential frames over time duration
Implementation Details
Core Logic
function generateSyntheticFrame ( aircraftData , config , rng ) {
const detections = [ ] ;
const adsb = [ ] ;
// Process each aircraft
for ( const aircraft of aircraftData ) {
// Simulate missed detection
if ( rng . random ( ) > config . detection_prob ) {
continue ;
}
// Calculate true delay/Doppler
const trueDelay = calculateBistaticDelay ( aircraft , config . rx , config . tx ) ;
const trueDoppler = calculateBistaticDoppler ( aircraft , config . rx , config . tx , config . fc ) ;
// Add Gaussian noise
const delay = trueDelay + rng . gaussian ( 0 , config . noise_delay ) ;
const doppler = trueDoppler + rng . gaussian ( 0 , config . noise_doppler ) ;
// Generate realistic SNR
const snr = rng . uniform ( config . snr_min , config . snr_max ) ;
detections . push ( { delay, doppler, snr } ) ;
adsb . push ( {
hex : aircraft . hex ,
lat : aircraft . lat ,
lon : aircraft . lon ,
alt_baro : aircraft . alt_baro ,
gs : aircraft . gs ,
track : aircraft . track
} ) ;
}
// Add false alarms (clutter)
const nFalseAlarms = rng . poisson ( config . false_alarm_rate ) ;
for ( let i = 0 ; i < nFalseAlarms ; i ++ ) {
detections . push ( {
delay : rng . uniform ( config . delay_min , config . delay_max ) ,
doppler : rng . uniform ( config . doppler_min , config . doppler_max ) ,
snr : rng . uniform ( config . snr_min , config . snr_max * 0.8 ) // Lower SNR for clutter
} ) ;
adsb . push ( null ) ;
}
return { detections, adsb } ;
}
Random Number Generation
Use a seedable PRNG (e.g., seedrandom) for reproducibility:
import seedrandom from 'seedrandom' ;
const rng = seedrandom ( config . seed || Date . now ( ) ) ;
Dependencies
seedrandom: Seedable PRNG
gaussian: For Box-Muller transform (or implement inline)
Files to Modify
src/server.js : Add new /api/synthetic-detections endpoint
src/node/synthetic.js (NEW): Synthetic detection generation logic
package.json : Add seedrandom dependency
README.md : Document new endpoint and usage examples
Testing
Create test/synthetic.test.js:
Verify output format matches extended .detection spec
Check noise statistics (mean ≈ 0, std ≈ configured value)
Validate detection probability
Test repeatability with fixed seed
Verify false alarm rate
Example Usage
# Generate 10 seconds of synthetic data with medium noise
curl " http://localhost:49155/api/synthetic-detections?\
server=http://sfo1.retnode.com&\
rx=37.7644,-122.3954,23&\
tx=37.49917,-121.87222,783&\
fc=503&\
noise_delay=0.5&\
noise_doppler=2.0&\
snr_min=8&\
snr_max=20&\
detection_prob=0.95&\
false_alarm_rate=0.5&\
duration=10&\
seed=42" > test_synthetic.detection
Then use with retina-tracker:
cd ../retina-tracker
python -m tracker.track_detections test_synthetic.detection -o tracks.json
Alternative: Extend Existing Endpoint
Instead of a new endpoint, could add synthetic=true parameter to /api/dd:
/api/dd?...&synthetic=true&noise_delay=0.5&...
Pros : Reuses existing logic
Cons : Conflates real-time and synthetic modes
Recommendation : Use new endpoint for clearer separation of concerns.
Future Enhancements
Batch generation : Generate entire datasets offline
Scenarios : Predefined noise profiles (low/medium/high)
Time-varying noise : SNR degradation over time
Multi-sensor support : Different noise for different receivers
Track-correlated noise : Aircraft-specific noise characteristics
Acceptance Criteria
Dependencies
Requires blah2-arm#14 extended detection format as reference
Will be used by retina-tracker#1 for testing ADS-B features
Related Issues
blah2-arm#14: ADS-B association in detection output
retina-tracker#1: ADS-B-assisted track initialization
tar1090-node#5: Shared geometry library (future consolidation)
Summary
Add a synthetic detection mode to adsb2dd that generates realistic radar detection data with configurable noise/imperfections for testing downstream components like retina-tracker and 3lips.
Motivation
Currently, adsb2dd provides perfect delay-Doppler truth data. To test tracking and geolocator algorithms, we need realistic synthetic radar detections that include:
This synthetic data will enable:
Proposed Solution
New API Endpoint:
/api/synthetic-detectionsAdd a new endpoint that converts adsb2dd's per-aircraft output into frame-based detection arrays with realistic imperfections:
Query Parameters:
Output Format
Extended
.detectionformat compatible with blah2-arm#14 and retina-tracker:{ "timestamp": 1718747745000, "delay": [16.1, 22.3, 15.8], "doppler": [134.5, -50.2, 88.3], "snr": [15.2, 12.8, 18.5], "adsb": [ { "hex": "a12345", "lat": 37.7749, "lon": -122.4194, "alt_baro": 5000, "gs": 250, "track": 45 }, { "hex": "b67890", "lat": 37.8123, "lon": -122.3456, "alt_baro": 8500, "gs": 300, "track": 120 }, null // False alarm (clutter) ] }Key differences from current output:
delay,doppler,snr,adsbadsb[i]corresponds todelay[i], ornullfor clutterImplementation Details
Core Logic
Random Number Generation
Use a seedable PRNG (e.g.,
seedrandom) for reproducibility:Dependencies
seedrandom: Seedable PRNGgaussian: For Box-Muller transform (or implement inline)Files to Modify
src/server.js: Add new/api/synthetic-detectionsendpointsrc/node/synthetic.js(NEW): Synthetic detection generation logicpackage.json: AddseedrandomdependencyREADME.md: Document new endpoint and usage examplesTesting
Create
test/synthetic.test.js:.detectionspecExample Usage
Then use with retina-tracker:
cd ../retina-tracker python -m tracker.track_detections test_synthetic.detection -o tracks.jsonAlternative: Extend Existing Endpoint
Instead of a new endpoint, could add
synthetic=trueparameter to/api/dd:Pros: Reuses existing logic
Cons: Conflates real-time and synthetic modes
Recommendation: Use new endpoint for clearer separation of concerns.
Future Enhancements
Acceptance Criteria
/api/synthetic-detectionsimplemented.detectionformatDependencies
Related Issues