HORUS/blog

Sep 5, 2026 · rust · middleware · ros2 · robot-architecture

Rust Robotics Middleware: What Exists and Who It's For

Rust robotics middleware is real but small. ROS 2 with Rust bindings suits most teams; Rust-native stacks fit one-board robots with strict timing.

Rust robotics middleware is real and usable, but for most teams ROS 2 with Rust bindings remains the better first choice today. The Rust-native projects, HORUS among them, are young and small, and you trade a large catalogue of ready-made parts for a stack that behaves the same on every run. That flips when your robot is one board with tight timing. The rest of this post is for a Rust developer sizing up robotics, or a robotics developer wondering whether writing the stack in Rust is worth it.

You have written Rust for a couple of years and you like what it does to your code. Then you look at robotics and the ground goes soft. Every tutorial is C++ or Python. Every job posting says ROS. Every forum thread about Rust in robotics has the same shape: an enthusiastic post from three years ago, four replies, a link to a repository whose last commit was a while back.

So you start searching, and the results are ambiguous rather than useless. Some projects call themselves frameworks and turn out to be a message bus. Some call themselves middleware and turn out to be a set of async helpers. A few look serious but have nine stars and a README written for the author. You cannot tell which ones somebody is actually running on hardware right now.

Underneath that is a question you have not quite let yourself ask. Are you drawn to this because Rust would make your robot better, or because you would rather be writing Rust? Those two answers point at different stacks, and only one of them ends with a working robot on schedule.

Should you build a robot on Rust middleware or on ROS 2?

Start on ROS 2 unless you can name your reason in one sentence. The reasons that count are narrow: your robot runs on a single board where a pause at the wrong moment is a real failure, or your team is two or three people who already write Rust fluently and would rather own a small stack than learn a large one. Everything else is true and still not decisive. Memory safety is good. The compiler catching your mistakes is good. Neither is worth giving up the mapping, navigation, visualisation and vendor driver code that the older ecosystem hands you while you are still working out what your robot is supposed to do.

The uncomfortable shape of this decision is that the Rust ecosystem is strong at the layer underneath and thin at the layer above. Message passing, timing behaviour, memory handling: in good order. A tested path planner for a differential-drive base, with the right footprint handling and recovery behaviours, maintained by people who have run it on a hundred robots: not there. You will write that yourself or borrow it from the other side, and both cost weeks.

What does robotics middleware actually do?

Middleware is the delivery system between the separate programs running on your robot. A camera driver reads frames. A perception program turns frames into a list of things it saw. A planner turns that list into a path. A controller turns the path into motor commands. Each of those is a separate program, often written by a different person, and the middleware is what lets them talk without any of them knowing where the others are or when they started.

That is the visible half. The invisible half is everything around delivery: finding out which programs exist, starting them in a sensible order, keeping a shared clock, recording every message so you can replay a bad run at your desk, and deciding what happens when a reader falls behind the writer. Those services are why teams adopt middleware instead of opening sockets themselves, and they are the reason a thin message library is not a substitute for one.

What middleware never does is the robot's actual thinking. No middleware knows how to map a room or grasp a mug. For a plain-language walk through the layer, what middleware actually does in a robot assumes no background.

What Rust robotics middleware actually exists?

Six things exist that a serious person might pick, and they are not the same category. The ROS 2 side offers community client libraries, ros2-rust and r2r, which let you write nodes in Rust that speak to the rest of a ROS 2 graph. Zenoh is a pub-sub and query protocol written in Rust that works standalone or underneath ROS 2. Dora-rs is a dataflow framework aimed at robots that run models, with Python bindings alongside the Rust. Copper is a Rust framework built around predictable, replayable execution. HORUS is an open-source real-time robotics middleware where Rust, Python and C++ share the same shared-memory ring buffers, so messages between processes on one machine are not serialised. And on microcontrollers, Embassy and RTIC occupy the space that middleware occupies on a Linux board.

The seventh option is no framework at all: Rust's own channels inside one process, plus a socket or a shared file when you need to cross a process boundary. That is a real choice for a small robot and it is where more Rust robots start than anyone admits.

How do the Rust options compare side by side?

The honest comparison is about what each option assumes you already have, not about which is best. A team with ROS 2 experience and a Rust preference wants something very different from a team that has never installed a ROS distribution and does not intend to.

