SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SUMOVehicleParserHelper.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // Helper methods for parsing vehicle attributes
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
14 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <utils/common/ToString.h>
41 
42 #ifdef CHECK_MEMORY_LEAKS
43 #include <foreign/nvwa/debug_new.h>
44 #endif // CHECK_MEMORY_LEAKS
45 
46 
47 // ===========================================================================
48 // static members
49 // ===========================================================================
51 
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
58 SUMOVehicleParserHelper::parseFlowAttributes(const SUMOSAXAttributes& attrs, const SUMOTime beginDefault, const SUMOTime endDefault) {
59  bool ok = true;
60  std::string id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
62  throw ProcessError("At most one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
63  "' and '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
64  "' has to be given in the definition of flow '" + id + "'.");
65  }
68  throw ProcessError("If '" + attrs.getName(SUMO_ATTR_PERIOD) +
69  "' or '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
70  "' are given at most one of '" + attrs.getName(SUMO_ATTR_END) +
71  "' and '" + attrs.getName(SUMO_ATTR_NUMBER) +
72  "' are allowed in flow '" + id + "'.");
73  }
74  } else {
75  if (!attrs.hasAttribute(SUMO_ATTR_NUMBER)) {
76  throw ProcessError("At least one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
77  "', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
78  "', and '" + attrs.getName(SUMO_ATTR_NUMBER) +
79  "' is needed in flow '" + id + "'.");
80  }
81  }
83  ret->id = id;
84  try {
85  parseCommonAttributes(attrs, ret, "flow");
86  } catch (ProcessError&) {
87  delete ret;
88  throw;
89  }
90 
91  // parse repetition information
92  if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
94 #ifdef HAVE_SUBSECOND_TIMESTEPS
95  ret->repetitionOffset = attrs.getSUMOTimeReporting(SUMO_ATTR_PERIOD, id.c_str(), ok);
96 #else
97  ret->repetitionOffset = attrs.get<SUMOReal>(SUMO_ATTR_PERIOD, id.c_str(), ok);
98 #endif
99  }
100  if (attrs.hasAttribute(SUMO_ATTR_VEHSPERHOUR)) {
102  const SUMOReal vph = attrs.get<SUMOReal>(SUMO_ATTR_VEHSPERHOUR, id.c_str(), ok);
103  if (ok && vph <= 0) {
104  delete ret;
105  throw ProcessError("Invalid repetition rate in the definition of flow '" + id + "'.");
106  }
107  if (ok && vph != 0) {
108  ret->repetitionOffset = TIME2STEPS(3600. / vph);
109  }
110  }
111 
112  ret->depart = beginDefault;
113  if (attrs.hasAttribute(SUMO_ATTR_BEGIN)) {
114  ret->depart = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok);
115  }
116  if (ok && ret->depart < 0) {
117  delete ret;
118  throw ProcessError("Negative begin time in the definition of flow '" + id + "'.");
119  }
120  SUMOTime end = endDefault;
121  if (end < 0) {
122  end = SUMOTime_MAX;
123  }
124  if (attrs.hasAttribute(SUMO_ATTR_END)) {
125  end = attrs.getSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok);
126  }
127  if (ok && end <= ret->depart) {
128  delete ret;
129  throw ProcessError("Flow '" + id + "' ends before or at its begin time.");
130  }
131  if (attrs.hasAttribute(SUMO_ATTR_NUMBER)) {
132  ret->repetitionNumber = attrs.get<int>(SUMO_ATTR_NUMBER, id.c_str(), ok);
134  if (ret->repetitionNumber == 0) {
135  WRITE_WARNING("Flow '" + id + "' has 0 vehicles; will skip it...");
136  } else {
137  if (ok && ret->repetitionNumber < 0) {
138  delete ret;
139  throw ProcessError("Negative repetition number in the definition of flow '" + id + "'.");
140  }
141  if (ok && ret->repetitionOffset < 0) {
142  ret->repetitionOffset = (end - ret->depart) / ret->repetitionNumber;
143  }
144  }
145  } else {
146  if (ok && ret->repetitionOffset <= 0) {
147  delete ret;
148  throw ProcessError("Invalid repetition rate in the definition of flow '" + id + "'.");
149  }
150  if (end == SUMOTime_MAX) {
151  ret->repetitionNumber = INT_MAX;
152  } else {
153  ret->repetitionNumber = static_cast<int>(static_cast<SUMOReal>(end - ret->depart) / ret->repetitionOffset + 0.5);
154  }
155  }
156  if (!ok) {
157  delete ret;
158  throw ProcessError();
159  }
160  return ret;
161 }
162 
163 
166  bool optionalID, bool skipDepart) {
167  bool ok = true;
168  std::string id, errorMsg;
169  if (optionalID) {
170  id = attrs.getOpt<std::string>(SUMO_ATTR_ID, 0, ok, "");
171  } else {
172  id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
173  }
175  throw ProcessError("The attributes '" + attrs.getName(SUMO_ATTR_PERIOD) +
176  "' and '" + attrs.getName(SUMO_ATTR_REPNUMBER) +
177  "' have to be given both in the definition of '" + id + "'.");
178  }
180  ret->id = id;
181  try {
182  parseCommonAttributes(attrs, ret, "vehicle");
183  } catch (ProcessError&) {
184  delete ret;
185  throw;
186  }
187  if (!skipDepart) {
188  const std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPART, 0, ok);
189  if (helper == "triggered") {
191  } else {
193  ret->depart = attrs.getSUMOTimeReporting(SUMO_ATTR_DEPART, id.c_str(), ok);
194  if (ok && ret->depart < 0) {
195  errorMsg = "Negative departure time in the definition of '" + id + "'.";
196  ok = false;
197  }
198  }
199  }
200  // parse repetition information
201  if (attrs.hasAttribute(SUMO_ATTR_PERIOD)) {
202  WRITE_WARNING("period and repno are deprecated in vehicle '" + id + "', use flows instead.");
204 #ifdef HAVE_SUBSECOND_TIMESTEPS
205  ret->repetitionOffset = attrs.getSUMOTimeReporting(SUMO_ATTR_PERIOD, id.c_str(), ok);
206 #else
207  ret->repetitionOffset = attrs.get<SUMOReal>(SUMO_ATTR_PERIOD, id.c_str(), ok);
208 #endif
209  }
210  if (attrs.hasAttribute(SUMO_ATTR_REPNUMBER)) {
212  ret->repetitionNumber = attrs.get<int>(SUMO_ATTR_REPNUMBER, id.c_str(), ok);
213  }
214 
215  if (!ok) {
216  delete ret;
217  throw ProcessError(errorMsg);
218  }
219  return ret;
220 }
221 
222 
223 void
225  SUMOVehicleParameter* ret, std::string element) {
226  //ret->refid = attrs.getStringSecure(SUMO_ATTR_REFID, "");
227  bool ok = true;
228  // parse route information
229  if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
230  ret->setParameter |= VEHPARS_ROUTE_SET; // !!! needed?
231  ret->routeid = attrs.get<std::string>(SUMO_ATTR_ROUTE, 0, ok);
232  }
233  // parse type information
234  if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
235  ret->setParameter |= VEHPARS_VTYPE_SET; // !!! needed?
236  ret->vtypeid = attrs.get<std::string>(SUMO_ATTR_TYPE, 0, ok);
237  }
238  // parse line information
239  if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
240  ret->setParameter |= VEHPARS_LINE_SET; // !!! needed?
241  ret->line = attrs.get<std::string>(SUMO_ATTR_LINE, 0, ok);
242  }
243  // parse zone information
246  ret->fromTaz = attrs.get<std::string>(SUMO_ATTR_FROM_TAZ, 0, ok);
247  ret->toTaz = attrs.get<std::string>(SUMO_ATTR_TO_TAZ, 0, ok);
248  }
249  // parse reroute information
250  if (attrs.getOpt<bool>(SUMO_ATTR_REROUTE, 0, ok, false)) {
252  }
253 
254  std::string error;
255  // parse depart lane information
256  if (attrs.hasAttribute(SUMO_ATTR_DEPARTLANE)) {
258  const std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPARTLANE, 0, ok);
259  if (!SUMOVehicleParameter::parseDepartLane(helper, element, ret->id, ret->departLane, ret->departLaneProcedure, error)) {
260  throw ProcessError(error);
261  }
262  }
263  // parse depart position information
264  if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
266  const std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPARTPOS, 0, ok);
267  if (!SUMOVehicleParameter::parseDepartPos(helper, element, ret->id, ret->departPos, ret->departPosProcedure, error)) {
268  throw ProcessError(error);
269  }
270  }
271  // parse depart speed information
272  if (attrs.hasAttribute(SUMO_ATTR_DEPARTSPEED)) {
274  std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPARTSPEED, 0, ok);
275  if (!SUMOVehicleParameter::parseDepartSpeed(helper, element, ret->id, ret->departSpeed, ret->departSpeedProcedure, error)) {
276  throw ProcessError(error);
277  }
278  }
279 
280  // parse arrival lane information
281  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALLANE)) {
283  std::string helper = attrs.get<std::string>(SUMO_ATTR_ARRIVALLANE, 0, ok);
284  if (!SUMOVehicleParameter::parseArrivalLane(helper, element, ret->id, ret->arrivalLane, ret->arrivalLaneProcedure, error)) {
285  throw ProcessError(error);
286  }
287  }
288  // parse arrival position information
289  if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
291  std::string helper = attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, 0, ok);
292  if (!SUMOVehicleParameter::parseArrivalPos(helper, element, ret->id, ret->arrivalPos, ret->arrivalPosProcedure, error)) {
293  throw ProcessError(error);
294  }
295  }
296  // parse arrival speed information
299  std::string helper = attrs.get<std::string>(SUMO_ATTR_ARRIVALSPEED, 0, ok);
300  if (!SUMOVehicleParameter::parseArrivalSpeed(helper, element, ret->id, ret->arrivalSpeed, ret->arrivalSpeedProcedure, error)) {
301  throw ProcessError(error);
302  }
303  }
304 
305  // parse color
306  if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
308  ret->color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, ret->id.c_str(), ok);
309  } else {
311  }
312  // parse person number
315  ret->personNumber = attrs.get<int>(SUMO_ATTR_PERSON_NUMBER, 0, ok);
316  }
317  // parse person capacity
320  ret->personCapacity = attrs.get<int>(SUMO_ATTR_PERSON_CAPACITY, 0, ok);
321  }
322 }
323 
324 
326 SUMOVehicleParserHelper::beginVTypeParsing(const SUMOSAXAttributes& attrs, const std::string& file) {
327  SUMOVTypeParameter* vtype = new SUMOVTypeParameter();
328  bool ok = true;
329  vtype->id = attrs.get<std::string>(SUMO_ATTR_ID, 0, ok);
330  if (attrs.hasAttribute(SUMO_ATTR_LENGTH)) {
331  vtype->length = attrs.get<SUMOReal>(SUMO_ATTR_LENGTH, vtype->id.c_str(), ok);
333  }
334  if (attrs.hasAttribute(SUMO_ATTR_MINGAP)) {
335  vtype->minGap = attrs.get<SUMOReal>(SUMO_ATTR_MINGAP, vtype->id.c_str(), ok);
337  }
338  if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED)) {
339  vtype->maxSpeed = attrs.get<SUMOReal>(SUMO_ATTR_MAXSPEED, vtype->id.c_str(), ok);
341  }
342  if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR)) {
343  vtype->speedFactor = attrs.get<SUMOReal>(SUMO_ATTR_SPEEDFACTOR, vtype->id.c_str(), ok);
345  }
346  if (attrs.hasAttribute(SUMO_ATTR_SPEEDDEV)) {
347  vtype->speedDev = attrs.get<SUMOReal>(SUMO_ATTR_SPEEDDEV, vtype->id.c_str(), ok);
349  }
351  vtype->emissionClass = parseEmissionClass(attrs, vtype->id);
353  }
354  if (attrs.hasAttribute(SUMO_ATTR_IMPATIENCE)) {
355  if (attrs.get<std::string>(SUMO_ATTR_IMPATIENCE, vtype->id.c_str(), ok) == "off") {
357  } else {
358  vtype->impatience = attrs.get<SUMOReal>(SUMO_ATTR_IMPATIENCE, vtype->id.c_str(), ok);
359  }
361  }
362  if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
363  vtype->vehicleClass = parseVehicleClass(attrs, vtype->id);
365  }
366  if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
367  vtype->width = attrs.get<SUMOReal>(SUMO_ATTR_WIDTH, vtype->id.c_str(), ok);
369  }
370  if (attrs.hasAttribute(SUMO_ATTR_HEIGHT)) {
371  vtype->height = attrs.get<SUMOReal>(SUMO_ATTR_HEIGHT, vtype->id.c_str(), ok);
373  }
374  if (attrs.hasAttribute(SUMO_ATTR_GUISHAPE)) {
375  vtype->shape = parseGuiShape(attrs, vtype->id);
377  }
378  if (attrs.hasAttribute(SUMO_ATTR_OSGFILE)) {
379  vtype->osgFile = attrs.get<std::string>(SUMO_ATTR_OSGFILE, vtype->id.c_str(), ok);
381  }
382  if (attrs.hasAttribute(SUMO_ATTR_IMGFILE)) {
383  vtype->imgFile = attrs.get<std::string>(SUMO_ATTR_IMGFILE, vtype->id.c_str(), ok);
384  if (vtype->imgFile != "" && !FileHelpers::isAbsolute(vtype->imgFile)) {
386  }
388  }
389  if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
390  vtype->color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, vtype->id.c_str(), ok);
392  } else {
393  vtype->color = RGBColor::YELLOW;
394  }
395  if (attrs.hasAttribute(SUMO_ATTR_PROB)) {
396  vtype->defaultProbability = attrs.get<SUMOReal>(SUMO_ATTR_PROB, vtype->id.c_str(), ok);
398  }
400  const std::string lcmS = attrs.get<std::string>(SUMO_ATTR_LANE_CHANGE_MODEL, vtype->id.c_str(), ok);
401  if (SUMOXMLDefinitions::LaneChangeModels.hasString(lcmS)) {
404  } else {
405  WRITE_ERROR("Unknown lane change model '" + lcmS + "' when parsing vtype '" + vtype->id + "'");
406  throw ProcessError();
407  }
408  }
409  try {
410  parseVTypeEmbedded(*vtype, SUMO_TAG_CF_KRAUSS, attrs, true);
411  } catch (ProcessError&) {
412  throw;
413  }
414  if (!ok) {
415  delete vtype;
416  throw ProcessError();
417  }
418  return vtype;
419 }
420 
421 
422 void
424  int element, const SUMOSAXAttributes& attrs,
425  bool fromVType) {
426  const CFAttrMap& allowedAttrs = getAllowedCFModelAttrs();
427  CFAttrMap::const_iterator cf_it;
428  for (cf_it = allowedAttrs.begin(); cf_it != allowedAttrs.end(); cf_it++) {
429  if (cf_it->first == element) {
430  break;
431  }
432  }
433  if (cf_it == allowedAttrs.end()) {
434  if (SUMOXMLDefinitions::Tags.has(element)) {
435  WRITE_ERROR("Unknown cfmodel " + toString((SumoXMLTag)element) + " when parsing vtype '" + into.id + "'");
436  } else {
437  WRITE_ERROR("Unknown cfmodel when parsing vtype '" + into.id + "'");
438  }
439  throw ProcessError();
440  return;
441  }
442  if (!fromVType) {
443  into.cfModel = cf_it->first;
444  }
445  bool ok = true;
446  for (std::set<SumoXMLAttr>::const_iterator it = cf_it->second.begin(); it != cf_it->second.end(); it++) {
447  if (attrs.hasAttribute(*it)) {
448  into.cfParameter[*it] = attrs.get<SUMOReal>(*it, into.id.c_str(), ok);
449  if (*it == SUMO_ATTR_TAU && TIME2STEPS(into.cfParameter[*it]) < DELTA_T) {
450  WRITE_WARNING("Value of tau=" + toString(into.cfParameter[*it])
451  + " in car following model '" + toString(into.cfModel) + "' lower than simulation step size may cause collisions");
452  }
453  }
454  }
455  if (!ok) {
456  throw ProcessError();
457  }
458 }
459 
460 
463  // init on first use
464  if (allowedCFModelAttrs.size() == 0) {
465  std::set<SumoXMLAttr> krausParams;
466  krausParams.insert(SUMO_ATTR_ACCEL);
467  krausParams.insert(SUMO_ATTR_DECEL);
468  krausParams.insert(SUMO_ATTR_SIGMA);
469  krausParams.insert(SUMO_ATTR_TAU);
473 
474  std::set<SumoXMLAttr> smartSKParams;
475  smartSKParams.insert(SUMO_ATTR_ACCEL);
476  smartSKParams.insert(SUMO_ATTR_DECEL);
477  smartSKParams.insert(SUMO_ATTR_SIGMA);
478  smartSKParams.insert(SUMO_ATTR_TAU);
479  smartSKParams.insert(SUMO_ATTR_TMP1);
480  smartSKParams.insert(SUMO_ATTR_TMP2);
481  smartSKParams.insert(SUMO_ATTR_TMP3);
482  smartSKParams.insert(SUMO_ATTR_TMP4);
483  smartSKParams.insert(SUMO_ATTR_TMP5);
484  allowedCFModelAttrs[SUMO_TAG_CF_SMART_SK] = smartSKParams;
485 
486  std::set<SumoXMLAttr> daniel1Params;
487  daniel1Params.insert(SUMO_ATTR_ACCEL);
488  daniel1Params.insert(SUMO_ATTR_DECEL);
489  daniel1Params.insert(SUMO_ATTR_SIGMA);
490  daniel1Params.insert(SUMO_ATTR_TAU);
491  daniel1Params.insert(SUMO_ATTR_TMP1);
492  daniel1Params.insert(SUMO_ATTR_TMP2);
493  daniel1Params.insert(SUMO_ATTR_TMP3);
494  daniel1Params.insert(SUMO_ATTR_TMP4);
495  daniel1Params.insert(SUMO_ATTR_TMP5);
496  allowedCFModelAttrs[SUMO_TAG_CF_DANIEL1] = daniel1Params;
497 
498  std::set<SumoXMLAttr> pwagParams;
499  pwagParams.insert(SUMO_ATTR_ACCEL);
500  pwagParams.insert(SUMO_ATTR_DECEL);
501  pwagParams.insert(SUMO_ATTR_SIGMA);
502  pwagParams.insert(SUMO_ATTR_TAU);
503  pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_TAULAST);
504  pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_APPROB);
506 
507  std::set<SumoXMLAttr> idmParams;
508  idmParams.insert(SUMO_ATTR_ACCEL);
509  idmParams.insert(SUMO_ATTR_DECEL);
510  idmParams.insert(SUMO_ATTR_TAU);
511  idmParams.insert(SUMO_ATTR_CF_IDM_DELTA);
512  idmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
514 
515  std::set<SumoXMLAttr> idmmParams;
516  idmmParams.insert(SUMO_ATTR_ACCEL);
517  idmmParams.insert(SUMO_ATTR_DECEL);
518  idmmParams.insert(SUMO_ATTR_TAU);
519  idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_FACTOR);
520  idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_TIME);
521  idmmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
523 
524  std::set<SumoXMLAttr> bkernerParams;
525  bkernerParams.insert(SUMO_ATTR_ACCEL);
526  bkernerParams.insert(SUMO_ATTR_DECEL);
527  bkernerParams.insert(SUMO_ATTR_TAU);
528  bkernerParams.insert(SUMO_ATTR_K);
529  bkernerParams.insert(SUMO_ATTR_CF_KERNER_PHI);
530  allowedCFModelAttrs[SUMO_TAG_CF_BKERNER] = bkernerParams;
531 
532  std::set<SumoXMLAttr> wiedemannParams;
533  wiedemannParams.insert(SUMO_ATTR_ACCEL);
534  wiedemannParams.insert(SUMO_ATTR_DECEL);
535  wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_SECURITY);
536  wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_ESTIMATION);
537  allowedCFModelAttrs[SUMO_TAG_CF_WIEDEMANN] = wiedemannParams;
538  }
539  return allowedCFModelAttrs;
540 }
541 
542 
545  const std::string& id) {
546  SUMOVehicleClass vclass = SVC_UNKNOWN;
547  try {
548  bool ok = true;
549  std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_VCLASS, id.c_str(), ok, "");
550  if (vclassS == "") {
551  return vclass;
552  }
553  return getVehicleClassID(vclassS);
554  } catch (...) {
555  WRITE_ERROR("The class for " + attrs.getObjectType() + " '" + id + "' is not known.");
556  }
557  return vclass;
558 }
559 
560 
563  try {
564  bool ok = true;
565  std::string eClassS = attrs.getOpt<std::string>(SUMO_ATTR_EMISSIONCLASS, id.c_str(), ok, "");
566  return getVehicleEmissionTypeID(eClassS);
567  } catch (...) {
568  WRITE_ERROR("The emission class for " + attrs.getObjectType() + " '" + id + "' is not known.");
569  return SVE_UNKNOWN;
570  }
571 }
572 
573 
575 SUMOVehicleParserHelper::parseGuiShape(const SUMOSAXAttributes& attrs, const std::string& id) {
576  bool ok = true;
577  std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_GUISHAPE, id.c_str(), ok, "");
578  if (SumoVehicleShapeStrings.hasString(vclassS)) {
579  return SumoVehicleShapeStrings.get(vclassS);
580  } else {
581  WRITE_ERROR("The shape '" + vclassS + "' for " + attrs.getObjectType() + " '" + id + "' is not known.");
582  return SVS_UNKNOWN;
583  }
584 }
585 
586 /****************************************************************************/
587