SUMO - Simulation of Urban MObility

AGWorkAndSchool.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Generates trips to work and to school
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors
00011 // activitygen module
00012 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
00013 /****************************************************************************/
00014 //
00015 //   This program is free software; you can redistribute it and/or modify
00016 //   it under the terms of the GNU General Public License as published by
00017 //   the Free Software Foundation; either version 2 of the License, or
00018 //   (at your option) any later version.
00019 //
00020 /****************************************************************************/
00021 
00022 
00023 // ===========================================================================
00024 // included modules
00025 // ===========================================================================
00026 #ifdef _MSC_VER
00027 #include <windows_config.h>
00028 #else
00029 #include <config.h>
00030 #endif
00031 
00032 #include "AGWorkAndSchool.h"
00033 #include <list>
00034 #include "../city/AGCar.h"
00035 
00036 
00037 // ===========================================================================
00038 // method definitions
00039 // ===========================================================================
00040 bool
00041 AGWorkAndSchool::generateTrips() {
00042     //buildDestinations();
00043     // generation of the waiting list for the accompaniment
00044     buildChildrenAccompaniment();
00045 
00046     buildWorkDestinations();
00047 
00048     if (hh->getCarNbr() < (int)personsDrivingCars.size()) {
00049         return false;    //to rebuild the household
00050     }
00051     if (childrenNeedingCarAccompaniment.size() !=0 && hh->getCarNbr() == 0) {
00052         return false;    //to rebuild the household
00053     }
00054     if (adultNeedingCarAccompaniment.size() != 0 && hh->getCarNbr() == 0) {
00055         return false;
00056     }
00057 
00058     carAllocation();
00059 
00060     if (personsDrivingCars.empty() && notNeedingDrivers.empty()) {
00061         genDone = true;
00062         return true; // no trip to generate
00063     }
00064 
00065     if (! carsToTrips()) {
00066         return false;
00067     }
00068 
00069     genDone = true;
00070     return true;
00071 }
00072 
00073 void
00074 AGWorkAndSchool::buildChildrenAccompaniment() {
00075     std::list<AGChild>::iterator itC;
00076     for (itC=hh->children.begin() ; itC!=hh->children.end() ; ++itC) {
00077         if (itC->haveASchool()) {
00078             if (this->availableTranspMeans(hh->getPosition(), itC->getSchoolLocation()) == 0) {
00079                 //in this case the school is far from home and bus stations too
00080                 this->childrenNeedingCarAccompaniment.push_back(*itC);
00081             }
00082         }
00083     }
00084 }
00085 
00086 void
00087 AGWorkAndSchool::buildWorkDestinations() {
00088     std::list<AGAdult>::iterator itA;
00089     for (itA=hh->adults.begin() ; itA!=hh->adults.end() ; ++itA) {
00090         if (itA->isWorking()) {
00091             if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) % 2 == 0) {
00092                 //not too close, to not being able to go by foot
00093                 if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) > 4) {
00094                     //too far from home ==> Car or Bus AND Car and bus are possible
00095                     workingPeoplePossCar.push_back(*itA);
00096                 } else if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) == 4) {
00097                     //only the car is possible (and there is one (use of possibleTranspMean))
00098                     if (hh->getCarNbr() > (int)personsDrivingCars.size()) {
00099                         personsDrivingCars.push_back(*itA);
00100                     } else {
00101                         adultNeedingCarAccompaniment.push_back(*itA);
00102                     }
00103                 }
00104             }
00105         }
00106     }
00107 
00108     // sometimes, people still have choice: when vehicles are available and their car take a bus.
00109     std::list<AGAdult>::iterator it;
00110     for (it=workingPeoplePossCar.begin() ; it!=workingPeoplePossCar.end() ; ++it) {
00111         if (possibleTranspMean(it->getWorkPosition().getPosition()) == 6 && hh->getCarNbr() > (int)personsDrivingCars.size()) {
00112             //car or bus (always because of workDestinations' construction) AND at least one car not used
00113             if (hh->adults.front().decide(this->carPreference)) {
00114                 personsDrivingCars.push_back(*it);
00115             }
00116         }
00117     }
00118 }
00119 
00120 void
00121 AGWorkAndSchool::carAllocation() {
00122     // only two adults are possibles: no car, 1 car, 2 cars and more
00123     // the only choice case: 1 car / 2 adults needing this car (otherwise no choice problems)
00124     if (! personsDrivingCars.empty() && ! adultNeedingCarAccompaniment.empty()) {
00125         //in that case there is only one element in each list and only one car.
00126         if (adultNeedingCarAccompaniment.front().getWorkPosition().getOpening() >= personsDrivingCars.front().getWorkPosition().getOpening()) {
00127             //we will invert the driver and the accompanied
00128             personsDrivingCars.push_back(adultNeedingCarAccompaniment.front());
00129             adultNeedingCarAccompaniment.pop_front();
00130             adultNeedingCarAccompaniment.push_back(personsDrivingCars.front());
00131             personsDrivingCars.pop_front();
00132         }
00133     }
00134     if (personsDrivingCars.empty() && ! childrenNeedingCarAccompaniment.empty()) {
00135         //at least one adult exists because no household contains less than one adult
00136         if (workingPeoplePossCar.size() != hh->getAdultNbr()) { //personsDrivingCars.size() + adultNeedingCarAccompaniment.size() is equal to 0
00137             std::list<AGAdult>::iterator itUA;
00138             for (itUA=hh->adults.begin() ; itUA!=hh->adults.end() ; ++itUA) {
00139                 if (! itUA->isWorking()) {
00140                     notNeedingDrivers.push_back(*itUA);
00141                     break;
00142                 }
00143             }
00144         } else {
00145             personsDrivingCars.push_back(workingPeoplePossCar.front());
00146             workingPeoplePossCar.pop_front();
00147         }
00148     }
00149 }
00150 
00151 bool
00152 AGWorkAndSchool::carsToTrips() {
00153     std::list<AGAdult>::iterator itDriA;
00154     std::list<AGCar>::iterator itCar = hh->cars.begin();
00155     for (itDriA=personsDrivingCars.begin() ; itDriA!= personsDrivingCars.end() ; ++itDriA) {
00156         //check if the number of cars is lower than the number of drivers
00157         if (itCar == hh->cars.end()) {
00158             return false;
00159         }
00160         AGTrip trip(hh->getPosition(), itDriA->getWorkPosition().getPosition(), *itCar, depHour(hh->getPosition(), itDriA->getWorkPosition().getPosition(), itDriA->getWorkPosition().getOpening()));
00161         ++itCar;
00162         tempTrip.push_back(trip);
00163     }
00164 
00165     std::list<AGAdult>::iterator itAccA;
00166     for (itAccA=adultNeedingCarAccompaniment.begin() ; itAccA!= adultNeedingCarAccompaniment.end() ; ++itAccA) {
00167         AGTrip trip(hh->getPosition(), itAccA->getWorkPosition().getPosition(), depHour(hh->getPosition(), itAccA->getWorkPosition().getPosition(), itAccA->getWorkPosition().getOpening()));
00168         tempAccTrip.push_back(trip);
00169     }
00170 
00171     std::list<AGChild>::iterator itAccC;
00172     for (itAccC=childrenNeedingCarAccompaniment.begin() ; itAccC!= childrenNeedingCarAccompaniment.end() ; ++itAccC) {
00173         AGTrip trip(hh->getPosition(), itAccC->getSchoolLocation(), depHour(hh->getPosition(), itAccC->getSchoolLocation(), itAccC->getSchoolOpeining()));
00174         tempAccTrip.push_back(trip);
00175     }
00176 
00177     checkAndBuildTripConsistancy();
00178     if (isThereUnusedCar() && ! checkDriversScheduleMatching()) {
00179         makePossibleDriversDrive();
00180     }
00181 
00182     generateListTrips();
00183     return true;
00184 }
00185 
00186 bool
00187 AGWorkAndSchool::isThereUnusedCar() {
00188     return (hh->getCarNbr() > static_cast<int>(notNeedingDrivers.size() + personsDrivingCars.size()));
00189 }
00190 
00191 bool
00192 AGWorkAndSchool::checkAndBuildTripConsistancy() {
00193     bool finish = false;
00194     int diff1, diff2;
00195     int arrTime;
00196     std::list<AGTrip>::iterator it1, it2;
00197 
00198     while (!finish) {
00199         finish = true;
00200         for (it1=tempAccTrip.begin() ; it1!=tempAccTrip.end() ; ++it1) {
00201             for (it2=tempAccTrip.begin() ; it2 != tempAccTrip.end() ; ++it2) {
00202                 if (it1 == it2) {
00203                     continue;
00204                 }
00205                 diff1 = it2->getTime() - it1->getRideBackArrTime(this->timePerKm);
00206                 diff2 = it1->getTime() - it2->getRideBackArrTime(this->timePerKm);
00207 
00208                 if (diff1 < 0 || diff2 < 0) {
00209                     if (diff2 < diff1) {
00210                         arrTime = it2->getArrTime(this->timePerKm);
00211                         it2->addLayOver(*it1);
00212                         it2->setDepTime(it2->estimateDepTime(arrTime, this->timePerKm));
00213                         tempAccTrip.erase(it1);
00214                     } else {
00215                         arrTime = it1->getArrTime(this->timePerKm);
00216                         it1->addLayOver(*it2);
00217                         it1->setDepTime(it1->estimateDepTime(arrTime, this->timePerKm));
00218                         tempAccTrip.erase(it2);
00219                     }
00220                     finish = false;
00221                     break;
00222                 }
00223             }
00224             if (!finish) {
00225                 break; // return to while
00226             }
00227         }
00228     }
00229     return finish;
00230 }
00231 
00232 bool
00233 AGWorkAndSchool::checkDriversScheduleMatching() {
00234     bool check = false;
00235     std::list<AGTrip>::iterator itAccT;
00236     std::list<AGTrip>::iterator itDriT;
00237     std::list<AGAdult>::iterator itA;
00238     for (itAccT=tempAccTrip.begin() ; itAccT!=tempAccTrip.end() ; ++itAccT) {
00239         for (itDriT=tempTrip.begin() ; itDriT!=tempTrip.end() ; ++itDriT) {
00240             if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm)) {
00241                 check = true;
00242             }
00243         }
00244         for (itA=notNeedingDrivers.begin() ; itA!=notNeedingDrivers.end() ; ++itA) {
00245             if (!itA->isWorking()) {
00246                 check = true;
00247             } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening()) {
00248                 check = true;
00249             }
00250         }
00251         if (!check) { //at least one trip is not performed by the existing drivers because it is to late for them
00252             return false;
00253         }
00254         check = false;
00255     }
00256     return true;
00257 }
00258 
00259 void
00260 AGWorkAndSchool::generateListTrips() {
00261     int arrTime;
00262     std::list<AGTrip>::iterator itAccT;
00263     std::list<AGTrip>::iterator itDriT;
00264     std::list<AGAdult>::iterator itA;
00265     bool alreadyDone;
00266 
00270     for (itAccT=tempAccTrip.begin() ; itAccT!=tempAccTrip.end() ; ++itAccT) {
00271         alreadyDone = false;
00272         for (itDriT=tempTrip.begin() ; itDriT!=tempTrip.end() ; ++itDriT) {
00273             if (!alreadyDone) {
00274                 if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm) && !alreadyDone) {
00275                     //Add the accompaniment trip to the driver's trip OR new trip
00276                     if (itAccT->getRideBackArrTime(this->timePerKm) < itDriT->getTime()) {
00277                         //there is enough time to accompany people and go back home before going to work
00278                         itAccT->setVehicleName(itDriT->getVehicleName());
00279                         itAccT->addLayOver(itAccT->getArr());   //final destination is the last accompaniment stop: not the destination of the course
00280                         itAccT->setArr(hh->getPosition());      //final destination of the whole trip: home
00281                         partialActivityTrips.push_back(*itAccT);
00282                         alreadyDone = true;
00283                     } else {
00284                         //the driver drives people to their working place or school and goes directly to work after that
00285                         arrTime = itDriT->getArrTime(this->timePerKm);
00286                         itDriT->addLayOver(*itAccT);
00287                         itDriT->setDepTime(itDriT->estimateDepTime(arrTime, this->timePerKm));
00288                         //tempAccTrip.erase(itAccT);
00289                         //--itAccT; //because of erasure
00290                         alreadyDone = true;
00291                     }
00292                 }
00293             }
00294         }
00295 
00296         for (itA=notNeedingDrivers.begin() ; itA!=notNeedingDrivers.end() ; ++itA) {
00297             if (!itA->isWorking() && !alreadyDone) {
00298                 std::string nameC = getUnusedCar();
00299                 if (nameC.size() != 0) {
00300                     itAccT->setVehicleName(getUnusedCar());
00301                     itAccT->addLayOver(itAccT->getArr());
00302                     itAccT->setArr(hh->getPosition());
00303                     partialActivityTrips.push_back(*itAccT);
00304                     alreadyDone = true;
00305                 }
00306             } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening() && !alreadyDone) {
00307                 std::string nameC = getUnusedCar();
00308                 if (nameC.size() != 0) {
00309                     itAccT->setVehicleName(getUnusedCar());
00310                     itAccT->addLayOver(itAccT->getArr());
00311                     itAccT->setArr(hh->getPosition());
00312                     partialActivityTrips.push_back(*itAccT);
00313                     alreadyDone = true;
00314                 }
00315             }
00316         }
00317     }
00318 
00322     for (itDriT=tempTrip.begin() ; itDriT!=tempTrip.end() ; ++itDriT) {
00323         partialActivityTrips.push_back(*itDriT);
00324     }
00325 
00329     for (itA=personsDrivingCars.begin() ; itA!= personsDrivingCars.end() ; ++itA) {
00330         for (itDriT=tempTrip.begin() ; itDriT!=tempTrip.end() ; ++itDriT) {
00331             if (itA->getWorkPosition().getPosition() == itDriT->getArr()) {
00332                 AGTrip trip(itA->getWorkPosition().getPosition(), hh->getPosition(), itDriT->getVehicleName(), itA->getWorkPosition().getClosing());
00333                 partialActivityTrips.push_back(trip);
00334                 tempTrip.erase(itDriT);
00335                 break;
00336             }
00337         }
00338     }
00339 }
00340 
00341 std::string
00342 AGWorkAndSchool::getUnusedCar() {
00343     std::string nameCar = "";
00344     std::string nameCarUsed = "";
00345     //only two cars can be used in the household, so: the first one or the last one is not used.
00346     if (!tempTrip.empty()) {
00347         nameCarUsed = tempTrip.front().getVehicleName();
00348     } else if (!partialActivityTrips.empty()) {
00349         nameCarUsed = partialActivityTrips.front().getVehicleName();
00350     }
00351 
00352     if (nameCarUsed.size() != 0) {
00353         if (hh->cars.front().getName() == nameCarUsed) {
00354             nameCar = hh->cars.back().getName();
00355         } else {
00356             nameCar = hh->cars.front().getName();
00357         }
00358     }
00359     return nameCar;
00360 }
00361 
00362 void
00363 AGWorkAndSchool::makePossibleDriversDrive() {
00364     //give to a non working adult the ability to drive children or someone else.
00365     if (workingPeoplePossCar.size() + personsDrivingCars.size() + adultNeedingCarAccompaniment.size() != hh->getAdultNbr()) {
00366         std::list<AGAdult>::iterator itUA;
00367         for (itUA=hh->adults.begin() ; itUA!=hh->adults.end() ; ++itUA) {
00368             if (! itUA->isWorking()) {
00369                 notNeedingDrivers.push_back(*itUA);
00370                 break;
00371             }
00372         }
00373     }
00374 }
00375 
00376 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines