1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Programación con Python y JPype

From openrocket

Revision as of 23:49, 1 March 2012 by Jesmanrec (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Programación OpenRocket con Python y JPype

La capacidad de realizar scripts para OpenRocket con el objetivo de mejorarlo con el código escrito por el propio usuario, es un tema frecuentemente discutido entre la comunidad de OpenRocket.

Este artículo muestra una aproximación al problema. Utilizando la biblioteca Python [1] y JPype [2] es posible escribir scripts externos que se ejecutan fuera de OpenRocket, pero haciendo uso de OpenRocket como cualquier otra biblioteca Python.

Este enfoque proporciona un entorno de desarrollo muy rápido para la optimización de diseños de cohetes, la mejora y la exploración de la simulación. También es probablemente el mejor método si está interesado en hacer uso de OpenRocket como parte de algo más grande. Una ventaja importante de este enfoque en algo así como scripts incrustados Jython es que usted tiene acceso completo a todo el ecosistema de Python, fundamentalmente NumPy [3], SciPy [4], Matplotlib [5] y otras bibliotecas CPython únicas. Sin embargo, dado que los scripts requieren de un software externo, éstos no se pueden integrar en una distribución OpenRocket independiente. No obstante, sí proporcionan una buena manera de crear prototipos de nuevas características para OpenRocket.

Requisitos

Para ejecutar los siguientes ejemplos necesitará instalar Python 2.5 o posteriores versiones 2.x de Python, y Jpype, y una versión de OpenRocket superior a la 1.1.9. Se requiere disponer de las bibliotecas NumPy, SciPy, y Matplotlib (por lo general éstas vienen juntas). Estos scripts hacen uso de un módulo de Python orhelper.py (abajo). Nota: Hasta que no encontremos una mejor manera de organizar los archivos, pueden descargarse desde el archivo de la lista de correo.

Orhelper: Archivo:orhelper.py

Este es un módulo muy ligero con el que se han escrito estos ejemplos para que se haga cargo de algunos de los aspectos más complicados de script para OpenRocket con JPype.

En el momento de escribir el módulo Orhelper, contendrá:

  1. Una clase OpenRocketInstance que se encarga de poner en marcha una JVM (Máquina Virtual de Java) y una instancia de trabajo OpenRocket. Se equipara con los métodos __enter__ y __exit__ y está pensado para ser llamado utilizando el constructor 'with' [6] de Python 2.5. Esto es para asegurarse de que no importa lo que ocurra dentro de ese contexto, la JVM siempre permanecerá convenientemente detenida y (con suerte) obtendrá información de excepción útil.
  2. Una clase Helper, que simplemente contiene un montón de funciones auxiliares útiles y contenedores para utilizar con OpenRocket mediante Jpype. Estos están destinados a hacerse cargo de algunos de los aspectos más complicados sobre las llamadas a los métodos, o proporcionar más estructuras de datos de 'Pythonic' para uso general. El espacio de nombres (namespace) completo net.sf.openrocket está disponible como el orp o propietario de esta clase.
  3. Una clase AbstractSimulationListener. Esta es esencialmente una versión de la clase OpenRocket.simulation.listerners de Python del mismo nombre. Se puede extender esta clase para hacer sus propias extensiones de la simulación con Python y recibir respuestas de la simulación OpenRocket.
  4. Hay también una pequeña clase de contenedor, JIterator que es para el uso de iteradores de Java como si fueran iteradores Python.

Ejemplo 1: Archivo: simple_plot.py

Este es un ejemplo sencillo para trazar el vuelo de un cohete con Matplotlib. Se genera una representación gráfica de la altitud y la velocidad vertical respecto al tiempo, con anotaciones para diversos eventos mucho mejor que el representado por defecto en OpenRocket.

En este ejemplo, toda la interacción con OpenRocket se realiza a través de diversos métodos Orhelper. La clase orhelper.Helper a partir de ahora se denominará orh.

En primer lugar, iniciamos una instancia OpenRocket dentro del entorno protegido 'with'. Por tanto asegúrese de cambiar el nombre del archivo OpenRocket.jar. A continuación, cargamos un documento OpenRocket, yo utilizo aquí el ejemplo de 'Un modelo de cohete básico'. A continuación, sacamos un objeto de la simulación fuera de este archivo. Este archivo tiene múltiples simulaciones ya creadas, justamente hemos tomado la primera. A continuación, ejecutamos la simulación. Ahora tenemos que extraer los datos de la simulación. Esto se hace con el método orh.get_timeseries. Este método devuelve un diccionario de datos de series temporales (como matrices NumPy) de una simulación a partir una secuencia de nombres de variables. Los nombres de variables van de acuerdo con las del entorno local por defecto, eche un vistazo al interior de la ventana del gráfico de OpenRocket para ver los nombres exactos. Para añadir anotaciones al gráfico, necesitamos conseguir un diccionario que contenga todos los eventos del vuelo. Esto se hace con el método orh.get_events (las claves son los nombres de los eventos, y los valores son los tiempos).

El resto del código es material estándar de Matplotlib - si no está familiarizado, compruebe su documentación. Hay sin embargo un par de funciones en línea que serán dignas de una explicación más detallada. Ahora quiero tener las etiquetas de los ejes y las marcas del mismo color que las líneas. Matplotlib no tiene una forma integrada de cambiar todas las marcas, pero eso se hace fácilmente con la función en línea 'change_color'. Además, debido a que 'get_events' sólo nos da información del tiempo, necesitamos extraer el índice de la matriz correspondiente para incluir las anotaciones en el lugar correcto. Esto se hace con la función 'index_at' que a su vez hace uso de la función NumPy 'argmin'.

File: simple_plot.png

Ejemplo 2: Archivo: lazy.py

El propósito de este ejemplo es mostrar cómo puede modificarse una simulación, y demostrar el uso de métodos numéricos de SciPy. El problema en el que estamos trabajando es el de un modelista que es un perezoso, y tras lanzar su cohete, no quiere caminar mucho desde el lugar de lanzamiento para ir a recogerlo y preferiría que su cohete volase describiendo un arco preciso que lo regrese cerca de su punto de salida. Se supone que el cohete está volando contra el viento, y en consecuencia se desea optimizar el ángulo de inclinación de la rampa de lanzamiento. Queremos representar una familia de curvas de distintos ángulos y poner de relieve el ángulo optimizado.

La estructura del programa y las líneas iniciales para la carga del modelo de cohete son los mismos que en el ejemplo anterior. En este ejemplo, tenemos que definir una función para variar el ángulo de lanzamiento antes de la simulación del vuelo. Esto nos obliga a obtener las opciones de simulación fuera de la propia simulación con el método getOptions(), y a continuación podemos ajustar el ángulo interior del objeto SimulationOptions. Para los no iniciados, en OpenRocket la clase simulation.SimulationOptions básicamente contiene todas las opciones que se encuentran en la ventana de edición de la simulación. Cuando se inicia la simulación, estas opciones se usan para hacer un objeto simulation.SimulationConditions. Después de ejecutar la simulación, observamos las variable de Altitud y posición contra el viento, que son las que nos interesan. Una opción sería la de recuperar sólo los valores finales con orh.get_final_values, sin embargo, por razones que serían poco claras, recuperamos la serie entera de tiempos.

Para ejecutar un método de optimización, necesitamos alguna función cuyo resultado es cero en el punto óptimo. Esto no es tan simple como conseguir la distancia contra el viento final, ya que la simulación paso a paso, normalmente tendrá poco exceso y calculará un punto final con una altura negativa. También queremos excluir el lanzamiento. Hay más formas elaboradas que podrían hacerlo --- aquí por simplicidad, acotamos por la última mitad de los datos, buscamos el índice con la menor altitud absoluta y devolvemos la distancia contra el viento correspondiente. A continuación, podemos seguir adelante y trasladar esto a nuestro método de optimización dando un valor inicial (40 grados) para empezar. SciPy tiene una amplia gama de métodos de optimización con un rico patrimonio, en nuestro caso elegimos el fmin básico que emplea el algoritmo "simplex cuesta abajo".

En este ejemplo, queremos trazar una familia de curvas, por lo que generaremos un rango de 10 ángulos de lanzamiento con np.linspace y añadiremos nuestro ángulo óptimo. A continuación, ejecutamos las simulaciones haciendo una lista de todos los diccionarios de las series temporales de datos y la agregamos una clave Ángulo a cada diccionario. A continuación, seguimos adelante y lo representamos usando un estilo de línea continua para la curva óptima y líneas de puntos para el resto.

File: lazy.png

Ejemplo 3: Archivo: monte_carlo.py

Como todo estudiante de introducción a la física sabe, presentar sólo un número como resultado de un cálculo no es realmente suficiente - también es necesario conocer la incertidumbre para que sea significativo. El propósito de este ejemplo es demostrar un método simple de Monte Carlo [7], donde se ejecutan múltiples simulaciones con diferentes parámetros distorsionados para determinar la incertidumbre general del lugar de aterrizaje en términos de alcance, y el "colchón o margen" del sitio de lanzamiento. Este ejemplo demuestra también la utilización de las Extensiones de la simulación implementadas en Python. Las Extensiones de la simulación de OpenRocket se tratan en el apartado 9 de la Guía del usuario.

La estructura de este script es ligeramente diferente de los ejemplos anteriores. En primer lugar considere cómo obtener el rango de aterrizaje y la información del colchón. Esta información no está disponible directamente como una variable de simulación, aunque sean la latitud y la longnitud. Una opción sería la de obtener estas variables, y hacer el cálculo en Python. Sin embargo, OpenRocket ya incluye métodos para hacerlo, como parte de la clase util.GeodeticComputationStratery, que es un parámetro de cada simulación, por lo que es bueno hacer uso de ellos ya que operan de forma nativa en los objetos util.WorldCoordinate. Hacemos esto mediante la definición de una nueva Extensión de la simulación LandingPoint la cual extiende la clase orhelper.AbstractSimulationListener. Se define un método endSimulation que captura la simulación GeodeticComputationStratergy y lo utiliza para encontrar la distancia y el colchón del sitio de lanzamiento WorldCoordinate (desde SimulationConditions) a la posición del cohete (desde SimulationStatus). Estos se guardan como instancias de las variables LandingPoint.

Se almacenan múltiples objetos LandingPoint en un LandingPointList, que es como una lista normal, excepto que puede rellenarse con los puntos de aterrizaje mediante la ejecución de múltiples simulaciones OpenRocket. Se definen varios parámetros mediante elección de valores en una distribución gaussiana, con una desviación media y estándar determinada (método Python random.gauss). El código para ejecutar las simulaciones ha sido discutido anteriormente en su mayoría, y se ha utilizado el mismo ejemplo de cohete, aunque en mi caso activé un poco de viento y una turbulencia y cambié a un método de cálculo de "Tierra esférica". Un aspecto que es nuevo, es la modificación del modelo de cohete. Un objeto rocketcomponent.Rocket puede obtenerse a partir de las opciones de la simulación. Esta es la raíz de una estructura de datos tipo "árbol", que contiene todos los componentes del cohete. Nuestra clase orh.Helper tiene un método para encontrar los componentes en el árbol por el nombre. Lo utilizamos para obtener los componentes "Ojiva" y "Cuerpo tubular", y anular sus masas con valores distorsionados. La ejecución de la simulación se realiza utilizando una vez más orh.runsimulation, excepto que en este caso enviamos una secuencia de objetos Extensiones para usar. Para aumentar la variabilidad, aún pasamos una Extensión AirStart con la altitud de inicio establecida al azar. Este detector es una copia Python del ejemplo suministrado con OpenRocket.

Por último, cuando se ejecuta la función principal del script, realiza una nuevaLandingPointList, que se llena y luego utiliza el método ' print_stats para mostrar las estadísticas finales del aterrizaje, algo como:

Zona de aterrizaje del cohete 3.833,57 m + - 1,116.91 m colchón -89.98 grados + - 0,0713 grados desde el sitio de lanzamiento. Basado en 20 simulaciones. </ code>

Tenga en cuenta que puede tardar un minuto o dos en ejecutar todas las simulaciones.

Personal tools