Briefly about C++
Here you'll find just a quick overview of some good basic C++ practices. More can be learned in the MRS Documentation.
Memory Management
- Do not use raw pointers! Smart pointers from
<memory>free resources automatically, thus preventing memory leaks. - Avoid using references for
std::shared_ptrsince that subverts the reference counting. If the original instance goes out of scope and the reference is being used it accesses freed memory.
Thread Safety
- When using
MultiThreadedExecutororReentrantCallbackGroup, multiple callbacks may execute in parallel. Protect shared mutable state: If a member variable is read/written by multiple concurrent callbacks, you must protect it with a mutex (e.g.,std::lock_guard). Note: Read-only data (const) or variables accessed by only one thread do not require locking.
Use C++17 scoped_lock which unlocks the mutex after leaving the scope. This way, you can't forget to unlock the mutex.
Testing
- At minimum, write thorough unit tests for core application logic, using mocks where appropriate to isolate the tested functionality. If the application logic is well-separated from the ROS 2 nodes, the nodes themselves do not require unit tests.
- Test ROS 2 nodes, including their communication behavior, as part of integration testing.
- Aim for high test coverage (90-100%).
- Avoid using arbitrary sleeps in tests, as they can make tests non-deterministic and flaky. Instead of sleeping to wait for a ROS message, use synchronization mechanisms or wait for the expected result with a proper timeout.
When doing a PR, and tests are already available, make sure to run them before pushing your code. If you are adding new functionality, make sure to add tests for it and run them before pushing.
Do not push untested code to master branches on Git (or main devel branches)! Doing so can ruin experiments and drones at best!
General points
- Avoid hardcoding values like timeouts, control gains, or buffer sizes. Field conditions often require tuning these values on the fly.
- Rule of Thumb: If a number affects behavior, make it a ROS parameter loaded from
config.yaml. - Why: Recompiling C++ on a drone in freezing weather is miserable. Editing a config file is fast.
- Rule of Thumb: If a number affects behavior, make it a ROS parameter loaded from
If you cannot figure something out, ask in Software Google Spaces for help. If you figure something out that did not work before, note somewhere how you solved it and you can share it in chat. There is a high chance that you (or someone else) will have to do the same thing again.