OptionWho it is forWhat it assumes you knowWhen to pick itWhen not to
ROS 2 with Rust bindingsTeams who need the ecosystem but prefer Rust for their own codeROS 2 concepts, plus tolerance for community-maintained bindingsYou want navigation, drivers and tooling, and Rust only where you writeYou are allergic to the ROS build and dependency setup
HORUSSmall teams on one board mixing Rust, Python and C++Ordinary Rust, and how your own robot is structuredSame-machine message traffic and steady timing matter more than a package catalogueYou need mapping, navigation or a vendor's supported driver
Dora-rsBuilders wiring models into a robot as a dataflow graphPython and model serving, plus a graph way of thinkingYour robot is mostly a pipeline from sensors to a model to commandsYour robot is mostly closed-loop control with feedback everywhere
CopperEngineers who care about replaying a run exactlyRust, and what determinism costs youReproducing a bad run at your desk is the thing you need mostYou want a large community to answer questions
Zenoh on its ownPeople connecting machines, robots or sites that already have codeNetworking concepts and your own message definitionsThe hard problem is links between machines, not inside oneYou expected a robotics framework and wanted lifecycle and launch
Embassy or RTICFirmware developers on microcontrollersEmbedded Rust, interrupts, no operating systemThe compute is a microcontroller, not a Linux boardYour robot has a Linux board doing the real work
No framework, just Rust cratesSolo builders with a simple robotEnough systems Rust to own your own plumbingThe robot is a few programs and you value understanding all of itA second person joins, or the program count grows past a handful

Who is Rust robotics middleware actually for?

It is for small teams who will own their stack for years. That is the group where the arithmetic works. When two or three people are responsible for everything and nobody is spare, the cost of learning a large ecosystem is paid every week, and a compiler that refuses to build code with a whole class of mistake in it is worth real money. Those teams also tend to know exactly what their robot does, which means the missing package catalogue costs them less, because they were going to write their own controller anyway.

It is not for a research group that changes direction every term, because you will spend your time rebuilding parts that already exist elsewhere. It is not for a company hiring quickly, because the pool of people who write Rust and understand robots is small and you will feel that on every job posting. And it is not for a first robot, because you do not yet know which of your problems are real.

The clearest signal is boring: if you already argue about your own message formats and process boundaries, you are ready. If you have not built the robot yet, you are not.

What hardware suits a Rust-first robot stack?

One Linux board doing most of the work, with everything that matters sharing that board. This is where a Rust-native stack is at its strongest, because the problem it solves best is many programs on one machine passing data to each other without waste and without surprises. A single-board computer or a small compute module running a camera, a perception step, a planner and a controller is the shape that fits.

It fits less well when your robot is several computers that must agree. Once messages cross a network link, the properties that make a same-machine stack pleasant stop applying, and you are back to network questions that mature protocols have spent years on. A Rust stack can still be the right choice there, but the reason has changed and you should notice that it has.

Microcontrollers are their own world. If your control loop lives on a microcontroller and the Linux board only supervises, the interesting Rust story is the embedded one, and the middleware question shrinks to how the two sides exchange messages. Whether microcontrollers need middleware too is worth reading before you decide the answer is obvious.

How long before a Rust stack pays for itself?

Longer than a demo and shorter than a product, which is the awkward middle where most people give up. In the first fortnight, a Rust-native stack is faster to get moving than a full ROS 2 install, because there is less of it and less to configure. Then you hit the first thing you assumed would exist and does not, and the curve turns. That is usually a driver for a specific sensor, or a transform library, or the moment you want a graphical view of what your robot believes.

The payback shows up in the second half of the project, in the things nobody writes tutorials about. Fewer crashes at the boundary between two people's code. Fewer runs where the robot behaves differently for no reason you can find. Less time reading configuration files written in a format you only use for this. If your project ends when the demo works, you will never reach the payback and you should not pay the price.

Rough guide: three months is too short to know. A year on the same robot is long enough that the choice was either clearly right or clearly not.

Do you need to know Rust well before starting?

You need to be comfortable, not expert, and the gap between those matters less than people expect. Robotics code in Rust is mostly ordinary: structs, enums, matching, a few traits, and a lot of arithmetic. The parts of the language that take a year to feel natural, the deeper generic and lifetime work, mostly appear when you are writing a library rather than when you are using one. If you can write a small command-line tool without fighting the compiler for an afternoon, you can write a robot controller.

What actually stops people is not the language. It is that robotics has its own body of knowledge that no amount of Rust covers: coordinate frames, timestamps that must line up, the difference between what a sensor reports and what is true, and the discipline of never blocking a loop that has to run on time. Those cost more learning than the borrow checker did.

If you are still weighing the language itself rather than the stack, whether you should write robot software in Rust is the better starting point.

What does it look like when the Rust choice goes wrong?

It goes wrong quietly, and always in the same place: the day you need something you assumed you could download. The robot works. Your code is clean. Then somebody asks for a map of the room, or a live view of what the robot sees, or support for a lidar whose manufacturer ships a C++ library and a ROS package and nothing else. Suddenly you are writing a driver, badly, from a PDF, in the week you had allocated to something else.

