As I’ve started diving deeper into my first real robotics project, I’ve taken a look at what the Open Source options are for robot software. It seemed like a good idea to code with a popular framework to save time and follow the best practices set out by the community. However when I tried to use the preeminent Robot Operating System 2, I found a lot of architectural decisions that I personally thought weren’t best practice, and that ultimately led me to build my own system on top of a NATS and protobuf message bus. I can’t claim to be an expert on ROS 2, because this write up is about how I tried ROS 2 and bounced off of it. This article became a bit of a hit-piece on ROS 2, but I hope it might also help some beginners, students, or other folks questioning if this is really how things should be.

Here’s a prototype of my robot: an AUV (robotic submarine) that I’m building for fun
How robot software works
For anyone who hasn’t tried to program a complex robot before, here’s how it works: Each chunk of software with a separate responsibility (think a sensor, a PID loop, a motor controller) is written as its own little modular program that runs independently, usually as a process on the robot’s Linux computer. All those nodes communicate with each other through a message bus that they can all listen to and publish on. This modular architecture is good for a lot of reasons, but a main one is that it keeps software handling one part of the robot from blocking another while it thinks. Instead of one main file called “robot.cpp”, each piece can run at their own pace and communicate with the rest of the machine, and the robot is a sum of its parts. ROS 2 is a framework to help build that sort of robot.
So what’s the problem?
- Ubuntu
ROS 2 is hard in on Ubuntu. I mean like..hard. Not Debian, not RaspiOS, not Linux in general, just Ubuntu. ROS 2 packages are Ubuntu packages. If you install a ROS 2 package, you do it with Ubuntu’s package manager, Apt. As far as I can tell, there was not much consideration to make ROS 2 portable. Even using RaspiOS, the Ubuntu fork designed for Raspberry Pis, is out. That means that on the hardware which 95% of hobbyists will be using, the most supported operating system is going to be really tough to get going. Using Ubuntu on a Raspberry Pi does technically work, but it just isn’t as good. There are more bugs and more weirdness.
The prescribed solution for using an unsupported OS with ROS 2 is just to containerize your ROS deployment. And that does work, but managing an ARM64 docker container on a system that I already have to SSH into and making sure the container has full access to and plays nice with all of the system’s hardware like SPI buses, GPIO pins, serial, etc… It’s doable, but it’s not that fun. It’s a bandaid on top of tech debt.
Maybe building and using ROS 2 on a different operating system is doable, I’m not sure. I see the wiki claiming OSX and Windows support. Based on how everything else went for me, my guess would be that it’s hard.
- Versioning
To make matters worse (oh, so much worse) each version of ROS 2 only works with a set version of Ubuntu, and there are often breaking changes between each version of ROS 2. If you want to use a specific version of Ubuntu, you end up on a specific version of ROS 2.

