Skip to content

Sport Client (Joystick) — Python Example

Source: rbq_sdk/python/example/sport/rbq_sport_client_joy.py

Python port of the C++ rbq_sport_client_joy.
Drives the robot using a gamepad / joystick via the Python SportClient API.
Analog sticks stream continuous Move velocity commands at 10 Hz; buttons trigger discrete actions.

How it works

Unlike the C++ version's two-thread design, the Python example uses a single event loop at 10 Hz:

  1. Poll joystick events.
  2. Check button chords → discrete action or analog-stick Move.
  3. Call the matching SportClient method.
  4. Sleep for the remainder of the 100 ms tick.

This is simpler and sufficient for the 10 Hz control rate that the SportClient high-level interface operates at.

Prerequisites

  • rbq_sdk_py installed — see Python SDK Overview.
  • A Linux joystick device at /dev/input/js*.
  • Robot stack running (simulation or hardware).

Run

From rbq_sdk/python/example/sport/:

bash
python3 rbq_sport_client_joy.py <networkInterface> [joystickPath]
# auto-detect joystick:
python3 rbq_sport_client_joy.py eth0
# explicit joystick:
python3 rbq_sport_client_joy.py eth0 /dev/input/js1

Joystick auto-detection order:

  1. argv[2] if given and readable.
  2. $JOY environment variable.
  3. First /dev/input/js* device whose name matches logitech, gamepad, x-box, xbox, or wireless.
  4. First available /dev/input/js* node.
  5. /dev/input/js0 as a last resort.

Gamepad bindings

The mapping follows the Logitech F710 / Xbox layout on Linux.

Button chords (checked first)

Buttons pressedAction
L2 + BDamp — emergency stop
L2 + A (1st press)StandUp — lock joints standing
L2 + A (2nd press)StandDown — go prone
STARTSwitchGait(ID_DEFAULT_MODE) — default gait
L2 + STARTSwitchGait(ID_RUNNING_MODE) — running mode
L2 + XRecoveryStand
R1 + XSwitchGait(ID_CLIMB_MODE) — climb mode
L1 + Xnot supported on this robot
L1 + Ynot supported on this robot
BACKStopMove

Double-click bindings

ButtonWindowAction
Double X400 msLeftSideGait(1)
Double Y400 msRightSideGait(1)
Double R1400 msnot supported on this robot
Double R2 (trigger)400 msnot supported on this robot

Analog stick velocity (when no button is pressed)

Axis constantPhysicalMaps toMax
AXIS_LY (1)Left stick forwardvel_x±1.0 m/s
AXIS_LX (0)Left stick leftvel_y±0.5 m/s
AXIS_RX (3)Right stick leftvyaw±1.0 rad/s

Deadzone: 0.12 on all axes.

Axis and button index reference

python
AXIS_LX, AXIS_LY, AXIS_RX = 0, 1, 3
AXIS_LT, AXIS_RT           = 2, 5   # triggers; idle = -1, full press = +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

These match the standard Xbox / Logitech F710 Linux js* mapping.
If buttons or axes appear swapped on your controller, check with jstest /dev/input/js0.

Key implementation notes

  • edge detection: The Joy class stores prev[] and edge[] arrays. edge[i] is set to True only on a rising transition (button newly pressed, not held), and cleared by end_frame() at the end of each tick.
  • R2 as virtual button: r2_pressed = joy.ax[AXIS_RT] > 0.0; a rising edge r2_edge is computed manually and passed to consume_double.
  • lock_toggle_to_prone: Alternates StandUp / StandDown on successive L2+A presses, matching the physical A2 controller behaviour.
  • Error streak: Consecutive non-zero return codes increment err_streak; a warning is printed every 50 failures.

Differences from the C++ version

AspectC++Python
Thread model2 threads (joy + control)Single loop at 10 Hz
Control rate10 Hz10 Hz
Double-click trackingstd::chrono::steady_clocktime.monotonic()
Joystick APIJoystick C++ classSelf-contained Joy Python class (raw fcntl/struct)

See also

This user manual is intended for RBQ users.