Skip to main content

play_launch

Resolve, run, and analyze ROS 2 launch executions with resource monitoring and interactive management.

Watch the demo

Upgrading? CHANGELOG.md lists the breaking changes — 0.9.0 has several, and a few of them change behaviour rather than erroring.

Installation

Requires Ubuntu 22.04+ with ROS 2 (Humble or Jazzy), Python 3.10+, and:

sudo apt install libz3-dev
sudo apt install ros-${ROS_DISTRO}-rclcpp-components ros-${ROS_DISTRO}-class-loader

Install from PyPI:

pip install play_launch

This installs the play_launch command, which carries the whole surface: launch, run, up, resolve, dump, check, plot, contract, context, setcap, verify.

Optional: grant the helper binaries the capabilities they need for per-process I/O monitoring and non-root RT scheduling (requires sudo):

play_launch setcap

This enables per-process I/O monitoring and non-root RT scheduling (--sched): play_launch setcap grants CAP_SYS_PTRACE to the I/O helper and CAP_SYS_NICE to the RT helper — both are small ROS-free binaries. The main play_launch binary is never given a file capability — that would put it in secure-execution mode and stop it finding its ROS libraries.

See the Real-Time Scheduling Guide for the scheduling spec format and how it maps onto processes, threads, and the kernel.

Quick Start

Launch any ROS 2 package with monitoring and Web UI enabled by default:

play_launch launch demo_nodes_cpp topics/talker_listener.launch.py

Access Web UI at http://127.0.0.1:8080 for real-time node management and log streaming.

The Rust parser is used by default for speed. For maximum compatibility, use --parser python.

Usage

Launch Files

Replace ros2 launch with play_launch launch:

play_launch launch <package> <launch_file> [arguments...]

Single Nodes

Replace ros2 run with play_launch run:

play_launch run <package> <executable> [arguments...]

Two-Step Workflow

Resolve once, bring the system up as often as you like:

# Resolve once — writes system_model.yaml
play_launch dump launch <package> <launch_file> [arguments...]

# Bring it up, as often as you like
play_launch up system_model.yaml

up takes the model path positionally or as --model <path>; it is required either way, since the model is the only thing up spawns from.

Features

All features enabled by default:

  • Resource monitoring: CPU, memory, I/O, GPU (2s interval)
  • Diagnostic monitoring: /diagnostics and /diagnostics_agg topics
  • Web UI: Interactive management at http://127.0.0.1:8080
  • Container isolation: Composable nodes run in isolated processes via fork+exec (default)

Disable Features

Disable specific features:

play_launch launch <package> <launch_file> --disable-monitoring
play_launch launch <package> <launch_file> --disable-diagnostics
play_launch launch <package> <launch_file> --disable-web-ui
play_launch launch <package> <launch_file> --disable-all

Container Mode

Control how composable nodes are managed (default: isolated):

# Isolated: fork+exec per-node process isolation (default)
play_launch launch <pkg> <file> --container-mode isolated

# Observable: ComponentEvent publishing, shared process
play_launch launch <pkg> <file> --container-mode observable

# Stock: use original container from launch file, no override
play_launch launch <pkg> <file> --container-mode stock

Adjust Monitoring

Change sampling interval (default: 2000ms):

play_launch launch <package> <launch_file> --monitor-interval-ms 500

Configure Web UI

Change address or port (default: 127.0.0.1:8080):

play_launch launch <package> <launch_file> --web-addr 0.0.0.0:8080

Configuration File

Use YAML for advanced control:

# config.yaml
monitoring:
  enabled: true
  sample_interval_ms: 2000

processes:
  - node_pattern: "NODE 'rclcpp_components/component_container*"
    cpu_affinity: [0, 1]
    nice: 5

Apply configuration:

play_launch launch <package> <launch_file> --config config.yaml
play_launch up system_model.yaml --config config.yaml

Visualization

Generate interactive plots from monitoring data:

# Plot latest execution
play_launch plot

# Plot specific log directory
play_launch plot --log-dir play_log/2025-10-28_16-17-56

# Plot specific metrics
play_launch plot --metrics cpu --metrics memory

# List available metrics
play_launch plot --list-metrics

Output saved to play_log/<timestamp>/plot/:

  • cpu_timeline.html - CPU usage over time
  • memory_timeline.html - Memory usage over time
  • io_timeline.html - I/O read/write rates
  • cpu_distribution.html - CPU distribution box plot
  • memory_distribution.html - Memory distribution box plot
  • statistics.txt - Top 10 rankings for all metrics

Web UI Features

  • Node management: Start/Stop/Restart individual or all nodes
  • Container controls: Load/Unload composable nodes
  • Real-time logs: Stream stdout/stderr with log level coloring and filtering
  • Diagnostics panel: View /diagnostics messages with level filtering
  • Status monitoring: Color-coded node states
  • Auto-restart: Per-node automatic restart configuration
  • Search & filter: Find nodes in large deployments

Output Structure

play_log/<timestamp>/
├── node/<node_name>/
│   ├── metadata.json
│   ├── metrics.csv       # Resource metrics (when enabled)
│   ├── out/err           # Process logs
│   ├── pid/status/cmdline
│   └── params_files/     # ROS parameter files
├── load_node/<name>/
│   └── out/err           # Per-composable-node logs (isolated mode)
├── system_stats.csv      # System-wide metrics
├── diagnostics.csv       # Diagnostic messages (when enabled)
└── plot/                 # Generated visualizations

