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 이미 포함된 클라이언트가 필요합니다. 튜토리얼 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)’ 장면은 작업 공간의 원점에 구체를 렌더링합니다. 튜토리얼 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
조작법
- 파이썬
- C++
키를 누르고 있으면 계속 이동합니다. 키를 놓으면 멈춥니다.
| 키 | 액션 |
|---|---|
→ / ← | +X / −X |
↑ / ↓ | +Y / −Y |
Page Up / Page Down | +Z / −Z |
= / - | 탐색 속도 높이기 / 낮추기 |
0 | 작업 공간을 원점으로 재설정 |
H | 도움말 보기 |
Esc | 종료 (Ctrl+C (이것도 작동합니다) |
줄 단위 — 입력 후 Enter 키를 누르세요.
| 명령 | 액션 |
|---|---|
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 | 모든 속도를 0으로 설정 |
reset | 초속도 0 및 원점 복귀 |
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 text — 튜토리얼 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}}}}}]
}
포지션은 티크 단위로 누적됩니다. 약 1kHz 간격으로 서비스가 다시 적용됩니다. set_transform 매 틱마다(제로차 홀드) 적용되므로, 작업 영역은 마지막으로 이동시킨 위치에 그대로 유지됩니다.
set_transform vs configure.mount두 명령어 모두 세션별로 영구적인 변환을 저장하지만, 작업 공간 변환은 ~에 더해 파이프라인 내의 마운트 (참조: 마운트 및 작업 공간). 튜토리얼 09가 재생 중입니다 set_transform 매 틱마다, 새로운 WebSocket 프레임은 이전에 스트리밍된 작업 공간 변환을 대체하므로, 다른 클라이언트가 스트리밍하는 set_transform 동일한 장치에 대한 설정은 다음 틱에서 재설정됩니다. configure.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 flag는 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 — 베이스 및 마운트