Bearing-PN is a three-dimensional simulator and reference implementation of bearing-only proportional navigation. The guidance loop receives target azimuth, target elevation, measurement timestamps, and the interceptor's own kinematic state. It does not receive target range, Cartesian position, velocity, acceleration, or closing speed.
The repository provides repeatable JSON scenarios, noisy angular measurements, line-of-sight (LOS) rate filtering, constrained point-mass dynamics, static and animated diagnostics, Monte Carlo noise analysis, and a timestamped real-time input interface.
This is a guidance and simulation reference, not a complete vehicle control system. A practical integration requires authoritative own-state feedback, coordinate-frame handling, safety constraints, and a lower-level controller.
The target trajectory shown in each animation is hidden simulation truth. The guidance law sees only noisy azimuth/elevation measurements and interceptor state. Capture is declared only by the simulator's evaluation layer when hidden separation is at or below the configured capture radius.
For each timestamped bearing measurement, the implementation:
- converts azimuth and elevation to a unit LOS vector;
- filters the LOS direction on the unit sphere;
- estimates the three-dimensional LOS angular-rate vector;
- computes a speed-scaled lateral PN acceleration;
- adds a separate forward-speed command;
- applies acceleration, jerk, and speed limits; and
- propagates the interceptor point-mass state.
The mathematical derivation, sign conventions, parameter definitions, JSON
schema, real-time interface, and observability limitations are documented in
docs/BEARING_PN_PIPELINE.md.
Bearing-PN/
├── assets/simulations/ README demonstration GIFs
├── analysis/ Monte Carlo angular-noise study
├── bearing_pn/ Reusable measurement, guidance, and simulation code
├── docs/ Mathematical pipeline documentation
├── examples/ Timestamped bearing-stream example
├── scenarios/ Within/outside-assumption JSON experiments
├── tests/ Automated unit and integration tests
├── demo.py Scenario runner and visualization CLI
└── realtime_demo.py CSV replay and continuous stream CLI
- Python 3.10 or later
- NumPy 1.24 or later
- Matplotlib 3.7 or later
- Pillow 9 or later
- Plotly 5.18 or later
git clone https://github.com/Waliboii/Bearing-PN.git
cd Bearing-PN
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e .On Linux or macOS, activate the environment with
source .venv/bin/activate.
Generate the default PNG diagnostic:
python demo.py --config scenarios\within_assumptions\02_constant_velocity_crossing.jsonGenerate a PNG, GIF, and self-contained rotatable Plotly animation:
python demo.py `
--config scenarios\within_assumptions\05_slow_helix.json `
--output outputs\slow_helix.png `
--animation outputs\slow_helix.gif `
--interactive outputs\slow_helix.html `
--fps 15The HTML output supports orbit, pan, zoom, play, pause, and time scrubbing. It does not require a Python server or internet connection.
Run python demo.py without --config to enter an interactive scenario. The
Cartesian target values requested by that prompt exist only to construct hidden
simulation truth; they are not passed to guidance.
scenarios/within_assumptions/ contains cases expected to be suitable for
direct bearing-only PN:
- stationary offset target;
- constant-velocity crossing;
- slower receding target;
- moderate bearing noise; and
- nonlinear slow helical motion.
scenarios/outside_assumptions/ deliberately exercises faster escape,
aggressive maneuvers, sparse/noisy updates, and collinear bearing ambiguity.
Failure in those cases is an expected experimental result. See
scenarios/README.md for the complete catalogue.
The real-time interface accepts exactly three target-measurement fields:
timestamp,azimuth,elevation
0.000,8.000,5.000
0.050,8.120,5.030
0.100,8.250,5.060Angles are degrees by default. Use --units rad for radians. Replay the example
at its recorded timing:
python realtime_demo.py `
--csv examples\bearings.csv `
--realtime `
--visualize `
--initial-position 0,0,2 `
--initial-velocity 12,0,0 `
--output-csv outputs\realtime_commands.csvThe live plot shows the dead-reckoned interceptor trail and an arbitrary-length LOS ray. It does not place a target marker because range is not observable from a single bearing stream.
Read CSV triples or JSON Lines continuously from standard input:
Get-Content examples\bearings.csv |
python realtime_demo.py --stream --realtime --visualizeFollow an actively growing measurement file:
Get-Content measurements\live_bearings.csv -Wait |
python realtime_demo.py --stream --visualize --output-csv outputs\commands.csvEach accepted measurement immediately emits one JSON diagnostic record to
standard output. --output-csv writes the same records to a flushed CSV log.
A serial, UDP, ROS, or other transport adapter can supply the documented stream
format through standard input.
For operational use, the essential downstream command is timestamp plus
acceleration_x, acceleration_y, and acceleration_z. The remaining fields
support diagnosis and analysis. See REALTIME.md for the full
stream and output schemas.
Run the Monte Carlo angular-noise sweep:
python analysis\noise_sweep.py --trials 30 --workers 4The analysis writes raw trial results, aggregate capture rates, confidence
intervals, threshold summaries, and a plot under outputs/noise_sweep/. See
analysis/README.md for options and interpretation.
python -m unittest discover -s tests -vThe test suite covers angle conversion, LOS-rate behavior, acceleration limits, configuration units, representative captures, the collinear ambiguity, and the timestamped real-time processor.
- Bearings and interceptor state use the same known, stabilized inertial frame.
- Measurement timestamps are finite, monotonic, and sufficiently accurate.
- The interceptor normally has speed and maneuver-authority margin over the target.
- Target motion is constant or changes slowly relative to guidance bandwidth.
- Bearing updates are frequent enough and quiet enough to estimate LOS rate.
- Target identity is maintained and the target remains in the sensor field of view.
- The model is three-degree-of-freedom point-mass motion without obstacles, latency, packet loss, drag, gravity, or attitude dynamics.
Bearing-only PN cannot independently determine range, closing speed, or time-to-go. A zero LOS rate may describe a collision course, a stationary point, or a target receding on the same ray. These limitations are intentional and are covered in detail in the pipeline document.


