The shelf is actually a great test-bed for what I have planned for my full layout. To summarize, I really love fully-automated devices, but when it simply has to follow the exact same motions over and over again it gets boring to watch. The rough overview of my goals are to build a system where each loco is given a task to fulfill. Switchers move the cars for loading and unloading, and prep a string for pickup. Mainline locos pick up the strings and take them from town to town.
Now sure, I can program a set routine for each loco, but again that's just boring. So to begin with, I'll throw in some random factors. A car didn't get unloaded in time, so it'll have to be rescheduled for tomorrow's pick-up. A loco stalled while climbing the mountain, so it fouls one of the mainlines while waiting for a helper loco, causing reschedules or using alternate routes. Get the idea?
Having a short train isn't too difficult to work around. The software just needs to realize that only two cars are being dropped at a siding instead of three. But rerouting and rescheduling on the fly... that's where the real meat of the software will be. Part of the task is to map out the entire layout, so if one route is blocked, an alternate route can be selected. But wait, if another train is already scheduled on that route, can I slip in around it? There will also be priorities for each train, so a passenger train looking for an alternate route could supersede a freight train. How do we calculate priorities? Well someone on this forum posed an interested question last year regarding if anyone worked with budgets on their layout, calculating the cost of running a train per the weight and value of the loads. It made me think that if I could have lookup tables of the dry and loaded weights of each type of car (plus or minus some randomness of course), and the value of each load per ton, and throw in a generic running cost for the loco to pull the train... now you've got something that allows you to calculate a general cost/value of each train, and a way to automatically prioritize who gets to use the available mainlines.
There are a few more random variables that can be tossed in. For example, if I have a string of 10 hoppers with the same load, but I only need to drop off three at the first industry, which three do I drop? I could take the first ones after the loco, I could take the last ones before the caboose, or I could slice three from the middle. This will ensure cars get mixed up so you don't always see exactly the same hopper right behind the loco. Another way to mix them up is to have industries with varying needs. The lumber mill needs 5 flats today, but a big order requires 8 flats tomorrow.
So to begin with, the software needs to always know where every loco is at. Between a combination of block detectors, IR sensors, and RFID tag readers, I hope to keep track of everything. And I need good block control with trains respecting the signals. Then I need sensors for when cars are approaching the end of a siding, and sensors over the decoupling magnets to verify the cars were released. The RFID readers can also verify the string of cars leaving a yard match the itinerary.
If you've followed so far, you can see where a tight shelf switching layout with a couple active switchers sorting cars can provide a multitude of situations to test out a large number of the ideas above. So HOW am I going to do it? Good question!

Piece by piece, I'll start with the basics of moving trains around and go from there. Various pieces will need different data structures, some parts might be handled by a server while others are done in arduinos. I might model the structure of what cars are going where after the various types a yard card systems that people have described, but another piece may have to be designed from the ground up. It's gonna be a wild ride...