Sep 5, 2026 · ros2 · getting-started · robotics-middleware · choosing-tools
Do You Actually Need ROS 2 to Build a Robot?
No. A first robot rarely needs ROS 2, but the moment you want other people's drivers, mapping and navigation, ROS 2 becomes the right answer.
No, you do not need ROS 2 to build a robot — plain code, a smaller middleware, and ROS 2 itself are all legitimate starting points. What you need depends on how many separate programs must agree while the robot moves, and one loop on one board needs neither ROS 2 nor HORUS. The answer flips the moment you want other people's drivers, mapping and navigation. The rest of this post is for someone starting a first or second robot who wants to choose a foundation once and not tear it out later.
You have a board, a motor, a sensor and a weekend. Every tutorial you open assumes ROS 2, so the first evening goes into a workspace, a build tool, a line added to your shell profile, and a launch file for a program you have not written yet. Nothing has moved. The second evening, something builds but the node cannot see the other node, and the fix you find on a forum is a setting you have never heard of about how programs find each other on the network. Meanwhile the actual robot — the thing where the wheel turns when the sensor sees the wall — is a page of code you could have written on the first evening.
So you start wondering whether the whole apparatus is for you at all. It clearly works for the labs and the companies. But you are one person, or three, and it is not obvious what the ceremony buys. The uncomfortable part is that you cannot tell whether you are dodging complexity you never needed or complexity that is coming for you anyway, and picking wrong costs either weeks of setup or a rewrite you did not plan.
Do you actually need ROS 2 to build a robot?
No — ROS 2 becomes necessary when you want to stop writing the parts other people have already written. A robot that reads a sensor, decides something, and drives a motor lives happily in one program in one file with nothing underneath it. ROS 2 does not exist because robot code is hard to write; it exists because robots are assembled from many programs written by different people, and something must carry messages between them without every author agreeing on a format first. If your robot is one program, that problem has not arrived. If your robot is a camera pipeline written by a stranger, a navigation stack written by another, and your own control code wedged between them, that problem is the entire job. Most people asking this sit in between: one program today, three by the end of the month. So the useful question is whether you will want borrowed code later, and how much of your robot it will be.
What does robotics middleware actually do?
Middleware is the postal service between the separate programs that make up a robot. One program owns the camera, another owns the wheels, a third decides where to go, and each runs at its own pace and can crash without the others noticing. Middleware lets them address each other by topic name rather than by process, so the planner asks for wheel odometry rather than knowing which program produces it. It also settles the awkward questions: what happens when the producer outruns the consumer, whether a stale message should be delivered or dropped, how a program that starts late finds the ones already running, and what a subscriber sees when a publisher dies halfway through a message. Those decisions are where the real difficulty lives, and they are why middleware looks like overhead right up until the day it saves you. Skip it and you write that machinery yourself: a socket, a queue, and a growing pile of special cases about data that arrived too late to be useful.
What are the real options for a first robot?
There are four honest options and only one of them is ROS 2. You can keep everything in a single program and skip middleware entirely. You can adopt ROS 2 and inherit its ecosystem along with its build system. You can use a smaller middleware such as HORUS, an open-source real-time robotics middleware for Rust, Python and C++ in which all three languages share the same shared-memory ring buffers, so messages between processes on one machine are not serialised. Or you can stay on a microcontroller and let firmware be the whole robot. Beneath those sit the fallbacks people reach for by accident: a general message broker borrowed from web work, or the SDK that shipped with the arm or base you bought. Every one of them is right for somebody. Read the table as a description of a person and a situation, not as a ranking of software.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| Single program, no middleware | One builder, one board, one loop | Basic Python or C++, plus your sensor's driver | The robot is one sensor, one decision, one actuator | Two parts need separate rhythms |
| ROS 2 | Anyone wanting existing drivers, mapping, navigation | Linux, workspaces, launch files, package layout | The ecosystem matters more than owning the plumbing | You must demo next week and have never used it |
| HORUS | Mixed-language builders on a single machine | Your message types and how your loops are scheduled | Python, C++ and Rust parts share data on one box | Borrowed packages are the value and would need porting |
| Microcontroller firmware | Builders whose robot is a fixed behaviour | Embedded C or MicroPython, and your board's pins | The behaviour fits on the board | You want vision, mapping or recorded logs |
| General message broker | Teams reusing web or IoT infrastructure | Brokers, topics, keeping a service alive | The robot is mostly telemetry and remote commands | A control loop depends on message ordering |
| Vendor SDK | Buyers of a complete arm or mobile base | The vendor's API and its one supported language | You want the machine to do its documented job | You must mix in hardware the vendor never planned for |
What should you pick if you are one person building in the evenings?
Start with the smallest thing that moves, because your scarce resource is attention, not compute. A solo builder who spends three weekends on a workspace, a build tool and a discovery problem has spent three weekends not learning what their robot does when the floor is uneven. Write the loop first: read the sensor, print the number, drive the motor, watch it overshoot, fix it. That teaches you the shape of your problem, and the shape of your problem is the only thing that can tell you which foundation you need. The counter-case is worth naming. If your robot is a wheeled base that must map a room and drive to a goal, the mapping code is the project, and writing it yourself is a multi-year detour. That is a ROS 2 project on day one. The difference between those two builders is not skill; it is whether the interesting part of the robot already exists as code.
What should you run on a Raspberry Pi or a small onboard computer?
A small board changes the answer less than people expect, and mostly by way of memory and boot time. Every program brings its own runtime, libraries and start-up cost, so a design with many processes feels heavier on a small board than on a laptop — not because messages cost more, but because the board spends its first stretch after power-on getting everything alive. That matters more than beginners expect: a robot that takes a long time to become responsive after switching on is a robot you will test less often, and testing less often is how projects die. Keep the number of separate programs to the number you need, put the parts that must hold a steady rhythm together, and be honest about whether a program exists because the architecture requires it or because a tutorial had one. On a small board, a diagram with many boxes is a promise you pay for at every boot.
What if you need something moving in three weeks?
Pick the thing you already know, and if you know nothing, pick the shortest path from an empty folder to a spinning wheel. A deadline is not the moment to absorb a package layout, a build tool and a message-definition language at the same time as debugging your own control logic. Three weeks is enough to make a robot do one impressive thing badly, which is usually the point of a deadline, and not enough to learn an ecosystem and then use it. If the demo needs navigation, or a sensor whose only driver is a ROS 2 package, the decision is made for you: take ROS 2 and accept that the first week is setup. If the demo is your own behaviour on your own hardware, skip what you can and write the loop. The mistake in both directions is choosing a foundation for the robot you imagine in a year instead of the one that must work this month.
What if you have never written multi-process code before?
If splitting work across programs is new to you, the hardest part of your project will not be the robot; it will be the first time two programs disagree about what time it is. Concurrency is a genuinely different skill from writing a control loop, and it arrives whether or not you chose it: the moment the camera program runs slower than the motor program, you have to decide what the motor does with a picture that describes where the robot used to be. Middleware makes that decision easier to express but does not make it for you. If this is new, the kind thing to do for yourself is to start with one program and two clear rhythms inside it, feel where the timing hurts, then split. You will split along the right line because you will have felt where the line is. Splitting first, from a diagram, tends to produce boundaries that look tidy and then need to be moved once the robot is real and something is late.
What does it look like when you have outgrown your first choice?
The signal is that your bugs stop being about the robot and start being about the plumbing. The arm hesitates and it turns out the vision code held the loop for a moment. You add a sleep somewhere and it helps, which should worry you. Programs must be started in a particular order or nothing connects, so there is now a document describing the order. A message arrives with a timestamp older than the one before it and the filter produces an impossible position. Someone adds logging and the logging changes the behaviour. Individually each looks small; together they are a category, and the category is that your parts have no agreed way to hand data to each other under time pressure. That is when middleware, whichever one you pick, stops being ceremony and starts keeping the robot honest. Reaching that point is not failure. Patching around it for another six months is.
What do most people try first, and why does it stop working?
Most people start with one script and a couple of threads, which works well and works for longer than the internet suggests. It stops working at a predictable point: when one part must keep a steady rhythm while another waits on something outside its control — a camera frame, a disk write, a network call. Once a waiting task lives in the same program as a rhythmic one, the rhythmic one inherits every hesitation of the other, and the robot expresses that as a stutter you can see. The usual next move is to bolt on a queue and a background thread, which buys real time and quietly introduces the question nobody wanted: what should the control side do when the queue holds data that is no longer true? A middleware exists to give that question a standard answer instead of a bespoke one per project. You can keep answering it yourself, and many good robots do, right up until a second person joins.
What do you give up by not using ROS 2?
You give up other people's work, which is the largest single asset in robotics. That means mapping and navigation you did not write, drivers for sensors you have not bought yet, a visualiser that shows what the robot believes about the world, recording and replay so you can debug last Tuesday's failure at your desk, and a decade of forum answers written by people who hit your problem first. You also give up onboarding: a contributor who knows ROS 2 can read a ROS 2 robot on their first day and cannot read your private architecture at all. Those are heavy losses, and they are the real argument for the ecosystem. What you get back is a smaller thing to hold in your head, a start-up sequence you can explain in a sentence, and freedom from a build system you did not choose. Whether that trade is good depends entirely on how much of your robot you intend to write yourself.
When is ROS 2 the better choice?
ROS 2 is the better choice whenever the value of your robot lives in code you did not write. A wheeled base that must map a building and navigate to a goal is a ROS 2 project, because the mapping and navigation packages represent work you cannot reproduce on a hobby schedule. An arm doing collision-aware motion planning is a ROS 2 project for the same reason. A research group where every student already knows the tooling is a ROS 2 project, because shared vocabulary beats a better transport every time. If your sensor's only usable driver is a ROS 2 package, that settles it. If your system spans several computers — a robot and a workstation, or a fleet — ROS 2 was designed for that and is well travelled there. HORUS is not the answer for those projects, and picking it there trades a real ecosystem for plumbing you would have to rebuild. Say no to a middleware, this one included, when the packages are the point.
Is ROS 2 too heavy for a small robot?
No, and here is why: the heaviness people describe is conceptual, not computational. ROS 2 runs perfectly well on the small computers people put on hobby robots, and the resource question is rarely what makes someone give up. What makes them give up is the number of ideas that must be understood before the wheel turns — workspaces, packages, build steps, launch descriptions, parameters, message definitions, and the way programs find each other on the network. That vocabulary stands between you and your first moving robot, and calling it heavy is an honest reaction misdirected at the runtime. The distinction changes the fix. If the problem were resource use, the answer would be a smaller machine. Because the problem is vocabulary, the answer is either to learn it deliberately, which is worth it if you will stay, or to start smaller and adopt it later when you know what each concept protects you from. The six things that trip newcomers up are learnable in a weekend if you know they are coming.
Will skipping ROS 2 mean rewriting the whole robot later?
Partly, but not the way you think. The part you rewrite is the plumbing — how programs are started, how messages are addressed, how a subscriber handles data that is too old to trust. That is real work, usually a couple of weeks for a small robot, and it is annoying rather than catastrophic. What you do not rewrite is the part that took months: the control logic, the calibration, the state machine that knows when the gripper has actually got the object, the values you discovered by breaking things. That knowledge lives in your functions, not your transport. So keeping a future port cheap is boring discipline. Keep control logic in plain functions that take data and return commands rather than functions that also fetch and publish. Keep your message shapes defined in one place. Keep the code that touches hardware apart from the code that decides. Do those three things and switching foundations later is a mechanical job. Skip them and any migration becomes a rewrite, regardless of which foundation you left.
How do you decide what to start on?
Name the piece of software you would be genuinely sad to have to write yourself, and let that answer decide. If that piece is a navigation stack, a mapping system, or a driver for a sensor you own, the ecosystem holding it wins and everything else is a detail. If nothing on that list exists — if the interesting part is behaviour only you understand — you are free, and the right move is the smallest foundation that lets you see the robot move today. Ask a second question to break ties: how many computers will this robot be, and how many languages will it speak? One machine and one language means you can defer the decision a long time. One machine and three languages is where a shared transport stops being a nicety. Several machines on a network is where the mature ecosystem earns its complexity. Neither question is about speed. A first robot is almost never limited by messaging; it is limited by how quickly its builder can try the next idea, which is why writing a node without ceremony matters more early than any property of the transport.
Decide by situation rather than preference:
- If you are one person with one board and one loop -> plain code, because middleware would be the biggest part of the project.
- If your robot's value is mapping, navigation or a borrowed driver -> ROS 2, because the packages are the point.
- If Python, C++ and Rust parts must share data on one machine -> a shared-memory middleware, because the language boundary is eating your time.
- If you have a deadline and already know one option -> the one you know, because the learning curve is the schedule.
- If your robot is a fixed behaviour with no camera and no map -> firmware, because nothing above it earns its place.
When the choice is close, weigh it on the five axes of the HORUS Fit Framework — ecosystem size, setup effort, team size fit, deployment target, and licence — and take the option that loses on the fewest. No score, no numbers: five honest questions about your situation rather than about the software. If your project keeps landing on one machine, more than one language, and behaviour only you understand, star HORUS on GitHub so it is in your list when you start building, and read how sensor fusion gets wired up first.