Visualización tridimensional en simuladores de material rodante basados ​​en el motor OpenSceneGraph



Hace poco menos de un año, se publicó una publicación donde hablamos sobre el complejo de capacitación y laboratorio (ULK) del tren eléctrico ES1 Lastochka desarrollado por nuestra universidad. Luego prometí que esta no sería la última publicación sobre este tema, en particular, amenacé con hablar sobre los problemas de crear una visualización tridimensional para tales simuladores y describir los principales enfoques para resolverlos.

El año pasado, estuvimos satisfechos con nuestro próximo lanzamiento: el ULK del tren eléctrico de alta velocidad Sapsan EVS2, que tuvo lugar en agosto del año pasado. El complejo educativo y de laboratorio de este tren eléctrico en sí merece una historia aparte, pero en el contexto de esta publicación hablaremos sobre la llaga: el problema de crear un subsistema adecuado de visualización tridimensional, cuya solución se acercó a nuestro equipo desde diferentes lados durante aproximadamente dos años. El lanzamiento del simulador Sapsan es significativo (entre otras cosas) y en eso determinó el vector de desarrollo de nuestros desarrollos en esta área.

1. Brevemente sobre ULK EVS2 "Sapsan"


Quiero enfatizar una vez más (lo que hago con una frecuencia envidiable) que los complejos educativos y de laboratorio de material rodante desarrollados en nuestra universidad no están destinados a la preparación de brigadas de locomotoras. Como uno de los comentaristas del artículo anterior señaló acertadamente, nuestros ULK no son simuladores, sino simuladores, donde el énfasis principal está en la implementación competente de la física del movimiento del tren y la simulación de la operación de los subsistemas de material rodante que aseguran su movimiento y parada. El simulador Sapsan no es una excepción, en la que se resuelven las siguientes tareas:

  • Se implementó un modelo dinámico de la parte mecánica del tren teniendo en cuenta las fuerzas longitudinales y el perfil de la vía.
  • Se ha construido un modelo informático detallado del funcionamiento de los subsistemas clave del tren eléctrico: circuito eléctrico de potencia, accionamiento eléctrico de tracción, frenos neumáticos y electroneumáticos.
  • Se reproducen los algoritmos básicos del funcionamiento del sistema de control del tren eléctrico a diferentes niveles.

Además, el complejo de capacitación y laboratorio incluye un modelo de tamaño completo de la cabina del tren eléctrico con los controles principales y los medios para mostrar la información. A diferencia del simulador Swallows, esta cabina no fue fabricada por nosotros por nuestra cuenta, sino que fue comprada en 2015 en una oficina en el país que produce simuladores de entrenamiento. Por lo tanto, el proceso de desarrollo del simulador se centró en la creación de software.

Foto de la cabina
Vista general del interior de la cabina.


Ver a través del parabrisas


Display dispositivo locomotor de seguridad integrado (CLUB-U). El rojo "290" es el límite de velocidad actual obtenido de la tarjeta electrónica CLUB-U. Hasta ahora, el límite de velocidad alcanzado por Sapsan en el ferrocarril de octubre hace alarde aquí. En el futuro, la tarjeta electrónica se implementará como se hace en la vida.


Pantalla principal "Interfaz hombre-máquina"


Visualización del estado del sistema de frenos del tren eléctrico.


Ajustador de velocidad y controlador de tracción


Controlador de control de freno de tren eléctrico


Interruptores de palanca para el control de colectores de corriente y dispositivos de protección (BV / GV) - interruptores de palanca negros cerca del ajustador de velocidad


Interfaz de gestión de formación: pantalla de selección de ruta


Pantalla de control de volumen de efectos de audio


Contador de kilometraje. Una historia divertida se asocia con su apariencia. Cuando entregamos nuestro primer simulador de la locomotora diesel 2TE116, el representante del cliente bromeó con nuestra pregunta sobre cuándo se firmará el acto de finalización: “Bueno, hagámoslo como en la vida: cuando se pone en funcionamiento una nueva locomotora, debe pasar por una carrera de 5000 kilómetros. Eso pasará ... ". El acto, por supuesto, se firmó mucho antes, pero, evaluando el humor de la situación, ya hicimos un contador similar en el simulador Swallows. El contador se puede restablecer a "0" ingresando la contraseña de servicio.


Panel accesorio derecho con manómetros de freno y válvula de freno de emergencia. No todos los elementos inherentes a este Sapsan están instalados aquí; el proveedor recibió un control remoto de este tipo


