Rail3D*

   

 

Motive Power Depot



Introduction

Have you ever wanted to randomly vary the locomotives on your Rail 3D trains, but still want to make sure the train has the appropriate amount of motive power? This article discusses a scripted solution for a motive power depot.

1  Background

For a nice touch of realism to your layout, you might want to consider varying the locomotives on the front of any given train. This normally is quite difficult to achieve because it requires planning where each locomotive will be at any point in time, because the whole thing would have to have been orchestrated with complex route changing sequences.

Now we are able to take advantage of scripts to set train routes for us. The main benefit here is that a new route can be assigned to a train based on criteria other than its current route.

Written with multiple-locomotive trains in mind, this article demonstrates two things:

  1. Sorting locomotives from a terminating train into a depot/yard area.
  2. Retrieving various locomotives from the depot/yard to form the motive power for an originating train.

The yard, or, as I shall be referring to it in this article, the Motive Power Depot, is going to look like this:

Trains arrive from the left on the Arrival Road, and depart on the right on the Departure Road.

2  Arriving locomotives

2.1  Setting up the track

The arrival end of the motive power depot looks like this:

Things to note:

  • There are three location markers, marked in dark blue.
  • A Divider is shown in light blue. It is set to divide trains at “1″, and applies to trains on the “ArrivalLocos” route. The Front Route box should be set to mpdepot, and the Rear Route set to ArrivalLocos.
  • A dos (Drive On Sight) feature is located just after signal E, shown by a pale yellow dot.
  • Signal E is controlled.

2.2  Sorting arriving locomotives

For this to work well, you want to have locomotives sorted into yard roads in some sort of logical fashion. A good idea is to group locomotives with similar power capabilities. Typically this means that locomotives of the same class share the same road in the depot, but you might get two classes sharing the same road if their rated powers are similar or identical.

You can write the script so that the type of each locomotive is checked, but in Rail 3D this will mean lots of programming if you have multiple versions of the same locomotive (different liveries or minor design differences, perhaps). In my test layout, I have the following locomotive models:

Locomotive Type Power Rail 3D model
G Class 2460 kW au-Vic_G-fa
G Class_FA
G Class_VL
X Class 1460 kW X Class
T Class 820 kW T Class_FV
P Class 820 kW P Class_FA
P Class_VL
P Class_VLF

As you can see, there are multiple models of the same class, and some classes share the same power rating. I am going to allocate locomotives as follows:

Road Locomotive Type
No. 2 X Class
No. 3 T Class

P Class

No. 4 G Class

(No. 1 Road is the through-running road.)

To ensure each locomotive goes the right way, set the default route of the points 701, 702 and 703 as indicated in the diagram above. Then:

  • Points 701 should have mpdepot* specified for Other Route.
  • Points 702 should have mpdepot_X specified for Other Route.
  • Points 703 should have mpdepot_T, mpdepot_P specified for Other Route.

2.3 The script

I’ll go through the script in parts. The division of locomotives is done largely by the Divider alone. If you look carefully, the Divider cuts off one locomotive at a time, and the renames the rear route so that the process is repeated for the remaining locomotives.

First we have the Init() entry point:

Init()
{
	string ArrivingTrain="";
	string Location;
}

The ArrivingTrain variable will be used to store the route of the arriving locomotives while they are being sorted and uncoupled.

Next, we have the OnLocation() entry point. The first part is the declaration of variables that will be used to temporarily hold values of functions that aren’t properly evaluated when part of an if expression.

OnLocation()
{
	string LocoType;
	string Route;
	int Length;

	signal sigMPDepot2=Document.GetSigByID("2");
	signal sigMPDepot3=Document.GetSigByID("3");
	signal sigMPDepot4=Document.GetSigByID("4");

	LocoType=Train.GetNumber();
	LocoType=Left(LocoType,1);
	Route=Train.GetRoute();
	Length=Train.GetLength();

Note that LocoType gets the first character of the locomotive’s road number. In my case, this transcends whatever models I’m using for each particular locomotive class because all G class locomotives take a number from G511 to G543, all P class are P11 to P23, and so on. The class can then be more easily determined this way.

The next part stores the train’s route number when it arrives so that it can be reapplied to it later. For the purposes of dividing the locomotives, it’s much easier to use other route names instead of the train’s original route name:

	if(Location=="MPDepotArrival")
	{
		ArrivingTrain=Route;
		Train.SetRoute("ArrivalLocos");
	}

This last bit reassigns route names to the locomotives after they have been detached, but before they enter the motive power depot:

	if((Location=="ArrivalPoint")&&(Route=="MPDepot"))
	{
		Train.SetRoute("MPDepot_"+LocoType);
	}

	if((Location=="ArrivalPoint")&&(Route=="ArrivalLocos"))
	{
		Train.SetRoute(ArrivingTrain);
		ArrivingTrain="";
	}
}

The Divider assigns the route “mpdepot” to each locomotive it detaches, and the class letter is then appended to this by the script. We set up the points earlier to deal with sorting each class.

The last locomotive is not affected by the Divider since it is of length one. It simply passes the signal and is directed into No. 1 road.

2.4  The last locomotive

We could alter the script so that the last locomotive is also sorted like the other locomotives. However, when the time comes to get the locomotives out of the depot to make up the next train, you will need a locomotive from somewhere to initiate this. Locomotives in the depot cannot be given timetabled start times because we don’t know which service they will operate.

For this reason, the last locomotive is sent to No. 1 road, where you can route it elsewhere to a stabling point while it awaits the next timetabled departure time. (See the section entitled Pilot operation near the end of this article for a better solution for handling this.)

3  Departing locomotives

3.1  Setting up the track

The departure end of the motive power depot looks like this:

There are a few more notes this time:

  • There are three location markers, shown by blue dots.
  • There is a Reverse, which is to be labelled “DeparturePoint” and applies to all trains travelling from right to left.
  • There is also a Combiner, whose label is “Departure Road”. It applies to all trains on route “ContinueMarshalling”, and the New Route box should also be “ContinueMarshalling”. Also ensure that Reverse is set.
  • Four signals govern movements of trains from the yard area to the Departure Road. They are all controlled signals with the Hold flag set. Additionally:
    • Signal 1 has a Release for all routes attached to it. The Release is positioned between location marker “BeginMarshalling1” and Signal 1.
    • Signals 2, 3 and 4 all have the Shunt flag set, which allows departing locomotives to couple onto locomotives waiting on the Departure Road. You also need to place a Shunt track feature: I put it on the same node as the location “mpdepotExit”.

3.2  Overview

As mentioned earlier, the idea is that you keep a locomotive somewhere else until its timetabled departure time. When the time comes, the locomotive comes to the motive power depot to pick up however many other locomotives the train requires. It will arrive at the depot on No. 1 Road.

Upon passing the “BeginMarshalling” location markers, it will be reassigned a temporary route to aid the coupling process. A “queue” will be established (very similar to the level crossing “stacks” in Express Selection), which will detail exactly the locomotives that should be retrieved from the motive power depot, in a specific order and of specific quantity.

Locomotives get released from the motive power depot one by one until the consist is complete. The train will then have its original route name restored, and it will be free to leave via the Departure Road.

3.3  The script

Again, I’ll do this in parts.

First, we need to add some lines to the existing OnInit() entry point so that it looks like this:

Init()
{
	string ArrivingTrain="";
	string MarshallingTrain="";
	string MarshallingQueue="";
	string Location;

	// variables for temporary use
	int intTemp;
	string strTemp;
}

Next, we start adding more code to the end of the OnLocation() entry point section. This first part is called when a train passes “BeginMarshalling1”:

	if(Location=="BeginMarshalling1")
	{
		MarshallingTrain=Route;
		Train.SetRoute("ContinueMarshalling");
		if(MarshallingTrain=="0461")
		{
			MarshallingQueue="4";
		}
		else
		{
			MarshallingQueue="423";
		}
	}

The route name of the locomotive arriving via No. 1 Road (the “initial” locomotive) is stored in MarshallingTrain, while it has its route set to “ContinueMarshalling”.

Then comes the code for determining which locomotives are to be retrieved from the depot. In this example, train 0461 is scheduled to recieve a single locomotive from No. 4 road (as per the queue MarshallingQueue), which will be a G class locomotive. Train 0461 will then have two locomotives, the second of which will be the G class from the depot.

According to this example, all other trains are scheduled to be given three locomotives - firstly a locomotive from No. 4 Road, then one from No. 2 Road, and finally one from No. 3 Road. This will eventually yield a four-locomotive consist of the original locomotive, a G class, an X class and then either a T or a P class.

