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