ECE346 ROS 2 Foxy development environment running in Docker.
- Ubuntu 20.04+ (any version)
- Git
Docker packages software into containers — lightweight, isolated environments that include everything needed to run an application (OS, libraries, dependencies). We use Docker so that everyone runs the exact same ROS 2 Foxy environment regardless of what Ubuntu version is on your laptop. Think of it as a virtual machine, but faster and lighter.
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
newgrp dockerThe last two commands add your user to the docker group so you can run Docker without sudo. If you still get "permission denied" errors when running docker commands, log out and back in (or reboot).
What is sudo? sudo runs a command with administrator (root) privileges. Installing software requires root access, which is why the install commands above use sudo. After setup, you should be able to run docker commands without sudo thanks to the usermod step. If a docker command fails with "permission denied", try prefixing it with sudo.
Verify: docker --version
This step allows Docker to access your NVIDIA GPU for GPU-accelerated compute. If you have AMD/Intel, or if this step fails, skip it and move on — the simulation and rviz2 will still work fine without it.
First, check if you have NVIDIA drivers installed:
nvidia-smiIf this command fails, you need to install NVIDIA drivers first:
sudo apt install nvidia-driver-535
sudo rebootOnce nvidia-smi shows your GPU, install the toolkit:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockerIf any of the above fails, don't worry — just move on to step 3. This step is not required for the labs.
If you've never used git before, we recommend this introductory tutorial.
-
In the upper-right corner of any page on GitHub, select '+', then click New repository.
-
Type
ECE346_GroupXXas the name for your repository, add a README file, and an optional description. -
Choose Private as your repository visibility.
-
Click Create repository.
-
In your terminal, clone the course repository:
git clone https://github.com/SafeRoboticsLab/ECE346.git
-
From inside the cloned directory, rename the original
ECE346GitHub repo toupstream(default isorigin), which you'll use to fetch future lab assignments and updates.cd ECE346 git remote rename origin upstream git remote set-url --push upstream DISABLE -
Add your new private repository as a new remote named
origin. To locate your private repo's URL, navigate to its main page on GitHub, select the green<> Codeicon, select SSH, and copy this URL to your clipboard.git remote add origin <URL of your private repo>
-
Configure your Git identity. Note: run these commands inside your ECE346 directory.
git config --global user.email "your_email@example.com" git config --global user.name "Your Name"
-
Set up Git authentication (choose one):
Option A — Personal Access Token (easiest):
- Go to GitHub > Settings > Developer Settings > Personal Access Tokens > Tokens (classic)
- Click Generate new token (classic), give it a name, select the
reposcope, and click Generate token - Copy the token — you'll use it as your password when pushing
- To save it so you only enter it once:
git config --global credential.helper store
Option B — SSH Keys
- Follow GitHub's SSH key guide to generate a key and add it to your GitHub account
- In step 7, use the SSH URL instead:
git@github.com:YOUR_USERNAME/ECE346_GroupXX.git
-
Push the
SP2026branch to your private repository, which has now become a private fork ofECE346.git push -u origin SP2026
If prompted for a password, paste your access token from step 9.
-
Add all course AIs as collaborators to your private fork: navigate to your private repository's Settings > Collaborators and Teams under Access > Add People > CalvinTAVN
cd ECE346
docker compose buildThe first build takes a few minutes (downloads ROS 2 Foxy image + installs all dependencies).
./start.shThis starts the container, and opens a shell inside it.
colcon build --symlink-install
source install/setup.bash# Start the container and open a shell
./start.sh
# Open another terminal into the same running container
sudo docker compose exec ros bash
# Stop the container
./start.sh down
# Rebuild the Docker image (only needed if Dockerfile or requirements.txt changed)
./start.sh buildFrom here, go to the individual lab README in src/racecar_ece346/ece346/ for lab-specific instructions.
./start.sh # start container + open shell
./start.sh build # rebuild image (after Dockerfile/requirements changes)
./start.sh down # stop the containerTo open additional terminal windows into the same container:
sudo docker compose exec ros bash| Change | Action |
|---|---|
Edit .py files |
Nothing — changes are live instantly |
Edit .yaml config files |
Nothing — changes are live instantly |
Change .msg, .srv, or CMakeLists.txt |
Run colcon build inside the container |
Change Dockerfile or requirements.txt |
Run ./start.sh build |
ECE346/
├── src/
│ ├── racecar_msgs/ # Custom messages (ServoMsg, OdometryArray, SetArray)
│ ├── racecar_routing/ # Lanelet2 map routing + services
│ ├── racecar_interface/ # Simulator, traffic sim, visualization
│ └── racecar_ece346/ # Lab code (Lab0)
├── HOST_setup/linux/
├── docker/ # Entrypoint script
├── Dockerfile
├── docker-compose.yml
├── docker-compose.nvidia.yml
├── requirements.txt
└── start.sh # launch Container
When working on labs and making changes to your code, push to your private repo:
git add .
git commit -m "Completed Lab X"
git push origin SP2026When new labs or updates are released:
# Make sure your changes are committed first
git add .
git commit -m "Save current work"
# Pull updates from the course repo
git pull upstream SP2026If you encounter merge conflicts, this tutorial can help. If you're unsure about merging, you can create a temporary branch first:
git checkout -b temp
git pull upstream SP2026
# Inspect changes, then merge into your main branch
git checkout SP2026
git merge temp
git branch --delete temp