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