Railway sidings and train pathfinding

Post your ideas and suggestions how to improve the game.

Moderator: ickputzdirwech

rcombs
Manual Inserter
Manual Inserter
Posts: 4
Joined: Thu Apr 27, 2017 8:46 pm
Contact:

Railway sidings and train pathfinding

Post by rcombs »

The train pathfinding system in Factorio has confused me for quite some time, and I think I've figured out why: sidings don't work the way I'd expect them to (and it doesn't seem to be possible to make them work in quite the way I want, though I've found a method that comes close).

Take this image for example:
factorio-siding.png
factorio-siding.png (2.49 MiB) Viewed 354 times
This is a pair of sidings off of a long main line. The sidings have regular rail signals at their entry points, while the main line has only chain signals. What I'd expect is that trains would use the siding to wait if their path takes them past it, but they'd be blocked somewhere further ahead. Instead, sidings like this don't seem to be used only sporadically, with trains instead waiting to take a "lock" on their entire route at once, rather than accepting a path that makes forward progress and then stops at the siding. My understanding is that this is a quirk of the pathfinding algorithm: the main line is shorter (since it doesn't have the curves), so trains prefer to use it! This means that unless there happens to be a train in the block at the time, the main line will win the path cost check, and the train will attempt to take it, without considering the siding.

This leads to a workaround: have the "sidings" actually be bypasses, with the parking spots being on what looks like the main line!
working-pseudo-sidings.png
working-pseudo-sidings.png (2.46 MiB) Viewed 385 times
Trains do actually use these correctly, but they're pretty unintuitive (I haven't seen any documentation anywhere on this technique) and kinda unsightly. There's also one substantial issue with this approach: trains stopped at this kind of siding will only attempt to proceed to the next siding every 30 seconds (or 5 if there are multiple destination stations with the same name).

In some cases, the main line and siding are the same length (e.g. if building it into some kinds of turns), and then I have no idea what happens.

The common alternative we tend to see is this:
factorio-siding-no-chain.png
factorio-siding-no-chain.png (2.48 MiB) Viewed 385 times
In this pair, both the sidings and the main line use regular (non-chain) signals. This forces trains to make use of the sidings, but has a clear problem: it's possible for two trains to end up waiting side-by-side, with one on the main line and one in the siding. This violates a basic rule of railroading: don't park trains on the main line! We'd all prefer not to be CSX, so this is generally seen as a bad thing.
many-trains-stuck.png
many-trains-stuck.png (1.78 MiB) Viewed 385 times
Some players suggest using large "stacker" waiting areas at each station, but these take up a lot of space, particularly since each individual station generally needs its own. They also don't fully solve the "parking on the shared main line vs waiting to lock too large a mutex" problem like proper sidings do.

Ultimately, what I'd like is a way to tell the game that a given block is a siding (and what the associated main-line block is), so it can do something like this:
- First, attempt to pathfind with a small penalty applied to siding blocks (enough to overcome the length difference)
- If the route is clear and the train can proceed, go ahead
- Otherwise, search the route for mainline blocks with associated sidings, starting from the end and moving towards the train's current position
- For each such block, retry pathfinding with the siding-block penalty removed, and a corresponding penalty instead applied to the mainline block (enough to overcome a stopped train)
- Repeat backwards until either a route is found that allows the train to make forward progress, or all sidings on the route have been exhausted

Also, I'd want a repath to be triggered when any of the siding blocks along the current path become unoccupied, so trains don't end up waiting 30 seconds to make forward progress.

I do have one other issue with the current rail signaling system: there's no way to get efficient use of long mainline sections without using periodic non-chain signals, and non-chain signals mean you risk having trains park on your main line! This can be mitigated using the "bypass sidings" I described above, but it's inefficient to build those *everywhere* (in the extreme case, you end up basically quad-tracking with frequent crossovers). Take this example:
inefficient-line-usage.png
inefficient-line-usage.png (1.62 MiB) Viewed 385 times
Here we have a main line leading to two stations. There are periodic chain signals, but they don't really do anything; functionally they're just cosmetic. But they shouldn't have to be! Let's see it in action:



As we can see, there are two trains attempting to use the line to reach their respective stations. The first goes ahead, it has to get all the way to its destination before the second can depart. Non-chain signals would solve this, but also create risk of trains waiting on the main line! We can do better:
- First, run a check on the immediate following block, and turn red if it's occupied (as with non-chain signals)
- Then, check for any trains in the rest of the chain (as is done currently)
- Instead of setting the signal red if any exist, check if they have reserved a path that will allow them to exit the chain, and only turn red if they haven't

This would allow the second train to always follow the first one (behind by one signal) without needing to introduce potential points where trains could end up waiting on the main line in automated operation.

It's plausible that there might be some complex chain-signal application around intersections or loops that I'm missing where this solution would break something; if so, I could imagine this could be applied only to chain signals with a configuration setting applied, or to a new third type of rail signal.

This post ended up being pretty long and rambly, and I hope it makes sense to everyone! If nothing else, the "bypass siding" technique seems powerful enough as-is to be worth documenting on the wiki somewhere.
Attachments
inefficient-line-usage.mp4
(10.48 MiB) Downloaded 14 times
Last edited by rcombs on Thu Dec 19, 2024 8:31 am, edited 1 time in total.
mmmPI
Smart Inserter
Smart Inserter
Posts: 3954
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: Railway sidings and train pathfinding

Post by mmmPI »

