Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/activitygen/AGActivityGenHandler.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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
/****************************************************************************/
16
/// @file AGActivityGenHandler.cpp
17
/// @author Piotr Woznica
18
/// @author Daniel Krajzewicz
19
/// @author Jakob Erdmann
20
/// @author Michael Behrisch
21
/// @author Walter Bamberger
22
/// @date July 2010
23
///
24
// The handler for parsing the statistics file.
25
/****************************************************************************/
26
#include <config.h>
27
28
#include "AGActivityGenHandler.h"
29
#include <iostream>
30
#include <utility>
31
#include <map>
32
#include <string>
33
#include <utils/options/OptionsCont.h>
34
#include <utils/common/MsgHandler.h>
35
#include <utils/common/StringTokenizer.h>
36
#include <utils/common/UtilExceptions.h>
37
#include <utils/xml/SUMOSAXHandler.h>
38
#include <utils/xml/SUMOXMLDefinitions.h>
39
#include <router/RONet.h>
40
#include "city/AGCity.h"
41
#include "city/AGSchool.h"
42
#include "city/AGPosition.h"
43
#include "city/AGBusLine.h"
44
45
46
// ===========================================================================
47
// method definitions
48
// ===========================================================================
49
AGActivityGenHandler::AGActivityGenHandler(AGCity& city, RONet* net)
50
: SUMOSAXHandler("sumo-stat"),
51
myCity(city), net(net) {}
52
53
54
AGActivityGenHandler::~AGActivityGenHandler() {}
55
56
57
void
58
AGActivityGenHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
59
try {
60
switch (element) {
61
case AGEN_TAG_GENERAL:
62
parseGeneralCityInfo(attrs);
63
break;
64
case AGEN_TAG_STREET:
65
parseStreets(attrs);
66
break;
67
case AGEN_TAG_WORKHOURS:
68
parseWorkHours();
69
break;
70
case AGEN_TAG_OPENING:
71
parseOpeningHour(attrs);
72
break;
73
case AGEN_TAG_CLOSING:
74
parseClosingHour(attrs);
75
break;
76
case AGEN_TAG_SCHOOLS:
77
parseSchools();
78
break;
79
case AGEN_TAG_SCHOOL:
80
parseSchool(attrs);
81
break;
82
case AGEN_TAG_BUSSTATION:
83
parseBusStation(attrs);
84
break;
85
case AGEN_TAG_BUSLINE:
86
parseBusLine(attrs);
87
break;
88
case AGEN_TAG_STATIONS:
89
parseStations();
90
break;
91
case AGEN_TAG_REV_STATIONS:
92
parseRevStations();
93
break;
94
case AGEN_TAG_STATION:
95
parseStation(attrs);
96
break;
97
case AGEN_TAG_FREQUENCY:
98
parseFrequency(attrs);
99
break;
100
case AGEN_TAG_POPULATION:
101
parsePopulation();
102
break;
103
/*case AGEN_TAG_CHILD_ACOMP:
104
parseChildrenAccompaniment();
105
break;*/
106
case AGEN_TAG_BRACKET:
107
parseBracket(attrs);
108
break;
109
case AGEN_TAG_PARAM:
110
parseParameters(attrs);
111
break;
112
case AGEN_TAG_ENTRANCE:
113
parseCityGates(attrs);
114
break;
115
default:
116
break;
117
}
118
} catch (const std::exception& e) {
119
throw ProcessError(e.what());
120
}
121
}
122
123
124
void
125
AGActivityGenHandler::parseGeneralCityInfo(const SUMOSAXAttributes& attrs) {
126
try {
127
bool ok;
128
myCity.statData.inhabitants = attrs.getInt(AGEN_ATTR_INHABITANTS);
129
myCity.statData.households = attrs.getInt(AGEN_ATTR_HOUSEHOLDS);
130
myCity.statData.limitAgeChildren = attrs.getOpt<int>(AGEN_ATTR_CHILDREN, nullptr, ok, 18);
131
myCity.statData.limitAgeRetirement = attrs.getOpt<int>(AGEN_ATTR_RETIREMENT, nullptr, ok, 63);
132
myCity.statData.carRate = attrs.getOpt<double>(AGEN_ATTR_CARS, nullptr, ok, 0.58);
133
myCity.statData.unemployement = attrs.getOpt<double>(AGEN_ATTR_UNEMPLOYEMENT, nullptr, ok, 0.06);
134
myCity.statData.laborDemand = attrs.getOpt<double>(AGEN_ATTR_LABORDEMAND, nullptr, ok, 1.05);
135
myCity.statData.maxFootDistance = attrs.getOpt<double>(AGEN_ATTR_MAX_FOOT_DIST, nullptr, ok, 300.0);
136
myCity.statData.incomingTraffic = attrs.getOpt<int>(AGEN_ATTR_IN_TRAFFIC, nullptr, ok, 0);
137
myCity.statData.outgoingTraffic = attrs.getOpt<int>(AGEN_ATTR_OUT_TRAFFIC, nullptr, ok, 0);
138
} catch (const std::exception& e) {
139
WRITE_ERROR("Error while parsing the element " +
140
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_GENERAL) + ": " +
141
e.what());
142
throw ProcessError();
143
}
144
}
145
146
void
147
AGActivityGenHandler::parseParameters(const SUMOSAXAttributes& attrs) {
148
try {
149
bool ok;
150
myCity.statData.carPreference = attrs.getOpt<double>(AGEN_ATTR_CARPREF, nullptr, ok, 0.0);
151
myCity.statData.speedTimePerKm = attrs.getOpt<double>(AGEN_ATTR_CITYSPEED, nullptr, ok, 360.0);
152
myCity.statData.freeTimeActivityRate = attrs.getOpt<double>(AGEN_ATTR_FREETIMERATE, nullptr, ok, 0.15);
153
myCity.statData.uniformRandomTrafficRate = attrs.getOpt<double>(AGEN_ATTR_UNI_RAND_TRAFFIC, nullptr, ok, 0.0);
154
myCity.statData.departureVariation = attrs.getOpt<double>(AGEN_ATTR_DEP_VARIATION, nullptr, ok, 0.0);
155
} catch (const std::exception& e) {
156
WRITE_ERROR("Error while parsing the element " +
157
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_PARAM) + ": " +
158
e.what());
159
throw ProcessError();
160
}
161
}
162
163
void
164
AGActivityGenHandler::parseStreets(const SUMOSAXAttributes& attrs) {
165
try {
166
double pop = 0;
167
double work = 0;
168
169
std::string eid = attrs.getString(SUMO_ATTR_EDGE);
170
if (attrs.hasAttribute(AGEN_ATTR_POPULATION)) {
171
pop = attrs.getFloat(AGEN_ATTR_POPULATION);
172
if (std::isnan(pop)) {
173
pop = 0;
174
WRITE_WARNINGF(TL("Invalid % value of edge % is treated as zero."), SUMOXMLDefinitions::Attrs.getString(AGEN_ATTR_POPULATION), eid);
175
}
176
}
177
if (attrs.hasAttribute(AGEN_ATTR_OUT_WORKPOSITION)) {
178
work = attrs.getFloat(AGEN_ATTR_OUT_WORKPOSITION);
179
if (std::isnan(work)) {
180
work = 0;
181
WRITE_WARNINGF(TL("Invalid % value of edge % is treated as zero."), SUMOXMLDefinitions::Attrs.getString(AGEN_ATTR_OUT_WORKPOSITION), eid);
182
}
183
}
184
AGStreet* street = dynamic_cast<AGStreet*>(net->getEdge(eid));
185
if (street == nullptr) {
186
WRITE_ERRORF(TL("Edge '%' is not known."), eid);
187
return;
188
}
189
street->setPopulation(pop * street->getLength());
190
street->setWorkplaceNumber(work * street->getLength());
191
myCity.streets.push_back(street);
192
} catch (const std::exception& e) {
193
WRITE_ERROR("Error while parsing the element " +
194
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_STREET) + ": " +
195
e.what());
196
throw ProcessError();
197
}
198
}
199
200
void
201
AGActivityGenHandler::parseCityGates(const SUMOSAXAttributes& attrs) {
202
try {
203
std::string edge = attrs.getString(SUMO_ATTR_EDGE);
204
double positionOnEdge = attrs.getFloat(SUMO_ATTR_POSITION);
205
AGPosition posi(myCity.getStreet(edge), positionOnEdge);
206
myCity.statData.incoming[(int)myCity.cityGates.size()] = attrs.getFloat(AGEN_ATTR_INCOMING);
207
myCity.statData.outgoing[(int)myCity.cityGates.size()] = attrs.getFloat(AGEN_ATTR_OUTGOING);
208
myCity.cityGates.push_back(posi);
209
210
} catch (const std::exception& e) {
211
WRITE_ERROR("Error while parsing the element " +
212
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_CITYGATES) + ": " +
213
e.what());
214
throw ProcessError();
215
}
216
}
217
218
void
219
AGActivityGenHandler::parseWorkHours() {
220
myCurrentObject = "workHours";
221
}
222
223
void
224
AGActivityGenHandler::parseOpeningHour(const SUMOSAXAttributes& attrs) {
225
if (myCurrentObject == "workHours") {
226
try {
227
myCity.statData.beginWorkHours[attrs.getInt(AGEN_ATTR_HOUR)] = attrs.getFloat(AGEN_ATTR_PROP);
228
229
} catch (const std::exception& e) {
230
WRITE_ERROR("Error while parsing the element " +
231
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_OPENING) + ": "
232
+ e.what());
233
throw ProcessError();
234
}
235
}
236
}
237
238
void
239
AGActivityGenHandler::parseClosingHour(const SUMOSAXAttributes& attrs) {
240
if (myCurrentObject == "workHours") {
241
try {
242
myCity.statData.endWorkHours[attrs.getInt(AGEN_ATTR_HOUR)] = attrs.getFloat(AGEN_ATTR_PROP);
243
244
} catch (const std::exception& e) {
245
WRITE_ERROR("Error while parsing the element " +
246
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_CLOSING) + ": "
247
+ e.what());
248
throw ProcessError();
249
}
250
}
251
}
252
253
void
254
AGActivityGenHandler::parseSchools() {
255
myCurrentObject = "schools";
256
}
257
258
void
259
AGActivityGenHandler::parseSchool(const SUMOSAXAttributes& attrs) {
260
try {
261
bool ok = true;
262
std::string edge = attrs.getString(SUMO_ATTR_EDGE, &ok);
263
if (!ok) {
264
throw ProcessError("Cannot parse edge attribute");
265
}
266
double positionOnEdge = attrs.hasAttribute(SUMO_ATTR_POSITION) ? attrs.getFloat(SUMO_ATTR_POSITION) : 0.;
267
AGPosition posi(myCity.getStreet(edge), positionOnEdge);
268
int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE);
269
int endAge = attrs.getInt(AGEN_ATTR_ENDAGE);
270
int capacity = attrs.getInt(AGEN_ATTR_CAPACITY);
271
int openingHour = attrs.getInt(AGEN_ATTR_OPENING);
272
int closingHour = attrs.getInt(AGEN_ATTR_CLOSING);
273
AGSchool sch(capacity, posi, beginAge, endAge, openingHour, closingHour);
274
myCity.schools.push_back(sch);
275
276
} catch (const std::exception& e) {
277
WRITE_ERROR("Error while parsing the element " +
278
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_SCHOOL) + ": " +
279
e.what());
280
throw ProcessError();
281
}
282
}
283
284
void
285
AGActivityGenHandler::parseBusStation(const SUMOSAXAttributes& attrs) {
286
try {
287
bool ok = true;
288
std::string edge = attrs.getString(SUMO_ATTR_EDGE, &ok);
289
if (!ok) {
290
throw ProcessError("Cannot parse edge attribute");
291
};
292
double positionOnEdge = attrs.hasAttribute(SUMO_ATTR_POSITION) ? attrs.getFloat(SUMO_ATTR_POSITION) : 0.;
293
int id = attrs.getInt(SUMO_ATTR_ID);
294
AGPosition posi(myCity.getStreet(edge), positionOnEdge);
295
myCity.statData.busStations.insert(std::pair<int, AGPosition>(id, posi));
296
297
} catch (const std::exception& e) {
298
WRITE_ERROR("Error while parsing the element " +
299
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSSTATION) + ": " +
300
e.what());
301
throw ProcessError();
302
}
303
}
304
305
void
306
AGActivityGenHandler::parseBusLine(const SUMOSAXAttributes& attrs) {
307
try {
308
myCurrentObject = "busLine";
309
AGBusLine busL(attrs.getString(SUMO_ATTR_ID));
310
busL.setMaxTripTime(attrs.getInt(AGEN_ATTR_MAX_TRIP_DURATION));
311
myCity.busLines.push_front(busL);
312
currentBusLine = &*myCity.busLines.begin();
313
314
} catch (const std::exception& e) {
315
WRITE_ERROR("Error while parsing the element " +
316
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSLINE) + ": " +
317
e.what());
318
throw ProcessError();
319
}
320
}
321
322
void
323
AGActivityGenHandler::parseStations() {
324
isRevStation = false;
325
}
326
327
void
328
AGActivityGenHandler::parseRevStations() {
329
isRevStation = true;
330
}
331
332
void
333
AGActivityGenHandler::parseStation(const SUMOSAXAttributes& attrs) {
334
if (myCurrentObject != "busLine") {
335
return;
336
}
337
338
try {
339
bool ok = true;
340
int refID = attrs.get<int>(SUMO_ATTR_REFID, myCurrentObject.c_str(), ok);
341
if (!ok) {
342
throw ProcessError();
343
}
344
if (myCity.statData.busStations.count(refID) == 0) {
345
throw ProcessError(TLF("Unknown bus station '%'.", refID));
346
}
347
if (!isRevStation) {
348
currentBusLine->locateStation(myCity.statData.busStations.find(refID)->second);
349
} else {
350
currentBusLine->locateRevStation(myCity.statData.busStations.find(refID)->second);
351
}
352
353
} catch (const std::exception& e) {
354
WRITE_ERROR("Error while parsing the element " +
355
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_STATION) + ": " +
356
e.what());
357
throw ProcessError();
358
}
359
}
360
361
void
362
AGActivityGenHandler::parseFrequency(const SUMOSAXAttributes& attrs) {
363
if (myCurrentObject != "busLine") {
364
return;
365
}
366
367
try {
368
int beginB = attrs.getInt(SUMO_ATTR_BEGIN);
369
int endB = attrs.getInt(SUMO_ATTR_END);
370
int rateB = attrs.getInt(AGEN_ATTR_RATE);
371
currentBusLine->generateBuses(beginB, endB, rateB);
372
373
} catch (const std::exception& e) {
374
WRITE_ERROR("Error while parsing the element " +
375
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_FREQUENCY) + ": " +
376
e.what());
377
throw ProcessError();
378
}
379
}
380
381
void
382
AGActivityGenHandler::parsePopulation() {
383
myCurrentObject = "population";
384
}
385
386
void
387
AGActivityGenHandler::parseBracket(const SUMOSAXAttributes& attrs) {
388
try {
389
390
int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE); //included in the bracket
391
int endAge = attrs.getInt(AGEN_ATTR_ENDAGE); //NOT included in the bracket
392
bool overlapping = false;
393
// evaluate age
394
if (beginAge < endAge) {
395
for (auto it = myCity.statData.ageSpan.begin(); it != myCity.statData.ageSpan.end(); ++it) {
396
if (!(beginAge >= it->second || endAge <= it->first)) {
397
overlapping = true;
398
}
399
}
400
if (!overlapping) {
401
myCity.statData.ageSpan[beginAge] = endAge;
402
403
if (myCurrentObject == "population") {
404
myCity.statData.population[endAge] = attrs.getInt(AGEN_ATTR_PEOPLENBR);
405
}
406
} else {
407
WRITE_ERROR("Error while parsing the element " +
408
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population is overlapping");
409
throw ProcessError();
410
}
411
} else {
412
WRITE_ERROR("Error while parsing the element " +
413
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population are not properly set");
414
throw ProcessError();
415
}
416
417
} catch (const std::exception& e) {
418
WRITE_ERROR("Error while parsing the element " +
419
SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": " +
420
e.what());
421
throw ProcessError();
422
}
423
}
424
425
426
/****************************************************************************/
427
428