Por lo tanto, algunos de los controles que son críticos para nosotros se implementaron en el software, en particular, el panel de interruptores de derivación controlados desde la pantalla táctil


El desarrollo de software para dicho simulador es una pregunta muy amplia, y trataré (lo mejor que pueda) de satisfacer el interés de los lectores en estos temas en el futuro (si corresponde), pero por ahora, volvamos al tema principal del artículo: visualización tridimensional del proceso de movimiento del tren.

2. Antecedentes y tecnología del pasado.


En los comentarios al último artículo , se hizo una pregunta que, francamente, me divirtió bastante. Sí, de hecho, en muchos simuladores que todavía se usan hoy en día, este enfoque todavía se usa: el video se graba en una sección real del ferrocarril y luego se desplaza en el simulador a una velocidad proporcional a la velocidad de movimiento. Esto se hizo solo porque en aquellos días en que se crearon tales simuladores, la calidad de los gráficos tridimensionales dejaba mucho que desear, y esto también se aplicaba a las estaciones gráficas duras en Unix comerciales, y no había duda de una PC. Por lo tanto, incluso los fabricantes de juegos de computadora, por ejemplo este , no dudaron en utilizar este enfoque.

Esto no tiene sentido hoy, porque:

  1. La velocidad de fotogramas insuficiente a bajas velocidades del tren no proporciona la suavidad deseada de la actualización de la imagen. Tendremos los atesorados 25 fps solo a la velocidad a la que se grabó el video desde la cabina del conductor. Y esta falla fatal no se puede superar de ninguna manera, ni disparando con una cámara de alta velocidad (¿cuánto pesará el video a 120 cuadros por segundo? Eso es lo mismo ...), ni por la generación programada de cuadros intermedios. Este último lo llevamos a cabo utilizando la tecnología OpenCV, pero no condujo a resultados normales. Esta pregunta se estudió repetidamente desde todos los lados y, como resultado, se concluyó que el costo de los recursos para crear dicho sistema es mucho mayor que el desarrollo de un sistema similar, pero basado en gráficos 3D
  2. Dificultades para desplazar suavemente el video hacia atrás. E incluso teniendo en cuenta que serán superados, entonces, ¿dónde correrán los perros que corren en la plataforma? ¿Creemos que debemos ir en reversa?
  3. La falta de toda "interactividad". ¿Qué hacer con un cambio en el semáforo, con el movimiento de desvíos, el movimiento de trenes que se aproximan y pasan?

Por lo tanto, todos los simuladores y simuladores modernos se crean utilizando gráficos 3D interactivos, ya que hoy en día no existen obstáculos desde el punto de vista del software o del hardware.

Si todo está muy claro desde el punto de vista del hardware: el monitor instalado en lugar del parabrisas está conectado a una PC con una tarjeta de video normal (ni siquiera la de gama alta), entonces, desde el punto de vista del software, surge la pregunta de elegir la tecnología para implementar la tarea.

3. El motor gráfico versus el motor del juego o por qué se eligió OpenSceneGraph


Puedo estar equivocado, pero anticipo los comentarios por adelantado, lo que hará una pregunta completamente lógica, ¿por qué, al analizar las tecnologías existentes, nuestra elección no se detuvo en mastodontes como Unity o Unreal Engine 4? Contestaré esta pregunta, además, justificaré mi respuesta.

Brevemente, ni Unity ni Unreal Engine satisfacen los requisitos de la tarea que se está resolviendo. Una respuesta más detallada proporciona, en primer lugar, una lista de los requisitos en cuestión. TK, compilado por nosotros en el subsistema de visualización tridimensional, incluye (en orden decreciente de importancia) las siguientes disposiciones:

  1. Independencia del proceso de desarrollo de software del subsistema de visualización y del proceso de creación de recursos para él. Los recursos, en este caso, incluyen modelos tridimensionales, texturas, así como las llamadas rutas . Una ruta se entiende como una combinación de objetos de configuración y recursos que permiten que el subsistema de video muestre la sección deseada del ferrocarril y simule el movimiento del tren a lo largo de él. Esto también incluye la posibilidad de cambiar la ruta sin reconstruir la parte del software del subsistema de video
  2. Crea rutas de longitud ilimitada. Haré una reserva de que una longitud ilimitada es en principio inalcanzable debido a los recursos limitados de hardware. Este requisito debe entenderse que la longitud de la ruta debe estar al menos dentro de un "arcén", es decir, una sección de la carretera entre los puntos de giro, y esto, dependiendo de varios factores, es una distancia suficientemente grande, estimada en más de cien kilómetros. Este requisito impone la necesidad de proporcionar carga / descarga dinámica de los recursos del programa con suficiente suavidad con un consumo de memoria razonable. Y es deseable que el motor contenga dicha funcionalidad "fuera de la caja"
  3. Integración conveniente con la pila de tecnología utilizada. Tradicionalmente, debido a razones objetivas nuevamente, nuestro equipo usa lenguaje C ++ con Qt Framework, QtCreator IDE y Git como un sistema de control de versiones para desarrollar software para ULK PS. Como plataforma de sistema ULK PS, se utiliza un sistema operativo basado en el kernel de Linux

