Зачем ИИ нужно тело? (Спойлер: без него он просто болтает)
Все эти LLM в облаках — они как философы в башне из слоновой кости. Умные, эрудированные, но дверь открыть не могут. Embodiment — это когда ИИ получает руки, ноги и глаза. Когда он может взаимодействовать с физическим миром, а не просто генерировать текст про него.
Rider Pi — это минимальный жизнеспособный продукт в мире воплощенного ИИ. Не робот-гуманоид за миллион долларов, а простая платформа на колесах, которая видит, думает и двигается. И самое главное — вы можете собрать ее за выходные.
Важно: Этот проект не про супер-сложные нейросети. Мы используем Raspberry Pi 5, а не сервер с восемью H100. Здесь главное — архитектура, а не вычислительная мощность. Если нужны тяжелые модели — смотрите гайд про подключение eGPU к Raspberry Pi.
Что внутри коробки (и почему Mius-UI — темная лошадка)
Список компонентов выглядит скромно, но каждый элемент выбран не просто так:
- Raspberry Pi 5 (8GB) — мозг системы. Pi 4 тоже сойдет, но с Pi 5 OpenCV работает в 2-3 раза быстрее.
- Камера Raspberry Pi HQ Camera — 12.3 МП, сменные объективы. Можно и обычную V2, но HQ дает больше деталей.
- Двигатели с энкодерами + драйвер L298N — базовый набор для движения. Если хочется плавности — берите драйверы на DRV8833.
- Аккумулятор 12V + понижающий преобразователь до 5V — питание для моторов и Pi.
- Шасси с колесами — любое, где помещается электроника.
А теперь про Mius-UI. Это не просто "еще один дашборд". Это TypeScript-фреймворк для embedded-интерфейсов, который работает на чем угодно — от Raspberry Pi до Radxa RK3588. Легкий (десятки килобайт), быстрый, с native-подобным рендерингом. И да, он умеет в MJPEG-стримы из коробки.
1 Собираем железо: где ошибаются 90% новичков
Схема подключения простая, но есть три критических момента:
- Раздельное питание — моторы кушают 12V, Raspberry Pi — 5V. Если запитать все от одного источника без преобразователя, Pi умрет от скачков напряжения при старте моторов.
- Земля (GND) — общая земля между драйвером моторов и Pi обязательна. Без этого ШИМ-сигналы будут плавать.
- Охлаждение Pi 5 — без радиатора или кулера процессор троттлится через 2 минуты работы с OpenCV.
Собирайте в таком порядке: шасси → моторы → драйвер → аккумулятор → преобразователь → Raspberry Pi → камера. Так проще переделывать, если что-то пошло не так.
2 Настройка Raspberry Pi: не просто apt-get install
Ставим Raspberry Pi OS Lite (64-bit). Desktop не нужен — все равно работаем через SSH и веб-интерфейс.
# Обновляемся до актуальных версий на февраль 2026
sudo apt update && sudo apt full-upgrade -y
# Устанавливаем Python 3.11 (в последних версиях Raspberry Pi OS он по умолчанию)
sudo apt install python3.11 python3.11-venv python3-pip -y
# Устанавливаем OpenCV 4.10 (последняя стабильная на 2026 год)
sudo apt install libopencv-dev python3-opencv -y
# Проверяем установку
python3 -c "import cv2; print(f'OpenCV version: {cv2.__version__}')"
Теперь включаем камеру и I2C/SPI для будущих датчиков:
sudo raspi-config
# Interface Options → Camera → Enable
# Interface Options → I2C → Enable
# Interface Options → SPI → Enable
Предупреждение: Не устанавливайте OpenCV через pip (opencv-python) на Raspberry Pi. Сборка из исходников займет 6 часов, а готовая версия из репозитория оптимизирована под ARM. Разница в скорости — до 40%.
3 Пишем ядро: камера + движение + стрим
Создаем файл rider_core.py. Здесь будет три потока: захват видео, обработка кадров, управление моторами. Не пытайтесь сделать все в одном потоке — камера будет тормозить.
import cv2
import threading
import time
from flask import Flask, Response
import RPi.GPIO as GPIO
class RiderCore:
def __init__(self):
# Настройка GPIO для моторов
self.MOTOR1_PIN1 = 17
self.MOTOR1_PIN2 = 18
self.MOTOR2_PIN1 = 22
self.MOTOR2_PIN2 = 23
GPIO.setmode(GPIO.BCM)
GPIO.setup([self.MOTOR1_PIN1, self.MOTOR1_PIN2,
self.MOTOR2_PIN1, self.MOTOR2_PIN2], GPIO.OUT)
# Инициализация камеры
self.camera = cv2.VideoCapture(0)
self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
self.latest_frame = None
self.frame_lock = threading.Lock()
# Флаг для остановки потоков
self.running = True
def camera_thread(self):
"""Поток захвата видео"""
while self.running:
ret, frame = self.camera.read()
if ret:
with self.frame_lock:
self.latest_frame = frame
time.sleep(0.03) # ~30 FPS
def generate_mjpeg_stream(self):
"""Генератор MJPEG потока для веб-интерфейса"""
while self.running:
with self.frame_lock:
if self.latest_frame is not None:
# Кодируем кадр в JPEG
ret, jpeg = cv2.imencode('.jpg', self.latest_frame,
[cv2.IMWRITE_JPEG_QUALITY, 70])
if ret:
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' +
jpeg.tobytes() + b'\r\n')
time.sleep(0.03)
def move_forward(self, duration=1.0):
"""Движение вперед"""
GPIO.output(self.MOTOR1_PIN1, GPIO.HIGH)
GPIO.output(self.MOTOR1_PIN2, GPIO.LOW)
GPIO.output(self.MOTOR2_PIN1, GPIO.HIGH)
GPIO.output(self.MOTOR2_PIN2, GPIO.LOW)
time.sleep(duration)
self.stop()
def stop(self):
"""Остановка моторов"""
GPIO.output(self.MOTOR1_PIN1, GPIO.LOW)
GPIO.output(self.MOTOR1_PIN2, GPIO.LOW)
GPIO.output(self.MOTOR2_PIN1, GPIO.LOW)
GPIO.output(self.MOTOR2_PIN2, GPIO.LOW)
def cleanup(self):
"""Корректное завершение"""
self.running = False
self.camera.release()
GPIO.cleanup()
# Flask сервер для MJPEG стрима
app = Flask(__name__)
rider = RiderCore()
@app.route('/video_feed')
def video_feed():
return Response(rider.generate_mjpeg_stream(),
mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/move/')
def move(direction):
if direction == 'forward':
rider.move_forward(1.0)
return 'Moving forward'
return 'Unknown direction'
if __name__ == '__main__':
# Запускаем поток камеры
cam_thread = threading.Thread(target=rider.camera_thread)
cam_thread.daemon = True
cam_thread.start()
# Запускаем Flask сервер
app.run(host='0.0.0.0', port=5000, threaded=True)
Это базовая версия. В реальном проекте добавьте обработку ошибок, логирование и конфигурационный файл. И да, используйте threading, а не multiprocessing — на Raspberry Pi разница в накладных расходах заметна.
4 Mius-UI дашборд: где интерфейс весит меньше картинки
Создаем папку mius-dashboard и инициализируем проект:
npm init -y
npm install mius-ui@latest
Файл src/app.tsx:
import { MiusApp, Widget, VideoStream, Button } from 'mius-ui';
const RiderDashboard = () => {
const handleMove = (direction: string) => {
fetch(`http://${window.location.hostname}:5000/move/${direction}`)
.catch(err => console.error('Movement error:', err));
};
return (
CPU Temperature: --°C
Uptime: --
Camera: Active
);
};
export default RiderDashboard;
Собираем и запускаем:
npm run build
# Копируем файлы в /var/www/html или запускаем через serve
npx serve -s build -l 3000
Теперь открываем браузер на http://raspberry-pi-ip:3000 и видим интерфейс с видео-стримом и кнопками управления. Весит это удовольствие ~150KB против 50MB у Electron-аналога.
А теперь добавляем ИИ (но не тот, о котором вы подумали)
Самый частый вопрос: "Какую нейросеть поставить?". Ответ: сначала — самую простую. Не пытайтесь запустить AlpamayoR1 или Youtu-VL-4B-Instruct на Raspberry Pi без eGPU. Начните с классического компьютерного зрения.
Добавляем в rider_core.py обнаружение лиц (как пример):
def detect_faces(self, frame):
"""Обнаружение лиц с помощью Haar cascades"""
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
)
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
return frame, len(faces)
# В потоке камеры после захвата кадра:
processed_frame, face_count = self.detect_faces(frame)
with self.frame_lock:
self.latest_frame = processed_frame
Это работает на Raspberry Pi 5 со скоростью 15-20 FPS. Достаточно для демонстрации. Когда освоите базовый пайплайн — можно подключать легкие модели типа MobileNet или LFM2-350M через Femtobot.
Пять ошибок, которые сломают ваш Rider Pi
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Нет общей земли | Моторы не слушаются, GPIO ведут себя странно | Соединить GND драйвера моторов с GND на Raspberry Pi |
| Питание моторов от 5V пинов Pi | Raspberry Pi перезагружается при движении | Использовать отдельный источник 12V для моторов |
| Блокировка основного потока Flask | Интерфейс "зависает" при движении | Выносить длительные операции в отдельные потоки |
| MJPEG стрим без буферизации | Видео тормозит с несколькими клиентами | Использовать queue.Queue для кадров |
| Отсутствие охлаждения Pi 5 | Троттлинг через 2-3 минуты работы | Установить радиатор или активное охлаждение |
Куда развивать проект (если не надоело)
Базовый Rider Pi — это холст. Вот что можно добавить:
- Навигация по AR-меткам — распознавание AprilTags или ArUco markers для точного позиционирования
- Голосовое управление — Whisper для распознавания команд + локальный TTS
- Автономная навигация — SLAM с помощью Intel RealSense (тяжело для Pi, но возможно)
- Манипулятор — добавить руку как в проекте мобильного робота-манипулятора
- Локальная VLM — запуск легкой vision-language модели для описания окружения
Философский вопрос: это уже ИИ или еще нет?
Rider Pi в текущей версии — это инструмент. Умный инструмент, но инструмент. Настоящее воплощение ИИ начинается, когда система:
- Имеет внутреннюю модель мира (не только текущий кадр, но и память о предыдущих)
- Способна к простейшему планированию ("чтобы объехать препятствие, нужно сначала отъехать назад")
- Может обучаться на своих ошибках (если врезался в стену — запомнить это место)
Но даже в текущем виде Rider Pi делает главное — соединяет код с физическим миром. Из абстрактных чисел в Python — в реальное движение в пространстве. И это, черт возьми, впечатляет.
Собирайте. Экспериментируйте. Ломайте. Чините. Именно так, а не через API-вызовы к ChatGPT, и рождается настоящее понимание того, что такое искусственный интеллект в физическом теле.
P.S. Если ваш Rider Pi научится приносить пиво из холодильника — считайте, что вы опередили Boston Dynamics лет на пять. Шучу. Но попробовать можно.