raspberry pi connected to an IMU over i2c
Let me give you an example of how painful this can get. I fried my Pi4 robot brain last month when I accidentally got it too hot with my soldering iron. Alright, no worries, I’ll grab a Pi5 from Amazon. Faster processor, might as well. When it shows up, I realize it will only run the newest versions of Ubuntu because of some modern hardware on the board. Because I had to use a newer Ubuntu, I had to use the newest bleeding-edge version of ROS 2. And because I got forced into that, the packages that I was leveraging all broke. Using those packages was a major part of the reason for being in the ecosystem to begin with. It’s very typical in ROS 2 libraries to only support the latest LTS version with your package, so no fault to the devs, but that left me out to dry. Just for choosing to use the most mainstream computer.
This is painful. This is what tech debt looks like. Things that probably shouldn’t be tightly coupled in the first place end up depending on each other, and then those problems cascade into hours of bugs, incompabilities, and workarounds. The shared libraries of prebuilt tools and nodes which other people have already solved should be the greatest strength of a popular framework like ROS, however they are greatly diminished by these problems with version lock-in.
Oh, and maybe this one is just a “me problem”, but I absolutely cannot stand the version naming scheme. ROS 2 took a page from Ubuntu’s naming scheme, meaning that each version has a name instead of just a number. You can’t just infer that version 20 comes after version 19. You have to remember that Iron Irwini comes after Humble Hawksbill, and that Jazzy Jalisco is the newest version which doesn’t have a lot of support yet. Also, remember that Humble only runs on Ubuntu Jammy. Keep that in your head.I just don’t like it. It confuses me.
- Language lock-in
ROS 2 supports C++ and Python. That’s it. For a lot of people, I think that’s fine. Neither one would be my go-to choice, though. There’s not a lot to say here, except that I think it’s unnecessary to be this locked in. If you choose a message system that already has broad support, writing more client libraries isn’t hard because most of the work is done for you. The advantage of using a message bus and having a modular robot should be that we have more languages to choose from, in my opinion. Even if the support is a little patchy or there aren’t as many convenience functions in the client library, it should be possible without having to write C++ bindings/FFI.
- Code Sharing
Because the package manager for ROS 2 is Ubuntu’s APT, publishing packages is clunky. And because of that, in most of the smaller packages that people have published, the prescribed way to use them is to clone them to your project. Copy, paste. In addition to the version compatibility issues I mentioned above, this is certainly not an ideal situation.
Compared to something like Arduino’s package manager, ROS 2 is far behind. Arduino took the time to set up a dedicated package manager that met the needs of their community. It is easy to use as a package consumer, easy to search, and easy to publish to. I’m sure that was more work up front and it needs to be hosted and so on, but frontloading that pays off.
- Complex and Convoluted DevEx
TL;DR on this part: It’s a lot to learn and the CLI commands are weird.
Aside from needing to learn all of the above to be an effective ROS 2 developer, the stack itself is actually fairly hard to learn. A normal developer experience is like this: You’ve just installed ros2, but command not found: ros2. It needs to be source d. It doesn’t add itself to the path like every other tool, so whenever we start our machine, we have to source it before we can call it. Fine, we do that, and then we cd into our project and want to start running commands. But no, ros2 doesn’t simply respect the working directory it’s in to figure out what you want, you have to source the workspace too. So in the root of your project you have bash files that you call source on and NOW ros2 is loaded and your project code is loaded.
If you want to install something, you don’t call ros2, you call rosdep, which is the package manager that calls apt under the hood. Alright. And before we run our package, even our python package, we have to build it. And to do that, we don’t call ros2 build,we call colcon build. “Colcon” is ROS 2’s build system. In ROS 1, it was called catkin, and now it’s called Colcon. Also worth noting is that these tools have some pretty clunky commands and flags, and a lot of them are a mouthful to type out.
Anyway, I’m not sure how ROS 2 can be the go-to framework for education uses when it is so complicated to learn. For a senior dev, this is just confusing, but I think I would be pulling my hair out if I was still in school. As a senior dev, I know to add the source /whatever/ros2-setup.bash to my zshrc or bashrc profile so I don’t have to call it every boot, but a new engineer might not know that. I really worry that a new engineer might not be able to make sense of this framework and might bounce off programming in general.
Enough bashing, it’s easy to be negative but hard to be constructive. How would I build this if I had the chance:
- Framework, not operating system. The identity crisis of being a framework that thinks it’s an operating system (it’s not) is a major source of pain for ROS 2.
- If possible, it would be even better to just be a design pattern with as little runtime and CLI as is practical. I’d write as slim as possible of a client library on top of popular Open Source swarm management and communication tools.
- Dedicated package manager, or failing that a better one than APT.
Do that and you’ll end up with something that is portable, simple, and extensible. I set out to do something similar using NATS, a lightweight Open Source pub-sub system, and so far it is going incredibly well. Messages are strongly typed using protobuf and because both protobuf and NATS support every major language, it’s portable not just between operating systems but languages too. Here is my tiny TS client library if you want to see how it works. Basically, it’s 150 lines and it gives me a strongly typed message bus. I’m using the language I want, the operating system I want, and instead of using ROS 2 libraries for boilerplate code, an LLM takes care of the boring parts. I haven’t yet created an orchestrator to start and manage nodes, however I was thinking maybe Kubernetes. Not sure yet. I imagine the community sharing nodes as super-portable docker containers with the convention that their message proto type definitions and config files mount to a given volume on the host. That’s probably a ways off.
I have yet to get my own robot working yet, let alone productionalize a framework out of it, but it’s starting to look more possible. Thanks for reading and watch your salt intake.
Responses (8)
lookoutking
Hi, I feel your pain and completely agree with you. I tried to dabble in ROS2 a few years ago and it was a nightmare. I've built a few differential drive (tracked) robots and currently using NodeRed as a simple controller. I too am contemplating on…more2
"Things that probably shouldn’t be tightly coupled in the first place end up depending on each other, and then those problems cascade into hours of bugs, incompatibilities, and workarounds."Well said. I definitely hope this aspect improves.If you're…more1
VERY insightful article, thank you!!2