Metadata-Version: 2.4
Name: play_launch
Version: 0.7.1
Summary: ROS2 Launch Inspection Tool - Record and replay launch executions for performance analysis
Author-email: "Lin, Hsiang-Jui" <jerry73204@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Repository, https://github.com/NEWSLabNTU/play_launch
Project-URL: Documentation, https://github.com/NEWSLabNTU/play_launch#readme
Keywords: ros2,launch,profiling,monitoring,robotics
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Rust
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: pyyaml>=6.0
Requires-Dist: lark>=1.2
Requires-Dist: packaging>=24.0
Requires-Dist: plotly>=5.4.1
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: pytest-mock>=3.12; extra == "dev"
Requires-Dist: ruff>=0.8.0; extra == "dev"
Requires-Dist: build; extra == "dev"
Dynamic: license-file

# play_launch

Record, replay, and analyze ROS 2 launch executions with resource monitoring and interactive management.

[![Watch the demo](assets/demo.png)](assets/demo.mp4)

## Installation

Install from PyPI:

```bash
pip install play_launch
```

Optional: Enable I/O monitoring (requires sudo):

```bash
play_launch setcap-io-helper
```

## Quick Start

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

```bash
play_launch launch demo_nodes_cpp 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`:

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

### Single Nodes

Replace `ros2 run` with `play_launch run`:

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

### Two-Step Workflow

Record first, replay multiple times:

```bash
# Record
play_launch dump launch <package> <launch_file> [arguments...]

# Replay
play_launch replay
```

## 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:

```bash
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`):

```bash
# 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):

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

### Configure Web UI

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

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

### Configuration File

Use YAML for advanced control:

```yaml
# 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:

```bash
play_launch replay --config config.yaml
```

## Visualization

Generate interactive plots from monitoring data:

```bash
# 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 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

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

# Dump and replay
play_launch dump launch <package> <launch_file> [args...]
play_launch replay [--input-file record.json]

# 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 memory io gpu
play_launch plot --list-metrics
```

## Development

See [CLAUDE.md](CLAUDE.md) for development guidelines and architecture details.

```bash
# Run checks (clippy + rustfmt + ruff + cpplint + clang-format)
just check

# Format code
just format

# Run tests
just test
```

## License

MIT License. See [LICENSE.txt](LICENSE.txt).
