trensim.comSimulación Ferroviaria
   

Descifrando un Script

Foro destinado a la discusión de aspectos relacionados con la creación de scripts en RailWorks.

Moderador: Moderadores

Descifrando un Script

Notapor asdru » Vie Oct 26, 2012 6:37 pm

Vamos a intentar descifrar el script de la locomotora de DutchRail NS1300 para usarlo como ayuda a todos los diseñadores y en especial para aprovechar el funcionamiento de su regulador en el proyecto de japonesa en el que me he embarcado.

Que cada usuario que quiera aporte sus conocimientos o dudas para entre todos llegar a controlar un poquito en ésto del scripting lua

Si os parece nos saltamos la declaracion de variables ( aunque tengo dudas sobre muchas de ellas, sobre todo las globales )

Lo primero que nos encontramos y que no he tenido mucho problema para descifrar es la funcion checkstuurstroom:

Código: Seleccionar todo
function Checkstuurstroom ()

   stuurschakelstatus = ( Call("*:GetControlValue", "stuurstroom", 0) )
   stuurvolt = ( Call("*:GetControlValue", "StuurstroomVolt", 0) )

   if stuurschakelstatus == 1 then
      if stuurvolt < 600 then
         stuurvolt = stuurvolt + 3
         Call("*:SetControlValue", "StuurstroomVolt", 0, ( stuurvolt ) )
      end
   end

   if stuurschakelstatus == 0 then
      if stuurvolt > 0 then
         stuurvolt = stuurvolt - 2.5
         Call("*:SetControlValue", "StuurstroomVolt", 0, ( stuurvolt ) )
      end
   end

end
Imagen
Avatar de Usuario
asdru
 
Mensajes: 1049
Registrado: Mar Mar 09, 2004 8:50 pm
Ubicación: Un dia en Madrid y otro en Pamplona

Re: Descifrando un Script

Notapor asdru » Vie Oct 26, 2012 6:49 pm

Intento explicar lo que creo entender:

Lo primero que hace es llamar a los valores del "stuursroom" o control de baterias on y del stuursroomvolt o valor del voltaje de las baterias y almacenarlos en las variables stuurschakelstatus y stuurvolt .

Despues mediante un if, declara que si el valor del control de las baterias es igual a 1( boton arriba ) y si el valor de voltaje es menor a 600 entonces aplica un crecimiento de +3 al voltaje.

Esto entiendo que hace que el voltimetro suba despacio hasta el valor 600

y si el valor del control de baterias es igual a 0 ( boton de panto abajo ) y si el voltaje es mayor de 0 entonces aplica una deceleracion -2.5 al control de voltaje.

Basicamente para que la aguja del voltimetro de las baterias suba o baje progresivamente en funcion al mando de baterias arriba o abajo,.

Que los expertos me corrijan si me equivoco en algo. :oops:
Imagen
Avatar de Usuario
asdru
 
Mensajes: 1049
Registrado: Mar Mar 09, 2004 8:50 pm
Ubicación: Un dia en Madrid y otro en Pamplona

Re: Descifrando un Script

Notapor RTP » Vie Oct 26, 2012 7:29 pm

Es correcto.
Pero habría que conocer la frecuencia de ejecución de este script para saber realmente como varían estos valores.
De hecho, creo que esta frecuencia establece la constante de tiempo fundamental del sistema.

Por cierto, para revisar programas con indentado os recomiendo el
Notepad++
que es un editor potentisimo y gratuito del grupo GNU
y es perfecto para seguir la pista a paréntesis y demás líos de todos estos programas.

Saludos.
Avatar de Usuario
RTP
 
Mensajes: 456
Registrado: Mar Ene 01, 2008 8:59 pm
Ubicación: BCN

Re: Descifrando un Script

Notapor HANNIBAL SMITH 2 » Vie Oct 26, 2012 10:48 pm

Si la frecuencia de ejecución es un problema siempre se puede crear un temporizador...
ME ENCANTA QUE LOS PLANES SALGAN BIEN
Avatar de Usuario
HANNIBAL SMITH 2
 
Mensajes: 282
Registrado: Sab Sep 08, 2012 8:06 pm

Re: Descifrando un Script

Notapor RTP » Vie Oct 26, 2012 11:58 pm

Antes de profundizar en estas cosas, y si no estáis familiarizados con programación en tiempo real,
como autómatas programables, robotica, os aconsejo que os estudiéis uno sencillo como puede ser el
SIEMENS Simatic-1200 , en particular la programación SCL.

El script reseñado tiene una programación descuidada: el valor de la batería puede alcanzar valores
negativos, lo cual conduce a pequeños errores de representación, y si en algún otro sitio se
comprueba si este valor es cero o no, el resultado sera que no con consecuencias impredecibles.

Estos valores nunca bajan linealmente, una aproximación mejor seria algo del estilo
Bateria = Bateria * 0.8;
Si Bateria < 1 entonces Bateria = 0;
Que es una aproximación asintotica, de ahí el IF de cierre.

Y esto no es mas que una gota de un mar.

Saludos y aspirinas.
Avatar de Usuario
RTP
 
Mensajes: 456
Registrado: Mar Ene 01, 2008 8:59 pm
Ubicación: BCN

Re: Descifrando un Script

Notapor HANNIBAL SMITH 2 » Sab Oct 27, 2012 1:47 am

Yo he programado S-300 y 400, normalmente en AWL. Aunque parezca mentira me gusta programar en AWL, sacándole todo el jugo a la maquina :mrgreen:

Un manual de programación en SCL, bastante detallado, que por manuales no será en esto de los autómatas...
http://cache.automation.siemens.com/dnl/Dc1NzU5OQAA_1137188_HB/SCLV4_e.pdf

El manual es mejor leerlo globalmente, no sirve de nada profundizar a menos que te quieras poner a programar un automata de siemens.
ME ENCANTA QUE LOS PLANES SALGAN BIEN
Avatar de Usuario
HANNIBAL SMITH 2
 
Mensajes: 282
Registrado: Sab Sep 08, 2012 8:06 pm

Re: Descifrando un Script

Notapor RTP » Sab Oct 27, 2012 2:11 am

Aunque parezca broma cuando leáis el manual, el 1200 es un autómata sencillo.
De ahí el recomendarlo.
Un programa, escrito en cualquier lenguaje, no es mas que la descripción detallada de un proceso,
sujeta a unas reglas estrictas.
De modo que, SI UNO NO CONOCE EL PROCESO, es inútil leer el programa.
El SCL es lo bastante genérico, como para que todos los lenguajes estructurados de
programación en tiempo real se le parezcan.
Por cierto, en un programa industrial serio ( o sea que funciona y se vende )
las verificaciones, seguridades, controles, alarmas...
ocupan entre el 20% y el 50% del volumen de la programación.
Esto hay que tenerlo muy en cuenta a la hora de descifrar un programa ajeno.

Saludos y suerte.
Avatar de Usuario
RTP
 
Mensajes: 456
Registrado: Mar Ene 01, 2008 8:59 pm
Ubicación: BCN

Re: Descifrando un Script

Notapor asdru » Sab Oct 27, 2012 8:19 am

No sé ni que contestar...me he perdido por completo... :oops:

¿Necesito saber todo eso para poder compreder el script del que hablamos?

Me parece que os quedais sin japo...
Imagen
Avatar de Usuario
asdru
 
Mensajes: 1049
Registrado: Mar Mar 09, 2004 8:50 pm
Ubicación: Un dia en Madrid y otro en Pamplona

Re: Descifrando un Script

Notapor blas_dani » Sab Oct 27, 2012 8:51 am

Hola Asdru:

Sobre los script lua, yo estuve trabajando en una idea y realmente el quid del asunto está en entender en primer lugar el funcionamiento de los mismos.

El script es propio de cada unidad. Durante el juego se van sucediendo mensajes (OnConsistMessage) que cada script puede o no interpretar según se programe.
Hay mensajes definidos en el simulador y tambien puedes crear custom, a base de definirte una etiqueta propia.

El timing es importante. Repo nos sugirió un esquema de timing que no depende de los frames, sino del reloj del sistema. Es más exacto e incluso más fácil de entender.

Te pongo un esquema general de como tenia estructurados los scripts de mi invento.

Primero puedes ver la definición de una etiqueta, en este caso un identificador para un mensaje propio
La función initialise es la que se ejecuta el principio y la que lanza el script; allí se inicializan las variables, como poner a cero el timing.
La funcion update es el 'corazón del script'. Cada 'x' tiempo se hacen cosas. Normalmente las cosas que se hacen llevan al envio de mensajes (CallSendConsistMessage) tanto del core como los propios.
Luego esta la función OnConsistMessage que es la que recibe todos los mensajes durante la ejecución del escenario. Evidentemente, tu script sólo actuará frente a un mensaje si tu has programado en el script que reponda a ese mensaje.

En esencia, un script es esto.

Tu ahora mismo estás intentando analizar una función y si, creo que las has interpretado correctamente. Aunque quizá primero deberias ver como y cuando se empieza a llamar a la función y los mensajes ligados a ella.



