Skip to main content

Pixi extension for ROS package management

Project description

pixi-ros

Bridge your ROS workspace to the modern conda/Pixi ecosystem

pixi-ros helps ROS developers transition from rosdep to Pixi for package management. It automatically reads your ROS workspace's package.xml files and generates a pixi.toml manifest with all dependencies resolved from conda channels (primarily robostack).

Quick Start

Installation

Install pixi first if you haven't already:

curl -fsSL https://pixi.sh/install.sh | bash

Or follow instructions at https://pixi.sh/latest/installation/

Install pixi-ros globally using pixi:

pixi global install pixi-ros

Initialize Your ROS Workspace

Navigate to your ROS workspace and run:

pixi-ros init --distro humble

This will:

  1. Discover all ROS packages in your workspace (by finding package.xml files)
  2. Read dependencies from each package.xml
  3. Validate and resolve each dependency using the priority system:
    • Skip workspace packages (built locally)
    • Use custom mappings from YAML files
    • Query ROS distro index for ROS packages
    • Auto-detect packages on conda-forge
    • Flag packages that can't be found
  4. Generate/update pixi.toml with proper channels and dependencies
  5. Check package availability in conda channels for each platform
  6. Create helpful build/test/clean tasks
  7. Display detailed validation results with source information

Install and Build

After initialization, use standard pixi commands:

# Install all dependencies
pixi install

# Build your workspace
pixi run build

# Run tests
pixi run test

# Activate environment for direct ROS commands
pixi shell

How It Works

Dependency Mapping & Validation

pixi-ros reads all dependency types from package.xml files and intelligently resolves them to conda packages using a priority-based validation system.

Validation Priority Order

When resolving a ROS package dependency, pixi-ros checks sources in this order:

  1. Workspace packages (local source) → Skipped, won't be added to dependencies
  2. Mapping files → Use custom conda package mappings from the embedded mapping.
  3. ROS distribution → Query the official ROS distro index for ros-{distro}-{package} packages
  4. conda-forge (auto-detection) → Search conda-forge for packages without ros-distro prefix
  5. Custom channels → Search any channels supplied via --channel (see below)
  6. NOT FOUND → Mark as unavailable and comment out in pixi.toml

Package Sources

The dependency tables show where each package comes from:

  • ROS {distro}: Official ROS distribution packages from robostack (e.g., ros-humble-rclcpp)
  • Mapping: Custom mappings from YAML files (e.g., cmakecmake, udevlibusb + libudev)
  • conda-forge: Auto-detected packages available directly on conda-forge
  • {custom-channel-name}: Package found in a custom channel (shown in purple, named after the channel)
  • Workspace: Local packages in your workspace (skipped from dependencies)
  • NOT FOUND: Packages that couldn't be resolved (commented out in pixi.toml)

