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