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