The mapping rules are defined in YAML files (see src/pixi_ros/data/conda-forge.yaml) and can be customized by placing your own mapping files in pixi-ros/*.yaml or ~/.pixi-ros/*.yaml.

After dependency resolution, pixi-ros validates package availability in the configured channels for each target platform by connecting to https://prefix.dev.

Example Output

When you run pixi-ros init --distro humble, you'll see validation results:

Found 2 package(s): my_package, other_package
Initializing ROS humble distribution validator...

╭─────────────────── Package: my_package ───────────────────╮
│ ROS Dependency │ Type    │ Conda Packages          │ Source       │
├────────────────┼─────────┼─────────────────────────┼──────────────┤
│ rclcpp         │ Build   │ ros-humble-rclcpp       │ ROS humble   │
│ std_msgs       │ Runtime │ ros-humble-std-msgs     │ ROS humble   │
│ cmake          │ Build   │ cmake                   │ Mapping      │
│ eigen          │ Build   │ eigen                   │ conda-forge  │
╰────────────────┴─────────┴─────────────────────────┴──────────────╯

Validation Summary:
  ✓ 2 workspace packages (skipped)
  ✓ 1 packages from mappings
  ✓ 5 packages from ROS humble distro
  ✓ 1 packages from conda-forge (auto-detected)

  Total external dependencies: 7

Given a package.xml with:

<depend>rclcpp</depend>
<build_depend>ament_cmake</build_depend>
<build_depend>cmake</build_depend>
<exec_depend>std_msgs</exec_depend>

pixi-ros init --distro humble generates a pixi.toml with:

[dependencies]
# Base ROS dependencies
ros-humble-ros-base = "*"
pkg-config = "*"
compilers = "*"
make = "*"
ninja = "*"

# Build tools
colcon-common-extensions = "*"

# Workspace dependencies
cmake = "*"                      # From mapping
ros-humble-ament-cmake = "*"    # From ROS humble
ros-humble-rclcpp = "*"         # From ROS humble
ros-humble-std-msgs = "*"       # From ROS humble

Version Constraints

pixi-ros supports version constraints from package.xml files and automatically applies them to the generated pixi.toml.

Supported Version Attributes

You can specify version requirements in your package.xml using standard ROS version attributes:

package.xml attribute pixi.toml constraint Description
version_eq="X.Y.Z" ==X.Y.Z Exactly version X.Y.Z
version_gte="X.Y.Z" >=X.Y.Z Version X.Y.Z or newer
version_gt="X.Y.Z" >X.Y.Z Newer than version X.Y.Z
version_lte="X.Y.Z" <=X.Y.Z Version X.Y.Z or older
version_lt="X.Y.Z" <X.Y.Z Older than version X.Y.Z

Multiple constraints can be combined on the same dependency and will be joined with commas in the output.

Given a package.xml with version constraints:

<depend version_gte="3.12.4">cmake</depend>
<build_depend version_gte="3.3.0" version_lt="4.0.0">eigen</build_depend>
<exec_depend version_eq="1.2.3">boost</exec_depend>

pixi-ros init generates:

[dependencies]
cmake = ">=3.12.4"
eigen = ">=3.3.0,<4.0.0"
boost = "==1.2.3"

Command Reference

pixi-ros init

Initialize or update a ROS workspace's pixi.toml.

pixi-ros init --distro <ros_distro>
pixi-ros init --distro humble --platform linux-64 --platform osx-arm64
pixi-ros init

Options:

  • --distro, -d: ROS distribution (optional, will prompt if not provided)
  • --platform, -p: Target platforms (optional, can be specified multiple times, will prompt if not provided)
    • Available: linux-64, osx-64, osx-arm64, win-64
    • Platforms come from the mapping files and determine which dependencies are available
  • --channel, -c: Additional channels to search for packages (optional, can be specified multiple times)
    • Accepts URLs (https://prefix.dev/my-channel) or local paths (./my-channel, ~/channels/my-channel)
    • Channels are added to pixi.toml with higher priority than the default robostack and conda-forge channels

What it does:

  • Scans workspace for package.xml files
  • Reads all dependency types (build, exec, test) and version constraints
  • Validates dependencies using the priority-based system (workspace → mapping → ROS distro → conda-forge)
  • Maps ROS dependencies to conda packages for each platform
  • Applies version constraints from package.xml to pixi.toml dependencies
  • Configures robostack channels
  • Checks package availability per platform
  • Creates build tasks using colcon
  • Generates helpful README_PIXI.md
  • Sets up platform-specific dependencies in pixi.toml
  • Displays validation results showing where each dependency was found

Running multiple times: The command is idempotent - you can run it multiple times to update dependencies as your workspace changes.

Multi-Platform Support

pixi-ros supports generating cross-platform configurations. When you specify multiple platforms, it:

  1. Analyzes dependencies per platform: Some packages have platform-specific mappings (e.g., OpenGL requirements differ between Linux and macOS)

  2. Organizes dependencies intelligently:

    • Common dependencies (available on all platforms) → [dependencies]
    • Unix dependencies (available on Linux and macOS, but not Windows) → [target.unix.dependencies]
    • Platform-specific dependencies[target.linux.dependencies], [target.osx.dependencies], etc.
  3. Sets up correct platform list: The [workspace] section gets the appropriate pixi platform names

Platform Naming

pixi-ros uses standard pixi platform names:

  • linux-64 - Linux x86_64
  • osx-64 - macOS Intel
  • osx-arm64 - macOS Apple Silicon (M1/M2/M3)
  • win-64 - Windows x86_64

Internally, mapping files use a simplified format (linux, osx, win64), but this is transparent to users. When you specify osx-64 and osx-arm64, they both use the same osx mapping rules since package availability is typically the same for both architectures.

Example: Multi-Platform Setup

pixi-ros init --distro humble --platform linux-64 --platform osx-arm64

Generates:

[workspace]
name = "my_workspace"
channels = [
    "https://prefix.dev/robostack-humble",
    "https://prefix.dev/conda-forge",
]
platforms = ["linux-64", "osx-arm64"]

[dependencies]
# Common dependencies (available on all platforms)
ros-humble-rclcpp = "*"
ros-humble-std-msgs = "*"

[target.unix.dependencies]
# Unix-specific dependencies (Linux and macOS)
xorg-libx11 = "*"
xorg-libxext = "*"

[target.linux.dependencies]
# Linux-specific dependencies
libgl-devel = "*"
libopengl-devel = "*"

Interactive Platform Selection

If you don't specify platforms, you'll be prompted:

$ pixi-ros init --distro humble

Available target platforms:
  1. linux-64
  2. osx-64
  3. osx-arm64
  4. win-64

Select platforms (enter numbers or names, comma or space separated): 1 3

Custom Channels

If your workspace depends on packages that live outside the default robostack and conda-forge channels — for example, internal builds or early-access ROS packages — you can point pixi-ros at additional channels with --channel / -c.

# Single custom channel
pixi-ros init --distro kilted --channel https://prefix.dev/my-org

# Multiple custom channels
pixi-ros init --distro kilted -c https://prefix.dev/channel-a -c https://prefix.dev/channel-b

# Local channel (relative or absolute path)
pixi-ros init --distro kilted --channel ./my-local-channel
pixi-ros init --distro kilted --channel ~/channels/staging

Channel priority in pixi.toml

Custom channels are written to pixi.toml before the default channels, giving them the highest resolution priority when pixi install runs:

[workspace]
channels = [
    "https://prefix.dev/my-org",          # custom — highest priority
    "https://prefix.dev/robostack-kilted", # default
    "https://prefix.dev/conda-forge",      # default
]

Local channels

Relative and home-directory paths are accepted and preserved as-is in pixi.toml so pixi can resolve them relative to the workspace. Internally, pixi-ros resolves them to absolute file:// URIs only for the validation step.

pixi-ros init --distro kilted --channel ./tests/data/my-channel
# pixi.toml — relative path kept intact
channels = [
    "./tests/data/my-channel",
    "https://prefix.dev/robostack-kilted",
    "https://prefix.dev/conda-forge",
]

Philosophy

pixi-ros aims to be a quick gateway drug. It:

  • Respects existing ROS conventions (package.xml as source of truth)
  • Uses standard ROS build tools (colcon)
  • Focuses only on dependency management and environment setup
  • Doesn't replace ros2 CLI or other ROS tooling
  • Should eventually become unnecessary as the ecosystem matures

Think of it as a "gateway" to help ROS developers benefit from modern package management while keeping familiar workflows.

Project Structure

After initialization, your workspace will have:

workspace/
├── src/                    # Your ROS packages
│   └── my_package/
│       ├── package.xml    # ROS package manifest (source of truth)
│       └── ...
├── pixi.toml              # Generated pixi manifest
├── pixi.lock              # Locked dependencies (commit this!)
└── README_PIXI.md         # Generated usage guide

Troubleshooting

Package Not Found

If pixi-ros marks packages as "NOT FOUND" (shown in red in the validation output):

  1. Check the ROS distro: Verify the package exists in robostack: https://prefix.dev/channels/robostack-{distro}
  2. Check for typos: Review your package.xml for spelling errors
  3. Check conda-forge: Some packages may be available directly on conda-forge without the ros-distro- prefix
  4. Use a custom channel: If the package lives in a non-default channel, pass it with --channel:
    pixi-ros init --distro humble --channel https://prefix.dev/my-org
    
  5. Create a mapping: Add a custom mapping in pixi-ros/*.yaml if the package has a different conda name
  6. Add to workspace: Consider including the package source in your workspace instead of depending on it
  7. Contribute to RoboStack: If the package should be available but isn't, consider adding it to the appropriate RoboStack repository:

The validation table shows exactly where each dependency was checked, making it easier to diagnose issues.

Different Package Names

pixi-ros includes mapping files for system packages (e.g., cmakecmake, eigeneigen). You can override mappings by creating pixi-ros/*.yaml files in your workspace or ~/.pixi-ros/.

Platform-Specific Issues

Some packages have platform-specific mappings. pixi-ros handles this automatically, but you can test different platforms using the internal API with platform_override.

Active ROS Environment Detected

If you have an existing ROS environment sourced (e.g., from source /opt/ros/humble/setup.bash in your ~/.bashrc), pixi-ros init will warn you:

⚠️  Important: Active ROS environment detected!
   Pixi manages the environment automatically. Remove any source /opt/ros/...
   or source install/setup.bash from your shell config (e.g. ~/.bashrc).

This warning appears when any of these environment variables are detected:

  • ROS_DISTRO - Indicates a sourced ROS distribution
  • ROS_VERSION - Set by ROS 1 or ROS 2
  • AMENT_PREFIX_PATH - ROS 2 specific variable
  • ROS_PACKAGE_PATH - ROS 1 specific variable

Why this matters: Having a manually sourced ROS environment can conflict with pixi's managed environment, leading to version mismatches and unexpected behavior. Pixi automatically sources the correct setup scripts when you use pixi shell or pixi run, so manual sourcing is unnecessary.

How to fix:

  1. Open your shell configuration file (e.g., ~/.bashrc, ~/.zshrc)
  2. Remove or comment out any lines like:
    source /opt/ros/humble/setup.bash
    source ~/ros_ws/install/setup.bash
    
  3. Restart your shell or run source ~/.bashrc (or equivalent)

Contributing

Contributions welcome! Feel free to open issues or PRs on GitHub.

Learn More

Disclaimer

This tool is build with heavy use of AI assistance and is under active development. Please report issues or contribute on GitHub!

I (Ruben) hope pixi-ros can die ASAP, as all of the workflows this tool provides should ideally be native to Pixi itself. But until then, I hope this initialization tool helps you get started!

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

pixi_ros-0.6.1.tar.gz (119.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pixi_ros-0.6.1-py3-none-any.whl (37.6 kB view details)

Uploaded Python 3

File details

Details for the file pixi_ros-0.6.1.tar.gz.

File metadata

  • Download URL: pixi_ros-0.6.1.tar.gz
  • Upload date:
  • Size: 119.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixi_ros-0.6.1.tar.gz
Algorithm Hash digest
SHA256 e7cecd874502a158b8cbb1eab32bdcdd2176221dc2b4b19a4757a6fec5bd9177
MD5 daad41a1e27ea1cff48a040355b81dd6
BLAKE2b-256 fe8a03f041d6e5e72804e1b4170ac6bb38739c94aa6c6d7137c2780d98731873

See more details on using hashes here.

File details

Details for the file pixi_ros-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: pixi_ros-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 37.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixi_ros-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 24acb4ff82d5c6e7c71854c5b564ad0d691bd9d7800871bf6eaf9e35790af294
MD5 fdd0b3e1e802408af9d179a82c9adefb
BLAKE2b-256 385f6b2120a2b972571857ed815c78ae313bf84d91e5308568cf0557fe69cff9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page