Command Reference

# Launch (all features enabled by default)
play_launch launch <package> <launch_file> [args...]
play_launch run <package> <executable> [args...]

# Dump and up (dump emits the SystemModel by default — one artifact)
play_launch dump launch <package> <launch_file> [args...]
play_launch up system_model.yaml            # or: play_launch up --model system_model.yaml

# Parser selection (Rust is default)
play_launch launch <pkg> <file> --parser rust     # Default, fast
play_launch launch <pkg> <file> --parser python   # Maximum compatibility

# Container mode
play_launch launch <pkg> <file> --container-mode isolated    # Default
play_launch launch <pkg> <file> --container-mode observable
play_launch launch <pkg> <file> --container-mode stock

# Disable features
play_launch launch <pkg> <file> --disable-monitoring
play_launch launch <pkg> <file> --disable-diagnostics
play_launch launch <pkg> <file> --disable-web-ui
play_launch launch <pkg> <file> --disable-all
play_launch launch <pkg> <file> --disable-respawn

# Enable only specific features
play_launch launch <pkg> <file> --enable monitoring
play_launch launch <pkg> <file> --enable web-ui --enable diagnostics

# Adjust settings
play_launch launch <pkg> <file> --monitor-interval-ms 500
play_launch launch <pkg> <file> --web-addr 0.0.0.0:8080
play_launch launch <pkg> <file> --config config.yaml

# Logging
play_launch launch <pkg> <file> --verbose              # Enable INFO level
RUST_LOG=play_launch=debug play_launch launch <pkg> <file>  # DEBUG level

# Visualization
play_launch plot
play_launch plot --log-dir <dir>
play_launch plot --metrics cpu --metrics memory --metrics io --metrics gpu
play_launch plot --list-metrics

Development

Prerequisites

  • ROS 2 (Humble on Ubuntu 22.04, Jazzy on 24.04)
  • Rust toolchain (stable)
  • Python 3.10+
  • just command runner
  • cargo-nextest test runner
  • uv Python package manager

Install Dependencies

just install-deps

This installs colcon-cargo-ros2 and runs rosdep install for all ROS dependencies.

Build

just build          # Full build: colcon + interception .so + wheel
just build-cpp      # C++ only (msgs + container)
just build-rust     # Rust only (assumes C++ install/ exists)
just build-wheel    # Bundle + wheel only (no colcon rebuild)

Optional: grant the I/O helper its monitoring capability and the RT helper its scheduling capability (requires sudo). After this, RT scheduling (--sched) works without root:

play_launch setcap

Re-run it after every rebuild or upgrade. A file capability is bound to the exact contents of a binary, so replacing that binary drops it — deliberately, since carrying privilege across a change would grant it to code nobody vetted. play_launch says so when it happens, naming the grant it is replacing rather than telling you to run a command you already ran.

(A just setcap recipe also exists. It is a DEVELOPER convenience that avoids the password prompt via a throwaway container, it needs a source checkout, and it does not work under rootless Docker. play_launch setcap is the supported path.)

Run

just run launch <package> <launch_file> [arguments...]
just run run <package> <executable> [arguments...]

Test

just test               # Parser unit + fast integration (~3s)
just test-all           # Parser unit + all integration (~30s)
just test-unit          # Parser unit tests only
just test-integration   # All integration tests
just test-autoware      # Autoware integration tests

Code Quality

just check      # clippy + rustfmt + ruff + cpplint + clang-format
just format     # Auto-format Rust + Python + C++
just quality    # Format then check

Install Wheel Locally

just install-wheel

License

MIT License. See LICENSE.txt.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

play_launch-0.9.0-py3-none-manylinux_2_35_x86_64.whl (11.1 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ x86-64

play_launch-0.9.0-py3-none-manylinux_2_35_aarch64.whl (10.2 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ ARM64

File details

Details for the file play_launch-0.9.0-py3-none-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for play_launch-0.9.0-py3-none-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 74564cd1fb53136e9629c302e7d7feb01e78e461ebecc57b6399a635233fffbe
MD5 d779f3b7c574b83b01527399d6e42f05
BLAKE2b-256 bf3e82e04fcb31abbb7835ae8c39dae15aa2b333426dfa88405dd1f97c61e540

See more details on using hashes here.

Provenance

The following attestation bundles were made for play_launch-0.9.0-py3-none-manylinux_2_35_x86_64.whl:

Publisher: release-wheel.yml on NEWSLabNTU/play_launch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file play_launch-0.9.0-py3-none-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for play_launch-0.9.0-py3-none-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 efb1a6a1ee362c3a30d9630c0dba461ee4c01458cb8cddbe29130a2856c46401
MD5 dd3eb1c062db4d688024462230dc72ae
BLAKE2b-256 23177e74baf0da10aa7e64dfd418261191bc4a533aeace7971d813e23d5ef164

See more details on using hashes here.

Provenance

The following attestation bundles were made for play_launch-0.9.0-py3-none-manylinux_2_35_aarch64.whl:

Publisher: release-wheel.yml on NEWSLabNTU/play_launch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.9.0 This release

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page