09. WebSocket 工作区导航器
浏览设备的 工作区位置(实时) 通过流媒体 set_transform 通过 WebSocket 通道发送命令。本教程使用 HTTP 来发现会话和设备(与 教程 08),然后在每个时间步长内打开一个 WebSocket 来推送位置更新。
这说明了两种变换操作之间的区别:
| 操作 | 教程 | 典型用法 |
|---|---|---|
configure.mount — 持久挂载转换 | 08 | 只需设置一次(或极少设置),用于描述设备的物理安装方式 |
set_transform — 持久化工作区变换 | 09(本期) | 同样是持久性的,但可以每帧流式传输,以实现实时工作区导航 |
这两个命令均可通过 HTTP 和 WebSocket,而且两者都是 持久的 — 该服务会记住您上次发送的值。两者的区别在于用途和更新频率: configure.mount 适用于更新频率较低的情况(物理配置),而 set_transform 已针对高频流式传输(场景导航)进行了优化。
使用 set_transform 当工作区原点需要追踪运行时发生变化的对象时——例如跟随手部动作、动画化过程偏移,或是让操作员实时微调虚拟工作区。
就个人而言, configure.mount 和 set_transform 看似产生了相同的效果,但它们是 由……抚养长大: 已应用工作区变换 除此之外 坐标管道中的挂载点(device → basis → mount → workspace → application). 参见 安装与工作区 完整流程。
用例
- 实时工作空间导航。在不暂停触觉场景的情况下,移动设备的游标工作空间(即末端执行器能够触及的边界区域)。
- 由操作员控制的对齐。在主触觉应用运行时,让另一台终端的用户按住方向键来移动工作区——这在实时会话中进行用户专属的桌面校准时非常有用。
- 基于流程的工作区运动。通过在每个时间步长发送仅包含位置的变换补丁,利用脚本(如音频响应式、物理驱动式等)控制工作区的位置。
先决条件
教程 09 需要一个活跃的 WebSocket 会话——即一个客户端,该客户端的Inverse3 已处于运行Inverse3 触觉循环Inverse3 。随后,教程 09 会连接到该会话,并实时切换其工作空间。
打开Haply 并启动Orb演示程序。这将打开一个持久的触觉会话,您可以立即开始操作:
./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"
“Orb”场景会在工作空间原点处渲染一个球体——通过“Tutorial 09”移动工作空间会实时移动整个场景,从而为您提供即时视觉反馈。
任何其他运行触觉循环的教程(01–07)也适用。先在一个终端中启动它,然后在另一个终端中启动教程 09,并让其以交互方式发现该会话。
使用方法
# Discover session interactively, use first detected device
./09-haply-inverse-ws-remote-control
python 09-haply-inverse-ws-remote-control.py
# Target the Haply Hub Orb demo directly
./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"
# Target a session directly, specify device
./09-haply-inverse-ws-remote-control --session :my_profile:0 --device A14
python 09-haply-inverse-ws-remote-control.py --session "#42" --device A14
控制
- Python
- C++
按住按键可连续移动。松开按键即可停止。
| 关键 | 行动 |
|---|---|
→ / ← | +X / −X |
↑ / ↓ | +Y / −Y |
Page Up / Page Down | +Z / −Z |
= / - | 加快/减慢导航速度 |
0 | 将工作区重置为原点 |
H | 显示帮助 |
Esc | 退出 (Ctrl+C (也适用) |
基于行输入——输入内容后按回车键。
| 命令 | 行动 |
|---|---|
x+[N] / x-[N] | 将 X 轴速度设置为 ±N 毫米/帧(仅 x+ (使用当前默认速度) |
y+[N] / y-[N] | 将Y轴速度设置为±N毫米/帧 |
z+[N] / z-[N] | 将Z轴速度设置为±N毫米/帧 |
s+[N] / s-[N] | 将默认速度调整为±N 毫米/帧 |
stop | 将所有速度归零 |
reset | 零速度和返回原点 |
h | 显示帮助 |
按Ctrl+C(或 Ctrl+D / EOF)退出。
工作原理
步骤 1 — HTTP 会话与设备发现
本教程复用了相同的 discover_session() / discover_device() 辅助程序作为 教程 08: GET /sessions (或 GET /sessions/<selector> 与 --session),然后 GET /devices (或使用 --device (直接)。这两个辅助程序都支持相同的 CLI 选项,且 SESSION_HELP 文本 — 来自教程 00 或 08 的选择器在此处无需修改即可使用。
步骤 2 — WebSocket 会话,首次消息握手
该教程会打开一个 WebSocket 连接至 ws://localhost:10001. 在 仅接收第一条消息,它会发送会话配置文件注册:
{
"session": {"configure": {"profile": {"name": "co.haply.inverse.tutorials:ws-remote-control"}}},
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0, "y": 0, "z": 0}}}}}]
}
后续的刻度省略 session — 只有 inverse3 发送命令数组。
第 3 步 — 每时钟周期 set_transform
set_transform 接受一个 部分变换 — 仅修改您想要更改的字段。本教程仅发送位置信息;旋转和缩放仍保持其会话默认值(由 configure.mount(如有)。
{
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0.02, "y": 0.0, "z": 0.01}}}}}]
}
该位置以逐帧方式累积。当频率约为 1 kHz 时,服务会重新应用 set_transform 在每次更新时(零阶保持),因此工作区会保持在您上次推送的位置。
set_transform vs configure.mount这两个命令都会为每个会话存储一个持久化变换,但工作区变换位于 除此之外 管道中的挂载点(参见 安装与工作区). 教程 09 正在播放 set_transform 在每个时钟周期内,每个新的 WebSocket 帧都会替换之前流式传输的工作区变换——因此,任何其他正在流式传输的客户端 set_transform 对同一设备的设置将在下一个时钟周期被覆盖。 configure.mount 是独立的,并保持其值。在实际操作中,请为每个关注点选择一个通道:mount 用于物理配置, set_transform 用于实时导航。
线程模型(C++)
该 C++ 教程使用了两个线程,它们共享一个位置累加器:
| 主题 | 角色 |
|---|---|
| 主线程 | 阅读量 std::getline(std::cin, ...),解析令牌,更新 nav_vel[] 和 default_step |
| WebSocket 回调线程 | 进展 nav_pos[] 使用 nav_vel[] * dt, 序列化 set_transform, 发送 |
std::mutex nav_mutex 保护 nav_pos[], nav_vel[]和 default_step. 该 last_tick 时间戳和 first_ws_msg 这些标志仅在 WS 回调范围内有效,无需互斥锁。
ws.onmessage = [&](const std::string &) {
float pos_snap[3];
{
std::lock_guard<std::mutex> lk(nav_mutex);
for (int i = 0; i < 3; ++i) nav_pos[i] += nav_vel[i] * 0.001f; // mm/frame → m
for (int i = 0; i < 3; ++i) pos_snap[i] = nav_pos[i];
}
// build and send set_transform with pos_snap
};
来源
教程 09 已随 SDK 一起本地安装——请查看 tutorials/09-haply-inverse-ws-remote-control/ 位于服务安装目录下。
相关: set_transform 命令 · 会话 — 首次消息握手 · 安装与工作区 · 选择器 · 教程 08 — HTTP 远程配置 · 教程 07 — 基座与安装