If your day job title is some variation of “developer” (maybe as opposed to “programmer”!), chances are that you spend more time on figuring out how to use various libraries and frameworks and how to “glue” things together, rather than creating a lot of novel code from scratch or inventing things. Doing Pi Wars can be an escape from all this, with complete freedom to experiment – which also means that reinventing the wheel is perfectly fine! But the opposite can also be true: figuring out what existing building blocks you need and how to fit them together efficiently to achieve a goal can be an interesting puzzle in itself. And creating from scratch “yet another” variant of everything that’s been done by others before can also feel wasteful after a while.
I see Pi Wars mainly not as a competition or an opportunity just to play and experiment but also to learn from others and maybe advance a bit towards something more serious. I’ve always wanted to see how “the big boys” do things in robotics – and ROS (the Robot Operating System) seems to be used everywhere from research to industry, so I came across it many times, was intrigued but never tried it for real until now.
Early on in the project, when we first started discussing Flig’s software stack, Daniel proposed to use his framework, PyROS (Python Rover Operating System) – which has been used many times for Pi Wars already with great success, so it’s definitely a proven, battle-tested tool, with probably the ideal balance of complexity/simplicity/ease of use for Pi Wars (see also a previous post: First Software). But perhaps somewhat rudely I answered something non-committal and said I’d like to use this project as an excuse to explore ROS first. So even though I broke with my Pi Wars tradition so far of starting from scratch and reinventing every time, I didn’t choose the sensible thing either!
ROS is a framework, rather than a library: but it’s more a set of tools, scaffolding, standardised conventions and loosely coupled, smaller and bigger, projects solving specific problems, rather than a big, monolithic, clunky system you have to adapt to. It’s really up to you to choose what to use and how: I could have chosen to only use some of the basic networking or visualisation tools from it while building all my control logic and bits closer to the hardware in a “from scratch” fashion. But as you learn more, it becomes more appealing to use more of the existing patterns or solutions to many common, already well-researched problems. It’s not easy though! The learning curve is quite steep, and you’ll work with a set of loosely-coupled open source libraries of varying quality, from many different organisations or random people, where almost everything is a moving target (ROS2 is in very much active development).
ROS officially supports both C++ and Python. There are implementations of the ROS client library for other languages too, but pretty much all the tools or libraries you encounter are written either in C++ or Python (with the latter used extensively for all sorts of “support” that’s less performance-critical: command line tools, scripting, visualisation, etc.)
The idea of programming your robot in C++ might sound scary or even an anachronism, depending on your background. But of course, C++ isn’t unusual at all in “serious” robotics, not just in ROS or as historical baggage.
In theory I could have chosen to do everything in Python. The main reason I wanted to also try C++ was that some libraries I’m using (and have to understand and/or modify) are already written in C++. Also, I discovered earlier that Python is slow (which is not at all original or surprising). I know it’s all relative and it is indeed fast enough for many things, but it can be really too slow for anything resembling real-time and juggling even small amounts of data – especially with limited resources like a Pi Zero (or even Zero 2). C++ has this idea of zero-cost abstractions: you get a pretty high-level language, you can build layers and layers of abstractions to solve your problems, but it all ends up as highly optimised, compiled, code with no run-time overhead (but with increased compile-time cost instead). This is in a way the opposite of Python: you get a high level language, with very quick write-run-modify-try-again turnaround (great for experimenting) but a lot of run-time overhead. So the ability to almost freely “mix” these two languages in a ROS system is a real benefit.
My Setup and Workflow
- I set up ROS2 Galactic on an Ubuntu 20.04 desktop machine (from packages, it’s trivial) including all the visualisation etc. tools I need.
- I compiled some of the core ROS packages from source on a Pi Zero 2 W, with a beta 64-bit PI OS image – and the same for some extra packages I’m using (this is far from trivial).
- The two machines are connected by USB (Ethernet Gadget), and the Pi also has internet access via Wi-Fi.
My workflow has been roughly like this so far:
- Write something quickly in Python to experiment, and run it on the desktop machine (seamlessly connects to other bits running on the Pi).
- Clean it up, do it more “properly”, maybe split into multiple nodes or separate stuff that’s only needed for visualisation or debugging.
- If performance is critical for a node, rewrite it in C++, compile and try it out on the desktop machine again.
- Finally, move it to the Pi, and recompile it there (slow).
So is it worth it for Pi Wars? I don’t know! It’s certainly possible and it runs happily even on a Pi Zero 2 – although without much “official” support so building and setting things up initially was challenging. Some of the benefits I found particularly interesting:
- Transparent networking between a Pi on the robot and a laptop/desktop machine: this means you can run anything on either machine (except the bits that directly talk to some hardware) making visualisation, debugging, logging, experimenting very easy.
- A fairly large ecosystem of libraries and tools that implement some of the more common bits you need so you can focus on your own task instead of “scaffolding” or reinventing basic things.
- Nice package and build system (colcon, cmake etc.) that makes it relatively easy to compose your system from reusable 3rd party modules and your own.
- Extensive range of tools for visualisation, debugging, telemetry.
- Standardised “base concepts”, like how to represent coordinates, velocities, etc.
- Particularly well developed tools and projects around robot arms – this probably being the most common industrial usage.
- Simulation: I haven’t even looked at it, that’s a whole new area to explore maybe later. But even without “proper” physics simulation, just using RViz to visualise the robot in 3D and running controllers with some “fake” hardware implementation is extremely useful.