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.
2023-09-11 - Conductor 2: Route Statistics with Numbers
Category Rtac
In the latest version of Conductor 2, I’ve added “end-of-route statistics”. I’ve now accumulated enough data to start looking at it.
First, I needed to parse a JSON log file (a log file with one JSON entry per line per day per run), and I needed a way to convert that to CSV to dump it in a Google Spreadsheet. I briefly considered writing a short python script to do that, then realized that nothing can beat the awesomeness of sed, so I ended up with this:
$ grep '{"name"' conductor-log-2023-09-* | sed -E -n '/Recovery/d; /true/d; s/^[^0-9]+//; s/([0-9-]{10})[^:]+:/\1 /; s/ R Seq[^\{]+/@ /; s/":/" /g; s/[^a-zA-Z0-9@.:-]+/,/g; s/@/,/g; s/,ms,([0-9]{3,})/,\1,ms/g; s/([0-9])([0-9]{3}),ms/\1.\2,ms/g; s/,name,|,th|,act|,err,false,nodes|,n|,ms//g; p' | tee ~/temp/_csv.txt |
I regret nothing. <insert appropriate meme>
I shall note that this expression purposely only selects log lines that have no errors, that is, successful runs that have completed with no issue. This will become relevant later.
Now let’s look at the collected data.
Freight Route
This is a simple shuttle route over two blocks: we’re moving from block B311 (the Stockton Station) to B321 (the Sonora Station), stopping there, and then back again to B311. The way I wrote the route stats aggregator, I add an index number when a block is repeated, so “B311.1” means “block B311 when leaving”, and “B311.2” means “block B311 when coming back”.
I have 98 runs for this one, and when we compute the stats we get a very nice result:
All the times are in seconds, per length of block occupation. It takes about 26 seconds to move to the second block, and we spend a total of about 160 seconds on that block -- and that includes the 30 second paused time at the 2nd station before reversing back.
As a reminder, one of the major revamps I did in Conductor 2 is to have the ability to define min/max times per block. In this case, I have a min of 10 seconds, and a max of 180 seconds. These are hard limits -- if the trains do not spent at least 10 seconds in a block or spend more than 180 seconds on a block, something’s wrong and the entire route automation stops.
So that’s good: here we have a good margin. The min time is 25 seconds, well above the 10 seconds limit, and the max time is 164 seconds, well below our max limit.
It’s all nice looking and smooth and almost boring, so let’s move on.
Passenger Route
This is the longest route. We’re crossing a good part of the mainline, also in a shuttle (back-and-worth). We’re starting from block B503b (the Stockton Station) up the way to B370 at the top of the mountain, then back down again.
We have 102 data points, however this time there’s a lot of variation, and a few surprises:
Clearly, there’s a lot of variability in the duration it takes to cross each block. A few blocks have a variation of 20 seconds between their min and their max -- B360 and B340 have a fairly high standard deviation of almost 6 seconds in their return trip. I’m not sure how I’d explain that, because these are the blocks where the train is going down the mountain.
I highlighted some cells: some blocks have a minimum time of 10 seconds, or very close to it. B503a notably is really close or strictly equal to 10 seconds in this minimum. This turned out to be a problem.
Remember how I said the logs here are filtered to only show successful runs? Well it turns out that for the last 2 days, the automation was stopping for that specific train. Investigation showed that the crossing time for B503a could be as low as 9.5 seconds, yet the block was programmed with a minimum crossing time of 10 seconds. Since the next block was activated too soon, the automation was stopping the train and entering error mode. The fix was to change the minimum time for this block -- I’ve set it to 5 seconds -- that seems safe, there’s no way the train can cross that block that fast. I had also noticed that B504 was fairly close to 10 seconds and adjusted its minimum time accordingly.
In case it’s not obvious, there’s a rationale behind that “minimum time to cross a block”: it’s designed to detect accidental block occupancy. Let’s say a train is running its route, and the next block suddenly appears occupied… I use electric-current based block detection, and the computer only knows that something is on the block, drawing electricity without really knowing what or why. If a train is running on block A and should logically move to block B next, and then that block B suddenly gets activated, that can only mean 2 things: either the train has successfully crossed from block A to B (that’s good), or something else is suddenly occupying block B, and we should really stop as soon as possible. By default, I set the minimum time to 10 seconds, so if the next block gets activated before 10 seconds, that means either that something is now occupying the block (not good), or the train moved too fast (suspicious), or that my timing is not adequate enough. And here we have an example of the latter. My ballpark conservative figure of “at least 10 seconds on every block” was only mostly right.
Now, this data here shows me we have a similar potential problem on B340.2, so I should adjust its min time to something appropriate, after I physically measure the crossing time by manually running the engine at various (reasonable) speeds.
Branchline Route
The branchline is yet another shuttle (back-and-worth). We’re starting from block B801 (aptly named “BL Parked”) up the way to B860 (a.k.a. “BL Reverse”) at the You Bet station, then back down again.
I have 190 data points:
Although there’s a bit of noise, this is a well behaved run, fairly consistent. The timings are well within the enforced ranges (10 seconds min, 120 seconds max), and the standard deviation looks fairly reasonable.