Author: Stefan

Most of us who work on Crazyflie firmware live in one corner of it at a time — a driver here, a control loop there — and rarely step back to see the whole tree at once. We built a treemap of the firmware to do exactly that: one picture, every source file, sized by how much code it actually is and grouped by the directory it lives in. It makes you realize how much is going on in the firmware to make your part work.

How the map was built

The map straight out of a real build: for the cf2 target, we let Kbuild run to completion and then read its own .cmd files, the bookkeeping Kbuild already writes for every compiled object, recording exactly which source file produced it. Group those files by their top-level directory under src/ — deck, drivers, hal, init, lib, modules, platform, utils — plus vendor and scripts alongside, size each tile by lines of code, and the tree draws itself.

The treemap

Below is the top-level view of the crazyflie-firmware. Quite beautiful, right? We think so, at least. It contains years of work from the Bitcraze team and all of you out there who have directly contributed or indirectly by finding bugs and asking for new features.

Click into modules/src and it’s 91 files, 27,680 lines — the flight logic. hal/src is leaner: 21 files, 7,036 lines, sitting right above the raw drivers.

Walking the tree

Ordered the way the map itself reads, biggest tile first:

  • vendor — a second, separate pile of third-party code (FreeRTOS itself, libdw1000, test frameworks), distinct from lib.
  • lib — vendored third-party libraries the firmware builds on (the STM32 standard peripheral library, CMSIS, FatFS, Segger RTT).
  • drivers — low-level code talking directly to individual chips: sensors, radio, motors.
  • modules — the flight logic: commander, controller, state estimator, Kalman filter, CRTP handling.
  • deck — drivers for the decks (flow deck, lighthouse, LED ring, and the rest), detected and brought up at runtime.
  • hal — the hardware abstraction layer sitting above the raw drivers (sensor fusion input, power management, storage) that the rest of the firmware calls into.
  • utils — small shared helpers used across the rest of the tree: CRC, PID, filters, assertions.
  • scripts — build tooling (Kconfig, Makefiles, dependency-checking scripts). Sized like everything else, but none of it is actually compiled into the firmware.

platform and init are in there too, but at this scale they barely register as pixels — more on why that’s fitting below.

Some observations

Diff two builds instead of looking at just one, and a couple of things pop out that are easy to state but satisfying to actually go and check.

CF2 vs. CF2.1 Brushless. These are two different physical boards, but walk the diff and the only directories where a single file differs are hal/src and platform/src. Everything else in the tree — all of modules, all of drivers, all of lib — is the same source code, regardless of whether it ends up on a brushed or a brushless frame. The resulting code differs mainly due to the configuration found in e.g. platform_defaults_cf2.h.

sensors_mpy9250_lps25h.c in the bottom left corner is not compiled into the Brushless – it does not have those sensors. The same is true for Crazyflie 2.1. However, the Crazyflie 2.0 has these sensors. The sensor setting is selected at runtime, which is why you can flash your CF2.0 and CF2.1 with the same firmware.

Every controller ships in every build. modules/src has a whole cluster of controllers sitting side by side — PID, Mellinger, INDI, Brescianini, Lee — and all of them get compiled in. Which controller actually flies the drone is a parameter you can flip at runtime.

Closing thoughts

Line them all up and the codebase is huge, but the part of it that’s actually specific to one physical board is tiny. platform and init — the directories that differ per board and handle bringing the system up — barely show up next to vendor and modules. That’s easy to feel intuitively after enough time in the codebase, and much easier to actually see laid out flat like this.

It would take a long time to work your way through every corner of this tree, if you ever fully do. The tool that generates this map can be found here, and it works on one or two (compare) Kbuild targets. It already has compiled examples.

Is this an interesting way to look at a codebase you already partly know? And now that it’s laid out flat in front of you — is there anything in here that looks like it could use some tidying up? We’d like to hear about it.

We are constantly amazed about what awesome things you, our users, do with our products, and how well you do it. Time and time again you push the limits of what the Crazyflie can do, and what is possible within the field of robotics. We do what we can to provide the best possible foundation for all your visions, both in terms of improvements to existing features and also adding new, awesome features. Once in a while, though, you find something that you think can be improved, that we have not thought about, and you know how it can be solved. This is what this blog post is about – how to take an idea that you have and make it available to all of our users…

First, let’s just clarify that we are talking about software today. There is hardware and mechanics as well, but let’s save that for another time. Our software is open source. Being open source is one of the foundational pillars that we at Bitcraze build upon. We believe that this a great way for you to understand our products; everyone has the possibility to understand and troubleshoot the Bitcraze products. It also makes it easier for us to collaborate with all of you and in the end makes for better products for all of you. A positive spiral of enabling awesomeness.

