它是可选的官方接口插件,但以 fastsim-tui 启动独立 companion 进程,不是 Runtime 托管插件,也不注册 fastsim.componentsfastsim.plugins entry point。TUI 不导入 FastSim Core 或任何仿真器 SDK。没有启动 TUI 时,FastSim 不会创建相关对象、回调、线程或网络任务。

text
fastsim-tui                         fastsim-server                    FastSim Run
┌──────────────────────┐  HTTP/WS  ┌──────────────────────┐  API    ┌──────────────┐
│ Textual 终端工作站   │◄─────────►│ 公共控制面           │◄───────►│ UniRoboSim   │
│ 独立进程             │  v1       │ Run generation 权威  │         │ 仿真后端     │
└──────────────────────┘            └──────────────────────┘         └──────────────┘

安装与连接

TUI 可安装在任意能够访问 Server 的 Python 3.11 或 3.12 环境中,不要求与 仿真器共用环境。

bash
python -m pip install ./packages/fastsim-plugin-tui
fastsim-tui --version
fastsim-tui --url http://127.0.0.1:8000 --connect

认证部署建议使用环境变量或受保护的 token 文件:

bash
FASTSIM_SERVER_TOKEN='...' fastsim-tui --url https://sim.example.com --connect
fastsim-tui --url https://sim.example.com --token-file /run/secrets/fastsim-token --connect

默认传输是带认证的增量 WebSocket。远程部署可指定 Server 允许的精确 Origin:

bash
fastsim-tui \
  --url https://sim-api.example.com \
  --realtime-origin https://console.example.com \
  --connect

轮询只是显式兼容模式,不会在 WebSocket 失败后静默降级:

bash
fastsim-tui --url http://127.0.0.1:8000 --transport compatibility-poll --connect

工作站页面

页面 功能
Dashboard Run generation、生命周期、tick、仿真时间、Server FPS、实测 tick 速率和当前订阅
Launch 从 Server root 或本地 YAML/JSON/TOML 启动,并指定 openpreparedrunning
Scene 按 generation 缓存、支持分页的实体目录,以及 latest-wins 实体状态
Camera 按需读取 Server JPEG/PNG;离开页面立即停止相机请求
Control 控制目标、joint path、物理 Track、抢占、超时和 applied-control 审计
Plugins 插件实例状态和可靠插件事件
Operations 进度、精确详情、已接受 operation ID 和取消操作
Logs 可靠 Server 日志,以及客户端传输/协议错误
Metrics 仅在页面可见时读取进程 CPU、内存和可选 GPU 显存

工作站采用克制的高对比度配色,并在紧凑、标准和宽屏终端宽度下自动重排。 Overview 会直接展示生命周期、仿真时间、tick、FPS、实测 tick rate、generation、 Run 身份和当前 realtime demand,不要求操作者先阅读原始 JSON。常驻活动栏会在 toast 消失后继续保留最近一次成功信息或准确错误。

19 可直接切换页面,也可按 Ctrl+P 搜索工作站命令。生命周期快捷键 与可见按钮经过同一套 Server admission gate,不会绕过当前 Run 的允许操作。

终端窄于 124 列时,横向标签会替换为一个紧凑的页面按钮。按钮始终显示当前 页面,并可打开包含全部 9 个页面的可滚动列表,不会因标签裁切导致功能不可发现。 Help 和确认对话框也会随终端自适应,空间不足时可滚动。

连接颜色具有明确语义:绿色仅表示 realtime 或显式 poll 会话已建立;黄色表示 connecting、reconnecting 或 degraded;红色表示 failed。首次连接失败会恢复可操作的 Connect 状态,不会停留在 CONNECTING

生命周期按钮同时服从 Server capability 与当前 Run 的 allowed_lifecycle_actions。例如运行状态下 Step 不可按,只有 Server 明确允许 时才启用。Step 数量显式可配并有上限。所有 Run 级 mutation 都携带当前 slot generation。

所有 mutation 进入同一条串行客户端通道;响应不明确时不会盲目重试。Server 返回的 operation ID 会保留在界面中,可继续查看进度或请求取消。

Joint path

选择控制目标或填写 actor 和 resource group,设置 dt、是否抢占及可选超时, 再输入矩形 JSON 轨迹:

json
[
  [0.0, -0.4, 0.2],
  [0.1, -0.3, 0.3]
]

物理 Track

物理 Track 对应完整 Server 多资源控制契约。每条 Track 明确版本化 controller、 command space、固定 axes/units 以及时间线:

json
{
  "tracks": [
    {
      "entity_id": "robots.droid",
      "resource_group": "arm",
      "controller": "joint.passthrough@1",
      "command_space": "joint.position@1",
      "interpolation": "linear",
      "frames": [
        {
          "time_from_start_s": 0.0,
          "axes": ["joint1", "joint2"],
          "values": [0.0, 0.0],
          "units": ["rad", "rad"]
        },
        {
          "time_from_start_s": 1.0,
          "axes": ["joint1", "joint2"],
          "values": [0.2, -0.2],
          "units": ["rad", "rad"]
        }
      ]
    }
  ]
}

提交前会校验有限数值、标识符、版本 ID、axes/units 稳定性、资源不重叠以及帧数 和传输上限。

传输与性能边界

  • REST 只用于发现、ticket、mutation、相机快照、目录分页和用户主动请求的详情。
  • 当前可见页面决定一组有界 realtime 订阅;隐藏页面不会产生 state、scene、 plugin、log、metrics、operation 或 applied-control 采样需求。
  • Realtime 支持 snapshot + JSON Patch delta、heartbeat ack、generation 感知重订阅、 cursor resume 和有界指数退避重连。
  • Scene catalog 按 slot generation 缓存;状态 latest-wins,事件、日志和 applied control 使用固定容量历史。
  • JSON 响应在解析前有字节上限,且只解析一次。解析阶段会拒绝非标准的非有限 JSON 常量;类型和有限值检查只作用于 TUI 实际消费的 metrics、相机时间、仿真时间、 FPS 和控制值,不再递归复查响应里每一个值。
  • 相机默认读取 JPEG(PNG 需显式 --camera-format png),只保留一个 worker 和 当前帧,不形成帧积压。
  • 断开或退出会关闭 timer、订阅、相机 worker、HTTP 连接池和 WebSocket 任务。

快捷键

按键 功能
19 依次打开 Overview 到 Metrics
Ctrl+P 搜索页面与工作站命令
C 连接或断开
Space 在 Server 允许时暂停或继续
N 在 Server 允许时执行指定 tick 数
R 确认后 reset
S 确认后 stop
F5 在兼容轮询模式显式刷新
? 帮助
Q 退出并清理客户端资源

开发验证

bash
python -m pytest -q
python -m ruff check src tests
python -m ruff format --check src tests
python -m mypy src
python -m build

测试 extra 包含官方 pytest-textual-snapshot 插件。已接受的 SVG 快照覆盖 80x24、88x32、160x50 终端以及紧凑导航、Help、连接/错误状态和长确认内容。只能在人工检查生成的视觉差异后 执行 pytest --snapshot-update;这是人工验收操作,不是格式化命令。

包内测试覆盖有界 HTTP、结构化错误、generation/idempotency header、按需 realtime 订阅、heartbeat、generation 变化、delta、断线重连与 resume、Textual 交互和干净 退出。包发布门禁还包括以 Server 0.7.6 作为已验证版本的 HTTP/WebSocket、installed Wheel、 Textual 重复卸载和有界资源 soak。可见的 Isaac DROID Run 属于单独的后端验收门禁, 不作为这个无仿真器依赖包已经完成的测试来宣称。