Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/common/SUMOVehicleClass.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 SUMOVehicleClass.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @author Walter Bamberger
19
/// @author Laura Bieker-Walz
20
/// @date 2006-01-24
21
///
22
// Definitions of SUMO vehicle classes and helper functions
23
/****************************************************************************/
24
#include <config.h>
25
26
#include <string>
27
#include <map>
28
#include "SUMOVehicleClass.h"
29
#include <utils/common/StringUtils.h>
30
#include <utils/common/ToString.h>
31
#include <utils/common/MsgHandler.h>
32
#include <utils/common/StringTokenizer.h>
33
#include <utils/iodevices/OutputDevice.h>
34
#include <utils/xml/SUMOSAXAttributes.h>
35
36
37
// ===========================================================================
38
// static members
39
// ===========================================================================
40
41
static StringBijection<SUMOVehicleClass>::Entry sumoVehicleClassStringInitializer[] = {
42
{"ignoring", SVC_IGNORING},
43
{"private", SVC_PRIVATE},
44
{"public_emergency", SVC_EMERGENCY}, // !!! deprecated
45
{"emergency", SVC_EMERGENCY},
46
{"public_authority", SVC_AUTHORITY}, // !!! deprecated
47
{"authority", SVC_AUTHORITY},
48
{"public_army", SVC_ARMY}, // !!! deprecated
49
{"army", SVC_ARMY},
50
{"vip", SVC_VIP},
51
{"passenger", SVC_PASSENGER},
52
{"hov", SVC_HOV},
53
{"taxi", SVC_TAXI},
54
{"public_transport", SVC_BUS}, // !!! deprecated
55
{"bus", SVC_BUS},
56
{"coach", SVC_COACH},
57
{"delivery", SVC_DELIVERY},
58
{"transport", SVC_TRUCK}, // !!! deprecated
59
{"truck", SVC_TRUCK},
60
{"trailer", SVC_TRAILER},
61
{"lightrail", SVC_TRAM}, // !!! deprecated
62
{"tram", SVC_TRAM},
63
{"cityrail", SVC_RAIL_URBAN}, // !!! deprecated
64
{"rail_urban", SVC_RAIL_URBAN},
65
{"rail_slow", SVC_RAIL}, // !!! deprecated
66
{"rail", SVC_RAIL},
67
{"rail_fast", SVC_RAIL_FAST},
68
{"rail_electric", SVC_RAIL_ELECTRIC},
69
{"motorcycle", SVC_MOTORCYCLE},
70
{"moped", SVC_MOPED},
71
{"bicycle", SVC_BICYCLE},
72
{"pedestrian", SVC_PEDESTRIAN},
73
{"evehicle", SVC_E_VEHICLE},
74
{"ship", SVC_SHIP},
75
{"container", SVC_CONTAINER},
76
{"cable_car", SVC_CABLE_CAR},
77
{"subway", SVC_SUBWAY},
78
{"aircraft", SVC_AIRCRAFT},
79
{"wheelchair", SVC_WHEELCHAIR},
80
{"scooter", SVC_SCOOTER},
81
{"drone", SVC_DRONE},
82
{"custom1", SVC_CUSTOM1},
83
{"custom2", SVC_CUSTOM2}
84
};
85
86
87
StringBijection<SUMOVehicleClass> SumoVehicleClassStrings(
88
sumoVehicleClassStringInitializer, SVC_CUSTOM2, false);
89
90
// count only non-deprecated classes
91
const int NUM_VCLASSES = SumoVehicleClassStrings.size() - 8;
92
93
std::set<std::string> deprecatedVehicleClassesSeen;
94
95
96
static StringBijection<SUMOVehicleShape>::Entry sumoVehicleShapeStringInitializer[] = {
97
{"pedestrian", SUMOVehicleShape::PEDESTRIAN},
98
{"bicycle", SUMOVehicleShape::BICYCLE},
99
{"moped", SUMOVehicleShape::MOPED},
100
{"motorcycle", SUMOVehicleShape::MOTORCYCLE},
101
{"passenger", SUMOVehicleShape::PASSENGER},
102
{"passenger/sedan", SUMOVehicleShape::PASSENGER_SEDAN},
103
{"passenger/hatchback", SUMOVehicleShape::PASSENGER_HATCHBACK},
104
{"passenger/wagon", SUMOVehicleShape::PASSENGER_WAGON},
105
{"passenger/van", SUMOVehicleShape::PASSENGER_VAN},
106
{"taxi", SUMOVehicleShape::TAXI},
107
{"delivery", SUMOVehicleShape::DELIVERY},
108
{"transport", SUMOVehicleShape::TRUCK}, // !!! deprecated
109
{"truck", SUMOVehicleShape::TRUCK},
110
{"transport/semitrailer", SUMOVehicleShape::TRUCK_SEMITRAILER}, // !!! deprecated
111
{"truck/semitrailer", SUMOVehicleShape::TRUCK_SEMITRAILER},
112
{"transport/trailer", SUMOVehicleShape::TRUCK_1TRAILER}, // !!! deprecated
113
{"truck/trailer", SUMOVehicleShape::TRUCK_1TRAILER},
114
{"bus/city", SUMOVehicleShape::BUS}, // !!! deprecated
115
{"bus", SUMOVehicleShape::BUS},
116
{"bus/overland", SUMOVehicleShape::BUS_COACH}, // !!! deprecated
117
{"bus/coach", SUMOVehicleShape::BUS_COACH},
118
{"bus/flexible", SUMOVehicleShape::BUS_FLEXIBLE},
119
{"bus/trolley", SUMOVehicleShape::BUS_TROLLEY},
120
{"rail/slow", SUMOVehicleShape::RAIL}, // !!! deprecated
121
{"rail/fast", SUMOVehicleShape::RAIL}, // !!! deprecated
122
{"rail", SUMOVehicleShape::RAIL},
123
{"rail/light", SUMOVehicleShape::RAIL_CAR}, // !!! deprecated
124
{"rail/city", SUMOVehicleShape::RAIL_CAR}, // !!! deprecated
125
{"rail/railcar", SUMOVehicleShape::RAIL_CAR},
126
{"rail/cargo", SUMOVehicleShape::RAIL_CARGO},
127
{"evehicle", SUMOVehicleShape::E_VEHICLE},
128
{"ant", SUMOVehicleShape::ANT},
129
{"ship", SUMOVehicleShape::SHIP},
130
{"emergency", SUMOVehicleShape::EMERGENCY},
131
{"firebrigade", SUMOVehicleShape::FIREBRIGADE},
132
{"police", SUMOVehicleShape::POLICE},
133
{"rickshaw", SUMOVehicleShape::RICKSHAW },
134
{"scooter", SUMOVehicleShape::SCOOTER},
135
{"aircraft", SUMOVehicleShape::AIRCRAFT},
136
{"", SUMOVehicleShape::UNKNOWN}
137
};
138
139
140
StringBijection<SUMOVehicleShape> SumoVehicleShapeStrings(
141
sumoVehicleShapeStringInitializer, SUMOVehicleShape::UNKNOWN, false);
142
143
// ===========================================================================
144
// static values used for cached
145
// ===========================================================================
146
147
static std::map<SVCPermissions, std::vector<std::string> > vehicleClassNamesListCached;
148
static std::map<std::string, SVCPermissions> parseVehicleClassesCached;
149
static std::map<SVCPermissions, std::string> getVehicleClassNamesCached;
150
static std::string VehicleClassNameAll = "all";
151
152
// ===========================================================================
153
// additional constants
154
// ===========================================================================
155
156
const SUMOVehicleClass SUMOVehicleClass_MAX = SVC_CUSTOM2;
157
158
const SVCPermissions SVCAll = 2 * (long long int)SUMOVehicleClass_MAX - 1; // all relevant bits set to 1
159
160
const SVCPermissions SVC_UNSPECIFIED = -1;
161
162
const SUMOEmissionClass EMISSION_CLASS_UNSPECIFIED = -1;
163
164
const std::string DEFAULT_VTYPE_ID("DEFAULT_VEHTYPE");
165
const std::string DEFAULT_PEDTYPE_ID("DEFAULT_PEDTYPE");
166
const std::string DEFAULT_BIKETYPE_ID("DEFAULT_BIKETYPE");
167
const std::string DEFAULT_CONTAINERTYPE_ID("DEFAULT_CONTAINERTYPE");
168
const std::string DEFAULT_TAXITYPE_ID("DEFAULT_TAXITYPE");
169
const std::string DEFAULT_RAILTYPE_ID("DEFAULT_RAILTYPE");
170
171
const std::set<std::string> DEFAULT_VTYPES({DEFAULT_VTYPE_ID, DEFAULT_PEDTYPE_ID, DEFAULT_BIKETYPE_ID, DEFAULT_CONTAINERTYPE_ID, DEFAULT_TAXITYPE_ID, DEFAULT_RAILTYPE_ID});
172
173
const double DEFAULT_VEH_PROB(1.);
174
const double DEFAULT_VEH_MASS(1500.);
175
const double DEFAULT_VEH_WIDTH(1.8);
176
const double DEFAULT_VEH_HEIGHT(1.5);
177
const double DEFAULT_VEH_SHUT_OFF_STOP(300.);
178
179
const double DEFAULT_PEDESTRIAN_SPEED(5. / 3.6);
180
181
const double DEFAULT_BICYCLE_SPEED(20. / 3.6);
182
183
const double DEFAULT_CONTAINER_TRANSHIP_SPEED(5. / 3.6);
184
185
186
// ===========================================================================
187
// method definitions
188
// ===========================================================================
189
190
// Stop Offset
191
192
StopOffset::StopOffset() :
193
myPermissions(SVCAll),
194
myOffset(0) {
195
}
196
197
198
StopOffset::StopOffset(const SUMOSAXAttributes& attrs, bool& ok) :
199
myPermissions(SVC_IGNORING),
200
myOffset(0) {
201
// first check conditions
202
if (attrs.hasAttribute(SUMO_ATTR_VCLASSES) && attrs.hasAttribute(SUMO_ATTR_EXCEPTIONS)) {
203
WRITE_ERROR(TL("Simultaneous specification of vClasses and exceptions is not allowed"));
204
ok = false;
205
}
206
if (!attrs.hasAttribute(SUMO_ATTR_VALUE)) {
207
WRITE_ERROR(TL("StopOffset requires an offset value"));
208
ok = false;
209
}
210
// parse elements
211
const std::string vClasses = attrs.getOpt<std::string>(SUMO_ATTR_VCLASSES, nullptr, ok, "");
212
const std::string exceptions = attrs.getOpt<std::string>(SUMO_ATTR_EXCEPTIONS, nullptr, ok, "");
213
// parse permissions
214
if (attrs.hasAttribute(SUMO_ATTR_VCLASSES)) {
215
myPermissions = parseVehicleClasses(vClasses);
216
} else if (attrs.hasAttribute(SUMO_ATTR_EXCEPTIONS)) {
217
myPermissions = ~parseVehicleClasses(exceptions);
218
} else {
219
// no vClasses specified, thus apply to all
220
myPermissions = parseVehicleClasses("all");
221
}
222
// parse offset
223
myOffset = attrs.getOpt<double>(SUMO_ATTR_VALUE, nullptr, ok, 0);
224
}
225
226
227
bool
228
StopOffset::isDefined() const {
229
return myOffset != 0;
230
}
231
232
233
void
234
StopOffset::reset() {
235
myPermissions = SVC_IGNORING;
236
myOffset = 0;
237
}
238
239
240
SVCPermissions
241
StopOffset::getPermissions() const {
242
return myPermissions;
243
}
244
245
246
std::string
247
StopOffset::getExceptions() const {
248
return getVehicleClassNames(~myPermissions);
249
}
250
251
252
double
253
StopOffset::getOffset() const {
254
return myOffset;
255
}
256
257
258
void
259
StopOffset::setPermissions(const SVCPermissions permissions) {
260
myPermissions = permissions;
261
}
262
263
264
void
265
StopOffset::setExceptions(const std::string permissions) {
266
myPermissions = ~parseVehicleClasses(permissions);
267
}
268
269
270
void
271
StopOffset::setOffset(const double offset) {
272
myOffset = offset;
273
}
274
275
276
bool
277
StopOffset::operator==(StopOffset const& other) const {
278
return ((myPermissions == other.myPermissions) &&
279
(myOffset == other.myOffset));
280
}
281
282
283
bool
284
StopOffset::operator!=(StopOffset const& other) const {
285
return ((myPermissions != other.myPermissions) ||
286
(myOffset != other.myOffset));
287
}
288
289
// Conversion of SUMOVehicleClass
290
291
const std::string&
292
getVehicleClassNames(SVCPermissions permissions, bool expand) {
293
if ((permissions & SVCAll) == SVCAll && !expand) {
294
return VehicleClassNameAll;
295
}
296
// check if previously was cached
297
if (getVehicleClassNamesCached.count(permissions) == 0) {
298
getVehicleClassNamesCached[permissions] = joinToString(getVehicleClassNamesList(permissions), ' ');
299
}
300
return getVehicleClassNamesCached.at(permissions);
301
}
302
303
304
const std::vector<std::string>&
305
getVehicleClassNamesList(SVCPermissions permissions) {
306
// first check if it's cached
307
if (vehicleClassNamesListCached.count(permissions) == 0) {
308
const std::vector<std::string> classNames = SumoVehicleClassStrings.getStrings();
309
std::vector<std::string> result;
310
for (std::vector<std::string>::const_iterator it = classNames.begin(); it != classNames.end(); it++) {
311
const SVCPermissions svc = (SVCPermissions)SumoVehicleClassStrings.get(*it);
312
if ((svc & permissions) == svc && svc != SVC_IGNORING) {
313
result.push_back(*it);
314
}
315
}
316
// add it into vehicleClassNamesListCached
317
vehicleClassNamesListCached[permissions] = result;
318
}
319
return vehicleClassNamesListCached.at(permissions);
320
}
321
322
323
SUMOVehicleClass
324
getVehicleClassID(const std::string& name) {
325
if (SumoVehicleClassStrings.hasString(name)) {
326
return SumoVehicleClassStrings.get(name);
327
}
328
throw InvalidArgument("Unknown vehicle class '" + name + "'.");
329
}
330
331
332
SVCPermissions
333
getVehicleClassCompoundID(const std::string& name) {
334
SVCPermissions ret = SVC_IGNORING;
335
const std::vector<std::string> names = SumoVehicleClassStrings.getStrings();
336
for (std::vector<std::string>::const_iterator it = names.begin(); it != names.end(); it++) {
337
if (name.find(*it) != std::string::npos) {
338
ret = ret | (SVCPermissions) SumoVehicleClassStrings.get(*it);
339
}
340
}
341
return ret;
342
}
343
344
345
SVCPermissions
346
parseVehicleClasses(const std::string& allowedS) {
347
if (allowedS == VehicleClassNameAll) {
348
return SVCAll;
349
}
350
// check if allowedS was previously cached
351
if (parseVehicleClassesCached.count(allowedS) == 0) {
352
SVCPermissions result = 0;
353
StringTokenizer sta(allowedS, " ");
354
while (sta.hasNext()) {
355
const std::string s = sta.next();
356
if (!SumoVehicleClassStrings.hasString(s)) {
357
if (gIgnoreUnknownVClass) {
358
WRITE_WARNINGF(TL("Unknown vehicle class '%' ignored."), s);
359
} else {
360
WRITE_ERRORF(TL("Unknown vehicle class '%' encountered."), s);
361
}
362
} else {
363
const SUMOVehicleClass vc = getVehicleClassID(s);
364
const std::string& realName = SumoVehicleClassStrings.getString(vc);
365
if (realName != s) {
366
deprecatedVehicleClassesSeen.insert(s);
367
}
368
result |= vc;
369
}
370
}
371
// save parsed vehicle class cached
372
parseVehicleClassesCached[allowedS] = result;
373
}
374
return parseVehicleClassesCached.at(allowedS);
375
}
376
377
378
bool
379
canParseVehicleClasses(const std::string& classes) {
380
if (classes == VehicleClassNameAll) {
381
return true;
382
}
383
// check if was previously cached
384
if (parseVehicleClassesCached.count(classes) != 0) {
385
return true;
386
}
387
StringTokenizer sta(classes, " ");
388
while (sta.hasNext()) {
389
if (!SumoVehicleClassStrings.hasString(sta.next())) {
390
return false;
391
}
392
}
393
return true;
394
}
395
396
397
SVCPermissions
398
parseVehicleClasses(const std::string& allowedS, const std::string& disallowedS, const MMVersion& networkVersion) {
399
if (allowedS.size() == 0 && disallowedS.size() == 0) {
400
return SVCAll;
401
} else if (allowedS.size() > 0 && disallowedS.size() > 0) {
402
WRITE_WARNING(TL("SVCPermissions must be specified either via 'allow' or 'disallow'. Ignoring 'disallow'"));
403
return parseVehicleClasses(allowedS);
404
} else if (allowedS.size() > 0) {
405
return parseVehicleClasses(allowedS);
406
} else {
407
return invertPermissions(extraDisallowed(parseVehicleClasses(disallowedS), networkVersion));
408
}
409
}
410
411
SVCPermissions
412
extraDisallowed(SVCPermissions disallowed, const MMVersion& networkVersion) {
413
if (networkVersion < MMVersion(1, 3)) {
414
disallowed |= SVC_RAIL_FAST;
415
}
416
if (networkVersion < MMVersion(1, 20)) {
417
if ((disallowed & SVC_RAIL_URBAN) != 0) {
418
disallowed |= SVC_SUBWAY;
419
disallowed |= SVC_CABLE_CAR;
420
}
421
}
422
return disallowed;
423
}
424
425
426
SVCPermissions
427
invertPermissions(SVCPermissions permissions) {
428
return SVCAll & ~permissions;
429
}
430
431
432
SVCPermissions
433
parseVehicleClasses(const std::vector<std::string>& allowedS) {
434
SVCPermissions result = 0;
435
if (std::find(allowedS.begin(), allowedS.end(), VehicleClassNameAll) != allowedS.end()) {
436
return SVCAll;
437
}
438
for (std::vector<std::string>::const_iterator i = allowedS.begin(); i != allowedS.end(); ++i) {
439
const SUMOVehicleClass vc = getVehicleClassID(*i);
440
const std::string& realName = SumoVehicleClassStrings.getString(vc);
441
if (realName != *i) {
442
WRITE_WARNINGF(TL("The vehicle class '%' is deprecated, use '%' instead."), (*i), realName);
443
}
444
result |= getVehicleClassID(*i);
445
}
446
return result;
447
}
448
449
450
void
451
writePermissions(OutputDevice& into, SVCPermissions permissions) {
452
if (permissions == SVCAll) {
453
return;
454
} else if (permissions == 0) {
455
into.writeAttr(SUMO_ATTR_DISALLOW, VehicleClassNameAll);
456
return;
457
} else {
458
int num_allowed = 0;
459
for (SVCPermissions mask = 1; mask <= SUMOVehicleClass_MAX; mask = mask << 1) {
460
if ((mask & permissions) == mask) {
461
++num_allowed;
462
}
463
}
464
if (num_allowed <= (NUM_VCLASSES - num_allowed) && num_allowed > 0) {
465
into.writeAttr(SUMO_ATTR_ALLOW, getVehicleClassNames(permissions));
466
} else {
467
into.writeAttr(SUMO_ATTR_DISALLOW, getVehicleClassNames(~permissions));
468
}
469
}
470
}
471
472
473
void
474
writePreferences(OutputDevice& into, SVCPermissions preferred) {
475
if (preferred == SVCAll || preferred == 0) {
476
return;
477
} else {
478
into.writeAttr(SUMO_ATTR_PREFER, getVehicleClassNames(preferred));
479
}
480
}
481
482
483
SUMOVehicleShape
484
getVehicleShapeID(const std::string& name) {
485
if (SumoVehicleShapeStrings.hasString(name)) {
486
return SumoVehicleShapeStrings.get(name);
487
} else {
488
throw InvalidArgument("Unknown vehicle shape '" + name + "'.");
489
}
490
}
491
492
493
bool
494
canParseVehicleShape(const std::string& shape) {
495
return SumoVehicleShapeStrings.hasString(shape);
496
}
497
498
499
std::string
500
getVehicleShapeName(SUMOVehicleShape id) {
501
return SumoVehicleShapeStrings.getString(id);
502
}
503
504
505
bool isRailway(SVCPermissions permissions) {
506
return (permissions & SVC_RAIL_CLASSES) != 0 && (permissions & ~(SVC_RAIL_CLASSES | SVC_TAXI)) == 0;
507
}
508
509
bool isRailwayOrShared(SVCPermissions permissions) {
510
// basically check that it isn't SVC_ALL
511
return (permissions & SVC_RAIL_CLASSES) != 0 && (permissions & SVC_NON_ROAD_RAIL) == 0;
512
}
513
514
bool isTram(SVCPermissions permissions) {
515
return (permissions & SVC_RAIL_CLASSES) == SVC_TRAM && (permissions & SVC_PASSENGER) == 0;
516
}
517
518
bool isBikepath(SVCPermissions permissions) {
519
return (permissions & SVC_BICYCLE) == SVC_BICYCLE && (permissions & SVC_ROAD_MOTOR_CLASSES) == 0;
520
}
521
522
523
bool
524
isWaterway(SVCPermissions permissions) {
525
return permissions == SVC_SHIP;
526
}
527
528
bool
529
isAirway(SVCPermissions permissions) {
530
return permissions == SVC_AIRCRAFT || permissions == SVC_DRONE;
531
}
532
533
bool
534
isForbidden(SVCPermissions permissions) {
535
return (permissions & SVCAll) == 0;
536
}
537
538
539
bool
540
isSidewalk(SVCPermissions permissions) {
541
return (permissions & SVCAll) == SVC_PEDESTRIAN;
542
}
543
544
545
bool
546
isForVulnerableModes(SVCPermissions permissions) {
547
return ((permissions & SVC_VULNERABLE) != 0 && (permissions & ~SVC_VULNERABLE) == 0);
548
}
549
550
551
bool
552
noVehicles(SVCPermissions permissions) {
553
return isForbidden(permissions) || isSidewalk(permissions);
554
}
555
556
557
double
558
getDefaultVehicleLength(const SUMOVehicleClass vc) {
559
switch (vc) {
560
case SVC_PEDESTRIAN:
561
return 0.215;
562
case SVC_WHEELCHAIR:
563
return 0.5;
564
case SVC_BICYCLE:
565
return 1.6;
566
case SVC_SCOOTER:
567
return 1.2;
568
case SVC_MOPED:
569
return 2.1;
570
case SVC_MOTORCYCLE:
571
return 2.2;
572
case SVC_TRUCK:
573
return 7.1;
574
case SVC_TRAILER:
575
return 16.5;
576
case SVC_BUS:
577
return 12.;
578
case SVC_COACH:
579
return 14.;
580
case SVC_TRAM:
581
return 22.;
582
case SVC_RAIL_URBAN:
583
case SVC_SUBWAY:
584
return 36.5 * 3;
585
case SVC_RAIL:
586
return 67.5 * 2;
587
case SVC_RAIL_ELECTRIC:
588
case SVC_RAIL_FAST:
589
return 25. * 8;
590
case SVC_DELIVERY:
591
case SVC_EMERGENCY:
592
return 6.5;
593
case SVC_SHIP:
594
return 17;
595
case SVC_CONTAINER:
596
return 6.096;
597
case SVC_DRONE:
598
return 0.5;
599
case SVC_AIRCRAFT:
600
return 72.7;
601
default:
602
return 5; /*4.3*/
603
}
604
}
605
606
607
608
/****************************************************************************/
609
610