Workspace-scoped Python dependency manager for ROS2
Project description
petal
Workspace-scoped Python dependency manager for ROS2.
Petal discovers Python dependencies in a ROS2 workspace, resolves apt-first, falls back to PyPI when needed, installs into workspace-local state, and writes petal.lock.
Philosophy
ROS 2 and Ubuntu LTS are intentionally paired: Ubuntu freezes package versions, and ROS builds against them. Packages like python3-numpy, python3-opencv, and python3-transforms3d exist so the ROS stack shares a known, coherent set of versions. Replacing them with pip-installed copies often creates a broken ROS environment, not a better one.
Petal works with this model instead of fighting it:
- Prefer apt for anything available as a
python3-*distro package. Petal records these inpetal.tomlso installs are reproducible, but it does not try to replace what ROS was built against. - Use an isolated
.petal/venvfor everything else: research packages, custom libraries, and PyPI-only tools. The venv uses--system-site-packagesso it can see apt-installed ROS Python packages without duplicating them. - Never pip into system Python. That is what causes dependency conflicts; Petal makes it unnecessary.
The result is a workspace that stays compatible with ROS while still letting you use the PyPI packages your project needs, cleanly and reproducibly.
Docker
Docker is great for CI, demos, deployment images, and reproducing a full OS environment. Petal is for the common case where you are developing directly on a ROS machine and want dependencies to stay aligned with that machine's Ubuntu/ROS install.
Use Docker for OS-level isolation. Use Petal for workspace-level dependency management without pip installs into system Python.
Install
uv tool install petal-ros
If you use the colcon verb, install the colcon extra:
uv tool install "petal-ros[colcon]"
Local development with uv, no system pip required:
git clone https://github.com/matthewyjiang/petal.git
cd petal
uv tool install --editable .
For one-off local runs without installing the petal command:
uv run petal --help
Requires Python 3.10+, ROS2 under /opt/ros/<distro>, rosdep, apt tools, and uv.
Quickstart
From a ROS2 workspace root:
petal init
petal sync
petal status
source <(petal activate)
Examples
Apt-resolved package:
petal add numpy
PyPI package:
petal add huggingface
Version spec:
petal add ultralytics ">=8,<9"
Rosdep-resolved ROS package:
petal add cv_bridge
Commands
| Command | Description |
|---|---|
petal init |
Create petal.toml and .petal/venv. |
petal add <name> [spec] |
Add a dependency and sync it. Use --apt or --pip to force a source. |
petal remove <name> |
Remove a dependency. |
petal sync |
Resolve, install, and write petal.lock. |
petal status |
Report drift; exits 2 when the workspace is out of sync. |
petal activate |
Print the ROS + venv activation snippet. |
petal clean |
Remove .petal/venv. |
Common sync flags: --yes, --no, --dry-run, --frozen.
petal sync and petal add print the resolved source for each dependency before installing.
Manifest
Petal records workspace dependencies in petal.toml:
[deps]
numpy = ">=1.24"
ultralytics = "*"
Resolution order: ROS/system modules, rosdep, apt (python3-<name>), then PyPI. Use petal add --apt or petal add --pip when you need to force a source.
Colcon Verb
Petal ships a colcon deps verb. Install with the colcon extra:
uv tool install "petal-ros[colcon]"
Then from a ROS2 workspace root:
colcon deps sync # resolve and install dependencies
colcon deps status # report drift; exits 2 on drift/missing/change
colcon deps sync --dry-run # show plan, install nothing
colcon deps sync --frozen # enforce petal.lock
colcon deps sync --workspace /path/to/ws # explicit workspace path
colcon deps is a thin wrapper around petal sync / petal status and honours the same flags.
Agent Skill
This repo includes an installable agent skill with Petal CLI usage guidance:
petal install-agent-skill
After installing, coding agents that support ~/.agents/skills can load the petal-cli skill when users ask about Petal.
Development
uv run --with pytest pytest -q
Unit tests use fake subprocess runners and do not require network, real ROS, apt, rosdep, uv, or colcon.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file petal_ros-0.2.1.tar.gz.
File metadata
- Download URL: petal_ros-0.2.1.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77c4fd971da415e0438e3bca1d3e17a84fda7cc3d7ff263f498624192070e7cb
|
|
| MD5 |
3d4f6902bb108d33c8532a9145cdc7ec
|
|
| BLAKE2b-256 |
59cff93029232a624882f2be4486cba4d15d7046c52ea93318f02b708771f1fe
|
Provenance
The following attestation bundles were made for petal_ros-0.2.1.tar.gz:
Publisher:
publish.yml on matthewyjiang/petal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
petal_ros-0.2.1.tar.gz -
Subject digest:
77c4fd971da415e0438e3bca1d3e17a84fda7cc3d7ff263f498624192070e7cb - Sigstore transparency entry: 1738840350
- Sigstore integration time:
-
Permalink:
matthewyjiang/petal@40a91ce2e8602c73186d90c1ca2383d820f4cbe0 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/matthewyjiang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40a91ce2e8602c73186d90c1ca2383d820f4cbe0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file petal_ros-0.2.1-py3-none-any.whl.
File metadata
- Download URL: petal_ros-0.2.1-py3-none-any.whl
- Upload date:
- Size: 30.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
242eca49c8b0c3f4278fc43d3404b1ae02d1f53bafc90c1b48d9d39cd79aa73e
|
|
| MD5 |
64a451b06c6660721cff490c0ded84d5
|
|
| BLAKE2b-256 |
4edfd8c292d1aa94ccd020b9ce52d6ef8f31681626c69d3b5f549c8d1c2f7d80
|
Provenance
The following attestation bundles were made for petal_ros-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on matthewyjiang/petal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
petal_ros-0.2.1-py3-none-any.whl -
Subject digest:
242eca49c8b0c3f4278fc43d3404b1ae02d1f53bafc90c1b48d9d39cd79aa73e - Sigstore transparency entry: 1738840352
- Sigstore integration time:
-
Permalink:
matthewyjiang/petal@40a91ce2e8602c73186d90c1ca2383d820f4cbe0 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/matthewyjiang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40a91ce2e8602c73186d90c1ca2383d820f4cbe0 -
Trigger Event:
workflow_dispatch
-
Statement type: