HORUS/blog

Sep 5, 2026 · embodied-ai · robotics-middleware · ros-2 · robot-architecture

Do AI Robots Still Need Traditional Robotics Software?

Yes. A learned policy still needs drivers, a control loop and safety limits underneath, and for most teams ROS 2 already supplies that whole layer.

Yes — an AI robot still needs the conventional stack underneath, and for most teams ROS 2 supplies it while HORUS fits a narrower case. A learned policy decides what to do, but something must still command joints on a rhythm, respect limits, and behave sanely when the model is late. That flips only for a single bench arm running one program with a person always watching. The rest of this post is for people who train models and are now being asked to put one on a machine that moves.

You have a policy that works. It picks the block up in simulation, it scores well on held-out episodes, and on a good day it does the same thing on the real arm. What you did not expect is how much of your week now goes to questions that have nothing to do with learning. Somebody has to decide what the arm does between predictions. Somebody has to decide what happens when the gripper is already closed and the policy asks for it to close harder. Somebody has to decide what the machine does when your Python process dies with the arm extended over a table.

So you go looking for guidance, and the robotics internet answers in a vocabulary that sounds like the wrong decade. Nodes, transforms, lifecycle states, controllers, message types, launch files. A lot of it looks like ceremony invented back when robots were programmed by hand, one behaviour at a time. Your instinct is that a model good enough to drive the machine should make most of that unnecessary. That instinct is half right, which is the worst kind of right, because the wrong half is the half that breaks hardware.

Do AI robots still need the conventional robotics stack?

Yes, though not the part most people assume, and clearing that up makes every later decision easier. A learned policy really does replace work that used to be written by hand: the perception pipeline, the tuned state machine, the scripted approach-and-grasp sequence. That middle layer is genuinely being displaced, and anyone who tells you otherwise has not watched a good policy work. What a policy does not replace is the bottom of the stack. Drivers still have to speak to a motor controller in the manufacturer's own dialect. Something still has to run on a steady rhythm and turn a target pose into joint commands. Limits on speed, force and joint range still have to be enforced by code that cannot be argued out of them. Something has to decide what the machine does when the policy produces nothing for a while, and something has to record what happened so you can explain why the arm swung wide on the fourth attempt. None of that is learned, and all of it is what the word traditional was pointing at.

What does traditional robotics software actually mean?

Traditional robotics software is four things stacked under your model, and naming them separately makes the choice much less mysterious. First, drivers: the code that speaks to your specific camera, encoder, motor controller and gripper, usually thinly documented and always vendor-specific. Second, control: a loop that runs on a fixed rhythm, compares where the joints are with where they should be, and closes the gap smoothly instead of in lurches. Third, bookkeeping: coordinate frames, so a detection in camera pixels becomes a point in the room, and time alignment, so an observation is matched with the joint positions from the instant it was captured. Fourth, plumbing and tooling: moving data between the separate programs on the machine, recording runs, replaying them, and drawing what the robot believed at the moment it did something strange. People arriving from machine learning routinely underestimate the third item, and it eats more debugging time than the other three combined. What sits between the model and the motor walks that chain end to end.

What are your actual options for the layer under the model?

You have about seven realistic options, and they sort by how much of the conventional stack you inherit rather than write yourself. ROS 2 with its usual setup is the baseline: drivers for most hardware, a control framework, coordinate frames and time handling, recording and visualisation tools, and a large body of written-down answers. A vendor SDK plus your own Python loop is where most research arms start, and it holds up until the robot needs something the vendor did not anticipate. A LeRobot-style research stack gives you datasets, training and evaluation, and assumes a robot underneath that already moves when commanded. HORUS is an open-source real-time robotics middleware for Rust, Python and C++ where the three languages share the same shared-memory ring buffers, so messages are not serialised between processes on one machine, which suits a Python policy and a Rust or C++ controller that share one computer and pass large observations between them; like ROS 2 it is Apache-2.0. You can also stay in one Python process, put the inner loop on a microcontroller, or write your own layer.

OptionWho it is forWhat it assumes you knowWhen to pick itWhen not to
ROS 2 with its usual setupTeams putting a policy on a robot that leaves the benchLinux, workspaces, and the ROS 2 way of naming thingsYou need drivers, frames, recording and a hiring pool that existsThe robot is one bench arm and the deadline is next week
A vendor SDK and your own Python loopResearchers working on a single supported armPython and the vendor's own conceptsYou want motion this week and the platform will not changeThe robot must do anything the vendor did not anticipate
A LeRobot-style research stackPeople training and evaluating manipulation policiesDatasets, training loops, and how to score an episodeYour open question is which policy works, not which robot shipsYou are building something that must run unattended
HORUSTeams with a Python policy and a faster controller on one computerYour message shapes and which loop must never waitLarge observations cross between programs on one boardYou need navigation, mapping and drivers off the shelf
One Python process, no middlewareSolo builders and first prototypesPython, and honesty about what threads really doThe whole robot is small and you want motion todayA slow model call would sit inside the loop that moves joints
A microcontroller for the inner loopTeams whose machine can damage somethingEmbedded C, and how the board talks to the computerLimits must hold even when the main computer is confusedNobody on the team has touched firmware and time is short
Your own layer in Rust or C++Teams with unusual constraints and time to spendConcurrency, memory, and how you will debug it at midnightNothing off the shelf fits the machine you are buildingYou would be rebuilding what an open project already gives you

