Skip to content

ai-libre/beachy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Reachy Elixir

Elixir/OTP implementation of the Reachy Mini robot control system, designed for fault-tolerance, real-time control, and expressive behaviors.

Features

  • Fault-Tolerant Architecture: Supervision trees mirror physical robot structure
  • Real-Time Control: 50Hz motor control loops with trajectory interpolation
  • Native Performance: Zig NIFs for Dynamixel protocol, Rust NIFs for kinematics
  • Expressive Behaviors: Idle animations, face tracking, and more
  • Web Interface: REST API and WebSocket for remote control
  • Nerves Ready: Production deployment to Raspberry Pi

Architecture

ReachyMini.Supervisor
β”œβ”€β”€ Registry
β”œβ”€β”€ PubSub
β”œβ”€β”€ DynamixelBus (Zig NIF)
β”œβ”€β”€ Safety.Controller
β”œβ”€β”€ Actuators.MotorSupervisor
β”‚   β”œβ”€β”€ Motor (body_yaw)
β”‚   β”œβ”€β”€ Motor (stewart_1..6)
β”‚   └── Motor (antenna_left, antenna_right)
β”œβ”€β”€ Actuators.StewartPlatform (Rust NIF)
β”œβ”€β”€ Motion
β”œβ”€β”€ Behaviors.Supervisor
β”‚   β”œβ”€β”€ IdleAnimations
β”‚   β”œβ”€β”€ FaceTracking
β”‚   └── Animations
β”œβ”€β”€ Recording
└── Bridge.Endpoint (Phoenix)

Quick Start

Development (Simulation)

# Install dependencies
mix deps.get

# Run in simulation mode
MIX_TARGET=host mix run --no-halt

# In another terminal, interact via IEx
iex -S mix

Hardware (Raspberry Pi)

# Set target
export MIX_TARGET=rpi4

# Get dependencies and build firmware
mix deps.get
mix firmware

# Deploy to robot
mix upload reachy.local

Usage

# Arm the robot
ReachyMini.arm()

# Move head
ReachyMini.set_head_pose(%{pitch: 0.2, yaw: 0.3})

# Look at a point
ReachyMini.look_at({0.5, 0.1, 0.3})

# Play animation
ReachyMini.play_animation(:happy)

# Wiggle antennas
ReachyMini.wiggle_antennas()

# Disarm
ReachyMini.disarm()

API

REST Endpoints

Endpoint Method Description
/api/state GET Get full robot state
/api/arm POST Arm the robot
/api/disarm POST Disarm the robot
/api/move/head POST Move head to pose
/api/move/look_at POST Look at point
/api/animation/:name POST Play animation

WebSocket

Connect to /api/ws for real-time updates:

const socket = new Phoenix.Socket("/api/ws")
socket.connect()

const channel = socket.channel("state:full")
channel.on("state", state => console.log(state))
channel.join()

Configuration

# config/config.exs

config :beachy,
  robot_name: "beachy",
  control_rate_hz: 50,
  dynamixel: [
    port: "/dev/ttyUSB0",
    baudrate: 1_000_000
  ],
  motors: %{
    body_yaw: %{id: 10, model: :xc330_m288},
    stewart_1: %{id: 11, model: :xl330_m288},
    # ...
  }

Project Structure

lib/
β”œβ”€β”€ beachy.ex              # Main API
β”œβ”€β”€ beachy/
β”‚   β”œβ”€β”€ application.ex          # OTP Application
β”‚   β”œβ”€β”€ safety.ex               # Safety controller
β”‚   β”œβ”€β”€ motion.ex               # Motion coordination
β”‚   β”œβ”€β”€ recording.ex            # Motion recording/playback
β”‚   β”œβ”€β”€ diagnostics.ex          # System diagnostics
β”‚   β”œβ”€β”€ telemetry.ex            # Metrics collection
β”‚   β”œβ”€β”€ actuators/
β”‚   β”‚   β”œβ”€β”€ motor.ex            # Individual motor control
β”‚   β”‚   β”œβ”€β”€ motor_supervisor.ex # Motor supervision
β”‚   β”‚   └── stewart_platform.ex # Stewart platform control
β”‚   β”œβ”€β”€ kinematics/
β”‚   β”‚   └── stewart.ex          # Stewart platform kinematics
β”‚   β”œβ”€β”€ protocol/
β”‚   β”‚   β”œβ”€β”€ dynamixel.ex        # Dynamixel protocol (Zig NIF)
β”‚   β”‚   └── dynamixel_bus.ex    # Serial bus management
β”‚   β”œβ”€β”€ behaviors/
β”‚   β”‚   β”œβ”€β”€ supervisor.ex       # Behavior supervision
β”‚   β”‚   β”œβ”€β”€ idle_animations.ex  # Idle animations
β”‚   β”‚   β”œβ”€β”€ face_tracking.ex    # Face tracking
β”‚   β”‚   └── animations.ex       # Predefined animations
β”‚   └── bridge/
β”‚       β”œβ”€β”€ endpoint.ex         # Phoenix endpoint
β”‚       β”œβ”€β”€ router.ex           # API routes
β”‚       β”œβ”€β”€ socket.ex           # WebSocket
β”‚       └── controllers/        # API controllers

native/
β”œβ”€β”€ dynamixel_nif/              # Zig implementation
β”‚   └── dynamixel.zig
└── kinematics_nif/             # Rust implementation
    β”œβ”€β”€ Cargo.toml
    └── src/lib.rs

Native Code

Dynamixel Protocol (Zig)

High-performance packet building and parsing with compile-time CRC tables:

// Build a sync write packet for all Stewart motors
pub fn buildSyncWritePacket(ids: []const u8, address: u16, ...) Packet

Stewart Platform Kinematics (Rust)

Fast inverse/forward kinematics using nalgebra:

// Compute leg lengths for desired head pose
pub fn inverse_kinematics(pose: &Pose) -> Result<[f64; 6], ()>

Testing

# Run all tests
mix test

# Run with coverage
mix test --cover

# Run specific test
mix test test/beachy/kinematics/stewart_test.exs

Deployment

OTA Updates

# Build new firmware
mix firmware

# Push to running robot
mix upload reachy.local

SSH Access

ssh reachy.local

# In IEx
iex> ReachyMini.status()
iex> ReachyMini.run_diagnostics()

License

Apache 2.0

About

BEAM + Reachy = Beachy πŸ–οΈ Fault-tolerant Elixir robotics for Reachy Mini.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published