PD: El mayor problema que tenemos es que no disponemos de manual sobre qué mensajes y qué funciones del core hay y que hacen exactamente.

Saludos y ánimo!

Código: Seleccionar todo
MIMENSAJE = 14071967001   ponemos un valor (mi fecha de cumple + 001)
             
function Initialise ()

     Declaro variables

     gTiempoNuevo = 0
     Call("BeginUpdate")    pongo en marcha el script
end


function Update (time)

  compruebo de cosas, llamadas a funciones, etc
 
  gTiempo = Call ("*:GetSimulationTime",0 )     
 
  if gTiempo > gTiempoNuevo then

        cambio variables, compruebo cosas, envio mensajes propios

        Call("SendConsistMessage", MIMENSAJE, "VariableX", 0)

        gTiempoNuevo = gTiempo + 0.25    (con esto controlo cada cuanto compruebo cosas, en este caso cada .25 seg)

  end
end


function OnConsistMessage ( msg, argument, direction )
   
    if msg == MIMENSAJE then    hago cosas         
    end
end
Avatar de Usuario
blas_dani
 
Mensajes: 2863
Registrado: Jue Sep 11, 2003 1:00 pm
Ubicación: Barri de Gràcia. Barcelona

Re: Descifrando un Script

Notapor Repo » Sab Oct 27, 2012 9:55 am

Así es Asdru, parece que cada cual va sacando adelante su propia experiencia en programación y así es bien difícil enfocarnos en lo que nos interesa, que no es nada más que las posibilidades que el lenguage LUA nos da (la única en realidad) para poder conseguir alguna semejanza descente entre una locomotra real y el modelo que se pretende hacer para el simuador.

De partida te digo que equivocas el planteamiento de discusión respecto al script. Acá no se trata de entender o interpretar una rutina en particular, como la que tú has mostrado. Lo que necesitamos entender es como se usa el LUA para hacer conseguir cosas en TS2013.

Para empezar, tenemos que entender las funciones propias de un script del simulador.

En el script para locomotoras tenemos dos funciones imprescindibles, que al final son las más útiles. "Initialise" y "Update".

La función "Initialise" solo corre o se ejecuta al principio una sola vez y es donde debemos declarar las variable de inicio, luego estas variables podrán cambiar, pero mientras tanto, acá podemos establecer valores con los que queremos empezar, es un poco como determinar el valor "default" de los controladores en el engine blueprint, la diferencia es que acá podemos establecer los valores originales de las variables.

Por otro lado la función Update se ejecuta por cada frame del simulador, los frames del simulador son nuestra real unidad de tiempo, no el tiempo real. Cada PC, dependiendo de su hardware, irá en más o menos frames por segundo, eso lo sabemos todos, la función Update se repetirá una vez por cada frame, es decir, acá es donde tenemos que poner las rutinas que representen cambios durante la simulación. Si ponemos dentro de la función Update una condición del tipo "If" entonces esa "pregunta" se repetirá en cada frame del simulador, y eso es bueno si queremos que ante un cambio en algun valor esa condición "If" la registre y haya alguna reacción correspondiente.

Otra cosa importantísima es conocer como obtengo o leo y como establezco o escribo el valor de un controlador.

Un controlador puede tener distintos valores en el tiempo, y tú puedes conocer el valor actual de este controlador y además puedes modificar, cambiar y establecer un nuevo valor para ese controlador.

Para conocer el valor del controlador se usa la siguiente frase:
Código: Seleccionar todo
Call("GetControlValue", "NombredelControlador", 0)
y esto se debe asignar a una variable como en:

Código: Seleccionar todo
gMiVariable = Call("GetControlValue", "NombredelControlador", 0)


Si uno coloca esto dentro de la función Update, la variable llamada "gMiVariable" valdrá lo mismo que el valor del controlador en cada frame del simulador.

Luego, uno puede traspasar el valor de la variable llamada "gMiVariable" a otro controlador, para aquello se debe usar:
Código: Seleccionar todo
Call("SetControlValue", "NombreDelOtroControlador", 0, VALOR)
o lo que es lo mismo:
Código: Seleccionar todo
Call("SetControlValue", "NombreDelOtroControlador", 0, gMiVariable)



Supongamos que tengo dos controladores llamados, por ejemplo, "Regulator" que es el que realmente da tracción a una locomotora y otro que hemos inventado llamado "VirtualThrottle" al cual hemos asignado el movimiento de la palanca de aceleración.

