HORUS/blog

Sep 5, 2026 · battery-powered-robots · robotics-middleware · edge-computing · ros-2

Best Robotics Middleware for Battery-Powered Robots

For a battery-powered robot, pick the stack that keeps work on one computer: HORUS suits mixed-language one-board builds, ROS 2 wins if you need its catalogue.

For a battery-powered robot the best middleware keeps work on one computer: HORUS for mixed-language single-board builds, ROS 2 when the catalogue matters. Every copy of a camera frame between processes is processor work, and processor work is battery. The verdict flips when your robot needs mapping, navigation or a driver only the ROS ecosystem ships, because rebuilding those costs months you do not have. This post is for someone building a robot that carries its own power and has noticed the battery draining faster than the work it does explains.

The robot works, and then it does not. You charge it overnight, it does one lap of the office, and by mid-afternoon it is back on the bench with the charger plugged in. The chassis is warm in a place you did not expect: not the motors, the little computer. The fan, if there is one, runs the whole time, including while the robot stands still waiting for something to happen. You have started planning around this. Demos get scheduled near a socket. The second camera came off the mast because everything got worse when it went on. Somebody suggested a bigger battery, so now the robot is heavier, the motors pull harder, and the gain was smaller than the arithmetic promised.

What makes this hard to fix is that nothing is obviously broken. There is no error, no crash, nothing in a log to search for. The robot quietly eats charge while doing what looks like very little, and every feature you add makes the working window shorter. The suspicion forming is that some of this is the software rather than the hardware, and there is no obvious way to tell how much.

What is the best middleware for a robot that runs on a battery?

The best middleware for a battery-powered robot is the one that copies the fewest messages and starts the fewest background processes, which in practice means a single-machine stack unless you need the ROS catalogue. Power on a robot goes to the motors first and the computer second, and software has no say at all over the first of those. What software decides is how busy the processor stays. A message layer that serialises every message on every hop charges you a copy each time a camera frame moves between programs, and a processor doing that copying never drops into a quiet state, so the clocks stay high and the fan keeps turning. That share is small on a robot whose motors are dragging a heavy base across carpet all day. It is large on an inspection rover that mostly parks and looks at things, on a stationary arm, and on anything carrying several cameras. So the honest answer is conditional on what your robot spends its day doing, and the section on telling the two apart is the one worth reading twice.

What does robotics middleware actually do on a battery robot?

Middleware is the part that carries messages between the separate programs making up your robot, and on a battery robot it also quietly decides how hard the processor works when nothing interesting is happening. A robot ends up as several programs because it has to: a camera driver, something that looks at the pictures, something that decides where to go, something that talks to the motors, and something watching all of them in case one dies. Those programs have to exchange data. Middleware is the plumbing that lets them, plus the conventions about message shapes and who is allowed to listen. On a mains-powered machine the cost of that plumbing is invisible. On a battery it shows up in three places: how many copies each message makes on its way across, how many background processes and daemons sit resident before your own code even starts, and how often the network stack and the radio are woken up by traffic that exists only so programs can find each other. What middleware actually does in a robot covers the job itself in more detail.

What are the actual options for a battery-powered robot?

There are eight options that appear in real battery robots, and most working machines use two of them together. First, no middleware at all: one program, one language, threads and a queue, which is the correct starting point far more often than people admit. Second, a single-machine middleware such as HORUS, where Rust, Python and C++ share the same shared-memory ring buffers so a message crossing between processes on that board is not serialised, and which is open source under Apache-2.0. Third, a general message library of the ZeroMQ or LCM sort, which delivers bytes and leaves message shapes, supervision and tooling to you. Fourth, an MQTT broker, which is right for status going to a phone and wrong for anything a control loop waits on. Fifth, ROS 2 tuned down: trimmed packages, a shared-memory transport, discovery limited to one interface. Sixth, ROS 2 as it installs, which brings the whole catalogue and the whole appetite. Seventh, firmware on a microcontroller for the loop that must never slip. Eighth, whatever SDK the platform vendor shipped.

How do the options compare for a robot on a battery?

The comparison that matters is not which option is lightest in isolation but which one is lightest given the parts you refuse to write yourself. A stack that saves you power and costs you six months of writing a navigation system has not saved you anything. Read the table across rather than down: find the row whose middle two columns describe your project, then check the last column honestly before deciding. Most battery robots end up combining the first or second row with the seventh, because the loop that must never slip belongs on a small board and everything else belongs on the main computer.

