Sep 5, 2026 · cpp · python · control-loops · getting-started
What C++ Gives You in Robotics That Python Can't
C++ gives a robot even timing, direct use of vendor drivers and room on small hardware. Python gives you speed of change, and most robots end up wanting both.
C++ gives a robot even timing and direct access to vendor drivers, which Python cannot, while Python stays better for the parts that change daily. The split is per part rather than per robot, since ROS 2 and HORUS both carry messages between Python and C++ code. That reverses only when nothing on your machine is ever late and every device you own has a Python library. The rest of this post is for someone whose robot mostly works, who keeps reading that real robotics is C++, and cannot tell whether that applies to them.
Your robot moves. That is the confusing part. It drives, it stops when it should, the arm goes where you sent it, and all of it is Python you wrote yourself over a few weekends. Then somebody in a thread says that Python is not used for anything serious, and you have no way to check whether they are describing your robot or a different one.
Meanwhile there are two small things you keep not fixing. The arm is smooth and then twitches, always at a moment you cannot reproduce, and nothing in your code explains it. And when the camera is doing something heavy, the wheels briefly hold their last command a beat too long, so the machine drifts wide on a turn it used to make cleanly.
You added a print statement to catch it, and the behaviour changed, which felt like the floor moving. Now you are stuck between two stories. Either you have an ordinary bug and a rewrite would be a waste of a month, or the language itself is the ceiling and every hour you spend polishing Python is an hour spent on the wrong thing.
Should you move part of your robot from Python to C++?
Move a part to C++ only when that part is late rather than wrong, and move that part alone. Lateness has a signature you can learn to recognise. Wrong code fails the same way every time and gets fixed by reading it. Late code produces correct results at unhelpful moments, changes behaviour when you add a print statement, and misbehaves more when the machine is busy doing something unrelated. That second pattern is what C++ addresses, because it removes the layer between your instructions and the processor that decides, on its own schedule, to pause and tidy up memory. What C++ does not address is a planner that picks bad paths, a calibration that drifted, or a driver returning stale numbers, and those are the actual cause of most robot misbehaviour. So the honest test is not how demanding your robot looks. It is whether the same code, given the same inputs, sometimes acts late. If it does, one subsystem moves and the rest of your Python stays exactly where it is. If it does not, a rewrite buys you a slower development cycle and nothing else.
What is the actual difference between a compiled language and an interpreted one?
A compiled language turns your instructions into machine code before the robot runs, and an interpreted language works them out while the robot is running. That gap is the whole subject. When Python executes a line, something has to decide what the line means: which types are involved, which function to call, whether memory is needed. That decision work happens during your control cycle, alongside the work you actually wanted. C++ does that thinking once, at build time, and what runs on the robot is a fixed sequence of operations. The second difference matters just as much and gets discussed less. Python decides on its own when to reclaim memory you are no longer using, and that housekeeping happens at a moment it chooses, not one you chose. In a program that produces a report, nobody notices. In a loop correcting a motor, a pause you did not schedule is a correction arriving after the moment it was for, and why a control loop's timing matters is the concept that turns this from trivia into a diagnosis.
What are the real language options for a robot, and who is each one for?
There are more options than the two in the title, and one of them is refusing to choose yet. You can stay in Python entirely, which carries further than the internet claims. You can move one subsystem to C++ and leave everything else alone, which is what most working robots actually look like. You can write everything in C++ because your team or your target board already does. You can choose Rust for new code you expect to run unattended. And you can let the foundation carry the split for you: ROS 2 runs Python and C++ nodes side by side with shared message definitions, so perception can be written in one language and control in the other, while HORUS is an open-source real-time middleware for Rust, Python and C++ under Apache-2.0 where all three languages share the same shared-memory ring buffers, so programs on one machine exchange messages without serialising them. Read the table as descriptions of situations rather than as a ranking of languages.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| Python everywhere | Beginners, researchers and anyone still deciding what the robot does | Installing packages and reading a stack trace | Nothing on the machine is arriving late | A loop must behave the same on every cycle |
| C++ for one part, Python elsewhere | Builders whose robot works except for one twitchy subsystem | Where your loop hesitates and why it hesitates there | One part is late while the rest is fine | You cannot yet say which part is late |
| C++ everywhere | Teams shipping a product that must run unattended | Compiling, linking, and where memory comes from | The whole machine is timing-sensitive | You are still changing the robot's purpose weekly |
| Rust | Programmers starting fresh code meant to run for years | Types, ownership, and patience with a strict compiler | You want the compiler to catch memory mistakes | Your project lives on borrowed C++ libraries |
| Embedded C on a microcontroller | Builders whose robot is a board, motors and a battery | Pins, timers and how to flash a chip | The robot has no operating system at all | You want cameras, maps or recorded logs |
| ROS 2 with Python and C++ nodes | Builders who need borrowed drivers, mapping or planning | Linux, workspaces, launch files, package layout | Existing packages are most of your robot | You must show movement before learning tooling |
| HORUS | Mixed-language builders whose programs share one machine | Your message shapes and how your loops are scheduled | Python, C++ and Rust parts must pass data on one box | Your robot's value lives in ROS 2 packages |
What should you write in if you are one person building your first robot?
Python, and do not treat that as a compromise. A first robot is limited by how many ideas you can try per evening, and Python removes nearly everything standing between an idea and a moving wheel: no build step to configure, an error message that names the line, and a manufacturer's example for whatever sensor you bought. The parts of robotics that are genuinely hard for a beginner are not language problems anyway. Working out why the arm overshoots, why the map drifts, why the gripper closes on nothing — none of that gets easier in C++, and all of it gets harder if each experiment costs a compile. Solo builders who start in C++ usually stall in the build system, which teaches them nothing about robots and takes the Saturday anyway. The exception is narrow and worth naming. If the specific machine in front of you is a microcontroller, the board has already chosen, and C is the door in. Otherwise stay in Python until something on your robot is late, then move that one thing, and whether Python is quick enough for robot control is the honest version of that argument.
What should you write in on a Raspberry Pi, a Jetson, or a microcontroller?
The board changes the answer, and it changes it more than your preferences do. A microcontroller has no operating system and very little memory, so C or C++ is not a choice but a fact, and even MicroPython, which is a legitimate way in, runs out of room the moment a motor must be corrected continuously against changing load. A Raspberry Pi runs full Linux and hosts Python happily, but memory is finite and heat is real, so the practical failure mode is not that Python is unsuitable — it is that you fill the board with programs and then everything hesitates together. A Jetson exists for cameras and models, and there the language question splits cleanly: the model work is already compiled code underneath a Python wrapper, so Python is fine at that layer, while the part steering the wheels while the model thinks is the part that wants a compiled language. Notice the pattern across all three boards. Language follows the layer, not the machine, and the layer that keeps time is the one that keeps asking for C++.
What should you write in if you need a demo in three weeks?
Python, without a second thought, and do not start a rewrite three weeks before anyone is watching. Deadlines are won by robots that do one thing convincingly, not by well-built robots that are still compiling. A rewrite in a compiled language is a month of work that produces exactly the behaviour you already had, minus the bugs you have not reintroduced yet, and nobody in the room can see the difference between a demo written in one language and a demo written in another. What they can see is a machine that hesitates at the wrong moment. So if your demo has a visible stutter, do not translate the whole robot — find the one loop responsible and give that loop what it needs, which is often not a language change at all but fewer things competing for the same processor at the same moment. Move the camera work into its own process. Stop doing heavy work inside the loop that steers. Both of those are afternoon jobs in Python, and both fix more demos than a rewrite ever has.
What should you write in if you have only ever written Python?
Keep writing Python, and learn C++ against a specific piece of your own robot rather than against a course. The failure mode for Python programmers learning C++ is trying to learn the language in the abstract, meeting pointers, templates and a build system in one week, and concluding they are not the sort of person who does this. The version that works is narrow: take one subsystem you already understand — the loop that steers the wheels, the driver you wrote for a sensor — and port that alone, with the Python version still there to compare against. You will meet three genuinely new ideas, not thirty: where memory comes from, what a build system does, and why the compiler wants to know types up front. Everything else you already know, because you understand what the code is supposed to do. Give yourself two weekends and expect the first to end badly. The prize is not the port itself, it is that afterwards you can read the driver code your hardware shipped with, which is written in C++ whether you like it or not.
Where does Python actually lose control of timing on a robot?
Python loses control in four specific places, and knowing which one you have hit decides the fix. First, the interpreter does work between your operations, deciding what each line means as it goes, so a loop with many small steps spends real time on bookkeeping. Second, memory is reclaimed when Python decides rather than when you decide, so a pause can land in the middle of a correction. Third, the global interpreter lock means adding threads does not spread work across processor cores the way it would elsewhere, which surprises people whose instinct is to thread their way out. Fourth, moving large data such as camera frames between Python processes usually means copying and repacking them, so the cost grows with the picture rather than with your logic. The first three are why control loops leave Python. The fourth is why perception pipelines get slow in a way that looks like the model's fault when it is really the plumbing, and how a robot ends up dropping sensor data usually starts there.
What does it look like when Python is the wrong tool for a part of the robot?
It looks like a robot that mostly works and occasionally misbehaves in a way your code cannot explain. The arm moves smoothly and then twitches, never at the same point in the motion. The wheels hold a line and then briefly surge when something unrelated is busy. You add a print statement and the symptom moves, which is the clearest signal of all, because logic bugs do not care whether you are watching. A second, unrelated symptom is availability rather than timing: the sensor you want ships as a C library with no Python binding, and writing that binding has quietly become your project instead of your robot. A third is size, when the machine you are deploying to has less memory than your laptop and the interpreter plus its libraries no longer fit comfortably. None of these mean abandoning Python. Each means one specific piece moves to a compiled language while everything else stays. A robot with a C++ driver, a C++ steering loop and a Python brain is not a compromise, it is what most working machines look like once they are honest.
What do you give up by writing that part in C++?
You give up the speed at which you can change your mind, and on a robot that is a bigger loss than it sounds. Every experiment now costs a compile, and a robot in its first year is one long series of experiments. You also give up a class of safety that Python was quietly providing: in C++ you can read memory that no longer belongs to you, and the machine will not stop you, so a robot can behave strangely for reasons that live nowhere in your logic. Those bugs take days rather than hours. You take on a build system, which is a genuine second skill, and you take on the job of keeping two languages agreeing about what a message looks like, because the moment your Python brain and your C++ driver disagree about units, the robot will do something confident and wrong. And you give up a bit of borrowability, since the tutorial you find at midnight is more likely to be Python. None of this argues against C++ for the parts that need it. It argues against using C++ for the parts that do not.
When is ROS 2 the better choice?
ROS 2 is the better choice whenever the work other people have already done is worth more to you than anything about languages. If you need a mobile base that maps a building and navigates it, ROS 2 hands you that, and no language decision compensates for writing navigation yourself. If you need an arm to plan around an obstacle, the motion planning ecosystem lives there. If your sensors ship with ROS 2 drivers, if your teammates already speak it, or if you want to hire people who are useful in their first fortnight, ROS 2 wins on grounds that have nothing to do with C++ or Python — and it supports both languages as first-class citizens with shared message definitions, so the mixed-language robot this post describes is exactly what ROS 2 was built to host. HORUS is not the answer in those cases, and no middleware substitutes for an ecosystem you actually need. Pick differently only when your problem is how data moves between programs on one machine rather than which packages you can borrow.
Is Python simply too slow for real robots?
No, and here is why. Real robots ship with Python in them constantly, because most of a robot is not a control loop. Deciding where to go next, working out which object to pick, talking to a server, running an experiment, watching a battery, reacting to a person — all of that happens at human speed, and human speed is comfortably within reach of an interpreted language. The heavy arithmetic in perception already runs as compiled code underneath a Python wrapper, so a Python program calling a vision model is not doing the maths in Python at all. What Python cannot promise is that a specific piece of work will finish before a specific moment, every single time, regardless of what else the machine is doing. That promise is what a control loop needs and almost nothing else does. So the accurate sentence is not that Python is too slow for robots; it is that Python cannot guarantee when it will be done, and one layer of your robot cares about that intensely while the rest does not care at all.
Will rewriting in C++ fix a robot that stutters?
Partly, but not the way you think. A great many stutters have nothing to do with the language and survive the rewrite intact, which is a miserable discovery to make a month in. The usual culprits are structural: too many things sharing one processor, heavy work happening inside the loop that should be steering, a sensor being polled when it should be waited on, or data being copied between programs on every cycle because the plumbing serialises it. Rewrite that arrangement in C++ and you get the same stutter, executed more briskly. The fix that generally works is separation first, language second — move the slow work out of the timing-sensitive loop, give the loop its own process, make sure the freshest reading is the one it acts on — and only then, if the loop still hesitates on its own, does the language become the remaining variable. Doing it in that order also tells you something a rewrite never would: exactly which part was late, and why.
How do you decide which parts belong in C++?
Ask which parts of your robot are judged on when they finish rather than on what they conclude, and put those in C++. Everything reacting at human speed stays in Python: behaviour, task sequencing, logging, analysis, the code you rewrite every fortnight while working out what the machine is for. Everything that must produce a result on a schedule, regardless of what else is running, is a candidate to move: the loop steering wheels or joints, state estimation, the code touching a device directly. Then apply one filter that overrides both. Anything that only exists as a C or C++ library is C++ whether you wanted it or not, because writing a binding is a project of its own. If you cannot name which of your loops is late, you are not ready to move anything, and the correct next step is measuring rather than porting. Two other pieces are worth reading before you commit: what a robot software stack looks like layer by layer and whether to use one language or several.
Decide by situation rather than by argument:
- If you are one person with your first robot -> Python everywhere, because nothing on it is late yet.
- If one loop hesitates while the rest is fine -> C++ for that loop alone, because the problem is timing, not language.
- If your robot is a chip with no operating system -> C or C++, because the board has already chosen for you.
- If your sensor ships only as a C library -> C++ for that driver, because the binding would otherwise become your project.
- If two people will maintain this codebase for years -> C++ or Rust for the parts touching hardware, because those change least and cost most when wrong.
When the plumbing under both languages becomes the question, 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, with no scores and no numbers involved. If your robot is heading towards a Python brain and a compiled loop on the same machine, star HORUS on GitHub so it is in your list when you start building.