Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/vehicle/SUMOVehicleParameter.cpp
169678 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
// 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 SUMOVehicleParameter.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Tue, 31.03.2009
19
///
20
// Structure representing possible vehicle parameter
21
/****************************************************************************/
22
#include <config.h>
23
#include <utils/common/MsgHandler.h>
24
#include <utils/common/StringTokenizer.h>
25
#include <utils/common/StringUtils.h>
26
#include <utils/common/ToString.h>
27
#include <utils/common/RandHelper.h>
28
#include <utils/iodevices/OutputDevice.h>
29
#include <utils/options/OptionsCont.h>
30
31
#include "SUMOVehicleParameter.h"
32
33
// ===========================================================================
34
// member method definitions
35
// ===========================================================================
36
37
SUMOVehicleParameter::SUMOVehicleParameter()
38
: tag(SUMO_TAG_NOTHING), vtypeid(DEFAULT_VTYPE_ID), color(RGBColor::DEFAULT_COLOR),
39
depart(-1), departProcedure(DepartDefinition::GIVEN),
40
departLane(0), departLaneProcedure(DepartLaneDefinition::DEFAULT),
41
departPos(0), departPosProcedure(DepartPosDefinition::DEFAULT),
42
departPosLat(0), departPosLatProcedure(DepartPosLatDefinition::DEFAULT),
43
departSpeed(-1), departSpeedProcedure(DepartSpeedDefinition::DEFAULT),
44
departEdge(0), departEdgeProcedure(RouteIndexDefinition::DEFAULT),
45
arrivalLane(0), arrivalLaneProcedure(ArrivalLaneDefinition::DEFAULT),
46
arrivalPos(0), arrivalPosProcedure(ArrivalPosDefinition::DEFAULT),
47
arrivalPosLat(0), arrivalPosLatProcedure(ArrivalPosLatDefinition::DEFAULT),
48
arrivalSpeed(-1), arrivalSpeedProcedure(ArrivalSpeedDefinition::DEFAULT),
49
arrivalEdge(-1), arrivalEdgeProcedure(RouteIndexDefinition::DEFAULT),
50
repetitionNumber(-1),
51
repetitionsDone(-1),
52
repetitionOffset(-1),
53
repetitionTotalOffset(0),
54
repetitionProbability(-1),
55
poissonRate(0),
56
repetitionEnd(-1),
57
line(), fromTaz(), toTaz(), personNumber(0), containerNumber(0),
58
speedFactor(-1),
59
calibratorSpeed(-1),
60
insertionChecks((int)InsertionCheck::ALL),
61
parametersSet(0)
62
{ }
63
64
65
SUMOVehicleParameter::~SUMOVehicleParameter() {
66
}
67
68
69
bool
70
SUMOVehicleParameter::defaultOptionOverrides(const OptionsCont& oc, const std::string& optionName) const {
71
return oc.exists(optionName) && oc.isSet(optionName) && oc.getBool("defaults-override");
72
}
73
74
75
void
76
SUMOVehicleParameter::write(OutputDevice& dev, const OptionsCont& oc, const SumoXMLTag altTag, const std::string& typeID) const {
77
if (!id.empty()) {
78
// only used by calibrator flows
79
dev.openTag(altTag).writeAttr(SUMO_ATTR_ID, id);
80
}
81
if (typeID == "") {
82
if (wasSet(VEHPARS_VTYPE_SET)) {
83
dev.writeAttr(SUMO_ATTR_TYPE, vtypeid);
84
}
85
} else {
86
dev.writeAttr(SUMO_ATTR_TYPE, typeID);
87
}
88
// write depart depending of tag
89
if (altTag == SUMO_TAG_FLOW
90
|| altTag == SUMO_TAG_PERSONFLOW
91
|| altTag == SUMO_TAG_CONTAINERFLOW
92
|| altTag == GNE_TAG_FLOW_ROUTE
93
|| altTag == GNE_TAG_FLOW_WITHROUTE
94
|| altTag == SUMO_TAG_FLOWSTATE) {
95
dev.writeAttr(SUMO_ATTR_BEGIN, getDepart());
96
} else {
97
dev.writeAttr(SUMO_ATTR_DEPART, getDepart());
98
}
99
// optional parameter
100
// departlane
101
if (wasSet(VEHPARS_DEPARTLANE_SET) && !defaultOptionOverrides(oc, "departlane")) {
102
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, getDepartLane());
103
} else if (oc.exists("departlane") && oc.isSet("departlane")) {
104
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
105
}
106
// departpos
107
if (wasSet(VEHPARS_DEPARTPOS_SET) && !defaultOptionOverrides(oc, "departpos")) {
108
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, getDepartPos());
109
} else if (oc.exists("departpos") && oc.isSet("departpos")) {
110
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, oc.getString("departpos"));
111
}
112
// departPosLat
113
if (wasSet(VEHPARS_DEPARTPOSLAT_SET)) {
114
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS_LAT, getDepartPosLat());
115
}
116
// departspeed
117
if (wasSet(VEHPARS_DEPARTSPEED_SET) && !defaultOptionOverrides(oc, "departspeed")) {
118
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, getDepartSpeed());
119
} else if (oc.exists("departspeed") && oc.isSet("departspeed")) {
120
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
121
}
122
// departedge
123
if (wasSet(VEHPARS_DEPARTEDGE_SET) && !defaultOptionOverrides(oc, "departedge")) {
124
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTEDGE, getDepartEdge());
125
} else if (oc.exists("departedge") && oc.isSet("departedge")) {
126
dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTEDGE, oc.getString("departedge"));
127
}
128
// arrivallane
129
if (wasSet(VEHPARS_ARRIVALLANE_SET) && !defaultOptionOverrides(oc, "arrivallane")) {
130
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, getArrivalLane());
131
} else if (oc.exists("arrivallane") && oc.isSet("arrivallane")) {
132
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
133
}
134
// arrivalpos
135
if (wasSet(VEHPARS_ARRIVALPOS_SET) && !defaultOptionOverrides(oc, "arrivalpos")) {
136
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, getArrivalPos());
137
} else if (oc.exists("arrivalpos") && oc.isSet("arrivalpos")) {
138
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
139
}
140
// arrivalPosLat
141
if (wasSet(VEHPARS_ARRIVALPOSLAT_SET)) {
142
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS_LAT, getArrivalPosLat());
143
}
144
// arrivalspeed
145
if (wasSet(VEHPARS_ARRIVALSPEED_SET) && !defaultOptionOverrides(oc, "arrivalspeed")) {
146
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, getArrivalSpeed());
147
} else if (oc.exists("arrivalspeed") && oc.isSet("arrivalspeed")) {
148
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
149
}
150
// arrivalEdge
151
if (wasSet(VEHPARS_ARRIVALEDGE_SET) && !defaultOptionOverrides(oc, "arrivaledge") && arrivalEdge >= 0) {
152
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALEDGE, getArrivalEdge());
153
} else if (oc.exists("arrivaledge") && oc.isSet("arrivaledge")) {
154
dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALEDGE, oc.getString("arrivaledge"));
155
}
156
// color
157
if (wasSet(VEHPARS_COLOR_SET)) {
158
dev.writeAttr(SUMO_ATTR_COLOR, color);
159
}
160
// line
161
if (wasSet(VEHPARS_LINE_SET)) {
162
dev.writeAttr(SUMO_ATTR_LINE, line);
163
}
164
// from TAZ
165
if (wasSet(VEHPARS_FROM_TAZ_SET)) {
166
dev.writeAttr(SUMO_ATTR_FROM_TAZ, fromTaz);
167
}
168
// to TAZ
169
if (wasSet(VEHPARS_TO_TAZ_SET)) {
170
dev.writeAttr(SUMO_ATTR_TO_TAZ, toTaz);
171
}
172
// person number
173
if (wasSet(VEHPARS_PERSON_NUMBER_SET)) {
174
dev.writeAttr(SUMO_ATTR_PERSON_NUMBER, personNumber);
175
}
176
// container number
177
if (wasSet(VEHPARS_CONTAINER_NUMBER_SET)) {
178
dev.writeAttr(SUMO_ATTR_CONTAINER_NUMBER, containerNumber);
179
}
180
// individual speedFactor
181
if (wasSet(VEHPARS_SPEEDFACTOR_SET)) {
182
// might be saving state with custom precision
183
const int precision = dev.getPrecision();
184
dev.setPrecision(MAX2(gPrecisionRandom, precision));
185
dev.writeAttr(SUMO_ATTR_SPEEDFACTOR, speedFactor);
186
dev.setPrecision(precision);
187
}
188
// speed (only used by calibrators)
189
if (wasSet(VEHPARS_CALIBRATORSPEED_SET)) {
190
dev.writeAttr(SUMO_ATTR_SPEED, calibratorSpeed);
191
}
192
// insertionChecks
193
if (wasSet(VEHPARS_INSERTION_CHECKS_SET) && insertionChecks != (int)InsertionCheck::ALL) {
194
std::vector<std::string> checks;
195
if (insertionChecks == (int)InsertionCheck::NONE) {
196
checks.push_back(toString(InsertionCheck::NONE));
197
} else {
198
for (auto it : SUMOXMLDefinitions::InsertionChecks.getValues()) {
199
if (((int)it & insertionChecks) != 0) {
200
checks.push_back(toString(it));
201
}
202
}
203
}
204
dev.writeAttr(SUMO_ATTR_INSERTIONCHECKS, checks);
205
}
206
// parking access rights
207
if (wasSet(VEHPARS_PARKING_BADGES_SET)) {
208
dev.writeNonEmptyAttr(SUMO_ATTR_PARKING_BADGES, joinToString(parkingBadges, " "));
209
}
210
}
211
212
213
void
214
SUMOVehicleParameter::Stop::write(OutputDevice& dev, const bool close, const bool writeTagAndParents) const {
215
if (writeTagAndParents) {
216
dev.openTag(SUMO_TAG_STOP);
217
if (busstop != "") {
218
dev.writeAttr(SUMO_ATTR_BUS_STOP, busstop);
219
}
220
if (containerstop != "") {
221
dev.writeAttr(SUMO_ATTR_CONTAINER_STOP, containerstop);
222
}
223
if (chargingStation != "") {
224
dev.writeAttr(SUMO_ATTR_CHARGING_STATION, chargingStation);
225
}
226
if (parkingarea != "") {
227
dev.writeAttr(SUMO_ATTR_PARKING_AREA, parkingarea);
228
}
229
if ((busstop == "") && (containerstop == "") && (parkingarea == "") && (chargingStation == "")) {
230
if (lane != "") {
231
dev.writeAttr(SUMO_ATTR_LANE, lane);
232
} else {
233
dev.writeAttr(SUMO_ATTR_EDGE, edge);
234
}
235
if ((parametersSet & STOP_START_SET) != 0) {
236
dev.writeAttr(SUMO_ATTR_STARTPOS, startPos);
237
}
238
if ((parametersSet & STOP_END_SET) != 0) {
239
dev.writeAttr(SUMO_ATTR_ENDPOS, endPos);
240
}
241
}
242
}
243
if (index > 0) {
244
dev.writeAttr(SUMO_ATTR_INDEX, index);
245
}
246
if ((parametersSet & STOP_POSLAT_SET) != 0 && posLat != INVALID_DOUBLE) {
247
dev.writeAttr(SUMO_ATTR_POSITION_LAT, posLat);
248
}
249
if ((parametersSet & STOP_ARRIVAL_SET) && (arrival >= 0)) {
250
dev.writeAttr(SUMO_ATTR_ARRIVAL, time2string(arrival));
251
}
252
if ((parametersSet & STOP_DURATION_SET) && (duration >= 0)) {
253
dev.writeAttr(SUMO_ATTR_DURATION, time2string(duration));
254
}
255
if ((parametersSet & STOP_UNTIL_SET) && (until >= 0)) {
256
dev.writeAttr(SUMO_ATTR_UNTIL, time2string(until));
257
}
258
if ((parametersSet & STOP_STARTED_SET) && (started >= 0)) {
259
dev.writeAttr(SUMO_ATTR_STARTED, time2string(started));
260
}
261
if ((parametersSet & STOP_ENDED_SET) && (ended >= 0)) {
262
dev.writeAttr(SUMO_ATTR_ENDED, time2string(ended));
263
}
264
if ((parametersSet & STOP_EXTENSION_SET) && (extension >= 0)) {
265
dev.writeAttr(SUMO_ATTR_EXTENSION, time2string(extension));
266
}
267
if ((parametersSet & STOP_TRIGGER_SET) != 0) {
268
const std::vector<std::string> triggers = getTriggers();
269
if (triggers.size() > 0) {
270
dev.writeAttr(SUMO_ATTR_TRIGGERED, triggers);
271
}
272
}
273
if ((parametersSet & STOP_PARKING_SET) != 0) {
274
dev.writeAttr(SUMO_ATTR_PARKING, parking);
275
}
276
if ((parametersSet & STOP_EXPECTED_SET) != 0 && awaitedPersons.size() > 0) {
277
dev.writeAttr(SUMO_ATTR_EXPECTED, awaitedPersons);
278
}
279
if ((parametersSet & STOP_PERMITTED_SET) != 0 && permitted.size() > 0) {
280
dev.writeAttr(SUMO_ATTR_PERMITTED, permitted);
281
}
282
if ((parametersSet & STOP_EXPECTED_CONTAINERS_SET) != 0 && awaitedContainers.size() > 0) {
283
dev.writeAttr(SUMO_ATTR_EXPECTED_CONTAINERS, awaitedContainers);
284
}
285
if ((parametersSet & STOP_TRIP_ID_SET) != 0) {
286
dev.writeAttr(SUMO_ATTR_TRIP_ID, tripId);
287
}
288
if ((parametersSet & STOP_LINE_SET) != 0) {
289
dev.writeAttr(SUMO_ATTR_LINE, line);
290
}
291
if ((parametersSet & STOP_SPLIT_SET) != 0) {
292
dev.writeAttr(SUMO_ATTR_SPLIT, split);
293
}
294
if ((parametersSet & STOP_JOIN_SET) != 0) {
295
dev.writeAttr(SUMO_ATTR_JOIN, join);
296
}
297
if ((parametersSet & STOP_SPEED_SET) != 0) {
298
dev.writeAttr(SUMO_ATTR_SPEED, speed);
299
}
300
if ((parametersSet & STOP_ONDEMAND_SET) != 0) {
301
dev.writeAttr(SUMO_ATTR_ONDEMAND, onDemand);
302
}
303
if ((parametersSet & STOP_JUMP_SET) != 0 && jump >= 0) {
304
dev.writeAttr(SUMO_ATTR_JUMP, time2string(jump));
305
}
306
if ((parametersSet & STOP_JUMP_UNTIL_SET) != 0 && jumpUntil >= 0) {
307
dev.writeAttr(SUMO_ATTR_JUMP_UNTIL, time2string(jumpUntil));
308
}
309
if ((parametersSet & STOP_PRIORITY_SET) != 0 && priority >= 0) {
310
dev.writeAttr(SUMO_ATTR_PRIORITY, priority);
311
}
312
if (collision) {
313
dev.writeAttr(SUMO_ATTR_COLLISION, collision);
314
}
315
// only write friendly position if is true
316
if (friendlyPos) {
317
dev.writeAttr(SUMO_ATTR_FRIENDLY_POS, friendlyPos);
318
}
319
// only write act type if isn't empty
320
if (!actType.empty()) {
321
dev.writeAttr(SUMO_ATTR_ACTTYPE, actType);
322
}
323
if (close) {
324
// the user is closing the stop it is responsible for writing params
325
writeParams(dev);
326
dev.closeTag();
327
}
328
}
329
330
std::vector<std::string>
331
SUMOVehicleParameter::Stop::getStoppingPlaceIDs() const {
332
std::vector<std::string> result;
333
if (busstop != "") {
334
result.push_back(busstop);
335
}
336
if (containerstop != "") {
337
result.push_back(containerstop);
338
}
339
if (chargingStation != "") {
340
result.push_back(chargingStation);
341
}
342
if (parkingarea != "") {
343
result.push_back(parkingarea);
344
}
345
return result;
346
}
347
348
bool
349
SUMOVehicleParameter::parseDepart(const std::string& val, const std::string& element, const std::string& id,
350
SUMOTime& depart, DepartDefinition& dd, std::string& error, const std::string& attr) {
351
if (val == "triggered") {
352
dd = DepartDefinition::TRIGGERED;
353
} else if (val == "containerTriggered") {
354
dd = DepartDefinition::CONTAINER_TRIGGERED;
355
} else if (val == "now") {
356
// only used via TraCI. depart must be set by the calling code
357
dd = DepartDefinition::NOW;
358
} else if (val == "split") {
359
dd = DepartDefinition::SPLIT;
360
} else if (val == "begin") {
361
dd = DepartDefinition::BEGIN;
362
} else {
363
try {
364
depart = string2time(val);
365
dd = DepartDefinition::GIVEN;
366
if (depart < 0) {
367
error = "Negative " + attr + " time in the definition of " + element + " '" + id + "'.";
368
return false;
369
}
370
} catch (...) {
371
if (id.empty()) {
372
error = "Invalid " + attr + " time for " + element + ". Must be one of (\"triggered\", \"containerTriggered\", \"now\", or a float >= 0)";
373
} else {
374
error = "Invalid " + attr + " time for " + element + " '" + id + "';\n must be one of (\"triggered\", \"containerTriggered\", \"now\", or a float >= 0)";
375
}
376
return false;
377
}
378
}
379
return true;
380
}
381
382
383
bool
384
SUMOVehicleParameter::parseDepartLane(const std::string& val, const std::string& element, const std::string& id,
385
int& lane, DepartLaneDefinition& dld, std::string& error) {
386
bool ok = true;
387
lane = 0;
388
dld = DepartLaneDefinition::GIVEN;
389
if (val == "random") {
390
dld = DepartLaneDefinition::RANDOM;
391
} else if (val == "free") {
392
dld = DepartLaneDefinition::FREE;
393
} else if (val == "allowed") {
394
dld = DepartLaneDefinition::ALLOWED_FREE;
395
} else if (val == "best") {
396
dld = DepartLaneDefinition::BEST_FREE;
397
} else if (val == "best_prob") {
398
dld = DepartLaneDefinition::BEST_PROB;
399
} else if (val == "first") {
400
dld = DepartLaneDefinition::FIRST_ALLOWED;
401
} else {
402
try {
403
lane = StringUtils::toInt(val);
404
if (lane < 0) {
405
ok = false;
406
}
407
} catch (...) {
408
ok = false;
409
}
410
}
411
if (!ok) {
412
if (id.empty()) {
413
error = "Invalid departLane definition for " + element + ". Must be one of (\"random\", \"free\", \"allowed\", \"best\", \"best_prob\", \"first\", or an int>=0)";
414
} else {
415
error = "Invalid departLane definition for " + element + " '" + id + "';\n must be one of (\"random\", \"free\", \"allowed\", \"best\", \"best_prob\", \"first\", or an int>=0)";
416
}
417
}
418
return ok;
419
}
420
421
422
bool
423
SUMOVehicleParameter::parseDepartPos(const std::string& val, const std::string& element, const std::string& id,
424
double& pos, DepartPosDefinition& dpd, std::string& error) {
425
bool ok = true;
426
pos = 0.;
427
dpd = DepartPosDefinition::GIVEN;
428
if (val == "random") {
429
dpd = DepartPosDefinition::RANDOM;
430
} else if (val == "random_free") {
431
dpd = DepartPosDefinition::RANDOM_FREE;
432
} else if (val == "random_location") {
433
dpd = DepartPosDefinition::RANDOM_LOCATION;
434
} else if (val == "free") {
435
dpd = DepartPosDefinition::FREE;
436
} else if (val == "base") {
437
dpd = DepartPosDefinition::BASE;
438
} else if (val == "last") {
439
dpd = DepartPosDefinition::LAST;
440
} else if (val == "splitFront") {
441
dpd = DepartPosDefinition::SPLIT_FRONT;
442
} else if (val == "stop") {
443
dpd = DepartPosDefinition::STOP;
444
} else {
445
try {
446
pos = StringUtils::toDouble(val);
447
} catch (...) {
448
ok = false;
449
}
450
}
451
if (!ok) {
452
if (id.empty()) {
453
error = "Invalid departPos definition for " + element + ". Must be one of (\"random\", \"random_free\", \"free\", \"base\", \"last\" or a float)";
454
} else {
455
error = "Invalid departPos definition for " + element + " '" + id + "';\n must be one of (\"random\", \"random_free\", \"free\", \"base\", \"last\" or a float)";
456
}
457
}
458
return ok;
459
}
460
461
462
bool
463
SUMOVehicleParameter::parseDepartPosLat(const std::string& val, const std::string& element, const std::string& id,
464
double& pos, DepartPosLatDefinition& dpd, std::string& error) {
465
bool ok = true;
466
pos = 0.;
467
dpd = DepartPosLatDefinition::GIVEN;
468
if (val == "random") {
469
dpd = DepartPosLatDefinition::RANDOM;
470
} else if (val == "random_free") {
471
dpd = DepartPosLatDefinition::RANDOM_FREE;
472
} else if (val == "free") {
473
dpd = DepartPosLatDefinition::FREE;
474
} else if (val == "right") {
475
dpd = DepartPosLatDefinition::RIGHT;
476
} else if (val == "center") {
477
dpd = DepartPosLatDefinition::CENTER;
478
} else if (val == "left") {
479
dpd = DepartPosLatDefinition::LEFT;
480
} else {
481
try {
482
pos = StringUtils::toDouble(val);
483
} catch (...) {
484
ok = false;
485
}
486
}
487
if (!ok) {
488
if (id.empty()) {
489
error = "Invalid departPosLat definition for " + element + ". Must be one of (\"random\", \"random_free\", \"free\", \"right\", \"center\", \"left\", or a float)";
490
} else {
491
error = "Invalid departPosLat definition for " + element + " '" + id + "';\n must be one of (\"random\", \"random_free\", \"free\", \"right\", \"center\", \"left\", or a float)";
492
}
493
}
494
return ok;
495
}
496
497
498
bool
499
SUMOVehicleParameter::parseDepartSpeed(const std::string& val, const std::string& element, const std::string& id,
500
double& speed, DepartSpeedDefinition& dsd, std::string& error) {
501
bool ok = true;
502
speed = -1.;
503
dsd = DepartSpeedDefinition::GIVEN;
504
if (val == "random") {
505
dsd = DepartSpeedDefinition::RANDOM;
506
} else if (val == "max") {
507
dsd = DepartSpeedDefinition::MAX;
508
} else if (val == "desired") {
509
dsd = DepartSpeedDefinition::DESIRED;
510
} else if (val == "speedLimit") {
511
dsd = DepartSpeedDefinition::LIMIT;
512
} else if (val == "last") {
513
dsd = DepartSpeedDefinition::LAST;
514
} else if (val == "avg") {
515
dsd = DepartSpeedDefinition::AVG;
516
} else {
517
try {
518
speed = StringUtils::toDouble(val);
519
if (speed < 0) {
520
ok = false;
521
}
522
} catch (...) {
523
ok = false;
524
}
525
}
526
if (!ok) {
527
if (id.empty()) {
528
error = "Invalid departSpeed definition for " + element + ". Must be one of (\"random\", \"max\", or a float>=0)";
529
} else {
530
error = "Invalid departSpeed definition for " + element + " '" + id + "';\n must be one of (\"random\", \"max\", or a float>=0)";
531
}
532
}
533
return ok;
534
}
535
536
537
bool
538
SUMOVehicleParameter::parseRouteIndex(const std::string& val, const std::string& element, const std::string& id,
539
const SumoXMLAttr attr, int& edgeIndex, RouteIndexDefinition& rid, std::string& error) {
540
bool ok = true;
541
edgeIndex = -1;
542
rid = RouteIndexDefinition::GIVEN;
543
if (val == "random") {
544
rid = RouteIndexDefinition::RANDOM;
545
} else {
546
try {
547
edgeIndex = StringUtils::toInt(val);
548
if (edgeIndex < 0) {
549
ok = false;
550
}
551
} catch (...) {
552
ok = false;
553
}
554
}
555
if (!ok) {
556
if (id.empty()) {
557
error = "Invalid " + toString(attr) + " definition for " + element + ". Must be one of (\"random\", \"free\", or an int>=0)";
558
} else {
559
error = "Invalid " + toString(attr) + " definition for " + element + " '" + id + "';\n must be one of (\"random\", \"free\", or an int>=0)";
560
}
561
}
562
return ok;
563
}
564
565
566
bool
567
SUMOVehicleParameter::parseArrivalLane(const std::string& val, const std::string& element, const std::string& id,
568
int& lane, ArrivalLaneDefinition& ald, std::string& error) {
569
bool ok = true;
570
lane = 0;
571
ald = ArrivalLaneDefinition::GIVEN;
572
if (val == "current") {
573
ald = ArrivalLaneDefinition::CURRENT;
574
} else if (val == "random") {
575
ald = ArrivalLaneDefinition::RANDOM;
576
} else if (val == "first") {
577
ald = ArrivalLaneDefinition::FIRST_ALLOWED;
578
} else {
579
try {
580
lane = StringUtils::toInt(val);
581
if (lane < 0) {
582
ok = false;
583
}
584
} catch (...) {
585
ok = false;
586
}
587
}
588
if (!ok) {
589
if (id.empty()) {
590
error = "Invalid arrivalLane definition for " + element + ". Must be one of (\"current\", or an int>=0)";
591
} else {
592
error = "Invalid arrivalLane definition for " + element + " '" + id + "';\n must be one of (\"current\", or an int>=0)";
593
}
594
}
595
return ok;
596
}
597
598
599
bool
600
SUMOVehicleParameter::parseArrivalPos(const std::string& val, const std::string& element, const std::string& id,
601
double& pos, ArrivalPosDefinition& apd, std::string& error) {
602
bool ok = true;
603
pos = 0.;
604
apd = ArrivalPosDefinition::GIVEN;
605
if (val == "random") {
606
apd = ArrivalPosDefinition::RANDOM;
607
} else if (val == "center") {
608
apd = ArrivalPosDefinition::CENTER;
609
} else if (val == "max") {
610
apd = ArrivalPosDefinition::MAX;
611
} else {
612
try {
613
pos = StringUtils::toDouble(val);
614
} catch (...) {
615
ok = false;
616
}
617
}
618
if (!ok) {
619
if (id.empty()) {
620
error = "Invalid arrivalPos definition for " + element + ". Must be one of (\"random\", \"max\", or a float)";
621
} else {
622
error = "Invalid arrivalPos definition for " + element + " '" + id + "';\n must be one of (\"random\", \"max\", or a float)";
623
}
624
}
625
return ok;
626
}
627
628
629
bool
630
SUMOVehicleParameter::parseArrivalPosLat(const std::string& val, const std::string& element, const std::string& id,
631
double& pos, ArrivalPosLatDefinition& apd, std::string& error) {
632
bool ok = true;
633
pos = 0.;
634
apd = ArrivalPosLatDefinition::GIVEN;
635
if (val == "right") {
636
apd = ArrivalPosLatDefinition::RIGHT;
637
} else if (val == "center") {
638
apd = ArrivalPosLatDefinition::CENTER;
639
} else if (val == "left") {
640
apd = ArrivalPosLatDefinition::LEFT;
641
} else {
642
try {
643
pos = StringUtils::toDouble(val);
644
} catch (...) {
645
ok = false;
646
}
647
}
648
if (!ok) {
649
if (id.empty()) {
650
error = "Invalid arrivalPosLat definition for " + element + ". Must be one of (\"right\", \"center\", \"left\", or a float)";
651
} else {
652
error = "Invalid arrivalPosLat definition for " + element + " '" + id + "';\n must be one of (\"right\", \"center\", \"left\", or a float)";
653
}
654
}
655
return ok;
656
}
657
658
659
bool
660
SUMOVehicleParameter::parseArrivalSpeed(const std::string& val, const std::string& element, const std::string& id,
661
double& speed, ArrivalSpeedDefinition& asd, std::string& error) {
662
bool ok = true;
663
speed = -1.;
664
asd = ArrivalSpeedDefinition::GIVEN;
665
if (val == "current") {
666
asd = ArrivalSpeedDefinition::CURRENT;
667
} else {
668
try {
669
speed = StringUtils::toDouble(val);
670
if (speed < 0) {
671
ok = false;
672
}
673
} catch (...) {
674
ok = false;
675
}
676
}
677
if (!ok) {
678
if (id.empty()) {
679
error = "Invalid arrivalSpeed definition for " + element + ". Must be one of (\"current\", or a float>=0)";
680
} else {
681
error = "Invalid arrivalSpeed definition for " + element + " '" + id + "';\n must be one of (\"current\", or a float>=0)";
682
}
683
}
684
return ok;
685
}
686
687
688
double
689
SUMOVehicleParameter::interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string& id, bool silent) {
690
if (pos < 0) {
691
pos = maximumValue + pos;
692
}
693
if (pos > maximumValue && pos != std::numeric_limits<double>::infinity()) {
694
if (!silent) {
695
WRITE_WARNINGF(TL("Invalid % % given for %. Using edge end instead."), toString(attr), toString(pos), id);
696
}
697
pos = maximumValue;
698
}
699
return pos;
700
}
701
702
703
bool
704
SUMOVehicleParameter::parsePersonModes(const std::string& modes, const std::string& element, const std::string& id, SVCPermissions& modeSet, std::string& error) {
705
// separte modes in different strings, and check if modes are valid
706
for (StringTokenizer st(modes); st.hasNext();) {
707
const std::string mode = st.next();
708
if (mode == "car") {
709
modeSet |= SVC_PASSENGER;
710
} else if (mode == "taxi") {
711
modeSet |= SVC_TAXI;
712
} else if (mode == "bicycle") {
713
modeSet |= SVC_BICYCLE;
714
} else if (mode == "public") {
715
modeSet |= SVC_BUS;
716
} else {
717
if (id.empty()) {
718
error = "Unknown person mode '" + mode + "'. Must be a combination of (\"car\", \"taxi\", \"bicycle\" or \"public\")";
719
} else {
720
error = "Unknown person mode '" + mode + "' for " + element + " '" + id + "';\n must be a combination of (\"car\", \"taxi\", \"bicycle\" or \"public\")";
721
}
722
return false;
723
}
724
}
725
return true;
726
}
727
728
729
void
730
SUMOVehicleParameter::parseStopTriggers(const std::vector<std::string>& triggers, bool expectTrigger, Stop& stop) {
731
if (triggers.size() == 0 && expectTrigger) {
732
stop.triggered = true;
733
}
734
for (std::string val : triggers) {
735
if (val == toString(SUMO_TAG_PERSON)) {
736
stop.triggered = true;
737
} else if (val == toString(SUMO_TAG_CONTAINER)) {
738
stop.containerTriggered = true;
739
} else if (val == toString(SUMO_ATTR_JOIN)) {
740
stop.joinTriggered = true;
741
} else {
742
try {
743
stop.triggered = StringUtils::toBool(val);
744
} catch (BoolFormatException&) {
745
WRITE_ERROR(TL("Value of stop attribute 'trigger' must be 'person', 'container', 'join' or a boolean"));
746
}
747
}
748
}
749
}
750
751
752
ParkingType
753
SUMOVehicleParameter::parseParkingType(const std::string& value) {
754
if (value == toString(ParkingType::OPPORTUNISTIC)) {
755
return ParkingType::OPPORTUNISTIC;
756
} else {
757
return StringUtils::toBool(value) ? ParkingType::OFFROAD : ParkingType::ONROAD;
758
}
759
}
760
761
762
std::vector<std::string>
763
SUMOVehicleParameter::Stop::getTriggers() const {
764
std::vector<std::string> triggers;
765
if (triggered) {
766
triggers.push_back(toString(SUMO_TAG_PERSON));
767
}
768
if (containerTriggered) {
769
triggers.push_back(toString(SUMO_TAG_CONTAINER));
770
}
771
if (joinTriggered) {
772
triggers.push_back(toString(SUMO_ATTR_JOIN));
773
}
774
return triggers;
775
}
776
777
int
778
SUMOVehicleParameter::Stop::getFlags() const {
779
return (((parking == ParkingType::OFFROAD) ? 1 : 0) +
780
(triggered ? 2 : 0) +
781
(containerTriggered ? 4 : 0) +
782
(busstop != "" ? 8 : 0) +
783
(containerstop != "" ? 16 : 0) +
784
(chargingStation != "" ? 32 : 0) +
785
(parkingarea != "" ? 64 : 0) +
786
(overheadWireSegment != "" ? 128 : 0));
787
}
788
789
790
std::string
791
SUMOVehicleParameter::getDepart() const {
792
if (departProcedure == DepartDefinition::TRIGGERED) {
793
return "triggered";
794
} else if (departProcedure == DepartDefinition::CONTAINER_TRIGGERED) {
795
return "containerTriggered";
796
// } else if (departProcedure == DepartDefinition::NOW) { // TODO check whether this is useful in XML input (currently TraCI only)
797
// return "now";
798
} else if (departProcedure == DepartDefinition::SPLIT) {
799
return "split";
800
} else if (departProcedure == DepartDefinition::BEGIN) {
801
return "begin";
802
} else {
803
return time2string(depart);
804
}
805
}
806
807
808
std::string
809
SUMOVehicleParameter::getDepartLane() const {
810
std::string val;
811
switch (departLaneProcedure) {
812
case DepartLaneDefinition::GIVEN:
813
val = toString(departLane);
814
break;
815
case DepartLaneDefinition::RANDOM:
816
val = "random";
817
break;
818
case DepartLaneDefinition::FREE:
819
val = "free";
820
break;
821
case DepartLaneDefinition::ALLOWED_FREE:
822
val = "allowed";
823
break;
824
case DepartLaneDefinition::BEST_FREE:
825
val = "best";
826
break;
827
case DepartLaneDefinition::BEST_PROB:
828
val = "best_prob";
829
break;
830
case DepartLaneDefinition::FIRST_ALLOWED:
831
val = "first";
832
break;
833
case DepartLaneDefinition::DEFAULT:
834
default:
835
break;
836
}
837
return val;
838
}
839
840
841
std::string
842
SUMOVehicleParameter::getDepartPos() const {
843
std::string val;
844
switch (departPosProcedure) {
845
case DepartPosDefinition::GIVEN:
846
val = toString(departPos);
847
break;
848
case DepartPosDefinition::GIVEN_VEHROUTE:
849
val = StringUtils::pruneZeros(toString(departPos, MAX2(gPrecisionRandom, gPrecision)), 2);
850
break;
851
case DepartPosDefinition::RANDOM:
852
val = "random";
853
break;
854
case DepartPosDefinition::RANDOM_FREE:
855
val = "random_free";
856
break;
857
case DepartPosDefinition::RANDOM_LOCATION:
858
val = "random_location";
859
break;
860
case DepartPosDefinition::FREE:
861
val = "free";
862
break;
863
case DepartPosDefinition::LAST:
864
val = "last";
865
break;
866
case DepartPosDefinition::BASE:
867
val = "base";
868
break;
869
case DepartPosDefinition::SPLIT_FRONT:
870
val = "splitFront";
871
break;
872
case DepartPosDefinition::STOP:
873
val = "stop";
874
break;
875
case DepartPosDefinition::DEFAULT:
876
default:
877
break;
878
}
879
return val;
880
}
881
882
883
std::string
884
SUMOVehicleParameter::getDepartPosLat() const {
885
std::string val;
886
switch (departPosLatProcedure) {
887
case DepartPosLatDefinition::GIVEN:
888
val = toString(departPosLat);
889
break;
890
case DepartPosLatDefinition::GIVEN_VEHROUTE:
891
val = StringUtils::pruneZeros(toString(departPosLat, MAX2(gPrecisionRandom, gPrecision)), 2);
892
break;
893
case DepartPosLatDefinition::RANDOM:
894
val = "random";
895
break;
896
case DepartPosLatDefinition::RANDOM_FREE:
897
val = "random_free";
898
break;
899
case DepartPosLatDefinition::FREE:
900
val = "free";
901
break;
902
case DepartPosLatDefinition::RIGHT:
903
val = "right";
904
break;
905
case DepartPosLatDefinition::CENTER:
906
val = "center";
907
break;
908
case DepartPosLatDefinition::LEFT:
909
val = "left";
910
break;
911
case DepartPosLatDefinition::DEFAULT:
912
default:
913
break;
914
}
915
return val;
916
}
917
918
919
std::string
920
SUMOVehicleParameter::getDepartSpeed() const {
921
std::string val;
922
switch (departSpeedProcedure) {
923
case DepartSpeedDefinition::GIVEN:
924
val = toString(departSpeed);
925
break;
926
case DepartSpeedDefinition::GIVEN_VEHROUTE:
927
val = StringUtils::pruneZeros(toString(departSpeed, MAX2(gPrecisionRandom, gPrecision)), 2);
928
break;
929
case DepartSpeedDefinition::RANDOM:
930
val = "random";
931
break;
932
case DepartSpeedDefinition::MAX:
933
val = "max";
934
break;
935
case DepartSpeedDefinition::DESIRED:
936
val = "desired";
937
break;
938
case DepartSpeedDefinition::LIMIT:
939
val = "speedLimit";
940
break;
941
case DepartSpeedDefinition::LAST:
942
val = "last";
943
break;
944
case DepartSpeedDefinition::AVG:
945
val = "avg";
946
break;
947
case DepartSpeedDefinition::DEFAULT:
948
default:
949
break;
950
}
951
return val;
952
}
953
954
955
std::string
956
SUMOVehicleParameter::getDepartEdge() const {
957
std::string val;
958
switch (departEdgeProcedure) {
959
case RouteIndexDefinition::GIVEN:
960
val = toString(departEdge);
961
break;
962
case RouteIndexDefinition::RANDOM:
963
val = "random";
964
break;
965
case RouteIndexDefinition::DEFAULT:
966
default:
967
break;
968
}
969
return val;
970
}
971
972
std::string
973
SUMOVehicleParameter::getArrivalEdge() const {
974
std::string val;
975
switch (arrivalEdgeProcedure) {
976
case RouteIndexDefinition::GIVEN:
977
val = toString(arrivalEdge);
978
break;
979
case RouteIndexDefinition::RANDOM:
980
val = "random";
981
break;
982
case RouteIndexDefinition::DEFAULT:
983
default:
984
break;
985
}
986
return val;
987
}
988
989
990
991
992
std::string
993
SUMOVehicleParameter::getArrivalLane() const {
994
std::string val;
995
switch (arrivalLaneProcedure) {
996
case ArrivalLaneDefinition::GIVEN:
997
val = toString(arrivalLane);
998
break;
999
case ArrivalLaneDefinition::CURRENT:
1000
val = "current";
1001
break;
1002
case ArrivalLaneDefinition::RANDOM:
1003
val = "random";
1004
break;
1005
case ArrivalLaneDefinition::FIRST_ALLOWED:
1006
val = "first";
1007
break;
1008
case ArrivalLaneDefinition::DEFAULT:
1009
default:
1010
break;
1011
}
1012
return val;
1013
}
1014
1015
1016
std::string
1017
SUMOVehicleParameter::getArrivalPos() const {
1018
std::string val;
1019
switch (arrivalPosProcedure) {
1020
case ArrivalPosDefinition::GIVEN:
1021
val = toString(arrivalPos);
1022
break;
1023
case ArrivalPosDefinition::RANDOM:
1024
val = "random";
1025
break;
1026
case ArrivalPosDefinition::CENTER:
1027
val = "center";
1028
break;
1029
case ArrivalPosDefinition::MAX:
1030
val = "max";
1031
break;
1032
case ArrivalPosDefinition::DEFAULT:
1033
default:
1034
break;
1035
}
1036
return val;
1037
}
1038
1039
1040
std::string
1041
SUMOVehicleParameter::getArrivalPosLat() const {
1042
std::string val;
1043
switch (arrivalPosLatProcedure) {
1044
case ArrivalPosLatDefinition::GIVEN:
1045
val = toString(arrivalPosLat);
1046
break;
1047
case ArrivalPosLatDefinition::RIGHT:
1048
val = "right";
1049
break;
1050
case ArrivalPosLatDefinition::CENTER:
1051
val = "center";
1052
break;
1053
case ArrivalPosLatDefinition::LEFT:
1054
val = "left";
1055
break;
1056
case ArrivalPosLatDefinition::DEFAULT:
1057
default:
1058
break;
1059
}
1060
return val;
1061
}
1062
1063
1064
std::string
1065
SUMOVehicleParameter::getArrivalSpeed() const {
1066
std::string val;
1067
switch (arrivalSpeedProcedure) {
1068
case ArrivalSpeedDefinition::GIVEN:
1069
val = toString(arrivalSpeed);
1070
break;
1071
case ArrivalSpeedDefinition::CURRENT:
1072
val = "current";
1073
break;
1074
case ArrivalSpeedDefinition::DEFAULT:
1075
default:
1076
break;
1077
}
1078
return val;
1079
}
1080
1081
1082
void
1083
SUMOVehicleParameter::incrementFlow(double scale, SumoRNG* rng) {
1084
repetitionsDone++;
1085
// equidistant or exponential offset (for poisson distributed arrivals)
1086
if (repetitionProbability < 0) {
1087
if (repetitionOffset >= 0) {
1088
repetitionTotalOffset += (SUMOTime)((double)repetitionOffset / scale);
1089
} else {
1090
assert(poissonRate > 0);
1091
// we need to cache this do avoid double generation of the rng in the TIME2STEPS macro
1092
const double r = RandHelper::randExp(poissonRate, rng);
1093
repetitionTotalOffset += TIME2STEPS(r / scale);
1094
}
1095
}
1096
}
1097
1098
1099
std::string
1100
SUMOVehicleParameter::getInsertionChecks() const {
1101
if ((insertionChecks == 0) || (insertionChecks == (int)InsertionCheck::ALL)) {
1102
return SUMOXMLDefinitions::InsertionChecks.getString(InsertionCheck::ALL);
1103
} else {
1104
std::vector<std::string> insertionChecksStrs;
1105
const auto insertionCheckValues = SUMOXMLDefinitions::InsertionChecks.getValues();
1106
// iterate over values
1107
for (const auto insertionCheckValue : insertionCheckValues) {
1108
if ((insertionCheckValue != InsertionCheck::ALL) && (insertionChecks & (int)insertionCheckValue) != 0) {
1109
insertionChecksStrs.push_back(SUMOXMLDefinitions::InsertionChecks.getString(insertionCheckValue));
1110
}
1111
}
1112
return toString(insertionChecksStrs);
1113
}
1114
}
1115
1116
1117
bool
1118
SUMOVehicleParameter::areInsertionChecksValid(const std::string& value) const {
1119
if (value.empty()) {
1120
return true;
1121
} else {
1122
// split value in substrinsg
1123
StringTokenizer valueStrs(value, " ");
1124
// iterate over values
1125
while (valueStrs.hasNext()) {
1126
if (!SUMOXMLDefinitions::InsertionChecks.hasString(valueStrs.next())) {
1127
return false;
1128
}
1129
}
1130
return true;
1131
}
1132
}
1133
1134
1135
int
1136
SUMOVehicleParameter::parseInsertionChecks(const std::string& value) {
1137
// first reset insertionChecks
1138
int result = 0;
1139
if (value.empty()) {
1140
return (int)InsertionCheck::ALL;
1141
} else {
1142
// split value in substrinsg
1143
StringTokenizer insertionCheckStrs(value, " ");
1144
while (insertionCheckStrs.hasNext()) {
1145
std::string val = insertionCheckStrs.next();
1146
if (SUMOXMLDefinitions::InsertionChecks.hasString(val)) {
1147
result |= (int)SUMOXMLDefinitions::InsertionChecks.get(val);
1148
} else {
1149
throw InvalidArgument("Unknown value '" + val + "' in " + toString(SUMO_ATTR_INSERTIONCHECKS) + ".");
1150
}
1151
}
1152
}
1153
return result;
1154
}
1155
1156
/****************************************************************************/
1157
1158