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)
- JSON Interface: Simple input/output format for easy integration
- Modular Design: Clean separation of detection parsing, initial guess, and solver components
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
}
}- Run the solver:
python main_3det.py input_detections.json- Get results:
{
"timestamp": 1700000000,
"latitude": 40.799619,
"longitude": 286.029864,
"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]
}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
-
Solves 6D optimization using Levenberg-Marquardt algorithm to minimize measurement residuals
-
Returns solution in geographic coordinates with velocity vector
detection_triple.py: Parses and validates 3-detection input datainitial_guess_3det.py: Generates initial position/velocity estimatelm_solver_3det.py: Levenberg-Marquardt solver with bounds checkingmain_3det.py: Main entry point and JSON interfaceGeometry.py: Coordinate system conversions (LLA ↔ ECEF ↔ ENU)
Run the test suite to verify functionality:
# Run unit tests
python -m pytest test_detection_triple.py test_lm_solver_3det.py -v
# Run convergence tests
python test_convergence.py
# Test with sample data
python main_3det.py test_case.jsonExpected performance:
- 100% convergence rate on well-conditioned problems
- Sub-meter accuracy for typical scenarios
- <1 second processing time 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) |
Note: All three detections must have the same timestamp (simultaneous).
| 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 git submodules:
# Initialize submodules
git submodule update --init --recursive
# Use tools for data generation and processing
cd tools/synthetic-adsb # Generate synthetic radar data
cd tools/adsb2dd # Convert ADS-B to detection formatsynthetic-adsb → adsb2dd → RETINAsolver
- synthetic-adsb: Generates synthetic aircraft movement and radar measurements
- adsb2dd: Converts ADS-B aircraft tracking data to delay-Doppler detection format
- RETINAsolver: Solves for target position and velocity
- Input/Output: Geographic coordinates (WGS84 lat/lon/alt)
- Internal: Local East-North-Up (ENU) tangent plane
- Conversions: Via ECEF intermediate coordinate system
- Method: Levenberg-Marquardt least squares
- State Vector:
[x, y, z, vx, vy, vz](6 dimensions) - Constraints: Altitude bounds (0-30km), reasonable velocity limits
- Residuals: 6 equations (3 range + 3 Doppler measurements)
- Geometry: Ellipse intersection method
- Position: Average of ellipse centers between sensor pairs
- Velocity: Zero initial velocity assumption
- Bounds: Ensures positive altitude for convergence
The solver returns {"error": "No Solution"} when:
- Input validation fails
- Initial guess is outside bounds
- Levenberg-Marquardt fails to converge
- Altitude constraints violated
- Convergence Rate: >95% for well-conditioned scenarios
- Accuracy: Sub-meter position, ~1 m/s velocity
- Processing Time: <1 second per solve
- Memory Usage: Minimal (<10MB)
- Dependencies: Only numpy and scipy required
- Run tests before submitting changes
- Follow existing code style and modularity
- Update tests for new features
- Maintain backward compatibility for JSON interface
[Add appropriate license information]
[Add citation information if this is research software]
Generated using Claude Code