Skip to content

What is radarcontrol.io?

radarcontrol.io is an ATC sim that runs in your browser. You manage aircraft the way real controllers do - issue clearances, maintain separation, and move traffic through busy airspace.

Two ways to play:

  • Manual - click aircraft, type instructions, issue clearances in real-time
  • Code - write Javascript to automate traffic management

This is an early preview under heavy development by balintb. Expect bugs.

How it works

Interactive mode

Click aircraft on the radar, type instructions, or use the control panel.

Text instructions:

AAL123 cfl200 s400 dr KMART    # Climb FL200, speed 400, direct KMART
DAL456 c10000ft s250           # Descend 10,000ft, speed 250

Control panel:

  • Click an aircraft to select it
  • Use the altitude, speed, and routing buttons
  • Type instructions with autocomplete for waypoints and callsigns

Code mode

Use the built-in editor (same engine as VS Code) to write traffic management logic:

javascript
onSpawn((aircraft) => {
  // Initial clearances for new aircraft
  aircraft
    .climb(fl(aircraft.plan.cruiseFL))
    .speed(420);

  // Set up handover at exit
  aircraft.over(aircraft.plan.exitPoint, (ac) => {
    ac.handover();
  });
});

onTick(({ traffic }) => {
  // Manage spacing between aircraft
  const flights = traffic.all();

  for (let i = 0; i < flights.length - 1; i++) {
    const lead = flights[i];
    const trail = flights[i + 1];

    const dist = distance(trail.pos, lead.pos);

    if (dist < 8) {
      trail.speed(Math.max(lead.targetIASKts - 30, 320));
    }
  }
});

Hit Ctrl+Enter or click "Load Script" to run your code.

Core concepts

Aircraft spawning

Aircraft enter from three sources:

Overflights spawn at sector entry waypoints, already at cruise altitude and immediately controllable.

Departures spawn on airport runways and take off. Below 10,000 feet they follow standard departure procedures automatically - you can't control them yet. Once they hit 10,000 feet, the pilot checks in ("American one two three with you, 10,000 feet") and the onDepartureControllable event fires.

Arrivals enter at sector waypoints at cruise altitude, headed for airports in your sector. You descend them, vector to the ILS, clear the approach, and hand off to tower. See Arrivals & ILS Approaches.

Want ground control instead? Tower mode gives you pushback, taxi, and runway operations at 300+ airports.

Traffic intensity: Hover the Spawn button in the toolbar. Slider goes from 0% (no auto-spawn) to 100% (roughly every 2 minutes). Setting saves automatically.

Event handlers

Your code responds to these events:

  • onSpawn() - aircraft enters your sector (overflights and arrivals)
  • onDepartureControllable() - departure hits 10,000ft and checks in
  • onTick() - every simulation tick (~0.5s), for continuous management
  • onConflict() - two aircraft predicted to lose separation
  • onApproachCleared() - aircraft cleared for ILS approach
  • onILSEstablished() - aircraft captures the localizer
  • onLanding() - aircraft touches down

Safety and crashes

DANGER

Two things will kill aircraft:

Midair collision. Less than 0.5nm lateral AND less than 200ft vertical = loss of both aircraft. Crash screen appears. Keep 5nm lateral or 1000ft vertical separation at all times.

Weather. Deny a deviation request and the aircraft flies into severe weather? It's gone. Approve deviations unless you have a specific reason not to.

Aircraft control

javascript
aircraft.climb(fl(350))        // Climb to FL350
aircraft.descend(fl(240))      // Descend to FL240
aircraft.speed(420)            // Set speed to 420 knots
aircraft.direct("KMART")       // Direct to waypoint
aircraft.offset(2)             // Offset 2nm right
aircraft.handover()            // Clear for handover
aircraft.clearILS("27L")       // Clear ILS runway 27L
aircraft.contactTower()        // Hand off to tower
aircraft.goAround()            // Instruct go-around

Waypoint events

React to aircraft reaching specific waypoints:

javascript
// Do something when aircraft reaches a waypoint
aircraft.over("KMART", (ac) => {
  ac.climb(fl(380));
});

// Do something before reaching a waypoint
aircraft.before("MERGE", 30, (ac) => {
  ac.speed(320);
});

// Ensure a constraint is met at a waypoint
aircraft.reach("EXIT").altitude(fl(240));

Helper functions

javascript
distance(ac1.pos, ac2.pos)     // Distance in nm
headingTo(from, to)            // Heading in degrees
fl(350)                        // Convert FL to feet (35000)
log("message")                 // Activity panel output

Tips

  • log() is your best debugging tool
  • Start simple. Add complexity once things work.
  • Radar shows predicted tracks (dotted lines) so you can spot conflicts early
  • Press Ctrl+Space in the editor for autocomplete

Next steps