F Prime (F’), Code in Space, and WebAssembly
I have been a “drone nut” for quite some time. I was a member of the AUVSI and I was even part of a (very short-lived) startup that involved building consumer-grade drones for photography, search & rescue, and other uses. I’ve written ground control software and even dabbled at modifying autopilot code running directly on drones.
Quite possibly the single most difficult (and rage-inducing) aspect of writing code for the drone ecosystem is that your code is interacting with hardware. Worse, this hardware can change configuration rapidly, meaning the motor you thought you could control over PIN 5 had been moved to PIN 3, etc. Making this even more difficult was testing. Developers building applications for the cloud can have it easy in that they have a very fast feedback loop: They can go from modifying a line of code to compiling, unit testing, deploying, and testing in production all in a matter of minutes.
The feedback loop on a typical hardware development process is nowhere near as short, and often far less satisfying. Numerous studies have been done on software engineering concerning how the speed and ease with which a developer can iterate is directly related to the quality of their code and the morale of the team.
When I was writing some of my custom drone code, I had a physics engine from a 3D game environment connected to my core logic functions with duct tape, plastic straws, and the distilled tears of junior developers. I used this to try and simulate various conditions so that I could test my code without having to deploy to a real device, go outside, fly it, and pray that I could verify behavior before smashing the drone into a tree. It could still take hours for me to get “from tweak to test”, which is exhausting.
When you build for hardware, anti-corruption layers are crucial, because having the right abstractions in place means you can write simulators. Writing simulators takes a lot of time and effort. Writing your core functions such that they can be invoked either from simulators or from real hardware also takes a lot of effort and time. Some industries have a robust community full of simulators, including things like model trains, consumer drones, robots, radio controlled cars, etc. But what do you do if you’re trying to build something that doesn’t have simulators or industry standards for how to decouple a set of logic from hardware abstractions?
Typically, you suffer in silence. Fast-forwarding out of my memories and into the not-so-distant past, I discovered a technology called WebAssembly. While most of the people looking at this thought it might be great for web browsers, I had other ideas.
I thought, “You can exploit the hard boundary, portable isolation of the module to make it so the code can run anywhere. You can have code deployed to a simulator and then deployed to a production device that never needs to be recompiled.”
Even before I’d conceived of “cloud native WebAssembly” and my open source project, wasmcloud, my ideal use case for WebAssembly was for portable firmware.
I envisioned a world where I could write pure business logic inside a WebAssembly module. This logic could then react to stimulus from a host runtime and make requests of that host based on capabilities that were available. Picture a web browser where you have a whole bunch of interactive knobs and switches and meters that let you control world physics, and then you can simply upload a
.wasm file into your browser and you’re visually simulating a drone. You could even use a 3D canvas to render your drone virtually.
Then, the same code that you exercised in the browser could be dropped wholesale onto a physical device and you could expect it to behave the same.
When I heard that there was going to be a helicopter on board the Perseverance Mars probe (the Ingenuity), I immediately wondered what the development feedback loop looked like on such a device. This led me to the F prime open source project. F Prime separates the various aspects of a flight (or other hardware) system into ports that connect components, as well as events, commands, deployments, ground systems, and toolchains.
F Prime uses C++ code generation and a large amount of copy/pasted boilerplate, project templates, and YAML to wrap a bunch of ceremony around these abstractions, letting developers focus on writing, testing, and certifying core functionality.
This kind of hard barrier between components in a system is exactly what I had been working toward with WebAssembly. However, my goal had also been to reduce or outright remove boilerplate and copy/pasted ceremony code from the process.
The earliest F prime work started before 2017, and so much of it developed in parallel with WebAssembly during conception, standardization, and implementation. I can’t help but wonder what it might look like if some of the teams using F Prime had experimented with WebAssembly to satisfy their loose coupling, testing, and simulation concerns rather than C++ boilerplate.
I still want to see the day where I can write code once that I can simulate in the browser, test on ad hoc infrastructure in the cloud with massive simulated scenarios, and then deploy that same secure, immutable artifact on a physical device. It would be even more amazing if I could use that workflow to write code that @NASAPersevere took into space to run on another planet!
WebAssembly doesn’t just belong in browsers and in the cloud — it belongs in space!