How to use Trainstatic simulator on Windows

Hi Serge,

your layout is really cool and I like the way you are experimenting with Lua scripting.
Complex things can be achieved with a bit of creativity!

@reinder to mitigate on_tick() callback hang problem I suggest we allow registering timers.
In this example Serge wants to wait 5 ticks before departing again, instead of checking repeatedly the on_tick() callback, we could pass the time delta or deadline time to Traintastic C++ side and have it callback Lua only once timeout expires.
This then translates directly to a boost::asio timer which if useful could be made cancellable by Lua too and of course on script end/stop every associated timer gets canceled.

About train stopping at red signal, this is an interesting topic, if we go for automatic driving throttle or mixed driving throttle (like manual driving but speed limits automatically enforced by Traintastic or by Lua), then this would remove the deceleration part from having to be implemented in each Lua script manually.

Of course real life railway signalling has greater block lengths and train braking rate are way lower than model trains so mapping real signalling behavior to model layout is challenging.
If needed we could have the concept of “ghost” signal, not shown on the layout but trains react to it.
For my project of Padua station simulation I’m considering implementing ghost signals in simulator.

About this, I see 2 options:

  • Putting a small resistor glued to wagon’s wheel and axle, over the isolated joint.
  • Considering virtual occupation on Traintastic based on direction, known train lenght, available sensors etc. (I really like this challenge)

Well actually I think there is a way.
If you just need to communicate simple data, you can create a virtual turnout, maybe with DCC extended output so it can have 256 state values.

From one script you control the turnout, from the other you listen to state change event.
Then maybe have a turnout which does the opposite to do a sort of “reply” message back to first script.

An example would be:

  • Train script wants to depart from Station A, asks readiness by setting turnout fake#1 to thrown
  • Station A script reacts, sets points, asks next station, plays sound voice, level crossing, anything really… When done, it switches turnout fake#2 to say “I’m ready”
  • Train script acknowledges and actually starts the train, then resets fake#1 turnout.
  • Station A script reacts again by resetting turnout fake#2

This way you achieve a separation between Train driving logic and Station path logic.
Furthermore each station could have it’s own script, and when it’s platform tracks are full, not only it will not accept new train, it could be programmed that previous station does not even let trains depart. This way you handle traffic on single track railway by asking to send a train and prevent front collisions if both station send a train at same time.

Actually Traintastic path reservation spans across entire layout so there is not really a concept of “station A” and “station B” etc, it’s more used in modular layouts like FREMO where each station has a telephone and must call next station before sending train on single track lines.

Hi, why not keeping the start number and increase the number column while also deleting old entries? Sometimes if many messages of same type come together it can be useful to see message number increasing.

That could be an option too, still think it is a bit waste of screen space, the timestamp already increases.

@reinder to mitigate on_tick() callback hang problem I suggest we allow registering timers.

Yes I agree, that crossed my mind to, basically you need two types, a one shot timer and an interval timer. Technically is it not hard with a boost asio timer, the hard(er) part is the Lua side, how do we expose it to the end user. Over time Lua will get more and more features, the challange is to keep it structured and not become a mess.

Well actually I think there is a way.
If you just need to communicate simple data, you can create a virtual turnout, maybe with DCC extended output so it can have 256 state values.

This is a really bad hack…it a creative workaround I must say :slight_smile:

Let’s zoom out a bit: What is the main issue here? Is it the lengthy script? The need for enabling/disabling some scripts while other need to communicate with eachother?

I’m not against inter-script communication, if it has a proper use-case I’m in. If the reason is splits script so it is easier to maintain I’m not a fan.

Currently a script is just a single “page”, another option could be to make multiple tabs (with labels), when running the script, just glue them together to and run it in a single sandbox.

If we need inter-script communication I think the producer/consumer pattern is useful, something like:

Script 1:

local ready = xyz.publish_bool('i_am_ready', false)

ready = true

Script 2:

local is_he_ready = xyz.consume('i_am_ready', 
  function (value)
    log.debug('changed', value)
  end)

log.debug('current value is', is_he_ready.value)

xyz is a global, which needs a proper name. Besides bool it can also support other (simple) types.

Greetings,
Reinder

I knew you’s like it :rofl: .

Well since I’ve never did complex script yet I can’t say. Maybe dividing scripts in many small parts helps reuse same script? But still we do not allow launching “generic” script with custom environment arguments so you cannot have yet a generic script.

As in sharing own script in the internet, one can always edit it, or take just the part of interest so yes, long scripts are not bad.

On website I read you would like to support modular layouts, now that could change somethin, as stations by different peoples will have different scripts so they can operate independently but might need communication to operate tied togheter?

I really like the consumer approach, it would allow having front end script, multiple similar backend scripts abstracted by a bunch of variables, then based on which backed you start it operates differently. For example generic frontend, then multiple backends based on epoch.