Development
Overview
We use the following tools for development:
Bash shell (some of the scripts will modify your
.bashrc
)Docker and Docker Compose for isolating system states and for development containers
pixi
for package-level dependency management across platformsruff
andpyright
for linting, code-style enforcement, and type checking of Python codeclang-tidy
andclang-format
for C++ codepre-commit
for registering code checks as commit hookspytest
for python code tests
We ensure that all code checks pass in a CI workflow before allowing PRs to merge into main
.
Getting Started
First, there are local dependencies required to use our development pipeline. Run the following script from the repo root:
source dev_setup.sh --dev-sys-deps
newgrp docker
This will install docker
, nvidia-container-toolkit
, pixi
, uv
, and nvm
(required for pyright
). It also sets the OBELISK_ROOT
environment variable to the path of the repository root on your local filesystem and installs some useful aliases to the .bashrc
. If you do not want to install docker
or the development dependencies, instead just run
source dev_setup.sh --skip-docker
Optionally, to build the development Docker container, run from the repo root:
docker compose -f docker/docker-compose.yml run --build obelisk
To enter the container without rebuilding or to join from a different terminal window, run
docker compose -f docker/docker-compose.yml run obelisk
If you are running on a machine with no Nvidia GPUs, you can instead run
docker compose -f docker/docker-compose-no-gpu.yml run --build obelisk
If your IDE supports it, you can instead use the provided .devcontainer
to launch this container (VScode provides good support, and at the time of writing, devcontainers
are a beta feature in JetBrains IDEs). Either way, your repository root will be mounted into the container at the exact same file location, your username, user ID, and group ID will be shared with the container, and you can freely run sudo
without supplying a password for any command.
Once ready for development, you should start the pixi
shell, which is like activating a conda
environment (but pixi
environments are project/directory-specific, not shell-wide). To do this, run in the repo root:
# if your machine has a gpu
pixi shell -e dev
# if your machine has no gpu
pixi shell -e dev-no-gpu
The environment dev
contains the most critical development dependencies. However, you can view the available environment sets in the pixi.toml
to start a different environment if you would like. For example, if you are only updating the docs, you can do this by setting the environment flag to docs
.
While in the pixi
shell and/or Docker container, all changes made in the repository or to the ~/.bashrc
file persist in your local file system. You can also use git
with no issue to push changes.
Building and Running the ROS Stack
All of the following commands should be run from within the devcontainer
and within the dev
pixi virtual environment (which can be entered by running pixi shell -e dev
).
You can build eveerything with the terminal command:
obk-build
this will also be sure to build everything in the correct order.
In a seperate terminal, we can run a ROS stack with:
obk-launch config_file_path=<config file> device_name=<device>
Specifically, for the dummy examples this may look like:
obk-launch config_file_path=dummy_cpp.yaml device_name=onboard
All the documentation for the Obelisk terminal aliases can be found here.
Building and Running C++ Code
We can easily run C++ code using pixi
. From within the dev
enviroment, the available commands are:
cpp-ctest
will run all tests registered withCTest
. This is the command used in the CI to verify unit tests, so every test should be registered with CTest - see below.cpp-test-node
will run all the tests for the main Obelisk library and will do so using the Catch2 framework.cmake
which will re-build the cmake.cpp-build
which will compile the code.
Note that all the commands will automatically run the commands they depend on. For this reason, to re-build the cmake, compile the code, and run the tests, all we need to do is run cpp-ctest
.
We can enter the dev
enviroment with pixi shell -e dev
or we can run those commands from the normal shell by pre-pending with pixi run -e dev
. For example, to run the ctests, pixi run -e dev cpp-ctest
.
In the future we will add more commands to run other parts of the code.
C++ Code Structure
The C++ libraries in obelisk/cpp
are built with CMake.
All obelisk
C++ libraries are placed in obelisk/
. Each library should have its own folder. Within that folder there should be an include
folder, a CMakeLists.txt
, and the source files (i.e., not the header files - those go in include
).
Testing
Unit tests are managed with Catch2
. Ultimately we plan to run the tests with CTest
, and therefore all unit tests need to be registered with CTest
, see here. The tests are all placed within tests/tests_cpp
.