From Threads to Drones: Learning Distributed Systems by Building

April 30, 2026 · engineering

In 2015, I stood at Kennedy Space Center presenting a system designed to work when everything else has fallen apart. No cell towers, no internet, no centralized control - just a swarm of autonomous quadcopters coordinating as a distributed system with no single point of failure. We won second prize at the Intel Cornell Cup.

That project was the capstone of a two-year journey through distributed and parallel computing — from raw threads, to cloud infrastructure, to autonomous agents operating without any infrastructure at all.

ADRA — Autonomous Disaster Relief Assistants

ADRA was a swarm project — autonomous quadcopters that could coordinate with each other to assist relief workers in disaster scenarios. The key constraint was that you couldn’t rely on existing infrastructure. No cell towers, no internet, no centralized control. The drones had to communicate, coordinate, and make decisions as a distributed system with no single point of failure.

ADRA system architecture: drone swarm, ground station, and cloud layers

The project was hard, and required specialities in multiple domains — hardware to build the quadcopters, on-device software to provide telemetry data, and command center software to understand that data and make decisions in near real-time.

I remember using the university’s “build labs” to design and assemble quadcopter components. Spending late evenings debugging ROS code, trying to figure out why decisions weren’t being communicated between nodes. And building a simulation world to test things out, since we didn’t have a budget for many physical drones.

If I were building it today, the tooling would be wildly different — ROS2, better simulation, better networking stacks. But the core challenge remains the same: how do you get independent agents to act as one?

That question never stopped being interesting.


But ADRA wasn’t built in a vacuum. It was built on foundations laid in two earlier projects.

OpenMP Pre-Processor

During my Operating Systems coursework, I wrote a pre-processor in C/C++ that translated OpenMP directives into equivalent PThreads code — parallel, parallel for, critical, single, sections, and barriers.

The point was to understand what the compiler actually does when you write #pragma omp parallel for. It managed thread pools, implicit barriers, data scoping.

The specifics are less important than the lesson:

Abstractions are useful, but understanding what lies beneath them is what makes you effective at debugging when they break.

ADRA’s drones made decisions autonomously. That kind of parallelism doesn’t come from nowhere — it starts at the thread level.

CIRRUS

A web application for monitoring and managing cloud infrastructure deployed on OpenStack. This was my first real exposure to API-driven orchestration — managing distributed state through dashboards, keeping monitoring data in sync with live infrastructure, and building tools for systems you don’t fully control.

It was the bridge project: moving from parallelism inside a single program to coordination across many machines. The same kind of coordination ADRA’s swarm needed, but with the luxury of a reliable network.


Tracing back from that stage at Kennedy Space Center, I can see how each project was a stepping stone. The pre-processor taught me what parallelism means at the machine level. CIRRUS showed me coordination across machines — imperfect, over a network. And ADRA forced me to think about coordination when there’s no infrastructure at all.

Somewhere between the thread-level debugger and the drone swarm, I stopped thinking like a programmer and started thinking like a systems builder.