Certainly you're free to use the source for this purpose. We've released the software under the LGPL.
We've discussed your proposed reasearch, however, and our primary concern is that the algorithm (in our opinion) is in need of a rewrite. If you want to work with what's there right now, org.intranet.elevator.model.operate.CarController is the class that handles the dispatching of requests.
Let us know if you have any questions about the source. We'll try to watch the forums more closely in the future.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am happy to see your reply and know that the 0.3 release is available. However, it also means that I have to spend another one or two weeks on the source code, as I did on the 0.2 release, in order to understand it. It is not an easy thing to under other's code, but fortunely, you have done quite well in the source code and made it clear and easy to understand.
I have not look into the source code of 0.3 release carefully. After I run it, I find that there is still a problem as in 0.2 release. I think that the time spending in a simulation should be able to change. It can run faster if I am going to simulate elevators that running in a whole day. The software should be finished in one or half an hour, rather than a whole day.
I am not in an English speaking country and not good at it. I hope you can understand what I said.
I will post messages if have problems in understanding the source code of 0.3 release.
Looking forward to your answer.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Depending on what you want to use the simulation for, you can now use the multiple simulation to do very quick runs instead. Multiple simulation doesn't use a real-time clock, so the simulation should run much faster. Plus you can specify ranges of values and look at the resulting output by comparing any pair of variables.
In the list of available simulations you'll also see a morning simulation (all the people start on the ground floor) and an evening simulation (all the people have the ground floor as a destination). These do not use a uniform distribution, but a normal distribution instead and you can specify the standard deviation across the insertion time.
Hopefully, some of these new options will allow you to run it faster and even give you some ideas for other simulations that could be setup. Unfortunately, mouseman and I are still working on cleaning up the scheduling and assignment approach. There's still a number of things to do.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry to bother you again.
I have read most of the source code in these days and there is something I am not quite sure.
The first question is in class CarController. I know that the function getCost() result in the dispatching of requests. However, the function getNearestBase() is not easy to understand, either is the function createFloorContext(). Can you explain them and tell me what is the meaning of a "nearest base"?
The second question is about the passenger generation model. In the morning simulation (or evening simulation), passengers arrive under a normal distribution, but the destinations use a uniform distribution, which is not like the truth. How can I make the destinations also under a normal distribution?
There are some trivial problems in the source code:
1)I am not able to compare different dispatching algorithms at one time as the multiple simulation intended to do.
2)If I use only one simulation in the multiple simulation mode, the result of the simulation is not readable because the color of result is black.
3)Choosing the morning simulation (or the evening simulation) with multiple simulation and click the apply button right away, then exception will be thrown out. The cause of it is, when parsing the parameter of "Rider insertion time", the default value 1.0 is not of long type,thus the code
"long base = Long.parseLong(baseValue);" throw out a NumberFormatException.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Problems in the source code --
1) The multiple simulation is intended to compare different variables in the simulation. We don't yet support varying dispatch algorithms as variables. We'll add this on the list of TODOs.
2) This is now fixed in CVS. The background color will be white.
3) This has been fixed. Each Parameter now computes its own list of strings for a range of values.
Now on to the other questions.
CarController -- we understand your confusion, CarController is high on our list of things to refactor. However, I'll try to give you some ideas of what is going on.
The point of getNearestBase() is to determine what floor the car could next stop at. (And now looking at the comment, that's what it says.) First of all, the method name is bad, because there is not really a "Base" concept in the system; so ignore that. It has to deal with the 3 states of the car -- Docked, Idle, and Travelling. I won't describe Docked or Idle, because those are easier to figure out.
The floors that the car can realistically travel to are available in the request panel -- car.getFloorRequestPanel(). This method used to loop through the floors and figuring out based on direction and stopping distance and what not which floor we could stop at next. This was very complex logic, so we created the concept of FloorContext (we couldn't think of a better name at the time) and wrote a method that would create a list of them from the available floors and the current car direction. This list is ordered. The FloorContext defines a range between floors, and includes enough information to tell if a car is in that range, and what the stop at the end of the range and the next stop after that range would be. These can then be used by getNearestBase() along with the stopping distance to find out the next place the car can stop.
And finally, for the passenger generation model, see org.intranet.elevator.ElevatorSimulationApplication for the list of simulations that show up in the opening dialog. You can create new simulations and add them there. We typically copy an existing simulation and make changes. As far as the distribution goes, we assumed that each floor would hold about the same number of people. For example, in the building I work in, there are 19 floors, 3 of which are used by the company I work in, and there are about the same number of people on two of the floors and a bit fewer on the third. If you wanted some kind of distribution, feel free to change initializeModel() in the simulation of your choice to get the behavior you want.
I hope this response helps. We value your input highly! It's nice to have someone else looking over our shoulders.
Chris + Neil
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Problems first:
1.At time about 94000 in the real-time simulation of random rider insertion, using a model of 10 floors,3 elevators,20 people,50000ms,random seed=65538, when the second elevator goes to the first floor, it opens the door to let passengers out,then close the door.Then open the door again immediately to take two passengers.I don't think the door should open twice because passengers can get in while the doors open the first time.
2.A trivial problem of deploy: File icon.gif should be packed into the jar file, or a NullPointerException will be thrown out.
About the latest codes:
I have read your latest codes. You are doing something that exactly meets our needs. So thank you for your work.
I would like to say something first.
As a client developer of the simulator, I need to know the following things:
1.How to generate passenger events in any model I preferred? (You have done this in Simulator.initializeModel() )
2.When there comes a request, where is the entry point to process the request? (i.e. where can I write my own dispatching algorithm to determine a dispatch?)
3.How to response to a call from a passenger?
a)How can I get the current status of the building (the current positions of all the elevators, the requests from passengers which have not been processed)?
b)After my decision is made, how can I control the cars to the destination? And do I need to control other things such as closing doors and opening doors to pick up passengers?
In fact, I think I have got the answers to the questions above after reading your codes. But each time when you do some modifications, I have to go over the source code again, in order to get the idea of flows and to do my modification on it. It would be helpful if you can provide some documents or some charts to indicate the flows of the program.
Another question to consult you:
I would like to know, in a real elevator system, how does a program control the elevator? What information can it get and what can it do?
Thank you.
Leeson
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For the problems:
1) Excellent catch! We've added a check to see if the car is at the extreme end of its cycle, switch directions right away, and properly set the entrance light to up or down. This problem could potentially occur in more places than at the ground floor, so this was a good addition.
2) Oops! We've added a line to build.xml. This problem should be fixed now.
For the code questions:
1) I'm not sure if I understand the question, so I'm going to assume that you want to write your own Simulator implementation (like RandomElevatorSimulator for example).
The Person has some set behaviour if a destination is set. Person will try to enter a car if one is available or will press a request button and activate an ArrivalListener to wait for a car. This sequence is started by setting a destination for the person, which is what we do in initializeModel. If you just want to add more destinations to the same Person over time, you can schedule these as events either in advance or from inside Person (based on behaviour you write).
If you want to make Person behave *very* differently, you may want to write your own ModelElement (as a replacement for Person). You'd need to replace Building and I'm afraid the setup for collecting and displaying statistics would be hard to plug into at this point.
2) SimpleController doesn't have a "dispatch" algorithm. It completely ignores incoming requests, only using them as a trigger to start the cars moving.
MetaController is a proper dispatching controller. It receives requests through requestCar(), which is part of the Controller interface. This interface is invoked from CarRequest, which has a specific controller passed to it when it is created. CarRequest is a CarRequestPanel.ButtonListener, meaning it is listening for a Person calling pressUp() or pressDown() in CarRequestPanel and passing the request through to the Controller.
The Simulator.initializeModel() method should create the Building with a specific Controller implementation. The Building creates Floors that have CarRequestPanels and also creates CarRequests, which are CarRequestPanel.ButtonListeners. This means they are listening for pressedUp() or pressedDown() calls. During the simulation, a Person calls CarRequestPanel.pressUp() or pressDown() to request a car and these methods invoke the listener's pressedUp() or pressedDown() if there's no car available at the Floor.
So, creating your own dispatcher is a matter of implementing the Controller interface and creating a Simulation that will pass this new Controller to the Building during initializeModel(). You can look at how RandomElevatorSimulator does this when there's a list of Controllers to choose from.
3) I think the description above describes somewhat how the Person gets involved in this process. Really, it's creating the Controller and adding it into the simulation that's the key.
3a) By design, all of this state information is tracked by each individual ModelElement. Building has the lists of Floors, Cars, and People. These lists are how, for example, the ui (BuildingView) traverses the model objects and draws the interface.
3b) The primary purpose of the Controller implementation is to call Car.setDestination() and Car.undock() at appropriate times. Car is responsible for docking, but will notify Car.Listeners that docking has happened. Obviously, the Controller needs to listen to the Car.
The Controller is also responsible for opening and closing the doors (look at any sample docked() implementation of the Car.Listener). We've talking about this not belonging in the Controller, so this may be refactored in the future and moved out.
Regarding the code changes, I certainly agree with you. We do have some pencil sketches that informed our initial design. We will consider how to add this to the Javadocs.
For your final question, we don't know anything about real elevators except as users of them. Some of our control decisions are made based on our observations of elevator behaviour, but that's the extent of our knowledge. We do hope to read up more on real elevator systems to make the simulator more useful, but that's in the future.
We would both like to thank you for these comments, questions, and bug reports. They've been very helpful in our thinking about the design and how we've implemented the simulator. We've indicated in our changelog.txt which changes or bug fixes have been the result of your input.
Thanks again.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am going to use this software to do some research on the call allocation algorithm, do I have the authorization to do so?
Certainly you're free to use the source for this purpose. We've released the software under the LGPL.
We've discussed your proposed reasearch, however, and our primary concern is that the algorithm (in our opinion) is in need of a rewrite. If you want to work with what's there right now, org.intranet.elevator.model.operate.CarController is the class that handles the dispatching of requests.
Let us know if you have any questions about the source. We'll try to watch the forums more closely in the future.
I am happy to see your reply and know that the 0.3 release is available. However, it also means that I have to spend another one or two weeks on the source code, as I did on the 0.2 release, in order to understand it. It is not an easy thing to under other's code, but fortunely, you have done quite well in the source code and made it clear and easy to understand.
I have not look into the source code of 0.3 release carefully. After I run it, I find that there is still a problem as in 0.2 release. I think that the time spending in a simulation should be able to change. It can run faster if I am going to simulate elevators that running in a whole day. The software should be finished in one or half an hour, rather than a whole day.
I am not in an English speaking country and not good at it. I hope you can understand what I said.
I will post messages if have problems in understanding the source code of 0.3 release.
Looking forward to your answer.
Depending on what you want to use the simulation for, you can now use the multiple simulation to do very quick runs instead. Multiple simulation doesn't use a real-time clock, so the simulation should run much faster. Plus you can specify ranges of values and look at the resulting output by comparing any pair of variables.
In the list of available simulations you'll also see a morning simulation (all the people start on the ground floor) and an evening simulation (all the people have the ground floor as a destination). These do not use a uniform distribution, but a normal distribution instead and you can specify the standard deviation across the insertion time.
Hopefully, some of these new options will allow you to run it faster and even give you some ideas for other simulations that could be setup. Unfortunately, mouseman and I are still working on cleaning up the scheduling and assignment approach. There's still a number of things to do.
Sorry to bother you again.
I have read most of the source code in these days and there is something I am not quite sure.
The first question is in class CarController. I know that the function getCost() result in the dispatching of requests. However, the function getNearestBase() is not easy to understand, either is the function createFloorContext(). Can you explain them and tell me what is the meaning of a "nearest base"?
The second question is about the passenger generation model. In the morning simulation (or evening simulation), passengers arrive under a normal distribution, but the destinations use a uniform distribution, which is not like the truth. How can I make the destinations also under a normal distribution?
There are some trivial problems in the source code:
1)I am not able to compare different dispatching algorithms at one time as the multiple simulation intended to do.
2)If I use only one simulation in the multiple simulation mode, the result of the simulation is not readable because the color of result is black.
3)Choosing the morning simulation (or the evening simulation) with multiple simulation and click the apply button right away, then exception will be thrown out. The cause of it is, when parsing the parameter of "Rider insertion time", the default value 1.0 is not of long type,thus the code
"long base = Long.parseLong(baseValue);" throw out a NumberFormatException.
Last questions first ...
Problems in the source code --
1) The multiple simulation is intended to compare different variables in the simulation. We don't yet support varying dispatch algorithms as variables. We'll add this on the list of TODOs.
2) This is now fixed in CVS. The background color will be white.
3) This has been fixed. Each Parameter now computes its own list of strings for a range of values.
Now on to the other questions.
CarController -- we understand your confusion, CarController is high on our list of things to refactor. However, I'll try to give you some ideas of what is going on.
The point of getNearestBase() is to determine what floor the car could next stop at. (And now looking at the comment, that's what it says.) First of all, the method name is bad, because there is not really a "Base" concept in the system; so ignore that. It has to deal with the 3 states of the car -- Docked, Idle, and Travelling. I won't describe Docked or Idle, because those are easier to figure out.
The floors that the car can realistically travel to are available in the request panel -- car.getFloorRequestPanel(). This method used to loop through the floors and figuring out based on direction and stopping distance and what not which floor we could stop at next. This was very complex logic, so we created the concept of FloorContext (we couldn't think of a better name at the time) and wrote a method that would create a list of them from the available floors and the current car direction. This list is ordered. The FloorContext defines a range between floors, and includes enough information to tell if a car is in that range, and what the stop at the end of the range and the next stop after that range would be. These can then be used by getNearestBase() along with the stopping distance to find out the next place the car can stop.
And finally, for the passenger generation model, see org.intranet.elevator.ElevatorSimulationApplication for the list of simulations that show up in the opening dialog. You can create new simulations and add them there. We typically copy an existing simulation and make changes. As far as the distribution goes, we assumed that each floor would hold about the same number of people. For example, in the building I work in, there are 19 floors, 3 of which are used by the company I work in, and there are about the same number of people on two of the floors and a bit fewer on the third. If you wanted some kind of distribution, feel free to change initializeModel() in the simulation of your choice to get the behavior you want.
I hope this response helps. We value your input highly! It's nice to have someone else looking over our shoulders.
Chris + Neil
Problems first:
1.At time about 94000 in the real-time simulation of random rider insertion, using a model of 10 floors,3 elevators,20 people,50000ms,random seed=65538, when the second elevator goes to the first floor, it opens the door to let passengers out,then close the door.Then open the door again immediately to take two passengers.I don't think the door should open twice because passengers can get in while the doors open the first time.
2.A trivial problem of deploy: File icon.gif should be packed into the jar file, or a NullPointerException will be thrown out.
About the latest codes:
I have read your latest codes. You are doing something that exactly meets our needs. So thank you for your work.
I would like to say something first.
As a client developer of the simulator, I need to know the following things:
1.How to generate passenger events in any model I preferred? (You have done this in Simulator.initializeModel() )
2.When there comes a request, where is the entry point to process the request? (i.e. where can I write my own dispatching algorithm to determine a dispatch?)
3.How to response to a call from a passenger?
a)How can I get the current status of the building (the current positions of all the elevators, the requests from passengers which have not been processed)?
b)After my decision is made, how can I control the cars to the destination? And do I need to control other things such as closing doors and opening doors to pick up passengers?
In fact, I think I have got the answers to the questions above after reading your codes. But each time when you do some modifications, I have to go over the source code again, in order to get the idea of flows and to do my modification on it. It would be helpful if you can provide some documents or some charts to indicate the flows of the program.
Another question to consult you:
I would like to know, in a real elevator system, how does a program control the elevator? What information can it get and what can it do?
Thank you.
Leeson
For the problems:
1) Excellent catch! We've added a check to see if the car is at the extreme end of its cycle, switch directions right away, and properly set the entrance light to up or down. This problem could potentially occur in more places than at the ground floor, so this was a good addition.
2) Oops! We've added a line to build.xml. This problem should be fixed now.
For the code questions:
1) I'm not sure if I understand the question, so I'm going to assume that you want to write your own Simulator implementation (like RandomElevatorSimulator for example).
The Person has some set behaviour if a destination is set. Person will try to enter a car if one is available or will press a request button and activate an ArrivalListener to wait for a car. This sequence is started by setting a destination for the person, which is what we do in initializeModel. If you just want to add more destinations to the same Person over time, you can schedule these as events either in advance or from inside Person (based on behaviour you write).
If you want to make Person behave *very* differently, you may want to write your own ModelElement (as a replacement for Person). You'd need to replace Building and I'm afraid the setup for collecting and displaying statistics would be hard to plug into at this point.
2) SimpleController doesn't have a "dispatch" algorithm. It completely ignores incoming requests, only using them as a trigger to start the cars moving.
MetaController is a proper dispatching controller. It receives requests through requestCar(), which is part of the Controller interface. This interface is invoked from CarRequest, which has a specific controller passed to it when it is created. CarRequest is a CarRequestPanel.ButtonListener, meaning it is listening for a Person calling pressUp() or pressDown() in CarRequestPanel and passing the request through to the Controller.
The Simulator.initializeModel() method should create the Building with a specific Controller implementation. The Building creates Floors that have CarRequestPanels and also creates CarRequests, which are CarRequestPanel.ButtonListeners. This means they are listening for pressedUp() or pressedDown() calls. During the simulation, a Person calls CarRequestPanel.pressUp() or pressDown() to request a car and these methods invoke the listener's pressedUp() or pressedDown() if there's no car available at the Floor.
So, creating your own dispatcher is a matter of implementing the Controller interface and creating a Simulation that will pass this new Controller to the Building during initializeModel(). You can look at how RandomElevatorSimulator does this when there's a list of Controllers to choose from.
3) I think the description above describes somewhat how the Person gets involved in this process. Really, it's creating the Controller and adding it into the simulation that's the key.
3a) By design, all of this state information is tracked by each individual ModelElement. Building has the lists of Floors, Cars, and People. These lists are how, for example, the ui (BuildingView) traverses the model objects and draws the interface.
3b) The primary purpose of the Controller implementation is to call Car.setDestination() and Car.undock() at appropriate times. Car is responsible for docking, but will notify Car.Listeners that docking has happened. Obviously, the Controller needs to listen to the Car.
The Controller is also responsible for opening and closing the doors (look at any sample docked() implementation of the Car.Listener). We've talking about this not belonging in the Controller, so this may be refactored in the future and moved out.
Regarding the code changes, I certainly agree with you. We do have some pencil sketches that informed our initial design. We will consider how to add this to the Javadocs.
For your final question, we don't know anything about real elevators except as users of them. Some of our control decisions are made based on our observations of elevator behaviour, but that's the extent of our knowledge. We do hope to read up more on real elevator systems to make the simulator more useful, but that's in the future.
We would both like to thank you for these comments, questions, and bug reports. They've been very helpful in our thinking about the design and how we've implemented the simulator. We've indicated in our changelog.txt which changes or bug fixes have been the result of your input.
Thanks again.