Three is a swarm.

Benefits of contributing – doing things together

Now why would you contribute? You have made an improvement, and maybe you think: Well, I have what I need, there is no direct value for me to make this change available to everyone. Or maybe you think it is an issue that only you have encountered, or that the change is not big enough to merge to the main repository. Or too much work to do it… Here is the good thing: as soon as you let us know what you are working on, we can help you understand the value and the effort of that change request – we know the community, what it is doing and what it needs. We also know how to take an idea and turn it into a product. Once you have said “I have an idea”, we will take the torch that you lit and push the idea forward. You will be accredited for the contribution (e.g. your name will show in our repository), but we will take the responsibility for it: We will test it, support it and maintain it, so that you don’t have to. We will make sure it follows the evolution of the software.

Another benefit of contributing is that when you contribute, another person somewhere else, working on similar things, is also contributing. We truly believe that the more our users contribute, the more our users contribute – the positive spiral mentioned earlier. There is a community out there, and it is filled with talented and knowledgeable people; it is welcoming and it is simply great to be a part of. This seems like a fitting place to say: Thank you for being awesome, community! We are so happy to have you.

Lending each other a helping hand when needed.

Some recent examples

Over the years a number of external contributions have been made, all of which have been appreciated around the globe. Here are a few recent ones:

Solution of buffer overflow in syslink

A change doesn’t have to be big to be valuable. This is a great example of finding a bug, and fixing it. Deep in the firmware things become quite niche, and therefore difficult to understand if you don’t have that specific competence.

https://github.com/bitcraze/crazyflie-firmware/issues/1585

Mellinger controller angle limitation fix

This was contributed by a user who found that there was a limitation to what angle could be commanded when flying the Crazyflie in manual mode using the Mellinger controller.

https://github.com/bitcraze/crazyflie-firmware/pull/1596

Thrust battery compensation documentation

Thrust battery compensation is an external contribution to begin with. Here is a pull request to improve the documentation of it, in order to increase usability. Good for everyone!

https://github.com/bitcraze/crazyflie-firmware/pull/1606

Building Out Of Tree controllers on macOS

We do our best to make all our software work on as many operating systems as possible. This can be difficult though, and yet very appreciated by a lot of people when it works. Here is an example of a change that makes it easier to build Out Of Tree controller on macOS.

https://github.com/bitcraze/crazyflie-firmware/pull/1595

Account for drag in EKF for flapper

The Flapper Nimble has completely different aerodynamic properties than a Crazyflie. This work adds the possibility to account for that in the Extended Kalman Filter (EKF) of the onboard firmware.

https://github.com/bitcraze/crazyflie-firmware/pull/1584

How to become a contributor

For software contributions, the current procedure is to fork the repository for which you want to do a change, and then create a pull request to the original repository from your fork. If you feel that you are not ready to do that, or have questions, then please reach out via email or Github discussions in the corresponding repository. We are happy to discuss ideas before turning them into pull requests. During the process of merging the change into the main branch, we might ask you to provide additional information. This is because we want to make sure we fully understand what problem you are trying to solve and how. Doing so, we can take over the responsibility, and you can let go of it (if you want to). Smaller changes usually means less effort, and vice versa. However, you can contribute with as much time and effort as you see fit.

Ready for takeoff.

Worth noting also is that not all ideas or pull requests will end up in changes in the software. There could be a number of reasons for an idea being discarded, where effort compared to value is the main justification. Whatever happens we promise to have an open dialogue about your idea, and that we are transparent with the decisions that we make, so that future contributions will be even better! Just remember, no idea is too big or too small to pitch.

Pushing forward, together

Making it easier to do contributions, and increase the quality of the contributions, is something that we are dedicated to and prepared to make efforts for. So if you have any thoughts on how we can improve, or think about reasons that keep you from contributing that we can solve, we would very much like to hear it!

We are looking forward to collaborating on all amazing, crazy, improving and mind-blowing ideas out there!

Hello!

My name is Stefan, and on Wednesday the 7th of January I had the honor of joining the Bitcraze team as a software developer. I have thirteen years of experience working with robotics software in product development industry; as a developer, product owner and group manager, mainly within the areas controls, planning and sensor fusion. My vision is to bring as much of my experience into Bitcraze as possible, and have fun while doing it!

My heart has always belonged in the software development, connecting real life with control software, understanding the full chain from decisions in software to product behavior. This is especially present at Bitcraze, with small yet capable products. Understanding the entire system also lets you optimize the system as a whole, which is a complex but stimulating task. I am really looking forward to dig into this!

Going forward, I’m hoping for great collaboration, of course within the team but also with users of our products. Reach out if you have ideas, improvement suggestions or interesting projects! We are here to make your ideas fly!