The next part of the code deals with retrieving the locomotives one by one:

	if(Location=="BeginMarshalling2")
	{
		intTemp=Len(MarshallingQueue);
		strTemp=Left(MarshallingQueue,1);
		if(intTemp==0)
		{
			// locos ready for departure
			Train.SetRoute(MarshallingTrain);
			MarshallingTrain="";
			MarshallingQueue="";
		}
		else
		{
			// release next loco
			if(strTemp=="2")
			{
				sigMPDepot2.SetHold(0);
			}
			if(strTemp=="3")
			{
				sigMPDepot3.SetHold(0);
			}
			if(strTemp=="4")
			{
				sigMPDepot4.SetHold(0);
			}
			intTemp=intTemp-1;
			MarshallingQueue=Right(MarshallingQueue,intTemp);
		}
	}

The basic idea of this part is that the variable MarshallingQueue is parsed character by character, and the signals on the corresponding roads in the depot are released as appropriate. As each locomotive comes out of the depot to join the consist, it passes the location marker mpdepotExit, where the following code is executed to restore the holds on signals 2, 3 and 4:

	if(Location=="MPDepotExit")
	{
		sigMPDepot2.SetHold(1);
		sigMPDepot3.SetHold(1);
		sigMPDepot4.SetHold(1);
	}

After coupling, the whole consist reverses to the reverse, where the queue is parsed for the next instruction. This section is in an OnReverse() entry point, but is identical to the previous code executed at BeginMarshalling2 except that the if statement checks for the location “DeparturePoint” instead of “BeginMarshalling2”.

OnReverse()
{
	if(Location=="DeparturePoint")
	{
		intTemp=Len(MarshallingQueue);
		strTemp=Left(MarshallingQueue,1);
		if(intTemp==0)
		{
			// locos ready for departure
			... (as before)
		}
		else
		{
			// release next loco
			... (as before)
		}
	}
}

Once the queue is empty, i.e. MarshallingQueue==“”, the train’s route is reverted to the route the initial locomotive had when it arrived via No. 1 Road, and it continues past the Combiner instead of waiting for any other locomotives.

3.4 More complexities you can add

If you’re really up for it, you can consider the following:

  • The initial locomotive’s type may be of importance, in which case the queue can be set accordingly. For instance, if the train requires a G class and an X class, the queue can be set to “4″ if the initial locomotive is an X class (this will retrive a G class from the depot), or to “2″ if it is a G class (this will retrieve an X class from the depot). This will ensure you end up with a G class and an X class — unless the initial locomotive is neither!
  • Although Rail 3D doesn’t have a Random function available for scripting purposes, you can invent other ways to produce variety; e.g. use the value of the GetSec() function to choose between two different queues, or have a counter counting something useless somewhere whose value is used to choose between different possible queues.
  • If a road at the depot for a particular type of locomotive is empty, then trains might not want to call for that particular type, otherwise they may be waiting a long time! It is possible to add code to only call on locomotives that are present.

3.5 Pilot operation

Nobody has said that the “initial” locomotive must form part of the departing train! If this locomotive is a yard pilot of some description, its job would be to come past the motive power depot, collect the required locomotives for a train and then drop them off somewhere. This way, it doesn’t matter what class the initial locomotive is, as it won’t be forming part of the train anyway.

The benefits with this type of operation is that the yard pilot can use Rail 3D’s diagramming feature to outline its marshalling tasks one by one. So long as it returns to a common starting point once it has finished each marshalling operation, its route will be updated according to a specific sequence.

4  Conclusion

Although this seems long and complex, you really only need to do it once on your layout (assuming you have one central location for this sort of thing). Once it’s set up, it works very well and is extremely versatile. You can request any combination of locomotives for any particular train, and the motive power depot is easily expanded to accommodate more roads and more locomotive types.

The only other two things to be aware of are:

  • A second train can currently arrive via No. 1 Road while the first train is collecting locomotives. This will disrupt the the first train, but can be easily avoided with some extra signals.
  • At present, variables are not saved when you close/open the layout, so any trains in the process of marshalling extra locomotives may be disrupted. This issue should be resolved soon.

David Morley (24 January 2007)



import