09. WebSocket 工作区导航器
浏览 工作空间——设备的实时位置,方法是 set_transform-通过 WebSocket 通道流式传输命令。本教程使用 HTTP 来识别会话和设备(就像 教程 08),随后建立一个 WebSocket 连接,以便在每次 tick 时发送持仓更新。
该图说明了两种变换操作之间的区别:
| 操作 | 教程 | 典型用途 |
|---|---|---|
configure.mount — 持久的蒙特变换 | 08 | 仅使用一次(或极少使用),用于描述设备的物理安装过程 |
set_transform — 持久化的工作区转换 | 09(本) | 同样是持久性的,但可以在每个时间点流式传输,以供工作区中的实时导航使用 |
这两个命令均可通过 HTTP 和 WebSocket 调用,而且两者都是 持久的 — 该服务会记住上次发送的值。两者的区别在于用途和更新频率: configure.mount 已针对罕见的更新情况进行了优化(物理配置),而 set_transform 针对高频流媒体播放(场景导航)进行了优化。
请使用 set_transform,当工作区的原点需要跟随一个在运行时发生变化的对象时,例如一只手、一个动画化的过程偏移量,或者一位操作员实时移动虚拟工作区。
单就其本身而言,似乎 configure.mount und set_transform 虽然能产生同样的效果,但它们 按层次关联: 工作空间变换将在坐标处理管道中进行 auf简体中文(大陆) den Mount 应用(device → basis → mount → workspace → application). 完整的流程请参见 安装与工作区.
应用场景
- 工作空间中的实时导航。在不暂停触觉场景的情况下,移动设备的游标工作空间(即末端执行器能够到达的边界区域)。
- 由操作员控制的定位。在主触觉应用程序运行期间,可让另一名操作员在第二个终端上长按方向键来移动工作区——这在会话进行期间对工作站进行校准非常有用。
- 基于流程的工作区移动。通过在每次时钟脉冲时发送纯位置变换补丁,可在脚本中控制工作区的位置(如音频控制、基于物理等)。
先决条件
教程 09 需要一个活跃的 WebSocket 会话,即一个客户端,其Inverse3 已在运行中的触觉循环中处于活动状态。教程 09 随后会连接到该会话,并实时移动其工作区。
打开Haply Hub并启动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”场景会在工作区的原点处渲染一个球体——当您按照教程 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++
按住任意按键即可持续移动。松开按键即可停止。
| 口味 | Aktion |
|---|---|
→ / ← | +X / −X |
↑ / ↓ | +Y / −Y |
Page Up / Page Down | +Z / −Z |
= / - | 提高/降低航行速度 |
0 | 将工作区重置为初始状态 |
H | 显示帮助 |
Esc | 结束 (Ctrl+C (同样有效) |
基于行输入——输入命令后按回车键。
| 命令 | Aktion |
|---|---|
x+[N] / x-[N] | 将X轴速度设置为±N mm/帧(未使用具体数值) x+ (当前标准速度) |
y+[N] / y-[N] | 将Y轴速度设置为±N mm/帧 |
z+[N] / z-[N] | 将Z轴速度设置为±N mm/帧 |
s+[N] / s-[N] | 调整标准速度至 ±N mm/帧 |
stop | 将所有速度设为零 |
reset | 将速度设为零并返回原点 |
h | 显示帮助 |
按Ctrl+C(或 Ctrl+D / EOF)退出程序。
工作原理
步骤 1 — HTTP 会话和设备识别
本教程使用了相同的辅助函数 discover_session() / discover_device() wie简体中文(大陆) 教程 08: GET /sessions (或 GET /sessions/<selector> mit --session),随后 GET /devices (或直接 --device (使用)。这两个辅助函数都支持相同的 CLI 标志,且其 SESSION_HELP-文本——来自教程 00 或 08 的选择器在此处无需修改即可使用。
步骤 2 — 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}}}}}]
}
后续的Ticks让 session weg — 仅发送命令数组 inverse3.
步骤 3 — set_transform pro Tick
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这两个命令都会为每个会话保存一个持久化转换。然而,工作区转换位于管道中 auf简体中文(大陆) dem Mount(参见 安装与工作区). Solange 教程 09:每次时钟脉冲 set_transform 在流式传输过程中,每个新的 WebSocket 帧都会替换之前流式传输的工作区转换。另一个客户端,如果 set_transform 由于同一台设备正在进行流媒体传输,因此该数据将在下一个时标被覆盖。 configure.mount 这与之无关,且其价值依然存在。在实际操作中,您应针对每项需求选择一个渠道:Mount 用于物理配置, set_transform 用于实时导航。
线程模型(C++)
该 C++ 教程使用了两个线程,它们共享一个位置累加器:
| 主题 | 罗勒 |
|---|---|
| 主线程 | Liest std::getline(std::cin, ...), 解析令牌,更新 nav_vel[] und default_step |
| WebSocket 回调线程 | Schreibt nav_pos[] 嗯 nav_vel[] * dt fort,连载 set_transform 并发送 |
std::mutex nav_mutex 保护 nav_pos[], nav_vel[] und 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 · 会话——通过第一条消息建立连接 · 安装与工作区 · Selektoren · 教程 08 — HTTP 远程配置 · 教程 07 — 基座与安装