From 164d537e4d8b218f1993106549606269cc38d0fc Mon Sep 17 00:00:00 2001 From: Sidra Date: Thu, 13 Aug 2026 16:23:18 +0400 Subject: [PATCH] Update 2026-08-13 16:23 --- .gitignore | 30 + README.md | 402 +++++ systemd_user/x2-dashboard-agent.service | 28 + systemd_user/x2-dashboard.service | 27 + systemd_user/x2-dashboard.timer | 19 + x2_dashboard/backend/__init__.py | 3 + x2_dashboard/backend/__main__.py | 98 ++ x2_dashboard/backend/announce.py | 348 ++++ x2_dashboard/backend/bridge_agent.py | 610 +++++++ x2_dashboard/backend/bridge_base.py | 241 +++ x2_dashboard/backend/bridge_mock.py | 520 ++++++ x2_dashboard/backend/hub.py | 107 ++ x2_dashboard/backend/netinfo.py | 346 ++++ x2_dashboard/backend/nic.py | 592 +++++++ x2_dashboard/backend/plugin_api.py | 229 +++ x2_dashboard/backend/plugins/__init__.py | 8 + x2_dashboard/backend/plugins/_template.py | 105 ++ .../backend/plugins/example_battery_guard.py | 112 ++ .../backend/plugins/example_greeter.py | 95 ++ x2_dashboard/backend/recovery.py | 118 ++ x2_dashboard/backend/registry.py | 203 +++ x2_dashboard/backend/server.py | 1062 ++++++++++++ x2_dashboard/backend/settings.py | 227 +++ x2_dashboard/backend/voice_session.py | 306 ++++ x2_dashboard/backend/x2_spec.py | 773 +++++++++ x2_dashboard/config.json | 27 + x2_dashboard/web/css/app.css | 991 +++++++++++ x2_dashboard/web/index.html | 176 ++ x2_dashboard/web/js/charts.js | 423 +++++ x2_dashboard/web/js/core.js | 349 ++++ x2_dashboard/web/js/main.js | 538 ++++++ x2_dashboard/web/js/model3d.js | 372 +++++ x2_dashboard/web/js/tabs/console.js | 238 +++ x2_dashboard/web/js/tabs/control.js | 438 +++++ x2_dashboard/web/js/tabs/extensions.js | 363 ++++ x2_dashboard/web/js/tabs/interaction.js | 535 ++++++ x2_dashboard/web/js/tabs/lidar.js | 430 +++++ x2_dashboard/web/js/tabs/model.js | 443 +++++ x2_dashboard/web/js/tabs/motion.js | 321 ++++ x2_dashboard/web/js/tabs/navigation.js | 276 +++ x2_dashboard/web/js/tabs/overview.js | 222 +++ x2_dashboard/web/js/tabs/power.js | 246 +++ x2_dashboard/web/js/tabs/sensors.js | 249 +++ x2_dashboard/web/js/tabs/settings.js | 606 +++++++ x2_dashboard/web/js/tabs/vision.js | 326 ++++ x2_dashboard/web/js/ui.js | 286 ++++ x2_dashboard/web/model/model.bin | Bin 0 -> 1447950 bytes x2_dashboard/web/model/model.json | 1 + x2_dashboard_agent/ensure_agent.sh | 41 + x2_dashboard_agent/run_agent.sh | 45 + x2_dashboard_agent/run_agent.sh.bak | 26 + x2_dashboard_agent/run_dashboard.sh | 73 + .../run_dashboard.sh.bak-20260805-204141 | 53 + x2_dashboard_agent/x2-dashboard-agent.service | 29 + x2_dashboard_agent/x2_agent.py | 1477 +++++++++++++++++ 55 files changed, 16209 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 systemd_user/x2-dashboard-agent.service create mode 100644 systemd_user/x2-dashboard.service create mode 100644 systemd_user/x2-dashboard.timer create mode 100644 x2_dashboard/backend/__init__.py create mode 100644 x2_dashboard/backend/__main__.py create mode 100644 x2_dashboard/backend/announce.py create mode 100644 x2_dashboard/backend/bridge_agent.py create mode 100644 x2_dashboard/backend/bridge_base.py create mode 100644 x2_dashboard/backend/bridge_mock.py create mode 100644 x2_dashboard/backend/hub.py create mode 100644 x2_dashboard/backend/netinfo.py create mode 100644 x2_dashboard/backend/nic.py create mode 100644 x2_dashboard/backend/plugin_api.py create mode 100644 x2_dashboard/backend/plugins/__init__.py create mode 100644 x2_dashboard/backend/plugins/_template.py create mode 100644 x2_dashboard/backend/plugins/example_battery_guard.py create mode 100644 x2_dashboard/backend/plugins/example_greeter.py create mode 100644 x2_dashboard/backend/recovery.py create mode 100644 x2_dashboard/backend/registry.py create mode 100644 x2_dashboard/backend/server.py create mode 100644 x2_dashboard/backend/settings.py create mode 100644 x2_dashboard/backend/voice_session.py create mode 100644 x2_dashboard/backend/x2_spec.py create mode 100644 x2_dashboard/config.json create mode 100644 x2_dashboard/web/css/app.css create mode 100644 x2_dashboard/web/index.html create mode 100644 x2_dashboard/web/js/charts.js create mode 100644 x2_dashboard/web/js/core.js create mode 100644 x2_dashboard/web/js/main.js create mode 100644 x2_dashboard/web/js/model3d.js create mode 100644 x2_dashboard/web/js/tabs/console.js create mode 100644 x2_dashboard/web/js/tabs/control.js create mode 100644 x2_dashboard/web/js/tabs/extensions.js create mode 100644 x2_dashboard/web/js/tabs/interaction.js create mode 100644 x2_dashboard/web/js/tabs/lidar.js create mode 100644 x2_dashboard/web/js/tabs/model.js create mode 100644 x2_dashboard/web/js/tabs/motion.js create mode 100644 x2_dashboard/web/js/tabs/navigation.js create mode 100644 x2_dashboard/web/js/tabs/overview.js create mode 100644 x2_dashboard/web/js/tabs/power.js create mode 100644 x2_dashboard/web/js/tabs/sensors.js create mode 100644 x2_dashboard/web/js/tabs/settings.js create mode 100644 x2_dashboard/web/js/tabs/vision.js create mode 100644 x2_dashboard/web/js/ui.js create mode 100644 x2_dashboard/web/model/model.bin create mode 100644 x2_dashboard/web/model/model.json create mode 100644 x2_dashboard_agent/ensure_agent.sh create mode 100644 x2_dashboard_agent/run_agent.sh create mode 100644 x2_dashboard_agent/run_agent.sh.bak create mode 100644 x2_dashboard_agent/run_dashboard.sh create mode 100644 x2_dashboard_agent/run_dashboard.sh.bak-20260805-204141 create mode 100644 x2_dashboard_agent/x2-dashboard-agent.service create mode 100644 x2_dashboard_agent/x2_agent.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c0c8ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# --- secrets --- +.env +.env.* +*.pem +*.key + +# --- dependencies --- +node_modules/ +vendor/ +venv/ +.venv/ +__pycache__/ + +# --- build output --- +dist/ +build/ +out/ +bin/ +obj/ +*.pyc + +# --- editors / os --- +.vs/ +.idea/ +.DS_Store +Thumbs.db + +# --- logs --- +*.log +npm-debug.log* diff --git a/README.md b/README.md new file mode 100644 index 0000000..53ab30a --- /dev/null +++ b/README.md @@ -0,0 +1,402 @@ +# AGIBOT X2 Dashboard + +A web control room for the AGIBOT X2 humanoid. Open `http://:8770` from a laptop, phone or tablet on the same network and you get live telemetry, motion control, camera and LiDAR feeds, a posed 3D digital twin, and speech/expression control — with no app to install and no ROS on the client. + +The browser never speaks ROS 2. A small agent on the robot bridges ROS 2 DDS to plain TCP, and the dashboard serves an ordinary web page over HTTP. + +--- + +## Contents + +- [Architecture](#architecture) +- [Quick start](#quick-start) +- [The interface — 13 tabs](#the-interface--13-tabs) +- [Safety model](#safety-model) +- [Backend modules](#backend-modules) +- [The on-robot agent](#the-on-robot-agent) +- [HTTP API](#http-api) +- [Configuration](#configuration) +- [Extensions](#extensions) +- [Deployment](#deployment) +- [Repository layout](#repository-layout) +- [Design notes](#design-notes) + +--- + +## Architecture + +Two processes, one socket between them: + +``` + Browser ──HTTP + WebSocket──▶ Dashboard server ──JSON lines over TCP──▶ Agent ──▶ ROS 2 DDS + (any device) :8770 (FastAPI, Python) :8781 (rclpy, on robot) +``` + +**The dashboard server never imports `rclpy`.** That single decision drives most of the design: + +- It runs anywhere — including Windows — because it needs no ROS installation. +- The web UI stays up when the robot is **off**, so it can show an offline gate that says "power the robot on" instead of dying with a connection error. +- Reconnection is automatic and continuous. Switch the robot off and the UI shows the gate; switch it on and the dashboard reattaches by itself. + +Every bridge implements one interface (`bridge_base.py`), so the server and the entire frontend are identical whether a real robot is attached or not. + +| Bridge mode | Behaviour | +|---|---| +| `auto` | Talk to the robot agent if a host is configured, otherwise simulate | +| `agent` | Require the real robot — never silently fall back to simulation | +| `mock` | Always simulate, for UI work away from the robot | + +The mock is deliberately more than a random-number generator: battery drains at a rate that depends on what the robot is doing, odometry integrates the velocity you command, joints ease toward their targets, and mode transitions enforce the same preconditions the real robot does. UI logic exercised against the mock behaves the same way once a real bridge is attached. + +--- + +## Quick start + +**On the robot** (needs ROS 2 Humble and the AimDK workspace): + +```bash +cd ~/x2_dashboard_agent +./run_agent.sh # sources ROS 2 + AimDK, starts the agent on :8781 +``` + +**The dashboard** (on the robot, or on any machine that can reach it): + +```bash +cd x2_dashboard +python3 -m backend # binds 0.0.0.0:8770 +``` + +It prints every address it is reachable on, so you can open it from a phone without knowing the host's IP in advance. + +To run both together with a crash-restart watchdog, use `run_dashboard.sh` — it is idempotent and safe to call every minute (see [Deployment](#deployment)). + +> **DDS profile required.** Camera and LiDAR topics will connect but deliver *nothing* without the vendor Fast DDS profile. `run_agent.sh` exports `FASTRTPS_DEFAULT_PROFILES_FILE` for this reason — see [Design notes](#design-notes). + +--- + +## The interface — 13 tabs + +### Overview +The at-a-glance page: one hero figure, supporting stat tiles, and trend sparklines. Battery, mode, uptime, attitude and compass. + +### Control +Mode switching, input-source arbitration, driving, and preset motions. + +- **18 motion modes** in 6 groups — safety/basic, joint control, standing, locomotion, posture, external. Each carries a description and a danger flag. +- **Driving** with `W`/`A`/`S`/`D` or arrow keys; `Space` is an emergency stop that zeroes velocity immediately. +- **34 preset motions** in 5 groups: greeting (wave, handshake, salute, bow), expressive (heart, thumbs up, hug, cheer, sad), gesture (clap, fist, cross arms), performance (two bass dances, photo poses) and head (point, shake). +- Velocity is only accepted in driveable modes; joint commands only in `JOINT_DEFAULT` / `JOINT_FREEZE`. + +### Motion +Joint-level control and end effectors. Four joint groups — **head, waist, arms, legs** — with per-joint sliders, live position/effort bars, and **4 hand presets**. + +### Sensors +IMU (chest and torso), the **8-zone head touch sensor**, LiDAR status, and a topic-liveness table so you can see which topics are actually publishing. + +### Vision +**Nine selectable feeds** — six live cameras plus three perception debug views — each switched on by hand: + +| Feed | Notes | +|---|---| +| Head front (imx900c) | 2688×1944 JPEG, ~10 Hz | +| Head rear | 2064×1552 JPEG, ~10 Hz, mounted upright | +| Orbbec Gemini 335 colour | Module is mounted **upside down** — rotated 180° by default | +| Orbbec depth | 16-bit millimetre map, ~14 Hz, tops out ~4.2 m | +| Stereo pair (left / right) | Both eyes, JPEG ~10 Hz | +| Perception debug ×3 | Input image, segmentation mask, line colour map | + +Nothing is subscribed on the robot until you switch a feed on, and switching it off **destroys the subscription on the robot** rather than merely hiding the ``. This is not a nicety: a frame is 170–430 KB and the RGB feeds together publish at ~60 Hz, which pushed roughly **15 MB/s through DDS for pictures nobody was looking at** — over the same Wi-Fi the robot uses to walk. + +Frames are polled as single images rather than streamed, so a quiet topic degrades into "nothing is publishing" instead of a hung connection. + +### LiDAR +Live 3D point cloud from the chest sensor. A scan is ~25 500 points (816 KB) at 2 Hz, decimated on the robot to 4 000 points before crossing the network. Off until switched on, like the cameras. + +### Model — the digital twin +The real X2 URDF, posed and shaded by live telemetry. The robot reports all **31 revolute joint positions and efforts at 100 Hz**; this tab draws them across a rigid-body tree of **41 links**. An arm folded in the picture but straight in the room means the encoder, the model, or your idea of which robot you are connected to is wrong. + +Shaded by **effort, not temperature** — this robot publishes no joint temperature at all. `aimdk_msgs/JointState` carries name, position, velocity, effort and error code and nothing else, and across all 53 `aimdk_msgs` types the only temperature fields belong to the PMU and the battery. Effort is honest and nearly as useful: motor heating is I²R and current tracks torque, so the joint pulling hardest is the joint getting hottest. + +Load is shown as a **percentage of each joint's rated torque**, taken from the URDF's `` and baked into `model.json`. That matters — rated torque here runs from 0.6 Nm to 120 Nm, so an absolute Nm ramp would paint every wrist permanently cold and every leg permanently hot regardless of what the robot was doing. + +Geometry is baked offline: **112 MB of vendor STL down to 1.4 MB**. Nothing parses a URDF at runtime. + +### Interaction +Speech (text-to-speech with priority and interrupt), volume and mute, screen expressions/emoji, and the LED strip. Also hosts the voice-session switch that starts and stops the conversation loop. + +### Power +Battery detail — percentage, voltage, current, temperature, cycle count, capacity in mAh, output power — plus **8 power rails** (48 V bus, 48 V output, 12 V output, head power, Orin NX, RK3588, fan rail, 48 V PMOS), fan RPM and thermals, with history charts. + +### Navigation +Odometry, heading and travelled path. **No mapping controls are offered on purpose**: this firmware does not expose the documented SLAM interface (`/integrated_command`, `/relocalization_pose`, `GetStoredMapByName` are all absent from the live graph), and a button that silently does nothing is worse than no button. + +### Extensions +Renders whatever plugins the backend found. Nothing in this tab knows about any specific plugin — see [Extensions](#extensions). + +### Console +Event log, raw ROS access (publish to any topic, call any service) and the discovered ROS graph. + +### Settings +Robot discovery, network, transport and safety limits. This is where the "works on any IP" promise lives: the dashboard never stores a fixed robot address — it discovers one on whatever network you are currently attached to, and reports every address it is itself reachable on. + +Includes a **QR code** of the numeric dashboard URL. Typing an IP into a phone is exactly the friction that makes people want a hostname; a QR sidesteps the naming question entirely, since it needs no mDNS, no multicast and no DNS — it works even on Wi-Fi that isolates clients from each other. + +--- + +## Safety model + +| Guard | Detail | +|---|---| +| **Deadman** | Velocity commands expire after `locomotion_deadman_s` (default 0.5 s). The UI republishes at 20 Hz while a key is held; release it and the robot stops. | +| **Zero-torque confirm** | Entering `PASSIVE_DEFAULT` requires an explicit confirmation dialog (`require_confirm_zero_torque`). These modes collapse a free-standing robot. | +| **Danger flags** | Passive, zero-torque, soft e-stop, run and both stair gaits are flagged in the spec, and the UI renders them as destructive actions. | +| **Mode gating** | Velocity is rejected outside driveable modes; joint commands are rejected outside joint-control modes. | +| **Velocity clamps** | Forward −0.6…0.8 m/s, lateral ±0.7 m/s, angular ±0.8 rad/s — configurable downward in Settings. | +| **Space bar** | Global emergency stop, zeroes velocity immediately. | + +--- + +## Backend modules + +| Module | Lines | Purpose | +|---|---:|---| +| `server.py` | 1062 | FastAPI app — all HTTP routes and the WebSocket | +| `x2_spec.py` | 773 | The interface specification (see below) | +| `bridge_agent.py` | 610 | TCP bridge to the on-robot agent, with auto-reconnect | +| `nic.py` | 592 | Picks the LAN address this machine is *actually* reachable on | +| `bridge_mock.py` | 520 | Physics-lite simulated X2 | +| `announce.py` | 348 | mDNS — advertises the dashboard as `.local` | +| `netinfo.py` | 346 | Address enumeration, subnet derivation, robot discovery sweep | +| `voice_session.py` | 306 | On/off switch for the conversation loop | +| `bridge_base.py` | 241 | The contract every bridge implements | +| `plugin_api.py` | 229 | The extension API | +| `settings.py` | 227 | Runtime config, persisted to `config.json` | +| `registry.py` | 203 | Plugin discovery, loading and hot reload | +| `recovery.py` | 118 | Find the robot and start its agent over SSH | +| `hub.py` | 107 | Fan-out from one bridge to N browsers | +| `__main__.py` | 98 | Entry point — `python -m backend` | + +### `x2_spec.py` — the ground truth + +Every constant in this file was **read back from the robot itself** by introspecting the installed `aimdk_msgs` package and the live ROS 2 graph — not copied from the published documentation. Where the two disagree, the robot wins. Differences found: + +- `McAction` has **18 modes, not 5**. `PASSIVE_DEFAULT` (1) and `ZERO_TORQUE_DEFAULT` (4) are distinct; the docs conflated them. +- `McControlArea` is a **bitmask** (`LEFT_HAND=1`, `RIGHT_HAND=2`, `HEAD=4`, `WAIST=8`) — which is why the docs' "area 3" (both arms) and "area 11" (whole body) work out: 3 = 1|2, 11 = 1|2|8. +- Several documented preset motion IDs (1007, 1010, 1011, 3017, 3024, 3025, 3031) **do not exist** in the firmware enum. +- `PmuState` spells its fan field `fan_pecentage` (sic), and `battery_remaining_capacity` is **mAh, not percent** — the percentage lives in `battery_remaining_capacity_percentage`. + +### `hub.py` — why each browser gets its own queue + +One bridge produces state; N browsers consume it. Each client has a bounded queue, so a slow tab (a backgrounded phone, say) can never stall the telemetry loop for everyone else — it just drops frames. + +### `nic.py` — why address selection is not a connectivity test + +The dashboard publishes `http://:8770`, so picking the wrong address hands someone a link that cannot work. This is genuinely hard: a *disconnected* Ethernet adapter still holding an address will **answer a local HTTP fetch successfully**, because Windows routes traffic to any of its own addresses through loopback, skipping the adapter entirely — and it answers *faster* than the real one. No connect, bind or fetch test can distinguish a reachable address from a dead one; the decision has to come from adapter metadata. The rule used here was chosen by running candidates against 23 synthetic adapter tables (VPNs of three shapes, Hyper-V bridges, mobile hotspot, docked Ethernet, duplicate-IP detection, campus public addressing, renamed adapters). + +### `recovery.py` — why recovery lives on the dashboard host + +The X2 cannot reliably bring its own agent up after a power cycle: + +- `systemd --user` units only run while the user has a login session, and the `agi` account cannot enable lingering (`loginctl enable-linger` is denied, and sudo forbids running as root). +- The cron fallback does not fire either — the robot's clock jumps backwards by several hours shortly after boot (RTC vs NTP), and cron stalls on a backward jump. + +So the dashboard finds the robot wherever DHCP put it and starts the agent over SSH. + +--- + +## The on-robot agent + +`x2_dashboard_agent/x2_agent.py` — ~1 480 lines, runs on PC2 (Jetson Orin). Its only dependency beyond `rclpy` is the standard library. + +**Protocol:** newline-delimited JSON. + +``` +-> {"type":"hello","data":{...}} (agent, on connect) +-> {"type":"state","data":{...}} (agent, ~10 Hz) +<- {"type":"cmd","id":7,"name":"set_mode","args":{}} (client) +-> {"type":"result","id":7,"ok":true,"message":"..."} (agent) +``` + +**Commands:** `set_mode`, `get_mode`, `set_velocity`, `stop`, `preset`, `register_source`, `set_joints`, `set_hand`, `speak`, `set_volume`, `set_mute`, `emoji`, `led`, `camera_frame`, `graph`, `publish_raw`, `ping`, `stream_set`, `stream_list`, `lidar_points`. + +**Flags:** `--host` (default `0.0.0.0`), `--port` (default `8781`), `--hz` (state broadcast rate, default 10). + +Cameras and the LiDAR are **on-demand**: no subscription exists until `stream_set` turns one on. + +--- + +## HTTP API + +All under `/api`. The WebSocket at `/ws` carries the live telemetry stream. + +| Area | Endpoints | +|---|---| +| **State** | `GET /bootstrap` · `/state` · `/series` · `/series/keys` · `/events` · `/topics` · `/health` | +| **Settings** | `GET`/`POST /settings` | +| **Network** | `GET /network` · `POST /network/probe` · `/network/scan` · `/bridge/restart` | +| **Motion** | `GET`/`POST /mode` · `POST /velocity` · `/stop` · `/preset` · `/joints` · `/hand` | +| **Interaction** | `POST /speak` · `/volume` · `/mute` · `/emoji` · `/led` · `GET`/`POST /voice/session` | +| **Arbitration** | `POST /input-source` | +| **Raw ROS** | `POST /raw/publish` · `/raw/service` | +| **Streams** | `GET /streams` · `POST /streams/{key}` · `GET /lidar/points` · `/camera/{key}/frame` | +| **Recovery** | `POST /robot/find` · `/robot/wake` · `GET /robot/status` · `GET /qr` | +| **Plugins** | `GET /plugins` · `POST /plugins/reload` · `POST /plugins/{id}/{control}` | + +Interactive API docs are served at `/api/docs`. + +--- + +## Configuration + +`config.json` sits beside the project root. Every field is editable from the Settings tab while the server is running. + +| Key | Default | Meaning | +|---|---|---| +| `robot_host` | `127.0.0.1` | Agent address | +| `agent_port` | `8781` | Agent TCP port | +| `robot_label` | `AGIBOT X2` | Display name | +| `dashboard_name` | `agibot` | mDNS name → `agibot.local` | +| `advertise_name` | `true` | Publish that name over mDNS | +| `auto_discover` | `true` | Sweep the subnet when the saved address stops answering | +| `auto_start_agent` | `false` | SSH in and start the agent if it is not running | +| `robot_ssh_user` / `_password` / `_port` | `agi` / *(empty)* / `22` | SSH credentials for recovery | +| `agent_start_command` | `ensure_agent.sh` | What to run over SSH | +| `ros_domain_id` | `0` | Shown for reference; used by the agent | +| `rmw_implementation` | `rmw_fastrtps_cpp` | Shown for reference | +| `bridge_mode` | `agent` | `auto` · `agent` · `mock` | +| `host` / `port` | `0.0.0.0` / `8770` | HTTP bind | +| `telemetry_hz` | `10` | State broadcast rate | +| `history_seconds` | `120` | Chart history window | +| `require_confirm_zero_torque` | `true` | Confirm before passive/zero-torque | +| `locomotion_deadman_s` | `0.5` | Velocity command expiry | +| `max_forward_velocity` | `0.8` | m/s | +| `max_lateral_velocity` | `0.7` | m/s | +| `max_angular_velocity` | `0.8` | rad/s | +| `theme` / `accent` | `dark` / `blue` | UI | + +`host` is the only key the browser may not change. + +> **Note:** `robot_ssh_password` ships empty. Fill it in through the Settings tab at runtime rather than committing a value. + +--- + +## Extensions + +Drop a `.py` file into `backend/plugins/` that builds a `Plugin`, and the dashboard grows a new panel for it — no frontend work, no server edits. Each control you declare is rendered by the browser from the manifest, and clicking it calls your handler. + +```python +from backend.plugin_api import Plugin + +plugin = Plugin(id="hello", name="Hello", icon="👋") + +@plugin.action("wave", label="Wave hello") +async def wave(ctx): + await ctx.bridge.play_preset(motion=1002, area=2) + return "Waved" +``` + +Press **Reload** in the Extensions tab to pick up edits without restarting the server. A plugin that fails to import does not take the dashboard down — the error is recorded and shown in the UI next to the plugin that caused it. + +Two worked examples ship in `backend/plugins/`: + +- **`example_greeter.py`** — sequencing several subsystems: one button drives mode, motion, speech, screen and lights together. +- **`example_battery_guard.py`** — a background monitor: watches the PMU battery level, warns once per threshold crossing, and can drop the robot into a safe mode before it browns out mid-stride. Demonstrates `on_tick`, `ctx.push` readouts and charted series. + +`_template.py` is a blank starting point. + +--- + +## Deployment + +Three systemd **user** units, in `systemd_user/`: + +| Unit | Role | +|---|---| +| `x2-dashboard.service` | `Type=oneshot` launcher — runs `run_dashboard.sh`, then returns | +| `x2-dashboard.timer` | Watchdog — fires 30 s after boot, then every wall-clock minute | +| `x2-dashboard-agent.service` | The ROS bridge alone | + +```bash +cp systemd_user/*.service systemd_user/*.timer ~/.config/systemd/user/ +systemctl --user daemon-reload +systemctl --user enable --now x2-dashboard.timer +``` + +Two non-obvious details are load-bearing: + +- **`Type=oneshot` *without* `RemainAfterExit`.** The unit must return to `inactive` after each run, or the timer never re-triggers. +- **`OnCalendar=*:*:00`, not `OnUnitActiveSec`.** The launcher `setsid`s its children into their own sessions so they outlive the one-shot; an activity-relative timer would compute `NextElapse=infinity`. `KillMode=none` stops systemd reaping those children when the unit deactivates. + +`run_dashboard.sh` is idempotent by design — it starts only what is not already running, so it is safe from the timer, from `@reboot`, and by hand. It guards on `/proc` rather than trusting `pgrep -f` alone, because `pgrep -f` also matches any shell whose command line merely mentions the pattern; that bug launched a second backend on top of the first during the ~10 s before the port binds. It also trims its own logs at 2 MB. + +--- + +## Repository layout + +``` +X2_dashboard/ +├── x2_dashboard/ the dashboard server + web UI +│ ├── backend/ +│ │ ├── server.py FastAPI app, all routes, WebSocket +│ │ ├── x2_spec.py interface spec, read off the real robot +│ │ ├── bridge_base.py the bridge contract +│ │ ├── bridge_agent.py TCP bridge to the on-robot agent +│ │ ├── bridge_mock.py simulated X2 +│ │ ├── hub.py fan-out to N browsers +│ │ ├── registry.py plugin discovery + hot reload +│ │ ├── plugin_api.py the extension API +│ │ ├── settings.py config load/save +│ │ ├── announce.py mDNS +│ │ ├── netinfo.py discovery + addressing +│ │ ├── nic.py reachable-address selection +│ │ ├── recovery.py find + wake the robot over SSH +│ │ ├── voice_session.py conversation-loop control +│ │ └── plugins/ drop-in extensions +│ ├── web/ +│ │ ├── index.html +│ │ ├── css/app.css design tokens, layout, components +│ │ ├── js/ +│ │ │ ├── core.js store, transport, notifications +│ │ │ ├── main.js shell, rail, routing, shortcuts +│ │ │ ├── ui.js DOM builders +│ │ │ ├── charts.js SVG charts +│ │ │ ├── model3d.js WebGL URDF renderer +│ │ │ └── tabs/ the 13 pages +│ │ └── model/ quantised URDF geometry (1.4 MB) +│ └── config.json +├── x2_dashboard_agent/ runs ON the robot +│ ├── x2_agent.py ROS 2 ⇄ TCP bridge +│ ├── run_agent.sh sources ROS 2 + AimDK + DDS profile +│ ├── run_dashboard.sh idempotent launcher for both +│ ├── ensure_agent.sh called over SSH by recovery +│ └── x2-dashboard-agent.service +└── systemd_user/ unit files +``` + +--- + +## Design notes + +**No framework, no CDN, no build step.** The frontend is plain ES modules and hand-written DOM. The robot has no internet access, and the dashboard is often loaded over the robot's own Wi-Fi — the same link it uses to walk. A framework would cost more than it saves at this size. + +That constraint also explains two hand-rolled renderers: + +- **`charts.js`** — SVG charts. 2 px lines with round joins, area washes at 10 % opacity, ≥8 px end markers with a 2 px surface ring, hairline gridlines, endpoint-only direct labels, a legend from two series up, and a crosshair tooltip on hover. Text always wears text tokens, never the series colour. +- **`model3d.js`** — one shader, flat shading, a rigid-body tree of 41 links. Geometry arrives as **uint16 positions quantised inside each mesh's bounding box** and the shader expands them back to metres, so the 4× saving over float32 costs two extra instructions per vertex. Normals are computed per-face in the fragment shader from screen-space derivatives, so the vertex buffer carries positions and nothing else. + +**Nothing assumes a fixed IP.** Every URL in the frontend is derived from `window.location`, so opening the page from a laptop, a phone, a tablet or a hostname all work with no configuration. The server binds `0.0.0.0` and enumerates its own addresses. + +**The Fast DDS profile is not optional.** A camera frame is 170–430 KB and a LiDAR scan is 816 KB. Fast DDS defaults to a 512 KB shared-memory segment and small socket buffers, and it **drops samples that large in complete silence** — discovery succeeds, the reader matches the writer, `ros2 topic info` reports a publisher, and not one message is ever delivered. The vendor profile raises the segment to 32 MB and UDP buffers to 10 MB. An earlier revision of `x2_spec.py` concluded this unit had one camera and no chest LiDAR; it has six camera feeds and a LiDAR, and the agent simply could not receive them. + +**mDNS is implemented on the stdlib, not `zeroconf`.** The advertised name is additive and reversible — the host keeps its own identity, and the extra name exists only while the dashboard is running, so it needs neither administrator rights nor a reboot. + +--- + +## What is not in this copy + +Two things were deliberately excluded when this snapshot was taken from the robot: + +- **The Sanad API service** (`sanad_api_x2`) — it carries live credentials in a `.env`, so it is not published here. +- **Teach mode / Manual Recorder** — the record-an-arm-motion-by-hand feature and its `/api/recorder/*` routes were removed from this copy. The dashboard runs without it; the feature still exists on the robot. + +No API keys or credentials are present in this repository. The Gemini and LinkSoul credentials the voice session depends on are read at runtime from `~/.sanad_agibot_env` on the robot and are never embedded in this code. diff --git a/systemd_user/x2-dashboard-agent.service b/systemd_user/x2-dashboard-agent.service new file mode 100644 index 0000000..8a70351 --- /dev/null +++ b/systemd_user/x2-dashboard-agent.service @@ -0,0 +1,28 @@ +[Unit] +Description=AGIBOT X2 dashboard agent (ROS 2 to TCP bridge) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +WorkingDirectory=/home/agi/x2_dashboard_agent +ExecStart=/home/agi/x2_dashboard_agent/run_agent.sh +Restart=always +RestartSec=5 +TimeoutStopSec=15 +KillMode=mixed +# The robot's own stack takes a while to come up after power-on; the agent +# tolerates an empty graph and fills in as topics appear, so starting early is +# fine and means the dashboard attaches as soon as possible. +StandardOutput=journal +StandardError=journal +# Fast DDS writes a very high volume of discovery chatter (to stdout, alongside +# the agent's own messages, so it cannot simply be dropped). Rate-limiting keeps +# the journal from being swamped while still letting the agent's lines through. +LogRateLimitIntervalSec=30s +LogRateLimitBurst=300 +Environment=RCUTILS_LOGGING_SEVERITY=ERROR +Environment=ROS_DOMAIN_ID=0 + +[Install] +WantedBy=default.target diff --git a/systemd_user/x2-dashboard.service b/systemd_user/x2-dashboard.service new file mode 100644 index 0000000..f92076a --- /dev/null +++ b/systemd_user/x2-dashboard.service @@ -0,0 +1,27 @@ +[Unit] +Description=AGIBOT X2 web dashboard (serves http://:8770) +After=network-online.target +Wants=network-online.target + +[Service] +# A one-shot launcher: run_dashboard.sh starts the ROS bridge and the web +# dashboard if they are not already up, then returns. It is idempotent, so the +# timer below re-runs it every minute as a crash-and-restart watchdog. +# +# Type=oneshot WITHOUT RemainAfterExit: the unit goes back to "inactive" after +# each run, which is what lets the timer's OnUnitActiveSec fire again. With +# RemainAfterExit=yes the unit stays "active" forever and the timer never +# re-triggers (NextElapse=infinity). +Type=oneshot +WorkingDirectory=/home/agi/x2_dashboard +ExecStart=/home/agi/x2_dashboard_agent/run_dashboard.sh +TimeoutStartSec=120 +# The launcher setsid's the agent and dashboard into their own sessions so they +# outlive this one-shot. KillMode=none stops systemd from reaping them when the +# unit deactivates, and lets the unit return to "inactive" cleanly - which is +# what re-arms the watchdog timer (OnUnitActiveSec). Without this the cgroup +# stays populated, the unit stays "active" forever, and NextElapse=infinity. +KillMode=none + +[Install] +WantedBy=default.target diff --git a/systemd_user/x2-dashboard.timer b/systemd_user/x2-dashboard.timer new file mode 100644 index 0000000..aa108e7 --- /dev/null +++ b/systemd_user/x2-dashboard.timer @@ -0,0 +1,19 @@ +[Unit] +Description=Keep the AGIBOT X2 dashboard and agent running + +[Timer] +# A watchdog: run the idempotent launcher shortly after boot, then on every +# wall-clock minute. This is the crash-and-restart safety net, and it means +# neither the dashboard nor the ROS bridge depends on any external machine. +# +# OnCalendar (not OnUnitActiveSec) on purpose: the launcher is Type=oneshot and +# its background processes keep the unit reading "active", so an activity-relative +# timer never re-arms (NextElapse=infinity). A wall-clock schedule fires +# regardless of the service's state. +OnBootSec=30s +OnCalendar=*:*:00 +Persistent=true +AccuracySec=5s + +[Install] +WantedBy=timers.target diff --git a/x2_dashboard/backend/__init__.py b/x2_dashboard/backend/__init__.py new file mode 100644 index 0000000..dfc399f --- /dev/null +++ b/x2_dashboard/backend/__init__.py @@ -0,0 +1,3 @@ +"""AGIBOT X2 dashboard backend.""" + +__version__ = "1.0.0" diff --git a/x2_dashboard/backend/__main__.py b/x2_dashboard/backend/__main__.py new file mode 100644 index 0000000..3451108 --- /dev/null +++ b/x2_dashboard/backend/__main__.py @@ -0,0 +1,98 @@ +""" +Entry point: ``python -m backend`` + +Binds 0.0.0.0 and prints every address the dashboard is reachable on, so you can +open it from a phone or tablet on the same Wi-Fi without knowing this machine's +IP in advance. +""" + +from __future__ import annotations + +import argparse +import sys + +from . import netinfo, settings + + +def main() -> int: + parser = argparse.ArgumentParser(prog="python -m backend", + description="AGIBOT X2 dashboard server") + parser.add_argument("--port", type=int, help="HTTP port (default from config.json)") + parser.add_argument("--host", default=None, help="Bind address (default 0.0.0.0 - all interfaces)") + parser.add_argument("--robot", default=None, help="Robot host or IP; saved to config.json") + parser.add_argument("--domain", type=int, default=None, help="ROS_DOMAIN_ID") + parser.add_argument("--mode", choices=["auto", "ros2", "mock"], default=None, + help="Bridge mode: auto (default), ros2 (require rclpy), mock (simulate)") + parser.add_argument("--reload", action="store_true", help="Auto-reload on source changes") + args = parser.parse_args() + + updates = {} + if args.port is not None: + updates["port"] = args.port + if args.robot is not None: + updates["robot_host"] = args.robot + if args.domain is not None: + updates["ros_domain_id"] = args.domain + if args.mode is not None: + updates["bridge_mode"] = args.mode + if updates: + settings.save(updates) + + config = settings.load() + host = args.host or config["host"] + port = config["port"] + + try: + import uvicorn + except ImportError: + print("uvicorn is not installed. Run: pip install -r requirements.txt", file=sys.stderr) + return 1 + + name = config.get("dashboard_name") if config.get("advertise_name") else None + detail = netinfo.address_detail() + + print() + print(" AGIBOT X2 Dashboard") + print(" " + "-" * 52) + if detail["ip"]: + print(" Open this from a phone, tablet or laptop:") + print(f" http://{detail['ip']}:{port}") + print(f" (live {detail['kind'] or 'network'} address on '{detail['adapter']}')") + else: + print(" No usable network address right now:") + print(f" {detail['reason_text'] or detail['reason']}") + print(" The dashboard is still running; it will pick the address up") + print(" automatically when the network comes back.") + + others = [u for u in netinfo.dashboard_urls(port, name) + if u != f"http://{detail['ip']}:{port}"] + if others: + print() + print(" Also reachable at:") + for url in others: + print(f" {url}") + print(" " + "-" * 52) + print(f" robot host {config['robot_host'] or '(not set - use the Settings tab)'}") + print(f" bridge mode {config['bridge_mode']}") + print(f" ROS_DOMAIN_ID {config['ros_domain_id']}") + print(" Open any address above from any device on this network.") + print(flush=True) + + uvicorn.run( + "backend.server:app", + host=host, + port=port, + reload=args.reload, + log_level="info", + access_log=False, + # websockets 16.x crashes uvicorn's default WS impl (starlette/anyio + # "cancel scope" error) -> stuck "Connecting". wsproto is a stable, + # isolated WS engine that avoids it without touching the shared + # `websockets` package the voice pipeline depends on. + ws="wsproto", + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/x2_dashboard/backend/announce.py b/x2_dashboard/backend/announce.py new file mode 100644 index 0000000..e17055f --- /dev/null +++ b/x2_dashboard/backend/announce.py @@ -0,0 +1,348 @@ +""" +Advertise the dashboard on the LAN under its own name, e.g. `agibot.local`. + +Why this exists +--------------- +The link people type should be about the robot, not about whatever the PC +happens to be called. Renaming the computer would do it, but that needs +administrator rights and a reboot and changes the machine's identity for +everything else. Publishing an extra name over mDNS is additive, reversible and +needs neither: the computer keeps its own name, and the advertised name exists +only while the dashboard is running. + +Why stdlib and not the `zeroconf` package +----------------------------------------- +Two measured constraints on this machine, either of which would have made a +separate helper process silently useless: + + * Windows' Public firewall profile is BlockInbound and every inbound rule for + UDP 5353 is *program*-scoped, not port-scoped. The built-in "mDNS (UDP-In)" + rule is scoped to svchost.exe/dnscache and grants a Python process nothing. + The only interpreter with a blanket inbound allow is the base Python that + already serves the dashboard - so the responder has to live *inside* that + process to be reachable from another device. + * A same-host HTTP fetch to the PC's own LAN address is routed via loopback + and skips inbound firewall filtering entirely, so a helper running under the + wrong interpreter passes every local test while remaining invisible to a + phone. Running in-process removes that whole failure mode. + +Being stdlib-only also means no extra dependency to install in the interpreter +that matters. + +Scope +----- +Only the `.local` form is published. A bare single-label `http://agibot:` +appears to work on Windows because Windows appends `.local` to single-label +names, but it is unreliable (its negative DNS cache can poison the name for +minutes) and no iPhone, Android, Mac or Linux client resolves it. Publishing it +would be advertising something that only works on one machine. +""" + +from __future__ import annotations + +import logging +import socket +import struct +import threading +import time + +log = logging.getLogger("x2.announce") + +MDNS_ADDR = "224.0.0.251" +MDNS_PORT = 5353 +TTL = 120 # seconds a client may cache the record +QTYPE_A = 1 +QTYPE_ANY = 255 +CLASS_IN = 1 +CACHE_FLUSH = 0x8000 # tells clients this is the authoritative answer +UNICAST_RESPONSE = 0x8000 # the "QU" bit on a question's class + + +def _encode_name(name: str) -> bytes: + out = bytearray() + for label in name.rstrip(".").split("."): + raw = label.encode("utf-8") + out.append(len(raw)) + out += raw + out.append(0) + return bytes(out) + + +def _decode_name(data: bytes, offset: int) -> tuple[str, int]: + """Read a DNS name, following compression pointers. Returns (name, next_offset).""" + labels: list[str] = [] + jumped = False + end = offset + hops = 0 + + while True: + if offset >= len(data) or hops > 20: + break + length = data[offset] + + if length & 0xC0 == 0xC0: # compression pointer + if offset + 1 >= len(data): + break + pointer = struct.unpack_from("!H", data, offset)[0] & 0x3FFF + if not jumped: + end = offset + 2 + offset = pointer + jumped = True + hops += 1 + continue + + offset += 1 + if length == 0: + if not jumped: + end = offset + break + labels.append(data[offset:offset + length].decode("utf-8", "replace")) + offset += length + + return ".".join(labels), end + + +def _build_response(name: str, ip: str) -> bytes: + header = struct.pack( + "!HHHHHH", + 0, # ID - always 0 in mDNS + 0x8400, # QR=1 (response), AA=1 (authoritative) + 0, # no questions echoed + 1, # one answer + 0, 0, + ) + answer = ( + _encode_name(name) + + struct.pack("!HHIH", QTYPE_A, CLASS_IN | CACHE_FLUSH, TTL, 4) + + socket.inet_aton(ip) + ) + return header + answer + + +def _build_query(name: str) -> bytes: + header = struct.pack("!HHHHHH", 0, 0x0000, 1, 0, 0, 0) + return header + _encode_name(name) + struct.pack("!HH", QTYPE_A, CLASS_IN) + + +class Announcer: + """Answers mDNS A queries for one name, for as long as it runs.""" + + def __init__(self, name: str, port: int, address_provider): + self.name = f"{name.strip().strip('.').lower()}.local" + self.port = port + self._address_of = address_provider + self._sock: socket.socket | None = None + self._thread: threading.Thread | None = None + self._stop = threading.Event() + self.ip: str | None = None + self.answered = 0 + self.error = "" + self.conflict = False + + # -- lifecycle ---------------------------------------------------------- + + def start(self) -> bool: + self.ip = self._address_of() + if not self.ip: + self.error = "No LAN address to advertise" + log.warning("mDNS: %s", self.error) + return False + + try: + self._sock = self._open_socket() + except OSError as exc: + self.error = f"Could not open UDP {MDNS_PORT}: {exc}" + log.warning("mDNS: %s", self.error) + return False + + # RFC 6762 probing: if something else already owns the name, do not + # fight it - two hosts answering for one name gives whichever reply + # arrives first, which is worse than not advertising at all. + if self._name_taken(): + self.conflict = True + self.error = f"{self.name} is already claimed by another device on this network" + log.warning("mDNS: %s", self.error) + self._close() + return False + + self._stop.clear() + self._thread = threading.Thread(target=self._serve, name="mdns-announce", daemon=True) + self._thread.start() + log.info("mDNS: advertising %s -> %s:%s", self.name, self.ip, self.port) + return True + + def stop(self) -> None: + self._stop.set() + self._close() + if self._thread: + self._thread.join(timeout=3.0) + self._thread = None + + def _close(self) -> None: + if self._sock is not None: + try: + self._sock.close() + except OSError: + pass + self._sock = None + + # -- socket ------------------------------------------------------------- + + def _open_socket(self) -> socket.socket: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + # Several responders normally share 5353 (Windows' own, Bonjour, and + # anything Chrome is doing); SO_REUSEPORT where available lets us join + # them rather than fail. + if hasattr(socket, "SO_REUSEPORT"): + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + except OSError: + pass + sock.bind(("", MDNS_PORT)) + + membership = socket.inet_aton(MDNS_ADDR) + socket.inet_aton(self.ip) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, membership) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.ip)) + sock.settimeout(1.0) + return sock + + def _name_taken(self) -> bool: + """Ask whether anyone else already answers for our name.""" + probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + probe.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + probe.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) + probe.settimeout(0.4) + probe.sendto(_build_query(self.name), (MDNS_ADDR, MDNS_PORT)) + + deadline = time.time() + 0.9 + while time.time() < deadline: + try: + data, addr = probe.recvfrom(4096) + except socket.timeout: + continue + except OSError: + break + if addr[0] == self.ip: + continue # our own machine, ignore + if self._is_answer_for_us(data): + log.warning("mDNS: %s already answered by %s", self.name, addr[0]) + return True + except OSError: + pass + finally: + probe.close() + return False + + def _is_answer_for_us(self, data: bytes) -> bool: + try: + _, flags, qd, an, _, _ = struct.unpack_from("!HHHHHH", data, 0) + except struct.error: + return False + if not (flags & 0x8000) or an == 0: + return False + + offset = 12 + for _ in range(qd): + _, offset = _decode_name(data, offset) + offset += 4 + for _ in range(an): + name, offset = _decode_name(data, offset) + try: + rtype, _, _, rdlen = struct.unpack_from("!HHIH", data, offset) + except struct.error: + return False + offset += 10 + rdlen + if rtype == QTYPE_A and name.lower() == self.name: + return True + return False + + # -- serving ------------------------------------------------------------ + + def _serve(self) -> None: + last_ip_check = time.time() + + while not self._stop.is_set(): + sock = self._sock + if sock is None: + return + try: + data, addr = sock.recvfrom(4096) + except socket.timeout: + data = None + except OSError: + if not self._stop.is_set(): + log.debug("mDNS: socket closed") + return + + # DHCP leases change; an advertiser pinned to a stale address will + # confidently point the name at nothing. + if time.time() - last_ip_check > 30: + last_ip_check = time.time() + current = self._address_of() + if current and current != self.ip: + log.info("mDNS: address changed %s -> %s, re-advertising", self.ip, current) + self.ip = current + + if not data: + continue + + try: + self._handle(data, addr) + except Exception as exc: # never let one packet stop us + log.debug("mDNS: bad packet from %s: %s", addr, exc) + + def _handle(self, data: bytes, addr) -> None: + try: + _, flags, qdcount, _, _, _ = struct.unpack_from("!HHHHHH", data, 0) + except struct.error: + return + if flags & 0x8000 or qdcount == 0: # a response, not a question + return + + offset = 12 + for _ in range(qdcount): + name, offset = _decode_name(data, offset) + try: + qtype, qclass = struct.unpack_from("!HH", data, offset) + except struct.error: + return + offset += 4 + + if name.lower() != self.name: + continue + if qtype not in (QTYPE_A, QTYPE_ANY): + continue + + response = _build_response(self.name, self.ip) + wants_unicast = bool(qclass & UNICAST_RESPONSE) + sock = self._sock + if sock is None: + return + try: + if wants_unicast: + sock.sendto(response, addr) + else: + # Multicast so every listener refreshes its cache, and + # unicast too because some stacks only accept the direct + # reply. + sock.sendto(response, (MDNS_ADDR, MDNS_PORT)) + sock.sendto(response, addr) + self.answered += 1 + except OSError: + pass + + # -- introspection ------------------------------------------------------ + + def status(self) -> dict: + return { + "name": self.name, + "url": f"http://{self.name}:{self.port}", + "ip": self.ip, + "running": bool(self._thread and self._thread.is_alive()), + "answered": self.answered, + "conflict": self.conflict, + "error": self.error, + } diff --git a/x2_dashboard/backend/bridge_agent.py b/x2_dashboard/backend/bridge_agent.py new file mode 100644 index 0000000..40a7e2d --- /dev/null +++ b/x2_dashboard/backend/bridge_agent.py @@ -0,0 +1,610 @@ +""" +Bridge to the on-robot agent (agent/x2_agent.py) over plain TCP. + +This is the bridge that drives a real X2. The dashboard server itself never +imports rclpy - it talks JSON-lines to the agent running on PC2. That keeps the +dashboard usable on any machine (including Windows) and, more importantly, keeps +the web UI up when the robot is powered off so it can say so instead of dying. + +Reconnection is automatic and continuous: switch the robot off and the UI shows +the offline gate; switch it on and the dashboard reattaches on its own. +""" + +from __future__ import annotations + +import asyncio +import base64 +import contextlib +import json +import time + +from . import netinfo, recovery, settings, x2_spec +from .bridge_base import Bridge, CommandResult + +RECONNECT_MIN = 1.0 +RECONNECT_MAX = 6.0 +COMMAND_TIMEOUT = 12.0 + +# asyncio's StreamReader defaults to a 64 KiB limit per line, and readline() +# raises once a line exceeds it. Camera frames arrive base64-encoded at roughly +# 400 KB and a full ROS graph dump is over 100 KB, so the default silently tore +# the link down mid-command. 32 MiB leaves generous headroom. +STREAM_LIMIT = 32 * 1024 * 1024 + + +class AgentBridge(Bridge): + name = "agent" + simulated = False + + def __init__(self, hub, config: dict): + super().__init__(hub, config) + self._reader = None + self._writer = None + self._task: asyncio.Task | None = None + self._push_task: asyncio.Task | None = None + self._pending: dict[int, asyncio.Future] = {} + self._next_id = 1 + self._connected = asyncio.Event() + self._closing = False + self._agent_info: dict = {} + # key -> (ts, bytes, content_type, flip_used) + self._frames: dict[str, tuple[float, bytes, str, bool | None]] = {} + self._attempts = 0 + self._last_error = "" + self._recovering = False + + # -- lifecycle ---------------------------------------------------------- + + @property + def host(self) -> str: + return (self.config.get("robot_host") or "").strip() + + @property + def port(self) -> int: + return int(self.config.get("agent_port") or x2_spec.AGENT_PORT) + + async def start(self) -> None: + if not self.host and not self.config.get("auto_discover"): + raise RuntimeError( + "No robot host configured. Set it in the Settings tab, run the " + "server with --robot , or enable auto-discovery." + ) + self._closing = False + self.state.connection.transport = "agent" + self.state.connection.host = f"{self.host}:{self.port}" + self.state.connection.simulated = False + self.state.connection.online = False + + self._task = asyncio.create_task(self._link_loop(), name="agent-link") + self._push_task = asyncio.create_task(self._push_loop(), name="agent-push") + + # Give the first connection a moment so the UI opens attached rather + # than flashing the offline gate, but never block startup on it. + with contextlib.suppress(asyncio.TimeoutError): + await asyncio.wait_for(self._connected.wait(), timeout=4.0) + + async def stop(self) -> None: + self._closing = True + for task in (self._task, self._push_task): + if task: + task.cancel() + with contextlib.suppress(asyncio.CancelledError, Exception): + await task + await self._drop_link() + self.state.connection.online = False + self.state.connection.transport = "none" + + async def reconfigure(self, config: dict) -> None: + """ + Adopt new settings, and re-dial immediately if the address changed. + + Without the re-dial an operator who corrects the robot address sees + nothing happen until they restart the bridge by hand, because the link + loop only reads the address when it next reconnects - and a healthy + connection never reconnects. + """ + before = (self.host, self.port) + self.config = config + after = ((config.get("robot_host") or "").strip(), + int(config.get("agent_port") or x2_spec.AGENT_PORT)) + + if before != after and self._writer is not None: + await self.hub.emit("info", "robot", + f"Robot address changed to {after[0]}:{after[1]} - reconnecting") + self._attempts = 0 + # Dropping the socket makes _connect_once return; the link loop then + # dials the new address on its next pass. + await self._drop_link() + + # -- link --------------------------------------------------------------- + + async def _link_loop(self) -> None: + while not self._closing: + try: + await self._connect_once() + except asyncio.CancelledError: + raise + except Exception as exc: + self._last_error = str(exc) + finally: + await self._drop_link() + + if self._closing: + return + + if self.state.connection.online: + # We were up and lost it - that is worth saying out loud. + self.state.connection.online = False + self.state.connection.error = self._last_error or "link lost" + await self.hub.emit("warn", "robot", + f"Lost connection to the robot ({self._last_error or 'link closed'})") + + self._attempts += 1 + + # After a few plain retries, try harder: the robot may have come + # back on a different address, or be up with the agent not running. + if self._attempts % 4 == 0: + await self._attempt_recovery() + + delay = min(RECONNECT_MAX, RECONNECT_MIN * (1.35 ** min(self._attempts, 8))) + await asyncio.sleep(delay) + + async def _attempt_recovery(self) -> None: + """ + Try to get the robot back without the operator doing anything. + + Two failure modes are handled, in order of likelihood after a power + cycle: the agent is not running (robot answers SSH but not the agent + port), and the robot moved to a different DHCP address. + """ + if self._recovering: + return + self._recovering = True + try: + config = settings.load() + port = int(config.get("agent_port") or x2_spec.AGENT_PORT) + host = self.host + + # 1. Is the robot there at all, just without the agent running? + if host and config.get("auto_start_agent"): + info = await netinfo.probe_host( + host, ports=[port, int(config.get("robot_ssh_port") or 22)], timeout=1.5) + open_ports = info.get("open_ports") or [] + if port in open_ports: + return # agent is up; the next retry will land + if 22 in open_ports: + await self._start_agent_on(host, config, port) + return + + # 2. Otherwise look for it somewhere else on this network. + if not config.get("auto_discover"): + return + + self._set_recovery("Looking for the robot on this network…") + await self.hub.emit("info", "robot", + "Robot not answering - scanning the network for it") + candidates = await recovery.find_robot(port, int(config.get("robot_ssh_port") or 22)) + candidates = [c for c in candidates if c["host"] != host] + + running = next((c for c in candidates if c["agent"]), None) + if running: + await self._adopt(running["host"], "found the agent running there") + return + + if config.get("auto_start_agent"): + for candidate in candidates: + if not candidate["ssh"]: + continue + if await self._start_agent_on(candidate["host"], config, port, adopt=True): + return + + self._set_recovery("") + except asyncio.CancelledError: + raise + except Exception as exc: + self._set_recovery("") + await self.hub.emit("warn", "robot", f"Recovery attempt failed: {exc}") + finally: + self._recovering = False + + async def _start_agent_on(self, host: str, config: dict, port: int, + adopt: bool = False) -> bool: + self._set_recovery(f"Robot is on at {host} but the agent is not running — starting it…") + await self.hub.emit("info", "robot", + f"{host} is reachable but the agent is down - starting it over SSH") + + ok, message = await recovery.start_agent(host, config) + if not ok: + self._set_recovery(message) + await self.hub.emit("warn", "robot", message) + return False + + if await recovery.wait_for_agent(host, port, timeout=45.0): + self._set_recovery("") + if adopt: + await self._adopt(host, "started the agent there") + else: + await self.hub.emit("info", "robot", "Agent started - reconnecting") + return True + + self._set_recovery("Started the agent, but it has not come up yet…") + return False + + async def _adopt(self, host: str, why: str) -> None: + """Switch to a newly found address and remember it.""" + settings.save({"robot_host": host}) + self.config = settings.load() + self.state.connection.host = f"{host}:{self.port}" + self._attempts = 0 + self._set_recovery("") + await self.hub.emit("info", "robot", f"Robot found at {host} - {why}") + await self.hub.broadcast("settings", settings.describe()) + + def _set_recovery(self, message: str) -> None: + """Progress text for the offline gate, so the operator sees us working.""" + self.state.custom["recovery"] = message + if message: + self.state.connection.error = message + + async def _connect_once(self) -> None: + host, port = self.host, self.port + if not host: + # Nothing to dial yet - let the recovery pass find one. + self.state.connection.error = "Looking for the robot on this network…" + raise ConnectionError("no robot address yet") + try: + self._reader, self._writer = await asyncio.wait_for( + asyncio.open_connection(host, port, limit=STREAM_LIMIT), timeout=5.0) + except (asyncio.TimeoutError, OSError) as exc: + self._last_error = f"{host}:{port} unreachable" + self.state.connection.error = ( + f"Cannot reach the robot agent at {host}:{port}. " + "Is the robot powered on and on this network?" + ) + raise ConnectionError(self._last_error) from exc + + was_offline = not self.state.connection.online + self._attempts = 0 + self._last_error = "" + self.state.connection.online = True + self.state.connection.since = time.time() + self.state.connection.error = "" + self._connected.set() + + if was_offline: + await self.hub.emit("info", "robot", f"Connected to robot agent at {host}:{port}") + + # Re-assert anything that does not survive a reconnect. + self.state.source_registered = False + asyncio.create_task(self._announce_self()) + + while not self._closing: + line = await self._reader.readline() + if not line: + raise ConnectionError("agent closed the connection") + try: + message = json.loads(line) + except json.JSONDecodeError: + continue + self._on_message(message) + + async def _announce_self(self) -> None: + """ + Tell the robot this dashboard exists as a control source. + + The motion controller ignores velocity from a source it has never heard + of, so this has to happen before the joystick will do anything. It is + not a takeover: registering only makes the dashboard *eligible*, and + arbitration still hands control to the highest-priority source that is + actively sending - the handheld RC (80) and mobile app (60) both + outrank us at 30. + + Done automatically rather than left to a button, because there is no + situation where an operator wants the dashboard connected but not + allowed to drive, and "register input source" means nothing to someone + who just wants to move the robot. + """ + source = x2_spec.DASHBOARD_INPUT_SOURCE + for attempt in range(3): + await asyncio.sleep(1.0 if attempt == 0 else 3.0) + if not self.state.connection.online: + return + result = await self.register_input_source( + source["name"], source["priority"], source["timeout"]) + if result.ok: + return + if attempt == 2: + await self.hub.emit( + "warn", "control", + f"Could not announce the dashboard to the robot: {result.message}. " + "Driving will be refused until this succeeds - use the Control tab to retry.", + ) + + async def _drop_link(self) -> None: + self._connected.clear() + writer, self._writer, self._reader = self._writer, None, None + if writer is not None: + with contextlib.suppress(Exception): + writer.close() + await writer.wait_closed() + for future in self._pending.values(): + if not future.done(): + future.set_exception(ConnectionError("link dropped")) + self._pending.clear() + + def _on_message(self, message: dict) -> None: + kind = message.get("type") + if kind == "state": + self._apply_state(message.get("data") or {}) + elif kind == "hello": + self._agent_info = message.get("data") or {} + self.state.custom["agent"] = self._agent_info + # Report the domain the agent is actually on, rather than whatever + # this machine has configured - only the agent's value is real. + try: + self.state.connection.ros_domain_id = int( + self._agent_info.get("ros_domain_id", 0)) + except (TypeError, ValueError): + pass + elif kind == "result": + future = self._pending.pop(message.get("id"), None) + if future and not future.done(): + future.set_result(message) + + # -- state mapping ------------------------------------------------------ + + def _apply_state(self, data: dict) -> None: + s = self.state + + s.mode = data.get("mode") or "UNKNOWN" + spec = x2_spec.MC_MODE_BY_ID.get(s.mode) + s.mode_desc = spec["label"] if spec else s.mode + status = data.get("mode_status") + s.mode_status = x2_spec.MC_ACTION_STATUS.get(status, str(status or "")) + + for field in ("battery_pct", "battery_voltage", "battery_current", + "battery_temp", "battery_cycles", "pmu_temp", + "fan_rpm", "fan_pct"): + setattr(s, field, data.get(field)) + s.charging = bool(data.get("charging")) + + rails = {} + for spec_rail in x2_spec.PMU_RAILS: + live = (data.get("rails") or {}).get(spec_rail["key"]) + if not live: + continue + rails[spec_rail["key"]] = { + "label": spec_rail["label"], + "nominal": spec_rail["nominal"], + "voltage": live.get("voltage"), + "current": live.get("current"), + "ok": live.get("ok", True), + } + s.rails = rails + + s.imu = data.get("imu") or {} + s.joints = data.get("joints") or {} + s.hand_type = data.get("hand_type") or "None" + s.hand_state = data.get("hand_state") or {} + s.touch_head = data.get("touch_head") or {} + s.velocity = data.get("velocity") or s.velocity + s.velocity_command = data.get("velocity_command") or s.velocity_command + s.odom = data.get("odom") or s.odom + s.volume = data.get("volume") if data.get("volume") is not None else s.volume + s.muted = bool(data.get("muted")) + s.emoji_id = data.get("emoji_id") + s.led = data.get("led") or s.led + s.input_source = data.get("input_source") or "" + s.topic_stats = data.get("topic_stats") or {} + + s.custom["pmu_raw"] = data.get("pmu_raw") or {} + s.custom["pmu_info"] = data.get("pmu_info") or {} + s.custom["cameras"] = data.get("cameras") or {} + # Which feeds are actually subscribed on the robot right now. The + # Vision tab reads this rather than tracking its own idea of on/off, + # so a second browser sees the true state instead of "off". + s.custom["streams"] = data.get("streams") or {} + s.custom["face_status"] = data.get("face_status") + s.custom["battery_capacity_mah"] = data.get("battery_capacity_mah") + s.custom["battery_power"] = data.get("battery_power") + s.custom["agent_version"] = data.get("agent_version") + s.custom["hand_left_type"] = data.get("hand_left_type") + s.custom["hand_right_type"] = data.get("hand_right_type") + + s.updated = time.time() + + async def _push_loop(self) -> None: + """Forward state to browsers and record chart series.""" + hz = max(1, int(self.config.get("telemetry_hz", 10))) + while True: + try: + await asyncio.sleep(1.0 / hz) + now = time.time() + if self.state.connection.online: + self._record(now) + await self.hub.broadcast("state", self.state.as_dict()) + except asyncio.CancelledError: + raise + except Exception: + await asyncio.sleep(1.0) + + def _record(self, now: float) -> None: + for key, value in ( + ("battery_pct", self.state.battery_pct), + ("battery_voltage", self.state.battery_voltage), + ("battery_current", self.state.battery_current), + ("battery_temp", self.state.battery_temp), + ("pmu_temp", self.state.pmu_temp), + ("fan_pct", self.state.fan_pct), + ("vel_forward", self.state.velocity.get("forward")), + ("vel_lateral", self.state.velocity.get("lateral")), + ("vel_angular", self.state.velocity.get("angular")), + ): + if value is not None: + self.hub.record(key, value, now) + chest = self.state.imu.get("chest") or {} + for key, field in (("imu_roll", "roll"), ("imu_pitch", "pitch"), ("imu_yaw", "yaw")): + if field in chest: + self.hub.record(key, chest[field], now) + + # -- command plumbing --------------------------------------------------- + + async def _send(self, name: str, args: dict | None = None, + timeout: float = COMMAND_TIMEOUT) -> CommandResult: + if self._writer is None or not self.state.connection.online: + return CommandResult.failure( + "The robot is not connected. Power it on and wait for the dashboard to reattach." + ) + + message_id = self._next_id + self._next_id += 1 + future: asyncio.Future = asyncio.get_running_loop().create_future() + self._pending[message_id] = future + + payload = json.dumps({"type": "cmd", "id": message_id, + "name": name, "args": args or {}}) + "\n" + try: + self._writer.write(payload.encode()) + await self._writer.drain() + except Exception as exc: + self._pending.pop(message_id, None) + return CommandResult.failure(f"Send failed: {exc}") + + try: + reply = await asyncio.wait_for(future, timeout=timeout) + except asyncio.TimeoutError: + self._pending.pop(message_id, None) + return CommandResult.failure(f"The robot did not answer '{name}' within {timeout:g} s") + except ConnectionError: + return CommandResult.failure("Connection to the robot dropped mid-command") + + return CommandResult(bool(reply.get("ok")), + reply.get("message", ""), + reply.get("detail")) + + # -- commands ----------------------------------------------------------- + + async def set_mode(self, mode_id: str) -> CommandResult: + result = await self._send("set_mode", {"mode": mode_id}) + if result.ok: + await self.hub.emit("info", "mode", f"Mode set to {mode_id}") + return result + + async def get_mode(self) -> CommandResult: + return await self._send("get_mode") + + async def set_velocity(self, forward: float, lateral: float, angular: float) -> CommandResult: + return await self._send("set_velocity", + {"forward": forward, "lateral": lateral, "angular": angular}, + timeout=4.0) + + async def stop_motion(self) -> CommandResult: + return await self._send("stop", timeout=4.0) + + async def play_preset(self, motion: int, area: int, interrupt: bool = True) -> CommandResult: + return await self._send("preset", {"motion": motion, "area": area, + "interrupt": interrupt}, timeout=15.0) + + async def set_joints(self, group: str, mode: str, targets: dict, + stiffness=None, damping=None) -> CommandResult: + return await self._send("set_joints", { + "group": group, "mode": mode, "targets": targets, + "stiffness": stiffness, "damping": damping, + }) + + async def set_hand(self, side: str, positions: list) -> CommandResult: + return await self._send("set_hand", {"side": side, "positions": positions}) + + async def speak(self, text: str, priority: int = 6, interrupt: bool = False) -> CommandResult: + return await self._send("speak", {"text": text, "priority": priority, + "interrupt": interrupt}, timeout=15.0) + + async def set_volume(self, volume: int) -> CommandResult: + return await self._send("set_volume", {"volume": volume}) + + async def set_mute(self, muted: bool) -> CommandResult: + return await self._send("set_mute", {"muted": muted}) + + async def play_emoji(self, emotion_id: int, mode: int = 1, priority: int = 6) -> CommandResult: + return await self._send("emoji", {"emotion_id": emotion_id, "mode": mode, + "priority": priority}) + + async def set_led(self, mode: int, r: int, g: int, b: int, priority: int = 6, + keep: bool = True) -> CommandResult: + return await self._send("led", {"mode": mode, "r": r, "g": g, "b": b, + "priority": priority, "keep": keep}) + + async def register_input_source(self, name: str, priority: int, timeout: int) -> CommandResult: + result = await self._send("register_source", {"name": name, "priority": priority, + "timeout": timeout}) + if result.ok: + self.state.source_registered = True + self.state.input_source = name + return result + + async def publish_raw(self, topic: str, message_type: str, payload: dict) -> CommandResult: + return await self._send("publish_raw", {"topic": topic, "type": message_type, + "fields": payload}) + + async def call_service(self, service: str, service_type: str, payload: dict) -> CommandResult: + return CommandResult.failure( + "Arbitrary service calls are not exposed by the agent. Use the typed commands, " + "or add a handler to agent/x2_agent.py." + ) + + async def list_topics(self) -> list[dict]: + return list(self.state.topic_stats.values()) + + async def graph(self) -> dict: + result = await self._send("graph", timeout=10.0) + return result.detail if result.ok and result.detail else {"topics": [], "services": []} + + # -- on-demand streams -------------------------------------------------- + + async def set_stream(self, key: str, active: bool) -> CommandResult: + """Switch a camera or the LiDAR on or off on the robot.""" + result = await self._send("stream_set", {"key": key, "active": bool(active)}, + timeout=8.0) + if result.ok: + # A stopped feed must not keep serving its last frame from cache. + if not active: + self._frames.pop(key, None) + await self.hub.emit("info", "vision", + f"{key} switched {'on' if active else 'off'}") + return result + + async def list_streams(self) -> CommandResult: + return await self._send("stream_list", timeout=6.0) + + async def lidar_points(self) -> CommandResult: + return await self._send("lidar_points", timeout=8.0) + + # -- camera ------------------------------------------------------------- + + async def camera_frame(self, camera_key: str, stream: str = "rgb", + flip: bool | None = None) -> bytes | None: + cached = self._frames.get(camera_key) + # The agent pushes on request; a 120 ms cache stops several browser tabs + # from each pulling the same frame off the robot. + if cached and (time.time() - cached[0]) < 0.12 and cached[3] == flip: + return cached[1] + + args: dict = {"key": camera_key} + if flip is not None: + args["flip"] = bool(flip) + result = await self._send("camera_frame", args, timeout=6.0) + if not result.ok or not result.detail: + return None + try: + data = base64.b64decode(result.detail["b64"]) + except (KeyError, ValueError): + return None + fmt = result.detail.get("format", "jpeg") + self._frames[camera_key] = (time.time(), data, + "image/png" if fmt == "png" else "image/jpeg", + flip) + return data + + def frame_content_type(self, camera_key: str = "", stream: str = "rgb") -> str: + cached = self._frames.get(camera_key) + return cached[2] if cached else "image/jpeg" diff --git a/x2_dashboard/backend/bridge_base.py b/x2_dashboard/backend/bridge_base.py new file mode 100644 index 0000000..3d11114 --- /dev/null +++ b/x2_dashboard/backend/bridge_base.py @@ -0,0 +1,241 @@ +""" +The contract every robot bridge implements. + +Two bridges exist: bridge_ros2 (real rclpy over the network) and bridge_mock +(a physics-lite simulation). The server and the whole frontend only ever talk to +this interface, so the UI is identical whether or not a robot is present. +""" + +from __future__ import annotations + +import time +from dataclasses import dataclass, field, asdict +from typing import Any + +from . import x2_spec + + +@dataclass +class CommandResult: + ok: bool + message: str = "" + detail: Any = None + + def as_dict(self) -> dict: + return {"ok": self.ok, "message": self.message, "detail": self.detail} + + @classmethod + def failure(cls, message: str, detail: Any = None) -> "CommandResult": + return cls(False, message, detail) + + @classmethod + def success(cls, message: str = "OK", detail: Any = None) -> "CommandResult": + return cls(True, message, detail) + + +@dataclass +class Connection: + online: bool = False + transport: str = "none" # "ros2" | "mock" | "none" + host: str = "" + ros_domain_id: int = 0 + since: float | None = None + error: str = "" + simulated: bool = True + + @property + def uptime_s(self) -> float: + return (time.time() - self.since) if self.since else 0.0 + + +@dataclass +class RobotState: + """Everything the dashboard knows about the robot right now.""" + + connection: Connection = field(default_factory=Connection) + + mode: str = "UNKNOWN" + mode_desc: str = "" + mode_status: str = "unknown" + + # Power (from /aima/hal/pmu/state) + battery_pct: float | None = None + battery_voltage: float | None = None + battery_current: float | None = None + battery_temp: float | None = None + battery_cycles: int | None = None + charging: bool = False + pmu_temp: float | None = None + fan_rpm: float | None = None + fan_pct: float | None = None + rails: dict[str, dict] = field(default_factory=dict) + + # IMU (from /aima/hal/imu/*/state) + imu: dict[str, dict] = field(default_factory=dict) + + # Joints, keyed by group ("head" | "waist" | "arm" | "leg") + joints: dict[str, list] = field(default_factory=dict) + + # End effector + hand_type: str = "unknown" + hand_state: dict[str, list] = field(default_factory=dict) + + # Sensors + touch_head: dict = field(default_factory=dict) + + # Motion + velocity: dict = field(default_factory=lambda: {"forward": 0.0, "lateral": 0.0, "angular": 0.0}) + velocity_command: dict = field(default_factory=lambda: {"forward": 0.0, "lateral": 0.0, "angular": 0.0}) + odom: dict = field(default_factory=lambda: {"x": 0.0, "y": 0.0, "yaw": 0.0}) + + # Interaction + volume: int = 60 + muted: bool = False + emoji_id: int | None = None + led: dict = field(default_factory=lambda: {"mode": 0, "r": 0, "g": 0, "b": 0}) + + # Arbitration + input_source: str = "" + input_sources: list = field(default_factory=list) + source_registered: bool = False + + # Topic liveness, keyed by topic name + topic_stats: dict[str, dict] = field(default_factory=dict) + + # Anything a plugin wants to publish into the shared state + custom: dict[str, Any] = field(default_factory=dict) + + updated: float = field(default_factory=time.time) + + def as_dict(self) -> dict: + data = asdict(self) + data["connection"]["uptime_s"] = round(self.connection.uptime_s, 1) + return data + + def mark_topic(self, topic: str, expected_hz: float | None = None) -> None: + now = time.time() + stat = self.topic_stats.get(topic) + if stat is None: + stat = {"topic": topic, "count": 0, "last": now, "hz": 0.0, + "expected_hz": expected_hz, "first": now} + self.topic_stats[topic] = stat + gap = now - stat["last"] + if gap > 0: + # Exponential moving average keeps the rate readable rather than jittery. + instant = 1.0 / gap + stat["hz"] = round(instant if stat["count"] == 0 else stat["hz"] * 0.8 + instant * 0.2, 2) + stat["count"] += 1 + stat["last"] = now + if expected_hz is not None: + stat["expected_hz"] = expected_hz + + +class Bridge: + """Abstract robot bridge. Subclasses override what they can support.""" + + name = "base" + simulated = True + + def __init__(self, hub, config: dict): + self.hub = hub + self.config = config + self.state = RobotState() + + # -- lifecycle ---------------------------------------------------------- + + async def start(self) -> None: + raise NotImplementedError + + async def stop(self) -> None: + raise NotImplementedError + + async def reconfigure(self, config: dict) -> None: + self.config = config + + # -- introspection ------------------------------------------------------ + + def snapshot(self) -> dict: + return self.state.as_dict() + + async def list_topics(self) -> list[dict]: + return list(self.state.topic_stats.values()) + + # -- commands ----------------------------------------------------------- + + async def set_mode(self, mode_id: str) -> CommandResult: + return CommandResult.failure("set_mode not supported by this bridge") + + async def get_mode(self) -> CommandResult: + return CommandResult.success(detail={"mode": self.state.mode}) + + async def set_velocity(self, forward: float, lateral: float, angular: float) -> CommandResult: + return CommandResult.failure("set_velocity not supported by this bridge") + + async def stop_motion(self) -> CommandResult: + """ + Zero the velocity command unconditionally. + + Deliberately not routed through set_velocity: every precondition that + method enforces (right mode, registered input source) is a reason to + refuse *starting* motion, never a reason to refuse stopping it. An + emergency stop that can be declined is not an emergency stop. + """ + self.state.velocity_command = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + return CommandResult.success("Motion stopped") + + async def play_preset(self, motion: int, area: int, interrupt: bool = True) -> CommandResult: + return CommandResult.failure("play_preset not supported by this bridge") + + async def set_joints(self, group: str, mode: str, targets: dict[str, float], + stiffness: float | None = None, + damping: float | None = None) -> CommandResult: + return CommandResult.failure("set_joints not supported by this bridge") + + async def set_hand(self, side: str, positions: list[float]) -> CommandResult: + return CommandResult.failure("set_hand not supported by this bridge") + + async def speak(self, text: str, priority: int = 6, interrupt: bool = False) -> CommandResult: + return CommandResult.failure("speak not supported by this bridge") + + async def set_volume(self, volume: int) -> CommandResult: + return CommandResult.failure("set_volume not supported by this bridge") + + async def set_mute(self, muted: bool) -> CommandResult: + return CommandResult.failure("set_mute not supported by this bridge") + + async def play_emoji(self, emotion_id: int, mode: int = 1, priority: int = 6) -> CommandResult: + return CommandResult.failure("play_emoji not supported by this bridge") + + async def set_led(self, mode: int, r: int, g: int, b: int, + priority: int = x2_spec.LED_DEFAULT_PRIORITY, + keep: bool = True) -> CommandResult: + return CommandResult.failure("set_led not supported by this bridge") + + async def register_input_source(self, name: str, priority: int, timeout: int) -> CommandResult: + return CommandResult.failure("register_input_source not supported by this bridge") + + async def camera_frame(self, camera_key: str, stream: str = "rgb", + flip: bool | None = None) -> bytes | None: + """Latest frame as JPEG bytes, or None if unavailable.""" + return None + + # -- on-demand streams -------------------------------------------------- + # Cameras and the LiDAR stay unsubscribed on the robot until switched on + # here, so an unopened tab costs no bandwidth. + + async def set_stream(self, key: str, active: bool) -> CommandResult: + return CommandResult.failure("set_stream not supported by this bridge") + + async def list_streams(self) -> CommandResult: + return CommandResult.failure("list_streams not supported by this bridge") + + async def lidar_points(self) -> CommandResult: + return CommandResult.failure("lidar_points not supported by this bridge") + + # -- escape hatch for plugins ------------------------------------------ + + async def publish_raw(self, topic: str, message_type: str, payload: dict) -> CommandResult: + return CommandResult.failure("publish_raw not supported by this bridge") + + async def call_service(self, service: str, service_type: str, payload: dict) -> CommandResult: + return CommandResult.failure("call_service not supported by this bridge") diff --git a/x2_dashboard/backend/bridge_mock.py b/x2_dashboard/backend/bridge_mock.py new file mode 100644 index 0000000..43b87a9 --- /dev/null +++ b/x2_dashboard/backend/bridge_mock.py @@ -0,0 +1,520 @@ +""" +Simulated X2, for building and testing the dashboard without a robot present. + +It is deliberately more than a random-number generator: the battery drains at a +rate that depends on what the robot is doing, odometry integrates the velocity +you command, joints ease toward their targets, and mode transitions enforce the +same preconditions the real robot does. That means UI logic exercised here +behaves the same way once a real bridge is attached. +""" + +from __future__ import annotations + +import asyncio +import math +import struct +import time +import zlib + +from . import x2_spec +from .bridge_base import Bridge, CommandResult + + +def _png(width: int, height: int, rgb_rows: list[bytes]) -> bytes: + """Minimal PNG encoder - stdlib only, no Pillow dependency.""" + raw = b"".join(b"\x00" + row for row in rgb_rows) + + def chunk(tag: bytes, data: bytes) -> bytes: + body = tag + data + return struct.pack(">I", len(data)) + body + struct.pack(">I", zlib.crc32(body) & 0xFFFFFFFF) + + return ( + b"\x89PNG\r\n\x1a\n" + + chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0)) + + chunk(b"IDAT", zlib.compress(raw, 6)) + + chunk(b"IEND", b"") + ) + + +class MockBridge(Bridge): + name = "mock" + simulated = True + + def __init__(self, hub, config: dict): + super().__init__(hub, config) + self._task: asyncio.Task | None = None + self._started = 0.0 + self._joint_targets: dict[str, dict[str, float]] = {} + self._preset_until = 0.0 + self._preset_label = "" + self._last_command = 0.0 + self._frame_seq = 0 + # Every feed starts off, matching the real agent. + self._streams: dict[str, bool] = { + **{camera["key"]: False for camera in x2_spec.CAMERAS}, + x2_spec.LIDAR["key"]: False, + } + + # -- lifecycle ---------------------------------------------------------- + + async def start(self) -> None: + self._started = time.time() + + self.state.connection.online = True + self.state.connection.transport = "mock" + self.state.connection.host = self.config.get("robot_host") or "simulated" + self.state.connection.ros_domain_id = self.config.get("ros_domain_id", 0) + self.state.connection.since = self._started + self.state.connection.simulated = True + self.state.connection.error = "" + + self.state.mode = "DAMPING_DEFAULT" + self.state.mode_desc = "Damping" + self.state.mode_status = "ready" + + self.state.battery_pct = 87.0 + self.state.battery_voltage = 50.4 + self.state.battery_current = -2.1 + self.state.battery_temp = 31.5 + self.state.battery_cycles = 142 + self.state.pmu_temp = 38.0 + self.state.fan_rpm = 2400.0 + self.state.fan_pct = 42.0 + self.state.hand_type = "OmniHand Dynamic Edition 2025" + + self.state.hand_type = "None" + for rail in x2_spec.PMU_RAILS: + self.state.rails[rail["key"]] = { + "label": rail["label"], + "voltage": rail["nominal"], + "current": 0.8, + "nominal": rail["nominal"], + "ok": True, + } + + for group in x2_spec.JOINT_GROUPS: + self.state.joints[group["key"]] = [ + {"name": j["name"], "label": j["label"], "position": 0.0, + "velocity": 0.0, "effort": 0.0, "error": 0} + for j in group["joints"] + ] + self._joint_targets[group["key"]] = {j["name"]: 0.0 for j in group["joints"]} + + # This unit reports hand type NONE, so the simulator matches it: no hand + # joints are reported until hardware is attached. + self.state.hand_state = {"left": [], "right": [], "left_type": 0, "right_type": 0} + + self.state.input_sources = list(x2_spec.BUILTIN_INPUT_SOURCES) + self.state.touch_head = {"touched": False, "zones": [False] * x2_spec.TOUCH_ZONE_COUNT} + + self._task = asyncio.create_task(self._loop(), name="mock-bridge") + await self.hub.emit("info", "bridge", "Simulation bridge started - no robot required") + + async def stop(self) -> None: + if self._task: + self._task.cancel() + try: + await self._task + except asyncio.CancelledError: + pass + self._task = None + self.state.connection.online = False + self.state.connection.transport = "none" + + # -- simulation loop ---------------------------------------------------- + + async def _loop(self) -> None: + hz = max(1, int(self.config.get("telemetry_hz", 10))) + dt = 1.0 / hz + tick = 0 + + while True: + try: + await asyncio.sleep(dt) + tick += 1 + now = time.time() + + self._step_motion(dt, now) + self._step_joints(dt) + self._step_imu(now) + self._step_power(dt, tick, hz) + self._step_sensors(now) + + self.state.updated = now + for topic in (x2_spec.TOPIC_IMU_CHEST, x2_spec.TOPIC_IMU_TORSO, + x2_spec.TOPIC_LOCOMOTION_VELOCITY): + self.state.mark_topic(topic) + + self._record_series(now) + await self.hub.broadcast("state", self.state.as_dict()) + + except asyncio.CancelledError: + raise + except Exception as exc: # keep the loop alive; surface the fault + await self.hub.emit("error", "bridge", f"Simulation step failed: {exc}") + await asyncio.sleep(1.0) + + def _step_motion(self, dt: float, now: float) -> None: + cmd = self.state.velocity_command + moving_mode = self.state.mode in x2_spec.DRIVEABLE_MODES + + # Dead-man: a browser that stops sending joystick frames must not leave + # the robot walking. Same rule the real bridge enforces. + deadman = float(self.config.get("locomotion_deadman_s", x2_spec.LOCOMOTION_DEADMAN_S)) + if self._last_command and (now - self._last_command) > deadman: + cmd = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + self.state.velocity_command = dict(cmd) + + target = cmd if moving_mode else {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + + # Apply the documented activation dead-band. + eff = {} + for axis, key in (("forward", "forward"), ("lateral", "lateral"), ("angular", "angular")): + value = target[axis] + if abs(value) < x2_spec.VELOCITY_THRESHOLDS[key] and abs(self.state.velocity[axis]) < 1e-3: + value = 0.0 + eff[axis] = value + + # First-order lag toward the commanded velocity. + alpha = min(1.0, dt * 4.0) + for axis in ("forward", "lateral", "angular"): + self.state.velocity[axis] = round( + self.state.velocity[axis] + (eff[axis] - self.state.velocity[axis]) * alpha, 4 + ) + + yaw = self.state.odom["yaw"] + self.state.velocity["angular"] * dt + fwd = self.state.velocity["forward"] * dt + lat = self.state.velocity["lateral"] * dt + self.state.odom = { + "x": round(self.state.odom["x"] + fwd * math.cos(yaw) - lat * math.sin(yaw), 4), + "y": round(self.state.odom["y"] + fwd * math.sin(yaw) + lat * math.cos(yaw), 4), + "yaw": round(math.atan2(math.sin(yaw), math.cos(yaw)), 4), + } + + if self._preset_until and now > self._preset_until: + self._preset_until = 0.0 + self._preset_label = "" + + def _step_joints(self, dt: float) -> None: + speed = min(1.0, dt * 3.0) + walking = abs(self.state.velocity["forward"]) + abs(self.state.velocity["angular"]) > 0.05 + phase = time.time() * 4.0 + + for group_key, joints in self.state.joints.items(): + targets = self._joint_targets.get(group_key, {}) + for idx, joint in enumerate(joints): + target = targets.get(joint["name"], 0.0) + + # Legs get a gait overlay while walking so the joint view is alive. + if group_key == "leg" and walking: + side = 0.0 if idx < 6 else math.pi + target += 0.22 * math.sin(phase + side) * (1 if idx % 6 in (0, 3) else 0.4) + if group_key == "arm" and self._preset_until: + target += 0.5 * math.sin(phase * 0.8) * (1 if idx % 7 < 3 else 0.3) + + previous = joint["position"] + joint["position"] = round(previous + (target - previous) * speed, 4) + joint["velocity"] = round((joint["position"] - previous) / dt, 4) + joint["effort"] = round(abs(joint["velocity"]) * 3.2 + abs(joint["position"]) * 1.4, 3) + + def _step_imu(self, now: float) -> None: + walking = abs(self.state.velocity["forward"]) > 0.05 + wobble = 0.035 if walking else 0.004 + base = now * 3.0 + + for key, offset in (("chest", 0.0), ("torso", 1.1)): + roll = wobble * math.sin(base * 2.1 + offset) + pitch = wobble * math.cos(base * 1.7 + offset) - self.state.velocity["forward"] * 0.08 + self.state.imu[key] = { + "roll": round(roll, 4), + "pitch": round(pitch, 4), + "yaw": round(self.state.odom["yaw"], 4), + "accel_x": round(self.state.velocity["forward"] * 1.2 + wobble * 9 * math.sin(base * 5), 3), + "accel_y": round(self.state.velocity["lateral"] * 1.2 + wobble * 7 * math.cos(base * 4), 3), + "accel_z": round(9.81 + wobble * 5 * math.sin(base * 6 + offset), 3), + "gyro_x": round(wobble * 4 * math.cos(base * 3), 4), + "gyro_y": round(wobble * 4 * math.sin(base * 3.3), 4), + "gyro_z": round(self.state.velocity["angular"], 4), + "temp": round(34.0 + math.sin(base * 0.05) * 1.5, 2), + } + + def _step_power(self, dt: float, tick: int, hz: int) -> None: + # Draw scales with what the robot is actually doing. + load = 0.5 + if self.state.mode in ("STAND_DEFAULT", "LOCOMOTION_DEFAULT"): + load = 1.4 + load += abs(self.state.velocity["forward"]) * 2.0 + load += abs(self.state.velocity["angular"]) * 1.2 + if self._preset_until: + load += 1.0 + + drain_per_hour = 6.0 * load + self.state.battery_pct = max(0.0, round(self.state.battery_pct - drain_per_hour * dt / 3600.0, 4)) + self.state.battery_current = round(-3.0 * load, 3) + self.state.battery_voltage = round(44.0 + (self.state.battery_pct / 100.0) * 8.4, 3) + self.state.battery_temp = round(30.0 + load * 3.5 + math.sin(time.time() * 0.02) * 0.6, 2) + self.state.pmu_temp = round(35.0 + load * 4.0, 2) + self.state.fan_pct = round(min(100.0, 30.0 + load * 28.0), 1) + self.state.fan_rpm = round(1200 + self.state.fan_pct * 42, 0) + self.state.charging = False + + for key, rail in self.state.rails.items(): + nominal = rail["nominal"] + rail["voltage"] = round(nominal - load * 0.12 + math.sin(time.time() * 0.7) * 0.03, 3) + rail["current"] = round(0.6 + load * (1.8 if key in ("bus_48v", "orin") else 0.5), 3) + rail["ok"] = rail["voltage"] > nominal * 0.85 + + if tick % max(1, hz * 5) == 0: + self.state.mark_topic(x2_spec.TOPIC_PMU_STATE, x2_spec.PMU_RATE_HZ) + + def _step_sensors(self, now: float) -> None: + # A periodic touch event so the sensors tab shows something happening. + touched = (int(now) % 37) < 2 + zones = [False] * x2_spec.TOUCH_ZONE_COUNT + if touched: + zones[int(now) % x2_spec.TOUCH_ZONE_COUNT] = True + self.state.touch_head = {"touched": touched, "zones": zones} + self.state.mark_topic(x2_spec.TOPIC_TOUCH_HEAD, 100) + + def _record_series(self, now: float) -> None: + self.hub.record("battery_pct", self.state.battery_pct, now) + self.hub.record("battery_voltage", self.state.battery_voltage, now) + self.hub.record("battery_current", self.state.battery_current, now) + self.hub.record("battery_temp", self.state.battery_temp, now) + self.hub.record("pmu_temp", self.state.pmu_temp, now) + self.hub.record("fan_pct", self.state.fan_pct, now) + self.hub.record("vel_forward", self.state.velocity["forward"], now) + self.hub.record("vel_lateral", self.state.velocity["lateral"], now) + self.hub.record("vel_angular", self.state.velocity["angular"], now) + chest = self.state.imu.get("chest", {}) + self.hub.record("imu_roll", chest.get("roll"), now) + self.hub.record("imu_pitch", chest.get("pitch"), now) + self.hub.record("imu_yaw", chest.get("yaw"), now) + + # -- commands ----------------------------------------------------------- + + async def set_mode(self, mode_id: str) -> CommandResult: + match = next((m for m in x2_spec.MC_MODES if m["id"] == mode_id), None) + if not match: + return CommandResult.failure(f"Unknown mode '{mode_id}'") + + self.state.mode = mode_id + self.state.mode_desc = match["label"] + self.state.mode_status = "Running" + if mode_id not in x2_spec.DRIVEABLE_MODES: + self.state.velocity_command = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + await self.hub.emit("info", "mode", f"Mode set to {match['label']}") + return CommandResult.success(f"Mode set to {match['label']}", {"mode": mode_id}) + + async def set_velocity(self, forward: float, lateral: float, angular: float) -> CommandResult: + if self.state.mode not in x2_spec.DRIVEABLE_MODES: + return CommandResult.failure("Switch to Stable stand or Locomotion before commanding velocity") + if not self.state.source_registered: + return CommandResult.failure("Register an MC input source first (Control tab)") + + self.state.velocity_command = { + "forward": round(float(forward), 4), + "lateral": round(float(lateral), 4), + "angular": round(float(angular), 4), + } + self._last_command = time.time() + return CommandResult.success("Velocity accepted", self.state.velocity_command) + + async def stop_motion(self) -> CommandResult: + self.state.velocity_command = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + self._last_command = time.time() + return CommandResult.success("Motion stopped") + + async def play_preset(self, motion: int, area: int, interrupt: bool = True) -> CommandResult: + if self.state.mode != "STAND_DEFAULT": + return CommandResult.failure("Preset motions require Stable stand mode") + preset = next((p for p in x2_spec.PRESET_MOTIONS + if p["motion"] == motion and p["area"] == area), None) + label = preset["label"] if preset else f"motion {motion}" + self._preset_until = time.time() + 3.0 + self._preset_label = label + await self.hub.emit("info", "motion", f"Playing preset: {label}") + return CommandResult.success(f"Playing {label}", + {"task_id": int(time.time() * 1000) % 1_000_000}) + + async def set_joints(self, group: str, mode: str, targets: dict[str, float], + stiffness=None, damping=None) -> CommandResult: + if group not in self._joint_targets: + return CommandResult.failure(f"Unknown joint group '{group}'") + spec = x2_spec.JOINT_GROUP_BY_KEY[group] + limits = {j["name"]: j for j in spec["joints"]} + + applied, rejected = {}, {} + for name, value in targets.items(): + joint = limits.get(name) + if joint is None: + rejected[name] = "unknown joint" + continue + lo = math.radians(joint["min_deg"]) + hi = math.radians(joint["max_deg"]) + clamped = max(lo, min(hi, float(value))) + if abs(clamped - float(value)) > 1e-6: + rejected[name] = f"clamped to [{joint['min_deg']}, {joint['max_deg']}] deg" + self._joint_targets[group][name] = clamped + applied[name] = round(clamped, 4) + + return CommandResult.success(f"{len(applied)} joint target(s) applied", + {"applied": applied, "adjusted": rejected}) + + async def set_hand(self, side: str, positions: list[float]) -> CommandResult: + if side not in ("left", "right"): + return CommandResult.failure(f"Unknown side '{side}'") + # Mirror the real unit: with hand type NONE there is nothing to drive. + self.state.hand_state[side] = [ + {"name": name, "position": round(float(positions[i]), 4) if i < len(positions) else 0.0, + "velocity": 0.0, "effort": 0.0, "fault": 0} + for i, name in enumerate(x2_spec.DEXHAND_JOINTS) + ] + return CommandResult.success(f"{side} hand updated") + + async def speak(self, text: str, priority: int = 6, interrupt: bool = False) -> CommandResult: + if not text.strip(): + return CommandResult.failure("Nothing to say") + await self.hub.emit("info", "voice", f'TTS: "{text[:120]}"') + return CommandResult.success("Queued for speech", {"text": text, "priority": priority}) + + async def set_volume(self, volume: int) -> CommandResult: + self.state.volume = max(0, min(100, int(volume))) + return CommandResult.success(f"Volume {self.state.volume}") + + async def set_mute(self, muted: bool) -> CommandResult: + self.state.muted = bool(muted) + return CommandResult.success("Muted" if muted else "Unmuted") + + async def play_emoji(self, emotion_id: int, mode: int = 1, priority: int = 6) -> CommandResult: + self.state.emoji_id = int(emotion_id) + entry = next((e for e in x2_spec.EMOJIS if e["id"] == int(emotion_id)), None) + return CommandResult.success(f"Showing {entry['label'] if entry else emotion_id}") + + async def set_led(self, mode: int, r: int, g: int, b: int, priority: int = 6, + keep: bool = True) -> CommandResult: + self.state.led = {"mode": int(mode), "r": int(r), "g": int(g), + "b": int(b), "keep": bool(keep)} + return CommandResult.success("LED updated", self.state.led) + + async def register_input_source(self, name: str, priority: int, timeout: int) -> CommandResult: + existing = next((s for s in self.state.input_sources if s["name"] == name), None) + if existing: + existing.update({"priority": priority, "timeout": timeout}) + else: + self.state.input_sources.append( + {"name": name, "priority": priority, "timeout": timeout, "desc": "This dashboard"} + ) + self.state.source_registered = True + # The built-in sources are listed for reference but nothing is actually + # driving them in simulation, so the newly registered source wins + # arbitration. On a real robot the firmware decides this. + self.state.input_source = name + await self.hub.emit("info", "control", f"Input source '{name}' registered at priority {priority}") + return CommandResult.success(f"Registered '{name}'", {"current": self.state.input_source}) + + async def publish_raw(self, topic: str, message_type: str, payload: dict) -> CommandResult: + self.state.mark_topic(topic) + return CommandResult.success(f"[simulated] published to {topic}", payload) + + async def call_service(self, service: str, service_type: str, payload: dict) -> CommandResult: + return CommandResult.success(f"[simulated] called {service}", {"request": payload}) + + # -- synthetic camera --------------------------------------------------- + + async def camera_frame(self, camera_key: str, stream: str = "rgb", + flip: bool | None = None) -> bytes | None: + """A moving synthetic scene, so the Vision tab is testable without hardware.""" + # Off means off in simulation too, or the Vision tab's switches would + # look broken here and only work against real hardware. + if not self._streams.get(camera_key): + return None + + width, height = 192, 144 + self._frame_seq += 1 + t = time.time() + yaw = self.state.odom["yaw"] + depth = stream == "depth" or camera_key.startswith("depth") + + # Horizon shifts with pitch, scene pans with yaw - so driving the robot + # visibly changes the view. + pitch = self.state.imu.get("chest", {}).get("pitch", 0.0) + horizon = int(height * 0.55 + pitch * 220) + pan = (yaw * 90.0 + t * 6.0) % width + + rows = [] + for y in range(height): + row = bytearray() + for x in range(width): + if depth: + # Distance rises toward the horizon; a nearby object sweeps past. + d = abs(y - horizon) / height + obj = math.exp(-(((x - pan) % width - width / 2) ** 2) / 400.0) + v = max(0.0, min(1.0, d * 1.6 - obj * 0.5)) + # Single-hue blue ramp, light = near, dark = far. + r = int(205 * (1 - v) + 13 * v) + g = int(226 * (1 - v) + 54 * v) + b = int(251 * (1 - v) + 107 * v) + else: + if y < horizon: + shade = y / max(1, horizon) + r, g, b = int(24 + 26 * shade), int(28 + 32 * shade), int(38 + 46 * shade) + else: + shade = (y - horizon) / max(1, height - horizon) + r, g, b = int(30 + 24 * shade), int(34 + 20 * shade), int(32 + 16 * shade) + # Vertical markers that slide with yaw, giving visible motion. + if (int(x + pan) // 24) % 2 == 0 and y > horizon: + r, g, b = min(255, r + 26), min(255, g + 22), min(255, b + 18) + if abs(y - horizon) <= 1: + r, g, b = 57, 135, 229 + row += bytes((r, g, b)) + rows.append(bytes(row)) + + if flip: + # 180 degrees = reverse the row order, and the pixels within each + # row. Pixels are 3 bytes, so reverse in triples, not bytewise. + def reverse_pixels(row: bytes) -> bytes: + return b"".join(row[i - 3:i] for i in range(len(row), 0, -3)) + + rows = [reverse_pixels(row) for row in reversed(rows)] + + return _png(width, height, rows) + + def frame_content_type(self, camera_key: str = "", stream: str = "rgb") -> str: + return "image/png" + + # -- on-demand streams -------------------------------------------------- + + async def set_stream(self, key: str, active: bool) -> CommandResult: + self._streams[key] = bool(active) + self.state.custom["streams"] = { + k: {"key": k, "active": v} for k, v in self._streams.items() + } + return CommandResult.success( + f"[simulated] {key} {'on' if active else 'off'}", {"key": key, "active": active}) + + async def list_streams(self) -> CommandResult: + return CommandResult.success("[simulated] streams", { + "streams": {k: {"key": k, "active": v} for k, v in self._streams.items()}, + }) + + async def lidar_points(self) -> CommandResult: + """A synthetic room, so the LiDAR view is testable with no robot attached.""" + if not self._streams.get(x2_spec.LIDAR["key"]): + return CommandResult.failure("LiDAR is off") + + t = time.time() + points = [] + # Four walls and a floor patch, swept by a rotating scan line so the + # view visibly updates. + for i in range(900): + angle = (i / 900.0) * math.tau + radius = 3.0 + 0.8 * math.sin(angle * 4 + t * 0.3) + for z in (-0.4, 0.1, 0.6, 1.1): + points.append([round(radius * math.cos(angle), 3), + round(radius * math.sin(angle), 3), + z, round(40 + 60 * abs(math.sin(angle + t)), 1)]) + return CommandResult.success("[simulated] points", { + "ts": t, "count": len(points), "points": points, + "frame": x2_spec.LIDAR["frame"], + }) diff --git a/x2_dashboard/backend/hub.py b/x2_dashboard/backend/hub.py new file mode 100644 index 0000000..3ebaf35 --- /dev/null +++ b/x2_dashboard/backend/hub.py @@ -0,0 +1,107 @@ +""" +Fan-out hub between the robot bridge and every connected browser. + +One bridge produces state; N browsers consume it. Each client gets its own +bounded queue so a slow tab (a backgrounded phone, say) can never stall the +telemetry loop for everyone else - it just drops frames. +""" + +from __future__ import annotations + +import asyncio +import json +import time +from collections import deque +from typing import Any + + +class Hub: + def __init__(self, history_seconds: int = 120, sample_hz: int = 10): + self._clients: set[asyncio.Queue] = set() + self._lock = asyncio.Lock() + self._series: dict[str, deque] = {} + self._history_points = max(60, int(history_seconds * sample_hz)) + self._events: deque = deque(maxlen=400) + + # -- client lifecycle --------------------------------------------------- + + async def register(self) -> asyncio.Queue: + queue: asyncio.Queue = asyncio.Queue(maxsize=32) + async with self._lock: + self._clients.add(queue) + return queue + + async def unregister(self, queue: asyncio.Queue) -> None: + async with self._lock: + self._clients.discard(queue) + + @property + def client_count(self) -> int: + return len(self._clients) + + # -- broadcast ---------------------------------------------------------- + + async def broadcast(self, kind: str, payload: Any) -> None: + message = json.dumps({"type": kind, "ts": time.time(), "data": payload}, + separators=(",", ":"), default=str) + dead = [] + for queue in list(self._clients): + try: + queue.put_nowait(message) + except asyncio.QueueFull: + # Drop the oldest frame rather than the newest - stale telemetry + # is worth less than current telemetry. + try: + queue.get_nowait() + queue.put_nowait(message) + except (asyncio.QueueEmpty, asyncio.QueueFull): + dead.append(queue) + for queue in dead: + await self.unregister(queue) + + # -- time series -------------------------------------------------------- + + def record(self, key: str, value: float, ts: float | None = None) -> None: + """Append one sample to a named series for the dashboard's charts.""" + if value is None: + return + try: + value = float(value) + except (TypeError, ValueError): + return + series = self._series.get(key) + if series is None: + series = deque(maxlen=self._history_points) + self._series[key] = series + series.append((ts if ts is not None else time.time(), round(value, 4))) + + def series(self, key: str, limit: int | None = None) -> list[list[float]]: + data = list(self._series.get(key, ())) + if limit: + data = data[-limit:] + return [[t, v] for t, v in data] + + def all_series(self, limit: int | None = None) -> dict[str, list]: + return {k: self.series(k, limit) for k in self._series} + + def series_keys(self) -> list[str]: + return sorted(self._series) + + # -- event log ---------------------------------------------------------- + + def log(self, level: str, source: str, message: str, detail: Any = None) -> dict: + entry = { + "ts": time.time(), + "level": level, + "source": source, + "message": message, + "detail": detail, + } + self._events.append(entry) + return entry + + def events(self, limit: int = 200) -> list[dict]: + return list(self._events)[-limit:] + + async def emit(self, level: str, source: str, message: str, detail: Any = None) -> None: + await self.broadcast("event", self.log(level, source, message, detail)) diff --git a/x2_dashboard/backend/netinfo.py b/x2_dashboard/backend/netinfo.py new file mode 100644 index 0000000..fcfcf7e --- /dev/null +++ b/x2_dashboard/backend/netinfo.py @@ -0,0 +1,346 @@ +""" +Network discovery and host addressing. + +Nothing in this dashboard assumes a fixed IP. Three separate problems are solved +here: + +1. Which addresses is this dashboard reachable on? -> local_addresses() + The server binds 0.0.0.0, so it answers on every interface. We enumerate them + so the operator can open the dashboard from a phone on the same Wi-Fi. + +2. What subnets are we on? -> local_networks() + Derived from the live interface list, so moving between networks just works. + +3. Where is the robot right now? -> scan_subnet() / probe_host() + A bounded TCP sweep of the current subnet, matching hosts that answer on the + ports an X2 exposes. +""" + +from __future__ import annotations + +import asyncio +import ipaddress +import socket +import subprocess +import sys +import time +from typing import Iterable + +from . import x2_spec + + +# -------------------------------------------------------------------------- +# Local interface enumeration +# -------------------------------------------------------------------------- + +def _addresses_from_os() -> set[str]: + """ + Every IPv4 the OS reports, by asking the OS directly. + + getaddrinfo() and the UDP-connect trick below both under-report: the first + depends on how the hostname resolves, the second only ever reveals the + default-route interface. On a machine with both Wi-Fi and Ethernet that + means the dashboard advertised only one of its addresses. + """ + found: set[str] = set() + try: + if sys.platform == "win32": + out = subprocess.run( + ["ipconfig"], capture_output=True, text=True, timeout=8, + creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0), + ).stdout + for line in out.splitlines(): + line = line.strip() + # Localised Windows uses a translated label, so match on the + # "IPv4" token rather than the full English phrase. + if "IPv4" in line and ":" in line: + found.add(line.split(":")[-1].strip().replace("(Preferred)", "").strip()) + else: + out = subprocess.run( + ["ip", "-o", "-4", "addr", "show"], + capture_output=True, text=True, timeout=8, + ).stdout + for line in out.splitlines(): + for token in line.split(): + if "/" in token and token[0].isdigit(): + found.add(token.split("/")[0]) + break + except (OSError, subprocess.SubprocessError, ValueError): + pass + return found + + +def _addresses_via_socket() -> set[str]: + """Addresses this host answers on, without third-party dependencies.""" + found: set[str] = set(_addresses_from_os()) + + try: + for info in socket.getaddrinfo(socket.gethostname(), None, socket.AF_INET): + found.add(info[4][0]) + except socket.gaierror: + pass + + # Opening a UDP socket toward a public address makes the kernel pick the + # outbound interface and tell us its address - no packet is actually sent. + for probe in ("8.8.8.8", "1.1.1.1"): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + sock.connect((probe, 80)) + found.add(sock.getsockname()[0]) + except OSError: + pass + finally: + sock.close() + + cleaned = set() + for addr in found: + try: + ipaddress.IPv4Address(addr) + cleaned.add(addr) + except ipaddress.AddressValueError: + continue + return cleaned + + +def _netmask_for(addr: str) -> str | None: + """Best-effort netmask lookup. Falls back to a /24 assumption.""" + try: + if sys.platform == "win32": + out = subprocess.run( + ["ipconfig"], capture_output=True, text=True, timeout=5, + creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0), + ).stdout + block: list[str] = [] + for line in out.splitlines(): + block.append(line) + if addr in line: + # The mask is printed on the line after the address. + idx = block.index(line) + for follow in out.splitlines()[idx + 1: idx + 4]: + if "Mask" in follow or "掩码" in follow: + return follow.split(":")[-1].strip() + else: + out = subprocess.run( + ["ip", "-o", "-f", "inet", "addr", "show"], + capture_output=True, text=True, timeout=5, + ).stdout + for line in out.splitlines(): + if f"{addr}/" in line: + for tok in line.split(): + if tok.startswith(f"{addr}/"): + return tok.split("/")[1] + except (OSError, subprocess.SubprocessError, ValueError): + pass + return None + + +def local_addresses() -> list[dict]: + """Every usable IPv4 this machine holds, loopback last.""" + result = [] + for addr in sorted(_addresses_via_socket()): + try: + ip = ipaddress.IPv4Address(addr) + except ipaddress.AddressValueError: + continue + result.append({ + "address": addr, + "loopback": ip.is_loopback, + "private": ip.is_private, + "link_local": ip.is_link_local, + }) + result.sort(key=lambda r: (r["loopback"], r["link_local"], not r["private"], r["address"])) + return result + + +def local_networks() -> list[str]: + """CIDR networks this host sits on, excluding loopback and link-local.""" + nets: list[str] = [] + for entry in local_addresses(): + if entry["loopback"] or entry["link_local"]: + continue + addr = entry["address"] + mask = _netmask_for(addr) + try: + iface = ipaddress.IPv4Interface(f"{addr}/{mask}" if mask else f"{addr}/24") + except (ipaddress.AddressValueError, ipaddress.NetmaskValueError, ValueError): + iface = ipaddress.IPv4Interface(f"{addr}/24") + cidr = str(iface.network) + if cidr not in nets: + nets.append(cidr) + return nets + + +def primary_address() -> str | None: + """ + The address other devices on the LAN would actually reach us on. + + Delegates to nic.detect(), which ranks real adapters and refuses to return a + stale one. Enumerating "the first non-loopback address" is not good enough: + a disconnected adapter keeps its address, answers local connections through + loopback, and would be published as a link nobody else can open. + """ + from . import nic + + return nic.primary_address() + + +def address_detail() -> dict: + """Full detection result - which adapter won, what was rejected and why.""" + from . import nic + + found = nic.detect() + primary = found["primary"] + return { + "ip": primary["ip"] if primary else None, + "adapter": primary["adapter"] if primary else None, + "kind": ("wifi" if primary and primary.get("iftype") == nic.IF_TYPE_WIFI + else "wired" if primary else None), + "gateway": primary.get("gateway") if primary else None, + "reason": found["reason"], + "reason_text": nic.REASON_TEXT.get(found["reason"] or "", ""), + "alternates": [ + {"ip": a["ip"], "adapter": a["adapter"], + "kind": "wifi" if a.get("iftype") == nic.IF_TYPE_WIFI else "wired"} + for a in found["alternates"] + ], + "rejected": [ + {"ip": r["ip"], "adapter": r["adapter"], "why": r["rejected"]} + for r in found["rejected"] + if not str(r["ip"]).startswith("127.") + ], + "checked_at": found["checked_at"], + } + + +def hostname_urls(port: int, advertised: str | None = None) -> list[str]: + """ + Name-based URLs for the dashboard. + + Only the name the dashboard advertises for itself is offered. The PC's own + computer name is deliberately not published: this is a robot dashboard, and + the link should say so. The bare single-label form is left out too - it + resolves on Windows from local configuration without a packet reaching the + network, and no phone resolves it at all. + """ + if not advertised: + return [] + return [f"http://{advertised.strip().strip('.').lower()}.local:{port}"] + + +def dashboard_urls(port: int, advertised: str | None = None) -> list[str]: + """ + URLs for the dashboard, best first. + + The live Wi-Fi address leads: it is what a phone can always reach, needing + no mDNS, no multicast and no DNS. Names come after it, because on many + access points `.local` resolution is blocked between wireless clients. + """ + urls: list[str] = [] + detail = address_detail() + if detail["ip"]: + urls.append(f"http://{detail['ip']}:{port}") + for alternate in detail["alternates"]: + urls.append(f"http://{alternate['ip']}:{port}") + + for url in hostname_urls(port, advertised): + if url not in urls: + urls.append(url) + + urls.append(f"http://localhost:{port}") + return urls + + +# -------------------------------------------------------------------------- +# Robot probing +# -------------------------------------------------------------------------- + +async def _tcp_open(host: str, port: int, timeout: float) -> bool: + try: + fut = asyncio.open_connection(host, port) + reader, writer = await asyncio.wait_for(fut, timeout=timeout) + writer.close() + try: + await writer.wait_closed() + except (ConnectionError, OSError): + pass + return True + except (asyncio.TimeoutError, OSError): + return False + + +async def probe_host(host: str, ports: Iterable[int] | None = None, + timeout: float = 0.6) -> dict: + """Check which of the X2's known ports a host answers on.""" + ports = list(ports or x2_spec.DISCOVERY_PORTS) + started = time.monotonic() + results = await asyncio.gather(*[_tcp_open(host, p, timeout) for p in ports]) + open_ports = [p for p, ok in zip(ports, results) if ok] + + hostname = None + if open_ports: + try: + hostname = await asyncio.get_running_loop().run_in_executor( + None, lambda: socket.gethostbyaddr(host)[0] + ) + except (OSError, socket.herror): + hostname = None + + return { + "host": host, + "reachable": bool(open_ports), + "open_ports": open_ports, + "hostname": hostname, + "latency_ms": round((time.monotonic() - started) * 1000, 1), + "is_pc1": host == x2_spec.PC1_MOTION_CONTROL_IP, + } + + +async def scan_subnet(cidr: str, ports: Iterable[int] | None = None, + timeout: float = 0.4, concurrency: int = 128, + progress=None) -> list[dict]: + """ + Sweep a subnet for hosts answering on X2 ports. + + Refuses networks larger than /22 - a /16 sweep is 65k hosts and would hang + for minutes rather than seconds. + """ + network = ipaddress.IPv4Network(cidr, strict=False) + if network.num_addresses > 1024: + raise ValueError( + f"{cidr} has {network.num_addresses} addresses; " + "narrow the range to /22 or smaller before scanning." + ) + + hosts = list(network.hosts()) + semaphore = asyncio.Semaphore(concurrency) + done = 0 + total = len(hosts) + + async def one(ip): + nonlocal done + async with semaphore: + res = await probe_host(str(ip), ports, timeout) + done += 1 + if progress and done % 16 == 0: + await progress(done, total) + return res + + results = await asyncio.gather(*[one(ip) for ip in hosts]) + if progress: + await progress(total, total) + return [r for r in results if r["reachable"]] + + +async def resolve(host: str) -> str | None: + """Resolve a hostname to an IPv4 address, or return it unchanged if already one.""" + try: + ipaddress.IPv4Address(host) + return host + except ipaddress.AddressValueError: + pass + try: + loop = asyncio.get_running_loop() + info = await loop.getaddrinfo(host, None, family=socket.AF_INET) + return info[0][4][0] + except (socket.gaierror, OSError, IndexError): + return None diff --git a/x2_dashboard/backend/nic.py b/x2_dashboard/backend/nic.py new file mode 100644 index 0000000..351fdfb --- /dev/null +++ b/x2_dashboard/backend/nic.py @@ -0,0 +1,592 @@ +""" +Find the LAN address this machine is actually reachable on, live. + +The dashboard publishes `http://:8770`, so picking the wrong address means +handing someone a link that cannot work. That is easy to get wrong: this very +machine has a *disconnected* Ethernet adapter still holding 192.168.123.222, and +a local HTTP fetch to that address SUCCEEDS - Windows routes traffic to any of +its own addresses through loopback, skipping the adapter entirely. It even +answers faster than the real one. There is therefore no connect, bind or fetch +test that can tell a reachable address from a dead one; the decision has to come +from adapter metadata. + +The rule below was chosen by running candidate rules against 23 synthetic +adapter tables (VPNs of three different shapes, Hyper-V bridges, mobile hotspot, +docked Ethernet, duplicate-IP detection, campus public addressing, renamed +adapters). Two obvious-looking rules broke 9 times each; this one breaks once, +on a case that is genuinely undecidable (two Wi-Fi radios, nothing in the +adapter table says which one the phone is associated to). + +Deliberate non-decisions, each of which was tried and rejected: + +* No `is_private` test. It over-rejects campus and CGNAT (100.64/10) addresses + that phones reach perfectly well, and under-rejects Hyper-V's 172.x. +* No adapter *name* matching. "Wi-Fi" is user-renameable and every ipconfig + label is translated on non-English Windows. +* Interface metric is the LAST tiebreak, never a gate. Corporate VPNs + deliberately set a low metric, and on this machine four *disconnected* + adapters sit at metric 25 while the one working NIC is at 30. +""" + +from __future__ import annotations + +import ipaddress +import json +import logging +import os +import platform +import subprocess +import threading +import time + +log = logging.getLogger("x2.nic") + +# Re-read this often at most. At ~2 ms a detection the cost is irrelevant; the +# TTL exists so two requests in one page load cannot disagree mid-roam, and so a +# stale address never outlives a single human retry. +TTL_SECONDS = 2.0 + +IF_TYPE_ETHERNET = 6 +IF_TYPE_LOOPBACK = 24 +IF_TYPE_WIFI = 71 +IF_TYPE_TUNNEL = 131 + +OPER_STATUS_UP = 1 +DAD_STATE_PREFERRED = 4 +PREFIX_ORIGIN_WELLKNOWN = 2 +PREFIX_ORIGIN_DHCP = 3 + + +# -------------------------------------------------------------------------- +# Ranking - platform independent, operating on normalised records +# -------------------------------------------------------------------------- + +def _class_of(record: dict) -> int: + """Higher is a better candidate to hand to a phone.""" + hardware = record.get("hardware") + iftype = record.get("iftype") + if hardware and iftype == IF_TYPE_WIFI: + return 3 # a real Wi-Fi radio + if hardware and iftype == IF_TYPE_ETHERNET: + return 2 # a real wired NIC + if iftype == IF_TYPE_WIFI: + return 1 # hotspot / Wi-Fi Direct - still a radio + return 0 # bridge or unknown + + +def _rejected(record: dict) -> str | None: + """Why this address must not be published, or None if it is usable.""" + iftype = record.get("iftype") + if iftype in (IF_TYPE_LOOPBACK, IF_TYPE_TUNNEL): + return "loopback or tunnel" + if record.get("oper_status") != OPER_STATUS_UP: + return "adapter is down" + if record.get("connected") is False: + return "no link" + if record.get("dad_state") not in (None, DAD_STATE_PREFERRED): + # Deprecated = the stale address on a disconnected NIC. + # Tentative = still running duplicate-address detection. + # Duplicate = the stack itself refuses to send from it. + return "address not preferred" + if record.get("prefix_origin") == PREFIX_ORIGIN_WELLKNOWN: + return "self-assigned (APIPA)" + + try: + ip = ipaddress.IPv4Address(record["ip"]) + except (ipaddress.AddressValueError, KeyError): + return "not an IPv4 address" + if ip.is_loopback or ip.is_link_local: + return "loopback or link-local" + + # Virtual adapters (VPN NDIS miniports, Hyper-V, WSL, docker) are not a path + # to a phone. Two exceptions: any Wi-Fi-class radio, which covers the mobile + # hotspot case; and a bridge that has taken over a live physical NIC's + # address, which is what a Hyper-V *external* switch does. + if not record.get("hardware", True): + is_radio = iftype == IF_TYPE_WIFI + is_external_bridge = ( + record.get("physical_link_present") + and record.get("has_gateway") + and record.get("prefix_origin") == PREFIX_ORIGIN_DHCP + ) + if not (is_radio or is_external_bridge): + return "virtual adapter" + return None + + +def _sort_key(record: dict): + try: + numeric = int(ipaddress.IPv4Address(record["ip"])) + except Exception: + numeric = 0 + return ( + 1 if record.get("has_gateway") else 0, + _class_of(record), + 1 if record.get("prefix_origin") == PREFIX_ORIGIN_DHCP else 0, + -(record.get("metric") or 0), + -numeric, + ) + + +def rank(records: list[dict]) -> tuple[list[dict], list[dict]]: + """Split candidates into (usable, best first) and (rejected, with reasons).""" + usable, rejected = [], [] + for record in records: + why = _rejected(record) + if why: + rejected.append({**record, "rejected": why}) + else: + usable.append(record) + usable.sort(key=_sort_key, reverse=True) + return usable, rejected + + +def _reason_for_nothing(rejected: list[dict]) -> str: + """Explain an empty result honestly instead of guessing an address.""" + if not rejected: + return "no_network_interface" + kinds = {r.get("rejected") for r in rejected} + wifi = [r for r in rejected if r.get("iftype") == IF_TYPE_WIFI and r.get("hardware")] + if wifi and all(r.get("oper_status") != OPER_STATUS_UP or r.get("connected") is False + for r in wifi): + return "wifi_down" + if "address not preferred" in kinds or "self-assigned (APIPA)" in kinds: + return "awaiting_dhcp" + if all(not r.get("has_gateway") for r in rejected): + return "no_router_on_this_network" + return "no_usable_address" + + +# -------------------------------------------------------------------------- +# Windows collector - GetAdaptersAddresses + GetIfTable2 via ctypes +# -------------------------------------------------------------------------- + +def _collect_windows() -> list[dict]: + import ctypes + from ctypes import wintypes + + iphlpapi = ctypes.WinDLL("iphlpapi") + + class SOCKET_ADDRESS(ctypes.Structure): + _fields_ = [("lpSockaddr", ctypes.c_void_p), ("iSockaddrLength", ctypes.c_int)] + + class IP_ADAPTER_UNICAST_ADDRESS(ctypes.Structure): + pass + + IP_ADAPTER_UNICAST_ADDRESS._fields_ = [ + ("Length", wintypes.ULONG), + ("Flags", wintypes.DWORD), + ("Next", ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)), + ("Address", SOCKET_ADDRESS), + ("PrefixOrigin", ctypes.c_int), + ("SuffixOrigin", ctypes.c_int), + ("DadState", ctypes.c_int), + ("ValidLifetime", wintypes.ULONG), + ("PreferredLifetime", wintypes.ULONG), + ("LeaseLifetime", wintypes.ULONG), + ("OnLinkPrefixLength", ctypes.c_ubyte), + ] + + class IP_ADAPTER_GATEWAY_ADDRESS(ctypes.Structure): + pass + + IP_ADAPTER_GATEWAY_ADDRESS._fields_ = [ + ("Length", wintypes.ULONG), + ("Reserved", wintypes.DWORD), + ("Next", ctypes.POINTER(IP_ADAPTER_GATEWAY_ADDRESS)), + ("Address", SOCKET_ADDRESS), + ] + + class IP_ADAPTER_ADDRESSES(ctypes.Structure): + pass + + IP_ADAPTER_ADDRESSES._fields_ = [ + ("Length", wintypes.ULONG), + ("IfIndex", wintypes.DWORD), + ("Next", ctypes.POINTER(IP_ADAPTER_ADDRESSES)), + ("AdapterName", ctypes.c_char_p), + ("FirstUnicastAddress", ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)), + ("FirstAnycastAddress", ctypes.c_void_p), + ("FirstMulticastAddress", ctypes.c_void_p), + ("FirstDnsServerAddress", ctypes.c_void_p), + ("DnsSuffix", ctypes.c_wchar_p), + ("Description", ctypes.c_wchar_p), + ("FriendlyName", ctypes.c_wchar_p), + ("PhysicalAddress", ctypes.c_ubyte * 8), + ("PhysicalAddressLength", wintypes.ULONG), + ("Flags", wintypes.ULONG), + ("Mtu", wintypes.ULONG), + ("IfType", wintypes.ULONG), + ("OperStatus", ctypes.c_int), + ("Ipv6IfIndex", wintypes.DWORD), + ("ZoneIndices", wintypes.ULONG * 16), + ("FirstPrefix", ctypes.c_void_p), + ("TransmitLinkSpeed", ctypes.c_uint64), + ("ReceiveLinkSpeed", ctypes.c_uint64), + ("FirstWinsServerAddress", ctypes.c_void_p), + ("FirstGatewayAddress", ctypes.POINTER(IP_ADAPTER_GATEWAY_ADDRESS)), + ("Ipv4Metric", wintypes.ULONG), + ("Ipv6Metric", wintypes.ULONG), + ("Luid", ctypes.c_uint64), + ("Dhcpv4Server", SOCKET_ADDRESS), + ("CompartmentId", wintypes.DWORD), + ("NetworkGuid", ctypes.c_ubyte * 16), + ("ConnectionType", ctypes.c_int), + ("TunnelType", ctypes.c_int), + ] + + AF_INET = 2 + GAA_FLAG_INCLUDE_GATEWAYS = 0x0080 + GAA_FLAG_SKIP_ANYCAST = 0x0002 + GAA_FLAG_SKIP_MULTICAST = 0x0004 + GAA_FLAG_SKIP_DNS_SERVER = 0x0008 + flags = (GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_SKIP_ANYCAST + | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER) + + def sockaddr_to_ip(sa: SOCKET_ADDRESS) -> str | None: + if not sa.lpSockaddr: + return None + raw = ctypes.string_at(sa.lpSockaddr, 8) + if int.from_bytes(raw[0:2], "little") != AF_INET: + return None + return ".".join(str(b) for b in raw[4:8]) + + # The buffer is allocated per call; sharing one across threads corrupts it. + size = wintypes.ULONG(15000) + buffer = ctypes.create_string_buffer(size.value) + result = iphlpapi.GetAdaptersAddresses( + AF_INET, flags, None, ctypes.byref(buffer), ctypes.byref(size)) + if result == 111: # ERROR_BUFFER_OVERFLOW + buffer = ctypes.create_string_buffer(size.value) + result = iphlpapi.GetAdaptersAddresses( + AF_INET, flags, None, ctypes.byref(buffer), ctypes.byref(size)) + if result != 0: + raise OSError(f"GetAdaptersAddresses failed: {result}") + + # First pass: collect IfType per interface so the GetIfTable2 parse below can + # be validated against a second, independent source. + known_types: dict[int, int] = {} + node = ctypes.cast(buffer, ctypes.POINTER(IP_ADAPTER_ADDRESSES)) + while node: + known_types[int(node.contents.IfIndex)] = int(node.contents.IfType) + node = node.contents.Next + + hardware, connected, physical_live = _windows_interface_flags(known_types) + + records: list[dict] = [] + node = ctypes.cast(buffer, ctypes.POINTER(IP_ADAPTER_ADDRESSES)) + while node: + adapter = node.contents + gateways = [] + gw = adapter.FirstGatewayAddress + while gw: + ip = sockaddr_to_ip(gw.contents.Address) + if ip: + gateways.append(ip) + gw = gw.contents.Next + + unicast = adapter.FirstUnicastAddress + while unicast: + entry = unicast.contents + ip = sockaddr_to_ip(entry.Address) + if ip: + index = int(adapter.IfIndex) + records.append({ + "ip": ip, + "prefix_length": int(entry.OnLinkPrefixLength), + "adapter": adapter.FriendlyName or "", + "description": adapter.Description or "", + "if_index": index, + "iftype": int(adapter.IfType), + "oper_status": int(adapter.OperStatus), + "dad_state": int(entry.DadState), + "prefix_origin": int(entry.PrefixOrigin), + "metric": int(adapter.Ipv4Metric), + "has_gateway": bool(gateways), + "gateway": gateways[0] if gateways else None, + "hardware": hardware.get(index), + "connected": connected.get(index), + "physical_link_present": physical_live, + }) + unicast = entry.Next + node = adapter.Next + + return records + + +def _windows_interface_flags(known_types: dict | None = None) -> tuple[dict, dict, bool]: + """ + Per-interface HardwareInterface / MediaConnectState from GetIfTable2. + + These two gates cannot be derived from GetAdaptersAddresses, and they are + what separates a real NIC from a VPN miniport or a Hyper-V bridge without + matching English adapter names. + + MIB_IF_ROW2 must be modelled COMPLETELY, trailing statistics counters and + all: the rows are read as a contiguous array, so a struct even one field + short gives the wrong stride and every row after the first is garbage - + silently, with no error from the API. `known_types` therefore carries the + IfType values already read from GetAdaptersAddresses so the parse can be + checked against them; on disagreement we discard the whole table and let the + ranking fall back to `hardware: None` (unknown), which is treated as "do not + reject", never as "virtual". + """ + import ctypes + from ctypes import wintypes + + try: + iphlpapi = ctypes.WinDLL("iphlpapi") + + class MIB_IF_ROW2(ctypes.Structure): + _fields_ = [ + ("InterfaceLuid", ctypes.c_uint64), + ("InterfaceIndex", wintypes.DWORD), + ("InterfaceGuid", ctypes.c_ubyte * 16), + ("Alias", ctypes.c_wchar * 257), + ("Description", ctypes.c_wchar * 257), + ("PhysicalAddressLength", wintypes.ULONG), + ("PhysicalAddress", ctypes.c_ubyte * 32), + ("PermanentPhysicalAddress", ctypes.c_ubyte * 32), + ("Mtu", wintypes.ULONG), + ("Type", wintypes.ULONG), + ("TunnelType", ctypes.c_int), + ("MediaType", ctypes.c_int), + ("PhysicalMediumType", ctypes.c_int), + ("AccessType", ctypes.c_int), + ("DirectionType", ctypes.c_int), + ("InterfaceAndOperStatusFlags", ctypes.c_ubyte), + ("OperStatus", ctypes.c_int), + ("AdminStatus", ctypes.c_int), + ("MediaConnectState", ctypes.c_int), + ("NetworkGuid", ctypes.c_ubyte * 16), + ("ConnectionType", ctypes.c_int), + ("TransmitLinkSpeed", ctypes.c_uint64), + ("ReceiveLinkSpeed", ctypes.c_uint64), + # Everything below is unused, but its size decides the stride. + ("InOctets", ctypes.c_uint64), + ("InUcastPkts", ctypes.c_uint64), + ("InNUcastPkts", ctypes.c_uint64), + ("InDiscards", ctypes.c_uint64), + ("InErrors", ctypes.c_uint64), + ("InUnknownProtos", ctypes.c_uint64), + ("InUcastOctets", ctypes.c_uint64), + ("InMulticastOctets", ctypes.c_uint64), + ("InBroadcastOctets", ctypes.c_uint64), + ("OutOctets", ctypes.c_uint64), + ("OutUcastPkts", ctypes.c_uint64), + ("OutNUcastPkts", ctypes.c_uint64), + ("OutDiscards", ctypes.c_uint64), + ("OutErrors", ctypes.c_uint64), + ("OutUcastOctets", ctypes.c_uint64), + ("OutMulticastOctets", ctypes.c_uint64), + ("OutBroadcastOctets", ctypes.c_uint64), + ("OutQLen", ctypes.c_uint64), + ] + + class MIB_IF_TABLE2(ctypes.Structure): + # NumEntries then the rows - there is no reserved field here. Adding + # one shifts Table by 8 bytes and every row parses as garbage. + _fields_ = [("NumEntries", wintypes.ULONG), + ("Table", MIB_IF_ROW2 * 1)] + + iphlpapi.GetIfTable2.argtypes = [ctypes.POINTER(ctypes.POINTER(MIB_IF_TABLE2))] + iphlpapi.GetIfTable2.restype = ctypes.c_ulong + + table_ptr = ctypes.POINTER(MIB_IF_TABLE2)() + status = iphlpapi.GetIfTable2(ctypes.byref(table_ptr)) + if status != 0 or not table_ptr: + log.debug("GetIfTable2 returned %s", status) + return {}, {}, False + + try: + count = int(table_ptr.contents.NumEntries) + if not 0 < count < 4096: + log.debug("GetIfTable2 gave an implausible row count: %s", count) + return {}, {}, False + + rows = ctypes.cast( + ctypes.byref(table_ptr.contents.Table), + ctypes.POINTER(MIB_IF_ROW2 * count)).contents + + hardware, connected, types = {}, {}, {} + physical_live = False + for row in rows: + index = int(row.InterfaceIndex) + if not 0 < index < 10_000_000: + log.debug("GetIfTable2 row has a bogus index (%s) - bad layout", index) + return {}, {}, False + media = int(row.MediaConnectState) + is_hardware = bool(row.InterfaceAndOperStatusFlags & 0x01) + is_connected = media == 1 + hardware[index] = is_hardware + connected[index] = is_connected if media in (1, 2) else None + types[index] = int(row.Type) + if is_hardware and is_connected and int(row.Type) in ( + IF_TYPE_ETHERNET, IF_TYPE_WIFI): + physical_live = True + + # Cross-check against the types GetAdaptersAddresses already gave + # us. If the two disagree, this parse is not trustworthy. + for index, iftype in (known_types or {}).items(): + if index in types and types[index] != iftype: + log.warning("GetIfTable2 disagrees with GetAdaptersAddresses on if%s " + "(%s vs %s) - ignoring hardware flags", + index, types[index], iftype) + return {}, {}, False + + return hardware, connected, physical_live + finally: + iphlpapi.FreeMibTable(table_ptr) + except Exception as exc: + log.debug("GetIfTable2 unavailable (%s); ranking without hardware flags", exc) + return {}, {}, False + + +# -------------------------------------------------------------------------- +# Linux collector - `ip -j addr` enriched from sysfs +# -------------------------------------------------------------------------- + +def _sysfs(interface: str, leaf: str) -> str | None: + try: + with open(f"/sys/class/net/{interface}/{leaf}", "r") as handle: + return handle.read().strip() + except OSError: + return None + + +def _linux_gateways() -> set[str]: + """Interfaces owning a default route, from /proc/net/route.""" + owners: set[str] = set() + try: + with open("/proc/net/route", "r") as handle: + next(handle, None) + for line in handle: + parts = line.split() + if len(parts) > 2 and parts[1] == "00000000": + owners.add(parts[0]) + except OSError: + pass + return owners + + +def _collect_linux() -> list[dict]: + try: + raw = subprocess.run(["ip", "-j", "-4", "addr", "show"], + capture_output=True, text=True, timeout=5).stdout + interfaces = json.loads(raw or "[]") + except (OSError, subprocess.SubprocessError, ValueError): + return [] + + gateways = _linux_gateways() + physical_live = False + records: list[dict] = [] + + for iface in interfaces: + name = iface.get("ifname", "") + # The `device` symlink exists only when a real PCI/USB/platform device + # backs the interface - absent for docker0, veth*, tun*, br-*, lo. It is + # the structural equivalent of Windows' HardwareInterface. + is_hardware = os.path.exists(f"/sys/class/net/{name}/device") + is_wireless = os.path.isdir(f"/sys/class/net/{name}/phy80211") or \ + os.path.isdir(f"/sys/class/net/{name}/wireless") + carrier = _sysfs(name, "carrier") + operstate = _sysfs(name, "operstate") + up = (operstate == "up") or ("UP" in (iface.get("flags") or [])) + + iftype = IF_TYPE_WIFI if is_wireless else ( + IF_TYPE_LOOPBACK if name == "lo" else IF_TYPE_ETHERNET) + if is_hardware and carrier == "1" and iftype in (IF_TYPE_ETHERNET, IF_TYPE_WIFI): + physical_live = True + + for addr in iface.get("addr_info", []): + if addr.get("family") != "inet": + continue + records.append({ + "ip": addr.get("local"), + "prefix_length": addr.get("prefixlen"), + "adapter": name, + "description": name, + "if_index": iface.get("ifindex"), + "iftype": iftype, + "oper_status": OPER_STATUS_UP if up else 2, + # `scope: global` is the practical stand-in for Preferred; it + # also drops link-local for free. + "dad_state": DAD_STATE_PREFERRED if addr.get("scope") == "global" else 1, + "prefix_origin": PREFIX_ORIGIN_DHCP if addr.get("dynamic") else 1, + "metric": 0, + "has_gateway": name in gateways, + "gateway": None, + "hardware": is_hardware, + "connected": None if carrier is None else carrier == "1", + "physical_link_present": physical_live, + }) + + for record in records: + record["physical_link_present"] = physical_live + return records + + +# -------------------------------------------------------------------------- +# Public interface +# -------------------------------------------------------------------------- + +_lock = threading.Lock() +_cache: dict | None = None +_cache_at = 0.0 + + +def _collect() -> list[dict]: + if platform.system() == "Windows": + return _collect_windows() + return _collect_linux() + + +def detect(force: bool = False) -> dict: + """ + The current LAN address, re-read live. + + Returns {primary, alternates, rejected, reason, checked_at}. `primary` is + None when there is genuinely nothing usable - the caller must show that + honestly rather than print a stale or invented URL. + """ + global _cache, _cache_at + + with _lock: + # monotonic, never time.time(): the wall clock jumps on NTP sync and on + # resume from sleep, which would freeze or expire the cache wrongly. + now = time.monotonic() + if not force and _cache is not None and (now - _cache_at) < TTL_SECONDS: + return _cache + + try: + records = _collect() + except Exception as exc: + log.warning("address detection failed: %s", exc) + records = [] + + usable, rejected = rank(records) + result = { + "primary": usable[0] if usable else None, + "alternates": usable[1:], + "rejected": rejected, + "reason": None if usable else _reason_for_nothing(rejected), + "checked_at": time.time(), + } + _cache, _cache_at = result, now + return result + + +def primary_address() -> str | None: + """Just the address, for callers that do not care why.""" + found = detect() + return found["primary"]["ip"] if found["primary"] else None + + +REASON_TEXT = { + "wifi_down": "Wi-Fi is off or not connected", + "awaiting_dhcp": "connected, still waiting for an address", + "no_router_on_this_network": "connected, but this network has no router", + "no_physical_adapter": "no network adapter found", + "no_network_interface": "no network interface found", + "no_usable_address": "no usable network address", +} diff --git a/x2_dashboard/backend/plugin_api.py b/x2_dashboard/backend/plugin_api.py new file mode 100644 index 0000000..c5635c1 --- /dev/null +++ b/x2_dashboard/backend/plugin_api.py @@ -0,0 +1,229 @@ +""" +The extension API. + +Drop a ``.py`` file into ``backend/plugins/`` that builds a ``Plugin`` and the +dashboard grows a new panel for it - no frontend work, no server edits. Each +control you declare is rendered by the browser from the manifest this module +produces, and clicking it calls your handler. + +Minimal example:: + + from backend.plugin_api import Plugin + + plugin = Plugin(id="hello", name="Hello", icon="\U0001F44B") + + @plugin.action("wave", label="Wave hello") + async def wave(ctx): + await ctx.bridge.play_preset(motion=1002, area=2) + return "Waved" + +Handlers may be async or plain functions. Whatever they return is shown as the +result toast; raise an exception and the message is surfaced as an error. +""" + +from __future__ import annotations + +import inspect +import time +from dataclasses import dataclass, field +from typing import Any, Callable + + +@dataclass +class Context: + """Everything a handler is given. Passed as the first argument.""" + + bridge: Any + hub: Any + config: dict + storage: dict + plugin_id: str + + @property + def state(self): + """Live robot state - the same object the dashboard renders.""" + return self.bridge.state + + async def log(self, message: str, level: str = "info") -> None: + await self.hub.emit(level, f"plugin:{self.plugin_id}", message) + + async def push(self, key: str, value: Any) -> None: + """Publish a value into the shared state under ``custom``.""" + bucket = self.bridge.state.custom.setdefault(self.plugin_id, {}) + bucket[key] = value + + def record(self, key: str, value: float) -> None: + """Append a sample to a chartable time series.""" + self.hub.record(f"{self.plugin_id}.{key}", value) + + +@dataclass +class Control: + key: str + kind: str + label: str + handler: Callable | None = None + options: dict = field(default_factory=dict) + + def manifest(self) -> dict: + return {"key": self.key, "kind": self.kind, "label": self.label, **self.options} + + +class Plugin: + """A named group of controls that appears as its own card in the Extensions tab.""" + + def __init__(self, id: str, name: str, description: str = "", + icon: str = "◆", order: int = 100, tab: str = "extensions"): + self.id = id + self.name = name + self.description = description + self.icon = icon + self.order = order + self.tab = tab + self.controls: list[Control] = [] + self.readouts: list[dict] = [] + self._on_start: Callable | None = None + self._on_tick: Callable | None = None + self._tick_interval = 1.0 + self.storage: dict = {} + + # -- control declarations ---------------------------------------------- + + def action(self, key: str, label: str = "", style: str = "default", + confirm: str = "", icon: str = "", help: str = ""): + """A button. ``style`` is one of default | primary | warn | danger.""" + def wrap(fn): + self.controls.append(Control(key, "action", label or key, fn, { + "style": style, "confirm": confirm, "icon": icon, "help": help, + })) + return fn + return wrap + + def slider(self, key: str, label: str = "", min: float = 0.0, max: float = 1.0, + step: float = 0.01, default: float = 0.0, unit: str = "", + live: bool = False, help: str = ""): + """A continuous value. ``live=True`` fires while dragging.""" + def wrap(fn): + self.controls.append(Control(key, "slider", label or key, fn, { + "min": min, "max": max, "step": step, "default": default, + "unit": unit, "live": live, "help": help, + })) + return fn + return wrap + + def toggle(self, key: str, label: str = "", default: bool = False, help: str = ""): + def wrap(fn): + self.controls.append(Control(key, "toggle", label or key, fn, { + "default": default, "help": help, + })) + return fn + return wrap + + def select(self, key: str, label: str = "", options: list | None = None, + default: Any = None, help: str = ""): + """``options`` is a list of {"value": ..., "label": ...} or bare strings.""" + def wrap(fn): + normalised = [] + for option in (options or []): + if isinstance(option, dict): + normalised.append(option) + else: + normalised.append({"value": option, "label": str(option)}) + self.controls.append(Control(key, "select", label or key, fn, { + "options": normalised, "default": default, "help": help, + })) + return fn + return wrap + + def text(self, key: str, label: str = "", default: str = "", placeholder: str = "", + multiline: bool = False, submit_label: str = "Send", help: str = ""): + def wrap(fn): + self.controls.append(Control(key, "text", label or key, fn, { + "default": default, "placeholder": placeholder, "multiline": multiline, + "submit_label": submit_label, "help": help, + })) + return fn + return wrap + + def number(self, key: str, label: str = "", min: float | None = None, + max: float | None = None, step: float = 1.0, default: float = 0.0, + unit: str = "", help: str = ""): + def wrap(fn): + self.controls.append(Control(key, "number", label or key, fn, { + "min": min, "max": max, "step": step, "default": default, + "unit": unit, "help": help, + })) + return fn + return wrap + + def color(self, key: str, label: str = "", default: str = "#3987e5", help: str = ""): + def wrap(fn): + self.controls.append(Control(key, "color", label or key, fn, { + "default": default, "help": help, + })) + return fn + return wrap + + # -- readouts ---------------------------------------------------------- + + def readout(self, key: str, label: str, unit: str = "", chart: bool = False, + format: str = "number", precision: int = 2) -> None: + """ + Declare a value this plugin publishes via ``ctx.push(key, value)``. + + ``chart=True`` also draws a sparkline from ``ctx.record(key, value)``. + """ + self.readouts.append({ + "key": key, "label": label, "unit": unit, "chart": chart, + "format": format, "precision": precision, + }) + + # -- lifecycle --------------------------------------------------------- + + def on_start(self, fn): + """Called once when the plugin loads.""" + self._on_start = fn + return fn + + def on_tick(self, interval: float = 1.0): + """Called repeatedly on a background timer.""" + def wrap(fn): + self._on_tick = fn + self._tick_interval = max(0.1, float(interval)) + return fn + return wrap + + # -- introspection ----------------------------------------------------- + + def manifest(self) -> dict: + return { + "id": self.id, + "name": self.name, + "description": self.description, + "icon": self.icon, + "order": self.order, + "tab": self.tab, + "controls": [c.manifest() for c in self.controls], + "readouts": self.readouts, + "has_tick": self._on_tick is not None, + "tick_interval": self._tick_interval, + } + + def find(self, key: str) -> Control | None: + return next((c for c in self.controls if c.key == key), None) + + +async def invoke(handler: Callable, ctx: Context, value: Any = None) -> Any: + """Call a handler, passing ``value`` only when it takes one.""" + signature = inspect.signature(handler) + args = [ctx] + if len(signature.parameters) > 1: + args.append(value) + result = handler(*args) + if inspect.isawaitable(result): + result = await result + return result + + +def now_ms() -> int: + return int(time.time() * 1000) diff --git a/x2_dashboard/backend/plugins/__init__.py b/x2_dashboard/backend/plugins/__init__.py new file mode 100644 index 0000000..9101d15 --- /dev/null +++ b/x2_dashboard/backend/plugins/__init__.py @@ -0,0 +1,8 @@ +""" +Drop-in extension directory. + +Any ``.py`` file here that defines a module-level ``Plugin`` becomes a card in +the Extensions tab. See ``_template.py`` for the shape and ``example_patrol.py`` +for a working one. Press "Reload extensions" in the UI after editing - no +server restart needed. +""" diff --git a/x2_dashboard/backend/plugins/_template.py b/x2_dashboard/backend/plugins/_template.py new file mode 100644 index 0000000..cc636a6 --- /dev/null +++ b/x2_dashboard/backend/plugins/_template.py @@ -0,0 +1,105 @@ +""" +Copy this file, rename it, change the id - you have a new dashboard panel. + +Every control below shows one widget type. Delete what you do not need. +After editing, press "Reload extensions" in the Extensions tab. + +Files starting with an underscore are skipped by the loader, so this template +never appears in the UI until you copy it to a normal name. +""" + +from backend.plugin_api import Plugin + +plugin = Plugin( + id="template", + name="Template", + description="Every control type, as a starting point.", + icon="\U0001F9E9", + order=900, +) + + +# A button. style: default | primary | warn | danger +@plugin.action("hello", label="Say hello", style="primary", icon="\U0001F44B") +async def hello(ctx): + await ctx.bridge.speak("Hello from a dashboard extension") + return "Spoke" + + +# A destructive button asks for confirmation first. +@plugin.action("reset", label="Reset counter", style="danger", + confirm="Reset the stored counter to zero?") +async def reset(ctx): + ctx.storage["count"] = 0 + await ctx.push("count", 0) + return "Counter reset" + + +# A slider. live=True fires continuously while dragging; leave it False to fire +# only on release, which is what you want for anything that moves the robot. +@plugin.slider("speed", label="Cruise speed", min=0.0, max=0.6, + step=0.05, default=0.2, unit="m/s", + help="Applied when the routine below starts.") +async def speed(ctx, value): + ctx.storage["speed"] = value + return f"Speed set to {value:.2f} m/s" + + +@plugin.toggle("verbose", label="Verbose logging", default=False) +async def verbose(ctx, value): + ctx.storage["verbose"] = value + return "Verbose on" if value else "Verbose off" + + +@plugin.select("gait", label="Gait", default="normal", options=[ + {"value": "slow", "label": "Slow and steady"}, + {"value": "normal", "label": "Normal"}, + {"value": "brisk", "label": "Brisk"}, +]) +async def gait(ctx, value): + ctx.storage["gait"] = value + return f"Gait: {value}" + + +@plugin.text("announce", label="Announcement", placeholder="Type something to say", + submit_label="Speak") +async def announce(ctx, value): + result = await ctx.bridge.speak(value, priority=6) + return result.message + + +@plugin.number("repeats", label="Repeat count", min=1, max=10, step=1, default=3) +async def repeats(ctx, value): + ctx.storage["repeats"] = int(value) + return f"Will repeat {int(value)}x" + + +@plugin.color("tint", label="Strip colour", default="#3987e5") +async def tint(ctx, value): + value = value.lstrip("#") + r, g, b = (int(value[i:i + 2], 16) for i in (0, 2, 4)) + result = await ctx.bridge.set_led(mode=0, r=r, g=g, b=b) + return result.message + + +# Declared readouts appear as stat tiles. chart=True adds a sparkline fed by +# ctx.record(). +plugin.readout("count", "Ticks", chart=True, precision=0) +plugin.readout("battery", "Battery seen", unit="%", precision=1) + + +@plugin.on_start +async def start(ctx): + ctx.storage.setdefault("count", 0) + await ctx.log("Template extension loaded") + + +@plugin.on_tick(interval=2.0) +async def tick(ctx): + ctx.storage["count"] = ctx.storage.get("count", 0) + 1 + await ctx.push("count", ctx.storage["count"]) + ctx.record("count", ctx.storage["count"]) + + battery = ctx.state.battery_pct + if battery is not None: + await ctx.push("battery", round(battery, 1)) diff --git a/x2_dashboard/backend/plugins/example_battery_guard.py b/x2_dashboard/backend/plugins/example_battery_guard.py new file mode 100644 index 0000000..d5c3745 --- /dev/null +++ b/x2_dashboard/backend/plugins/example_battery_guard.py @@ -0,0 +1,112 @@ +""" +Battery guard - a worked example of a background monitor. + +Watches the PMU battery level, warns once per threshold crossing, and can drop +the robot into a safe mode before it browns out mid-stride. Demonstrates +on_tick, ctx.push readouts and charted series. +""" + +from backend.plugin_api import Plugin + +plugin = Plugin( + id="battery_guard", + name="Battery guard", + description="Warns on low battery and can auto-safe the robot before it browns out.", + icon="\U0001F50B", + order=20, +) + + +@plugin.slider("warn_at", label="Warn below", min=5, max=60, step=1, default=25, unit="%") +async def warn_at(ctx, value): + ctx.storage["warn_at"] = float(value) + ctx.storage["warned"] = False + return f"Warning threshold set to {value:.0f}%" + + +@plugin.slider("safe_at", label="Auto-safe below", min=1, max=30, step=1, default=10, unit="%", + help="Switches to Damping so the robot settles instead of collapsing.") +async def safe_at(ctx, value): + ctx.storage["safe_at"] = float(value) + ctx.storage["safed"] = False + return f"Auto-safe threshold set to {value:.0f}%" + + +@plugin.toggle("auto_safe", label="Auto-safe enabled", default=False, + help="Off by default - turn on only when you want the robot to act unattended.") +async def auto_safe(ctx, value): + ctx.storage["auto_safe"] = bool(value) + return "Auto-safe armed" if value else "Auto-safe disarmed" + + +@plugin.action("reset_alarms", label="Reset alarms", style="default") +async def reset_alarms(ctx): + ctx.storage["warned"] = False + ctx.storage["safed"] = False + await ctx.push("status", "armed") + return "Alarms reset" + + +plugin.readout("level", "Battery", unit="%", chart=True, precision=1) +plugin.readout("draw", "Draw", unit="A", precision=2) +plugin.readout("status", "Guard status", format="text") +plugin.readout("est_runtime", "Estimated runtime", unit="min", precision=0) + + +@plugin.on_start +async def start(ctx): + ctx.storage.setdefault("warn_at", 25.0) + ctx.storage.setdefault("safe_at", 10.0) + ctx.storage.setdefault("auto_safe", False) + ctx.storage.setdefault("warned", False) + ctx.storage.setdefault("safed", False) + await ctx.push("status", "armed") + + +@plugin.on_tick(interval=3.0) +async def tick(ctx): + level = ctx.state.battery_pct + if level is None: + await ctx.push("status", "no PMU data") + return + + current = ctx.state.battery_current + await ctx.push("level", round(level, 1)) + ctx.record("level", level) + if current is not None: + await ctx.push("draw", round(abs(current), 2)) + + # A crude but useful projection: remaining percent over the observed drain + # rate. Only meaningful while discharging. + history = ctx.hub.series("battery_pct", limit=120) + if len(history) >= 20: + (t0, v0), (t1, v1) = history[0], history[-1] + elapsed = t1 - t0 + drop = v0 - v1 + if elapsed > 5 and drop > 0.01: + minutes = (level / (drop / elapsed)) / 60.0 + await ctx.push("est_runtime", round(min(minutes, 9999), 0)) + + safe_at = ctx.storage["safe_at"] + warn_at = ctx.storage["warn_at"] + + if level <= safe_at: + await ctx.push("status", "critical") + if ctx.storage.get("auto_safe") and not ctx.storage.get("safed"): + ctx.storage["safed"] = True + await ctx.bridge.stop_motion() + outcome = await ctx.bridge.set_mode("DAMPING_DEFAULT") + await ctx.log( + f"Battery {level:.1f}% - auto-safe engaged: {outcome.message}", level="error" + ) + await ctx.bridge.speak("Battery critical. Entering safe mode.", priority=10) + elif level <= warn_at: + await ctx.push("status", "low") + if not ctx.storage.get("warned"): + ctx.storage["warned"] = True + await ctx.log(f"Battery low: {level:.1f}%", level="warn") + await ctx.bridge.set_led(mode=2, r=250, g=178, b=25) + else: + await ctx.push("status", "normal") + ctx.storage["warned"] = False + ctx.storage["safed"] = False diff --git a/x2_dashboard/backend/plugins/example_greeter.py b/x2_dashboard/backend/plugins/example_greeter.py new file mode 100644 index 0000000..2e206b7 --- /dev/null +++ b/x2_dashboard/backend/plugins/example_greeter.py @@ -0,0 +1,95 @@ +""" +Greeter routine - a worked example of sequencing several subsystems. + +Shows how one button can drive mode, motion, speech, screen and lights together, +which is the usual reason to write an extension rather than clicking four tabs. +""" + +import asyncio + +from backend.plugin_api import Plugin + +plugin = Plugin( + id="greeter", + name="Greeter routine", + description="A one-button welcome: stand, wave, speak, smile, glow.", + icon="\U0001F44B", + order=10, +) + +GREETINGS = { + "en": "Hello, I am X2. Nice to meet you.", + "formal": "Good day. Welcome. How may I assist you?", + "short": "Hi there.", +} + + +@plugin.select("phrase", label="Greeting", default="en", options=[ + {"value": "en", "label": "Friendly"}, + {"value": "formal", "label": "Formal"}, + {"value": "short", "label": "Short"}, +]) +async def phrase(ctx, value): + ctx.storage["phrase"] = value + return f"Greeting set to '{value}'" + + +@plugin.toggle("with_lights", label="Include light cue", default=True) +async def with_lights(ctx, value): + ctx.storage["with_lights"] = value + return "Light cue on" if value else "Light cue off" + + +@plugin.action("run", label="Run greeting", style="primary", icon="▶", + help="Requires clear space around the robot.") +async def run(ctx): + if ctx.storage.get("running"): + return {"ok": False, "message": "Greeting already running"} + + ctx.storage["running"] = True + try: + # Preset motions need Stable stand, so get there first if we are not. + if ctx.state.mode != "STAND_DEFAULT": + outcome = await ctx.bridge.set_mode("STAND_DEFAULT") + if not outcome.ok: + return {"ok": False, "message": f"Could not enter Stable stand: {outcome.message}"} + await asyncio.sleep(1.5) + + if ctx.storage.get("with_lights", True): + await ctx.bridge.set_led(mode=1, r=57, g=135, b=229) + + await ctx.bridge.play_emoji(90, mode=1) # Happy + await ctx.bridge.play_preset(motion=1002, area=2) # Right-hand wave + + text = GREETINGS.get(ctx.storage.get("phrase", "en"), GREETINGS["en"]) + await ctx.bridge.speak(text, priority=6) + + ctx.storage["count"] = ctx.storage.get("count", 0) + 1 + await ctx.push("count", ctx.storage["count"]) + await ctx.log(f"Greeting played ({ctx.storage['count']} total)") + return "Greeting played" + finally: + ctx.storage["running"] = False + + +@plugin.action("goodbye", label="Say goodbye", style="default", icon="\U0001F44B") +async def goodbye(ctx): + if ctx.state.mode != "STAND_DEFAULT": + return {"ok": False, "message": "Switch to Stable stand first"} + await ctx.bridge.play_emoji(110, mode=1) # Sad + # TURN_WAVE_HAND (2001), whole body. The documented "wave goodbye" id 3031 + # does not exist in this firmware's McPresetMotion enum. + await ctx.bridge.play_preset(motion=2001, area=11) + await ctx.bridge.speak("Goodbye. See you soon.", priority=6) + return "Goodbye played" + + +plugin.readout("count", "Greetings played", precision=0) + + +@plugin.on_start +async def start(ctx): + ctx.storage.setdefault("count", 0) + ctx.storage.setdefault("phrase", "en") + ctx.storage.setdefault("with_lights", True) + await ctx.push("count", ctx.storage["count"]) diff --git a/x2_dashboard/backend/recovery.py b/x2_dashboard/backend/recovery.py new file mode 100644 index 0000000..4423522 --- /dev/null +++ b/x2_dashboard/backend/recovery.py @@ -0,0 +1,118 @@ +""" +Getting the robot back after a power cycle. + +The X2 cannot reliably bring the dashboard agent up on its own: + + * `systemd --user` units only run while the user has a login session, and the + `agi` account is not allowed to enable lingering (`loginctl enable-linger` + is denied, and sudo forbids running as root). + * The cron fallback does not fire either - the robot's clock jumps backwards + by several hours shortly after boot (RTC vs NTP), and cron stalls on a + backward jump. + +The dashboard host is the dependable machine in this setup, so recovery lives +here instead: find the robot wherever DHCP put it, and start the agent over SSH +if it is not already running. +""" + +from __future__ import annotations + +import asyncio +import time + +from . import netinfo, x2_spec + + +class RecoveryError(Exception): + pass + + +async def find_robot(agent_port: int, ssh_port: int = 22, + networks: list[str] | None = None) -> list[dict]: + """ + Sweep the current subnets for anything that looks like the robot. + + A host already running the agent is the strongest signal; a host answering + on SSH is a candidate we may be able to start the agent on. + """ + cidrs = networks or netinfo.local_networks() + found: list[dict] = [] + + for cidr in cidrs[:3]: + try: + hosts = await netinfo.scan_subnet(cidr, ports=[agent_port, ssh_port], timeout=0.4) + except (ValueError, Exception): + continue + for host in hosts: + open_ports = host.get("open_ports") or [] + found.append({ + "host": host["host"], + "hostname": host.get("hostname"), + "agent": agent_port in open_ports, + "ssh": ssh_port in open_ports, + "latency_ms": host.get("latency_ms"), + }) + + # Anything already running the agent sorts first. + found.sort(key=lambda h: (not h["agent"], not h["ssh"], h["host"])) + return found + + +def _start_over_ssh_blocking(host: str, port: int, user: str, password: str, + command: str, timeout: float = 25.0) -> tuple[bool, str]: + try: + import paramiko + except ImportError: + return False, ("paramiko is not installed on the dashboard host - " + "run: pip install -r requirements.txt") + + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + client.connect(host, port=port, username=user, password=password, + timeout=timeout, allow_agent=False, look_for_keys=False, + banner_timeout=timeout, auth_timeout=timeout) + except Exception as exc: + return False, f"SSH to {user}@{host}:{port} failed: {type(exc).__name__}: {exc}" + + try: + # The helper is idempotent: it exits immediately if the agent is already + # listening, so running it when we raced a manual start is harmless. + stdin, stdout, stderr = client.exec_command(command, timeout=timeout) + stdout.channel.recv_exit_status() + err = stderr.read().decode("utf-8", "replace").strip() + if err and "warning" not in err.lower(): + return True, f"start command ran with stderr: {err[:200]}" + return True, "start command ran" + except Exception as exc: + return False, f"Running the start command failed: {exc}" + finally: + client.close() + + +async def start_agent(host: str, config: dict) -> tuple[bool, str]: + """Log in and run the agent starter. Returns (attempted_ok, message).""" + user = (config.get("robot_ssh_user") or "").strip() + password = config.get("robot_ssh_password") or "" + command = (config.get("agent_start_command") or "").strip() + ssh_port = int(config.get("robot_ssh_port") or 22) + + if not user or not command: + return False, "SSH user or start command is not configured" + if not password: + return False, ("No SSH password saved. Add it in Settings so the dashboard can " + "start the agent after the robot reboots.") + + return await asyncio.to_thread( + _start_over_ssh_blocking, host, ssh_port, user, password, command) + + +async def wait_for_agent(host: str, port: int, timeout: float = 45.0) -> bool: + """Poll until the agent's port opens, or give up.""" + deadline = time.time() + timeout + while time.time() < deadline: + info = await netinfo.probe_host(host, ports=[port], timeout=1.0) + if info.get("reachable"): + return True + await asyncio.sleep(2.0) + return False diff --git a/x2_dashboard/backend/registry.py b/x2_dashboard/backend/registry.py new file mode 100644 index 0000000..fa19dfc --- /dev/null +++ b/x2_dashboard/backend/registry.py @@ -0,0 +1,203 @@ +""" +Plugin discovery, loading and dispatch. + +Scans ``backend/plugins/*.py``, imports each one, and collects any module-level +``Plugin`` instance. Reloading is supported at runtime so you can edit a plugin +and press "Reload" in the Extensions tab without restarting the server. + +A plugin that fails to import does not take the dashboard down - the error is +recorded and shown in the UI next to the plugin that caused it. +""" + +from __future__ import annotations + +import asyncio +import importlib +import importlib.util +import sys +import traceback +from pathlib import Path + +from .plugin_api import Context, Plugin, invoke + +PLUGIN_DIR = Path(__file__).resolve().parent / "plugins" + + +class Registry: + def __init__(self, hub, config: dict): + self.hub = hub + self.config = config + self.bridge = None + self.plugins: dict[str, Plugin] = {} + self.errors: list[dict] = [] + self._tasks: dict[str, asyncio.Task] = {} + self._storage: dict[str, dict] = {} + + def attach(self, bridge) -> None: + self.bridge = bridge + + # -- loading ------------------------------------------------------------ + + async def load(self) -> dict: + """Import every plugin file. Safe to call repeatedly.""" + await self._stop_tasks() + self.plugins.clear() + self.errors.clear() + + PLUGIN_DIR.mkdir(parents=True, exist_ok=True) + init = PLUGIN_DIR / "__init__.py" + if not init.exists(): + init.write_text("", encoding="utf-8") + + # A leading underscore marks a file as private: __init__.py and the + # _template.py starting point are both skipped. + for path in sorted(PLUGIN_DIR.glob("*.py")): + if path.name.startswith("_"): + continue + self._load_file(path) + + for plugin in self.plugins.values(): + plugin.storage = self._storage.setdefault(plugin.id, {}) + await self._start_plugin(plugin) + + summary = { + "loaded": sorted(self.plugins), + "errors": list(self.errors), + "count": len(self.plugins), + } + if self.errors: + await self.hub.emit("warn", "plugins", + f"{len(self.plugins)} plugin(s) loaded, {len(self.errors)} failed") + else: + await self.hub.emit("info", "plugins", f"{len(self.plugins)} plugin(s) loaded") + return summary + + def _load_file(self, path: Path) -> None: + module_name = f"backend.plugins.{path.stem}" + try: + # Always build a fresh module from the file rather than calling + # importlib.reload. reload() requires the parent package to be in + # sys.modules and re-runs stale bytecode paths; executing the file + # afresh is both simpler and a true reload of what is on disk. + spec = importlib.util.spec_from_file_location(module_name, path) + if spec is None or spec.loader is None: + raise ImportError(f"Cannot build import spec for {path.name}") + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + + found = [v for v in vars(module).values() if isinstance(v, Plugin)] + if not found: + self.errors.append({ + "file": path.name, + "error": "No Plugin instance found at module level", + "trace": "", + }) + return + + for plugin in found: + if plugin.id in self.plugins: + self.errors.append({ + "file": path.name, + "error": f"Duplicate plugin id '{plugin.id}' - ignoring this one", + "trace": "", + }) + continue + self.plugins[plugin.id] = plugin + + except Exception as exc: + self.errors.append({ + "file": path.name, + "error": f"{type(exc).__name__}: {exc}", + "trace": traceback.format_exc(limit=6), + }) + sys.modules.pop(module_name, None) + + async def _start_plugin(self, plugin: Plugin) -> None: + ctx = self.context(plugin) + if plugin._on_start: + try: + await invoke(plugin._on_start, ctx) + except Exception as exc: + self.errors.append({ + "file": plugin.id, + "error": f"on_start failed: {exc}", + "trace": traceback.format_exc(limit=6), + }) + if plugin._on_tick: + self._tasks[plugin.id] = asyncio.create_task( + self._tick_loop(plugin), name=f"plugin-{plugin.id}" + ) + + async def _tick_loop(self, plugin: Plugin) -> None: + ctx = self.context(plugin) + failures = 0 + while True: + try: + await asyncio.sleep(plugin._tick_interval) + await invoke(plugin._on_tick, ctx) + failures = 0 + except asyncio.CancelledError: + raise + except Exception as exc: + failures += 1 + await self.hub.emit("error", f"plugin:{plugin.id}", f"Tick failed: {exc}") + if failures >= 5: + await self.hub.emit("warn", f"plugin:{plugin.id}", + "Tick disabled after 5 consecutive failures") + return + await asyncio.sleep(2.0) + + async def _stop_tasks(self) -> None: + for task in self._tasks.values(): + task.cancel() + for task in list(self._tasks.values()): + try: + await task + except (asyncio.CancelledError, Exception): + pass + self._tasks.clear() + + async def shutdown(self) -> None: + await self._stop_tasks() + + # -- dispatch ----------------------------------------------------------- + + def context(self, plugin: Plugin) -> Context: + return Context( + bridge=self.bridge, + hub=self.hub, + config=self.config, + storage=self._storage.setdefault(plugin.id, {}), + plugin_id=plugin.id, + ) + + async def dispatch(self, plugin_id: str, control_key: str, value=None) -> dict: + plugin = self.plugins.get(plugin_id) + if plugin is None: + return {"ok": False, "message": f"No plugin '{plugin_id}'"} + + control = plugin.find(control_key) + if control is None or control.handler is None: + return {"ok": False, "message": f"No control '{control_key}' in '{plugin_id}'"} + + try: + result = await invoke(control.handler, self.context(plugin), value) + except Exception as exc: + await self.hub.emit("error", f"plugin:{plugin_id}", f"{control_key}: {exc}") + return {"ok": False, "message": f"{type(exc).__name__}: {exc}", + "detail": traceback.format_exc(limit=4)} + + if isinstance(result, dict) and "ok" in result: + return result + return {"ok": True, "message": str(result) if result is not None else "Done"} + + # -- introspection ------------------------------------------------------ + + def manifest(self) -> dict: + return { + "plugins": sorted((p.manifest() for p in self.plugins.values()), + key=lambda m: (m["order"], m["name"])), + "errors": list(self.errors), + "directory": str(PLUGIN_DIR), + } diff --git a/x2_dashboard/backend/server.py b/x2_dashboard/backend/server.py new file mode 100644 index 0000000..2791381 --- /dev/null +++ b/x2_dashboard/backend/server.py @@ -0,0 +1,1062 @@ +""" +HTTP + WebSocket server for the AGIBOT X2 dashboard. + +Binds 0.0.0.0 so the dashboard answers on every interface this machine holds. +The browser derives its API and WebSocket URLs from window.location, so opening +the page from a laptop, a phone, or a tablet all work with no configuration and +no hardcoded address anywhere. +""" + +from __future__ import annotations + +import asyncio +import contextlib +import hashlib +import re +import time +from pathlib import Path +from typing import Any + +from fastapi import Body, FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import FileResponse, JSONResponse, Response +from fastapi.staticfiles import StaticFiles + +from . import netinfo, settings, voice_session, x2_spec +from .bridge_agent import AgentBridge +from .bridge_mock import MockBridge +from .hub import Hub +from .registry import Registry + +ROOT = Path(__file__).resolve().parent.parent +WEB_DIR = ROOT / "web" + +app = FastAPI(title="AGIBOT X2 Dashboard", version="1.0.0", docs_url="/api/docs") + +# The dashboard is meant to be opened from any device on the LAN, so the browser +# origin varies with whichever IP was used to reach it. +app.add_middleware( + CORSMiddleware, + allow_origin_regex=r"https?://.*", + allow_credentials=False, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.middleware("http") +async def track_clients(request: Request, call_next): + """ + Remember which devices have actually reached this server. + + This is the only way to tell, without standing next to the person holding + the phone, whether a failure is "the phone cannot resolve the name" or "the + phone cannot reach this machine at all". The first is an mDNS/multicast + problem; the second is the network or the firewall. They need opposite fixes. + """ + client = request.client.host if request.client else None + if client and client not in ("127.0.0.1", "::1"): + seen = runtime.clients_seen.setdefault(client, {"first": time.time(), "hits": 0}) + seen["hits"] += 1 + seen["last"] = time.time() + seen["agent"] = (request.headers.get("user-agent") or "")[:120] + return await call_next(request) + + +@app.middleware("http") +async def no_stale_frontend(request: Request, call_next): + """ + Stop browsers serving a stale frontend. + + The dashboard ships unversioned filenames, so a browser that cached + /js/tabs/vision.js will happily keep running it against a newer API - which + is exactly how the Vision tab ended up throwing "Cannot convert undefined or + null to object" after the camera list changed shape. + + `no-store` rather than `no-cache`: no-cache still permits the browser to + keep the entry and reuse it under heuristic freshness, which is how a copy + stored *before* these headers existed survives a normal reload. no-store + forbids storing it at all. Combined with the build-stamped import URLs in + version_js() below, one ordinary reload is always enough. + + API responses are untouched; they set their own caching. + """ + response = await call_next(request) + path = request.url.path + if path.startswith("/model/"): + # The exception. /model/model.bin is 1.4 MB of baked geometry that only + # changes when build_model.py is re-run, and the Twin tab fetches it on + # every visit. Re-downloading that over the robot's Wi-Fi to redraw the + # same unchanged robot is precisely the waste the rest of this dashboard + # goes out of its way to avoid. + response.headers["Cache-Control"] = "public, max-age=604800" + elif not path.startswith("/api/") and path != "/ws": + response.headers["Cache-Control"] = "no-store, must-revalidate" + response.headers["Pragma"] = "no-cache" + return response + + +# -------------------------------------------------------------------------- +# Frontend serving with build-stamped module URLs +# -------------------------------------------------------------------------- + +# Matches the module specifiers this codebase uses: `from './core.js'`, +# `from '../ui.js'`, `import('./tabs/x.js')`. Deliberately narrow - it only +# touches relative paths ending in .js that sit in an import position. +_IMPORT_RE = re.compile( + r"""(\bfrom\s+|\bimport\s*\(\s*)(['"])(\.{1,2}/[^'"]+?\.js)\2""" +) + + +def frontend_build() -> str: + """A short hash of every file under web/, so any edit changes the URL.""" + parts = [] + for path in sorted(WEB_DIR.rglob("*")): + if path.is_file(): + stat = path.stat() + parts.append(f"{path.name}:{stat.st_mtime_ns}:{stat.st_size}") + return hashlib.sha1("|".join(parts).encode()).hexdigest()[:12] + + +def version_js(source: str, build: str) -> str: + """ + Stamp every relative import with the current build. + + Versioning only the entry point is not enough: the browser would fetch a + fresh main.js and then satisfy its `./core.js` import from cache. Rewriting + the whole module graph means one navigation pulls a consistent set. + """ + return _IMPORT_RE.sub( + lambda m: f"{m.group(1)}{m.group(2)}{m.group(3)}?b={build}{m.group(2)}", + source, + ) + + +def _safe_web_path(*parts: str) -> Path: + target = (WEB_DIR.joinpath(*parts)).resolve() + if not str(target).startswith(str(WEB_DIR.resolve())): + raise HTTPException(status_code=404, detail="Not found") + return target + + +@app.get("/js/{path:path}") +async def serve_module(path: str): + target = _safe_web_path("js", path) + if not target.is_file() or target.suffix != ".js": + raise HTTPException(status_code=404, detail="Not found") + body = version_js(target.read_text(encoding="utf-8"), frontend_build()) + return Response(body, media_type="text/javascript; charset=utf-8", + headers={"Cache-Control": "no-store"}) + + +class Runtime: + """Holds the live objects the request handlers reach for.""" + + def __init__(self) -> None: + config = settings.load() + self.hub = Hub(history_seconds=config["history_seconds"], + sample_hz=config["telemetry_hz"]) + self.registry = Registry(self.hub, config) + self.bridge = None + self.bridge_error = "" + self.started_at = time.time() + self._scan_task: asyncio.Task | None = None + self.announcer = None + self.clients_seen: dict[str, dict] = {} + + # -- name advertisement ------------------------------------------------- + + def start_announcer(self) -> None: + """ + Publish .local so the link is about the robot. + + Deliberately runs inside this process rather than as a helper: on + Windows the inbound firewall rules for UDP 5353 are program-scoped, and + this interpreter is the one already permitted to receive traffic from + other devices. A helper under a different interpreter would answer every + local test and still be invisible to a phone. + """ + config = settings.load() + if not config.get("advertise_name"): + return + name = (config.get("dashboard_name") or "").strip() + if not name: + return + + from .announce import Announcer + + self.announcer = Announcer( + name=name, + port=int(config.get("port") or 8770), + address_provider=netinfo.primary_address, + ) + if not self.announcer.start(): + # Not fatal - the IP and the PC's own name still work. + self.hub.log("warn", "network", + f"Could not advertise {self.announcer.name}: {self.announcer.error}") + + def stop_announcer(self) -> None: + if self.announcer is not None: + self.announcer.stop() + self.announcer = None + + # -- live address watching ---------------------------------------------- + + async def watch_address(self) -> None: + """ + Re-check the LAN address continuously and push changes to open pages. + + The published URL is only useful if it is current. Roaming to another + Wi-Fi, a DHCP renewal or simply unplugging changes it, and a browser + left open on the Settings tab would otherwise keep showing an address + that stopped working. Detection costs ~4 ms and is cached for 2 s, so + this loop is effectively free. + """ + last: str | None = None + misses = 0 + + while True: + try: + await asyncio.sleep(3.0) + detail = await asyncio.to_thread(netinfo.address_detail) + current = detail["ip"] + + # A brief gap is normal during a DHCP renewal or a roam, so do + # not announce "no network" on the first empty read. But never + # keep showing an address we know is gone. + if current is None: + misses += 1 + if misses < 2 and last is not None: + continue + else: + misses = 0 + + if current == last: + continue + + if last is not None: + where = current or detail["reason_text"] or "no network" + await self.hub.emit("info", "network", + f"Dashboard address changed: {last} -> {where}") + last = current + + config = settings.load() + await self.hub.broadcast("network", { + "urls": netinfo.dashboard_urls(config["port"], + config.get("dashboard_name")), + "address": detail, + "port": config["port"], + }) + + # Keep the advertised name pointing at the new address. + if self.announcer is not None and current: + self.announcer.ip = current + except asyncio.CancelledError: + raise + except Exception as exc: + log_once = getattr(self, "_watch_warned", False) + if not log_once: + self._watch_warned = True + await self.hub.emit("warn", "network", + f"Address watcher error: {exc}") + await asyncio.sleep(5.0) + + # -- bridge selection --------------------------------------------------- + + async def start_bridge(self) -> None: + config = settings.load() + mode = config.get("bridge_mode", "auto") + self.bridge_error = "" + + if mode in ("auto", "agent"): + # With auto-discovery on we can start without a saved address - the + # bridge sweeps the network for the robot itself. + if config.get("robot_host") or config.get("auto_discover"): + try: + self.bridge = AgentBridge(self.hub, config) + await self.bridge.start() + self.registry.attach(self.bridge) + return + except Exception as exc: + self.bridge_error = str(exc) + self.bridge = None + await self.hub.emit("error", "bridge", f"Agent bridge failed: {exc}") + if mode == "agent": + raise + else: + self.bridge_error = "No robot host is configured." + if mode == "agent": + raise RuntimeError( + "bridge_mode is 'agent' but no robot_host is set. " + "Set it in the Settings tab or pass --robot ." + ) + await self.hub.emit( + "warn", "bridge", + "No robot host configured - running in simulation. " + "Set the robot address in Settings to attach to the real X2.", + ) + + self.bridge = MockBridge(self.hub, config) + await self.bridge.start() + self.registry.attach(self.bridge) + + async def stop_bridge(self) -> None: + if self.bridge is not None: + with contextlib.suppress(Exception): + await self.bridge.stop() + self.bridge = None + + async def restart_bridge(self) -> dict: + await self.stop_bridge() + try: + await self.start_bridge() + except Exception as exc: + self.bridge_error = str(exc) + return {"ok": False, "message": str(exc)} + await self.registry.load() + return {"ok": True, "message": f"Bridge restarted ({self.bridge.name})", + "detail": {"transport": self.bridge.name}} + + +runtime = Runtime() + + +def require_bridge(): + if runtime.bridge is None: + raise HTTPException(status_code=503, detail="No bridge is running. Check the Settings tab.") + return runtime.bridge + + +def result(command_result) -> JSONResponse: + payload = command_result.as_dict() + return JSONResponse(payload, status_code=200 if payload["ok"] else 400) + + +# -------------------------------------------------------------------------- +# Lifecycle +# -------------------------------------------------------------------------- + +@app.on_event("startup") +async def _startup() -> None: + runtime.start_announcer() + runtime.address_task = asyncio.create_task(runtime.watch_address(), name="address-watch") + await runtime.start_bridge() + await runtime.registry.load() + + +@app.on_event("shutdown") +async def _shutdown() -> None: + task = getattr(runtime, "address_task", None) + if task: + task.cancel() + with contextlib.suppress(asyncio.CancelledError, Exception): + await task + runtime.stop_announcer() + await runtime.registry.shutdown() + await runtime.stop_bridge() + + +# -------------------------------------------------------------------------- +# Bootstrap and state +# -------------------------------------------------------------------------- + +@app.get("/api/bootstrap") +async def bootstrap() -> dict: + """One request the page makes on load: spec, config, state, plugins, network.""" + config = settings.load() + return { + "spec": x2_spec.client_spec(), + "settings": settings.describe(), + "state": runtime.bridge.snapshot() if runtime.bridge else None, + "plugins": runtime.registry.manifest(), + "events": runtime.hub.events(120), + "bridge": { + "name": runtime.bridge.name if runtime.bridge else "none", + "simulated": runtime.bridge.simulated if runtime.bridge else True, + "online": bool(runtime.bridge and runtime.bridge.state.connection.online), + "error": runtime.bridge_error or ( + runtime.bridge.state.connection.error if runtime.bridge else ""), + "agent": (runtime.bridge.state.custom.get("agent") + if runtime.bridge else None), + "host": config.get("robot_host", ""), + "agent_port": config.get("agent_port", x2_spec.AGENT_PORT), + }, + "network": { + "addresses": netinfo.local_addresses(), + "networks": netinfo.local_networks(), + "urls": netinfo.dashboard_urls(config["port"], config.get("dashboard_name")), + "address": netinfo.address_detail(), + "advertised": runtime.announcer.status() if runtime.announcer else None, + "port": config["port"], + }, + "server": { + "version": app.version, + "uptime_s": round(time.time() - runtime.started_at, 1), + "clients": runtime.hub.client_count, + }, + } + + +@app.get("/api/state") +async def get_state() -> dict: + return require_bridge().snapshot() + + +@app.get("/api/series") +async def get_series(keys: str = "", limit: int = 600) -> dict: + if keys: + wanted = [k.strip() for k in keys.split(",") if k.strip()] + return {k: runtime.hub.series(k, limit) for k in wanted} + return runtime.hub.all_series(limit) + + +@app.get("/api/series/keys") +async def series_keys() -> dict: + return {"keys": runtime.hub.series_keys()} + + +@app.get("/api/events") +async def get_events(limit: int = 200) -> dict: + return {"events": runtime.hub.events(limit)} + + +@app.get("/api/topics") +async def get_topics(graph: bool = False) -> dict: + """Topic liveness, plus the full ROS graph on request (it is a heavy call).""" + bridge = require_bridge() + payload = { + "tracked": await bridge.list_topics(), + "documented": x2_spec.SENSOR_TOPICS, + "graph": {"topics": [], "services": [], "nodes": []}, + } + if graph and hasattr(bridge, "graph"): + try: + payload["graph"] = await bridge.graph() + except Exception as exc: + payload["graph_error"] = str(exc) + return payload + + +@app.get("/api/health") +async def health() -> dict: + bridge = runtime.bridge + return { + "ok": bridge is not None and bridge.state.connection.online, + "bridge": bridge.name if bridge else "none", + "simulated": bridge.simulated if bridge else True, + "clients": runtime.hub.client_count, + "uptime_s": round(time.time() - runtime.started_at, 1), + } + + +# -------------------------------------------------------------------------- +# Settings and networking +# -------------------------------------------------------------------------- + +@app.get("/api/settings") +async def get_settings() -> dict: + return settings.describe() + + +@app.post("/api/settings") +async def post_settings(payload: dict = Body(...)) -> dict: + before = settings.load() + after = settings.save(payload) + + # Changing any of these means the bridge has to be rebuilt to take effect. + restart_keys = ("robot_host", "ros_domain_id", "rmw_implementation", "bridge_mode") + needs_restart = any(before.get(k) != after.get(k) for k in restart_keys) + + if runtime.bridge is not None: + await runtime.bridge.reconfigure(after) + runtime.registry.config = after + + await runtime.hub.broadcast("settings", settings.describe()) + return {"ok": True, "settings": settings.describe(), "needs_restart": needs_restart} + + +@app.get("/api/network") +async def get_network() -> dict: + config = settings.load() + + local = {a["address"] for a in netinfo.local_addresses()} + others = [ + {"address": ip, **info} + for ip, info in sorted(runtime.clients_seen.items()) + if ip not in local and ip != config.get("robot_host") + ] + + return { + "addresses": netinfo.local_addresses(), + "networks": netinfo.local_networks(), + "urls": netinfo.dashboard_urls(config["port"], config.get("dashboard_name")), + "address": netinfo.address_detail(), + "advertised": runtime.announcer.status() if runtime.announcer else None, + # Devices other than this PC that have loaded the dashboard. Proof of + # what a phone can and cannot reach. + "other_devices": others, + "port": config["port"], + "robot_host": config["robot_host"], + "pc1_warning": x2_spec.PC1_MOTION_CONTROL_IP, + } + + +@app.post("/api/network/probe") +async def post_probe(payload: dict = Body(...)) -> dict: + host = str(payload.get("host", "")).strip() + if not host: + raise HTTPException(status_code=400, detail="host is required") + resolved = await netinfo.resolve(host) + if resolved is None: + return {"ok": False, "message": f"Could not resolve '{host}'"} + info = await netinfo.probe_host(resolved) + info["input"] = host + return {"ok": info["reachable"], "detail": info, + "message": (f"{resolved} answered on ports {info['open_ports']}" + if info["reachable"] else f"{resolved} did not answer on any known port")} + + +@app.post("/api/network/scan") +async def post_scan(payload: dict = Body(default={})) -> dict: + """ + Sweep a subnet for the robot. Defaults to whichever networks this machine is + on right now, so moving between Wi-Fi networks needs no reconfiguration. + """ + cidrs = payload.get("networks") or netinfo.local_networks() + if not cidrs: + return {"ok": False, "message": "No usable network interface found", "hosts": []} + + async def progress(done: int, total: int) -> None: + await runtime.hub.broadcast("scan_progress", {"done": done, "total": total}) + + found: list[dict] = [] + for cidr in cidrs[:3]: + try: + found.extend(await netinfo.scan_subnet(cidr, progress=progress)) + except ValueError as exc: + await runtime.hub.emit("warn", "network", str(exc)) + except Exception as exc: + await runtime.hub.emit("error", "network", f"Scan of {cidr} failed: {exc}") + + local = {a["address"] for a in netinfo.local_addresses()} + for host in found: + host["is_self"] = host["host"] in local + + await runtime.hub.emit("info", "network", + f"Scan finished: {len(found)} responding host(s) across {len(cidrs[:3])} network(s)") + return {"ok": True, "hosts": found, "networks": cidrs[:3], + "message": f"{len(found)} host(s) responding"} + + +@app.post("/api/bridge/restart") +async def post_bridge_restart() -> dict: + return await runtime.restart_bridge() + + +# -------------------------------------------------------------------------- +# Robot commands +# -------------------------------------------------------------------------- + +@app.post("/api/mode") +async def post_mode(payload: dict = Body(...)): + mode = str(payload.get("mode", "")) + if mode == "PASSIVE_DEFAULT" and settings.get("require_confirm_zero_torque", True): + if not payload.get("confirmed"): + raise HTTPException( + status_code=428, + detail="Zero-torque drops all holding force. Re-send with confirmed=true.", + ) + return result(await require_bridge().set_mode(mode)) + + +@app.get("/api/mode") +async def get_mode(): + return result(await require_bridge().get_mode()) + + +@app.post("/api/velocity") +async def post_velocity(payload: dict = Body(...)): + config = settings.load() + + def clamp(value: Any, cap: float) -> float: + try: + value = float(value) + except (TypeError, ValueError): + return 0.0 + return max(-cap, min(cap, value)) + + return result(await require_bridge().set_velocity( + clamp(payload.get("forward", 0), config["max_forward_velocity"]), + clamp(payload.get("lateral", 0), config["max_lateral_velocity"]), + clamp(payload.get("angular", 0), config["max_angular_velocity"]), + )) + + +@app.post("/api/stop") +async def post_stop(): + bridge = require_bridge() + outcome = await bridge.stop_motion() + await runtime.hub.emit("warn", "control", "Stop issued from dashboard") + return result(outcome) + + +@app.post("/api/preset") +async def post_preset(payload: dict = Body(...)): + key = payload.get("key") + if key: + preset = next((p for p in x2_spec.PRESET_MOTIONS if p["key"] == key), None) + if preset is None: + raise HTTPException(status_code=400, detail=f"Unknown preset '{key}'") + motion, area = preset["motion"], preset["area"] + else: + motion, area = int(payload.get("motion", 0)), int(payload.get("area", 0)) + + return result(await require_bridge().play_preset( + motion, area, bool(payload.get("interrupt", True)) + )) + + +@app.post("/api/joints") +async def post_joints(payload: dict = Body(...)): + group = str(payload.get("group", "")) + mode = str(payload.get("mode", "position")) + targets = payload.get("targets") or {} + if not isinstance(targets, dict): + raise HTTPException(status_code=400, detail="targets must be an object of joint -> value") + return result(await require_bridge().set_joints( + group, mode, targets, + payload.get("stiffness"), payload.get("damping"), + )) + + +@app.post("/api/hand") +async def post_hand(payload: dict = Body(...)): + side = str(payload.get("side", "right")) + preset_key = payload.get("preset") + if preset_key: + preset = next((p for p in x2_spec.HAND_PRESETS if p["key"] == preset_key), None) + if preset is None: + raise HTTPException(status_code=400, detail=f"Unknown hand preset '{preset_key}'") + positions = preset["positions"] + else: + positions = payload.get("positions") or [] + return result(await require_bridge().set_hand(side, [float(v) for v in positions])) + + +@app.post("/api/speak") +async def post_speak(payload: dict = Body(...)): + return result(await require_bridge().speak( + str(payload.get("text", "")), + int(payload.get("priority", 6)), + bool(payload.get("interrupt", False)), + )) + + +@app.post("/api/volume") +async def post_volume(payload: dict = Body(...)): + return result(await require_bridge().set_volume(int(payload.get("volume", 60)))) + + +@app.post("/api/mute") +async def post_mute(payload: dict = Body(...)): + return result(await require_bridge().set_mute(bool(payload.get("muted", False)))) + + +# -------------------------------------------------------------------------- +# Voice session - the conversational loop (Muza / Lumi) +# -------------------------------------------------------------------------- + +@app.get("/api/voice/session") +async def get_voice_session() -> dict: + return await asyncio.to_thread(voice_session.snapshot) + + +@app.post("/api/voice/session") +async def post_voice_session(payload: dict = Body(...)) -> dict: + """Apply the operator's selection, then greet if it was switched on. + + systemctl blocks for a second or two, so it runs off the event loop - the + telemetry websocket must keep flowing while the unit restarts. + """ + outcome = await asyncio.to_thread( + voice_session.apply, + bool(payload.get("enabled", False)), + payload.get("gender"), + payload.get("language"), + payload.get("model"), + ) + + if not outcome.get("ok"): + raise HTTPException(status_code=400, detail=outcome.get("error", "apply failed")) + + # The dashboard deliberately does NOT speak the greeting. Both voice paths + # now render it themselves in the selected character's voice - Gemini in + # gemini/script.py, LinkSoul in linksoul/runner.py - because the only tool + # available here is the robot's built-in PlayTts, whose request message has + # `voice_id` commented out by the vendor. That engine has exactly one voice, + # so it announced the female character in a male voice on every Apply. + await runtime.hub.broadcast("voice_session", outcome["snapshot"]) + return outcome + + +@app.post("/api/emoji") +async def post_emoji(payload: dict = Body(...)): + return result(await require_bridge().play_emoji( + int(payload.get("emotion_id", 1)), + int(payload.get("mode", 1)), + int(payload.get("priority", 6)), + )) + + +@app.post("/api/led") +async def post_led(payload: dict = Body(...)): + def channel(name: str) -> int: + return max(0, min(255, int(payload.get(name, 0)))) + + # keep=True asks the bridge to re-assert this setting periodically, because + # the robot's task_manager reclaims the strip on its own after about a + # minute. See led_keepalive() in agent/x2_agent.py. + return result(await require_bridge().set_led( + int(payload.get("mode", 0)), channel("r"), channel("g"), channel("b"), + int(payload.get("priority", x2_spec.LED_DEFAULT_PRIORITY)), + keep=bool(payload.get("keep", True)), + )) + + +@app.post("/api/input-source") +async def post_input_source(payload: dict = Body(...)): + source = x2_spec.DASHBOARD_INPUT_SOURCE + return result(await require_bridge().register_input_source( + str(payload.get("name", source["name"])), + int(payload.get("priority", source["priority"])), + int(payload.get("timeout", source["timeout"])), + )) + + +@app.post("/api/raw/publish") +async def post_raw_publish(payload: dict = Body(...)): + return result(await require_bridge().publish_raw( + str(payload.get("topic", "")), + str(payload.get("type", "")), + payload.get("fields") or {}, + )) + + +@app.post("/api/raw/service") +async def post_raw_service(payload: dict = Body(...)): + return result(await require_bridge().call_service( + str(payload.get("service", "")), + str(payload.get("type", "")), + payload.get("fields") or {}, + )) + + +# -------------------------------------------------------------------------- +# Camera +# -------------------------------------------------------------------------- + +@app.get("/api/streams") +async def get_streams() -> dict: + """Which feeds are subscribed on the robot right now.""" + bridge = require_bridge() + outcome = await bridge.list_streams() + return { + "ok": outcome.ok, + "message": outcome.message, + "streams": (outcome.detail or {}).get("streams", {}) if outcome.ok else {}, + "cameras": x2_spec.CAMERAS, + "lidar": x2_spec.LIDAR, + } + + +@app.post("/api/streams/{key}") +async def post_stream(key: str, payload: dict = Body(default={})): + """ + Switch a camera or the LiDAR on or off. + + Nothing is subscribed on the robot until this is called. A camera frame here + is 170-430 KB and the LiDAR pushes 816 KB a scan, so leaving them all + running would compete with the robot's own traffic for pictures nobody is + looking at. + """ + known = {c["key"] for c in x2_spec.CAMERAS} | {x2_spec.LIDAR["key"]} + if key not in known: + raise HTTPException(status_code=404, detail=f"Unknown stream '{key}'") + return result(await require_bridge().set_stream(key, bool(payload.get("active", False)))) + + +@app.get("/api/lidar/points") +async def get_lidar_points(): + outcome = await require_bridge().lidar_points() + if not outcome.ok: + # "Off" is an ordinary state, not a failure - the browser polls this and + # a 4xx per poll would fill the console for something working correctly. + return JSONResponse({"ok": False, "message": outcome.message, + "off": bool((outcome.detail or {}).get("off")), + "points": []}, status_code=200) + return JSONResponse({"ok": True, **(outcome.detail or {})}) + + +@app.get("/api/camera/{camera_key}/frame") +async def camera_frame(camera_key: str, stream: str = "rgb", flip: bool = False): + bridge = require_bridge() + if not any(c["key"] == camera_key for c in x2_spec.CAMERAS): + raise HTTPException(status_code=404, detail=f"Unknown camera '{camera_key}'") + + data = await bridge.camera_frame(camera_key, stream, flip=flip) + if not data: + # 204, not an error status. A camera whose topic has no publisher is a + # normal state on this robot (the perception debug feeds only run with + # that module), and an error status makes every browser log a failed + # request several times a second for something that is working as + # intended. 404 above still covers a camera that does not exist. + return Response(status_code=204, headers={"Cache-Control": "no-store"}) + + content_type = "image/jpeg" + getter = getattr(bridge, "frame_content_type", None) + if callable(getter): + try: + content_type = getter(camera_key, stream) + except TypeError: + content_type = getter() + + return Response(content=data, media_type=content_type, + headers={"Cache-Control": "no-store"}) + + +@app.get("/api/qr") +async def qr_code(url: str = "") -> Response: + """ + A QR code for a dashboard URL. + + Typing an IP address into a phone is exactly the friction that makes people + want a name in the first place. A QR of the numeric URL sidesteps the whole + naming question: it needs no mDNS, no multicast and no DNS, so it works even + on a Wi-Fi that isolates clients from each other. + """ + config = settings.load() + if not url: + address = netinfo.primary_address() + if not address: + raise HTTPException(status_code=503, detail="No LAN address to encode") + url = f"http://{address}:{config['port']}" + + try: + import io + + import qrcode + import qrcode.image.svg + except ImportError: + raise HTTPException( + status_code=501, + detail="qrcode is not installed - run: pip install -r requirements.txt", + ) + + image = qrcode.make(url, image_factory=qrcode.image.svg.SvgPathImage, box_size=10, border=2) + buffer = io.BytesIO() + image.save(buffer) + return Response(buffer.getvalue(), media_type="image/svg+xml", + headers={"Cache-Control": "no-store"}) + + +@app.post("/api/robot/find") +async def robot_find() -> dict: + """ + Sweep the current network for the robot, from the offline screen. + + Reports both hosts already running the agent and hosts that merely answer + on SSH, because the second kind can usually be started. + """ + from . import recovery + + config = settings.load() + port = int(config.get("agent_port") or x2_spec.AGENT_PORT) + ssh_port = int(config.get("robot_ssh_port") or 22) + + candidates = await recovery.find_robot(port, ssh_port) + local = {a["address"] for a in netinfo.local_addresses()} + for candidate in candidates: + candidate["is_self"] = candidate["host"] in local + + return { + "ok": True, + "candidates": [c for c in candidates if not c["is_self"]], + "current": config.get("robot_host", ""), + "agent_port": port, + } + + +@app.post("/api/robot/wake") +async def robot_wake(payload: dict = Body(default={})) -> dict: + """Log into the robot and start the agent, then wait for it to come up.""" + from . import recovery + + config = settings.load() + host = str(payload.get("host") or config.get("robot_host") or "").strip() + if not host: + raise HTTPException(status_code=400, detail="No robot address to start the agent on") + + port = int(config.get("agent_port") or x2_spec.AGENT_PORT) + ok, message = await recovery.start_agent(host, config) + if not ok: + return {"ok": False, "message": message} + + came_up = await recovery.wait_for_agent(host, port, timeout=45.0) + if came_up and host != config.get("robot_host"): + settings.save({"robot_host": host}) + await runtime.hub.broadcast("settings", settings.describe()) + + return { + "ok": came_up, + "message": ("Agent started" if came_up + else "Start command ran, but the agent has not come up yet"), + "host": host, + } + + +@app.get("/api/robot/status") +async def robot_status() -> dict: + """ + Cheap liveness probe the browser polls while the robot is off, so the + offline gate can clear itself the moment the robot comes back. + """ + bridge = runtime.bridge + connection = bridge.state.connection if bridge else None + config = settings.load() + return { + "online": bool(connection and connection.online), + "simulated": bool(bridge and bridge.simulated), + "host": config.get("robot_host", ""), + "agent_port": config.get("agent_port", x2_spec.AGENT_PORT), + "error": connection.error if connection else "No bridge running", + "uptime_s": round(connection.uptime_s, 1) if connection else 0, + "mode": bridge.state.mode if bridge else None, + # What the automatic recovery is doing right now, so the offline screen + # can show progress instead of a static "waiting". + "recovery": (bridge.state.custom.get("recovery") or "") if bridge else "", + "auto_discover": bool(config.get("auto_discover")), + "auto_start_agent": bool(config.get("auto_start_agent")), + "has_ssh_password": bool(config.get("robot_ssh_password")), + } + + +# -------------------------------------------------------------------------- +# Plugins +# -------------------------------------------------------------------------- + +@app.get("/api/plugins") +async def get_plugins() -> dict: + return runtime.registry.manifest() + + +@app.post("/api/plugins/reload") +async def reload_plugins() -> dict: + summary = await runtime.registry.load() + manifest = runtime.registry.manifest() + await runtime.hub.broadcast("plugins", manifest) + return {"ok": True, "summary": summary, "manifest": manifest} + + +@app.post("/api/plugins/{plugin_id}/{control_key}") +async def run_plugin_control(plugin_id: str, control_key: str, payload: dict = Body(default={})): + outcome = await runtime.registry.dispatch(plugin_id, control_key, payload.get("value")) + return JSONResponse(outcome, status_code=200 if outcome.get("ok") else 400) + + +# -------------------------------------------------------------------------- +# WebSocket +# -------------------------------------------------------------------------- + +@app.websocket("/ws") +async def websocket_endpoint(socket: WebSocket) -> None: + await socket.accept() + queue = await runtime.hub.register() + + try: + if runtime.bridge is not None: + await socket.send_json({"type": "state", "ts": time.time(), + "data": runtime.bridge.snapshot()}) + + async def pump() -> None: + while True: + message = await queue.get() + await socket.send_text(message) + + sender = asyncio.create_task(pump()) + try: + while True: + # Inbound messages are the joystick's high-rate path - going over + # the socket avoids an HTTP round trip per frame. + message = await socket.receive_json() + await _handle_socket_message(socket, message) + finally: + sender.cancel() + with contextlib.suppress(asyncio.CancelledError): + await sender + + except WebSocketDisconnect: + pass + except Exception: + pass + finally: + await runtime.hub.unregister(queue) + + +async def _handle_socket_message(socket: WebSocket, message: dict) -> None: + kind = message.get("type") + + if kind == "ping": + await socket.send_json({"type": "pong", "ts": time.time(), + "data": {"echo": message.get("data")}}) + return + + if kind == "velocity" and runtime.bridge is not None: + data = message.get("data") or {} + config = settings.load() + + def clamp(value, cap): + try: + return max(-cap, min(cap, float(value))) + except (TypeError, ValueError): + return 0.0 + + outcome = await runtime.bridge.set_velocity( + clamp(data.get("forward", 0), config["max_forward_velocity"]), + clamp(data.get("lateral", 0), config["max_lateral_velocity"]), + clamp(data.get("angular", 0), config["max_angular_velocity"]), + ) + if not outcome.ok: + await socket.send_json({"type": "command_error", "ts": time.time(), + "data": {"source": "velocity", "message": outcome.message}}) + return + + if kind == "stop" and runtime.bridge is not None: + await runtime.bridge.stop_motion() + return + + +# -------------------------------------------------------------------------- +# Static frontend - mounted last so /api routes win +# -------------------------------------------------------------------------- + +@app.get("/") +async def index() -> Response: + """Serve index.html with the entry module stamped with the current build.""" + build = frontend_build() + html = (WEB_DIR / "index.html").read_text(encoding="utf-8") + html = html.replace('src="/js/main.js"', f'src="/js/main.js?b={build}"') + # The placeholder is {{BUILD}}, not __BUILD__: replacing the latter would + # also rewrite the `window.__BUILD__` identifier on the same line and + # produce `window. = ""`. + html = html.replace("{{BUILD}}", build) + return Response(html, media_type="text/html; charset=utf-8", + headers={"Cache-Control": "no-store"}) + + +@app.get("/favicon.ico") +async def favicon() -> Response: + return Response(status_code=204) + + +if WEB_DIR.exists(): + app.mount("/", StaticFiles(directory=str(WEB_DIR), html=True), name="web") diff --git a/x2_dashboard/backend/settings.py b/x2_dashboard/backend/settings.py new file mode 100644 index 0000000..96688dd --- /dev/null +++ b/x2_dashboard/backend/settings.py @@ -0,0 +1,227 @@ +""" +Runtime configuration, persisted to config.json beside the project root. + +The robot address lives here rather than in code, and every field can be changed +from the Settings tab while the server is running. +""" + +from __future__ import annotations + +import json +import os +import threading +from pathlib import Path +from typing import Any + +from . import x2_spec + +ROOT = Path(__file__).resolve().parent.parent +CONFIG_PATH = ROOT / "config.json" + +_lock = threading.Lock() + +DEFAULTS: dict[str, Any] = { + # Where the on-robot agent is reachable. Empty means "not yet configured" - + # the Settings tab prompts for it and the discovery scan can fill it in. + # Deliberately not a compiled-in address. + "robot_host": "", + "agent_port": x2_spec.AGENT_PORT, + "robot_label": "AGIBOT X2", + + # The name the dashboard advertises for itself on the network, so the link + # people type is about the robot rather than whatever the PC happens to be + # called. Served as .local via mDNS - see backend/announce.py. + "dashboard_name": "agibot", + "advertise_name": True, + + # Finding the robot again after a power cycle. + # + # auto_discover: when the saved address stops answering, sweep the current + # subnets for a host running the agent (or reachable over SSH) and adopt + # it. Handles the robot getting a different DHCP lease. + # auto_start_agent: if the robot answers on SSH but the agent is not + # running, log in and start it. The robot cannot reliably start it by + # itself - the agi account cannot enable systemd lingering, and its clock + # jumps backwards after boot, which stalls cron. + "auto_discover": True, + "auto_start_agent": True, + "robot_ssh_user": "agi", + "robot_ssh_password": "", + "robot_ssh_port": 22, + "agent_start_command": "/home/agi/x2_dashboard_agent/ensure_agent.sh", + + # ROS 2 settings are used by the agent on the robot, and shown here for + # reference so the operator can confirm both ends agree. + "ros_domain_id": x2_spec.DEFAULT_ROS_DOMAIN_ID, + "rmw_implementation": "rmw_fastrtps_cpp", + + # "auto" - talk to the robot agent if a host is set, else simulate + # "agent" - require the robot agent, never fall back to simulation + # "mock" - always simulate, for UI work away from the robot + "bridge_mode": "auto", + + # HTTP server + "host": "0.0.0.0", + "port": 8770, + + # Telemetry + "telemetry_hz": 10, + "history_seconds": 120, + + # Safety + "require_confirm_zero_torque": True, + "locomotion_deadman_s": x2_spec.LOCOMOTION_DEADMAN_S, + "max_forward_velocity": x2_spec.VELOCITY_LIMITS["forward"]["max"], + "max_lateral_velocity": x2_spec.VELOCITY_LIMITS["lateral"]["max"], + "max_angular_velocity": x2_spec.VELOCITY_LIMITS["angular"]["max"], + + # UI + "theme": "dark", + "accent": "blue", +} + +# Fields the browser is allowed to change. +WRITABLE = set(DEFAULTS) - {"host"} + +_cache: dict[str, Any] | None = None + +# Keys an environment variable may force for a single run. These must survive a +# save() that re-reads the file, or the forced value would be lost mid-session. +_ENV_FORCED: set[str] = set() + + +def _read_disk() -> dict[str, Any]: + if not CONFIG_PATH.exists(): + return {} + try: + with CONFIG_PATH.open("r", encoding="utf-8") as fh: + data = json.load(fh) + return data if isinstance(data, dict) else {} + except (OSError, json.JSONDecodeError): + return {} + + +def load() -> dict[str, Any]: + """Current configuration: defaults <- config.json <- environment.""" + global _cache + with _lock: + if _cache is None: + merged = dict(DEFAULTS) + merged.update({k: v for k, v in _read_disk().items() if k in DEFAULTS}) + + # Environment wins, so `X2_ROBOT_HOST=... python -m backend` works + # for one-off runs without editing the saved config. + if os.environ.get("X2_ROBOT_HOST"): + merged["robot_host"] = os.environ["X2_ROBOT_HOST"] + _ENV_FORCED.add("robot_host") + if os.environ.get("X2_PORT"): + try: + merged["port"] = int(os.environ["X2_PORT"]) + _ENV_FORCED.add("port") + except ValueError: + pass + if os.environ.get("ROS_DOMAIN_ID"): + try: + merged["ros_domain_id"] = int(os.environ["ROS_DOMAIN_ID"]) + _ENV_FORCED.add("ros_domain_id") + except ValueError: + pass + if os.environ.get("X2_BRIDGE_MODE") in ("auto", "agent", "mock"): + merged["bridge_mode"] = os.environ["X2_BRIDGE_MODE"] + _ENV_FORCED.add("bridge_mode") + + _cache = merged + return dict(_cache) + + +def get(key: str, fallback: Any = None) -> Any: + return load().get(key, fallback) + + +def save(updates: dict[str, Any]) -> dict[str, Any]: + """ + Apply and persist a partial update. Unknown keys are ignored. + + Merges against what is on disk RIGHT NOW rather than against this process's + cached copy. The cache is per-process and never re-read, so a writer holding + a stale copy would otherwise rewrite the whole file from it and silently + revert anything another process had saved in the meantime - which is exactly + how a saved SSH password disappears. Only the keys in `updates` are the + caller's to change; everything else comes from disk. + """ + global _cache + clean = _coerce(updates) + with _lock: + current = dict(DEFAULTS) + current.update({k: v for k, v in _read_disk().items() if k in DEFAULTS}) + + # Environment overrides still win, so a value forced for this run is not + # written back over the operator's saved configuration. + if _cache is not None: + for key in _ENV_FORCED: + if key in _cache: + current[key] = _cache[key] + + current.update(clean) + _cache = current + try: + CONFIG_PATH.write_text( + json.dumps(current, indent=2, ensure_ascii=False) + "\n", + encoding="utf-8", + ) + except OSError: + # A read-only filesystem should not take the dashboard down; the + # change still applies for this session. + pass + return dict(current) + + +def _coerce(updates: dict[str, Any]) -> dict[str, Any]: + """Validate and type-correct incoming settings from the browser.""" + out: dict[str, Any] = {} + for key, value in updates.items(): + if key not in WRITABLE: + continue + default = DEFAULTS[key] + try: + if isinstance(default, bool): + out[key] = bool(value) + elif isinstance(default, int): + out[key] = int(value) + elif isinstance(default, float): + out[key] = float(value) + else: + out[key] = str(value).strip() + except (TypeError, ValueError): + continue + + if "port" in out: + out["port"] = max(1, min(65535, out["port"])) + if "agent_port" in out: + out["agent_port"] = max(1, min(65535, out["agent_port"])) + if "ros_domain_id" in out: + out["ros_domain_id"] = max(0, min(232, out["ros_domain_id"])) + if "telemetry_hz" in out: + out["telemetry_hz"] = max(1, min(60, out["telemetry_hz"])) + if "bridge_mode" in out and out["bridge_mode"] not in ("auto", "agent", "mock"): + out.pop("bridge_mode") + + for key, cap in ( + ("max_forward_velocity", x2_spec.VELOCITY_LIMITS["forward"]["max"]), + ("max_lateral_velocity", x2_spec.VELOCITY_LIMITS["lateral"]["max"]), + ("max_angular_velocity", x2_spec.VELOCITY_LIMITS["angular"]["max"]), + ): + if key in out: + out[key] = max(0.0, min(cap, out[key])) + + return out + + +def describe() -> dict[str, Any]: + """Config plus metadata the Settings tab renders.""" + return { + "values": load(), + "defaults": DEFAULTS, + "writable": sorted(WRITABLE), + "config_path": str(CONFIG_PATH), + } diff --git a/x2_dashboard/backend/voice_session.py b/x2_dashboard/backend/voice_session.py new file mode 100644 index 0000000..29c75ea --- /dev/null +++ b/x2_dashboard/backend/voice_session.py @@ -0,0 +1,306 @@ +"""Voice-session control — the on/off switch behind the Interaction page. + +The conversation loop is a systemd *user* unit (sanad_agibot.service) that the +dashboard already has the rights to drive, because both run as `agi` in the same +user session. So "turn speaking on" is: persist the operator's selection, then +start/restart that unit; "off" is stopping it. + +The (gender, language, model) -> (persona, voice) mapping deliberately lives in +Sanad's own voice/session_profile.py and is imported from there by path rather +than copied here. A copy would drift, and a drifted copy means the dashboard +shows one character while the robot speaks as another. + +Everything in here degrades to a readable status instead of raising: if Sanad +is not deployed, or systemd is unavailable, the card still renders and explains +what is missing. +""" + +from __future__ import annotations + +import importlib.util +import os +import shutil +import subprocess +import time +from pathlib import Path +from typing import Any + +SERVICE = os.environ.get("SANAD_SERVICE_NAME", "sanad_agibot.service") + +SANAD_DIR = Path(os.environ.get( + "SANAD_DIR", + Path.home() / "sanad_deploy" / "sanad_package_1" / "vendor" / "Sanad", +)) +_PROFILE_MODULE_PATH = SANAD_DIR / "voice" / "session_profile.py" + +# Choices the UI renders. Kept server-side so the page and the robot can never +# disagree about what is selectable. +OPTIONS: dict[str, list[dict[str, str]]] = { + "gender": [ + {"value": "female", "label": "Female — Muza / موزة"}, + {"value": "male", "label": "Male — Lumi / لومي"}, + ], + "language": [ + {"value": "arabic", "label": "Arabic only (Emirati)"}, + {"value": "multi", "label": "Multi-language"}, + ], + # The second value is still keyed "linksoul" so an already-saved selection + # keeps working; the label describes what it actually does now. + "model": [ + {"value": "gemini", "label": "Gemini Live"}, + {"value": "linksoul", "label": "Pipeline — Fatima / Hamdan"}, + ], +} + +_profile_mod = None +_profile_err: str | None = None + + +def _profile(): + """Sanad's session_profile module, loaded from disk on first use.""" + global _profile_mod, _profile_err + if _profile_mod is not None or _profile_err is not None: + return _profile_mod + + try: + spec = importlib.util.spec_from_file_location( + "sanad_session_profile", _PROFILE_MODULE_PATH) + if spec is None or spec.loader is None: + raise ImportError(f"cannot load {_PROFILE_MODULE_PATH}") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + _profile_mod = module + except Exception as exc: # noqa: BLE001 - reported, never fatal + _profile_err = f"{type(exc).__name__}: {exc}" + return _profile_mod + + +def _systemctl(*args: str, timeout: float = 20.0) -> tuple[int, str]: + if not shutil.which("systemctl"): + return 127, "systemctl not available on this host" + try: + proc = subprocess.run( + ["systemctl", "--user", *args], + capture_output=True, text=True, timeout=timeout, + ) + return proc.returncode, (proc.stdout + proc.stderr).strip() + except subprocess.TimeoutExpired: + return 124, f"systemctl --user {' '.join(args)} timed out" + except OSError as exc: + return 1, str(exc) + + +_VOICE_PATTERNS = ( + r"vendor/Sanad/voice/sanad_voice\.py", + r"vendor/Sanad/pipeline/runner\.py", +) + + +def _kill_voice_processes(grace: float = 6.0) -> int: + """Stop the running voice process whoever started it. + + Needed because the process is launched by keepalive_daemon.sh rather than + systemd, so stopping the unit is not enough to silence the robot. SIGINT + first so it releases ROS audio focus and closes the Gemini session cleanly. + """ + import signal + import subprocess as sp + + pids: list[str] = [] + for pat in _VOICE_PATTERNS: + try: + out = sp.run(["pgrep", "-f", pat], capture_output=True, text=True, timeout=5) + pids += [p for p in out.stdout.split() if p.strip()] + except Exception: # noqa: BLE001 + pass + if not pids: + return 0 + for p in pids: + try: + os.kill(int(p), signal.SIGINT) + except Exception: # noqa: BLE001 + pass + time.sleep(grace) + for p in pids: + try: + os.kill(int(p), signal.SIGKILL) + except Exception: # noqa: BLE001 + pass + return len(pids) + + +def service_status() -> dict[str, Any]: + code, out = _systemctl("is-active", SERVICE, timeout=10.0) + active = out.strip() or ("unknown" if code else "inactive") + return { + "unit": SERVICE, + "state": active, + "running": active == "active", + } + + +ENV_FILE = Path(os.environ.get("SANAD_ENV_FILE", Path.home() / ".sanad_agibot_env")) + +_CRED_KEYS = ("LINKSOUL_APP_ID", "LINKSOUL_APP_KEY", "LINKSOUL_APP_SECRET") + + +def _env_file_keys() -> set[str]: + """Names assigned in ~/.sanad_agibot_env. + + Checked here rather than in os.environ because that file is sourced by the + launcher, not by the dashboard — the credentials are never visible in this + process's own environment, so reading os.environ would always report them + missing. Only key names are collected; the values are never read. + """ + found: set[str] = set() + try: + for line in ENV_FILE.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if line.startswith("export "): + line = line[len("export "):].lstrip() + name, sep, value = line.partition("=") + if sep and value.strip().strip("\"'"): + found.add(name.strip()) + except OSError: + pass + return found + + +def linksoul_ready() -> dict[str, Any]: + """Whether the pipeline brain can actually run right now. + + It needs edge-tts for the Emirati voice, miniaudio to decode that MP3 (this + robot has no ffmpeg and the `agi` account has no sudo), requests for the STT + call, and a Gemini key. It does NOT need the LinkSoul cloud SDK or its app + credentials - that was the earlier cloud design, which required AgiBot to + bind this robot to an application. The pipeline talks to the mic and speaker + directly, so it works with no platform registration at all. + """ + missing_pkgs = [p for p in ("edge_tts", "miniaudio", "requests") + if importlib.util.find_spec(p) is None] + has_key = ("SANAD_GEMINI_API_KEY" in _env_file_keys() + or bool(os.environ.get("SANAD_GEMINI_API_KEY")) + or bool(os.environ.get("GEMINI_API_KEY"))) + + reasons = [] + if missing_pkgs: + reasons.append("missing Python packages: " + ", ".join(missing_pkgs) + + " (pip3 install --user " + " ".join(missing_pkgs) + ")") + if not has_key: + reasons.append(f"SANAD_GEMINI_API_KEY is not set in {ENV_FILE}") + return {"ready": not reasons, "reasons": reasons} + + +def snapshot() -> dict[str, Any]: + """Everything the Interaction card needs to render itself.""" + mod = _profile() + if mod is None: + return { + "available": False, + "error": _profile_err or "session_profile.py not found", + "sanad_dir": str(SANAD_DIR), + "options": OPTIONS, + "service": service_status(), + "linksoul": linksoul_ready(), + } + + resolved = mod.resolve() + return { + "available": True, + "error": "", + "options": OPTIONS, + **mod.catalog(), + "profile": {k: resolved[k] for k in ("enabled", "gender", "language", "model")}, + "persona": { + "file": resolved["persona_file"], + "exists": resolved["persona_exists"], + "name_en": resolved["name_en"], + "name_ar": resolved["name_ar"], + }, + "voice": { + "gemini": resolved["gemini_voice"], + "edge": resolved["edge_voice"], + }, + "greeting": resolved["greeting"], + "service": service_status(), + "linksoul": linksoul_ready(), + } + + +def apply(enabled: bool, gender: str | None, language: str | None, + model: str | None) -> dict[str, Any]: + """Persist the selection and bring the conversation loop to that state. + + Returns the new snapshot plus a `greeting` the caller should speak when the + session has just been switched on. The greeting is spoken by the dashboard + rather than by the persona so it fires exactly once, at the moment Apply is + pressed, on whichever model is selected — the LinkSoul path is a passive + callback and cannot start talking on its own. + """ + mod = _profile() + if mod is None: + return {"ok": False, "error": _profile_err or "session_profile.py not found", + "snapshot": snapshot()} + + # Validate a CANDIDATE before persisting anything. Saving first and + # rejecting afterwards left an unlaunchable selection on disk: the dashboard + # refused to start it, but start_agibot.sh would happily replay it at the + # next boot, exec a runner that exits immediately, and Restart=on-failure + # would turn that into a crash loop with the robot mute. + current = mod.load() + candidate = mod.normalize({ + "enabled": enabled, + "gender": gender or current["gender"], + "language": language or current["language"], + "model": model or current["model"], + }) + resolved = mod.resolve(candidate) + + if not resolved["persona_exists"]: + return { + "ok": False, + "error": f"Persona file missing: {resolved['persona_file']}", + "snapshot": snapshot(), + } + + if enabled and resolved["model"] == "linksoul": + ready = linksoul_ready() + if not ready["ready"]: + return {"ok": False, + "error": "LinkSoul is not usable yet — " + "; ".join(ready["reasons"]), + "snapshot": snapshot()} + + saved = mod.save(**{k: candidate[k] for k in ("enabled", "gender", "language", "model")}) + resolved = mod.resolve(saved) + + # The voice process is owned by keepalive_daemon.sh, not by systemd - the + # user manager dies with the last login session (no linger, needs root), so + # the daemon had to take over. That means `systemctl stop` no longer stops + # anything: pressing "Speaking off" left the robot still listening. So act + # on the processes directly here, and let the daemon keep enforcing it. + _kill_voice_processes() + + if enabled: + _systemctl("reset-failed", SERVICE, timeout=10.0) + code, out = _systemctl("restart", SERVICE, timeout=45.0) + action = "restarted" + else: + code, out = _systemctl("stop", SERVICE, timeout=30.0) + action = "stopped" + # The voice process does not exit on SIGINT within TimeoutStopSec, so + # systemd SIGKILLs it and books the unit as failed. That is an artifact + # of an operator-requested stop, not a fault, and showing "failed" on + # the card after pressing Off would be plainly wrong. + if code == 0: + _systemctl("reset-failed", SERVICE, timeout=10.0) + + if code != 0: + return {"ok": False, "error": f"systemctl {action} failed: {out}", + "snapshot": snapshot()} + + return { + "ok": True, + "action": action, + "greeting": resolved["greeting"] if enabled else "", + "snapshot": snapshot(), + } diff --git a/x2_dashboard/backend/x2_spec.py b/x2_dashboard/backend/x2_spec.py new file mode 100644 index 0000000..55d99f8 --- /dev/null +++ b/x2_dashboard/backend/x2_spec.py @@ -0,0 +1,773 @@ +""" +AGIBOT X2 interface specification. + +IMPORTANT: every constant in this file was read back from the robot itself +(10.255.254.84, PC2 / Jetson Orin) by introspecting the installed `aimdk_msgs` +package and the live ROS 2 graph - not copied from the published documentation. +Where the two disagree, the robot wins. Notable differences found: + + * McAction has 18 modes, not 5. PASSIVE_DEFAULT (1) and ZERO_TORQUE_DEFAULT + (4) are distinct; the docs conflated them. + * McControlArea is a BITMASK (LEFT_HAND=1, RIGHT_HAND=2, HEAD=4, WAIST=8), + which is why the docs' "area 3" (both arms) and "area 11" (whole body) + work out - 3 = 1|2 and 11 = 1|2|8. + * Several documented preset motion IDs (1007, 1010, 1011, 3017, 3024, 3025, + 3031) do not exist in the firmware enum. The real list is below. + * PmuState spells its fan field `fan_pecentage` (sic) and reports charge in + `battery_remaining_capacity_percentage`; `battery_remaining_capacity` is + mAh, not percent. + * Joint names carry a `_joint` suffix. + * This unit exposes SIX working camera feeds and a chest LiDAR. An earlier + revision of this file claimed one camera, no rear camera and an unreachable + Orbbec; all three were wrong. Corrected by subscribing to each topic and + decoding a real frame off it - see CAMERA_INVENTORY. SLAM command topics + are still genuinely absent. +""" + +from __future__ import annotations + +# -------------------------------------------------------------------------- +# Network +# -------------------------------------------------------------------------- +# PC1 runs motion control and must never be used as a build/run host. +PC1_MOTION_CONTROL_IP = "10.0.1.40" +# PC2 (this robot's development unit) as seen on the internal develop0 network. +PC2_DEVELOP_IP = "10.0.1.41" + +DEFAULT_ROS_DOMAIN_ID = 0 + +# Port the on-robot agent listens on. +AGENT_PORT = 8781 + +# Ports probed when scanning a subnet for the robot. +DISCOVERY_PORTS = [AGENT_PORT, 22, 8080, 9090] + + +# -------------------------------------------------------------------------- +# Sensor topics (verified present on the live graph) +# -------------------------------------------------------------------------- +TOPIC_IMU_CHEST = "/aima/hal/imu/chest/state" +TOPIC_IMU_TORSO = "/aima/hal/imu/torso/state" +TOPIC_TOUCH_HEAD = "/aima/hal/sensor/touch_head" +TOPIC_MODULE_INFO = "/aima/hal/sensor/module_info" + +# Every feed is on demand - `always_on` is gone. Nothing is subscribed on the +# robot until the operator switches that feed on in the Vision tab, and the +# agent drops the lot when the last browser disconnects. A single frame here is +# 170-430 KB; holding six of them open for a tab nobody is looking at competes +# with the robot's own traffic on the same Wi-Fi. +CAMERAS = [ + { + "key": "rgb_head_front_center", + "label": "Head camera (front)", + "kind": "rgb", + "rate_hz": 10, + "topic": "/aima/hal/sensor/rgb_head_front_center/rgb_image/compressed", + "info_topic": "/aima/hal/sensor/rgb_head_front_center/camera_info", + "flip": False, + }, + { + "key": "rgb_head_rear", + "label": "Head camera (rear)", + "kind": "rgb", + "rate_hz": 10, + "topic": "/aima/hal/sensor/rgb_head_rear/rgb_image/compressed", + "info_topic": "/aima/hal/sensor/rgb_head_rear/camera_info", + "flip": False, + }, + { + "key": "rgbd_head_front", + "label": "RGB-D colour (Orbbec)", + "kind": "rgb", + "rate_hz": 10, + "topic": "/aima/hal/sensor/rgbd_head_front/rgb_image/compressed", + "info_topic": "/aima/hal/sensor/rgbd_head_front/rgb_camera_info", + "flip": True, + "note": "This module is mounted upside down, so the feed is rotated 180 by " + "default. Use the button below if yours is not.", + }, + { + "key": "depth_front", + "label": "Depth (colourised)", + "kind": "depth", + "rate_hz": 14, + "topic": "/camera/depth/image_raw/compressedDepth", + "flip": True, + "note": "16-bit millimetre map, rendered to a JET ramp over 0-4.5 m on the robot " + "and rotated 180 like the colour feed it shares a module with. " + "Black is 'no return', not 'very close'.", + }, + { + "key": "stereo_head_front_left", + "label": "Stereo left", + "kind": "rgb", + "rate_hz": 10, + "topic": "/aima/hal/sensor/stereo_head_front_left/rgb_image/compressed", + "info_topic": "/aima/hal/sensor/stereo_head_front_left/camera_info", + "flip": False, + }, + { + "key": "stereo_head_front_right", + "label": "Stereo right", + "kind": "rgb", + "rate_hz": 10, + "topic": "/aima/hal/sensor/stereo_head_front_right/rgb_image/compressed", + "info_topic": "/aima/hal/sensor/stereo_head_front_right/camera_info", + "flip": False, + }, + { + "key": "perception_input", + "label": "Perception input", + "kind": "debug", + "rate_hz": 10, + "topic": "/mono_perception/debug/input_image", + "flip": False, + "note": "Only carries frames while the mono-perception module is running.", + }, + { + "key": "perception_seg", + "label": "Segmentation mask", + "kind": "debug", + "rate_hz": 10, + "topic": "/mono_perception/debug/seg_mask", + "flip": False, + "note": "Only carries frames while the mono-perception module is running.", + }, + { + "key": "perception_lines", + "label": "Line colour map", + "kind": "debug", + "rate_hz": 10, + "topic": "/mono_perception/debug/line_color_map", + "flip": False, + "note": "Only carries frames while the mono-perception module is running.", + }, +] + +# What this unit actually has, established the only way that settles it: by +# subscribing to each topic and decoding a frame. A previous revision inferred +# the inventory from the v4l2 device map and the em app list, and got it wrong +# three ways - the rear camera and the Orbbec feeds are on the shared ROS graph +# and publish perfectly well to an ordinary `agi` subscriber. Reading the device +# tree tells you which sensors the SoC enumerates, not which topics carry data. +CAMERA_INVENTORY = [ + { + "name": "Head front (imx900c)", + "detail": "MIPI/GMSL sensor 2-0039, 2064x1552 12-bit Bayer, ISP-processed " + "and published as 2688x1944 JPEG at ~10 Hz.", + "status": "live", + "where": "/aima/hal/sensor/rgb_head_front_center/rgb_image/compressed", + }, + { + "name": "Head rear", + "detail": "Fitted and publishing 2064x1552 JPEG at ~10 Hz, mounted upright " + "(no rotation needed). Confirmed by decoding a frame.", + "status": "live", + "where": "/aima/hal/sensor/rgb_head_rear/rgb_image/compressed", + }, + { + "name": "Orbbec Gemini 335 (RGB-D)", + "detail": "Colour and depth both reachable from the agi account. Depth is a " + "16-bit millimetre map published as compressedDepth at ~14 Hz, " + "topping out around 4.2 m. The module is mounted upside down - both " + "its feeds are rotated 180 by default.", + "status": "live", + "where": "/aima/hal/sensor/rgbd_head_front/* and /camera/depth/image_raw/compressedDepth", + }, + { + "name": "Stereo pair (front left / right)", + "detail": "Both eyes publish JPEG at ~10 Hz. Useful side by side for depth " + "the RGB-D sensor misses on reflective surfaces.", + "status": "live", + "where": "/aima/hal/sensor/stereo_head_front_{left,right}/rgb_image/compressed", + }, + { + "name": "Perception debug views", + "detail": "Input image, segmentation mask and line colour map. Real topics, " + "but only carry frames while the mono-perception module is running.", + "status": "intermittent", + "where": "/mono_perception/debug/*", + }, +] + +# -------------------------------------------------------------------------- +# Chest LiDAR +# -------------------------------------------------------------------------- +# Live on this unit at 2 Hz. Field layout read off the topic rather than +# assumed: x/y/z float32 at offsets 0/4/8, intensity float32 at 16, ring uint16 +# at 20, timestamp float64 at 24, point_step 32. A scan is ~25.5k points +# (816 KB), decimated on the robot before it crosses the network. +LIDAR = { + "key": "lidar_chest_front", + "label": "Chest LiDAR", + "topic": "/aima/hal/sensor/lidar_chest_front/lidar_pointcloud_down_sampling", + "status_topic": "/aima/hal/sensor/lidar_chest_front/lidar_status", + "type": "sensor_msgs/PointCloud2", + "rate_hz": 2, + "frame": "lidar_chest_front", + "max_points": 4000, +} + +SENSOR_TOPICS = [ + {"topic": TOPIC_IMU_CHEST, "type": "sensor_msgs/Imu", "rate_hz": 500, "label": "Chest IMU"}, + {"topic": TOPIC_IMU_TORSO, "type": "sensor_msgs/Imu", "rate_hz": 500, "label": "Torso IMU"}, + {"topic": TOPIC_TOUCH_HEAD, "type": "aimdk_msgs/TouchState", "rate_hz": 100, "label": "Head touch"}, + {"topic": "/aima/hal/pmu/state", "type": "aimdk_msgs/PmuState", "rate_hz": 1, "label": "Power management"}, + {"topic": "/aima/hal/joint/head/state", "type": "aimdk_msgs/JointStateArray", "rate_hz": 100, "label": "Head joints"}, + {"topic": "/aima/hal/joint/waist/state", "type": "aimdk_msgs/JointStateArray", "rate_hz": 100, "label": "Waist joints"}, + {"topic": "/aima/hal/joint/arm/state", "type": "aimdk_msgs/JointStateArray", "rate_hz": 100, "label": "Arm joints"}, + {"topic": "/aima/hal/joint/leg/state", "type": "aimdk_msgs/JointStateArray", "rate_hz": 100, "label": "Leg joints"}, + {"topic": "/aima/hal/joint/hand/state", "type": "aimdk_msgs/HandStateArray", "rate_hz": 30, "label": "Hand state"}, + {"topic": CAMERAS[0]["topic"], "type": "sensor_msgs/CompressedImage", "rate_hz": 10, "label": "Head camera"}, + {"topic": "/aima/mc/leg_odometry", "type": "nav_msgs/Odometry", "rate_hz": 50, "label": "Leg odometry"}, + {"topic": "/face_ui_proxy/status", "type": "aimdk_msgs/FaceEmojiStatus", "rate_hz": 1, "label": "Face status"}, +] + +# Head touch reports 8 independent zones. +TOUCH_ZONE_COUNT = 8 + + +# -------------------------------------------------------------------------- +# Power management (exact PmuState field names) +# -------------------------------------------------------------------------- +TOPIC_PMU_STATE = "/aima/hal/pmu/state" +PMU_RATE_HZ = 1.0 + +PMU_FIELDS = { + "battery_pct": "battery_remaining_capacity_percentage", + "battery_voltage": "battery_voltage", + "battery_pack_voltage": "battery_pack_voltage", + "battery_current": "battery_current", + "battery_temp": "battery_temperature", + "battery_cycles": "battery_cycle_count", + "battery_capacity_mah": "battery_remaining_capacity", + "battery_power": "battery_output_power", + "pmu_temp": "pmu_temperature", + "fan_rpm": "fan_speed", + "fan_pct": "fan_pecentage", # firmware spells it this way +} + +# (display label, voltage field, current field, nominal volts) +PMU_RAILS = [ + {"key": "bus_48v", "label": "48 V bus", "voltage": "bus_48v_voltage", + "current": "bus_48v_current", "nominal": 48.0}, + {"key": "output_48v", "label": "48 V output", "voltage": "output_48v_voltage", + "current": "output_48v_current", "nominal": 48.0}, + {"key": "output_12v", "label": "12 V output", "voltage": "output_12v_voltage", + "current": "output_12v_current", "nominal": 12.0}, + {"key": "head_power", "label": "Head power", "voltage": "head_power_voltage", + "current": "head_power_current", "nominal": 24.0}, + {"key": "orin", "label": "Orin NX", "voltage": "orin_voltage", + "current": "orin_current", "nominal": 19.0}, + {"key": "rk3588", "label": "RK3588", "voltage": "rk3588_voltage", + "current": "rk3588_current", "nominal": 12.0}, + {"key": "fan", "label": "Fan rail", "voltage": "fan_voltage", + "current": None, "nominal": 12.0}, + {"key": "bus_48v_pmos", "label": "48 V PMOS", "voltage": "bus_48v_pmos_voltage", + "current": None, "nominal": 48.0}, +] + +PMU_INFO_FIELDS = [ + ("bms_manufacturer", "BMS manufacturer"), + ("bms_serial_number", "BMS serial"), + ("bms_hardware_version", "BMS hardware"), + ("bms_software_version", "BMS software"), + ("pmu_software_version", "PMU software"), + ("pmu_hardware_version", "PMU hardware"), + ("pmu_protocol_version", "PMU protocol"), +] + + +# -------------------------------------------------------------------------- +# Motion modes (aimdk_msgs/msg/McAction constants, read from the robot) +# -------------------------------------------------------------------------- +SRV_GET_MC_ACTION = "/aimdk_5Fmsgs/srv/GetMcAction" +SRV_SET_MC_ACTION = "/aimdk_5Fmsgs/srv/SetMcAction" + +MC_MODES = [ + # -- safety / low level ------------------------------------------------- + {"id": "PASSIVE_DEFAULT", "value": 1, "label": "Passive", "group": "basic", + "desc": "Joints released, no holding force. The robot must be supported.", + "danger": True}, + {"id": "ZERO_TORQUE_DEFAULT", "value": 4, "label": "Zero torque", "group": "basic", + "desc": "Explicit zero-torque command. The robot will collapse if free-standing.", + "danger": True}, + {"id": "SOFT_EMERGENCY_STOP", "value": 2, "label": "Soft E-stop", "group": "basic", + "desc": "Controlled emergency stop.", "danger": True}, + {"id": "DAMPING_DEFAULT", "value": 3, "label": "Damping", "group": "basic", + "desc": "Joints hold damping - the safe resting state.", "danger": False}, + + # -- position control --------------------------------------------------- + {"id": "JOINT_DEFAULT", "value": 100, "label": "Joint control", "group": "joint", + "desc": "Position-controlled joints. Required for direct joint commands.", + "danger": False}, + {"id": "JOINT_FREEZE", "value": 101, "label": "Joint freeze", "group": "joint", + "desc": "Hold the current joint positions.", "danger": False}, + + # -- standing ----------------------------------------------------------- + {"id": "STAND_DEFAULT", "value": 200, "label": "Stable stand", "group": "stand", + "desc": "Active balance. Prerequisite for preset motions and walking.", + "danger": False}, + {"id": "STAND_BODY_CONTROL", "value": 201, "label": "Body control", "group": "stand", + "desc": "Standing with body pose control enabled.", "danger": False}, + + # -- locomotion --------------------------------------------------------- + {"id": "LOCOMOTION_DEFAULT", "value": 300, "label": "Walk", "group": "locomotion", + "desc": "Normal walking gait.", "danger": False}, + {"id": "LOCOMOTION_STEP", "value": 302, "label": "Step", "group": "locomotion", + "desc": "Stepping gait.", "danger": False}, + {"id": "RUN_DEFAULT", "value": 301, "label": "Run", "group": "locomotion", + "desc": "Running gait. Needs clear space.", "danger": True}, + {"id": "ASCEND_STAIRS", "value": 2006, "label": "Ascend stairs", "group": "locomotion", + "desc": "Stair-climbing gait.", "danger": True}, + {"id": "DESCEND_STAIRS", "value": 2008, "label": "Descend stairs", "group": "locomotion", + "desc": "Stair-descending gait.", "danger": True}, + + # -- postures ----------------------------------------------------------- + {"id": "STAND_UP_DEFAULT", "value": 2005, "label": "Stand up", "group": "posture", + "desc": "Rise to standing.", "danger": False}, + {"id": "SIT_DOWN_DEFAULT", "value": 2000, "label": "Sit down", "group": "posture", + "desc": "Sit down from standing.", "danger": False}, + {"id": "CROUCH_DOWN_DEFAULT", "value": 2002, "label": "Crouch", "group": "posture", + "desc": "Crouch down.", "danger": False}, + {"id": "LIE_DOWN_DEFAULT", "value": 2004, "label": "Lie down", "group": "posture", + "desc": "Lie down.", "danger": False}, + + # -- external ----------------------------------------------------------- + {"id": "VR_REMOTE_CONTROLLER", "value": 400, "label": "VR teleop", "group": "external", + "desc": "Hand control to the VR teleoperation bridge.", "danger": False}, +] + +MC_MODE_GROUPS = [ + {"key": "basic", "label": "Basic / safety"}, + {"key": "joint", "label": "Joint control"}, + {"key": "stand", "label": "Standing"}, + {"key": "locomotion", "label": "Locomotion"}, + {"key": "posture", "label": "Posture"}, + {"key": "external", "label": "External control"}, +] + +MC_MODE_BY_ID = {m["id"]: m for m in MC_MODES} +MC_MODE_BY_VALUE = {m["value"]: m for m in MC_MODES} +MC_MODE_IDS = [m["id"] for m in MC_MODES] + +# Modes in which the robot will accept a velocity command. +DRIVEABLE_MODES = {"LOCOMOTION_DEFAULT", "LOCOMOTION_STEP", "RUN_DEFAULT", + "STAND_DEFAULT", "STAND_BODY_CONTROL"} + +# Modes in which direct joint commands make sense. +JOINT_CONTROL_MODES_ALLOWED = {"JOINT_DEFAULT", "JOINT_FREEZE"} + +MC_ACTION_STATUS = {0: "Idle", 100: "Running", 200: "Transition"} + +COMMON_STATE = { + 0: "Unknown", 1: "Success", 2: "Failure", 3: "Aborted", 4: "Timeout", + 5: "Invalid", 6: "In manual", 100: "Not ready", 200: "Pending", + 300: "Created", 400: "Running", +} + + +# -------------------------------------------------------------------------- +# Locomotion +# -------------------------------------------------------------------------- +TOPIC_LOCOMOTION_VELOCITY = "/aima/mc/locomotion/velocity" +TOPIC_LEG_ODOMETRY = "/aima/mc/leg_odometry" +TOPIC_BODY_POSE = "/aima/mc/body_pose" + +VELOCITY_THRESHOLDS = {"forward": 0.09, "lateral": 0.60, "angular": 0.03} + +VELOCITY_LIMITS = { + "forward": {"min": -0.6, "max": 0.8, "step": 0.01, "unit": "m/s"}, + "lateral": {"min": -0.7, "max": 0.7, "step": 0.01, "unit": "m/s"}, + "angular": {"min": -0.8, "max": 0.8, "step": 0.01, "unit": "rad/s"}, +} + +LOCOMOTION_PUBLISH_HZ = 20 +LOCOMOTION_DEADMAN_S = 0.5 + + +# -------------------------------------------------------------------------- +# Input source arbitration +# -------------------------------------------------------------------------- +SRV_GET_CURRENT_INPUT_SOURCE = "/aimdk_5Fmsgs/srv/GetCurrentInputSource" +SRV_SET_MC_INPUT_SOURCE = "/aimdk_5Fmsgs/srv/SetMcInputSource" + +INPUT_SOURCE_ACTION = { + "ADD": 1001, "MODIFY": 1002, "DELETE": 1003, "ENABLE": 2001, "DISABLE": 2002, +} + +BUILTIN_INPUT_SOURCES = [ + {"name": "rc", "priority": 80, "timeout": 1000, "desc": "Handheld remote controller"}, + {"name": "vr", "priority": 70, "timeout": 1000, "desc": "VR teleoperation"}, + {"name": "app_proxy", "priority": 60, "timeout": 1000, "desc": "Mobile app"}, + {"name": "interaction", "priority": 50, "timeout": 1000, "desc": "Interaction module"}, + {"name": "pnc", "priority": 40, "timeout": 1000, "desc": "Planning and control"}, +] + +DASHBOARD_INPUT_SOURCE = {"name": "x2_dashboard", "priority": 30, "timeout": 1000} + + +# -------------------------------------------------------------------------- +# Preset motions (aimdk_msgs/msg/McPresetMotion constants, read from robot) +# McControlArea is a bitmask: LEFT_HAND=1 RIGHT_HAND=2 HEAD=4 WAIST=8 +# -------------------------------------------------------------------------- +SRV_SET_PRESET_MOTION = "/aimdk_5Fmsgs/srv/SetMcPresetMotion" + +AREA_LEFT_HAND = 1 +AREA_RIGHT_HAND = 2 +AREA_BOTH_HANDS = 3 +AREA_HEAD = 4 +AREA_WAIST = 8 +AREA_BODY = 11 # both hands + waist + +MC_CONTROL_AREAS = { + 0: "None", 1: "Left arm", 2: "Right arm", 3: "Both arms", + 4: "Head", 8: "Waist", 11: "Whole body", +} + +PRESET_MOTIONS = [ + # -- greeting ----------------------------------------------------------- + {"key": "wave_right", "label": "Wave", "side": "right", "motion": 1002, "area": AREA_RIGHT_HAND, "group": "greeting", "enum": "WAVE_HAND"}, + {"key": "wave_left", "label": "Wave", "side": "left", "motion": 1002, "area": AREA_LEFT_HAND, "group": "greeting", "enum": "WAVE_HAND"}, + {"key": "shake_right", "label": "Handshake", "side": "right", "motion": 1003, "area": AREA_RIGHT_HAND, "group": "greeting", "enum": "SHAKE_HAND"}, + {"key": "shake_left", "label": "Handshake", "side": "left", "motion": 1003, "area": AREA_LEFT_HAND, "group": "greeting", "enum": "SHAKE_HAND"}, + {"key": "raise_right", "label": "Raise hand", "side": "right", "motion": 1001, "area": AREA_RIGHT_HAND, "group": "greeting", "enum": "RAISE_HAND"}, + {"key": "raise_left", "label": "Raise hand", "side": "left", "motion": 1001, "area": AREA_LEFT_HAND, "group": "greeting", "enum": "RAISE_HAND"}, + {"key": "raise_both", "label": "Raise both hands", "side": "both", "motion": 1001, "area": AREA_BOTH_HANDS, "group": "greeting", "enum": "RAISE_HAND"}, + {"key": "salute_right", "label": "Salute", "side": "right", "motion": 1013, "area": AREA_RIGHT_HAND, "group": "greeting", "enum": "SALUTE"}, + {"key": "salute_left", "label": "Salute", "side": "left", "motion": 1013, "area": AREA_LEFT_HAND, "group": "greeting", "enum": "SALUTE"}, + {"key": "turn_wave", "label": "Turn and wave", "side": "body", "motion": 2001, "area": AREA_BODY, "group": "greeting", "enum": "TURN_WAVE_HAND"}, + {"key": "bow", "label": "Bow", "side": "body", "motion": 3001, "area": AREA_BODY, "group": "greeting", "enum": "INTERACTION_BOW"}, + + # -- expressive --------------------------------------------------------- + {"key": "kiss_right", "label": "Flying kiss", "side": "right", "motion": 1004, "area": AREA_RIGHT_HAND, "group": "expressive", "enum": "FLYING_KISS_HAND"}, + {"key": "kiss_left", "label": "Flying kiss", "side": "left", "motion": 1004, "area": AREA_LEFT_HAND, "group": "expressive", "enum": "FLYING_KISS_HAND"}, + {"key": "blowkiss", "label": "Blow kiss", "side": "body", "motion": 3012, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_BLOWKISS"}, + {"key": "sweatheart", "label": "Heart", "side": "body", "motion": 3004, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_SWEATHEART"}, + {"key": "like", "label": "Thumbs up", "side": "body", "motion": 3002, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_LIKE"}, + {"key": "ye", "label": "Peace sign", "side": "body", "motion": 3003, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_YE"}, + {"key": "hug", "label": "Hug", "side": "body", "motion": 3008, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_HUG"}, + {"key": "cheer", "label": "Cheer", "side": "body", "motion": 3011, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_CHEER"}, + {"key": "sad", "label": "Sad", "side": "body", "motion": 3006, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_SAD"}, + {"key": "speak", "label": "Speaking gesture", "side": "body", "motion": 3016, "area": AREA_BODY, "group": "expressive", "enum": "INTERACTION_SPEAK"}, + + # -- gesture ------------------------------------------------------------ + {"key": "clap", "label": "Clap", "side": "both", "motion": 1008, "area": AREA_BOTH_HANDS, "group": "gesture", "enum": "CLAP_HAND"}, + {"key": "hitclap", "label": "Hit clap", "side": "body", "motion": 3015, "area": AREA_BODY, "group": "gesture", "enum": "HITCLAP"}, + {"key": "fist_right", "label": "Fist", "side": "right", "motion": 1009, "area": AREA_RIGHT_HAND, "group": "gesture", "enum": "CLIPFIST"}, + {"key": "fist_left", "label": "Fist", "side": "left", "motion": 1009, "area": AREA_LEFT_HAND, "group": "gesture", "enum": "CLIPFIST"}, + {"key": "handx", "label": "Cross arms", "side": "body", "motion": 3009, "area": AREA_BODY, "group": "gesture", "enum": "INTERACTION_HANDX"}, + {"key": "chestwave", "label": "Chest wave", "side": "body", "motion": 3010, "area": AREA_BODY, "group": "gesture", "enum": "INTERACTION_CHESTWAVE"}, + {"key": "lightwave", "label": "Light wave", "side": "body", "motion": 3007, "area": AREA_BODY, "group": "gesture", "enum": "INTERACTION_LIGHTWAVE"}, + + # -- performance -------------------------------------------------------- + {"key": "dance1", "label": "Bass dance 1", "side": "body", "motion": 3013, "area": AREA_BODY, "group": "performance", "enum": "INTERACTION_BASSDANCE1"}, + {"key": "dance2", "label": "Bass dance 2", "side": "body", "motion": 3014, "area": AREA_BODY, "group": "performance", "enum": "INTERACTION_BASSDANCE2"}, + {"key": "photo", "label": "Photo pose", "side": "body", "motion": 3018, "area": AREA_BODY, "group": "performance", "enum": "INTERACTION_PHOTOPOSTURE"}, + {"key": "photo3", "label": "Triple photo pose", "side": "body", "motion": 3019, "area": AREA_BODY, "group": "performance", "enum": "INTERACTION_PHOTOTRIPPLEPOSTURE"}, + + # -- head --------------------------------------------------------------- + {"key": "point_head", "label": "Point head", "side": "head", "motion": 4001, "area": AREA_HEAD, "group": "head", "enum": "POINT_HEAD"}, + {"key": "shake_head", "label": "Shake head", "side": "head", "motion": 4002, "area": AREA_HEAD, "group": "head", "enum": "SHAKE_HEAD"}, +] + +PRESET_GROUPS = [ + {"key": "greeting", "label": "Greeting"}, + {"key": "expressive", "label": "Expressive"}, + {"key": "gesture", "label": "Gesture"}, + {"key": "performance", "label": "Performance"}, + {"key": "head", "label": "Head"}, +] + + +# -------------------------------------------------------------------------- +# Joints (names read from live JointStateArray messages) +# Limits: about_agibot_X2/joint_name_and_limit.html, X2 Ultra ranges. +# -------------------------------------------------------------------------- +SRV_GET_ALL_JOINT_STATE = "/aimdk_5Fmsgs/srv/GetAllJointState" + + +def _j(name, label, lo, hi): + return {"name": name, "label": label, "min_deg": lo, "max_deg": hi} + + +JOINT_GROUPS = [ + { + "key": "head", "label": "Head", + "command_topic": "/aima/hal/joint/head/command", + "state_topic": "/aima/hal/joint/head/state", + "joints": [ + _j("head_yaw_joint", "Head yaw", -20.0, 20.0), + _j("head_pitch_joint", "Head pitch", 0.0, 0.0), + ], + }, + { + "key": "waist", "label": "Waist", + "command_topic": "/aima/hal/joint/waist/command", + "state_topic": "/aima/hal/joint/waist/state", + "joints": [ + _j("waist_yaw_joint", "Waist yaw", -196.5, 126.5), + _j("waist_pitch_joint", "Waist pitch", -18.0, 18.0), + _j("waist_roll_joint", "Waist roll", -28.0, 28.0), + ], + }, + { + "key": "arm", "label": "Arms", + "command_topic": "/aima/hal/joint/arm/command", + "state_topic": "/aima/hal/joint/arm/state", + "joints": [ + _j("left_shoulder_pitch_joint", "L shoulder pitch", -116.5, 176.5), + _j("left_shoulder_roll_joint", "L shoulder roll", -3.5, 174.5), + _j("left_shoulder_yaw_joint", "L shoulder yaw", -146.5, 146.5), + _j("left_elbow_joint", "L elbow", -135.0, 0.0), + _j("left_wrist_yaw_joint", "L wrist yaw", -146.5, 146.5), + _j("left_wrist_pitch_joint", "L wrist pitch", -33.0, 33.0), + _j("left_wrist_roll_joint", "L wrist roll", -86.5, 41.5), + _j("right_shoulder_pitch_joint", "R shoulder pitch", -116.5, 176.5), + _j("right_shoulder_roll_joint", "R shoulder roll", -3.5, 174.5), + _j("right_shoulder_yaw_joint", "R shoulder yaw", -146.5, 146.5), + _j("right_elbow_joint", "R elbow", -135.0, 0.0), + _j("right_wrist_yaw_joint", "R wrist yaw", -146.5, 146.5), + _j("right_wrist_pitch_joint", "R wrist pitch", -33.0, 33.0), + _j("right_wrist_roll_joint", "R wrist roll", -86.5, 41.5), + ], + }, + { + "key": "leg", "label": "Legs", + "command_topic": "/aima/hal/joint/leg/command", + "state_topic": "/aima/hal/joint/leg/state", + "joints": [ + _j("left_hip_pitch_joint", "L hip pitch", -146.5, 146.5), + _j("left_hip_roll_joint", "L hip roll", -13.5, 166.5), + _j("left_hip_yaw_joint", "L hip yaw", -196.5, 96.5), + _j("left_knee_joint", "L knee", 0.0, 138.0), + _j("left_ankle_pitch_joint", "L ankle pitch", -26.0, 46.0), + _j("left_ankle_roll_joint", "L ankle roll", -15.0, 15.0), + _j("right_hip_pitch_joint", "R hip pitch", -146.5, 146.5), + _j("right_hip_roll_joint", "R hip roll", -13.5, 166.5), + _j("right_hip_yaw_joint", "R hip yaw", -196.5, 96.5), + _j("right_knee_joint", "R knee", 0.0, 138.0), + _j("right_ankle_pitch_joint", "R ankle pitch", -26.0, 46.0), + _j("right_ankle_roll_joint", "R ankle roll", -15.0, 15.0), + ], + }, +] + +JOINT_GROUP_BY_KEY = {g["key"]: g for g in JOINT_GROUPS} + +JOINT_CONTROL_MODES = [ + {"id": "position", "label": "Position", "unit": "rad", "desc": "Target angle."}, + {"id": "velocity", "label": "Velocity", "unit": "rad/s", "desc": "Target angular velocity."}, + {"id": "torque", "label": "Torque", "unit": "N·m", "desc": "Direct effort output."}, +] + + +# -------------------------------------------------------------------------- +# End effectors +# -------------------------------------------------------------------------- +TOPIC_HAND_COMMAND = "/aima/hal/joint/hand/command" +TOPIC_HAND_STATE = "/aima/hal/joint/hand/state" +SRV_GET_HAND_TYPE = "/aimdk_5Fmsgs/srv/GetHandType" + +HAND_TYPES = { + 0: "None", 1: "Nimble hands", 2: "Claw gripper", + 3: "Leisai nimble hands", 255: "Error", +} + +DEXHAND_JOINTS = [ + "ThumbRoll", "ThumbAbAd", "ThumbMCP", + "IndexAbAd", "IndexPIP", "MiddlePIP", + "RingAbAd", "RingPIP", "PinkyAbAd", "PinkyPIP", +] + +HAND_PRESETS = [ + {"key": "open", "label": "Open", "positions": [0.0] * 10}, + {"key": "close", "label": "Close", "positions": [0.6, 0.6, 1.2, 0.2, 1.4, 1.4, 0.2, 1.4, 0.2, 1.4]}, + {"key": "pinch", "label": "Pinch", "positions": [0.4, 0.5, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]}, + {"key": "point", "label": "Point", "positions": [0.6, 0.6, 1.2, 0.0, 0.0, 1.4, 0.2, 1.4, 0.2, 1.4]}, +] + + +# -------------------------------------------------------------------------- +# Voice / audio +# -------------------------------------------------------------------------- +SRV_PLAY_TTS = "/aimdk_5Fmsgs/srv/PlayTts" +SRV_GET_VOLUME = "/aimdk_5Fmsgs/srv/GetVolume" +SRV_SET_VOLUME = "/aimdk_5Fmsgs/srv/SetVolume" +SRV_GET_MUTE = "/aimdk_5Fmsgs/srv/GetMute" +SRV_SET_MUTE = "/aimdk_5Fmsgs/srv/SetMute" +TOPIC_AUDIO_OUTPUT = "/agent/process_audio_output" +TOPIC_TTS_STATUS = "/interaction/tts_status" + +# aimdk_msgs/msg/TtsPriorityLevel constants, read from the robot. +TTS_PRIORITIES = [ + {"id": "SAFETY_L10", "value": 10, "label": "Safety", "desc": "Emergency alerts"}, + {"id": "WARNING_L8", "value": 8, "label": "Warning", "desc": "Hazard warnings"}, + {"id": "SYSTEM_L7", "value": 7, "label": "System", "desc": "System notices"}, + {"id": "INTERACTION_L6", "value": 6, "label": "Interaction", "desc": "User responses"}, + {"id": "MISSION_L4", "value": 4, "label": "Mission", "desc": "Task execution"}, + {"id": "SERVICE_L2", "value": 2, "label": "Service", "desc": "Proactive services"}, + {"id": "BACKGROUND_L1", "value": 1, "label": "Background", "desc": "Background logging"}, +] + +AUDIO_VAD_STATES = {0: "None", 1: "Speech begin", 2: "Processing", 3: "Speech end"} + + +# -------------------------------------------------------------------------- +# Screen / face +# -------------------------------------------------------------------------- +SRV_PLAY_EMOJI = "/aimdk_5Fmsgs/srv/PlayEmoji" +TOPIC_FACE_STATUS = "/face_ui_proxy/status" + +EMOJI_PLAY_MODES = [{"value": 1, "label": "Once"}, {"value": 2, "label": "Loop"}] + +FACE_STATUS = {0: "Idle", 1: "Start", 2: "Running", 3: "Finished", 4: "Stopped"} + +EMOJIS = [ + {"id": 1, "label": "Blink", "glyph": "\U0001F60C", "group": "neutral"}, + {"id": 10, "label": "Calm (eyes 1)", "glyph": "\U0001F642", "group": "neutral"}, + {"id": 11, "label": "Calm (eyes 2)", "glyph": "\U0001F642", "group": "neutral"}, + {"id": 20, "label": "Calm (game)", "glyph": "\U0001F3AE", "group": "neutral"}, + {"id": 30, "label": "Cute 1", "glyph": "\U0001F970", "group": "neutral"}, + {"id": 31, "label": "Cute 2", "glyph": "\U0001F970", "group": "neutral"}, + {"id": 32, "label": "Cute 3", "glyph": "\U0001F970", "group": "neutral"}, + {"id": 33, "label": "Cute 4", "glyph": "\U0001F970", "group": "neutral"}, + {"id": 40, "label": "Close eyes", "glyph": "\U0001F636", "group": "neutral"}, + {"id": 50, "label": "Open eyes", "glyph": "\U0001F440", "group": "neutral"}, + {"id": 60, "label": "Bored", "glyph": "\U0001F644", "group": "neutral"}, + {"id": 80, "label": "Sleeping", "glyph": "\U0001F634", "group": "neutral"}, + + {"id": 90, "label": "Happy", "glyph": "\U0001F604", "group": "positive"}, + {"id": 100, "label": "Extra happy", "glyph": "\U0001F606", "group": "positive"}, + {"id": 101, "label": "Ecstatic", "glyph": "\U0001F929", "group": "positive"}, + {"id": 150, "label": "Acting cute", "glyph": "\U0001F60A", "group": "positive"}, + {"id": 200, "label": "Adoration", "glyph": "\U0001F60D", "group": "positive"}, + {"id": 210, "label": "Extra adoring", "glyph": "\U0001F929", "group": "positive"}, + + {"id": 110, "label": "Sad", "glyph": "\U0001F622", "group": "negative"}, + {"id": 120, "label": "Sympathy", "glyph": "\U0001F97A", "group": "negative"}, + {"id": 130, "label": "Confused", "glyph": "\U0001F615", "group": "negative"}, + {"id": 140, "label": "Shocked", "glyph": "\U0001F62E", "group": "negative"}, + {"id": 160, "label": "Serious", "glyph": "\U0001F610", "group": "negative"}, + {"id": 170, "label": "Thinking", "glyph": "\U0001F914", "group": "negative"}, + {"id": 180, "label": "Angry", "glyph": "\U0001F620", "group": "negative"}, + {"id": 190, "label": "Extra angry", "glyph": "\U0001F621", "group": "negative"}, + + {"id": 70, "label": "Abnormal", "glyph": "⚠️", "group": "system"}, + {"id": 220, "label": "Charging", "glyph": "\U0001F50B", "group": "system"}, +] + +EMOJI_GROUPS = [ + {"key": "neutral", "label": "Neutral"}, + {"key": "positive", "label": "Positive"}, + {"key": "negative", "label": "Negative"}, + {"key": "system", "label": "System"}, +] + + +# -------------------------------------------------------------------------- +# LED strip +# -------------------------------------------------------------------------- +SRV_SET_PMU_LED = "/aimdk_5Fmsgs/srv/SetPmuLed" +TOPIC_PMU_LED_STATE = "/aima/hal/pmu/led_state" + +LED_MODES = [ + {"value": 0, "label": "Steady", "desc": "Continuous solid colour"}, + {"value": 1, "label": "Breathing", "desc": "4 s sinusoidal brightness cycle"}, + {"value": 2, "label": "Blinking", "desc": "1 s cycle, toggles every 0.5 s"}, + {"value": 3, "label": "Flowing", "desc": "2 s cycle, left to right then off"}, +] + +LED_DEFAULT_PRIORITY = 6 + +LED_SWATCHES = [ + {"label": "Ice", "r": 57, "g": 135, "b": 229}, + {"label": "Aqua", "r": 25, "g": 158, "b": 112}, + {"label": "Amber", "r": 201, "g": 133, "b": 0}, + {"label": "Ember", "r": 217, "g": 89, "b": 38}, + {"label": "Rose", "r": 213, "g": 81, "b": 129}, + {"label": "Violet", "r": 144, "g": 133, "b": 233}, + {"label": "White", "r": 255, "g": 255, "b": 255}, + {"label": "Off", "r": 0, "g": 0, "b": 0}, +] + + +# -------------------------------------------------------------------------- +# System / diagnostics topics present on this robot +# -------------------------------------------------------------------------- +TOPIC_ALERT_CODES = "/aima/hds/alert_code_list" +TOPIC_SM_SYSTEM_STATE = "/aima/sm/system_state" +TOPIC_TASK_MASTER_STATE = "/task_master/state" +PROCESS_INFO_TOPICS = [ + "/aima/hds/process/info/soc0", + "/aima/hds/process/info/soc1", + "/aima/hds/process/info/soc2", +] + + +# -------------------------------------------------------------------------- +# Safety notes shown in the UI +# -------------------------------------------------------------------------- +SAFETY_NOTES = [ + {"scope": "mode", "level": "critical", + "text": "Passive and Zero-torque release all joint holding force. A free-standing robot " + "will collapse. Only select them when the robot is supported or already seated."}, + {"scope": "locomotion", "level": "warning", + "text": "Enter Stable stand and register an input source before driving. Keep the handheld " + "remote controller within reach - it outranks this dashboard."}, + {"scope": "preset", "level": "warning", + "text": "Preset motions require Stable stand and clear space around the robot."}, + {"scope": "network", "level": "critical", + "text": f"Never use PC1 ({PC1_MOTION_CONTROL_IP}) as a build or run host. The dashboard " + f"agent runs on PC2 ({PC2_DEVELOP_IP})."}, +] + + +def client_spec() -> dict: + """Everything the browser needs, in one payload.""" + return { + "modes": MC_MODES, + "mode_groups": MC_MODE_GROUPS, + "driveable_modes": sorted(DRIVEABLE_MODES), + "joint_control_modes_allowed": sorted(JOINT_CONTROL_MODES_ALLOWED), + "action_status": MC_ACTION_STATUS, + "presets": PRESET_MOTIONS, + "preset_groups": PRESET_GROUPS, + "control_areas": MC_CONTROL_AREAS, + "joint_groups": JOINT_GROUPS, + "joint_modes": JOINT_CONTROL_MODES, + "velocity_limits": VELOCITY_LIMITS, + "velocity_thresholds": VELOCITY_THRESHOLDS, + "cameras": CAMERAS, + "camera_inventory": CAMERA_INVENTORY, + "lidar": LIDAR, + "sensor_topics": SENSOR_TOPICS, + "touch_zones": TOUCH_ZONE_COUNT, + "pmu_rails": PMU_RAILS, + "pmu_info_fields": PMU_INFO_FIELDS, + "emojis": EMOJIS, + "emoji_groups": EMOJI_GROUPS, + "emoji_modes": EMOJI_PLAY_MODES, + "face_status": FACE_STATUS, + "led_modes": LED_MODES, + "led_swatches": LED_SWATCHES, + "tts_priorities": TTS_PRIORITIES, + "hand_presets": HAND_PRESETS, + "hand_types": HAND_TYPES, + "dexhand_joints": DEXHAND_JOINTS, + "builtin_input_sources": BUILTIN_INPUT_SOURCES, + "dashboard_input_source": DASHBOARD_INPUT_SOURCE, + "safety_notes": SAFETY_NOTES, + "agent_port": AGENT_PORT, + "topics": { + "locomotion": TOPIC_LOCOMOTION_VELOCITY, + "pmu": TOPIC_PMU_STATE, + "imu_chest": TOPIC_IMU_CHEST, + "imu_torso": TOPIC_IMU_TORSO, + "touch_head": TOPIC_TOUCH_HEAD, + "hand_command": TOPIC_HAND_COMMAND, + "hand_state": TOPIC_HAND_STATE, + "odometry": TOPIC_LEG_ODOMETRY, + "camera": CAMERAS[0]["topic"], + }, + } diff --git a/x2_dashboard/config.json b/x2_dashboard/config.json new file mode 100644 index 0000000..f8b78ca --- /dev/null +++ b/x2_dashboard/config.json @@ -0,0 +1,27 @@ +{ + "robot_host": "127.0.0.1", + "agent_port": 8781, + "robot_label": "AGIBOT X2", + "dashboard_name": "agibot", + "advertise_name": true, + "auto_discover": true, + "auto_start_agent": false, + "robot_ssh_user": "agi", + "robot_ssh_password": "", + "robot_ssh_port": 22, + "agent_start_command": "/home/agi/x2_dashboard_agent/ensure_agent.sh", + "ros_domain_id": 0, + "rmw_implementation": "rmw_fastrtps_cpp", + "bridge_mode": "agent", + "host": "0.0.0.0", + "port": 8770, + "telemetry_hz": 10, + "history_seconds": 120, + "require_confirm_zero_torque": true, + "locomotion_deadman_s": 0.5, + "max_forward_velocity": 0.8, + "max_lateral_velocity": 0.7, + "max_angular_velocity": 0.8, + "theme": "dark", + "accent": "blue" +} diff --git a/x2_dashboard/web/css/app.css b/x2_dashboard/web/css/app.css new file mode 100644 index 0000000..5da779c --- /dev/null +++ b/x2_dashboard/web/css/app.css @@ -0,0 +1,991 @@ +/* ========================================================================== + AGIBOT X2 Dashboard + Design tokens first, then layout, then components. + Series colours are the validated data-viz palette; chrome greys are neutral + so nothing competes with the data. + ========================================================================== */ + +:root { + color-scheme: dark; + + /* Surfaces */ + --bg: #0b0c0e; + --surface: #141619; + --surface-2: #1b1e22; + --surface-3: #23262b; + --surface-hi: #2b2f36; + --border: #262a30; + --border-soft: #1e2126; + + /* Ink */ + --text: #f2f4f7; + --text-2: #a4adb8; + --text-3: #6d7681; + + /* Categorical series - validated for CVD against a dark surface */ + --series-1: #3987e5; + --series-2: #d95926; + --series-3: #199e70; + --series-4: #c98500; + --series-5: #d55181; + --series-6: #008300; + --series-7: #9085e9; + --series-8: #e66767; + + /* Status - reserved, never used for a series */ + --good: #0ca30c; + --warning: #fab219; + --serious: #ec835a; + --critical: #d03b3b; + + --accent: var(--series-1); + --accent-soft: rgba(57, 135, 229, 0.14); + --accent-line: rgba(57, 135, 229, 0.4); + + /* Chart chrome */ + --grid: #22262c; + --axis: #333941; + + --radius: 12px; + --radius-sm: 8px; + --radius-lg: 18px; + + --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .6); + --shadow-lg: 0 20px 60px -20px rgba(0, 0, 0, .8); + + --rail-w: 216px; + --topbar-h: 60px; + + --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace; + + --ease: cubic-bezier(.2, .7, .3, 1); +} + +:root[data-theme="light"] { + color-scheme: light; + --bg: #f4f5f7; + --surface: #ffffff; + --surface-2: #f7f8fa; + --surface-3: #eef0f4; + --surface-hi: #e4e7ec; + --border: #dfe3e9; + --border-soft: #e9ecf1; + + --text: #10131a; + --text-2: #4d5663; + --text-3: #7d8794; + + --series-1: #2a78d6; + --series-2: #eb6834; + --series-3: #1baf7a; + --series-4: #eda100; + --series-5: #e87ba4; + --series-6: #008300; + --series-7: #4a3aa7; + --series-8: #e34948; + + --accent: var(--series-1); + --accent-soft: rgba(42, 120, 214, 0.1); + --accent-line: rgba(42, 120, 214, 0.35); + + --grid: #e8eaee; + --axis: #cfd4dc; + + --shadow: 0 1px 2px rgba(16, 19, 26, .06), 0 8px 24px -14px rgba(16, 19, 26, .18); + --shadow-lg: 0 24px 60px -24px rgba(16, 19, 26, .28); +} + +* { box-sizing: border-box; } + +html, body { + margin: 0; + height: 100%; + background: var(--bg); + color: var(--text); + font-family: var(--font); + font-size: 14px; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +body { overflow: hidden; } + +button, input, select, textarea { font: inherit; color: inherit; } +h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; } +a { color: var(--accent); } + +::-webkit-scrollbar { width: 10px; height: 10px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: var(--surface-hi); border-radius: 8px; border: 2px solid var(--bg); } +::-webkit-scrollbar-thumb:hover { background: var(--text-3); } + +:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; } + +/* ========================================================================== + App shell + ========================================================================== */ + +.app { + display: grid; + grid-template-columns: var(--rail-w) 1fr; + grid-template-rows: var(--topbar-h) 1fr; + grid-template-areas: "top top" "rail content"; + height: 100vh; + height: 100dvh; +} + +/* Grid and flex children default to min-width:auto, so their min-content width + props the track open and the whole page scrolls sideways on a phone. Every + shell region opts out and scrolls internally instead. */ +.app > * { min-width: 0; } + +/* -- Topbar -------------------------------------------------------------- */ + +.topbar { + grid-area: top; + display: flex; + align-items: center; + gap: 20px; + padding: 0 16px; + background: var(--surface); + border-bottom: 1px solid var(--border); + z-index: 30; +} + +.brand { display: flex; align-items: center; gap: 11px; min-width: 0; flex-shrink: 0; } + +.brand-mark { + width: 34px; height: 34px; + border-radius: 10px; + background: linear-gradient(150deg, var(--series-1), #1f4f8f); + display: grid; place-items: center; + flex-shrink: 0; + box-shadow: inset 0 1px 0 rgba(255,255,255,.2); +} +.brand-dot { + width: 9px; height: 9px; border-radius: 50%; + background: #fff; + box-shadow: 0 0 0 3px rgba(255,255,255,.25); +} +.brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; } +.brand-text strong { font-size: 14px; letter-spacing: -0.01em; } +.brand-text span { font-size: 11px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + +.topbar-status { + display: flex; align-items: center; gap: 8px; + flex: 1 1 0; min-width: 0; + overflow-x: auto; overflow-y: hidden; + scrollbar-width: none; +} +.topbar-status::-webkit-scrollbar { display: none; } + +.pill { + display: inline-flex; align-items: center; gap: 7px; + height: 30px; padding: 0 11px; + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: 999px; + font-size: 12px; + white-space: nowrap; + transition: background .15s var(--ease); +} +.pill-key { color: var(--text-3); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; } +.pill-label { font-weight: 550; font-variant-numeric: tabular-nums; } +.pill .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-3); flex-shrink: 0; } +.pill .dot[data-state="online"] { background: var(--good); box-shadow: 0 0 0 3px rgba(12,163,12,.18); } +.pill .dot[data-state="sim"] { background: var(--warning); box-shadow: 0 0 0 3px rgba(250,178,25,.18); } +.pill .dot[data-state="offline"]{ background: var(--critical); box-shadow: 0 0 0 3px rgba(208,59,59,.18); } +.pill[data-level="warning"] { border-color: rgba(250,178,25,.4); } +.pill[data-level="critical"]{ border-color: rgba(208,59,59,.5); background: rgba(208,59,59,.1); } + +.topbar-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } + +.icon-btn { + width: 34px; height: 34px; + display: grid; place-items: center; + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + cursor: pointer; + transition: background .15s var(--ease), border-color .15s var(--ease); +} +.icon-btn:hover { background: var(--surface-3); border-color: var(--surface-hi); } +.ico { width: 18px; height: 18px; fill: currentColor; display: block; } + +.btn-stop { + display: inline-flex; align-items: center; gap: 8px; + height: 34px; padding: 0 16px; + background: var(--critical); + color: #fff; + border: 1px solid transparent; + border-radius: var(--radius-sm); + font-weight: 700; font-size: 12px; letter-spacing: .08em; + cursor: pointer; + transition: filter .15s var(--ease), transform .08s var(--ease); +} +.btn-stop:hover { filter: brightness(1.12); } +.btn-stop:active { transform: scale(.97); } +.btn-stop .ico { width: 16px; height: 16px; } + +/* -- Rail ---------------------------------------------------------------- */ + +.rail { + grid-area: rail; + background: var(--surface); + border-right: 1px solid var(--border); + padding: 12px 10px; + overflow-y: auto; + display: flex; flex-direction: column; gap: 2px; +} + +.rail-group { + font-size: 10px; text-transform: uppercase; letter-spacing: .1em; + color: var(--text-3); font-weight: 600; + padding: 14px 10px 6px; +} +.rail-group:first-child { padding-top: 4px; } + +.rail-item { + display: flex; align-items: center; gap: 11px; + padding: 9px 11px; + border-radius: var(--radius-sm); + color: var(--text-2); + background: transparent; + border: 0; width: 100%; + cursor: pointer; + text-align: left; + font-size: 13px; font-weight: 500; + position: relative; + transition: background .13s var(--ease), color .13s var(--ease); +} +.rail-item .ico { width: 17px; height: 17px; flex-shrink: 0; opacity: .85; } +.rail-item:hover { background: var(--surface-2); color: var(--text); } +.rail-item[aria-current="page"] { + background: var(--accent-soft); + color: var(--text); + font-weight: 600; +} +.rail-item[aria-current="page"] .ico { opacity: 1; color: var(--accent); } +.rail-item[aria-current="page"]::before { + content: ""; position: absolute; left: -10px; top: 50%; transform: translateY(-50%); + width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--accent); +} +.rail-badge { + margin-left: auto; + font-size: 10px; font-weight: 700; + min-width: 18px; height: 18px; padding: 0 5px; + border-radius: 9px; + background: var(--surface-3); color: var(--text-2); + display: grid; place-items: center; + font-variant-numeric: tabular-nums; +} +.rail-badge[data-tone="warn"] { background: rgba(250,178,25,.2); color: var(--warning); } +.rail-badge[data-tone="bad"] { background: rgba(208,59,59,.2); color: var(--critical); } + +/* -- Content ------------------------------------------------------------- */ + +.content { + grid-area: content; + overflow-y: auto; + overflow-x: hidden; + padding: 20px 22px 60px; + scroll-behavior: smooth; +} +.content:focus { outline: none; } + +.page-head { + display: flex; align-items: flex-end; justify-content: space-between; + gap: 16px; flex-wrap: wrap; + margin-bottom: 18px; +} +.page-head h1 { font-size: 22px; letter-spacing: -0.02em; } +.page-head p { margin: 4px 0 0; color: var(--text-2); font-size: 13px; max-width: 68ch; } +.page-head-actions { display: flex; gap: 8px; flex-wrap: wrap; } + +/* ========================================================================== + Layout primitives + ========================================================================== */ + +.grid { display: grid; gap: 14px; } +.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); } +.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); } +.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); } +.grid.cols-auto { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } +/* A narrow leading column beside a flexible one. Collapses rather than + overflowing, which a fixed two-track template would do on a phone. */ +.grid.split { grid-template-columns: minmax(250px, 330px) 1fr; } +.grid.pair { grid-template-columns: 1fr 1fr; } +@media (max-width: 900px) { + .grid.split, .grid.pair { grid-template-columns: 1fr; } +} +.stack { display: flex; flex-direction: column; gap: 14px; } +.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; } +.row.tight { gap: 6px; } +.row.between { justify-content: space-between; } +.spacer { flex: 1; } +.span-2 { grid-column: span 2; } +@media (max-width: 820px) { .span-2 { grid-column: span 1; } } + +/* ========================================================================== + Card + ========================================================================== */ + +.card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; + display: flex; flex-direction: column; +} +.card-head { + display: flex; align-items: center; gap: 10px; + padding: 13px 16px; + border-bottom: 1px solid var(--border-soft); +} +.card-head h3 { font-size: 13px; letter-spacing: .01em; } +.card-head .sub { font-size: 11px; color: var(--text-3); } +.card-head-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; } +.card-body { padding: 16px; flex: 1; } +.card-body.flush { padding: 0; } +.card-foot { + padding: 10px 16px; + border-top: 1px solid var(--border-soft); + background: var(--surface-2); + font-size: 12px; color: var(--text-2); +} + +/* ========================================================================== + Buttons and inputs + ========================================================================== */ + +.btn { + display: inline-flex; align-items: center; justify-content: center; gap: 7px; + height: 34px; padding: 0 14px; + background: var(--surface-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + font-size: 13px; font-weight: 550; + cursor: pointer; + white-space: nowrap; + transition: background .13s var(--ease), border-color .13s var(--ease), transform .08s var(--ease); +} +.btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--surface-hi); } +.btn:active:not(:disabled) { transform: scale(.98); } +.btn:disabled { opacity: .42; cursor: not-allowed; } +.btn .ico { width: 15px; height: 15px; } + +.btn-primary { background: var(--accent); border-color: transparent; color: #fff; } +.btn-primary:hover:not(:disabled) { filter: brightness(1.12); background: var(--accent); } +.btn-danger { background: var(--critical); border-color: transparent; color: #fff; } +.btn-danger:hover:not(:disabled) { filter: brightness(1.12); background: var(--critical); } +.btn-warn { background: rgba(250,178,25,.16); border-color: rgba(250,178,25,.4); color: var(--warning); } +.btn-warn:hover:not(:disabled) { background: rgba(250,178,25,.24); } +.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); } +.btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); } +.btn-sm { height: 28px; padding: 0 10px; font-size: 12px; } +.btn-block { width: 100%; } + +.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; } +.field > label { font-size: 12px; font-weight: 550; color: var(--text-2); } +/* Not scoped to .field - hints are also used standalone beside toggles. */ +.hint { font-size: 11px; color: var(--text-3); line-height: 1.45; } + +.input, .select, .textarea { + height: 34px; + padding: 0 11px; + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text); + width: 100%; + transition: border-color .13s var(--ease), background .13s var(--ease); +} +.textarea { height: auto; min-height: 78px; padding: 9px 11px; resize: vertical; line-height: 1.5; } +.input:focus, .select:focus, .textarea:focus { + outline: none; border-color: var(--accent); background: var(--surface); + box-shadow: 0 0 0 3px var(--accent-soft); +} +.input::placeholder, .textarea::placeholder { color: var(--text-3); } +.select { appearance: none; cursor: pointer; padding-right: 30px; + background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); + background-position: right 13px center, right 8px center; + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; +} +.input[type="color"] { padding: 3px; height: 34px; cursor: pointer; } + +/* Toggle */ +.switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; } +.switch input { position: absolute; opacity: 0; width: 0; height: 0; } +.switch-track { + width: 38px; height: 21px; border-radius: 999px; + background: var(--surface-hi); border: 1px solid var(--border); + position: relative; flex-shrink: 0; + transition: background .16s var(--ease); +} +.switch-track::after { + content: ""; position: absolute; top: 2px; left: 2px; + width: 15px; height: 15px; border-radius: 50%; + background: var(--text-2); + transition: transform .16s var(--ease), background .16s var(--ease); +} +.switch input:checked + .switch-track { background: var(--accent); border-color: transparent; } +.switch input:checked + .switch-track::after { transform: translateX(17px); background: #fff; } +.switch input:focus-visible + .switch-track { box-shadow: 0 0 0 3px var(--accent-soft); } +.switch-label { font-size: 13px; } + +/* Range */ +.range { display: flex; align-items: center; gap: 12px; } +.range input[type="range"] { + flex: 1; appearance: none; height: 4px; border-radius: 2px; + background: var(--surface-hi); cursor: pointer; min-width: 60px; +} +.range input[type="range"]::-webkit-slider-thumb { + appearance: none; width: 16px; height: 16px; border-radius: 50%; + background: var(--accent); border: 2px solid var(--surface); + box-shadow: 0 1px 3px rgba(0,0,0,.4); cursor: grab; +} +.range input[type="range"]::-webkit-slider-thumb:active { cursor: grabbing; } +.range input[type="range"]::-moz-range-thumb { + width: 14px; height: 14px; border-radius: 50%; + background: var(--accent); border: 2px solid var(--surface); cursor: grab; +} +.range-value { + min-width: 62px; text-align: right; + font-variant-numeric: tabular-nums; font-size: 12px; + color: var(--text-2); font-family: var(--mono); +} + +/* Segmented control */ +.segmented { + display: inline-flex; padding: 3px; gap: 2px; + background: var(--surface-2); border: 1px solid var(--border); + border-radius: var(--radius-sm); +} +.segmented button { + border: 0; background: transparent; color: var(--text-2); + padding: 5px 12px; border-radius: 6px; cursor: pointer; + font-size: 12px; font-weight: 550; + transition: background .13s var(--ease), color .13s var(--ease); +} +.segmented button:hover { color: var(--text); } +.segmented button[aria-pressed="true"] { background: var(--surface-hi); color: var(--text); } + +/* ========================================================================== + Stat tiles & meters + ========================================================================== */ + +.stat { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 14px 15px; + display: flex; flex-direction: column; gap: 3px; + min-width: 0; +} +.stat-label { + font-size: 11px; color: var(--text-3); + text-transform: uppercase; letter-spacing: .07em; font-weight: 600; +} +.stat-value { + font-size: 25px; font-weight: 600; letter-spacing: -.02em; + line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} +.stat-value .unit { font-size: 13px; font-weight: 500; color: var(--text-3); margin-left: 3px; } +.stat-sub { font-size: 11.5px; color: var(--text-3); } +.stat-spark { margin-top: 6px; height: 30px; } +.stat[data-tone="good"] .stat-value { color: var(--good); } +.stat[data-tone="warning"] .stat-value { color: var(--warning); } +.stat[data-tone="critical"] .stat-value { color: var(--critical); } + +.hero { + font-size: 52px; font-weight: 600; letter-spacing: -.03em; line-height: 1; +} +.hero .unit { font-size: 20px; color: var(--text-3); margin-left: 4px; font-weight: 500; } + +.meter { height: 7px; border-radius: 4px; background: var(--surface-hi); overflow: hidden; } +.meter-fill { height: 100%; border-radius: 4px; background: var(--accent); transition: width .35s var(--ease), background .3s var(--ease); } +.meter-fill[data-tone="good"] { background: var(--good); } +.meter-fill[data-tone="warning"] { background: var(--warning); } +.meter-fill[data-tone="critical"] { background: var(--critical); } + +/* ========================================================================== + Badges, chips, notes + ========================================================================== */ + +.badge { + display: inline-flex; align-items: center; gap: 5px; + height: 21px; padding: 0 8px; + border-radius: 6px; + font-size: 11px; font-weight: 600; + background: var(--surface-3); color: var(--text-2); + white-space: nowrap; +} +.badge[data-tone="good"] { background: rgba(12,163,12,.15); color: var(--good); } +.badge[data-tone="warning"] { background: rgba(250,178,25,.15); color: var(--warning); } +.badge[data-tone="serious"] { background: rgba(236,131,90,.15); color: var(--serious); } +.badge[data-tone="critical"] { background: rgba(208,59,59,.16); color: var(--critical); } +.badge[data-tone="accent"] { background: var(--accent-soft); color: var(--accent); } + +.note { + display: flex; gap: 10px; align-items: flex-start; + padding: 11px 13px; + border-radius: var(--radius-sm); + font-size: 12.5px; line-height: 1.5; + background: var(--surface-2); + border: 1px solid var(--border); + color: var(--text-2); +} +.note strong { color: var(--text); font-weight: 600; } +.note-icon { flex-shrink: 0; font-size: 14px; line-height: 1.3; } +.note[data-level="critical"] { background: rgba(208,59,59,.08); border-color: rgba(208,59,59,.3); } +.note[data-level="warning"] { background: rgba(250,178,25,.07); border-color: rgba(250,178,25,.28); } +.note[data-level="info"] { background: var(--accent-soft); border-color: var(--accent-line); } + +.kv { display: grid; grid-template-columns: auto 1fr; gap: 7px 16px; font-size: 12.5px; align-items: baseline; } +.kv dt { color: var(--text-3); white-space: nowrap; } +.kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); font-size: 12px; word-break: break-all; } + +.mono { font-family: var(--mono); font-size: 12px; } +.muted { color: var(--text-3); } +.nowrap { white-space: nowrap; } + +/* ========================================================================== + Tables + ========================================================================== */ + +.table-wrap { overflow-x: auto; } +table.data { + width: 100%; border-collapse: collapse; font-size: 12.5px; +} +table.data th { + text-align: left; font-weight: 600; font-size: 11px; + text-transform: uppercase; letter-spacing: .06em; + color: var(--text-3); + padding: 9px 14px; + border-bottom: 1px solid var(--border); + background: var(--surface-2); + position: sticky; top: 0; z-index: 1; + white-space: nowrap; +} +table.data td { + padding: 8px 14px; + border-bottom: 1px solid var(--border-soft); + font-variant-numeric: tabular-nums; + white-space: nowrap; +} +table.data tr:last-child td { border-bottom: 0; } +table.data tbody tr:hover { background: var(--surface-2); } +table.data td.num { text-align: right; font-family: var(--mono); font-size: 11.5px; } +table.data td.name { font-weight: 500; white-space: normal; } + +/* ========================================================================== + Joystick + ========================================================================== */ + +.joystick-wrap { display: flex; gap: 22px; flex-wrap: wrap; align-items: flex-start; } + +.joystick { + width: 200px; height: 200px; + border-radius: 50%; + background: radial-gradient(circle at 50% 42%, var(--surface-3), var(--surface-2) 68%); + border: 1px solid var(--border); + position: relative; + touch-action: none; + cursor: grab; + flex-shrink: 0; + user-select: none; +} +.joystick:active { cursor: grabbing; } +.joystick::before, .joystick::after { + content: ""; position: absolute; background: var(--border); pointer-events: none; +} +.joystick::before { left: 12%; right: 12%; top: 50%; height: 1px; } +.joystick::after { top: 12%; bottom: 12%; left: 50%; width: 1px; } +.joystick-ring { + position: absolute; inset: 22%; + border: 1px dashed var(--border); border-radius: 50%; pointer-events: none; +} +.joystick-knob { + position: absolute; width: 56px; height: 56px; + left: 50%; top: 50%; margin: -28px 0 0 -28px; + border-radius: 50%; + background: linear-gradient(160deg, var(--accent), #1f4f8f); + box-shadow: 0 4px 14px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.24); + pointer-events: none; + transition: transform .05s linear; +} +.joystick[data-active="false"] .joystick-knob { transition: transform .22s var(--ease); } +.joystick-label { + position: absolute; font-size: 10px; color: var(--text-3); + text-transform: uppercase; letter-spacing: .08em; pointer-events: none; font-weight: 600; +} +.joystick-label.n { top: 8px; left: 50%; transform: translateX(-50%); } +.joystick-label.s { bottom: 8px; left: 50%; transform: translateX(-50%); } +.joystick-label.w { left: 8px; top: 50%; transform: translateY(-50%); } +.joystick-label.e { right: 8px; top: 50%; transform: translateY(-50%); } + +.joystick-readout { display: flex; flex-direction: column; gap: 12px; min-width: 190px; flex: 1; } + +/* Key hints */ +.keys { display: flex; gap: 5px; flex-wrap: wrap; } +kbd { + display: inline-grid; place-items: center; + min-width: 22px; height: 22px; padding: 0 6px; + background: var(--surface-3); border: 1px solid var(--border); + border-bottom-width: 2px; + border-radius: 5px; + font-family: var(--mono); font-size: 11px; color: var(--text-2); +} + +/* ========================================================================== + Preset / emoji / swatch grids + ========================================================================== */ + +.tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(126px, 1fr)); gap: 8px; } + +.tile { + display: flex; flex-direction: column; gap: 3px; + padding: 11px 12px; + background: var(--surface-2); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + cursor: pointer; text-align: left; + transition: background .13s var(--ease), border-color .13s var(--ease), transform .08s var(--ease); +} +.tile:hover:not(:disabled) { background: var(--surface-3); border-color: var(--accent-line); } +.tile:active:not(:disabled) { transform: scale(.97); } +.tile:disabled { opacity: .4; cursor: not-allowed; } +.tile-name { font-size: 12.5px; font-weight: 550; } +.tile-meta { font-size: 10.5px; color: var(--text-3); font-family: var(--mono); } +.tile[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); } + +.emoji-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 7px; } +.emoji-tile { + display: flex; flex-direction: column; align-items: center; gap: 5px; + padding: 11px 6px; + background: var(--surface-2); border: 1px solid var(--border); + border-radius: var(--radius-sm); cursor: pointer; + transition: background .13s var(--ease), border-color .13s var(--ease), transform .08s var(--ease); +} +.emoji-tile:hover { background: var(--surface-3); border-color: var(--accent-line); } +.emoji-tile:active { transform: scale(.95); } +.emoji-glyph { font-size: 24px; line-height: 1; } +.emoji-name { font-size: 10px; color: var(--text-3); text-align: center; line-height: 1.25; } +.emoji-tile[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); } + +.swatches { display: flex; gap: 7px; flex-wrap: wrap; } +.swatch { + width: 34px; height: 34px; border-radius: 9px; + border: 1px solid var(--border); + cursor: pointer; position: relative; + transition: transform .1s var(--ease), box-shadow .13s var(--ease); +} +.swatch:hover { transform: scale(1.08); } +.swatch[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); } + +/* ========================================================================== + Charts + ========================================================================== */ + +.chart { width: 100%; display: block; overflow: visible; } +.chart .grid-line { stroke: var(--grid); stroke-width: 1; shape-rendering: crispEdges; } +.chart .axis-line { stroke: var(--axis); stroke-width: 1; shape-rendering: crispEdges; } +.chart .tick-text { fill: var(--text-3); font-size: 10px; font-family: var(--font); font-variant-numeric: tabular-nums; } +.chart .series-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; } +.chart .series-area { stroke: none; opacity: .1; } +.chart .end-dot { stroke: var(--surface); stroke-width: 2; } +.chart .crosshair { stroke: var(--text-3); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; } +.chart .end-label { fill: var(--text-2); font-size: 10.5px; font-family: var(--font); font-variant-numeric: tabular-nums; } + +.legend { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 8px; } +.legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-2); } +.legend-key { width: 11px; height: 2.5px; border-radius: 2px; flex-shrink: 0; } + +.chart-tip { + position: fixed; z-index: 60; pointer-events: none; + background: var(--surface-3); + border: 1px solid var(--surface-hi); + border-radius: var(--radius-sm); + padding: 8px 10px; + font-size: 11.5px; + box-shadow: var(--shadow-lg); + min-width: 118px; + opacity: 0; transition: opacity .1s; +} +.chart-tip[data-show="true"] { opacity: 1; } +.chart-tip .tip-time { color: var(--text-3); font-size: 10.5px; margin-bottom: 5px; } +.chart-tip .tip-row { display: flex; align-items: center; gap: 7px; justify-content: space-between; } +.chart-tip .tip-row b { font-variant-numeric: tabular-nums; font-weight: 600; } + +/* Gauge / attitude. The horizon plate is drawn oversized and clipped, so this + svg must not inherit the overflow:visible that line charts need for labels. */ +.attitude { display: grid; place-items: center; } +.attitude .chart { overflow: hidden; } + +/* ========================================================================== + Camera + ========================================================================== */ + +.cam { + position: relative; + background: #000; + border-radius: var(--radius-sm); + overflow: hidden; + aspect-ratio: 4 / 3; + display: grid; place-items: center; +} +.cam img { width: 100%; height: 100%; object-fit: cover; display: block; image-rendering: auto; } +.cam-placeholder { color: var(--text-3); font-size: 12px; text-align: center; padding: 20px; line-height: 1.6; } +.cam-overlay { + position: absolute; inset: auto 0 0 0; + padding: 8px 10px; + background: linear-gradient(transparent, rgba(0,0,0,.75)); + display: flex; justify-content: space-between; align-items: center; + font-size: 11px; color: #e8ecf2; + font-family: var(--mono); +} +.cam-live { display: inline-flex; align-items: center; gap: 5px; } +.cam-live::before { + content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--critical); + animation: pulse 1.6s ease-in-out infinite; +} +@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .3 } } + +/* ========================================================================== + Console / log + ========================================================================== */ + +.log { + font-family: var(--mono); font-size: 11.5px; + max-height: 460px; overflow-y: auto; + background: var(--bg); +} +.log-row { + display: grid; grid-template-columns: 74px 62px 100px 1fr; + gap: 10px; padding: 5px 14px; + border-bottom: 1px solid var(--border-soft); + align-items: baseline; +} +.log-row:hover { background: var(--surface-2); } +.log-time { color: var(--text-3); } +.log-level { font-weight: 700; font-size: 10px; text-transform: uppercase; letter-spacing: .05em; } +.log-level[data-level="info"] { color: var(--series-1); } +.log-level[data-level="warn"] { color: var(--warning); } +.log-level[data-level="error"] { color: var(--critical); } +.log-source { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; } +.log-msg { color: var(--text-2); white-space: pre-wrap; word-break: break-word; } + +/* ========================================================================== + Toasts & modal + ========================================================================== */ + +.toasts { + position: fixed; right: 18px; bottom: 18px; z-index: 100; + display: flex; flex-direction: column-reverse; gap: 9px; + max-width: min(400px, calc(100vw - 36px)); +} +.toast { + display: flex; gap: 10px; align-items: flex-start; + padding: 11px 14px; + background: var(--surface-3); + border: 1px solid var(--surface-hi); + border-left: 3px solid var(--accent); + border-radius: var(--radius-sm); + box-shadow: var(--shadow-lg); + font-size: 12.5px; + animation: toast-in .22s var(--ease); +} +.toast[data-tone="good"] { border-left-color: var(--good); } +.toast[data-tone="warning"] { border-left-color: var(--warning); } +.toast[data-tone="critical"] { border-left-color: var(--critical); } +.toast.leaving { animation: toast-out .18s var(--ease) forwards; } +.toast-body { flex: 1; min-width: 0; } +.toast-title { font-weight: 600; margin-bottom: 2px; } +.toast-msg { color: var(--text-2); word-break: break-word; } +@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.97) } } +@keyframes toast-out { to { opacity: 0; transform: translateX(20px) } } + +.modal-backdrop { + position: fixed; inset: 0; z-index: 200; + background: rgba(0,0,0,.6); + display: grid; place-items: center; + padding: 20px; + backdrop-filter: blur(3px); +} +.modal-backdrop[hidden] { display: none; } +.modal { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + padding: 22px; + max-width: 440px; width: 100%; + box-shadow: var(--shadow-lg); + animation: toast-in .2s var(--ease); +} +.modal h2 { font-size: 16px; margin-bottom: 8px; } +.modal p { color: var(--text-2); font-size: 13px; margin: 0 0 20px; line-height: 1.55; } +.modal-actions { display: flex; gap: 9px; justify-content: flex-end; } + +/* ========================================================================== + Offline gate - covers everything while the robot is unreachable + ========================================================================== */ + +.gate { + position: fixed; inset: 0; z-index: 300; + display: grid; place-items: center; + padding: 24px; + background: var(--bg); + animation: gate-in .25s var(--ease); +} +.gate[hidden] { display: none; } +@keyframes gate-in { from { opacity: 0 } } + +.gate-card { + max-width: 520px; width: 100%; + text-align: center; + display: flex; flex-direction: column; align-items: center; gap: 16px; +} +.gate-icon { color: var(--warning); line-height: 0; } +.gate-icon svg { animation: gate-pulse 2.6s ease-in-out infinite; } +@keyframes gate-pulse { 0%, 100% { opacity: .85 } 50% { opacity: .38 } } + +.gate-card h1 { font-size: 26px; letter-spacing: -.02em; } +.gate-card > p { + margin: 0; color: var(--text-2); font-size: 14px; line-height: 1.6; max-width: 44ch; +} + +.gate-status { + display: inline-flex; align-items: center; gap: 10px; + padding: 9px 16px; + background: var(--surface); border: 1px solid var(--border); + border-radius: 999px; + font-size: 12.5px; color: var(--text-2); +} +.gate-spinner { + width: 13px; height: 13px; flex-shrink: 0; + border: 2px solid var(--surface-hi); + border-top-color: var(--accent); + border-radius: 50%; + animation: spin .9s linear infinite; +} + +.gate-facts { + display: grid; grid-template-columns: auto auto; gap: 6px 18px; + margin: 0; font-size: 12px; + padding: 14px 20px; + background: var(--surface); border: 1px solid var(--border); + border-radius: var(--radius); + text-align: left; +} +.gate-facts dt { color: var(--text-3); } +.gate-facts dd { margin: 0; font-family: var(--mono); font-size: 11.5px; text-align: right; } + +.gate-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; } + +.gate-address { + width: 100%; max-width: 420px; + display: flex; flex-direction: column; gap: 7px; + padding: 14px 16px; + background: var(--surface); border: 1px solid var(--border); + border-radius: var(--radius); + text-align: left; +} +.gate-address[hidden] { display: none; } +.gate-address > label { font-size: 12px; font-weight: 550; color: var(--text-2); } +.gate-address-row { display: flex; gap: 8px; } +.gate-address-row .input { flex: 1; min-width: 0; } + +.gate-results { + width: 100%; max-width: 460px; + display: flex; flex-direction: column; gap: 7px; + text-align: left; +} +.gate-results[hidden] { display: none; } +.gate-result { + display: flex; align-items: center; gap: 10px; + padding: 10px 13px; + background: var(--surface); border: 1px solid var(--border); + border-radius: var(--radius-sm); + font-size: 12.5px; +} +.gate-result .host { font-family: var(--mono); font-size: 12.5px; } +.gate-result .spacer { flex: 1; } +/* Needs to out-specify `.gate-card > p` above, which would otherwise make the + hint as prominent as the main message. */ +.gate-card > p.gate-hint { + margin: 0; font-size: 11.5px; color: var(--text-3); max-width: 46ch; line-height: 1.6; +} + +/* While the gate is up the shell behind it must not be reachable by keyboard. */ +.app[inert] { filter: blur(2px); } + +/* ========================================================================== + Empty / loading + ========================================================================== */ + +.empty { + padding: 44px 20px; text-align: center; color: var(--text-3); font-size: 13px; + display: flex; flex-direction: column; align-items: center; gap: 10px; +} +.empty-title { font-size: 14px; font-weight: 600; color: var(--text-2); } + +.skeleton { + background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%); + background-size: 200% 100%; + animation: shimmer 1.3s infinite; + border-radius: var(--radius-sm); +} +@keyframes shimmer { to { background-position: -200% 0 } } + +.spin { animation: spin 1s linear infinite; } +@keyframes spin { to { transform: rotate(360deg) } } + +/* ========================================================================== + Responsive + ========================================================================== */ + +@media (max-width: 980px) { + :root { --rail-w: 60px; } + .rail-item span:not(.rail-badge) { display: none; } + .rail-item { justify-content: center; padding: 11px 0; } + .rail-group { display: none; } + .rail-item .rail-badge { position: absolute; top: 3px; right: 3px; margin: 0; } + .brand-text { display: none; } +} + +@media (max-width: 720px) { + .app { + grid-template-columns: 1fr; + grid-template-rows: var(--topbar-h) 1fr auto; + grid-template-areas: "top" "content" "rail"; + } + .rail { + flex-direction: row; + border-right: 0; border-top: 1px solid var(--border); + overflow-x: auto; overflow-y: hidden; + padding: 7px 8px; + padding-bottom: max(7px, env(safe-area-inset-bottom)); + } + .rail-item { flex-direction: column; gap: 3px; min-width: 56px; font-size: 10px; padding: 7px 4px; } + .rail-item span:not(.rail-badge) { display: block; font-size: 9.5px; } + .rail-item[aria-current="page"]::before { display: none; } + .content { padding: 14px 13px 28px; } + .topbar { padding: 0 11px; gap: 10px; } + .topbar-status { gap: 5px; } + .pill[data-optional] { display: none; } + .page-head h1 { font-size: 19px; } + .toasts { right: 10px; left: 10px; bottom: 78px; max-width: none; } + .joystick { width: 172px; height: 172px; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/x2_dashboard/web/index.html b/x2_dashboard/web/index.html new file mode 100644 index 0000000..be85cf0 --- /dev/null +++ b/x2_dashboard/web/index.html @@ -0,0 +1,176 @@ + + + + + + +AGIBOT X2 · Control Dashboard + + + + + + + +
+ +
+
+ +
+ AGIBOT X2 + Control dashboard +
+
+ +
+
+ + Connecting +
+
+ Mode + +
+
+ Batt + +
+
+ Host + +
+
+ +
+ + +
+
+ + + +
+ +
+ + + + +
+ + + + + + + + diff --git a/x2_dashboard/web/js/charts.js b/x2_dashboard/web/js/charts.js new file mode 100644 index 0000000..50fa6b6 --- /dev/null +++ b/x2_dashboard/web/js/charts.js @@ -0,0 +1,423 @@ +/* ========================================================================== + SVG charts. + + Mark specs follow the house data-viz rules: 2px lines with round joins, area + washes at 10% opacity, >=8px end markers carrying a 2px surface ring, solid + hairline gridlines, selective direct labels (endpoint only), a legend + whenever there are two or more series, and a crosshair + tooltip on hover. + Text always wears text tokens, never the series colour. + ========================================================================== */ + +import { el, clear } from './ui.js'; +import { seriesColor, cssVar } from './core.js'; + +const NS = 'http://www.w3.org/2000/svg'; + +function svgEl(tag, attrs = {}) { + const node = document.createElementNS(NS, tag); + for (const [key, value] of Object.entries(attrs)) { + if (value !== null && value !== undefined) node.setAttribute(key, value); + } + return node; +} + +function niceTicks(min, max, count = 4) { + if (!Number.isFinite(min) || !Number.isFinite(max)) return [0, 1]; + if (min === max) { min -= 0.5; max += 0.5; } + const span = max - min; + const raw = span / count; + const magnitude = Math.pow(10, Math.floor(Math.log10(raw))); + const normalised = raw / magnitude; + const step = (normalised >= 5 ? 10 : normalised >= 2 ? 5 : normalised >= 1 ? 2 : 1) * magnitude; + const ticks = []; + for (let t = Math.ceil(min / step) * step; t <= max + step * 0.001; t += step) { + ticks.push(Number(t.toFixed(10))); + } + return ticks.length >= 2 ? ticks : [min, max]; +} + +const fmt = (v, precision) => Number(v).toLocaleString(undefined, { + minimumFractionDigits: precision, maximumFractionDigits: precision, +}); + +/* -- Sparkline ------------------------------------------------------------ */ + +/** + * A bare trend line for a stat tile. No axes, no legend - the tile's label and + * value carry the meaning; this only shows shape. + */ +export function sparkline(points, { width = 200, height = 30, colorIndex = 0, fill = true } = {}) { + const svg = svgEl('svg', { + class: 'chart', viewBox: `0 0 ${width} ${height}`, + preserveAspectRatio: 'none', height, + }); + svg.style.width = '100%'; + + const values = (points || []).map((p) => (Array.isArray(p) ? p[1] : p)).filter(Number.isFinite); + if (values.length < 2) return svg; + + const min = Math.min(...values); + const max = Math.max(...values); + const span = (max - min) || 1; + const pad = 3; + const x = (i) => (i / (values.length - 1)) * width; + const y = (v) => height - pad - ((v - min) / span) * (height - pad * 2); + + const line = values.map((v, i) => `${i ? 'L' : 'M'}${x(i).toFixed(2)},${y(v).toFixed(2)}`).join(''); + const color = seriesColor(colorIndex); + + if (fill) { + svg.appendChild(svgEl('path', { + class: 'series-area', d: `${line}L${width},${height}L0,${height}Z`, fill: color, + })); + } + svg.appendChild(svgEl('path', { class: 'series-line', d: line, stroke: color })); + svg.appendChild(svgEl('circle', { + class: 'end-dot', cx: width, cy: y(values.at(-1)), r: 2.5, fill: color, + })); + return svg; +} + +/* -- Time series ---------------------------------------------------------- */ + +/** + * series: [{ key, label, points: [[ts, value], ...], colorIndex, unit }] + * Returns a container element with an .update(series) method. + */ +export function timeSeries(series, { + height = 200, precision = 2, unit = '', yMin = null, yMax = null, + zeroLine = false, showLegend = null, directLabel = true, +} = {}) { + const host = el('div', { style: { position: 'relative' } }); + const svg = svgEl('svg', { class: 'chart', height, preserveAspectRatio: 'none' }); + svg.style.width = '100%'; + host.appendChild(svg); + + const tip = el('div.chart-tip'); + document.body.appendChild(tip); + let currentSeries = series; + let hover = null; + + const cleanup = new MutationObserver(() => { + if (!host.isConnected) { tip.remove(); cleanup.disconnect(); } + }); + cleanup.observe(document.body, { childList: true, subtree: true }); + + function render() { + const rect = host.getBoundingClientRect(); + const width = Math.max(220, rect.width || 480); + const padL = 44, padR = directLabel ? 52 : 12, padT = 10, padB = 22; + const plotW = width - padL - padR; + const plotH = height - padT - padB; + + clear(svg); + svg.setAttribute('viewBox', `0 0 ${width} ${height}`); + + const active = currentSeries.filter((s) => (s.points || []).length >= 2); + if (!active.length) { + svg.appendChild(svgEl('text', { + x: width / 2, y: height / 2, 'text-anchor': 'middle', class: 'tick-text', + })).textContent = 'Waiting for data…'; + return; + } + + const allValues = active.flatMap((s) => s.points.map((p) => p[1])).filter(Number.isFinite); + const allTimes = active.flatMap((s) => s.points.map((p) => p[0])); + let lo = yMin !== null ? yMin : Math.min(...allValues); + let hi = yMax !== null ? yMax : Math.max(...allValues); + if (lo === hi) { lo -= 0.5; hi += 0.5; } + const headroom = (hi - lo) * 0.12; + if (yMin === null) lo -= headroom; + if (yMax === null) hi += headroom; + if (zeroLine) { lo = Math.min(lo, 0); hi = Math.max(hi, 0); } + + const t0 = Math.min(...allTimes), t1 = Math.max(...allTimes); + const tSpan = (t1 - t0) || 1; + const X = (t) => padL + ((t - t0) / tSpan) * plotW; + const Y = (v) => padT + plotH - ((v - lo) / (hi - lo)) * plotH; + + // Gridlines - solid hairlines, one step off the surface, recessive. + for (const tick of niceTicks(lo, hi, 4)) { + if (tick < lo || tick > hi) continue; + const y = Y(tick); + svg.appendChild(svgEl('line', { class: 'grid-line', x1: padL, x2: padL + plotW, y1: y, y2: y })); + const label = svgEl('text', { class: 'tick-text', x: padL - 7, y: y + 3.5, 'text-anchor': 'end' }); + label.textContent = fmt(tick, precision); + svg.appendChild(label); + } + + if (zeroLine && lo < 0 && hi > 0) { + svg.appendChild(svgEl('line', { class: 'axis-line', x1: padL, x2: padL + plotW, y1: Y(0), y2: Y(0) })); + } + + svg.appendChild(svgEl('line', { + class: 'axis-line', x1: padL, x2: padL + plotW, y1: padT + plotH, y2: padT + plotH, + })); + + const surface = cssVar('--surface') || '#141619'; + + // When series converge their end-labels overlap. Nudging them apart would + // detach each label from its line and read as noise, so drop direct labels + // for this render and let the legend and tooltip carry identity instead. + const endYs = active.map((s) => Y(s.points.at(-1)[1])).sort((a, b) => a - b); + const labelsCollide = endYs.some((y, i) => i > 0 && Math.abs(y - endYs[i - 1]) < 13); + const showEndLabels = directLabel && !labelsCollide; + + active.forEach((s, i) => { + const color = seriesColor(s.colorIndex ?? i); + const path = s.points + .map((p, idx) => `${idx ? 'L' : 'M'}${X(p[0]).toFixed(2)},${Y(p[1]).toFixed(2)}`) + .join(''); + + if (active.length === 1) { + svg.appendChild(svgEl('path', { + class: 'series-area', fill: color, + d: `${path}L${X(t1)},${padT + plotH}L${X(t0)},${padT + plotH}Z`, + })); + } + svg.appendChild(svgEl('path', { class: 'series-line', d: path, stroke: color })); + + // End marker: >=8px with a 2px surface ring so overlaps stay legible. + const last = s.points.at(-1); + svg.appendChild(svgEl('circle', { + class: 'end-dot', cx: X(last[0]), cy: Y(last[1]), r: 4, fill: color, stroke: surface, + })); + + // Direct-label the endpoint only - never a number on every point. + if (showEndLabels) { + const label = svgEl('text', { + class: 'end-label', x: X(last[0]) + 9, y: Y(last[1]) + 3.5, + }); + label.textContent = `${fmt(last[1], precision)}${s.unit ?? unit}`; + svg.appendChild(label); + } + }); + + if (hover !== null) { + const x = padL + hover * plotW; + svg.appendChild(svgEl('line', { class: 'crosshair', x1: x, x2: x, y1: padT, y2: padT + plotH })); + } + + // Hover layer sits above everything and is the full plot height, so the hit + // target is far bigger than the marks. + const overlay = svgEl('rect', { + x: padL, y: padT, width: plotW, height: plotH, fill: 'transparent', style: 'cursor:crosshair', + }); + overlay.addEventListener('pointermove', (event) => { + const bounds = svg.getBoundingClientRect(); + const scale = width / bounds.width; + const px = (event.clientX - bounds.left) * scale; + hover = Math.max(0, Math.min(1, (px - padL) / plotW)); + const t = t0 + hover * tSpan; + + const rows = active.map((s, i) => { + let best = s.points[0], bestGap = Infinity; + for (const p of s.points) { + const gap = Math.abs(p[0] - t); + if (gap < bestGap) { bestGap = gap; best = p; } + } + return { label: s.label, value: best[1], unit: s.unit ?? unit, color: seriesColor(s.colorIndex ?? i) }; + }); + + tip.innerHTML = ''; + tip.appendChild(el('div.tip-time', { text: new Date(t * 1000).toLocaleTimeString([], { hour12: false }) })); + for (const row of rows) { + tip.appendChild(el('div.tip-row', {}, + el('span', { style: { display: 'inline-flex', alignItems: 'center', gap: '6px' } }, + el('span', { style: { width: '10px', height: '2.5px', borderRadius: '2px', background: row.color } }), + el('span', { text: row.label, style: { color: 'var(--text-2)' } }), + ), + el('b', { text: `${fmt(row.value, precision)}${row.unit}` }), + )); + } + tip.dataset.show = 'true'; + const tipBox = tip.getBoundingClientRect(); + tip.style.left = `${Math.min(window.innerWidth - tipBox.width - 10, event.clientX + 14)}px`; + tip.style.top = `${Math.max(10, event.clientY - tipBox.height - 12)}px`; + render(); + }); + overlay.addEventListener('pointerleave', () => { + hover = null; tip.dataset.show = 'false'; render(); + }); + svg.appendChild(overlay); + } + + // A legend is always present for two or more series - identity never rests on + // colour alone. One series needs none; the card title already names it. + const legendVisible = showLegend ?? (series.length >= 2); + if (legendVisible) { + const legend = el('div.legend'); + series.forEach((s, i) => { + legend.appendChild(el('div.legend-item', {}, + el('span.legend-key', { style: { background: seriesColor(s.colorIndex ?? i) } }), + el('span', { text: s.label }), + )); + }); + host.appendChild(legend); + } + + host.update = (next) => { currentSeries = next; render(); }; + host.redraw = render; + + requestAnimationFrame(render); + const observer = new ResizeObserver(() => render()); + observer.observe(host); + + return host; +} + +/* -- Horizontal bars ------------------------------------------------------ */ + +/** + * rows: [{ label, value, min, max, tone }] + * Used for joint positions - a diverging bar around a zero centre reads better + * than a table of numbers when you are looking for the joint that is off. + */ +export function bars(rows, { height = 20, precision = 2, unit = '', diverging = true } = {}) { + const host = el('div', { style: { display: 'flex', flexDirection: 'column', gap: '4px' } }); + + for (const row of rows) { + const min = row.min ?? -1; + const max = row.max ?? 1; + const span = (max - min) || 1; + const value = Math.max(min, Math.min(max, row.value ?? 0)); + + const zeroFrac = diverging && min < 0 && max > 0 ? (0 - min) / span : 0; + const valueFrac = (value - min) / span; + const left = Math.min(zeroFrac, valueFrac) * 100; + const width = Math.abs(valueFrac - zeroFrac) * 100; + + const track = el('div', { + style: { + position: 'relative', height: `${height - 8}px`, borderRadius: '3px', + background: 'var(--surface-3)', flex: '1', minWidth: '60px', overflow: 'hidden', + }, + }, + // 4px rounded data-end, square where it meets the baseline. + el('div', { + style: { + position: 'absolute', left: `${left}%`, width: `${Math.max(width, 0.6)}%`, + top: '0', bottom: '0', + background: row.tone === 'critical' ? 'var(--critical)' + : row.tone === 'warning' ? 'var(--warning)' : seriesColor(row.colorIndex ?? 0), + borderRadius: valueFrac >= zeroFrac ? '0 4px 4px 0' : '4px 0 0 4px', + }, + }), + zeroFrac > 0 ? el('div', { + style: { + position: 'absolute', left: `${zeroFrac * 100}%`, top: '0', bottom: '0', + width: '1px', background: 'var(--axis)', + }, + }) : null, + ); + + host.appendChild(el('div', { style: { display: 'flex', alignItems: 'center', gap: '10px' } }, + el('span', { + text: row.label, + style: { fontSize: '11.5px', color: 'var(--text-2)', minWidth: '118px', + whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }, + }), + track, + el('span', { + text: `${Number(row.value ?? 0).toFixed(precision)}${unit}`, + style: { fontSize: '11px', fontFamily: 'var(--mono)', color: 'var(--text-2)', + minWidth: '58px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' }, + }), + )); + } + + return host; +} + +/* -- Attitude indicator --------------------------------------------------- */ + +/** Artificial horizon from IMU roll and pitch - the one place a dial beats a number. */ +export function attitude(roll = 0, pitch = 0, { size = 150 } = {}) { + const svg = svgEl('svg', { class: 'chart', viewBox: '0 0 200 200', width: size, height: size }); + const clipId = `att-clip-${Math.random().toString(36).slice(2, 8)}`; + + const defs = svgEl('defs'); + const clip = svgEl('clipPath', { id: clipId }); + clip.appendChild(svgEl('circle', { cx: 100, cy: 100, r: 84 })); + defs.appendChild(clip); + svg.appendChild(defs); + + const group = svgEl('g', { 'clip-path': `url(#${clipId})` }); + const pitchPx = Math.max(-70, Math.min(70, pitch * (180 / Math.PI) * 2)); + const inner = svgEl('g', { + transform: `rotate(${-roll * (180 / Math.PI)} 100 100) translate(0 ${pitchPx})`, + }); + + inner.appendChild(svgEl('rect', { x: -60, y: -80, width: 320, height: 180, fill: 'var(--surface-3)' })); + inner.appendChild(svgEl('rect', { x: -60, y: 100, width: 320, height: 200, fill: 'var(--surface-hi)' })); + inner.appendChild(svgEl('line', { x1: -60, x2: 260, y1: 100, y2: 100, + stroke: seriesColor(0), 'stroke-width': 2 })); + for (const offset of [-40, -20, 20, 40]) { + const wide = Math.abs(offset) === 40; + inner.appendChild(svgEl('line', { + x1: 100 - (wide ? 26 : 16), x2: 100 + (wide ? 26 : 16), + y1: 100 + offset, y2: 100 + offset, + stroke: 'var(--text-3)', 'stroke-width': 1, + })); + } + group.appendChild(inner); + svg.appendChild(group); + + svg.appendChild(svgEl('circle', { cx: 100, cy: 100, r: 84, fill: 'none', + stroke: 'var(--border)', 'stroke-width': 1.5 })); + // Fixed aircraft reference. + svg.appendChild(svgEl('path', { + d: 'M62 100 h22 l8 8 l8 -8 h22', fill: 'none', + stroke: 'var(--text)', 'stroke-width': 2.5, 'stroke-linejoin': 'round', 'stroke-linecap': 'round', + })); + svg.appendChild(svgEl('path', { + d: 'M100 16 l-7 12 h14 z', fill: 'var(--text-2)', + })); + + return svg; +} + +/* -- Compass / heading ---------------------------------------------------- */ + +export function compass(yaw = 0, { size = 150 } = {}) { + const svg = svgEl('svg', { class: 'chart', viewBox: '0 0 200 200', width: size, height: size }); + svg.appendChild(svgEl('circle', { cx: 100, cy: 100, r: 84, fill: 'var(--surface-2)', + stroke: 'var(--border)', 'stroke-width': 1.5 })); + + const dial = svgEl('g', { transform: `rotate(${-yaw * (180 / Math.PI)} 100 100)` }); + for (let deg = 0; deg < 360; deg += 15) { + const major = deg % 45 === 0; + const rad = (deg - 90) * Math.PI / 180; + const r1 = major ? 66 : 74; + dial.appendChild(svgEl('line', { + x1: 100 + Math.cos(rad) * r1, y1: 100 + Math.sin(rad) * r1, + x2: 100 + Math.cos(rad) * 80, y2: 100 + Math.sin(rad) * 80, + stroke: major ? 'var(--text-3)' : 'var(--border)', 'stroke-width': major ? 1.5 : 1, + })); + } + for (const [label, deg] of [['N', 0], ['E', 90], ['S', 180], ['W', 270]]) { + const rad = (deg - 90) * Math.PI / 180; + const text = svgEl('text', { + x: 100 + Math.cos(rad) * 52, y: 100 + Math.sin(rad) * 52 + 4, + 'text-anchor': 'middle', class: 'tick-text', + style: 'font-size:11px;font-weight:600', + }); + text.textContent = label; + dial.appendChild(text); + } + svg.appendChild(dial); + + svg.appendChild(svgEl('path', { + d: 'M100 34 L110 100 L100 92 L90 100 Z', fill: seriesColor(0), + })); + svg.appendChild(svgEl('circle', { cx: 100, cy: 100, r: 4, fill: 'var(--text-2)' })); + + const heading = svgEl('text', { + x: 100, y: 132, 'text-anchor': 'middle', class: 'tick-text', + style: 'font-size:15px;font-weight:600;fill:var(--text)', + }); + heading.textContent = `${(((yaw * 180 / Math.PI) % 360 + 360) % 360).toFixed(0)}°`; + svg.appendChild(heading); + + return svg; +} diff --git a/x2_dashboard/web/js/core.js b/x2_dashboard/web/js/core.js new file mode 100644 index 0000000..cbf5b65 --- /dev/null +++ b/x2_dashboard/web/js/core.js @@ -0,0 +1,349 @@ +/* ========================================================================== + Core: store, transport, notifications, formatting. + + Every URL here is derived from window.location, so the dashboard works from + whatever address you happened to open it on - laptop, phone, tablet, or a + hostname. Nothing is hardcoded. + ========================================================================== */ + +export const API = `${location.origin}`; +export const WS_URL = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws`; + +/* -- Store ---------------------------------------------------------------- */ + +class Store { + constructor() { + this.state = null; // live robot state + this.spec = null; // constants from the backend + this.settings = null; + this.plugins = { plugins: [], errors: [] }; + this.bridge = null; + this.network = null; + this.server = null; + this.events = []; + this.connected = false; + this._subs = new Map(); + this._nextId = 1; + } + + on(channel, fn) { + if (!this._subs.has(channel)) this._subs.set(channel, new Map()); + const id = this._nextId++; + this._subs.get(channel).set(id, fn); + return () => this._subs.get(channel)?.delete(id); + } + + emit(channel, payload) { + const subs = this._subs.get(channel); + if (!subs) return; + for (const fn of subs.values()) { + try { fn(payload); } catch (err) { console.error(`[${channel}]`, err); } + } + } +} + +export const store = new Store(); + +/* -- HTTP ----------------------------------------------------------------- */ + +export async function api(path, options = {}) { + const { method = 'GET', body, timeout = 15000 } = options; + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), timeout); + + try { + const res = await fetch(`${API}${path}`, { + method, + headers: body ? { 'Content-Type': 'application/json' } : undefined, + body: body ? JSON.stringify(body) : undefined, + signal: controller.signal, + }); + + const text = await res.text(); + let data = null; + try { data = text ? JSON.parse(text) : null; } catch { data = { detail: text }; } + + if (!res.ok) { + const message = data?.detail || data?.message || `${res.status} ${res.statusText}`; + const error = new Error(typeof message === 'string' ? message : JSON.stringify(message)); + error.status = res.status; + error.data = data; + throw error; + } + return data; + } catch (err) { + if (err.name === 'AbortError') throw new Error(`Request timed out after ${timeout / 1000}s`); + throw err; + } finally { + clearTimeout(timer); + } +} + +export const get = (path) => api(path); +export const post = (path, body) => api(path, { method: 'POST', body: body ?? {} }); + +/** + * POST that reports its own outcome as a toast. Returns the payload on success + * and null on failure, so callers can `if (!await command(...)) return;`. + */ +export async function command(path, body, { silent = false, successTitle } = {}) { + try { + const data = await post(path, body); + if (!silent) toast(successTitle || 'Done', data?.message || '', 'good'); + return data; + } catch (err) { + if (!silent) toast('Command failed', err.message, 'critical'); + return null; + } +} + +/* -- WebSocket ------------------------------------------------------------ */ + +class Socket { + constructor() { + this.ws = null; + this.attempts = 0; + this.closing = false; + this._pending = null; + this._pendingTimer = null; + } + + connect() { + if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) return; + this.closing = false; + + try { + this.ws = new WebSocket(WS_URL); + } catch (err) { + this._retry(); + return; + } + + this.ws.onopen = () => { + this.attempts = 0; + store.connected = true; + store.emit('link', { connected: true }); + }; + + this.ws.onmessage = (event) => { + let message; + try { message = JSON.parse(event.data); } catch { return; } + this._route(message); + }; + + this.ws.onclose = () => { + store.connected = false; + store.emit('link', { connected: false }); + if (!this.closing) this._retry(); + }; + + this.ws.onerror = () => { /* onclose handles recovery */ }; + } + + _route(message) { + const { type, data } = message; + switch (type) { + case 'state': + store.state = data; + store.emit('state', data); + break; + case 'event': + store.events.push(data); + if (store.events.length > 500) store.events.splice(0, store.events.length - 500); + store.emit('event', data); + if (data.level === 'error') toast('Robot', data.message, 'critical'); + else if (data.level === 'warn') toast('Robot', data.message, 'warning'); + break; + case 'plugins': + store.plugins = data; + store.emit('plugins', data); + break; + case 'settings': + store.settings = data; + store.emit('settings', data); + break; + case 'scan_progress': + store.emit('scan_progress', data); + break; + case 'command_error': + store.emit('command_error', data); + break; + default: + store.emit(type, data); + } + } + + _retry() { + // Back off to 8 s so a robot that is off overnight does not spam the network. + const delay = Math.min(8000, 500 * Math.pow(1.6, this.attempts++)); + setTimeout(() => this.connect(), delay); + } + + send(type, data) { + if (this.ws?.readyState !== WebSocket.OPEN) return false; + this.ws.send(JSON.stringify({ type, data })); + return true; + } + + /** + * Rate-limited send for the joystick. Coalesces to ~25 Hz so dragging never + * floods the socket, but always delivers the final position. + */ + sendThrottled(type, data, interval = 40) { + this._pending = { type, data }; + if (this._pendingTimer) return; + const flush = () => { + if (!this._pending) { this._pendingTimer = null; return; } + const { type: t, data: d } = this._pending; + this._pending = null; + this.send(t, d); + this._pendingTimer = setTimeout(flush, interval); + }; + flush(); + } +} + +export const socket = new Socket(); + +/* -- Toasts --------------------------------------------------------------- */ + +const toastHost = () => document.getElementById('toasts'); + +export function toast(title, message = '', tone = 'default', ttl = 4200) { + const host = toastHost(); + if (!host) return; + + const node = document.createElement('div'); + node.className = 'toast'; + node.dataset.tone = tone; + node.innerHTML = ` +
+
+ ${message ? '
' : ''} +
`; + node.querySelector('.toast-title').textContent = title; + if (message) node.querySelector('.toast-msg').textContent = message; + + host.appendChild(node); + while (host.children.length > 5) host.firstElementChild.remove(); + + setTimeout(() => { + node.classList.add('leaving'); + setTimeout(() => node.remove(), 200); + }, ttl); +} + +/* -- Confirm modal -------------------------------------------------------- */ + +export function confirmDialog(title, body, { confirmLabel = 'Confirm', danger = true } = {}) { + return new Promise((resolve) => { + const backdrop = document.getElementById('modal-backdrop'); + const confirmBtn = document.getElementById('modal-confirm'); + const cancelBtn = document.getElementById('modal-cancel'); + + document.getElementById('modal-title').textContent = title; + document.getElementById('modal-body').textContent = body; + confirmBtn.textContent = confirmLabel; + confirmBtn.className = danger ? 'btn btn-danger' : 'btn btn-primary'; + backdrop.hidden = false; + confirmBtn.focus(); + + const finish = (value) => { + backdrop.hidden = true; + confirmBtn.removeEventListener('click', onYes); + cancelBtn.removeEventListener('click', onNo); + backdrop.removeEventListener('click', onBackdrop); + document.removeEventListener('keydown', onKey); + resolve(value); + }; + const onYes = () => finish(true); + const onNo = () => finish(false); + const onBackdrop = (e) => { if (e.target === backdrop) finish(false); }; + const onKey = (e) => { if (e.key === 'Escape') finish(false); }; + + confirmBtn.addEventListener('click', onYes); + cancelBtn.addEventListener('click', onNo); + backdrop.addEventListener('click', onBackdrop); + document.addEventListener('keydown', onKey); + }); +} + +/* -- Formatting ----------------------------------------------------------- */ + +export const RAD2DEG = 180 / Math.PI; +export const DEG2RAD = Math.PI / 180; + +export function num(value, precision = 2, fallback = '—') { + if (value === null || value === undefined || Number.isNaN(Number(value))) return fallback; + return Number(value).toFixed(precision); +} + +export function compact(value) { + if (value === null || value === undefined) return '—'; + const abs = Math.abs(value); + if (abs >= 1e9) return `${(value / 1e9).toFixed(1)}B`; + if (abs >= 1e6) return `${(value / 1e6).toFixed(1)}M`; + if (abs >= 1e4) return `${(value / 1e3).toFixed(1)}K`; + return value.toLocaleString(undefined, { maximumFractionDigits: 0 }); +} + +export function clockTime(ts) { + const d = new Date(ts * 1000); + return d.toLocaleTimeString([], { hour12: false }); +} + +export function duration(seconds) { + if (!seconds || seconds < 0) return '—'; + const s = Math.floor(seconds % 60); + const m = Math.floor((seconds / 60) % 60); + const h = Math.floor(seconds / 3600); + if (h) return `${h}h ${m}m`; + if (m) return `${m}m ${s}s`; + return `${s}s`; +} + +export function batteryTone(pct) { + if (pct === null || pct === undefined) return 'default'; + if (pct <= 10) return 'critical'; + if (pct <= 25) return 'warning'; + return 'good'; +} + +export function tempTone(celsius, warn = 55, crit = 70) { + if (celsius === null || celsius === undefined) return 'default'; + if (celsius >= crit) return 'critical'; + if (celsius >= warn) return 'warning'; + return 'good'; +} + +export function throttle(fn, ms) { + let last = 0, timer = null, queued = null; + return (...args) => { + const now = Date.now(); + queued = args; + if (now - last >= ms) { last = now; fn(...queued); queued = null; return; } + if (timer) return; + timer = setTimeout(() => { + timer = null; last = Date.now(); + if (queued) { fn(...queued); queued = null; } + }, ms - (now - last)); + }; +} + +export function debounce(fn, ms) { + let timer = null; + return (...args) => { + clearTimeout(timer); + timer = setTimeout(() => fn(...args), ms); + }; +} + +/* Series colours, read from CSS so the theme toggle stays authoritative. */ +export function seriesColor(index) { + const styles = getComputedStyle(document.documentElement); + return styles.getPropertyValue(`--series-${(index % 8) + 1}`).trim() || '#3987e5'; +} + +export function cssVar(name) { + return getComputedStyle(document.documentElement).getPropertyValue(name).trim(); +} diff --git a/x2_dashboard/web/js/main.js b/x2_dashboard/web/js/main.js new file mode 100644 index 0000000..cd48f8d --- /dev/null +++ b/x2_dashboard/web/js/main.js @@ -0,0 +1,538 @@ +/* ========================================================================== + Application shell: bootstrap, rail, routing, topbar, global shortcuts. + ========================================================================== */ + +import { store, socket, get, post, toast, num, batteryTone, confirmDialog } from './core.js'; +import { el, clear, icon, emptyState, button, badge } from './ui.js'; + +import overview from './tabs/overview.js'; +import control from './tabs/control.js'; +import motion from './tabs/motion.js'; +import sensors from './tabs/sensors.js'; +import vision from './tabs/vision.js'; +import lidar from './tabs/lidar.js'; +import model from './tabs/model.js'; +import interaction from './tabs/interaction.js'; +import power from './tabs/power.js'; +import navigation from './tabs/navigation.js'; +import extensions from './tabs/extensions.js'; +import consoleTab from './tabs/console.js'; +import settings from './tabs/settings.js'; + +const TABS = [ + { ...overview, group: 'Monitor' }, + { ...power, group: 'Monitor' }, + { ...sensors, group: 'Monitor' }, + { ...vision, group: 'Monitor' }, + { ...lidar, group: 'Monitor' }, + { ...model, group: 'Monitor' }, + { ...control, group: 'Operate' }, + { ...motion, group: 'Operate' }, + { ...interaction, group: 'Operate' }, + { ...navigation, group: 'Operate' }, + { ...extensions, group: 'System' }, + { ...consoleTab, group: 'System' }, + { ...settings, group: 'System' }, +]; + +// Report which build this bundle came from. index.html (always served fresh) +// compares it against the server's build and warns if they differ, which is the +// only reliable way to notice that a browser served a stale cached bundle. +try { + window.__MAIN_BUILD__ = new URL(import.meta.url).searchParams.get('b') || 'dev'; +} catch { /* non-critical */ } + +const content = document.getElementById('content'); +const rail = document.getElementById('rail'); + +let activeId = null; +let activeDispose = null; + +/* -- Routing -------------------------------------------------------------- */ + +function buildRail() { + clear(rail); + let lastGroup = null; + + for (const tab of TABS) { + if (tab.group !== lastGroup) { + rail.appendChild(el('div.rail-group', { text: tab.group })); + lastGroup = tab.group; + } + const item = el('button.rail-item', { + type: 'button', + dataset: { tab: tab.id }, + 'aria-current': tab.id === activeId ? 'page' : 'false', + onclick: () => navigate(tab.id), + }, + icon(tab.icon), + el('span', { text: tab.label }), + ); + rail.appendChild(item); + } +} + +function markActive() { + for (const item of rail.querySelectorAll('.rail-item')) { + item.setAttribute('aria-current', item.dataset.tab === activeId ? 'page' : 'false'); + } +} + +export function setRailBadge(tabId, value, tone = 'default') { + const item = rail.querySelector(`.rail-item[data-tab="${tabId}"]`); + if (!item) return; + let badge = item.querySelector('.rail-badge'); + if (!value) { badge?.remove(); return; } + if (!badge) { + badge = el('span.rail-badge'); + item.appendChild(badge); + } + badge.textContent = String(value); + badge.dataset.tone = tone; +} + +async function navigate(id, { replace = false } = {}) { + const tab = TABS.find((t) => t.id === id) || TABS[0]; + if (activeDispose) { try { activeDispose(); } catch (err) { console.error(err); } } + activeDispose = null; + activeId = tab.id; + + markActive(); + if (replace) history.replaceState({ tab: tab.id }, '', `#${tab.id}`); + else if (location.hash.slice(1) !== tab.id) history.pushState({ tab: tab.id }, '', `#${tab.id}`); + + clear(content); + content.scrollTop = 0; + + try { + const result = await tab.render(); + if (result && result.node) { + content.appendChild(result.node); + activeDispose = result.dispose || null; + } else if (result instanceof Node) { + content.appendChild(result); + } + } catch (err) { + console.error(`Tab "${tab.id}" failed:`, err); + const stale = window.__MAIN_BUILD__ !== window.__BUILD__; + content.appendChild(emptyState( + 'This section failed to render', + stale + ? `${err?.message || err}\n\nThis page is running an outdated copy of the dashboard, ` + + 'which is very likely the cause. Load the current version and try again.' + : String(err?.message || err), + el('div.row', {}, + button('Retry', () => navigate(tab.id, { replace: true }), { style: 'primary' }), + stale + ? button('Load the current version', + () => location.replace(`${location.pathname}?r=${Date.now()}`)) + : null, + ), + )); + } +} + +window.addEventListener('popstate', () => { + const id = location.hash.slice(1); + if (id && id !== activeId) navigate(id, { replace: true }); +}); + +/* -- Topbar --------------------------------------------------------------- */ + +const pills = { + connection: document.getElementById('pill-connection'), + mode: document.getElementById('pill-mode'), + battery: document.getElementById('pill-battery'), + host: document.getElementById('pill-host'), +}; + +function setPill(node, label, { state, level } = {}) { + node.querySelector('.pill-label').textContent = label; + if (state) node.querySelector('.dot')?.setAttribute('data-state', state); + if (level) node.dataset.level = level; else delete node.dataset.level; +} + +function updateTopbar() { + const state = store.state; + const bridge = store.bridge; + + if (!store.connected) { + setPill(pills.connection, 'Reconnecting…', { state: 'offline' }); + } else if (bridge?.simulated) { + setPill(pills.connection, 'Simulation', { state: 'sim' }); + pills.connection.title = 'No robot attached - the dashboard is running against the built-in simulator.'; + } else if (state?.connection?.online) { + setPill(pills.connection, 'Live', { state: 'online' }); + pills.connection.title = `Connected to the robot agent at ${state.connection.host}`; + } else { + setPill(pills.connection, 'Robot off', { state: 'offline' }); + pills.connection.title = state?.connection?.error || 'The robot agent is not reachable.'; + } + + const modeSpec = store.spec?.modes?.find((m) => m.id === state?.mode); + setPill(pills.mode, modeSpec?.label || state?.mode || '—', { + level: modeSpec?.danger ? 'critical' : undefined, + }); + + const pct = state?.battery_pct; + const tone = batteryTone(pct); + setPill(pills.battery, pct === null || pct === undefined ? '—' : `${num(pct, 0)}%`, { + level: tone === 'good' ? undefined : tone, + }); + + const host = state?.connection?.host || store.settings?.values?.robot_host; + setPill(pills.host, host || 'not set'); + pills.host.dataset.optional = ''; +} + +/* -- Offline gate --------------------------------------------------------- + + The dashboard server runs on this machine, not on the robot, so the page + stays up when the X2 is switched off. That is the whole point of the gate: + instead of a dead link, the operator gets "power the robot on", and the + dashboard reattaches by itself the moment the agent answers again. + -------------------------------------------------------------------------- */ + +const gate = { + root: document.getElementById('gate'), + title: document.getElementById('gate-title'), + message: document.getElementById('gate-message'), + status: document.getElementById('gate-status-text'), + facts: document.getElementById('gate-facts'), + hint: document.getElementById('gate-hint'), + address: document.getElementById('gate-address'), + hostInput: document.getElementById('gate-host'), + results: document.getElementById('gate-results'), + visible: false, + since: 0, + poll: null, + busy: false, +}; + +function gateReason() { + // Simulation is a deliberate choice, not an outage - never gate on it. + if (store.bridge?.simulated) return null; + if (!store.connected) return 'server'; + if (!store.state?.connection?.online) return 'robot'; + return null; +} + +function showGate(reason) { + const host = store.settings?.values?.robot_host || '—'; + const port = store.settings?.values?.agent_port || 8781; + + if (reason === 'server') { + gate.title.textContent = 'Dashboard server not responding'; + gate.message.textContent = + 'The page loaded but lost its connection to the dashboard server. ' + + 'It will reconnect automatically once the server is running again.'; + gate.hint.textContent = 'This is the server on this computer, not the robot.'; + } else { + gate.title.textContent = 'Robot is powered off'; + gate.message.textContent = + 'The dashboard cannot reach the X2. Switch the robot on and this page will ' + + 'connect by itself — no need to reload.'; + gate.hint.textContent = + 'If the robot is already on, check that it is on this Wi-Fi network and that ' + + 'the dashboard agent is running on it.'; + } + + const error = store.state?.connection?.error || store.bridge?.error || ''; + clear(gate.facts); + const facts = [ + ['Robot address', host === '—' ? 'not set' : `${host}:${port}`], + ['Last seen', gate.since ? new Date(gate.since).toLocaleTimeString([], { hour12: false }) : 'not yet this session'], + ]; + if (error) facts.push(['Detail', error]); + for (const [key, value] of facts) { + gate.facts.appendChild(el('dt', { text: key })); + gate.facts.appendChild(el('dd', { text: value })); + } + + if (!gate.visible) { + gate.visible = true; + gate.root.hidden = false; + document.getElementById('app').setAttribute('inert', ''); + if (!gate.hostInput.value) { + gate.hostInput.value = store.settings?.values?.robot_host || ''; + } + if (!gate.poll) gate.poll = setInterval(pollRobot, 2500); + } +} + +function hideGate() { + if (!gate.visible) return; + gate.visible = false; + gate.root.hidden = true; + document.getElementById('app').removeAttribute('inert'); + if (gate.poll) { clearInterval(gate.poll); gate.poll = null; } + toast('Robot connected', 'Live telemetry is flowing again.', 'good'); + // Re-render the current tab so it rebuilds against real data. + if (activeId) navigate(activeId, { replace: true }); +} + +async function pollRobot() { + // Anything the operator kicked off owns the status line until it finishes. + if (gate.busy) return; + try { + const status = await get('/api/robot/status'); + if (status.online) { + gate.status.textContent = 'Robot answered — reconnecting…'; + store.state = store.state || {}; + store.state.connection = { ...(store.state.connection || {}), online: true }; + updateGate(); + return; + } + // The bridge reports what its automatic recovery is doing; showing that is + // far more use than a fixed "waiting" message. + gate.status.textContent = status.recovery + || `Waiting for the robot at ${status.host || 'no address set'}…`; + + if (!status.has_ssh_password && status.auto_start_agent) { + gate.hint.textContent = + 'Tip: save the robot\'s SSH password in Settings and the dashboard can start the ' + + 'agent for you after a power cycle, instead of waiting for the robot to do it.'; + } + } catch { + gate.status.textContent = 'Waiting for the dashboard server…'; + } +} + +function updateGate() { + const reason = gateReason(); + if (reason) showGate(reason); + else { + if (store.state?.connection?.online) gate.since = Date.now(); + hideGate(); + } +} + +document.getElementById('gate-retry').addEventListener('click', async (event) => { + const button = event.currentTarget; + button.disabled = true; + gate.busy = true; + gate.status.textContent = 'Reconnecting…'; + try { + await post('/api/bridge/restart'); + gate.busy = false; + await pollRobot(); + } catch (err) { + gate.status.textContent = err.message; + } finally { + gate.busy = false; + button.disabled = false; + } +}); + +document.getElementById('gate-toggle-address').addEventListener('click', (event) => { + const shown = !gate.address.hidden; + gate.address.hidden = shown; + event.currentTarget.textContent = shown ? 'Set address manually' : 'Hide address box'; + if (!shown) gate.hostInput.focus(); +}); + +async function saveGateHost(host) { + if (!host) return; + gate.busy = true; + gate.status.textContent = `Connecting to ${host}…`; + try { + await post('/api/settings', { robot_host: host }); + await post('/api/bridge/restart'); + // Give the bridge a moment to dial before we report anything. + await new Promise((resolve) => setTimeout(resolve, 2500)); + gate.busy = false; + await pollRobot(); + } catch (err) { + gate.status.textContent = `Could not connect: ${err.message}`; + } finally { + gate.busy = false; + } +} + +document.getElementById('gate-save').addEventListener('click', + () => saveGateHost(gate.hostInput.value.trim())); +gate.hostInput.addEventListener('keydown', (event) => { + if (event.key === 'Enter') saveGateHost(gate.hostInput.value.trim()); +}); + +document.getElementById('gate-find').addEventListener('click', async (event) => { + const button = event.currentTarget; + button.disabled = true; + gate.busy = true; + gate.results.hidden = true; + gate.status.textContent = 'Scanning this network for the robot…'; + + try { + const data = await post('/api/robot/find'); + const found = data.candidates || []; + clear(gate.results); + gate.results.hidden = !found.length; + + if (!found.length) { + gate.status.textContent = + 'Nothing found. Is the robot powered on and joined to this Wi-Fi?'; + return; + } + + gate.status.textContent = `Found ${found.length} device${found.length > 1 ? 's' : ''}.`; + for (const item of found) { + const ready = item.agent; + gate.results.appendChild(el('div.gate-result', {}, + el('span.host', { text: item.host }), + item.hostname ? el('span', { text: item.hostname, style: { color: 'var(--text-3)' } }) : null, + badge(ready ? 'agent running' : 'reachable, agent off', ready ? 'good' : 'warning'), + el('span.spacer'), + button_(ready ? 'Connect' : 'Start & connect', async (btn) => { + btn.disabled = true; + gate.busy = true; + try { + if (!ready) { + gate.status.textContent = `Starting the agent on ${item.host}…`; + const woke = await post('/api/robot/wake', { host: item.host }); + if (!woke.ok) { + gate.status.textContent = woke.message; + return; + } + } + await saveGateHost(item.host); + } finally { + gate.busy = false; + btn.disabled = false; + } + }), + )); + } + } catch (err) { + gate.status.textContent = `Scan failed: ${err.message}`; + } finally { + gate.busy = false; + button.disabled = false; + } +}); + +/* Small local button helper - the gate is built before the UI module's styles + are relevant, and it only needs the one variant. */ +function button_(label, onClick) { + const node = el('button.btn.btn-sm', { type: 'button', text: label }); + node.addEventListener('click', () => onClick(node)); + return node; +} + +/* -- Theme ---------------------------------------------------------------- */ + +function initTheme() { + const saved = localStorage.getItem('x2-theme'); + if (saved) document.documentElement.dataset.theme = saved; + + document.getElementById('btn-theme').addEventListener('click', () => { + const next = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'; + document.documentElement.dataset.theme = next; + localStorage.setItem('x2-theme', next); + store.emit('theme', next); + // Charts read their colours from CSS variables, so a re-render picks up the + // new palette rather than keeping stale hexes. + if (activeId) navigate(activeId, { replace: true }); + }); +} + +/* -- Global controls ------------------------------------------------------ */ + +function initStop() { + const stop = async () => { + socket.send('stop', {}); + try { + await post('/api/stop'); + toast('Stopped', 'Velocity zeroed', 'warning'); + } catch (err) { + toast('Stop failed', err.message, 'critical'); + } + }; + + document.getElementById('btn-stop').addEventListener('click', stop); + + document.addEventListener('keydown', (event) => { + const typing = ['INPUT', 'TEXTAREA', 'SELECT'].includes(event.target.tagName); + + if (event.code === 'Space' && !typing) { + event.preventDefault(); + stop(); + return; + } + if (typing || event.metaKey || event.ctrlKey || event.altKey) return; + + // Number keys jump between sections. + const index = Number(event.key) - 1; + if (Number.isInteger(index) && index >= 0 && index < TABS.length) { + navigate(TABS[index].id); + } + }); +} + +/* -- Boot ----------------------------------------------------------------- */ + +async function boot() { + initTheme(); + initStop(); + + try { + const data = await get('/api/bootstrap'); + store.spec = data.spec; + store.settings = data.settings; + store.state = data.state; + store.plugins = data.plugins; + store.bridge = data.bridge; + store.network = data.network; + store.server = data.server; + store.events = data.events || []; + } catch (err) { + clear(content); + content.appendChild(emptyState( + 'Cannot reach the dashboard server', + `${err.message}\n\nThe page loaded but /api/bootstrap did not answer. Check that the server process is still running, then reload.`, + button('Reload', () => location.reload(), { style: 'primary' }), + )); + return; + } + + const name = store.settings?.values?.robot_label || 'AGIBOT X2'; + document.getElementById('brand-name').textContent = name; + document.getElementById('brand-sub').textContent = + store.bridge?.simulated ? 'Simulation mode' : 'Live control'; + + buildRail(); + updateTopbar(); + updateGate(); + + store.on('state', () => { updateTopbar(); updateGate(); }); + store.on('link', () => { updateTopbar(); updateGate(); }); + store.on('settings', (data) => { + store.settings = data; + document.getElementById('brand-name').textContent = data.values.robot_label || 'AGIBOT X2'; + updateTopbar(); + }); + store.on('plugins', (data) => { + store.plugins = data; + setRailBadge('extensions', data.errors?.length || 0, 'bad'); + }); + store.on('command_error', (data) => toast('Blocked', data.message, 'warning')); + + setRailBadge('extensions', store.plugins?.errors?.length || 0, 'bad'); + + socket.connect(); + + const initial = location.hash.slice(1); + await navigate(TABS.some((t) => t.id === initial) ? initial : TABS[0].id, { replace: true }); + + if (store.bridge?.simulated) { + toast( + 'Simulation mode', + 'No robot address is configured, so the dashboard is driving a simulated X2. ' + + 'Set the address in Settings to attach to the real one.', + 'warning', 9000, + ); + } +} + +boot(); + +export { navigate, TABS }; diff --git a/x2_dashboard/web/js/model3d.js b/x2_dashboard/web/js/model3d.js new file mode 100644 index 0000000..f262bfe --- /dev/null +++ b/x2_dashboard/web/js/model3d.js @@ -0,0 +1,372 @@ +/* A small WebGL renderer for the X2's URDF model. + + Deliberately hand-rolled rather than pulled from a 3D library. What this + needs is narrow - one shader, flat shading, a rigid-body tree of 41 links - + and the alternative is several hundred kilobytes fetched over the robot's + own Wi-Fi, from a CDN the robot cannot reach. + + Geometry arrives as uint16 positions quantised inside each mesh's bounding + box (see build_model.py); the shader expands them back to metres, so the + 4x saving over float32 costs two extra instructions per vertex. + + Normals are computed per-face in the fragment shader from screen-space + derivatives. That means the vertex buffer carries positions and nothing + else - no normal buffer, no smoothing groups, no index-order assumptions - + and flat shading is the honest look for a machined-metal robot anyway. +*/ + +const VERTEX_SHADER = ` +attribute vec3 a_quantised; +uniform mat4 u_viewProjection; +uniform mat4 u_model; +uniform vec3 u_lo; +uniform vec3 u_span; +varying vec3 v_world; +void main() { + vec3 local = u_lo + (a_quantised / 65535.0) * u_span; + vec4 world = u_model * vec4(local, 1.0); + v_world = world.xyz; + gl_Position = u_viewProjection * world; +}`; + +const FRAGMENT_SHADER = ` +precision mediump float; +varying vec3 v_world; +uniform vec3 u_colour; +uniform float u_alpha; +void main() { + // Face normal straight from the derivative of world position across the + // triangle. No normal attribute needed, and it cannot disagree with the + // geometry the way a stale baked normal can. + vec3 normal = normalize(cross(dFdx(v_world), dFdy(v_world))); + vec3 keyDir = normalize(vec3(0.45, 0.7, 0.85)); + vec3 fillDir = normalize(vec3(-0.6, -0.3, 0.4)); + float key = max(dot(normal, keyDir), 0.0); + float fill = max(dot(normal, fillDir), 0.0) * 0.35; + // A little rim light so the silhouette stays readable against a dark panel. + float rim = pow(1.0 - abs(normal.z), 2.0) * 0.18; + vec3 shaded = u_colour * (0.30 + 0.72 * key + fill) + rim; + gl_FragColor = vec4(shaded, u_alpha); +}`; + +/* -- Small matrix helpers (column-major, as WebGL expects) ----------------- */ + +export function identity() { + return new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); +} + +export function multiply(a, b) { + const out = new Float32Array(16); + for (let col = 0; col < 4; col += 1) { + for (let row = 0; row < 4; row += 1) { + out[col * 4 + row] = + a[row] * b[col * 4] + + a[4 + row] * b[col * 4 + 1] + + a[8 + row] * b[col * 4 + 2] + + a[12 + row] * b[col * 4 + 3]; + } + } + return out; +} + +/** URDF fixed-axis roll-pitch-yaw: R = Rz(yaw) * Ry(pitch) * Rx(roll). */ +export function fromOrigin(xyz, rpy) { + const [x, y, z] = xyz; + const [roll, pitch, yaw] = rpy; + const cr = Math.cos(roll), sr = Math.sin(roll); + const cp = Math.cos(pitch), sp = Math.sin(pitch); + const cy = Math.cos(yaw), sy = Math.sin(yaw); + + return new Float32Array([ + cy * cp, sy * cp, -sp, 0, + cy * sp * sr - sy * cr, sy * sp * sr + cy * cr, cp * sr, 0, + cy * sp * cr + sy * sr, sy * sp * cr - cy * sr, cp * cr, 0, + x, y, z, 1, + ]); +} + +/** Rotation of `angle` about an arbitrary unit axis (Rodrigues). */ +export function fromAxisAngle(axis, angle) { + let [x, y, z] = axis; + const length = Math.hypot(x, y, z) || 1; + x /= length; y /= length; z /= length; + const c = Math.cos(angle), s = Math.sin(angle), t = 1 - c; + + return new Float32Array([ + t * x * x + c, t * x * y + s * z, t * x * z - s * y, 0, + t * x * y - s * z, t * y * y + c, t * y * z + s * x, 0, + t * x * z + s * y, t * y * z - s * x, t * z * z + c, 0, + 0, 0, 0, 1, + ]); +} + +export function perspective(fovY, aspect, near, far) { + const f = 1 / Math.tan(fovY / 2); + return new Float32Array([ + f / aspect, 0, 0, 0, + 0, f, 0, 0, + 0, 0, (far + near) / (near - far), -1, + 0, 0, (2 * far * near) / (near - far), 0, + ]); +} + +export function lookAt(eye, target, up) { + const zx = eye[0] - target[0], zy = eye[1] - target[1], zz = eye[2] - target[2]; + const zl = Math.hypot(zx, zy, zz) || 1; + const z = [zx / zl, zy / zl, zz / zl]; + + const xx = up[1] * z[2] - up[2] * z[1]; + const xy = up[2] * z[0] - up[0] * z[2]; + const xz = up[0] * z[1] - up[1] * z[0]; + const xl = Math.hypot(xx, xy, xz) || 1; + const x = [xx / xl, xy / xl, xz / xl]; + + const y = [ + z[1] * x[2] - z[2] * x[1], + z[2] * x[0] - z[0] * x[2], + z[0] * x[1] - z[1] * x[0], + ]; + + return new Float32Array([ + x[0], y[0], z[0], 0, + x[1], y[1], z[1], 0, + x[2], y[2], z[2], 0, + -(x[0] * eye[0] + x[1] * eye[1] + x[2] * eye[2]), + -(y[0] * eye[0] + y[1] * eye[1] + y[2] * eye[2]), + -(z[0] * eye[0] + z[1] * eye[1] + z[2] * eye[2]), + 1, + ]); +} + +/* -- Renderer -------------------------------------------------------------- */ + +export class RobotModel { + constructor(canvas) { + this.canvas = canvas; + this.gl = canvas.getContext('webgl', { + antialias: true, alpha: false, depth: true, preserveDrawingBuffer: false, + }); + if (!this.gl) throw new Error('This browser has no WebGL support.'); + + // Flat shading needs dFdx/dFdy, which is an extension in WebGL 1. Without + // it the shader still links on most drivers but every face comes out + // uniformly lit, so say so rather than render something misleading. + this.derivatives = this.gl.getExtension('OES_standard_derivatives'); + + this.model = null; + this.parts = []; + this.jointAngles = new Map(); + this.jointsByChild = new Map(); + this.linkParent = new Map(); + this.colour = [0.62, 0.66, 0.72]; + this.accent = [0.22, 0.53, 0.90]; + this.highlight = new Set(); + // link name -> [r, g, b]. Anything not listed falls back to this.colour, so + // a link whose joint reports nothing stays neutral grey rather than + // rendering as "zero load", which would read as a measurement. + this.linkColours = new Map(); + + this._buildProgram(); + } + + _buildProgram() { + const gl = this.gl; + const prefix = this.derivatives ? '#extension GL_OES_standard_derivatives : enable\n' : ''; + + const compile = (type, source) => { + const shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + throw new Error(`Shader failed to compile: ${gl.getShaderInfoLog(shader)}`); + } + return shader; + }; + + const program = gl.createProgram(); + gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX_SHADER)); + gl.attachShader(program, compile(gl.FRAGMENT_SHADER, prefix + FRAGMENT_SHADER)); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + throw new Error(`Shader failed to link: ${gl.getProgramInfoLog(program)}`); + } + + this.program = program; + this.attribs = { quantised: gl.getAttribLocation(program, 'a_quantised') }; + this.uniforms = { + viewProjection: gl.getUniformLocation(program, 'u_viewProjection'), + model: gl.getUniformLocation(program, 'u_model'), + lo: gl.getUniformLocation(program, 'u_lo'), + span: gl.getUniformLocation(program, 'u_span'), + colour: gl.getUniformLocation(program, 'u_colour'), + alpha: gl.getUniformLocation(program, 'u_alpha'), + }; + } + + /** Upload the baked model. `geometry` is the raw model.bin ArrayBuffer. */ + load(model, geometry) { + const gl = this.gl; + this.model = model; + this.parts = []; + + for (const joint of model.joints) { + this.jointsByChild.set(joint.child, joint); + this.linkParent.set(joint.child, joint.parent); + if (joint.type === 'revolute') this.jointAngles.set(joint.name, 0); + } + + for (const [linkName, link] of Object.entries(model.links)) { + for (const mesh of link.meshes) { + const vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, + new Uint16Array(geometry, mesh.vertex_offset, mesh.vertex_count * 3), + gl.STATIC_DRAW); + + const indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + const indices = mesh.index_bits === 16 + ? new Uint16Array(geometry, mesh.index_offset, mesh.index_count) + : new Uint32Array(geometry, mesh.index_offset, mesh.index_count); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); + + this.parts.push({ + link: linkName, + vertexBuffer, + indexBuffer, + count: mesh.index_count, + type: mesh.index_bits === 16 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT, + lo: mesh.lo, + span: mesh.span, + local: fromOrigin(mesh.origin.xyz, mesh.origin.rpy), + }); + } + } + + // 32-bit indices are an extension in WebGL 1. Every mesh here is under + // 65535 vertices so it should never come up, but a silent wrong-geometry + // render is worse than a clear failure. + if (this.parts.some((part) => part.type === gl.UNSIGNED_INT) + && !gl.getExtension('OES_element_index_uint')) { + throw new Error('This browser cannot draw 32-bit indices (OES_element_index_uint).'); + } + } + + setJoint(name, radians) { + if (this.jointAngles.has(name)) this.jointAngles.set(name, radians); + } + + setJoints(values) { + for (const [name, radians] of Object.entries(values)) this.setJoint(name, radians); + } + + /** World transform for a link, walking up to the root through its joints. */ + worldTransform(linkName) { + const chain = []; + let current = linkName; + // Guarded against a malformed tree: a cycle would otherwise hang the frame. + for (let depth = 0; current && depth < 64; depth += 1) { + const joint = this.jointsByChild.get(current); + if (!joint) break; + chain.push(joint); + current = joint.parent; + } + + let matrix = identity(); + for (const joint of chain) { + let local = fromOrigin(joint.origin.xyz, joint.origin.rpy); + if (joint.type === 'revolute') { + const angle = this.jointAngles.get(joint.name) || 0; + local = multiply(local, fromAxisAngle(joint.axis, angle)); + } + matrix = multiply(local, matrix); + } + return matrix; + } + + resize() { + const gl = this.gl; + // Cap the backing store at 2x CSS pixels: past that the extra fragments + // cost real milliseconds on a phone and buy nothing visible. + const ratio = Math.min(window.devicePixelRatio || 1, 2); + const width = Math.round(this.canvas.clientWidth * ratio); + const height = Math.round(this.canvas.clientHeight * ratio); + if (width && height && (this.canvas.width !== width || this.canvas.height !== height)) { + this.canvas.width = width; + this.canvas.height = height; + } + gl.viewport(0, 0, this.canvas.width, this.canvas.height); + } + + render(camera, background = [0.09, 0.10, 0.12]) { + const gl = this.gl; + this.resize(); + + gl.clearColor(background[0], background[1], background[2], 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + if (!this.model) return; + + gl.enable(gl.DEPTH_TEST); + // Backface culling stays off: vertex clustering does not preserve winding + // reliably, so culling by winding punches holes in the model. Depth testing + // alone is correct here; the cost is shading some faces we then overwrite. + gl.disable(gl.CULL_FACE); + + const aspect = this.canvas.width / Math.max(1, this.canvas.height); + const eye = [ + camera.target[0] + camera.distance * Math.cos(camera.pitch) * Math.cos(camera.yaw), + camera.target[1] + camera.distance * Math.cos(camera.pitch) * Math.sin(camera.yaw), + camera.target[2] + camera.distance * Math.sin(camera.pitch), + ]; + const viewProjection = multiply( + perspective(camera.fov ?? 0.8, aspect, 0.05, 60), + // Z is up in URDF, so the camera's up vector is Z, not Y. + lookAt(eye, camera.target, [0, 0, 1]), + ); + + gl.useProgram(this.program); + gl.uniformMatrix4fv(this.uniforms.viewProjection, false, viewProjection); + gl.enableVertexAttribArray(this.attribs.quantised); + + const worldCache = new Map(); + + for (const part of this.parts) { + let world = worldCache.get(part.link); + if (!world) { + world = this.worldTransform(part.link); + worldCache.set(part.link, world); + } + + gl.uniformMatrix4fv(this.uniforms.model, false, multiply(world, part.local)); + gl.uniform3fv(this.uniforms.lo, part.lo); + gl.uniform3fv(this.uniforms.span, part.span); + + const tinted = this.linkColours.get(part.link); + const colour = tinted || (this.highlight.has(part.link) ? this.accent : this.colour); + gl.uniform3fv(this.uniforms.colour, colour); + gl.uniform1f(this.uniforms.alpha, 1.0); + + gl.bindBuffer(gl.ARRAY_BUFFER, part.vertexBuffer); + // normalized=false: the shader divides by 65535 itself, because + // normalising here would also apply to the index-style values and makes + // the dequantisation harder to follow. + gl.vertexAttribPointer(this.attribs.quantised, 3, gl.UNSIGNED_SHORT, false, 0, 0); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, part.indexBuffer); + gl.drawElements(gl.TRIANGLES, part.count, part.type, 0); + } + } + + dispose() { + const gl = this.gl; + for (const part of this.parts) { + gl.deleteBuffer(part.vertexBuffer); + gl.deleteBuffer(part.indexBuffer); + } + this.parts = []; + gl.deleteProgram(this.program); + // Free the drawing buffer immediately rather than waiting for GC. Browsers + // cap the number of live WebGL contexts (often 16), and navigating between + // tabs repeatedly would otherwise start losing them. + gl.getExtension('WEBGL_lose_context')?.loseContext(); + } +} diff --git a/x2_dashboard/web/js/tabs/console.js b/x2_dashboard/web/js/tabs/console.js new file mode 100644 index 0000000..3479370 --- /dev/null +++ b/x2_dashboard/web/js/tabs/console.js @@ -0,0 +1,238 @@ +/* Console - event log, raw ROS access, discovered graph. */ + +import { store, get, post, toast, clockTime, num } from '../core.js'; +import { + el, card, pageHead, button, note, badge, table, input, textarea, field, + kv, segmented, emptyState, setChildren, +} from '../ui.js'; + +export default { + id: 'console', + label: 'Console', + icon: 'console', + + async render() { + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Console', + 'Everything the bridge has logged, plus direct access to publish a topic or call a service.', + )); + + /* ================================================================== + Event log + ================================================================== */ + + let levelFilter = 'all'; + let autoScroll = true; + const logHost = el('div.log'); + + function paintLog() { + const events = store.events.filter( + (e) => levelFilter === 'all' || e.level === levelFilter, + ); + + if (!events.length) { + logHost.replaceChildren(emptyState('Nothing logged yet')); + return; + } + + const wasAtBottom = logHost.scrollHeight - logHost.scrollTop - logHost.clientHeight < 40; + + logHost.replaceChildren(...events.slice(-400).map((event) => el('div.log-row', {}, + el('span.log-time', { text: clockTime(event.ts) }), + el('span.log-level', { text: event.level, dataset: { level: event.level } }), + el('span.log-source', { text: event.source, title: event.source }), + el('span.log-msg', { text: event.message }), + ))); + + if (autoScroll && wasAtBottom) logHost.scrollTop = logHost.scrollHeight; + } + + const levelTabs = segmented( + [ + { value: 'all', label: 'All' }, + { value: 'info', label: 'Info' }, + { value: 'warn', label: 'Warnings' }, + { value: 'error', label: 'Errors' }, + ], + levelFilter, + (value) => { levelFilter = value; paintLog(); }, + ); + + root.appendChild(card('Event log', { + sub: 'Bridge, control and extension events', + actions: [ + levelTabs, + button('Clear view', () => { store.events.length = 0; paintLog(); }, { size: 'sm', style: 'ghost' }), + ], + flush: true, + }, logHost)); + + /* ================================================================== + Raw publish / service call + ================================================================== */ + + const pubTopic = input({ placeholder: '/aima/hal/joint/head/command' }); + const pubType = input({ placeholder: 'aimdk_msgs/msg/JointCommandArray' }); + const pubFields = textarea({ placeholder: '{\n "field": 1.0\n}', rows: 5 }); + + const publishBtn = button('Publish', async (node) => { + let fields; + try { + fields = pubFields.value.trim() ? JSON.parse(pubFields.value) : {}; + } catch (err) { + toast('Invalid JSON', err.message, 'critical'); + return; + } + node.disabled = true; + try { + const data = await post('/api/raw/publish', { + topic: pubTopic.value.trim(), + type: pubType.value.trim(), + fields, + }); + toast('Published', data.message, data.ok ? 'good' : 'critical'); + } catch (err) { + toast('Publish failed', err.message, 'critical'); + } finally { + node.disabled = false; + } + }, { style: 'primary' }); + + const agentHost = el('div'); + + root.appendChild(el('div.grid.cols-2', {}, + card('Publish a topic', { sub: 'Raw escape hatch' }, + el('div.stack', {}, + field('Topic', pubTopic), + field('Message type', pubType, 'Package/kind/Name, e.g. aimdk_msgs/msg/McLocomotionVelocity'), + field('Fields (JSON)', pubFields, + 'Only top-level fields the message actually defines are set; the rest are ignored.'), + publishBtn, + note('This bypasses every guard the Control tab applies. Know what the message does ' + + 'before you send it.', 'warning', '⚠'), + ), + ), + card('Robot agent', { sub: 'The process bridging ROS 2 to this dashboard' }, agentHost), + )); + + /* ================================================================== + Discovered graph + ================================================================== */ + + const graphHost = el('div'); + let graphFilter = ''; + const graphSearch = input({ placeholder: 'Filter topics and services…' }); + graphSearch.addEventListener('input', () => { + graphFilter = graphSearch.value.toLowerCase(); + paintGraph(); + }); + + let graph = { topics: [], services: [] }; + + async function refreshGraph() { + try { + // Enumerating the graph is a round trip to the robot, so it is opt-in + // rather than part of the routine topic-stats poll. + const data = await get('/api/topics?graph=true'); + graph = data.graph || { topics: [], services: [], nodes: [] }; + paintGraph(); + } catch { /* best-effort */ } + } + + function paintAgent() { + const agent = store.bridge?.agent || store.state?.custom?.agent || null; + const connection = store.state?.connection || {}; + setChildren(agentHost, + el('div.row', { style: { marginBottom: '12px' } }, + badge(connection.online ? 'connected' : 'not connected', + connection.online ? 'good' : 'critical'), + store.bridge?.simulated ? badge('simulation', 'warning') : null, + ), + kv([ + ['Address', connection.host || store.bridge?.host || '—'], + ['Agent version', agent?.agent_version || '—'], + ['Robot hostname', agent?.hostname || '—'], + ['ROS domain', agent?.ros_domain_id ?? '—'], + ['Link uptime', connection.uptime_s ? `${Math.round(connection.uptime_s)} s` : '—'], + ['Cameras', (agent?.cameras || []).length || '—'], + ]), + connection.error + ? el('div', { style: { marginTop: '10px' } }, note(connection.error, 'critical', '⚠')) + : null, + ); + } + + function paintGraph() { + const match = (entry) => !graphFilter || entry.name.toLowerCase().includes(graphFilter); + const topics = (graph.topics || []).filter(match); + const services = (graph.services || []).filter(match); + + if (!graph.topics?.length && !graph.services?.length) { + graphHost.replaceChildren(emptyState( + 'No ROS graph available', + store.bridge?.simulated + ? 'The simulator has no ROS graph. Connect to a real robot to enumerate topics and services.' + : 'The bridge has not enumerated the graph yet — it refreshes every 5 seconds.', + )); + return; + } + + graphHost.replaceChildren( + el('div.grid.cols-2', {}, + el('div', {}, + el('div.row', { style: { marginBottom: '8px' } }, + el('strong', { text: 'Topics', style: { fontSize: '12px' } }), + badge(String(topics.length)), + ), + table([ + { key: 'name', label: 'Name' }, + { key: 'types', label: 'Type', get: (r) => (r.types || []).join(', ') }, + ], topics.slice(0, 300), { empty: 'No matching topics' }), + ), + el('div', {}, + el('div.row', { style: { marginBottom: '8px' } }, + el('strong', { text: 'Services', style: { fontSize: '12px' } }), + badge(String(services.length)), + ), + table([ + { key: 'name', label: 'Name' }, + { key: 'types', label: 'Type', get: (r) => (r.types || []).join(', ') }, + ], services.slice(0, 300), { empty: 'No matching services' }), + ), + ), + ); + } + + root.appendChild(card('ROS graph', { + sub: 'What the robot is advertising right now', + actions: [ + graphSearch, + button('Refresh', () => refreshGraph(), { size: 'sm', style: 'ghost', iconName: 'refresh' }), + ], + }, graphHost)); + graphSearch.style.maxWidth = '240px'; + + /* -- Wiring ----------------------------------------------------------- */ + + paintLog(); + paintAgent(); + refreshGraph(); + + const unsubscribe = store.on('event', () => paintLog()); + let lastAgent = 0; + const unsubState = store.on('state', () => { + const now = Date.now(); + if (now - lastAgent < 2000) return; + lastAgent = now; + paintAgent(); + }); + const timer = setInterval(refreshGraph, 15000); + + return { + node: root, + dispose: () => { unsubscribe(); unsubState(); clearInterval(timer); }, + }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/control.js b/x2_dashboard/web/js/tabs/control.js new file mode 100644 index 0000000..58db81c --- /dev/null +++ b/x2_dashboard/web/js/tabs/control.js @@ -0,0 +1,438 @@ +/* Control - mode switching, arbitration, driving, preset motions. */ + +import { store, socket, post, command, toast, num, confirmDialog } from '../core.js'; +import { + el, card, pageHead, button, note, badge, table, range, keyHint, kv, setChildren, +} from '../ui.js'; + +export default { + id: 'control', + label: 'Control', + icon: 'control', + + async render() { + const spec = store.spec; + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Control', + 'Motion mode, drive input and preset motions. Keep the physical remote controller within reach — it outranks this dashboard.', + )); + + /* ================================================================== + Motion mode + ================================================================== */ + + const modeTiles = el('div.stack'); + const modeButtons = new Map(); + + for (const group of spec?.mode_groups || []) { + const inGroup = (spec?.modes || []).filter((m) => m.group === group.key); + if (!inGroup.length) continue; + + const grid = el('div.tile-grid'); + for (const mode of inGroup) { + const tile = el('button.tile', { + type: 'button', + 'aria-pressed': 'false', + title: mode.desc, + onclick: () => setMode(mode), + }, + el('div.row.between', {}, + el('span.tile-name', { text: mode.label }), + mode.danger ? badge('risk', 'critical') : null, + ), + el('span.tile-meta', { text: `${mode.id} · ${mode.value}` }), + el('span', { + text: mode.desc, + style: { fontSize: '11px', color: 'var(--text-3)', lineHeight: '1.4' }, + }), + ); + modeButtons.set(mode.id, tile); + grid.appendChild(tile); + } + + modeTiles.appendChild(el('div', {}, + el('div', { + text: group.label, + style: { fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.07em', + color: 'var(--text-3)', fontWeight: '600', margin: '2px 0 8px' }, + }), + grid, + )); + } + + async function setMode(mode) { + if (mode.danger) { + const releases = ['PASSIVE_DEFAULT', 'ZERO_TORQUE_DEFAULT'].includes(mode.id); + const ok = await confirmDialog( + `Switch to ${mode.label}?`, + releases + ? 'This removes all joint holding force. A free-standing robot will collapse. ' + + 'Only continue if the robot is supported or already seated.' + : `${mode.desc} Make sure the area around the robot is clear before continuing.`, + { confirmLabel: `Yes, switch to ${mode.label}` }, + ); + if (!ok) return; + } + await command('/api/mode', { mode: mode.id, confirmed: true }, + { successTitle: `Mode: ${mode.label}` }); + } + + const modeCard = card('Motion mode', { + sub: `SetMcAction · ${(spec?.modes || []).length} modes`, + }, + modeTiles, + el('div', { style: { marginTop: '12px' } }, + note('Stable stand is the prerequisite for preset motions and for walking. ' + + 'Joint control mode is required before direct joint commands take effect.', 'info'), + ), + ); + + /* ================================================================== + Input source arbitration + ================================================================== */ + + const dash = spec?.dashboard_input_source || { name: 'x2_dashboard', priority: 30, timeout: 1000 }; + const sourceStatus = el('div'); + + const registerBtn = button('Announce the dashboard again', async () => { + await command('/api/input-source', dash, { successTitle: 'Dashboard announced' }); + }, { size: 'sm' }); + + const arbitrationRows = [ + ...(spec?.builtin_input_sources || []), + { name: dash.name, priority: dash.priority, timeout: dash.timeout, desc: 'This dashboard' }, + ].sort((a, b) => b.priority - a.priority); + + const sourceCard = card('Who is allowed to drive', { sub: 'Control arbitration' }, + el('div.stack', {}, + sourceStatus, + + el('p', { + style: { margin: '0', fontSize: '13px', color: 'var(--text-2)', lineHeight: '1.6' }, + text: 'Several things can send movement commands to this robot at once — the handheld ' + + 'remote, the mobile app, VR teleoperation, and this dashboard. The robot listens ' + + 'to whichever one is actively sending and has the highest priority.', + }), + el('p', { + style: { margin: '0', fontSize: '13px', color: 'var(--text-2)', lineHeight: '1.6' }, + text: 'The robot ignores commands from a sender it has never heard of, so the dashboard ' + + 'introduces itself automatically as soon as it connects. That is all "announcing" ' + + 'means — it does not take control away from anyone. You only need the button below ' + + 'if the robot restarts and forgets.', + }), + + table( + [ + { key: 'name', label: 'Sender' }, + { key: 'priority', label: 'Priority', align: 'right' }, + { key: 'desc', label: 'What it is' }, + ], + arbitrationRows, + ), + + note(`This dashboard sits at priority ${dash.priority} on purpose — below the handheld ` + + 'remote (80) and the mobile app (60). If someone picks up the remote while you are ' + + 'driving, the remote wins immediately.', 'info'), + + el('div.row', {}, registerBtn), + ), + ); + + root.appendChild(el('div.grid.cols-2', {}, modeCard, sourceCard)); + + /* ================================================================== + Drive + ================================================================== */ + + const limits = spec?.velocity_limits || { + forward: { max: 0.8 }, lateral: { max: 0.7 }, angular: { max: 0.8 }, + }; + const thresholds = spec?.velocity_thresholds || {}; + + let scale = 0.5; + let vector = { forward: 0, lateral: 0, angular: 0 }; + let strafeMode = false; + + const knob = el('div.joystick-knob'); + const pad = el('div.joystick', { dataset: { active: 'false' } }, + el('div.joystick-ring'), + el('span.joystick-label.n', { text: 'fwd' }), + el('span.joystick-label.s', { text: 'back' }), + el('span.joystick-label.w', { text: 'left' }), + el('span.joystick-label.e', { text: 'right' }), + knob, + ); + + const readoutHost = el('div'); + const strafeToggle = el('div.segmented'); + for (const [label, value] of [['Turn', false], ['Strafe', true]]) { + const btn = el('button', { type: 'button', text: label, 'aria-pressed': String(value === strafeMode) }); + btn.addEventListener('click', () => { + strafeMode = value; + for (const b of strafeToggle.children) b.setAttribute('aria-pressed', String(b === btn)); + setVector(0, 0); + }); + strafeToggle.appendChild(btn); + } + + const scaleRange = range({ + min: 0.1, max: 1, step: 0.05, value: scale, precision: 2, + onInput: (v) => { scale = v; }, + }); + + function setVector(nx, ny) { + // nx / ny are -1..1 in pad space; y is inverted so up is forward. + const forward = -ny * (limits.forward.max ?? 0.8) * scale; + const secondary = nx * ((strafeMode ? limits.lateral.max : limits.angular.max) ?? 0.7) * scale; + + vector = { + forward: Number(forward.toFixed(3)), + lateral: strafeMode ? Number(secondary.toFixed(3)) : 0, + // A joystick pushed right should turn right, i.e. clockwise, which is a + // negative yaw rate under the documented counter-clockwise-positive sign. + angular: strafeMode ? 0 : Number((-secondary).toFixed(3)), + }; + + knob.style.transform = `translate(${nx * 62}px, ${ny * 62}px)`; + socket.sendThrottled('velocity', vector); + paintReadout(); + } + + function paintReadout() { + const s = store.state; + const measured = s?.velocity || {}; + const belowThreshold = (axis, value) => { + const limit = thresholds[axis]; + return limit !== undefined && Math.abs(value) > 0 && Math.abs(value) < limit; + }; + + readoutHost.replaceChildren( + kv([ + ['Forward cmd', `${num(vector.forward, 2)} m/s`], + ['Lateral cmd', `${num(vector.lateral, 2)} m/s`], + ['Yaw cmd', `${num(vector.angular, 2)} rad/s`], + ['Forward now', `${num(measured.forward, 2)} m/s`], + ['Yaw now', `${num(measured.angular, 2)} rad/s`], + ]), + ); + + const warnings = []; + if (belowThreshold('forward', vector.forward)) { + warnings.push(`Forward command is below the ${thresholds.forward} m/s activation threshold — the robot will not start moving.`); + } + if (belowThreshold('angular', vector.angular)) { + warnings.push(`Yaw command is below the ${thresholds.angular} rad/s activation threshold.`); + } + if (belowThreshold('lateral', vector.lateral)) { + warnings.push(`Lateral command is below the ${thresholds.lateral} m/s activation threshold.`); + } + for (const text of warnings) readoutHost.appendChild(note(text, 'warning', '⚠')); + } + + /* Pointer drive */ + let pointerId = null; + + function padPoint(event) { + const rect = pad.getBoundingClientRect(); + const cx = rect.left + rect.width / 2; + const cy = rect.top + rect.height / 2; + const radius = rect.width / 2 - 28; + let dx = (event.clientX - cx) / radius; + let dy = (event.clientY - cy) / radius; + const magnitude = Math.hypot(dx, dy); + if (magnitude > 1) { dx /= magnitude; dy /= magnitude; } + return [dx, dy]; + } + + pad.addEventListener('pointerdown', (event) => { + pointerId = event.pointerId; + pad.setPointerCapture(pointerId); + pad.dataset.active = 'true'; + setVector(...padPoint(event)); + }); + pad.addEventListener('pointermove', (event) => { + if (event.pointerId !== pointerId) return; + setVector(...padPoint(event)); + }); + const releasePad = (event) => { + if (event.pointerId !== pointerId) return; + pointerId = null; + pad.dataset.active = 'false'; + setVector(0, 0); + }; + pad.addEventListener('pointerup', releasePad); + pad.addEventListener('pointercancel', releasePad); + + /* Keyboard drive */ + const held = new Set(); + const KEYS = { + KeyW: 'up', ArrowUp: 'up', + KeyS: 'down', ArrowDown: 'down', + KeyA: 'left', ArrowLeft: 'left', + KeyD: 'right', ArrowRight: 'right', + }; + + function applyKeys() { + const nx = (held.has('right') ? 1 : 0) - (held.has('left') ? 1 : 0); + const ny = (held.has('down') ? 1 : 0) - (held.has('up') ? 1 : 0); + setVector(nx, ny); + } + + const onKeyDown = (event) => { + if (['INPUT', 'TEXTAREA', 'SELECT'].includes(event.target.tagName)) return; + const dir = KEYS[event.code]; + if (!dir) return; + event.preventDefault(); + if (held.has(dir)) return; + held.add(dir); + applyKeys(); + }; + const onKeyUp = (event) => { + const dir = KEYS[event.code]; + if (!dir) return; + held.delete(dir); + applyKeys(); + }; + // A lost window must not leave the robot walking. + const onBlur = () => { held.clear(); setVector(0, 0); }; + + document.addEventListener('keydown', onKeyDown); + document.addEventListener('keyup', onKeyUp); + window.addEventListener('blur', onBlur); + + const driveCard = card('Drive', { sub: 'McLocomotionVelocity · /aima/mc/locomotion/velocity' }, + el('div.joystick-wrap', {}, + pad, + el('div.joystick-readout', {}, + el('div.row.between', {}, + el('span', { text: 'Horizontal axis', style: { fontSize: '12px', color: 'var(--text-2)' } }), + strafeToggle, + ), + el('div', {}, + el('div', { text: 'Speed scale', style: { fontSize: '12px', color: 'var(--text-2)', marginBottom: '4px' } }), + scaleRange, + ), + readoutHost, + ), + ), + el('div.stack', { style: { marginTop: '14px', gap: '8px' } }, + keyHint(['W', 'A', 'S', 'D'], 'or arrow keys to drive'), + keyHint(['Space'], 'emergency stop — zeroes velocity immediately'), + note('Velocity is republished continuously while you hold the stick. If this browser stops ' + + 'sending for half a second the server zeroes the command automatically.', 'info'), + ), + ); + + root.appendChild(driveCard); + + /* ================================================================== + Preset motions + ================================================================== */ + + const presetHost = el('div.stack'); + const groups = spec?.preset_groups || []; + const presets = spec?.presets || []; + + for (const group of groups) { + const inGroup = presets.filter((p) => p.group === group.key); + if (!inGroup.length) continue; + + const grid = el('div.tile-grid'); + for (const preset of inGroup) { + grid.appendChild(el('button.tile', { + type: 'button', + onclick: async (event) => { + const node = event.currentTarget; + node.disabled = true; + await command('/api/preset', { key: preset.key }, { successTitle: preset.label }); + setTimeout(() => { node.disabled = false; }, 900); + }, + }, + el('span.tile-name', { text: preset.label }), + el('span.tile-meta', { text: `${preset.side} · ${preset.enum}` }), + el('span.tile-meta', { + text: `motion ${preset.motion} · area ${preset.area}`, + style: { opacity: '.7' }, + }), + )); + } + + presetHost.appendChild(el('div', {}, + el('div', { + text: group.label, + style: { fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.07em', + color: 'var(--text-3)', fontWeight: '600', margin: '2px 0 8px' }, + }), + grid, + )); + } + + root.appendChild(card('Preset motions', { sub: `SetMcPresetMotion · ${presets.length} actions` }, + note('All preset motions require Stable stand mode and clear space around the robot.', 'warning', '⚠'), + el('div', { style: { marginTop: '12px' } }, presetHost), + )); + + /* ================================================================== + Live binding + ================================================================== */ + + function paintState() { + const s = store.state; + if (!s) return; + + for (const [id, tile] of modeButtons) { + tile.setAttribute('aria-pressed', String(id === s.mode)); + } + + const registered = s.source_registered; + const winner = s.input_source; + setChildren(sourceStatus, + el('div.row', {}, + badge(registered ? 'Dashboard can drive' : 'Not announced yet', + registered ? 'good' : 'warning'), + winner && winner !== dash.name + ? badge(`${winner} is driving`, 'accent') + : null, + ), + registered ? null : el('div', { style: { marginTop: '8px' } }, + note('The robot has not acknowledged the dashboard yet. This normally clears within a ' + + 'second or two of connecting; if it does not, use the button below.', 'warning', '⚠'), + ), + ); + + const driveable = (spec?.driveable_modes || []).includes(s.mode); + const canDrive = driveable && registered; + pad.style.opacity = canDrive ? '1' : '.45'; + pad.style.pointerEvents = canDrive ? 'auto' : 'none'; + pad.title = canDrive ? '' + : !driveable ? `Mode ${s.mode} does not accept velocity — switch to Stable stand or Walk` + : 'Register an input source to drive'; + } + + paintState(); + paintReadout(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 400) return; + last = now; + paintState(); + paintReadout(); + }); + + return { + node: root, + dispose: () => { + unsubscribe(); + document.removeEventListener('keydown', onKeyDown); + document.removeEventListener('keyup', onKeyUp); + window.removeEventListener('blur', onBlur); + // Leaving the tab must not leave a velocity command standing. + socket.send('velocity', { forward: 0, lateral: 0, angular: 0 }); + }, + }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/extensions.js b/x2_dashboard/web/js/tabs/extensions.js new file mode 100644 index 0000000..41ec8b0 --- /dev/null +++ b/x2_dashboard/web/js/tabs/extensions.js @@ -0,0 +1,363 @@ +/* Extensions - renders whatever plugins the backend found. + + Nothing here knows about any specific plugin. Each control in the manifest + maps to a widget, and using it POSTs to /api/plugins//. Add a + Python file, press Reload, and it appears. +*/ + +import { store, get, post, command, toast, num, confirmDialog } from '../core.js'; +import { + el, card, pageHead, button, note, badge, range, select, input, textarea, + emptyState, stat, field, kv, +} from '../ui.js'; +import { sparkline } from '../charts.js'; + +export default { + id: 'extensions', + label: 'Extensions', + icon: 'extensions', + + async render() { + const root = el('div.stack'); + const body = el('div.stack'); + + const reloadBtn = button('Reload extensions', async () => { + reloadBtn.disabled = true; + reloadBtn.querySelector('.ico')?.classList.add('spin'); + try { + const data = await post('/api/plugins/reload'); + store.plugins = data.manifest; + toast('Extensions reloaded', + `${data.summary.count} loaded${data.summary.errors.length ? `, ${data.summary.errors.length} failed` : ''}`, + data.summary.errors.length ? 'warning' : 'good'); + paint(); + } catch (err) { + toast('Reload failed', err.message, 'critical'); + } finally { + reloadBtn.disabled = false; + reloadBtn.querySelector('.ico')?.classList.remove('spin'); + } + }, { iconName: 'refresh', style: 'primary' }); + + root.appendChild(pageHead( + 'Extensions', + 'Custom controls you have added. Drop a Python file into the plugins folder and reload — ' + + 'no frontend changes needed.', + [reloadBtn], + )); + + root.appendChild(body); + + /* -- Rendering -------------------------------------------------------- */ + + const readoutNodes = new Map(); // `${pluginId}.${key}` -> { value, spark } + let seriesCache = {}; + + function paint() { + const manifest = store.plugins || { plugins: [], errors: [] }; + body.replaceChildren(); + readoutNodes.clear(); + + /* How-to, always visible so the workflow is discoverable. */ + body.appendChild(card('How to add a control', { sub: manifest.directory || 'backend/plugins/' }, + el('div.stack', { style: { gap: '10px' } }, + el('p', { + text: 'Create a file in the plugins folder, build a Plugin, decorate a handler. ' + + 'It becomes a card on this page the moment you press Reload.', + style: { margin: '0', color: 'var(--text-2)', fontSize: '13px' }, + }), + el('pre', { + style: { + margin: '0', padding: '13px 15px', background: 'var(--bg)', + border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', + fontFamily: 'var(--mono)', fontSize: '11.5px', lineHeight: '1.65', + overflowX: 'auto', color: 'var(--text-2)', + }, + text: `from backend.plugin_api import Plugin + +plugin = Plugin(id="my_tool", name="My tool", icon="⚙") + +@plugin.action("go", label="Do the thing", style="primary") +async def go(ctx): + await ctx.bridge.play_preset(motion=1002, area=2) + return "Done" + +@plugin.slider("speed", label="Speed", min=0, max=0.6, default=0.2, unit="m/s") +async def speed(ctx, value): + ctx.storage["speed"] = value + return f"Speed {value:.2f}" + +plugin.readout("speed", "Current speed", unit="m/s", chart=True)`, + }), + el('div.row.tight', {}, + badge('action → button'), badge('slider → range'), badge('toggle → switch'), + badge('select → dropdown'), badge('text → input'), badge('number → stepper'), + badge('color → picker'), badge('readout → stat tile'), + ), + note('ctx gives you .bridge (every robot command), .state (live telemetry), ' + + '.storage (persists across calls), .log(), .push() and .record().', 'info'), + ), + )); + + /* Load errors */ + if (manifest.errors?.length) { + body.appendChild(card('Extensions that failed to load', {}, + el('div.stack', { style: { gap: '10px' } }, + ...manifest.errors.map((error) => el('div', { + style: { + padding: '12px 14px', borderRadius: 'var(--radius-sm)', + background: 'rgba(208,59,59,.07)', border: '1px solid rgba(208,59,59,.3)', + }, + }, + el('div.row.between', { style: { marginBottom: '6px' } }, + el('strong', { text: error.file, style: { fontSize: '13px' } }), + badge('failed', 'critical'), + ), + el('div', { text: error.error, style: { fontSize: '12px', color: 'var(--text-2)' } }), + error.trace ? el('pre', { + text: error.trace, + style: { + margin: '8px 0 0', fontSize: '10.5px', fontFamily: 'var(--mono)', + color: 'var(--text-3)', whiteSpace: 'pre-wrap', maxHeight: '150px', + overflowY: 'auto', + }, + }) : null, + )), + ), + )); + } + + /* Plugin cards */ + if (!manifest.plugins?.length) { + body.appendChild(emptyState( + 'No extensions loaded yet', + 'The plugins folder has no usable files. Copy _template.py to a new name to start.', + )); + return; + } + + const grid = el('div.grid.cols-2'); + for (const plugin of manifest.plugins) grid.appendChild(renderPlugin(plugin)); + body.appendChild(grid); + + paintReadouts(); + } + + function renderPlugin(plugin) { + const controls = el('div.stack', { style: { gap: '13px' } }); + + for (const control of plugin.controls) { + const node = renderControl(plugin, control); + if (node) controls.appendChild(node); + } + + const readouts = el('div.grid.cols-2', { style: { gap: '9px' } }); + for (const readout of plugin.readouts || []) { + const valueNode = el('div.stat-value', { text: '—' }); + const sparkHost = readout.chart ? el('div.stat-spark') : null; + const tile = el('div.stat', {}, + el('div.stat-label', { text: readout.label }), + valueNode, + sparkHost, + ); + readoutNodes.set(`${plugin.id}.${readout.key}`, { readout, valueNode, sparkHost }); + readouts.appendChild(tile); + } + + return card(plugin.name, { + sub: plugin.description, + actions: [ + el('span', { text: plugin.icon, style: { fontSize: '16px' } }), + plugin.has_tick ? badge(`ticks ${plugin.tick_interval}s`, 'accent') : null, + ].filter(Boolean), + }, + el('div.stack', {}, + plugin.readouts?.length ? readouts : null, + plugin.controls.length ? controls + : note('This extension declares no controls.', 'default'), + ), + ); + } + + function renderControl(plugin, control) { + const path = `/api/plugins/${plugin.id}/${control.key}`; + + const run = async (value, node) => { + if (control.confirm) { + const ok = await confirmDialog(control.label, control.confirm, + { danger: control.style === 'danger' }); + if (!ok) return; + } + if (node) node.disabled = true; + try { + const data = await post(path, { value }); + toast(control.label, data?.message || 'Done', data?.ok === false ? 'critical' : 'good'); + } catch (err) { + toast(control.label, err.message, 'critical'); + } finally { + if (node) node.disabled = false; + } + }; + + switch (control.kind) { + case 'action': { + const btn = button(control.label, (node) => run(null, node), { + style: control.style || 'default', + title: control.help || '', + block: true, + }); + return control.help + ? el('div', {}, btn, el('div.hint', { text: control.help, style: { marginTop: '4px' } })) + : btn; + } + + case 'slider': { + const control_ = range({ + min: control.min, max: control.max, step: control.step, + value: control.default, unit: control.unit ? ` ${control.unit}` : '', + precision: decimalsFor(control.step), + onInput: control.live ? throttle((v) => run(v), 200) : undefined, + onChange: control.live ? undefined : (v) => run(v), + }); + return field(control.label, control_, control.help); + } + + case 'toggle': { + const box = el('input', { type: 'checkbox', checked: control.default }); + box.addEventListener('change', () => run(box.checked)); + return el('div', {}, + el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: control.label })), + control.help ? el('div.hint', { text: control.help, style: { marginTop: '4px' } }) : null, + ); + } + + case 'select': { + const node = select(control.options || [], { + value: control.default, + onChange: (value) => run(value), + }); + return field(control.label, node, control.help); + } + + case 'text': { + const box = control.multiline + ? textarea({ placeholder: control.placeholder || '', value: control.default || '' }) + : input({ placeholder: control.placeholder || '', value: control.default || '' }); + const submit = button(control.submit_label || 'Send', (node) => { + const value = box.value; + if (!value.trim()) { box.focus(); return; } + run(value, node).then(() => { box.value = ''; }); + }, { style: 'primary', size: 'sm' }); + if (!control.multiline) { + box.addEventListener('keydown', (e) => { if (e.key === 'Enter') submit.click(); }); + } + return field(control.label, + el('div.row', { style: { gap: '8px', flexWrap: 'nowrap' } }, box, submit), + control.help); + } + + case 'number': { + const box = input({ + type: 'number', value: control.default, + min: control.min ?? undefined, max: control.max ?? undefined, step: control.step, + }); + box.addEventListener('change', () => run(Number(box.value))); + return field( + control.unit ? `${control.label} (${control.unit})` : control.label, + box, control.help, + ); + } + + case 'color': { + const box = el('input.input', { type: 'color', value: control.default || '#3987e5' }); + box.addEventListener('change', () => run(box.value)); + return field(control.label, box, control.help); + } + + default: + return note(`Unsupported control type "${control.kind}"`, 'warning', '⚠'); + } + } + + /* -- Readouts --------------------------------------------------------- */ + + function paintReadouts() { + const custom = store.state?.custom || {}; + + for (const [key, entry] of readoutNodes) { + const [pluginId, readoutKey] = splitOnce(key, '.'); + const value = custom[pluginId]?.[readoutKey]; + const { readout, valueNode, sparkHost } = entry; + + if (value === undefined || value === null) { + valueNode.textContent = '—'; + } else if (readout.format === 'text' || typeof value === 'string') { + valueNode.textContent = String(value); + valueNode.style.fontSize = '17px'; + } else { + valueNode.textContent = num(value, readout.precision ?? 2); + valueNode.style.fontSize = ''; + if (readout.unit) valueNode.appendChild(el('span.unit', { text: readout.unit })); + } + + if (sparkHost) { + const points = seriesCache[`${pluginId}.${readoutKey}`] || []; + sparkHost.replaceChildren( + points.length > 2 ? sparkline(points, { height: 30, colorIndex: 2 }) : el('span'), + ); + } + } + } + + async function refreshSeries() { + const wanted = [...readoutNodes.entries()] + .filter(([, entry]) => entry.readout.chart) + .map(([key]) => key); + if (!wanted.length) return; + try { + seriesCache = await get(`/api/series?keys=${wanted.join(',')}&limit=120`); + } catch { /* best-effort */ } + } + + paint(); + await refreshSeries(); + paintReadouts(); + + const unsubPlugins = store.on('plugins', () => paint()); + let last = 0; + const unsubState = store.on('state', () => { + const now = Date.now(); + if (now - last < 900) return; + last = now; + paintReadouts(); + }); + const timer = setInterval(() => refreshSeries().then(paintReadouts), 4000); + + return { + node: root, + dispose: () => { unsubPlugins(); unsubState(); clearInterval(timer); }, + }; + }, +}; + +function decimalsFor(step) { + const text = String(step); + const dot = text.indexOf('.'); + return dot === -1 ? 0 : Math.min(4, text.length - dot - 1); +} + +function splitOnce(text, separator) { + const index = text.indexOf(separator); + return index === -1 ? [text, ''] : [text.slice(0, index), text.slice(index + 1)]; +} + +function throttle(fn, ms) { + let last = 0; + return (...args) => { + const now = Date.now(); + if (now - last < ms) return; + last = now; + fn(...args); + }; +} diff --git a/x2_dashboard/web/js/tabs/interaction.js b/x2_dashboard/web/js/tabs/interaction.js new file mode 100644 index 0000000..ee54eea --- /dev/null +++ b/x2_dashboard/web/js/tabs/interaction.js @@ -0,0 +1,535 @@ +/* Interaction - speech, screen expression, LED strip. */ + +import { store, command, num, api, get, toast } from '../core.js'; +import { + el, card, pageHead, button, note, badge, range, select, textarea, field, + segmented, emptyState, +} from '../ui.js'; + +export default { + id: 'interaction', + label: 'Interaction', + icon: 'interaction', + + async render() { + const spec = store.spec; + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Interaction', + 'What the robot says, shows on its face, and signals with its light strip.', + )); + + /* ================================================================== + Conversation — the listening loop (Muza / Lumi) + ================================================================== + The robot only starts listening once a character, a language and a model + have been chosen and Apply is pressed. Selections are staged locally in + `draft` and committed in one request, because switching any of them means + relaunching the voice process — doing that per-click would restart the + pipeline three times on the way to one setup. */ + + let session = null; + let applying = false; + const draft = { enabled: false, gender: 'female', language: 'arabic', model: 'gemini' }; + + const sessionControlsHost = el('div.stack'); + const sessionStatusHost = el('div'); + const sessionDetailHost = el('div'); + const sessionWarnHost = el('div'); + + const applyBtn = button('Apply', async () => { + applying = true; + applyBtn.disabled = true; + applyBtn.textContent = draft.enabled ? 'Starting…' : 'Stopping…'; + paintStatus(); + try { + // Deliberately not `command()`: a unit restart can outlast its 15s + // default timeout, and a timed-out apply that actually succeeded is + // the most confusing possible outcome here. + const data = await api('/api/voice/session', { + method: 'POST', body: { ...draft }, timeout: 90000, + }); + // Re-seed from what the server ACTUALLY applied, never from `draft`. + // Showing the requested state instead of the achieved one is what made + // the card read "muza_ar.txt / Kore" while Lumi was selected. + syncFromServer(data.snapshot); + if (data.snapshot?.profile?.enabled) { + const who = `${session.persona.name_en} · ${session.persona.name_ar}`; + toast('Starting', `${who} — the greeting plays once the voice ` + + 'connects, usually within about ten seconds.', 'good'); + } else { + toast('Speaking off', 'The robot has stopped listening.', 'good'); + } + } catch (err) { + toast('Could not apply', err.message, 'critical'); + // Pull the real state back: a failed apply may still have changed it. + get('/api/voice/session').then(syncFromServer).catch(() => {}); + } finally { + applying = false; + applyBtn.disabled = false; + applyBtn.textContent = 'Apply'; + paintStatus(); + } + }, { style: 'primary' }); + + /* Controls are rebuilt only when the SERVER's state changes, not on every + local click — rebuilding mid-interaction would tear down the widget the + operator just clicked. Local clicks mutate `draft` and repaint only the + read-only lines below it. */ + function buildSessionControls() { + const enableBox = el('input', { type: 'checkbox', checked: draft.enabled }); + enableBox.addEventListener('change', () => { + draft.enabled = enableBox.checked; + paintDetail(); + }); + + sessionControlsHost.replaceChildren( + el('label.switch', {}, enableBox, el('span.switch-track'), + el('span.switch-label', { text: 'Speaking on' })), + + field('Character', + segmented(session.options.gender, draft.gender, (value) => { + draft.gender = value; + paintDetail(); + }), + 'Female speaks as Muza (موزة); male speaks as Lumi (لومي).'), + + field('Language', + segmented(session.options.language, draft.language, (value) => { + draft.language = value; + paintDetail(); + }), + 'Arabic only is pure Emirati dialect. Multi-language still opens in ' + + 'Emirati and follows the visitor from there.'), + + field('Model', + segmented(session.options.model, draft.model, (value) => { + draft.model = value; + paintDetail(); + }), + 'Gemini Live is streaming speech-to-speech. LinkSoul routes through ' + + 'the robot’s own agent, which keeps its native co-speech motion.'), + + el('div.row.between', {}, sessionWarnHost, applyBtn), + ); + } + + function paintStatus() { + const running = session?.service?.running; + sessionStatusHost.replaceChildren( + applying ? badge('Starting…', 'accent') + : badge(running ? 'Listening' : 'Off', running ? 'good' : 'default'), + ); + } + + function paintDetail() { + if (!session) return; + + // Everything below describes the STAGED selection, so it has to be + // derived from `draft` — reading persona/voice off the last snapshot is + // what made the line disagree with the selected character. + const persona = (session.personas || {})[`${draft.gender}_${draft.language}`]; + const voice = draft.model === 'linksoul' + ? session.voices?.edge?.[draft.gender] + : session.voices?.gemini?.[draft.gender]; + + const staged = draft.enabled !== !!session.profile?.enabled + || draft.gender !== session.profile?.gender + || draft.language !== session.profile?.language + || draft.model !== session.profile?.model; + + sessionDetailHost.replaceChildren( + el('div.hint', { + text: `${staged ? 'Will apply' : 'Running'}: persona ${persona || '—'} · ` + + `voice ${voice || '—'} · unit ${session.service?.unit || '—'} ` + + `(${session.service?.state || '—'})`, + }), + ); + + // Only warn about LinkSoul while LinkSoul is the staged choice — the + // missing SDK is irrelevant noise when Gemini is selected. + const ls = session.linksoul; + sessionWarnHost.replaceChildren( + draft.model === 'linksoul' && ls && !ls.ready + ? note(`LinkSoul cannot start yet — ${ls.reasons.join('; ')}.`, 'warning') + : el('span'), + ); + } + + function syncFromServer(snapshot) { + if (!snapshot) return; + session = snapshot; + if (!snapshot.available) { + sessionControlsHost.replaceChildren( + note(`Voice session unavailable — ${snapshot.error}. Looked for Sanad at ` + + `${snapshot.sanad_dir || 'the configured path'}.`, 'warning'), + ); + return; + } + // Seed the toggle from the SAVED INTENT, not from whether the unit + // happens to be up. Reading service.running here meant that pressing + // Apply during a restart (or any moment the unit was briefly down) sent + // enabled:false and STOPPED the voice instead of starting it — which + // reads exactly like "I pressed Apply and now it never answers". + // paintStatus() still shows the real unit state, so a disagreement + // between intent and reality stays visible without rewriting the intent. + Object.assign(draft, snapshot.profile); + buildSessionControls(); + paintStatus(); + paintDetail(); + } + + const conversationCard = card('Conversation', { + sub: 'Muza / Lumi', + actions: [sessionStatusHost], + }, el('div.stack', {}, sessionControlsHost, sessionDetailHost)); + + root.appendChild(conversationCard); + + get('/api/voice/session').then(syncFromServer).catch((err) => { + sessionControlsHost.replaceChildren( + note(`Could not read the voice session: ${err.message}`, 'warning'), + ); + }); + + /* ================================================================== + Voice + ================================================================== */ + + const speechBox = textarea({ + placeholder: 'Type what the robot should say…', + rows: 3, + }); + + const prioritySelect = select( + (spec?.tts_priorities || []).map((p) => ({ value: p.value, label: `${p.label} (${p.value}) — ${p.desc}` })), + { value: 6 }, + ); + + let interrupt = false; + + const speakBtn = button('Speak', async () => { + const text = speechBox.value.trim(); + if (!text) { speechBox.focus(); return; } + const ok = await command('/api/speak', { + text, + priority: Number(prioritySelect.value), + interrupt, + }, { successTitle: 'Sent to TTS' }); + if (ok) speechBox.value = ''; + }, { style: 'primary' }); + + // Ctrl/Cmd+Enter is the expected shortcut in a text box that has a submit button. + speechBox.addEventListener('keydown', (event) => { + if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) speakBtn.click(); + }); + + const quickPhrases = [ + 'Hello, I am X2.', + 'Please stand clear.', + 'Starting the routine now.', + 'Task complete.', + 'Battery is low.', + ]; + + const volumeRange = range({ + min: 0, max: 100, step: 1, value: store.state?.volume ?? 60, precision: 0, unit: '%', + onChange: (value) => command('/api/volume', { volume: value }, { silent: true }), + }); + + const muteHost = el('div'); + const ttsStatusHost = el('div'); + + const voiceCard = card('Speech', { sub: 'PlayTts' }, + el('div.stack', {}, + field('Text', speechBox, 'Ctrl + Enter to send'), + el('div.row.tight', {}, + ...quickPhrases.map((phrase) => button(phrase, () => { + speechBox.value = phrase; + speechBox.focus(); + }, { size: 'sm', style: 'ghost' })), + ), + field('Priority', prioritySelect, + 'Higher priorities pre-empt queued speech. Reserve 8–10 for genuine safety announcements.'), + el('div.row.between', {}, + (() => { + const box = el('input', { type: 'checkbox' }); + box.addEventListener('change', () => { interrupt = box.checked; }); + return el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: 'Interrupt current speech' })); + })(), + speakBtn, + ), + ), + ); + + const audioCard = card('Audio', { sub: 'GetVolume / SetVolume / SetMute' }, + el('div.stack', {}, + el('div', {}, + el('div', { text: 'Output volume', style: { fontSize: '12px', color: 'var(--text-2)', marginBottom: '5px' } }), + volumeRange, + ), + muteHost, + ttsStatusHost, + note('Microphone source switching is not exposed as a service on this firmware, so it is ' + + 'not offered here. Volume and mute are live.', 'info'), + ), + ); + + root.appendChild(el('div.grid.cols-2', {}, voiceCard, audioCard)); + + /* ================================================================== + Screen / emoji + ================================================================== */ + + let emojiMode = 1; + const emojiHost = el('div.stack'); + const emojiTiles = new Map(); + + const modeTabs = segmented( + (spec?.emoji_modes || []).map((m) => ({ value: m.value, label: m.label })), + emojiMode, + (value) => { emojiMode = value; }, + ); + + for (const group of spec?.emoji_groups || []) { + const inGroup = (spec?.emojis || []).filter((e) => e.group === group.key); + if (!inGroup.length) continue; + + const grid = el('div.emoji-grid'); + for (const emoji of inGroup) { + const tile = el('button.emoji-tile', { + type: 'button', + 'aria-pressed': 'false', + title: `ID ${emoji.id}`, + onclick: () => command('/api/emoji', { emotion_id: emoji.id, mode: emojiMode }, + { successTitle: emoji.label }), + }, + el('span.emoji-glyph', { text: emoji.glyph }), + el('span.emoji-name', { text: emoji.label }), + ); + emojiTiles.set(emoji.id, tile); + grid.appendChild(tile); + } + + emojiHost.appendChild(el('div', {}, + el('div', { + text: group.label, + style: { fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.07em', + color: 'var(--text-3)', fontWeight: '600', margin: '2px 0 8px' }, + }), + grid, + )); + } + + root.appendChild(card('Face', { + sub: `PlayEmoji · ${(spec?.emojis || []).length} expressions`, + actions: [modeTabs], + }, emojiHost)); + + /* ================================================================== + LED strip + ================================================================== */ + + let led = { mode: 0, r: 57, g: 135, b: 229 }; + let ledKeep = true; + + const preview = el('div', { + style: { + width: '100%', height: '54px', borderRadius: 'var(--radius-sm)', + border: '1px solid var(--border)', + background: `rgb(${led.r}, ${led.g}, ${led.b})`, + transition: 'background .2s', + }, + }); + + const colorInput = el('input.input', { type: 'color', value: rgbToHex(led) }); + colorInput.addEventListener('input', () => { + Object.assign(led, hexToRgb(colorInput.value)); + preview.style.background = `rgb(${led.r}, ${led.g}, ${led.b})`; + markSwatch(); + }); + + const swatchHost = el('div.swatches'); + const swatchNodes = []; + for (const swatch of spec?.led_swatches || []) { + const node = el('button.swatch', { + type: 'button', + title: swatch.label, + 'aria-pressed': 'false', + style: { + background: `rgb(${swatch.r}, ${swatch.g}, ${swatch.b})`, + borderColor: swatch.r + swatch.g + swatch.b === 0 ? 'var(--surface-hi)' : 'transparent', + }, + onclick: () => { + led = { ...led, r: swatch.r, g: swatch.g, b: swatch.b }; + colorInput.value = rgbToHex(led); + preview.style.background = `rgb(${led.r}, ${led.g}, ${led.b})`; + markSwatch(); + }, + }); + node._swatch = swatch; + swatchNodes.push(node); + swatchHost.appendChild(node); + } + + function markSwatch() { + for (const node of swatchNodes) { + const s = node._swatch; + node.setAttribute('aria-pressed', String(s.r === led.r && s.g === led.g && s.b === led.b)); + } + } + markSwatch(); + + const ledModeTabs = segmented( + (spec?.led_modes || []).map((m) => ({ value: m.value, label: m.label })), + led.mode, + (value) => { led.mode = value; }, + ); + + const ledCard = card('Light strip', { sub: 'SetPmuLed', actions: [ledModeTabs] }, + el('div.stack', {}, + preview, + swatchHost, + field('Custom colour', colorInput), + + (() => { + const box = el('input', { type: 'checkbox', checked: ledKeep }); + box.addEventListener('change', () => { ledKeep = box.checked; }); + return el('div', {}, + el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: 'Keep it on' })), + el('div.hint', { + text: 'The robot\'s own task_manager reclaims the light strip after about a minute. ' + + 'With this on, the dashboard re-applies your setting every 20 seconds so it ' + + 'stays. Turn it off if you want a single one-off flash instead.', + style: { marginTop: '5px' }, + }), + ); + })(), + + el('div.row', {}, + button('Apply', () => command('/api/led', { ...led, keep: ledKeep }, + { successTitle: ledKeep ? 'LED set and held' : 'LED set once' }), + { style: 'primary' }), + button('Turn off', () => { + led = { ...led, r: 0, g: 0, b: 0 }; + colorInput.value = '#000000'; + preview.style.background = '#000'; + markSwatch(); + // keep:false also cancels the keepalive, so "off" stays off. + return command('/api/led', { ...led, mode: 0, keep: false }, + { successTitle: 'LED off' }); + }), + ), + el('div', {}, + ...(spec?.led_modes || []).map((m) => el('div', { + text: `${m.label} — ${m.desc}`, + style: { fontSize: '11.5px', color: 'var(--text-3)', lineHeight: '1.6' }, + })), + ), + ), + ); + + const statusCard = card('Current output', {}, + el('div', { id: 'interaction-status' }), + ); + + root.appendChild(el('div.grid.cols-2', {}, ledCard, statusCard)); + + /* ================================================================== + Live state + ================================================================== */ + + function paint() { + const s = store.state; + if (!s) return; + + muteHost.replaceChildren((() => { + const box = el('input', { type: 'checkbox', checked: s.muted }); + box.addEventListener('change', () => + command('/api/mute', { muted: box.checked }, { silent: true })); + return el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: s.muted ? 'Muted' : 'Sound on' })); + })()); + + const faceStatus = s.custom?.face_status; + const faceLabel = (spec?.face_status || {})[faceStatus]; + ttsStatusHost.replaceChildren( + el('div.row', {}, + el('span', { text: 'Face playback', style: { fontSize: '12px', color: 'var(--text-2)' } }), + badge(faceLabel || 'unknown', + faceStatus === 2 ? 'good' : faceStatus === 0 ? 'default' : 'accent'), + ), + ); + + for (const [id, tile] of emojiTiles) { + tile.setAttribute('aria-pressed', String(id === s.emoji_id)); + } + + const activeEmoji = (spec?.emojis || []).find((e) => e.id === s.emoji_id); + const modeLabel = (spec?.led_modes || []).find((m) => m.value === s.led?.mode)?.label || '—'; + + document.getElementById('interaction-status')?.replaceChildren( + el('div.grid.cols-2', { style: { gap: '10px' } }, + el('div.stat', {}, + el('div.stat-label', { text: 'Face' }), + el('div.row', { style: { gap: '8px', alignItems: 'center', marginTop: '4px' } }, + el('span', { text: activeEmoji?.glyph || '—', style: { fontSize: '26px' } }), + el('span', { text: activeEmoji?.label || 'nothing set', style: { fontSize: '13px' } }), + ), + ), + el('div.stat', {}, + el('div.stat-label', { text: 'Light strip' }), + el('div.row', { style: { gap: '8px', alignItems: 'center', marginTop: '4px' } }, + el('span', { + style: { + width: '22px', height: '22px', borderRadius: '6px', + border: '1px solid var(--border)', + background: `rgb(${s.led?.r ?? 0}, ${s.led?.g ?? 0}, ${s.led?.b ?? 0})`, + }, + }), + el('span', { text: modeLabel, style: { fontSize: '13px' } }), + ), + ), + el('div.stat', {}, + el('div.stat-label', { text: 'Volume' }), + el('div.stat-value', { text: `${s.volume ?? 0}` }, el('span.unit', { text: '%' })), + ), + el('div.stat', {}, + el('div.stat-label', { text: 'Audio' }), + el('div', { style: { marginTop: '6px' } }, + badge(s.muted ? 'Muted' : 'Active', s.muted ? 'warning' : 'good'), + ), + ), + ), + ); + } + + paint(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 800) return; + last = now; + paint(); + }); + + return { node: root, dispose: unsubscribe }; + }, +}; + +function rgbToHex({ r, g, b }) { + return `#${[r, g, b].map((v) => Math.max(0, Math.min(255, v | 0)).toString(16).padStart(2, '0')).join('')}`; +} + +function hexToRgb(hex) { + const clean = hex.replace('#', ''); + return { + r: parseInt(clean.slice(0, 2), 16) || 0, + g: parseInt(clean.slice(2, 4), 16) || 0, + b: parseInt(clean.slice(4, 6), 16) || 0, + }; +} diff --git a/x2_dashboard/web/js/tabs/lidar.js b/x2_dashboard/web/js/tabs/lidar.js new file mode 100644 index 0000000..823d1c2 --- /dev/null +++ b/x2_dashboard/web/js/tabs/lidar.js @@ -0,0 +1,430 @@ +/* LiDAR - live 3D point cloud from the chest sensor. + + Off until switched on, like the cameras: a scan is 816 KB at 2 Hz and there + is no reason to carry that when nobody is looking. + + Rendered with a hand-rolled projection onto a 2D canvas rather than a 3D + library. Points need no lighting, no materials and no scene graph - just a + matrix multiply and a fillRect - so a library would be a few hundred KB + fetched over the same link we are trying not to saturate. The robot has no + internet either, which rules out a CDN. +*/ + +import { store, get, post, num, toast } from '../core.js'; +import { el, card, pageHead, button, badge, note, stat, segmented, toggle } from '../ui.js'; + +export default { + id: 'lidar', + label: 'LiDAR', + icon: 'scan', + + async render() { + const spec = store.spec?.lidar || {}; + const key = spec.key || 'lidar_chest_front'; + + const root = el('div.stack'); + let active = false; + let busy = false; + let timer = null; + + /* -- View state -------------------------------------------------------- */ + + const view = { + yaw: -0.6, // radians, orbit around Z (up) + pitch: 0.45, // radians above the horizon + distance: 12, // metres from the origin + colourBy: 'height', + accumulate: false, + }; + + let live = []; // newest scan: [x, y, z, intensity] + const trailScans = []; // recent scans, when accumulating + const MAX_TRAIL = 12; + + /* -- Controls ---------------------------------------------------------- */ + + const statusBadge = badge('off'); + const powerBox = el('input', { type: 'checkbox' }); + powerBox.addEventListener('change', () => setActive(powerBox.checked)); + const power = el('label.switch', {}, powerBox, el('span.switch-track'), + el('span.switch-label', { text: 'Off' })); + const powerLabel = power.querySelector('.switch-label'); + + root.appendChild(pageHead( + 'LiDAR', + 'Chest LiDAR point cloud, decimated on the robot before it crosses the network. ' + + 'Drag to orbit, scroll to zoom.', + [power, statusBadge], + )); + + const tiles = el('div.grid.cols-4'); + const refs = {}; + for (const [tileKey, label] of [ + ['points', 'Points drawn'], + ['scan', 'Points per scan'], + ['rate', 'Scan rate'], + ['range', 'Furthest return'], + ]) { + const node = stat(label, '—', { sub: ' ' }); + refs[tileKey] = node; + tiles.appendChild(node); + } + root.appendChild(tiles); + + function setTile(tileKey, value, sub, unit = '') { + const node = refs[tileKey]; + if (!node) return; + const valueNode = node.querySelector('.stat-value'); + valueNode.textContent = String(value); + if (unit) valueNode.appendChild(el('span.unit', { text: unit })); + node.querySelector('.stat-sub').textContent = sub || ''; + } + + const canvas = el('canvas', { + width: 1200, height: 720, + style: { width: '100%', height: 'auto', display: 'block', cursor: 'grab', + borderRadius: 'var(--radius-sm)', touchAction: 'none' }, + }); + + root.appendChild(card('Point cloud', { + sub: spec.topic || '', + actions: [ + segmented( + [{ value: 'height', label: 'Height' }, + { value: 'distance', label: 'Distance' }, + { value: 'intensity', label: 'Intensity' }], + view.colourBy, + (value) => { view.colourBy = value; draw(); }, + ), + toggle('Trail', false, (on) => { + view.accumulate = on; + trailScans.length = 0; + draw(); + }), + button('Reset view', () => { + view.yaw = -0.6; view.pitch = 0.45; view.distance = 12; + draw(); + }, { size: 'sm', style: 'ghost' }), + ], + flush: true, + }, canvas)); + + root.appendChild(note( + 'Points are in the sensor frame: X forward, Y left, Z up, metres. The robot decimates ' + + `each scan to ${spec.max_points || 4000} points — the full scan is ~25 000, which looks ` + + 'identical on screen and costs ten times the bandwidth.', + 'info', + )); + + /* -- Switching --------------------------------------------------------- */ + + async function setActive(on) { + if (busy) return; + busy = true; + powerBox.disabled = true; + statusBadge.textContent = on ? 'starting…' : 'stopping…'; + statusBadge.dataset.tone = 'default'; + + try { + await post(`/api/streams/${key}`, { active: on }); + active = on; + powerLabel.textContent = on ? 'On' : 'Off'; + if (on) { + schedule(); + } else { + if (timer) clearTimeout(timer); + timer = null; + live = []; + trailScans.length = 0; + statusBadge.textContent = 'off'; + statusBadge.dataset.tone = 'default'; + setTile('points', '—', ''); + setTile('scan', '—', ''); + setTile('rate', '—', ''); + setTile('range', '—', ''); + draw(); + } + } catch (err) { + toast('Could not switch the LiDAR', err.message, 'critical'); + powerBox.checked = active; + } finally { + busy = false; + powerBox.disabled = false; + } + } + + /* -- Polling ----------------------------------------------------------- */ + + // The sensor publishes at 2 Hz, so asking faster than that just re-fetches + // the same scan. 400 ms keeps the view current without waste. + const POLL_MS = 400; + let lastTs = 0; + let scanTimes = []; + + function schedule() { + if (timer) clearTimeout(timer); + timer = active ? setTimeout(fetchPoints, POLL_MS) : null; + } + + async function fetchPoints() { + if (!active) return; + try { + const data = await get('/api/lidar/points'); + if (data.off) { + // Something else turned it off - follow rather than fight it. + active = false; + powerBox.checked = false; + powerLabel.textContent = 'Off'; + statusBadge.textContent = 'off'; + statusBadge.dataset.tone = 'default'; + return; + } + if (!data.ok) { + statusBadge.textContent = data.message || 'waiting'; + statusBadge.dataset.tone = 'warning'; + return; + } + + if (data.ts && data.ts !== lastTs) { + scanTimes.push(data.ts); + if (scanTimes.length > 8) scanTimes.shift(); + lastTs = data.ts; + + if (view.accumulate) { + trailScans.push(live); + while (trailScans.length > MAX_TRAIL) trailScans.shift(); + } + live = data.points || []; + } + + statusBadge.textContent = 'live'; + statusBadge.dataset.tone = 'good'; + + const hz = scanTimes.length > 1 + ? (scanTimes.length - 1) / (scanTimes.at(-1) - scanTimes[0]) + : 0; + const drawn = live.length + (view.accumulate + ? trailScans.reduce((sum, scan) => sum + scan.length, 0) : 0); + let furthest = 0; + for (const p of live) { + const d = Math.hypot(p[0], p[1], p[2]); + if (d > furthest) furthest = d; + } + + setTile('points', drawn.toLocaleString(), view.accumulate ? 'including trail' : 'this scan'); + setTile('scan', (data.count || 0).toLocaleString(), 'after decimation'); + setTile('rate', num(hz, 1), 'measured', ' Hz'); + setTile('range', num(furthest, 1), 'from the sensor', ' m'); + + draw(); + } catch { + statusBadge.textContent = 'no answer'; + statusBadge.dataset.tone = 'warning'; + } finally { + schedule(); + } + } + + /* -- Interaction ------------------------------------------------------- */ + + let dragging = null; + + canvas.addEventListener('pointerdown', (event) => { + dragging = { x: event.clientX, y: event.clientY }; + canvas.setPointerCapture(event.pointerId); + canvas.style.cursor = 'grabbing'; + }); + + canvas.addEventListener('pointermove', (event) => { + if (!dragging) return; + view.yaw += (event.clientX - dragging.x) * 0.007; + // Clamped just short of straight down so the view never flips over. + view.pitch = Math.max(-1.5, Math.min(1.5, view.pitch + (event.clientY - dragging.y) * 0.007)); + dragging = { x: event.clientX, y: event.clientY }; + draw(); + }); + + for (const type of ['pointerup', 'pointercancel']) { + canvas.addEventListener(type, () => { dragging = null; canvas.style.cursor = 'grab'; }); + } + + canvas.addEventListener('wheel', (event) => { + event.preventDefault(); + view.distance = Math.max(1.5, Math.min(60, view.distance * (1 + Math.sign(event.deltaY) * 0.12))); + draw(); + }, { passive: false }); + + /* -- Rendering --------------------------------------------------------- */ + + const context = canvas.getContext('2d'); + + // Robot frame is X forward, Y left, Z up. Screen is X right, Y down. The + // camera orbits the origin looking at it. + function project(x, y, z, cam) { + // World -> camera: yaw about Z, then pitch. + const cy = Math.cos(cam.yaw), sy = Math.sin(cam.yaw); + const rx = x * cy - y * sy; + const ry = x * sy + y * cy; + + const cp = Math.cos(cam.pitch), sp = Math.sin(cam.pitch); + const depth = ry * cp + z * sp + cam.distance; + const up = -ry * sp + z * cp; + + // Behind the camera - drop it rather than projecting it to a mirrored + // point somewhere silly on screen. + if (depth <= 0.05) return null; + + const scale = cam.focal / depth; + return { sx: cam.cx + rx * scale, sy: cam.cy - up * scale, depth }; + } + + function draw() { + const width = canvas.width; + const height = canvas.height; + const styles = getComputedStyle(document.documentElement); + const surface = styles.getPropertyValue('--surface-2').trim() || '#1b1e22'; + const gridColor = styles.getPropertyValue('--grid').trim() || '#22262c'; + const axisColor = styles.getPropertyValue('--axis').trim() || '#333941'; + const muted = styles.getPropertyValue('--text-3').trim() || '#6d7681'; + + context.fillStyle = surface; + context.fillRect(0, 0, width, height); + + const cam = { + yaw: view.yaw, pitch: view.pitch, distance: view.distance, + focal: height * 0.9, cx: width / 2, cy: height / 2, + }; + + // Ground grid, 1 m squares, so distances are readable at a glance. + const half = 10; + context.lineWidth = 1; + for (let i = -half; i <= half; i += 1) { + for (const [a, b] of [[[i, -half], [i, half]], [[-half, i], [half, i]]]) { + const p1 = project(a[0], a[1], 0, cam); + const p2 = project(b[0], b[1], 0, cam); + if (!p1 || !p2) continue; + context.strokeStyle = i === 0 ? axisColor : gridColor; + context.beginPath(); + context.moveTo(p1.sx, p1.sy); + context.lineTo(p2.sx, p2.sy); + context.stroke(); + } + } + + if (!active) { + context.fillStyle = muted; + context.font = '16px system-ui, sans-serif'; + context.textAlign = 'center'; + context.fillText('LiDAR is off — switch it on to see the point cloud', + width / 2, height / 2); + return; + } + + if (!live.length) { + context.fillStyle = muted; + context.font = '15px system-ui, sans-serif'; + context.textAlign = 'center'; + context.fillText('Waiting for the first scan…', width / 2, height / 2); + return; + } + + // Older scans first so the newest sits on top. + const batches = view.accumulate + ? [...trailScans.map((scan, i) => ({ scan, fade: 0.25 + 0.45 * (i / MAX_TRAIL) })), + { scan: live, fade: 1 }] + : [{ scan: live, fade: 1 }]; + + for (const { scan, fade } of batches) { + for (const point of scan) { + const projected = project(point[0], point[1], point[2], cam); + if (!projected) continue; + if (projected.sx < 0 || projected.sx > width + || projected.sy < 0 || projected.sy > height) continue; + + context.fillStyle = colourFor(point, projected.depth, fade); + // Nearer points draw larger - the only depth cue a flat point cloud + // has once perspective alone stops being obvious. + const size = Math.max(1, Math.min(3.5, 9 / projected.depth)); + context.fillRect(projected.sx, projected.sy, size, size); + } + } + + // Sensor origin, so "where is the robot" is never in doubt. + const origin = project(0, 0, 0, cam); + if (origin) { + context.strokeStyle = styles.getPropertyValue('--series-2').trim() || '#d95926'; + context.lineWidth = 2; + context.beginPath(); + context.arc(origin.sx, origin.sy, 6, 0, Math.PI * 2); + context.stroke(); + } + + context.fillStyle = muted; + context.font = '11px system-ui, sans-serif'; + context.textAlign = 'left'; + context.fillText('1 m grid · X forward, Y left, Z up', 12, height - 12); + } + + function colourFor(point, depth, fade) { + let t; + if (view.colourBy === 'height') { + t = (point[2] + 1.5) / 4.0; // -1.5 m .. 2.5 m + } else if (view.colourBy === 'intensity') { + t = (point[3] || 0) / 150; + } else { + t = Math.hypot(point[0], point[1], point[2]) / 15; + } + t = Math.max(0, Math.min(1, t)); + + // Blue -> cyan -> green -> yellow -> red. Enough steps that a wall at a + // constant height reads as one colour rather than a gradient. + const stops = [[59, 130, 246], [34, 211, 238], [74, 222, 128], + [250, 204, 21], [239, 68, 68]]; + const scaled = t * (stops.length - 1); + const index = Math.min(stops.length - 2, Math.floor(scaled)); + const frac = scaled - index; + const a = stops[index], b = stops[index + 1]; + const r = Math.round(a[0] + (b[0] - a[0]) * frac); + const g = Math.round(a[1] + (b[1] - a[1]) * frac); + const bl = Math.round(a[2] + (b[2] - a[2]) * frac); + return `rgba(${r},${g},${bl},${fade})`; + } + + /* -- Follow the robot's own state -------------------------------------- */ + + function applyStreams(streams) { + if (!streams || busy) return; + const on = !!streams[key]?.active; + if (on === active) return; + active = on; + powerBox.checked = on; + powerLabel.textContent = on ? 'On' : 'Off'; + if (on) { + schedule(); + } else { + if (timer) clearTimeout(timer); + timer = null; + live = []; + trailScans.length = 0; + statusBadge.textContent = 'off'; + statusBadge.dataset.tone = 'default'; + draw(); + } + } + + applyStreams(store.state?.custom?.streams); + const unsubscribe = store.on('state', () => applyStreams(store.state?.custom?.streams)); + + draw(); + + return { + node: root, + dispose: () => { + unsubscribe(); + if (timer) clearTimeout(timer); + // Never leave the sensor streaming into a page that has gone away. + if (active) post(`/api/streams/${key}`, { active: false }).catch(() => {}); + }, + }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/model.js b/x2_dashboard/web/js/tabs/model.js new file mode 100644 index 0000000..618eaa1 --- /dev/null +++ b/x2_dashboard/web/js/tabs/model.js @@ -0,0 +1,443 @@ +/* Digital twin - the real X2 model, posed and shaded by live telemetry. + + The robot already reports all 31 revolute joint positions and efforts at + 100 Hz, and the dashboard already streams them. This tab draws them, which + turns a table of numbers into something you can check against the machine in + front of you: an arm folded in the picture but straight in the room means the + encoder, the model, or your idea of which robot you are connected to is wrong. + + ON LOAD, AND WHY IT IS NOT TEMPERATURE + -------------------------------------- + This robot does not publish joint temperature. aimdk_msgs/JointState carries + name, position, velocity, effort and error_code and nothing else; the + GetAllJointState service returns the same type; /diagnostics is the Orbbec + camera's own internals; and across all 53 aimdk_msgs types the only + temperature fields are pmu_temperature and battery_temperature. The + norealtime DCU joint topics may carry more, but their message type is not + installed anywhere on the robot, so nothing here can deserialise them. + + So this shades by *effort*, which is honest and nearly as useful: motor + heating is I squared R, and current tracks torque, so the joint pulling + hardest is the joint getting hottest. Every number on screen is measured. + + Load is shown as a percentage of each joint's RATED torque, taken from the + URDF's and baked into model.json. That matters: rated + torque here runs from 0.6 Nm to 120 Nm, so an absolute Nm ramp would paint + every wrist permanently cold and every leg permanently hot regardless of what + the robot was doing. + + Geometry is baked offline by build_model.py - 112 MB of vendor STL down to + 1.4 MB. Nothing here parses a URDF at runtime. +*/ + +import { store, num } from '../core.js'; +import { el, card, pageHead, button, badge, note, toggle, segmented, stat, emptyState } from '../ui.js'; +import { RobotModel } from '../model3d.js'; + +const POSES = { + zero: {}, + stand: { + left_hip_pitch_joint: -0.30, right_hip_pitch_joint: -0.30, + left_knee_joint: 0.62, right_knee_joint: 0.62, + left_ankle_pitch_joint: -0.32, right_ankle_pitch_joint: -0.32, + left_shoulder_roll_joint: -0.10, right_shoulder_roll_joint: 0.10, + left_elbow_joint: -0.30, right_elbow_joint: -0.30, + }, + crouch: { + left_hip_pitch_joint: -1.20, right_hip_pitch_joint: -1.20, + left_knee_joint: 2.00, right_knee_joint: 2.00, + left_ankle_pitch_joint: -0.85, right_ankle_pitch_joint: -0.85, + waist_pitch_joint: 0.25, + left_elbow_joint: -0.60, right_elbow_joint: -0.60, + }, + tpose: { left_shoulder_roll_joint: -1.57, right_shoulder_roll_joint: 1.57 }, + wave: { + right_shoulder_pitch_joint: -0.4, right_shoulder_roll_joint: 1.30, + right_elbow_joint: -1.30, right_wrist_pitch_joint: 0.3, + left_shoulder_roll_joint: -0.10, + }, +}; + +// Cool grey through blue, green, amber, red. Grey rather than deep blue at the +// bottom so an idle joint reads as "nothing happening" instead of "measured +// zero", which matters when half the robot is parked. +const LOAD_RAMP = [ + [0.42, 0.46, 0.52], + [0.23, 0.51, 0.87], + [0.29, 0.76, 0.55], + [0.95, 0.75, 0.16], + [0.90, 0.28, 0.20], +]; + +function rampColour(t) { + const clamped = Math.max(0, Math.min(1, t)); + const scaled = clamped * (LOAD_RAMP.length - 1); + const index = Math.min(LOAD_RAMP.length - 2, Math.floor(scaled)); + const frac = scaled - index; + const a = LOAD_RAMP[index], b = LOAD_RAMP[index + 1]; + return [a[0] + (b[0] - a[0]) * frac, + a[1] + (b[1] - a[1]) * frac, + a[2] + (b[2] - a[2]) * frac]; +} + +function css(colour) { + return `rgb(${colour.map((c) => Math.round(c * 255)).join(',')})`; +} + +export default { + id: 'model', + label: 'Twin', + icon: 'motion', + + async render() { + const root = el('div.stack'); + + const statusBadge = badge('loading…'); + const canvas = el('canvas', { + style: { width: '100%', height: '520px', display: 'block', cursor: 'grab', + borderRadius: 'var(--radius-sm)', touchAction: 'none' }, + }); + + const camera = { yaw: -0.9, pitch: 0.18, distance: 3.0, target: [0, 0, 0.75], fov: 0.75 }; + + let robot = null; + let source = 'live'; + let shading = 'load'; // 'load' | 'plain' + let spinning = false; + let frame = null; + let disposed = false; + const manual = {}; + + // joint name -> {link, rated}. Built once the model is loaded: shading + // paints links, but telemetry is per joint, and the link a joint drives is + // its child in the URDF tree. + const jointMeta = new Map(); + + root.appendChild(pageHead( + 'Digital twin', + 'The real X2 model, posed by live joint telemetry and shaded by how hard each ' + + 'joint is working. Drag to orbit, scroll to zoom.', + [ + segmented( + [{ value: 'load', label: 'Load' }, { value: 'plain', label: 'Plain' }], + shading, + (value) => { shading = value; legend.style.display = value === 'load' ? '' : 'none'; }, + ), + segmented( + [{ value: 'live', label: 'Follow robot' }, { value: 'pose', label: 'Poses' }], + source, + (value) => { + source = value; + poseRow.style.display = value === 'pose' ? '' : 'none'; + statusBadge.textContent = value === 'live' ? 'following robot' : 'manual pose'; + statusBadge.dataset.tone = value === 'live' ? 'good' : 'accent'; + }, + ), + statusBadge, + ], + )); + + /* -- Load tiles -------------------------------------------------------- */ + + const tiles = el('div.grid.cols-4'); + const refs = {}; + for (const [key, label] of [ + ['peak', 'Highest load'], + ['total', 'Total torque'], + ['busy', 'Joints under load'], + ['faults', 'Joints reporting error'], + ]) { + // sub: ' ' rather than '' so the .stat-sub element always exists and + // setTile can write into it. Same pattern as the Navigation tab. + const node = stat(label, '—', { sub: ' ' }); + refs[key] = node; + tiles.appendChild(node); + } + root.appendChild(tiles); + + function setTile(key, value, sub, tone = 'default', unit = '') { + const node = refs[key]; + if (!node) return; + node.dataset.tone = tone; + const valueNode = node.querySelector('.stat-value'); + valueNode.textContent = String(value); + if (unit) valueNode.appendChild(el('span.unit', { text: unit })); + node.querySelector('.stat-sub').textContent = sub || ''; + } + + /* -- Legend and hardest-working list ----------------------------------- */ + + const legend = el('div.row', { + style: { gap: '10px', alignItems: 'center', flexWrap: 'wrap' }, + }, + el('span', { text: 'Load', style: { fontSize: '11.5px', color: 'var(--text-3)' } }), + (() => { + const bar = el('div', { + style: { + height: '10px', width: '190px', borderRadius: '5px', + border: '1px solid var(--border)', + background: `linear-gradient(90deg, ${LOAD_RAMP.map(css).join(',')})`, + }, + }); + return bar; + })(), + el('span', { text: '0 % → 100 % of rated torque', + style: { fontSize: '11.5px', color: 'var(--text-3)' } }), + ); + + const poseRow = el('div.row', { style: { gap: '8px', flexWrap: 'wrap', display: 'none' } }, + ...Object.keys(POSES).map((name) => button( + name === 'tpose' ? 'T-pose' : name[0].toUpperCase() + name.slice(1), + () => applyPose(name), + { size: 'sm' }, + )), + ); + + const hardest = el('div.stack', { style: { gap: '5px' } }); + + root.appendChild(card('X2 Ultra', { + sub: '41 links · 31 revolute joints · baked from x2_ultra.urdf', + actions: [ + toggle('Spin', false, (on) => { spinning = on; }), + button('Reset view', () => { + camera.yaw = -0.9; camera.pitch = 0.18; camera.distance = 3.0; + camera.target = [0, 0, 0.75]; + }, { size: 'sm', style: 'ghost' }), + ], + flush: true, + foot: el('div.stack', { style: { gap: '10px' } }, legend, poseRow), + }, canvas)); + + root.appendChild(card('Working hardest', { + sub: 'Measured torque against each joint’s rated limit, highest first', + }, hardest)); + + root.appendChild(note( + 'This robot does not report joint temperature — aimdk_msgs/JointState carries only ' + + 'position, velocity, effort and an error code, and no service or topic on the unit ' + + 'exposes motor temperature. Colour here is measured torque as a share of each joint’s ' + + 'rated limit, which is the closest honest indicator of which joints are heating: motor ' + + 'heating rises with current, and current tracks torque.', + 'info', + )); + + /* -- Boot -------------------------------------------------------------- */ + + try { + robot = new RobotModel(canvas); + } catch (err) { + root.replaceChildren(pageHead('Digital twin', 'The 3D view could not start.'), + emptyState('WebGL unavailable', err.message)); + return { node: root }; + } + + try { + const [modelRes, geometryRes] = await Promise.all([ + fetch('/model/model.json', { cache: 'force-cache' }), + fetch('/model/model.bin', { cache: 'force-cache' }), + ]); + if (!modelRes.ok || !geometryRes.ok) { + throw new Error('The baked model is not on the server (web/model/).'); + } + const model = await modelRes.json(); + const geometry = await geometryRes.arrayBuffer(); + robot.load(model, geometry); + + for (const joint of model.joints) { + if (joint.type !== 'revolute') continue; + jointMeta.set(joint.name, { + link: joint.child, + // Fall back to a mid-range rating rather than 0 - dividing by zero + // would paint an unrated joint permanently red. + rated: joint.effort && joint.effort > 0 ? joint.effort : 40, + }); + } + + statusBadge.textContent = 'following robot'; + statusBadge.dataset.tone = 'good'; + } catch (err) { + robot.dispose(); + root.replaceChildren( + pageHead('Digital twin', 'The 3D model could not be loaded.'), + emptyState('Model missing', err.message), + ); + return { node: root }; + } + + /* -- Interaction -------------------------------------------------------- */ + + let dragging = null; + + canvas.addEventListener('pointerdown', (event) => { + dragging = { x: event.clientX, y: event.clientY }; + canvas.setPointerCapture(event.pointerId); + canvas.style.cursor = 'grabbing'; + }); + + canvas.addEventListener('pointermove', (event) => { + if (!dragging) return; + camera.yaw -= (event.clientX - dragging.x) * 0.008; + camera.pitch = Math.max(-1.35, Math.min(1.35, + camera.pitch + (event.clientY - dragging.y) * 0.008)); + dragging = { x: event.clientX, y: event.clientY }; + }); + + for (const type of ['pointerup', 'pointercancel']) { + canvas.addEventListener(type, () => { dragging = null; canvas.style.cursor = 'grab'; }); + } + + canvas.addEventListener('wheel', (event) => { + event.preventDefault(); + camera.distance = Math.max(0.8, Math.min(12, + camera.distance * (1 + Math.sign(event.deltaY) * 0.1))); + }, { passive: false }); + + function applyPose(name) { + source = 'pose'; + poseRow.style.display = ''; + statusBadge.textContent = 'manual pose'; + statusBadge.dataset.tone = 'accent'; + for (const key of robot.jointAngles.keys()) manual[key] = 0; + Object.assign(manual, POSES[name] || {}); + } + + /* -- Live telemetry ------------------------------------------------------ */ + + function readJoints() { + const groups = store.state?.joints || {}; + const rows = []; + for (const list of Object.values(groups)) { + if (!Array.isArray(list)) continue; + for (const joint of list) { + if (joint && typeof joint.position === 'number') rows.push(joint); + } + } + return rows; + } + + /* -- Frame loop ---------------------------------------------------------- */ + + const styles = getComputedStyle(document.documentElement); + + function background() { + const raw = (styles.getPropertyValue('--surface-2') || '').trim(); + const match = /^#?([0-9a-f]{6})$/i.exec(raw); + if (!match) return [0.09, 0.10, 0.12]; + const value = parseInt(match[1], 16); + return [((value >> 16) & 255) / 255, ((value >> 8) & 255) / 255, (value & 255) / 255]; + } + + let lastPanel = 0; + + function loop() { + if (disposed) return; + frame = requestAnimationFrame(loop); + + if (spinning && !dragging) camera.yaw += 0.004; + + const rows = source === 'live' ? readJoints() : []; + const angles = {}; + if (source === 'live') { + for (const joint of rows) angles[joint.name] = joint.position; + } else { + Object.assign(angles, manual); + } + robot.setJoints(angles); + + // Shading. In pose mode there is no live torque to show, so the model + // stays neutral rather than freezing the last real reading onto a pose + // the robot is not actually holding. + robot.linkColours.clear(); + let loads = []; + if (shading === 'load' && source === 'live') { + for (const joint of rows) { + const meta = jointMeta.get(joint.name); + if (!meta) continue; + const effort = Math.abs(joint.effort || 0); + const share = effort / meta.rated; + robot.linkColours.set(meta.link, rampColour(share)); + loads.push({ name: joint.name, effort, share, rated: meta.rated, + error: joint.error || 0 }); + } + } + + robot.render(camera, background()); + + const now = Date.now(); + if (now - lastPanel > 300) { + lastPanel = now; + paintPanels(loads); + } + } + + function paintPanels(loads) { + if (!loads.length) { + const why = source === 'live' ? 'Waiting for joint telemetry…' + : 'Manual pose — no live torque to show.'; + hardest.replaceChildren(el('div', { + text: why, style: { fontSize: '12.5px', color: 'var(--text-3)' }, + })); + for (const key of ['peak', 'total', 'busy', 'faults']) setTile(key, '—', ''); + return; + } + + loads.sort((a, b) => b.share - a.share); + const peak = loads[0]; + const total = loads.reduce((sum, l) => sum + l.effort, 0); + const busy = loads.filter((l) => l.share >= 0.25).length; + const faults = loads.filter((l) => l.error).length; + + setTile('peak', num(peak.share * 100, 0), + `${peak.name.replace(/_joint$/, '').replace(/_/g, ' ')} · ${num(peak.effort, 1)} Nm`, + peak.share > 0.8 ? 'critical' : peak.share > 0.5 ? 'warning' : 'good', ' %'); + setTile('total', num(total, 0), 'sum across 31 joints', 'default', ' Nm'); + setTile('busy', busy, 'above 25 % of rated', + busy > 6 ? 'warning' : 'default'); + setTile('faults', faults, faults ? 'check the Motion tab' : 'all clear', + faults ? 'critical' : 'good'); + + hardest.replaceChildren(...loads.slice(0, 6).map((l) => el('div.row', { + style: { gap: '10px', alignItems: 'center' }, + }, + el('span', { + text: l.name.replace(/_joint$/, '').replace(/_/g, ' '), + style: { fontSize: '12px', width: '170px', flexShrink: '0' }, + }), + el('div', { + style: { + flex: '1', height: '8px', borderRadius: '4px', + background: 'var(--surface-2)', overflow: 'hidden', minWidth: '60px', + }, + }, + el('div', { + style: { + width: `${Math.max(2, Math.min(100, l.share * 100))}%`, height: '100%', + background: css(rampColour(l.share)), transition: 'width .25s', + }, + }), + ), + el('span', { + text: `${num(l.effort, 1)} / ${num(l.rated, 0)} Nm`, + style: { fontSize: '11px', fontFamily: 'var(--mono)', color: 'var(--text-3)', + width: '110px', textAlign: 'right', flexShrink: '0' }, + }), + el('span', { + text: `${num(l.share * 100, 0)}%`, + style: { fontSize: '11.5px', fontWeight: '600', width: '42px', + textAlign: 'right', flexShrink: '0', color: css(rampColour(l.share)) }, + }), + ))); + } + + loop(); + + return { + node: root, + dispose: () => { + disposed = true; + if (frame) cancelAnimationFrame(frame); + robot.dispose(); + }, + }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/motion.js b/x2_dashboard/web/js/tabs/motion.js new file mode 100644 index 0000000..7fb11cc --- /dev/null +++ b/x2_dashboard/web/js/tabs/motion.js @@ -0,0 +1,321 @@ +/* Motion - joint-level control and end effectors. */ + +import { + store, command, num, RAD2DEG, DEG2RAD, +} from '../core.js'; +import { + el, card, pageHead, button, note, segmented, range, table, badge, emptyState, +} from '../ui.js'; +import { bars } from '../charts.js'; + +export default { + id: 'motion', + label: 'Motion', + icon: 'motion', + + async render() { + const spec = store.spec; + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Motion', + 'Drive joints and end effectors directly. Limits shown are the published X2 ' + + 'Ultra ranges; the server clamps anything outside them before publishing.', + )); + + /* ================================================================== + Joint control + ================================================================== */ + + const groups = spec?.joint_groups || []; + let activeGroup = groups[0]?.key || 'arm'; + let controlMode = 'position'; + + const sliders = new Map(); // joint name -> range control + const targets = new Map(); // joint name -> radians + const editorHost = el('div'); + const stateHost = el('div'); + + const stiffness = range({ min: 0, max: 200, step: 1, value: 60, precision: 0, unit: ' N·m/rad' }); + const damping = range({ min: 0, max: 20, step: 0.5, value: 3, precision: 1, unit: ' N·m·s/rad' }); + + function buildEditor() { + const group = groups.find((g) => g.key === activeGroup); + if (!group) { editorHost.replaceChildren(emptyState('Unknown joint group')); return; } + + sliders.clear(); + const rows = el('div.stack', { style: { gap: '10px' } }); + + for (const joint of group.joints) { + const fixed = joint.min_deg === joint.max_deg; + const current = targets.get(joint.name) ?? 0; + + const control = range({ + min: joint.min_deg, max: joint.max_deg, + step: fixed ? 1 : 0.5, + value: current * RAD2DEG, + precision: 1, unit: '°', + onInput: (deg) => targets.set(joint.name, deg * DEG2RAD), + }); + if (fixed) { + control.querySelector('input').disabled = true; + control.style.opacity = '.5'; + } + sliders.set(joint.name, control); + + rows.appendChild(el('div', {}, + el('div.row.between', { style: { marginBottom: '3px' } }, + el('span', { text: joint.label, style: { fontSize: '12px', fontWeight: '550' } }), + el('span', { + text: fixed ? 'fixed' : `${joint.min_deg}° … ${joint.max_deg}°`, + style: { fontSize: '10.5px', color: 'var(--text-3)', fontFamily: 'var(--mono)' }, + }), + ), + control, + )); + } + + editorHost.replaceChildren(rows); + } + + async function sendTargets() { + const group = groups.find((g) => g.key === activeGroup); + if (!group) return; + const payload = {}; + for (const joint of group.joints) { + if (joint.min_deg === joint.max_deg) continue; + payload[joint.name] = targets.get(joint.name) ?? 0; + } + await command('/api/joints', { + group: activeGroup, + mode: controlMode, + targets: payload, + stiffness: stiffness.getValue(), + damping: damping.getValue(), + }, { successTitle: `${group.label} command sent` }); + } + + function zeroTargets() { + const group = groups.find((g) => g.key === activeGroup); + for (const joint of group?.joints || []) { + targets.set(joint.name, 0); + sliders.get(joint.name)?.setValue(0); + } + } + + function syncFromRobot() { + const live = store.state?.joints?.[activeGroup] || []; + for (const joint of live) { + targets.set(joint.name, joint.position); + sliders.get(joint.name)?.setValue(joint.position * RAD2DEG); + } + } + + const groupTabs = segmented( + groups.map((g) => ({ value: g.key, label: g.label })), + activeGroup, + (value) => { activeGroup = value; buildEditor(); paintState(); }, + ); + + const modeTabs = segmented( + (spec?.joint_modes || []).map((m) => ({ value: m.id, label: m.label })), + controlMode, + (value) => { controlMode = value; }, + ); + + buildEditor(); + + root.appendChild(el('div.grid.pair', {}, + card('Joint targets', { sub: 'JointCommandArray', actions: [groupTabs] }, + el('div.stack', {}, + el('div.row.between', {}, + el('span', { text: 'Control mode', style: { fontSize: '12px', color: 'var(--text-2)' } }), + modeTabs, + ), + editorHost, + el('div.grid.cols-2', { style: { gap: '10px' } }, + el('div', {}, + el('div', { text: 'Stiffness', style: { fontSize: '12px', color: 'var(--text-2)', marginBottom: '4px' } }), + stiffness, + ), + el('div', {}, + el('div', { text: 'Damping', style: { fontSize: '12px', color: 'var(--text-2)', marginBottom: '4px' } }), + damping, + ), + ), + el('div.row', {}, + button('Send targets', sendTargets, { style: 'primary' }), + button('Sync from robot', syncFromRobot), + button('Zero all', zeroTargets, { style: 'ghost' }), + ), + note('Head pitch has a published range of 0° on the X2 Ultra — the axis exists in the ' + + 'message but is not articulated, so its slider is disabled.', 'info'), + ), + ), + card('Measured joint state', { sub: 'JointStateArray' }, stateHost), + )); + + /* ================================================================== + End effectors + ================================================================== */ + + let handSide = 'right'; + const handSliders = []; + const handHost = el('div'); + const handStateHost = el('div'); + + function buildHand() { + const joints = spec?.dexhand_joints || []; + handSliders.length = 0; + const rows = el('div.stack', { style: { gap: '8px' } }); + + joints.forEach((name, index) => { + const control = range({ min: 0, max: 1.6, step: 0.02, value: 0, precision: 2, unit: ' rad' }); + handSliders.push(control); + rows.appendChild(el('div', {}, + el('div', { text: name, style: { fontSize: '11.5px', color: 'var(--text-2)', marginBottom: '2px' } }), + control, + )); + }); + + handHost.replaceChildren(rows); + } + + async function sendHand() { + await command('/api/hand', { + side: handSide, + positions: handSliders.map((s) => s.getValue()), + }, { successTitle: `${handSide} hand` }); + } + + async function applyHandPreset(preset) { + preset.positions.forEach((value, index) => handSliders[index]?.setValue(value)); + await command('/api/hand', { side: handSide, preset: preset.key }, + { successTitle: `${preset.label} · ${handSide}` }); + } + + buildHand(); + + const handSendBtn = button('Send hand pose', sendHand, { style: 'primary' }); + + const presetRow = el('div.row.tight', {}, + ...(spec?.hand_presets || []).map((preset) => + button(preset.label, () => applyHandPreset(preset), { size: 'sm' })), + ); + + const sideTabs = segmented( + [{ value: 'left', label: 'Left' }, { value: 'right', label: 'Right' }], + handSide, + (value) => { handSide = value; paintState(); }, + ); + + root.appendChild(el('div.grid.pair', {}, + card('Dexterous hand', { sub: 'HandCommandArray · OmniHand', actions: [sideTabs] }, + el('div.stack', {}, + presetRow, + handHost, + handSendBtn, + note('Disable native motor control first — run "aima em stop-app mc" on the robot — or the ' + + 'built-in controller and these commands will fight each other.', 'warning', '⚠'), + ), + ), + card('Hand state', { sub: 'HandStateArray' }, handStateHost), + )); + + /* ================================================================== + Live state + ================================================================== */ + + function paintState() { + const s = store.state; + if (!s) return; + + const group = groups.find((g) => g.key === activeGroup); + const live = s.joints?.[activeGroup] || []; + const limits = Object.fromEntries((group?.joints || []).map((j) => [j.name, j])); + + if (!live.length) { + stateHost.replaceChildren(emptyState( + 'No joint state yet', + `Nothing has been received on ${group?.state_topic || 'the joint state topic'}.`, + )); + } else { + const rows = live.map((joint) => { + const limit = limits[joint.name] || { min_deg: -180, max_deg: 180 }; + const deg = joint.position * RAD2DEG; + const range_ = (limit.max_deg - limit.min_deg) || 1; + const headroom = Math.min(deg - limit.min_deg, limit.max_deg - deg) / range_; + return { + label: joint.label || joint.name, + value: deg, + min: limit.min_deg, + max: limit.max_deg, + colorIndex: 0, + tone: joint.error ? 'critical' : headroom < 0.03 ? 'warning' : 'default', + }; + }); + + stateHost.replaceChildren( + bars(rows, { precision: 1, unit: '°' }), + el('div', { style: { marginTop: '14px' } }, + table([ + { key: 'name', label: 'Joint', get: (r) => r.label || r.name }, + { key: 'pos', label: 'Position', align: 'right', get: (r) => `${num(r.position * RAD2DEG, 1)}°` }, + { key: 'vel', label: 'Velocity', align: 'right', get: (r) => num(r.velocity, 3) }, + { key: 'eff', label: 'Effort', align: 'right', get: (r) => num(r.effort, 2) }, + { + key: 'err', label: 'Fault', + get: (r) => (r.error ? badge(`code ${r.error}`, 'critical') : badge('ok', 'good')), + }, + ], live), + ), + ); + } + + const hand = s.hand_state?.[handSide] || []; + const attached = (s.hand_type || 'None') !== 'None'; + + handStateHost.replaceChildren( + el('div.row', { style: { marginBottom: '10px' } }, + badge(s.hand_type || 'unknown', attached ? 'accent' : 'warning'), + badge(`${hand.length} joints reported`), + ), + hand.length + ? bars(hand.map((joint) => ({ + label: joint.name, value: joint.position, min: 0, max: 1.6, colorIndex: 2, + })), { precision: 2, unit: ' rad', diverging: false }) + : emptyState( + attached ? 'No hand state yet' : 'No hand hardware attached', + attached + ? 'Nothing received on /aima/hal/joint/hand/state.' + : 'GetHandType reports NONE for both sides on this robot, and the state message ' + + 'carries no joints. Attach an OmniHand or OmniPicker to use this panel.', + ), + ); + + // Sending hand commands with no hand attached would silently do nothing. + for (const control of handSliders) { + control.querySelector('input').disabled = !attached; + } + handSendBtn.disabled = !attached; + for (const btn of presetRow.children) btn.disabled = !attached; + } + + paintState(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 600) return; + last = now; + paintState(); + }); + + return { + node: root, + dispose: () => { + unsubscribe(); + }, + }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/navigation.js b/x2_dashboard/web/js/tabs/navigation.js new file mode 100644 index 0000000..a701502 --- /dev/null +++ b/x2_dashboard/web/js/tabs/navigation.js @@ -0,0 +1,276 @@ +/* Navigation - odometry, heading and travelled path. + + This firmware does not expose the documented SLAM command interface + (/integrated_command, /relocalization_pose, GetStoredMapByName are all absent + from the live graph), so no mapping controls are offered - a button that + silently does nothing is worse than no button. What the robot does publish is + leg odometry, and that is what this tab shows. +*/ + +import { store, num, RAD2DEG } from '../core.js'; +import { el, card, pageHead, button, note, badge, stat, kv, emptyState } from '../ui.js'; +import { compass, attitude } from '../charts.js'; + +export default { + id: 'navigation', + label: 'Navigation', + icon: 'nav', + + async render() { + const root = el('div.stack'); + const trail = []; + let following = true; + + root.appendChild(pageHead( + 'Navigation', + 'Where the robot has been, from leg odometry. Values advance while it walks and hold ' + + 'steady when it is parked.', + [ + button('Clear path', () => { trail.length = 0; drawTrail(); }, { size: 'sm', style: 'ghost' }), + ], + )); + + /* -- Tiles ------------------------------------------------------------ */ + + const tiles = el('div.grid.cols-4'); + const refs = {}; + for (const [key, label] of [ + ['x', 'Position X'], + ['y', 'Position Y'], + ['heading', 'Heading'], + ['speed', 'Ground speed'], + ['distance', 'Distance travelled'], + ['points', 'Path points'], + ['mode', 'Motion mode'], + ['status', 'Odometry'], + ]) { + const node = stat(label, '—', { sub: ' ' }); + refs[key] = node; + tiles.appendChild(node); + } + root.appendChild(tiles); + + function setTile(key, value, sub, tone = 'default', unit = '') { + const node = refs[key]; + if (!node) return; + node.dataset.tone = tone; + const valueNode = node.querySelector('.stat-value'); + valueNode.textContent = String(value); + if (unit) valueNode.appendChild(el('span.unit', { text: unit })); + node.querySelector('.stat-sub').textContent = sub || ''; + } + + /* -- Heading and attitude --------------------------------------------- */ + + const compassHost = el('div.attitude'); + const attitudeHost = el('div.attitude'); + const readoutHost = el('div'); + const trailCanvas = el('canvas', { + width: 960, height: 620, + style: { width: '100%', height: 'auto', display: 'block', borderRadius: 'var(--radius-sm)' }, + }); + + root.appendChild(el('div.grid.split', {}, + card('Heading and attitude', { sub: 'Odometry yaw · chest IMU' }, + el('div.stack', { style: { alignItems: 'center' } }, + el('div.row', { style: { justifyContent: 'center', gap: '14px', flexWrap: 'wrap' } }, + compassHost, attitudeHost, + ), + readoutHost, + ), + ), + card('Travelled path', { + sub: 'Top-down, 1 m grid', + actions: [ + (() => { + const box = el('input', { type: 'checkbox', checked: true }); + box.addEventListener('change', () => { following = box.checked; drawTrail(); }); + return el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: 'Follow robot' })); + })(), + ], + flush: true, + }, trailCanvas), + )); + + root.appendChild(note( + 'SLAM mapping and relocalization are not offered here: this firmware does not advertise the ' + + '/integrated_command topic or the GetStoredMapByName service, so there is nothing for the ' + + 'dashboard to call. Use the AGIBOT mobile app for map building on this unit.', + 'info', + )); + + /* -- Trail rendering --------------------------------------------------- */ + + const context = trailCanvas.getContext('2d'); + + function drawTrail() { + const width = trailCanvas.width; + const height = trailCanvas.height; + const styles = getComputedStyle(document.documentElement); + const surface = styles.getPropertyValue('--surface-2').trim() || '#1b1e22'; + const gridColor = styles.getPropertyValue('--grid').trim() || '#22262c'; + const axis = styles.getPropertyValue('--axis').trim() || '#333941'; + const line = styles.getPropertyValue('--series-1').trim() || '#3987e5'; + const marker = styles.getPropertyValue('--series-2').trim() || '#d95926'; + const muted = styles.getPropertyValue('--text-3').trim() || '#6d7681'; + + context.fillStyle = surface; + context.fillRect(0, 0, width, height); + + if (!trail.length) { + context.fillStyle = muted; + context.font = '15px system-ui, sans-serif'; + context.textAlign = 'center'; + context.fillText('Waiting for odometry — walk the robot to draw a path', + width / 2, height / 2); + return; + } + + const xs = trail.map((p) => p.x); + const ys = trail.map((p) => p.y); + const last = trail.at(-1); + + const spanX = Math.max(2, Math.max(...xs) - Math.min(...xs)); + const spanY = Math.max(2, Math.max(...ys) - Math.min(...ys)); + const pad = 44; + const scale = Math.min((width - pad * 2) / spanX, (height - pad * 2) / spanY, 110); + + const centreX = following ? last.x : (Math.min(...xs) + Math.max(...xs)) / 2; + const centreY = following ? last.y : (Math.min(...ys) + Math.max(...ys)) / 2; + + // Robot X is forward and Y is left; canvas y grows downward, so flip it. + const X = (x) => width / 2 + (x - centreX) * scale; + const Y = (y) => height / 2 - (y - centreY) * scale; + + const step = scale >= 60 ? 1 : scale >= 25 ? 2 : 5; + context.lineWidth = 1; + const firstX = Math.floor(centreX - width / 2 / scale) - 1; + const lastX = Math.ceil(centreX + width / 2 / scale) + 1; + const firstY = Math.floor(centreY - height / 2 / scale) - 1; + const lastY = Math.ceil(centreY + height / 2 / scale) + 1; + + for (let m = Math.ceil(firstX / step) * step; m <= lastX; m += step) { + context.strokeStyle = m === 0 ? axis : gridColor; + context.beginPath(); context.moveTo(X(m), 0); context.lineTo(X(m), height); context.stroke(); + } + for (let m = Math.ceil(firstY / step) * step; m <= lastY; m += step) { + context.strokeStyle = m === 0 ? axis : gridColor; + context.beginPath(); context.moveTo(0, Y(m)); context.lineTo(width, Y(m)); context.stroke(); + } + + // Scale key. + context.fillStyle = muted; + context.font = '11px system-ui, sans-serif'; + context.textAlign = 'left'; + context.fillText(`${step} m grid`, 12, height - 12); + + if (trail.length > 1) { + context.strokeStyle = line; + context.lineWidth = 2; + context.lineJoin = 'round'; + context.lineCap = 'round'; + context.beginPath(); + trail.forEach((point, index) => { + const px = X(point.x), py = Y(point.y); + if (index === 0) context.moveTo(px, py); else context.lineTo(px, py); + }); + context.stroke(); + + // Start marker with a surface ring so it stays legible over the line. + const start = trail[0]; + context.beginPath(); + context.arc(X(start.x), Y(start.y), 5, 0, Math.PI * 2); + context.fillStyle = surface; + context.fill(); + context.strokeStyle = line; + context.lineWidth = 2; + context.stroke(); + } + + // Robot marker, pointing along its heading. + context.save(); + context.translate(X(last.x), Y(last.y)); + context.rotate(-last.yaw); + context.fillStyle = marker; + context.strokeStyle = surface; + context.lineWidth = 2.5; + context.beginPath(); + context.moveTo(14, 0); context.lineTo(-9, 8); context.lineTo(-4, 0); context.lineTo(-9, -8); + context.closePath(); + context.fill(); + context.stroke(); + context.restore(); + } + + /* -- Painting ---------------------------------------------------------- */ + + let distance = 0; + + function paint() { + const s = store.state; + if (!s) return; + + const odom = s.odom || { x: 0, y: 0, yaw: 0 }; + const vel = s.velocity || {}; + const chest = s.imu?.chest || {}; + + const previous = trail.at(-1); + const moved = !previous || Math.hypot(odom.x - previous.x, odom.y - previous.y) > 0.015; + if (moved) { + if (previous) distance += Math.hypot(odom.x - previous.x, odom.y - previous.y); + trail.push({ x: odom.x, y: odom.y, yaw: odom.yaw }); + if (trail.length > 4000) trail.shift(); + } else if (previous) { + previous.yaw = odom.yaw; + } + + const speed = Math.hypot(vel.forward || 0, vel.lateral || 0); + const yawDeg = ((odom.yaw || 0) * RAD2DEG + 360) % 360; + + setTile('x', num(odom.x, 2), 'forward positive', 'default', ' m'); + setTile('y', num(odom.y, 2), 'left positive', 'default', ' m'); + setTile('heading', num(yawDeg, 0), 'counter-clockwise positive', 'default', '°'); + setTile('speed', num(speed, 2), `yaw ${num(vel.angular, 2)} rad/s`, 'default', ' m/s'); + setTile('distance', num(distance, 1), 'since this tab opened', 'default', ' m'); + setTile('points', trail.length, 'samples held'); + + const modeSpec = store.spec?.modes?.find((m) => m.id === s.mode); + setTile('mode', modeSpec?.label || s.mode || '—', modeSpec?.group || '', + modeSpec?.danger ? 'critical' : 'default'); + + const stat = s.topic_stats?.['/aima/mc/leg_odometry']; + const age = stat ? (Date.now() / 1000) - stat.last : null; + const live = age !== null && age < 2; + setTile('status', live ? 'Live' : 'Idle', + live ? `${num(stat.hz, 0)} Hz` : 'no recent messages', + live ? 'good' : 'default'); + + compassHost.replaceChildren(compass(odom.yaw || 0, { size: 150 })); + attitudeHost.replaceChildren(attitude(chest.roll || 0, chest.pitch || 0, { size: 150 })); + + readoutHost.replaceChildren(kv([ + ['Roll', `${num((chest.roll || 0) * RAD2DEG, 2)}°`], + ['Pitch', `${num((chest.pitch || 0) * RAD2DEG, 2)}°`], + ['Yaw (odometry)', `${num(yawDeg, 1)}°`], + ['Forward', `${num(vel.forward, 3)} m/s`], + ['Lateral', `${num(vel.lateral, 3)} m/s`], + ['Yaw rate', `${num(vel.angular, 3)} rad/s`], + ])); + + drawTrail(); + } + + paint(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 250) return; + last = now; + paint(); + }); + + return { node: root, dispose: unsubscribe }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/overview.js b/x2_dashboard/web/js/tabs/overview.js new file mode 100644 index 0000000..4466f4b --- /dev/null +++ b/x2_dashboard/web/js/tabs/overview.js @@ -0,0 +1,222 @@ +/* Overview - the at-a-glance page. One hero figure, supporting tiles, trends. */ + +import { store, get, num, duration, batteryTone, tempTone } from '../core.js'; +import { el, card, stat, meter, note, pageHead, button, kv } from '../ui.js'; +import { timeSeries, sparkline, attitude, compass } from '../charts.js'; + +export default { + id: 'overview', + label: 'Overview', + icon: 'overview', + + async render() { + const root = el('div.stack'); + + /* -- Hero ------------------------------------------------------------- */ + + const heroNumber = el('span', { text: '—' }); + const heroValue = el('div.hero', {}, heroNumber, el('span.unit', { text: '%' })); + const meterHost = el('div'); + const heroSub = el('div.stat-sub', { text: 'Battery remaining' }); + const heroSpark = el('div', { style: { marginTop: '8px', height: '40px' } }); + + /* -- Tiles ------------------------------------------------------------ */ + + const tiles = el('div.grid.cols-3'); + const tileRefs = {}; + for (const [key, label] of [ + ['mode', 'Motion mode'], + ['transport', 'Link'], + ['uptime', 'Bridge uptime'], + ['speed', 'Ground speed'], + ['heading', 'Heading'], + ['temp', 'Battery temp'], + ]) { + const node = stat(label, '—', { sub: ' ' }); + tileRefs[key] = node; + tiles.appendChild(node); + } + + function setTile(key, value, sub, tone = 'default', unit = '') { + const node = tileRefs[key]; + if (!node) return; + node.dataset.tone = tone; + const valueNode = node.querySelector('.stat-value'); + valueNode.textContent = String(value); + if (unit) valueNode.appendChild(el('span.unit', { text: unit })); + node.querySelector('.stat-sub').textContent = sub || ''; + } + + /* -- Attitude --------------------------------------------------------- */ + + const attitudeHost = el('div.attitude'); + const compassHost = el('div.attitude'); + const attitudeReadout = el('div'); + + /* -- Charts ----------------------------------------------------------- */ + + const velChart = timeSeries([ + { key: 'vel_forward', label: 'Forward', points: [], colorIndex: 0, unit: ' m/s' }, + { key: 'vel_lateral', label: 'Lateral', points: [], colorIndex: 1, unit: ' m/s' }, + { key: 'vel_angular', label: 'Yaw rate', points: [], colorIndex: 2, unit: ' rad/s' }, + ], { height: 176, precision: 2, zeroLine: true }); + + const batteryChart = timeSeries( + [{ key: 'battery_pct', label: 'Battery', points: [], colorIndex: 0, unit: '%' }], + { height: 168, precision: 1 }, + ); + + const tempChart = timeSeries([ + { key: 'battery_temp', label: 'Battery', points: [], colorIndex: 1, unit: ' °C' }, + { key: 'pmu_temp', label: 'PMU', points: [], colorIndex: 3, unit: ' °C' }, + ], { height: 168, precision: 1 }); + + /* -- Assemble --------------------------------------------------------- */ + + root.appendChild(pageHead( + 'Overview', + 'Live condition of the robot. Everything here is read-only — use Control to act.', + [button('Refresh trends', () => refreshCharts(), { iconName: 'refresh', size: 'sm', style: 'ghost' })], + )); + + root.appendChild(el('div.grid.split', {}, + card('Battery', { sub: 'PMU · 0.2 Hz' }, + el('div.stack', { style: { gap: '10px' } }, heroValue, meterHost, heroSub, heroSpark), + ), + tiles, + )); + + root.appendChild(el('div.grid.cols-2', {}, + card('Attitude', { sub: 'Chest IMU' }, + el('div.row', { style: { justifyContent: 'space-around', alignItems: 'center', gap: '16px' } }, + attitudeHost, compassHost, + ), + el('div', { style: { marginTop: '14px' } }, attitudeReadout), + ), + card('Velocity', { sub: 'Measured, last 2 minutes' }, velChart), + )); + + root.appendChild(el('div.grid.cols-2', {}, + card('Battery trend', { sub: 'Last 2 minutes' }, batteryChart), + card('Thermals', { sub: 'Battery cell and PMU' }, tempChart), + )); + + const safety = (store.spec?.safety_notes || []).filter((n) => n.level !== 'info'); + if (safety.length) { + root.appendChild(card('Before you operate', {}, + el('div.stack', { style: { gap: '8px' } }, + ...safety.map((n) => note(n.text, n.level, n.level === 'critical' ? '⚠' : 'ⓘ')), + ), + )); + } + + /* -- Painting --------------------------------------------------------- */ + + let meterNode = meter(0); + meterHost.appendChild(meterNode); + + function paint() { + const s = store.state; + if (!s) return; + + const pct = s.battery_pct; + const tone = batteryTone(pct); + + heroNumber.textContent = pct === null || pct === undefined ? '—' : num(pct, 1); + heroValue.style.color = tone === 'critical' ? 'var(--critical)' + : tone === 'warning' ? 'var(--warning)' : 'var(--text)'; + + const nextMeter = meter((pct || 0) / 100, tone); + meterNode.replaceWith(nextMeter); + meterNode = nextMeter; + + const { battery_voltage: voltage, battery_current: current } = s; + heroSub.textContent = [ + voltage != null ? `${num(voltage, 1)} V` : null, + current != null ? `${num(Math.abs(current), 1)} A ${current > 0 ? 'charging' : 'draw'}` : null, + s.battery_cycles ? `${s.battery_cycles} cycles` : null, + ].filter(Boolean).join(' · ') || 'Battery remaining'; + + const modeSpec = store.spec?.modes?.find((m) => m.id === s.mode); + setTile('mode', modeSpec?.label || s.mode || '—', modeSpec?.desc || '', + s.mode === 'PASSIVE_DEFAULT' ? 'critical' : 'default'); + + const online = s.connection?.online; + const agent = s.custom?.agent; + setTile('transport', + s.connection?.simulated ? 'Simulated' : online ? 'Live' : 'Robot off', + s.connection?.simulated + ? 'No robot attached' + : online + ? `${agent?.hostname || 'agent'} · ROS domain ${s.connection?.ros_domain_id ?? 0}` + : 'Agent unreachable', + online ? (s.connection.simulated ? 'warning' : 'good') : 'critical'); + + setTile('uptime', duration(s.connection?.uptime_s), s.connection?.host || ''); + + const speed = Math.hypot(s.velocity?.forward || 0, s.velocity?.lateral || 0); + setTile('speed', num(speed, 2), 'linear, from odometry', 'default', ' m/s'); + + const yawDeg = ((s.odom?.yaw || 0) * 180 / Math.PI + 360) % 360; + setTile('heading', num(yawDeg, 0), + `x ${num(s.odom?.x, 2)} m · y ${num(s.odom?.y, 2)} m`, 'default', '°'); + + setTile('temp', num(s.battery_temp, 1), 'cell temperature', + tempTone(s.battery_temp, 45, 55), ' °C'); + + const chest = s.imu?.chest || {}; + attitudeHost.replaceChildren(attitude(chest.roll || 0, chest.pitch || 0, { size: 148 })); + compassHost.replaceChildren(compass(s.odom?.yaw || 0, { size: 148 })); + + attitudeReadout.replaceChildren(kv([ + ['Roll', `${num((chest.roll || 0) * 180 / Math.PI, 2)}°`], + ['Pitch', `${num((chest.pitch || 0) * 180 / Math.PI, 2)}°`], + ['Yaw', `${num((chest.yaw || 0) * 180 / Math.PI, 2)}°`], + ['Vertical accel', `${num(chest.accel_z, 2)} m/s²`], + ])); + } + + async function refreshCharts() { + try { + const keys = 'battery_pct,battery_temp,pmu_temp,vel_forward,vel_lateral,vel_angular'; + const data = await get(`/api/series?keys=${keys}&limit=400`); + + batteryChart.update([ + { key: 'battery_pct', label: 'Battery', points: data.battery_pct || [], colorIndex: 0, unit: '%' }, + ]); + tempChart.update([ + { key: 'battery_temp', label: 'Battery', points: data.battery_temp || [], colorIndex: 1, unit: ' °C' }, + { key: 'pmu_temp', label: 'PMU', points: data.pmu_temp || [], colorIndex: 3, unit: ' °C' }, + ]); + velChart.update([ + { key: 'vel_forward', label: 'Forward', points: data.vel_forward || [], colorIndex: 0, unit: ' m/s' }, + { key: 'vel_lateral', label: 'Lateral', points: data.vel_lateral || [], colorIndex: 1, unit: ' m/s' }, + { key: 'vel_angular', label: 'Yaw rate', points: data.vel_angular || [], colorIndex: 2, unit: ' rad/s' }, + ]); + + const history = data.battery_pct || []; + heroSpark.replaceChildren( + history.length > 2 ? sparkline(history, { height: 40, colorIndex: 0 }) : el('span'), + ); + } catch { + // A failed trend refresh is not worth interrupting the operator over - + // the live tiles above are still updating from the WebSocket. + } + } + + paint(); + refreshCharts(); + + // Twice a second reads as live without repainting SVG on every frame. + let lastPaint = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - lastPaint < 500) return; + lastPaint = now; + paint(); + }); + const timer = setInterval(refreshCharts, 3000); + + return { node: root, dispose: () => { unsubscribe(); clearInterval(timer); } }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/power.js b/x2_dashboard/web/js/tabs/power.js new file mode 100644 index 0000000..9d21527 --- /dev/null +++ b/x2_dashboard/web/js/tabs/power.js @@ -0,0 +1,246 @@ +/* Power - battery detail, rails, thermals. */ + +import { store, get, num, batteryTone, tempTone, duration } from '../core.js'; +import { el, card, pageHead, stat, meter, badge, table, note, emptyState, kv } from '../ui.js'; +import { timeSeries, sparkline } from '../charts.js'; + +export default { + id: 'power', + label: 'Power', + icon: 'power', + + async render() { + const spec = store.spec; + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Power', + 'Power management unit telemetry. Published at 0.2 Hz, so these values move slowly by design.', + )); + + /* -- Headline --------------------------------------------------------- */ + + const tiles = el('div.grid.cols-4'); + const refs = {}; + for (const [key, label] of [ + ['level', 'Charge'], + ['voltage', 'Pack voltage'], + ['current', 'Pack current'], + ['cell_temp', 'Cell temp'], + ['pmu_temp', 'PMU temp'], + ['fan', 'Fan'], + ['cycles', 'Cycles'], + ['runtime', 'Est. remaining'], + ]) { + const node = stat(label, '—', { sub: ' ' }); + refs[key] = node; + tiles.appendChild(node); + } + root.appendChild(tiles); + + function setTile(key, value, sub, tone = 'default', unit = '') { + const node = refs[key]; + if (!node) return; + node.dataset.tone = tone; + const valueNode = node.querySelector('.stat-value'); + valueNode.textContent = String(value); + if (unit) valueNode.appendChild(el('span.unit', { text: unit })); + node.querySelector('.stat-sub').textContent = sub || ''; + } + + /* -- Charts ----------------------------------------------------------- */ + + const chargeChart = timeSeries( + [{ key: 'battery_pct', label: 'Charge', points: [], colorIndex: 0, unit: '%' }], + { height: 190, precision: 1, yMin: 0, yMax: 100 }, + ); + + const electricalChart = timeSeries([ + { key: 'battery_voltage', label: 'Voltage', points: [], colorIndex: 0, unit: ' V' }, + ], { height: 190, precision: 2 }); + + const currentChart = timeSeries([ + { key: 'battery_current', label: 'Current', points: [], colorIndex: 1, unit: ' A' }, + ], { height: 190, precision: 2, zeroLine: true }); + + const thermalChart = timeSeries([ + { key: 'battery_temp', label: 'Battery cell', points: [], colorIndex: 1, unit: ' °C' }, + { key: 'pmu_temp', label: 'PMU', points: [], colorIndex: 3, unit: ' °C' }, + { key: 'fan_pct', label: 'Fan duty', points: [], colorIndex: 2, unit: ' %' }, + ], { height: 190, precision: 1 }); + + root.appendChild(el('div.grid.cols-2', {}, + card('State of charge', { sub: 'Last 2 minutes' }, chargeChart), + card('Thermals and cooling', { sub: 'Battery, PMU, fan duty' }, thermalChart), + )); + + root.appendChild(el('div.grid.cols-2', {}, + card('Pack voltage', {}, electricalChart), + card('Pack current', { sub: 'Positive is charging' }, currentChart), + )); + + /* -- Rails ------------------------------------------------------------ */ + + const railHost = el('div'); + root.appendChild(card('Power rails', { sub: 'Per-rail voltage and draw' }, railHost)); + + /* -- Hardware identity ------------------------------------------------ */ + + const infoHost = el('div'); + root.appendChild(card('Battery and PMU hardware', { + sub: 'Reported by the pack itself', + }, infoHost)); + + /* -- Raw -------------------------------------------------------------- */ + + const rawHost = el('div'); + root.appendChild(card('Raw PmuState', { + sub: 'Every field the message carried, unmapped', + }, rawHost)); + + /* -- Painting --------------------------------------------------------- */ + + function paint() { + const s = store.state; + if (!s) return; + + const pct = s.battery_pct; + const tone = batteryTone(pct); + + setTile('level', pct == null ? '—' : num(pct, 1), s.charging ? 'charging' : 'discharging', tone, '%'); + setTile('voltage', num(s.battery_voltage, 2), 'pack terminal', 'default', ' V'); + setTile('current', num(s.battery_current, 2), + s.battery_current > 0 ? 'into pack' : 'out of pack', 'default', ' A'); + setTile('cell_temp', num(s.battery_temp, 1), 'cell', tempTone(s.battery_temp, 45, 55), ' °C'); + setTile('pmu_temp', num(s.pmu_temp, 1), 'controller', tempTone(s.pmu_temp, 60, 75), ' °C'); + setTile('fan', num(s.fan_pct, 0), s.fan_rpm ? `${num(s.fan_rpm, 0)} rpm` : '', 'default', '%'); + setTile('cycles', s.battery_cycles ?? '—', 'charge cycles'); + + // Runtime projection from the observed drain rate. + const runtime = estimateRuntime(pct); + setTile('runtime', runtime.label, runtime.sub, runtime.tone); + + /* Rails */ + const rails = s.rails || {}; + const railRows = (spec?.pmu_rails || []).map((definition) => { + const live = rails[definition.key]; + const voltage = live?.voltage; + const nominal = definition.nominal; + const deviation = voltage != null && nominal ? Math.abs(voltage - nominal) / nominal : null; + const ok = live?.ok !== false && (deviation === null || deviation < 0.12); + + return { + label: definition.label, + nominal: `${num(nominal, 1)} V`, + voltage: voltage == null ? '—' : `${num(voltage, 2)} V`, + current: live?.current == null ? '—' : `${num(live.current, 2)} A`, + power: voltage != null && live?.current != null + ? `${num(voltage * live.current, 1)} W` : '—', + status: live ? badge(ok ? 'nominal' : 'out of range', ok ? 'good' : 'critical') + : badge('no data', 'default'), + }; + }); + + railHost.replaceChildren( + railRows.length + ? table([ + { key: 'label', label: 'Rail' }, + { key: 'nominal', label: 'Nominal', align: 'right' }, + { key: 'voltage', label: 'Measured', align: 'right' }, + { key: 'current', label: 'Current', align: 'right' }, + { key: 'power', label: 'Power', align: 'right' }, + { key: 'status', label: 'Status' }, + ], railRows) + : emptyState('No rail data', 'The PMU message has not been received yet.'), + ); + + /* Hardware identity */ + const info = s.custom?.pmu_info || {}; + const infoPairs = (spec?.pmu_info_fields || []) + .map(([field, label]) => [label, info[field]]) + .filter(([, value]) => value); + infoHost.replaceChildren( + infoPairs.length + ? el('div', { style: { columnWidth: '260px', columnGap: '28px' } }, kv(infoPairs)) + : emptyState('No hardware identity reported', + 'The PMU message has not arrived yet.'), + ); + + /* Raw fields */ + const raw = s.custom?.pmu_raw; + if (raw && Object.keys(raw).length) { + const pairs = Object.entries(raw) + .filter(([, v]) => typeof v !== 'object') + .map(([k, v]) => [k, typeof v === 'number' ? num(v, 3) : String(v)]); + rawHost.replaceChildren(el('div', { style: { columnWidth: '260px', columnGap: '28px' } }, kv(pairs))); + } else { + rawHost.replaceChildren(emptyState( + 'No raw message captured', + store.bridge?.simulated + ? 'The simulator publishes mapped values only; connect a real robot to see the full PmuState.' + : 'Waiting for the first /aima/hal/pmu/state message.', + )); + } + } + + function estimateRuntime(pct) { + const history = seriesCache.battery_pct || []; + if (pct == null || history.length < 20) { + return { label: '—', sub: 'needs more history', tone: 'default' }; + } + const [t0, v0] = history[0]; + const [t1, v1] = history.at(-1); + const elapsed = t1 - t0; + const drop = v0 - v1; + if (elapsed < 10 || drop <= 0.005) { + return { label: '—', sub: 'not discharging', tone: 'default' }; + } + const minutes = (pct / (drop / elapsed)) / 60; + return { + label: duration(minutes * 60), + sub: `at ${num((drop / elapsed) * 3600, 1)} %/h`, + tone: minutes < 15 ? 'critical' : minutes < 40 ? 'warning' : 'good', + }; + } + + const seriesCache = {}; + + async function refreshCharts() { + try { + const keys = 'battery_pct,battery_voltage,battery_current,battery_temp,pmu_temp,fan_pct'; + const data = await get(`/api/series?keys=${keys}&limit=600`); + Object.assign(seriesCache, data); + + chargeChart.update([ + { key: 'battery_pct', label: 'Charge', points: data.battery_pct || [], colorIndex: 0, unit: '%' }, + ]); + electricalChart.update([ + { key: 'battery_voltage', label: 'Voltage', points: data.battery_voltage || [], colorIndex: 0, unit: ' V' }, + ]); + currentChart.update([ + { key: 'battery_current', label: 'Current', points: data.battery_current || [], colorIndex: 1, unit: ' A' }, + ]); + thermalChart.update([ + { key: 'battery_temp', label: 'Battery cell', points: data.battery_temp || [], colorIndex: 1, unit: ' °C' }, + { key: 'pmu_temp', label: 'PMU', points: data.pmu_temp || [], colorIndex: 3, unit: ' °C' }, + { key: 'fan_pct', label: 'Fan duty', points: data.fan_pct || [], colorIndex: 2, unit: ' %' }, + ]); + } catch { /* best-effort */ } + } + + paint(); + await refreshCharts(); + paint(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 1000) return; + last = now; + paint(); + }); + const timer = setInterval(() => { refreshCharts().then(paint); }, 4000); + + return { node: root, dispose: () => { unsubscribe(); clearInterval(timer); } }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/sensors.js b/x2_dashboard/web/js/tabs/sensors.js new file mode 100644 index 0000000..9d92d73 --- /dev/null +++ b/x2_dashboard/web/js/tabs/sensors.js @@ -0,0 +1,249 @@ +/* Sensors - IMU, touch, LiDAR and topic liveness. */ + +import { store, get, num, clockTime, RAD2DEG } from '../core.js'; +import { el, card, pageHead, badge, table, stat, note, emptyState, kv, button } from '../ui.js'; +import { timeSeries, attitude } from '../charts.js'; + +export default { + id: 'sensors', + label: 'Sensors', + icon: 'sensors', + + async render() { + const spec = store.spec; + const root = el('div.stack'); + + root.appendChild(pageHead( + 'Sensors', + 'Hardware abstraction layer feeds — IMU, touch, LiDAR — and how fresh each topic is.', + )); + + /* -- IMU -------------------------------------------------------------- */ + + const imuHosts = { + chest: { attitude: el('div.attitude'), readout: el('div') }, + torso: { attitude: el('div.attitude'), readout: el('div') }, + }; + + const imuChart = timeSeries([ + { key: 'imu_roll', label: 'Roll', points: [], colorIndex: 0, unit: '°' }, + { key: 'imu_pitch', label: 'Pitch', points: [], colorIndex: 1, unit: '°' }, + ], { height: 176, precision: 2, zeroLine: true }); + + root.appendChild(el('div.grid.cols-2', {}, + card('Chest IMU', { sub: '/aima/hal/imu/chest/state · 500 Hz' }, + el('div.row', { style: { gap: '18px', alignItems: 'flex-start' } }, + imuHosts.chest.attitude, + el('div', { style: { flex: '1', minWidth: '160px' } }, imuHosts.chest.readout), + ), + ), + card('Torso IMU', { sub: '/aima/hal/imu/torso/state · 500 Hz' }, + el('div.row', { style: { gap: '18px', alignItems: 'flex-start' } }, + imuHosts.torso.attitude, + el('div', { style: { flex: '1', minWidth: '160px' } }, imuHosts.torso.readout), + ), + ), + )); + + root.appendChild(card('Attitude history', { sub: 'Chest IMU, degrees' }, imuChart)); + + /* -- Touch + LiDAR ---------------------------------------------------- */ + + const touchHost = el('div'); + const odomHost = el('div'); + + root.appendChild(el('div.grid.cols-2', {}, + card('Head touch', { sub: '/aima/hal/sensor/touch_head · 8 zones · 100 Hz' }, touchHost), + card('Odometry', { sub: '/aima/mc/leg_odometry' }, odomHost), + )); + + /* -- Topic health ----------------------------------------------------- */ + + const healthHost = el('div'); + root.appendChild(card('Topic health', { + sub: 'Measured rate against the documented rate', + actions: [button('Refresh', () => refreshTopics(), { size: 'sm', style: 'ghost', iconName: 'refresh' })], + }, healthHost)); + + let tracked = []; + + async function refreshTopics() { + try { + const data = await get('/api/topics'); + tracked = data.tracked || []; + paintHealth(); + } catch { + healthHost.replaceChildren(emptyState('Could not read topic statistics')); + } + } + + function paintHealth() { + const documented = spec?.sensor_topics || []; + const byTopic = Object.fromEntries(tracked.map((t) => [t.topic, t])); + const now = Date.now() / 1000; + + const rows = documented.map((doc) => { + const live = byTopic[doc.topic]; + const age = live ? now - live.last : null; + const stale = age === null || age > 3; + const rateRatio = live && doc.rate_hz ? live.hz / doc.rate_hz : null; + + let tone = 'critical'; + let label = 'silent'; + if (live && !stale) { + if (rateRatio === null || rateRatio > 0.6) { tone = 'good'; label = 'healthy'; } + else { tone = 'warning'; label = 'slow'; } + } else if (live) { + tone = 'warning'; label = 'stale'; + } + + return { + topic: doc.topic, + label: doc.label, + type: doc.type, + expected: doc.rate_hz ? `${doc.rate_hz} Hz` : '—', + actual: live ? `${num(live.hz, 1)} Hz` : '—', + count: live ? live.count.toLocaleString() : '0', + age: age === null ? '—' : `${num(age, 1)} s`, + status: badge(label, tone), + }; + }); + + // Anything the bridge saw that is not in the documented list still matters. + for (const live of tracked) { + if (documented.some((d) => d.topic === live.topic)) continue; + rows.push({ + topic: live.topic, label: '—', type: '—', + expected: '—', actual: `${num(live.hz, 1)} Hz`, + count: live.count.toLocaleString(), + age: `${num(now - live.last, 1)} s`, + status: badge('extra', 'accent'), + }); + } + + healthHost.replaceChildren(table([ + { key: 'label', label: 'Sensor' }, + { key: 'topic', label: 'Topic' }, + { key: 'type', label: 'Type' }, + { key: 'expected', label: 'Expected', align: 'right' }, + { key: 'actual', label: 'Measured', align: 'right' }, + { key: 'count', label: 'Messages', align: 'right' }, + { key: 'age', label: 'Last seen', align: 'right' }, + { key: 'status', label: 'Status' }, + ], rows, { empty: 'No topics observed yet' })); + } + + /* -- Painting --------------------------------------------------------- */ + + function paintImu(key) { + const data = store.state?.imu?.[key]; + const host = imuHosts[key]; + if (!host) return; + + if (!data) { + host.attitude.replaceChildren(); + host.readout.replaceChildren(emptyState('No data', 'Nothing received on this IMU topic.')); + return; + } + + host.attitude.replaceChildren(attitude(data.roll || 0, data.pitch || 0, { size: 132 })); + host.readout.replaceChildren(kv([ + ['Roll', `${num((data.roll || 0) * RAD2DEG, 2)}°`], + ['Pitch', `${num((data.pitch || 0) * RAD2DEG, 2)}°`], + ['Yaw', `${num((data.yaw || 0) * RAD2DEG, 2)}°`], + ['Accel X', `${num(data.accel_x, 2)} m/s²`], + ['Accel Y', `${num(data.accel_y, 2)} m/s²`], + ['Accel Z', `${num(data.accel_z, 2)} m/s²`], + ['Gyro Z', `${num(data.gyro_z, 3)} rad/s`], + ])); + } + + function paint() { + const s = store.state; + if (!s) return; + + paintImu('chest'); + paintImu('torso'); + + const touch = s.touch_head || {}; + const zones = Array.isArray(touch.zones) ? touch.zones : []; + const raw = Array.isArray(touch.data) ? touch.data : []; + + touchHost.replaceChildren( + el('div.row', { style: { marginBottom: '12px' } }, + badge(touch.touched ? 'Contact' : 'No contact', touch.touched ? 'good' : 'default'), + badge(`${zones.filter(Boolean).length} of ${zones.length || 8} active`), + ), + zones.length + ? el('div', { + style: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '6px' }, + }, + ...zones.map((active, index) => el('div', { + style: { + padding: '13px 6px', textAlign: 'center', + borderRadius: 'var(--radius-sm)', + background: active ? 'var(--accent-soft)' : 'var(--surface-2)', + border: `1px solid ${active ? 'var(--accent)' : 'var(--border)'}`, + fontSize: '11px', fontWeight: '600', + color: active ? 'var(--accent)' : 'var(--text-3)', + transition: 'background .15s, border-color .15s', + }, + }, + el('div', { text: `Z${index + 1}` }), + raw.length > index + ? el('div', { + text: String(raw[index]), + style: { fontSize: '9.5px', fontFamily: 'var(--mono)', opacity: '.75' }, + }) + : null, + )), + ) + : note('No TouchState message received yet.', 'default'), + ); + + const odom = s.odom || {}; + const vel = s.velocity || {}; + odomHost.replaceChildren( + kv([ + ['Position X', `${num(odom.x, 3)} m`], + ['Position Y', `${num(odom.y, 3)} m`], + ['Heading', `${num((odom.yaw || 0) * RAD2DEG, 1)}°`], + ['Forward speed', `${num(vel.forward, 3)} m/s`], + ['Lateral speed', `${num(vel.lateral, 3)} m/s`], + ['Yaw rate', `${num(vel.angular, 3)} rad/s`], + ]), + el('div', { style: { marginTop: '12px' } }, + note('Leg odometry publishes while the robot is walking. It sits still in Passive or ' + + 'Damping mode, which is why these values stop updating when the robot is parked.', + 'info'), + ), + ); + } + + async function refreshChart() { + try { + const data = await get('/api/series?keys=imu_roll,imu_pitch&limit=400'); + const toDeg = (points) => (points || []).map(([t, v]) => [t, v * RAD2DEG]); + imuChart.update([ + { key: 'imu_roll', label: 'Roll', points: toDeg(data.imu_roll), colorIndex: 0, unit: '°' }, + { key: 'imu_pitch', label: 'Pitch', points: toDeg(data.imu_pitch), colorIndex: 1, unit: '°' }, + ]); + } catch { /* chart refresh is best-effort */ } + } + + paint(); + refreshTopics(); + refreshChart(); + + let last = 0; + const unsubscribe = store.on('state', () => { + const now = Date.now(); + if (now - last < 400) return; + last = now; + paint(); + }); + const timer = setInterval(() => { refreshTopics(); refreshChart(); }, 3000); + + return { node: root, dispose: () => { unsubscribe(); clearInterval(timer); } }; + }, +}; diff --git a/x2_dashboard/web/js/tabs/settings.js b/x2_dashboard/web/js/tabs/settings.js new file mode 100644 index 0000000..228a480 --- /dev/null +++ b/x2_dashboard/web/js/tabs/settings.js @@ -0,0 +1,606 @@ +/* Settings - robot discovery, network, transport and safety limits. + + This is where the "works on any IP" promise lives: the dashboard never stores + a fixed robot address, it discovers one on whatever network you are currently + attached to, and it reports every address it is itself reachable on. +*/ + +import { store, get, post, toast, num } from '../core.js'; +import { + el, card, pageHead, button, note, badge, table, input, select, field, + emptyState, toggle, range, kv, segmented, setChildren, +} from '../ui.js'; + +export default { + id: 'settings', + label: 'Settings', + icon: 'settings', + + async render() { + const root = el('div.stack'); + let config = store.settings?.values || {}; + let network = store.network || {}; + + root.appendChild(pageHead( + 'Settings', + 'Connection, transport and safety limits. Changes are saved to config.json immediately.', + )); + + /* ================================================================== + Robot connection + discovery + ================================================================== */ + + const hostInput = input({ value: config.robot_host || '', placeholder: 'IP address or hostname' }); + const probeResult = el('div'); + const scanResult = el('div'); + const scanProgress = el('div', { style: { display: 'none' } }); + + const saveHost = async (value) => { + const data = await post('/api/settings', { robot_host: value }); + config = data.settings.values; + store.settings = data.settings; + toast('Robot host saved', value || 'cleared', + 'good'); + if (data.needs_restart) restartNote.style.display = ''; + }; + + const probeBtn = button('Test', async (node) => { + const host = hostInput.value.trim(); + if (!host) { hostInput.focus(); return; } + node.disabled = true; + probeResult.replaceChildren(el('span.muted', { text: 'Probing…' })); + try { + const data = await post('/api/network/probe', { host }); + const info = data.detail || {}; + setChildren(probeResult, + el('div.row', {}, + badge(data.ok ? 'reachable' : 'no answer', data.ok ? 'good' : 'critical'), + info.hostname ? badge(info.hostname) : null, + info.open_ports?.length ? badge(`ports ${info.open_ports.join(', ')}`, 'accent') : null, + badge(`${num(info.latency_ms, 0)} ms`), + ), + info.is_pc1 + ? note('This is PC1, the motion-control unit. The documentation forbids using it as a ' + + 'build or run host. Point the dashboard at PC2 instead.', 'critical', '⚠') + : null, + ); + } catch (err) { + probeResult.replaceChildren(note(err.message, 'critical', '⚠')); + } finally { + node.disabled = false; + } + }); + + const scanBtn = button('Scan this network', async (node) => { + node.disabled = true; + scanProgress.style.display = ''; + scanProgress.replaceChildren(el('span.muted', { text: 'Starting sweep…' })); + scanResult.replaceChildren(); + try { + const data = await post('/api/network/scan', {}, ); + const hosts = data.hosts || []; + scanResult.replaceChildren( + el('div.row', { style: { marginBottom: '10px' } }, + badge(`${hosts.length} responding`, hosts.length ? 'good' : 'warning'), + ...(data.networks || []).map((n) => badge(n, 'accent')), + ), + hosts.length + ? table([ + { key: 'host', label: 'Address' }, + { key: 'hostname', label: 'Name', get: (r) => r.hostname || '—' }, + { key: 'ports', label: 'Open ports', get: (r) => r.open_ports.join(', ') }, + { key: 'latency', label: 'Latency', align: 'right', get: (r) => `${num(r.latency_ms, 0)} ms` }, + { + key: 'tags', label: '', + get: (r) => el('div.row.tight', {}, + r.is_self ? badge('this machine', 'default') : null, + r.is_pc1 ? badge('PC1 — do not use', 'critical') : null, + ), + }, + { + key: 'use', label: '', + get: (r) => button('Use', async () => { + hostInput.value = r.host; + await saveHost(r.host); + }, { size: 'sm', style: r.is_pc1 ? 'warn' : 'primary' }), + }, + ], hosts) + : emptyState('Nothing answered', + 'No host on this subnet responded on the ports an X2 exposes. ' + + 'Check that the robot is powered and on the same network.'), + ); + } catch (err) { + scanResult.replaceChildren(note(err.message, 'critical', '⚠')); + } finally { + node.disabled = false; + scanProgress.style.display = 'none'; + } + }, { iconName: 'scan', style: 'primary' }); + + const restartNote = el('div', { style: { display: 'none' } }, + note('Transport settings changed. Restart the bridge to apply them.', 'warning', '⚠'), + ); + + const restartBtn = button('Restart bridge', async (node) => { + node.disabled = true; + try { + const data = await post('/api/bridge/restart'); + toast(data.ok ? 'Bridge restarted' : 'Restart failed', data.message, + data.ok ? 'good' : 'critical'); + if (data.ok) { + restartNote.style.display = 'none'; + const boot = await get('/api/bootstrap'); + store.bridge = boot.bridge; + store.state = boot.state; + } + } catch (err) { + toast('Restart failed', err.message, 'critical'); + } finally { + node.disabled = false; + } + }, { iconName: 'refresh' }); + + root.appendChild(card('Robot connection', { sub: 'No fixed address is stored' }, + el('div.stack', {}, + field('Robot host', + el('div.row', { style: { gap: '8px', flexWrap: 'nowrap' } }, + hostInput, + probeBtn, + button('Save', () => saveHost(hostInput.value.trim())), + ), + 'Leave empty to rely on ROS 2 DDS multicast discovery, which finds the robot on the local ' + + 'segment without an address. Set it when you want the dashboard to report and probe a ' + + 'specific host.', + ), + probeResult, + el('div.row.between', {}, + el('span', { text: 'Find the robot automatically', style: { fontSize: '12px', color: 'var(--text-2)' } }), + scanBtn, + ), + scanProgress, + scanResult, + note('The sweep covers whichever subnets this machine is on right now. Move to a different ' + + 'Wi-Fi network and scan again — nothing is cached.', 'info'), + + el('div', { style: { borderTop: '1px solid var(--border-soft)', margin: '4px 0 2px' } }), + + toggle('Find the robot automatically if its address changes', config.auto_discover, + (value) => saveSetting('auto_discover', value)), + + toggle('Start the agent over SSH if the robot is on but not answering', + config.auto_start_agent, + (value) => saveSetting('auto_start_agent', value)), + + el('div.grid.cols-2', { style: { gap: '10px' } }, + field('SSH user', + input({ + value: config.robot_ssh_user, + onchange: (e) => saveSetting('robot_ssh_user', e.target.value), + }), + ), + field('SSH password', + input({ + type: 'password', + value: config.robot_ssh_password, + placeholder: config.robot_ssh_password ? '' : 'not saved', + onchange: (e) => saveSetting('robot_ssh_password', e.target.value), + }), + ), + ), + + note('The robot cannot start the dashboard agent by itself: the agi account is not ' + + 'allowed to enable systemd lingering, and the robot\'s clock jumps backwards after ' + + 'boot, which stalls cron. With these credentials the dashboard logs in and starts ' + + 'it for you after a power cycle. Stored in config.json on this machine.', + 'warning', '⚠'), + + restartNote, + ), + )); + + /* ================================================================== + Dashboard reachability + ================================================================== */ + + const urlHost = el('div'); + + function paintUrls() { + const urls = network.urls || []; + + const primary = network.address?.ip + ? `http://${network.address.ip}:${network.port}` : null; + + const describe = (url) => { + if (url === primary) return { label: 'use this — works everywhere', tone: 'good' }; + if (url.includes('localhost') || url.includes('127.0.0.1')) { + return { label: 'this machine only', tone: 'default' }; + } + // Names need mDNS, which many access points block between clients. + if (!/\/\/\d+\.\d+\.\d+\.\d+/.test(url)) { + return { label: 'needs mDNS — often blocked on Wi-Fi', tone: 'warning' }; + } + return { label: 'other adapter', tone: 'accent' }; + }; + + urlHost.replaceChildren( + el('div.stack', { style: { gap: '8px' } }, + ...urls.map((url) => { + const meta = describe(url); + return el('div.row.between', { + style: { + padding: '10px 13px', background: 'var(--surface-2)', + border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', + }, + }, + el('span', { text: url, style: { fontFamily: 'var(--mono)', fontSize: '12.5px' } }), + el('div.row.tight', {}, + badge(meta.label, meta.tone), + button('Copy', async () => { + try { + await navigator.clipboard.writeText(url); + toast('Copied', url, 'good', 1800); + } catch { + toast('Copy blocked', 'Select and copy the address manually.', 'warning'); + } + }, { size: 'sm', style: 'ghost' }), + ), + ); + }), + ), + ); + } + + const nameHost = el('div'); + + function paintName() { + const adv = network.advertised; + setChildren(nameHost, + field('Dashboard name on the network', + el('div.row', { style: { gap: '8px', flexWrap: 'nowrap' } }, + input({ + value: config.dashboard_name, + placeholder: 'agibot', + onchange: (e) => saveSetting('dashboard_name', e.target.value.trim().toLowerCase()), + }), + adv?.running ? badge('publishing', 'good') + : adv?.conflict ? badge('name taken', 'critical') + : badge('not publishing', 'warning'), + ), + 'The dashboard publishes this over mDNS, so the link is about the robot rather than ' + + 'this PC. Takes effect when the server restarts.', + ), + adv?.error ? el('div', { style: { marginTop: '8px' } }, note(adv.error, 'warning', '⚠')) : null, + ); + } + + const qrHost = el('div'); + const devicesHost = el('div'); + + function paintQr() { + const detail = network.address || {}; + + if (!detail.ip) { + setChildren(qrHost, + note(`No network address right now — ${detail.reason_text || 'not connected'}. ` + + 'The dashboard keeps checking and will show the link the moment the ' + + 'network is back.', 'warning', '⚠'), + ); + return; + } + + const url = `http://${detail.ip}:${network.port}`; + setChildren(qrHost, + el('div.row', { style: { gap: '18px', alignItems: 'center', flexWrap: 'wrap' } }, + el('img', { + src: `/api/qr?url=${encodeURIComponent(url)}&t=${Date.now()}`, + alt: `QR code for ${url}`, + style: { + width: '156px', height: '156px', background: '#fff', + padding: '8px', borderRadius: 'var(--radius-sm)', + }, + }), + el('div', { style: { flex: '1', minWidth: '220px' } }, + el('div', { text: 'Open this on your phone', + style: { fontWeight: '600', marginBottom: '6px' } }), + el('div', { + text: url, + style: { fontFamily: 'var(--mono)', fontSize: '17px', color: 'var(--text)' }, + }), + (() => { + const kindLabel = detail.kind === 'wifi' ? 'Wi-Fi' : 'wired'; + const adapter = detail.adapter || ''; + return el('div.row.tight', { style: { marginTop: '8px' } }, + badge(kindLabel, detail.kind === 'wifi' ? 'good' : 'accent'), + // The adapter is usually just called "Wi-Fi" too - only worth a + // second badge when it actually says something different. + adapter && adapter.toLowerCase() !== kindLabel.toLowerCase() + ? badge(adapter) : null, + detail.gateway ? badge(`via ${detail.gateway}`) : null, + badge('live', 'good'), + ); + })(), + el('div.hint', { + text: 'Read from the network adapter and re-checked continuously — if this PC ' + + 'gets a new address the link above updates by itself. Scan or type it; ' + + 'it needs no name resolution, so it works even where .local does not.', + style: { marginTop: '8px' }, + }), + el('div.row.tight', { style: { marginTop: '8px' } }, + button('Copy link', async () => { + try { + await navigator.clipboard.writeText(url); + toast('Copied', url, 'good', 1800); + } catch { + toast('Copy blocked', 'Select and copy it manually.', 'warning'); + } + }, { size: 'sm' }), + ), + ), + ), + (detail.rejected || []).length + ? el('details', { style: { marginTop: '10px' } }, + el('summary', { + text: `${detail.rejected.length} other address(es) ignored`, + style: { cursor: 'pointer', fontSize: '12px', color: 'var(--text-3)' }, + }), + el('div', { style: { marginTop: '8px' } }, + table([ + { key: 'ip', label: 'Address' }, + { key: 'adapter', label: 'Adapter' }, + { key: 'why', label: 'Why it is not used' }, + ], detail.rejected), + ), + ) + : null, + ); + } + + function paintDevices() { + const devices = network.other_devices || []; + setChildren(devicesHost, + el('div.row', { style: { marginBottom: '8px' } }, + el('strong', { text: 'Devices that have opened this dashboard', + style: { fontSize: '12.5px' } }), + badge(String(devices.length), devices.length ? 'good' : 'warning'), + ), + devices.length + ? table([ + { key: 'address', label: 'Address' }, + { key: 'hits', label: 'Requests', align: 'right' }, + { + key: 'agent', label: 'Browser', + get: (r) => { + const a = r.agent || ''; + if (/iPhone|iPad/i.test(a)) return 'iPhone / iPad'; + if (/Android/i.test(a)) return 'Android'; + if (/Macintosh/i.test(a)) return 'Mac'; + if (/Windows/i.test(a)) return 'Windows'; + return a.slice(0, 28) || '—'; + }, + }, + ], devices) + : note('Nothing but this PC has loaded the dashboard yet. If your phone appears here ' + + 'after scanning the QR code, the network is fine and only the .local name is ' + + 'being blocked — which is the access point filtering multicast, not something ' + + 'this dashboard can fix.', 'warning', '⚠'), + ); + } + + root.appendChild(card('Open on another device', { + sub: 'The server binds every interface', + actions: [button('Refresh', async () => { + network = await get('/api/network'); + store.network = network; + paintUrls(); + paintName(); + paintQr(); + paintDevices(); + }, { size: 'sm', style: 'ghost', iconName: 'refresh' })], + }, + el('div.stack', {}, + qrHost, + urlHost, + nameHost, + devicesHost, + note('The .local link goes over mDNS, which iPhone, iPad, Mac, Android 12+ and Windows ' + + 'understand. Many access points block multicast between wireless clients, and then ' + + 'no .local name resolves from a phone no matter what the PC does — scan the QR code ' + + 'instead.', 'info'), + ), + )); + paintUrls(); + paintName(); + paintQr(); + paintDevices(); + + // The server pushes a "network" message whenever the detected address + // changes, so a page left open never shows a link that stopped working. + const unsubscribeNetwork = store.on('network', (data) => { + network = { ...network, ...data }; + store.network = network; + paintUrls(); + paintQr(); + toast('Network address changed', + data.address?.ip ? `Now at ${data.address.ip}` : 'No network address', + data.address?.ip ? 'good' : 'warning'); + }); + + /* ================================================================== + Transport + ================================================================== */ + + const transportFields = el('div.stack'); + + function paintTransport() { + const bridge = store.bridge || {}; + const online = store.state?.connection?.online; + setChildren(transportFields, + el('div.row', { style: { marginBottom: '4px' } }, + badge(bridge.simulated ? 'Simulation' : online ? 'Live' : 'Robot off', + bridge.simulated ? 'warning' : online ? 'good' : 'critical'), + bridge.agent?.agent_version ? badge(`agent ${bridge.agent.agent_version}`, 'accent') : null, + bridge.agent?.hostname ? badge(bridge.agent.hostname) : null, + ), + bridge.simulated + ? note('No robot address is set, so the dashboard is driving the built-in simulator. ' + + 'Enter the robot address above and restart the bridge to attach to the real X2.', + 'warning', '⚠') + : null, + bridge.error ? note(bridge.error, 'critical', '⚠') : null, + + field('Bridge mode', + select([ + { value: 'auto', label: 'Auto — use the robot agent when an address is set' }, + { value: 'agent', label: 'Robot only — never fall back to simulation' }, + { value: 'mock', label: 'Simulation only — never touch a real robot' }, + ], { + value: config.bridge_mode, + onChange: (value) => saveSetting('bridge_mode', value), + }), + ), + + field('Agent port', + input({ + type: 'number', min: 1, max: 65535, value: config.agent_port, + onchange: (e) => saveSetting('agent_port', Number(e.target.value)), + }), + 'The TCP port x2_agent.py listens on aboard the robot.', + ), + + field('ROS_DOMAIN_ID', + input({ + type: 'number', min: 0, max: 232, value: config.ros_domain_id, + onchange: (e) => saveSetting('ros_domain_id', Number(e.target.value)), + }), + 'Reference only — the agent inherits the domain from the shell that launched it.', + ), + + el('div.row', {}, restartBtn), + ); + } + + /* ================================================================== + Safety and server + ================================================================== */ + + const limits = store.spec?.velocity_limits || {}; + + const safetyCard = card('Safety limits', { sub: 'Applied server-side to every command' }, + el('div.stack', {}, + el('div', {}, + el('div', { text: 'Max forward velocity', style: labelStyle }), + range({ + min: 0.1, max: limits.forward?.max ?? 0.8, step: 0.05, + value: config.max_forward_velocity, precision: 2, unit: ' m/s', + onChange: (v) => saveSetting('max_forward_velocity', v), + }), + ), + el('div', {}, + el('div', { text: 'Max lateral velocity', style: labelStyle }), + range({ + min: 0.1, max: limits.lateral?.max ?? 0.7, step: 0.05, + value: config.max_lateral_velocity, precision: 2, unit: ' m/s', + onChange: (v) => saveSetting('max_lateral_velocity', v), + }), + ), + el('div', {}, + el('div', { text: 'Max yaw rate', style: labelStyle }), + range({ + min: 0.1, max: limits.angular?.max ?? 0.8, step: 0.05, + value: config.max_angular_velocity, precision: 2, unit: ' rad/s', + onChange: (v) => saveSetting('max_angular_velocity', v), + }), + ), + el('div', {}, + el('div', { text: 'Dead-man timeout', style: labelStyle }), + range({ + min: 0.2, max: 3, step: 0.1, + value: config.locomotion_deadman_s, precision: 1, unit: ' s', + onChange: (v) => saveSetting('locomotion_deadman_s', v), + }), + el('div.hint', { text: 'Velocity is zeroed if the browser stops sending for this long.' }), + ), + toggle('Confirm before zero-torque', config.require_confirm_zero_torque, + (value) => saveSetting('require_confirm_zero_torque', value)), + ), + ); + + const serverCard = card('Server', { sub: store.settings?.config_path || 'config.json' }, + el('div.stack', {}, + field('Display name', + input({ + value: config.robot_label, + onchange: (e) => saveSetting('robot_label', e.target.value), + }), + ), + field('HTTP port', + input({ + type: 'number', min: 1, max: 65535, value: config.port, + onchange: (e) => saveSetting('port', Number(e.target.value)), + }), + 'Takes effect the next time the server starts.', + ), + el('div', {}, + el('div', { text: 'Telemetry rate', style: labelStyle }), + range({ + min: 1, max: 30, step: 1, value: config.telemetry_hz, precision: 0, unit: ' Hz', + onChange: (v) => saveSetting('telemetry_hz', v), + }), + el('div.hint', { text: 'How often state is pushed to the browser. Lower it on a weak link.' }), + ), + el('div', { style: { marginTop: '4px' } }, + kv([ + ['Server version', store.server?.version || '—'], + ['Connected clients', String(store.server?.clients ?? '—')], + ['Config file', store.settings?.config_path || '—'], + ]), + ), + ), + ); + + root.appendChild(el('div.grid.cols-2', {}, + card('Transport', { sub: 'How the dashboard reaches the robot' }, transportFields), + safetyCard, + )); + root.appendChild(serverCard); + + paintTransport(); + + /* ================================================================== + Helpers + ================================================================== */ + + async function saveSetting(key, value) { + try { + const data = await post('/api/settings', { [key]: value }); + config = data.settings.values; + store.settings = data.settings; + if (data.needs_restart) restartNote.style.display = ''; + toast('Saved', `${key} = ${value}`, 'good', 1800); + } catch (err) { + toast('Could not save', err.message, 'critical'); + } + } + + const unsubscribe = store.on('scan_progress', (data) => { + scanProgress.replaceChildren( + el('div', {}, + el('div.row.between', { style: { fontSize: '12px', color: 'var(--text-2)', marginBottom: '5px' } }, + el('span', { text: 'Sweeping subnet' }), + el('span', { text: `${data.done} / ${data.total}` }), + ), + el('div.meter', {}, + el('div.meter-fill', { style: { width: `${(data.done / data.total) * 100}%` } }), + ), + ), + ); + }); + + return { + node: root, + dispose: () => { unsubscribe(); unsubscribeNetwork(); }, + }; + }, +}; + +const labelStyle = { fontSize: '12px', color: 'var(--text-2)', marginBottom: '5px' }; diff --git a/x2_dashboard/web/js/tabs/vision.js b/x2_dashboard/web/js/tabs/vision.js new file mode 100644 index 0000000..955bdde --- /dev/null +++ b/x2_dashboard/web/js/tabs/vision.js @@ -0,0 +1,326 @@ +/* Vision - camera feeds, each switched on by hand. + + Nothing is subscribed on the robot until a feed is switched on here. That is + not a nicety: a frame off this robot is 170-430 KB, and the six RGB feeds + together publish at ~60 Hz. Subscribing to the lot at startup pushed roughly + 15 MB/s through DDS for pictures nobody was looking at, on the same Wi-Fi the + robot uses to walk. Switching a feed off destroys the subscription on the + robot rather than merely hiding the . + + Frames are polled as single images rather than streamed, so a quiet topic + degrades into "nothing is publishing" instead of a hung connection. +*/ + +import { store, API, get, post, toast } from '../core.js'; +import { el, card, pageHead, badge, segmented, note, emptyState, button } from '../ui.js'; + +export default { + id: 'vision', + label: 'Vision', + icon: 'vision', + + async render() { + const cameras = store.spec?.cameras || []; + const root = el('div.stack'); + const feeds = new Map(); + + let fps = 2; + + const fpsControl = segmented( + [{ value: 1, label: '1 fps' }, { value: 2, label: '2 fps' }, + { value: 5, label: '5 fps' }, { value: 10, label: '10 fps' }], + fps, + (value) => { fps = value; for (const feed of feeds.values()) schedule(feed); }, + ); + + root.appendChild(pageHead( + 'Vision', + 'Every feed is off until you switch it on — that keeps the robot from streaming ' + + 'pictures nobody is watching. Compressed feeds pass through untouched; depth is ' + + 'colourised on the robot.', + [ + fpsControl, + button('Turn all off', () => stopAll(), { size: 'sm', style: 'ghost' }), + ], + )); + + if (!cameras.length) { + root.appendChild(emptyState('No cameras declared', 'The backend reported an empty camera list.')); + return { node: root }; + } + + const grid = el('div.grid.cols-2'); + root.appendChild(grid); + + /* -- One card per camera ---------------------------------------------- */ + + for (const camera of cameras) { + const feed = { + camera, + key: camera.key, + active: false, + flip: !!camera.flip, + busy: false, + failures: 0, + timer: null, + objectUrl: null, + img: el('img', { alt: `${camera.label} live view`, decoding: 'async' }), + status: badge('off'), + meta: el('span', { text: '—' }), + }; + + feed.img.style.display = 'none'; + feed.placeholder = el('div.cam-placeholder', { text: 'Switched off' }); + + const shell = el('div.cam', {}, feed.placeholder, feed.img, + el('div.cam-overlay', {}, + el('span.cam-live', { text: camera.key }), + feed.meta, + ), + ); + + // The power switch. Checked state follows the robot, not this browser - + // see applyStreams() - so two tabs never disagree about what is running. + const box = el('input', { type: 'checkbox' }); + box.addEventListener('change', () => setActive(feed, box.checked)); + feed.checkbox = box; + const power = el('label.switch', {}, box, el('span.switch-track'), + el('span.switch-label', { text: 'Off' })); + feed.powerLabel = power.querySelector('.switch-label'); + + const flipBtn = button('Rotate 180°', () => { + feed.flip = !feed.flip; + flipBtn.dataset.on = feed.flip ? '1' : ''; + flipBtn.classList.toggle('btn-primary', feed.flip); + if (feed.active) tick(feed); + }, { size: 'sm', style: 'ghost' }); + feed.flipBtn = flipBtn; + + grid.appendChild(card(camera.label, { + sub: camera.topic, + actions: [power, feed.status], + flush: true, + foot: el('div.row.between', { style: { gap: '10px', flexWrap: 'wrap' } }, + el('span', { + text: camera.note || (camera.kind === 'depth' + ? 'Depth map, colourised on the robot.' + : `${camera.kind} · ~${camera.rate_hz || '?'} Hz`), + style: { fontSize: '11.5px', color: 'var(--text-3)' }, + }), + flipBtn, + ), + }, shell)); + + feeds.set(camera.key, feed); + } + + /* -- Hardware inventory ------------------------------------------------ */ + + const TONE = { + live: 'good', unreachable: 'critical', intermittent: 'warning', absent: 'default', + }; + const LABEL = { + live: 'publishing', unreachable: 'not reachable', + intermittent: 'only while running', absent: 'not fitted', + }; + + const inventory = store.spec?.camera_inventory || []; + if (inventory.length) { + root.appendChild(card('What cameras this robot has', { + sub: 'Confirmed by decoding a real frame off each topic, not read from the datasheet', + }, + el('div.stack', { style: { gap: '10px' } }, + ...inventory.map((item) => el('div', { + style: { + padding: '12px 14px', borderRadius: 'var(--radius-sm)', + background: 'var(--surface-2)', border: '1px solid var(--border)', + }, + }, + el('div.row.between', { style: { marginBottom: '5px' } }, + el('strong', { text: item.name, style: { fontSize: '13px' } }), + badge(LABEL[item.status] || item.status, TONE[item.status] || 'default'), + ), + el('div', { + text: item.detail, + style: { fontSize: '12.5px', color: 'var(--text-2)', lineHeight: '1.55' }, + }), + el('div', { + text: item.where, + style: { fontSize: '11px', color: 'var(--text-3)', fontFamily: 'var(--mono)', + marginTop: '5px', wordBreak: 'break-all' }, + }), + )), + ), + )); + } + + root.appendChild(note( + 'Switching a feed off destroys the subscription on the robot, so an unwatched camera ' + + 'costs nothing. Closing this page turns every feed off by itself.', + 'info', + )); + + /* -- Switching --------------------------------------------------------- */ + + async function setActive(feed, active) { + if (feed.busy) return; + feed.busy = true; + feed.checkbox.disabled = true; + setStatus(feed, active ? 'starting…' : 'stopping…', 'default'); + + try { + await post(`/api/streams/${feed.key}`, { active }); + feed.active = active; + feed.failures = 0; + + if (active) { + feed.placeholder.textContent = 'Waiting for the first frame…'; + feed.placeholder.style.display = 'block'; + schedule(feed); + } else { + stop(feed); + } + paintPower(feed); + } catch (err) { + toast('Could not switch that feed', err.message, 'critical'); + feed.checkbox.checked = feed.active; + paintPower(feed); + } finally { + feed.busy = false; + feed.checkbox.disabled = false; + } + } + + function paintPower(feed) { + feed.checkbox.checked = feed.active; + feed.powerLabel.textContent = feed.active ? 'On' : 'Off'; + if (!feed.active) { + setStatus(feed, 'off', 'default'); + feed.meta.textContent = '—'; + feed.img.style.display = 'none'; + feed.placeholder.style.display = 'block'; + feed.placeholder.textContent = 'Switched off'; + } + } + + function setStatus(feed, text, tone) { + feed.status.textContent = text; + feed.status.dataset.tone = tone; + } + + function stopAll() { + for (const feed of feeds.values()) { + if (feed.active) setActive(feed, false); + } + } + + /* -- Polling ----------------------------------------------------------- */ + + // A feed that keeps coming back empty is retried slowly rather than at the + // full rate: the perception topics only publish while that module runs, and + // hammering them fills the console for something working as intended. + const IDLE_RETRY_MS = 10000; + const FAILURES_BEFORE_BACKOFF = 3; + + function schedule(feed) { + if (feed.timer) clearTimeout(feed.timer); + feed.timer = null; + if (!feed.active) return; + const period = feed.failures >= FAILURES_BEFORE_BACKOFF ? IDLE_RETRY_MS : 1000 / fps; + feed.timer = setTimeout(() => tick(feed), period); + } + + // Fetched rather than assigned straight to img.src: a 204 from a topic + // nobody publishes to is an ordinary answer here, whereas an that + // fails to load logs a console error the page cannot suppress. + async function tick(feed) { + if (!feed.active) return; + const url = `${API}/api/camera/${feed.key}/frame` + + `?flip=${feed.flip ? 'true' : 'false'}&t=${Date.now()}`; + + try { + const res = await fetch(url, { cache: 'no-store' }); + if (res.status === 204 || !res.ok) { onMiss(feed); return; } + + const blob = await res.blob(); + if (!blob.size) { onMiss(feed); return; } + const objectUrl = URL.createObjectURL(blob); + const recovered = feed.failures >= FAILURES_BEFORE_BACKOFF; + + await new Promise((resolve) => { + feed.img.onload = resolve; + feed.img.onerror = resolve; + feed.img.src = objectUrl; + }); + + // Release the previous frame; without this every frame leaks. + if (feed.objectUrl) URL.revokeObjectURL(feed.objectUrl); + feed.objectUrl = objectUrl; + + feed.failures = 0; + feed.img.style.display = 'block'; + feed.placeholder.style.display = 'none'; + setStatus(feed, 'live', 'good'); + feed.meta.textContent = + `${feed.img.naturalWidth}×${feed.img.naturalHeight} · ${Math.round(blob.size / 1024)} KB`; + if (recovered) toast('Feed restored', feed.camera.label, 'good', 2500); + } catch { + onMiss(feed); + } finally { + schedule(feed); + } + } + + function onMiss(feed) { + feed.failures += 1; + if (feed.failures < 2) return; + feed.img.style.display = 'none'; + feed.placeholder.style.display = 'block'; + feed.placeholder.textContent = store.bridge?.simulated + ? 'Simulated feed unavailable' + : `Nothing is publishing on\n${feed.camera.topic}`; + setStatus(feed, feed.failures >= FAILURES_BEFORE_BACKOFF ? 'not publishing' : 'no signal', + 'warning'); + feed.meta.textContent = '—'; + } + + function stop(feed) { + if (feed.timer) clearTimeout(feed.timer); + feed.timer = null; + if (feed.objectUrl) URL.revokeObjectURL(feed.objectUrl); + feed.objectUrl = null; + } + + /* -- Follow the robot's own idea of what is running -------------------- + Another browser (or the agent dropping everything when the last client + left) can change this behind our back. Reading it from state keeps the + switches honest instead of showing what this tab last asked for. */ + + function applyStreams(streams) { + if (!streams) return; + for (const feed of feeds.values()) { + if (feed.busy) continue; + const active = !!streams[feed.key]?.active; + if (active === feed.active) continue; + feed.active = active; + paintPower(feed); + if (active) schedule(feed); else stop(feed); + } + } + + applyStreams(store.state?.custom?.streams); + const unsubscribe = store.on('state', () => applyStreams(store.state?.custom?.streams)); + + function dispose() { + unsubscribe(); + for (const feed of feeds.values()) { + stop(feed); + // Leaving the tab must not leave the robot streaming. Fire and forget: + // the page is going away and there is nothing useful to report. + if (feed.active) post(`/api/streams/${feed.key}`, { active: false }).catch(() => {}); + } + } + + return { node: root, dispose }; + }, +}; diff --git a/x2_dashboard/web/js/ui.js b/x2_dashboard/web/js/ui.js new file mode 100644 index 0000000..edfef66 --- /dev/null +++ b/x2_dashboard/web/js/ui.js @@ -0,0 +1,286 @@ +/* ========================================================================== + UI builders. Plain DOM, no framework - the dashboard is small enough that a + framework would cost more than it saves, and this keeps the payload tiny for + a phone on the robot's Wi-Fi. + ========================================================================== */ + +import { confirmDialog } from './core.js'; + +/** el('div.card', {id:'x'}, child, child) - tag string supports .class and #id */ +export function el(spec, props = {}, ...children) { + const [tagPart, ...classParts] = String(spec).split('.'); + const [tag, id] = tagPart.split('#'); + const node = document.createElement(tag || 'div'); + if (id) node.id = id; + if (classParts.length) node.className = classParts.join(' '); + + for (const [key, value] of Object.entries(props || {})) { + if (value === null || value === undefined || value === false) continue; + if (key === 'class') node.className = `${node.className} ${value}`.trim(); + else if (key === 'text') node.textContent = value; + else if (key === 'html') node.innerHTML = value; + else if (key === 'style' && typeof value === 'object') Object.assign(node.style, value); + else if (key === 'dataset') Object.assign(node.dataset, value); + else if (key.startsWith('on') && typeof value === 'function') { + node.addEventListener(key.slice(2).toLowerCase(), value); + } else if (key in node && key !== 'list' && typeof value !== 'object') { + try { node[key] = value; } catch { node.setAttribute(key, value); } + } else { + node.setAttribute(key, value === true ? '' : value); + } + } + + append(node, children); + return node; +} + +export function append(parent, children) { + for (const child of children.flat(4)) { + if (child === null || child === undefined || child === false) continue; + parent.appendChild(child instanceof Node ? child : document.createTextNode(String(child))); + } + return parent; +} + +export function clear(node) { + while (node.firstChild) node.removeChild(node.firstChild); + return node; +} + +/** + * Replace a node's children, dropping null / undefined / false entries. + * + * The native replaceChildren() stringifies anything that is not a Node, so a + * conditional child written as `cond ? el(...) : null` renders the literal word + * "null" on the page. This keeps the same forgiving semantics as el(). + */ +export function setChildren(node, ...children) { + clear(node); + append(node, children); + return node; +} + +export function icon(name, cls = 'ico') { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('class', cls); + svg.setAttribute('aria-hidden', 'true'); + const use = document.createElementNS('http://www.w3.org/2000/svg', 'use'); + use.setAttribute('href', `#i-${name}`); + svg.appendChild(use); + return svg; +} + +/* -- Page ----------------------------------------------------------------- */ + +export function pageHead(title, description, actions = []) { + return el('div.page-head', {}, + el('div', {}, + el('h1', { text: title }), + description ? el('p', { text: description }) : null, + ), + actions.length ? el('div.page-head-actions', {}, ...actions) : null, + ); +} + +/* -- Card ----------------------------------------------------------------- */ + +export function card(title, { sub, actions = [], flush = false, foot } = {}, ...body) { + const head = title + ? el('div.card-head', {}, + el('h3', { text: title }), + sub ? el('span.sub', { text: sub }) : null, + actions.length ? el('div.card-head-actions', {}, ...actions) : null, + ) + : null; + + return el('section.card', {}, + head, + el('div.card-body', { class: flush ? 'flush' : '' }, ...body), + foot ? el('div.card-foot', {}, foot) : null, + ); +} + +/* -- Buttons -------------------------------------------------------------- */ + +export function button(label, onClick, { style = '', iconName, size = '', disabled = false, + confirm = null, title = '', block = false } = {}) { + const classes = ['btn']; + if (style === 'primary') classes.push('btn-primary'); + else if (style === 'danger') classes.push('btn-danger'); + else if (style === 'warn') classes.push('btn-warn'); + else if (style === 'ghost') classes.push('btn-ghost'); + if (size === 'sm') classes.push('btn-sm'); + if (block) classes.push('btn-block'); + + const node = el('button', { class: classes.join(' '), disabled, title, type: 'button' }, + iconName ? icon(iconName) : null, + label ? el('span', { text: label }) : null, + ); + + node.addEventListener('click', async () => { + if (confirm) { + const ok = await confirmDialog('Confirm', confirm, { danger: style === 'danger' }); + if (!ok) return; + } + onClick?.(node); + }); + return node; +} + +/* -- Fields --------------------------------------------------------------- */ + +export function field(label, control, hint) { + return el('label.field', {}, + label ? el('span', { text: label, style: { fontSize: '12px', fontWeight: '550', color: 'var(--text-2)' } }) : null, + control, + hint ? el('span.hint', { text: hint }) : null, + ); +} + +export function input(props = {}) { + return el('input.input', { type: 'text', ...props }); +} + +export function textarea(props = {}) { + return el('textarea.textarea', props); +} + +export function select(options, { value, onChange, ...rest } = {}) { + const node = el('select.select', rest); + for (const option of options) { + const opt = typeof option === 'object' ? option : { value: option, label: String(option) }; + node.appendChild(el('option', { value: opt.value, text: opt.label ?? String(opt.value) })); + } + if (value !== undefined && value !== null) node.value = String(value); + if (onChange) node.addEventListener('change', () => onChange(node.value, node)); + return node; +} + +export function toggle(label, checked, onChange) { + const box = el('input', { type: 'checkbox', checked }); + box.addEventListener('change', () => onChange?.(box.checked)); + return el('label.switch', {}, box, el('span.switch-track'), el('span.switch-label', { text: label })); +} + +export function range({ min = 0, max = 1, step = 0.01, value = 0, unit = '', + precision = 2, onInput, onChange } = {}) { + const slider = el('input', { type: 'range', min, max, step, value }); + const readout = el('span.range-value', { text: `${Number(value).toFixed(precision)}${unit}` }); + + slider.addEventListener('input', () => { + const v = Number(slider.value); + readout.textContent = `${v.toFixed(precision)}${unit}`; + onInput?.(v); + }); + slider.addEventListener('change', () => onChange?.(Number(slider.value))); + + const wrap = el('div.range', {}, slider, readout); + wrap.setValue = (v) => { + slider.value = v; + readout.textContent = `${Number(v).toFixed(precision)}${unit}`; + }; + wrap.getValue = () => Number(slider.value); + return wrap; +} + +export function segmented(options, value, onChange) { + const node = el('div.segmented', { role: 'group' }); + const buttons = []; + for (const option of options) { + const opt = typeof option === 'object' ? option : { value: option, label: String(option) }; + const btn = el('button', { type: 'button', text: opt.label, + 'aria-pressed': String(opt.value === value) }); + btn.addEventListener('click', () => { + buttons.forEach((b) => b.setAttribute('aria-pressed', String(b === btn))); + onChange?.(opt.value); + }); + buttons.push(btn); + node.appendChild(btn); + } + node.setValue = (v) => { + options.forEach((option, i) => { + const optValue = typeof option === 'object' ? option.value : option; + buttons[i].setAttribute('aria-pressed', String(optValue === v)); + }); + }; + return node; +} + +/* -- Display -------------------------------------------------------------- */ + +export function stat(label, value, { unit = '', sub = '', tone = 'default', spark = null } = {}) { + return el('div.stat', { dataset: { tone } }, + el('div.stat-label', { text: label }), + el('div.stat-value', {}, String(value), unit ? el('span.unit', { text: unit }) : null), + sub ? el('div.stat-sub', { text: sub }) : null, + spark, + ); +} + +export function badge(text, tone = 'default') { + return el('span.badge', { text, dataset: { tone } }); +} + +export function meter(fraction, tone = 'default') { + const pct = Math.max(0, Math.min(1, fraction || 0)) * 100; + return el('div.meter', {}, el('div.meter-fill', { dataset: { tone }, style: { width: `${pct}%` } })); +} + +export function note(text, level = 'default', iconGlyph = 'ⓘ') { + return el('div.note', { dataset: { level } }, + el('span.note-icon', { text: iconGlyph }), + el('div', { text }), + ); +} + +export function kv(pairs) { + const list = el('dl.kv'); + for (const [key, value] of pairs) { + if (value === undefined) continue; + list.appendChild(el('dt', { text: key })); + list.appendChild(value instanceof Node ? el('dd', {}, value) : el('dd', { text: String(value ?? '—') })); + } + return list; +} + +export function table(columns, rows, { empty = 'No data' } = {}) { + if (!rows.length) return emptyState(empty); + + const head = el('tr'); + for (const column of columns) { + head.appendChild(el('th', { text: column.label, + style: column.align === 'right' ? { textAlign: 'right' } : {} })); + } + + const body = el('tbody'); + for (const row of rows) { + const tr = el('tr'); + for (const column of columns) { + const value = column.get ? column.get(row) : row[column.key]; + const cls = column.align === 'right' ? 'num' : (column.key === 'name' ? 'name' : ''); + tr.appendChild(value instanceof Node + ? el('td', { class: cls }, value) + : el('td', { class: cls, text: value === null || value === undefined ? '—' : String(value) })); + } + body.appendChild(tr); + } + + return el('div.table-wrap', {}, el('table.data', {}, el('thead', {}, head), body)); +} + +export function emptyState(title, detail, action) { + return el('div.empty', {}, + el('div.empty-title', { text: title }), + detail + ? el('div', { text: detail, style: { maxWidth: '52ch', whiteSpace: 'pre-line' } }) + : null, + action, + ); +} + +export function keyHint(keys, description) { + return el('div.row.tight', { style: { fontSize: '11.5px', color: 'var(--text-3)' } }, + el('div.keys', {}, ...keys.map((k) => el('kbd', { text: k }))), + el('span', { text: description }), + ); +} diff --git a/x2_dashboard/web/model/model.bin b/x2_dashboard/web/model/model.bin new file mode 100644 index 0000000000000000000000000000000000000000..c3ce6237df1643586384b8e20cc60a0fc3f69ac3 GIT binary patch literal 1447950 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

H?*xS`?g4 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 z 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�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 z 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

M0RuAr+Cu5L)GldcTxL5knZkVrX7 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 z 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

-LMN^Bi0h`;% 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 W(F=ka*>xAt_+Jpzy)x^r@P7avcQ;7@ literal 0 HcmV?d00001 diff --git a/x2_dashboard/web/model/model.json b/x2_dashboard/web/model/model.json new file mode 100644 index 0000000..f8960a8 --- /dev/null +++ b/x2_dashboard/web/model/model.json @@ -0,0 +1 @@ +{"name":"x2t2.5","source":"X2_URDF-v1.3.0/x2_ultra.urdf","generated_by":"build_model.py (vertex-clustered, uint16-quantised)","target_triangles_per_link":1500,"root":"base_link","links":{"pelvis":{"name":"pelvis","meshes":[{"file":"pelvis.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.074959,-0.085881,-0.065252],"span":[0.139767,0.171762,0.133113],"vertex_offset":0,"vertex_count":1889,"index_offset":11334,"index_count":17790,"index_bits":16}]},"imu_in_pelvis_link":{"name":"imu_in_pelvis_link","meshes":[{"file":"imu_in_pelvis_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.010545,-0.010971,-0.0104],"span":[0.02405,0.0224,0.014],"vertex_offset":46914,"vertex_count":1078,"index_offset":53382,"index_count":8190,"index_bits":16}]},"left_hip_pitch_link":{"name":"left_hip_pitch_link","meshes":[{"file":"left_hip_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.04,-0.0,-0.06154],"span":[0.07585,0.127505,0.123361],"vertex_offset":69762,"vertex_count":2046,"index_offset":82038,"index_count":15648,"index_bits":16}]},"left_hip_roll_link":{"name":"left_hip_roll_link","meshes":[{"file":"left_hip_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.063426,-0.058888,-0.147494],"span":[0.128001,0.118888,0.1965],"vertex_offset":113334,"vertex_count":920,"index_offset":118854,"index_count":9768,"index_bits":16}]},"left_hip_yaw_link":{"name":"left_hip_yaw_link","meshes":[{"file":"left_hip_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.068093,-0.057893,-0.243918],"span":[0.130093,0.11589,0.242774],"vertex_offset":138390,"vertex_count":1107,"index_offset":145032,"index_count":14154,"index_bits":16}]},"left_knee_link":{"name":"left_knee_link","meshes":[{"file":"left_knee_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.054872,-0.052325,-0.30291],"span":[0.117822,0.105558,0.354794],"vertex_offset":173340,"vertex_count":879,"index_offset":178614,"index_count":10014,"index_bits":16}]},"left_ankle_pitch_link":{"name":"left_ankle_pitch_link","meshes":[{"file":"left_ankle_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.0411,-0.0343,-0.032007],"span":[0.0799,0.0686,0.064016],"vertex_offset":198642,"vertex_count":2502,"index_offset":213654,"index_count":16596,"index_bits":16}]},"left_ankle_roll_link":{"name":"left_ankle_roll_link","meshes":[{"file":"left_ankle_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.071262,-0.062702,-0.073327],"span":[0.219221,0.127237,0.105327],"vertex_offset":246846,"vertex_count":1284,"index_offset":254550,"index_count":15654,"index_bits":16}]},"right_hip_pitch_link":{"name":"right_hip_pitch_link","meshes":[{"file":"right_hip_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.04,-0.127505,-0.06154],"span":[0.07506,0.127505,0.12336],"vertex_offset":285858,"vertex_count":2067,"index_offset":298260,"index_count":15546,"index_bits":16}]},"right_hip_roll_link":{"name":"right_hip_roll_link","meshes":[{"file":"right_hip_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.064,-0.057848,-0.147494],"span":[0.128001,0.117844,0.1965],"vertex_offset":329352,"vertex_count":917,"index_offset":334854,"index_count":9750,"index_bits":16}]},"right_hip_yaw_link":{"name":"right_hip_yaw_link","meshes":[{"file":"right_hip_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.067862,-0.057893,-0.243996],"span":[0.129862,0.11589,0.242852],"vertex_offset":354354,"vertex_count":1106,"index_offset":360990,"index_count":14082,"index_bits":16}]},"right_knee_link":{"name":"right_knee_link","meshes":[{"file":"right_knee_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.055371,-0.052516,-0.302812],"span":[0.118321,0.106199,0.354696],"vertex_offset":389154,"vertex_count":880,"index_offset":394434,"index_count":10008,"index_bits":16}]},"right_ankle_pitch_link":{"name":"right_ankle_pitch_link","meshes":[{"file":"right_ankle_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.0411,-0.0343,-0.032007],"span":[0.0799,0.0686,0.064016],"vertex_offset":414450,"vertex_count":2502,"index_offset":429462,"index_count":16596,"index_bits":16}]},"right_ankle_roll_link":{"name":"right_ankle_roll_link","meshes":[{"file":"right_ankle_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.071262,-0.062702,-0.073327],"span":[0.219221,0.127237,0.105327],"vertex_offset":462654,"vertex_count":1284,"index_offset":470358,"index_count":15654,"index_bits":16}]},"waist_yaw_link":{"name":"waist_yaw_link","meshes":[{"file":"waist_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.066501,-0.066407,-0.00192],"span":[0.136,0.135868,0.107426],"vertex_offset":501666,"vertex_count":2519,"index_offset":516780,"index_count":19146,"index_bits":16}]},"waist_pitch_link":{"name":"waist_pitch_link","meshes":[{"file":"waist_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.014794,-0.0336,-0.014799],"span":[0.056394,0.0672,0.029598],"vertex_offset":555072,"vertex_count":2701,"index_offset":571278,"index_count":18138,"index_bits":16}]},"torso_link":{"name":"torso_link","meshes":[{"file":"torso_plus_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.170017,-0.145923,-0.014582],"span":[0.278206,0.297135,0.388253],"vertex_offset":607554,"vertex_count":446,"index_offset":610230,"index_count":6072,"index_bits":16}]},"imu_in_torso_link":{"name":"imu_in_torso_link","meshes":[{"file":"imu_in_torso_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.010671,-0.01315,-0.003637],"span":[0.02405,0.022427,0.014037],"vertex_offset":622374,"vertex_count":1004,"index_offset":628398,"index_count":7521,"index_bits":16}]},"left_shoulder_pitch_link":{"name":"left_shoulder_pitch_link","meshes":[{"file":"left_shoulder_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.036025,0.0,-0.044986],"span":[0.069291,0.0946,0.090176],"vertex_offset":643440,"vertex_count":2317,"index_offset":657342,"index_count":15162,"index_bits":16}]},"left_shoulder_roll_link":{"name":"left_shoulder_roll_link","meshes":[{"file":"left_shoulder_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.051908,-0.042503,-0.128576],"span":[0.104798,0.085005,0.171294],"vertex_offset":687666,"vertex_count":2155,"index_offset":700596,"index_count":18936,"index_bits":16}]},"left_shoulder_yaw_link":{"name":"left_shoulder_yaw_link","meshes":[{"file":"left_shoulder_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.042048,-0.042001,-0.119876],"span":[0.090311,0.084,0.139876],"vertex_offset":738468,"vertex_count":2147,"index_offset":751350,"index_count":17880,"index_bits":16}]},"left_elbow_link":{"name":"left_elbow_link","meshes":[{"file":"left_elbow_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.05349,-0.040201,-0.125599],"span":[0.080923,0.084666,0.153119],"vertex_offset":787110,"vertex_count":2226,"index_offset":800466,"index_count":16842,"index_bits":16}]},"left_wrist_yaw_link":{"name":"left_wrist_yaw_link","meshes":[{"file":"left_wrist_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.03979,-0.042547,-0.099227],"span":[0.079998,0.087047,0.102016],"vertex_offset":834150,"vertex_count":1808,"index_offset":844998,"index_count":15126,"index_bits":16}]},"left_wrist_pitch_link":{"name":"left_wrist_pitch_link","meshes":[{"file":"left_wrist_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.0355,-0.0305,-0.024725],"span":[0.0705,0.058,0.047725],"vertex_offset":875250,"vertex_count":2157,"index_offset":888192,"index_count":19212,"index_bits":16}]},"left_wrist_roll_link":{"name":"left_wrist_roll_link","meshes":[{"file":"left_wrist_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.041,-0.044168,-0.180866],"span":[0.096174,0.070314,0.197366],"vertex_offset":926616,"vertex_count":1712,"index_offset":936888,"index_count":13452,"index_bits":16}]},"right_shoulder_pitch_link":{"name":"right_shoulder_pitch_link","meshes":[{"file":"right_shoulder_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.035989,-0.0946,-0.045002],"span":[0.068996,0.0946,0.090002],"vertex_offset":963792,"vertex_count":2381,"index_offset":978078,"index_count":15510,"index_bits":16}]},"right_shoulder_roll_link":{"name":"right_shoulder_roll_link","meshes":[{"file":"right_shoulder_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.051901,-0.042502,-0.12855],"span":[0.104789,0.085005,0.17127],"vertex_offset":1009098,"vertex_count":2143,"index_offset":1021956,"index_count":19008,"index_bits":16}]},"right_shoulder_yaw_link":{"name":"right_shoulder_yaw_link","meshes":[{"file":"right_shoulder_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.041381,-0.041999,-0.118296],"span":[0.089644,0.084,0.138542],"vertex_offset":1059972,"vertex_count":2005,"index_offset":1072002,"index_count":15018,"index_bits":16}]},"right_elbow_link":{"name":"right_elbow_link","meshes":[{"file":"right_elbow_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.052234,-0.044465,-0.125494],"span":[0.080927,0.084667,0.153104],"vertex_offset":1102038,"vertex_count":2152,"index_offset":1114950,"index_count":16284,"index_bits":16}]},"right_wrist_yaw_link":{"name":"right_wrist_yaw_link","meshes":[{"file":"right_wrist_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.03808,-0.044499,-0.09903],"span":[0.080283,0.087047,0.10203],"vertex_offset":1147518,"vertex_count":1801,"index_offset":1158324,"index_count":15270,"index_bits":16}]},"right_wrist_pitch_link":{"name":"right_wrist_pitch_link","meshes":[{"file":"right_wrist_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.0355,-0.0275,-0.024725],"span":[0.0705,0.058,0.047725],"vertex_offset":1188864,"vertex_count":2148,"index_offset":1201752,"index_count":19164,"index_bits":16}]},"right_wrist_roll_link":{"name":"right_wrist_roll_link","meshes":[{"file":"right_wrist_roll_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.041,-0.026239,-0.180986],"span":[0.096433,0.070973,0.197486],"vertex_offset":1240080,"vertex_count":1782,"index_offset":1250772,"index_count":14226,"index_bits":16}]},"head_yaw_link":{"name":"head_yaw_link","meshes":[{"file":"head_yaw_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.06375,-0.05625,-0.0102],"span":[0.108249,0.112595,0.036301],"vertex_offset":1279224,"vertex_count":2002,"index_offset":1291236,"index_count":12672,"index_bits":16}]},"head_pitch_link":{"name":"head_pitch_link","meshes":[{"file":"head_pitch_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.083809,-0.071063,-0.083977],"span":[0.16395,0.142162,0.169877],"vertex_offset":1316580,"vertex_count":1465,"index_offset":1325370,"index_count":19098,"index_bits":16}]},"imu_in_head_link":{"name":"imu_in_head_link","meshes":[{"file":"imu_in_head_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.010704,-0.013179,-0.0036],"span":[0.024077,0.022466,0.014],"vertex_offset":1363566,"vertex_count":1008,"index_offset":1369614,"index_count":7632,"index_bits":16}]},"rgbd_head_front":{"name":"rgbd_head_front","meshes":[{"file":"rgbd_head_front_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.030684,-0.009356,-0.000675],"span":[0.083354,0.018756,0.000903],"vertex_offset":1384878,"vertex_count":244,"index_offset":1386342,"index_count":1440,"index_bits":16}]},"stereo_head_front":{"name":"stereo_head_front","meshes":[{"file":"stereo_head_front_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.009444,-0.0125,-0.02123],"span":[0.078889,0.025,0.023228],"vertex_offset":1389222,"vertex_count":1317,"index_offset":1397124,"index_count":7704,"index_bits":16}]},"rgb_head_rear":{"name":"rgb_head_rear","meshes":[{"file":"rgb_head_rear_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.0175,-0.01,-0.01855],"span":[0.035,0.02,0.020758],"vertex_offset":1412532,"vertex_count":933,"index_offset":1418130,"index_count":5970,"index_bits":16}]},"rgb_head_center":{"name":"rgb_head_center","meshes":[{"file":"rgb_head_center_link.STL","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"lo":[-0.015,-0.017,-0.0156],"span":[0.03,0.034,0.015945],"vertex_offset":1430070,"vertex_count":848,"index_offset":1435158,"index_count":6396,"index_bits":16}]},"lidar_chest_front":{"name":"lidar_chest_front","meshes":[]},"base_link":{"name":"base_link","meshes":[]}},"joints":[{"name":"imu_in_pelvis_joint","type":"fixed","parent":"pelvis","child":"imu_in_pelvis_link","origin":{"xyz":[0.0239464627920677,-0.00022868187247424,0.0417100000000296],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"left_hip_pitch_joint","type":"revolute","parent":"pelvis","child":"left_hip_pitch_link","origin":{"xyz":[0.0,0.0713499997541465,0.0],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-2.704,"upper":2.556,"effort":120.0,"velocity":11.936},{"name":"left_hip_roll_joint","type":"revolute","parent":"left_hip_pitch_link","child":"left_hip_roll_link","origin":{"xyz":[-0.000574999999960968,0.0657000000000312,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.235,"upper":2.906,"effort":120.0,"velocity":11.936},{"name":"left_hip_yaw_joint","type":"revolute","parent":"left_hip_roll_link","child":"left_hip_yaw_link","origin":{"xyz":[0.000574999999972778,0.0,-0.136850000000045],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-1.684,"upper":3.43,"effort":120.0,"velocity":11.936},{"name":"left_knee_joint","type":"revolute","parent":"left_hip_yaw_link","child":"left_knee_link","origin":{"xyz":[-0.00765999999995284,0.000225000000070329,-0.18309999999998],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":0.0,"upper":2.4073,"effort":120.0,"velocity":11.936},{"name":"left_ankle_pitch_joint","type":"revolute","parent":"left_knee_link","child":"left_ankle_pitch_link","origin":{"xyz":[-0.0100000000000136,-0.000124910735236235,-0.282000000000081],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-0.803,"upper":0.453,"effort":36.0,"velocity":13.087},{"name":"left_ankle_roll_joint","type":"revolute","parent":"left_ankle_pitch_link","child":"left_ankle_roll_link","origin":{"xyz":[-0.00174999998947351,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.262,"upper":0.262,"effort":24.0,"velocity":15.077},{"name":"right_hip_pitch_joint","type":"revolute","parent":"pelvis","child":"right_hip_pitch_link","origin":{"xyz":[0.0,-0.0713499997541464,0.0],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-2.704,"upper":2.556,"effort":120.0,"velocity":11.936},{"name":"right_hip_roll_joint","type":"revolute","parent":"right_hip_pitch_link","child":"right_hip_roll_link","origin":{"xyz":[0.0,-0.0657000004916197,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-2.906,"upper":0.235,"effort":120.0,"velocity":11.936},{"name":"right_hip_yaw_joint","type":"revolute","parent":"right_hip_roll_link","child":"right_hip_yaw_link","origin":{"xyz":[0.0,0.0,-0.136850000000023],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-3.43,"upper":1.684,"effort":120.0,"velocity":11.936},{"name":"right_knee_joint","type":"revolute","parent":"right_hip_yaw_link","child":"right_knee_link","origin":{"xyz":[-0.00766000000003646,-0.000225000000000253,-0.183100000000014],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":0.0,"upper":2.4073,"effort":120.0,"velocity":11.936},{"name":"right_ankle_pitch_joint","type":"revolute","parent":"right_knee_link","child":"right_ankle_pitch_link","origin":{"xyz":[-0.00999999999984942,0.000124910735223305,-0.282000000000021],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-0.803,"upper":0.453,"effort":36.0,"velocity":13.088},{"name":"right_ankle_roll_joint","type":"revolute","parent":"right_ankle_pitch_link","child":"right_ankle_roll_link","origin":{"xyz":[-0.00174999998537372,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.2625,"upper":0.2625,"effort":24.0,"velocity":15.077},{"name":"waist_yaw_joint","type":"revolute","parent":"pelvis","child":"waist_yaw_link","origin":{"xyz":[0.0,0.0,0.0670600000000297],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-3.43,"upper":2.382,"effort":120.0,"velocity":11.936},{"name":"waist_pitch_joint","type":"revolute","parent":"waist_yaw_link","child":"waist_pitch_link","origin":{"xyz":[0.0,0.0,0.0880106468356499],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-0.314,"upper":0.314,"effort":48.0,"velocity":13.088},{"name":"waist_roll_joint","type":"revolute","parent":"waist_pitch_link","child":"torso_link","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.488,"upper":0.488,"effort":48.0,"velocity":13.088},{"name":"imu_in_torso_joint","type":"fixed","parent":"torso_link","child":"imu_in_torso_link","origin":{"xyz":[-0.0248787003951661,0.0019852778697029,0.105938055641669],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"left_shoulder_pitch_joint","type":"revolute","parent":"torso_link","child":"left_shoulder_pitch_link","origin":{"xyz":[0.00329906676354264,0.143031506663431,0.241647721005027],"rpy":[0.209439453777995,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-3.08,"upper":2.04,"effort":36.0,"velocity":13.088},{"name":"left_shoulder_roll_joint","type":"revolute","parent":"left_shoulder_pitch_link","child":"left_shoulder_roll_link","origin":{"xyz":[-0.000499991072907324,0.0495,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.061,"upper":2.993,"effort":36.0,"velocity":13.088},{"name":"left_shoulder_yaw_joint","type":"revolute","parent":"left_shoulder_roll_link","child":"left_shoulder_yaw_link","origin":{"xyz":[0.00122423638490546,0.0,-0.121194848262102],"rpy":[0.0,-0.00597565694965793,0.0]},"axis":[0.0,0.0,1.0],"lower":-2.556,"upper":2.556,"effort":24.0,"velocity":15.077},{"name":"left_elbow_joint","type":"revolute","parent":"left_shoulder_yaw_link","child":"left_elbow_link","origin":{"xyz":[0.0140000000488655,0.000199986464082369,-0.0829500000002385],"rpy":[0.0,0.00597565694965793,0.0]},"axis":[0.0,1.0,0.0],"lower":-2.3556,"upper":0.0,"effort":24.0,"velocity":15.077},{"name":"left_wrist_yaw_joint","type":"revolute","parent":"left_elbow_link","child":"left_wrist_yaw_link","origin":{"xyz":[-0.0132797235062217,-9.75487744990788e-05,-0.120575783591803],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-2.556,"upper":2.556,"effort":24.0,"velocity":15.077},{"name":"left_wrist_pitch_joint","type":"revolute","parent":"left_wrist_yaw_link","child":"left_wrist_pitch_link","origin":{"xyz":[0.000490001227040848,0.0,-0.0819985359552045],"rpy":[0.0,-0.00597566028430406,0.0]},"axis":[0.0,1.0,0.0],"lower":-0.558,"upper":0.558,"effort":4.8,"velocity":4.188},{"name":"left_wrist_roll_joint","type":"revolute","parent":"left_wrist_pitch_link","child":"left_wrist_roll_link","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-1.571,"upper":0.724,"effort":4.8,"velocity":4.188},{"name":"right_shoulder_pitch_joint","type":"revolute","parent":"torso_link","child":"right_shoulder_pitch_link","origin":{"xyz":[0.00330093831251838,-0.143030971450747,0.241648201390685],"rpy":[-0.209442812383636,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-3.08,"upper":2.04,"effort":36.0,"velocity":13.088},{"name":"right_shoulder_roll_joint","type":"revolute","parent":"right_shoulder_pitch_link","child":"right_shoulder_roll_link","origin":{"xyz":[-0.000499999994070091,-0.0495000000000002,0.0],"rpy":[0.0,0.000154003092926045,0.0]},"axis":[1.0,0.0,0.0],"lower":-2.993,"upper":0.061,"effort":36.0,"velocity":13.088},{"name":"right_shoulder_yaw_joint","type":"revolute","parent":"right_shoulder_roll_link","child":"right_shoulder_yaw_link","origin":{"xyz":[0.000499999999999765,0.0,-0.121199999999934],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-2.556,"upper":2.556,"effort":24.0,"velocity":15.077},{"name":"right_elbow_joint","type":"revolute","parent":"right_shoulder_yaw_link","child":"right_elbow_link","origin":{"xyz":[0.0139999999999662,-0.0002000000000143,-0.0829500000000745],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-2.3556,"upper":0.0,"effort":24.0,"velocity":15.077},{"name":"right_wrist_yaw_joint","type":"revolute","parent":"right_elbow_link","child":"right_wrist_yaw_link","origin":{"xyz":[-0.0140000017961392,9.7526096753231e-05,-0.120694276209686],"rpy":[0.0,0.0,3.27341906322599e-05]},"axis":[0.0,0.0,1.0],"lower":-2.556,"upper":2.556,"effort":24.0,"velocity":15.077},{"name":"right_wrist_pitch_joint","type":"revolute","parent":"right_wrist_yaw_link","child":"right_wrist_pitch_link","origin":{"xyz":[0.0,0.0,-0.081799999999999],"rpy":[0.0,0.0,-3.27341932546355e-05]},"axis":[0.0,1.0,0.0],"lower":-0.558,"upper":0.558,"effort":4.8,"velocity":4.188},{"name":"right_wrist_roll_joint","type":"revolute","parent":"right_wrist_pitch_link","child":"right_wrist_roll_link","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[1.0,0.0,0.0],"lower":-0.724,"upper":1.571,"effort":4.8,"velocity":4.188},{"name":"head_yaw_joint","type":"revolute","parent":"torso_link","child":"head_yaw_link","origin":{"xyz":[0.00834772789983268,0.0,0.309397077276121],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":-0.366,"upper":0.366,"effort":2.6,"velocity":6.019},{"name":"head_pitch_joint","type":"revolute","parent":"head_yaw_link","child":"head_pitch_link","origin":{"xyz":[0.0,0.0,0.0889],"rpy":[0.0,0.0,0.0]},"axis":[0.0,1.0,0.0],"lower":-0.3838,"upper":0.3838,"effort":0.6,"velocity":6.28},{"name":"imu_in_head_joint","type":"fixed","parent":"head_pitch_link","child":"imu_in_head_link","origin":{"xyz":[0.0259998716312927,-8.2538922380776e-05,0.0175999960932565],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"rgbd_head_front","type":"fixed","parent":"head_pitch_link","child":"rgbd_head_front","origin":{"xyz":[0.05761,-0.011183,-0.04837],"rpy":[2.2689,0.0,1.5708]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"stereo_head_front","type":"fixed","parent":"head_pitch_link","child":"stereo_head_front","origin":{"xyz":[0.067995,0.029784,0.05],"rpy":[-1.5708,0.0,-1.574]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"rgb_head_rear","type":"fixed","parent":"head_pitch_link","child":"rgb_head_rear","origin":{"xyz":[-0.0834,0.00026495,0.0],"rpy":[-1.5708,0.0,1.5676]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"rgb_head_center","type":"fixed","parent":"head_pitch_link","child":"rgb_head_center","origin":{"xyz":[0.0684,-0.00021713,0.05],"rpy":[-1.5708,0.0,-1.574]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"lidar_chest_front","type":"fixed","parent":"torso_link","child":"lidar_chest_front","origin":{"xyz":[0.102632855873251,0.0,0.181586916322065],"rpy":[-1.5707963267949,0.0,0.0]},"axis":[0.0,0.0,0.0],"lower":null,"upper":null,"effort":null,"velocity":null},{"name":"base_link_joint","type":"fixed","parent":"base_link","child":"pelvis","origin":{"xyz":[0.0,0.0,0.0],"rpy":[0.0,0.0,0.0]},"axis":[0.0,0.0,1.0],"lower":null,"upper":null,"effort":null,"velocity":null}],"geometry_bytes":1447950} \ No newline at end of file diff --git a/x2_dashboard_agent/ensure_agent.sh b/x2_dashboard_agent/ensure_agent.sh new file mode 100644 index 0000000..c0bd40e --- /dev/null +++ b/x2_dashboard_agent/ensure_agent.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Idempotent starter for the X2 dashboard agent. +# +# Run this every minute from cron. If the agent is already up it does nothing; +# if it is not, it starts it. That covers three cases with one mechanism: +# * boot - the robot came back and nobody logged in +# * crash - the process died +# * manual kill - someone stopped it by hand +# +# Why not systemd? The agi account cannot enable linger (`loginctl +# enable-linger` is denied, and sudo forbids running as root here), so a +# `systemd --user` unit only runs while a login session exists - which is +# exactly not the case after a power cycle. A cron watchdog needs no root and +# does not depend on @reboot firing correctly. + +set -e + +DIR="$(dirname "$(readlink -f "$0")")" +PORT="${X2_AGENT_PORT:-8781}" +LOG="$DIR/agent.log" + +# Already listening? Nothing to do. Checking the port rather than the process +# also catches a process that is alive but wedged before binding. +if ss -ltn 2>/dev/null | grep -q ":${PORT} "; then + exit 0 +fi + +# Avoid stacking instances if a previous start is still coming up. +if pgrep -f "x2_agent.py" >/dev/null 2>&1; then + exit 0 +fi + +echo "[$(date -Is)] agent not listening on ${PORT} - starting" >> "$LOG" + +# Keep the log from growing without bound (cron runs this every minute). +if [ -f "$LOG" ] && [ "$(stat -c%s "$LOG" 2>/dev/null || echo 0)" -gt 1000000 ]; then + tail -n 200 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG" +fi + +setsid nohup "$DIR/run_agent.sh" >> "$LOG" 2>&1 < /dev/null & +exit 0 diff --git a/x2_dashboard_agent/run_agent.sh b/x2_dashboard_agent/run_agent.sh new file mode 100644 index 0000000..7c97053 --- /dev/null +++ b/x2_dashboard_agent/run_agent.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Launcher for the X2 dashboard agent. Sources ROS 2 and the AimDK workspace, +# then runs the agent. Used both interactively and by the systemd --user unit. +# +# Note: no `set -u` here. The ROS 2 setup scripts read variables that are not +# defined on a fresh shell (AMENT_TRACE_SETUP_FILES among them), so nounset +# makes sourcing them fail outright. + +set -e + +export RCUTILS_LOGGING_SEVERITY="${RCUTILS_LOGGING_SEVERITY:-ERROR}" +export ROS_DOMAIN_ID="${ROS_DOMAIN_ID:-0}" + +# shellcheck disable=SC1091 +source /opt/ros/humble/setup.bash + +if [ -f "$HOME/aimdk/install/setup.bash" ]; then + # shellcheck disable=SC1091 + source "$HOME/aimdk/install/setup.bash" +fi + +# Fast DDS profile - REQUIRED for the camera and LiDAR topics. +# +# A camera frame off this robot is 170-430 KB and a LiDAR scan is 816 KB. Fast +# DDS defaults to a 512 KB shared-memory segment and small socket buffers, and +# it drops samples that large in complete silence: discovery succeeds, the +# reader matches the writer, `ros2 topic info` reports a publisher, and not one +# message is ever delivered. The vendor profile raises the SHM segment to 32 MB +# and the UDP buffers to 10 MB, which is the entire reason those topics work. +# +# This is why an earlier revision of backend/x2_spec.py concluded that the unit +# had one camera and no chest LiDAR. It has six feeds and a LiDAR; the agent +# just could not receive them without this line. +DDS_PROFILE="${FASTRTPS_DEFAULT_PROFILES_FILE:-/agibot/data/home/agi/.aima/env/ros_dds_configuration.xml}" +if [ -f "$DDS_PROFILE" ]; then + export FASTRTPS_DEFAULT_PROFILES_FILE="$DDS_PROFILE" +else + echo "[run_agent] WARNING: no DDS profile at $DDS_PROFILE - camera and LiDAR feeds will connect but deliver nothing" >&2 +fi + +# -u keeps the agent's own prints unbuffered so they reach the journal promptly. +# Fast DDS writes a very high volume of discovery chatter to stderr; the systemd +# unit sends stderr to /dev/null so it does not swamp the journal. Run this +# script by hand if you need to see it. +exec python3 -u "$(dirname "$(readlink -f "$0")")/x2_agent.py" "$@" diff --git a/x2_dashboard_agent/run_agent.sh.bak b/x2_dashboard_agent/run_agent.sh.bak new file mode 100644 index 0000000..eea437b --- /dev/null +++ b/x2_dashboard_agent/run_agent.sh.bak @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Launcher for the X2 dashboard agent. Sources ROS 2 and the AimDK workspace, +# then runs the agent. Used both interactively and by the systemd --user unit. +# +# Note: no `set -u` here. The ROS 2 setup scripts read variables that are not +# defined on a fresh shell (AMENT_TRACE_SETUP_FILES among them), so nounset +# makes sourcing them fail outright. + +set -e + +export RCUTILS_LOGGING_SEVERITY="${RCUTILS_LOGGING_SEVERITY:-ERROR}" +export ROS_DOMAIN_ID="${ROS_DOMAIN_ID:-0}" + +# shellcheck disable=SC1091 +source /opt/ros/humble/setup.bash + +if [ -f "$HOME/aimdk/install/setup.bash" ]; then + # shellcheck disable=SC1091 + source "$HOME/aimdk/install/setup.bash" +fi + +# -u keeps the agent's own prints unbuffered so they reach the journal promptly. +# Fast DDS writes a very high volume of discovery chatter to stderr; the systemd +# unit sends stderr to /dev/null so it does not swamp the journal. Run this +# script by hand if you need to see it. +exec python3 -u "$(dirname "$(readlink -f "$0")")/x2_agent.py" "$@" diff --git a/x2_dashboard_agent/run_dashboard.sh b/x2_dashboard_agent/run_dashboard.sh new file mode 100644 index 0000000..398020d --- /dev/null +++ b/x2_dashboard_agent/run_dashboard.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Bring the X2 dashboard up ON THE ROBOT and keep it up. +# +# The dashboard is served by the robot itself, so the link people open is the +# robot's own address - http://:8770. Nothing depends on any laptop +# being switched on, and when the robot joins a different Wi-Fi the link simply +# follows its new address. +# +# Idempotent by design: it starts only what is not already running, so it is +# safe to call from cron every minute, from @reboot, and by hand. +# +# No `set -u` - the ROS setup scripts read undefined variables. + +set -e + +DIR="$(dirname "$(readlink -f "$0")")" +LOG_DIR="/home/agi/x2_dashboard_logs" +AGENT_PORT="${X2_AGENT_PORT:-8781}" +WEB_PORT="${X2_WEB_PORT:-8770}" + +mkdir -p "$LOG_DIR" + +listening() { + ss -ltn 2>/dev/null | grep -q ":$1 " +} + +# The previous guard here was `pgrep -f "x2_dashboard/-m backend|backend.server"`, +# and neither alternative can match the real command line, which is plain +# `python3 -m backend`. That left the port check as the only guard, and the port +# is not bound for the first ~10 s of startup - so the every-minute timer fired +# again mid-boot and launched a second backend on top of the first. That is the +# recurring "[Errno 98] address already in use" in dashboard.log. +# +# Matching on /proc rather than trusting pgrep alone: `pgrep -f` also matches any +# shell whose command line merely mentions the pattern, so require python argv[0]. +backend_running() { + local p cmd + for p in $(pgrep -f 'python3 -m backend' 2>/dev/null); do + cmd=$(tr '\0' ' ' < "/proc/$p/cmdline" 2>/dev/null) + case "$cmd" in + python*|*/python*) return 0 ;; + esac + done + return 1 +} + +trim() { # keep the logs from growing without bound + [ -f "$1" ] || return 0 + if [ "$(stat -c%s "$1" 2>/dev/null || echo 0)" -gt 2000000 ]; then + tail -n 300 "$1" > "$1.tmp" && mv "$1.tmp" "$1" + fi +} + +# 1. the ROS bridge ------------------------------------------------------- +if ! listening "$AGENT_PORT" && ! pgrep -f "x2_agent.py" >/dev/null 2>&1; then + trim "$LOG_DIR/agent.log" + echo "[$(date -Is)] starting agent" >> "$LOG_DIR/agent.log" + setsid nohup "$DIR/run_agent.sh" >> "$LOG_DIR/agent.log" 2>&1 < /dev/null & + sleep 3 +fi + +# 2. the web dashboard ---------------------------------------------------- +if ! listening "$WEB_PORT" && ! backend_running; then + trim "$LOG_DIR/dashboard.log" + echo "[$(date -Is)] starting dashboard" >> "$LOG_DIR/dashboard.log" + cd /home/agi/x2_dashboard + # The dashboard talks to the agent over localhost and needs no ROS itself, + # but sourcing costs nothing and keeps one environment for both. + setsid nohup env PYTHONUNBUFFERED=1 python3 -m backend \ + >> "$LOG_DIR/dashboard.log" 2>&1 < /dev/null & +fi + +exit 0 diff --git a/x2_dashboard_agent/run_dashboard.sh.bak-20260805-204141 b/x2_dashboard_agent/run_dashboard.sh.bak-20260805-204141 new file mode 100644 index 0000000..44985a3 --- /dev/null +++ b/x2_dashboard_agent/run_dashboard.sh.bak-20260805-204141 @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Bring the X2 dashboard up ON THE ROBOT and keep it up. +# +# The dashboard is served by the robot itself, so the link people open is the +# robot's own address - http://:8770. Nothing depends on any laptop +# being switched on, and when the robot joins a different Wi-Fi the link simply +# follows its new address. +# +# Idempotent by design: it starts only what is not already running, so it is +# safe to call from cron every minute, from @reboot, and by hand. +# +# No `set -u` - the ROS setup scripts read undefined variables. + +set -e + +DIR="$(dirname "$(readlink -f "$0")")" +LOG_DIR="/home/agi/x2_dashboard_logs" +AGENT_PORT="${X2_AGENT_PORT:-8781}" +WEB_PORT="${X2_WEB_PORT:-8770}" + +mkdir -p "$LOG_DIR" + +listening() { + ss -ltn 2>/dev/null | grep -q ":$1 " +} + +trim() { # keep the logs from growing without bound + [ -f "$1" ] || return 0 + if [ "$(stat -c%s "$1" 2>/dev/null || echo 0)" -gt 2000000 ]; then + tail -n 300 "$1" > "$1.tmp" && mv "$1.tmp" "$1" + fi +} + +# 1. the ROS bridge ------------------------------------------------------- +if ! listening "$AGENT_PORT" && ! pgrep -f "x2_agent.py" >/dev/null 2>&1; then + trim "$LOG_DIR/agent.log" + echo "[$(date -Is)] starting agent" >> "$LOG_DIR/agent.log" + setsid nohup "$DIR/run_agent.sh" >> "$LOG_DIR/agent.log" 2>&1 < /dev/null & + sleep 3 +fi + +# 2. the web dashboard ---------------------------------------------------- +if ! listening "$WEB_PORT" && ! pgrep -f "x2_dashboard/-m backend|backend.server" >/dev/null 2>&1; then + trim "$LOG_DIR/dashboard.log" + echo "[$(date -Is)] starting dashboard" >> "$LOG_DIR/dashboard.log" + cd /home/agi/x2_dashboard + # The dashboard talks to the agent over localhost and needs no ROS itself, + # but sourcing costs nothing and keeps one environment for both. + setsid nohup env PYTHONUNBUFFERED=1 python3 -m backend \ + >> "$LOG_DIR/dashboard.log" 2>&1 < /dev/null & +fi + +exit 0 diff --git a/x2_dashboard_agent/x2-dashboard-agent.service b/x2_dashboard_agent/x2-dashboard-agent.service new file mode 100644 index 0000000..2c5630a --- /dev/null +++ b/x2_dashboard_agent/x2-dashboard-agent.service @@ -0,0 +1,29 @@ +[Unit] +Description=AGIBOT X2 dashboard agent (ROS 2 to TCP bridge) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=agi +WorkingDirectory=/home/agi/x2_dashboard_agent +ExecStart=/home/agi/x2_dashboard_agent/run_agent.sh +Restart=always +RestartSec=5 +TimeoutStopSec=15 +KillMode=mixed +# The robot's own stack takes a while to come up after power-on; the agent +# tolerates an empty graph and fills in as topics appear, so starting early is +# fine and means the dashboard attaches as soon as possible. +StandardOutput=journal +StandardError=journal +# Fast DDS writes a very high volume of discovery chatter (to stdout, alongside +# the agent's own messages, so it cannot simply be dropped). Rate-limiting keeps +# the journal from being swamped while still letting the agent's lines through. +LogRateLimitIntervalSec=30s +LogRateLimitBurst=300 +Environment=RCUTILS_LOGGING_SEVERITY=ERROR +Environment=ROS_DOMAIN_ID=0 + +[Install] +WantedBy=multi-user.target diff --git a/x2_dashboard_agent/x2_agent.py b/x2_dashboard_agent/x2_agent.py new file mode 100644 index 0000000..3902060 --- /dev/null +++ b/x2_dashboard_agent/x2_agent.py @@ -0,0 +1,1477 @@ +#!/usr/bin/env python3 +""" +AGIBOT X2 dashboard agent - runs ON the robot (PC2). + +Why this exists +--------------- +A browser cannot speak ROS 2 DDS, and the dashboard is meant to stay reachable +even when the robot is switched off (so it can show "power the robot on" rather +than a dead link). So the dashboard server lives on the operator's machine and +this small agent lives on the robot, bridging ROS 2 to a plain TCP socket. + +Protocol: newline-delimited JSON, no dependencies beyond rclpy. + + -> {"type":"hello","data":{...}} (agent, on connect) + -> {"type":"state","data":{...}} (agent, ~10 Hz) + <- {"type":"cmd","id":7,"name":"set_mode","args":{}} (client) + -> {"type":"result","id":7,"ok":true,"message":"..."} (agent) + +Run it with ROS 2 and the AimDK workspace sourced: + + source /opt/ros/humble/setup.bash + source ~/aimdk/install/setup.bash + python3 x2_agent.py +""" + +from __future__ import annotations + +import argparse +import asyncio +import base64 +import importlib +import json +import math +import os +import signal +import socket +import threading +import time +import traceback + +os.environ.setdefault("RCUTILS_LOGGING_SEVERITY", "ERROR") + +import rclpy # noqa: E402 +from rclpy.callback_groups import MutuallyExclusiveCallbackGroup # noqa: E402 +from rclpy.executors import MultiThreadedExecutor # noqa: E402 +from rclpy.qos import ( # noqa: E402 + QoSProfile, ReliabilityPolicy, DurabilityPolicy, HistoryPolicy, +) + +VERSION = "1.1.0" +DEFAULT_PORT = 8781 + +# -------------------------------------------------------------------------- +# Interface constants - these mirror backend/x2_spec.py and were read off this +# robot's own aimdk_msgs package. +# -------------------------------------------------------------------------- + +SRV = { + "get_mode": ("aimdk_msgs/srv/GetMcAction", "/aimdk_5Fmsgs/srv/GetMcAction"), + "set_mode": ("aimdk_msgs/srv/SetMcAction", "/aimdk_5Fmsgs/srv/SetMcAction"), + "preset": ("aimdk_msgs/srv/SetMcPresetMotion", "/aimdk_5Fmsgs/srv/SetMcPresetMotion"), + "set_source": ("aimdk_msgs/srv/SetMcInputSource", "/aimdk_5Fmsgs/srv/SetMcInputSource"), + "get_source": ("aimdk_msgs/srv/GetCurrentInputSource", "/aimdk_5Fmsgs/srv/GetCurrentInputSource"), + "tts": ("aimdk_msgs/srv/PlayTts", "/aimdk_5Fmsgs/srv/PlayTts"), + "emoji": ("aimdk_msgs/srv/PlayEmoji", "/aimdk_5Fmsgs/srv/PlayEmoji"), + "led": ("aimdk_msgs/srv/SetPmuLed", "/aimdk_5Fmsgs/srv/SetPmuLed"), + "set_volume": ("aimdk_msgs/srv/SetVolume", "/aimdk_5Fmsgs/srv/SetVolume"), + "get_volume": ("aimdk_msgs/srv/GetVolume", "/aimdk_5Fmsgs/srv/GetVolume"), + "set_mute": ("aimdk_msgs/srv/SetMute", "/aimdk_5Fmsgs/srv/SetMute"), + "get_mute": ("aimdk_msgs/srv/GetMute", "/aimdk_5Fmsgs/srv/GetMute"), + "hand_type": ("aimdk_msgs/srv/GetHandType", "/aimdk_5Fmsgs/srv/GetHandType"), +} + +TOPIC_PMU = "/aima/hal/pmu/state" +TOPIC_IMU_CHEST = "/aima/hal/imu/chest/state" +TOPIC_IMU_TORSO = "/aima/hal/imu/torso/state" +TOPIC_TOUCH = "/aima/hal/sensor/touch_head" +TOPIC_HAND_STATE = "/aima/hal/joint/hand/state" +TOPIC_HAND_CMD = "/aima/hal/joint/hand/command" +TOPIC_VELOCITY = "/aima/mc/locomotion/velocity" +TOPIC_ODOM = "/aima/mc/leg_odometry" +TOPIC_FACE = "/face_ui_proxy/status" + +JOINT_GROUPS = { + "head": ("/aima/hal/joint/head/state", "/aima/hal/joint/head/command"), + "waist": ("/aima/hal/joint/waist/state", "/aima/hal/joint/waist/command"), + "arm": ("/aima/hal/joint/arm/state", "/aima/hal/joint/arm/command"), + "leg": ("/aima/hal/joint/leg/state", "/aima/hal/joint/leg/command"), +} + +# Every camera on this robot, verified against the live ROS graph rather than +# the datasheet. All of them are *on demand*: nothing is subscribed until the +# operator switches a feed on. A compressed frame off this robot is 170-430 KB +# and the six RGB feeds together publish at ~60 Hz, so subscribing to the lot at +# startup would push ~15 MB/s through the DDS stack for pictures nobody is +# looking at - on the same Wi-Fi the robot uses to walk. +# +# `flip` is a per-feed default the browser can override. Every value below was +# set by pulling a real frame and looking at it, not by guessing: +# * both head cameras and the stereo pair are mounted upright +# * the Orbbec RGB-D module is mounted UPSIDE DOWN - its colour frame shows +# the floor across the top and the chairs hanging from it - so its colour +# and depth feeds both default to a 180 rotation. +CAMERAS = { + "rgb_head_front_center": { + "topic": "/aima/hal/sensor/rgb_head_front_center/rgb_image/compressed", + "type": "sensor_msgs/msg/CompressedImage", "kind": "rgb", "flip": False, + }, + "rgb_head_rear": { + "topic": "/aima/hal/sensor/rgb_head_rear/rgb_image/compressed", + "type": "sensor_msgs/msg/CompressedImage", "kind": "rgb", "flip": False, + }, + "rgbd_head_front": { + "topic": "/aima/hal/sensor/rgbd_head_front/rgb_image/compressed", + "type": "sensor_msgs/msg/CompressedImage", "kind": "rgb", "flip": True, + }, + "stereo_head_front_left": { + "topic": "/aima/hal/sensor/stereo_head_front_left/rgb_image/compressed", + "type": "sensor_msgs/msg/CompressedImage", "kind": "rgb", "flip": False, + }, + "stereo_head_front_right": { + "topic": "/aima/hal/sensor/stereo_head_front_right/rgb_image/compressed", + "type": "sensor_msgs/msg/CompressedImage", "kind": "rgb", "flip": False, + }, + "depth_front": { + "topic": "/camera/depth/image_raw/compressedDepth", + "type": "sensor_msgs/msg/CompressedImage", "kind": "depth", "flip": True, + }, + "perception_input": { + "topic": "/mono_perception/debug/input_image", + "type": "sensor_msgs/msg/CompressedImage", "kind": "debug", "flip": False, + }, + "perception_seg": { + "topic": "/mono_perception/debug/seg_mask", + "type": "sensor_msgs/msg/CompressedImage", "kind": "debug", "flip": False, + }, + "perception_lines": { + "topic": "/mono_perception/debug/line_color_map", + "type": "sensor_msgs/msg/CompressedImage", "kind": "debug", "flip": False, + }, +} + +# Chest LiDAR. 25.5k points per scan at 2 Hz, 816 KB a message - far too much to +# hold open for a tab nobody has opened, so it is on demand like the cameras. +LIDAR_KEY = "lidar_chest_front" +LIDAR = { + "topic": "/aima/hal/sensor/lidar_chest_front/lidar_pointcloud_down_sampling", + "type": "sensor_msgs/msg/PointCloud2", "kind": "lidar", +} + +# Points kept per scan after decimation. The browser draws these as a point +# cloud; beyond a few thousand the JSON hop costs more than the picture gains. +LIDAR_MAX_POINTS = 4000 + +# compressedDepth frames carry a 12-byte ConfigHeader before the PNG payload +# (an int32 format enum plus two float32 quantisation params). Verified by +# decoding a real frame off this robot: strip 12 and a 720x1280 uint16 image +# decodes; strip 8, 16 or 20 and it does not. +DEPTH_HEADER_BYTES = 12 +# Depth arrives in millimetres. Measured maximum return on this unit is ~4.2 m, +# so the ramp covers 4.5 m: stretching it to 6 m spent a third of the colour +# range on distances the sensor never reports, and flattened the near field +# everyone actually looks at into a single shade of blue. +DEPTH_RANGE_MM = 4500 + +MC_ACTION_VALUES = { + "PASSIVE_DEFAULT": 1, "SOFT_EMERGENCY_STOP": 2, "DAMPING_DEFAULT": 3, + "ZERO_TORQUE_DEFAULT": 4, "JOINT_DEFAULT": 100, "JOINT_FREEZE": 101, + "STAND_DEFAULT": 200, "STAND_BODY_CONTROL": 201, "LOCOMOTION_DEFAULT": 300, + "RUN_DEFAULT": 301, "LOCOMOTION_STEP": 302, "VR_REMOTE_CONTROLLER": 400, + "SIT_DOWN_DEFAULT": 2000, "CROUCH_DOWN_DEFAULT": 2002, "LIE_DOWN_DEFAULT": 2004, + "STAND_UP_DEFAULT": 2005, "ASCEND_STAIRS": 2006, "DESCEND_STAIRS": 2008, +} +MC_VALUE_TO_NAME = {v: k for k, v in MC_ACTION_VALUES.items()} + +PMU_RAILS = [ + ("bus_48v", "bus_48v_voltage", "bus_48v_current", 48.0), + ("output_48v", "output_48v_voltage", "output_48v_current", 48.0), + ("output_12v", "output_12v_voltage", "output_12v_current", 12.0), + ("head_power", "head_power_voltage", "head_power_current", 24.0), + ("orin", "orin_voltage", "orin_current", 19.0), + ("rk3588", "rk3588_voltage", "rk3588_current", 12.0), + ("fan", "fan_voltage", None, 12.0), + ("bus_48v_pmos", "bus_48v_pmos_voltage", None, 48.0), +] + +DRIVEABLE_MODES = {"LOCOMOTION_DEFAULT", "LOCOMOTION_STEP", "RUN_DEFAULT", + "STAND_DEFAULT", "STAND_BODY_CONTROL"} + +DEADMAN_S = 0.5 +VELOCITY_HZ = 20 + + +def load_type(path: str): + pkg, kind, name = path.split("/") + return getattr(importlib.import_module(f"{pkg}.{kind}"), name) + + +def seq(value): + """ + Normalise a ROS array field to a plain list. + + Fixed-size array fields come back as numpy arrays, where `value or default` + raises ValueError instead of testing emptiness. Everything that touches an + array field goes through here. + """ + if value is None: + return [] + try: + return list(value) + except TypeError: + return [] + + +def quat_to_rpy(x, y, z, w): + roll = math.atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)) + s = 2 * (w * y - z * x) + pitch = math.copysign(math.pi / 2, s) if abs(s) >= 1 else math.asin(s) + yaw = math.atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z)) + return roll, pitch, yaw + + +def flatten(msg, depth=0): + """ROS message -> JSON-safe dict.""" + if depth > 3: + return None + try: + fields = msg.get_fields_and_field_types() + except AttributeError: + return msg if isinstance(msg, (int, float, str, bool)) else str(msg)[:120] + out = {} + for name in fields: + value = getattr(msg, name, None) + if isinstance(value, (int, float, str, bool)): + out[name] = value + elif hasattr(value, "get_fields_and_field_types"): + out[name] = flatten(value, depth + 1) + else: + try: + out[name] = [flatten(v, depth + 1) for v in list(value)[:32]] + except TypeError: + pass + return out + + +class Agent: + def __init__(self, node): + self.node = node + self.lock = threading.Lock() + self.state = { + "agent_version": VERSION, + "hostname": socket.gethostname(), + "mode": "UNKNOWN", "mode_desc": "", "mode_value": None, "mode_status": "", + "battery_pct": None, "battery_voltage": None, "battery_current": None, + "battery_temp": None, "battery_cycles": None, "battery_capacity_mah": None, + "battery_power": None, "charging": False, + "pmu_temp": None, "fan_rpm": None, "fan_pct": None, + "rails": {}, "pmu_info": {}, "pmu_raw": {}, + "imu": {}, "joints": {}, "hand_type": "None", "hand_state": {}, + "touch_head": {"touched": False, "zones": []}, + "velocity": {"forward": 0.0, "lateral": 0.0, "angular": 0.0}, + "velocity_command": {"forward": 0.0, "lateral": 0.0, "angular": 0.0}, + "odom": {"x": 0.0, "y": 0.0, "yaw": 0.0}, + "volume": None, "muted": False, "emoji_id": None, "face_status": None, + "led": {"mode": 0, "r": 0, "g": 0, "b": 0}, + "input_source": "", "source_registered": False, + "topic_stats": {}, "cameras": {}, "streams": {}, + } + self.frames = {} # camera key -> (ts, bytes, format) + self.clients = set() + self.publishers = {} + self.service_clients = {} + self.last_velocity_cmd = 0.0 + self.led_keepalive = None + self.loop = None + + # -- on-demand streams ------------------------------------------------ + # Cameras and the LiDAR are not subscribed until asked for. `_streams` + # is the live registry; `_stream_wanted` is what the operator has asked + # for. The two are reconciled on the executor thread (see + # _reconcile_streams) because rclpy entity creation is not thread-safe. + self._streams = {} # key -> {"sub": obj, "spec": dict} + self._stream_wanted = {} # key -> bool + self._stream_lock = threading.Lock() + + # Callback groups matter enormously here, and getting them wrong fails + # silently. Three separate groups, for three separate reasons: + # + # * Everything defaults into ONE MutuallyExclusiveCallbackGroup, which + # runs one callback at a time for the whole node. That group already + # carries two 500 Hz IMUs, four 100 Hz joint arrays and 100 Hz touch. + # Adding six camera feeds on top - each callback copying 170-430 KB - + # starved the reconcile timer within seconds of the first camera + # delivering data: switching feeds on and off stopped working while + # telemetry carried on looking perfectly healthy. + # + # * The timer therefore gets a group to itself, so nothing can delay it. + # + # * The streams get their own MutuallyExclusive group - deliberately NOT + # Reentrant. A reentrant group has no concurrency limit, so seven live + # feeds happily occupied all six executor threads and starved the + # timer all over again, just more slowly. Serialising them costs + # nothing (each callback is a memcpy - 60 frames/s measured at about + # 3% of one thread) and bounds their thread use at exactly one. + self._stream_group = MutuallyExclusiveCallbackGroup() + self._control_group = MutuallyExclusiveCallbackGroup() + self.cloud = None # (ts, [[x,y,z,intensity], ...]) + for key in list(CAMERAS) + [LIDAR_KEY]: + self.state["streams"][key] = { + "key": key, "active": False, "frames": 0, "last": None, + "since": None, "error": "", + } + + self._setup() + + # -- ROS wiring --------------------------------------------------------- + + def _qos(self, reliable=True, transient=False, depth=5): + return QoSProfile( + reliability=ReliabilityPolicy.RELIABLE if reliable else ReliabilityPolicy.BEST_EFFORT, + durability=DurabilityPolicy.TRANSIENT_LOCAL if transient else DurabilityPolicy.VOLATILE, + history=HistoryPolicy.KEEP_LAST, depth=depth, + ) + + def _sub(self, type_path, topic, handler, depth=2): + """ + Subscribe with BEST_EFFORT + VOLATILE. + + In DDS a reader matches a writer when the writer *offers at least* what + the reader *requests*. BEST_EFFORT/VOLATILE requests the least of + anything, so this one profile matches every publisher on the robot - + the RELIABLE ones and the TRANSIENT_LOCAL ones alike. Requesting more + (an earlier version subscribed twice, once TRANSIENT_LOCAL) buys nothing + for live telemetry and makes Fast DDS retain history it then complains + about overflowing on the high-rate topics. + """ + try: + cls = load_type(type_path) + except Exception as exc: + print(f"[agent] cannot load {type_path} for {topic}: {exc}") + return + try: + self.node.create_subscription( + cls, topic, self._guard(topic, handler), + self._qos(reliable=False, transient=False, depth=depth)) + except Exception as exc: + print(f"[agent] subscribe failed {topic}: {exc}") + + def _guard(self, topic, handler): + """ + Wrap a subscription callback so it can never kill the executor. + + rclpy lets an exception raised inside a callback propagate out of + MultiThreadedExecutor.spin(), which terminates the spin thread outright: + every subscription, timer and pending service response stops, silently, + for the life of the process. One malformed message must not be able to + take the whole bridge down, so each callback swallows and reports + instead. + """ + state = {"errors": 0} + + def wrapped(msg): + try: + handler(msg) + except Exception as exc: + state["errors"] += 1 + if state["errors"] <= 3: + print(f"[agent] callback error on {topic}: " + f"{type(exc).__name__}: {exc}") + traceback.print_exc() + elif state["errors"] == 4: + print(f"[agent] further errors on {topic} suppressed") + self.state.setdefault("callback_errors", {})[topic] = state["errors"] + + return wrapped + + def _setup(self): + self._sub("aimdk_msgs/msg/PmuState", TOPIC_PMU, self.on_pmu) + self._sub("sensor_msgs/msg/Imu", TOPIC_IMU_CHEST, lambda m: self.on_imu("chest", m)) + self._sub("sensor_msgs/msg/Imu", TOPIC_IMU_TORSO, lambda m: self.on_imu("torso", m)) + self._sub("aimdk_msgs/msg/TouchState", TOPIC_TOUCH, self.on_touch) + self._sub("aimdk_msgs/msg/HandStateArray", TOPIC_HAND_STATE, self.on_hand) + self._sub("nav_msgs/msg/Odometry", TOPIC_ODOM, self.on_odom) + self._sub("aimdk_msgs/msg/FaceEmojiStatus", TOPIC_FACE, self.on_face) + self._sub("aimdk_msgs/msg/McLocomotionVelocity", TOPIC_VELOCITY, self.on_velocity) + + for key, (state_topic, _) in JOINT_GROUPS.items(): + self._sub("aimdk_msgs/msg/JointStateArray", state_topic, + (lambda k: (lambda m: self.on_joints(k, m)))(key)) + + # Cameras and the LiDAR are deliberately NOT subscribed here. They are + # created and destroyed at runtime by _reconcile_streams below, so a + # feed costs nothing until somebody switches it on. + + # Every publisher and service client is created here, before the + # executor starts spinning. rclpy is not thread-safe for entity + # creation: making a client from a worker thread while the executor is + # spinning wedges the executor, and subscriptions silently stop firing. + for alias in SRV: + try: + type_path, name = SRV[alias] + self.service_clients[alias] = self.node.create_client( + load_type(type_path), name) + except Exception as exc: + print(f"[agent] cannot create client for {alias}: {exc}") + + for topic, type_path in ( + (TOPIC_VELOCITY, "aimdk_msgs/msg/McLocomotionVelocity"), + (TOPIC_HAND_CMD, "aimdk_msgs/msg/HandCommandArray"), + *[(cmd_topic, "aimdk_msgs/msg/JointCommandArray") + for _, cmd_topic in JOINT_GROUPS.values()], + ): + try: + self.publishers[topic] = self.node.create_publisher( + load_type(type_path), topic, self._qos(depth=10)) + except Exception as exc: + print(f"[agent] cannot create publisher for {topic}: {exc}") + + # Heartbeat. If this stops incrementing the executor has wedged, which + # is otherwise invisible - subscriptions just quietly stop arriving. + self.node.create_timer(1.0, self._on_heartbeat) + + # Reconciles requested streams with live subscriptions. This has to be a + # timer rather than something the command handler does directly: + # commands run on an asyncio worker thread (see serve()), and creating + # or destroying a subscription off the executor thread while the + # executor is spinning wedges it - every subscription and timer stops, + # silently, for the life of the process. Timer callbacks run *on* the + # executor, which is exactly where this work is safe. + # + # _control_group, not the default one: see the note in __init__ about + # this timer being starved by the high-rate telemetry callbacks. + self.node.create_timer(0.2, self._reconcile_streams, + callback_group=self._control_group) + + def _on_heartbeat(self): + try: + self.state["spin_ticks"] = self.state.get("spin_ticks", 0) + 1 + except Exception: + pass + + # -- on-demand streams -------------------------------------------------- + + def want_stream(self, key: str, active: bool) -> None: + """Record a request. The executor timer does the actual ROS work.""" + with self._stream_lock: + self._stream_wanted[key] = active + + def stop_all_streams(self, why: str = "") -> None: + with self._stream_lock: + if not any(self._stream_wanted.values()): + return + for key in self._stream_wanted: + self._stream_wanted[key] = False + print(f"[agent] stopping all streams{f' ({why})' if why else ''}") + + def _reconcile_streams(self): + """Bring live subscriptions in line with what has been asked for. + + Runs on the executor thread, ~5 Hz. Cheap when nothing has changed. + """ + with self._stream_lock: + wanted = dict(self._stream_wanted) + + for key, active in wanted.items(): + live = key in self._streams + if active == live: + continue + if active: + self._open_stream(key) + else: + self._close_stream(key) + + def _open_stream(self, key: str): + spec = LIDAR if key == LIDAR_KEY else CAMERAS.get(key) + if spec is None: + return + entry = self.state["streams"].setdefault(key, {"key": key}) + + try: + cls = load_type(spec["type"]) + except Exception as exc: + entry.update(active=False, error=f"cannot load {spec['type']}: {exc}") + with self._stream_lock: + self._stream_wanted[key] = False + return + + handler = (self.on_cloud if key == LIDAR_KEY + else (lambda k: (lambda m: self.on_frame(k, m)))(key)) + try: + sub = self.node.create_subscription( + cls, spec["topic"], self._guard(spec["topic"], handler), + # depth=1: only the newest frame or scan is ever served, so + # queueing older ones is pure memory for data that is already + # stale by the time anyone asks. + self._qos(reliable=False, transient=False, depth=1), + callback_group=self._stream_group) + except Exception as exc: + entry.update(active=False, error=str(exc)) + with self._stream_lock: + self._stream_wanted[key] = False + return + + self._streams[key] = {"sub": sub, "spec": spec} + entry.update(active=True, error="", since=time.time(), frames=0, last=None) + print(f"[agent] stream on: {key} -> {spec['topic']}") + + def _close_stream(self, key: str): + entry = self._streams.pop(key, None) + if entry is not None: + try: + self.node.destroy_subscription(entry["sub"]) + except Exception as exc: + print(f"[agent] destroy_subscription failed for {key}: {exc}") + # Drop the retained payload too - a stopped feed must not keep serving + # the last picture it saw as though it were live. + self.frames.pop(key, None) + if key == LIDAR_KEY: + self.cloud = None + self.state["cameras"].pop(key, None) + status = self.state["streams"].setdefault(key, {"key": key}) + status.update(active=False, since=None, last=None) + print(f"[agent] stream off: {key}") + + def mark(self, topic): + stats = self.state["topic_stats"] + now = time.time() + entry = stats.get(topic) + if entry is None: + stats[topic] = {"topic": topic, "count": 1, "last": now, "hz": 0.0} + return + gap = now - entry["last"] + if gap > 0: + inst = 1.0 / gap + entry["hz"] = round(inst if entry["count"] < 2 else entry["hz"] * 0.85 + inst * 0.15, 2) + entry["count"] += 1 + entry["last"] = now + + # -- subscription handlers --------------------------------------------- + + def on_pmu(self, msg): + s = self.state + g = lambda f, d=None: getattr(msg, f, d) # noqa: E731 + + s["battery_pct"] = float(g("battery_remaining_capacity_percentage", 0) or 0) + s["battery_voltage"] = g("battery_voltage") + s["battery_current"] = g("battery_current") + s["battery_temp"] = g("battery_temperature") + s["battery_cycles"] = g("battery_cycle_count") + s["battery_capacity_mah"] = g("battery_remaining_capacity") + s["battery_power"] = g("battery_output_power") + s["pmu_temp"] = g("pmu_temperature") + s["fan_rpm"] = g("fan_speed") + s["fan_pct"] = g("fan_pecentage") + current = s["battery_current"] + s["charging"] = bool(current is not None and current > 0.05) + + rails = {} + for key, vfield, cfield, nominal in PMU_RAILS: + voltage = g(vfield) + current = g(cfield) if cfield else None + rails[key] = { + "voltage": voltage, "current": current, "nominal": nominal, + "ok": voltage is None or voltage > nominal * 0.8, + } + s["rails"] = rails + + s["pmu_info"] = {f: g(f) for f in ( + "bms_manufacturer", "bms_serial_number", "bms_hardware_version", + "bms_software_version", "pmu_software_version", "pmu_hardware_version", + "pmu_protocol_version")} + s["pmu_raw"] = flatten(msg) + self.mark(TOPIC_PMU) + + def on_imu(self, key, msg): + q = msg.orientation + roll, pitch, yaw = quat_to_rpy(q.x, q.y, q.z, q.w) + self.state["imu"][key] = { + "roll": round(roll, 5), "pitch": round(pitch, 5), "yaw": round(yaw, 5), + "accel_x": round(msg.linear_acceleration.x, 4), + "accel_y": round(msg.linear_acceleration.y, 4), + "accel_z": round(msg.linear_acceleration.z, 4), + "gyro_x": round(msg.angular_velocity.x, 5), + "gyro_y": round(msg.angular_velocity.y, 5), + "gyro_z": round(msg.angular_velocity.z, 5), + } + self.mark(TOPIC_IMU_CHEST if key == "chest" else TOPIC_IMU_TORSO) + + def on_touch(self, msg): + # TouchState's fixed-size arrays arrive as numpy arrays, and + # `numpy_array or []` raises ValueError ("truth value ... is + # ambiguous"). Convert explicitly; never lean on truthiness here. + touched = [bool(v) for v in seq(getattr(msg, "is_touched", None))] + self.state["touch_head"] = { + "touched": any(touched), + "zones": touched, + "data": [int(v) for v in seq(getattr(msg, "data", None))], + "threshold": [int(v) for v in seq(getattr(msg, "threshold", None))], + "event_type": int(getattr(msg, "event_type", 0) or 0), + } + self.mark(TOPIC_TOUCH) + + def on_hand(self, msg): + def side(prefix): + return [{ + "name": getattr(h, "name", "") or f"j{i}", + "position": round(float(getattr(h, "position", 0.0)), 4), + "velocity": round(float(getattr(h, "velocity", 0.0)), 4), + "effort": round(float(getattr(h, "effort", 0.0)), 4), + "fault": int(getattr(h, "faultcode", 0) or 0), + } for i, h in enumerate(seq(getattr(msg, f"{prefix}_hands", None)))] + + left_type = getattr(getattr(msg, "left_hand_type", None), "value", 0) + right_type = getattr(getattr(msg, "right_hand_type", None), "value", 0) + self.state["hand_state"] = { + "left": side("left"), "right": side("right"), + "left_type": int(left_type), "right_type": int(right_type), + } + self.mark(TOPIC_HAND_STATE) + + def on_joints(self, key, msg): + rows = [] + for j in seq(getattr(msg, "joints", None)): + rows.append({ + "name": getattr(j, "name", ""), + "position": round(float(getattr(j, "position", 0.0)), 5), + "velocity": round(float(getattr(j, "velocity", 0.0)), 5), + "effort": round(float(getattr(j, "effort", 0.0)), 4), + "error": int(getattr(j, "error_code", 0) or 0), + }) + self.state["joints"][key] = rows + self.mark(JOINT_GROUPS[key][0]) + + def on_odom(self, msg): + p = msg.pose.pose.position + q = msg.pose.pose.orientation + _, _, yaw = quat_to_rpy(q.x, q.y, q.z, q.w) + self.state["odom"] = {"x": round(p.x, 4), "y": round(p.y, 4), "yaw": round(yaw, 4)} + t = msg.twist.twist + self.state["velocity"] = { + "forward": round(t.linear.x, 4), + "lateral": round(t.linear.y, 4), + "angular": round(t.angular.z, 4), + } + self.mark(TOPIC_ODOM) + + def on_velocity(self, msg): + # Someone (possibly us) is commanding velocity; reflect it so the UI can + # show the RC or app driving even when the dashboard is not. + self.state["velocity_command"] = { + "forward": round(float(getattr(msg, "forward_velocity", 0.0)), 4), + "lateral": round(float(getattr(msg, "lateral_velocity", 0.0)), 4), + "angular": round(float(getattr(msg, "angular_velocity", 0.0)), 4), + "source": getattr(msg, "source", ""), + } + self.mark(TOPIC_VELOCITY) + + def on_face(self, msg): + self.state["emoji_id"] = int(getattr(msg, "e_id", 0) or 0) + self.state["face_status"] = int(getattr(msg, "status", 0) or 0) + self.mark(TOPIC_FACE) + + def on_frame(self, key, msg): + fmt = (getattr(msg, "format", "") or "jpeg").lower() + data = bytes(msg.data) + now = time.time() + # Kept encoded exactly as it arrived. Depth is decoded lazily in + # cmd_camera_frame instead of here: this callback runs on the executor + # thread at the publish rate (~13 Hz for depth), while the browser asks + # for 1-5 frames a second, so decoding here would burn CPU on the + # robot's own control machine for frames nobody collects. + self.frames[key] = (now, data, "png" if "png" in fmt else "jpeg") + self.state["cameras"][key] = {"bytes": len(data), "ts": now, "format": fmt} + + status = self.state["streams"].setdefault(key, {"key": key}) + status["frames"] = status.get("frames", 0) + 1 + status["last"] = now + self.mark(CAMERAS[key]["topic"]) + + def on_cloud(self, msg): + """Decimate a PointCloud2 to something a browser can draw. + + Fields on this robot: x,y,z float32 at offsets 0/4/8 and intensity + float32 at 16, point_step 32 (read off the live topic, not assumed). + A scan is ~25.5k points; sending them all as JSON would be several MB a + second for a picture that looks identical at a tenth of the points. + """ + import numpy as np + + step = int(msg.point_step) + raw = np.frombuffer(bytes(msg.data), dtype=np.uint8) + count = raw.size // step + if not count: + return + rows = raw[:count * step].reshape(count, step) + + # Stride rather than random choice: it keeps the scan's angular + # structure, so walls stay walls instead of dissolving into noise. + if count > LIDAR_MAX_POINTS: + rows = rows[:: max(1, count // LIDAR_MAX_POINTS)][:LIDAR_MAX_POINTS] + + xyz = np.frombuffer(rows[:, 0:12].tobytes(), dtype=np.float32).reshape(-1, 3) + try: + intensity = np.frombuffer(rows[:, 16:20].tobytes(), dtype=np.float32) + except ValueError: + intensity = np.zeros(len(xyz), dtype=np.float32) + + good = np.isfinite(xyz).all(axis=1) + xyz, intensity = xyz[good], intensity[good] + + points = np.column_stack([xyz.round(3), intensity.round(1)]) + self.cloud = (time.time(), points.tolist()) + + status = self.state["streams"].setdefault(LIDAR_KEY, {"key": LIDAR_KEY}) + status["frames"] = status.get("frames", 0) + 1 + status["last"] = time.time() + status["points"] = int(len(points)) + status["scan_points"] = int(count) + self.mark(LIDAR["topic"]) + + # -- service helpers ---------------------------------------------------- + + def client_for(self, alias): + """Clients are all pre-created in _setup - never build one here.""" + type_path, _ = SRV[alias] + cli = self.service_clients.get(alias) + if cli is None: + raise RuntimeError(f"no client for '{alias}' (creation failed at startup)") + return cli, load_type(type_path) + + def call(self, alias, build=None, timeout=6.0): + """ + Blocking service call, made from a worker thread. + + Deliberately does NOT use wait_for_service. That builds a second wait + set on the same context while the executor is already waiting on one, + which deadlocks the executor in rclpy/Humble - subscriptions fire once + and then never again. service_is_ready() is a plain graph query with no + wait set, so it is safe to call from here. + """ + try: + cli, cls = self.client_for(alias) + except Exception as exc: + return False, f"type unavailable: {exc}", None + + deadline = time.time() + timeout + while not cli.service_is_ready(): + if time.time() > deadline: + return False, f"service {SRV[alias][1]} unavailable", None + time.sleep(0.05) + + req = cls.Request() + if build: + try: + build(req) + except Exception as exc: + return False, f"bad request: {exc}", None + future = cli.call_async(req) + deadline = time.time() + timeout + while not future.done() and time.time() < deadline: + time.sleep(0.01) + if not future.done(): + return False, "service call timed out", None + resp = future.result() + return True, "ok", flatten(resp) + + def publisher(self, topic, type_path): + pub = self.publishers.get(topic) + if pub is None: + # Only reached by publish_raw for a topic not known at startup. + # Creating it now is a calculated risk the typed commands avoid. + pub = self.node.create_publisher(load_type(type_path), topic, self._qos(depth=10)) + self.publishers[topic] = pub + return pub + + # -- polling ------------------------------------------------------------ + + def poll_slow(self): + """Mode, volume, mute, hand type - not available as topics.""" + ok, _, detail = self.call("get_mode", timeout=3.0) + if ok and detail: + info = detail.get("info") or {} + desc = info.get("action_desc") or "" + value = (info.get("current_action") or {}).get("value") + status = (info.get("status") or {}).get("value") + if desc: + self.state["mode"] = desc + elif value in MC_VALUE_TO_NAME: + self.state["mode"] = MC_VALUE_TO_NAME[value] + self.state["mode_value"] = value + self.state["mode_status"] = status + + ok, _, detail = self.call("get_volume", timeout=3.0) + if ok and detail and "audio_volume" in detail: + self.state["volume"] = detail["audio_volume"] + + ok, _, detail = self.call("get_mute", timeout=3.0) + if ok and detail and "is_mute" in detail: + self.state["muted"] = bool(detail["is_mute"]) + + ok, _, detail = self.call("hand_type", timeout=3.0) + if ok and detail: + left = (detail.get("left_hands_type") or {}).get("value", 0) + right = (detail.get("right_hands_type") or {}).get("value", 0) + names = {0: "None", 1: "Nimble hands", 2: "Claw gripper", + 3: "Leisai nimble hands", 255: "Error"} + self.state["hand_type"] = names.get(right or left, "Unknown") + self.state["hand_left_type"] = int(left) + self.state["hand_right_type"] = int(right) + + ok, _, detail = self.call("get_source", timeout=3.0) + if ok and detail: + src = (detail.get("input_source") or {}).get("name", "") + self.state["input_source"] = src + + def publish_velocity(self, forward, lateral, angular): + msg = load_type("aimdk_msgs/msg/McLocomotionVelocity")() + msg.source = "x2_dashboard" + msg.forward_velocity = float(forward) + msg.lateral_velocity = float(lateral) + msg.angular_velocity = float(angular) + self.publisher(TOPIC_VELOCITY, "aimdk_msgs/msg/McLocomotionVelocity").publish(msg) + + # -- command handlers --------------------------------------------------- + + def cmd_set_mode(self, args): + mode = str(args.get("mode", "")) + if mode not in MC_ACTION_VALUES: + return {"ok": False, "message": f"unknown mode '{mode}'"} + + def build(req): + req.source = "x2_dashboard" + req.command.action.value = MC_ACTION_VALUES[mode] + req.command.action_desc = mode + + ok, msg, detail = self.call("set_mode", build) + if ok: + self.state["mode"] = mode + return {"ok": ok, "message": f"mode -> {mode}" if ok else msg, "detail": detail} + + def cmd_get_mode(self, args): + self.poll_slow() + return {"ok": True, "message": self.state["mode"], + "detail": {"mode": self.state["mode"], "status": self.state["mode_status"]}} + + def cmd_set_velocity(self, args): + mode = self.state.get("mode") + if mode not in DRIVEABLE_MODES: + return {"ok": False, + "message": f"mode {mode} does not accept velocity - enter Stable stand or Walk"} + if not self.state.get("source_registered"): + return {"ok": False, "message": "register an input source first"} + f = float(args.get("forward", 0.0)) + l = float(args.get("lateral", 0.0)) + a = float(args.get("angular", 0.0)) + self.state["velocity_command"] = {"forward": f, "lateral": l, "angular": a} + self.last_velocity_cmd = time.time() + try: + self.publish_velocity(f, l, a) + except Exception as exc: + return {"ok": False, "message": f"publish failed: {exc}"} + return {"ok": True, "message": "velocity published", + "detail": {"forward": f, "lateral": l, "angular": a}} + + def cmd_stop(self, args): + """Never gated - an emergency stop that can be refused is not one.""" + self.state["velocity_command"] = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + self.last_velocity_cmd = time.time() + try: + self.publish_velocity(0.0, 0.0, 0.0) + except Exception as exc: + return {"ok": False, "message": f"stop publish failed: {exc}"} + return {"ok": True, "message": "motion stopped"} + + def cmd_preset(self, args): + motion = int(args.get("motion", 0)) + area = int(args.get("area", 0)) + interrupt = bool(args.get("interrupt", True)) + + def build(req): + req.area.value = area + req.motion.value = motion + req.interrupt = interrupt + req.ani_path = "" + req.play_timestamp = 0 + + ok, msg, detail = self.call("preset", build, timeout=8.0) + return {"ok": ok, "message": "preset started" if ok else msg, "detail": detail} + + def cmd_register_source(self, args): + name = str(args.get("name", "x2_dashboard")) + priority = int(args.get("priority", 30)) + timeout = int(args.get("timeout", 1000)) + + def build(req): + req.action.value = 1001 # INPUTACTION_ADD + req.input_source.name = name + req.input_source.priority = priority + req.input_source.timeout = timeout + + ok, msg, detail = self.call("set_source", build) + if ok: + self.state["source_registered"] = True + self.state["input_source"] = name + return {"ok": ok, "message": f"registered '{name}'" if ok else msg, "detail": detail} + + def cmd_set_joints(self, args): + group = str(args.get("group", "")) + if group not in JOINT_GROUPS: + return {"ok": False, "message": f"unknown joint group '{group}'"} + mode = str(args.get("mode", "position")) + targets = args.get("targets") or {} + stiffness = args.get("stiffness") + damping = args.get("damping") + + try: + ArrayT = load_type("aimdk_msgs/msg/JointCommandArray") + CmdT = load_type("aimdk_msgs/msg/JointCommand") + except Exception as exc: + return {"ok": False, "message": f"aimdk_msgs unavailable: {exc}"} + + live = self.state["joints"].get(group) or [] + names = [j["name"] for j in live] or list(targets) + + commands = [] + for name in names: + c = CmdT() + c.name = name + value = float(targets.get(name, 0.0)) + if mode == "position": + c.position = value + elif mode == "velocity": + c.velocity = value + else: + c.effort = value + if stiffness is not None: + c.stiffness = float(stiffness) + if damping is not None: + c.damping = float(damping) + commands.append(c) + + arr = ArrayT() + arr.joints = commands + try: + self.publisher(JOINT_GROUPS[group][1], + "aimdk_msgs/msg/JointCommandArray").publish(arr) + except Exception as exc: + return {"ok": False, "message": f"publish failed: {exc}"} + return {"ok": True, "message": f"{len(commands)} joint command(s) published"} + + def cmd_set_hand(self, args): + side = str(args.get("side", "right")) + positions = [float(v) for v in (args.get("positions") or [])] + try: + ArrayT = load_type("aimdk_msgs/msg/HandCommandArray") + CmdT = load_type("aimdk_msgs/msg/HandCommand") + except Exception as exc: + return {"ok": False, "message": f"aimdk_msgs unavailable: {exc}"} + + arr = ArrayT() + cmds = [] + for v in positions: + c = CmdT() + c.position = v + cmds.append(c) + if side == "left": + arr.left_hands = cmds + else: + arr.right_hands = cmds + try: + self.publisher(TOPIC_HAND_CMD, "aimdk_msgs/msg/HandCommandArray").publish(arr) + except Exception as exc: + return {"ok": False, "message": f"publish failed: {exc}"} + return {"ok": True, "message": f"{side} hand command published"} + + def cmd_speak(self, args): + text = str(args.get("text", "")).strip() + if not text: + return {"ok": False, "message": "nothing to say"} + priority = int(args.get("priority", 6)) + interrupt = bool(args.get("interrupt", False)) + + def build(req): + req.tts_req.text = text + req.tts_req.priority_level.value = priority + req.tts_req.priority_weight = 50 + req.tts_req.domain = "dashboard" + req.tts_req.trace_id = f"dash-{int(time.time() * 1000)}" + req.tts_req.is_interrupted = interrupt + + ok, msg, detail = self.call("tts", build, timeout=8.0) + return {"ok": ok, "message": "speaking" if ok else msg, "detail": detail} + + def cmd_set_volume(self, args): + volume = max(0, min(100, int(args.get("volume", 50)))) + ok, msg, detail = self.call("set_volume", lambda r: setattr(r, "audio_volume", volume)) + if ok: + self.state["volume"] = volume + return {"ok": ok, "message": f"volume {volume}" if ok else msg, "detail": detail} + + def cmd_set_mute(self, args): + muted = bool(args.get("muted", False)) + ok, msg, detail = self.call("set_mute", lambda r: setattr(r, "is_mute", muted)) + if ok: + self.state["muted"] = muted + return {"ok": ok, "message": "muted" if muted else "unmuted", "detail": detail} + + def cmd_emoji(self, args): + emotion = int(args.get("emotion_id", 1)) + mode = int(args.get("mode", 1)) + priority = int(args.get("priority", 6)) + + def build(req): + req.emotion_id = emotion + req.mode = mode + req.priority = priority + + ok, msg, detail = self.call("emoji", build) + return {"ok": ok, "message": "emoji sent" if ok else msg, "detail": detail} + + def _send_led(self, mode, r, g, b, priority): + def build(req): + req.trace_id = f"dash-{int(time.time() * 1000)}" + req.led_strip_mode = int(mode) + req.r = int(r) + req.g = int(g) + req.b = int(b) + req.priority = int(priority) + req.reset_priority = False + + return self.call("led", build) + + def cmd_led(self, args): + mode = int(args.get("mode", 0)) + r, g, b = (int(args.get(k, 0)) for k in ("r", "g", "b")) + priority = int(args.get("priority", 6)) + keep = bool(args.get("keep", True)) + + ok, msg, detail = self._send_led(mode, r, g, b, priority) + if ok: + self.state["led"] = {"mode": mode, "r": r, "g": g, "b": b, "keep": keep} + # The robot's own task_manager drives this strip too and reclaims it + # after roughly a minute, which is why a colour set from here fades + # away on its own. Remembering the request lets the keepalive below + # put it back. + self.led_keepalive = ( + {"mode": mode, "r": r, "g": g, "b": b, "priority": priority} + if keep else None + ) + return {"ok": ok, "message": "led updated" if ok else msg, "detail": detail} + + def cmd_camera_frame(self, args): + key = str(args.get("key", "")) + if key not in self.state["streams"]: + return {"ok": False, "message": f"unknown stream '{key}'"} + if not self.state["streams"][key].get("active"): + return {"ok": False, "message": "feed is off", "detail": {"off": True}} + + entry = self.frames.get(key) + if not entry: + return {"ok": False, "message": "no frame received on this topic yet"} + ts, data, fmt = entry + if time.time() - ts > 5.0: + return {"ok": False, "message": "feed is stale"} + + spec = CAMERAS.get(key) or {} + flip = bool(args.get("flip", spec.get("flip", False))) + + if spec.get("kind") == "depth": + data, fmt = self._render_depth(data, flip) + if data is None: + return {"ok": False, "message": fmt} + elif flip: + rotated = self._rotate180(data) + if rotated is not None: + data, fmt = rotated, "jpeg" + + return {"ok": True, "message": "frame", + "detail": {"format": fmt, "ts": ts, "bytes": len(data), + "b64": base64.b64encode(data).decode("ascii")}} + + @staticmethod + def _rotate180(data): + try: + import cv2 + import numpy as np + img = cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR) + if img is None: + return None + ok, jpeg = cv2.imencode(".jpg", cv2.rotate(img, cv2.ROTATE_180), + [cv2.IMWRITE_JPEG_QUALITY, 80]) + return jpeg.tobytes() if ok else None + except Exception: + return None + + @staticmethod + def _render_depth(data, flip=False): + """Turn a compressedDepth payload into a viewable colour image. + + The raw frame is a 16-bit millimetre map behind a 12-byte header - a + browser cannot show that, and scaling it by eye ruins the near field. + Mapping a fixed metric range to a colour ramp keeps distances readable + and, more importantly, comparable between frames. + """ + try: + import cv2 + import numpy as np + except ImportError: + return None, "depth needs numpy and opencv on the robot" + + try: + img = cv2.imdecode(np.frombuffer(data[DEPTH_HEADER_BYTES:], np.uint8), + cv2.IMREAD_UNCHANGED) + if img is None: + return None, "could not decode depth frame" + + depth = img.astype(np.float32) + if img.dtype != np.uint16: + # 32FC1 variants carry metres, not millimetres. + depth *= 1000.0 + + scaled = np.clip(depth / DEPTH_RANGE_MM * 255.0, 0, 255).astype(np.uint8) + coloured = cv2.applyColorMap(scaled, cv2.COLORMAP_JET) + # 0 means "no return", not "touching the lens". Painting it black + # stops the sky and every reflective surface reading as closest. + coloured[depth <= 0] = 0 + if flip: + coloured = cv2.rotate(coloured, cv2.ROTATE_180) + + ok, jpeg = cv2.imencode(".jpg", coloured, [cv2.IMWRITE_JPEG_QUALITY, 80]) + if not ok: + return None, "could not encode depth frame" + return jpeg.tobytes(), "jpeg" + except Exception as exc: + return None, f"depth render failed: {type(exc).__name__}: {exc}" + + def cmd_stream_set(self, args): + """Switch a camera or the LiDAR on or off.""" + key = str(args.get("key", "")) + active = bool(args.get("active", False)) + if key not in self.state["streams"]: + return {"ok": False, "message": f"unknown stream '{key}'"} + + self.want_stream(key, active) + + # Wait for the executor timer to apply it, so the caller gets a truthful + # answer rather than an optimistic one. + deadline = time.time() + 6.0 + while time.time() < deadline: + status = self.state["streams"][key] + if bool(status.get("active")) == active: + return {"ok": True, + "message": f"{key} {'on' if active else 'off'}", + "detail": dict(status)} + if status.get("error"): + return {"ok": False, "message": status["error"], "detail": dict(status)} + time.sleep(0.05) + + return {"ok": False, "message": "the agent did not apply that in time", + "detail": dict(self.state["streams"][key])} + + def cmd_stream_list(self, args): + return {"ok": True, "message": "streams", "detail": { + "streams": self.state["streams"], + "cameras": {k: {"topic": v["topic"], "kind": v["kind"], "flip": v["flip"]} + for k, v in CAMERAS.items()}, + "lidar": {"key": LIDAR_KEY, **LIDAR}, + }} + + def cmd_lidar_points(self, args): + status = self.state["streams"].get(LIDAR_KEY) or {} + if not status.get("active"): + return {"ok": False, "message": "LiDAR is off", "detail": {"off": True}} + if not self.cloud: + return {"ok": False, "message": "no scan received yet"} + ts, points = self.cloud + if time.time() - ts > 8.0: + return {"ok": False, "message": "scan is stale"} + return {"ok": True, "message": "points", "detail": { + "ts": ts, "count": len(points), "points": points, + "frame": "lidar_chest_front", + }} + + def cmd_graph(self, args): + return {"ok": True, "message": "graph", "detail": { + "topics": [{"name": n, "types": list(t)} + for n, t in self.node.get_topic_names_and_types()], + "services": [{"name": n, "types": list(t)} + for n, t in self.node.get_service_names_and_types()], + "nodes": [f"{ns}{n}" for n, ns in self.node.get_node_names_and_namespaces()], + }} + + def cmd_publish_raw(self, args): + topic = str(args.get("topic", "")) + type_path = str(args.get("type", "")) + fields = args.get("fields") or {} + try: + msg = load_type(type_path)() + for k, v in fields.items(): + if hasattr(msg, k): + setattr(msg, k, v) + self.publisher(topic, type_path).publish(msg) + except Exception as exc: + return {"ok": False, "message": f"{type(exc).__name__}: {exc}"} + return {"ok": True, "message": f"published to {topic}"} + + def cmd_ping(self, args): + return {"ok": True, "message": "pong", "detail": {"ts": time.time()}} + + HANDLERS = { + "set_mode": cmd_set_mode, "get_mode": cmd_get_mode, + "set_velocity": cmd_set_velocity, "stop": cmd_stop, + "preset": cmd_preset, "register_source": cmd_register_source, + "set_joints": cmd_set_joints, "set_hand": cmd_set_hand, + "speak": cmd_speak, "set_volume": cmd_set_volume, "set_mute": cmd_set_mute, + "emoji": cmd_emoji, "led": cmd_led, "camera_frame": cmd_camera_frame, + "graph": cmd_graph, "publish_raw": cmd_publish_raw, "ping": cmd_ping, + "stream_set": cmd_stream_set, "stream_list": cmd_stream_list, + "lidar_points": cmd_lidar_points, + } + + def dispatch(self, name, args): + handler = self.HANDLERS.get(name) + if handler is None: + return {"ok": False, "message": f"unknown command '{name}'"} + try: + return handler(self, args or {}) + except Exception as exc: + traceback.print_exc() + return {"ok": False, "message": f"{type(exc).__name__}: {exc}"} + + +# -------------------------------------------------------------------------- +# TCP server +# -------------------------------------------------------------------------- + +async def serve(agent: Agent, host: str, port: int): + async def handle(reader, writer): + peer = writer.get_extra_info("peername") + agent.clients.add(writer) + print(f"[agent] client connected: {peer}") + try: + hello = {"type": "hello", "data": { + "agent_version": VERSION, + "hostname": socket.gethostname(), + "ros_domain_id": os.environ.get("ROS_DOMAIN_ID", "0"), + "cameras": list(CAMERAS), + "camera_specs": {k: {"topic": v["topic"], "kind": v["kind"], + "flip": v["flip"]} for k, v in CAMERAS.items()}, + "lidar": {"key": LIDAR_KEY, **LIDAR}, + "on_demand": True, + "started": AGENT_STARTED, + }} + writer.write((json.dumps(hello) + "\n").encode()) + await writer.drain() + + while True: + line = await reader.readline() + if not line: + break + try: + msg = json.loads(line) + except json.JSONDecodeError: + continue + if msg.get("type") != "cmd": + continue + result = await asyncio.to_thread( + agent.dispatch, msg.get("name", ""), msg.get("args")) + result["type"] = "result" + result["id"] = msg.get("id") + writer.write((json.dumps(result) + "\n").encode()) + await writer.drain() + except (ConnectionError, asyncio.IncompleteReadError): + pass + except Exception as exc: + print(f"[agent] client error: {exc}") + finally: + agent.clients.discard(writer) + try: + writer.close() + except Exception: + pass + # Nobody left to watch: drop every camera and the LiDAR. Otherwise + # closing the last browser leaves the robot pushing megabytes a + # second through DDS forever, and the operator has no way to tell. + if not agent.clients: + agent.stop_all_streams("no clients connected") + print(f"[agent] client disconnected: {peer}") + + server = await asyncio.start_server(handle, host, port) + addrs = ", ".join(str(s.getsockname()) for s in server.sockets) + print(f"[agent] listening on {addrs}") + async with server: + await server.serve_forever() + + +async def broadcaster(agent: Agent, hz: float): + period = 1.0 / hz + while True: + await asyncio.sleep(period) + if not agent.clients: + continue + agent.state["ts"] = time.time() + payload = (json.dumps({"type": "state", "data": agent.state}, + default=str) + "\n").encode() + for writer in list(agent.clients): + try: + writer.write(payload) + except Exception: + agent.clients.discard(writer) + + +async def velocity_keepalive(agent: Agent): + """Republish the standing velocity command and zero it if the client goes quiet.""" + period = 1.0 / VELOCITY_HZ + while True: + await asyncio.sleep(period) + cmd = agent.state["velocity_command"] + moving = any(abs(float(cmd.get(k, 0) or 0)) > 1e-6 + for k in ("forward", "lateral", "angular")) + if not moving or not agent.last_velocity_cmd: + continue + if time.time() - agent.last_velocity_cmd > DEADMAN_S: + agent.state["velocity_command"] = {"forward": 0.0, "lateral": 0.0, "angular": 0.0} + try: + agent.publish_velocity(0.0, 0.0, 0.0) + except Exception: + pass + print("[agent] dead-man timeout - velocity zeroed") + continue + try: + agent.publish_velocity(cmd["forward"], cmd["lateral"], cmd["angular"]) + except Exception: + pass + + +async def led_keepalive(agent: Agent): + """ + Keep re-asserting the requested light-strip setting. + + The PMU animations (breathing, blinking, flowing) are cyclic and would run + forever on their own, but the robot's task_manager also owns this strip and + takes it back after roughly a minute, so a colour set from the dashboard + quietly disappears. Re-sending the same request wins it back. + + The interval is 20 s on purpose: it is a whole multiple of all three + animation cycles (4 s breathing, 1 s blinking, 2 s flowing), so the restart + lands on a cycle boundary and is not visible as a stutter. A value like 15 s + would cut the 4 s breathing cycle mid-way and look like a glitch. + """ + INTERVAL = 20.0 + misses = 0 + while True: + await asyncio.sleep(INTERVAL) + wanted = agent.led_keepalive + if not wanted: + misses = 0 + continue + try: + ok, msg, _ = await asyncio.to_thread( + agent._send_led, wanted["mode"], wanted["r"], wanted["g"], + wanted["b"], wanted["priority"]) + if ok: + misses = 0 + else: + misses += 1 + if misses in (1, 5): + print(f"[agent] led keepalive failed: {msg}") + except asyncio.CancelledError: + raise + except Exception as exc: + print(f"[agent] led keepalive error: {exc}") + + +async def slow_poller(agent: Agent): + quiet_failures = 0 + while True: + # Once rclpy is tearing down, every service call raises. Stop rather + # than filling the journal with the same error twice a second. + if not rclpy.ok(): + return + try: + await asyncio.to_thread(agent.poll_slow) + quiet_failures = 0 + except asyncio.CancelledError: + raise + except Exception as exc: + quiet_failures += 1 + if quiet_failures <= 3: + print(f"[agent] poll error: {exc}") + elif quiet_failures == 4: + print("[agent] further poll errors suppressed") + await asyncio.sleep(2.0) + + +AGENT_STARTED = time.time() + + +def main(): + parser = argparse.ArgumentParser(description="AGIBOT X2 dashboard agent") + parser.add_argument("--host", default="0.0.0.0") + parser.add_argument("--port", type=int, default=DEFAULT_PORT) + parser.add_argument("--hz", type=float, default=10.0, help="state broadcast rate") + args = parser.parse_args() + + rclpy.init() + node = rclpy.create_node("x2_dashboard_agent") + agent = Agent(node) + + # Six threads, not four: there are now three callback groups (core + # telemetry, the reentrant stream group, and the reconcile timer), and the + # stream group wants room to copy several large frames at once. + executor = MultiThreadedExecutor(num_threads=6) + executor.add_node(node) + spin_thread = threading.Thread(target=executor.spin, daemon=True, name="ros-spin") + spin_thread.start() + print(f"[agent] x2_agent {VERSION} up on ROS domain {os.environ.get('ROS_DOMAIN_ID', '0')}") + + async def run(): + loop = asyncio.get_running_loop() + agent.loop = loop + stopping = asyncio.Event() + + # systemd stops the unit with SIGTERM, which never surfaces as + # KeyboardInterrupt. Without this the loop keeps running after rclpy is + # torn down, the unit sits in "deactivating" until it is killed, and the + # journal fills with invalid-context errors. + for sig in (signal.SIGTERM, signal.SIGINT): + try: + loop.add_signal_handler(sig, stopping.set) + except NotImplementedError: + pass + + tasks = [ + asyncio.create_task(serve(agent, args.host, args.port), name="serve"), + asyncio.create_task(broadcaster(agent, args.hz), name="broadcast"), + asyncio.create_task(velocity_keepalive(agent), name="velocity"), + asyncio.create_task(led_keepalive(agent), name="led"), + asyncio.create_task(slow_poller(agent), name="poller"), + ] + + await stopping.wait() + print("[agent] stop requested, shutting down") + + # Leave the robot safe: never hand back control with a velocity standing. + try: + agent.publish_velocity(0.0, 0.0, 0.0) + except Exception: + pass + + for task in tasks: + task.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + + try: + asyncio.run(run()) + except KeyboardInterrupt: + print("\n[agent] interrupted") + finally: + try: + executor.shutdown() + except Exception: + pass + try: + node.destroy_node() + except Exception: + pass + try: + if rclpy.ok(): + rclpy.shutdown() + except Exception: + pass + print("[agent] stopped") + + +if __name__ == "__main__": + main()