Layer 1 · the orchestrator, visible
Type a mission. Watch it fly.
Loading viewport…
plan: mock
🛬 loading traffic…
drag = orbit · scroll = zoom · right-drag = pan
MissionPlan (typed)
{
"name": "mock-patrol",
"goal": "patrol Marina beach in a triangle, 30m altitude",
"drones": [
{
"drone_id": "cf01",
"color": "#7cf7c1"
},
{
"drone_id": "cf02",
"color": "#f7c17c"
},
{
"drone_id": "cf03",
"color": "#7cb7f7"
}
],
"legs": [
{
"drone_id": "cf01",
"waypoints": [
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
},
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
}
],
"speed_mps": 2
},
{
"drone_id": "cf02",
"waypoints": [
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
},
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
}
],
"speed_mps": 2
},
{
"drone_id": "cf03",
"waypoints": [
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
},
{
"x": -25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 25,
"y": -15,
"z": 20,
"dwell_s": 1
},
{
"x": 0,
"y": 25,
"z": 20,
"dwell_s": 1
}
],
"speed_mps": 2
}
],
"safety": {
"max_alt_m": 30,
"min_alt_m": 5,
"geofence_radius_m": 100,
"rth_battery_pct": 25
},
"home": {
"lat": 13.0067,
"lon": 80.2206,
"alt_m": 10
}
}Same Pydantic schema as
flymax-orchestrator. Same JSON flies in this browser sim, in Gazebo, and on a real Crazyflie 2.1+. The orchestrator never knows which backend it's talking to.