Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/vehicle/SUMOVehicleParserHelper.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2008-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file SUMOVehicleParserHelper.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Axel Wegener
18
/// @author Michael Behrisch
19
/// @author Laura Bieker
20
/// @author Mirko Barthauer
21
/// @date Mon, 07.04.2008
22
///
23
// Helper methods for parsing vehicle attributes
24
/****************************************************************************/
25
#include <config.h>
26
27
#include <utils/common/FileHelpers.h>
28
#include <utils/common/MsgHandler.h>
29
#include <utils/common/RandHelper.h>
30
#include <utils/common/StringTokenizer.h>
31
#include <utils/common/StringUtils.h>
32
#include <utils/common/ToString.h>
33
#include <utils/common/UtilExceptions.h>
34
#include <utils/options/OptionsCont.h>
35
#include <utils/emissions/PollutantsInterface.h>
36
#include <utils/router/IntermodalNetwork.h>
37
#include <utils/vehicle/SUMOVTypeParameter.h>
38
#include <utils/vehicle/SUMOVehicleParameter.h>
39
#include <utils/xml/SUMOSAXAttributes.h>
40
41
#include "SUMOVehicleParserHelper.h"
42
43
44
// ===========================================================================
45
// static members
46
// ===========================================================================
47
48
SUMOVehicleParserHelper::CFAttrMap SUMOVehicleParserHelper::allowedCFModelAttrs;
49
SUMOVehicleParserHelper::LCAttrMap SUMOVehicleParserHelper::allowedLCModelAttrs;
50
51
52
// ===========================================================================
53
// method definitions
54
// ===========================================================================
55
56
SUMOVehicleParameter*
57
SUMOVehicleParserHelper::parseFlowAttributes(SumoXMLTag tag, const SUMOSAXAttributes& attrs, const bool hardFail, const bool needID,
58
const SUMOTime beginDefault, const SUMOTime endDefault, const bool allowInternalRoutes) {
59
// first parse ID
60
const std::string id = attrs.hasAttribute(SUMO_ATTR_ID) ? parseID(attrs, tag) : "";
61
// check if ID is valid
62
if (!needID || !id.empty()) {
63
if (needID && !SUMOXMLDefinitions::isValidVehicleID(id)) {
64
return handleVehicleError(hardFail, nullptr, "Invalid flow id '" + id + "'.");
65
}
66
// declare flags
67
const bool hasPeriod = attrs.hasAttribute(SUMO_ATTR_PERIOD);
68
const bool hasVPH = attrs.hasAttribute(SUMO_ATTR_VEHSPERHOUR);
69
const bool hasPPH = attrs.hasAttribute(SUMO_ATTR_PERSONSPERHOUR);
70
const bool hasCPH = attrs.hasAttribute(SUMO_ATTR_CONTAINERSPERHOUR);
71
const bool hasPH = attrs.hasAttribute(SUMO_ATTR_PERHOUR);
72
const bool hasXPH = hasVPH || hasPPH || hasCPH || hasPH;
73
const bool hasProb = attrs.hasAttribute(SUMO_ATTR_PROB);
74
const bool hasNumber = attrs.hasAttribute(SUMO_ATTR_NUMBER);
75
const bool hasBegin = attrs.hasAttribute(SUMO_ATTR_BEGIN);
76
const bool hasEnd = attrs.hasAttribute(SUMO_ATTR_END);
77
SumoXMLAttr PERHOUR = SUMO_ATTR_PERHOUR;
78
if (hasVPH) {
79
PERHOUR = SUMO_ATTR_VEHSPERHOUR;
80
}
81
if (hasPPH) {
82
PERHOUR = SUMO_ATTR_PERSONSPERHOUR;
83
}
84
if (hasCPH) {
85
PERHOUR = SUMO_ATTR_CONTAINERSPERHOUR;
86
}
87
if (hasXPH && !(hasVPH ^ hasPPH ^ hasCPH ^ hasPH)) {
88
return handleVehicleError(hardFail, nullptr,
89
"At most one of '" + attrs.getName(SUMO_ATTR_PERHOUR) +
90
"', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
91
"', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
92
"' and '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
93
"' has to be given in the definition of " + toString(tag) + " '" + id + "'.");
94
}
95
if (hasPeriod && hasXPH) {
96
return handleVehicleError(hardFail, nullptr,
97
"At most one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
98
"' and '" + attrs.getName(PERHOUR) +
99
"' has to be given in the definition of "
100
+ toString(tag) + " '" + id + "'.");
101
}
102
if (hasPeriod && hasProb) {
103
return handleVehicleError(hardFail, nullptr,
104
"At most one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
105
"' and '" + attrs.getName(SUMO_ATTR_PROB) +
106
"' has to be given in the definition of "
107
+ toString(tag) + " '" + id + "'.");
108
}
109
if (hasProb && hasXPH) {
110
return handleVehicleError(hardFail, nullptr,
111
"At most one of '" + attrs.getName(SUMO_ATTR_PROB) +
112
"' and '" + attrs.getName(PERHOUR) +
113
"' has to be given in the definition of "
114
+ toString(tag) + " '" + id + "'.");
115
}
116
if (hasPeriod || hasXPH || hasProb) {
117
if (hasEnd && hasNumber) {
118
return handleVehicleError(hardFail, nullptr,
119
"If '" + attrs.getName(SUMO_ATTR_PERIOD) +
120
"', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
121
"', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
122
"', '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
123
"', '" + attrs.getName(SUMO_ATTR_PERHOUR) +
124
"' or '" + attrs.getName(SUMO_ATTR_PROB) +
125
"' are given at most one of '" + attrs.getName(SUMO_ATTR_END) +
126
"' and '" + attrs.getName(SUMO_ATTR_NUMBER) +
127
"' are allowed in "
128
+ toString(tag) + " '" + id + "'.");
129
}
130
} else {
131
if (!hasNumber) {
132
return handleVehicleError(hardFail, nullptr,
133
"At least one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
134
"', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
135
"', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
136
"', '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
137
"', '" + attrs.getName(SUMO_ATTR_PERHOUR) +
138
"', '" + attrs.getName(SUMO_ATTR_PROB) +
139
"', and '" + attrs.getName(SUMO_ATTR_NUMBER) +
140
"' is needed in "
141
+ toString(tag) + " '" + id + "'.");
142
}
143
}
144
// declare flow
145
SUMOVehicleParameter* flowParameter = new SUMOVehicleParameter();
146
// set tag
147
flowParameter->tag = tag;
148
// set id
149
flowParameter->id = id;
150
if (tag == SUMO_TAG_PERSONFLOW) {
151
flowParameter->vtypeid = DEFAULT_PEDTYPE_ID;
152
}
153
if (tag == SUMO_TAG_CONTAINERFLOW) {
154
flowParameter->vtypeid = DEFAULT_CONTAINERTYPE_ID;
155
}
156
// parse common vehicle attributes
157
try {
158
parseCommonAttributes(attrs, flowParameter, tag, allowInternalRoutes);
159
} catch (ProcessError& attributeError) {
160
// check if continue handling another vehicles or stop handling
161
if (hardFail) {
162
throw ProcessError(attributeError.what());
163
} else {
164
return nullptr;
165
}
166
}
167
// parse period
168
bool poissonFlow = false;
169
if (hasPeriod) {
170
bool ok = true;
171
const std::string description = attrs.get<std::string>(SUMO_ATTR_PERIOD, id.c_str(), ok);
172
const std::string distName = description.substr(0, description.find('('));
173
if (distName == "exp") {
174
// declare rate
175
double rate = -1;
176
// parse rate
177
try {
178
rate = StringUtils::toDouble(description.substr(distName.size() + 1, description.size() - distName.size() - 2));
179
} catch (ProcessError& attributeError) {
180
// check if continue handling another vehicles or stop handling
181
if (hardFail) {
182
throw ProcessError(attributeError.what());
183
} else {
184
return nullptr;
185
}
186
}
187
if (rate <= 0) {
188
return handleVehicleError(hardFail, flowParameter, "Invalid rate parameter for exponentially distributed period in the definition of " + toString(tag) + " '" + id + "'.");
189
}
190
flowParameter->poissonRate = rate;
191
poissonFlow = true;
192
} else {
193
flowParameter->repetitionOffset = attrs.getSUMOTimeReporting(SUMO_ATTR_PERIOD, id.c_str(), ok);
194
}
195
if (!ok) {
196
return handleVehicleError(hardFail, flowParameter);
197
} else {
198
flowParameter->parametersSet |= VEHPARS_PERIOD_SET;
199
}
200
}
201
// parse vehicle/person/container/etc per hour
202
if (hasXPH) {
203
bool ok = true;
204
const double vph = attrs.get<double>(PERHOUR, id.c_str(), ok);
205
if (!ok) {
206
return handleVehicleError(hardFail, flowParameter);
207
} else if (vph <= 0) {
208
return handleVehicleError(hardFail, flowParameter, "Invalid repetition rate in the definition of " + toString(tag) + " '" + id + "'.");
209
} else {
210
if (vph != 0) {
211
flowParameter->repetitionOffset = TIME2STEPS(3600. / vph);
212
}
213
flowParameter->parametersSet |= VEHPARS_VPH_SET;
214
}
215
}
216
// parse probability
217
if (hasProb) {
218
bool ok = true;
219
flowParameter->repetitionProbability = attrs.get<double>(SUMO_ATTR_PROB, id.c_str(), ok);
220
if (!ok) {
221
return handleVehicleError(hardFail, flowParameter);
222
} else if (flowParameter->repetitionProbability <= 0 || flowParameter->repetitionProbability > 1) {
223
return handleVehicleError(hardFail, flowParameter, "Invalid repetition probability in the definition of " + toString(tag) + " '" + id + "'.");
224
} else {
225
flowParameter->parametersSet |= VEHPARS_PROB_SET;
226
}
227
}
228
// set default begin
229
flowParameter->depart = beginDefault;
230
// parse begin
231
if (hasBegin) {
232
// first get begin
233
bool ok = true;
234
const std::string begin = attrs.get<std::string>(SUMO_ATTR_BEGIN, id.c_str(), ok);
235
if (!ok) {
236
return handleVehicleError(hardFail, flowParameter);
237
} else {
238
// parse begin
239
std::string errorMsg;
240
if (!SUMOVehicleParameter::parseDepart(begin, toString(tag), id, flowParameter->depart, flowParameter->departProcedure, errorMsg, "begin")) {
241
return handleVehicleError(hardFail, flowParameter, errorMsg);
242
}
243
}
244
}
245
if (flowParameter->depart < 0) {
246
return handleVehicleError(hardFail, flowParameter, "Negative begin time in the definition of " + toString(tag) + " '" + id + "'.");
247
}
248
// set default end
249
flowParameter->repetitionEnd = endDefault;
250
if (flowParameter->repetitionEnd < 0) {
251
flowParameter->repetitionEnd = SUMOTime_MAX;
252
}
253
// parse end
254
if (hasEnd) {
255
bool ok = true;
256
flowParameter->repetitionEnd = attrs.getSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok);
257
if (!ok) {
258
return handleVehicleError(hardFail, flowParameter);
259
} else {
260
flowParameter->parametersSet |= VEHPARS_END_SET;
261
}
262
} else if (flowParameter->departProcedure == DepartDefinition::TRIGGERED) {
263
if (!hasNumber) {
264
return handleVehicleError(hardFail, flowParameter, toString(tag) + " '" + id + "' with triggered begin must define 'number'.");
265
} else {
266
flowParameter->repetitionEnd = flowParameter->depart;
267
}
268
} else if ((endDefault == SUMOTime_MAX || endDefault < 0) && (!hasNumber || (!hasProb && !hasPeriod && !hasXPH))) {
269
WRITE_WARNINGF(TL("Undefined end for % '%', defaulting to 24hour duration."), toString(tag), id);
270
flowParameter->repetitionEnd = flowParameter->depart + TIME2STEPS(24 * 3600);
271
}
272
if (flowParameter->repetitionEnd < flowParameter->depart) {
273
std::string flow = toString(tag);
274
flow[0] = (char)::toupper((char)flow[0]);
275
return handleVehicleError(hardFail, flowParameter, flow + " '" + id + "' ends before its begin time.");
276
}
277
// parse number
278
if (hasNumber) {
279
bool ok = true;
280
flowParameter->repetitionNumber = attrs.get<int>(SUMO_ATTR_NUMBER, id.c_str(), ok);
281
if (!ok) {
282
return handleVehicleError(hardFail, flowParameter);
283
} else {
284
flowParameter->parametersSet |= VEHPARS_NUMBER_SET;
285
if (flowParameter->repetitionNumber == 0) {
286
std::string flow = toString(tag);
287
flow[0] = (char)::toupper((char)flow[0]);
288
WRITE_WARNING(flow + " '" + id + "' has no instances; will skip it.");
289
flowParameter->repetitionEnd = flowParameter->depart;
290
} else {
291
if (flowParameter->repetitionNumber < 0) {
292
return handleVehicleError(hardFail, flowParameter, "Negative repetition number in the definition of " + toString(tag) + " '" + id + "'.");
293
}
294
if (flowParameter->repetitionOffset < 0 && !hasProb) {
295
if (poissonFlow) {
296
flowParameter->repetitionEnd = SUMOTime_MAX;
297
} else {
298
flowParameter->repetitionOffset = (flowParameter->repetitionEnd - flowParameter->depart) / flowParameter->repetitionNumber;
299
}
300
}
301
}
302
}
303
} else {
304
// interpret repetitionNumber
305
if (flowParameter->repetitionProbability > 0) {
306
flowParameter->repetitionNumber = std::numeric_limits<int>::max();
307
} else {
308
if (flowParameter->repetitionOffset <= 0) {
309
if (poissonFlow) {
310
// number is random but flow has a fixed end time
311
flowParameter->repetitionNumber = std::numeric_limits<int>::max();
312
} else {
313
return handleVehicleError(hardFail, flowParameter, "Invalid repetition rate in the definition of " + toString(tag) + " '" + id + "'.");
314
}
315
} else {
316
if (flowParameter->repetitionEnd == SUMOTime_MAX) {
317
flowParameter->repetitionNumber = std::numeric_limits<int>::max();
318
} else {
319
const SUMOTime repLength = flowParameter->repetitionEnd - flowParameter->depart;
320
flowParameter->repetitionNumber = (int)ceil((double)repLength / (double)flowParameter->repetitionOffset);
321
}
322
}
323
}
324
}
325
// all ok, then return flow parameter
326
return flowParameter;
327
} else {
328
return handleVehicleError(hardFail, nullptr, toString(tag) + " cannot be created");
329
}
330
}
331
332
333
SUMOVehicleParameter*
334
SUMOVehicleParserHelper::parseVehicleAttributes(int element, const SUMOSAXAttributes& attrs, const bool hardFail, const bool optionalID, const bool skipDepart, const bool allowInternalRoutes) {
335
// declare vehicle ID
336
std::string id;
337
// for certain vehicles, ID can be optional
338
if (optionalID) {
339
bool ok = true;
340
id = attrs.getOpt<std::string>(SUMO_ATTR_ID, nullptr, ok, "");
341
if (!ok) {
342
return handleVehicleError(hardFail, nullptr);
343
}
344
} else {
345
// parse ID
346
id = parseID(attrs, (SumoXMLTag)element);
347
}
348
// only continue if id is valid, or if is optional
349
if (optionalID || !id.empty()) {
350
// declare vehicle parameter
351
SUMOVehicleParameter* vehicleParameter = new SUMOVehicleParameter();
352
vehicleParameter->id = id;
353
if (element == SUMO_TAG_PERSON) {
354
vehicleParameter->vtypeid = DEFAULT_PEDTYPE_ID;
355
} else if (element == SUMO_TAG_CONTAINER) {
356
vehicleParameter->vtypeid = DEFAULT_CONTAINERTYPE_ID;
357
}
358
// parse common attributes
359
try {
360
parseCommonAttributes(attrs, vehicleParameter, (SumoXMLTag)element, allowInternalRoutes);
361
} catch (ProcessError& attributeError) {
362
// check if continue handling another vehicles or stop handling
363
if (hardFail) {
364
throw ProcessError(attributeError.what());
365
} else {
366
return nullptr;
367
}
368
}
369
// check depart
370
if (!skipDepart) {
371
bool ok = true;
372
const std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPART, vehicleParameter->id.c_str(), ok);
373
if (!ok) {
374
return handleVehicleError(hardFail, vehicleParameter);
375
}
376
// now parse depart
377
std::string departErrorMsg;
378
if (!SUMOVehicleParameter::parseDepart(helper, "vehicle", vehicleParameter->id, vehicleParameter->depart, vehicleParameter->departProcedure, departErrorMsg)) {
379
return handleVehicleError(hardFail, vehicleParameter, departErrorMsg);
380
}
381
}
382
// set tag
383
vehicleParameter->tag = (SumoXMLTag)element;
384
// all ok, then return vehicleParameter
385
return vehicleParameter;
386
} else {
387
return handleVehicleError(hardFail, nullptr, toString((SumoXMLTag)element) + " cannot be created");
388
}
389
}
390
391
392
std::string
393
SUMOVehicleParserHelper::parseID(const SUMOSAXAttributes& attrs, const SumoXMLTag element) {
394
bool ok = true;
395
std::string id;
396
// first check if attrs contain an ID
397
if (attrs.hasAttribute(SUMO_ATTR_ID)) {
398
id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
399
if (SUMOXMLDefinitions::isValidVehicleID(id)) {
400
return id;
401
} else if (id.empty()) {
402
// add extra information for empty IDs
403
WRITE_ERRORF(TL("Invalid % id '%'."), toString(element), id);
404
} else {
405
WRITE_ERRORF(TL("Invalid % id '%'. Contains invalid characters."), toString(element), id);
406
}
407
} else {
408
WRITE_ERROR("Attribute '" + toString(SUMO_ATTR_ID) + "' is missing in definition of " + toString(element));
409
}
410
// return empty (invalid) ID
411
return "";
412
}
413
414
415
void
416
SUMOVehicleParserHelper::parseCommonAttributes(const SUMOSAXAttributes& attrs, SUMOVehicleParameter* ret, SumoXMLTag tag, const bool allowInternalRoutes) {
417
const std::string element = toString(tag);
418
//ret->refid = attrs.getStringSecure(SUMO_ATTR_REFID, "");
419
// parse route information
420
if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
421
bool ok = true;
422
std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, ret->id.c_str(), ok);
423
if (!allowInternalRoutes && isInternalRouteID(routeID)) {
424
WRITE_WARNINGF(TL("Internal routes receive an ID starting with '!' and must not be referenced in other vehicle or flow definitions. Please remove all references to route '%' in case it is internal."), routeID);
425
}
426
ret->routeid = routeID;
427
if (ok) {
428
ret->parametersSet |= VEHPARS_ROUTE_SET; // !!! needed?
429
} else {
430
handleVehicleError(true, ret);
431
}
432
}
433
// parse type information
434
if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
435
bool ok = true;
436
ret->vtypeid = attrs.get<std::string>(SUMO_ATTR_TYPE, ret->id.c_str(), ok);
437
if (ok) {
438
ret->parametersSet |= VEHPARS_VTYPE_SET; // !!! needed?
439
} else {
440
handleVehicleError(true, ret);
441
}
442
}
443
// parse line information
444
if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
445
bool ok = true;
446
ret->line = attrs.get<std::string>(SUMO_ATTR_LINE, ret->id.c_str(), ok);
447
if (ok) {
448
ret->parametersSet |= VEHPARS_LINE_SET; // !!! needed?
449
} else {
450
handleVehicleError(true, ret);
451
}
452
}
453
// parse zone information
454
if (attrs.hasAttribute(SUMO_ATTR_FROM_TAZ)) {
455
bool ok = true;
456
ret->fromTaz = attrs.get<std::string>(SUMO_ATTR_FROM_TAZ, ret->id.c_str(), ok);
457
if (ok) {
458
ret->parametersSet |= VEHPARS_FROM_TAZ_SET;
459
} else {
460
handleVehicleError(true, ret);
461
}
462
}
463
if (attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) {
464
bool ok = true;
465
ret->toTaz = attrs.get<std::string>(SUMO_ATTR_TO_TAZ, ret->id.c_str(), ok);
466
if (ok) {
467
ret->parametersSet |= VEHPARS_TO_TAZ_SET;
468
} else {
469
handleVehicleError(true, ret);
470
}
471
}
472
// parse reroute information
473
if (attrs.hasAttribute(SUMO_ATTR_REROUTE)) {
474
bool ok = true;
475
if (attrs.get<bool>(SUMO_ATTR_REROUTE, ret->id.c_str(), ok)) {
476
if (ok) {
477
ret->parametersSet |= VEHPARS_FORCE_REROUTE;
478
} else {
479
handleVehicleError(true, ret);
480
}
481
}
482
}
483
// parse depart lane information
484
if (attrs.hasAttribute(SUMO_ATTR_DEPARTLANE)) {
485
bool ok = true;
486
const std::string departLaneStr = attrs.get<std::string>(SUMO_ATTR_DEPARTLANE, ret->id.c_str(), ok);
487
int lane;
488
DepartLaneDefinition dld;
489
std::string error;
490
if (SUMOVehicleParameter::parseDepartLane(departLaneStr, element, ret->id, lane, dld, error)) {
491
ret->parametersSet |= VEHPARS_DEPARTLANE_SET;
492
ret->departLane = lane;
493
ret->departLaneProcedure = dld;
494
} else {
495
handleVehicleError(true, ret, error);
496
}
497
}
498
// parse depart position information
499
if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
500
bool ok = true;
501
const std::string departPosStr = attrs.get<std::string>(SUMO_ATTR_DEPARTPOS, ret->id.c_str(), ok);
502
double pos;
503
DepartPosDefinition dpd;
504
std::string error;
505
if (SUMOVehicleParameter::parseDepartPos(departPosStr, element, ret->id, pos, dpd, error)) {
506
ret->parametersSet |= VEHPARS_DEPARTPOS_SET;
507
ret->departPos = pos;
508
ret->departPosProcedure = dpd;
509
} else {
510
handleVehicleError(true, ret, error);
511
}
512
}
513
// parse lateral depart position information
514
if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS_LAT)) {
515
bool ok = true;
516
const std::string departPosLatStr = attrs.get<std::string>(SUMO_ATTR_DEPARTPOS_LAT, ret->id.c_str(), ok);
517
double pos;
518
DepartPosLatDefinition dpd;
519
std::string error;
520
if (SUMOVehicleParameter::parseDepartPosLat(departPosLatStr, element, ret->id, pos, dpd, error)) {
521
ret->parametersSet |= VEHPARS_DEPARTPOSLAT_SET;
522
ret->departPosLat = pos;
523
ret->departPosLatProcedure = dpd;
524
} else {
525
handleVehicleError(true, ret, error);
526
}
527
}
528
// parse depart speed information
529
if (attrs.hasAttribute(SUMO_ATTR_DEPARTSPEED)) {
530
bool ok = true;
531
const std::string departSpeed = attrs.get<std::string>(SUMO_ATTR_DEPARTSPEED, ret->id.c_str(), ok);
532
double speed;
533
DepartSpeedDefinition dsd;
534
std::string error;
535
if (SUMOVehicleParameter::parseDepartSpeed(departSpeed, element, ret->id, speed, dsd, error)) {
536
ret->parametersSet |= VEHPARS_DEPARTSPEED_SET;
537
ret->departSpeed = speed;
538
ret->departSpeedProcedure = dsd;
539
} else {
540
handleVehicleError(true, ret, error);
541
}
542
}
543
// parse depart edge information
544
if (attrs.hasAttribute(SUMO_ATTR_DEPARTEDGE)) {
545
bool ok = true;
546
const std::string departEdgeStr = attrs.get<std::string>(SUMO_ATTR_DEPARTEDGE, ret->id.c_str(), ok);
547
int edgeIndex;
548
RouteIndexDefinition rid;
549
std::string error;
550
if (SUMOVehicleParameter::parseRouteIndex(departEdgeStr, element, ret->id, SUMO_ATTR_DEPARTEDGE, edgeIndex, rid, error)) {
551
ret->parametersSet |= VEHPARS_DEPARTEDGE_SET;
552
ret->departEdge = edgeIndex;
553
ret->departEdgeProcedure = rid;
554
} else {
555
handleVehicleError(true, ret, error);
556
}
557
}
558
// parse arrival lane information
559
if (attrs.hasAttribute(SUMO_ATTR_ARRIVALLANE)) {
560
bool ok = true;
561
const std::string arrivalLaneStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALLANE, ret->id.c_str(), ok);
562
int lane;
563
ArrivalLaneDefinition ald;
564
std::string error;
565
if (SUMOVehicleParameter::parseArrivalLane(arrivalLaneStr, element, ret->id, lane, ald, error)) {
566
ret->parametersSet |= VEHPARS_ARRIVALLANE_SET;
567
ret->arrivalLane = lane;
568
ret->arrivalLaneProcedure = ald;
569
} else {
570
handleVehicleError(true, ret, error);
571
}
572
}
573
// parse arrival position information
574
if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
575
bool ok = true;
576
const std::string arrivalPosStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, ret->id.c_str(), ok);
577
double pos;
578
ArrivalPosDefinition apd;
579
std::string error;
580
if (SUMOVehicleParameter::parseArrivalPos(arrivalPosStr, element, ret->id, pos, apd, error)) {
581
ret->parametersSet |= VEHPARS_ARRIVALPOS_SET;
582
ret->arrivalPos = pos;
583
ret->arrivalPosProcedure = apd;
584
} else {
585
handleVehicleError(true, ret, error);
586
}
587
}
588
// parse lateral arrival position information
589
if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS_LAT)) {
590
bool ok = true;
591
const std::string arrivalPosLatStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS_LAT, ret->id.c_str(), ok);
592
double pos;
593
ArrivalPosLatDefinition apd;
594
std::string error;
595
if (SUMOVehicleParameter::parseArrivalPosLat(arrivalPosLatStr, element, ret->id, pos, apd, error)) {
596
ret->parametersSet |= VEHPARS_ARRIVALPOSLAT_SET;
597
ret->arrivalPosLat = pos;
598
ret->arrivalPosLatProcedure = apd;
599
} else {
600
handleVehicleError(true, ret, error);
601
}
602
}
603
// parse arrival speed information
604
if (attrs.hasAttribute(SUMO_ATTR_ARRIVALSPEED)) {
605
bool ok = true;
606
std::string arrivalSpeedStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALSPEED, ret->id.c_str(), ok);
607
double speed;
608
ArrivalSpeedDefinition asd;
609
std::string error;
610
if (SUMOVehicleParameter::parseArrivalSpeed(arrivalSpeedStr, element, ret->id, speed, asd, error)) {
611
ret->parametersSet |= VEHPARS_ARRIVALSPEED_SET;
612
ret->arrivalSpeed = speed;
613
ret->arrivalSpeedProcedure = asd;
614
} else {
615
handleVehicleError(true, ret, error);
616
}
617
}
618
// parse arrival edge information
619
if (attrs.hasAttribute(SUMO_ATTR_ARRIVALEDGE)) {
620
bool ok = true;
621
std::string arrivalEdgeStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALEDGE, ret->id.c_str(), ok);
622
int edgeIndex;
623
RouteIndexDefinition rid;
624
std::string error;
625
if (SUMOVehicleParameter::parseRouteIndex(arrivalEdgeStr, element, ret->id, SUMO_ATTR_ARRIVALEDGE, edgeIndex, rid, error)) {
626
ret->parametersSet |= VEHPARS_ARRIVALEDGE_SET;
627
ret->arrivalEdge = edgeIndex;
628
ret->arrivalEdgeProcedure = rid;
629
} else {
630
handleVehicleError(true, ret, error);
631
}
632
}
633
// parse color
634
if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
635
bool ok = true;
636
ret->color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, ret->id.c_str(), ok);
637
if (ok) {
638
ret->parametersSet |= VEHPARS_COLOR_SET;
639
} else {
640
handleVehicleError(true, ret, "Invalid RGBColor format");
641
}
642
} else {
643
ret->color = RGBColor::DEFAULT_COLOR;
644
}
645
// parse person number
646
if (attrs.hasAttribute(SUMO_ATTR_PERSON_NUMBER)) {
647
bool ok = true;
648
int personNumber = attrs.get<int>(SUMO_ATTR_PERSON_NUMBER, ret->id.c_str(), ok);
649
if (!ok) {
650
handleVehicleError(true, ret);
651
} else if (personNumber >= 0) {
652
ret->parametersSet |= VEHPARS_PERSON_NUMBER_SET;
653
ret->personNumber = personNumber;
654
} else {
655
handleVehicleError(true, ret, toString(SUMO_ATTR_PERSON_NUMBER) + " cannot be negative");
656
}
657
}
658
// parse container number
659
if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_NUMBER)) {
660
bool ok = true;
661
int containerNumber = attrs.get<int>(SUMO_ATTR_CONTAINER_NUMBER, ret->id.c_str(), ok);
662
if (!ok) {
663
handleVehicleError(true, ret);
664
} else if (containerNumber >= 0) {
665
ret->parametersSet |= VEHPARS_CONTAINER_NUMBER_SET;
666
ret->containerNumber = containerNumber;
667
} else {
668
handleVehicleError(true, ret, toString(SUMO_ATTR_CONTAINER_NUMBER) + " cannot be negative");
669
}
670
}
671
// parse individual speedFactor
672
if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR)) {
673
bool ok = true;
674
double speedFactor = attrs.get<double>(SUMO_ATTR_SPEEDFACTOR, ret->id.c_str(), ok);
675
if (!ok) {
676
handleVehicleError(true, ret);
677
} else if (speedFactor > 0) {
678
ret->parametersSet |= VEHPARS_SPEEDFACTOR_SET;
679
ret->speedFactor = speedFactor;
680
} else {
681
handleVehicleError(true, ret, toString(SUMO_ATTR_SPEEDFACTOR) + " must be positive");
682
}
683
}
684
// parse insertion checks
685
if (attrs.hasAttribute(SUMO_ATTR_INSERTIONCHECKS)) {
686
ret->parametersSet |= VEHPARS_INSERTION_CHECKS_SET;
687
bool ok = true;
688
std::string checks = attrs.get<std::string>(SUMO_ATTR_INSERTIONCHECKS, ret->id.c_str(), ok);
689
if (!ok) {
690
handleVehicleError(true, ret);
691
} else {
692
try {
693
ret->insertionChecks = SUMOVehicleParameter::parseInsertionChecks(checks);
694
} catch (InvalidArgument& e) {
695
handleVehicleError(true, ret, e.what());
696
}
697
}
698
}
699
// parse parking access rights
700
if (attrs.hasAttribute(SUMO_ATTR_PARKING_BADGES)) {
701
bool ok = true;
702
std::vector<std::string> badges = attrs.get<std::vector<std::string>>(SUMO_ATTR_PARKING_BADGES, ret->id.c_str(), ok);
703
if (!ok) {
704
handleVehicleError(true, ret);
705
} else {
706
ret->parametersSet |= VEHPARS_PARKING_BADGES_SET;
707
ret->parkingBadges = badges;
708
}
709
}
710
// parse modes (transportables only)
711
ret->modes = 0;
712
if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
713
bool ok = true;
714
const std::string modeString = attrs.get<std::string>(SUMO_ATTR_MODES, ret->id.c_str(), ok);
715
if (!ok) {
716
handleVehicleError(true, ret);
717
} else {
718
std::string errorMsg;
719
if (!SUMOVehicleParameter::parsePersonModes(modeString, toString(tag), ret->id, ret->modes, errorMsg)) {
720
handleVehicleError(true, ret, errorMsg);
721
}
722
}
723
}
724
// parse usable vehicle types (transportables only)
725
if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
726
bool ok = true;
727
ret->vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, ret->id.c_str(), ok);
728
if (!ok) {
729
handleVehicleError(true, ret);
730
}
731
}
732
// parse speed (only used by calibrators flow)
733
// also used by vehicle in saved state but this is parsed elsewhere
734
if (tag == SUMO_TAG_FLOW && attrs.hasAttribute(SUMO_ATTR_SPEED)) {
735
bool ok = true;
736
double calibratorSpeed = attrs.get<double>(SUMO_ATTR_SPEED, ret->id.c_str(), ok);
737
if (!ok) {
738
handleVehicleError(true, ret);
739
} else if (calibratorSpeed >= 0 || calibratorSpeed == -1) {
740
ret->parametersSet |= VEHPARS_CALIBRATORSPEED_SET;
741
ret->calibratorSpeed = calibratorSpeed;
742
} else {
743
handleVehicleError(true, ret, toString(SUMO_ATTR_SPEED) + " may not be negative");
744
}
745
}
746
/*/ parse via
747
if (attrs.hasAttribute(SUMO_ATTR_VIA)) {
748
ret->setParameter |= VEHPARS_VIA_SET;
749
SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_VIA, ret->id.c_str(), ok), ret->via);
750
}
751
*/
752
}
753
754
755
SUMOVTypeParameter*
756
SUMOVehicleParserHelper::beginVTypeParsing(const SUMOSAXAttributes& attrs, const bool hardFail, const std::string& file) {
757
// first obtain ID
758
std::string id = parseID(attrs, SUMO_TAG_VTYPE);
759
// check if ID is valid
760
if (!id.empty()) {
761
SUMOVehicleClass vClass = SVC_PASSENGER;
762
if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
763
vClass = parseVehicleClass(attrs, id);
764
}
765
// create vType
766
SUMOVTypeParameter* vType = new SUMOVTypeParameter(id, vClass);
767
// parse attributes
768
if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
769
vType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
770
}
771
if (attrs.hasAttribute(SUMO_ATTR_LENGTH)) {
772
bool ok = true;
773
const double length = attrs.get<double>(SUMO_ATTR_LENGTH, vType->id.c_str(), ok);
774
if (!ok) {
775
return handleVehicleTypeError(hardFail, vType);
776
} else if (length <= 0) {
777
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_LENGTH) + " must be greater than 0");
778
} else {
779
vType->length = length;
780
vType->parametersSet |= VTYPEPARS_LENGTH_SET;
781
}
782
}
783
if (attrs.hasAttribute(SUMO_ATTR_MINGAP)) {
784
bool ok = true;
785
const double minGap = attrs.get<double>(SUMO_ATTR_MINGAP, vType->id.c_str(), ok);
786
if (!ok) {
787
return handleVehicleTypeError(hardFail, vType);
788
} else if (minGap < 0) {
789
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MINGAP) + " must be equal or greater than 0");
790
} else {
791
vType->minGap = minGap;
792
vType->parametersSet |= VTYPEPARS_MINGAP_SET;
793
}
794
}
795
if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED)) {
796
bool ok = true;
797
const double maxSpeed = attrs.get<double>(SUMO_ATTR_MAXSPEED, vType->id.c_str(), ok);
798
if (!ok) {
799
return handleVehicleTypeError(hardFail, vType);
800
} else if (maxSpeed <= 0) {
801
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MAXSPEED) + " must be greater than 0");
802
} else {
803
vType->maxSpeed = maxSpeed;
804
vType->parametersSet |= VTYPEPARS_MAXSPEED_SET;
805
}
806
}
807
if (attrs.hasAttribute(SUMO_ATTR_DESIRED_MAXSPEED)) {
808
bool ok = true;
809
const double desiredMaxSpeed = attrs.get<double>(SUMO_ATTR_DESIRED_MAXSPEED, vType->id.c_str(), ok);
810
if (!ok) {
811
return handleVehicleTypeError(hardFail, vType);
812
} else if (desiredMaxSpeed <= 0) {
813
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_DESIRED_MAXSPEED) + " must be greater than 0");
814
} else {
815
vType->desiredMaxSpeed = desiredMaxSpeed;
816
vType->parametersSet |= VTYPEPARS_DESIRED_MAXSPEED_SET;
817
}
818
} else if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED)) {
819
if (vClass == SVC_PEDESTRIAN) {
820
// backward compatibility because pedestrian maxSpeed was subject to speedFactor up to 1.14.1
821
vType->desiredMaxSpeed = vType->maxSpeed;;
822
vType->maxSpeed = MAX2(vType->maxSpeed, SUMOVTypeParameter::VClassDefaultValues(vClass).maxSpeed);
823
} else if (vClass == SVC_BICYCLE) {
824
// backward compatibility because default desired speed did not exist up to 1.14.1
825
vType->desiredMaxSpeed = MAX2(vType->maxSpeed, vType->desiredMaxSpeed);
826
}
827
}
828
829
if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR)) {
830
bool ok = true;
831
vType->speedFactor.parse(attrs.get<std::string>(SUMO_ATTR_SPEEDFACTOR, vType->id.c_str(), ok), hardFail);
832
if (!ok) {
833
return handleVehicleTypeError(hardFail, vType);
834
} else {
835
vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
836
}
837
}
838
if (attrs.hasAttribute(SUMO_ATTR_SPEEDDEV)) {
839
bool ok = true;
840
const double speedDev = attrs.get<double>(SUMO_ATTR_SPEEDDEV, vType->id.c_str(), ok);
841
if (!ok) {
842
return handleVehicleTypeError(hardFail, vType);
843
} else if (speedDev < 0) {
844
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_SPEEDDEV) + " must be equal or greater than 0");
845
} else {
846
vType->speedFactor.setParameter(1, speedDev);
847
vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
848
}
849
}
850
// validate speed distribution
851
const std::string& error = vType->speedFactor.isValid();
852
if (error != "") {
853
return handleVehicleTypeError(hardFail, vType, "Invalid speed distribution when parsing vType '" + vType->id + "' (" + error + ")");
854
}
855
if (attrs.hasAttribute(SUMO_ATTR_ACTIONSTEPLENGTH)) {
856
bool ok = true;
857
const double actionStepLengthSecs = attrs.get<double>(SUMO_ATTR_ACTIONSTEPLENGTH, vType->id.c_str(), ok);
858
if (!ok) {
859
return handleVehicleTypeError(hardFail, vType);
860
} else {
861
// processActionStepLength(...) function includes warnings
862
vType->actionStepLength = processActionStepLength(actionStepLengthSecs);
863
vType->parametersSet |= VTYPEPARS_ACTIONSTEPLENGTH_SET;
864
}
865
}
866
if (attrs.hasAttribute(SUMO_ATTR_EMISSIONCLASS)) {
867
bool ok = true;
868
const std::string parsedEmissionClass = attrs.getOpt<std::string>(SUMO_ATTR_EMISSIONCLASS, id.c_str(), ok, "");
869
// check if emission class is correct
870
try {
871
vType->emissionClass = PollutantsInterface::getClassByName(parsedEmissionClass);
872
vType->parametersSet |= VTYPEPARS_EMISSIONCLASS_SET;
873
} catch (...) {
874
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_EMISSIONCLASS) + " with name '" + parsedEmissionClass + "' doesn't exist.");
875
}
876
}
877
if (attrs.hasAttribute(SUMO_ATTR_MASS)) {
878
bool ok = true;
879
const double mass = attrs.get<double>(SUMO_ATTR_MASS, vType->id.c_str(), ok);
880
if (!ok) {
881
return handleVehicleTypeError(hardFail, vType);
882
} else if (mass < 0) {
883
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MASS) + " must be equal or greater than 0");
884
} else {
885
vType->mass = mass;
886
vType->parametersSet |= VTYPEPARS_MASS_SET;
887
}
888
}
889
if (attrs.hasAttribute(SUMO_ATTR_IMPATIENCE)) {
890
bool ok = true;
891
const std::string impatienceStr = attrs.get<std::string>(SUMO_ATTR_IMPATIENCE, vType->id.c_str(), ok);
892
if (!ok) {
893
return handleVehicleTypeError(hardFail, vType);
894
} else if (impatienceStr == "off") {
895
vType->impatience = -std::numeric_limits<double>::max();
896
} else {
897
const double impatienceDouble = attrs.get<double>(SUMO_ATTR_IMPATIENCE, vType->id.c_str(), ok);
898
if (!ok) {
899
return handleVehicleTypeError(hardFail, vType);
900
} else {
901
vType->impatience = impatienceDouble;
902
vType->parametersSet |= VTYPEPARS_IMPATIENCE_SET;
903
}
904
}
905
}
906
if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
907
bool ok = true;
908
const double width = attrs.get<double>(SUMO_ATTR_WIDTH, vType->id.c_str(), ok);
909
if (!ok) {
910
return handleVehicleTypeError(hardFail, vType);
911
} else if (width <= 0) {
912
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_WIDTH) + " must be greater than 0");
913
} else {
914
vType->width = width;
915
vType->parametersSet |= VTYPEPARS_WIDTH_SET;
916
if (vClass == SVC_PEDESTRIAN
917
&& OptionsCont::getOptions().exists("pedestrian.striping.stripe-width")
918
&& OptionsCont::getOptions().getString("pedestrian.model") == "striping"
919
&& OptionsCont::getOptions().getFloat("pedestrian.striping.stripe-width") < vType->width) {
920
WRITE_WARNINGF(TL("Pedestrian vType '%' width % is larger than pedestrian.striping.stripe-width and this may cause collisions with vehicles."), id, vType->width);
921
}
922
}
923
}
924
if (attrs.hasAttribute(SUMO_ATTR_HEIGHT)) {
925
bool ok = true;
926
const double height = attrs.get<double>(SUMO_ATTR_HEIGHT, vType->id.c_str(), ok);
927
if (!ok) {
928
return handleVehicleTypeError(hardFail, vType);
929
} else if (height < 0) {
930
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_HEIGHT) + " must be equal or greater than 0");
931
} else {
932
vType->height = height;
933
vType->parametersSet |= VTYPEPARS_HEIGHT_SET;
934
}
935
}
936
if (attrs.hasAttribute(SUMO_ATTR_GUISHAPE)) {
937
vType->shape = parseGuiShape(attrs, vType->id);
938
if (vType->shape != SUMOVehicleShape::UNKNOWN) {
939
vType->parametersSet |= VTYPEPARS_SHAPE_SET;
940
}
941
}
942
if (attrs.hasAttribute(SUMO_ATTR_OSGFILE)) {
943
bool ok = true;
944
const std::string osgFile = attrs.get<std::string>(SUMO_ATTR_OSGFILE, vType->id.c_str(), ok);
945
if (!ok) {
946
return handleVehicleTypeError(hardFail, vType);
947
} else {
948
vType->osgFile = osgFile;
949
vType->parametersSet |= VTYPEPARS_OSGFILE_SET;
950
}
951
}
952
if (attrs.hasAttribute(SUMO_ATTR_IMGFILE)) {
953
bool ok = true;
954
std::string imgFile = attrs.get<std::string>(SUMO_ATTR_IMGFILE, vType->id.c_str(), ok);
955
if (!ok) {
956
return handleVehicleTypeError(hardFail, vType);
957
} else {
958
// check relative path
959
if ((imgFile != "") && !FileHelpers::isAbsolute(imgFile)) {
960
imgFile = FileHelpers::getConfigurationRelative(file, imgFile);
961
}
962
vType->imgFile = imgFile;
963
vType->parametersSet |= VTYPEPARS_IMGFILE_SET;
964
}
965
}
966
if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
967
bool ok = true;
968
const RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, vType->id.c_str(), ok);
969
if (!ok) {
970
return handleVehicleTypeError(hardFail, vType);
971
} else {
972
vType->color = color;
973
vType->parametersSet |= VTYPEPARS_COLOR_SET;
974
}
975
} else {
976
vType->color = RGBColor::YELLOW;
977
}
978
if (attrs.hasAttribute(SUMO_ATTR_PROB)) {
979
bool ok = true;
980
const double defaultProbability = attrs.get<double>(SUMO_ATTR_PROB, vType->id.c_str(), ok);
981
if (!ok) {
982
return handleVehicleTypeError(hardFail, vType);
983
} else if (defaultProbability < 0) {
984
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_PROB) + " must be equal or greater than 0");
985
} else {
986
vType->defaultProbability = defaultProbability;
987
vType->parametersSet |= VTYPEPARS_PROBABILITY_SET;
988
}
989
}
990
if (attrs.hasAttribute(SUMO_ATTR_LANE_CHANGE_MODEL)) {
991
bool ok = true;
992
std::string lcmS = attrs.get<std::string>(SUMO_ATTR_LANE_CHANGE_MODEL, vType->id.c_str(), ok);
993
if (!ok) {
994
return handleVehicleTypeError(hardFail, vType);
995
} else if (lcmS == "JE2013") {
996
WRITE_WARNING(TL("Lane change model 'JE2013' is deprecated. Using default model instead."));
997
lcmS = "default";
998
}
999
if (SUMOXMLDefinitions::LaneChangeModels.hasString(lcmS)) {
1000
vType->lcModel = SUMOXMLDefinitions::LaneChangeModels.get(lcmS);
1001
vType->parametersSet |= VTYPEPARS_LANE_CHANGE_MODEL_SET;
1002
} else {
1003
return handleVehicleTypeError(hardFail, vType, "Unknown lane change model '" + lcmS + "' when parsing vType '" + vType->id + "'");
1004
}
1005
}
1006
if (attrs.hasAttribute(SUMO_ATTR_CAR_FOLLOW_MODEL)) {
1007
bool ok = true;
1008
const std::string cfmValue = attrs.get<std::string>(SUMO_ATTR_CAR_FOLLOW_MODEL, vType->id.c_str(), ok);
1009
if (!ok) {
1010
return handleVehicleTypeError(hardFail, vType);
1011
} else if (SUMOXMLDefinitions::CarFollowModels.hasString(cfmValue)) {
1012
vType->cfModel = SUMOXMLDefinitions::CarFollowModels.get(cfmValue);
1013
vType->parametersSet |= VTYPEPARS_CAR_FOLLOW_MODEL;
1014
} else {
1015
return handleVehicleTypeError(hardFail, vType, "Unknown car following model '" + cfmValue + "' when parsing vType '" + vType->id + "'");
1016
}
1017
}
1018
if (attrs.hasAttribute(SUMO_ATTR_PERSON_CAPACITY)) {
1019
bool ok = true;
1020
const int personCapacity = attrs.get<int>(SUMO_ATTR_PERSON_CAPACITY, vType->id.c_str(), ok);
1021
if (!ok) {
1022
return handleVehicleTypeError(hardFail, vType);
1023
} else if (personCapacity < 0) {
1024
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_PERSON_CAPACITY) + " must be equal or greater than 0");
1025
} else {
1026
vType->personCapacity = personCapacity;
1027
vType->parametersSet |= VTYPEPARS_PERSON_CAPACITY;
1028
}
1029
}
1030
if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_CAPACITY)) {
1031
bool ok = true;
1032
const int containerCapacity = attrs.get<int>(SUMO_ATTR_CONTAINER_CAPACITY, vType->id.c_str(), ok);
1033
if (!ok) {
1034
return handleVehicleTypeError(hardFail, vType);
1035
} else if (containerCapacity < 0) {
1036
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_CONTAINER_CAPACITY) + " must be equal or greater than 0");
1037
} else {
1038
vType->containerCapacity = containerCapacity;
1039
vType->parametersSet |= VTYPEPARS_CONTAINER_CAPACITY;
1040
}
1041
}
1042
if (attrs.hasAttribute(SUMO_ATTR_BOARDING_DURATION)) {
1043
bool ok = true;
1044
const SUMOTime boardingDuration = attrs.getSUMOTimeReporting(SUMO_ATTR_BOARDING_DURATION, vType->id.c_str(), ok);
1045
if (!ok) {
1046
return handleVehicleTypeError(hardFail, vType);
1047
} else if (boardingDuration < 0) {
1048
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_BOARDING_DURATION) + " must be equal or greater than 0");
1049
} else {
1050
vType->boardingDuration = boardingDuration;
1051
vType->parametersSet |= VTYPEPARS_BOARDING_DURATION;
1052
}
1053
}
1054
if (attrs.hasAttribute(SUMO_ATTR_LOADING_DURATION)) {
1055
bool ok = true;
1056
const SUMOTime loadingDuration = attrs.getSUMOTimeReporting(SUMO_ATTR_LOADING_DURATION, vType->id.c_str(), ok);
1057
if (!ok) {
1058
return handleVehicleTypeError(hardFail, vType);
1059
} else if (loadingDuration < 0) {
1060
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_LOADING_DURATION) + " must be equal or greater than 0");
1061
} else {
1062
vType->loadingDuration = loadingDuration;
1063
vType->parametersSet |= VTYPEPARS_LOADING_DURATION;
1064
}
1065
}
1066
if (attrs.hasAttribute(SUMO_ATTR_SCALE)) {
1067
bool ok = true;
1068
const double scale = attrs.get<double>(SUMO_ATTR_SCALE, id.c_str(), ok);
1069
if (!ok) {
1070
return handleVehicleTypeError(hardFail, vType);
1071
} else if (scale < 0) {
1072
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_SCALE) + " may be not be negative");
1073
} else {
1074
vType->scale = scale;
1075
vType->parametersSet |= VTYPEPARS_SCALE_SET;
1076
}
1077
}
1078
if (attrs.hasAttribute(SUMO_ATTR_TIME_TO_TELEPORT)) {
1079
bool ok = true;
1080
const SUMOTime ttt = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME_TO_TELEPORT, vType->id.c_str(), ok);
1081
if (!ok) {
1082
return handleVehicleTypeError(hardFail, vType);
1083
} else {
1084
vType->timeToTeleport = ttt;
1085
vType->parametersSet |= VTYPEPARS_TTT_SET;
1086
}
1087
}
1088
if (attrs.hasAttribute(SUMO_ATTR_TIME_TO_TELEPORT_BIDI)) {
1089
bool ok = true;
1090
const SUMOTime tttb = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME_TO_TELEPORT_BIDI, vType->id.c_str(), ok);
1091
if (!ok) {
1092
return handleVehicleTypeError(hardFail, vType);
1093
} else {
1094
vType->timeToTeleportBidi = tttb;
1095
vType->parametersSet |= VTYPEPARS_TTT_BIDI_SET;
1096
}
1097
}
1098
if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR_PREMATURE)) {
1099
bool ok = true;
1100
const double sfp = attrs.get<double>(SUMO_ATTR_SPEEDFACTOR_PREMATURE, id.c_str(), ok);
1101
if (!ok) {
1102
return handleVehicleTypeError(hardFail, vType);
1103
} else {
1104
vType->speedFactorPremature = sfp;
1105
vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_PREMATURE_SET;
1106
}
1107
}
1108
if (attrs.hasAttribute(SUMO_ATTR_BOARDING_FACTOR)) {
1109
bool ok = true;
1110
const double bf = attrs.get<double>(SUMO_ATTR_BOARDING_FACTOR, id.c_str(), ok);
1111
if (!ok) {
1112
return handleVehicleTypeError(hardFail, vType);
1113
} else if (bf < 0) {
1114
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_BOARDING_FACTOR) + " must be equal or greater than 0");
1115
} else {
1116
vType->boardingFactor = bf;
1117
vType->parametersSet |= VTYPEPARS_BOARDING_FACTOR_SET;
1118
}
1119
}
1120
if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED_LAT)) {
1121
bool ok = true;
1122
const double maxSpeedLat = attrs.get<double>(SUMO_ATTR_MAXSPEED_LAT, vType->id.c_str(), ok);
1123
if (!ok) {
1124
return handleVehicleTypeError(hardFail, vType);
1125
} else if (maxSpeedLat <= 0) {
1126
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MAXSPEED_LAT) + " must be greater than 0");
1127
} else {
1128
vType->maxSpeedLat = maxSpeedLat;
1129
vType->parametersSet |= VTYPEPARS_MAXSPEED_LAT_SET;
1130
}
1131
}
1132
if (attrs.hasAttribute(SUMO_ATTR_MINGAP_LAT)) {
1133
bool ok = true;
1134
const double minGapLat = attrs.get<double>(SUMO_ATTR_MINGAP_LAT, vType->id.c_str(), ok);
1135
if (!ok) {
1136
return handleVehicleTypeError(hardFail, vType);
1137
} else if (minGapLat < 0) {
1138
return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MINGAP_LAT) + " must be equal or greater than 0");
1139
} else {
1140
vType->minGapLat = minGapLat;
1141
vType->parametersSet |= VTYPEPARS_MINGAP_LAT_SET;
1142
}
1143
}
1144
if (attrs.hasAttribute(SUMO_ATTR_LATALIGNMENT)) {
1145
bool ok = true;
1146
const std::string alignS = attrs.get<std::string>(SUMO_ATTR_LATALIGNMENT, vType->id.c_str(), ok);
1147
if (!ok) {
1148
return handleVehicleTypeError(hardFail, vType);
1149
} else {
1150
double lao;
1151
LatAlignmentDefinition lad;
1152
if (SUMOVTypeParameter::parseLatAlignment(alignS, lao, lad)) {
1153
vType->latAlignmentOffset = lao;
1154
vType->latAlignmentProcedure = lad;
1155
vType->parametersSet |= VTYPEPARS_LATALIGNMENT_SET;
1156
} else {
1157
return handleVehicleTypeError(hardFail, vType, "Unknown lateral alignment '" + alignS + "' when parsing vType '" + vType->id + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
1158
}
1159
}
1160
}
1161
if (attrs.hasAttribute(SUMO_ATTR_MANEUVER_ANGLE_TIMES)) {
1162
bool ok = true;
1163
const std::string angleTimesS = attrs.get<std::string>(SUMO_ATTR_MANEUVER_ANGLE_TIMES, vType->id.c_str(), ok);
1164
if (!ok) {
1165
return handleVehicleTypeError(hardFail, vType);
1166
} else if (parseAngleTimesMap(vType, angleTimesS)) {
1167
vType->parametersSet |= VTYPEPARS_MANEUVER_ANGLE_TIMES_SET;
1168
} else {
1169
return handleVehicleTypeError(hardFail, vType, "Invalid manoeuver angle times map for vType '" + vType->id + "'");
1170
}
1171
}
1172
if (attrs.hasAttribute(SUMO_ATTR_PARKING_BADGES)) {
1173
bool ok = true;
1174
std::vector<std::string> badges = attrs.get<std::vector<std::string>>(SUMO_ATTR_PARKING_BADGES, vType->id.c_str(), ok);
1175
if (!ok) {
1176
return handleVehicleTypeError(hardFail, vType);
1177
} else {
1178
vType->parametersSet |= VTYPEPARS_PARKING_BADGES_SET;
1179
vType->parkingBadges = badges;
1180
}
1181
}
1182
// try to parse Car Following Model params
1183
if (!parseCFMParams(vType, vType->cfModel, attrs, false)) {
1184
return handleVehicleTypeError(hardFail, vType, "Invalid parsing embedded VType");
1185
}
1186
// try to parse Lane Change Model params
1187
if (!parseLCParams(vType, vType->lcModel, attrs)) {
1188
return handleVehicleTypeError(hardFail, vType, "Invalid Lane Change Model Parameters");
1189
}
1190
// try to Junction Model params
1191
if (!parseJMParams(vType, attrs)) {
1192
return handleVehicleTypeError(hardFail, vType, "Invalid Junction Model Parameters");
1193
}
1194
// all ok, then return vType
1195
return vType;
1196
} else {
1197
return handleVehicleTypeError(hardFail, nullptr, "VType cannot be created");
1198
}
1199
}
1200
1201
1202
bool
1203
SUMOVehicleParserHelper::parseAngleTimesMap(SUMOVTypeParameter* vtype, const std::string atm) {
1204
StringTokenizer st(atm, ",");
1205
std::map<int, std::pair<SUMOTime, SUMOTime>> angleTimesMap;
1206
int tripletCount = 0;
1207
while (st.hasNext()) {
1208
StringTokenizer pos(st.next());
1209
if (pos.size() != 3) {
1210
WRITE_ERRORF(TL("maneuverAngleTimes format for vType '%' % contains an invalid triplet."), vtype->id, atm);
1211
return false;
1212
} else {
1213
try {
1214
const int angle = StringUtils::toInt(pos.next());
1215
const SUMOTime t1 = string2time(pos.next());
1216
const SUMOTime t2 = string2time(pos.next());
1217
angleTimesMap[angle] = std::make_pair(t1, t2);
1218
} catch (...) {
1219
WRITE_ERRORF(TL("Triplet '%' for vType '%' maneuverAngleTimes cannot be parsed as 'int double double'"), st.get(tripletCount), vtype->id);
1220
return false;
1221
}
1222
tripletCount++;
1223
}
1224
}
1225
if (angleTimesMap.size() > 0) {
1226
vtype->myManoeuverAngleTimes.clear();
1227
for (const auto& angleTime : angleTimesMap) {
1228
vtype->myManoeuverAngleTimes.insert(angleTime);
1229
}
1230
angleTimesMap.clear();
1231
return true;
1232
} else {
1233
return false;
1234
}
1235
}
1236
1237
1238
bool
1239
SUMOVehicleParserHelper::parseCFMParams(SUMOVTypeParameter* into, const SumoXMLTag element, const SUMOSAXAttributes& attrs, const bool nestedCFM) {
1240
const CFAttrMap& allowedCFM = getAllowedCFModelAttrs();
1241
CFAttrMap::const_iterator cf_it = allowedCFM.find(element);
1242
// check if given CFM is allowed
1243
if (cf_it == allowedCFM.end()) {
1244
if (SUMOXMLDefinitions::Tags.has((int)element)) {
1245
WRITE_ERRORF(TL("Unknown car-following model % when parsing vType '%'"), toString(element), into->id);
1246
} else {
1247
WRITE_ERRORF(TL("Unknown car-following model when parsing vType '%'"), into->id);
1248
}
1249
return false;
1250
}
1251
// check if we're parsing a nested CFM
1252
if (nestedCFM) {
1253
into->cfModel = cf_it->first;
1254
into->parametersSet |= VTYPEPARS_CAR_FOLLOW_MODEL;
1255
}
1256
// set CFM values
1257
for (const auto& it : cf_it->second) {
1258
if (attrs.hasAttribute(it)) {
1259
// first obtain CFM attribute in string format
1260
bool ok = true;
1261
std::string parsedCFMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1262
// check CFM Attribute
1263
if (!ok) {
1264
return false;
1265
} else if (it == SUMO_ATTR_TRAIN_TYPE) {
1266
// check if train value is valid
1267
if (!SUMOXMLDefinitions::TrainTypes.hasString(parsedCFMAttribute)) {
1268
WRITE_ERROR("Invalid train type '" + parsedCFMAttribute + "' used in Car-Following-Attribute " + toString(it));
1269
return false;
1270
}
1271
// add parsedCFMAttribute to cfParameter
1272
into->cfParameter[it] = parsedCFMAttribute;
1273
} else if (it == SUMO_ATTR_SPEED_TABLE || it == SUMO_ATTR_TRACTION_TABLE || it == SUMO_ATTR_RESISTANCE_TABLE) {
1274
into->cfParameter[it] = parsedCFMAttribute;
1275
} else if (it == SUMO_ATTR_CF_IDM_STEPPING) {
1276
// declare a int in wich save CFM int attribute
1277
double CFMDoubleAttribute = -1;
1278
try {
1279
// obtain CFM attribute in int format
1280
CFMDoubleAttribute = StringUtils::toDouble(parsedCFMAttribute);
1281
} catch (...) {
1282
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Cannot be parsed to float"), toString(it));
1283
return false;
1284
}
1285
if (CFMDoubleAttribute <= 0) {
1286
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Must be greater than 0"), toString(it));
1287
return false;
1288
}
1289
// add parsedCFMAttribute to cfParameter
1290
into->cfParameter[it] = parsedCFMAttribute;
1291
} else if (it == SUMO_ATTR_MAXACCEL_PROFILE || it == SUMO_ATTR_DESACCEL_PROFILE) {
1292
if (validProfile(into, parsedCFMAttribute, it)) {
1293
into->cfParameter[it] = parsedCFMAttribute;
1294
} else {
1295
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Cannot be parsed as a vector of <speed accel> pairs"), toString(it));
1296
return false;
1297
}
1298
} else {
1299
// declare a double in wich save CFM float attribute
1300
double CFMDoubleAttribute = -1;
1301
try {
1302
// obtain CFM attribute in double format
1303
CFMDoubleAttribute = StringUtils::toDouble(parsedCFMAttribute);
1304
} catch (...) {
1305
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Cannot be parsed to float"), toString(it));
1306
return false;
1307
}
1308
// check attributes of type "positiveFloatType" (> 0)
1309
switch (it) {
1310
case SUMO_ATTR_ACCEL:
1311
case SUMO_ATTR_DECEL:
1312
case SUMO_ATTR_APPARENTDECEL:
1313
case SUMO_ATTR_EMERGENCYDECEL:
1314
case SUMO_ATTR_TAU:
1315
if (CFMDoubleAttribute <= 0) {
1316
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Must be greater than 0"), toString(it));
1317
return false;
1318
}
1319
break;
1320
default:
1321
break;
1322
}
1323
// check attributes restricted to [0-1]
1324
switch (it) {
1325
case SUMO_ATTR_SIGMA:
1326
if ((CFMDoubleAttribute < 0) || (CFMDoubleAttribute > 1)) {
1327
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Only values between [0-1] are allowed"), toString(it));
1328
return false;
1329
}
1330
break;
1331
default:
1332
break;
1333
}
1334
// add parsedCFMAttribute to cfParameter
1335
into->cfParameter[it] = parsedCFMAttribute;
1336
}
1337
}
1338
}
1339
// all CFM successfully parsed, then return true
1340
return true;
1341
}
1342
1343
1344
const SUMOVehicleParserHelper::CFAttrMap&
1345
SUMOVehicleParserHelper::getAllowedCFModelAttrs() {
1346
// init on first use
1347
if (allowedCFModelAttrs.size() == 0) {
1348
std::set<SumoXMLAttr> genericParams;
1349
genericParams.insert(SUMO_ATTR_TAU);
1350
genericParams.insert(SUMO_ATTR_ACCEL);
1351
genericParams.insert(SUMO_ATTR_DECEL);
1352
genericParams.insert(SUMO_ATTR_APPARENTDECEL);
1353
genericParams.insert(SUMO_ATTR_EMERGENCYDECEL);
1354
genericParams.insert(SUMO_ATTR_SPEED_TABLE);
1355
genericParams.insert(SUMO_ATTR_MAXACCEL_PROFILE);
1356
genericParams.insert(SUMO_ATTR_DESACCEL_PROFILE);
1357
genericParams.insert(SUMO_ATTR_COLLISION_MINGAP_FACTOR);
1358
genericParams.insert(SUMO_ATTR_STARTUP_DELAY);
1359
// Krauss
1360
std::set<SumoXMLAttr> kraussParams(genericParams);
1361
kraussParams.insert(SUMO_ATTR_SIGMA);
1362
kraussParams.insert(SUMO_ATTR_SIGMA_STEP);
1363
allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS] = kraussParams;
1364
allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS_ORIG1] = kraussParams;
1365
allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS_PLUS_SLOPE] = kraussParams;
1366
std::set<SumoXMLAttr> allParams(kraussParams);
1367
// KraussX
1368
std::set<SumoXMLAttr> kraussXParams(kraussParams);
1369
kraussXParams.insert(SUMO_ATTR_TMP1);
1370
kraussXParams.insert(SUMO_ATTR_TMP2);
1371
kraussXParams.insert(SUMO_ATTR_TMP3);
1372
kraussXParams.insert(SUMO_ATTR_TMP4);
1373
kraussXParams.insert(SUMO_ATTR_TMP5);
1374
allowedCFModelAttrs[SUMO_TAG_CF_KRAUSSX] = kraussXParams;
1375
allParams.insert(kraussXParams.begin(), kraussXParams.end());
1376
// SmartSK
1377
std::set<SumoXMLAttr> smartSKParams(genericParams);
1378
smartSKParams.insert(SUMO_ATTR_SIGMA);
1379
smartSKParams.insert(SUMO_ATTR_TMP1);
1380
smartSKParams.insert(SUMO_ATTR_TMP2);
1381
smartSKParams.insert(SUMO_ATTR_TMP3);
1382
smartSKParams.insert(SUMO_ATTR_TMP4);
1383
smartSKParams.insert(SUMO_ATTR_TMP5);
1384
allowedCFModelAttrs[SUMO_TAG_CF_SMART_SK] = smartSKParams;
1385
allParams.insert(smartSKParams.begin(), smartSKParams.end());
1386
// Daniel
1387
std::set<SumoXMLAttr> daniel1Params(genericParams);
1388
daniel1Params.insert(SUMO_ATTR_SIGMA);
1389
daniel1Params.insert(SUMO_ATTR_TMP1);
1390
daniel1Params.insert(SUMO_ATTR_TMP2);
1391
daniel1Params.insert(SUMO_ATTR_TMP3);
1392
daniel1Params.insert(SUMO_ATTR_TMP4);
1393
daniel1Params.insert(SUMO_ATTR_TMP5);
1394
allowedCFModelAttrs[SUMO_TAG_CF_DANIEL1] = daniel1Params;
1395
allParams.insert(daniel1Params.begin(), daniel1Params.end());
1396
// Peter Wagner
1397
std::set<SumoXMLAttr> pwagParams(genericParams);
1398
pwagParams.insert(SUMO_ATTR_SIGMA);
1399
pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_TAULAST);
1400
pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_APPROB);
1401
allowedCFModelAttrs[SUMO_TAG_CF_PWAGNER2009] = pwagParams;
1402
allParams.insert(pwagParams.begin(), pwagParams.end());
1403
// IDM params
1404
std::set<SumoXMLAttr> idmParams(genericParams);
1405
idmParams.insert(SUMO_ATTR_CF_IDM_DELTA);
1406
idmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1407
allowedCFModelAttrs[SUMO_TAG_CF_IDM] = idmParams;
1408
allParams.insert(idmParams.begin(), idmParams.end());
1409
// EIDM
1410
std::set<SumoXMLAttr> eidmParams(genericParams);
1411
eidmParams.insert(SUMO_ATTR_CF_IDM_DELTA);
1412
eidmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1413
eidmParams.insert(SUMO_ATTR_CF_EIDM_T_LOOK_AHEAD);
1414
eidmParams.insert(SUMO_ATTR_CF_EIDM_T_PERSISTENCE_DRIVE);
1415
eidmParams.insert(SUMO_ATTR_CF_EIDM_T_REACTION);
1416
eidmParams.insert(SUMO_ATTR_CF_EIDM_T_PERSISTENCE_ESTIMATE);
1417
eidmParams.insert(SUMO_ATTR_CF_EIDM_C_COOLNESS);
1418
eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_LEADER);
1419
eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_GAP);
1420
eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_ERROR);
1421
eidmParams.insert(SUMO_ATTR_CF_EIDM_JERK_MAX);
1422
eidmParams.insert(SUMO_ATTR_CF_EIDM_EPSILON_ACC);
1423
eidmParams.insert(SUMO_ATTR_CF_EIDM_T_ACC_MAX);
1424
eidmParams.insert(SUMO_ATTR_CF_EIDM_M_FLATNESS);
1425
eidmParams.insert(SUMO_ATTR_CF_EIDM_M_BEGIN);
1426
eidmParams.insert(SUMO_ATTR_CF_EIDM_USEVEHDYNAMICS);
1427
eidmParams.insert(SUMO_ATTR_CF_EIDM_MAX_VEH_PREVIEW);
1428
allowedCFModelAttrs[SUMO_TAG_CF_EIDM] = eidmParams;
1429
allParams.insert(eidmParams.begin(), eidmParams.end());
1430
// IDMM
1431
std::set<SumoXMLAttr> idmmParams(genericParams);
1432
idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_FACTOR);
1433
idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_TIME);
1434
idmmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1435
allowedCFModelAttrs[SUMO_TAG_CF_IDMM] = idmmParams;
1436
allParams.insert(idmmParams.begin(), idmmParams.end());
1437
// Bieker
1438
std::set<SumoXMLAttr> bkernerParams(genericParams);
1439
bkernerParams.insert(SUMO_ATTR_K);
1440
bkernerParams.insert(SUMO_ATTR_CF_KERNER_PHI);
1441
allowedCFModelAttrs[SUMO_TAG_CF_BKERNER] = bkernerParams;
1442
allParams.insert(bkernerParams.begin(), bkernerParams.end());
1443
// Wiedemann
1444
std::set<SumoXMLAttr> wiedemannParams(genericParams);
1445
wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_SECURITY);
1446
wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_ESTIMATION);
1447
allowedCFModelAttrs[SUMO_TAG_CF_WIEDEMANN] = wiedemannParams;
1448
allParams.insert(wiedemannParams.begin(), wiedemannParams.end());
1449
// W99
1450
std::set<SumoXMLAttr> w99Params(genericParams);
1451
w99Params.insert(SUMO_ATTR_CF_W99_CC1);
1452
w99Params.insert(SUMO_ATTR_CF_W99_CC2);
1453
w99Params.insert(SUMO_ATTR_CF_W99_CC3);
1454
w99Params.insert(SUMO_ATTR_CF_W99_CC4);
1455
w99Params.insert(SUMO_ATTR_CF_W99_CC5);
1456
w99Params.insert(SUMO_ATTR_CF_W99_CC6);
1457
w99Params.insert(SUMO_ATTR_CF_W99_CC7);
1458
w99Params.insert(SUMO_ATTR_CF_W99_CC8);
1459
w99Params.insert(SUMO_ATTR_CF_W99_CC9);
1460
allowedCFModelAttrs[SUMO_TAG_CF_W99] = w99Params;
1461
allParams.insert(w99Params.begin(), w99Params.end());
1462
// Rail
1463
std::set<SumoXMLAttr> railParams(genericParams);
1464
railParams.insert(SUMO_ATTR_TRAIN_TYPE);
1465
railParams.insert(SUMO_ATTR_TRACTION_TABLE);
1466
railParams.insert(SUMO_ATTR_RESISTANCE_TABLE);
1467
railParams.insert(SUMO_ATTR_MASSFACTOR);
1468
railParams.insert(SUMO_ATTR_MAXPOWER);
1469
railParams.insert(SUMO_ATTR_MAXTRACTION);
1470
railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_CONSTANT);
1471
railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_LINEAR);
1472
railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_QUADRATIC);
1473
allowedCFModelAttrs[SUMO_TAG_CF_RAIL] = railParams;
1474
allParams.insert(railParams.begin(), railParams.end());
1475
// ACC
1476
std::set<SumoXMLAttr> ACCParams(genericParams);
1477
ACCParams.insert(SUMO_ATTR_SC_GAIN);
1478
ACCParams.insert(SUMO_ATTR_GCC_GAIN_SPEED);
1479
ACCParams.insert(SUMO_ATTR_GCC_GAIN_SPACE);
1480
ACCParams.insert(SUMO_ATTR_GC_GAIN_SPEED);
1481
ACCParams.insert(SUMO_ATTR_GC_GAIN_SPACE);
1482
ACCParams.insert(SUMO_ATTR_CA_GAIN_SPEED);
1483
ACCParams.insert(SUMO_ATTR_CA_GAIN_SPACE);
1484
ACCParams.insert(SUMO_ATTR_CA_OVERRIDE);
1485
ACCParams.insert(SUMO_ATTR_APPLYDRIVERSTATE);
1486
allowedCFModelAttrs[SUMO_TAG_CF_ACC] = ACCParams;
1487
allParams.insert(ACCParams.begin(), ACCParams.end());
1488
// CACC
1489
std::set<SumoXMLAttr> CACCParams(genericParams);
1490
CACCParams.insert(SUMO_ATTR_SC_GAIN_CACC);
1491
CACCParams.insert(SUMO_ATTR_GCC_GAIN_GAP_CACC);
1492
CACCParams.insert(SUMO_ATTR_GCC_GAIN_GAP_DOT_CACC);
1493
CACCParams.insert(SUMO_ATTR_GC_GAIN_GAP_CACC);
1494
CACCParams.insert(SUMO_ATTR_GC_GAIN_GAP_DOT_CACC);
1495
CACCParams.insert(SUMO_ATTR_CA_GAIN_GAP_CACC);
1496
CACCParams.insert(SUMO_ATTR_CA_GAIN_GAP_DOT_CACC);
1497
CACCParams.insert(SUMO_ATTR_GCC_GAIN_SPEED);
1498
CACCParams.insert(SUMO_ATTR_GCC_GAIN_SPACE);
1499
CACCParams.insert(SUMO_ATTR_GC_GAIN_SPEED);
1500
CACCParams.insert(SUMO_ATTR_GC_GAIN_SPACE);
1501
CACCParams.insert(SUMO_ATTR_CA_GAIN_SPEED);
1502
CACCParams.insert(SUMO_ATTR_CA_GAIN_SPACE);
1503
CACCParams.insert(SUMO_ATTR_CA_OVERRIDE);
1504
CACCParams.insert(SUMO_ATTR_HEADWAY_TIME_CACC_TO_ACC);
1505
CACCParams.insert(SUMO_ATTR_APPLYDRIVERSTATE);
1506
CACCParams.insert(SUMO_ATTR_SC_MIN_GAP);
1507
allowedCFModelAttrs[SUMO_TAG_CF_CACC] = CACCParams;
1508
allParams.insert(CACCParams.begin(), CACCParams.end());
1509
// CC
1510
std::set<SumoXMLAttr> ccParams(genericParams);
1511
ccParams.insert(SUMO_ATTR_CF_CC_C1);
1512
ccParams.insert(SUMO_ATTR_CF_CC_CCDECEL);
1513
ccParams.insert(SUMO_ATTR_CF_CC_CONSTSPACING);
1514
ccParams.insert(SUMO_ATTR_CF_CC_KP);
1515
ccParams.insert(SUMO_ATTR_CF_CC_LAMBDA);
1516
ccParams.insert(SUMO_ATTR_CF_CC_OMEGAN);
1517
ccParams.insert(SUMO_ATTR_CF_CC_TAU);
1518
ccParams.insert(SUMO_ATTR_CF_CC_XI);
1519
ccParams.insert(SUMO_ATTR_CF_CC_LANES_COUNT);
1520
ccParams.insert(SUMO_ATTR_CF_CC_CCACCEL);
1521
ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_KP);
1522
ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_KD);
1523
ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_H);
1524
ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KA);
1525
ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KV);
1526
ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KP);
1527
ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_D);
1528
ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_H);
1529
allowedCFModelAttrs[SUMO_TAG_CF_CC] = ccParams;
1530
allParams.insert(ccParams.begin(), ccParams.end());
1531
// last element
1532
allowedCFModelAttrs[SUMO_TAG_NOTHING] = allParams;
1533
}
1534
return allowedCFModelAttrs;
1535
}
1536
1537
1538
bool
1539
SUMOVehicleParserHelper::parseLCParams(SUMOVTypeParameter* into, LaneChangeModel model, const SUMOSAXAttributes& attrs) {
1540
if (allowedLCModelAttrs.size() == 0) {
1541
// lc2013
1542
std::set<SumoXMLAttr> lc2013Params;
1543
lc2013Params.insert(SUMO_ATTR_LCA_STRATEGIC_PARAM);
1544
lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_PARAM);
1545
lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_PARAM);
1546
lc2013Params.insert(SUMO_ATTR_LCA_KEEPRIGHT_PARAM);
1547
lc2013Params.insert(SUMO_ATTR_LCA_OPPOSITE_PARAM);
1548
lc2013Params.insert(SUMO_ATTR_LCA_LOOKAHEADLEFT);
1549
lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAINRIGHT);
1550
lc2013Params.insert(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING);
1551
lc2013Params.insert(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR);
1552
lc2013Params.insert(SUMO_ATTR_LCA_MAXDISTLATSTANDING);
1553
lc2013Params.insert(SUMO_ATTR_LCA_ASSERTIVE);
1554
lc2013Params.insert(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD);
1555
lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD);
1556
lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME);
1557
lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_URGENCY);
1558
lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT);
1559
lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_SPEED);
1560
lc2013Params.insert(SUMO_ATTR_LCA_OVERTAKE_RIGHT);
1561
lc2013Params.insert(SUMO_ATTR_LCA_SIGMA);
1562
lc2013Params.insert(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME);
1563
lc2013Params.insert(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR);
1564
lc2013Params.insert(SUMO_ATTR_LCA_CONTRIGHT);
1565
lc2013Params.insert(SUMO_ATTR_LCA_EXPERIMENTAL1);
1566
allowedLCModelAttrs[LaneChangeModel::LC2013] = lc2013Params;
1567
// sl2015 (extension of lc2013)
1568
std::set<SumoXMLAttr> sl2015Params = lc2013Params;
1569
sl2015Params.insert(SUMO_ATTR_LCA_PUSHY);
1570
sl2015Params.insert(SUMO_ATTR_LCA_PUSHYGAP);
1571
sl2015Params.insert(SUMO_ATTR_LCA_SUBLANE_PARAM);
1572
sl2015Params.insert(SUMO_ATTR_LCA_IMPATIENCE);
1573
sl2015Params.insert(SUMO_ATTR_LCA_TIME_TO_IMPATIENCE);
1574
sl2015Params.insert(SUMO_ATTR_LCA_ACCEL_LAT);
1575
sl2015Params.insert(SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE);
1576
sl2015Params.insert(SUMO_ATTR_LCA_LANE_DISCIPLINE);
1577
allowedLCModelAttrs[LaneChangeModel::SL2015] = sl2015Params;
1578
// DK2008
1579
std::set<SumoXMLAttr> noParams;
1580
allowedLCModelAttrs[LaneChangeModel::DK2008] = noParams;
1581
// default model may be either LC2013 or SL2015
1582
// we allow both sets (sl2015 is a superset of lc2013Params)
1583
allowedLCModelAttrs[LaneChangeModel::DEFAULT] = sl2015Params;
1584
}
1585
std::set<SumoXMLAttr> allowed = allowedLCModelAttrs[model];
1586
// iterate over LCM attributes
1587
for (const auto& it : allowed) {
1588
if (attrs.hasAttribute(it)) {
1589
// first obtain CFM attribute in string format
1590
bool ok = true;
1591
std::string parsedLCMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1592
if (!ok) {
1593
return false;
1594
}
1595
// declare a double in wich save CFM attribute
1596
double LCMAttribute = -1;
1597
try {
1598
// obtain CFM attribute in double format
1599
LCMAttribute = StringUtils::toDouble(parsedLCMAttribute);
1600
} catch (...) {
1601
WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Cannot be parsed to float"), toString(it));
1602
return false;
1603
}
1604
// check attributes of type "nonNegativeFloatType" (>= 0)
1605
switch (it) {
1606
case SUMO_ATTR_LCA_PUSHYGAP:
1607
case SUMO_ATTR_LCA_MAXSPEEDLATSTANDING:
1608
case SUMO_ATTR_LCA_IMPATIENCE:
1609
case SUMO_ATTR_LCA_OVERTAKE_RIGHT:
1610
case SUMO_ATTR_LCA_ASSERTIVE:
1611
case SUMO_ATTR_LCA_LOOKAHEADLEFT:
1612
case SUMO_ATTR_LCA_SPEEDGAINRIGHT:
1613
case SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE:
1614
case SUMO_ATTR_LCA_TIME_TO_IMPATIENCE:
1615
case SUMO_ATTR_LCA_LANE_DISCIPLINE:
1616
case SUMO_ATTR_LCA_SIGMA:
1617
if (LCMAttribute < 0) {
1618
WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be equal or greater than 0"), toString(it));
1619
return false;
1620
}
1621
break;
1622
default:
1623
break;
1624
}
1625
// check attributes of type "positiveFloatType" (> 0)
1626
switch (it) {
1627
case SUMO_ATTR_LCA_ACCEL_LAT:
1628
if (LCMAttribute <= 0) {
1629
WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be greater than 0"), toString(it));
1630
return false;
1631
}
1632
break;
1633
default:
1634
break;
1635
}
1636
// check limits of attributes
1637
switch (it) {
1638
case SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR:
1639
if (LCMAttribute < -1 || LCMAttribute > 1) {
1640
WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be between -1 and 1"), toString(it));
1641
return false;
1642
}
1643
break;
1644
default:
1645
break;
1646
}
1647
// add parsedLCMAttribute to cfParameter
1648
into->lcParameter[it] = parsedLCMAttribute;
1649
}
1650
}
1651
// all LCM parsed ok, then return true
1652
return true;
1653
}
1654
1655
1656
bool
1657
SUMOVehicleParserHelper::parseJMParams(SUMOVTypeParameter* into, const SUMOSAXAttributes& attrs) {
1658
for (const auto& it : SUMOVTypeParameter::AllowedJMAttrs) {
1659
if (attrs.hasAttribute(it)) {
1660
// first obtain CFM attribute in string format
1661
bool ok = true;
1662
std::string parsedJMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1663
if (!ok) {
1664
return false;
1665
}
1666
// declare a double in wich save CFM attribute
1667
double JMAttribute = INVALID_DOUBLE;
1668
try {
1669
// obtain CFM attribute in double format
1670
JMAttribute = StringUtils::toDouble(parsedJMAttribute);
1671
} catch (...) {
1672
WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Cannot be parsed to float"), toString(it));
1673
return false;
1674
}
1675
// now continue checking other properties (-1 is the default value)
1676
if (JMAttribute != INVALID_DOUBLE) {
1677
// special case for sigma minor
1678
if (it == SUMO_ATTR_JM_SIGMA_MINOR) {
1679
// check attributes sigma minor
1680
if ((JMAttribute < 0) || (JMAttribute > 1)) {
1681
WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Only values between [0-1] are allowed"), toString(it));
1682
return false;
1683
}
1684
} else if (JMAttribute < 0
1685
&& it != SUMO_ATTR_JM_TIMEGAP_MINOR
1686
&& it != SUMO_ATTR_JM_EXTRA_GAP) {
1687
// attributes with error value
1688
if (JMAttribute != -1 || (it != SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME
1689
&& it != SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME
1690
&& it != SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME)) {
1691
// check attributes of type "nonNegativeFloatType" (>= 0)
1692
WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Must be equal or greater than 0"), toString(it));
1693
return false;
1694
}
1695
}
1696
// add parsedJMAttribute to cfParameter
1697
into->jmParameter[it] = parsedJMAttribute;
1698
}
1699
}
1700
}
1701
// all JM parameters successfully parsed, then return true
1702
return true;
1703
}
1704
1705
1706
SUMOVehicleClass
1707
SUMOVehicleParserHelper::parseVehicleClass(const SUMOSAXAttributes& attrs, const std::string& id) {
1708
SUMOVehicleClass vclass = SVC_IGNORING;
1709
bool ok = true;
1710
std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_VCLASS, id.c_str(), ok, "");
1711
if (vclassS == "") {
1712
return vclass;
1713
}
1714
try {
1715
const SUMOVehicleClass result = getVehicleClassID(vclassS);
1716
const std::string& realName = SumoVehicleClassStrings.getString(result);
1717
if (realName != vclassS) {
1718
WRITE_WARNING("The vehicle class '" + vclassS + "' for " + attrs.getObjectType() + " '" + id + "' is deprecated, use '" + realName + "' instead.");
1719
}
1720
return result;
1721
} catch (...) {
1722
WRITE_ERRORF(TL("The vehicle class '%' for % '%' is not known."), vclassS, attrs.getObjectType(), id);
1723
}
1724
return vclass;
1725
}
1726
1727
1728
SUMOVehicleShape
1729
SUMOVehicleParserHelper::parseGuiShape(const SUMOSAXAttributes& attrs, const std::string& id) {
1730
bool ok = true;
1731
std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_GUISHAPE, id.c_str(), ok, "");
1732
if (SumoVehicleShapeStrings.hasString(vclassS)) {
1733
const SUMOVehicleShape result = SumoVehicleShapeStrings.get(vclassS);
1734
const std::string& realName = SumoVehicleShapeStrings.getString(result);
1735
if (realName != vclassS) {
1736
WRITE_WARNING("The shape '" + vclassS + "' for " + attrs.getObjectType() + " '" + id + "' is deprecated, use '" + realName + "' instead.");
1737
}
1738
return result;
1739
} else {
1740
WRITE_ERRORF(TL("The shape '%' for % '%' is not known."), vclassS, attrs.getObjectType(), id);
1741
return SUMOVehicleShape::UNKNOWN;
1742
}
1743
}
1744
1745
1746
double
1747
SUMOVehicleParserHelper::parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string& id, double maxPos, const std::string& val, SumoRNG* rng) {
1748
double result;
1749
std::string error;
1750
ArrivalPosDefinition proc = ArrivalPosDefinition::DEFAULT;
1751
// only supports 'random' and 'max'
1752
if (!SUMOVehicleParameter::parseArrivalPos(val, toString(SUMO_TAG_WALK), id, result, proc, error)) {
1753
handleVehicleError(hardFail, nullptr, error);
1754
}
1755
if (proc == ArrivalPosDefinition::RANDOM) {
1756
result = RandHelper::rand(maxPos, rng);
1757
} else if (proc == ArrivalPosDefinition::CENTER) {
1758
result = maxPos / 2.;
1759
} else if (proc == ArrivalPosDefinition::MAX) {
1760
result = maxPos;
1761
}
1762
return SUMOVehicleParameter::interpretEdgePos(result, maxPos, attr, id);
1763
}
1764
1765
1766
SUMOTime
1767
SUMOVehicleParserHelper::processActionStepLength(double given) {
1768
const std::string defaultError = "The parameter action-step-length must be a non-negative multiple of the simulation step-length. ";
1769
SUMOTime result = TIME2STEPS(given);
1770
if (result <= 0) {
1771
if (result < 0) {
1772
WRITE_WARNING(defaultError + "Ignoring given value (=" + toString(STEPS2TIME(result)) + " s.)");
1773
}
1774
result = DELTA_T;
1775
} else if (result % DELTA_T != 0 && OptionsCont::getOptions().exists("step-length")) {
1776
result = (SUMOTime)((double)DELTA_T * floor(double(result) / double(DELTA_T)));
1777
result = MAX2(DELTA_T, result);
1778
if (fabs(given * 1000. - double(result)) > NUMERICAL_EPS) {
1779
WRITE_WARNING(defaultError + "Parsing given value (" + toString(given) + " s.) to the adjusted value " + toString(STEPS2TIME(result)) + " s.");
1780
}
1781
}
1782
return result;
1783
}
1784
1785
1786
bool
1787
SUMOVehicleParserHelper::isInternalRouteID(const std::string& id) {
1788
return id.substr(0, 1) == "!";
1789
}
1790
1791
1792
bool
1793
SUMOVehicleParserHelper::validProfile(SUMOVTypeParameter* vtype, const std::string data, const SumoXMLAttr attr) {
1794
for (std::string value : StringTokenizer(data).getVector()) {
1795
try {
1796
double v = StringUtils::toDouble(value);
1797
if (v < 0.) {
1798
WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. An acceleration profile value cannot be negative"), toString(attr));
1799
return false;
1800
}
1801
} catch (...) {
1802
WRITE_ERRORF(TL("Entry '%' of % table for vType '%' cannot be parsed as 'double'"), value, toString(attr), vtype->id);
1803
return false;
1804
}
1805
}
1806
return true;
1807
}
1808
1809
1810
int
1811
SUMOVehicleParserHelper::parseCarWalkTransfer(const OptionsCont& oc, const bool hasTaxi) {
1812
int carWalk = 0;
1813
for (const std::string& opt : oc.getStringVector("persontrip.transfer.car-walk")) {
1814
if (opt == "parkingAreas") {
1815
carWalk |= ModeChangeOptions::PARKING_AREAS;
1816
} else if (opt == "ptStops") {
1817
carWalk |= ModeChangeOptions::PT_STOPS;
1818
} else if (opt == "allJunctions") {
1819
carWalk |= ModeChangeOptions::ALL_JUNCTIONS;
1820
} else {
1821
WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1822
}
1823
}
1824
const StringVector taxiDropoff = oc.getStringVector("persontrip.transfer.taxi-walk");
1825
const StringVector taxiPickup = oc.getStringVector("persontrip.transfer.walk-taxi");
1826
if (taxiDropoff.empty() && hasTaxi) {
1827
carWalk |= ModeChangeOptions::TAXI_DROPOFF_ANYWHERE;
1828
} else {
1829
for (const std::string& opt : taxiDropoff) {
1830
if (opt == "parkingAreas") {
1831
carWalk |= ModeChangeOptions::TAXI_DROPOFF_PARKING_AREAS;
1832
} else if (opt == "ptStops") {
1833
carWalk |= ModeChangeOptions::TAXI_DROPOFF_PT;
1834
} else if (opt == "allJunctions") {
1835
carWalk |= ModeChangeOptions::TAXI_DROPOFF_ANYWHERE;
1836
} else {
1837
WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1838
}
1839
}
1840
}
1841
if (taxiPickup.empty() && hasTaxi) {
1842
carWalk |= ModeChangeOptions::TAXI_PICKUP_ANYWHERE;
1843
} else {
1844
for (const std::string& opt : taxiPickup) {
1845
if (opt == "parkingAreas") {
1846
carWalk |= ModeChangeOptions::TAXI_PICKUP_PARKING_AREAS;
1847
} else if (opt == "ptStops") {
1848
carWalk |= ModeChangeOptions::TAXI_PICKUP_PT;
1849
} else if (opt == "allJunctions") {
1850
carWalk |= ModeChangeOptions::TAXI_PICKUP_ANYWHERE;
1851
} else {
1852
WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1853
}
1854
}
1855
}
1856
return carWalk;
1857
}
1858
1859
1860
SUMOVehicleParameter*
1861
SUMOVehicleParserHelper::handleVehicleError(const bool hardFail, SUMOVehicleParameter* vehicleParameter, const std::string message) {
1862
if (vehicleParameter) {
1863
delete vehicleParameter;
1864
}
1865
if (hardFail) {
1866
throw ProcessError(message);
1867
} else if (message.size() > 0) {
1868
WRITE_ERROR(message);
1869
}
1870
return nullptr;
1871
}
1872
1873
1874
SUMOVTypeParameter*
1875
SUMOVehicleParserHelper::handleVehicleTypeError(const bool hardFail, SUMOVTypeParameter* vehicleTypeParameter, const std::string message) {
1876
if (vehicleTypeParameter) {
1877
delete vehicleTypeParameter;
1878
}
1879
if (hardFail) {
1880
throw ProcessError(message);
1881
} else if (message.size() > 0) {
1882
WRITE_ERROR(message);
1883
}
1884
return nullptr;
1885
}
1886
1887
/****************************************************************************/
1888
1889