Розробка мобільного приложення для керування роботом
Керування роботом з телефону — це майже завжди завдання реального часу з вимогами до затримки < 100 мс та надійною обробкою розриву з'єднання. Протокол зв'язку, архітектура команд та схема відновлення після втрати з'єднання важливіше UI. Розглянемо конкретні транспорти та паттерни, які працюють у production.
Транспорт та протоколи
ROS 2 + rosbridge (WebSocket)
Найпоширеніший стек для ROS-роботів: на роботі піднімається rosbridge_server, телефон підключається через WebSocket та публікує/підписується на топіки через JSON-протокол rosbridge_protocol. Для мобільних клієнтів є бібліотеки сумісні roslibjs, але для нативного Android/iOS пишемо клієнт самі — це 300–400 рядків коду з повторним підключенням та чергою повідомлень.
Проблема: rosbridge — JSON поверх WebSocket, це повільно для високочастотних топіків. Топік /cmd_vel з Twist-командами на 20 Гц через JSON дає ~40 кб/с трафіку. Якщо робот за Wi-Fi з реальною пропускною здатністю 1 Мбит/с — нормально. Якщо через LTE з джиттером — пакети приходять пачками, команди виконуються з затримкою. Рішення: знижуємо частоту команд до 10 Гц та додаємо watchdog: якщо від телефону немає команди 500 мс, робот переходить в safe_stop.
MQTT для легкого керування
Для IoT-роботів без ROS (AGV, сортування, кастомні платформи) — MQTT брокер (Mosquitto або EMQ X) плюс легкий протокол команд. Телефон публікує в robot/{id}/cmd, робот підписаний на цей топік. Телеметрія в зворотну сторону: robot/{id}/state, robot/{id}/battery.
QoS 1 (at least once) для команд керування — QoS 0 втрачає пакети при нестабільному Wi-Fi, QoS 2 створює лишні round-trips. Retained message для robot/{id}/state дозволяє новому підключившемуся клієнту одразу отримати актуальний стан без очікування наступного оновлення.
UDP для реального часу (< 50 мс)
Якщо потрібна мінімальна затримка — прямий UDP-сокет на порт керування. На Android — DatagramSocket в CoroutineScope(Dispatchers.IO), відправка кожні 50 мс. Немає гарантій доставки — це плюс: стара команда не блокує нову в черзі. Застосовується для керування маніпуляторами, де затримка команди важливіше гарантії доставки.
Архітектура мобільного клієнта
class RobotControlViewModel(
private val robotRepository: RobotRepository
) : ViewModel() {
private val _robotState = MutableStateFlow<RobotState>(RobotState.Disconnected)
val robotState: StateFlow<RobotState> = _robotState
fun sendVelocityCommand(linear: Float, angular: Float) {
viewModelScope.launch {
robotRepository.publishVelocity(
TwistCommand(linear = linear, angular = angular)
)
}
}
fun connect(robotIp: String) {
viewModelScope.launch {
robotRepository.connect(robotIp)
.onEach { state -> _robotState.value = state }
.launchIn(this)
}
}
}
RobotRepository інкапсулює конкретний транспорт — WebSocket, MQTT або UDP. Зміна транспорту не торкається ViewModel та UI. Це критично: у реальних проектах часто змінюється залізо або протокол між прототипом та production.
Віртуальний джойстик та обробка вводу
MotionEvent.ACTION_MOVE приходить до 60 разів на секунду при швидкому русі пальця. Відправляти команду на кожну подію — перегрузка каналу. Використовуємо throttleLatest(50) з Kotlin Coroutines Flow — беремо останнє значення за 50 мс. Старі проміжні значення відбрасуються, затримка відповіді — не більш 50 мс.
Мертва зона (dead zone) у центрі джойстика: 10–15% радіуса фільтруємо до нуля. Без цього мікротремор руки викликає постійні команди малої швидкості, робот «дергається» в спокої.
Видеопоток з камери робота
Для H.264-стримів з IP-камер на роботі використовуємо ExoPlayer (Android) або AVPlayer з HLS (iOS). Затримка HLS — 5–30 секунд. Для керування це неприпустимо. Правильний шлях: WebRTC (latency < 200 мс) або RTSP через LibVLC / ffmpeg у MediaCodec pipeline (latency 100–300 мс).
WebRTC складніший у налаштуванні (потрібен STUN/TURN-сервер або P2P в одній мережі), але дає мінімальну затримку та адаптивний бітрейт.
Безпека та аварійні сценарії
- Watchdog на роботі: немає команди 1–2 секунди →
safe_stopабо перехід в автономний режим утримання позиції - PIN/QR-аутентифікація для підключення до конкретного робота (щоб не керувати чужим)
- Блокування команд руху при відкритому захисному кожусі (через MQTT-статус або GPIO)
Терміни
Базовий клієнт з джойстиком, телеметрією та видеопотоком на одній платформі — 3–5 тижнів. Кросплатформене рішення з підтримкою кількох протоколів, картою приміщення та автономними місіями — 2–4 місяці. Оцінка після вивчення платформи робота та вимог до затримки.







