🌿BASIL🌿 is a meta-repository that ties together:
- A fork of the MIT Underactuated Robotics
underactuatedrepo, and - A forked Spot playground with our own controllers and trajectory optimization code,
into a single workspace for studying model-based control and trajectory optimization for Boston Dynamics’ Spot using Drake.
In this project we:
- Stabilize Spot in place using joint-level PD and LQR around a nominal standing pose.
- Generate an underactuated multi-step trot using centroidal trajectory optimization with passive knees.
- Build and validate a joint-space linear model as a candidate prediction model for a future MPC controller.
All of our custom code lives in the external/spot submodule, but it depends directly on modified files in the external/underactuated fork. You must therefore initialize both submodules (recursively) before running anything.
Spot_Underactuated_Walk.mp4
At a high level:
basil/
├── external/
│ ├── spot/ # Fork with all 🌿BASIL🌿 Spot controllers, sims, Docker, etc.
│ └── underactuated/ # Fork of MIT Underactuated repo, with local modifications
├── requirements.txt # Python dependencies for non-Docker usage
└── ...
Think of 🌿basil🌿 as the umbrella workspace:
- The top level manages submodules, Python environment, and documentation.
external/spotis where you actually run sims (via Docker or local Python).external/underactuatedprovides the Drake plus utilities infrastructure thatspotbuilds on.
This repo uses nested submodules (Spot and Underactuated, plus whatever they contain), so you must clone recursively:
git clone --recurse-submodules git@github.com:wgtayar/basil.git basil
cd basilIf you prefer a different folder name, replace the final basil argument with whatever you like.
If you previously ran a plain git clone and now external/spot or external/underactuated look empty or incomplete:
cd basil # or whatever your clone directory is called
git submodule update --init --recursiveThis will:
- Initialize all top-level submodules (
external/spot,external/underactuated), and - Recursively initialize all of their nested submodules as well.
(We still highly recommend using Docker 🙂)
If you want to run things outside Docker, we recommend:
cd basil
# Optional but recommended: create a virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install Python dependencies (Drake plus scientific stack)
pip install --upgrade pip
pip install -r requirements.txt
# Make the MIT Underactuated repo importable as `underactuated`
# (we skip its own dependency installation because Drake is already handled above)
pip install -e external/underactuated --no-depsThe requirements.txt here is a minimal environment inspired by the official underactuated requirements, including drake, numpy, scipy, matplotlib, and a few supporting libraries.
Installing external/underactuated in editable mode exposes the package as underactuated, which is required by the Spot scripts.
All the interesting 🌿BASIL🌿 experiments live in the Spot submodule:
cd basil/external/spotFrom here:
-
If you want a Docker-based workflow (recommended!!):
cd basil/external/spot docker compose build spot-sim docker compose run --rm --service-ports spot-simThis builds and runs a container that has Drake, the
underactuatedrepo, and the Spot playground wired up. Seeexternal/spot/README.mdfor details on the available demos. -
If you want to run locally (no Docker, not recommended!!), make sure you have installed
basil/requirements.txtandpip install -e external/underactuated --no-deps, then follow any non-Docker instructions in thespotREADME.
Examples that live in external/spot include:
- PD standing and disturbance rejection
- Joint-space LQR standing
- Full-state LQR experiments
- MPC Control of Spot
- Underactuated multi-step trot playback
To pull new changes and keep both submodules in sync:
cd basil
git pull
git submodule update --init --recursiveIf you want Git to always recurse into submodules when pulling:
git config --global submodule.recurse trueAfter that, a normal:
git pullwill also update external/spot, external/underactuated, and their nested submodules.
To verify that everything is initialized and on the expected commits:
cd basil
git submodule status- A leading space means clean and at the recorded commit.
+means the submodule has diverged (ahead or behind).-means it is not yet initialized.
-
Always use
--recurse-submoduleswhen cloning orgit submodule update --init --recursiveafter pulling. -
Treat
🌿basil🌿as the control tower andexternal/spotas the flight deck where you actually run experiments. -
If something behaves strangely after a
git pull, it is often fixed by:git submodule update --init --recursive
-
For reproducible non-Docker runs, use a fresh virtual environment and
pip install -r requirements.txtfollowed bypip install -e external/underactuated --no-deps.
Enjoy exploring model-based quadruped control with BASIL 🌿