Si queremos que la palanca transmita el mismo valor de la palanca al controlador real deberiamos poner en la función Update lo siquiente:

Inventamos una variable que llamaremos "gVinculo"

Entonces:

Código: Seleccionar todo
gVinculo = Call("GetControlValue",  "VirtualThrottle", 0) -- acá estamos poniendo el valor de controlador VirtualThrottle en la variable llamada "gVinculo"


Luego hacemos el traspaso del valor así:

Código: Seleccionar todo
Call("SetControlValue", "Regulator", 0, gVinculo) -- acá estamos dándole un valor al controlador llamado "Regulator"
¿Qué valor? El valor que ya habiamos asignado a esa variable, es decir el valor del controlador "VirtualThrottle".


No se si decir lamentablemente o afortunadamente, para manejar estas cosas, se debe hacer muchos experimentos y practicar mucho, ojalá, en locomotoras de prueba para ver como ir pasando los valores de un controlador a otro. Un buen ejercicio, que yo usé al principio para entender este funcionamiento fue hacer sonar el silbato de la locomotora si otro valor cualquiera era en algun momento igual a 1.

Por ejemplo la siguiente rutina:


Código: Seleccionar todo
Function Update (time)

   If Call("GetControlValue", "Sander", 0) == 1 then
       Call("SetControlValue", "Horn", 0, 1)
   end

end


Al poner esta simple rutina dentro de la función Update, tal y como está puesta en el ejemplo, se consigue que cada vez que el arenador, es decir el controlador llamado "Sander" este activo, o sea, tenga el valor: 1, entonces el valor del controlador llamado "Horn" será también 1. En definitiva, cada vez que se active el arenador, sonará el silbato.

Bueno, quizá me fui a lo muy básico, pero es que creo que es imposible hacer un buen script sin saber estas cosas básicas. Me gustaría seguir mostrando más ejemplos de como funcionan estas cosas básicas, para luego ir complicándolo todo mucho más. Con los conceptos básicos aprendidos luego se puede hacer lo que uno quiera, solo hará falta la creatividad.

Digánme qué opinión les merece estas líneas que he escrito, si son útiles y oportunas, en base a eso veremos si seguimos con otros ejemplos.

Saludos.

Ricardo.
Imagen
Avatar de Usuario
Repo
 
Mensajes: 1198
Registrado: Mar Oct 11, 2005 4:27 pm
Ubicación: Santiago de Chile

Re: Descifrando un Script

Notapor Bermúdez » Sab Oct 27, 2012 10:19 am

Repo escribió:Digánme qué opinión les merece estas líneas que he escrito, si son útiles y oportunas, en base a eso veremos si seguimos con otros ejemplos.

Para los profanos en la materia como yo, útiles no, utilísimas. :ok: :app: :app: :app:
Un saludo. :wink:

https://ferrosim.es - Foro y descargas para TS2020
Avatar de Usuario
Bermúdez
 
Mensajes: 4062
Registrado: Sab Nov 03, 2007 1:22 pm
Ubicación: Teruel, Aragón, España

Re: Descifrando un Script

Notapor 444.518 » Sab Oct 27, 2012 12:01 pm

Yo creo que el 'script' de la NS1300 es bastante complejo para aprender. Es mejor empezar por cosas algo más sencillas, como el manejo de los controles de la locomotora y los valores que se pueden modificar para obtener un resultado apetecido.

Repo indica perfectamente la esctructura del 'script' con las funciones más importantes. Partiendo de este punto, se pueden empezar a diseñar diversas funcionalidades. Por ejemplo, se puede conseguir fácilmente poner un arenero automático cuando la locomotora comience a derrapar:

Código: Seleccionar todo
if Call( "*:GetControlValue", "Wheelslip", 0 ) > 1.1 then -- comprueba el control de derrape de la locomotora. Si es mayor que 1.1

Call( "*:SetControlValue", "Sander", 0, 1) -- activa el arenero

end


O un sistema de frenado combinado:

Código: Seleccionar todo
controldefreno = Call( "*:GetControlValue", "TrainBrakeControl", 0 ) -- carga en la variable controldefreno el valor del freno de tren

Call( "*:SetControlValue", "DynamicBrake", 0, controldefreno ) -- lo aplica en el freno dinamico


Un control de potencia usando el inversor como controlador. Es necesario poner al inversor unas muescas, pero no es muy difícil:

Código: Seleccionar todo
regulador = Call( "*:GetControlValue", "VirtualThrottle", 0 ) --carga en la variable regulador el valor de 'VirtualThrottle'

