주요 콘텐츠로 건너뛰기
버전: 3.5.x

07. 베이시스 & 마운트 놀이터

장치의 기능을 대화형으로 제어합니다 마운트 변환 그리고 어떻게 하는지 보여줍니다 configure.basis, configure.preset및 configure.mount 와이어에서 함께 작업합니다. 수평 바닥을 고정시켜 두어, 구성 명령어에 대한 상호작용의 초점이 유지되도록 합니다.

배울 내용:

  • 설정 기초 순열 ("XZY" → Y-up 적용 프레임)
  • 선택하기 사전 설정 (arm_front) 및 해당 설정이 무엇을 구성하는지 이해하는 것
  • 실행 시점에 회전 쿼터니언을 사용하여 마운트 재정의하기 (키보드 제어)
  • 상호 배제 법칙: mount 그리고 preset 같은 곳에 공존할 수 없다 장치 구성 블록
  • 단편 configure 의미: 키를 누를 때마다 정확히 하나의 구성 메시지가 전송됩니다
  • (C++ Glaze) 배타적 필드 모델링 std::optional

작업 흐름​

  1. 첫 번째 메시지에: 다음을 보내세요 세션 프로필, configure.basis: "XZY"및 configure.preset: arm_front. 보내기 시작 set_cursor_force 고정 바닥용.
  2. 각 틱마다: 커서의 Y 좌표를 읽고, 계산한다 force_y = max(0, (floor_pos - y) * stiffness), 보내주세요.
  3. 사용자가 마운트 회전 키를 누르면, 플래그 pending_configure = true.
  4. 다음 틱에: 다음을 생성합니다 configure.mount 변환이 적용된 블록으로 rotation 는 단위 쿼터니언(현재 피치와 요의 Z-X 순서 합성)입니다. 생략 preset — 이 두 가지는 회선상에서 서로 배타적입니다.
  5. 재설정 키 (R)는 재정의 설정을 초기화하며, 다음 configure 단계에서는 preset 또.

매개변수​

이름기본값목적
BASIS"XZY"축 순열 — Y-up 적용 프레임
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"명명된 프리셋 — 기기의 바닥면을 원점으로 함
FLOOR_POS_Y0.0 m고정 바닥면 (Y축 적용)
STIFFNESS1000 해당 없음바닥 스프링 상수
MOUNT_STEP_DEG10°키를 누를 때마다 회전
PRINT_EVERY_MS200텔레메트리 스로틀

조작법​

키액션
W / S장치 +X축을 중심으로 마운트를 ±10° 회전(피치)
A / D장치 +Z축을 중심으로 마운트를 ±10° 회전(요)
R마운트 초기화 — 사전 설정으로 복원
H제어 항목 표시
Q종료
mount 그리고 preset 서로 배타적이다

이 서비스는 장치 구성 두 가지를 모두 포함하는 블록. 사용자가 마운트를 재정의하면, 튜토리얼에서는 preset 이후의 모든 configure 단계에서. 누르면 R 다시 활성화 preset 다음 configure 및 drops 시 mount.

다양한 입력 모델

C++ 변형은 백그라운드 stdin 스레드에서 줄 단위로 입력을 읽습니다(각 문자를 입력한 후 Enter 키를 누르세요). Python은 keyboard 메인 비동기 루프에서 실시간 키 폴링을 수행하는 패키지 — 엔터 키를 누를 필요가 없습니다. 동일한 키, 동일한 명령어입니다.

상태 필드 읽기​

발신자 data.inverse3[i].state:

  • cursor_position.y — vec3, 바닥 관통 깊이를 계산하는 데 사용됨
  • current_cursor_force — 원격 측정용으로 보고됨

보내기 / 받기​

페이로드의 형태는 모든 변형에서 동일하며, 흥미로운 차이점은 각 변형이 상호 배타적인 방식을 어떻게 구성하는지에 있다. mount / preset 분기 처리 및 입력 스레드가 WebSocket 스레드에 신호를 보내는 방식.

다음과 같은 실시간 키 폴링을 사용하는 단일 비동기 루프 keyboard 패키지. pending_configure 키 핸들러에 의해 설정되는 전역 플래그이며, 매번 configure 블록이 전송됩니다.

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["inverse3"][0]["device_id"]
# Handshake: profile + basis + preset
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": build_configure_block(first_handshake=True),
# -> {"basis": {"permutation": "XZY"},
# "preset": {"preset": "arm_front"}}
}],
}
else:
handle_key_inputs() # may set pending_configure = True (classic, not shown)

y = data["inverse3"][0]["state"]["cursor_position"]["y"]
force_y = 0.0 if y > FLOOR_POS_Y else (FLOOR_POS_Y - y) * STIFFNESS

entry = {
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": force_y, "z": 0.0}}},
}
if pending_configure:
entry["configure"] = build_configure_block(first_handshake=False)
# -> {"mount": {...}} OR {"preset": {...}} (never both)
pending_configure = False

request_msg = {"inverse3": [entry]}

await websocket.send(json.dumps(request_msg))
SDK 설치 프로그램과 함께 제공

튜토리얼 07도 SDK와 함께 로컬에 설치되어 있습니다. 다음 경로를 확인해 보세요. tutorials/07-haply-inverse-basis-and-mount/ 서비스 설치 디렉터리 아래에.

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

관련 기사: 기저 순열 · 마운트 및 작업 공간 · 장치 구성 · 제어 명령어 (set_cursor_force) · 유형 (변환) · 튜토리얼 04 (Hello Floor)