주요 내용으로 이동

09. WebSocket 작업 공간 탐색기

WebSocket 채널을 통해 스트리밍 방식으로 전송함으로써 set_transform 명령, 실시간 내비게이션 기기의작업 공간 위치. 이 튜토리얼에서는 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 클라이언트가 이미 있어야 합니다. 튜토리얼 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

제어​

특정 키를 누르고 있으면 계속 이동할 수 있으며, 손을 떼면 멈춥니다.

버튼작업
→ / ←+X / −X
↑ / ↓+Y / −Y
Page Up / Page Down+Z / −Z
= / -탐색 속도 높이기 / 낮추기
0작업 공간을 원점으로 재설정
H도움말 보기
Esc종료(Ctrl+C (마찬가지로 유효함)

작동 원리​

1단계 — HTTP 세션 및 장치 탐지​

이 튜토리얼에서는 재사용과 튜토리얼 08 같은 discover_session() / discover_device() 보조 함수: 먼저 실행 GET /sessions(만약 지정된 경우 --session, 이면 GET /sessions/<selector>), 그 다음 다음을 실행합니다. GET /devices(또는 직접 사용) --device). 두 보조 함수는 동일한 명령줄 인수를 받아들이며, 또한 SESSION_HELP 텍스트가 완전히 일치합니다. 튜토리얼 00 또는 08에 나오는 선택기는 수정할 필요 없이 여기에서 바로 사용할 수 있습니다.

2단계 — WebSocket 세션과 첫 번째 메시지의 핸드셰이크​

이 튜토리얼에서는 다음을 가리키는 ws://localhost:10001 WebSocket.첫 번째 메시지를 수신했을 때만,이때 세션 구성 등록 정보를 전송합니다:

{
"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(0차 유지)이므로 작업 공간은 마지막으로 푸시한 위치 그대로 유지됩니다.

set_transform 와 configure.mount 의 차이

두 명령어 모두 각 세션에 대해 하나의 영구 변환을 저장하지만, 파이프라인에서는 작업 공간 변환이 마운트된 위치에 있습니다.그 위(참조: 마운트 및 작업 공간). 튜토리얼 09에서는 매 틱마다 스트리밍 방식으로 전송할 때 set_transform 이때, 새로운 WebSocket 프레임 하나하나가 이전에 스트리밍으로 전송된 작업 공간 변환을 대체하게 됩니다. 따라서 동일한 장치로 스트리밍되는 다른 어떤 것도 set_transform 의 클라이언트는 다음 틱에서 덮어쓰게 됩니다.configure.mount 서로 독립적이며, 그 값을 변함없이 유지합니다. 실제 사용 시, 각 역할 유형별로 하나의 채널을 선택합니다: 물리적 설정을 위한 마운트,set_transform 실시간 내비게이션에 사용됩니다.

스레드 모델 (C++)​

이 C++ 튜토리얼에서는 두 개의 스레드가 하나의 위치 누적기를 공유하는 방법을 다룹니다:

스레드직무
메인 스레드읽기 std::getline(std::cin, ...), 토큰 분석, 업데이트 nav_vel[] 와 default_step
WebSocket 콜백 스레드사용 nav_vel[] * dt 추진 nav_pos[], 직렬화 set_transform 그리고 보내기

std::mutex nav_mutex 보호 nav_pos[]、nav_vel[] 와 default_step。last_tick 타임스탬프와 first_ws_msg `mark`는 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
};

소스 코드​

SDK 설치 프로그램과 함께 제공됩니다

튜토리얼 09는 SDK와 함께 로컬에 설치되어 있으므로, 서비스 설치 디렉터리 내의 tutorials/09-haply-inverse-ws-remote-control/ 에서 검색하세요.

관련 내용: set_transform 명령 · 세션 — 첫 번째 메시지 핸드셰이크 · 마운트 및 작업 공간 · 선택기 · 튜토리얼 08 — HTTP 원격 구성 · 튜토리얼 07 — Basis와 마운트