catkin_make (or catkin build, or colcon build), and… wait. Even if you just change a number, you might be waiting upwards of 8 seconds. While small in comparison to the time it takes to actually write the code, this can absolutely be distracting when you want to test the change right away. With these changes, I can recompile a ROS node that uses Eigen in less than 1.5 seconds. While I’m using ROS Noetic on Ubuntu 20.04, this is applicable to any codebase using C++.
A simple trend about compilers: the newer it is, the faster it is. So when Ubuntu 20.04 comes with GCC 9 from 2019, it’s going to be slower than Clang 12, an alternative C++ compiler, released in 2021. While there are newer versions of both GCC and Clang, Clang 12 is the newest compiler available in Ubuntu 20.04 with just a simple sudo apt install. As such, I recommend switching—simply sudo apt install clang-12. To use it, anytime you’d write gcc use clang-12 instead, and g++ can be replaced with clang++-12. There’s no changes needed to your code, as GCC and Clang both implement the C++ standard. To start using it in ROS, you’ll need to tell CMake to use Clang with a few environment variables. You’ll want to set CC to clang-12, CXX to clang++-12, and LD to clang++-12. To do this temporarily, run in a terminal:
export CC=clang-12
export CXX=clang++-12
export LD=clang++-12
(note: this will only have effect in that specific terminal, and will go away when you close it). Then, and this is an important step, delete previously compiled files by deleting the build folder in your workspace—there can be some issues when mixing compilers, and CMake won’t switch to the new compiler until you rebuild anyways. Now, just build! It should hopefully be faster. Make sure you set it permanently so it doesn’t switch back in the future.
If you’re not on Ubuntu 20.04, you might want to experiment with different compilers! If you’re using GCC, try Clang—it might just happen to be faster.
In C and C++, writing #include will look up that file, and then copy and paste its contents into the original file. As such, files that appear small have to look through an incredibly high amount of code. You can find how much code is included like this by running your compiler with with the -E flag, like g++ -E source.cpp or g++ -E source.cpp. As an example, one ROS node with only 250 lines of code expanded into over 200,000 lines with #includes processed!
Instead of re-reading, lexing, and parsing all these lines of headers that never change, you can enable precompiled headers in your compiler. By writing its internal data structures to disk, these steps happen only once! To use precompiled headers, you need to specify which specific headers to preprocess. CMake has an incredibly easy way to do this—the build tool already used by ROS! In your CMakeLists.txt, look for a line that looks like this:
add_executable(some_target_name src/some_source_file.cpp)
# --- OR ---
add_library(some_target_name src/some_source_file.cpp)
# --- OR ---
cs_add_executable(some_target_name src/some_source_file.cpp)
Anywhere after it, just add these lines to precompile headers, just making sure to update some_target_name with the name within add_executable!
target_precompile_headers(some_target_name
PRIVATE
<ros/ros.h>
<eigen3/Eigen/Core>
)
Note that this may use significant disk space. Expect 300MB with GCC 9 (the default on Ubuntu 20.04), and around 60MB with Clang 12.
Save some time by sharing precompiled headers! Instead of writing
add_executable(node_1 src/node_1.cpp)
add_executable(node_2 src/node_2.cpp)
# BAD WAY
target_precompile_headers(node_1
PRIVATE
<ros/ros.h>
<eigen3/Eigen/Core>
)
target_precompile_headers(node_2
PRIVATE
<ros/ros.h>
<eigen3/Eigen/Core>
)
you can reuse the precompiled header:
add_executable(node_1 src/node_1.cpp)
add_executable(node_2 src/node_2.cpp)
# GOOD WAY
target_precompile_headers(node_1
PRIVATE
<ros/ros.h>
<eigen3/Eigen/Core>
)
target_precompile_headers(node_2 REUSE_FROM node_1)
This will reduce the work needed to precompile headers (since it only needs to happen once) in addition to disk space. Unfortunately, reusing headers may not work if you want to include more headers in only one target—some compilers support this, but CMake doesn’t. This will also not work if one target is an executable and one is a library.
Thankfully, the Clang compiler has a built-in tool to show you what headers take the most time to compile! After making sure you’ve switched to Clang, add this to the CMakeLists.txt for the package you’d like to inspect:
add_compile_options(-ftime-trace)
If you’re using the compiler directly, you can use clang++ -ftime-trace instead
When you recompile, you’ll notice a bunch of json files in your build folder—find them with find build -name "*.cpp.json" when you’re currently in your ROS workspace directory. Head on over to ui.perfetto.dev and Open Trace File on the left panel, selecting that JSON file. You’ll be presented with a graph showing all the time spent compiling this file:

