Journal 2002 03 24
I've taken a new tack this week, focusing on the graphical side of this application. So I spent a bit learning MFC, and it's been kind of fun. More importantly, I've made some good progress. I've got it drawing pieces of track, which has led to the start of a format for a config/definition file. Not perfect yet, I need a better way to calculate the connections between track pieces, but it definitely looks like it will be feasible to have the program draw the track.
Also, I've got a nifty little right-click context menu, presumably for interacting with turnouts, photocells, etc. I don't know whether I'll use it, but the key is that it's fun to actually see things work. I have to say I've been pleasantly surprised by MFC. I've done a little bit of straight Windows API programming, and it feels to me that they did a nice job of wrapping it into reasonable objects. Anyways, progress and order!
This does not mean I would like a job writing MFC applications. Native Windows Applications are a dead end. :)
Journal 2002 03 03
This week I have reworked this website, and hammered through most of the problems outlined last week. I think I'm still getting too hung up on the issue of trains being derailed by a turnout switching half-way through.
Also this week, I visited the train in PAC again. Big revelation: that central intersection that caused a collision (I think Laura has been working on that in the TrainOS) is messy for me too, and I had not dealt with it. It brings back the somewhat messy turnout-as-a-track, but made it clear that train locations on tracks can be much easier tracked as ranges. I had been storing axle locations, and calculating the train between them. Now I plan to have the track store the full train range. Finding collisions during a move is just a matter of comparing ranges. (Photocell triggers between cars seem like they may be messier, I haven't dealt with that.)
Journal 2002 02 24
It looks like I forgot to add a journal entry last week. Since I last wrote here there has been a lot of progress, and some redesign.
I have a working implementation of a possible simulation of the track/train hardware, which has a lot of good elements and a few serious flaws. I also have a partial implementation of a more accurate, more complex hardware model. I'll describe the former model, then the fixes that are being made.
My first implementation models consists of tracks, trains, and turnouts. Track segments are logical, as long as possible until a dead end or turnout split. There is no concept of the layout of the overall track, any curvature etc, only connections between track segments. A track knows its length, and the locations of any trains or photocells along its length.
A train knows what track it is currently on, its speed, and direction. The main simulation creates trains, tracks, and connects the appropriate tracks. It then goes into a loop, checking for new input (train speed or direction changes, turnout switches) and signalling the trains to move every 1/2 second. When a train is asked to move, it calculates the "physical" distance it is moving (based on speed, direction, etc) and tells its track this distance. The track checks for interactions (collisions or photocells), and if the distance is greater than that remaining on the track. If so, the track passes the train to the connecting track, which performs the same interaction checks and movement.
Turnouts are modelled as subclasses of tracks, with zero length and internal state to determine which connecting track is currently the active one.
Now, the problems. First, an easy one: turnout complexity. A number of issues stemming from track movement on zero-length tracks, and managing opposing ends has now been simplified in both the tracks and the turnouts by making the turnouts a more abstract manager of tracks. That is, a turnout now just receives signals from the main simulation, and rearranges the track configuration. In this way, from the track's perspective there is only ever one connection at each end, and no question of where to send the leaving train.
One problem down, a few to go. My model of a train is much too abstract to deal with multiple car trains, and particularily derailment issues from switching a turnout while a train is travelling over it. Because of these problems, I've decided to re-design to the level of each train's axlesets. A train now consists of a variable number of cars, each with two axles. The train tells the axles to move, and they act like trains did in the previous example.
One final note. These implementations have been written in Python, the first one was mostly transferred to C++ before the need for a serious rewrite was discovered. I find these process actually been helpful. Python is very quick for me to try new ideas in, to write real testable code and find quick problems with algorithms and models. This methodology requires knowledge of both languages, and keeping in mind what is easily possible in both (so I don't write python code that looks more like Scheme than C++), but promotes refactoring and not being tied to the first design I come up with.
Journal 2002 02 10
After meeting with DCP, things have progressed smoothly this week. The simulation is firmly fixed into three parts: an implentation of the current dll interface, a representation of the physical hardware, and display of (and interaction with) the hardware state. First step is going to be a sufficient model of the hardware. I've got a few possibilities on paper right now, the challenge is in representing the track and trains so that the train knows nothing about the track it is on (so that trains don't need to know about turnouts or photocells) but the track is easy to define. Playing with a few options, keeping in mind that the track needs to be displayed visually at some point. Haven't decided yet whether the track config for the hardware side needs to be aware of the actual shape, or just lengths and intersections. I've got a quick implementation of a track manager running, a straight track with photocells triggered by a single train travelling along it. A long ways to go, but it's good to have some code started.
Journal 2002 02 03
Not much progress this week. I've browsed through (I think) all of the TrainOS code, fairly comfortable with where I'll need to take over. A little shaky on the way some things are done (hard coding the train layout is one that comes to mind).
This coming week I plan to start test coding. Notice I haven't designed much, so this code will be throw-away, just to make sure I actually can catch the signals from TrainOS, and some practice GUI code.
As mentioned in my first journal, my language preference for most things is Python. I need to talk to DCP about this, but I've done some research and it looks feasible to interact between Python and C++ for what I need. My main goal here is probably to avoid MFC coding, but even if I were using C++ I'd probably try to avoid that, using WxWindows or Qt, both cross-platform GUI Toolkits. Of course, if I do end up using Python I'll probably go WxWindows as well.
Journal 2002 01 27
Following the demonstration of the railroad on Thursday, I've started looking at the code. The operating system's connection to the railroad seems very straightforward and cleanly separated, just a number of library functions. I haven't looked through all the code yet, but it looks promising.
Most of the effort now looks to be in the user interface and animating the trains etc. The major features I'm trying for:
1. Extensible functions. Currently the functions the OS can perform are pretty limited, it will need to be clearly documented where to add new functions (for example, the lights, crossing guards, etc.)
2. Modifiable layout. The layout and configuration of the track needs to be easily defined, for instance if we add more light sensors or... I'm less sure how to plan for new features (such as trains with length, lights).
3. Variable action of every mechanical piece. How long it takes a switch to open, for a train to speed up, etc should be easily changed via the interface, at run-time. This will be on a per-item basis, so that you can disable a switch to see how the system reacts to errors.
4. Log every event. Based on this, I'd like to allow restoration of a "saved" state of the system. Also, perhaps being able to define a state (such as two trains colliding at a certain point) and run at high speed until that state is detected. I'm not entirely sure how useful or possible these last two are, but they're on my long list at the moment.
Journal 2002 01 22
Most thoughts so far have been related to my personal CompSci philosophy. I suppose this has to be the start of the project no matter what, asking why I'm excited about this project, my job, and programming in general.
I've started conceptualizing how I may split the various components of my project along clean interface lines. A lot of this depends on the current state of the TOS, but I see pretty clear separation between the actual emulation of the hardware (so the TOS thinks it's in the right place), the logic of decoding and encoding the signals from/to the TOS (can I interact with it at a command line or similar level), and finally the visual representation of the track and trains.
My strong personal preference will be to write this application in Python, I'm waiting to see how feasible that will be...