1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file SUMOVehicleClass.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @author Walter Bamberger
15 /// @author Laura Bieker-Walz
16 /// @date 2006-01-24
17 /// @version $Id$
18 ///
19 // Definitions of SUMO vehicle classes and helper functions
20 /****************************************************************************/
21
22
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27
28 #include <string>
29 #include <map>
30 #include "SUMOVehicleClass.h"
31 #include <utils/common/StringUtils.h>
32 #include <utils/common/ToString.h>
33 #include <utils/common/MsgHandler.h>
34 #include <utils/common/StringTokenizer.h>
35 #include <utils/iodevices/OutputDevice.h>
36 #include <utils/xml/SUMOSAXAttributes.h>
37
38
39 // ===========================================================================
40 // static members
41 // ===========================================================================
42
43 StringBijection<SUMOVehicleClass>::Entry sumoVehicleClassStringInitializer[] = {
44 {"ignoring", SVC_IGNORING},
45 {"private", SVC_PRIVATE},
46 {"public_emergency", SVC_EMERGENCY}, // !!! deprecated
47 {"emergency", SVC_EMERGENCY},
48 {"public_authority", SVC_AUTHORITY}, // !!! deprecated
49 {"authority", SVC_AUTHORITY},
50 {"public_army", SVC_ARMY}, // !!! deprecated
51 {"army", SVC_ARMY},
52 {"vip", SVC_VIP},
53 {"passenger", SVC_PASSENGER},
54 {"hov", SVC_HOV},
55 {"taxi", SVC_TAXI},
56 {"public_transport", SVC_BUS}, // !!! deprecated
57 {"bus", SVC_BUS},
58 {"coach", SVC_COACH},
59 {"delivery", SVC_DELIVERY},
60 {"transport", SVC_TRUCK},
61 {"truck", SVC_TRUCK},
62 {"trailer", SVC_TRAILER},
63 {"lightrail", SVC_TRAM}, // !!! deprecated
64 {"tram", SVC_TRAM},
65 {"cityrail", SVC_RAIL_URBAN}, // !!! deprecated
66 {"rail_urban", SVC_RAIL_URBAN},
67 {"rail_slow", SVC_RAIL}, // !!! deprecated
68 {"rail", SVC_RAIL},
69 {"rail_fast", SVC_RAIL_ELECTRIC}, // !!! deprecated
70 {"rail_electric", SVC_RAIL_ELECTRIC},
71 {"motorcycle", SVC_MOTORCYCLE},
72 {"moped", SVC_MOPED},
73 {"bicycle", SVC_BICYCLE},
74 {"pedestrian", SVC_PEDESTRIAN},
75 {"evehicle", SVC_E_VEHICLE},
76 //{"automated", SVC_AUTOMATED},
77 {"ship", SVC_SHIP},
78 {"custom1", SVC_CUSTOM1},
79 {"custom2", SVC_CUSTOM2}
80 };
81
82 StringBijection<SUMOVehicleClass> SumoVehicleClassStrings(
83 sumoVehicleClassStringInitializer, SVC_CUSTOM2, false);
84
85
86 std::set<std::string> deprecatedVehicleClassesSeen;
87
88
89 StringBijection<SUMOVehicleShape>::Entry sumoVehicleShapeStringInitializer[] = {
90 {"pedestrian", SVS_PEDESTRIAN},
91 {"bicycle", SVS_BICYCLE},
92 {"moped", SVS_MOPED},
93 {"motorcycle", SVS_MOTORCYCLE},
94 {"passenger", SVS_PASSENGER},
95 {"passenger/sedan", SVS_PASSENGER_SEDAN},
96 {"passenger/hatchback", SVS_PASSENGER_HATCHBACK},
97 {"passenger/wagon", SVS_PASSENGER_WAGON},
98 {"passenger/van", SVS_PASSENGER_VAN},
99 {"delivery", SVS_DELIVERY},
100 {"transport", SVS_TRUCK}, // !!! deprecated
101 {"truck", SVS_TRUCK},
102 {"transport/semitrailer", SVS_TRUCK_SEMITRAILER}, // !!! deprecated
103 {"truck/semitrailer", SVS_TRUCK_SEMITRAILER},
104 {"transport/trailer", SVS_TRUCK_1TRAILER}, // !!! deprecated
105 {"truck/trailer", SVS_TRUCK_1TRAILER},
106 {"bus/city", SVS_BUS}, // !!! deprecated
107 {"bus", SVS_BUS},
108 {"bus/overland", SVS_BUS_COACH}, // !!! deprecated
109 {"bus/coach", SVS_BUS_COACH},
110 {"bus/flexible", SVS_BUS_FLEXIBLE},
111 {"bus/trolley", SVS_BUS_TROLLEY},
112 {"rail/slow", SVS_RAIL}, // !!! deprecated
113 {"rail/fast", SVS_RAIL}, // !!! deprecated
114 {"rail", SVS_RAIL},
115 {"rail/light", SVS_RAIL_CAR}, // !!! deprecated
116 {"rail/city", SVS_RAIL_CAR}, // !!! deprecated
117 {"rail/railcar", SVS_RAIL_CAR},
118 {"rail/cargo", SVS_RAIL_CARGO},
119 {"evehicle", SVS_E_VEHICLE},
120 {"ant", SVS_ANT},
121 {"ship", SVS_SHIP},
122 {"emergency", SVS_EMERGENCY},
123 {"firebrigade", SVS_FIREBRIGADE},
124 {"police", SVS_POLICE},
125 {"rickshaw", SVS_RICKSHAW },
126 {"", SVS_UNKNOWN}
127 };
128
129
130 StringBijection<SUMOVehicleShape> SumoVehicleShapeStrings(
131 sumoVehicleShapeStringInitializer, SVS_UNKNOWN, false);
132
133 // ===========================================================================
134 // static values used for cached
135 // ===========================================================================
136
137 static std::map<int, std::vector<std::string> > vehicleClassNamesListCached;
138 static std::map<std::string, SVCPermissions> parseVehicleClassesCached;
139 static std::map<SVCPermissions, std::string> getVehicleClassNamesCached;
140 static std::string vehicleClassNameAll = "all";
141
142 // ===========================================================================
143 // additional constants
144 // ===========================================================================
145
146 const int SUMOVehicleClass_MAX = SVC_CUSTOM2;
147
148 const SVCPermissions SVCAll = 2 * SUMOVehicleClass_MAX - 1; // all relevant bits set to 1
149
150 const SVCPermissions SVC_UNSPECIFIED = -1;
151
152 const std::string DEFAULT_VTYPE_ID("DEFAULT_VEHTYPE");
153
154 const std::string DEFAULT_PEDTYPE_ID("DEFAULT_PEDTYPE");
155
156 const std::string DEFAULT_BIKETYPE_ID("DEFAULT_BIKETYPE");
157
158 const double DEFAULT_VEH_PROB(1.);
159
160 const double DEFAULT_PEDESTRIAN_SPEED(5. / 3.6);
161
162 const double DEFAULT_CONTAINER_TRANSHIP_SPEED(5. / 3.6);
163
164 // ===========================================================================
165 // method definitions
166 // ===========================================================================
167 // ------------ Conversion of SUMOVehicleClass
168
169 const std::string&
getVehicleClassNames(SVCPermissions permissions,bool expand)170 getVehicleClassNames(SVCPermissions permissions, bool expand) {
171 if (permissions == SVCAll && !expand) {
172 return vehicleClassNameAll;
173 }
174 // check if previously was cached
175 if (getVehicleClassNamesCached.count(permissions) == 0) {
176 getVehicleClassNamesCached[permissions] = joinToString(getVehicleClassNamesList(permissions), ' ');
177 }
178 return getVehicleClassNamesCached.at(permissions);
179 }
180
181
182 const std::vector<std::string>&
getVehicleClassNamesList(SVCPermissions permissions)183 getVehicleClassNamesList(SVCPermissions permissions) {
184 // first check if it's cached
185 if (vehicleClassNamesListCached.count(permissions) == 0) {
186 const std::vector<std::string> classNames = SumoVehicleClassStrings.getStrings();
187 std::vector<std::string> result;
188 for (std::vector<std::string>::const_iterator it = classNames.begin(); it != classNames.end(); it++) {
189 const int svc = (int)SumoVehicleClassStrings.get(*it);
190 if ((svc & permissions) == svc && svc != SVC_IGNORING) {
191 result.push_back(*it);
192 }
193 }
194 // add it into vehicleClassNamesListCached
195 vehicleClassNamesListCached[permissions] = result;
196 }
197 return vehicleClassNamesListCached.at(permissions);
198 }
199
200
201 SUMOVehicleClass
getVehicleClassID(const std::string & name)202 getVehicleClassID(const std::string& name) {
203 if (SumoVehicleClassStrings.hasString(name)) {
204 return SumoVehicleClassStrings.get(name);
205 }
206 throw InvalidArgument("Unknown vehicle class '" + name + "'.");
207 }
208
209
210 int
getVehicleClassCompoundID(const std::string & name)211 getVehicleClassCompoundID(const std::string& name) {
212 int ret = SVC_IGNORING;
213 const std::vector<std::string> names = SumoVehicleClassStrings.getStrings();
214 for (std::vector<std::string>::const_iterator it = names.begin(); it != names.end(); it++) {
215 if (name.find(*it) != std::string::npos) {
216 ret = ret | (int) SumoVehicleClassStrings.get(*it);
217 }
218 }
219 return ret;
220 }
221
222
223 SVCPermissions
parseVehicleClasses(const std::string & allowedS)224 parseVehicleClasses(const std::string& allowedS) {
225 if (allowedS == "all") {
226 return SVCAll;
227 }
228 // check if allowedS was previously cached
229 if (parseVehicleClassesCached.count(allowedS) == 0) {
230 SVCPermissions result = 0;
231 StringTokenizer sta(allowedS, " ");
232 while (sta.hasNext()) {
233 const std::string s = sta.next();
234 if (!SumoVehicleClassStrings.hasString(s)) {
235 WRITE_ERROR("Unknown vehicle class '" + s + "' encountered.");
236 } else {
237 const SUMOVehicleClass vc = getVehicleClassID(s);
238 const std::string& realName = SumoVehicleClassStrings.getString(vc);
239 if (realName != s) {
240 deprecatedVehicleClassesSeen.insert(s);
241 }
242 result |= vc;
243 }
244 }
245 // save parsed vehicle class cached
246 parseVehicleClassesCached[allowedS] = result;
247 }
248 return parseVehicleClassesCached.at(allowedS);
249 }
250
251
252 bool
canParseVehicleClasses(const std::string & classes)253 canParseVehicleClasses(const std::string& classes) {
254 if (classes == "all") {
255 return true;
256 }
257 // check if was previously cached
258 if (parseVehicleClassesCached.count(classes) != 0) {
259 return true;
260 }
261 StringTokenizer sta(classes, " ");
262 while (sta.hasNext()) {
263 if (!SumoVehicleClassStrings.hasString(sta.next())) {
264 return false;
265 }
266 }
267 return true;
268 }
269
270
271 SVCPermissions
parseVehicleClasses(const std::string & allowedS,const std::string & disallowedS)272 parseVehicleClasses(const std::string& allowedS, const std::string& disallowedS) {
273 if (allowedS.size() == 0 && disallowedS.size() == 0) {
274 return SVCAll;
275 } else if (allowedS.size() > 0 && disallowedS.size() > 0) {
276 WRITE_WARNING("SVCPermissions must be specified either via 'allow' or 'disallow'. Ignoring 'disallow'");
277 return parseVehicleClasses(allowedS);
278 } else if (allowedS.size() > 0) {
279 return parseVehicleClasses(allowedS);
280 } else {
281 return invertPermissions(parseVehicleClasses(disallowedS));
282 }
283 }
284
285
286 SVCPermissions
invertPermissions(SVCPermissions permissions)287 invertPermissions(SVCPermissions permissions) {
288 return SVCAll & ~permissions;
289 }
290
291
292 SVCPermissions
parseVehicleClasses(const std::vector<std::string> & allowedS)293 parseVehicleClasses(const std::vector<std::string>& allowedS) {
294 SVCPermissions result = 0;
295 if (std::find(allowedS.begin(), allowedS.end(), "all") != allowedS.end()) {
296 return SVCAll;
297 }
298 for (std::vector<std::string>::const_iterator i = allowedS.begin(); i != allowedS.end(); ++i) {
299 const SUMOVehicleClass vc = getVehicleClassID(*i);
300 const std::string& realName = SumoVehicleClassStrings.getString(vc);
301 if (realName != *i) {
302 WRITE_WARNING("The vehicle class '" + (*i) + "' is deprecated, use '" + realName + "' instead.");
303 }
304 result |= getVehicleClassID(*i);
305 }
306 return result;
307 }
308
309
310 void
writePermissions(OutputDevice & into,SVCPermissions permissions)311 writePermissions(OutputDevice& into, SVCPermissions permissions) {
312 if (permissions == SVCAll) {
313 return;
314 } else if (permissions == 0) {
315 into.writeAttr(SUMO_ATTR_DISALLOW, "all");
316 return;
317 } else {
318 int num_allowed = 0;
319 for (int mask = 1; mask <= SUMOVehicleClass_MAX; mask = mask << 1) {
320 if ((mask & permissions) == mask) {
321 ++num_allowed;
322 }
323 }
324 if (num_allowed <= (SumoVehicleClassStrings.size() - num_allowed) && num_allowed > 0) {
325 into.writeAttr(SUMO_ATTR_ALLOW, getVehicleClassNames(permissions));
326 } else {
327 into.writeAttr(SUMO_ATTR_DISALLOW, getVehicleClassNames(~permissions));
328 }
329 }
330 }
331
332
333 void
writePreferences(OutputDevice & into,SVCPermissions preferred)334 writePreferences(OutputDevice& into, SVCPermissions preferred) {
335 if (preferred == SVCAll || preferred == 0) {
336 return;
337 } else {
338 into.writeAttr(SUMO_ATTR_PREFER, getVehicleClassNames(preferred));
339 }
340 }
341
342
343 SUMOVehicleShape
getVehicleShapeID(const std::string & name)344 getVehicleShapeID(const std::string& name) {
345 if (SumoVehicleShapeStrings.hasString(name)) {
346 return SumoVehicleShapeStrings.get(name);
347 } else {
348 throw InvalidArgument("Unknown vehicle shape '" + name + "'.");
349 }
350 }
351
352
353 bool
canParseVehicleShape(const std::string & shape)354 canParseVehicleShape(const std::string& shape) {
355 return SumoVehicleShapeStrings.hasString(shape);
356 }
357
358
359 std::string
getVehicleShapeName(SUMOVehicleShape id)360 getVehicleShapeName(SUMOVehicleShape id) {
361 return SumoVehicleShapeStrings.getString(id);
362 }
363
364
isRailway(SVCPermissions permissions)365 bool isRailway(SVCPermissions permissions) {
366 return (permissions & SVC_RAIL_CLASSES) > 0 && (permissions & SVC_PASSENGER) == 0;
367 }
368
369
370 bool
isWaterway(SVCPermissions permissions)371 isWaterway(SVCPermissions permissions) {
372 return permissions == SVC_SHIP;
373 }
374
375
376 bool
isForbidden(SVCPermissions permissions)377 isForbidden(SVCPermissions permissions) {
378 return (permissions & SVCAll) == 0;
379 }
380
381
382 bool
isSidewalk(SVCPermissions permissions)383 isSidewalk(SVCPermissions permissions) {
384 return (permissions & SVCAll) == SVC_PEDESTRIAN;
385 }
386
387
388 bool
noVehicles(SVCPermissions permissions)389 noVehicles(SVCPermissions permissions) {
390 return isForbidden(permissions) || isSidewalk(permissions);
391 }
392
393
parseStopOffsets(const SUMOSAXAttributes & attrs,bool & ok)394 std::map<SVCPermissions, double> parseStopOffsets(const SUMOSAXAttributes& attrs, bool& ok) {
395 const std::string vClasses = attrs.getOpt<std::string>(SUMO_ATTR_VCLASSES, nullptr, ok, "");
396 const std::string exceptions = attrs.getOpt<std::string>(SUMO_ATTR_EXCEPTIONS, nullptr, ok, "");
397 if (attrs.hasAttribute(SUMO_ATTR_VCLASSES) && attrs.hasAttribute(SUMO_ATTR_EXCEPTIONS)) {
398 WRITE_ERROR("Simultaneous specification of vClasses and exceptions is not allowed!");
399 ok = false;
400 return std::map<SVCPermissions, double>();
401 }
402 const double value = attrs.get<double>(SUMO_ATTR_VALUE, nullptr, ok);
403
404 int vClassBitset;
405 if (attrs.hasAttribute(SUMO_ATTR_VCLASSES)) {
406 vClassBitset = parseVehicleClasses(vClasses);
407 } else if (attrs.hasAttribute(SUMO_ATTR_EXCEPTIONS)) {
408 vClassBitset = ~parseVehicleClasses(exceptions);
409 } else {
410 // no vClasses specified, thus apply to all
411 vClassBitset = parseVehicleClasses("all");
412 }
413
414 std::map<SVCPermissions, double> offsets;
415 offsets[vClassBitset] = value;
416 return offsets;
417 }
418
419 /****************************************************************************/
420
421