rcombs wrote: Thu Dec 19, 2024 7:33 am My understanding is that this is a quirk of the pathfinding algorithm: the main line is shorter (since it doesn't have the curves), so trains prefer to use it! This means that unless there happens to be a train in the block at the time, the main line will win the path cost check, and the train will attempt to take it, without considering the siding.
One of the attachment has disappeared, but this seem correct understanding to me ( provided i'm not doing a mistake myself x) ).

There are other "quirks" that may help you with that : a dummy train stop, "adds" some distance to a lane for the pathfinding purpose. So if the main lane happens to have one, then it would have an extra "2000" tiles worth of distance, seemingly being worse than the siding in "lengh". ( https://wiki.factorio.com/Railway/Train_path_finding ).
rcombs wrote: Thu Dec 19, 2024 7:33 am Also, I'd want a repath to be triggered when any of the siding blocks along the current path become unoccupied, so trains don't end up waiting 30 seconds to make forward progress.
This is unlikely to happen for performance reason, repath are potentially extremly costly because it depend on the size of the player network and its efficency, which can be abysmal.
rcombs wrote: Thu Dec 19, 2024 7:33 am I do have one other issue with the current rail signaling system: there's no way to get efficient use of long mainline sections without using periodic non-chain signals, and non-chain signals mean you risk having trains park on your main line!
This depend on what you call "parking" or "efficent", if you use the "train limit" system, then train aren't supposed to park in the mainline, they would only be travelling when they have a destination available, thus they could "temporarily stop" to make room for another train, but won't "park" as in "stay there until further notice" in the main lane. That's the purpose of the stackers. Making sure only train with a valid destination, and thus no reason to "park" be on the move.
rcombs
Manual Inserter
Manual Inserter
Posts: 4
Joined: Thu Apr 27, 2017 8:46 pm
Contact:

Re: Railway sidings and train pathfinding

Post by rcombs »

mmmPI wrote: Thu Dec 19, 2024 8:13 am One of the attachment has disappeared
Ah, whoops! Fixed, thanks.
mmmPI wrote: Thu Dec 19, 2024 8:13 am a dummy train stop, "adds" some distance to a lane for the pathfinding purpose
I did consider this, but a dummy stop adds a penalty of 2000, which is much more than the penalty for a train waiting at a signal (starts at 100), so it ends up not working here.
mmmPI wrote: Thu Dec 19, 2024 8:13 am This is unlikely to happen for performance reason, repath are potentially extremly costly because it depend on the size of the player network and its efficency, which can be abysmal.
True, but repaths already happen when the destination station becomes not-full, and this case could be seen as an extension of that behavior.
mmmPI wrote: Thu Dec 19, 2024 8:13 am if you use the "train limit" system, then train aren't supposed to park in the mainline, they would only be travelling when they have a destination available
This isn't necessarily the case, as far as I can tell; the train can still be blocked behind a different train blocked by a full station. But if I set a train limit of 1 on everything, then I'd have latency problems: no train would ever be able to leave its origin station until its destination was free, and the whole point of these sidings is to allow trains to make progress even when their destination is busy, thus reducing their latency!
mmmPI
Smart Inserter
Smart Inserter
Posts: 3954
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: Railway sidings and train pathfinding

Post by mmmPI »

rcombs wrote: Thu Dec 19, 2024 8:39 am This isn't necessarily the case, as far as I can tell; the train can still be blocked behind a different train blocked by a full station. But if I set a train limit of 1 on everything, then I'd have latency problems: no train would ever be able to leave its origin station until its destination was free, and the whole point of these sidings is to allow trains to make progress even when their destination is busy, thus reducing their latency!
Well the idea here would be to have every station able to accomodate the number of train that needs to be "constantly" on the move for it to be supplied "should everything stop at some imaginary moment".

So that "prevent" the need to have stacker for ALL trains in front of "every" station.

You could have a station with a limit of 3 or 5 with enough room to "host" 3 or 5 trains. "Capping" the limit to the available "parking" place.

No train blocked by a "station full" should end up bloking "another train" ( with a different destination).

Obviousy in game, it's always "over-estimation", not "just the perfect number of trains", because when outpost deplete , some trains will require longer path, or "more train constantly running" to supply the same station as previously. But if you suddenly add 20 trains, they won't clog the existing stations whose limits are already set supposedly, as there is at least enough "room" for them somewhere outside the main line.

(the problem i see with sidings is that to me it look like a double main lane, with one dedicated to park, and no way to tell the game which one should be used as main lane and one as siding, whereas the other options involve counting/limiting trains, to make sure all trains that are in the "main lane" have the same purpose of "not even trying to stop", removing the need for the game to sort it out)
rcombs
Manual Inserter
Manual Inserter
Posts: 4
Joined: Thu Apr 27, 2017 8:46 pm
Contact:

Re: Railway sidings and train pathfinding

Post by rcombs »

mmmPI wrote: Thu Dec 19, 2024 8:53 am You could have a station with a limit of 3 or 5 with enough room to "host" 3 or 5 trains. "Capping" the limit to the available "parking" place.
Even adding dedicated waiting space for one train at each station at least doubles the amount of track it requires, and makes it very difficult to place multiple stations in close proximity along the same main line. Sidings avoid the need for any extra infrastructure dedicated to a given stop, and can be placed anywhere along the main line with at least one train-length of space 2 rail-widths to its side.
mmmPI wrote: Thu Dec 19, 2024 8:53 am the problem i see with sidings is that to me it look like a double main lane, with one dedicated to park, and no way to tell the game which one should be used as main lane and one as siding
That's what the bypass-sidings approach shown in working-pseudo-sidings.png solves! The inner track (which acts as the siding) has regular signals, while the outer track (the bypass) has only chain signals. This means that the game puts trains on the inner track by default (because it's shorter), and allows them to wait there (because of the non-chain signals), but trains can use the outer track to bypass a waiting train (because the waiting trains result in a penalty larger than the small difference in track length). I'd love for the game to be able to more explicitly tell the game what's main-line and what's siding, but for now, this solution does work pretty elegantly (except for the 30-second wait to advance to a later siding).
mmmPI
Smart Inserter
Smart Inserter
Posts: 3954
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: Railway sidings and train pathfinding

Post by mmmPI »

rcombs wrote: Thu Dec 19, 2024 9:21 am Even adding dedicated waiting space for one train at each station at least doubles the amount of track it requires, and makes it very difficult to place multiple stations in close proximity along the same main line. Sidings avoid the need for any extra infrastructure dedicated to a given stop, and can be placed anywhere along the main line with at least one train-length of space 2 rail-widths to its side.
I don't think that's the case.I think the amount of track can stays roughly the same if you use sidings or stackers, because the number necessary to "hold" the amount train would be similar. It could be pictured as where on the network they are located. It would probably require less rails to use stackers, because all sidings wouldn't be available for all trains at all time, whereas using stacker, trains are "forced" into the area in which they fit, and there is no "extra" area, like "free unused siding". Those are related to the size of the network, so potentially a lot of them for a small number of trains if you extend the network with blueprints containing sidings but do not add extra train stop.

( for multiple station you can have a common stacker if they don't require a full train lane of incoming train as throughput)
rcombs wrote: Thu Dec 19, 2024 9:21 am That's what the bypass-sidings approach shown in working-pseudo-sidings.png solves! The inner track (which acts as the siding) has regular signals, while the outer track (the bypass) has only chain signals. This means that the game puts trains on the inner track by default (because it's shorter), and allows them to wait there (because of the non-chain signals), but trains can use the outer track to bypass a waiting train (because the waiting trains result in a penalty larger than the small difference in track length). I'd love for the game to be able to more explicitly tell the game what's main-line and what's siding, but for now, this solution does work pretty elegantly (except for the 30-second wait to advance to a later siding).
I think that given the tools available you are as close as possible as your stated wish to use sidings. I don't think you are missing something obvious and you are correct in your OP saying the game won't let you do exactly what you describe. Or at least i can't find any workaround that would do so if the adding dummy stop doesn't work with its hardcoded 2000 penalty distance. I don't share the reasons of why you'd want to do this though x). I think you are trying to implement a logic for which you are missing a few parts that the game doesn't provide. So i understand the suggestion, but i wouldn't say "it works" currently, and it would "work better" with the suggestion. I consider "it doesn't quite work" currently, but "could" with the suggestion.

Now it's an ugly workaround, but if you say :
True, but repaths already happen when the destination station becomes not-full, and this case could be seen as an extension of that behavior.
You can have some dummies train stop in a corner of the map, unconnected to any rails, that just turn on/off every second or so, for the purpose of triggering a repath on all other trains with a destination of similar name. I remember doing this but not sure what was the purpose. It is problematic when the network is a large cityblock network. Those are yielding exponentially complex cases for the path finders, and request are made exponentially more numerous when the number of train/size of network increases. I am sadly not imagining a different outcome everytime the train pathfinding is required to be "smarter" than it is.
rcombs
Manual Inserter
Manual Inserter
Posts: 4
Joined: Thu Apr 27, 2017 8:46 pm
Contact:

Re: Railway sidings and train pathfinding

Post by rcombs »

mmmPI wrote: Thu Dec 19, 2024 9:49 am I think the amount of track can stays roughly the same if you use sidings or stackers, because the number necessary to "hold" the amount train would be similar. It could be pictured as where on the network they are located. It would probably require less rails to use stackers, because all sidings wouldn't be available for all trains at all time, whereas using stacker, trains are "forced" into the area in which they fit, and there is no "extra" area, like "free unused siding". Those are related to the size of the network, so potentially a lot of them for a small number of trains if you extend the network with blueprints containing sidings but do not add extra train stop.
Yeah, sidings don't mean you need less total rail, but it does mean that you're using less of the valuable space adjacent to your base (which you'd probably rather be using for higher-value applications). Sidings can be distributed along your mainline, taking up space that you probably wouldn't have been using for anything anyway, but stackers have to be attached to your stations, and take up a lot of area there (since they generally require at least a couple 90° turns and often some 180°s, or a lot of extra length). Each siding just takes up a 4-tile-wide space along any train-length-plus-switches stretch of your mainline, which is basically free.
Post Reply

Return to “Ideas and Suggestions”