ros-project-generator creates a ROS 2 workspace skeleton and can optionally add a VS Code Dev Container configuration. It does not generate Docker images by itself.
Docker files are generated by robotics_dockers. It is declared as a Python dependency and installed automatically with this project.
ros-project-generator owns project structure:
- workspace files such as
README.md,pyproject.toml,.gitignore, and optional pre-commit config deps.repossrc/0_deps- starter ROS 2 packages such as
bringupandsimulation - optional VS Code files under
.devcontainer/,.vscode/, andws.code-workspace
robotics_dockers owns Docker image generation:
docker/Dockerfiledocker/build.pydocker/.resources/- ROS installation scripts
- entrypoints
- image user setup
- image-level extra package mechanisms
ros-project-generator owns the two project runtime definitions:
docker/compose_files/docker-compose.yaml.devcontainer/docker-compose.yaml
This boundary is intentional. If a generated file controls how the Docker image is built, it belongs in robotics_dockers. If a generated file controls the ROS workspace or the editor experience, it belongs in ros-project-generator.
Keep Python environments outside the source tree. This makes the separation between cloned source code and the installed Python runtime explicit.
robotics_dockers is obtained from the release tag declared in pyproject.toml, so every installation receives the same tested Docker-context contract.
Use this installation when you want to create ROS projects without modifying the generator:
git clone https://github.com/jfrascon/ros_project_generator.git
cd ros_project_generator
python3 -m venv "${HOME}/.python_venvs/ros-project-generator"
. "${HOME}/.python_venvs/ros-project-generator/bin/activate"
python -m pip install --upgrade pip
python -m pip install .Installing this project downloads and installs the declared robotics_dockers Git dependency in the same virtual environment. No second clone or submodule command is required.
Activate the same environment in each new terminal before using the command:
. "${HOME}/.python_venvs/ros-project-generator/bin/activate"
ros-project --helpUse two editable installations when developing and testing ros_project_generator together with robotics_dockers. The repositories do not need to be adjacent; the paths below are examples and may be replaced with any two source directories:
git clone \
https://github.com/jfrascon/robotics_dockers.git \
/ruta/a/robotics_dockers
git clone \
https://github.com/jfrascon/ros_project_generator.git \
/ruta/segunda/a/ros_project_generator
cd /ruta/segunda/a/ros_project_generator
python3 -m venv "${HOME}/.python_venvs/ros-project-generator-dev"
. "${HOME}/.python_venvs/ros-project-generator-dev/bin/activate"
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
python -m pip install --no-deps -e /ruta/a/robotics_dockersThe first editable installation connects ros_project_generator to its source checkout and installs its development dependencies. It also installs the robotics_dockers release tag declared in pyproject.toml, because that is the normal project dependency. The final command replaces only that installed dependency with the local editable checkout.
Afterwards, verify that both packages report an editable project location:
python -m pip show ros-project-generator robotics-dockersChanges in either source tree are now used immediately without reinstalling the package. Running python -m pip install -e '.[dev]' again may restore the declared robotics_dockers release tag. When that command is run again, repeat the final python -m pip install --no-deps -e /ruta/a/robotics_dockers command afterwards.
When changing only ros_project_generator, the final editable robotics_dockers command may be omitted. In that case, the generator continues to use the release tag declared in pyproject.toml.
Create a ROS 2 project:
ros-project new PROJECT_ID PROJECT_DIR ROS_DISTRO [options]Example:
ros-project new my_robot ~/workspaces/my_robot jazzy \
--img-id my_robot:jazzyPROJECT_ID also becomes the default Docker Compose project name. It must
start with a lowercase letter or digit and may contain only lowercase letters,
digits, - and _. This is checked before any project files are created.
Create the same project without VS Code files:
ros-project new my_robot ~/workspaces/my_robot jazzy \
--img-id my_robot:jazzy \
--no-vscodeThe project generator does not ask for an account. The generated Docker context is safe to commit because it contains no developer-specific UID or GID. Select the account later, when building the image:
cd ~/workspaces/my_robot/docker
python3 build.py developer "$(id --user)" "$(id --group)"The primary group name defaults to the build command's user name; pass --group GROUP_NAME to build.py when they must differ. The base image defaults to the Ubuntu release associated with ROS_DISTRO; use --base-img IMAGE on ros-project new only when the project needs another compatible base.
Supported ROS distributions are listed by:
ros-project new -hAt the time this README was written, the project supports ROS 2 distributions only.
A normal generated project contains:
PROJECT_DIR/
docker/
Dockerfile # image context generated through robotics_dockers
build.py
compose_files/
docker-compose.yaml # project runtime owned by ros-project-generator
robotics_dockers_user_env.py
env_files/
.gitkeep
deps.repos
pyproject.toml
README.md
src/
0_deps/
bringup/
simulation/
If VS Code support is enabled, the project also contains:
PROJECT_DIR/
.devcontainer/
code-devcont
devcont
devcontainer.json
docker-compose.yaml
.vscode/
c_cpp_properties.json
tasks.json
ws.code-workspace
The two generated Compose files have identical initial content but different purposes:
docker/compose_files/docker-compose.yamlis the normal production/deployment Compose file owned by the generated ROS project. Additional production or machine-specific Compose definitions can be stored beside it..devcontainer/docker-compose.yamlis an independent copy for VS Code. A developer may customize this copy without changing the normal project runtime.
The complete .devcontainer/ directory, .vscode/ directory and workspace
file are ignored by the generated Git repository. They are developer-local
starting points and may diverge completely between developers during the life
of the project.
There is currently one project Compose template in ros-project-generator.
It is rendered once for production and then copied into .devcontainer, so the two files start with identical mounts, devices, NVIDIA settings and capabilities. The generated files are physically independent and may diverge after project creation. If their intended runtime behavior diverges in the generator itself, the single source template can then be split deliberately.
Both files default their Compose project name to the generated ROS project ID. Set COMPOSE_PROJECT_NAME when two deployments or checkouts on the same host must use different names; the standard docker compose --project-name option can also override it.
The template also documents optional rtprio and memlock limits beside the SYS_NICE and IPC_LOCK capabilities they complement. These limits remain disabled until a project needs them. A 30-second stop grace period is active so ROS nodes, rosbag recorders and simulators can close before Docker sends SIGKILL.
The production and development environments are deliberately independent. docker/build.py builds and validates the image, but it does not create a Compose environment file. For each deployment machine, create a deliberately named file below docker/env_files/, such as production.env or robot-a.env. These files can be versioned when they contain shared machine configuration and no secrets.
After building or pulling the selected image, copy its five identity values into that file and then add the paths, display and device values belonging to the deployment machine:
cd docker
python3 robotics_dockers_user_env.py PROJECT_IMAGE \
--output env_files/production.env
docker compose \
--env-file env_files/production.env \
--file compose_files/docker-compose.yaml \
upThe helper preserves other variables and comments already present in the file. It does not create host-specific values.
The .devcontainer/code-devcont script inspects the configured Docker image, exports the generic IMAGE_USER_ID, IMAGE_USER_PRIMARY_GROUP_ID and COMPOSE_PROJECT_NAME Compose variables, adds HOST_WORKSPACE, DISPLAY, HOST_XAUTHORITY_FILE and RENDER_GID, and opens ws.code-workspace. It does not write an environment file; the Dev Containers extension inherits the exported values from the VS Code process.
The .devcontainer/devcont script starts or stops the independent Dev Container Compose project; running it without arguments is the same as devcont --up. devcont --up inspects the image and writes all development-machine values, including the effective COMPOSE_PROJECT_NAME, to .devcontainer/.env. devcont --down reuses that file, so it stops the same project even when the original shell override is no longer present. Neither command reads files below docker/env_files/.
devcontainer.json leaves remoteUser and containerUser unset, uses /workspace, and sets updateRemoteUserUID: false. Docker therefore uses the account stored in the selected image, whatever its name. VS Code must not apply a second UID conversion after robotics_dockers fixed the identity during the image build.
Run the test suite from this repository root:
pytest -qThe tests mock Docker generation only when checking argument delegation. Integration tests render the real robotics_dockers image context and the project-owned Compose template without building an image. They verify the generic identity contract, /workspace, XDG, optional NVIDIA configuration, the exact initial Compose copy and the later independence of the two Compose files.
- Do not add Dockerfile, Docker build, ROS installation, entrypoint, or image-extra resources to this repository.
- Add those resources to
robotics_dockersinstead, after explicitly deciding to change that project. - Keep
deps.reposandsrc/0_deps; they describe the source workspace, not the Docker image. - Keep ROS package templates here when they generate project packages such as
bringuporsimulation.
