C# * HTML * Data Engineering * Data Mining * Кейс Недавно прошел SOC Forum – большая конференция по информационной безопасности, на которой у нас был свой стенд. На стенде был мерч, работал лекторий, общались менеджеры. Но была одна деталь, которая сильно отличала нашу площадку от площадок коллег. Это гоночный симулятор с подвижной подвеской, который стал магнитом для любителей быстрой езды. Так как мы разрабатываем платформу для анализа данных, было бы странно не продемонстрировать ее возможности на живом потоке телеметрии. К тому же речь шла об интеграции с компьютерной игрой. Поэтому мы поставили задачу: подключить Assetto Corsa к Smart Monitor, собирать телеметрию в реальном времени и показывать пилотам наглядные отчеты. Эта статья про то, как мы настроили сбор телеметрии автосимулятора в Smart Monitor: от выбора способа интеграции и структуры событий до дашбордов и логики ачивок. В чем была идея Идея заключалась в демонстрации возможностей платформы данных Smart Monitor в качестве универсального решения для обработки и анализа данных. Поэтому было решено собирать события телеметрии и нарисовать пару интересных дашбордов с инфографикой заезда, а также рассчитать различные ачивки для пилотов (об этом позже). Как выглядит симулятор Симулятор включал ряд понятных компонентов: Платформа – подвеска, контроллеры (руль, педали), кресло пилота Оборудование – ПК с видеокартой, мониторы, аудио-система Программное обеспечение – автосимулятор Assetto Corsa (2014) и программные продукты интеграции с платформой (для передачи обратной связи) Шаг #1: Сбор данных Сбор данных осуществлялся непосредственно с автосимулятора Assetto Corsa. Сам симулятор давно стал народным за счет открытости для модификаций. Фанаты сформировали огромное сообщество с форумами и модификациями. Поэтому задача сбора и анализа сессий заездов была уже решена множество раз. И мы стали выбирать решения которые удовлетворяли нашим требованиям: Простота интеграции Сбор данных в режиме реального времени ACTI плагин Первым в цепочке был плагин ACTI . Это внутриигровое приложение, которое записывает телеметрию в режиме реального времени для использования в приложении анализа телеметрии гоночных автомобилей MoTeC i2. После установки и тестов нашего инженера (да, тесты являлись проездом кругов в Assetto Corsa на ноутбуке), было принято решение отказаться от использования данного плагина в качестве инструмента сбора данных. Причин было две: Файлы телеметрии формировались после завершения сессии гонки – отсутствовала возможность сбора данных в реальном времени. Сам файл телеметрии имеет формат ld, который нужно было дополнительно десериализовать – усложнение интеграции. Поэтому мы стали копать дальше. Simhub Simhub это мощный софт для симрейсинга, он позволяет использовать различные телеметрические настройки и устройства вокруг гоночного симулятора – создавать дашборды, управлять вибромоторами. В целом набор решаемых кейсов ограничен только фантазией инженера. Нам он был интересен возможностью отправлять телеметрию по UDP. Однако, для Assetto Corsa (2014) из коробки таких настроек UDP не нашлось. Для Competizione и других симуляторов отправка была доступна, для Assetto Corsa нет. Разбираться времени не было, да и в целом счет шел на дни, поэтому мы пошли дальше. Использовать SDK для Shared Memory Все описанные инструменты использовали один и тот же подход – чтение телеметрии из Shared Memory. Assetto Corsa данные телеметрии заполняла в структуры Shared Memory (блок общей памяти, реализованный через Memory-Mapped File), которые доступны любому процессу. С описанием заполняемых структур можно ознакомиться в этом проекте для Rust. Здесь кратко обозначу блоки, доступные для чтения: Static — статическая информация (машина, трасса, сессия и т.п.) Graphics — состояние сессии/интерфейса (круг, времена, флаги, статус сессии) Physics – физические параметры автомобиля и окружающей среды (скорость, ускорения, положение, педали, колеса и т.д.) Пример структуры Physics: struct SPageFilePhysics { int packetId = 0; float gas = 0; float brake = 0; float fuel = 0; int gear = 0; int rpms = 0; float steerAngle = 0; float speedKmh = 0; float velocity[3]; float accG[3]; float wheelSlip[4]; float wheelLoad[4]; float wheelsPressure[4]; float wheelAngularSpeed[4]; float tyreWear[4]; float tyreDirtyLevel[4]; float tyreCoreTemperature[4]; float camberRAD[4]; float suspensionTravel[4]; float drs = 0; float tc = 0; float heading = 0; float pitch = 0; float roll = 0; float cgHeight; float carDamage[5]; int numberOfTyresOut = 0; int pitLimiterOn = 0; float abs = 0; float kersCharge = 0; float kersInput = 0; int autoShifterOn = 0; float rideHeight[2]; float turboBoost = 0; float ballast = 0; float airDensity = 0; }; В результате сравнения мы выбрали именно этот подход для реализации сбора телеметрии. Механизм Сбор данных в реальном времени Плагин ACTI Нет. Отсутствует отправка во внешнюю систему SimHub Нет. Не найдена возможность отправки данных Да Да. Есть готовый проект на C# Да, достаточно реализовать отправку по UDP Чтобы не писать весь сбор самостоятельно (я напоминаю, это демо–кейс), мы воспользовались проектом Assetto Corsa Shared Memory Library , который уже содержал логику чтения телеметрии в структуры данных на C#. А дальше все просто – мы добавили в код транспорт в Logstash по UDP. Частота сбора — один раз в секунду. Для наших потребностей в части красивых графиков и аналитики такого потока было достаточно. UDP протокол был выбран как самый простой механизм транспорта с низкой задержкой. В результате был написан ACReader – это адаптированный коллектор на C# для отправки объекта телеметрии в Logstash. Сам коллектор, конечно же, устанавливается на ПК с игрой. В результате, мы в облаке развернули Smart Monitor и настроили сбор телеметрии. Схема компонентов Схема ПО и потоков данных Шаг #2: Знакомство с метриками и атрибутами заезда Структура событий достаточно простая, что помогло нам быстро собрать контент (дашборды, агрегаты). Блок session — контекст сессии Содержит атрибуты пилота и сессии (статические и динамические параметры). Формат объекта: session { session_id, driver, car, track, session_type, lap_time, best_lap_time, position, flag_type, … } Перечень параметров: Source: https://habr.com/ru/articles/973024/