Elvas Tower: Scriptable train control system - Elvas Tower

Jump to content

Posting Rules

All new threads will be started by members of the Open Rails team, Staff, and/or Admins. Existing threads started in other forums may get moved here when it makes sense to do so.

Once a thread is started any member may post replies to it.
  • 32 Pages +
  • 1
  • 2
  • 3
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic

Scriptable train control system Rate Topic: -----

#1 User is offline   gpz 

  • Superintendant
  • Group: Status: Elite Member
  • Posts: 1,772
  • Joined: 27-October 12
  • Gender:Male
  • Location:Budapest
  • Simulator:OpenRails
  • Country:

Posted 29 January 2014 - 02:51 PM

I opened this topic as a followup of of this older one.

I tried to implement a scripting framework (X1970) as suggested by James in this post. I would ask if I understood it well, and if the approach I made is right. And I am also curious what do you think about it, especially the lead developers. Should we go this way, or the scripting should be handled totally differently?

I attach a simple test script as well, that can be dropped into any locomotives \Script subdirectory in the Trainset folder (e.g. TRAINS\TRAINSET\ACELA\Script), and referenced in the corresponding eng file as "ORTSTrainControlSystem( EBICAB )". It implements almost the same currently, as the standard MSTS train control system, it is here just for an example.

I assume the scripting implementation might be far from perfect yet, but please keep in mind that this is the first time in my life I try to write such a thing. :sign_thanks:

deleted: EBICAB.zip

Edit: I removed the auto-prefixing of the script with namespace information, so the old script will not work. But attached the new script here:
Attached File  EBICAB_X1987.zip (1.58K)
Number of downloads: 721

#2 User is offline   PA1930 

  • Foreman Of Engines
  • Group: Status: Contributing Member
  • Posts: 782
  • Joined: 16-December 12
  • Gender:Male
  • Simulator:-
  • Country:

Posted 29 January 2014 - 03:43 PM

Well yes, it is a nice start for now Peter!
Back when Carlo wrote some special code for EBICAB testing with a specific RunActivity.exe file, the system was almost near perfect, and it had already some more further adjustments to it. :sign_thanks:
I like this idea a lot, and when I first saw it on the new experimental versions I thought already about making such a script...
But unfortunatly, speaking for myself, I do not understand how to compile or make such codes/scripts... (Yeah, I did give a look to the file too).

#3 User is online   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,490
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 30 January 2014 - 12:10 AM

A cursory look over the code seemed to be fine, though I think the diff was a bit confused about how you'd split TrainControlSystem into two classes. I'm also a little concerned we're introducing this stuff too early... but then again, if this stays absolutely nailed down to just the TCS (i.e. doesn't get access to anything else) it's probably fine. Just need to warn anyone writing a script that it can, and will, break during development. :aggressive:

#4 User is offline   Csantucci 

  • Member, Board of Directors
  • Group: Status: Elite Member
  • Posts: 6,996
  • Joined: 31-December 11
  • Gender:Male
  • Country:

Posted 30 January 2014 - 12:35 AM

Peter, I'm happy you started working on it! I fear a bit that the scripting approach will reduce amount of people able to provide contents, but for sure it is the most powerful and flexible approach. That's the time I will need to study C# seriously...
Do you plan to take into account on board subsystem and on earth subsystem in a modular way?

To Pedro: it's Peter who wrote the special code, I only built it for you :aggressive:

#5 User is offline   roeter 

  • Vice President
  • Group: Status: Elite Member
  • Posts: 2,424
  • Joined: 25-October 11
  • Gender:Male
  • Country:

Posted 30 January 2014 - 01:45 AM

Peter,

you rather over-simplified things when it comes to speed control.
The way you have set up the speedlimit values brings back the old MSTS problem that speed rises are activated immediately as the leading engine passes the signal or speedpost.
Depending on the actual system, that might be wrong - the rise in speed is valid only when the rear of the train passes that location, and some systems (most certainly the more modern systems) take this into account. There should be a script parameter reflecting this, i.e. whether the systems shows the speed immediately or at the proper moment.
For overspeed control as such, you should always use the proper value related to the full train.