The second failure is social. One person built the stack, understood every part, and then left, went on leave, or moved to another project. Nobody else can be onboarded from a tutorial, because there is no tutorial for your robot. With ROS 2 that person's replacement can at least read the manual for two-thirds of what they inherited.

The third is subtler. You spent the project's attention on plumbing that was never your differentiator, and shipped a robot whose actual behaviour is thin. Nobody buys a robot because its message layer was tidy.

What do you give up by picking a Rust-native stack?

You give up other people's work, and that is the whole cost in one sentence. No navigation stack that has driven thousands of real robots. No visualisation tool that everyone in your next hire's previous job already knew. No package for the depth camera you bought. No twenty answered forum threads for the error you are staring at. That absence is not a criticism of any Rust project, it is arithmetic: the older ecosystem has had two decades and tens of thousands of contributors.

You also give up a shared language with the rest of the field. When you describe your architecture at a conference or in an interview, ROS terms let people picture it instantly. Your own terms do not.

What you keep is control and predictability. Your stack does what you wrote and nothing more, upgrades happen when you decide, and a bad run tends to have one explanation rather than four candidate layers. Whether that trade is good depends entirely on whether you were going to write your own behaviour anyway.

When is ROS 2 the better choice?

ROS 2 is the better choice for most robots most of the time, and pretending otherwise would waste your year. If you need mapping and navigation, ROS 2 wins outright, because the navigation stack there has been tested on more real robots than anything else available and rewriting it is a multi-year project you have not budgeted. If you are hiring, ROS 2 wins, because you can post a job and get candidates who already know your architecture. If you are a research group publishing on top of somebody's released code, ROS 2 wins, because that released code is a ROS package.

ROS 2 also wins for anyone learning. The tutorials, the answered questions, the university courses and the assistants that write code for you all assume ROS, and fighting that current while also learning robotics is a bad trade.

In all those cases HORUS is not the answer, and neither is any other Rust-native stack. Pick the ecosystem, write your own nodes in Rust through the community bindings if you like the language, and spend your saved months on the robot's behaviour.

Is Rust middleware just ROS 2 rewritten in a nicer language?

No, and here is why. ROS 2 is a distribution: a message layer plus a large catalogue of packages covering navigation, motion planning, transforms, visualisation, simulation bridges, driver wrappers and build tooling, all released together on a schedule. The Rust projects in this space are the message layer and a little around it. Rewriting the message layer gets you a small slice of what people mean when they say ROS 2, and the rest of the catalogue is where the years went.

That distinction matters when you plan. If you assume a Rust stack is a drop-in swap, you will discover the gap in month three, on a deadline, and the recovery is expensive. If you assume it is a foundation you will build on, the same gap is a known cost you planned around.

There is also a design difference worth naming. Several Rust projects deliberately choose predictable, replayable behaviour over broad configurability, which is a genuinely different philosophy rather than a translation of an old one.

Does going Rust-native lock your Python people out?

Partly, but not the way you think. The real risk is not that Python becomes impossible. Several Rust-based stacks ship Python bindings precisely because everyone doing perception or model work lives in Python, and the bindings are usually pleasant to use. What actually happens is subtler: the Python people become consumers of a system they cannot modify. When something breaks below their layer, they file a ticket instead of fixing it, and the two or three Rust developers become a bottleneck for the whole team.

That is survivable with three people and painful with fifteen. The question to ask is not whether Python works, but who is allowed to change the parts underneath it, and whether that list is long enough to keep the team moving when the Rust developers are busy.

The mixed-language question is bigger than any one stack, and whether you should mix languages in a robot project works through the trade in more detail than a single section allows.

How do you decide which one to start with?

Answer one question honestly: what is the hardest part of your robot? If the answer involves navigating, mapping, manipulating or perceiving the world, you want the ecosystem with the most existing work in that area, and that is ROS 2 regardless of your language preference. If the answer is timing, or keeping several programs on one board fed with data, or shipping something two people can maintain for five years, a Rust-native stack is a real candidate.

Then apply a cheap test before committing. Spend one week building the smallest version of your robot's hardest part on each candidate. Not a tutorial: your part, your sensor, your loop. A week is enough to find the missing driver, the confusing build step, and the maintainer who does or does not reply.

Finally, check the maintenance signal: recent commits, more than one contributor, a licence you can ship, and answered issues from strangers. Telling a healthy project from a dead one matters more here than in almost any other software decision.

Compressed to a decision:

The HORUS Fit Framework reduces this to five axes you can score any option against: ecosystem size, setup effort, team size fit, deployment target, and licence. For Rust decisions, ecosystem size and team size fit usually settle the argument first.

If a Rust-native stack turns out to be your answer, the useful thing is having it on the shelf before the deadline that sends you looking. Put HORUS on that shelf: star it so it is in your list when you start building.

Found this useful? Share it:Discuss on HNShare on X