Back to Projects

// Simulation & Control · February 2026

Missile Trajectory Tracker

PythonPygameProportional NavigationGuidance & ControlFlight Dynamics3D RenderingPhysics Simulation

A ground-to-air intercept simulation: a proportional-navigation missile chases an aircraft that fights back, plotted in a 3-D space you can orbit.

The Problem

Pointing a missile at where an aircraft currently is doesn't intercept it. By the time you arrive the target has moved, and against anything manoeuvring a pure-pursuit missile ends up in a tail chase it can't win. Interception means steering toward where the target is going to be — using only what a seeker can actually measure, which is the bearing to the target and the rate at which that bearing is changing.

The Approach

Implemented proportional navigation, the guidance law real interceptors use: acceleration command = N × closing velocity × line-of-sight rate, with a navigation constant of 4. The insight it encodes is that if the bearing to your target isn't rotating, you're already on a collision course — so the missile steers to drive the line-of-sight rate to zero, which produces lead pursuit instead of a tail chase. The missile flies against real dynamics rather than in a vacuum: thrust along its own velocity vector, gravity, quadratic drag, a turn-rate limit and a hard speed cap, so the guidance has to cope with a vehicle that doesn't do exactly what it's told. The 3-D view is hand-rolled rather than imported — spherical camera position, forward/right/up basis vectors, perspective divide — which kept the whole simulation to a single dependency.

The Outcome

Built in one night; first commit at midnight, last at 01:29. The final commit is the one worth pointing at: once interception worked reliably, the target got a threat model. The aircraft computes a continuous 0-to-1 threat level from missile range and scales its whole response against it — turn rate from 1.2 to 3.0 rad/s, pitch authority from 15° to 50°, a speed boost, shorter intervals between manoeuvres, and hard break-turns perpendicular to the threat bearing. Making the problem harder once the easy version worked turned out to be more interesting than tuning the guidance further. Around 990 lines of Python, one dependency.

View on GitHub