Обработка данных и ИИ — Мозг для робота
Робот похож на человека: у него есть чувства (сенсоры), но без мозга (обработки данных) он не сможет ничего понять. Эта часть ПО превращает сырые, шумные данные в осмысленную информацию для принятия решений.
Зачем это нужно?
- Датчики врут — акселерометр дрожит, дальномер ошибается, камера видит помехи
- Мир сложен — объекты меняются, освещение разное, препятствия появляются неожиданно
- Ресурсы ограничены — маленький процессор, мало памяти, надо считать быстро
1. Фильтрация сигналов: Как убрать шум
Представь, что пытаешься слушать музыку в метро. Фильтрация — это наушники с шумоподавлением.
Пример: Дрожащая рука робота
Допустим, ультразвуковой дальномер выдаёт такие значения (расстояние в см):
[10.1, 9.8, 300.0 (выброс!), 10.2, 10.0, 9.9, 10.3]
Настоящее расстояние — 10 см, но датчик шумит и иногда глючит.
Простые методы:
Скользящее среднее (Moving Average)
def moving_average(data, window=3):
result = []
for i in range(len(data)):
window_data = data[max(0, i-window+1):i+1]
result.append(sum(window_data) / len(window_data))
return result
# До: [10.1, 9.8, 300.0, 10.2, 10.0, 9.9, 10.3]
# После (window=3): [10.1, 9.95, 106.63, 106.67, 106.73, 10.03, 10.07]
# Видишь? Выброс 300 всё ещё портит всё!
Медианный фильтр (Median Filter)
def median_filter(data, window=3):
result = []
for i in range(len(data)):
window_data = data[max(0, i-window+1):i+1]
window_data.sort()
result.append(window_data[len(window_data)//2]) # Берем середину
# До: [10.1, 9.8, 300.0, 10.2, 10.0, 9.9, 10.3]
# После: [10.1, 9.8, 10.2, 10.2, 10.0, 10.0, 10.0]
# Выброс 300 исчез! Медиана игнорирует резкие выбросы.
Более умный метод: Комплементарный фильтр
Проблема: У робота есть два датчика положения:
- Гироскоп — точный на коротких дистанциях, но “уплывает” со временем
- Акселерометр — точный в среднем, но шумит при движении
Решение: Объединяем их сильные стороны!
class ComplementaryFilter:
def __init__(self, alpha=0.98):
self.alpha = alpha # Доверие к гироскопу (0-1)
self.angle = 0
def update(self, gyro_rate, accel_angle, dt):
# 1. Гироскоп: angle += скорость * время
gyro_angle = self.angle + gyro_rate * dt
# 2. Смешиваем: 98% гироскопа + 2% акселерометра
self.angle = self.alpha * gyro_angle + (1 - self.alpha) * accel_angle
return self.angle
# Использование
filter = ComplementaryFilter(alpha=0.98)
while True:
# Читаем датчики
gyro = read_gyro() # градусы/секунду
accel = read_accel_angle() # угол по ускорению
# Обновляем фильтр
current_angle = filter.update(gyro, accel, 0.01) # dt = 10 мс
print(f"Текущий угол: {current_angle:.1f}°")
2. Компьютерное зрение: Как робот видит
Робот не видит “кошку” или “стол”. Он видит матрицу чисел (пикселей). Компьютерное зрение превращает эти числа в понимание.
Простой пример: Поиск красного мяча
import cv2
import numpy as np
def find_red_ball(image):
# 1. Преобразуем в HSV (проще работать с цветами)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 2. Задаем диапазон красного цвета
lower_red = np.array([0, 100, 100])
upper_red = np.array([10, 255, 255])
# 3. Ищем красные пиксели
mask = cv2.inRange(hsv, lower_red, upper_red)
# 4. Находим контуры
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 5. Ищем самый большой круглый контур (это и есть мяч)
if contours:
largest = max(contours, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(largest)
if radius > 10: # Игнорируем мелкие шумы
return (int(x), int(y), int(radius))
return None
# Использование в роботе
cap = cv2.VideoCapture(0) # Камера робота
while True:
ret, frame = cap.read()
if not ret:
break
ball = find_red_ball(frame)
if ball:
x, y, radius = ball
print(f"Мяч найден в ({x}, {y}), радиус {radius}")
# Рисуем круг на экране
cv2.circle(frame, (x, y), radius, (0, 255, 0), 2)
cv2.imshow('Робот видит', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Что может OpenCV:
- Распознавание лиц (как в телефоне)
- Чтение QR-кодов (где прописан адрес доставки)
- Определение расстояния по двум камерам (стереозрение)
- Слежение за объектом (держать мяч в центре кадра)
3. Искусственный интеллект: Как робот понимает
ИИ — это не магия, а математика + много данных. Нейросеть учится так же, как ты учишься отличать кошек от собак: показывают много примеров, а потом она сама начинает понимать.
Простая нейросеть для распознавания цифр (MNIST)
import tensorflow as tf
from tensorflow import keras
# 1. Загружаем данные (70,000 рукописных цифр)
mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 2. Создаём модель (очень простая)
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)), # Разворачиваем картинку 28x28
keras.layers.Dense(128, activation='relu'), # Скрытый слой (128 нейронов)
keras.layers.Dense(10, activation='softmax') # Выходной слой (10 цифр: 0-9)
])
# 3. Компилируем
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 4. Обучаем (это долго, можно пропустить на первом знакомстве)
model.fit(train_images, train_labels, epochs=5)
# 5. Тестируем
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"Точность на тесте: {test_acc*100:.2f}%") # Около 98%!
# 6. Используем
import numpy as np
from PIL import Image
# Загружаем свою цифру
img = Image.open('моя_цифра.png').convert('L').resize((28, 28))
img_array = np.array(img) / 255.0 # Нормализуем
img_array = np.expand_dims(img_array, 0) # Добавляем размерность
# Предсказываем
predictions = model.predict(img_array)
predicted_digit = np.argmax(predictions[0])
print(f"Робот думает, что это цифра: {predicted_digit}")
Edge AI: Нейросети прямо на роботе
Проблема: облачные нейросети требуют интернета и работают медленно. Решение: TinyML — крошечные нейросети для микроконтроллеров.
Пример на Arduino с камерой:
// Упрощённый пример для Arduino Nano 33 BLE Sense
#include <TensorFlowLite.h>
#include <tensorflow/lite/micro/all_ops_resolver.h>
#include "model.h" // Предобученная модель
// Загружаем модель
tflite::MicroInterpreter interpreter(model, op_resolver, tensor_arena, kTensorArenaSize);
void setup() {
Serial.begin(9600);
// Инициализация камеры OV7670
camera.begin();
}
void loop() {
// 1. Делаем снимок
uint8_t* image = camera.capture();
// 2. Подготавливаем данные для нейросети
float input[96*96]; // Модель ждёт картинку 96x96
for (int i = 0; i < 96*96; i++) {
input[i] = image[i] / 255.0;
}
// 3. Запускаем нейросеть
interpreter.input(0)->data.f = input;
interpreter.Invoke();
// 4. Получаем результат
float* output = interpreter.output(0)->data.f;
// output[0] - вероятность "кошка"
// output[1] - вероятность "собака"
// output[2] - вероятность "человек"
int prediction = 0;
float max_prob = output[0];
for (int i = 1; i < 3; i++) {
if (output[i] > max_prob) {
max_prob = output[i];
prediction = i;
}
}
const char* classes[] = {"кошка", "собака", "человек"};
Serial.print("Робот видит: ");
Serial.println(classes[prediction]);
delay(1000);
}
Что умеют современные нейросети в роботах:
| Задача | Пример | Технология |
|---|---|---|
| Распознавание объектов | “Это стул, а это стол” | YOLO, SSD |
| Сегментация | “Где точно на картинке дорога?” | U-Net, Mask R-CNN |
| Генерация текста | “Я вижу красный мяч слева” | GPT для роботов |
| Принятие решений | “Объехать слева или справа?” | Обучение с подкреплением |
| Предсказание | “Человек сейчас пойдёт налево” | LSTM, Transformers |
Практическое задание: Робот, который следует за цветом
Создадим простого робота на Raspberry Pi с камерой, который:
- Видит красный объект
- Едет к нему
- Останавливается на расстоянии 30 см
Полный код:
import cv2
import numpy as np
import RPi.GPIO as GPIO
import time
# Настройка моторов Raspberry Pi
GPIO.setmode(GPIO.BCM)
# ... настройка пинов для моторов ...
def find_color_object(frame, color='red'):
"""Находит цветной объект в кадре"""
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
if color == 'red':
lower = np.array([0, 100, 100])
upper = np.array([10, 255, 255])
elif color == 'green':
lower = np.array([40, 100, 100])
upper = np.array([80, 255, 255])
else: # blue
lower = np.array([100, 100, 100])
upper = np.array([140, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
# Находим центр объекта
moments = cv2.moments(mask)
if moments['m00'] > 0:
cx = int(moments['m10'] / moments['m00'])
cy = int(moments['m01'] / moments['m00'])
return (cx, cy), np.sum(mask) # Центр и размер объекта
return None, 0
def control_robot(object_center, object_size, frame_width):
"""Управляет моторами на основе положения объекта"""
if object_center is None:
# Объект не найден - медленно вращаемся
turn_left(speed=30)
return
cx, cy = object_center
# Определяем расстояние по размеру объекта в кадре
if object_size > 50000: # Очень большой - мы близко
stop()
print("Достиг цели!")
return
# Определяем направление
if cx < frame_width * 0.4:
# Объект слева
turn_left(speed=50)
elif cx > frame_width * 0.6:
# Объект справа
turn_right(speed=50)
else:
# Объект по центру - едем вперёд
forward(speed=60)
print(f"Объект в ({cx}, {cy}), размер: {object_size}")
# Главный цикл
cap = cv2.VideoCapture(0)
try:
while True:
ret, frame = cap.read()
if not ret:
break
# Находим красный объект
center, size = find_color_object(frame, 'red')
# Управляем роботом
control_robot(center, size, frame.shape[1])
# Показываем картинку (для отладки)
if center:
cv2.circle(frame, center, 10, (0, 255, 0), -1)
cv2.imshow('Робот', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(0.05) # 20 FPS
finally:
cap.release()
cv2.destroyAllWindows()
GPIO.cleanup()
Чеклист: Что попробовать самому
Для начинающих:
- Написать фильтр скользящего среднего для данных с датчика
- Сделать программу, которая находит на фото все круги
- Обучить нейросеть распознавать свои рукописные цифры
- Запустить готовую нейросеть YOLO на Raspberry Pi
Для продвинутых:
- Создать комплементарный фильтр для стабилизации дрона
- Написать стереозрение для оценки расстояний
- Обучить нейросеть отличать полезные объекты от мусора
- Реализовать простого чат-бота для робота на GPT
Инструменты для экспериментов:
- Google Colab — бесплатный GPU для обучения нейросетей
- Roboflow — готовые наборы данных для обучения
- Edge Impulse — создание TinyML моделей без кода
- ROS + OpenCV — готовые пакеты для компьютерного зрения
Важно помнить:
- Данные > Алгоритмы — хорошие данные важнее умного алгоритма
- Простота — начинай с самого простого, что работает
- Итерации — сделал → проверил → улучшил → повторил
- Физика важна — никакой ИИ не исправит плохие датчики
ИИ в робототехнике — это не про замену людей, а про то, чтобы роботы могли делать полезную работу в нашем сложном, неидеальном мире.
