Model Train-related Notes Blog -- these are personal notes and musings on the subject of model train control, automation, electronics, or whatever I find interesting. I also have more posts in a blog dedicated to the maintenance of the Randall Museum Model Railroad.
2022-01-23 - Conductor 2: Block Graph and Travel DirectionCategory Rtac
In Conductor 2, each route has its dedicated route type, driven by a “route manager”.
For our shuttle routes, we define an almost linear block list of blocks traveled.
- Normal: B311 → B321 → stop/reverse → B321 → B311.
As seen above, to handle the rare case of the end-run overrun, we want to actually have a block graph.
What we are not encoding here is the travel direction.
We are not encoding either which one is the startup point, not which one is the reverse point.
The argument is that we do not have to because a/ we don’t really need the information, and b/ if we really needed it, we could infer it from the graph.
So let’s discuss that.
Why don’t we need the information? In a normal setup scenario, the train is initially already located at the starting block, and stopped. This is the first block in the list. We don’t need extra information to denote that it is the start of the list.
As the train travels from one block to the next one, the manager keeps track of the “current active block”. It’s the one that was occupied. At some point the manager will notice the block being unoccupied, and should mark it as a trailing block, and move to the next one.
At the transition time, we can have 3 cases: 0 blocks occupied briefly, 1 block occupied (the next one), or 2 blocks occupied briefly.
- 0 blocks occupied. That can happen at some jonctions, or when a block sensor flickers. The manager should keep the current block active till transitioning to the new one for sure.
- 1 block occupied and it’s not the active one. Is it the next or one of the possible next ones? If yes, change that to be the new active block. If the new occupied block is not in the next list, we have an error situation.
- 2 blocks occupied briefly can also happen. This is similar to the previous “normal” case. If the new block is in the expected list, make it the current one.
Every time the current block changes, the old current block is marked as a trailing block, and the previous trailing block is unmarked.
We also need to account for sensor flakiness. Any unexpected state change should not be accepted right away, and given a little bit of time to see if it goes away (e.g. 2 seconds). However we’ll treat any expected state change as immediate to avoid delaying execution of events in the expected cases.
It’s worth noting that all that discussion about current block changing did not mention the travel direction. We don’t need to care -- the block list is linear and always executed from start to end. We only care about the “next block(s)”, never the previous ones.
The only case where we have an ambiguity is with abnormal startups: automation starts with the train already on the track in an expected block, and we want to recover by bringing it back to the start point. The manager needs to know which one to make the current block since in a shuttle mode most blocks appear twice. But in fact that’s not even an issue since we know the recovery method is to bring the train to the end point. Thus the only logical choice is the last occurrence of the current occupied block in the list, since it’s the one closer to the end point.
Finally, we don’t need to know the running direction, but if we really wanted to, it could be deduced easily. Since these are shuttle routes, they start and stop at the same block, and they have one single reversing block. The reversing block is easy to find since it has the same block as both previous and next. The same applies to a reversing loop with more than one block: any time a block appears more than once in the graph flattened as a linear sequence, the second occurrence must have the reverse direction of the first occurrence of the same block.