- PVSM.RU - https://www.pvsm.ru -
Чуть меньше года назад увидела свет публикация [1], где мы рассказывали об учебно-лабораторном комплексе (УЛК) электропоезда ЭС1 «Ласточка», разработанном нашем университете. Тогда я обещал, что это будет не последняя публикация на данную тему, в частности грозился рассказать о проблемах создания трехмерной визуализации для подобного рода симуляторов и очертить основные подходы к их решению.
Прошедший год порадовал нас очередным релизом — УЛК высокоскоростного электропоезда ЭВС2 «Сапсан», который состоялся ещё в августе прошлого года. Сам по себе учебно-лабораторный комплекс данного электропоезда заслуживает отдельного рассказа, но в контексте этой публикации речь пойдет о наболевшем — проблеме создания адекватной подсистемы трехмерной визуализации, к решению которой наша команда подступалась с разных сторон около двух лет. Релиз симулятора «Сапсана» знаменателен (среди прочего) и тем, что определил вектор развития наших разработок в этой области.
Хочу подчеркнуть ещё раз (что я делаю с завидной периодичностью) что учебно-лабораторные комплексы подвижного состава, разрабатываемые в нашем университете, не предназначены для подготовки локомотивных бригад. Как справедливо заметил один из комментаторов [2] предыдущей статьи, наши УЛК являются не тренажерами, а симуляторами, где основной упор делается на грамотную реализацию физики движения поезда и моделирование работы подсистем подвижного состава, обеспечивающих его движение и остановку. Не является исключением и симулятор «Сапсана», на котором решены следующие задачи:
Кроме того, учебно-лабораторный комплекс имеет в своем составе полноразмерный макет кабины электропоезда с основными органами управления и средствами отображения информации. В отличие от тренажера «Ласточки» эта кабина не изготавливалась нами самостоятельно, а была приобретена в 2015 году у одной известной в нашей стране конторы, занимающейся выпуском учебных тренажеров. Поэтому в процесс разработки симулятора сосредоточился на создании программного обеспечения.
Вид через лобовое стекло
Дисплей комплексного локомотивного устройства безопасности (КЛУБ-У). Красное «290» — это текущее ограничение скорости, получаемое из электронной карты КЛУБ-У. Пока здесь красуется предельная скорость, достигнутая «Сапсаном» на Октябрьской железной дороге. В будущем электронная карта будет реализована так, как это сделано в жизни
Главный дисплей «Интерфейс человек-машина»
Дисплей индикации состояния тормозной системы электропоезда
Задатчик скорости и контроллер тяги
Контроллер управления тормозами электропоезда
Тумблеры управления токоприемниками и аппаратами защиты (БВ/ГВ) — черные тумблеры около задатчика скорости
Интерфейс управления тренировкой — экран выбора маршрута движения
Экран управления громкостью аудиоэффектов
Счетчик пробега. С его появлением связана забавная история. Когда мы сдавали первый наш тренажер тепловоза 2ТЭ116, на наш вопрос когда будет подписан акт выполненных работ представитель заказчика отшутился: «Ну, давайте поступим как в жизни — при вводе нового локомотива в эксплуатацию он должен пройти 5000-километровый пробег. Вот пройдет...». Акт конечно был подписан намного раньше, но мы, оценив юмор ситуации, сделали подобный счетчик уже на тренажере «Ласточки». Счетчик можно сбросить в «0» введя сервисный пароль.
Правая вспомогательная панель с контрольными манометрами тормозной системы и клапаном экстренного торможения. Здесь установлены не все элементы присущие настоящему «Сапсану» — такой пульт был получен нами от поставщика
Поэтому, некоторые критичные для нас элементы управления были реализованы программно, в частности панель шунтирующих выключателей, управляемая с сенсорного дисплея
Разработка ПО подобного тренажера-симулятора вопрос очень широкий, и я постараюсь (в меру разумного) удовлетворить интерес читателей к этим вопросам в будущем (если таковой появится), но пока что, вернемся к основной теме статьи — трехмерной визуализации процесса движения поезда.
В комментариях к прошлой статье был задан вопрос [3], который, признаюсь честно, изрядно меня позабавил. Да, действительно, во многих, до сих пор эксплуатируемых сегодня тренажерах до сих пор применяется такой подход: снимается видео на реальном участке железной дороги, а затем прокручивается на тренажере со скоростью, пропорциональной скорости движения. Так делали только потому, что в те далекие времена, когда подобные тренажеры создавались, качество трехмерной графики, оставляло желать лучшего, причем это касалось и суровых графических станций на коммерческих юниксах, а уж о ПК и речи не шло. Поэтому, даже производители компьютерных игр, например вот этой [4], не гнушались использовать такой подход.
На сегодняшний день это не имеет смысла, потому что:
Поэтому все современные тренажеры и симуляторы создаются с применением интерактивной 3D-графики, благо сегодня нет никаких препятствий ни с программной, ни с аппаратной точки зрения.
Если с аппаратной точки зрения всё предельно ясно — монитор установленный вместо лобового стекла подключается к ПК с нормальной видеокартой (даже не самой топовой), то с программной точки зрения встает вопрос выбора технологии реализации задачи.
Могу ошибаться, но заранее предчувствую комментарии, в которых будет задаваться вполне закономерный вопрос, почему при анализе существующих технологий наш выбор не остановился на таких мастодонтах как Unity или Unreal Engine 4? Я отвечу на этот вопрос, более того, я обосную свой ответ.
Кратко — ни Unity ни Unreal Engine не удовлетворяют требованиям решаемой задачи. Более подробный ответ предусматривает, прежде всего перечисления тех требований, о которых идет речь. ТЗ, составленной нами на подсистему трехмерной визуализации, включает в себя (в порядке убывания значимости) следующие положения:
Что же не так с Unity и UE? Что тот, что другой движки способны импортировать ресурсы совершенно разных форматов. Однако при сборке проекта происходит их необратимое преобразование во внутренний бинарный формат, делающее невозможным добавление и изменение ресурсов без повторной сборки проекта. Технологии типа prefabs и asset bundles, доступные в Unity не решают задачу, так как редактор движка — не лучшее место для создания железнодорожных локаций, из-за чего возникает потребность расширения редактора, что приводит к необходимости писать «движок внутри движка». Кроме того, создание префабов и бандлов невозможно без применения редактора Unity, а это, как показала практика, не слишком удобно, особенно для чистых моделлеров и левел-дизайнеров. Что же касается UE, и на этом и на других ресурсах за два года мной было задано достаточно вопросов, о том как отделить процесс сборки проекта от процесса добавления/изменения используемых им ресурсов, и адекватного ответа я не получил ни в документации, ни от «матерых» геймдевелоперов. Буду очень рад (без сарказма) если меня аргументировано натыкают носом во что-то, что было мной упущено.
Что касается второго требования, то и Unity и UE вроде как обеспечивают возможность создания динамически загружаемых локаций, но остается нераскрытым вопрос, каким образом подобные локации можно создавать независимо от редактора и без пересборки проекта? Выход один — писать «движок внутри движка», который будет загружать «сырую» (в любом из наперед заданном формате экспорта из 3D-редакторов) геометрию и текстуры, применять к ним все необходимые эффекты и позиционировать в пространстве опираясь на данные, описанные в стороннем, независимом от движка формате, который нужно ещё разработать и научить движок его интерпретировать.
В связи с вышеперечисленным возникает вопрос — если для решения поставленной задачи необходимо писать мощную программную прослойку над игровым движком, большая часть функциональности которого в рассматриваемой задаче просто не нужна, то зачем нужен игровой движок?
Может быть достаточно графического движка? Этот вопрос я задавал предыдущей команде, бравшейся за обсуждаемую проблему опираясь на Unity (и закономерно слившейся чуть позже). В ответ получил встречный вопрос: «А что предлагаете вы?», ответив на который в духе приведенного выше текста получил саркастическую улыбку оппонента.
Если обойтись без сарказма, то представленная задача является типичной задачей визуализации — здесь требуется только фреймворк для работы с графикой, так как и физика, и аудиоподсистема, опирающаяся на физику реализованы на серверной стороне. Я и моя команды пришли к пониманию этого факта двигаясь по инерции предыдущих разработчиков сначала в сторону Unity, через UE и попытки прикрутить графическую подсистему от оного из открытых железнодорожных симуляторов (OpenBVE, что кстати получилось, но стало временным костылем)
OpenSceneGraph [5] является на сегодняшний день самым развитым (из открытых и бесплатных) графическим движком, ориентированным на C++ разработку. Он достаточно широко применяется за рубежом именно для технической трехмерной визуализации. Этот движок не обошли стороной и разного рода симулятора, наиболее известный из которых — FlightGear [6]. Некогда существовал и железнодорожный симулятор на базе этого движка — Indra [7], от которого, впрочем, остались только унылые скриншоты по вышеприведенной ссылке и его дальнейшая судьба мне неизвестна.
В контексте решаемой задачи графический движок OSG обладает следующими положительными качествами:
Потребовалось около полугода напряженного изучения возможностей OSG для того чтобы тщательно «прощупать почву» и найти подходы к решению поставленной задачи с помощью этого движка. То что родилось в итоге заслуживает отдельного разговора.
Видеоподсистема тренажеров подвижного состава (ВТПС) является клиентским приложением, буднично именуемым video3d-client и выполняет следующие функции:
Не то чтобы этот проект был opensource, однако с кодом полнофункциональной технологической демки вполне можно ознакомится здесь [8]. Проект состоит из следующих модулей:
При проектировании ВТПС встал вопрос выбора: разрабатывать формат маршрутов самостоятельно, либо воспользоваться существующим форматом маршрутов, а так же готовыми маршрутами отечественных железных дорог для существующего железнодорожного симулятора. На счастье подвернулось решение — закрытый проприетарный продукт ZDSimulator [9], обладающий той особенностью, что он заточен под отечественный подвижной состав и специфику работы сети железных дорог. Несмотря на похвальбу авторов проекта, он имеет массу существенных недостатков, но при этом имеет простой и понятный формат маршрутов, находящихся в открытом доступе. На первом этапе было грех не воспользоваться имеющейся возможностью, при том что графическая часть симулятора основана на открытом движке DGLEngine. Беда в том, что данный движок хоть и развивается (текущее состояние проекта можно увидеть тут [10]), но его текущая вторая версия несовместима с версией 1.1, на которой основан ZDSimulator. Исходники версии 1.1 утеряны, ссылки ведущие к ним давно протухли.
Тщательный поиск в вебархиве позволил найти утерянное и спасти, разместив DGLEngine v1.1 [11] на Gtihub. Этот движок использует свой, специфический формат 3D-моделей. Имея исходники движка нетрудно было написать соответствующий плагин для OSG.
Таким образом задача создания ВТПС свелась к написанию программной части на движке OSG. В дальнейшем планируется разработка собственного формата маршрутов, так как текущий формат предусматривает движение только по главным путям и обладает рядом недостатков, не позволяющих воссоздать ряд сложных маршрутов.
Иерархия основных классов ВТПС представлена на следующей диаграмме
Иерархия классов загрузчика маршрутов выглядит так
Загрузчик любого другого формата маршрутов может быть написан как плагин, содержащий класс, наследующий от класса RouteLoader. При старте ВТПС ей передается путь к каталогу с маршрутом, определяется формат маршрута и динамически загружается соответствующий плагин, выполняющий далее остальную грязную работу.
Принципиально важным нюансом явилась интеграция движка OSG и Qt. Таковая интеграция существует и именуется osgQt [12]. Эта библиотека не использована в данном проекте по двум причинам:
Возникло понимание того, что интеграция с Qt нужна в части использования концепции «сигналы-слоты», для обеспечения взаимодействия с сетевой подсистемой tcp-connection, использующей Qt и являющейся стандартом де-факто в наших разработках. Опираться на систему сообщений OSG и заново писать TCP-клиент (да ещё и кроссплатформенный) очень не хотелось. Нашлось элегантное решение, опирающееся на то, что если мы хотим, чтобы один объект послал сигнал, инициирующий срабатывание слота у другого объекта мы должны выполнить три условия:
При этом вовсе ни в коем случае не следует выполнять вызов QApplication::exec(), запускающий штатный цикл обработки сигналов, достаточно организовать цикл в котором просто обрабатывать сигналы вызовом QApplication::processEvents(). В OSG таковой цикл имеется (тот цикл, в котором выполняется рендеринг) и имеется возможность создать обработчик событий, в котором обрабатывается событие osgGA::GUIEventAdapter::FRAME, генерируемое движком при отрисовке очередного кадра. Таким образом вся интеграция свелась к коду
qt-events.h
#ifndef QT_EVENTS_H
#define QT_EVENTS_H
#include <osgGA/GUIEventHandler>
#include <QtCore/QtCore>
class QtEventsHandler : public osgGA::GUIEventHandler
{
public:
QtEventsHandler(){}
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
protected:
};
#endif // QT_EVENTS_H
qt-events.cpp
#include "qt-events.h"
bool QtEventsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::FRAME:
{
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
break;
}
default:
break;
}
return false;
}
main.cpp
#include "main.h"
/*!
* fn
* brief Entry point
*/
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
RouteViewer viewer(argc, argv);
if (viewer.isReady())
return viewer.run();
return 0;
}
после чего, классы унаследованные от QObject и его производных могут обмениваться сигналами до потери пульса.
Всё вышеперечисленной позволило за два месяца создать первый рабочий прототип ВТПС. Чтобы продемонстрировать что вышло в итоге, предлагаю следующую нарезку из опытных поездок по реальным маршрутам. Заранее прошу прощения за качество съемки — не разжились толковой техникой
Главным выводом, по крайней мере для нашей команды стало то, что «серябрянной пули» не существует и в вопросах выбора технологии реализации проекта. Агрессивно продвигаемые на рынок игровые движки не всегда подходят для решения специфических задач, к каким относится визуализация результатов моделирования технических систем. А если и подходят, то не являются оптимальными с точки зрения усилий, потраченных на разработку и сопровождение проекта.
Обидно, что весьма неплохой, а главное свободный, графический движок OSG по факту не имеет в нашей стране сообщества. Дабы исправить эту проблему я пишу цикл статей здесь на ресурсе [13] (там я собрал все ссылки на более менее адекватные источники информации, в том числе и на русском языке). Кроме того, в качестве документации, описывающей базовые принципы OSG могу предложить ещё и этот блог [14]. Надеюсь что кому-то эта информация окажется полезной.
Что касается ВТПС, то работа в этом направлении продолжается. На очереди ещё масса важных задач, которые предстоит решить в ближайшем будущем.
Благодарю за внимание!
Центр развития инновационных компетенций РГУПС [15]
Автор: maisvendoo
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/305513
Ссылки в тексте:
[1] публикация: https://habr.com/ru/post/408885/
[2] заметил один из комментаторов: https://habr.com/ru/post/408885/#comment_18492429
[3] был задан вопрос: https://habr.com/ru/post/408885/#comment_18492469
[4] вот этой: https://ru.wikipedia.org/wiki/Journeyman_Project
[5] OpenSceneGraph: http://www.openscenegraph.org/
[6] FlightGear: http://home.flightgear.org/
[7] Indra: http://openscenegraph.sourceforge.net/screenshots/Indra/
[8] здесь: https://github.com/maisvendoo/video3d-client
[9] ZDSimulator: https://zdsimulator.com.ua/
[10] можно увидеть тут: https://github.com/DGLE-HQ/DGLE
[11] DGLEngine v1.1: https://github.com/maisvendoo/DGLEngine
[12] osgQt: https://github.com/openscenegraph/osgQt
[13] цикл статей здесь на ресурсе: https://habr.com/ru/post/429816/
[14] этот блог: https://maisvendoo.github.io/
[15] Центр развития инновационных компетенций РГУПС: https://vk.com/crikrgups
[16] Источник: https://habr.com/ru/post/436276/?utm_campaign=436276
Нажмите здесь для печати.