Sport Client (조이스틱) — Python 예제
소스: rbq_sdk/python/example/sport/rbq_sport_client_joy.py
C++의 rbq_sport_client_joy를 Python으로 포팅한 버전입니다.
게임패드 / 조이스틱을 사용해 Python SportClient API로 로봇을 제어합니다.
아날로그 스틱은 10 Hz로 연속 Move 속도 명령을 전송하고, 버튼은 이산 동작을 트리거합니다.
동작 방식
C++ 버전의 2스레드 설계와 달리, Python 예제는 단일 이벤트 루프 (10 Hz)를 사용합니다:
- 조이스틱 이벤트 폴링.
- 버튼 조합 확인 → 이산 동작 또는 아날로그 스틱
Move. - 해당
SportClient메서드 호출. - 100 ms 틱의 나머지 시간 동안 슬립.
SportClient 고수준 인터페이스가 동작하는 10 Hz 제어 속도에 충분한 단순한 구조입니다.
사전 요구사항
rbq_sdk_py설치 완료 — Python SDK 개요 참조.- Linux 조이스틱 장치
/dev/input/js*. - 로봇 스택이 실행 중이며 네트워크 접근 가능.
실행
bash
python3 rbq_sport_client_joy.py <networkInterface> [joystickPath]
# 조이스틱 자동 감지:
python3 rbq_sport_client_joy.py eth0
# 장치 직접 지정:
python3 rbq_sport_client_joy.py eth0 /dev/input/js1조이스틱 자동 감지 순서:
- 지정된
argv[2](읽기 가능한 경우). $JOY환경 변수.- 이름에
logitech,gamepad,x-box,xbox,wireless가 포함된 첫 번째/dev/input/js*. - 사용 가능한 첫 번째
/dev/input/js*노드. - 최후 수단으로
/dev/input/js0.
게임패드 버튼 매핑
Linux에서 Logitech F710 / Xbox 레이아웃 기준.
버튼 조합 (chord) — 우선 검사
| 누르는 버튼 | 동작 |
|---|---|
| L2 + B | Damp — 비상 정지 |
| L2 + A (첫 번째 누름) | StandUp — 서기 자세로 관절 고정 |
| L2 + A (두 번째 누름) | StandDown — 엎드리기 |
| START | SwitchGait(ID_DEFAULT_MODE) — 기본 보행 |
| L2 + START | SwitchGait(ID_RUNNING_MODE) — 달리기 모드 |
| L2 + X | RecoveryStand |
| R1 + X | SwitchGait(ID_CLIMB_MODE) — 등반 모드 |
| L1 + X | 이 로봇에서는 지원하지 않음 |
| L1 + Y | 이 로봇에서는 지원하지 않음 |
| BACK | StopMove |
더블 클릭 매핑
| 버튼 | 윈도우 | 동작 |
|---|---|---|
| X 더블 클릭 | 400 ms | LeftSideGait(1) |
| Y 더블 클릭 | 400 ms | RightSideGait(1) |
| R1 더블 클릭 | 400 ms | HandStand(1) |
| R2 (트리거) 더블 클릭 | 400 ms | BipedStand(1) |
아날로그 스틱 속도 제어 (버튼 입력 없을 때)
| 축 상수 | 물리적 동작 | 매핑 | 최대값 |
|---|---|---|---|
AXIS_LY (1) | 왼쪽 스틱 앞으로 | vel_x | ±1.0 m/s |
AXIS_LX (0) | 왼쪽 스틱 왼쪽으로 | vel_y | ±0.5 m/s |
AXIS_RX (3) | 오른쪽 스틱 왼쪽으로 | vyaw | ±1.0 rad/s |
데드존: 모든 축에 0.12 적용.
⚠️ 주의 — FrontFlip, BackFlip은 넓은 공간에서만 실행해야 합니다.
축 및 버튼 인덱스 참조
python
AXIS_LX, AXIS_LY, AXIS_RX = 0, 1, 3
AXIS_LT, AXIS_RT = 2, 5 # 트리거; 유휴 = -1, 완전 누름 = +1
PAD_A, PAD_B, PAD_X, PAD_Y = 0, 1, 2, 3
PAD_LB, PAD_RB = 4, 5 # L1, R1
PAD_BACK, PAD_START = 6, 7컨트롤러에서 버튼이나 축이 바뀌어 보이면 jstest /dev/input/js0으로 확인하세요.
주요 구현 사항
- 엣지 감지:
Joy클래스가prev[]와edge[]배열을 관리합니다.edge[i]는 상승 전환(새로 누름, 홀드 아님)에서만True로 설정되며end_frame()에서 초기화됩니다. - R2를 가상 버튼으로 처리:
r2_pressed = joy.ax[AXIS_RT] > 0.0; 상승 엣지r2_edge가 수동으로 계산되어consume_double에 전달됩니다. lock_toggle_to_prone:L2+A연속 누름 시StandUp/StandDown을 번갈아 수행합니다 (실제 A2 컨트롤러 동작과 동일).- 에러 스트릭: 연속 비정상 반환 코드는
err_streak을 증가시키며 50번마다 경고를 출력합니다.
C++ 버전과의 차이점
| 항목 | C++ | Python |
|---|---|---|
| 스레드 모델 | 2스레드 (조이스틱 + 제어) | 단일 루프 (10 Hz) |
| 제어 속도 | 10 Hz | 10 Hz |
| 더블 클릭 추적 | std::chrono::steady_clock | time.monotonic() |
| 조이스틱 API | C++ Joystick 클래스 | 자체 Python Joy 클래스 (raw fcntl/struct) |
