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