Sep 5, 2026 · lightweight-frameworks · small-robots · robotics-middleware · ros-2
Best Lightweight Robotics Frameworks for Small Robots
For a small robot the best lightweight framework is often no framework at first, then a single-machine stack, and ROS 2 only when you need its catalogue.
For a small robot the best lightweight framework is usually no framework at first, then a single-machine stack such as HORUS, and ROS 2 only when its catalogue is the point. Small robots rarely need discovery, network transports or a package ecosystem, and every layer carrying those costs setup time you pay repeatedly. The verdict flips the instant your robot needs mapping, navigation or a planner other people already wrote. This post is for someone building a one-computer robot who wants the smallest stack that will still be there in a year.
Your robot is the size of a shoebox and the software feels the size of an office building. You wanted a camera to look at a thing and a motor to move towards it. Instead you have a workspace, a build tool, a launch file, an environment that must be sourced in every terminal, and message definitions in a folder you do not remember creating. When something goes wrong the error mentions a component you never installed. The board runs warm, the build takes long enough that you tab away and lose the thread, and after a reboot half of it does not come back until you retype something you found in your shell history.
The suspicion creeping in is that most of this machinery is for a robot much larger than yours. That suspicion is usually correct, and it is also where people make an expensive mistake in the other direction: they throw out the framework, wire everything together with files and sockets, and six months later they have built their own middleware by accident, with no tools and no documentation. The real question is where the floor is. How little can a small robot get away with, and what exactly do you lose on the way down?
What is the best lightweight framework for a small robot?
The best one is the smallest thing that covers the parts you were never going to write yourself. For a genuinely small robot — one computer, a few programs, hardware you can name from memory — that is often a single script to begin with, then a single-machine message layer once the script splits into pieces, and a full framework only when the robot needs mapping, navigation or an established motion planner. The mistake is not picking the wrong one. The mistake is picking by robot size instead of by the list of things you refuse to build. A shoebox rover that must autonomously map a building needs the big catalogue no matter how small it is. A desk-sized arm doing one repeatable task needs almost none of it, even if the arm cost more than a car. So write the refuse-to-build list before comparing anything. If it is long and specific, take the ecosystem and accept the weight. If it is short and vague, the weight is buying you nothing and the light option wins.
What does lightweight actually mean for robot software?
Lightweight means the stack assumes fewer things about your machine, your network and your project layout, not that it does less work per message. Weight shows up in four places, and they are worth separating because a project can be light in some and heavy in others. Installation weight: how many system packages, which exact operating system release, whether anything must be built from source. Runtime weight: how much memory sits resident and how many background processes run before your own code starts. Conceptual weight: how many ideas you must hold — workspaces, packages, launch files, quality settings, discovery — before two programs can exchange a message. And upkeep weight: how often the environment drifts, and how long it takes to restore a machine that has stopped building. For a small robot, conceptual and upkeep weight hurt most, because they are paid every single week by a person who has other things to do. Runtime weight matters mainly on a small board where memory is the wall you actually hit.
What are the actual lightweight options?
There are six real options, and only a few sensible combinations. First, no framework: one program, one language, threads and a queue, which is the correct first move more often than anyone admits. Second, a single-machine middleware such as HORUS, where Rust, Python and C++ share the same shared-memory ring buffers so a message crossing languages is not serialised between processes on that computer, and which is open source under Apache-2.0. Third, a general message library of the ZeroMQ or LCM sort, which gives you delivery and leaves every message shape, supervision rule and debugging tool to you. Fourth, a broker such as MQTT, which is right for status going to a phone or dashboard and wrong for anything the robot waits on. Fifth, ROS 2 trimmed to a few packages you actually use, which is heavier than the others but keeps a door open to the catalogue. Sixth, a microcontroller-side arrangement, where the tight loop lives in firmware and the computer only supervises. Most working small robots use two of these together.
How do the lightweight options compare?
The comparison worth making is what each option assumes about your robot, because that assumption is what turns into work later.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| One script, no framework | First prototypes in a single language | Threads and a queue in that language | The whole robot fits in one program | A second language or a crash boundary appears |
| HORUS | One-computer robots mixing Rust, Python and C++ | One of those languages, and life outside the ROS catalogue | Sensing, control and actuation share a board | You need ROS drivers or a graph across machines |
| A general message library | Builders happy defining their own contracts | Sockets, message shapes, process supervision | The parts are few and the shapes are stable | You would rebuild tools that already exist |
| A broker for telemetry | Robots reporting to a phone or dashboard | Topics, retained messages, running a service | The traffic is status and human commands | A control loop waits on the reply |
| ROS 2 trimmed to a few packages | Small robots needing one or two catalogue pieces | Which packages you truly use, and its build tool | You need a specific driver or planner | You end up rebuilding the rest anyway |
| ROS 2, full distribution | Small robots that must map and navigate | Linux packaging, its build tool, its message model | The robot is a mobile base with common sensors | Nobody has time for weekly upkeep |
| Firmware loop on a microcontroller | Robots where timing must never slip | Embedded build tooling and serial links | The tight loop can live off the computer | The board can stay simple and the computer smart |
| A kit vendor's own SDK | People who bought the robot rather than built it | Whatever model the vendor chose | The kit is the project | You expect to change hardware later |
A common and sensible pairing is a firmware loop underneath, a small message layer on the computer, and a broker carrying status to a phone.
Which fits a hobbyist building a robot at home?
Start with one script and add a message layer only when the script stops holding together. At home the scarce resource is evenings, and the framework you install in week one is a framework you maintain for as long as the project lives, usually alone, usually after a day of other work. A single Python program driving a motor from a camera reading is a complete robot, and thousands of good projects never need more. The signal to move on is specific rather than aesthetic: you add a component in another language because the sensor vendor only ships C++, or one slow part starts delaying a fast one, or a crash in the vision code takes down the code that was supposed to stop the wheels. At that point install the smallest message layer that lets separate programs talk on the one computer, keep every concept you can hold in your head, and write down the setup as a short script the same day. That last habit is worth more than any framework choice, because the way home projects die is a machine that no longer builds and a memory that no longer remembers why.
Which is right for a Raspberry Pi, an ESP32 or a Jetson?
Pick by whether the board runs an operating system, because that single fact splits the field. A microcontroller such as an ESP32 has no operating system and no processes, so middleware in the usual sense does not apply: you write a firmware loop, and you talk to the rest of the robot over serial or a network link. A Raspberry Pi or a Jetson runs Linux, so any of the software options apply, and the deciding factors become memory headroom and which operating system image the board shipped with. A vendor's customised image is where heavy stacks become painful, because the prebuilt packages assume a plain release and building from source on a small board is slow enough to eat days. The arrangement that suits most small robots is layered: firmware holds the loop that must never slip, the Linux board holds perception and decisions, and a link joins them. Whether microcontrollers need middleware too is worth reading before you push more of the robot onto the small board.
What if the robot has to work in a month?
Then choose by what you refuse to write, freeze the choice today, and spend the month on the robot. A month is enough to build a small robot and not enough to change foundations halfway through, and the projects that miss the date are almost always the ones that switched stacks in week three. If the month's goal includes mapping a space or planning an arm path around obstacles, install the ecosystem that already has those, accept the setup cost in week one, and never look at the alternatives again. If the goal is a repeatable motion, a pick, a follow, or a sensor-driven behaviour you were going to write anyway, take the lightest option and put the saved days into the parts that actually decide whether a demo works: does the robot stop safely when something unexpected happens, can it be restarted in front of people, and can a watcher tell what it is trying to do. Those three decide demos. No framework choice ever has. Set the deadline for the decision itself at one evening.
What if I have only ever written Arduino sketches?
Then you already understand the model that matters, and the gap is smaller than it looks. An Arduino sketch is a loop that reads inputs, decides and writes outputs, and every robot control loop on every framework is that same shape wrapped in more machinery. The genuinely new ideas are three: separate programs running at the same time, messages passed between them instead of shared variables, and what happens when one of those programs is slow or gone. A lightweight stack teaches those three and nothing else, which is exactly the right amount for a first step off the microcontroller. A full framework teaches them alongside workspaces, build tools, launch files and packaging, and beginners routinely lose weeks to the packaging rather than the robotics. Practical path: keep the sketch doing the loop that must never slip, put a Linux board next to it for the camera and the decisions, and use the simplest message layer between the programs on that board. What to use instead of ROS 2 on a small robot covers that shape in more detail.
What changes as a small robot starts asking for more?
Four things break the one-script arrangement, and they arrive in a predictable order. First a second language shows up, usually a vendor's C++ driver or a control loop you moved out of Python because it kept missing its moment, and now a queue inside a single script cannot reach it. Second, timing coupling appears: an image handler takes longer than expected and the wheels stutter because both live in the same program. Third, a crash somewhere unimportant takes down the part that was supposed to stop the motors, and you realise the robot has no failure boundary anywhere. Fourth, you need to see what happened during the run that went wrong, which means recording every message and replaying it at your desk, and nobody wants to write that by hand. Each of those is a middleware feature. The teams that push through all four without changing anything end up with a private middleware assembled from sockets, files and a supervisor script nobody understands, which is more expensive than choosing one deliberately and comes with no tools at all.
What do I give up by going lightweight?
You give up the catalogue, and the catalogue is the real product of the large ecosystems. No driver waiting for the specific lidar you bought. No navigation stack. No arm planner with years of use behind it. No simulator that already speaks your message types. No visualiser that discovers your topics on its own. Usually no recording tool, which is the loss people underestimate most, because replaying a bad run at your desk is how hard bugs get solved. You also give up strangers who have already had your exact problem, and you give up easy handover: a project on the standard stack can be picked up by a classmate or a contractor, while a project on your own arrangement of parts is one only you can maintain. What you keep is a stack you can hold in your head after three months away, a machine you can rebuild in an evening, and a robot whose weird behaviour is your code rather than a configuration setting three layers down. Whether that trade is good depends entirely on whether your hard problems will be framework problems or robot problems.
When is ROS 2 the better choice?
ROS 2 is the better choice for any small robot whose value comes from software other people already wrote. A shoebox rover that must map a room and drive across it autonomously: ROS 2, without hesitation, because that stack exists and rebuilding it is a multi-year project regardless of how small the robot is. A small arm using an established motion planner. Any robot you want to test in a simulator that already agrees with your message types. Any university project, because the supervisor, the marker and the students who inherit it all know the standard stack. Any robot that will span two computers, since HORUS is single-machine middleware and shared memory stops at the edge of the board. And any project where the hard problems are perception or navigation, because those are exactly the problems the catalogue already solved. In every one of those, lightweight is the wrong instinct: the weight is the packages, and the packages are why the robot works at all. Choosing small there costs a year and buys a property nobody needed.
Is lightweight just a nicer word for unfinished?
No, and here is why: weight describes where a project draws its boundary, and a narrow boundary is a design decision rather than a missing chapter. A middleware that only moves messages between programs on one machine has chosen not to ship a build system, a package catalogue, a simulator and a visualiser, and inside its own boundary that job can be done attentively precisely because it is the only job. The genuine risk with small projects is a different one and worth naming plainly: fewer people have run them on odd hardware, so you are more likely to be the first person to hit a given problem, and there is no forum thread waiting. Judge a small project by what it says it is not. Take the disclaimers at face value, check them against your parts list, and see whether the missing pieces are things you need. A project that tells you plainly it is not a simulator, not an inference engine and not a replacement for the ROS catalogue is being useful, not modest.
Will a lightweight stack hit a wall the moment the robot gets serious?
Partly, but not the way you think. The wall exists, and it is not where people expect: it is almost never about how many messages the robot can move, and almost always about a component you do not have. A serious robot needs a map, or a planner, or a driver for an unusual sensor, or a way to replay yesterday's failure, and a small stack hands you none of those. That is a real wall. What does not usually happen is the wall people fear — outgrowing a small message layer because the robot got more demanding. Adding cameras, arms and behaviours to a one-computer robot mostly adds programs and messages between them, which is the thing a message layer already does. So the honest test is not how far a lightweight stack scales. The test is your parts list and your feature list. Search every sensor and actuator by name, note which ones only ship a ROS driver, and note which features on your list are large pieces of software rather than code you would write. That list decides it.
How do I choose in one sitting?
Write three short lists and let them decide, because the general argument never resolves and the lists always do. First: what will I refuse to write myself — drivers, mapping, navigation, planning, a simulator, a recording tool. Second: how many computers will run my code when the robot works, today and in a year, counting microcontrollers separately. Third: how many languages will the robot contain. A long first list means take the ecosystem whatever the others say, because rebuilding a catalogue is a project of its own. A short first list plus one computer means take the lightest option and put the saved time into the robot. Several languages on one computer is exactly where a shared-memory message layer earns its place. Two computers means you want a networked message layer, which is a narrower field. And if the first list contains only things you were going to enjoy writing anyway, start with one script and add nothing until it breaks. Which middleware has the easiest first day is a useful tiebreaker when two options look equally suitable.
A short version, by situation:
- If your robot is one script in one language and still works -> no framework yet, because adding one before the boundaries exist is a cost with no return.
- If a vendor driver in C++ must talk to your Python code on one board -> a single-machine message layer, because a bridge you maintain forever is the alternative.
- If the robot must map a space or plan around obstacles -> ROS 2, because those are years of other people's work and small robots need them just as much.
- If the timing that must never slip lives on a microcontroller -> firmware for that loop plus a simple link, because no middleware fixes a loop on the wrong processor.
- If a classmate, marker or contractor will inherit the project -> ROS 2, because the stack they already know is worth more than any property of a smaller one.
When you want to compare candidates rather than symptoms, the HORUS Fit Framework lines them up on five things that are not numbers: ecosystem size, setup effort, team size fit, deployment target, and licence. On a small robot, deployment target and setup effort usually decide it, and ecosystem size is the axis that overrides everything when your refuse-to-write list is long.
If a single-machine stack in Rust, Python or C++ is what your lists point to, HORUS is open source under Apache-2.0 and the repository is linked below. Star it so it is in your list when you start building.