|
SUMO - Simulation of Urban MObility
|
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 /****************************************************************************/