Концепція
Чи бувало у Вас таке, що вийшовши з дому Ви не пам'ятаєте, чи вимкнули праску? Обговорюючи з другом черговий такий випадок, виникла жартівлива ідея зробити робота для дистанційної візуальної перевірки домашніх справ. Та й взагалі хотілося, на коліні зробити "шпигунського" робота керованого камерою зі смартфона. Ця ідея виношувалась нами давно, але руки дійшли тільки зараз. І ми одразу ж вирушили до найближчого бару для обговорень. Власне роботом це називати не зовсім правильно. Швидше це самохідна платформа з телеметричним керуванням через Інтернет. Але в статті використовуватиметься термін “робот” просто тому, що так звичніше.
Технологія WebRTC ідеально нам підійшла, тому що досить легко організувати передачу відео, аудіо та data каналів між двома peer'ами з мінімальною затримкою сигналу. Та й досвіду роботи з цією технологією ми не мали, тому дуже хотілося спробувати.
Користувач - оператор і робот - Raspberry PI заходять кожен на свою веб-сторінку, підключаються до сигнального сервера, після чого між ними створюється WebRTC сесія, через яку і передається відео-потік з робота користувачеві, і передаються керуючі сигнали роботі. Далі, керуючі сигнали робот відправляє на свій localhost де вже інший сервіс їх обробляє та виводить на GPIO, для керування моторами. Здається, все просто. Ось що в нас вийшло на цьому етапі:
Далі розберемося з цим більш детально.
Комплектуючі
Надивившись фільмів про роботів, багатьом із нас неодноразово хотілося побудувати свого бойового товариша. Але будувати двоногого термінатора складно і дорого, але наші китайські друзі діляться з нами не тільки вірусами. Проект замислювався як домашній, тому при виборі комплектуючих ми виходили з того, що у нас вже було або була можливість придбати за мінімальною ціною.
Головний контролер
Так як у нас було дві плати Raspberry Pi (3b і 4), і вони нас цілком влаштовували, було вирішено використовувати саме малинку зі стандартною OS Raspbian. Застосування цієї плати дає можливість удосконалення у майбутньому, використання OpenCV, підключення додаткової периферії тощо. І вона досить поширена, щоб можна було без проблем купити дешевий корпус і не бояться забруднити його в клей, або просвердлити парочку монтажних отворів.
Око (камера)
Як камеру можна використовувати будь-яку веб-камеру (що ми спочатку і робили), але в процесі тестування виявилося що краще купувати камеру з відносно високим показником FPS і світлочутливості. Тому майже відразу після перших тестів замінили стару веб-сайт Logitech QuickCam Connect на відносно сучасну Logitech C270 придбану на дошці безкоштовних оголошень за 12 $. Можна було використовувати і Raspicam, але це обійшлося б дещо дорожче.
Механіка
Механічна основа робота — гусенична платформа з диференціальним приводом — класична для простих робототехнічних експериментів. Два незалежні колеса обертають гусениці. Дане рішення виявилося дещо помилковим, оскільки такі конструкції не позбавлені таких недоліків:
- Часто злітають гусениці при повороті на поверхнях з високим коефіцієнтом тертя, наприклад, на килимі.
- Дуже гучні редуктори на моторах
Ідеальним рішенням була б звичайна платформа на колесах, керована танковою схемою. Але гусениці виглядають цікавіше.
Живлення
Для уникнення виникнення перешкод і просадок напруги ланцюга живлення моторів і Raspberry Pi було вирішено розділити. Спочатку драйвер моторів був запитаний від телефонного акумулятора на 3.7В з імпульсним перетворювачем напруги типу DC-DC MT3608, але драйвер моторів не захотів з ним адекватно працювати, і йшов у "зашкал". Ймовірно, через імпульсний характер напруги. Тому було куплено два однакові акумулятори від старого телефону Samsung. І вони ідеально вписалися в батарейний відсік, будучи з'єднаними конструктивно скотчем і електрично послідовно. А малинка запитана від power-банку Xiaomi зі швидкою зарядкою, яка також ідеально підходить під габарити платформи. Величини струму цілком вистачає для живлення Raspbery Pi4.
Драйвер двигунів
Спочатку був обраний драйвер L9110, але він часто вимикався при живленні від підвищуючого DC-DC перетворювача, тому код був виправлений та встановлений L293N. Проблеми це не вирішило, а модуль так і залишився. Принципової різниці у роботі модулів помічено не було.
Конструкційний монтаж
Так як це лише домашній прототип, то збирається все з поліморфу, палиць і супер-клею. Дуже зручно було використовувати радянський металевий конструктор “Малюк”, придбаний на дошці безкоштовних оголошень за 1$. Power-банк на дні, для збереження низького центру тяжкості. Притиснутий пластиною з конструктора, на яку пластиковими болтами закріплені дві скоби, до яких вже кріпиться корпус Raspberry Pi. Камера прикручена в задній частині тому що так зручніше управління. Простіше розуміти габарити коли бачиш краї гусениць, а об'єктив на камері не широкоформатний. Чудовим чином розмір пластини з конструктора співпав із габаритним розміром задньої частини платформи, що дало можливість сховати під пластину скручений довгий провід. Дрібні деталі кріпляться до супер-клею. А драйвер моторів – на двосторонній скотч прямо до power-банку.
Програмна частина
Так як це прототип, то якість коду та й усього проекту в цілому відповідна. Є некритичні помилки. Реалізовано проект мовами JavaScript та Python. Репозиторії проекту з коментованим кодом доступні за посиланням. Весь код тут наводити не буду, постараюся описати лише основні моменти.
Сигнальний сервер
Представлений примітивним NodeJS сервером. Він виконує дві функції:
- Віддає потрібні сторінки для платформи і пристрій оператора, який управляє роботом.
- Власне сигнальна функція, тобто. обслуговує підключення по веб-сокету.
При підключенні до сервера платформа "реєструється" під своїм унікальним ідентифікатором. Цей ідентифікатор повинен ввести в себе в інтерфейсі оператор. І повідомлення, що відправляються зі сторінки оператора, доставляються на сторінку платформи і навпаки. Таким чином реалізовано абстракцію типу кімнати, для можливості одночасного функціонування декількох платформ. З кодом сигнального сервера можна ознайомитись за посиланням.
Для спілкування з сигнальним сервером із клієнтської частини реалізовано клас SignalEmitter. Приймає в конструктор об'єкт із налаштуваннями. id - ідентифікатор платформи , isControl - змінна вказує на те платформа це або оператор. signalServer - uri сигнальний сервер. Розгорнутий він у нас на старому десятирічному ноутбуці.
const se = new SignalEmitter({
id: searchParams.get('id'),
isControl: false,
signalServer: config.signalServer
});
WebRTC
Для з'єднання за протоколом було реалізовано клас RTC. У конструктор приймає два параметри - об'єкт налаштувань options і екземпляр класу SignalEmitter, описаний вище. isControl - змінна платформа, що вказує на те, або сторінка оператора. platformSocket - uri localhost'а з портом на який відправляється керуючий сигнал для гусениць.
const webrtc = new RTC({
isControl: false,
platformSocket: config.platformSocket},
se);
Інтерфейс клієнтської частини
Для прототипування інтерфейсу використовувався Vue.js, оскільки він досить простий і дозволяє швидко реалізувати ідею. Все щодо інтерфейсу знаходиться в директорії /public. Як виглядає прототип інтерфейсу та його функціонал опублікував у відео:
Selenium
Щоб не запускати вручну кожен раз браузер, ми вирішили використовувати Selenium WebDriver + geckodriver у headless режимі. Код є імперативним і дуже простим, знаходиться у файлі robot-signal-server/selenium/index.js. Тут ми підключаємо конфігураційний файл, встановлюємо потрібні прапори браузеру та відкриваємо відповідну сторінку. Про призначення кожного з прапорів можна здогадатися інтуїтивно, або скористатися пошуковою системою. Можна додати виконання скрипту в /etc/network/if-up.d/ щоб він запускався автоматично при підключенні до мережі.
Управління драйвером двигунів
Ця частина написана на Python. Її функція - прийняти керуючий сигнал по веб-сокету зі сторінки платформи, перетворити сигнал і вивести відповідні значення на висновки GPIO. Оскільки схема управління в нас танкова, то контракт сигналу в нас такий: [0…+-1, 0…+-1] у форматі JSON. Тобто. два значення, для лівої та правої гусениці, що змінюються в межах від -1 до +1 з кроком 0.01. Що відповідає руху назад і вперед, і дає можливість точно регулювати швидкість руху за допомогою широтно-імпульсної модуляції. (Див. GItHub репозиторій)
Висновок
Як бачимо, складного нічого немає. Застосування даної схеми в production-варіанті реалізації можливе і для роботів-промоутерів або для мобільної, самохідної системи стеження та взагалі обмежується тільки фантазією. Відвідування музеїв та виставок так само можна було б зробити дистанційним, що особливо корисно за часів пандемії. Сидіть Ви у себе в кріслі та вивчаєте Собор Святого Петра у Римі або музей Васа у Стокгольмі.
А повсюдне поширення швидкісного 3/4/5G дає можливість використовувати інтернет замість традиційного радіоканалу в управлінні БпЛА типу різних коптерів із сучасними польотними контролерами зі стабілізацією та іншими плюшками, обмежуючи радіус дії лише покриттям мережі та можливостями акумулятора. І ще відео: