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 MSTransportable.cpp
15 : /// @author Melanie Weber
16 : /// @author Andreas Kendziorra
17 : /// @author Michael Behrisch
18 : /// @date Thu, 12 Jun 2014
19 : ///
20 : // The common superclass for modelling transportable objects like persons and containers
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <utils/common/StringTokenizer.h>
25 : #include <utils/geom/GeomHelper.h>
26 : #include <utils/vehicle/SUMOVehicleParameter.h>
27 : #include <utils/router/PedestrianRouter.h>
28 : #include <utils/router/IntermodalRouter.h>
29 : #include <libsumo/TraCIConstants.h>
30 : #include <microsim/MSEdge.h>
31 : #include <microsim/MSLane.h>
32 : #include <microsim/MSNet.h>
33 : #include <microsim/MSEventControl.h>
34 : #include <microsim/MSStoppingPlace.h>
35 : #include <microsim/MSVehicleControl.h>
36 : #include <microsim/devices/MSTransportableDevice.h>
37 : #include <microsim/transportables/MSTransportableControl.h>
38 : #include <microsim/transportables/MSPerson.h>
39 : #include <microsim/transportables/MSStageDriving.h>
40 : #include <microsim/transportables/MSStageTrip.h>
41 : #include <microsim/transportables/MSStageWaiting.h>
42 : #include <microsim/transportables/MSTransportable.h>
43 :
44 : SUMOTrafficObject::NumericalID MSTransportable::myCurrentNumericalIndex = 0;
45 :
46 : //#define DEBUG_PARKING
47 :
48 : // ===========================================================================
49 : // method definitions
50 : // ===========================================================================
51 457026 : MSTransportable::MSTransportable(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportablePlan* plan, const bool isPerson) :
52 : SUMOTrafficObject(pars->id),
53 457026 : myParameter(pars), myVType(vtype), myPlan(plan),
54 457026 : myAmPerson(isPerson),
55 457026 : myNumericalID(myCurrentNumericalIndex++) {
56 457026 : myStep = myPlan->begin();
57 : // init devices
58 457026 : MSDevice::buildTransportableDevices(*this, myDevices);
59 1378053 : for (MSStage* const stage : * myPlan) {
60 921027 : stage->init(this);
61 : }
62 457026 : }
63 :
64 :
65 595328 : MSTransportable::~MSTransportable() {
66 456976 : if (myStep != myPlan->end() && getCurrentStageType() == MSStageType::DRIVING) {
67 29749 : MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
68 29749 : if (stage->getVehicle() != nullptr) {
69 135 : stage->getVehicle()->removeTransportable(this);
70 29614 : } else if (stage->getOriginStop() != nullptr) {
71 439 : stage->getOriginStop()->removeTransportable(this);
72 : }
73 : }
74 456976 : if (myPlan != nullptr) {
75 1626898 : for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
76 1169922 : delete *i;
77 : }
78 456976 : delete myPlan;
79 456976 : myPlan = nullptr;
80 : }
81 710371 : for (MSTransportableDevice* dev : myDevices) {
82 253395 : delete dev;
83 : }
84 456976 : delete myParameter;
85 456976 : if (myVType->isVehicleSpecific()) {
86 58 : MSNet::getInstance()->getVehicleControl().removeVType(myVType);
87 : }
88 595328 : }
89 :
90 : SumoRNG*
91 67 : MSTransportable::getRNG() const {
92 67 : return getEdge()->getLanes()[0]->getRNG();
93 : }
94 :
95 : int
96 2240 : MSTransportable::getRNGIndex() const {
97 2240 : return getEdge()->getLanes()[0]->getRNGIndex();
98 : }
99 :
100 : bool
101 1103748 : MSTransportable::proceed(MSNet* net, SUMOTime time, const bool vehicleArrived) {
102 1103748 : MSStage* const prior = *myStep;
103 1103748 : const std::string& error = prior->setArrived(net, this, time, vehicleArrived);
104 : // must be done before increasing myStep to avoid invalid state for rendering
105 1103748 : prior->getEdge()->removeTransportable(this);
106 : myStep++;
107 1103748 : if (error != "") {
108 64 : throw ProcessError(error);
109 : }
110 : /* We need to check whether an access stage is needed (or maybe even two).
111 : The general scheme is: If the prior stage ended at a stop and the next stage
112 : starts at an edge which is not the one the stop is at, but the stop has an access to it
113 : we need an access stage. The same is true if prior ends at an edge, the next stage
114 : is allowed to start at any stop the edge has access to.
115 : If we start at a stop or end at a stop no access is needed.
116 : */
117 : bool accessToStop = false;
118 1103716 : if (prior->getStageType() == MSStageType::WALKING || prior->getStageType() == MSStageType::DRIVING) {
119 304818 : accessToStop = checkAccess(prior);
120 798898 : } else if (prior->getStageType() == MSStageType::WAITING_FOR_DEPART) {
121 676539 : for (MSTransportableDevice* const dev : myDevices) {
122 236308 : dev->notifyEnter(*this, MSMoveReminder::NOTIFICATION_DEPARTED, nullptr);
123 : }
124 : }
125 1103716 : if (!accessToStop && (myStep == myPlan->end()
126 692945 : || ((*myStep)->getStageType() != MSStageType::DRIVING
127 649069 : && (*myStep)->getStageType() != MSStageType::TRIP))) {
128 822300 : MSStoppingPlace* priorStop = prior->getStageType() == MSStageType::TRIP ? prior->getOriginStop() : prior->getDestinationStop();
129 : // a trip might resolve to DRIVING so we would have to stay at the stop
130 : // if a trip resolves to something else, this step will do stop removal
131 822300 : if (priorStop != nullptr) {
132 72272 : priorStop->removeTransportable(this);
133 : }
134 : }
135 1103716 : if (myStep != myPlan->end()) {
136 695519 : if ((*myStep)->getStageType() == MSStageType::WALKING && (prior->getStageType() != MSStageType::ACCESS || prior->getDestination() != (*myStep)->getFromEdge())) {
137 292632 : checkAccess(prior, false);
138 : }
139 695519 : (*myStep)->proceed(net, this, time, prior);
140 : return true;
141 : } else {
142 408197 : MSNet::getInstance()->getPersonControl().addArrived();
143 408197 : return false;
144 : }
145 : }
146 :
147 :
148 : void
149 0 : MSTransportable::setID(const std::string& /*newID*/) {
150 0 : throw ProcessError(TL("Changing a transportable ID is not permitted"));
151 : }
152 :
153 : SUMOTime
154 47732 : MSTransportable::getDesiredDepart() const {
155 47732 : return myParameter->depart;
156 : }
157 :
158 : void
159 17806 : MSTransportable::setDeparted(SUMOTime now) {
160 17806 : (*myStep)->setDeparted(now);
161 17806 : }
162 :
163 : SUMOTime
164 122 : MSTransportable::getDeparture() const {
165 262 : for (const MSStage* const stage : *myPlan) {
166 262 : if (stage->getDeparted() >= 0) {
167 122 : return stage->getDeparted();
168 : }
169 : }
170 : return -1;
171 : }
172 :
173 :
174 : double
175 2113784 : MSTransportable::getEdgePos() const {
176 2113784 : return (*myStep)->getEdgePos(MSNet::getInstance()->getCurrentTimeStep());
177 : }
178 :
179 : double
180 3477 : MSTransportable::getBackPositionOnLane(const MSLane* /*lane*/) const {
181 3477 : return getEdgePos() - getVehicleType().getLength();
182 : }
183 :
184 : int
185 359982 : MSTransportable::getDirection() const {
186 359982 : return (*myStep)->getDirection();
187 : }
188 :
189 : Position
190 5094400 : MSTransportable::getPosition() const {
191 5094400 : return (*myStep)->getPosition(MSNet::getInstance()->getCurrentTimeStep());
192 : }
193 :
194 : double
195 2934775 : MSTransportable::getAngle() const {
196 2934775 : return (*myStep)->getAngle(MSNet::getInstance()->getCurrentTimeStep());
197 : }
198 :
199 : double
200 1198 : MSTransportable::getWaitingSeconds() const {
201 1198 : return STEPS2TIME((*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep()));
202 : }
203 :
204 : double
205 836061 : MSTransportable::getSpeed() const {
206 836061 : return (*myStep)->getSpeed();
207 : }
208 :
209 :
210 : void
211 47732 : MSTransportable::tripInfoOutput(OutputDevice& os) const {
212 96176 : os.openTag(isPerson() ? "personinfo" : "containerinfo");
213 : os.writeAttr(SUMO_ATTR_ID, getID());
214 47732 : os.writeAttr(SUMO_ATTR_DEPART, time2string(getDesiredDepart()));
215 47732 : os.writeAttr(SUMO_ATTR_TYPE, getVehicleType().getID());
216 47732 : if (isPerson()) {
217 94040 : os.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
218 : }
219 : SUMOTime duration = 0;
220 : SUMOTime waitingTime = 0;
221 : SUMOTime timeLoss = 0;
222 : SUMOTime travelTime = 0;
223 : bool durationOK = true;
224 : bool waitingTimeOK = true;
225 : bool timeLossOK = true;
226 : bool travelTimeOK = true;
227 166093 : for (MSStage* const i : *myPlan) {
228 118361 : SUMOTime t = i->getDuration();
229 118361 : if (t != SUMOTime_MAX) {
230 118099 : duration += t;
231 : } else {
232 : durationOK = false;
233 : }
234 118361 : t = i->getWaitingTime();
235 118361 : if (t != SUMOTime_MAX) {
236 118355 : waitingTime += t;
237 : } else {
238 : waitingTimeOK = false;
239 : }
240 118361 : t = i->getTimeLoss(this);
241 118361 : if (t != SUMOTime_MAX) {
242 118121 : timeLoss += t;
243 : } else {
244 : timeLossOK = false;
245 : }
246 118361 : t = i->getTravelTime();
247 118361 : if (t != SUMOTime_MAX) {
248 118101 : travelTime += t;
249 : } else {
250 : travelTimeOK = false;
251 : }
252 : }
253 47732 : os.writeAttr(SUMO_ATTR_DURATION, durationOK ? time2string(duration) : "-1");
254 47732 : os.writeAttr(SUMO_ATTR_WAITINGTIME, waitingTimeOK ? time2string(waitingTime) : "-1");
255 47732 : os.writeAttr(SUMO_ATTR_TIMELOSS, timeLossOK ? time2string(timeLoss) : "-1");
256 47732 : os.writeAttr(SUMO_ATTR_TRAVELTIME, travelTimeOK ? time2string(travelTime) : "-1");
257 166093 : for (MSStage* const i : *myPlan) {
258 118361 : i->tripInfoOutput(os, this);
259 : }
260 47732 : os.closeTag();
261 47732 : }
262 :
263 :
264 : void
265 2678 : MSTransportable::routeOutput(OutputDevice& os, const bool withRouteLength) const {
266 : const std::string typeID = (
267 5296 : (isPerson() && getVehicleType().getID() == DEFAULT_PEDTYPE_ID)
268 5296 : || (isContainer() && getVehicleType().getID() == DEFAULT_CONTAINERTYPE_ID)) ? "" : getVehicleType().getID();
269 2738 : myParameter->write(os, OptionsCont::getOptions(), isPerson() ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, typeID);
270 2678 : if (hasArrived()) {
271 5232 : os.writeAttr("arrival", time2string(MSNet::getInstance()->getCurrentTimeStep()));
272 : }
273 : const MSStage* previous = nullptr;
274 10581 : for (const MSStage* const stage : *myPlan) {
275 7903 : stage->routeOutput(myAmPerson, os, withRouteLength, previous);
276 : previous = stage;
277 : }
278 2678 : myParameter->writeParams(os);
279 2678 : os.closeTag();
280 2678 : os.lf();
281 2678 : }
282 :
283 :
284 : void
285 32 : MSTransportable::setAbortWaiting(const SUMOTime timeout) {
286 32 : if (timeout < 0 && myAbortCommand != nullptr) {
287 : myAbortCommand->deschedule();
288 16 : myAbortCommand = nullptr;
289 16 : return;
290 : }
291 16 : myAbortCommand = new WrappingCommand<MSTransportable>(this, &MSTransportable::abortStage);
292 16 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myAbortCommand, SIMSTEP + timeout);
293 : }
294 :
295 :
296 : SUMOTime
297 16 : MSTransportable::abortStage(SUMOTime step) {
298 48 : WRITE_WARNINGF(TL("Teleporting % '%'; waited too long, from edge '%', time=%."),
299 : isPerson() ? "person" : "container", getID(), (*myStep)->getEdge()->getID(), time2string(step));
300 16 : MSTransportableControl& tc = isPerson() ? MSNet::getInstance()->getPersonControl() : MSNet::getInstance()->getContainerControl();
301 : tc.registerTeleportAbortWait();
302 16 : (*myStep)->abort(this);
303 16 : if (!proceed(MSNet::getInstance(), step)) {
304 8 : tc.erase(this);
305 : }
306 16 : return 0;
307 : }
308 :
309 :
310 :
311 : void
312 244031 : MSTransportable::appendStage(MSStage* stage, int next) {
313 : // myStep is invalidated upon modifying myPlan
314 244031 : const int stepIndex = (int)(myStep - myPlan->begin());
315 244031 : if (next < 0) {
316 479 : myPlan->push_back(stage);
317 : } else {
318 243552 : if (stepIndex + next > (int)myPlan->size()) {
319 0 : throw ProcessError("invalid index '" + toString(next) + "' for inserting new stage into plan of '" + getID() + "'");
320 : }
321 243552 : myPlan->insert(myPlan->begin() + stepIndex + next, stage);
322 : }
323 244031 : myStep = myPlan->begin() + stepIndex;
324 244031 : }
325 :
326 :
327 : void
328 1828 : MSTransportable::removeStage(int next, bool stayInSim) {
329 : assert(myStep + next < myPlan->end());
330 : assert(next >= 0);
331 1828 : if (next > 0) {
332 : // myStep is invalidated upon modifying myPlan
333 60 : int stepIndex = (int)(myStep - myPlan->begin());
334 60 : delete *(myStep + next);
335 60 : myPlan->erase(myStep + next);
336 60 : myStep = myPlan->begin() + stepIndex;
337 : } else {
338 1768 : if (myStep + 1 == myPlan->end() && stayInSim) {
339 : // stay in the simulation until the start of simStep to allow appending new stages (at the correct position)
340 288 : appendStage(new MSStageWaiting(getEdge(), nullptr, 0, 0, getEdgePos(), "last stage removed", false));
341 : }
342 1768 : (*myStep)->abort(this);
343 1768 : if (!proceed(MSNet::getInstance(), SIMSTEP)) {
344 51 : MSNet::getInstance()->getPersonControl().erase(this);
345 : }
346 : }
347 1828 : }
348 :
349 :
350 : void
351 17 : MSTransportable::setSpeed(double speed) {
352 45 : for (MSTransportablePlan::const_iterator i = myStep; i != myPlan->end(); ++i) {
353 28 : (*i)->setSpeed(speed);
354 : }
355 17 : getSingularType().setMaxSpeed(speed);
356 17 : }
357 :
358 :
359 : bool
360 0 : MSTransportable::replaceRoute(ConstMSRoutePtr newRoute, const std::string& /* info */, bool /* onInit */, int /* offset */, bool /* addRouteStops */, bool /* removeStops */, std::string* /* msgReturn */) {
361 0 : if (isPerson()) {
362 0 : static_cast<MSPerson*>(this)->reroute(newRoute->getEdges(), getPositionOnLane(), 0, 1);
363 0 : return true;
364 : }
365 : return false;
366 : }
367 :
368 :
369 : void
370 78 : MSTransportable::replaceVehicleType(MSVehicleType* type) {
371 78 : const SUMOVehicleClass oldVClass = myVType->getVehicleClass();
372 78 : if (myVType->isVehicleSpecific()) {
373 1 : MSNet::getInstance()->getVehicleControl().removeVType(myVType);
374 : }
375 78 : if (isPerson()
376 78 : && type->getVehicleClass() != oldVClass
377 12 : && type->getVehicleClass() != SVC_PEDESTRIAN
378 84 : && !type->getParameter().wasSet(VTYPEPARS_VEHICLECLASS_SET)) {
379 18 : WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), getID(), type->getID(), toString(type->getVehicleClass()));
380 : }
381 78 : myVType = type;
382 78 : }
383 :
384 :
385 : MSVehicleType&
386 85 : MSTransportable::getSingularType() {
387 85 : if (myVType->isVehicleSpecific()) {
388 : return *myVType;
389 : }
390 118 : MSVehicleType* type = myVType->buildSingularType(myVType->getID() + "@" + getID());
391 59 : replaceVehicleType(type);
392 59 : return *type;
393 : }
394 :
395 :
396 : PositionVector
397 1112555 : MSTransportable::getBoundingBox() const {
398 1112555 : PositionVector centerLine;
399 1112555 : const Position p = getPosition();
400 1112555 : const double angle = getAngle();
401 1112555 : const double length = getVehicleType().getLength();
402 1112555 : const Position back = p + Position(-cos(angle) * length, -sin(angle) * length);
403 1112555 : centerLine.push_back(p);
404 1112555 : centerLine.push_back(back);
405 1112555 : centerLine.move2side(0.5 * getVehicleType().getWidth());
406 : PositionVector result = centerLine;
407 1112555 : centerLine.move2side(-getVehicleType().getWidth());
408 1112555 : result.append(centerLine.reverse(), POSITION_EPS);
409 : //std::cout << " transp=" << getID() << " p=" << p << " angle=" << GeomHelper::naviDegree(angle) << " back=" << back << " result=" << result << "\n";
410 1112555 : return result;
411 1112555 : }
412 :
413 :
414 : std::string
415 0 : MSTransportable::getStageSummary(int stageIndex) const {
416 : assert(stageIndex < (int)myPlan->size());
417 : assert(stageIndex >= 0);
418 0 : return (*myPlan)[stageIndex]->getStageSummary(myAmPerson);
419 : }
420 :
421 :
422 : const std::set<SUMOTrafficObject::NumericalID>
423 0 : MSTransportable::getUpcomingEdgeIDs() const {
424 : std::set<SUMOTrafficObject::NumericalID> result;
425 0 : for (auto step = myStep; step != myPlan->end(); ++step) {
426 0 : for (const MSEdge* const e : (*step)->getEdges()) {
427 0 : result.insert(e->getNumericalID());
428 : }
429 : }
430 0 : return result;
431 : }
432 :
433 :
434 : bool
435 3752329 : MSTransportable::hasArrived() const {
436 3752329 : return myStep == myPlan->end();
437 : }
438 :
439 : bool
440 17929 : MSTransportable::hasDeparted() const {
441 17929 : return myPlan->size() > 0 && (myPlan->front()->getDeparted() >= 0 || myStep > myPlan->begin());
442 : }
443 :
444 :
445 : void
446 41 : MSTransportable::rerouteParkingArea(MSStoppingPlace* orig, MSStoppingPlace* replacement) {
447 : // check whether the transportable was riding to the orignal stop
448 : // @note: parkingArea can currently not be set as myDestinationStop so we
449 : // check for stops on the edge instead
450 : #ifdef DEBUG_PARKING
451 : std::cout << SIMTIME << " person=" << getID() << " rerouteParkingArea orig=" << orig->getID() << " replacement=" << replacement->getID() << "\n";
452 : #endif
453 : assert(getCurrentStageType() == MSStageType::DRIVING);
454 41 : if (!myAmPerson) {
455 0 : WRITE_WARNING(TL("parkingAreaReroute not support for containers"));
456 0 : return;
457 : }
458 41 : if (getDestination() == &orig->getLane().getEdge()) {
459 41 : MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
460 : assert(stage != 0);
461 : assert(stage->getVehicle() != 0);
462 : // adapt plan
463 41 : stage->setDestination(&replacement->getLane().getEdge(), replacement);
464 41 : stage->setArrivalPos((replacement->getBeginLanePosition() + replacement->getEndLanePosition()) / 2);
465 : #ifdef DEBUG_PARKING
466 : std::cout << " set ride destination\n";
467 : #endif
468 41 : if (myStep + 1 == myPlan->end()) {
469 : return;
470 : }
471 : // if the next step is a walk, adapt the route
472 41 : MSStage* nextStage = *(myStep + 1);
473 41 : if (nextStage->getStageType() == MSStageType::TRIP) {
474 31 : dynamic_cast<MSStageTrip*>(nextStage)->setOrigin(stage->getDestination());
475 : #ifdef DEBUG_PARKING
476 : std::cout << " set subsequent trip origin\n";
477 : #endif
478 10 : } else if (nextStage->getStageType() == MSStageType::WALKING) {
479 : #ifdef DEBUG_PARKING
480 : std::cout << " replace subsequent walk with a trip\n";
481 : #endif
482 5 : MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
483 5 : nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
484 5 : removeStage(1);
485 5 : appendStage(newStage, 1);
486 5 : } else if (nextStage->getStageType() == MSStageType::WAITING) {
487 : #ifdef DEBUG_PARKING
488 : std::cout << " add subsequent walk to reach stop\n";
489 : std::cout << " arrivalPos=" << nextStage->getArrivalPos() << "\n";
490 : #endif
491 5 : MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
492 5 : nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
493 5 : appendStage(newStage, 1);
494 : }
495 : // if the plan contains another ride with the same vehicle from the same
496 : // parking area, adapt the preceeding walk to end at the replacement
497 86 : for (auto it = myStep + 2; it != myPlan->end(); it++) {
498 55 : MSStage* const futureStage = *it;
499 55 : MSStage* const prevStage = *(it - 1);
500 55 : if (futureStage->getStageType() == MSStageType::DRIVING) {
501 : MSStageDriving* const ds = static_cast<MSStageDriving*>(futureStage);
502 : // ride origin is set implicitly from the walk destination
503 : ds->setOrigin(nullptr);
504 : if (ds->getLines() == stage->getLines()
505 10 : && prevStage->getDestination() == &orig->getLane().getEdge()) {
506 10 : if (prevStage->getStageType() == MSStageType::TRIP) {
507 5 : dynamic_cast<MSStageTrip*>(prevStage)->setDestination(stage->getDestination(), replacement);
508 : #ifdef DEBUG_PARKING
509 : std::cout << " replace later trip before ride (" << (it - myPlan->begin()) << ")\n";
510 : #endif
511 5 : } else if (prevStage->getStageType() == MSStageType::WALKING) {
512 : #ifdef DEBUG_PARKING
513 : std::cout << " replace later walk before ride (" << (it - myPlan->begin()) << ")\n";
514 : #endif
515 5 : MSStageTrip* newStage = new MSStageTrip(prevStage->getFromEdge(), nullptr, stage->getDestination(),
516 10 : replacement, -1, 0, "", -1, 1, getID(), 0, true, stage->getArrivalPos());
517 5 : int prevStageRelIndex = (int)(it - 1 - myStep);
518 5 : removeStage(prevStageRelIndex);
519 5 : appendStage(newStage, prevStageRelIndex);
520 : }
521 : break;
522 : }
523 : }
524 : }
525 : }
526 : }
527 :
528 :
529 : MSDevice*
530 702131 : MSTransportable::getDevice(const std::type_info& type) const {
531 1151243 : for (MSTransportableDevice* const dev : myDevices) {
532 972098 : if (typeid(*dev) == type) {
533 : return dev;
534 : }
535 : }
536 : return nullptr;
537 : }
538 :
539 :
540 : void
541 12 : MSTransportable::setJunctionModelParameter(const std::string& key, const std::string& value) {
542 30 : if (key == toString(SUMO_ATTR_JM_IGNORE_IDS) || key == toString(SUMO_ATTR_JM_IGNORE_TYPES)) {
543 6 : getParameter().parametersSet |= VEHPARS_JUNCTIONMODEL_PARAMS_SET;
544 6 : const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
545 : // checked in MSLink::ignoreFoe
546 : } else {
547 18 : throw InvalidArgument(getObjectType() + " '" + getID() + "' does not support junctionModel parameter '" + key + "'");
548 : }
549 6 : }
550 :
551 :
552 : double
553 0 : MSTransportable::getSlope() const {
554 0 : const MSEdge* edge = getEdge();
555 0 : const double ep = getEdgePos();
556 0 : const double gp = edge->getLanes()[0]->interpolateLanePosToGeometryPos(ep);
557 0 : return edge->getLanes()[0]->getShape().slopeDegreeAtOffset(gp);
558 : }
559 :
560 :
561 : SUMOTime
562 0 : MSTransportable::getWaitingTime(const bool /* accumulated */) const {
563 0 : return (*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep());
564 : }
565 :
566 :
567 : double
568 102175549 : MSTransportable::getMaxSpeed() const {
569 102175549 : return MIN2(getVehicleType().getMaxSpeed(), getVehicleType().getDesiredMaxSpeed() * getChosenSpeedFactor());
570 : }
571 :
572 :
573 : SUMOVehicleClass
574 1931395 : MSTransportable::getVClass() const {
575 1931395 : return getVehicleType().getVehicleClass();
576 : }
577 :
578 :
579 : int
580 0 : MSTransportable::getRoutingMode() const {
581 : /// @todo: allow configuring routing mode
582 0 : return libsumo::ROUTING_MODE_DEFAULT;
583 : }
584 :
585 : void
586 63 : MSTransportable::saveState(OutputDevice& out) {
587 : // this saves lots of departParameters which are only needed for transportables that did not yet depart
588 : // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
589 63 : myParameter->write(out, OptionsCont::getOptions(), myAmPerson ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, getVehicleType().getID());
590 63 : if (!myParameter->wasSet(VEHPARS_SPEEDFACTOR_SET) && getChosenSpeedFactor() != 1) {
591 60 : out.setPrecision(MAX2(gPrecisionRandom, gPrecision));
592 60 : out.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
593 60 : out.setPrecision(gPrecision);
594 : }
595 63 : int stepIdx = (int)(myStep - myPlan->begin());
596 147 : for (auto it = myPlan->begin(); it != myStep; ++it) {
597 84 : const MSStageType st = (*it)->getStageType();
598 84 : if (st == MSStageType::TRIP || st == MSStageType::ACCESS) {
599 27 : stepIdx--;
600 : }
601 : }
602 63 : std::ostringstream state;
603 126 : state << myParameter->parametersSet << " " << stepIdx;
604 63 : (*myStep)->saveState(state);
605 63 : out.writeAttr(SUMO_ATTR_STATE, state.str());
606 : const MSStage* previous = nullptr;
607 219 : for (const MSStage* const stage : *myPlan) {
608 156 : stage->routeOutput(myAmPerson, out, false, previous);
609 : previous = stage;
610 : }
611 63 : out.closeTag();
612 63 : }
613 :
614 :
615 : void
616 69 : MSTransportable::loadState(const std::string& state) {
617 69 : std::istringstream iss(state);
618 : int step;
619 69 : iss >> myParameter->parametersSet >> step;
620 69 : myStep = myPlan->begin() + step;
621 69 : (*myStep)->loadState(this, iss);
622 69 : }
623 :
624 :
625 : /****************************************************************************/
|