Metadata-Version: 2.4
Name: rosight
Version: 0.1.0
Summary: A lazygit-inspired terminal UI for ROS 2: topics, nodes, services, params, live message inspection and plotting.
Project-URL: Homepage, https://github.com/deyuf/rosight
Project-URL: Documentation, https://github.com/deyuf/rosight#readme
Project-URL: Repository, https://github.com/deyuf/rosight
Project-URL: Issues, https://github.com/deyuf/rosight/issues
Author: deyuf
License-File: LICENSE
Keywords: monitoring,plotting,robotics,ros2,textual,tui
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Requires-Dist: platformdirs>=4.0
Requires-Dist: plotext>=5.2
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.7
Requires-Dist: textual>=0.79
Requires-Dist: tomli>=2.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: pymdown-extensions>=10.7; extra == 'docs'
Description-Content-Type: text/markdown

# Rosight

[![CI](https://github.com/deyuf/rosight/actions/workflows/ci.yml/badge.svg)](https://github.com/deyuf/rosight/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> **Rosight** = ROS + sight. A keyboard-driven terminal cockpit for ROS 2.

Browse the live ROS 2 graph — messages, nodes, services, actions, parameters,
TF, bags, interfaces — and live-plot any numeric field, all from one screen
without a mouse. Built for SSH, tmux, robot consoles.

![Messages tab](docs/screenshots/01-messages.svg)

## What's inside

Nine tabs, keyboard-driven, all on one screen:

| `#` | Tab | What you can do |
|---|---|---|
| `1` | **Messages** | Filter the topic table, `Enter` to subscribe, the right pane shows live hz / bw / jitter and the message tree. Press `i` for static topic info (types, publishers, QoS). |
| `2` | **Nodes** | Discover every node, drill into its publishers, subscribers, service servers/clients, action servers/clients. |
| `3` | **Services** | List services with types. `c` opens a call form *(planned)*. |
| `4` | **Actions** | List action servers with types. Goal monitor *(planned)*. |
| `5` | **Params** | Browse parameters per node, get / set with type awareness. |
| `6` | **Plot** | Multi-series live plot of any numeric field — pick a field in the message tree and press `p`. Pause / window-scale / CSV export. |
| `7` | **TF** | Auto-built frame tree from `/tf` and `/tf_static`. |
| `8` | **Bags** | `ros2 bag record` / `play` / `info`. The header tells you which key stops the recording while it's running. |
| `9` | **Interfaces** | Browse `msg` / `srv` / `action` definitions of every interface package on the system. |

### Screenshots

![Nodes tab](docs/screenshots/02-nodes.svg)
*Nodes (`2`)*

![Services tab](docs/screenshots/03-services.svg)
*Services (`3`)*

![Actions tab](docs/screenshots/04-actions.svg)
*Actions (`4`)*

![Bags tab](docs/screenshots/06-bags.svg)
*Bags (`8`) — recording state*

Cross-cutting features:

- **Auto-QoS** — subscriber profile is negotiated to match every publisher of a topic (BEST_EFFORT vs RELIABLE, TRANSIENT_LOCAL, etc.), so sensor topics "just work".
- **Theme persistence** — pick a theme via `Ctrl+P → Change theme`; it survives restarts (stored next to your config in a small `state.toml`).
- **Runtime domain switch** — `:domain 5` reconnects the rclpy backend on a new `ROS_DOMAIN_ID` without restarting the app.
- **Live notifications** — important actions (subscribed, started recording, switched domain) show as toasts; nothing important hides in a covered status bar.
- **No ROS required for the UI** — the package imports cleanly without `rclpy`, so you can dev / unit-test on cloud machines. Run with `--no-ros` to stay offline.

## Install

Rosight is not yet on PyPI; install from source:

```bash
git clone https://github.com/deyuf/rosight
cd rosight
pip install -e .
```

Then, in any terminal where you want to use it:

```bash
source /opt/ros/<distro>/setup.bash
rosight
```

If you maintain multiple distros, source the one whose `rclpy` should drive
discovery before launching. See [`docs/installation.md`](docs/installation.md)
for the recommended `--system-site-packages` venv layout that keeps the system
`rclpy` reachable while pip manages everything else.

## Quick start

```bash
# launch (inherits ROS_DOMAIN_ID from env)
rosight

# pick a domain explicitly + log to file
rosight --domain-id 5 --log-file /tmp/rosight.log

# UI-only mode, no rclpy needed (great for theme / layout dev)
rosight --no-ros
```

Inside the app:

- `?` — keyboard reference overlay
- `:` — command palette (`topic <filter>`, `plot <topic> <path>`, `record`, `domain <N>`, `quit`)
- `1`–`9` — jump to a tab
- `q` or `Ctrl+C` — quit
- `r` — manual refresh

Plotting workflow (the question new users ask most):

1. **Messages tab**, cursor over a topic, **Enter** to subscribe (focus auto-jumps to the message tree)
2. Use arrow keys / Space to expand fields in the tree
3. Cursor on a *numeric* leaf (int / float), press **p** — series is added and the Plot tab opens

## Documentation

| Topic | File |
|-------|------|
| Installation per distro | [docs/installation.md](docs/installation.md) |
| Daily usage | [docs/usage.md](docs/usage.md) |
| Keybindings | [docs/keybindings.md](docs/keybindings.md) |
| Configuration | [docs/configuration.md](docs/configuration.md) |
| Plotting deep-dive | [docs/plotting.md](docs/plotting.md) |
| Architecture | [docs/architecture.md](docs/architecture.md) |
| Contributing | [docs/development.md](docs/development.md) |
| FAQ | [docs/faq.md](docs/faq.md) |

## Project layout

```
src/rosight/
├── app.py             # Textual App, panel registry, global key bindings
├── cli.py             # argparse entry point
├── config.py          # TOML config loader + state.toml persistence
├── ros/
│   ├── backend.py     # central rclpy facade (lifecycle, sub mgmt, domain switch)
│   ├── introspection.py  # dynamic message-type resolution
│   ├── qos.py         # plain-data QoS + auto-negotiation
│   └── stats.py       # hz / bw monitors
├── utils/
│   ├── datatable.py   # row-cursor preservation + last-column auto-fit
│   ├── ringbuffer.py  # thread-safe bounded buffers
│   ├── path.py        # message field-path parser
│   └── formatting.py  # human-readable display helpers
└── widgets/           # one file per panel + status bar / help / palette
```

## Tech stack & rationale — short version

- **Python 3.10+** + **rclpy** (first-class ROS 2 client, dynamic message introspection via `rosidl_runtime_py`)
- **Textual ≥ 0.79** (modern async TUI, CSS-like styling, headless pilot tests — that's how the 80-test suite stays meaningful for a TUI)
- **plotext** for ANSI plotting in the Plot tab
- **hatch + ruff + mypy + pytest-asyncio** for the dev loop
- **MkDocs Material** for the docs site
- rclpy runs on its own `MultiThreadedExecutor` daemon thread so DDS spinning never blocks the Textual main loop. See [`DESIGN.md`](DESIGN.md) for the full reasoning.

## Status

Beta. Discovery, subscription, plotting, TF, bag record/play, theme persistence,
runtime domain switch — all working. Auto-forms for service call and action
goal are on the roadmap.

## License

MIT. See [`LICENSE`](LICENSE).
