Sep 5, 2026 · ai-assistants · vibe-coding · robot-software · getting-started
What AI Coding Tools Get Wrong About Robot Software
AI coding tools write robot code that is correct on screen and wrong in time. Here is what they miss, why it breaks on hardware, and what to let them write.
AI coding tools fail the same way on ROS 2 and its alternatives: they write robot code correct on screen and wrong in time. They learned from software where a late answer is an inconvenience; on a robot a late answer is a machine still moving. That flips when the code never touches hardware, where the assistants are genuinely good on ROS 2 and on HORUS alike. The rest of this post is for somebody building a robot with an assistant open beside them, wondering which of its suggestions to trust.
The first hour is the best hour you have had in months. You describe a robot that watches a camera and moves an arm, and a working file appears — imports correct, structure sensible, comments explaining themselves. You run it, and something moves. It feels as though the hard part is behind you.
Then the second week happens. The arm overshoots, but only sometimes. You paste the error in and receive an apology and a short wait added to a loop, which fixes it for three runs. A camera callback starts arriving late whenever the motor draws current, and the suggested fix is a bigger buffer, which converts a stutter into a delay you can watch with your own eyes. Every individual answer sounds informed. Several of them refer to a version of the framework from two releases ago. Nothing in the conversation ever asks what the machine should do if a message does not arrive at all.
By the end of the month you notice something uncomfortable. You are the only one in the room who knows whether the robot is about to hit the table.
What do AI coding tools actually get wrong about robot software?
They get time wrong, and nearly everything else follows from that. An assistant is excellent at the shape of code: imports, class structure, argument order, and the boilerplate a framework demands before it will run at all. It is poor at the properties that decide whether a robot works, because those properties are not visible in any single file. Whether a loop finishes before the next one is due, whether a sensor reading is fresh enough to act on, what the machine does when a message never arrives, what state the hardware is left in when a program dies mid-motion — none of that is present in the text being predicted. Worse, the training material is full of examples where ignoring those questions was correct, because in a web service a slow response is a spinner and a crash is a restart. The tool has learned a reasonable set of habits for a world where nothing has momentum. On a robot, momentum is the whole problem, and those habits turn into failure modes.
What kind of software is robot software, in plain terms?
Robot software is software with a deadline attached to every action and no undo. Three things separate it from the applications most code is written for. First, it runs continuously instead of answering requests: the same loop repeats forever, and the interesting question is not what it computes but whether it finishes in time to compute the next one. Second, it touches something with mass. A late web request shows a spinner; a late stop command shows a dent in a table leg, and the world does not roll back when a program throws. Third, it is made of parts running at once — a camera arriving at its own rhythm, joints wanting commands at theirs, a planner thinking slowly, and a safety check that must never end up queued behind any of them. Most bugs live in the gaps between those parts rather than inside any one of them. That is why robot code can be correct line by line and wrong as a machine, and why reading the file tells you less than you expect.
What are you choosing between when an assistant suggests a stack?
You are choosing between five things, and the assistant will suggest one of them for reasons that have nothing to do with your robot. ROS 2 is the default answer, because the material behind it is enormous: tutorials, forum threads, thousands of packages, a decade of accumulated questions. That is a genuine advantage, since a tool that has read a great deal of a framework invents fewer function calls in it — but the same volume means advice from several incompatible versions gets blended into one confident answer. A single program with no middleware is what assistants write best, and for a small robot it is often the right choice. A hardware vendor's toolkit gets you moving soonest and least portably. A message broker suits telemetry leaving the robot. And there are lighter middlewares such as HORUS, 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 between processes on one computer are never serialised.
How do the stacks compare when an assistant writes most of the code?
They compare on which mistakes you would have to catch yourself, which is why the last column decides this rather than the feature list. A stack an assistant knows well produces code that runs sooner; a stack it knows less well produces code you must check against documentation line by line.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| ROS 2 | Robots that must perceive, map and navigate | Linux, build tools, how processes find each other | You need drivers and packages that exist | You cannot yet tell a config error from a code error |
| HORUS | Small teams whose robot is one loop on one computer | Rust, Python or C++, and where your processes split | Timing on one machine is what users notice | You need mapping and planners more than timing |
| One program, no middleware | First robots and anything a single loop can run | One language and one file | The whole robot fits in one process | A second program needs the same sensor data |
| A hardware vendor's toolkit | People with one arm or one base to drive | The vendor's tools and their examples | Getting specific hardware moving today | You will change supplier or add a machine |
| A message broker | Fleets, dashboards and telemetry off the robot | Networking, brokers and message formats | Data leaves the robot for something else | The control path itself depends on delivery |
| Simulation only | Learning, and testing behaviour safely | A simulator and its quirks | Nothing should move yet | Hardware quirks are the actual question |
Are you a web developer, a student, or a team shipping a machine?
Your background decides which of the assistant's mistakes you will miss. A web developer arrives with instincts that are exactly wrong here: retry the request, add a queue, make everything asynchronous and let the framework sort out ordering. Those habits are correct where work can wait and dangerous where a joint cannot, and an assistant will happily reinforce every one of them because its training agrees with you. A student is in the best position, because a tutor that never tires is worth a great deal and nothing on the bench can hurt anybody — the risk is learning patterns that quietly do not transfer to hardware. A team shipping a machine faces the subtlest version: generated code passes review because it reads well, and reviewers who would have questioned a colleague's shortcut nod at a file that looks like every tutorial they have seen. Whichever you are, the useful move is to name the failure your background will not notice, and put a second person on that part.
Does the hardware you drive change how far you can trust suggestions?
Yes, and it changes the stakes far more than the code changes. A small wheeled robot on a carpet forgives almost everything: a wrong sign sends it into a wall, you laugh, you fix it. An arm with reach, a gripper and a payload forgives nothing, because the same wrong sign puts a moving mass where a hand was. Anything with a blade, a heater, a heavy tool, or enough force to trap a finger belongs in a different category of review entirely, and generated code should not command it until a person has read every line that decides when it stops. Small computers add a quieter problem. Assistants write for the machine they were trained on, which is a desktop with generous memory and every library available, so the suggestion assumes a package that has no build for your board and a memory budget you do not have. None of that is visible in the answer, and all of it appears at the worst moment. What vibe coders should know before code controls hardware covers the safety half of this properly.
What if you have a weekend and want something moving?
Then use the assistant hard and shrink the blast radius physically instead of arguing with the code. Put the robot on a bench, take the payload off, keep the power limits low, and stand where you can reach the switch. Ask for one program in one language with no middleware, because that is the shape assistants write most reliably and the shape you can read end to end when it misbehaves. Do not ask for architecture over a weekend; ask for motion. Over two days, the questions this post is about mostly will not bite you, since nothing runs long enough for drift, load or a stale reading to matter, and that is precisely why a weekend result is weak evidence about a product. The important discipline is what you do afterwards. Write down every strange thing you saw and every workaround you accepted, because that list, not the working demo, is the honest starting point for anything you intend other people to stand near.
How much do you need to know to catch what the assistant misses?
Enough to ask three questions of any generated file, which is a much lower bar than writing the file yourself. First: what does this do if the message never arrives? If the answer is that the loop waits forever, or acts on whatever it saw last without knowing how old it is, you have found the most common defect in generated robot code. Second: what happens if this loop takes longer than the gap between sensor readings? If nobody has thought about that, the program works on an idle laptop and fails on a busy robot. Third: what state is the hardware left in if this program dies right here? A gripper mid-close and a joint mid-move are answers you want on purpose rather than by accident. You do not need to be able to write the code to ask those. You need to refuse to accept a file that has no answer, which is a habit rather than a skill.
Why does generated code work three times and fail the fourth?
Because the mistakes are about timing and ordering, and timing and ordering only misbehave when something else is happening. On the fourth run the motor draws current and the camera driver stalls for a moment. Or the log file has grown and a write takes longer than it did. Or a second program started, and the two now compete for the same processor while a control loop quietly slips past its deadline. The code is identical every time; the machine is not. This is why the pasted-error conversation goes in circles — an assistant reads the file and the traceback and correctly concludes the file is fine, then suggests a wait, a retry or a larger buffer, each of which hides the symptom by trading it for a delay. Intermittent failure on hardware is almost never a mystery bug in your logic. It is a timing assumption nobody wrote down, and finding it means measuring the machine rather than rereading the code. Why a robot behaves differently every run is the long version.
What do you give up by letting an assistant write the robot code?
You give up the mental model you would have built by writing it, and you notice the loss at the worst possible moment. When a machine misbehaves in front of a customer, debugging speed depends almost entirely on knowing what you expected to happen, and that knowledge is a by-product of having made the decisions yourself. Code you accepted is code whose assumptions you never chose. You also give up coherence: each answer is locally sensible and the collection drifts, so one part retries where another gives up, two parts define the same limit differently, and nothing tells you which behaviour was intended. And you give up a feel for what is load-bearing, so every file looks equally editable when three of them are not. In exchange you get real speed on the parts that are genuinely boilerplate, which is most of a project by volume. What actually breaks when you vibe-code a robot walks through the failure list.
When is ROS 2 the better choice?
ROS 2 is the better choice for most people building a robot with an assistant, and one of the reasons is unusual: assistants know ROS 2 better than they know anything else in robotics. Fewer invented function calls, fewer imaginary parameters, more chance that a suggestion matches something that exists. Beyond that, the ordinary reasons hold. If your robot must map a space, avoid people or plan a path, the packages are the product and generating replacements for them is not a weekend of work. If a sensor you depend on has one maintained driver, the decision was made before you started. If you want somebody else to be able to read your project, standard interfaces are a form of documentation. HORUS is not the answer in those situations, and picking a newer stack there means becoming the reviewer of every call an assistant invents, on top of building the ecosystem yourself. Why assistants recommend ROS 2 even when it is wrong covers the cases where the default is a poor fit.
Will a better model fix this?
No, and here is why: the missing information is not in the text, so no amount of reading fixes it. Models are getting better at the visible half of the problem — fewer invented functions, fewer answers that mix two incompatible versions, better recall of documentation you paste in — and that half will keep improving. The other half is different in kind. Whether your loop finishes in time, whether your joint controller faults when a command is late, whether your camera stalls under load: these are facts about a specific machine in a specific room, and a model that has never observed that machine cannot know them. What genuinely helps is giving the tool something to observe — running the tests, reading logs from real runs, hardware in the loop, a measurement it can look at. That is where the improvement will come from. Meanwhile, better models make the gap quieter rather than smaller, because the same missing assumption now arrives wrapped in more convincing prose.
Is the problem that the training data is out of date?
Partly, but not the way you think. Stale material is the most visible symptom — a deprecated call, a parameter that moved, an answer describing a release from two years ago — and it is also the easiest to fix, by pasting current documentation into the conversation and naming your exact version. Fixing it changes very little about the failures that hurt. Even perfectly current documentation does not contain the sentence your project needs, which is that this arm faults if a command is late, that this camera stalls when the motor spins up, that this loop shares a processor with a logger. No documentation anywhere has been written about your machine. There is a second, subtler data problem: assistants are pulled toward the most-written-about answer, so they suggest a heavyweight stack for a robot that needs one file, and fresh data makes that pull stronger rather than weaker. Currency is a maintenance chore. The rest is a category difference between reading and observing.
How do you decide what to let an assistant write?
Decide by consequence rather than by difficulty, because difficulty is what you feel and consequence is what hurts. Sort every file into three buckets. Generate freely: build configuration, message definitions, logging, plotting, test harnesses, simulation setup, and the glue that turns one data format into another — mistakes there announce themselves and injure nobody. Generate and interrogate: anything that reads a sensor or publishes a command, using the three questions about missing messages, slow loops and dying mid-motion. Write yourself, and have a person review it: whatever decides when the machine stops, whatever enforces a limit, and whatever runs while something has already gone wrong. That last bucket is small, often a single file, and it is the one worth your whole attention. Then test in that order too — simulator, bench with the payload removed, then the real thing. If you are also weighing what the stack underneath costs, what ROS 2 actually costs you is the companion decision.
Decide by situation rather than by principle:
- If you are a web developer starting out -> one program, no middleware, because you can read all of it in an afternoon.
- If you are a student learning -> an assistant plus a simulator, because a wrong answer should cost nothing but time.
- If your robot must perceive and navigate -> ROS 2, because assistants have read more of it than of anything else.
- If your robot is one loop on one computer -> a lighter middleware, and check every generated call against the documentation.
- If your machine can injure somebody -> write the stopping path yourself, because that is the code whose failure has no undo.
When two of those lines apply at once, weigh the candidates on the five axes of the HORUS Fit Framework — ecosystem size, setup effort, team size fit, deployment target, licence — and keep whichever loses on fewer. Those are questions about your project rather than scores about software. And if the code you keep rewriting by hand is the loop that must not slip, star HORUS on GitHub so it is in your list when you start building.