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