reachy-mini

SKILL.md

Reachy Mini SDK

Quick Start

from reachy_mini import ReachyMini
from reachy_mini.utils import create_head_pose
import numpy as np

with ReachyMini() as robot:
    robot.wake_up()

    # Move head
    pose = create_head_pose(x=0, y=0, z=0, roll=0, pitch=10, yaw=20, degrees=True)
    robot.goto_target(head=pose, antennas=[0.3, -0.3], duration=1.0)

    # Get camera frame
    frame = robot.media.get_frame()  # Returns BGR numpy array

    robot.goto_sleep()

Connection Options

# Local USB connection (default)
ReachyMini()

# Network discovery
ReachyMini(localhost_only=False)

# Simulation mode
ReachyMini(use_sim=True)

# Auto-spawn daemon
ReachyMini(spawn_daemon=True)

# Full options
ReachyMini(
    robot_name="reachy_mini",       # Robot identifier
    localhost_only=True,            # True=local daemon, False=network discovery
    spawn_daemon=False,             # Auto-spawn daemon process
    use_sim=False,                  # Use MuJoCo simulation
    timeout=5.0,                    # Connection timeout (seconds)
    automatic_body_yaw=True,        # Auto body yaw in IK
    log_level="INFO",               # "DEBUG", "INFO", "WARNING", "ERROR"
    media_backend="default"         # "default", "gstreamer", "webrtc", "no_media"
)

Head & Antenna Control

Creating Poses

from reachy_mini.utils import create_head_pose

# By position and rotation (degrees by default)
pose = create_head_pose(x=0, y=0, z=0, roll=0, pitch=15, yaw=-10, degrees=True)

# In radians
pose = create_head_pose(pitch=0.26, yaw=-0.17, degrees=False)

# Position in millimeters
pose = create_head_pose(x=50, y=0, z=30, mm=True)

Moving the Robot

from reachy_mini.motion.goto_move import InterpolationTechnique

# Immediate position (no interpolation)
robot.set_target(head=pose, antennas=[0.5, -0.5], body_yaw=0.1)

# Smooth motion with duration
robot.goto_target(
    head=pose,
    antennas=[0.5, -0.5],  # [right, left] in radians
    duration=1.0,
    method=InterpolationTechnique.MIN_JERK,
    body_yaw=0.0
)

Interpolation methods:

  • LINEAR - Linear interpolation
  • MIN_JERK - Default, smoothest motion
  • EASE_IN_OUT - Smooth start and end
  • CARTOON - Exaggerated animation style

Look-At Functions

# Look at pixel coordinates in camera image
robot.look_at_image(u=320, v=240, duration=0.5)

# Look at 3D world point (meters from robot origin)
robot.look_at_world(x=0.5, y=0.1, z=0.3, duration=0.5)

# Get pose without moving
pose = robot.look_at_image(u=320, v=240, perform_movement=False)

Antenna Values

Antennas are [right_angle, left_angle] in radians:

  • 0.0 = antennas down/closed
  • Positive = antennas up/open
  • Typical range: -0.5 to 1.0 radians

State Queries

# Current head pose (4x4 matrix)
pose = robot.get_current_head_pose()

# Joint positions
head_joints, antenna_joints = robot.get_current_joint_positions()
# head_joints: 7 values (body_rotation + 6 stewart platform)
# antenna_joints: 2 values [right, left]

# Antenna positions only
antennas = robot.get_present_antenna_joint_positions()  # [right, left]

Motor Control

# Enable/disable all motors
robot.enable_motors()
robot.disable_motors()

# Specific motors
robot.enable_motors(ids=["right_antenna", "left_antenna"])
robot.disable_motors(ids=["body_rotation"])

Motor IDs: "body_rotation", "stewart_1" through "stewart_6", "right_antenna", "left_antenna"

# Gravity compensation (requires Placo kinematics)
robot.enable_gravity_compensation()
robot.disable_gravity_compensation()

Behaviors

robot.wake_up()     # Wake animation + sound
robot.goto_sleep()  # Sleep position + sound

Camera