For these systems, you should not take speeds directly from signals or speedposts, but use these train variables :
        public float AllowedMaxSpeedMpS;                 // Max speed as allowed
        public float allowedMaxSpeedSignalMpS;           // Max speed as set by signal
        public float allowedMaxSpeedLimitMpS;            // Max speed as set by limit


These are updated according to the position of the complete train with regards to all speed indicators (signals and speedposts) along the way.
For overspeed detection you only should check against AllowedMaxSpeedMpS, which is properly updated according to the train position.

Another point is that speed limits set by signals never overrule line speed limits as set by speedposts. The method you use, this_signal_speed, gives the allowed speed as set in sigcfg.dat for that signal, regardless of line speed limits.
Therefor, you should not use the this_signal_speed method to determine the speed. Instead, you should use the variable actual_speed of the first signal-entry in SignalObjectItems, which is set according to the line speed limit.

Regards,
Rob Roeterdink

#6 User is offline   gpz 

  • Superintendant
  • Group: Status: Elite Member
  • Posts: 1,772
  • Joined: 27-October 12
  • Gender:Male
  • Location:Budapest
  • Simulator:OpenRails
  • Country:

Posted 30 January 2014 - 06:16 AM

View PostJames Ross, on 30 January 2014 - 12:10 AM, said:

I think the diff was a bit confused about how you'd split TrainControlSystem into two classes.

Might be because of practically I rewrote the whole file, because I rebasedthe previous MSTSTrainControlSystem onto the new scripting code. Now it uses the same API as is exposed to the scripts, just it is built in.

View PostJames Ross, on 30 January 2014 - 12:10 AM, said:

if this stays absolutely nailed down to just the TCS (i.e. doesn't get access to anything else) it's probably fine. Just need to warn anyone writing a script that it can, and will, break during development. :aggressive:

The scripting framework itself is capable to drive any other area, now it is just a matter of defining a different API for the other stuff. However I'm not intended to drop it in elsewhere currently, but it is there if needed...

Certainly the TCS API is subject to change, so it is far not ready for production. I have a question here: How can the intellisense be exposed to script developers? Even if I add a script to the csproj, the "using ORTS.Scripting.Api;" and "namespace ORTS.Scripting.Script" entries should be there for this to work. Now these are added only at compile-time, as you suggested, to prevent the script-writers to access other namespaces and system services. It is a really good thing, but it disables the intellisense as well...

Rob,

Honestly I was a bit confused how to get the necessary data out of the scripting code, so thank you for clarifying it. I will modify that piece accordingly. Is this data available in all playing modes, so there is no need to trick with it?

#7 User is online   James Ross 

  • Open Rails Developer
  • Group: Status: Elite Member
  • Posts: 5,490
  • Joined: 30-June 10
  • Gender:Not Telling
  • Simulator:Open Rails
  • Country:

Posted 30 January 2014 - 06:29 AM

View Postgpz, on 30 January 2014 - 06:16 AM, said:

I have a question here: How can the intellisense be exposed to script developers? Even if I add a script to the csproj, the "using ORTS.Scripting.Api;" and "namespace ORTS.Scripting.Script" entries should be there for this to work. Now these are added only at compile-time, as you suggested, to prevent the script-writers to access other namespaces and system services. It is a really good thing, but it disables the intellisense as well...


That is indeed a problem. In fact, I think that we'll need more than just a namespace around the code, as I've just seen an example that has 'using' inside the namespace. Maybe we need to prevent access in some other way... I will have to think about it. Feel free to see what other people have done in other projects, so long as no incompatibly-licensed code is copied.

#8 User is offline   PA1930 

  • Foreman Of Engines
  • Group: Status: Contributing Member
  • Posts: 782
  • Joined: 16-December 12
  • Gender:Male
  • Simulator:-
  • Country:

Posted 30 January 2014 - 06:41 AM

View PostCsantucci, on 30 January 2014 - 12:35 AM, said:



Thanks Carlo, I didn't remember about it well.
My apologies Peter! :aggressive:

#9 User is offline   roeter 

  • Vice President
  • Group: Status: Elite Member
  • Posts: 2,424
  • Joined: 25-October 11
  • Gender:Male
  • Country:

Posted 30 January 2014 - 06:47 AM

View Postgpz, on 30 January 2014 - 06:16 AM, said:

Is this data available in all playing modes, so there is no need to trick with it?

AllowedMaxSpeedMpS is available in all modes, but SignalObjectItems is available in AUTO mode only.
One option to get all required details is to call Train.GetTrainInfo() - this returns an instance of class TrainInfo which holds all required data (and a bit more). This is the method which is used to 'fill' the TrackMonitor window, and is available in all modes.

Regards,
Rob Roeterdink

#10 User is offline   gpz 

  • Superintendant
  • Group: Status: Elite Member
  • Posts: 1,772
  • Joined: 27-October 12
  • Gender:Male
  • Location:Budapest
  • Simulator:OpenRails
  • Country:

Posted 30 January 2014 - 10:31 AM

Now looking at my code in details I would have some more questions regarding the signalling.

View Postroeter, on 30 January 2014 - 01:45 AM, said:

For these systems, you should not take speeds directly from signals or speedposts, but use these train variables :
        public float AllowedMaxSpeedMpS;                 // Max speed as allowed
        public float allowedMaxSpeedSignalMpS;           // Max speed as set by signal
        public float allowedMaxSpeedLimitMpS;            // Max speed as set by limit


These are updated according to the position of the complete train with regards to all speed indicators (signals and speedposts) along the way.
For overspeed detection you only should check against AllowedMaxSpeedMpS, which is properly updated according to the train position.

The script functions are delegated currently as follows:
Script.TrainSpeedLimitMpS = () => Locomotive.Train.TrainMaxSpeedMpS;
Script.CurrentSignalSpeedLimitMpS = () => Locomotive.Train.allowedMaxSpeedSignalMpS;

I should set up one more function to query the "CurrentPostSpeedLimitMpS", which should point to Locomotive.Train.allowedMaxSpeedLimitMpS. (Is it right?)
Is that also right, that if the minimum of the above three will be calculated, then it will be the same as your AllowedMaxSpeedMpS variable? (I'm afraid that one cannot be used, because the different speed limits need to be passed to TCS separately, because any of them might also be needed for various things there. Some systems, mostly the older ones, don't know about speed posts, some others can only consider signals, etc...)

View Postroeter, on 30 January 2014 - 01:45 AM, said:

Another point is that speed limits set by signals never overrule line speed limits as set by speedposts. The method you use, this_signal_speed, gives the allowed speed as set in sigcfg.dat for that signal, regardless of line speed limits.
Therefor, you should not use the this_signal_speed method to determine the speed. Instead, you should use the variable actual_speed of the first signal-entry in SignalObjectItems, which is set according to the line speed limit.

So you say I should remove the test
if (Locomotive.Train.IndexNextSignal >= 0 && Locomotive.Train.ControlMode == Train.TRAIN_CONTROL.AUTO_SIGNAL)
from my function UpdateNextSignalFunctions(), and in all cases use the
Script.NextSignalSpeedLimitMpS = () => Locomotive.Train.SignalObjectItems[Locomotive.Train.IndexNextSignal].actual_speed;
delegation? It would simplify things greatly! (But if I recall correctly, there were problems with it, and that's why the alternative method was introduced in the past. But now I will remove it, and will see. :good2: )

  • 32 Pages +
  • 1
  • 2
  • 3
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users