A high-precision telemetry solver for bistatic passive radar systems. RETINAsolver processes simultaneous detections from multiple sensors to determine target position and velocity using Levenberg-Marquardt least squares optimization.
- 3-Detection System: Processes three simultaneous radar detections for enhanced accuracy
- 6D State Estimation: Solves for full position (x, y, z) and velocity (vx, vy, vz)
- High Precision: Sub-meter position accuracy with robust convergence
- Bistatic Radar Support: Handles sensors paired with illuminators of opportunity (IoO)
- Optional Initial Guess: Accept user-provided initial estimates for improved convergence
- JSON Interface: Simple input/output format for easy integration
- Modular Design: Clean separation of detection parsing, initial guess, and solver components
RETINAsolver/
├── main_3det.py # Main solver entry point
├── detection_triple.py # Input data structures and parsing
├── lm_solver_3det.py # Levenberg-Marquardt solver implementation
├── initial_guess_3det.py # Initial guess generation algorithms
├── Geometry.py # Coordinate system conversions
├── test_*.py # Unit and integration tests
├── ../adsb2dd/ # ADS-B to delay-doppler converter (sibling directory)
├── ../synthetic-adsb/ # Synthetic radar data generator (sibling directory)
├── test_3detections_final/ # Comprehensive test cases
├── analysis_tools/ # Performance analysis scripts
└── README.md # This file
pip install numpy scipy- Prepare detection data in JSON format:
{
"detection1": {
"sensor_lat": 40.7128,
"sensor_lon": -74.0060,
"ioo_lat": 40.7589,
"ioo_lon": -73.9851,
"freq_mhz": 1090.0,
"timestamp": 1700000000,
"bistatic_range_km": 25.5,
"doppler_hz": 150.0
},
"detection2": {
"sensor_lat": 40.6782,
"sensor_lon": -73.9442,
"ioo_lat": 40.7589,
"ioo_lon": -73.9851,
"freq_mhz": 1090.0,
"timestamp": 1700000000,
"bistatic_range_km": 28.2,
"doppler_hz": 125.0
},
"detection3": {
"sensor_lat": 40.7500,
"sensor_lon": -73.9860,
"ioo_lat": 40.7589,
"ioo_lon": -73.9851,
"freq_mhz": 1090.0,
"timestamp": 1700000000,
"bistatic_range_km": 22.8,
"doppler_hz": 175.0
}
}- Optional: Add initial guess for improved convergence:
{
"detection1": { ... },
"detection2": { ... },
"detection3": { ... },
"initial_guess": {
"position_lla": {
"lat": 40.8,
"lon": -74.0,
"alt": 10000.0
},
"velocity_enu": {
"east": 70.0,
"north": 300.0,
"up": 200.0
}
}
}- Run the solver:
python main_3det.py input_detections.json- Get results:
{
"timestamp": 1700000000,
"latitude": 40.799619,
"longitude": -73.970136,
"altitude": 10142.0,
"velocity_east": 69.7,
"velocity_north": 298.6,
"velocity_up": 200.0,
"convergence_metric": 0.617,
"residuals": [0.52, 21.3, -0.09, 7.5, -0.62, -124.2]
}You can now provide an initial guess to improve convergence for challenging scenarios:
Benefits:
- Faster convergence for distant targets
- Improved success rate in challenging geometries
- Backward compatible - works without initial guess
- Automatic validation and fallback to generated guess
Input Format: LLA position + ENU velocity in JSON Validation: Altitude 0-100km, velocity ±1000 m/s bounds checking Conversion: Automatic LLA→ENU coordinate transformation
The complete workflow from synthetic data to solved positions:
../synthetic-adsb → ../adsb2dd → RETINAsolver → analysis
- Generate synthetic data: Create realistic aircraft trajectories and radar measurements
- Convert to detection format: Transform ADS-B tracking data to bistatic measurements
- Solve for position/velocity: Process detections to recover target state
- Analyze performance: Validate accuracy and convergence characteristics
RETINAsolver implements a passive radar telemetry system that:
-
Takes simultaneous detections from three sensors, each measuring:
- Bistatic range (IoO → Target → Sensor path length)
- Doppler shift (frequency difference due to target motion)
-
Converts coordinates from geographic (lat/lon) to local ENU (East/North/Up) for calculations
-
Generates initial guess using ellipse intersection geometry or accepts user-provided estimate
-
Solves 6D optimization using Levenberg-Marquardt algorithm to minimize measurement residuals
-
Returns solution in geographic coordinates with velocity vector
- Input/Output: Geographic WGS84 (lat/lon/alt)
- Internal Processing: Local ENU tangent plane
- Conversions: Direct LLA↔ENU transformations
- Algorithm: Levenberg-Marquardt least squares
- State Vector: 6D position and velocity
[x, y, z, vx, vy, vz] - Measurements: 6 equations (3 bistatic range + 3 Doppler)
- Constraints: Altitude bounds, velocity limits, convergence criteria
- Automatic: Ellipse intersection geometry (default)
- User-Provided: LLA position + ENU velocity (optional)
- Validation: Bounds checking with automatic fallback
- Unit Tests: Individual component validation
- Integration Tests: End-to-end solver testing
- Performance Tests: Convergence rate and accuracy analysis
- Synthetic Data Tests: 20+ challenging geometric scenarios
# Core solver tests
python -m pytest test_*.py -v
# Integration tests with sample data
python main_3det.py test_3detections_final/3det_case_1_input.json
# Performance analysis
python analyze_initial_guess.py
python verify_3det_solution.py- Convergence Rate: >95% for well-conditioned problems
- Position Accuracy: Sub-meter typical, <10m worst-case
- Velocity Accuracy: ~1 m/s typical, <5 m/s worst-case
- Processing Time: <1 second per solve
Each detection requires:
| Field | Type | Description |
|---|---|---|
sensor_lat |
float | Sensor latitude (degrees) |
sensor_lon |
float | Sensor longitude (degrees) |
ioo_lat |
float | Illuminator of Opportunity latitude (degrees) |
ioo_lon |
float | Illuminator of Opportunity longitude (degrees) |
freq_mhz |
float | Transmission frequency (MHz) |
timestamp |
int | Unix timestamp (milliseconds) |
bistatic_range_km |
float | Total path IoO→Target→Sensor (km) |
doppler_hz |
float | Doppler frequency shift (Hz) |
| Field | Type | Description |
|---|---|---|
initial_guess.position_lla.lat |
float | Initial latitude estimate (degrees) |
initial_guess.position_lla.lon |
float | Initial longitude estimate (degrees) |
initial_guess.position_lla.alt |
float | Initial altitude estimate (meters, 0-100km) |
initial_guess.velocity_enu.east |
float | Initial eastward velocity (m/s, ±1000) |
initial_guess.velocity_enu.north |
float | Initial northward velocity (m/s, ±1000) |
initial_guess.velocity_enu.up |
float | Initial upward velocity (m/s, ±1000) |
| Field | Type | Description |
|---|---|---|
timestamp |
int | Input timestamp |
latitude |
float | Target latitude (degrees) |
longitude |
float | Target longitude (degrees) |
altitude |
float | Target altitude (meters) |
velocity_east |
float | Eastward velocity (m/s) |
velocity_north |
float | Northward velocity (m/s) |
velocity_up |
float | Upward velocity (m/s) |
convergence_metric |
float | Final optimization residual |
residuals |
array | Individual measurement residuals |
This repository includes supporting tools as sibling directories:
# Use tools for data generation and processing
cd ../synthetic-adsb # Generate synthetic radar data
cd ../adsb2dd # Convert ADS-B to detection formatcd ../synthetic-adsb
python server.py # Start synthetic radar APIGenerates realistic aircraft movement patterns and bistatic radar measurements for testing.
cd ../adsb2dd
npm start # Start web-based converterBrowser-based tool to convert ADS-B aircraft tracking data to detection format.
The solver returns {"error": "No Solution"} when:
- Input validation fails (invalid coordinates, frequencies, etc.)
- Initial guess validation fails (if provided)
- Levenberg-Marquardt fails to converge
- Altitude constraints violated during optimization
Error types:
{"error": "Detection X validation failed"}- Invalid detection data{"error": "Initial guess validation failed"}- Invalid initial guess bounds{"error": "No Solution"}- Optimization failed to converge
| Metric | Value |
|---|---|
| Convergence Rate | >95% |
| Position Accuracy | <1m typical |
| Velocity Accuracy | ~1 m/s typical |
| Processing Time | <1s per solve |
| Memory Usage | <10MB |
| Dependencies | numpy, scipy only |
- Code Standards: Follow existing modularity and style
- Testing: Add tests for new features
- Documentation: Update relevant README sections
- Backward Compatibility: Maintain JSON interface compatibility
- Performance: Validate solver accuracy before merging
- Modular Design: Core solver separated from data generation/conversion
- Sibling Directories: Tools maintained in separate repositories as sibling directories
- JSON Interface: Simple, language-agnostic input/output format
- Coordinate Flexibility: Handles global geographic coordinate systems
- Robust Validation: Comprehensive error checking and bounds validation
[Add appropriate license information]
[Add citation information if this is research software]
Generated using Claude Code