Take a look at those turquise blocks labeled “Source”—that’s all time spent reading source files! We can see that a whole 3 seconds is spent on header files. Click on them to see what file is taking a while:

That’s 1.4 seconds on ros/ros.h! There’s no need for that. So, after adding that, Eigen, and a few other headers used in this file as a precompiled header, we can check out the graph again:

Look how much less time is spent on Sources! Note that the graph always takes up the full screen width, so the sections that now appear bigger just take up the same amount of time as before.
]]>On the navigation side, we recently made changes to our costmap so our path planner can map a more ideal path. We first altered how we were weighing the area around obstacles so that the planner would not map a path too close to a buoy. At last year’s competition, our vessel would get too close to buoys at times. To prevent this, we increased the cost of the area around obstacles in the costmap to decrease the likelihood of the planner creating a path that travels near obstacles. Second, we increased the cost of the area behind the vessel so that we don’t end up planning a path where the vessel has to make large turns. Drastically changing directions in our path is unideal because our vessel is not able to make sharp turns efficiently.
Our subteam has now transitioned to working on making alterations to our controls code. We have made modifications to the intended velocity of the vessel in order to account for the vessel’s dynamics. Over the past two weeks, we have written code to calculate the change of angle of the vessel’s path and if this angle is within some threshold of 0, the velocity of the vessel will be greater. Otherwise, the vessel will go slower to better navigate turns in the path. We also implemented code so the vessel will slow down as it reaches its goal to decrease the likelihood of overshooting.
Finally, I got the opportunity to learn from Ben Shattinger, our AI lead, and write code to interface with the boat’s microcontroller. Whenever we receive a ROS message from the thrusters, we send a byte packet to the microcontroller to set PWM outputs. In the process of writing this code, I learned how to use packed structs in C++ in order to write and send byte packets according to an API provided by the Electrical team.
Looking forward, our subteam will be focusing more on controls code optimizations. We want to continue considering the change of angle of the path when determining the vessel’s velocity. We also want to implement code to reverse into the dock for the docking challenge, instead of entering the dock head-on. And finally, in the coming weeks, we expect to test our code on the vessel in the water, instead of the simulated environment. Overall, our subteam has made great progress this semester and we are on-track to achieve all of our goals before competition in February.
]]>Boeing has been a Gold sponsor for UM::Autonomy since 2017, providing us with not only the financial support to be able to go to competitions every year but also with yearly design reviews and meet & greets with the team. We’re incredibly grateful for their continued support, and the opportunity to be able to share our work with them. We look forward to working with them further as we prepare to set sail at the 2024 RoboBoat Competition in February!
]]>This was a great chance to network and connect with industry leaders, partake in resume coaching and diverse team-building workshops, and learn more about the work done at Ford. The team especially enjoyed their product reviews of the F150 Lightning and Mustang and the vehicle walk arounds.
Ford is a Platinum sponsor of the team and has historically provided the team with lots of technical support in designing, fabricating, and testing carbon fiber hull forms for our boats every year. In the past, they have provided foam molds for our carbon fiber vacuum infusion process (as shown below).
Thank you to Ford for inviting us to this event, and we look forward to another great competition season made possible through their support!
]]>I was first introduced to the team as a junior at Hagerty High School in Oviedo, Florida, where my school competed against UMich in RoboNation’s annual RoboBoat Competition, formerly in South Daytona, Florida. It was here that my love for robotics and applied engineering was brought to a burgeoning frontier, ripe with learning opportunities and growth - a place to try, test, and fail while encountering real-world challenges on a level incomparable to the student teams and competitions that I’d been exposed to in the past. In this environment of dynamic discovery and engineering is where I encountered this team, a group of students so compassionate and willing to help others, regardless of the atmosphere of competition.
I’m glad to say that six years later, I’m leading this same team as the President of UM::Autonomy - though I still have so much more to learn, and so many perilous challenges ahead that I feel anxious to face. What I love is that through it all, the environment of the team and the atmosphere of friendliness and welcoming has never changed, and I want it to remain that way - especially since that is the heart of this team, and speaks volumes about engineering overall.
I’ve come to learn that often, the ability to work with people, manage towering projects, and communicate ideas effectively is far more overlooked and important than technical prowess alone. Despite being an incredibly technical field, I have realized that engineering is mainly about the people around you, how they communicate, and how they learn and grow together more than anything. While I have made that realization, I have far from mastered that skill of managing projects and communicating with people effectively, and I’m excited to grow that ability even further.
So as our team looks forward to the RoboBoat Competition in Sarasota, FL in 2024, and I look forward to my last year in school, I’m excited to take on another year of hard but rewarding challenges for my team and I - especially knowing that I have a strong, unwavering, and talented group around me.
]]>