inversor = Call( "*:GetControlValue", "Reverser", 0 ) --carga en la variable inersor el valor del inversor

if inversor < 0 then

inversor = inversor * -1 -- esto evita que haya valores negativos al estar el inversor en marcha atrás

end

regulador = regulador * inversor -- multiplica los dos valores

Call( "*:SetControlValue", "Regulator", 0, regulador ) -- aplica la variable regulador al control Regulator de la locomotora



Lo importante es conocer siempre los controles y sus valores, haciendo que unos puedan interactuar con otros. Estas cosas de aquí arriba son muy sencillas, pero pueden transformar el comportamiento de una locomotora.
Un saludo, J.
Imagen
El problema de tener una mente abierta, es que la gente se empeña en llegar y tratar de poner cosas dentro.
-- Terry Pratchett
Avatar de Usuario
444.518
 
Mensajes: 1251
Registrado: Mar Jun 28, 2011 7:05 pm
Ubicación: Hospital de Móstoles

Re: Descifrando un Script

Notapor Repo » Sab Oct 27, 2012 12:50 pm

Bien 444.

Con toda seguridad Asdru podrá pensar: "todo esto está muy bien, pero todavía no veo nada a que pueda echar mano para conseguir todas las posibilidades de tracción que necesito para la 269". :mrgreen:

Y no lo culparía por pensar así, pero es que la alternativa sería construirle el script entero. No hay una formula mágica para hacer estas cosas, se debe partir por lo básico y en base a ello desarrollar lo que uno desea conseguir. Lamentablemente yo soy muy malo escribiendo tutoriales, me encantaría hacer con este asunto de los scripts LUA lo mismo que Pere hizo con sus tutoriales para aprender del 3D max, pero realmente me cuesta crear una escala de prioridades, enseñar desde lo básico a lo complejo, desde lo general a lo particular. Por lo pronto, si me ciñera a la forma como yo aprendí a crear scripts tendría que pedirles que cada cual hiciera una locomotora muy simple, no importa si se trata de una caja con ruedas de colores, y usarla unicamente para experimentar con su "engine script". Debería tener a lo menos los controles básicos como "Regulator", TrainBrakeControl", "Horn", "Startup" etc, etc, etc.

¿Alguno de los que hace acá material rodante podría ser tan amable de crear una locomotora con solamente lo básico para ir aprendiendo de scripts? Bastaría con una caja y sus bogies y enganches , todo muy simple, en colores puros, sin detalles ni nada parecido. Sólo útil para ir haciendo pruebas con algún script que podemos ir haciendo todos a la vez para aprender. Si alguien se anima a crear un "artefacto rodante" que sirva solo para hacer estas pruebas yo estoy dispuesto a que vayamos juntos escribiendo el script para que haga cosas interesantes.

Esa es mi propuesta, a ver si alguien me sigue en esto.

Saludos.
Imagen
Avatar de Usuario
Repo
 
Mensajes: 1198
Registrado: Mar Oct 11, 2005 4:27 pm
Ubicación: Santiago de Chile

Re: Descifrando un Script

Notapor blas_dani » Sab Oct 27, 2012 1:19 pm

Repo,

Si nos remontamos a los Developer docs de RailSimulator, allà tenemos un ejemplo de locomotora elèctrica, que podria servir.

Para la gente que no modela, se podria compilar, hacer el rwp y ponerlo en descargas (aunque al ser algo dado por RS, no sé si seria correcto ponerlo en descargas). En cualquier caso, se podria colgar en este hilo del foro, no en descargas, como ejemplo a seguir.

Saludos.
Avatar de Usuario
blas_dani
 
Mensajes: 2863
Registrado: Jue Sep 11, 2003 1:00 pm
Ubicación: Barri de Gràcia. Barcelona

Re: Descifrando un Script

Notapor Repo » Sab Oct 27, 2012 1:24 pm

blas_dani escribió:Repo,

Si nos remontamos a los Developer docs de RailSimulator, allà tenemos un ejemplo de locomotora elèctrica, que podria servir.

Para la gente que no modela, se podria compilar, hacer el rwp y ponerlo en descargas (aunque al ser algo dado por RS, no sé si seria correcto ponerlo en descargas). En cualquier caso, se podria colgar en este hilo del foro, no en descargas, como ejemplo a seguir.

Saludos.


Excelente idea.
Imagen
Avatar de Usuario
Repo
 
Mensajes: 1198
Registrado: Mar Oct 11, 2005 4:27 pm
Ubicación: Santiago de Chile

Siguiente

Volver a LUA Scripting RW

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados