Skip to content

Quick Start

Get started with radarcontrol.io in 5 minutes.

Your First Script

When you open radarcontrol.io, you'll see the default script already loaded. Here's what it does:

javascript
onSpawn((aircraft) => {
  log(`${aircraft.cs} (${aircraft.type}) at FL${aircraft.altFL}`);

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

This code:

  1. Logs when each overflight aircraft spawns from entry points
  2. Sets up automatic handover when aircraft reach their exit point

Note: Aircraft spawn from two sources: entry points (overflights at cruise altitude) and airports (departures). Overflights trigger onSpawn, while departures trigger onDepartureControllable when they reach 10,000ft and become controllable.

Loading Your Script

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

Basic Traffic Management

Let's add some actual traffic management. Replace the default script with this:

javascript
// Handle overflights entering from entry points
onSpawn((aircraft) => {
  // Climb to cruise altitude
  aircraft.climb(fl(aircraft.plan.cruiseFL));

  // Set cruise speed
  aircraft.speed(420);

  // Direct to exit point
  aircraft.direct(aircraft.plan.exitPoint);

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

// Handle departures when they become controllable at 10,000ft
onDepartureControllable((aircraft) => {
  log(`${aircraft.cs} checking in`);

  // Give climb clearance
  aircraft.climb(fl(aircraft.plan.cruiseFL));
  aircraft.speed(420);

  // Route to exit
  aircraft.direct(aircraft.plan.exitPoint);

  aircraft.over(aircraft.plan.exitPoint, (ac) => {
    ac.handover();
  });
});

onTick(({ traffic }) => {
  const flights = traffic.all();

  // Maintain spacing with speed control
  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) {
      // Too close - slow down
      trail.speed(Math.max(lead.targetIASKts - 30, 320));
    }
  }
});

Load this script and watch the simulation manage traffic automatically!

Understanding the Code

onSpawn()

Called when overflight aircraft enter your sector from entry points (already at cruise altitude). Use it for initial clearances:

javascript
onSpawn((aircraft) => {
  // aircraft has properties: cs, type, altFL, plan, etc.
  // aircraft has methods: climb(), speed(), direct(), etc.
});

onDepartureControllable()

Called when departure aircraft reach 10,000ft and become controllable. Departures spawn from airports and are uncontrollable during initial climb-out:

javascript
onDepartureControllable((aircraft) => {
  // Departure just checked in - give climb clearance
  aircraft.climb(fl(aircraft.plan.cruiseFL));
  aircraft.speed(420);
});

onTick()

Called every ~0.5 seconds. Use it for continuous management:

javascript
onTick(({ traffic, time, weather, fixes }) => {
  // Access all aircraft: traffic.all()
  // Get specific aircraft: traffic.byCallsign("AAL123")
});

Aircraft Control Methods

Control aircraft using method chaining:

javascript
aircraft
  .climb(fl(350))      // Climb to FL350
  .speed(420)          // Speed 420 knots
  .direct("KMART");    // Direct to KMART

Common Patterns

Vertical Separation

javascript
onTick(({ traffic }) => {
  const flights = traffic.all();

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

    const lateral = distance(a.pos, b.pos);
    const vertical = Math.abs(a.altFt - b.altFt);

    // If lateral separation is tight, ensure vertical
    if (lateral < 5 && vertical < 1000) {
      a.climb(a.altFt + 2000);
    }
  }
});

Conflict Resolution

javascript
onConflict((pair) => {
  const acA = traffic.byCallsign(pair.a);
  const acB = traffic.byCallsign(pair.b);

  if (acA && acB) {
    // Climb the higher aircraft
    if (acA.altFt > acB.altFt) {
      acA.climb(acA.altFt + 2000);
    } else {
      acB.climb(acB.altFt + 2000);
    }
  }
});

Waypoint Actions

javascript
onSpawn((aircraft) => {
  // Descend before reaching waypoint
  aircraft.before("KMART", 30, (ac) => {
    ac.descend(fl(240));
  });

  // Change speed at waypoint
  aircraft.over("MERGE", (ac) => {
    ac.speed(320);
  });

  // Ensure altitude constraint
  aircraft.reach("EXIT").altitude(fl(240));
});

Debugging

Use log() to output messages to the activity panel:

javascript
log(`${aircraft.cs} is at FL${aircraft.altFL}`);
log(`Distance: ${dist.toFixed(1)}nm`);
log(`Conflict between ${pair.a} and ${pair.b}`);

The activity panel at the bottom shows all your log messages and errors.

Interactive Mode

Want to take direct control of aircraft? Switch to Interactive mode using the tabs at the top!

In Interactive mode, you can:

  • Click aircraft to select them
  • Type commands like AAL123 cfl200 s400 dr KMART
  • Use buttons for quick altitude, speed, and routing commands
  • Control aircraft just like a real air traffic controller!

Tip: Hover over the Spawn button to access the traffic intensity slider. Set it from 0% (no auto-spawn) to 100% (maximum traffic rate) to control how often new aircraft appear.

Watch for readback errors

Just like in real ATC, pilots occasionally make readback errors. Listen carefully to what they read back - if a pilot reads back the wrong altitude or heading, you'll need to correct them!

See the Interactive Commands reference for all available commands.

Two Ways to Control

radarcontrol.io offers two control modes:

Code Mode (what you just learned):

  • Write Javascript to automate traffic management
  • Handle multiple aircraft with logic
  • Perfect for complex scenarios and automation

Interactive Mode:

  • Take direct control like a real controller
  • Issue commands via text or buttons
  • Perfect for hands-on, real-time control

Switch between modes anytime using the tabs at the top of the sidebar!

Next Steps

Happy controlling!