Недавно прошел SOC Forum – большая конференция по информационной безопасности, на которой у нас был свой стенд. На стенде был мерч, работал лекторий, общались менеджеры. Но была одна деталь, которая сильно отличала нашу площадку от площадок коллег. Это гоночный симулятор с подвижной подвеской, который стал магнитом для любителей быстрой езды.

Так как мы разрабатываем платформу для анализа данных, было бы странно не продемонстрировать ее возможности на живом потоке телеметрии. К тому же речь шла об интеграции с компьютерной игрой. Поэтому мы поставили задачу: подключить Assetto Corsa к Smart Monitor, собирать телеметрию в реальном времени и показывать пилотам наглядные отчеты.

Эта статья про то, как мы настроили сбор телеметрии автосимулятора в Smart Monitor: от выбора способа интеграции и структуры событий до дашбордов и логики ачивок.

В чем была идея

Идея заключалась в демонстрации возможностей платформы данных Smart Monitor в качестве универсального решения для обработки и анализа данных. Поэтому было решено собирать события телеметрии и нарисовать пару интересных дашбордов с инфографикой заезда, а также рассчитать различные ачивки для пилотов (об этом позже).

Как выглядит симулятор

Симулятор включал ряд понятных компонентов:

  1. Платформа – подвеска, контроллеры (руль, педали), кресло пилота

  2. Оборудование – ПК с видеокартой, мониторы, аудио-система

  3. Программное обеспечение – автосимулятор Assetto Corsa (2014) и программные продукты интеграции с платформой (для передачи обратной связи)

Шаг #1: Сбор данных

Сбор данных осуществлялся непосредственно с автосимулятора Assetto Corsa. Сам симулятор давно стал народным за счет открытости для модификаций. Фанаты сформировали огромное сообщество с форумами и модификациями. Поэтому задача сбора и анализа сессий заездов была уже решена множество раз. И мы стали выбирать решения которые удовлетворяли нашим требованиям:

  1. Простота интеграции

  2. Сбор данных в режиме реального времени

ACTI плагин

Первым в цепочке был плагин ACTI. Это внутриигровое приложение, которое записывает телеметрию в режиме реального времени для использования в приложении анализа телеметрии гоночных автомобилей MoTeC i2.

После установки и тестов нашего инженера (да, тесты являлись проездом кругов в Assetto Corsa на ноутбуке), было принято решение отказаться от использования данного плагина в качестве инструмента сбора данных.

Причин было две:

  1. Файлы телеметрии формировались после завершения сессии гонки – отсутствовала возможность сбора данных в реальном времени.

  2. Сам файл телеметрии имеет формат ld, который нужно было дополнительно десериализовать – усложнение интеграции.

Поэтому мы стали копать дальше.

Simhub

Simhub это мощный софт для симрейсинга, он позволяет использовать различные телеметрические настройки и устройства вокруг гоночного симулятора – создавать дашборды, управлять вибромоторами. В целом набор решаемых кейсов ограничен только фантазией инженера. Нам он был интересен возможностью отправлять телеметрию по UDP.

Однако, для Assetto Corsa (2014) из коробки таких настроек UDP не нашлось. Для Competizione и других симуляторов отправка была доступна, для Assetto Corsa нет. Разбираться времени не было, да и в целом счет шел на дни, поэтому мы пошли дальше.

Использовать SDK для Shared Memory

Все описанные инструменты использовали один и тот же подход – чтение телеметрии из Shared Memory. Assetto Corsa данные телеметрии заполняла в структуры Shared Memory (блок общей памяти, реализованный через Memory-Mapped File), которые доступны любому процессу. С описанием заполняемых структур можно ознакомиться в
этом проекте для Rust. Здесь кратко обозначу блоки, доступные для чтения:

  1. Static — статическая информация (машина, трасса, сессия и т.п.)

  2. Graphics — состояние сессии/интерфейса (круг, времена, флаги, статус сессии)

  3. 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

Нет. Не найдена возможность отправки данных

Да

SDK для Shared Memory

Да. Есть готовый проект на 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,
  ...
}

Перечень параметров:

Поле

Тип

Описание

short_comment

string

Комментарий

session_id

number

Уникальный ID сессии (генерируем самостоятельно в AC Collector)

current_sector_index

number

Текущий сектор

penalty_time

number

Время штрафа

is_valid_lap

number

Валидность круга

session_time_left

number

Остаток времени

driver

string

Имя пилота

car

string

ID автомобиля

icurrent_time

number

Текущее время

flag_type

string

Активный флаг

lap_time

number

Время круга

number_of_laps

number

Круги в сессии

session_type

string

Тип сессии

position

number

Позиция

track

string

Трасса

completed_laps

number

Завершенные круги

best_lap_time

number

Лучший круг

track_spline_length

number

Длина сплайна трассы

Блок metrics — телеметрия

Телеметрия содержит более 100 показателей, поэтому подсвечу основные блоки, которые мы использовали в аналитике:

  1. Скорость и двигатель – speed (скорость), gear (передача), engine_rpm (обороты), brake_pos (нажатие на педаль)

  2. Положение и ускорения – car_coordinates (координаты), heading (курс), distance_traveled (пройденная дистанция)

  3. Подвеска и крены – suspension_travel_* (ход подвески), ride_height_* (клиренс)

  4. Шины – tire_temp_* (температура), tire_pressure_* (давление)

  5. Тормоза и руль – throttle_pos (нажатие на педаль газа в процентах), steering_angle (угол руля)

  6. ERS/KERS/DRS – drs (флаг активности drs)

  7. Повреждения – car_damage_* (повреждения), number_of_tyres_out (колеса за трассой)

  8. Окружающая среда – air_temp (температура воздуха), road_temp (температура асфальта)

  9. Тайминги – current_time (текущее время), best_time (лучший круг)