OptionWho it is forWhat it assumes you knowWhen to pick itWhen not to
One program, no middlewareFirst battery prototypes in a single languageThreads and a queue in that languageThe whole robot still fits in one processA second language or a crash boundary appears
HORUSOne-board robots mixing Rust, Python and C++One of those languages, and life outside the ROS catalogueSensing, thinking and actuation share a boardYou need ROS drivers or a graph spread across machines
A general message libraryBuilders happy to define their own contractsSockets, message shapes, process supervisionFew parts, stable shapes, a tight power budgetYou would be rebuilding tools that already exist
An MQTT brokerRobots reporting home over a radio linkTopics, retained messages, running a serviceThe traffic is status and human commandsA control loop is waiting on the reply
ROS 2 tuned downTeams who need the catalogue on a batteryIts build tool, discovery settings, transport optionsYou need ROS packages and want the radio quietNobody has time to tune it and retune it later
ROS 2 as it installsMobile bases that must map and navigateLinux packaging, its build tool, its message modelMains power, or a generous battery and a big baseThe board is small and the charge budget is tight
Firmware on a microcontrollerRobots whose tightest loop must never slipEmbedded tooling and serial linksThat loop can leave the main computer entirelyThe main board is idle anyway and simplicity wins
The platform vendor's SDKPeople who bought the robot rather than built itWhatever model the vendor choseThe platform is the project and the deadline is nearYou expect to change hardware later

How do you tell whether your battery problem is software or hardware?

Park the robot with the software still running and watch what the charge does, because a robot that keeps draining noticeably while nothing moves has a problem on the computer side. That one test separates two situations people constantly confuse. If the drain mostly disappears when the wheels stop, your answer is mechanical: gearing, weight, carpet, an arm holding itself up against gravity, a gripper clamped shut all day. No middleware decision touches any of that. If the drain barely changes, work through the programs one at a time. Stop the perception program and see whether the fan slows. Unplug a camera and see whether the board cools. Disable the radio for one run purely to learn how large that share is, because chatty discovery traffic keeps a radio awake and radios are expensive. There is also a third situation worth naming: a robot that browns out or resets under load has a power delivery fault, not a software problem, and no framework change will help. Why your robot slows down as you add features covers the pattern where the drain and the stutter share a cause.

Which option fits the kind of builder you are?

Solo builders and pairs should take the smallest stack that covers the things they refuse to write, because tuning a large framework is a job that quietly becomes somebody's whole week. A hobbyist with one rover and a weekend budget wants one program until it genuinely stops fitting, then a lean message layer. A student team wants whatever the marker and the next cohort can read, which is a real argument for the mainstream option regardless of charge budgets. A startup building a product wants to be honest about who will own the tuning, because a trimmed ROS 2 install is only trimmed until the next person adds a package. A research lab that swaps hardware constantly wants the catalogue, because the time saved on drivers dwarfs the charge saved on transport. A contract shop delivering to a client wants the stack the client can maintain after handover. Middleware for solo builders and two-person teams works through the small-team version of this in more depth.

What hardware are you actually putting this on?

The board you chose constrains the decision more than the framework does, and it is worth settling the hardware question before the software one. A microcontroller alone runs firmware, not middleware, and the question does not apply. A small single-board computer with a modest thermal budget genuinely cannot absorb a heavy stack alongside your own code, and this is where a lean message layer pays for itself most clearly. A module with a GPU changes the arithmetic completely: the model you are running dominates everything else, and the transport becomes a rounding error next to inference. A small x86 machine on a large base has room to spare, and you should spend it on the ecosystem rather than saving it. The other hardware question is how many computers your robot has. Shared memory works between processes on one machine, so a robot split across two boards needs a network transport for the link between them regardless of what runs inside each one. Middleware for Raspberry Pi and Jetson robots maps the common boards to sensible answers.

How much time do you have before the robot has to work?

If the deadline is weeks, take the option with the shortest path from nothing to a moving robot, even when it is not the option you would pick given a year. Deadlines change this decision more than most people allow. Three weeks to a demo means the vendor SDK or one Python program, on mains power if necessary, with the battery question deferred entirely. One term or one semester means pick a lean stack early, because the tuning work on a large framework will eat the weeks you needed for the actual project. A year to a shippable product means the ordering flips: take the time to tune the ecosystem option if you need its parts, because a year is enough to do that properly and the parts are worth having. The trap is the middle case, where a team picks the heavy option for a short deadline on the theory that they will optimise later, and the optimising never gets scheduled. When is it too late to change middleware is the question that catches those teams eighteen months on.

What skill level does each option really need?

