Розробка трекинга передвиження транспорту в мобільному додатку
Трекинг транспорту відрізняється від курьерського в кількох принципіальних моментах: швидкості руху інші, GPS-шум на високій швидкості інший за характером, маршрути часто заранее відомі (рейсовий транспорт), а дані поступають не від смартфона водія, а від GPS-трекера через MQTT/протокол Wialon або FMB-пристроїв Teltonika.
Джерела даних: не тільки смартфон
Для логістичних компаній і управління парком транспортне пристрій — це апаратний GPS-трекер (Teltonika FMB920, Queclink GV350, Galileosky), а не телефон водія. Трекер відправляє пакети по MQTT або HTTP-протоколу на сервер. Додаток виступає тільки як візуалізатор даних, не як джерело.
Якщо задача — показувати громадський транспорт по даних GTFS Realtime (стандарт Google), то джерело — відкриті API міських транспортних операторів. Формат — Protocol Buffers (transit_realtime.FeedMessage), парсинг через бібліотеку gtfs-realtime-bindings.
Для додатків з телефоном водія (таксі, корпоративний транспорт) — той же стек, що у курьерського трекинга, але з поправками на швидкість руху.
GPS-фільтрація на високих швидкостях
На швидкості 80-120 км/ч горизонтальний GPS-дрейф менше, ніж в місті з багатоповерховими будівлями, але інша проблема: при різких поворотах маркер може «обганяти» реальне положення машини через затримку обновлення. Калман-фільтр згладжує цю затримку.
Проста реалізація фільтра Калмана для координат на Kotlin:
class KalmanFilter(private var accuracy: Float = 1f) {
private var lat = 0.0
private var lon = 0.0
private var variance = -1f
fun process(lat: Double, lon: Double, accuracy: Float, timestamp: Long): LatLng {
if (variance < 0) {
this.lat = lat; this.lon = lon; variance = accuracy * accuracy
} else {
val dt = (timestamp - lastTimestamp) / 1000f
variance += dt * 3f * 3f // швидкість змінення 3 m/s
val k = variance / (variance + accuracy * accuracy)
this.lat += k * (lat - this.lat)
this.lon += k * (lon - this.lon)
variance *= (1 - k)
}
lastTimestamp = timestamp
return LatLng(this.lat, this.lon)
}
private var lastTimestamp = 0L
}
На iOS аналогічна реалізація на Swift або використання CLLocationManager з CLActivityType.automotiveNavigation — Apple застосовує власний фільтр.
Map Matching для маршрутизованого транспорту
Рейсовий автобус їде по фіксованому маршруту — GPS-точки між зупинками мають лежати строго на цьому маршруту, а не прискакувати на паралельну вулицю. Map matching: беремо послідовність GPS-точок і «прижимаємо» їх до найближчого участку дорожного графа.
OSRM self-hosted: GET /match/v1/driving/{coordinates}?radiuses={radiuses}&geometries=geojson. Повертає matched-трек з waypoints. Latency < 20 мс при self-hosting, що прийнятно для реального часу.
Google Roads API snapToRoads — простіше в інтеграції, але платно ($5 за 1000 вызовів) і обмежено 100 точками за запит.
Відображення транспорту: маркери і маршрут
Маркер автобуса/грузовика — кастомний PNG або SVG з поворотом за напрямком руху. Напрямок у градусах: atan2(dLon, dLat) * 180 / PI. На Android — BitmapDescriptorFactory.fromBitmap(rotatedBitmap) з поворотом через Matrix.postRotate(). На iOS — GMSMarker з iconView, поворот через CGAffineTransform(rotationAngle:).
Маршрут — полілінія. Google Directions API для розрахунку або заранее збережений GTFS shapes.txt. На карті — GMSPolyline / Polyline з кастомним кольором і товщиною. Пройдений участок — інший колір (наприклад, сірий замість синього).
Анімація руху — інтерполяція між точками. Інтервал обновлення GPS-трекера звичайно 30-60 секунд, а не 5. Це означає, що маркер повинен плавно рухатися 30 секунд від однієї точки до іншої, а не прискакувати. ValueAnimator на Android з LinearInterpolator, CADisplayLink на iOS.
Серверна частина
Для парка з 50-200 машин — Socket.IO або WebSocket на Node.js. Сервер зберігає актуальні позиції в Redis з TTL. Клієнт підписується на канал fleet/updates і отримує обновлення всіх машин пачкою кожні 10-15 секунд замість індивідуальних событій — економить трафік.
Для великих парків (1000+ машин) — MQTT broker з топіками vehicle/{id}/gps. Клієнт підписується тільки на цікаві машини.
Історичне зберігання маршрутів: PostgreSQL + PostGIS для геопросторових запитів («покажи всі машини, які проїхали через зону X вчора»), TimescaleDB для time-series метрик (швидкість, паливо).
Процес роботи
Аудит джерела даних: трекер/телефон/GTFS. Проектування серверної шини і хранилища. Реалізація мобільного клієнта: маркери, маршрути, анімація, стани. Інтеграція map matching якщо потрібно. Тестування з емуляцією трафіку.
Строк: від двох до шести тижнів залежно від джерела даних, кількості платформ і масштабу парка.







