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