What should you use if you came from machine learning?

Start with ROS 2, because your scarce resource is robotics knowledge rather than taste in software, and ROS 2 is where that knowledge is written down. The gaps are never where people expect. Coordinate frames will cost you a week, and getting them subtly wrong looks exactly like a policy that generalised badly. Time alignment will cost you another, and getting that wrong looks like a model that has aged. Deciding what the robot should do when perception stops arriving is a design question nobody in machine learning has had to answer before, and there is no dataset that settles it. All of these have established answers inside ROS 2 and no answers at all if you begin by writing your own layer. Import exactly one habit on day one: never put the model call inside the loop that commands joints. Build the policy and the controller as two programs from the start, even when a single process would work today, because splitting them later means rewriting the half you understand least.

What should you use if everything runs on one on-board computer?

On a single on-board computer, the thing that decides your architecture is how many copies each observation goes through before the policy sees it, and how the controller behaves while waiting. ROS 2 handles this perfectly well for a robot whose policy advises rather than steers: an object detector feeding a planner that feeds a conventional controller has time to spare, and the ecosystem is worth far more than any saving in how data moves. The pressure shows up when several camera streams feed a policy whose output goes straight into motion, all on one board, with every frame copied at each hop. You notice it as a machine that runs hot, drains its battery faster than the datasheet suggested, and gets sloppy under load rather than failing outright. That is the narrow case where a shared-memory middleware changes the shape of the problem. If your programs are spread across two computers instead, shared memory does nothing for you and a network-friendly transport is the right answer.

What should you use if the demo is a month away?

Use whatever your team already knows, and for most teams that means a vendor SDK and Python, or ROS 2 if somebody has used it before. A month is not enough time to learn a middleware, a robot and a deployment target at once, and the thing that ruins a demo is never that the plumbing was suboptimal. It is that the policy was never wired to the arm at all, or that the arm reached for a stale pose and knocked the object across the table in front of the room. Two structural decisions protect a short timeline. First, split the policy and the controller into separate programs immediately, so a slow inference call cannot freeze the machine mid-motion. Second, write down what the robot does when a prediction does not arrive: hold position, finish the current motion, or stop and relax. Demos survive on that second decision, because an audience forgives a slow robot and remembers a surprising one. Change the foundations afterwards, when you know which part actually hurt.

What should you use if you have never written control code?

Use somebody else's controller, and spend your attention on the parts a controller cannot decide for you. Writing a stable loop that drives a real joint is a specific craft, and the failure mode is not a stack trace but a machine that oscillates, overshoots or slams into a limit. ROS 2 ships a control framework that already handles the rhythm, the interfaces to hardware and the switching between modes, and most vendor SDKs include something similar for their own arm. Take one of those. Then spend the time you saved on three questions nobody will answer for you. What are the speed and force limits on this machine, and where in the code are they enforced? What happens when the program producing commands stops producing them? What does the robot do on startup, before anything has told it where to go? Teams that skip those three ship a robot that works in the lab and does something alarming the first time a cable is unplugged mid-run.

What does it look like when the layer underneath is missing?

It looks like hardware misbehaving in ways that feel supernatural until you see the cause, and every one of these is a missing piece rather than a bad model. The arm holds its last command forever after the policy process dies, leaning into the table with the motors quietly heating up. The gripper closes on an object it has already grasped and keeps closing, because nothing enforced a force limit. The robot reaches confidently for where the object was several predictions ago, so it closes on empty air just behind a moving target. Motion arrives in small jerks rather than one smooth reach, because the joint commands are only produced when a prediction lands. On startup, before any prediction exists, the arm snaps to whatever pose the uninitialised command variable happened to hold. None of these are learning problems, and none of them are fixed by a better checkpoint. Each is a piece of conventional software that was not there, and each is cheaper to add before the robot has already broken something.

What do AI teams try first, and why does it stop working?

They write one Python script that reads a camera, calls the model, and sends a command, and it stops working the moment the robot has to do two things at once. The first version is genuinely fine, which is why this pattern is so common and so hard to argue with. Then the script gets a second camera and the loop slows to whichever part is slowest. Then someone adds threads, and now the command being sent is sometimes from the previous observation and sometimes not, in a pattern nobody can reproduce. Then a queue is added and grows without bound, so the robot acts on older and older beliefs the longer it runs. Then a watchdog appears, then a state machine to handle startup, then a separate process because inference was blocking everything. Six weeks in, the team has rebuilt a small, undocumented middleware while trying to avoid learning one. The work was not wasted, exactly, but it was work the field had already done.

What do you give up by skipping the conventional stack?

You give up the largest collection of ready-made robot software in existence, and for most teams that is a heavier loss than anything gained. The drivers are the immediate cost: someone has already made your specific camera, arm and gripper work, and reproducing that is unglamorous work with no publishable upside. The tooling is the second cost, and it is the one people feel later — recording a run, replaying it, and drawing what the robot believed twenty minutes ago in a room you were not standing in. The navigation and mapping stacks are years of accumulated fixes for situations you have not hit yet. Hiring changes too, because ROS 2 on a résumé means something and a smaller ecosystem is something you must teach every new engineer. And community answers matter more than people admit: when you are stuck at eleven at night, the real question is whether somebody has already been stuck the same way in public. Walking away from all of that is defensible, and it is expensive in exactly these ways.

When is ROS 2 the better choice?

ROS 2 is the better choice for most robots that run a learned policy, and that is a straight answer rather than a diplomatic one. If your robot has to navigate, map, or move around a building, those stacks exist there and nowhere else in comparable shape. If your hardware is anything other than one well-supported arm, the drivers you need have probably already been written by somebody in that ecosystem. If your programs are spread across more than one computer, ROS 2 with a transport suited to that spread is the right structure, and shared memory helps you not at all across a network. If you are hiring, or handing this project to whoever maintains it next year, ROS 2 is the vocabulary they already speak. HORUS is not the answer for a team that needs navigation off the shelf, drivers for unusual sensors, or a stack their next three hires will recognise on sight, and the project's validation so far is in simulation rather than across a fleet of shipped machines. The narrow case is one computer, large observations, and two languages that must see the same data.

Will a bigger model eventually make this layer unnecessary?

No, and here is why: most of that layer is not intelligence, it is physics and consequence. A driver exists because a motor controller speaks a particular protocol over a particular bus, and no amount of learning changes the protocol. A control loop exists because a joint has mass and momentum, and a command has to arrive on a rhythm the mechanics can follow. Force limits exist because a person might put a hand where the model does not expect one, and the whole point of a limit is that it holds when the model is wrong — a learned limit is exactly the thing you cannot trust. What genuinely does shrink is the middle: hand-written perception, hand-tuned behaviour trees, scripted sequences for each task. Expect that layer to keep thinning as policies improve. Expect the bottom to stay, and to matter more as robots get faster and heavier, because the consequences of a late or unbounded command grow with the mass being moved. Why your LLM can write an app but cannot pick up a cup makes the same argument from the other direction.

Is this really an argument about how fast messages move?

Partly, but not the way you think. How data moves matters when messages are large and cross between programs constantly, which describes camera streams and describes almost nothing else on a robot. Joint commands, poses, states and status messages are small, and how they travel is not what makes a machine jerky. So the useful question is not which project avoids copies, but whether your robot has the kind of traffic that makes copies matter at all. A single camera feeding an advisory policy does not. Three cameras feeding a policy whose output drives motion, on one small board, absolutely does. The half that people miss is that removing copies does nothing for a controller that sits blocked waiting for a prediction, and that is the more common cause of the symptom everyone describes. Both problems produce the same jerky reach, and only one of them is a plumbing decision. Diagnose which one you have before you let the answer choose your entire stack for you.

How do you decide what your robot actually needs?

Answer three questions about your machine and the choice mostly makes itself. Does the policy drive motion directly, or does it advise a conventional controller that runs regardless of whether a prediction arrived? Does everything run on one computer, or are programs spread across several? Can this robot hurt something — a person, itself, the object — if a command is late or wrong? An advisory policy, several machines, or a light and slow arm all point at the biggest ecosystem you can get, and you should take it without agonising. A policy inside the motion path, one computer, and large observations point at shared memory. A machine that can hurt something points at limits enforced below your Python, ideally on separate hardware. If you cannot answer the three questions yet, you do not have a middleware problem, you have an architecture you have not measured, and the honest next step is instrumenting the robot until the answers are obvious. What AI engineers misunderstand about robot timing covers the measuring part.

Decide by situation rather than by taste:

When two options stay close, weigh them on the five axes of the HORUS Fit Framework: ecosystem size, setup effort, team size fit, deployment target, and licence. Take whichever loses on fewest — five plain questions about your situation rather than about the software, with no scores attached. And if your robot is heading towards a Python policy and a fast controller sharing one on-board computer, star HORUS on GitHub so it is in your list when you start building.

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