¿Qué hay de malo en Unity y UE? ¿Cuál es el hecho de que otros motores pueden importar recursos de formatos completamente diferentes? Sin embargo, al ensamblar el proyecto, se convierten irreversiblemente al formato binario interno, lo que hace que sea imposible agregar y cambiar recursos sin volver a ensamblar el proyecto. Las tecnologías como los prefabricados y los paquetes de activos disponibles en Unity no resuelven el problema, ya que el editor del motor no es el mejor lugar para crear ubicaciones ferroviarias, lo que requiere la extensión del editor, lo que lleva a la necesidad de escribir un "motor dentro del motor". Además, la creación de prefabricados y paquetes es imposible sin el uso del editor de Unity, y esto, como ha demostrado la práctica, no es muy conveniente, especialmente para modeladores y diseñadores de niveles puros. En cuanto a la UE, hice muchas preguntas sobre este y otros recursos durante dos años sobre cómo separar el proceso de construcción de un proyecto del proceso de agregar / cambiar los recursos que usa, y no obtuve una respuesta adecuada ni en la documentación ni en " inveterados "desarrolladores de juegos. Sería muy feliz (sin sarcasmo) si me topara razonablemente con algo que me perdí.

En cuanto al segundo requisito, tanto Unity como UE parecen proporcionar la capacidad de crear ubicaciones cargadas dinámicamente, pero la pregunta sigue sin respuesta, ¿cómo pueden crearse dichas ubicaciones independientemente del editor y sin reconstruir el proyecto? Solo hay una salida: escribir un "motor dentro del motor", que cargará la geometría y las texturas "en bruto" (en cualquiera de los formatos de exportación establecidos previamente desde editores 3D), aplicará todos los efectos necesarios y colóquelas en el espacio en función de los datos descritos en un tercero independiente del formato del motor, que aún necesita ser desarrollado y enseñado para interpretar el motor.

En relación con lo anterior, surge la pregunta: si para resolver este problema es necesario escribir una capa de software potente sobre el motor del juego, cuya mayor parte de la funcionalidad simplemente no es necesaria en el problema en consideración, entonces ¿por qué necesitamos un motor de juego?

Tal vez el motor de gráficos es suficiente? Le hice esta pregunta al equipo anterior, que abordó el problema en discusión, confiando en Unity (y naturalmente se fusionó un poco más tarde). En respuesta, recibió una contrapregunta: "¿Qué sugieres?", Respondiendo que, en el espíritu del texto anterior, recibió la sonrisa sarcástica de un oponente.

Si no tiene sarcasmo, la tarea presentada es una tarea típica de visualización: solo requiere un marco para trabajar con gráficos, ya que tanto la física como el subsistema de audio basado en la física se implementan en el lado del servidor. Mi equipo y yo llegamos a comprender este hecho, moviéndonos por inercia de los desarrolladores anteriores, primero hacia Unity, a través de UE e intentando sujetar el subsistema de gráficos de uno de los simuladores de ferrocarril abierto (OpenBVE, que por cierto resultó, pero se convirtió en una muleta temporal)

OpenSceneGraph es, con mucho, el motor gráfico más desarrollado (abierto y gratuito) centrado en el desarrollo de C ++. Es ampliamente utilizado en el extranjero precisamente para la visualización técnica tridimensional. Este motor no se libró de ningún tipo de simulador, el más famoso de los cuales es FlightGear . Hubo una vez un simulador ferroviario basado en este motor: Indra , que, sin embargo, dejó solo capturas de pantalla aburridas del enlace de arriba y su destino adicional es desconocido para mí.