Пример события телеметрии:

{
  "@timestamp": "2025–11–20T15:43:02.573066968Z",
  "session": {
    "short_comment": "Tires Aid: 1,07 (SM)",
    "session_id": 1763652854706,
    "driver": "Ilya!",
    "car": "ks_ferrari_f2004",
    "icurrent_time": 0.021,
    "flag_type": "Blue_flag",
    "number_of_laps": 6,
    "session_type": "Practice",
    "track": "monza",
    ...
  },
  "metrics": {
    "tyre_wear_fr": 99.87746,
    "fuel_level": 7.6070175,
    "normalized_car_position": -206.18411,
    "tyre_temp_i": [
      108.70935,
      95.23845,
      131.87352,
      134.8018
    ],
    "engine_rpm": 17128,
    "cg_accel_lateral": 0.16582893,
    "wheel_angular_speed_fr": 252.20087,
    "air_density": 1.1556135,
    "camber_rr": 3.0028458,
    "max_power": 577933.5,
    ...
  },
  "timestamp": "2025–11–20T18:43:02.7053008+03:00"
}

Шаг #3: Делаем контент

Итак, интеграция завершена и данные поступают. Теперь можно делать дашборды, считать статистику сессий, предоставлять инфографику
гостям стенда.

Я определил два критерия успешности:

  1. Дашборды должны быть стильными – сухие дашборды со статистикой для игрового симулятора смотрелись бы инородно в атмосфере киберспортивного соревнования.

  2. Дашборды должны быть интересными – выводимые показатели должны привлекать внимание пилотов и зрителей.

Вооружившись нашим конструктором дашбордов, было реализовано два дашборда.

Assetto Corsa: Текущий заезд

Цель дашборда: показывать текущие параметры заезда и автомобиля во время активной сессии. Нам удалось привлечь внимание, желающие прокатиться с интересом наблюдали за изменением показателей. Давайте я просто покажу скриншоты, чтобы не затягивать повествование.

Основная панель мониторинга. Стильность панели заключалась в темной теме и формированием HTML-разметки (с изображением автомобиля, повреждениями и другими параметрами) для панели "Параметры заезда".

Накопившиеся итоги, статистика по кругам трассы

Метрики в разрезе кругов

Assetto Corsa: Сессии и ачивки

Цель дашборда: показать пилоту результаты его заезда в сравнении с другими сессиями и понять, заработал ли пилот ачивку.

Сессии заезда были оформлены в таблицы с фильтрами.

Ачивки представляли собой карточки с достижениями. Формировался топ лист, а затем выбирался лучший. Если пилот сохранял лидерство – по результату дня он получал мерч и аплодисменты.

Важно, что ачивки носили шуточный характер и были связаны с хорошей ездой лишь частично. Это было сделано намеренно.

Ачивки и фоновые задачи

Теперь немного подробнее про то, как мы считали ачивки и поддерживали их актуальность в режиме почти реального времени.

Каждая ачивка – это количественный показатель всех сессий пилота, рассчитываемый по определенной логике. Поэтому были сформированы справочники для каждой ачивки, которые обновлялись задачами по расписанию каждую минуту. Задача извлекала данные, выполняла логику расчета и обновляла справочник топ-листа для конкретной ачивки.

Пример задачи для ачивки "Амбассадор дрифта":

Результатом задачи был список пилотов с отслеживаемым параметром за текущий день:

Такие задачи были сформированы для каждой ачивки:

А на дашборде для панели выбирался топ 1:

Сама панель является HTML-элементом с токенами из результатов запроса (картинки для карточек нарисовал ИИ):

Таблица с логикой расчета для каждой ачивки

Ачивка

Логика расчета

Амбассадор дрифта

Угол руля (steering_angle) больше 25 градусов, скорость (speed) больше 60 км/ч

Владелец таксопарка

Общее количество автомобилей (car), которые использовал пилот (driver)

Дальнобойщик

Количество кругов (number_of_laps) * Длина трассы (track_spline_length)

Дитя природы

Количество секунд, когда все четыре колеса были вне трассы (number_of_tyres_out)

Любитель дерби

Суммарное повреждение за все сессии (car_damage_front + car_damage_rear + car_damage_left + car_damage_right)

Макс Ферстаппен

Средняя скорость (speed) за все сессии

Результаты

Наш небольшой аналитический проект по интеграции с Assetto Corsa привлекал внимание и давал контекст гостям стенда о возможностях платформы. Порой хочется отдохнуть от корреляционных правил, расследования инцидентов и погрузиться в мир больших скоростей и крутых поворотов.

Результат превзошел наши ожидания, возникали идеи промышленного применения аналитики для площадок обучения гонщиков и команд мотоспорта. Так что кейс хорошо масштабируется.

Вместо выводов ряд занятной статистики:

  1. Количество сессий за три дня: 229

  2. Количество пилотов: 140

  3. Общая длительность работы симулятора за три дня: 28 часов 4 минуты и 53 секунды

  4. Среднее время сессии: 5 минут 18 секунд

Комментарии (0)