Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 SUMORouteHandler.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @date Mon, 9 Jul 2001
20 : ///
21 : // Parser for routes during their loading
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/options/OptionsCont.h>
27 : #include <utils/vehicle/SUMOVTypeParameter.h>
28 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
29 : #include <utils/xml/XMLSubSys.h>
30 :
31 : #include "SUMORouteHandler.h"
32 :
33 :
34 : // ===========================================================================
35 : // method definitions
36 : // ===========================================================================
37 :
38 95349 : SUMORouteHandler::SUMORouteHandler(const std::string& file, const std::string& expectedRoot, const bool hardFail) :
39 : SUMOSAXHandler(file, expectedRoot),
40 95349 : myHardFail(hardFail),
41 95349 : myVehicleParameter(nullptr),
42 95349 : myLastDepart(-1),
43 95349 : myActiveRouteColor(nullptr),
44 95349 : myCurrentCosts(0.),
45 95349 : myCurrentVType(nullptr),
46 95349 : myBeginDefault(string2time(OptionsCont::getOptions().getString("begin"))),
47 95349 : myEndDefault(string2time(OptionsCont::getOptions().getString("end"))),
48 95349 : myFirstDepart(-1),
49 95349 : myInsertStopEdgesAt(-1),
50 95349 : myAllowInternalRoutes(false) {
51 95349 : }
52 :
53 :
54 92425 : SUMORouteHandler::~SUMORouteHandler() {
55 92425 : delete myVehicleParameter;
56 92425 : delete myCurrentVType;
57 92425 : }
58 :
59 :
60 : bool
61 442614 : SUMORouteHandler::checkLastDepart() {
62 442614 : if (myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
63 441738 : if (myVehicleParameter->depart < myLastDepart) {
64 2 : WRITE_WARNINGF(TL("Route file should be sorted by departure time, ignoring '%'!"), myVehicleParameter->id);
65 1 : return false;
66 : }
67 : }
68 : return true;
69 : }
70 :
71 :
72 : void
73 489460 : SUMORouteHandler::registerLastDepart() {
74 : // register only non public transport to parse all public transport lines in advance
75 489460 : if (myVehicleParameter && myVehicleParameter->line == "" && myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
76 484369 : myLastDepart = myVehicleParameter->depart;
77 484369 : if (myFirstDepart == -1) {
78 43214 : myFirstDepart = myLastDepart;
79 : }
80 : }
81 : // else: we don't know when this vehicle will depart. keep the previous known depart time
82 489460 : }
83 :
84 :
85 : void
86 11265620 : SUMORouteHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
87 11265620 : myElementStack.push_back(element);
88 11265620 : switch (element) {
89 395884 : case SUMO_TAG_VEHICLE:
90 : case SUMO_TAG_PERSON:
91 : case SUMO_TAG_CONTAINER:
92 : // if myVehicleParameter is nullptr this will do nothing
93 395884 : delete myVehicleParameter;
94 : // we set to nullptr to have a consistent state if the parsing fails
95 395884 : myVehicleParameter = nullptr;
96 395884 : myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
97 395624 : myParamStack.push_back(myVehicleParameter);
98 395624 : if (element != SUMO_TAG_VEHICLE) {
99 42183 : addTransportable(attrs, element == SUMO_TAG_PERSON);
100 : }
101 : break;
102 22426 : case SUMO_TAG_FLOW:
103 : // delete if myVehicleParameter isn't null
104 22426 : if (myVehicleParameter) {
105 0 : delete myVehicleParameter;
106 0 : myVehicleParameter = nullptr;
107 : }
108 : // parse vehicle parameters
109 : // might be called to parse vehicles from additional file in the
110 : // context of quickReload. In this case, rerouter flows must be ignored
111 22426 : if (myElementStack.size() == 1 || myElementStack[myElementStack.size() - 2] != SUMO_TAG_CALIBRATOR) {
112 22426 : myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOW, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
113 : }
114 : // check if myVehicleParameter was successfully created
115 22308 : if (myVehicleParameter) {
116 : // check tag
117 22308 : if (myVehicleParameter->routeid.empty()) {
118 : // open a route flow (It could be a flow with embedded route)
119 12434 : openFlow(attrs);
120 : } else {
121 : // open a route flow
122 9874 : openRouteFlow(attrs);
123 : }
124 22308 : myParamStack.push_back(myVehicleParameter);
125 : }
126 : break;
127 1979 : case SUMO_TAG_PERSONFLOW:
128 : case SUMO_TAG_CONTAINERFLOW:
129 : // delete if myVehicleParameter isn't null
130 1979 : if (myVehicleParameter) {
131 0 : delete myVehicleParameter;
132 0 : myVehicleParameter = nullptr;
133 : }
134 : // create a new flow
135 1979 : myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes((SumoXMLTag)element, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
136 1979 : myParamStack.push_back(myVehicleParameter);
137 1979 : break;
138 60383 : case SUMO_TAG_VTYPE:
139 : // delete if myCurrentVType isn't null
140 60383 : if (myCurrentVType != nullptr) {
141 4 : delete myCurrentVType;
142 4 : myCurrentVType = nullptr;
143 : }
144 : // create a new vType
145 60383 : myCurrentVType = SUMOVehicleParserHelper::beginVTypeParsing(attrs, myHardFail, getFileName());
146 60353 : myParamStack.push_back(myCurrentVType);
147 60353 : break;
148 520 : case SUMO_TAG_VTYPE_DISTRIBUTION:
149 520 : openVehicleTypeDistribution(attrs);
150 520 : break;
151 395929 : case SUMO_TAG_ROUTE:
152 395929 : openRoute(attrs);
153 395861 : break;
154 92156 : case SUMO_TAG_ROUTE_DISTRIBUTION:
155 92156 : openRouteDistribution(attrs);
156 92156 : break;
157 44069 : case SUMO_TAG_STOP:
158 44069 : myParamStack.push_back(addStop(attrs));
159 43959 : break;
160 74485 : case SUMO_TAG_TRIP: {
161 : // delete if myVehicleParameter isn't null
162 74485 : if (myVehicleParameter) {
163 0 : delete myVehicleParameter;
164 0 : myVehicleParameter = nullptr;
165 : }
166 : // parse vehicle parameters
167 74485 : myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
168 : // check if myVehicleParameter was successfully created
169 74431 : if (myVehicleParameter) {
170 74431 : myVehicleParameter->parametersSet |= VEHPARS_FORCE_REROUTE;
171 74431 : myActiveRouteID = "!" + myVehicleParameter->id;
172 : // open trip
173 74431 : openTrip(attrs);
174 74431 : myParamStack.push_back(myVehicleParameter);
175 : }
176 : break;
177 : }
178 3621 : case SUMO_TAG_PERSONTRIP:
179 3621 : addPersonTrip(attrs);
180 3608 : break;
181 38604 : case SUMO_TAG_WALK:
182 38604 : addWalk(attrs);
183 38582 : break;
184 15 : case SUMO_TAG_INTERVAL: {
185 : bool ok;
186 15 : myBeginDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok);
187 15 : myEndDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok);
188 : break;
189 : }
190 4804 : case SUMO_TAG_RIDE:
191 4804 : addRide(attrs);
192 4772 : break;
193 878 : case SUMO_TAG_TRANSPORT:
194 878 : addTransport(attrs);
195 864 : break;
196 519 : case SUMO_TAG_TRANSHIP:
197 519 : addTranship(attrs);
198 519 : break;
199 53788 : case SUMO_TAG_PARAM:
200 53788 : addParam(attrs);
201 53788 : break;
202 10075560 : default:
203 : // parse embedded car following model information
204 10075560 : if (myCurrentVType != nullptr) {
205 32 : WRITE_WARNINGF(TL("Defining car-following parameters in a nested element is deprecated in vType '%', use attributes instead!"), myCurrentVType->id);
206 16 : if (!SUMOVehicleParserHelper::parseCFMParams(myCurrentVType, (SumoXMLTag)element, attrs, true)) {
207 0 : if (myHardFail) {
208 0 : throw ProcessError(TL("Invalid parsing embedded VType"));
209 : } else {
210 0 : WRITE_ERROR(TL("Invalid parsing embedded VType"));
211 : }
212 : }
213 : }
214 : break;
215 : }
216 11264899 : }
217 :
218 :
219 : void
220 11254341 : SUMORouteHandler::myEndElement(int element) {
221 11254341 : switch (element) {
222 43959 : case SUMO_TAG_STOP:
223 : myParamStack.pop_back();
224 : break;
225 395861 : case SUMO_TAG_ROUTE:
226 395861 : closeRoute();
227 395807 : break;
228 60349 : case SUMO_TAG_VTYPE:
229 60349 : closeVType();
230 60325 : delete myCurrentVType;
231 60325 : myCurrentVType = nullptr;
232 : myParamStack.pop_back();
233 : break;
234 41292 : case SUMO_TAG_PERSON:
235 41292 : closePerson();
236 41266 : delete myVehicleParameter;
237 41266 : myVehicleParameter = nullptr;
238 : myParamStack.pop_back();
239 : break;
240 1668 : case SUMO_TAG_PERSONFLOW:
241 1668 : closePersonFlow();
242 1659 : delete myVehicleParameter;
243 1659 : myVehicleParameter = nullptr;
244 : myParamStack.pop_back();
245 : break;
246 791 : case SUMO_TAG_CONTAINER:
247 791 : closeContainer();
248 783 : delete myVehicleParameter;
249 783 : myVehicleParameter = nullptr;
250 : myParamStack.pop_back();
251 : break;
252 307 : case SUMO_TAG_CONTAINERFLOW:
253 307 : closeContainerFlow();
254 307 : delete myVehicleParameter;
255 307 : myVehicleParameter = nullptr;
256 : myParamStack.pop_back();
257 : break;
258 353295 : case SUMO_TAG_VEHICLE:
259 353295 : if (myVehicleParameter == nullptr) {
260 : break;
261 : }
262 353295 : if (myVehicleParameter->repetitionNumber > 0) {
263 0 : myVehicleParameter->repetitionNumber++; // for backwards compatibility
264 : // it is a flow, thus no break here
265 : FALLTHROUGH;
266 : } else {
267 353295 : closeVehicle();
268 352893 : delete myVehicleParameter;
269 352893 : myVehicleParameter = nullptr;
270 : myParamStack.pop_back();
271 : break;
272 : }
273 : case SUMO_TAG_FLOW:
274 22306 : if (myVehicleParameter) {
275 22306 : closeFlow();
276 22283 : delete myVehicleParameter;
277 : myParamStack.pop_back();
278 : }
279 22283 : myVehicleParameter = nullptr;
280 22283 : myInsertStopEdgesAt = -1;
281 22283 : break;
282 73870 : case SUMO_TAG_TRIP:
283 73870 : closeTrip();
284 73265 : delete myVehicleParameter;
285 73265 : myVehicleParameter = nullptr;
286 : myParamStack.pop_back();
287 73265 : myInsertStopEdgesAt = -1;
288 73265 : break;
289 520 : case SUMO_TAG_VTYPE_DISTRIBUTION:
290 520 : closeVehicleTypeDistribution();
291 520 : break;
292 92126 : case SUMO_TAG_ROUTE_DISTRIBUTION:
293 92126 : closeRouteDistribution();
294 92126 : break;
295 48341 : case SUMO_TAG_PERSONTRIP:
296 : case SUMO_TAG_RIDE:
297 : case SUMO_TAG_TRANSPORT:
298 : case SUMO_TAG_TRANSHIP:
299 : case SUMO_TAG_WALK:
300 48341 : if (myParamStack.size() == 2) {
301 : myParamStack.pop_back();
302 : }
303 : break;
304 15 : case SUMO_TAG_INTERVAL:
305 15 : myBeginDefault = string2time(OptionsCont::getOptions().getString("begin"));
306 15 : myEndDefault = string2time(OptionsCont::getOptions().getString("end"));
307 15 : break;
308 : default:
309 : break;
310 : }
311 : myElementStack.pop_back();
312 11253190 : }
313 :
314 :
315 : SUMORouteHandler::StopPos
316 92514 : SUMORouteHandler::checkStopPos(double& startPos, double& endPos, const double laneLength, const double minLength, const bool friendlyPos) {
317 92514 : if (minLength > laneLength) {
318 : return STOPPOS_INVALID_LANELENGTH;
319 : }
320 92514 : if (startPos < 0) {
321 93 : startPos += laneLength;
322 : }
323 92514 : if (endPos < 0) {
324 661 : endPos += laneLength;
325 : }
326 92514 : if ((endPos < minLength) || (endPos > laneLength)) {
327 111 : if (!friendlyPos) {
328 : return STOPPOS_INVALID_ENDPOS;
329 : }
330 106 : if (endPos < minLength) {
331 0 : endPos = minLength;
332 : }
333 106 : if (endPos > laneLength) {
334 106 : endPos = laneLength;
335 : }
336 : }
337 92509 : if ((startPos < 0) || (startPos > (endPos - minLength))) {
338 57 : if (!friendlyPos) {
339 : return STOPPOS_INVALID_STARTPOS;
340 : }
341 57 : if (startPos < 0) {
342 10 : startPos = 0;
343 : }
344 57 : if (startPos > (endPos - minLength)) {
345 47 : startPos = endPos - minLength;
346 : }
347 : }
348 : return STOPPOS_VALID;
349 : }
350 :
351 :
352 : bool
353 0 : SUMORouteHandler::isStopPosValid(const double startPos, const double endPos, const double laneLength, const double minLength, const bool friendlyPos) {
354 : // declare dummy start and end positions
355 0 : double dummyStartPos = startPos;
356 0 : double dummyEndPos = endPos;
357 : // return checkStopPos
358 0 : return (checkStopPos(dummyStartPos, dummyEndPos, laneLength, minLength, friendlyPos) == STOPPOS_VALID);
359 : }
360 :
361 :
362 : SUMOTime
363 100564 : SUMORouteHandler::getFirstDepart() const {
364 100564 : return myFirstDepart;
365 : }
366 :
367 :
368 : SUMOTime
369 2950046 : SUMORouteHandler::getLastDepart() const {
370 2950046 : return myLastDepart;
371 : }
372 :
373 :
374 : void
375 53788 : SUMORouteHandler::addParam(const SUMOSAXAttributes& attrs) {
376 53788 : bool ok = true;
377 53788 : const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
378 : // only continue if key isn't empty
379 53788 : if (ok && (key.size() > 0)) {
380 : // circumventing empty string test
381 53788 : const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
382 : // add parameter in current created element
383 53788 : if (!myParamStack.empty()) {
384 13496 : myParamStack.back()->setParameter(key, val);
385 : }
386 : }
387 53788 : }
388 :
389 :
390 : bool
391 44053 : SUMORouteHandler::parseStop(SUMOVehicleParameter::Stop& stop, const SUMOSAXAttributes& attrs, std::string errorSuffix, MsgHandler* const errorOutput) {
392 44053 : stop.parametersSet = 0;
393 44053 : if (attrs.hasAttribute(SUMO_ATTR_ARRIVAL)) {
394 381 : stop.parametersSet |= STOP_ARRIVAL_SET;
395 : }
396 44053 : if (attrs.hasAttribute(SUMO_ATTR_DURATION)) {
397 33001 : stop.parametersSet |= STOP_DURATION_SET;
398 : }
399 44053 : if (attrs.hasAttribute(SUMO_ATTR_UNTIL)) {
400 11787 : stop.parametersSet |= STOP_UNTIL_SET;
401 : }
402 44053 : if (attrs.hasAttribute(SUMO_ATTR_STARTED)) {
403 3191 : stop.parametersSet |= STOP_STARTED_SET;
404 : }
405 44053 : if (attrs.hasAttribute(SUMO_ATTR_ENDED)) {
406 2979 : stop.parametersSet |= STOP_ENDED_SET;
407 : }
408 44053 : if (attrs.hasAttribute(SUMO_ATTR_EXTENSION)) {
409 440 : stop.parametersSet |= STOP_EXTENSION_SET;
410 : }
411 44053 : if (attrs.hasAttribute(SUMO_ATTR_ENDPOS)) {
412 7978 : stop.parametersSet |= STOP_END_SET;
413 : }
414 44053 : if (attrs.hasAttribute(SUMO_ATTR_STARTPOS)) {
415 1349 : stop.parametersSet |= STOP_START_SET;
416 : }
417 44053 : if (attrs.hasAttribute(SUMO_ATTR_POSITION_LAT)) {
418 121 : stop.parametersSet |= STOP_POSLAT_SET;
419 : }
420 44053 : if (attrs.hasAttribute(SUMO_ATTR_TRIGGERED)) {
421 1218 : stop.parametersSet |= STOP_TRIGGER_SET;
422 : }
423 : // legacy attribute
424 44053 : if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_TRIGGERED)) {
425 56 : stop.parametersSet |= STOP_TRIGGER_SET;
426 : }
427 44053 : if (attrs.hasAttribute(SUMO_ATTR_PARKING)) {
428 959 : stop.parametersSet |= STOP_PARKING_SET;
429 : }
430 44053 : if (attrs.hasAttribute(SUMO_ATTR_EXPECTED)) {
431 242 : stop.parametersSet |= STOP_EXPECTED_SET;
432 : }
433 44053 : if (attrs.hasAttribute(SUMO_ATTR_PERMITTED)) {
434 320 : stop.parametersSet |= STOP_PERMITTED_SET;
435 : }
436 44053 : if (attrs.hasAttribute(SUMO_ATTR_EXPECTED_CONTAINERS)) {
437 82 : stop.parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
438 : }
439 44053 : if (attrs.hasAttribute(SUMO_ATTR_TRIP_ID)) {
440 408 : stop.parametersSet |= STOP_TRIP_ID_SET;
441 : }
442 44053 : if (attrs.hasAttribute(SUMO_ATTR_SPLIT)) {
443 222 : stop.parametersSet |= STOP_SPLIT_SET;
444 : }
445 44053 : if (attrs.hasAttribute(SUMO_ATTR_JOIN)) {
446 117 : stop.parametersSet |= STOP_JOIN_SET;
447 : }
448 44053 : if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
449 363 : stop.parametersSet |= STOP_LINE_SET;
450 : }
451 44053 : if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
452 617 : stop.parametersSet |= STOP_SPEED_SET;
453 : }
454 44053 : if (attrs.hasAttribute(SUMO_ATTR_ONDEMAND)) {
455 171 : stop.parametersSet |= STOP_ONDEMAND_SET;
456 : }
457 44053 : if (attrs.hasAttribute(SUMO_ATTR_JUMP)) {
458 365 : stop.parametersSet |= STOP_JUMP_SET;
459 : }
460 44053 : bool ok = true;
461 88106 : stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
462 44053 : stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop);
463 44053 : stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
464 44053 : stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
465 44053 : stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
466 88106 : stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
467 44053 : if (stop.busstop != "") {
468 29061 : errorSuffix = " at '" + stop.busstop + "'" + errorSuffix;
469 34366 : } else if (stop.chargingStation != "") {
470 3246 : errorSuffix = " at '" + stop.chargingStation + "'" + errorSuffix;
471 33284 : } else if (stop.overheadWireSegment != "") {
472 0 : errorSuffix = " at '" + stop.overheadWireSegment + "'" + errorSuffix;
473 33284 : } else if (stop.containerstop != "") {
474 1632 : errorSuffix = " at '" + stop.containerstop + "'" + errorSuffix;
475 32740 : } else if (stop.parkingarea != "") {
476 25806 : errorSuffix = " at '" + stop.parkingarea + "'" + errorSuffix;
477 24138 : } else if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
478 68160 : errorSuffix = " on lane '" + attrs.get<std::string>(SUMO_ATTR_LANE, nullptr, ok) + "'" + errorSuffix;
479 1418 : } else if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
480 3978 : errorSuffix = " on edge '" + attrs.get<std::string>(SUMO_ATTR_EDGE, nullptr, ok) + "'" + errorSuffix;
481 : } else {
482 184 : errorSuffix = " at undefined location" + errorSuffix;
483 : }
484 : // speed for counting as stopped
485 44053 : stop.speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, 0);
486 44053 : if (stop.speed < 0) {
487 12 : errorOutput->inform(TLF("Speed cannot be negative for stop%.", errorSuffix));
488 6 : return false;
489 : }
490 :
491 : // get the standing duration
492 44047 : bool expectTrigger = !attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL) && !attrs.hasAttribute(SUMO_ATTR_SPEED);
493 44047 : std::vector<std::string> triggers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_TRIGGERED, nullptr, ok);
494 : // legacy
495 44047 : if (attrs.getOpt<bool>(SUMO_ATTR_CONTAINER_TRIGGERED, nullptr, ok, false)) {
496 112 : triggers.push_back(toString(SUMO_TAG_CONTAINER));
497 : }
498 44047 : SUMOVehicleParameter::parseStopTriggers(triggers, expectTrigger, stop);
499 44047 : stop.arrival = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ARRIVAL, nullptr, ok, -1);
500 44047 : stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
501 44047 : stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, -1);
502 44047 : if (!expectTrigger && (!ok || (stop.duration < 0 && stop.until < 0 && stop.speed == 0))) {
503 36 : errorOutput->inform(TLF("Invalid duration or end time is given for a stop%.", errorSuffix));
504 12 : return false;
505 : }
506 44035 : if (triggers.size() > 0 && stop.speed > 0) {
507 9 : errorOutput->inform(TLF("Triggers and waypoints cannot be combined%.", errorSuffix));
508 3 : return false;
509 : }
510 44032 : stop.extension = attrs.getOptSUMOTimeReporting(SUMO_ATTR_EXTENSION, nullptr, ok, -1);
511 44032 : const bool defaultParking = (stop.triggered || stop.containerTriggered || stop.parkingarea != "");
512 44032 : stop.parking = attrs.getOpt<ParkingType>(SUMO_ATTR_PARKING, nullptr, ok, defaultParking ? ParkingType::OFFROAD : ParkingType::ONROAD);
513 44032 : if ((stop.parkingarea != "") && (stop.parking == ParkingType::ONROAD)) {
514 0 : WRITE_WARNINGF(TL("Stop at parkingArea overrides attribute 'parking' for stop%."), errorSuffix);
515 0 : stop.parking = ParkingType::OFFROAD;
516 : }
517 :
518 : // expected persons
519 44032 : const std::vector<std::string>& expected = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED, nullptr, ok);
520 : stop.awaitedPersons.insert(expected.begin(), expected.end());
521 44032 : if (stop.awaitedPersons.size() > 0) {
522 242 : stop.triggered = true;
523 242 : if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
524 95 : stop.parking = ParkingType::OFFROAD;
525 : }
526 : }
527 :
528 : // permitted transportables
529 44032 : const std::vector<std::string>& permitted = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_PERMITTED, nullptr, ok);
530 : stop.permitted.insert(permitted.begin(), permitted.end());
531 :
532 : // expected containers
533 44032 : const std::vector<std::string>& expectedContainers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED_CONTAINERS, nullptr, ok);
534 : stop.awaitedContainers.insert(expectedContainers.begin(), expectedContainers.end());
535 44032 : if (stop.awaitedContainers.size() > 0) {
536 82 : stop.containerTriggered = true;
537 82 : if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
538 60 : stop.parking = ParkingType::OFFROAD;
539 : }
540 : }
541 : // public transport trip id
542 44032 : stop.tripId = attrs.getOpt<std::string>(SUMO_ATTR_TRIP_ID, nullptr, ok, "");
543 44032 : stop.split = attrs.getOpt<std::string>(SUMO_ATTR_SPLIT, nullptr, ok, "");
544 44032 : stop.join = attrs.getOpt<std::string>(SUMO_ATTR_JOIN, nullptr, ok, "");
545 44032 : stop.line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, nullptr, ok, "");
546 :
547 44032 : const std::string idx = attrs.getOpt<std::string>(SUMO_ATTR_INDEX, nullptr, ok, "end");
548 44032 : if (idx == "end") {
549 43831 : stop.index = STOP_INDEX_END;
550 201 : } else if (idx == "fit") {
551 14 : stop.index = STOP_INDEX_FIT;
552 : } else {
553 187 : stop.index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
554 187 : if (!ok || stop.index < 0) {
555 18 : errorOutput->inform(TLF("Invalid 'index' for stop%.", errorSuffix));
556 6 : return false;
557 : }
558 : }
559 44026 : stop.started = attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1);
560 44026 : stop.ended = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1);
561 44026 : stop.posLat = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, nullptr, ok, INVALID_DOUBLE);
562 44026 : stop.actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
563 44026 : stop.onDemand = attrs.getOpt<bool>(SUMO_ATTR_ONDEMAND, nullptr, ok, false);
564 44026 : stop.jump = attrs.getOptSUMOTimeReporting(SUMO_ATTR_JUMP, nullptr, ok, -1);
565 44026 : stop.collision = attrs.getOpt<bool>(SUMO_ATTR_COLLISION, nullptr, ok, false);
566 44026 : return true;
567 44047 : }
568 :
569 :
570 : /****************************************************************************/
|