En el contexto de la tarea en cuestión, el motor de gráficos OSG tiene las siguientes cualidades positivas:

  • Multiplataforma, lo que hace posible su aplicación en el ecosistema GNU / Linux
  • El lenguaje de desarrollo es C ++ / STL, lo que permite integrarlo fácil y naturalmente en el proceso tecnológico de desarrollo establecido;
  • La gama más amplia de formatos de recursos admitidos "listos para usar": geometría 3D y texturas debido al sistema de plug-in desarrollado. Una interfaz simple e intuitiva para escribir sus propios complementos para configurar el administrador de recursos para formatos no estándar, que utilizamos (escribiré sobre esto a continuación);
  • Un sistema de gestión de memoria basado en su propio modelo de punteros inteligentes (históricamente se ha utilizado un formato patentado de punteros inteligentes, debido al hecho de que al comienzo del desarrollo del motor de puntero inteligente no había un estándar en C ++);
  • Arquitectura modular flexible;
  • El gestor de objetos de escena que carga dinámicamente objetos, proporciona carga y representación de solo aquellos objetos que caen dentro de la pirámide de recorte (debido a la clase osg :: PagedLOD)
  • Capacidad para integrarse con el marco Qt. Gracias al conveniente modelo de "señales - ranuras" proporcionado por Qt, que simplifica y acelera significativamente el desarrollo de C ++, utilizamos ampliamente este marco para desarrollar software complejo de capacitación. En consecuencia, hemos acumulado una importante base de código reutilizada en diferentes proyectos, especialmente con respecto a la biblioteca de comunicación entre procesos basada en sockets TCP. Usar las capacidades de Qt en el proyecto del subsistema de video parece ser una decisión lógica;
  • Suficiente calidad de imagen para la tarea a resolver.

Tomó cerca de seis meses de estudio intensivo de las capacidades de OSG para "investigar el terreno" a fondo y encontrar enfoques para resolver el problema con este motor. Lo que nació como resultado merece una discusión por separado.

4. De la arquitectura al prototipo de trabajo.


El subsistema de video de los simuladores de capacitación de material rodante (HTSC) es una aplicación cliente, denominada rutinariamente video3d-client, y realiza las siguientes funciones:

  • Solicitud de conexión a la parte del servidor del simulador, autorización en el servidor con solicitud periódica posterior para el identificador de la ruta cargada, y luego la posición actual del tren. Si la conexión se desconecta del lado del servidor, el sistema cambia al modo de espera para volver a conectarse;
  • Descarga de la ruta seleccionada, organización de la gestión dinámica de los contenidos de la escena renderizada;
  • Realmente renderizando la escena de acuerdo con la posición actual del tren en la ruta

No es que este proyecto fuera de código abierto, pero el código de una demostración de tecnología con todas las funciones se puede encontrar aquí . El proyecto consta de los siguientes módulos:

  • sistema de archivos : una biblioteca para trabajar con el sistema de archivos, proporciona la generación de rutas a archivos de configuración y recursos de aplicaciones
  • biblioteca : una implementación multiplataforma del cargador dinámico de bibliotecas. En general, una muleta escrita en un momento en que las posibilidades de integración con Qt (donde hay un módulo QLibrary listo para la batalla) todavía era vago
  • osgdb_dmd es un complemento para cargar modelos de un formato específico para el motor DGLEngine versión 1.1. Para lo que se requirió, explicaré un poco más abajo
  • route-loader es una biblioteca que proporciona una interfaz abstracta para el cargador de rutas. Es posible cargar rutas de formato arbitrario
  • tcp-connection : biblioteca de comunicación entre procesos a través de sockets TCP
  • visor - el principal módulo ejecutable del programa
  • zds-route-loader : complemento para cargar rutas del formato ZDSimulator

Al diseñar el VTPS, surgió la pregunta de si desarrollar un formato de ruta de forma independiente, o usar el formato de ruta existente, así como rutas ya preparadas de ferrocarriles domésticos para el simulador ferroviario existente. Afortunadamente, surgió la decisión: el producto cerrado ZDSimulator , que tiene la característica de que está diseñado para el material rodante nacional y los detalles de la red ferroviaria. A pesar de los elogios de los autores del proyecto, tiene muchos inconvenientes importantes, pero tiene un formato simple y claro de rutas de acceso público. En la primera etapa, era un pecado no aprovechar la oportunidad, a pesar de que la parte gráfica del simulador se basa en el motor abierto DGLEngine. El problema es que este motor, aunque está en desarrollo (el estado actual del proyecto se puede ver aquí ), pero su segunda versión actual es incompatible con la versión 1.1, en la que se basa ZDSimulator.Los códigos fuente de la versión 1.1 se pierden, los enlaces que conducen a ellos se han desvanecido durante mucho tiempo.

Una búsqueda exhaustiva en el archivo web permitió encontrar a los perdidos y guardarlos publicando DGLEngine v1.1 en Gtihub. Este motor utiliza su propio formato específico de modelos 3D. Teniendo la fuente del motor, fue fácil escribir el complemento apropiado para OSG.

