Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2008-2024 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 SUMOVehicleParserHelper.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Axel Wegener
18 : /// @author Michael Behrisch
19 : /// @author Laura Bieker
20 : /// @author Mirko Barthauer
21 : /// @date Mon, 07.04.2008
22 : ///
23 : // Helper methods for parsing vehicle attributes
24 : /****************************************************************************/
25 : #include <config.h>
26 :
27 : #include <utils/common/FileHelpers.h>
28 : #include <utils/common/MsgHandler.h>
29 : #include <utils/common/RandHelper.h>
30 : #include <utils/common/StringTokenizer.h>
31 : #include <utils/common/StringUtils.h>
32 : #include <utils/common/ToString.h>
33 : #include <utils/common/UtilExceptions.h>
34 : #include <utils/options/OptionsCont.h>
35 : #include <utils/emissions/PollutantsInterface.h>
36 : #include <utils/router/IntermodalNetwork.h>
37 : #include <utils/vehicle/SUMOVTypeParameter.h>
38 : #include <utils/vehicle/SUMOVehicleParameter.h>
39 : #include <utils/xml/SUMOSAXAttributes.h>
40 :
41 : #include "SUMOVehicleParserHelper.h"
42 :
43 :
44 : // ===========================================================================
45 : // static members
46 : // ===========================================================================
47 :
48 : SUMOVehicleParserHelper::CFAttrMap SUMOVehicleParserHelper::allowedCFModelAttrs;
49 : SUMOVehicleParserHelper::LCAttrMap SUMOVehicleParserHelper::allowedLCModelAttrs;
50 :
51 :
52 : // ===========================================================================
53 : // method definitions
54 : // ===========================================================================
55 :
56 : SUMOVehicleParameter*
57 24614 : SUMOVehicleParserHelper::parseFlowAttributes(SumoXMLTag tag, const SUMOSAXAttributes& attrs, const bool hardFail, const bool needID,
58 : const SUMOTime beginDefault, const SUMOTime endDefault, const bool allowInternalRoutes) {
59 : // first parse ID
60 24614 : const std::string id = attrs.hasAttribute(SUMO_ATTR_ID) ? parseID(attrs, tag) : "";
61 : // check if ID is valid
62 24614 : if (!needID || !id.empty()) {
63 24607 : if (needID && !SUMOXMLDefinitions::isValidVehicleID(id)) {
64 0 : return handleVehicleError(hardFail, nullptr, "Invalid flow id '" + id + "'.");
65 : }
66 : // declare flags
67 24607 : const bool hasPeriod = attrs.hasAttribute(SUMO_ATTR_PERIOD);
68 24607 : const bool hasVPH = attrs.hasAttribute(SUMO_ATTR_VEHSPERHOUR);
69 24607 : const bool hasPPH = attrs.hasAttribute(SUMO_ATTR_PERSONSPERHOUR);
70 24607 : const bool hasCPH = attrs.hasAttribute(SUMO_ATTR_CONTAINERSPERHOUR);
71 24607 : const bool hasPH = attrs.hasAttribute(SUMO_ATTR_PERHOUR);
72 24607 : const bool hasXPH = hasVPH || hasPPH || hasCPH || hasPH;
73 24607 : const bool hasProb = attrs.hasAttribute(SUMO_ATTR_PROB);
74 24607 : const bool hasNumber = attrs.hasAttribute(SUMO_ATTR_NUMBER);
75 24607 : const bool hasBegin = attrs.hasAttribute(SUMO_ATTR_BEGIN);
76 24607 : const bool hasEnd = attrs.hasAttribute(SUMO_ATTR_END);
77 : SumoXMLAttr PERHOUR = SUMO_ATTR_PERHOUR;
78 24607 : if (hasVPH) {
79 : PERHOUR = SUMO_ATTR_VEHSPERHOUR;
80 : }
81 24607 : if (hasPPH) {
82 : PERHOUR = SUMO_ATTR_PERSONSPERHOUR;
83 : }
84 24607 : if (hasCPH) {
85 : PERHOUR = SUMO_ATTR_CONTAINERSPERHOUR;
86 : }
87 24607 : if (hasXPH && !(hasVPH ^ hasPPH ^ hasCPH ^ hasPH)) {
88 0 : return handleVehicleError(hardFail, nullptr,
89 0 : "At most one of '" + attrs.getName(SUMO_ATTR_PERHOUR) +
90 0 : "', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
91 0 : "', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
92 0 : "' and '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
93 0 : "' has to be given in the definition of " + toString(tag) + " '" + id + "'.");
94 : }
95 3765 : if (hasPeriod && hasXPH) {
96 7 : return handleVehicleError(hardFail, nullptr,
97 14 : "At most one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
98 21 : "' and '" + attrs.getName(PERHOUR) +
99 : "' has to be given in the definition of "
100 14 : + toString(tag) + " '" + id + "'.");
101 : }
102 24600 : if (hasPeriod && hasProb) {
103 0 : return handleVehicleError(hardFail, nullptr,
104 0 : "At most one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
105 0 : "' and '" + attrs.getName(SUMO_ATTR_PROB) +
106 : "' has to be given in the definition of "
107 0 : + toString(tag) + " '" + id + "'.");
108 : }
109 24600 : if (hasProb && hasXPH) {
110 0 : return handleVehicleError(hardFail, nullptr,
111 0 : "At most one of '" + attrs.getName(SUMO_ATTR_PROB) +
112 0 : "' and '" + attrs.getName(PERHOUR) +
113 : "' has to be given in the definition of "
114 0 : + toString(tag) + " '" + id + "'.");
115 : }
116 24600 : if (hasPeriod || hasXPH || hasProb) {
117 16131 : if (hasEnd && hasNumber) {
118 7 : return handleVehicleError(hardFail, nullptr,
119 14 : "If '" + attrs.getName(SUMO_ATTR_PERIOD) +
120 21 : "', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
121 21 : "', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
122 21 : "', '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
123 21 : "', '" + attrs.getName(SUMO_ATTR_PERHOUR) +
124 21 : "' or '" + attrs.getName(SUMO_ATTR_PROB) +
125 21 : "' are given at most one of '" + attrs.getName(SUMO_ATTR_END) +
126 21 : "' and '" + attrs.getName(SUMO_ATTR_NUMBER) +
127 : "' are allowed in "
128 14 : + toString(tag) + " '" + id + "'.");
129 : }
130 : } else {
131 8469 : if (!hasNumber) {
132 7 : return handleVehicleError(hardFail, nullptr,
133 14 : "At least one of '" + attrs.getName(SUMO_ATTR_PERIOD) +
134 21 : "', '" + attrs.getName(SUMO_ATTR_VEHSPERHOUR) +
135 21 : "', '" + attrs.getName(SUMO_ATTR_PERSONSPERHOUR) +
136 21 : "', '" + attrs.getName(SUMO_ATTR_CONTAINERSPERHOUR) +
137 21 : "', '" + attrs.getName(SUMO_ATTR_PERHOUR) +
138 21 : "', '" + attrs.getName(SUMO_ATTR_PROB) +
139 21 : "', and '" + attrs.getName(SUMO_ATTR_NUMBER) +
140 : "' is needed in "
141 14 : + toString(tag) + " '" + id + "'.");
142 : }
143 : }
144 : // declare flow
145 24586 : SUMOVehicleParameter* flowParameter = new SUMOVehicleParameter();
146 : // set tag
147 24586 : flowParameter->tag = tag;
148 : // set id
149 24586 : flowParameter->id = id;
150 24586 : if (tag == SUMO_TAG_PERSONFLOW) {
151 1676 : flowParameter->vtypeid = DEFAULT_PEDTYPE_ID;
152 : }
153 24586 : if (tag == SUMO_TAG_CONTAINERFLOW) {
154 309 : flowParameter->vtypeid = DEFAULT_CONTAINERTYPE_ID;
155 : }
156 : // parse common vehicle attributes
157 : try {
158 24586 : parseCommonAttributes(attrs, flowParameter, tag, allowInternalRoutes);
159 48 : } catch (ProcessError& attributeError) {
160 : // check if continue handling another vehicles or stop handling
161 48 : if (hardFail) {
162 96 : throw ProcessError(attributeError.what());
163 : } else {
164 : return nullptr;
165 : }
166 48 : }
167 : // parse period
168 : bool poissonFlow = false;
169 24538 : if (hasPeriod) {
170 8371 : bool ok = true;
171 8371 : const std::string description = attrs.get<std::string>(SUMO_ATTR_PERIOD, id.c_str(), ok);
172 8371 : const std::string distName = description.substr(0, description.find('('));
173 8371 : if (distName == "exp") {
174 : // declare rate
175 : double rate = -1;
176 : // parse rate
177 : try {
178 508 : rate = StringUtils::toDouble(description.substr(distName.size() + 1, description.size() - distName.size() - 2));
179 0 : } catch (ProcessError& attributeError) {
180 : // check if continue handling another vehicles or stop handling
181 0 : if (hardFail) {
182 0 : throw ProcessError(attributeError.what());
183 : } else {
184 : return nullptr;
185 : }
186 0 : }
187 508 : if (rate <= 0) {
188 14 : return handleVehicleError(hardFail, flowParameter, "Invalid rate parameter for exponentially distributed period in the definition of " + toString(tag) + " '" + id + "'.");
189 : }
190 501 : flowParameter->poissonRate = rate;
191 : poissonFlow = true;
192 : } else {
193 7863 : flowParameter->repetitionOffset = attrs.getSUMOTimeReporting(SUMO_ATTR_PERIOD, id.c_str(), ok);
194 : }
195 8364 : if (!ok) {
196 7 : return handleVehicleError(hardFail, flowParameter);
197 : } else {
198 8364 : flowParameter->parametersSet |= VEHPARS_PERIOD_SET;
199 : }
200 : }
201 : // parse vehicle/person/container/etc per hour
202 24531 : if (hasXPH) {
203 3758 : bool ok = true;
204 3758 : const double vph = attrs.get<double>(PERHOUR, id.c_str(), ok);
205 3758 : if (!ok) {
206 0 : return handleVehicleError(hardFail, flowParameter);
207 3758 : } else if (vph <= 0) {
208 0 : return handleVehicleError(hardFail, flowParameter, "Invalid repetition rate in the definition of " + toString(tag) + " '" + id + "'.");
209 : } else {
210 : if (vph != 0) {
211 3758 : flowParameter->repetitionOffset = TIME2STEPS(3600. / vph);
212 : }
213 3758 : flowParameter->parametersSet |= VEHPARS_VPH_SET;
214 : }
215 : }
216 : // parse probability
217 24531 : if (hasProb) {
218 3995 : bool ok = true;
219 3995 : flowParameter->repetitionProbability = attrs.get<double>(SUMO_ATTR_PROB, id.c_str(), ok);
220 3995 : if (!ok) {
221 0 : return handleVehicleError(hardFail, flowParameter);
222 3995 : } else if (flowParameter->repetitionProbability <= 0 || flowParameter->repetitionProbability > 1) {
223 0 : return handleVehicleError(hardFail, flowParameter, "Invalid repetition probability in the definition of " + toString(tag) + " '" + id + "'.");
224 : } else {
225 3995 : flowParameter->parametersSet |= VEHPARS_PROB_SET;
226 : }
227 : }
228 : // set default begin
229 24531 : flowParameter->depart = beginDefault;
230 : // parse begin
231 24531 : if (hasBegin) {
232 : // first get begin
233 24349 : bool ok = true;
234 24349 : const std::string begin = attrs.get<std::string>(SUMO_ATTR_BEGIN, id.c_str(), ok);
235 24349 : if (!ok) {
236 7 : return handleVehicleError(hardFail, flowParameter);
237 : } else {
238 : // parse begin
239 : std::string errorMsg;
240 48698 : if (!SUMOVehicleParameter::parseDepart(begin, toString(tag), id, flowParameter->depart, flowParameter->departProcedure, errorMsg, "begin")) {
241 14 : return handleVehicleError(hardFail, flowParameter, errorMsg);
242 : }
243 : }
244 : }
245 24524 : if (flowParameter->depart < 0) {
246 0 : return handleVehicleError(hardFail, flowParameter, "Negative begin time in the definition of " + toString(tag) + " '" + id + "'.");
247 : }
248 : // set default end
249 24524 : flowParameter->repetitionEnd = endDefault;
250 24524 : if (flowParameter->repetitionEnd < 0) {
251 17086 : flowParameter->repetitionEnd = SUMOTime_MAX;
252 : }
253 : // parse end
254 24524 : if (hasEnd) {
255 22246 : bool ok = true;
256 22246 : flowParameter->repetitionEnd = attrs.getSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok);
257 22246 : if (!ok) {
258 0 : return handleVehicleError(hardFail, flowParameter);
259 : } else {
260 22246 : flowParameter->parametersSet |= VEHPARS_END_SET;
261 : }
262 2278 : } else if (flowParameter->departProcedure == DepartDefinition::TRIGGERED) {
263 47 : if (!hasNumber) {
264 0 : return handleVehicleError(hardFail, flowParameter, toString(tag) + " '" + id + "' with triggered begin must define 'number'.");
265 : } else {
266 47 : flowParameter->repetitionEnd = flowParameter->depart;
267 : }
268 2231 : } else if ((endDefault == SUMOTime_MAX || endDefault < 0) && (!hasNumber || (!hasProb && !hasPeriod && !hasXPH))) {
269 156 : WRITE_WARNINGF(TL("Undefined end for % '%', defaulting to 24hour duration."), toString(tag), id);
270 52 : flowParameter->repetitionEnd = flowParameter->depart + TIME2STEPS(24 * 3600);
271 : }
272 24524 : if (flowParameter->repetitionEnd < flowParameter->depart) {
273 7 : std::string flow = toString(tag);
274 7 : flow[0] = (char)::toupper((char)flow[0]);
275 21 : return handleVehicleError(hardFail, flowParameter, flow + " '" + id + "' ends before its begin time.");
276 : }
277 : // parse number
278 24517 : if (hasNumber) {
279 10377 : bool ok = true;
280 10377 : flowParameter->repetitionNumber = attrs.get<int>(SUMO_ATTR_NUMBER, id.c_str(), ok);
281 10377 : if (!ok) {
282 0 : return handleVehicleError(hardFail, flowParameter);
283 : } else {
284 10377 : flowParameter->parametersSet |= VEHPARS_NUMBER_SET;
285 10377 : if (flowParameter->repetitionNumber == 0) {
286 8 : std::string flow = toString(tag);
287 8 : flow[0] = (char)::toupper((char)flow[0]);
288 16 : WRITE_WARNING(flow + " '" + id + "' has no instances; will skip it.");
289 8 : flowParameter->repetitionEnd = flowParameter->depart;
290 : } else {
291 10369 : if (flowParameter->repetitionNumber < 0) {
292 14 : return handleVehicleError(hardFail, flowParameter, "Negative repetition number in the definition of " + toString(tag) + " '" + id + "'.");
293 : }
294 10362 : if (flowParameter->repetitionOffset < 0 && !hasProb) {
295 8449 : if (poissonFlow) {
296 43 : flowParameter->repetitionEnd = SUMOTime_MAX;
297 : } else {
298 8406 : flowParameter->repetitionOffset = (flowParameter->repetitionEnd - flowParameter->depart) / flowParameter->repetitionNumber;
299 : }
300 : }
301 : }
302 : }
303 : } else {
304 : // interpret repetitionNumber
305 14140 : if (flowParameter->repetitionProbability > 0) {
306 3953 : flowParameter->repetitionNumber = std::numeric_limits<int>::max();
307 : } else {
308 10187 : if (flowParameter->repetitionOffset <= 0) {
309 472 : if (poissonFlow) {
310 : // number is random but flow has a fixed end time
311 458 : flowParameter->repetitionNumber = std::numeric_limits<int>::max();
312 : } else {
313 28 : return handleVehicleError(hardFail, flowParameter, "Invalid repetition rate in the definition of " + toString(tag) + " '" + id + "'.");
314 : }
315 : } else {
316 9715 : if (flowParameter->repetitionEnd == SUMOTime_MAX) {
317 0 : flowParameter->repetitionNumber = std::numeric_limits<int>::max();
318 : } else {
319 9715 : const SUMOTime repLength = flowParameter->repetitionEnd - flowParameter->depart;
320 9715 : flowParameter->repetitionNumber = (int)ceil((double)repLength / (double)flowParameter->repetitionOffset);
321 : }
322 : }
323 : }
324 : }
325 : // all ok, then return flow parameter
326 24496 : return flowParameter;
327 : } else {
328 132 : return handleVehicleError(hardFail, nullptr, toString(tag) + " cannot be created");
329 : }
330 : }
331 :
332 :
333 : SUMOVehicleParameter*
334 472057 : SUMOVehicleParserHelper::parseVehicleAttributes(int element, const SUMOSAXAttributes& attrs, const bool hardFail, const bool optionalID, const bool skipDepart, const bool allowInternalRoutes) {
335 : // declare vehicle ID
336 : std::string id;
337 : // for certain vehicles, ID can be optional
338 472057 : if (optionalID) {
339 673 : bool ok = true;
340 673 : id = attrs.getOpt<std::string>(SUMO_ATTR_ID, nullptr, ok, "");
341 673 : if (!ok) {
342 0 : return handleVehicleError(hardFail, nullptr);
343 : }
344 : } else {
345 : // parse ID
346 942768 : id = parseID(attrs, (SumoXMLTag)element);
347 : }
348 : // only continue if id is valid, or if is optional
349 472057 : if (optionalID || !id.empty()) {
350 : // declare vehicle parameter
351 472041 : SUMOVehicleParameter* vehicleParameter = new SUMOVehicleParameter();
352 472041 : vehicleParameter->id = id;
353 472041 : if (element == SUMO_TAG_PERSON) {
354 41368 : vehicleParameter->vtypeid = DEFAULT_PEDTYPE_ID;
355 430673 : } else if (element == SUMO_TAG_CONTAINER) {
356 807 : vehicleParameter->vtypeid = DEFAULT_CONTAINERTYPE_ID;
357 : }
358 : // parse common attributes
359 : try {
360 472041 : parseCommonAttributes(attrs, vehicleParameter, (SumoXMLTag)element, allowInternalRoutes);
361 274 : } catch (ProcessError& attributeError) {
362 : // check if continue handling another vehicles or stop handling
363 274 : if (hardFail) {
364 548 : throw ProcessError(attributeError.what());
365 : } else {
366 : return nullptr;
367 : }
368 274 : }
369 : // check depart
370 471767 : if (!skipDepart) {
371 471094 : bool ok = true;
372 471094 : const std::string helper = attrs.get<std::string>(SUMO_ATTR_DEPART, vehicleParameter->id.c_str(), ok);
373 471094 : if (!ok) {
374 40 : return handleVehicleError(hardFail, vehicleParameter);
375 : }
376 : // now parse depart
377 : std::string departErrorMsg;
378 942156 : if (!SUMOVehicleParameter::parseDepart(helper, "vehicle", vehicleParameter->id, vehicleParameter->depart, vehicleParameter->departProcedure, departErrorMsg)) {
379 16 : return handleVehicleError(hardFail, vehicleParameter, departErrorMsg);
380 : }
381 : }
382 : // set tag
383 471743 : vehicleParameter->tag = (SumoXMLTag)element;
384 : // all ok, then return vehicleParameter
385 471743 : return vehicleParameter;
386 : } else {
387 346 : return handleVehicleError(hardFail, nullptr, toString((SumoXMLTag)element) + " cannot be created");
388 : }
389 : }
390 :
391 :
392 : std::string
393 556367 : SUMOVehicleParserHelper::parseID(const SUMOSAXAttributes& attrs, const SumoXMLTag element) {
394 556367 : bool ok = true;
395 : std::string id;
396 : // first check if attrs contain an ID
397 556367 : if (attrs.hasAttribute(SUMO_ATTR_ID)) {
398 556355 : id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
399 556355 : if (SUMOXMLDefinitions::isValidVehicleID(id)) {
400 556347 : return id;
401 8 : } else if (id.empty()) {
402 : // add extra information for empty IDs
403 24 : WRITE_ERRORF(TL("Invalid % id '%'."), toString(element), id);
404 : } else {
405 0 : WRITE_ERRORF(TL("Invalid % id '%'. Contains invalid characters."), toString(element), id);
406 : }
407 : } else {
408 36 : WRITE_ERROR("Attribute '" + toString(SUMO_ATTR_ID) + "' is missing in definition of " + toString(element));
409 : }
410 : // return empty (invalid) ID
411 20 : return "";
412 : }
413 :
414 :
415 : void
416 496627 : SUMOVehicleParserHelper::parseCommonAttributes(const SUMOSAXAttributes& attrs, SUMOVehicleParameter* ret, SumoXMLTag tag, const bool allowInternalRoutes) {
417 496627 : const std::string element = toString(tag);
418 : //ret->refid = attrs.getStringSecure(SUMO_ATTR_REFID, "");
419 : // parse route information
420 496627 : if (attrs.hasAttribute(SUMO_ATTR_ROUTE)) {
421 166809 : bool ok = true;
422 166809 : std::string routeID = attrs.get<std::string>(SUMO_ATTR_ROUTE, ret->id.c_str(), ok);
423 166809 : if (!allowInternalRoutes && isInternalRouteID(routeID)) {
424 0 : WRITE_WARNINGF(TL("Internal routes receive an ID starting with '!' and must not be referenced in other vehicle or flow definitions. Please remove all references to route '%' in case it is internal."), routeID);
425 : }
426 166809 : ret->routeid = routeID;
427 166809 : if (ok) {
428 166799 : ret->parametersSet |= VEHPARS_ROUTE_SET; // !!! needed?
429 : } else {
430 20 : handleVehicleError(true, ret);
431 : }
432 : }
433 : // parse type information
434 496617 : if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
435 213648 : bool ok = true;
436 213648 : ret->vtypeid = attrs.get<std::string>(SUMO_ATTR_TYPE, ret->id.c_str(), ok);
437 213648 : if (ok) {
438 213648 : ret->parametersSet |= VEHPARS_VTYPE_SET; // !!! needed?
439 : } else {
440 0 : handleVehicleError(true, ret);
441 : }
442 : }
443 : // parse line information
444 496617 : if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
445 2904 : bool ok = true;
446 2904 : ret->line = attrs.get<std::string>(SUMO_ATTR_LINE, ret->id.c_str(), ok);
447 2904 : if (ok) {
448 2898 : ret->parametersSet |= VEHPARS_LINE_SET; // !!! needed?
449 : } else {
450 6 : handleVehicleError(true, ret);
451 : }
452 : }
453 : // parse zone information
454 496611 : if (attrs.hasAttribute(SUMO_ATTR_FROM_TAZ)) {
455 26061 : bool ok = true;
456 26061 : ret->fromTaz = attrs.get<std::string>(SUMO_ATTR_FROM_TAZ, ret->id.c_str(), ok);
457 26061 : if (ok) {
458 26061 : ret->parametersSet |= VEHPARS_FROM_TAZ_SET;
459 : } else {
460 0 : handleVehicleError(true, ret);
461 : }
462 : }
463 496611 : if (attrs.hasAttribute(SUMO_ATTR_TO_TAZ)) {
464 26061 : bool ok = true;
465 26061 : ret->toTaz = attrs.get<std::string>(SUMO_ATTR_TO_TAZ, ret->id.c_str(), ok);
466 26061 : if (ok) {
467 26061 : ret->parametersSet |= VEHPARS_TO_TAZ_SET;
468 : } else {
469 0 : handleVehicleError(true, ret);
470 : }
471 : }
472 : // parse reroute information
473 496611 : if (attrs.hasAttribute(SUMO_ATTR_REROUTE)) {
474 3838 : bool ok = true;
475 3838 : if (attrs.get<bool>(SUMO_ATTR_REROUTE, ret->id.c_str(), ok)) {
476 3838 : if (ok) {
477 3838 : ret->parametersSet |= VEHPARS_FORCE_REROUTE;
478 : } else {
479 0 : handleVehicleError(true, ret);
480 : }
481 : }
482 : }
483 : // parse depart lane information
484 496611 : if (attrs.hasAttribute(SUMO_ATTR_DEPARTLANE)) {
485 110172 : bool ok = true;
486 110172 : const std::string departLaneStr = attrs.get<std::string>(SUMO_ATTR_DEPARTLANE, ret->id.c_str(), ok);
487 : int lane;
488 : DepartLaneDefinition dld;
489 : std::string error;
490 110172 : if (SUMOVehicleParameter::parseDepartLane(departLaneStr, element, ret->id, lane, dld, error)) {
491 110124 : ret->parametersSet |= VEHPARS_DEPARTLANE_SET;
492 110124 : ret->departLane = lane;
493 110124 : ret->departLaneProcedure = dld;
494 : } else {
495 96 : handleVehicleError(true, ret, error);
496 : }
497 : }
498 : // parse depart position information
499 496563 : if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS)) {
500 86907 : bool ok = true;
501 86907 : const std::string departPosStr = attrs.get<std::string>(SUMO_ATTR_DEPARTPOS, ret->id.c_str(), ok);
502 : double pos;
503 : DepartPosDefinition dpd;
504 : std::string error;
505 86907 : if (SUMOVehicleParameter::parseDepartPos(departPosStr, element, ret->id, pos, dpd, error)) {
506 86859 : ret->parametersSet |= VEHPARS_DEPARTPOS_SET;
507 86859 : ret->departPos = pos;
508 86859 : ret->departPosProcedure = dpd;
509 : } else {
510 96 : handleVehicleError(true, ret, error);
511 : }
512 : }
513 : // parse lateral depart position information
514 496515 : if (attrs.hasAttribute(SUMO_ATTR_DEPARTPOS_LAT)) {
515 8718 : bool ok = true;
516 8718 : const std::string departPosLatStr = attrs.get<std::string>(SUMO_ATTR_DEPARTPOS_LAT, ret->id.c_str(), ok);
517 : double pos;
518 : DepartPosLatDefinition dpd;
519 : std::string error;
520 8718 : if (SUMOVehicleParameter::parseDepartPosLat(departPosLatStr, element, ret->id, pos, dpd, error)) {
521 8718 : ret->parametersSet |= VEHPARS_DEPARTPOSLAT_SET;
522 8718 : ret->departPosLat = pos;
523 8718 : ret->departPosLatProcedure = dpd;
524 : } else {
525 0 : handleVehicleError(true, ret, error);
526 : }
527 : }
528 : // parse depart speed information
529 496515 : if (attrs.hasAttribute(SUMO_ATTR_DEPARTSPEED)) {
530 240762 : bool ok = true;
531 240762 : const std::string departSpeed = attrs.get<std::string>(SUMO_ATTR_DEPARTSPEED, ret->id.c_str(), ok);
532 : double speed;
533 : DepartSpeedDefinition dsd;
534 : std::string error;
535 240762 : if (SUMOVehicleParameter::parseDepartSpeed(departSpeed, element, ret->id, speed, dsd, error)) {
536 240714 : ret->parametersSet |= VEHPARS_DEPARTSPEED_SET;
537 240714 : ret->departSpeed = speed;
538 240714 : ret->departSpeedProcedure = dsd;
539 : } else {
540 96 : handleVehicleError(true, ret, error);
541 : }
542 : }
543 : // parse depart edge information
544 496467 : if (attrs.hasAttribute(SUMO_ATTR_DEPARTEDGE)) {
545 151 : bool ok = true;
546 151 : const std::string departEdgeStr = attrs.get<std::string>(SUMO_ATTR_DEPARTEDGE, ret->id.c_str(), ok);
547 : int edgeIndex;
548 : RouteIndexDefinition rid;
549 : std::string error;
550 151 : if (SUMOVehicleParameter::parseRouteIndex(departEdgeStr, element, ret->id, SUMO_ATTR_DEPARTEDGE, edgeIndex, rid, error)) {
551 144 : ret->parametersSet |= VEHPARS_DEPARTEDGE_SET;
552 144 : ret->departEdge = edgeIndex;
553 144 : ret->departEdgeProcedure = rid;
554 : } else {
555 14 : handleVehicleError(true, ret, error);
556 : }
557 : }
558 : // parse arrival lane information
559 496460 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVALLANE)) {
560 3141 : bool ok = true;
561 3141 : const std::string arrivalLaneStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALLANE, ret->id.c_str(), ok);
562 : int lane;
563 : ArrivalLaneDefinition ald;
564 : std::string error;
565 3141 : if (SUMOVehicleParameter::parseArrivalLane(arrivalLaneStr, element, ret->id, lane, ald, error)) {
566 3093 : ret->parametersSet |= VEHPARS_ARRIVALLANE_SET;
567 3093 : ret->arrivalLane = lane;
568 3093 : ret->arrivalLaneProcedure = ald;
569 : } else {
570 96 : handleVehicleError(true, ret, error);
571 : }
572 : }
573 : // parse arrival position information
574 496412 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS)) {
575 8062 : bool ok = true;
576 8062 : const std::string arrivalPosStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS, ret->id.c_str(), ok);
577 : double pos;
578 : ArrivalPosDefinition apd;
579 : std::string error;
580 8062 : if (SUMOVehicleParameter::parseArrivalPos(arrivalPosStr, element, ret->id, pos, apd, error)) {
581 8014 : ret->parametersSet |= VEHPARS_ARRIVALPOS_SET;
582 8014 : ret->arrivalPos = pos;
583 8014 : ret->arrivalPosProcedure = apd;
584 : } else {
585 96 : handleVehicleError(true, ret, error);
586 : }
587 : }
588 : // parse lateral arrival position information
589 496364 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVALPOS_LAT)) {
590 1065 : bool ok = true;
591 1065 : const std::string arrivalPosLatStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALPOS_LAT, ret->id.c_str(), ok);
592 : double pos;
593 : ArrivalPosLatDefinition apd;
594 : std::string error;
595 1065 : if (SUMOVehicleParameter::parseArrivalPosLat(arrivalPosLatStr, element, ret->id, pos, apd, error)) {
596 1065 : ret->parametersSet |= VEHPARS_ARRIVALPOSLAT_SET;
597 1065 : ret->arrivalPosLat = pos;
598 1065 : ret->arrivalPosLatProcedure = apd;
599 : } else {
600 0 : handleVehicleError(true, ret, error);
601 : }
602 : }
603 : // parse arrival speed information
604 496364 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVALSPEED)) {
605 3792 : bool ok = true;
606 3792 : std::string arrivalSpeedStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALSPEED, ret->id.c_str(), ok);
607 : double speed;
608 : ArrivalSpeedDefinition asd;
609 : std::string error;
610 3792 : if (SUMOVehicleParameter::parseArrivalSpeed(arrivalSpeedStr, element, ret->id, speed, asd, error)) {
611 3744 : ret->parametersSet |= VEHPARS_ARRIVALSPEED_SET;
612 3744 : ret->arrivalSpeed = speed;
613 3744 : ret->arrivalSpeedProcedure = asd;
614 : } else {
615 96 : handleVehicleError(true, ret, error);
616 : }
617 : }
618 : // parse arrival edge information
619 496316 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVALEDGE)) {
620 81 : bool ok = true;
621 81 : std::string arrivalEdgeStr = attrs.get<std::string>(SUMO_ATTR_ARRIVALEDGE, ret->id.c_str(), ok);
622 : int edgeIndex;
623 : RouteIndexDefinition rid;
624 : std::string error;
625 81 : if (SUMOVehicleParameter::parseRouteIndex(arrivalEdgeStr, element, ret->id, SUMO_ATTR_ARRIVALEDGE, edgeIndex, rid, error)) {
626 74 : ret->parametersSet |= VEHPARS_ARRIVALEDGE_SET;
627 74 : ret->arrivalEdge = edgeIndex;
628 74 : ret->arrivalEdgeProcedure = rid;
629 : } else {
630 14 : handleVehicleError(true, ret, error);
631 : }
632 : }
633 : // parse color
634 496309 : if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
635 8680 : bool ok = true;
636 8680 : ret->color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, ret->id.c_str(), ok);
637 8680 : if (ok) {
638 8680 : ret->parametersSet |= VEHPARS_COLOR_SET;
639 : } else {
640 0 : handleVehicleError(true, ret, "Invalid RGBColor format");
641 : }
642 : } else {
643 487629 : ret->color = RGBColor::DEFAULT_COLOR;
644 : }
645 : // parse person number
646 496309 : if (attrs.hasAttribute(SUMO_ATTR_PERSON_NUMBER)) {
647 986 : bool ok = true;
648 986 : int personNumber = attrs.get<int>(SUMO_ATTR_PERSON_NUMBER, ret->id.c_str(), ok);
649 986 : if (!ok) {
650 0 : handleVehicleError(true, ret);
651 986 : } else if (personNumber >= 0) {
652 986 : ret->parametersSet |= VEHPARS_PERSON_NUMBER_SET;
653 986 : ret->personNumber = personNumber;
654 : } else {
655 0 : handleVehicleError(true, ret, toString(SUMO_ATTR_PERSON_NUMBER) + " cannot be negative");
656 : }
657 : }
658 : // parse container number
659 496309 : if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_NUMBER)) {
660 980 : bool ok = true;
661 980 : int containerNumber = attrs.get<int>(SUMO_ATTR_CONTAINER_NUMBER, ret->id.c_str(), ok);
662 980 : if (!ok) {
663 0 : handleVehicleError(true, ret);
664 980 : } else if (containerNumber >= 0) {
665 980 : ret->parametersSet |= VEHPARS_CONTAINER_NUMBER_SET;
666 980 : ret->containerNumber = containerNumber;
667 : } else {
668 0 : handleVehicleError(true, ret, toString(SUMO_ATTR_CONTAINER_NUMBER) + " cannot be negative");
669 : }
670 : }
671 : // parse individual speedFactor
672 496309 : if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR)) {
673 10644 : bool ok = true;
674 10644 : double speedFactor = attrs.get<double>(SUMO_ATTR_SPEEDFACTOR, ret->id.c_str(), ok);
675 10644 : if (!ok) {
676 0 : handleVehicleError(true, ret);
677 10644 : } else if (speedFactor > 0) {
678 10644 : ret->parametersSet |= VEHPARS_SPEEDFACTOR_SET;
679 10644 : ret->speedFactor = speedFactor;
680 : } else {
681 0 : handleVehicleError(true, ret, toString(SUMO_ATTR_SPEEDFACTOR) + " must be positive");
682 : }
683 : }
684 : // parse insertion checks
685 496309 : if (attrs.hasAttribute(SUMO_ATTR_INSERTIONCHECKS)) {
686 1022 : ret->parametersSet |= VEHPARS_INSERTION_CHECKS_SET;
687 1022 : bool ok = true;
688 1022 : std::string checks = attrs.get<std::string>(SUMO_ATTR_INSERTIONCHECKS, ret->id.c_str(), ok);
689 1022 : if (!ok) {
690 4 : handleVehicleError(true, ret);
691 : } else {
692 : try {
693 1022 : ret->insertionChecks = SUMOVehicleParameter::parseInsertionChecks(checks);
694 4 : } catch (InvalidArgument& e) {
695 4 : handleVehicleError(true, ret, e.what());
696 4 : }
697 : }
698 : }
699 : // parse parking access rights
700 496305 : if (attrs.hasAttribute(SUMO_ATTR_PARKING_BADGES)) {
701 7 : bool ok = true;
702 7 : std::vector<std::string> badges = attrs.get<std::vector<std::string>>(SUMO_ATTR_PARKING_BADGES, ret->id.c_str(), ok);
703 7 : if (!ok) {
704 0 : handleVehicleError(true, ret);
705 : } else {
706 7 : ret->parametersSet |= VEHPARS_PARKING_BADGES_SET;
707 7 : ret->parkingBadges = badges;
708 : }
709 7 : }
710 : // parse modes (transportables only)
711 496305 : ret->modes = 0;
712 496305 : if (attrs.hasAttribute(SUMO_ATTR_MODES)) {
713 4 : bool ok = true;
714 4 : const std::string modeString = attrs.get<std::string>(SUMO_ATTR_MODES, ret->id.c_str(), ok);
715 4 : if (!ok) {
716 0 : handleVehicleError(true, ret);
717 : } else {
718 : std::string errorMsg;
719 8 : if (!SUMOVehicleParameter::parsePersonModes(modeString, toString(tag), ret->id, ret->modes, errorMsg)) {
720 0 : handleVehicleError(true, ret, errorMsg);
721 : }
722 : }
723 : }
724 : // parse usable vehicle types (transportables only)
725 496305 : if (attrs.hasAttribute(SUMO_ATTR_VTYPES)) {
726 0 : bool ok = true;
727 0 : ret->vTypes = attrs.get<std::string>(SUMO_ATTR_VTYPES, ret->id.c_str(), ok);
728 0 : if (!ok) {
729 0 : handleVehicleError(true, ret);
730 : }
731 : }
732 : // parse speed (only used by calibrators flow)
733 : // also used by vehicle in saved state but this is parsed elsewhere
734 496305 : if (tag == SUMO_TAG_FLOW && attrs.hasAttribute(SUMO_ATTR_SPEED)) {
735 216 : bool ok = true;
736 216 : double calibratorSpeed = attrs.get<double>(SUMO_ATTR_SPEED, ret->id.c_str(), ok);
737 216 : if (!ok) {
738 0 : handleVehicleError(true, ret);
739 216 : } else if (calibratorSpeed >= 0 || calibratorSpeed == -1) {
740 216 : ret->parametersSet |= VEHPARS_CALIBRATORSPEED_SET;
741 216 : ret->calibratorSpeed = calibratorSpeed;
742 : } else {
743 322 : handleVehicleError(true, ret, toString(SUMO_ATTR_SPEED) + " may not be negative");
744 : }
745 : }
746 : /*/ parse via
747 : if (attrs.hasAttribute(SUMO_ATTR_VIA)) {
748 : ret->setParameter |= VEHPARS_VIA_SET;
749 : SUMOSAXAttributes::parseStringVector(attrs.get<std::string>(SUMO_ATTR_VIA, ret->id.c_str(), ok), ret->via);
750 : }
751 : */
752 496305 : }
753 :
754 :
755 : SUMOVTypeParameter*
756 60376 : SUMOVehicleParserHelper::beginVTypeParsing(const SUMOSAXAttributes& attrs, const bool hardFail, const std::string& file) {
757 : // first obtain ID
758 60376 : std::string id = parseID(attrs, SUMO_TAG_VTYPE);
759 : // check if ID is valid
760 60376 : if (!id.empty()) {
761 : SUMOVehicleClass vClass = SVC_PASSENGER;
762 60372 : if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
763 35498 : vClass = parseVehicleClass(attrs, id);
764 : }
765 : // create vType
766 60372 : SUMOVTypeParameter* vType = new SUMOVTypeParameter(id, vClass);
767 : // parse attributes
768 60372 : if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
769 35498 : vType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
770 : }
771 60372 : if (attrs.hasAttribute(SUMO_ATTR_LENGTH)) {
772 37227 : bool ok = true;
773 37227 : const double length = attrs.get<double>(SUMO_ATTR_LENGTH, vType->id.c_str(), ok);
774 37227 : if (!ok) {
775 0 : return handleVehicleTypeError(hardFail, vType);
776 37227 : } else if (length <= 0) {
777 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_LENGTH) + " must be greater than 0");
778 : } else {
779 37227 : vType->length = length;
780 37227 : vType->parametersSet |= VTYPEPARS_LENGTH_SET;
781 : }
782 : }
783 60372 : if (attrs.hasAttribute(SUMO_ATTR_MINGAP)) {
784 35671 : bool ok = true;
785 35671 : const double minGap = attrs.get<double>(SUMO_ATTR_MINGAP, vType->id.c_str(), ok);
786 35671 : if (!ok) {
787 0 : return handleVehicleTypeError(hardFail, vType);
788 35671 : } else if (minGap < 0) {
789 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MINGAP) + " must be equal or greater than 0");
790 : } else {
791 35671 : vType->minGap = minGap;
792 35671 : vType->parametersSet |= VTYPEPARS_MINGAP_SET;
793 : }
794 : }
795 60372 : if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED)) {
796 36764 : bool ok = true;
797 36764 : const double maxSpeed = attrs.get<double>(SUMO_ATTR_MAXSPEED, vType->id.c_str(), ok);
798 36764 : if (!ok) {
799 0 : return handleVehicleTypeError(hardFail, vType);
800 36764 : } else if (maxSpeed <= 0) {
801 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MAXSPEED) + " must be greater than 0");
802 : } else {
803 36764 : vType->maxSpeed = maxSpeed;
804 36764 : vType->parametersSet |= VTYPEPARS_MAXSPEED_SET;
805 : }
806 : }
807 60372 : if (attrs.hasAttribute(SUMO_ATTR_DESIRED_MAXSPEED)) {
808 48 : bool ok = true;
809 48 : const double desiredMaxSpeed = attrs.get<double>(SUMO_ATTR_DESIRED_MAXSPEED, vType->id.c_str(), ok);
810 48 : if (!ok) {
811 0 : return handleVehicleTypeError(hardFail, vType);
812 48 : } else if (desiredMaxSpeed <= 0) {
813 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_DESIRED_MAXSPEED) + " must be greater than 0");
814 : } else {
815 48 : vType->desiredMaxSpeed = desiredMaxSpeed;
816 48 : vType->parametersSet |= VTYPEPARS_DESIRED_MAXSPEED_SET;
817 : }
818 60324 : } else if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED)) {
819 36751 : if (vClass == SVC_PEDESTRIAN) {
820 : // backward compatibility because pedestrian maxSpeed was subject to speedFactor up to 1.14.1
821 25868 : vType->desiredMaxSpeed = vType->maxSpeed;;
822 77600 : vType->maxSpeed = MAX2(vType->maxSpeed, SUMOVTypeParameter::VClassDefaultValues(vClass).maxSpeed);
823 10883 : } else if (vClass == SVC_BICYCLE) {
824 : // backward compatibility because default desired speed did not exist up to 1.14.1
825 192 : vType->desiredMaxSpeed = MAX2(vType->maxSpeed, vType->desiredMaxSpeed);
826 : }
827 : }
828 :
829 60372 : if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR)) {
830 2363 : bool ok = true;
831 2363 : vType->speedFactor.parse(attrs.get<std::string>(SUMO_ATTR_SPEEDFACTOR, vType->id.c_str(), ok), hardFail);
832 2363 : if (!ok) {
833 0 : return handleVehicleTypeError(hardFail, vType);
834 : } else {
835 2363 : vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
836 : }
837 : }
838 60372 : if (attrs.hasAttribute(SUMO_ATTR_SPEEDDEV)) {
839 2335 : bool ok = true;
840 2335 : const double speedDev = attrs.get<double>(SUMO_ATTR_SPEEDDEV, vType->id.c_str(), ok);
841 2335 : if (!ok) {
842 0 : return handleVehicleTypeError(hardFail, vType);
843 2335 : } else if (speedDev < 0) {
844 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_SPEEDDEV) + " must be equal or greater than 0");
845 : } else {
846 2335 : vType->speedFactor.getParameter()[1] = speedDev;
847 2335 : vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
848 : }
849 : }
850 : // validate speed distribution
851 60372 : const std::string& error = vType->speedFactor.isValid();
852 60372 : if (error != "") {
853 14 : return handleVehicleTypeError(hardFail, vType, "Invalid speed distribution when parsing vType '" + vType->id + "' (" + error + ")");
854 : }
855 60365 : if (attrs.hasAttribute(SUMO_ATTR_ACTIONSTEPLENGTH)) {
856 220 : bool ok = true;
857 220 : const double actionStepLengthSecs = attrs.get<double>(SUMO_ATTR_ACTIONSTEPLENGTH, vType->id.c_str(), ok);
858 220 : if (!ok) {
859 0 : return handleVehicleTypeError(hardFail, vType);
860 : } else {
861 : // processActionStepLength(...) function includes warnings
862 220 : vType->actionStepLength = processActionStepLength(actionStepLengthSecs);
863 220 : vType->parametersSet |= VTYPEPARS_ACTIONSTEPLENGTH_SET;
864 : }
865 : }
866 60365 : if (attrs.hasAttribute(SUMO_ATTR_EMISSIONCLASS)) {
867 1740 : bool ok = true;
868 1740 : const std::string parsedEmissionClass = attrs.getOpt<std::string>(SUMO_ATTR_EMISSIONCLASS, id.c_str(), ok, "");
869 : // check if emission class is correct
870 : try {
871 1740 : vType->emissionClass = PollutantsInterface::getClassByName(parsedEmissionClass);
872 1740 : vType->parametersSet |= VTYPEPARS_EMISSIONCLASS_SET;
873 0 : } catch (...) {
874 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_EMISSIONCLASS) + " with name '" + parsedEmissionClass + "' doesn't exist.");
875 0 : }
876 : }
877 60365 : if (attrs.hasAttribute(SUMO_ATTR_MASS)) {
878 233 : bool ok = true;
879 233 : const double mass = attrs.get<double>(SUMO_ATTR_MASS, vType->id.c_str(), ok);
880 233 : if (!ok) {
881 0 : return handleVehicleTypeError(hardFail, vType);
882 233 : } else if (mass < 0) {
883 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MASS) + " must be equal or greater than 0");
884 : } else {
885 233 : vType->mass = mass;
886 233 : vType->parametersSet |= VTYPEPARS_MASS_SET;
887 : }
888 : }
889 60365 : if (attrs.hasAttribute(SUMO_ATTR_IMPATIENCE)) {
890 233 : bool ok = true;
891 233 : const std::string impatienceStr = attrs.get<std::string>(SUMO_ATTR_IMPATIENCE, vType->id.c_str(), ok);
892 233 : if (!ok) {
893 0 : return handleVehicleTypeError(hardFail, vType);
894 233 : } else if (impatienceStr == "off") {
895 12 : vType->impatience = -std::numeric_limits<double>::max();
896 : } else {
897 221 : const double impatienceDouble = attrs.get<double>(SUMO_ATTR_IMPATIENCE, vType->id.c_str(), ok);
898 221 : if (!ok) {
899 0 : return handleVehicleTypeError(hardFail, vType);
900 : } else {
901 221 : vType->impatience = impatienceDouble;
902 221 : vType->parametersSet |= VTYPEPARS_IMPATIENCE_SET;
903 : }
904 : }
905 : }
906 60365 : if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
907 26733 : bool ok = true;
908 26733 : const double width = attrs.get<double>(SUMO_ATTR_WIDTH, vType->id.c_str(), ok);
909 26733 : if (!ok) {
910 0 : return handleVehicleTypeError(hardFail, vType);
911 26733 : } else if (width <= 0) {
912 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_WIDTH) + " must be greater than 0");
913 : } else {
914 26733 : vType->width = width;
915 26733 : vType->parametersSet |= VTYPEPARS_WIDTH_SET;
916 26733 : if (vClass == SVC_PEDESTRIAN
917 52840 : && OptionsCont::getOptions().exists("pedestrian.striping.stripe-width")
918 78947 : && OptionsCont::getOptions().getString("pedestrian.model") == "striping"
919 82130 : && OptionsCont::getOptions().getFloat("pedestrian.striping.stripe-width") < vType->width) {
920 12 : WRITE_WARNINGF(TL("Pedestrian vType '%' width % is larger than pedestrian.striping.stripe-width and this may cause collisions with vehicles."), id, vType->width);
921 : }
922 : }
923 : }
924 60365 : if (attrs.hasAttribute(SUMO_ATTR_HEIGHT)) {
925 359 : bool ok = true;
926 359 : const double height = attrs.get<double>(SUMO_ATTR_HEIGHT, vType->id.c_str(), ok);
927 359 : if (!ok) {
928 0 : return handleVehicleTypeError(hardFail, vType);
929 359 : } else if (height < 0) {
930 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_HEIGHT) + " must be equal or greater than 0");
931 : } else {
932 359 : vType->height = height;
933 359 : vType->parametersSet |= VTYPEPARS_HEIGHT_SET;
934 : }
935 : }
936 60365 : if (attrs.hasAttribute(SUMO_ATTR_GUISHAPE)) {
937 27142 : vType->shape = parseGuiShape(attrs, vType->id);
938 27142 : if (vType->shape != SUMOVehicleShape::UNKNOWN) {
939 27142 : vType->parametersSet |= VTYPEPARS_SHAPE_SET;
940 : }
941 : }
942 60365 : if (attrs.hasAttribute(SUMO_ATTR_OSGFILE)) {
943 21 : bool ok = true;
944 21 : const std::string osgFile = attrs.get<std::string>(SUMO_ATTR_OSGFILE, vType->id.c_str(), ok);
945 21 : if (!ok) {
946 0 : return handleVehicleTypeError(hardFail, vType);
947 : } else {
948 21 : vType->osgFile = osgFile;
949 21 : vType->parametersSet |= VTYPEPARS_OSGFILE_SET;
950 : }
951 : }
952 60365 : if (attrs.hasAttribute(SUMO_ATTR_IMGFILE)) {
953 25 : bool ok = true;
954 25 : std::string imgFile = attrs.get<std::string>(SUMO_ATTR_IMGFILE, vType->id.c_str(), ok);
955 25 : if (!ok) {
956 0 : return handleVehicleTypeError(hardFail, vType);
957 : } else {
958 : // check relative path
959 25 : if ((imgFile != "") && !FileHelpers::isAbsolute(imgFile)) {
960 46 : imgFile = FileHelpers::getConfigurationRelative(file, imgFile);
961 : }
962 25 : vType->imgFile = imgFile;
963 25 : vType->parametersSet |= VTYPEPARS_IMGFILE_SET;
964 : }
965 : }
966 60365 : if (attrs.hasAttribute(SUMO_ATTR_COLOR)) {
967 22716 : bool ok = true;
968 22716 : const RGBColor color = attrs.get<RGBColor>(SUMO_ATTR_COLOR, vType->id.c_str(), ok);
969 22716 : if (!ok) {
970 8 : return handleVehicleTypeError(hardFail, vType);
971 : } else {
972 22708 : vType->color = color;
973 22708 : vType->parametersSet |= VTYPEPARS_COLOR_SET;
974 : }
975 : } else {
976 37649 : vType->color = RGBColor::YELLOW;
977 : }
978 60357 : if (attrs.hasAttribute(SUMO_ATTR_PROB)) {
979 611 : bool ok = true;
980 611 : const double defaultProbability = attrs.get<double>(SUMO_ATTR_PROB, vType->id.c_str(), ok);
981 611 : if (!ok) {
982 0 : return handleVehicleTypeError(hardFail, vType);
983 611 : } else if (defaultProbability < 0) {
984 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_PROB) + " must be equal or greater than 0");
985 : } else {
986 611 : vType->defaultProbability = defaultProbability;
987 611 : vType->parametersSet |= VTYPEPARS_PROBABILITY_SET;
988 : }
989 : }
990 60357 : if (attrs.hasAttribute(SUMO_ATTR_LANE_CHANGE_MODEL)) {
991 477 : bool ok = true;
992 477 : std::string lcmS = attrs.get<std::string>(SUMO_ATTR_LANE_CHANGE_MODEL, vType->id.c_str(), ok);
993 477 : if (!ok) {
994 0 : return handleVehicleTypeError(hardFail, vType);
995 477 : } else if (lcmS == "JE2013") {
996 0 : WRITE_WARNING(TL("Lane change model 'JE2013' is deprecated. Using default model instead."));
997 : lcmS = "default";
998 : }
999 : if (SUMOXMLDefinitions::LaneChangeModels.hasString(lcmS)) {
1000 472 : vType->lcModel = SUMOXMLDefinitions::LaneChangeModels.get(lcmS);
1001 472 : vType->parametersSet |= VTYPEPARS_LANE_CHANGE_MODEL_SET;
1002 : } else {
1003 15 : return handleVehicleTypeError(hardFail, vType, "Unknown lane change model '" + lcmS + "' when parsing vType '" + vType->id + "'");
1004 : }
1005 : }
1006 60352 : if (attrs.hasAttribute(SUMO_ATTR_CAR_FOLLOW_MODEL)) {
1007 1235 : bool ok = true;
1008 1235 : const std::string cfmValue = attrs.get<std::string>(SUMO_ATTR_CAR_FOLLOW_MODEL, vType->id.c_str(), ok);
1009 1235 : if (!ok) {
1010 0 : return handleVehicleTypeError(hardFail, vType);
1011 : } else if (SUMOXMLDefinitions::CarFollowModels.hasString(cfmValue)) {
1012 1229 : vType->cfModel = SUMOXMLDefinitions::CarFollowModels.get(cfmValue);
1013 1229 : vType->parametersSet |= VTYPEPARS_CAR_FOLLOW_MODEL;
1014 : } else {
1015 18 : return handleVehicleTypeError(hardFail, vType, "Unknown car following model '" + cfmValue + "' when parsing vType '" + vType->id + "'");
1016 : }
1017 : }
1018 60346 : if (attrs.hasAttribute(SUMO_ATTR_PERSON_CAPACITY)) {
1019 345 : bool ok = true;
1020 345 : const int personCapacity = attrs.get<int>(SUMO_ATTR_PERSON_CAPACITY, vType->id.c_str(), ok);
1021 345 : if (!ok) {
1022 0 : return handleVehicleTypeError(hardFail, vType);
1023 345 : } else if (personCapacity < 0) {
1024 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_PERSON_CAPACITY) + " must be equal or greater than 0");
1025 : } else {
1026 345 : vType->personCapacity = personCapacity;
1027 345 : vType->parametersSet |= VTYPEPARS_PERSON_CAPACITY;
1028 : }
1029 : }
1030 60346 : if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_CAPACITY)) {
1031 346 : bool ok = true;
1032 346 : const int containerCapacity = attrs.get<int>(SUMO_ATTR_CONTAINER_CAPACITY, vType->id.c_str(), ok);
1033 346 : if (!ok) {
1034 0 : return handleVehicleTypeError(hardFail, vType);
1035 346 : } else if (containerCapacity < 0) {
1036 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_CONTAINER_CAPACITY) + " must be equal or greater than 0");
1037 : } else {
1038 346 : vType->containerCapacity = containerCapacity;
1039 346 : vType->parametersSet |= VTYPEPARS_CONTAINER_CAPACITY;
1040 : }
1041 : }
1042 60346 : if (attrs.hasAttribute(SUMO_ATTR_BOARDING_DURATION)) {
1043 101 : bool ok = true;
1044 101 : const SUMOTime boardingDuration = attrs.getSUMOTimeReporting(SUMO_ATTR_BOARDING_DURATION, vType->id.c_str(), ok);
1045 101 : if (!ok) {
1046 0 : return handleVehicleTypeError(hardFail, vType);
1047 101 : } else if (boardingDuration < 0) {
1048 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_BOARDING_DURATION) + " must be equal or greater than 0");
1049 : } else {
1050 101 : vType->boardingDuration = boardingDuration;
1051 101 : vType->parametersSet |= VTYPEPARS_BOARDING_DURATION;
1052 : }
1053 : }
1054 60346 : if (attrs.hasAttribute(SUMO_ATTR_LOADING_DURATION)) {
1055 49 : bool ok = true;
1056 49 : const SUMOTime loadingDuration = attrs.getSUMOTimeReporting(SUMO_ATTR_LOADING_DURATION, vType->id.c_str(), ok);
1057 49 : if (!ok) {
1058 0 : return handleVehicleTypeError(hardFail, vType);
1059 49 : } else if (loadingDuration < 0) {
1060 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_LOADING_DURATION) + " must be equal or greater than 0");
1061 : } else {
1062 49 : vType->loadingDuration = loadingDuration;
1063 49 : vType->parametersSet |= VTYPEPARS_LOADING_DURATION;
1064 : }
1065 : }
1066 60346 : if (attrs.hasAttribute(SUMO_ATTR_SCALE)) {
1067 32 : bool ok = true;
1068 32 : const double scale = attrs.get<double>(SUMO_ATTR_SCALE, id.c_str(), ok);
1069 32 : if (!ok) {
1070 0 : return handleVehicleTypeError(hardFail, vType);
1071 32 : } else if (scale < 0) {
1072 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_SCALE) + " may be not be negative");
1073 : } else {
1074 32 : vType->scale = scale;
1075 32 : vType->parametersSet |= VTYPEPARS_SCALE_SET;
1076 : }
1077 : }
1078 60346 : if (attrs.hasAttribute(SUMO_ATTR_TIME_TO_TELEPORT)) {
1079 13 : bool ok = true;
1080 13 : const SUMOTime ttt = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME_TO_TELEPORT, vType->id.c_str(), ok);
1081 13 : if (!ok) {
1082 0 : return handleVehicleTypeError(hardFail, vType);
1083 : } else {
1084 13 : vType->timeToTeleport = ttt;
1085 13 : vType->parametersSet |= VTYPEPARS_TTT_SET;
1086 : }
1087 : }
1088 60346 : if (attrs.hasAttribute(SUMO_ATTR_TIME_TO_TELEPORT_BIDI)) {
1089 5 : bool ok = true;
1090 5 : const SUMOTime tttb = attrs.getSUMOTimeReporting(SUMO_ATTR_TIME_TO_TELEPORT_BIDI, vType->id.c_str(), ok);
1091 5 : if (!ok) {
1092 0 : return handleVehicleTypeError(hardFail, vType);
1093 : } else {
1094 5 : vType->timeToTeleportBidi = tttb;
1095 5 : vType->parametersSet |= VTYPEPARS_TTT_BIDI_SET;
1096 : }
1097 : }
1098 60346 : if (attrs.hasAttribute(SUMO_ATTR_SPEEDFACTOR_PREMATURE)) {
1099 63 : bool ok = true;
1100 63 : const double sfp = attrs.get<double>(SUMO_ATTR_SPEEDFACTOR_PREMATURE, id.c_str(), ok);
1101 63 : if (!ok) {
1102 0 : return handleVehicleTypeError(hardFail, vType);
1103 : } else {
1104 63 : vType->speedFactorPremature = sfp;
1105 63 : vType->parametersSet |= VTYPEPARS_SPEEDFACTOR_PREMATURE_SET;
1106 : }
1107 : }
1108 60346 : if (attrs.hasAttribute(SUMO_ATTR_BOARDING_FACTOR)) {
1109 8 : bool ok = true;
1110 8 : const double bf = attrs.get<double>(SUMO_ATTR_BOARDING_FACTOR, id.c_str(), ok);
1111 8 : if (!ok) {
1112 0 : return handleVehicleTypeError(hardFail, vType);
1113 8 : } else if (bf < 0) {
1114 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_BOARDING_FACTOR) + " must be equal or greater than 0");
1115 : } else {
1116 8 : vType->boardingFactor = bf;
1117 8 : vType->parametersSet |= VTYPEPARS_BOARDING_FACTOR_SET;
1118 : }
1119 : }
1120 60346 : if (attrs.hasAttribute(SUMO_ATTR_MAXSPEED_LAT)) {
1121 73 : bool ok = true;
1122 73 : const double maxSpeedLat = attrs.get<double>(SUMO_ATTR_MAXSPEED_LAT, vType->id.c_str(), ok);
1123 73 : if (!ok) {
1124 0 : return handleVehicleTypeError(hardFail, vType);
1125 73 : } else if (maxSpeedLat <= 0) {
1126 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MAXSPEED_LAT) + " must be greater than 0");
1127 : } else {
1128 73 : vType->maxSpeedLat = maxSpeedLat;
1129 73 : vType->parametersSet |= VTYPEPARS_MAXSPEED_LAT_SET;
1130 : }
1131 : }
1132 60346 : if (attrs.hasAttribute(SUMO_ATTR_MINGAP_LAT)) {
1133 577 : bool ok = true;
1134 577 : const double minGapLat = attrs.get<double>(SUMO_ATTR_MINGAP_LAT, vType->id.c_str(), ok);
1135 577 : if (!ok) {
1136 0 : return handleVehicleTypeError(hardFail, vType);
1137 577 : } else if (minGapLat < 0) {
1138 0 : return handleVehicleTypeError(hardFail, vType, toString(SUMO_ATTR_MINGAP_LAT) + " must be equal or greater than 0");
1139 : } else {
1140 577 : vType->minGapLat = minGapLat;
1141 577 : vType->parametersSet |= VTYPEPARS_MINGAP_LAT_SET;
1142 : }
1143 : }
1144 60346 : if (attrs.hasAttribute(SUMO_ATTR_LATALIGNMENT)) {
1145 1704 : bool ok = true;
1146 1704 : const std::string alignS = attrs.get<std::string>(SUMO_ATTR_LATALIGNMENT, vType->id.c_str(), ok);
1147 1704 : if (!ok) {
1148 0 : return handleVehicleTypeError(hardFail, vType);
1149 : } else {
1150 : double lao;
1151 : LatAlignmentDefinition lad;
1152 1704 : if (SUMOVTypeParameter::parseLatAlignment(alignS, lao, lad)) {
1153 1704 : vType->latAlignmentOffset = lao;
1154 1704 : vType->latAlignmentProcedure = lad;
1155 1704 : vType->parametersSet |= VTYPEPARS_LATALIGNMENT_SET;
1156 : } else {
1157 0 : return handleVehicleTypeError(hardFail, vType, "Unknown lateral alignment '" + alignS + "' when parsing vType '" + vType->id + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
1158 : }
1159 : }
1160 : }
1161 60346 : if (attrs.hasAttribute(SUMO_ATTR_MANEUVER_ANGLE_TIMES)) {
1162 5 : bool ok = true;
1163 5 : const std::string angleTimesS = attrs.get<std::string>(SUMO_ATTR_MANEUVER_ANGLE_TIMES, vType->id.c_str(), ok);
1164 5 : if (!ok) {
1165 0 : return handleVehicleTypeError(hardFail, vType);
1166 10 : } else if (parseAngleTimesMap(vType, angleTimesS)) {
1167 5 : vType->parametersSet |= VTYPEPARS_MANEUVER_ANGLE_TIMES_SET;
1168 : } else {
1169 0 : return handleVehicleTypeError(hardFail, vType, "Invalid manoeuver angle times map for vType '" + vType->id + "'");
1170 : }
1171 : }
1172 60346 : if (attrs.hasAttribute(SUMO_ATTR_PARKING_BADGES)) {
1173 7 : bool ok = true;
1174 7 : std::vector<std::string> badges = attrs.get<std::vector<std::string>>(SUMO_ATTR_PARKING_BADGES, vType->id.c_str(), ok);
1175 7 : if (!ok) {
1176 0 : return handleVehicleTypeError(hardFail, vType);
1177 : } else {
1178 7 : vType->parametersSet |= VTYPEPARS_PARKING_BADGES_SET;
1179 7 : vType->parkingBadges = badges;
1180 : }
1181 7 : }
1182 : // try to parse Car Following Model params
1183 60346 : if (!parseCFMParams(vType, vType->cfModel, attrs, false)) {
1184 0 : return handleVehicleTypeError(hardFail, vType, "Invalid parsing embedded VType");
1185 : }
1186 : // try to parse Lane Change Model params
1187 60346 : if (!parseLCParams(vType, vType->lcModel, attrs)) {
1188 0 : return handleVehicleTypeError(hardFail, vType, "Invalid Lane Change Model Parameters");
1189 : }
1190 : // try to Junction Model params
1191 60346 : if (!parseJMParams(vType, attrs)) {
1192 26 : return handleVehicleTypeError(hardFail, vType, "Invalid Junction Model Parameters");
1193 : }
1194 : // all ok, then return vType
1195 : return vType;
1196 : } else {
1197 34 : return handleVehicleTypeError(hardFail, nullptr, "VType cannot be created");
1198 : }
1199 : }
1200 :
1201 :
1202 : bool
1203 5 : SUMOVehicleParserHelper::parseAngleTimesMap(SUMOVTypeParameter* vtype, const std::string atm) {
1204 15 : StringTokenizer st(atm, ",");
1205 : std::map<int, std::pair<SUMOTime, SUMOTime>> angleTimesMap;
1206 : int tripletCount = 0;
1207 30 : while (st.hasNext()) {
1208 25 : StringTokenizer pos(st.next());
1209 25 : if (pos.size() != 3) {
1210 0 : WRITE_ERRORF(TL("maneuverAngleTimes format for vType '%' % contains an invalid triplet."), vtype->id, atm);
1211 0 : return false;
1212 : } else {
1213 : try {
1214 25 : const int angle = StringUtils::toInt(pos.next());
1215 25 : const SUMOTime t1 = string2time(pos.next());
1216 25 : const SUMOTime t2 = string2time(pos.next());
1217 25 : angleTimesMap[angle] = std::make_pair(t1, t2);
1218 0 : } catch (...) {
1219 0 : WRITE_ERRORF(TL("Triplet '%' for vType '%' maneuverAngleTimes cannot be parsed as 'int double double'"), st.get(tripletCount), vtype->id);
1220 : return false;
1221 0 : }
1222 25 : tripletCount++;
1223 : }
1224 25 : }
1225 5 : if (angleTimesMap.size() > 0) {
1226 : vtype->myManoeuverAngleTimes.clear();
1227 30 : for (const auto& angleTime : angleTimesMap) {
1228 : vtype->myManoeuverAngleTimes.insert(angleTime);
1229 : }
1230 : angleTimesMap.clear();
1231 5 : return true;
1232 : } else {
1233 : return false;
1234 : }
1235 5 : }
1236 :
1237 :
1238 : bool
1239 60362 : SUMOVehicleParserHelper::parseCFMParams(SUMOVTypeParameter* into, const SumoXMLTag element, const SUMOSAXAttributes& attrs, const bool nestedCFM) {
1240 60362 : const CFAttrMap& allowedCFM = getAllowedCFModelAttrs();
1241 : CFAttrMap::const_iterator cf_it = allowedCFM.find(element);
1242 : // check if given CFM is allowed
1243 60362 : if (cf_it == allowedCFM.end()) {
1244 0 : if (SUMOXMLDefinitions::Tags.has((int)element)) {
1245 0 : WRITE_ERRORF(TL("Unknown car-following model % when parsing vType '%'"), toString(element), into->id);
1246 : } else {
1247 0 : WRITE_ERRORF(TL("Unknown car-following model when parsing vType '%'"), into->id);
1248 : }
1249 0 : return false;
1250 : }
1251 : // check if we're parsing a nested CFM
1252 60362 : if (nestedCFM) {
1253 16 : into->cfModel = cf_it->first;
1254 16 : into->parametersSet |= VTYPEPARS_CAR_FOLLOW_MODEL;
1255 : }
1256 : // set CFM values
1257 612297 : for (const auto& it : cf_it->second) {
1258 551935 : if (attrs.hasAttribute(it)) {
1259 : // first obtain CFM attribute in string format
1260 44520 : bool ok = true;
1261 44520 : std::string parsedCFMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1262 : // check CFM Attribute
1263 44520 : if (!ok) {
1264 : return false;
1265 44520 : } else if (it == SUMO_ATTR_TRAIN_TYPE) {
1266 : // check if train value is valid
1267 223 : if (!SUMOXMLDefinitions::TrainTypes.hasString(parsedCFMAttribute)) {
1268 0 : WRITE_ERROR("Invalid train type '" + parsedCFMAttribute + "' used in Car-Following-Attribute " + toString(it));
1269 0 : return false;
1270 : }
1271 : // add parsedCFMAttribute to cfParameter
1272 223 : into->cfParameter[it] = parsedCFMAttribute;
1273 44297 : } else if (it == SUMO_ATTR_SPEED_TABLE || it == SUMO_ATTR_TRACTION_TABLE || it == SUMO_ATTR_RESISTANCE_TABLE) {
1274 24 : into->cfParameter[it] = parsedCFMAttribute;
1275 44273 : } else if (it == SUMO_ATTR_CF_IDM_STEPPING) {
1276 : // declare a int in wich save CFM int attribute
1277 : double CFMDoubleAttribute = -1;
1278 : try {
1279 : // obtain CFM attribute in int format
1280 2 : CFMDoubleAttribute = StringUtils::toDouble(parsedCFMAttribute);
1281 0 : } catch (...) {
1282 0 : WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Cannot be parsed to float"), toString(it));
1283 : return false;
1284 0 : }
1285 2 : if (CFMDoubleAttribute <= 0) {
1286 0 : WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Must be greater than 0"), toString(it));
1287 0 : return false;
1288 : }
1289 : // add parsedCFMAttribute to cfParameter
1290 2 : into->cfParameter[it] = parsedCFMAttribute;
1291 : } else {
1292 : // declare a double in wich save CFM float attribute
1293 : double CFMDoubleAttribute = -1;
1294 : try {
1295 : // obtain CFM attribute in double format
1296 44271 : CFMDoubleAttribute = StringUtils::toDouble(parsedCFMAttribute);
1297 0 : } catch (...) {
1298 0 : WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Cannot be parsed to float"), toString(it));
1299 : return false;
1300 0 : }
1301 : // check attributes of type "positiveFloatType" (> 0)
1302 44271 : switch (it) {
1303 20723 : case SUMO_ATTR_ACCEL:
1304 : case SUMO_ATTR_DECEL:
1305 : case SUMO_ATTR_APPARENTDECEL:
1306 : case SUMO_ATTR_EMERGENCYDECEL:
1307 : case SUMO_ATTR_TAU:
1308 20723 : if (CFMDoubleAttribute <= 0) {
1309 0 : WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Must be greater than 0"), toString(it));
1310 0 : return false;
1311 : }
1312 : break;
1313 : default:
1314 : break;
1315 : }
1316 : // check attributes restricted to [0-1]
1317 44271 : switch (it) {
1318 22945 : case SUMO_ATTR_SIGMA:
1319 22945 : if ((CFMDoubleAttribute < 0) || (CFMDoubleAttribute > 1)) {
1320 0 : WRITE_ERRORF(TL("Invalid Car-Following-Model Attribute %. Only values between [0-1] are allowed"), toString(it));
1321 0 : return false;
1322 : }
1323 : break;
1324 : default:
1325 : break;
1326 : }
1327 : // add parsedCFMAttribute to cfParameter
1328 44271 : into->cfParameter[it] = parsedCFMAttribute;
1329 : }
1330 : }
1331 : }
1332 : // all CFM successfully parsed, then return true
1333 : return true;
1334 : }
1335 :
1336 :
1337 : const SUMOVehicleParserHelper::CFAttrMap&
1338 60362 : SUMOVehicleParserHelper::getAllowedCFModelAttrs() {
1339 : // init on first use
1340 60362 : if (allowedCFModelAttrs.size() == 0) {
1341 : std::set<SumoXMLAttr> genericParams;
1342 24504 : genericParams.insert(SUMO_ATTR_TAU);
1343 24504 : genericParams.insert(SUMO_ATTR_ACCEL);
1344 24504 : genericParams.insert(SUMO_ATTR_DECEL);
1345 24504 : genericParams.insert(SUMO_ATTR_APPARENTDECEL);
1346 24504 : genericParams.insert(SUMO_ATTR_EMERGENCYDECEL);
1347 24504 : genericParams.insert(SUMO_ATTR_COLLISION_MINGAP_FACTOR);
1348 24504 : genericParams.insert(SUMO_ATTR_STARTUP_DELAY);
1349 : // Krauss
1350 : std::set<SumoXMLAttr> kraussParams(genericParams);
1351 24504 : kraussParams.insert(SUMO_ATTR_SIGMA);
1352 24504 : kraussParams.insert(SUMO_ATTR_SIGMA_STEP);
1353 24504 : allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS] = kraussParams;
1354 24504 : allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS_ORIG1] = kraussParams;
1355 49008 : allowedCFModelAttrs[SUMO_TAG_CF_KRAUSS_PLUS_SLOPE] = kraussParams;
1356 : std::set<SumoXMLAttr> allParams(kraussParams);
1357 : // KraussX
1358 : std::set<SumoXMLAttr> kraussXParams(kraussParams);
1359 24504 : kraussXParams.insert(SUMO_ATTR_TMP1);
1360 24504 : kraussXParams.insert(SUMO_ATTR_TMP2);
1361 24504 : kraussXParams.insert(SUMO_ATTR_TMP3);
1362 24504 : kraussXParams.insert(SUMO_ATTR_TMP4);
1363 24504 : kraussXParams.insert(SUMO_ATTR_TMP5);
1364 49008 : allowedCFModelAttrs[SUMO_TAG_CF_KRAUSSX] = kraussXParams;
1365 24504 : allParams.insert(kraussXParams.begin(), kraussXParams.end());
1366 : // SmartSK
1367 : std::set<SumoXMLAttr> smartSKParams(genericParams);
1368 24504 : smartSKParams.insert(SUMO_ATTR_SIGMA);
1369 24504 : smartSKParams.insert(SUMO_ATTR_TMP1);
1370 24504 : smartSKParams.insert(SUMO_ATTR_TMP2);
1371 24504 : smartSKParams.insert(SUMO_ATTR_TMP3);
1372 24504 : smartSKParams.insert(SUMO_ATTR_TMP4);
1373 24504 : smartSKParams.insert(SUMO_ATTR_TMP5);
1374 49008 : allowedCFModelAttrs[SUMO_TAG_CF_SMART_SK] = smartSKParams;
1375 24504 : allParams.insert(smartSKParams.begin(), smartSKParams.end());
1376 : // Daniel
1377 : std::set<SumoXMLAttr> daniel1Params(genericParams);
1378 24504 : daniel1Params.insert(SUMO_ATTR_SIGMA);
1379 24504 : daniel1Params.insert(SUMO_ATTR_TMP1);
1380 24504 : daniel1Params.insert(SUMO_ATTR_TMP2);
1381 24504 : daniel1Params.insert(SUMO_ATTR_TMP3);
1382 24504 : daniel1Params.insert(SUMO_ATTR_TMP4);
1383 24504 : daniel1Params.insert(SUMO_ATTR_TMP5);
1384 49008 : allowedCFModelAttrs[SUMO_TAG_CF_DANIEL1] = daniel1Params;
1385 24504 : allParams.insert(daniel1Params.begin(), daniel1Params.end());
1386 : // Peter Wagner
1387 : std::set<SumoXMLAttr> pwagParams(genericParams);
1388 24504 : pwagParams.insert(SUMO_ATTR_SIGMA);
1389 24504 : pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_TAULAST);
1390 24504 : pwagParams.insert(SUMO_ATTR_CF_PWAGNER2009_APPROB);
1391 49008 : allowedCFModelAttrs[SUMO_TAG_CF_PWAGNER2009] = pwagParams;
1392 24504 : allParams.insert(pwagParams.begin(), pwagParams.end());
1393 : // IDM params
1394 : std::set<SumoXMLAttr> idmParams(genericParams);
1395 24504 : idmParams.insert(SUMO_ATTR_CF_IDM_DELTA);
1396 24504 : idmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1397 49008 : allowedCFModelAttrs[SUMO_TAG_CF_IDM] = idmParams;
1398 24504 : allParams.insert(idmParams.begin(), idmParams.end());
1399 : // EIDM
1400 : std::set<SumoXMLAttr> eidmParams(genericParams);
1401 24504 : eidmParams.insert(SUMO_ATTR_CF_IDM_DELTA);
1402 24504 : eidmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1403 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_T_LOOK_AHEAD);
1404 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_T_PERSISTENCE_DRIVE);
1405 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_T_REACTION);
1406 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_T_PERSISTENCE_ESTIMATE);
1407 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_C_COOLNESS);
1408 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_LEADER);
1409 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_GAP);
1410 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_SIG_ERROR);
1411 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_JERK_MAX);
1412 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_EPSILON_ACC);
1413 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_T_ACC_MAX);
1414 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_M_FLATNESS);
1415 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_M_BEGIN);
1416 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_USEVEHDYNAMICS);
1417 24504 : eidmParams.insert(SUMO_ATTR_CF_EIDM_MAX_VEH_PREVIEW);
1418 49008 : allowedCFModelAttrs[SUMO_TAG_CF_EIDM] = eidmParams;
1419 24504 : allParams.insert(eidmParams.begin(), eidmParams.end());
1420 : // IDMM
1421 : std::set<SumoXMLAttr> idmmParams(genericParams);
1422 24504 : idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_FACTOR);
1423 24504 : idmmParams.insert(SUMO_ATTR_CF_IDMM_ADAPT_TIME);
1424 24504 : idmmParams.insert(SUMO_ATTR_CF_IDM_STEPPING);
1425 49008 : allowedCFModelAttrs[SUMO_TAG_CF_IDMM] = idmmParams;
1426 24504 : allParams.insert(idmmParams.begin(), idmmParams.end());
1427 : // Bieker
1428 : std::set<SumoXMLAttr> bkernerParams(genericParams);
1429 24504 : bkernerParams.insert(SUMO_ATTR_K);
1430 24504 : bkernerParams.insert(SUMO_ATTR_CF_KERNER_PHI);
1431 49008 : allowedCFModelAttrs[SUMO_TAG_CF_BKERNER] = bkernerParams;
1432 24504 : allParams.insert(bkernerParams.begin(), bkernerParams.end());
1433 : // Wiedemann
1434 : std::set<SumoXMLAttr> wiedemannParams(genericParams);
1435 24504 : wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_SECURITY);
1436 24504 : wiedemannParams.insert(SUMO_ATTR_CF_WIEDEMANN_ESTIMATION);
1437 49008 : allowedCFModelAttrs[SUMO_TAG_CF_WIEDEMANN] = wiedemannParams;
1438 24504 : allParams.insert(wiedemannParams.begin(), wiedemannParams.end());
1439 : // W99
1440 : std::set<SumoXMLAttr> w99Params(genericParams);
1441 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC1);
1442 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC2);
1443 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC3);
1444 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC4);
1445 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC5);
1446 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC6);
1447 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC7);
1448 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC8);
1449 24504 : w99Params.insert(SUMO_ATTR_CF_W99_CC9);
1450 49008 : allowedCFModelAttrs[SUMO_TAG_CF_W99] = w99Params;
1451 24504 : allParams.insert(w99Params.begin(), w99Params.end());
1452 : // Rail
1453 : std::set<SumoXMLAttr> railParams(genericParams);
1454 24504 : railParams.insert(SUMO_ATTR_TRAIN_TYPE);
1455 24504 : railParams.insert(SUMO_ATTR_SPEED_TABLE);
1456 24504 : railParams.insert(SUMO_ATTR_TRACTION_TABLE);
1457 24504 : railParams.insert(SUMO_ATTR_RESISTANCE_TABLE);
1458 24504 : railParams.insert(SUMO_ATTR_MASSFACTOR);
1459 24504 : railParams.insert(SUMO_ATTR_MAXPOWER);
1460 24504 : railParams.insert(SUMO_ATTR_MAXTRACTION);
1461 24504 : railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_CONSTANT);
1462 24504 : railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_LINEAR);
1463 24504 : railParams.insert(SUMO_ATTR_RESISTANCE_COEFFICIENT_QUADRATIC);
1464 49008 : allowedCFModelAttrs[SUMO_TAG_CF_RAIL] = railParams;
1465 24504 : allParams.insert(railParams.begin(), railParams.end());
1466 : // ACC
1467 : std::set<SumoXMLAttr> ACCParams(genericParams);
1468 24504 : ACCParams.insert(SUMO_ATTR_SC_GAIN);
1469 24504 : ACCParams.insert(SUMO_ATTR_GCC_GAIN_SPEED);
1470 24504 : ACCParams.insert(SUMO_ATTR_GCC_GAIN_SPACE);
1471 24504 : ACCParams.insert(SUMO_ATTR_GC_GAIN_SPEED);
1472 24504 : ACCParams.insert(SUMO_ATTR_GC_GAIN_SPACE);
1473 24504 : ACCParams.insert(SUMO_ATTR_CA_GAIN_SPEED);
1474 24504 : ACCParams.insert(SUMO_ATTR_CA_GAIN_SPACE);
1475 24504 : ACCParams.insert(SUMO_ATTR_CA_OVERRIDE);
1476 24504 : ACCParams.insert(SUMO_ATTR_APPLYDRIVERSTATE);
1477 49008 : allowedCFModelAttrs[SUMO_TAG_CF_ACC] = ACCParams;
1478 24504 : allParams.insert(ACCParams.begin(), ACCParams.end());
1479 : // CACC
1480 : std::set<SumoXMLAttr> CACCParams(genericParams);
1481 24504 : CACCParams.insert(SUMO_ATTR_SC_GAIN_CACC);
1482 24504 : CACCParams.insert(SUMO_ATTR_GCC_GAIN_GAP_CACC);
1483 24504 : CACCParams.insert(SUMO_ATTR_GCC_GAIN_GAP_DOT_CACC);
1484 24504 : CACCParams.insert(SUMO_ATTR_GC_GAIN_GAP_CACC);
1485 24504 : CACCParams.insert(SUMO_ATTR_GC_GAIN_GAP_DOT_CACC);
1486 24504 : CACCParams.insert(SUMO_ATTR_CA_GAIN_GAP_CACC);
1487 24504 : CACCParams.insert(SUMO_ATTR_CA_GAIN_GAP_DOT_CACC);
1488 24504 : CACCParams.insert(SUMO_ATTR_GCC_GAIN_SPEED);
1489 24504 : CACCParams.insert(SUMO_ATTR_GCC_GAIN_SPACE);
1490 24504 : CACCParams.insert(SUMO_ATTR_GC_GAIN_SPEED);
1491 24504 : CACCParams.insert(SUMO_ATTR_GC_GAIN_SPACE);
1492 24504 : CACCParams.insert(SUMO_ATTR_CA_GAIN_SPEED);
1493 24504 : CACCParams.insert(SUMO_ATTR_CA_GAIN_SPACE);
1494 24504 : CACCParams.insert(SUMO_ATTR_CA_OVERRIDE);
1495 24504 : CACCParams.insert(SUMO_ATTR_HEADWAY_TIME_CACC_TO_ACC);
1496 24504 : CACCParams.insert(SUMO_ATTR_APPLYDRIVERSTATE);
1497 24504 : CACCParams.insert(SUMO_ATTR_SC_MIN_GAP);
1498 49008 : allowedCFModelAttrs[SUMO_TAG_CF_CACC] = CACCParams;
1499 24504 : allParams.insert(CACCParams.begin(), CACCParams.end());
1500 : // CC
1501 : std::set<SumoXMLAttr> ccParams(genericParams);
1502 24504 : ccParams.insert(SUMO_ATTR_CF_CC_C1);
1503 24504 : ccParams.insert(SUMO_ATTR_CF_CC_CCDECEL);
1504 24504 : ccParams.insert(SUMO_ATTR_CF_CC_CONSTSPACING);
1505 24504 : ccParams.insert(SUMO_ATTR_CF_CC_KP);
1506 24504 : ccParams.insert(SUMO_ATTR_CF_CC_LAMBDA);
1507 24504 : ccParams.insert(SUMO_ATTR_CF_CC_OMEGAN);
1508 24504 : ccParams.insert(SUMO_ATTR_CF_CC_TAU);
1509 24504 : ccParams.insert(SUMO_ATTR_CF_CC_XI);
1510 24504 : ccParams.insert(SUMO_ATTR_CF_CC_LANES_COUNT);
1511 24504 : ccParams.insert(SUMO_ATTR_CF_CC_CCACCEL);
1512 24504 : ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_KP);
1513 24504 : ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_KD);
1514 24504 : ccParams.insert(SUMO_ATTR_CF_CC_PLOEG_H);
1515 24504 : ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KA);
1516 24504 : ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KV);
1517 24504 : ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_KP);
1518 24504 : ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_D);
1519 24504 : ccParams.insert(SUMO_ATTR_CF_CC_FLATBED_H);
1520 49008 : allowedCFModelAttrs[SUMO_TAG_CF_CC] = ccParams;
1521 24504 : allParams.insert(ccParams.begin(), ccParams.end());
1522 : // last element
1523 49008 : allowedCFModelAttrs[SUMO_TAG_NOTHING] = allParams;
1524 : }
1525 60362 : return allowedCFModelAttrs;
1526 : }
1527 :
1528 :
1529 : bool
1530 60346 : SUMOVehicleParserHelper::parseLCParams(SUMOVTypeParameter* into, LaneChangeModel model, const SUMOSAXAttributes& attrs) {
1531 60346 : if (allowedLCModelAttrs.size() == 0) {
1532 : // lc2013
1533 : std::set<SumoXMLAttr> lc2013Params;
1534 24504 : lc2013Params.insert(SUMO_ATTR_LCA_STRATEGIC_PARAM);
1535 24504 : lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_PARAM);
1536 24504 : lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_PARAM);
1537 24504 : lc2013Params.insert(SUMO_ATTR_LCA_KEEPRIGHT_PARAM);
1538 24504 : lc2013Params.insert(SUMO_ATTR_LCA_OPPOSITE_PARAM);
1539 24504 : lc2013Params.insert(SUMO_ATTR_LCA_LOOKAHEADLEFT);
1540 24504 : lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAINRIGHT);
1541 24504 : lc2013Params.insert(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING);
1542 24504 : lc2013Params.insert(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR);
1543 24504 : lc2013Params.insert(SUMO_ATTR_LCA_MAXDISTLATSTANDING);
1544 24504 : lc2013Params.insert(SUMO_ATTR_LCA_ASSERTIVE);
1545 24504 : lc2013Params.insert(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD);
1546 24504 : lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT);
1547 24504 : lc2013Params.insert(SUMO_ATTR_LCA_COOPERATIVE_SPEED);
1548 24504 : lc2013Params.insert(SUMO_ATTR_LCA_OVERTAKE_RIGHT);
1549 24504 : lc2013Params.insert(SUMO_ATTR_LCA_SIGMA);
1550 24504 : lc2013Params.insert(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME);
1551 24504 : lc2013Params.insert(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR);
1552 24504 : lc2013Params.insert(SUMO_ATTR_LCA_CONTRIGHT);
1553 24504 : lc2013Params.insert(SUMO_ATTR_LCA_EXPERIMENTAL1);
1554 49008 : allowedLCModelAttrs[LaneChangeModel::LC2013] = lc2013Params;
1555 : // sl2015 (extension of lc2013)
1556 : std::set<SumoXMLAttr> sl2015Params = lc2013Params;
1557 24504 : sl2015Params.insert(SUMO_ATTR_LCA_PUSHY);
1558 24504 : sl2015Params.insert(SUMO_ATTR_LCA_PUSHYGAP);
1559 24504 : sl2015Params.insert(SUMO_ATTR_LCA_SUBLANE_PARAM);
1560 24504 : sl2015Params.insert(SUMO_ATTR_LCA_IMPATIENCE);
1561 24504 : sl2015Params.insert(SUMO_ATTR_LCA_TIME_TO_IMPATIENCE);
1562 24504 : sl2015Params.insert(SUMO_ATTR_LCA_ACCEL_LAT);
1563 24504 : sl2015Params.insert(SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE);
1564 24504 : sl2015Params.insert(SUMO_ATTR_LCA_LANE_DISCIPLINE);
1565 49008 : allowedLCModelAttrs[LaneChangeModel::SL2015] = sl2015Params;
1566 : // DK2008
1567 : std::set<SumoXMLAttr> noParams;
1568 24504 : allowedLCModelAttrs[LaneChangeModel::DK2008] = noParams;
1569 : // default model may be either LC2013 or SL2015
1570 : // we allow both sets (sl2015 is a superset of lc2013Params)
1571 49008 : allowedLCModelAttrs[LaneChangeModel::DEFAULT] = sl2015Params;
1572 : }
1573 60346 : std::set<SumoXMLAttr> allowed = allowedLCModelAttrs[model];
1574 : // iterate over LCM attributes
1575 1749262 : for (const auto& it : allowed) {
1576 1688916 : if (attrs.hasAttribute(it)) {
1577 : // first obtain CFM attribute in string format
1578 4005 : bool ok = true;
1579 4005 : std::string parsedLCMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1580 4005 : if (!ok) {
1581 : return false;
1582 : }
1583 : // declare a double in wich save CFM attribute
1584 : double LCMAttribute = -1;
1585 : try {
1586 : // obtain CFM attribute in double format
1587 4005 : LCMAttribute = StringUtils::toDouble(parsedLCMAttribute);
1588 0 : } catch (...) {
1589 0 : WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Cannot be parsed to float"), toString(it));
1590 : return false;
1591 0 : }
1592 : // check attributes of type "nonNegativeFloatType" (>= 0)
1593 4005 : switch (it) {
1594 1433 : case SUMO_ATTR_LCA_PUSHYGAP:
1595 : case SUMO_ATTR_LCA_MAXSPEEDLATSTANDING:
1596 : case SUMO_ATTR_LCA_IMPATIENCE:
1597 : case SUMO_ATTR_LCA_OVERTAKE_RIGHT:
1598 : case SUMO_ATTR_LCA_ASSERTIVE:
1599 : case SUMO_ATTR_LCA_LOOKAHEADLEFT:
1600 : case SUMO_ATTR_LCA_SPEEDGAINRIGHT:
1601 : case SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE:
1602 : case SUMO_ATTR_LCA_TIME_TO_IMPATIENCE:
1603 : case SUMO_ATTR_LCA_LANE_DISCIPLINE:
1604 : case SUMO_ATTR_LCA_SIGMA:
1605 1433 : if (LCMAttribute < 0) {
1606 0 : WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be equal or greater than 0"), toString(it));
1607 0 : return false;
1608 : }
1609 : break;
1610 : default:
1611 : break;
1612 : }
1613 : // check attributes of type "positiveFloatType" (> 0)
1614 4005 : switch (it) {
1615 10 : case SUMO_ATTR_LCA_ACCEL_LAT:
1616 10 : if (LCMAttribute <= 0) {
1617 0 : WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be greater than 0"), toString(it));
1618 0 : return false;
1619 : }
1620 : break;
1621 : default:
1622 : break;
1623 : }
1624 : // check limits of attributes
1625 4005 : switch (it) {
1626 90 : case SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR:
1627 90 : if (LCMAttribute < -1 || LCMAttribute > 1) {
1628 0 : WRITE_ERRORF(TL("Invalid Lane-Change-Model Attribute %. Must be between -1 and 1"), toString(it));
1629 0 : return false;
1630 : }
1631 : break;
1632 : default:
1633 : break;
1634 : }
1635 : // add parsedLCMAttribute to cfParameter
1636 4005 : into->lcParameter[it] = parsedLCMAttribute;
1637 : }
1638 : }
1639 : // all LCM parsed ok, then return true
1640 : return true;
1641 : }
1642 :
1643 :
1644 : bool
1645 60346 : SUMOVehicleParserHelper::parseJMParams(SUMOVTypeParameter* into, const SUMOSAXAttributes& attrs) {
1646 1025882 : for (const auto& it : SUMOVTypeParameter::AllowedJMAttrs) {
1647 965536 : if (attrs.hasAttribute(it)) {
1648 : // first obtain CFM attribute in string format
1649 1029 : bool ok = true;
1650 1029 : std::string parsedJMAttribute = attrs.get<std::string>(it, into->id.c_str(), ok);
1651 1029 : if (!ok) {
1652 : return false;
1653 : }
1654 : // declare a double in wich save CFM attribute
1655 : double JMAttribute = -1;
1656 : try {
1657 : // obtain CFM attribute in double format
1658 1029 : JMAttribute = StringUtils::toDouble(parsedJMAttribute);
1659 0 : } catch (...) {
1660 0 : WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Cannot be parsed to float"), toString(it));
1661 : return false;
1662 0 : }
1663 : // now continue checking other properties (-1 is the default value)
1664 1029 : if (JMAttribute != -1) {
1665 : // special case for sigma minor
1666 1011 : if (it == SUMO_ATTR_JM_SIGMA_MINOR) {
1667 : // check attributes sigma minor
1668 126 : if ((JMAttribute < 0) || (JMAttribute > 1)) {
1669 0 : WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Only values between [0-1] are allowed"), toString(it));
1670 0 : return false;
1671 : }
1672 : } else {
1673 : // check attributes of type "nonNegativeFloatType" (>= 0)
1674 885 : if (JMAttribute < 0) {
1675 0 : WRITE_ERRORF(TL("Invalid Junction-Model Attribute %. Must be equal or greater than 0"), toString(it));
1676 0 : return false;
1677 : }
1678 : }
1679 : // add parsedJMAttribute to cfParameter
1680 1011 : into->jmParameter[it] = parsedJMAttribute;
1681 : }
1682 : }
1683 : }
1684 : // all JM parameters successfully parsed, then return true
1685 : return true;
1686 : }
1687 :
1688 :
1689 : SUMOVehicleClass
1690 35498 : SUMOVehicleParserHelper::parseVehicleClass(const SUMOSAXAttributes& attrs, const std::string& id) {
1691 : SUMOVehicleClass vclass = SVC_IGNORING;
1692 35498 : bool ok = true;
1693 35498 : std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_VCLASS, id.c_str(), ok, "");
1694 35498 : if (vclassS == "") {
1695 : return vclass;
1696 : }
1697 : try {
1698 35474 : const SUMOVehicleClass result = getVehicleClassID(vclassS);
1699 35466 : const std::string& realName = SumoVehicleClassStrings.getString(result);
1700 35466 : if (realName != vclassS) {
1701 12 : WRITE_WARNING("The vehicle class '" + vclassS + "' for " + attrs.getObjectType() + " '" + id + "' is deprecated, use '" + realName + "' instead.");
1702 : }
1703 : return result;
1704 8 : } catch (...) {
1705 24 : WRITE_ERRORF(TL("The vehicle class '%' for % '%' is not known."), vclassS, attrs.getObjectType(), id);
1706 8 : }
1707 : return vclass;
1708 : }
1709 :
1710 :
1711 : SUMOVehicleShape
1712 27142 : SUMOVehicleParserHelper::parseGuiShape(const SUMOSAXAttributes& attrs, const std::string& id) {
1713 27142 : bool ok = true;
1714 54284 : std::string vclassS = attrs.getOpt<std::string>(SUMO_ATTR_GUISHAPE, id.c_str(), ok, "");
1715 : if (SumoVehicleShapeStrings.hasString(vclassS)) {
1716 27142 : const SUMOVehicleShape result = SumoVehicleShapeStrings.get(vclassS);
1717 27142 : const std::string& realName = SumoVehicleShapeStrings.getString(result);
1718 27142 : if (realName != vclassS) {
1719 0 : WRITE_WARNING("The shape '" + vclassS + "' for " + attrs.getObjectType() + " '" + id + "' is deprecated, use '" + realName + "' instead.");
1720 : }
1721 27142 : return result;
1722 : } else {
1723 0 : WRITE_ERRORF(TL("The shape '%' for % '%' is not known."), vclassS, attrs.getObjectType(), id);
1724 0 : return SUMOVehicleShape::UNKNOWN;
1725 : }
1726 : }
1727 :
1728 :
1729 : double
1730 31758 : SUMOVehicleParserHelper::parseWalkPos(SumoXMLAttr attr, const bool hardFail, const std::string& id, double maxPos, const std::string& val, SumoRNG* rng) {
1731 : double result;
1732 : std::string error;
1733 31758 : ArrivalPosDefinition proc = ArrivalPosDefinition::DEFAULT;
1734 : // only supports 'random' and 'max'
1735 63516 : if (!SUMOVehicleParameter::parseArrivalPos(val, toString(SUMO_TAG_WALK), id, result, proc, error)) {
1736 0 : handleVehicleError(hardFail, nullptr, error);
1737 : }
1738 31758 : if (proc == ArrivalPosDefinition::RANDOM) {
1739 888 : result = RandHelper::rand(maxPos, rng);
1740 30870 : } else if (proc == ArrivalPosDefinition::CENTER) {
1741 0 : result = maxPos / 2.;
1742 30870 : } else if (proc == ArrivalPosDefinition::MAX) {
1743 0 : result = maxPos;
1744 : }
1745 63516 : return SUMOVehicleParameter::interpretEdgePos(result, maxPos, attr, id);
1746 : }
1747 :
1748 :
1749 : SUMOTime
1750 299662 : SUMOVehicleParserHelper::processActionStepLength(double given) {
1751 299662 : const std::string defaultError = "The parameter action-step-length must be a non-negative multiple of the simulation step-length. ";
1752 299662 : SUMOTime result = TIME2STEPS(given);
1753 299662 : if (result <= 0) {
1754 42285 : if (result < 0) {
1755 36 : WRITE_WARNING(defaultError + "Ignoring given value (=" + toString(STEPS2TIME(result)) + " s.)");
1756 : }
1757 42285 : result = DELTA_T;
1758 257377 : } else if (result % DELTA_T != 0) {
1759 25 : result = (SUMOTime)((double)DELTA_T * floor(double(result) / double(DELTA_T)));
1760 : result = MAX2(DELTA_T, result);
1761 25 : if (fabs(given * 1000. - double(result)) > NUMERICAL_EPS) {
1762 100 : WRITE_WARNING(defaultError + "Parsing given value (" + toString(given) + " s.) to the adjusted value " + toString(STEPS2TIME(result)) + " s.");
1763 : }
1764 : }
1765 299662 : return result;
1766 : }
1767 :
1768 :
1769 : bool
1770 185252 : SUMOVehicleParserHelper::isInternalRouteID(const std::string& id) {
1771 185252 : return id.substr(0, 1) == "!";
1772 : }
1773 :
1774 :
1775 : int
1776 17247 : SUMOVehicleParserHelper::parseCarWalkTransfer(const OptionsCont& oc, const bool hasTaxi) {
1777 : int carWalk = 0;
1778 51741 : for (const std::string& opt : oc.getStringVector("persontrip.transfer.car-walk")) {
1779 17247 : if (opt == "parkingAreas") {
1780 17047 : carWalk |= ModeChangeOptions::PARKING_AREAS;
1781 200 : } else if (opt == "ptStops") {
1782 150 : carWalk |= ModeChangeOptions::PT_STOPS;
1783 50 : } else if (opt == "allJunctions") {
1784 50 : carWalk |= ModeChangeOptions::ALL_JUNCTIONS;
1785 : } else {
1786 0 : WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1787 : }
1788 : }
1789 17247 : const StringVector taxiDropoff = oc.getStringVector("persontrip.transfer.taxi-walk");
1790 34494 : const StringVector taxiPickup = oc.getStringVector("persontrip.transfer.walk-taxi");
1791 17247 : if (taxiDropoff.empty() && hasTaxi) {
1792 83 : carWalk |= ModeChangeOptions::TAXI_DROPOFF_ANYWHERE;
1793 : } else {
1794 17258 : for (const std::string& opt : taxiDropoff) {
1795 94 : if (opt == "parkingAreas") {
1796 0 : carWalk |= ModeChangeOptions::TAXI_DROPOFF_PARKING_AREAS;
1797 94 : } else if (opt == "ptStops") {
1798 62 : carWalk |= ModeChangeOptions::TAXI_DROPOFF_PT;
1799 32 : } else if (opt == "allJunctions") {
1800 32 : carWalk |= ModeChangeOptions::TAXI_DROPOFF_ANYWHERE;
1801 : } else {
1802 0 : WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1803 : }
1804 : }
1805 : }
1806 17247 : if (taxiPickup.empty() && hasTaxi) {
1807 77 : carWalk |= ModeChangeOptions::TAXI_PICKUP_ANYWHERE;
1808 : } else {
1809 17276 : for (const std::string& opt : taxiPickup) {
1810 106 : if (opt == "parkingAreas") {
1811 0 : carWalk |= ModeChangeOptions::TAXI_PICKUP_PARKING_AREAS;
1812 106 : } else if (opt == "ptStops") {
1813 74 : carWalk |= ModeChangeOptions::TAXI_PICKUP_PT;
1814 32 : } else if (opt == "allJunctions") {
1815 32 : carWalk |= ModeChangeOptions::TAXI_PICKUP_ANYWHERE;
1816 : } else {
1817 0 : WRITE_ERRORF(TL("Invalid transfer option '%'. Must be one of 'parkingAreas', 'ptStops' and 'allJunctions'"), opt);
1818 : }
1819 : }
1820 : }
1821 17247 : return carWalk;
1822 17247 : }
1823 :
1824 :
1825 : SUMOVehicleParameter*
1826 432 : SUMOVehicleParserHelper::handleVehicleError(const bool hardFail, SUMOVehicleParameter* vehicleParameter, const std::string message) {
1827 432 : if (vehicleParameter) {
1828 388 : delete vehicleParameter;
1829 : }
1830 432 : if (hardFail) {
1831 864 : throw ProcessError(message);
1832 0 : } else if (message.size() > 0) {
1833 0 : WRITE_ERROR(message);
1834 : }
1835 0 : return nullptr;
1836 : }
1837 :
1838 :
1839 : SUMOVTypeParameter*
1840 30 : SUMOVehicleParserHelper::handleVehicleTypeError(const bool hardFail, SUMOVTypeParameter* vehicleTypeParameter, const std::string message) {
1841 30 : if (vehicleTypeParameter) {
1842 26 : delete vehicleTypeParameter;
1843 : }
1844 30 : if (hardFail) {
1845 60 : throw ProcessError(message);
1846 0 : } else if (message.size() > 0) {
1847 0 : WRITE_ERROR(message);
1848 : }
1849 0 : return nullptr;
1850 : }
1851 :
1852 : /****************************************************************************/
|