SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
AGWorkAndSchool.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Generates trips to work and to school
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2001-2015 DLR (http://www.dlr.de/) and contributors
14 // activitygen module
15 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include "AGWorkAndSchool.h"
37 #include <list>
38 #include "../city/AGCar.h"
39 
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
44 bool
46  //buildDestinations();
47  // generation of the waiting list for the accompaniment
49 
51 
52  if (myHousehold->getCarNbr() < (int)personsDrivingCars.size()) {
53  return false; //to rebuild the household
54  }
55  if (childrenNeedingCarAccompaniment.size() != 0 && myHousehold->getCarNbr() == 0) {
56  return false; //to rebuild the household
57  }
58  if (adultNeedingCarAccompaniment.size() != 0 && myHousehold->getCarNbr() == 0) {
59  return false;
60  }
61 
62  carAllocation();
63 
64  if (personsDrivingCars.empty() && notNeedingDrivers.empty()) {
65  genDone = true;
66  return true; // no trip to generate
67  }
68 
69  if (! carsToTrips()) {
70  return false;
71  }
72 
73  genDone = true;
74  return true;
75 }
76 
77 void
79  std::list<AGChild>::const_iterator itC;
80  for (itC = myHousehold->getChildren().begin(); itC != myHousehold->getChildren().end(); ++itC) {
81  if (itC->haveASchool()) {
82  if (this->availableTranspMeans(myHousehold->getPosition(), itC->getSchoolLocation()) == 0) {
83  //in this case the school is far from home and bus stations too
84  this->childrenNeedingCarAccompaniment.push_back(*itC);
85  }
86  }
87  }
88 }
89 
90 void
92  std::list<AGAdult>::const_iterator itA;
93  for (itA = myHousehold->getAdults().begin(); itA != myHousehold->getAdults().end(); ++itA) {
94  if (itA->isWorking()) {
95  if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) % 2 == 0) {
96  //not too close, to not being able to go by foot
97  if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) > 4) {
98  //too far from home ==> Car or Bus AND Car and bus are possible
99  workingPeoplePossCar.push_back(*itA);
100  } else if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) == 4) {
101  //only the car is possible (and there is one (use of possibleTranspMean))
102  if (myHousehold->getCarNbr() > (int)personsDrivingCars.size()) {
103  personsDrivingCars.push_back(*itA);
104  } else {
105  adultNeedingCarAccompaniment.push_back(*itA);
106  }
107  }
108  }
109  }
110  }
111 
112  // sometimes, people still have choice: when vehicles are available and their car take a bus.
113  std::list<AGAdult>::iterator it;
114  for (it = workingPeoplePossCar.begin(); it != workingPeoplePossCar.end(); ++it) {
115  if (possibleTranspMean(it->getWorkPosition().getPosition()) == 6 && myHousehold->getCarNbr() > (int)personsDrivingCars.size()) {
116  //car or bus (always because of workDestinations' construction) AND at least one car not used
117  if (myHousehold->getAdults().front().decide(this->carPreference)) {
118  personsDrivingCars.push_back(*it);
119  }
120  }
121  }
122 }
123 
124 void
126  // only two adults are possibles: no car, 1 car, 2 cars and more
127  // the only choice case: 1 car / 2 adults needing this car (otherwise no choice problems)
128  if (! personsDrivingCars.empty() && ! adultNeedingCarAccompaniment.empty()) {
129  //in that case there is only one element in each list and only one car.
130  if (adultNeedingCarAccompaniment.front().getWorkPosition().getOpening() >= personsDrivingCars.front().getWorkPosition().getOpening()) {
131  //we will invert the driver and the accompanied
133  adultNeedingCarAccompaniment.pop_front();
135  personsDrivingCars.pop_front();
136  }
137  }
138  if (personsDrivingCars.empty() && ! childrenNeedingCarAccompaniment.empty()) {
139  //at least one adult exists because no household contains less than one adult
140  if (workingPeoplePossCar.size() != myHousehold->getAdultNbr()) { //personsDrivingCars.size() + adultNeedingCarAccompaniment.size() is equal to 0
141  std::list<AGAdult>::const_iterator itUA;
142  for (itUA = myHousehold->getAdults().begin(); itUA != myHousehold->getAdults().end(); ++itUA) {
143  if (! itUA->isWorking()) {
144  notNeedingDrivers.push_back(*itUA);
145  break;
146  }
147  }
148  } else {
149  personsDrivingCars.push_back(workingPeoplePossCar.front());
150  workingPeoplePossCar.pop_front();
151  }
152  }
153 }
154 
155 bool
157  // check if the starting edge allows cars
159  return false;
160  }
161  std::list<AGAdult>::const_iterator itDriA;
162  std::list<AGCar>::const_iterator itCar = myHousehold->getCars().begin();
163  for (itDriA = personsDrivingCars.begin(); itDriA != personsDrivingCars.end(); ++itDriA) {
164  //check if the number of cars is lower than the number of drivers
165  if (itCar == myHousehold->getCars().end()) {
166  return false;
167  }
168  // check if the destination edge allows cars
169  if (!itDriA->getWorkPosition().getPosition().getStreet().allows(SVC_PASSENGER)) {
170  return false;
171  }
172  AGTrip trip(myHousehold->getPosition(), itDriA->getWorkPosition().getPosition(), *itCar, depHour(myHousehold->getPosition(), itDriA->getWorkPosition().getPosition(), itDriA->getWorkPosition().getOpening()));
173  ++itCar;
174  tempTrip.push_back(trip);
175  }
176 
177  std::list<AGAdult>::iterator itAccA;
178  for (itAccA = adultNeedingCarAccompaniment.begin(); itAccA != adultNeedingCarAccompaniment.end(); ++itAccA) {
179  AGTrip trip(myHousehold->getPosition(), itAccA->getWorkPosition().getPosition(), depHour(myHousehold->getPosition(), itAccA->getWorkPosition().getPosition(), itAccA->getWorkPosition().getOpening()));
180  tempAccTrip.push_back(trip);
181  }
182 
183  std::list<AGChild>::iterator itAccC;
184  for (itAccC = childrenNeedingCarAccompaniment.begin(); itAccC != childrenNeedingCarAccompaniment.end(); ++itAccC) {
185  AGTrip trip(myHousehold->getPosition(), itAccC->getSchoolLocation(), depHour(myHousehold->getPosition(), itAccC->getSchoolLocation(), itAccC->getSchoolOpening()));
186  tempAccTrip.push_back(trip);
187  }
188 
192  }
193 
195  return true;
196 }
197 
198 bool
200  return (myHousehold->getCarNbr() > static_cast<int>(notNeedingDrivers.size() + personsDrivingCars.size()));
201 }
202 
203 bool
205  bool finish = false;
206  int diff1, diff2;
207  int arrTime;
208  std::list<AGTrip>::iterator it1, it2;
209 
210  while (!finish) {
211  finish = true;
212  for (it1 = tempAccTrip.begin(); it1 != tempAccTrip.end(); ++it1) {
213  for (it2 = tempAccTrip.begin(); it2 != tempAccTrip.end(); ++it2) {
214  if (it1 == it2) {
215  continue;
216  }
217  diff1 = it2->getTime() - it1->getRideBackArrTime(this->timePerKm);
218  diff2 = it1->getTime() - it2->getRideBackArrTime(this->timePerKm);
219 
220  if (diff1 < 0 || diff2 < 0) {
221  if (diff2 < diff1) {
222  arrTime = it2->getArrTime(this->timePerKm);
223  it2->addLayOver(*it1);
224  it2->setDepTime(it2->estimateDepTime(arrTime, this->timePerKm));
225  tempAccTrip.erase(it1);
226  } else {
227  arrTime = it1->getArrTime(this->timePerKm);
228  it1->addLayOver(*it2);
229  it1->setDepTime(it1->estimateDepTime(arrTime, this->timePerKm));
230  tempAccTrip.erase(it2);
231  }
232  finish = false;
233  break;
234  }
235  }
236  if (!finish) {
237  break; // return to while
238  }
239  }
240  }
241  return finish;
242 }
243 
244 bool
246  bool check = false;
247  std::list<AGTrip>::iterator itAccT;
248  std::list<AGTrip>::iterator itDriT;
249  std::list<AGAdult>::iterator itA;
250  for (itAccT = tempAccTrip.begin(); itAccT != tempAccTrip.end(); ++itAccT) {
251  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
252  if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm)) {
253  check = true;
254  }
255  }
256  for (itA = notNeedingDrivers.begin(); itA != notNeedingDrivers.end(); ++itA) {
257  if (!itA->isWorking()) {
258  check = true;
259  } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening()) {
260  check = true;
261  }
262  }
263  if (!check) { //at least one trip is not performed by the existing drivers because it is to late for them
264  return false;
265  }
266  check = false;
267  }
268  return true;
269 }
270 
271 void
273  int arrTime;
274  std::list<AGTrip>::iterator itAccT;
275  std::list<AGTrip>::iterator itDriT;
276  std::list<AGAdult>::iterator itA;
277  bool alreadyDone;
278 
282  for (itAccT = tempAccTrip.begin(); itAccT != tempAccTrip.end(); ++itAccT) {
283  alreadyDone = false;
284  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
285  if (!alreadyDone) {
286  if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm) && !alreadyDone) {
287  //Add the accompaniment trip to the driver's trip OR new trip
288  if (itAccT->getRideBackArrTime(this->timePerKm) < itDriT->getTime()) {
289  //there is enough time to accompany people and go back home before going to work
290  itAccT->setVehicleName(itDriT->getVehicleName());
291  itAccT->addLayOver(itAccT->getArr());//final destination is the last accompaniment stop: not the destination of the course
292  itAccT->setArr(myHousehold->getPosition());//final destination of the whole trip: home
293  myPartialActivityTrips.push_back(*itAccT);
294  alreadyDone = true;
295  } else {
296  //the driver drives people to their working place or school and goes directly to work after that
297  arrTime = itDriT->getArrTime(this->timePerKm);
298  itDriT->addLayOver(*itAccT);
299  itDriT->setDepTime(itDriT->estimateDepTime(arrTime, this->timePerKm));
300  //tempAccTrip.erase(itAccT);
301  //--itAccT; //because of erasure
302  alreadyDone = true;
303  }
304  }
305  }
306  }
307 
308  for (itA = notNeedingDrivers.begin(); itA != notNeedingDrivers.end(); ++itA) {
309  if (!itA->isWorking() && !alreadyDone) {
310  std::string nameC = getUnusedCar();
311  if (nameC.size() != 0) {
312  itAccT->setVehicleName(getUnusedCar());
313  itAccT->addLayOver(itAccT->getArr());
314  itAccT->setArr(myHousehold->getPosition());
315  myPartialActivityTrips.push_back(*itAccT);
316  alreadyDone = true;
317  }
318  } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening() && !alreadyDone) {
319  std::string nameC = getUnusedCar();
320  if (nameC.size() != 0) {
321  itAccT->setVehicleName(getUnusedCar());
322  itAccT->addLayOver(itAccT->getArr());
323  itAccT->setArr(myHousehold->getPosition());
324  myPartialActivityTrips.push_back(*itAccT);
325  alreadyDone = true;
326  }
327  }
328  }
329  }
330 
334  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
335  myPartialActivityTrips.push_back(*itDriT);
336  }
337 
341  for (itA = personsDrivingCars.begin(); itA != personsDrivingCars.end(); ++itA) {
342  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
343  if (itA->getWorkPosition().getPosition() == itDriT->getArr()) {
344  AGTrip trip(itA->getWorkPosition().getPosition(), myHousehold->getPosition(), itDriT->getVehicleName(), itA->getWorkPosition().getClosing());
345  myPartialActivityTrips.push_back(trip);
346  tempTrip.erase(itDriT);
347  break;
348  }
349  }
350  }
351 }
352 
353 std::string
355  std::string nameCar = "";
356  std::string nameCarUsed = "";
357  //only two cars can be used in the household, so: the first one or the last one is not used.
358  if (!tempTrip.empty()) {
359  nameCarUsed = tempTrip.front().getVehicleName();
360  } else if (!myPartialActivityTrips.empty()) {
361  nameCarUsed = myPartialActivityTrips.front().getVehicleName();
362  }
363 
364  if (nameCarUsed.size() != 0) {
365  if (myHousehold->getCars().front().getName() == nameCarUsed) {
366  nameCar = myHousehold->getCars().back().getName();
367  } else {
368  nameCar = myHousehold->getCars().front().getName();
369  }
370  }
371  return nameCar;
372 }
373 
374 void
376  //give to a non working adult the ability to drive children or someone else.
378  std::list<AGAdult>::const_iterator itUA;
379  for (itUA = myHousehold->getAdults().begin(); itUA != myHousehold->getAdults().end(); ++itUA) {
380  if (! itUA->isWorking()) {
381  notNeedingDrivers.push_back(*itUA);
382  break;
383  }
384  }
385  }
386 }
387 
388 /****************************************************************************/
int depHour(AGPosition from, AGPosition to, int arrival)
Definition: AGActivity.cpp:115
void makePossibleDriversDrive()
const std::list< AGCar > & getCars() const
const AGStreet & getStreet() const
Provides the street this AGPosition is located on.
Definition: AGPosition.cpp:108
std::list< AGAdult > notNeedingDrivers
SUMOReal carPreference
Definition: AGActivity.h:122
std::list< AGTrip > tempAccTrip
SUMOReal getPosition() const
Provides the relative position of this AGPosition on the street.
Definition: AGPosition.cpp:114
bool allows(const SUMOVehicleClass vclass) const
Returns whether the given vehicle class is allowed on this street.
Definition: AGStreet.cpp:80
int getCarNbr()
Definition: AGHousehold.cpp:89
std::list< AGAdult > adultNeedingCarAccompaniment
int availableTranspMeans(AGPosition from, AGPosition to)
Definition: AGActivity.cpp:92
AGHousehold * myHousehold
Definition: AGActivity.h:110
std::list< AGAdult > personsDrivingCars
const std::list< AGAdult > & getAdults() const
bool checkDriversScheduleMatching()
vehicle is a passenger car (a "normal" car)
AGPosition getPosition()
std::list< AGAdult > workingPeoplePossCar
std::list< AGChild > childrenNeedingCarAccompaniment
std::list< AGTrip > tempTrip
int possibleTranspMean(AGPosition destination)
Definition: AGActivity.cpp:55
std::list< AGTrip > myPartialActivityTrips
Definition: AGActivity.h:115
unsigned int getAdultNbr()
Definition: AGHousehold.cpp:99
void buildChildrenAccompaniment()
SUMOReal timePerKm
Definition: AGActivity.h:118
void buildWorkDestinations()
std::string getUnusedCar()
bool checkAndBuildTripConsistancy()
Definition: AGTrip.h:48
const std::list< AGChild > & getChildren() const
bool genDone
Definition: AGActivity.h:117