# Get frame (BGR numpy array, or None if unavailable)
frame = robot.media.get_frame()

# Camera properties
width, height = robot.media.camera.resolution
fps = robot.media.camera.framerate
K = robot.media.camera.K  # 3x3 intrinsic matrix
D = robot.media.camera.D  # Distortion coefficients

# Change resolution
from reachy_mini.media.camera.camera_constants import CameraResolution
robot.media.camera.set_resolution(CameraResolution.R1920x1080at30fps)

Common resolutions: R1280x720at30fps, R1280x720at60fps, R1920x1080at30fps, R1920x1080at60fps, R3840x2160at30fps

Audio

# Play sound file
robot.media.play_sound("wake_up.wav")

# Record audio
robot.media.start_recording()
sample = robot.media.get_audio_sample()  # numpy array
robot.media.stop_recording()

# Stream audio output
robot.media.start_playing()
robot.media.push_audio_sample(audio_data)
robot.media.stop_playing()

# Audio specs
sample_rate = robot.media.get_input_audio_samplerate()  # 16000 Hz
channels = robot.media.get_input_channels()  # 2

# Direction of Arrival (ReSpeaker only)
angle, valid = robot.media.get_DoA()  # angle in radians (0=left, pi/2=front, pi=right)

Motion Recording & Playback

Recording

robot.start_recording()
# ... perform motions manually or via code ...
recorded_data = robot.stop_recording()
# Returns list of dicts with timestamps, poses, joint positions

Playing Recorded Moves

from reachy_mini.motion.recorded_move import RecordedMoves

# Load move library from HuggingFace
moves = RecordedMoves("pollen-robotics/reachy-mini-dances-library")

# List available moves
print(moves.list_moves())

# Play a move
move = moves.get("dance_name")
robot.play_move(move, initial_goto_duration=1.0, sound=True)

# Async playback
await robot.async_play_move(move)

Kinematics

Three engines available:

Engine Install Speed Features
AnalyticalKinematics Default Fast Always available
PlacoKinematics pip install reachy_mini[placo_kinematics] Medium Collision checking, gravity compensation
NNKinematics pip install reachy_mini[nn_kinematics] Very fast Neural network based
# Direct kinematics access
from reachy_mini.kinematics.analytical import AnalyticalKinematics

kin = AnalyticalKinematics()
joint_angles = kin.ik(pose, body_yaw=0.0)  # Inverse kinematics: pose -> joints
pose = kin.fk(joint_angles)                 # Forward kinematics: joints -> pose

Simulation

# Start with simulation
robot = ReachyMini(use_sim=True)

# Or via daemon CLI
# reachy-mini-daemon --sim

Common Patterns

Face Tracking

# Detect face, get center coordinates (u, v)
robot.look_at_image(u=face_center_x, v=face_center_y, duration=0.3)

Expressive Movements

# Happy - antennas up
robot.goto_target(antennas=[0.8, 0.8], duration=0.3)

# Sad - antennas down
robot.goto_target(antennas=[-0.3, -0.3], duration=0.5)

# Curious tilt
pose = create_head_pose(roll=15, pitch=10, degrees=True)
robot.goto_target(head=pose, duration=0.4)

Idle Animation Loop

import time
while True:
    robot.goto_target(head=create_head_pose(yaw=10, degrees=True), duration=2.0)
    time.sleep(2.0)
    robot.goto_target(head=create_head_pose(yaw=-10, degrees=True), duration=2.0)
    time.sleep(2.0)

Reference Documentation

  • Architecture & Deployment - Daemon/client split, deployment modes (USB, wireless, simulation), running code, app distribution
  • API Reference - Complete method signatures, all parameters and return types
  • Motion Reference - Interpolation details, Move classes, GotoMove, RecordedMove
  • Media Reference - All camera resolutions, audio specs, backend options
  • Application Patterns - Advanced patterns: MovementManager, layered motion, audio-reactive movement, face tracking, LLM tool systems, OpenAI realtime integration
Weekly Installs
5
Installed on
claude-code4
opencode3
codex3
gemini-cli3
windsurf2
trae2