Por lo tanto, la tarea de crear HTPS se redujo a escribir la parte del software en el motor OSG. En el futuro, se planea desarrollar su propio formato de rutas, ya que el formato actual permite el movimiento solo a lo largo de las rutas principales y tiene una serie de inconvenientes que no permiten recrear una serie de rutas complejas.

La jerarquía de las clases principales de HTPS se presenta en el siguiente diagrama


La jerarquía de clases del cargador de rutas se ve así


El cargador de cualquier otro formato de ruta se puede escribir como un complemento que contiene una clase que hereda de la clase RouteLoader. Al comienzo de VTPS, la ruta al directorio con la ruta se transfiere a ella, se determina el formato de la ruta y el complemento correspondiente se carga dinámicamente, lo que realiza el resto del trabajo sucio.

Un matiz fundamentalmente importante fue la integración del motor OSG y Qt. Dicha integración existe y se llama osgQt . Esta biblioteca no se usó en este proyecto por dos razones:

  1. No hay necesidad de controles de ventana proporcionados por Qt. OSG tiene su propio sistema de gestión de ventanas GUI bien desarrollado y no tiene sentido cerrar la GUI encima de otra GUI, ya que osgQt está destinado principalmente a integrar el visor OSG en la GUI basada en Qt
  2. osgQt está sujeto a un error: operación incorrecta con el contexto OpenGL, que en algunos casos no se puede dividir entre OSG y QGLWidget, debido a que la escena se muestra en cualquier lugar, pero no en el widget Qt. Además, aún no ha sido posible descubrir las razones, ya que en algunos sistemas este error no se manifiesta.

Se entendió que la integración con Qt es necesaria en términos del uso del concepto de "ranuras de señal" para garantizar la interacción con el subsistema de red de conexión tcp que usa Qt y es el estándar de facto en nuestros diseños. Realmente no quería confiar en el sistema de mensajería OSG y reescribir el cliente TCP (e incluso multiplataforma). Se encontró una solución elegante, basada en el hecho de que si queremos que un objeto envíe una señal que active una ranura para otro objeto, debemos cumplir tres condiciones:

  1. Heredar clases interactivas de QObject
  2. Organice un bucle de procesamiento de señal
  3. Cree una instancia de la clase QApplication (o QCoreApplication) que existe en la memoria durante la operación de la aplicación

En este caso, en ningún caso debe realizar una llamada a QApplication :: exec (), que inicia el ciclo de procesamiento de señal regular, es suficiente para organizar un ciclo en el que sea fácil procesar señales llamando a QApplication :: processEvents (). OSG tiene dicho ciclo (el ciclo en el que se realiza el renderizado) y es posible crear un controlador de eventos en el que se procesa el evento osgGA :: GUIEventAdapter :: FRAME generado por el motor cuando se procesa el siguiente marco. Por lo tanto, toda la integración se redujo a código

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; } 

después de lo cual, las clases heredadas de QObject y sus derivados pueden intercambiar señales hasta que se pierde el pulso.

Todo lo anterior permitió durante dos meses crear el primer prototipo funcional de HTPS. Para demostrar lo que sucedió al final, propongo la siguiente sección de viajes experimentales en rutas reales. Pido disculpas de antemano por la calidad de los disparos: no obtuvieron tecnología inteligente


Conclusión y conclusiones


La conclusión principal, al menos para nuestro equipo, fue que no había una "bala gris" en la elección de la tecnología para implementar el proyecto. Los motores de juego comercializados agresivamente no siempre son adecuados para resolver tareas específicas, que incluyen la visualización de los resultados de los sistemas técnicos de modelado. Y si son adecuados, entonces no son óptimos en términos de los esfuerzos dedicados al desarrollo y mantenimiento del proyecto.

Es una pena que un motor de gráficos OSG muy bueno y, lo más importante, gratuito, de hecho, no tenga una comunidad en nuestro país. Para solucionar este problema, escribo una serie de artículos aquí sobre el recurso (allí recopilé todos los enlaces a fuentes de información más o menos adecuadas, incluso en ruso). Además, como documentación que describe los principios básicos de OSG, también puedo ofrecer este blog . Espero que alguien encuentre útil esta información.

En cuanto a HTSC, el trabajo en esta dirección continúa. Todavía hay muchas tareas importantes que deben resolverse en el futuro cercano.

Gracias por su atencion!

(c) Centro para el Desarrollo de Competencias de Innovación

Source: https://habr.com/ru/post/es436276/


All Articles