This is version 1 of an elevator
simulator. It implements manual control of up to 6 elevators traveling
across 2 to 8 floors with up/down Call buttons outside of the elevators on each
floor and
Floor Destination buttons inside each car.
A simple control strategy is implemented. Elevators have enough internal
intelligence to handle all floor and call buttons moving in one direction and
then those requests requiring travel in the opposite direction. Calls are
assigned by the scheduler to the first stopped car found.
Version 1 is presented primarily for programmers wishing to study the code
required to animate multiple elevators operating independently (using a
technique called "threading" ).
The next version will allow user to control the strategy for servicing calls
with the objective of minimizing total wait time for a particular set of
passenger arrivals.
I recently help an elevator company convert some real elevator control routines written in Basic to Delphi. That wasn't very exciting in itself, but it did lead me to finally tackle one of the programs on my "life objectives" list - an elevator simulation.
The logic required to control elevators are more complex than it seems on the surface, particularly the problem of responding to calls when there are multiple elevators to choose from. Should we closest the closest one? Probably not if it is moving in the opposite direction from the call button direction. What if an idle elevator is one floor away, but there is a moving elevator two floors away that will pass this floor anyway? For this version I've deferred addressing these issues and created a scheduler that assigns the first (lowest numbered) idle elevator to floor calls.
An earlier posting, Threadstest1, introduced simple "elevator-like" objects that used Delphi's threading capabilities to allow their independent operation. This program expands that start by adding call and elevator buttons and a scheduler to assign an elevator to a call button push. Each elevator had to become "smarter" in order to detect and handle floor destination buttons (the buttons inside the elevator) and floor call buttons (the buttons outside the elevators) that the scheduler had assigned to it.
Each elevator is represented by a TElevator descendant of TThread. Each has two arrays with entries for each floor; Stops entries are of type TCallrec, a record indicating which call button direction (up, down, or none), and a pointer to the TCallBtn object itself (so we can turn the button off when we handle the call). FloorBtns is a Boolean array with true entries for each destination button that was pressed from inside the elevator.
In Threadstest1, the Execute method for each elevator suspended it's execution when idle. There is probably no real advantage to this. The current implementation periodically (10 times per second) checks the button arrays to determine if we have any pending requests and never suspends itself.
A timer, Timer1, is used to invoke the Scheduler procedure, also 10 times per second. Scheduler checks for pending elevator call button pushes and assigns them to the Stops array of an idle elevators. This method, rather than giving the call button click the responsibility, solves the problem of what to do if all elevators are busy.
Timer1 also has responsibility for closing open elevator doors after it has been open for DefaultDoorOpenTime (currently set at 5 seconds) . Logically, closing the door should be the elevator's job, and may be in the next version. The problem is that a common panel control, ElPanel, is used to show the internal elevator buttons when the user clicks on an elevator and all of this logic; the elevator click, making the control panel visible, and keeping track of which elevator was clicked is all known to the form but not to the elevators. If manual control disappears in the next version then the need for an external control panel will display will go away, and the door closing job will be moved back to the elevator.
There are other nooks and crannies in the code, but the above outline the main elements. You may have the fun of exploring the rest on your own!
|
Version 2 will add more sophisticated scheduling option to control elevators movement and will allow user to define or run predefined passenger arrival scripts. Perhaps the objectives could include average minimizing passenger wait time, minimizing maximum passenger wait time, minimizing total elevator run time, or some combination of these. |
|
|
Animated passenger sprites? |
|
|
Floor button images should be incorporated as resources in a ".res" file to elimnate the requirement for separate ".bmp" image files. |
| Created: September 27, 2000 |
Modified: November 07, 2008 |