Every option here is learnable, but they demand different things, and the difficulty is not where beginners expect. The ecosystem route demands patience with tooling: workspaces, build systems, environment setup, distribution upgrades, and reading error messages that name components you never installed. It demands very little design work from you, because the shapes and conventions already exist. The lean route inverts that. Setup is short and the concepts are few, but you have to decide your own message shapes, decide what happens when a program dies, and build or forgo the recording tool that lets you replay yesterday's failure at a desk. Neither of those is harder than the other in any general sense, but they suit different people. Someone who enjoys designing a system and hates fighting build tools should go lean. Someone who wants to assemble known parts and get a robot navigating should take the catalogue and accept its upkeep. Which middleware has the easiest first day is a fair tiebreaker when two options look equally suitable.

What do you give up by choosing a lean single-machine stack?

You give up the catalogue, and that is a much bigger loss than the charge saving for most robots. Mapping, navigation, motion planning, drivers for sensors you have not bought yet, the visualiser everyone screenshots, the recording tool that replays a failure at your desk, and the vast pile of already-answered questions that comes with the largest ecosystem. You also give up hiring familiarity: an engineer joining your project already knows the mainstream stack and does not know yours. You give up the network graph for free, since a single-machine design assumes one computer and you will be adding the link yourself if a second one appears. And you take on the small-project risk honestly: fewer people have run a lean stack on your exact odd board, so you are more likely to be the first person to hit a given problem with no forum thread waiting. Weigh all of that against a battery that lasts through the afternoon, and for many robots the catalogue wins.

When is ROS 2 the better choice?

ROS 2 is the better choice whenever the parts you need already exist inside it, and that is true far more often than power-conscious builders want to hear. A mobile base that must build a map and plan around obstacles should use ROS 2, because mapping and navigation are years of other people's work and no charge saving compensates for writing them yourself. A robot with a sensor whose only maintained driver ships as a ROS package should use ROS 2. A team that plans to hire should use ROS 2, because the stack candidates already know is worth more than any property of a leaner one. A university project with a marker, a robot spread across several computers on a network, and anything that must interoperate with a partner's existing stack all point the same way. HORUS is not the answer in those cases and does not pretend to be. It is also worth saying plainly that a large base with a generous pack removes the pressure entirely, at which point the charge argument stops being a reason to avoid the ecosystem at all.

Is a bigger battery the simpler fix?

No, and here is why: a bigger pack is heavier, and on a robot that moves, some of the extra charge goes straight into carrying the extra weight around. The gain is real but it is never the full amount printed on the cell, and it shrinks as the base gets heavier relative to its motors. A larger pack also takes longer to charge, which matters more than people expect when a demo day involves several runs. It changes the balance and the space envelope on a small chassis. It brings shipping and certification questions that a small pack avoids. And crucially it does nothing about heat: a board that runs warm still throttles, and a robot that behaves differently at the end of a run than at the start is a debugging problem no amount of capacity solves. There is an honest exception. If the pack was genuinely undersized for the motors from the beginning, buy the bigger one, because software cannot fix a mechanical shortfall.

Will changing middleware make my robot last through the job?

Partly, but not the way you think. The change does not show up as a headline saving that rescues a robot dying halfway through its task. What it does is stop you paying for work that has nothing to do with the robot, and that shows up in three specific places: when camera-rate data crosses repeatedly between programs, when several programs share one small board, and when a radio never falls quiet because the stack keeps talking on it. Outside those three, the effect is small. Motors holding a load, a model running on a GPU, heating elements and an under-specified power path all dwarf anything a message layer does. The more valuable outcome is usually not charge at all but headroom. A board that is not already busy can take the third camera without the whole robot stuttering, and a cooler board throttles less, so the robot behaves the same way late in a run as it did at the start. Consistency is worth more than minutes.

How do you decide in one sitting?

Write three lists and let them decide, because the general argument never resolves and the lists always do. First: what you refuse to write yourself, naming each item — drivers, mapping, navigation, planning, a simulator, a recording tool. Second: how many computers will run your code when the robot works, counting microcontrollers separately. Third: how many languages the robot will contain. A long and specific first list means take the ecosystem whatever the charge budget says, because rebuilding a catalogue is a project of its own. A short first list with one computer means take the lean option and spend the saved time on the robot. Several languages on one board is exactly the situation a shared-memory message layer exists for. Two computers means you want a network transport for the link, whatever runs inside each machine. And if the first list holds only things you were looking forward to writing, start with one program and add nothing until it genuinely breaks.

A short version, by situation:

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 battery robot, deployment target and setup effort usually decide it, and ecosystem size is the axis that overrides everything else once your refuse-to-write list gets long.

If your lists point at a single-machine stack in Rust, Python or C++, 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.

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