Development
This page concerns details about developing the core of Obelisk, not how to use Obelisk in a downstream project.
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
To work in Obelisk, both as a dev and as a user, we suggest working in a docker container. Previously we had also supported pixi
, but due to some dependency conflicts/installation issues, we have for now reverted to a docker only build.
First, we need to setup obelisk. The following commands will (1) make sure docker is installed (2) set flags to make sure that the docker build script grabs the correct dependencies (these will NOT be installed on your local machine, only in the docker) (3) tell Obelisk what other options you want and (4) setup obelisk aliases. Please note that the aliases file will be modified on your local machine then mounted into docker.
source setup.sh --docker-install --install-sys-deps-docker --basic --obk-aliases --unitree
Sometimes we have found that .bash_aliases is a folder. For this to work, you will need to delete that and make sure that a single file is created.
If you have just installed docker for the first time, you may need to run
newgrp docker
Now, there are a few options. We suggest working with obelisk from within a dev container through an IDE. VSCode has good support for this and the Jetbrains IDEs have this feature in beta. If you take this (suggested) route, then you will want to open the the dev container in the IDE using the provided .devcontainer
.
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
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.
Building and Running the ROS Stack
All of the following commands should be run from within the devcontainer
.
We now need to activate obelisk. Assuming you installed the aliases, you can now run
obk
The first time this is run it also builds obelisk. This activation command sources all the relevant scripts (like ROS) so that the stack can be used without hassle.
You can also build everything with the terminal command:
obk-build
this will also be sure to build everything in the correct order.
To launch a ROS stack we can use the following commands.
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 looks 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
.