본문으로 바로 가기

03. 무선 VerseGrip 출력

튜토리얼 02와같은 패턴이지만 무선 VerseGrip용입니다 — 스트리밍 중일 때 버튼(A/B/C)과 배터리 잔량을 표시합니다.

학습 내용:

  • 무선 전용 상태 필드 읽기: buttons.{a,b,c}, battery_level, hall
  • 독립 관찰자용 keepalive로 probe_orientation 사용 방법
  • 튜토리얼 02와같이, 첫 번째 메시지에서만 수행되는 핸드셰이크 패턴

작업 흐름​

  1. ws://localhost:10001WebSocket 연결을 열고 첫 번째 상태 프레임을 기다립니다.
  2. wireless_verse_grip 배열에서 첫 번째 무선 VerseGrip의 device_id를 가져옵니다.
  3. 세션 프로필및 기기별 probe_orientation keepalive를 포함한 요청을 구성합니다.
  4. 요청을 보낸 후 session 필드를 제거합니다 — 이는 일회성 핸드셰이크이기 때문입니다.
  5. 이후 모든 프레임에서 쿼터니언을오일러 각으로 변환하고, 버튼 상태와 배터리 잔량을 포함한 텔레메트리 데이터를 주기적으로 제한하여 출력합니다. 매 틱마다 keepalive 신호를 다시 전송합니다.

매개변수​

이름기본값용도
URIws://localhost:10001시뮬레이션 채널 WebSocket URL
PRINT_EVERY_MS100콘솔 출력 간격 제한
세션 프로필 이름co.haply.inverse.tutorials:print-wireless-verse-gripHaply 허브에서 이 시뮬레이션을 식별
오일러 각 협약

변환은 애플리케이션 좌표계에서 이루어집니다. +X right, +Y forward, +Z up에서 내재적 Z-X-Y 순서(요 → 피치 → 롤)를 따릅니다. glm::eulerAngles를 사용하지 마십시오 — 이 함수는 다른 규약을 따르기 때문에 여기서는 잘못된 값을 읽게 됩니다. 세 가지 언어 변형 모두 동일한 수식을 구현하며, 공식은 소스 코드를 참조하십시오.

probe_orientation실제로 필요한 경우

probe_orientation이 세션은 Inverse3에 어떠한 명령도 전송하지 않을 때만 유용합니다. Inverse3에 명령(힘, 위치, 토크 등)을 전송하는 즉시, 서비스가 모든 상태 프레임에 대응하는 VerseGrip의 방향 값을 자동으로 스트리밍하므로 프로브가 필요하지 않습니다. probe_orientation이 튜토리얼에서와 같이 독립형 그립 모니터링 도구에서만 사용하십시오.

읽기 상태 필드​

data.wireless_verse_grip[0].state에서 읽은 값:

  • orientation — quaternion (w, x, y, z)
  • hall — 정수형 홀 센서 값
  • buttons.a, buttons.b, buttons.c — 불리언
  • battery_level — 실수형 (0.0 – 1.0)
  • transform.rotation — 작업 공간 회전 (quaternion). 방향 전용 장치에는 위치와 스케일이 적용되지 않으므로 전혀 전송되지 않습니다.
부분 업데이트 동작

transform.rotation 값이 항등 쿼터니언인 {w:1,x:0,y:0,z:0}인 경우 생략됩니다. 읽을 때 기본값을 지정하십시오. 항상 수신하려면 serialization/explicit_fields을 활성화하십시오.

송신 / 수신​

튜토리얼 02와 같은 구조이며, 장치 배열만 wireless_verse_grip로 변경됩니다. WebSocket 루프는 상태 프레임을 수신하여 핸드셰이크와 probe_orientation keepalive를 다시 전송합니다. 첫 번째 전송 메시지에는 세션 프로필이 포함되며, 그 이후의 모든 프레임에는 keepalive만 포함됩니다.

단일 비동기 루프입니다.

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
device_id = data["wireless_verse_grip"][0]["device_id"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-wireless-verse-grip"}}},
"wireless_verse_grip": [{
"device_id": device_id,
"commands": {"probe_orientation": {}} # empty — keepalive
}]
}

await websocket.send(json.dumps(request_msg))
request_msg.pop("session", None) # one-shot handshake

명령줄 플래그 (Python)​

Python 변형은 튜토리얼 01과동일한 두 가지 플래그를 지원합니다:

  • --full — 한 줄 요약 대신 원시 JSON 페이로드를 보기 좋게 출력합니다.
  • --query-config — 매 송신 틱마다 session.force_render_full_state를 다시 주입함으로써, 모든 프레임이 상태 변경분만 담는 대신 config 블록이 포함되도록 합니다.

--query-config는 config 블록은 일반 구성 필드 외에도 WVG 전용 sub_type 필드(stylus / prototype / ruko / kingfisher(3.5 버전에서 추가됨)을 포함하고 있어 무선 VerseGrip에서 특히 유용합니다. python 03-haply-inverse-print-wireless-verse-grip.py --full --query-config을 실행하면 다른 구성 값과 함께 config.sub_type 값이 실시간으로 갱신되는 것을 확인할 수 있습니다.

C++ 변형은 이 플래그를 노출하지 않습니다.

SDK 설치 프로그램에 함께 포함됨

튜토리얼 03도 SDK와 함께 로컬에 설치됩니다. 서비스 설치 디렉터리 아래의 tutorials/03-haply-inverse-print-wireless-verse-grip/ 폴더를 확인해 주십시오.

출처: Python · C++ · C++ Glaze

관련 문서: 튜토리얼 02 (유선 VG) · 유형 (쿼터니언) · 제어 명령 (probe_orientation) · WebSocket 프로토콜