1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSTransportable.cpp
11 /// @author  Melanie Weber
12 /// @author  Andreas Kendziorra
13 /// @author  Michael Behrisch
14 /// @date    Thu, 12 Jun 2014
15 /// @version $Id$
16 ///
17 // The common superclass for modelling transportable objects like persons and containers
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <utils/common/StringTokenizer.h>
27 #include <utils/geom/GeomHelper.h>
28 #include <utils/vehicle/SUMOVehicleParameter.h>
29 #include <utils/router/PedestrianRouter.h>
30 #include <utils/router/IntermodalRouter.h>
31 #include "MSEdge.h"
32 #include "MSLane.h"
33 #include "MSNet.h"
34 #include <microsim/pedestrians/MSPerson.h>
35 #include <microsim/devices/MSTransportableDevice.h>
36 #include "MSVehicleControl.h"
37 #include "MSTransportableControl.h"
38 #include "MSTransportable.h"
39 
40 /* -------------------------------------------------------------------------
41 * static member definitions
42 * ----------------------------------------------------------------------- */
43 const double MSTransportable::ROADSIDE_OFFSET(3);
44 
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 /* -------------------------------------------------------------------------
50  * MSTransportable::Stage - methods
51  * ----------------------------------------------------------------------- */
Stage(const MSEdge * destination,MSStoppingPlace * toStop,const double arrivalPos,StageType type)52 MSTransportable::Stage::Stage(const MSEdge* destination, MSStoppingPlace* toStop, const double arrivalPos, StageType type)
53     : myDestination(destination), myDestinationStop(toStop), myArrivalPos(arrivalPos), myDeparted(-1), myArrived(-1), myType(type) {}
54 
~Stage()55 MSTransportable::Stage::~Stage() {}
56 
57 const MSEdge*
getDestination() const58 MSTransportable::Stage::getDestination() const {
59     return myDestination;
60 }
61 
62 
63 const MSEdge*
getEdge() const64 MSTransportable::Stage::getEdge() const {
65     return myDestination;
66 }
67 
68 
69 const MSEdge*
getFromEdge() const70 MSTransportable::Stage::getFromEdge() const {
71     return myDestination;
72 }
73 
74 
75 double
getEdgePos(SUMOTime) const76 MSTransportable::Stage::getEdgePos(SUMOTime /* now */) const {
77     return myArrivalPos;
78 }
79 
80 
81 SUMOTime
getWaitingTime(SUMOTime) const82 MSTransportable::Stage::getWaitingTime(SUMOTime /* now */) const {
83     return 0;
84 }
85 
86 
87 double
getSpeed() const88 MSTransportable::Stage::getSpeed() const {
89     return 0.;
90 }
91 
92 
93 ConstMSEdgeVector
getEdges() const94 MSTransportable::Stage::getEdges() const {
95     ConstMSEdgeVector result;
96     result.push_back(getDestination());
97     return result;
98 }
99 
100 
101 void
setDeparted(SUMOTime now)102 MSTransportable::Stage::setDeparted(SUMOTime now) {
103     if (myDeparted < 0) {
104         myDeparted = now;
105     }
106 }
107 
108 SUMOTime
getDeparted() const109 MSTransportable::Stage::getDeparted() const {
110     return myDeparted;
111 }
112 
113 void
setArrived(MSNet *,MSTransportable *,SUMOTime now)114 MSTransportable::Stage::setArrived(MSNet* /* net */, MSTransportable* /* transportable */, SUMOTime now) {
115     myArrived = now;
116 }
117 
118 bool
isWaitingFor(const SUMOVehicle *) const119 MSTransportable::Stage::isWaitingFor(const SUMOVehicle* /*vehicle*/) const {
120     return false;
121 }
122 
123 Position
getEdgePosition(const MSEdge * e,double at,double offset) const124 MSTransportable::Stage::getEdgePosition(const MSEdge* e, double at, double offset) const {
125     return getLanePosition(e->getLanes()[0], at, offset);
126 }
127 
128 Position
getLanePosition(const MSLane * lane,double at,double offset) const129 MSTransportable::Stage::getLanePosition(const MSLane* lane, double at, double offset) const {
130     return lane->getShape().positionAtOffset(lane->interpolateLanePosToGeometryPos(at), offset);
131 }
132 
133 double
getEdgeAngle(const MSEdge * e,double at) const134 MSTransportable::Stage::getEdgeAngle(const MSEdge* e, double at) const {
135     return e->getLanes()[0]->getShape().rotationAtOffset(at);
136 }
137 
138 
139 void
setDestination(const MSEdge * newDestination,MSStoppingPlace * newDestStop)140 MSTransportable::Stage::setDestination(const MSEdge* newDestination, MSStoppingPlace* newDestStop) {
141     myDestination = newDestination;
142     myDestinationStop = newDestStop;
143     if (newDestStop != nullptr) {
144         myArrivalPos = (newDestStop->getBeginLanePosition() + newDestStop->getEndLanePosition()) / 2;
145     }
146 }
147 
148 
149 
150 /* -------------------------------------------------------------------------
151 * MSTransportable::Stage_Trip - methods
152 * ----------------------------------------------------------------------- */
Stage_Trip(const MSEdge * origin,MSStoppingPlace * fromStop,const MSEdge * destination,MSStoppingPlace * toStop,const SUMOTime duration,const SVCPermissions modeSet,const std::string & vTypes,const double speed,const double walkFactor,const double departPosLat,const bool hasArrivalPos,const double arrivalPos)153 MSTransportable::Stage_Trip::Stage_Trip(const MSEdge* origin, MSStoppingPlace* fromStop,
154                                         const MSEdge* destination, MSStoppingPlace* toStop,
155                                         const SUMOTime duration, const SVCPermissions modeSet,
156                                         const std::string& vTypes, const double speed, const double walkFactor,
157                                         const double departPosLat, const bool hasArrivalPos, const double arrivalPos):
158     MSTransportable::Stage(destination, toStop, arrivalPos, TRIP),
159     myOrigin(origin),
160     myOriginStop(fromStop),
161     myDuration(duration),
162     myModeSet(modeSet),
163     myVTypes(vTypes),
164     mySpeed(speed),
165     myWalkFactor(walkFactor),
166     myDepartPosLat(departPosLat),
167     myHaveArrivalPos(hasArrivalPos) {
168 }
169 
170 
~Stage_Trip()171 MSTransportable::Stage_Trip::~Stage_Trip() {}
172 
173 MSTransportable::Stage*
clone() const174 MSTransportable::Stage_Trip::clone() const {
175     return new Stage_Trip(myOrigin, const_cast<MSStoppingPlace*>(myOriginStop),
176                           myDestination, myDestinationStop, myDuration,
177                           myModeSet, myVTypes, mySpeed, myWalkFactor, myDepartPosLat, myHaveArrivalPos, myArrivalPos);
178 }
179 
180 
181 Position
getPosition(SUMOTime) const182 MSTransportable::Stage_Trip::getPosition(SUMOTime /* now */) const {
183     throw ProcessError("Should not get here!");
184 }
185 
186 
187 double
getAngle(SUMOTime) const188 MSTransportable::Stage_Trip::getAngle(SUMOTime /* now */) const {
189     throw ProcessError("Should not get here!");
190 }
191 
192 
193 const MSEdge*
getEdge() const194 MSTransportable::Stage_Trip::getEdge() const {
195     return myOrigin;
196 }
197 
198 
199 double
getEdgePos(SUMOTime) const200 MSTransportable::Stage_Trip::getEdgePos(SUMOTime /* now */) const {
201     return myDepartPos;
202 }
203 
204 
205 void
setArrived(MSNet * net,MSTransportable * transportable,SUMOTime now)206 MSTransportable::Stage_Trip::setArrived(MSNet* net, MSTransportable* transportable, SUMOTime now) {
207     MSTransportable::Stage::setArrived(net, transportable, now);
208     MSVehicleControl& vehControl = net->getVehicleControl();
209     std::vector<SUMOVehicleParameter*> pars;
210     for (StringTokenizer st(myVTypes); st.hasNext();) {
211         pars.push_back(new SUMOVehicleParameter());
212         pars.back()->vtypeid = st.next();
213         pars.back()->parametersSet |= VEHPARS_VTYPE_SET;
214         pars.back()->departProcedure = DEPART_TRIGGERED;
215         pars.back()->id = transportable->getID() + "_" + toString(pars.size() - 1);
216     }
217     if (pars.empty()) {
218         if ((myModeSet & SVC_PASSENGER) != 0) {
219             pars.push_back(new SUMOVehicleParameter());
220             pars.back()->id = transportable->getID() + "_0";
221             pars.back()->departProcedure = DEPART_TRIGGERED;
222         } else if ((myModeSet & SVC_BICYCLE) != 0) {
223             pars.push_back(new SUMOVehicleParameter());
224             pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
225             pars.back()->id = transportable->getID() + "_b0";
226             pars.back()->departProcedure = DEPART_TRIGGERED;
227         } else {
228             // allow shortcut via busStop even when not intending to ride
229             pars.push_back(nullptr);
230         }
231     }
232     MSTransportable::Stage* previous;
233     SUMOTime time = MSNet::getInstance()->getCurrentTimeStep();
234     if (transportable->getNumStages() == transportable->getNumRemainingStages()) { // this is a difficult way to check that we are the first stage
235         myDepartPos = transportable->getParameter().departPos;
236         if (transportable->getParameter().departPosProcedure == DEPART_POS_RANDOM) {
237             myDepartPos = RandHelper::rand(myOrigin->getLength());
238         }
239         previous = new MSTransportable::Stage_Waiting(myOrigin, nullptr, -1, transportable->getParameter().depart, myDepartPos, "start", true);
240         time = transportable->getParameter().depart;
241     } else {
242         previous = transportable->getNextStage(-1);
243         myDepartPos = previous->getArrivalPos();
244     }
245     // TODO This works currently only for a single vehicle type
246     for (SUMOVehicleParameter* vehPar : pars) {
247         SUMOVehicle* vehicle = nullptr;
248         if (vehPar != nullptr) {
249             MSVehicleType* type = vehControl.getVType(vehPar->vtypeid);
250             if (type->getVehicleClass() != SVC_IGNORING && (myOrigin->getPermissions() & type->getVehicleClass()) == 0) {
251                 WRITE_WARNING("Ignoring vehicle type '" + type->getID() + "' when routing person '" + transportable->getID() + "' because it is not allowed on the start edge.");
252             } else {
253                 const MSRoute* const routeDummy = new MSRoute(vehPar->id, ConstMSEdgeVector({ myOrigin }), false, nullptr, std::vector<SUMOVehicleParameter::Stop>());
254                 vehicle = vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes);
255             }
256         }
257         bool carUsed = false;
258         std::vector<MSNet::MSIntermodalRouter::TripItem> result;
259         int stageIndex = 1;
260         if (net->getIntermodalRouter().compute(myOrigin, myDestination, previous->getArrivalPos(), myArrivalPos, myDestinationStop == nullptr ? "" : myDestinationStop->getID(),
261                                                transportable->getVehicleType().getMaxSpeed() * myWalkFactor, vehicle, myModeSet, time, result)) {
262             for (std::vector<MSNet::MSIntermodalRouter::TripItem>::iterator it = result.begin(); it != result.end(); ++it) {
263                 if (!it->edges.empty()) {
264                     MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(it->destStop, SUMO_TAG_BUS_STOP);
265                     double localArrivalPos = bs != nullptr ? bs->getAccessPos(it->edges.back()) : it->edges.back()->getLength() / 2.;
266                     if (it + 1 == result.end() && myHaveArrivalPos) {
267                         localArrivalPos = myArrivalPos;
268                     }
269                     if (it->line == "") {
270                         double depPos = previous->getArrivalPos();
271                         if (previous->getDestinationStop() != nullptr) {
272                             depPos = previous->getDestinationStop()->getAccessPos(it->edges.front());
273                         } else if (previous->getEdge() != it->edges.front()) {
274 //                            if (previous->getEdge()->getToJunction() == it->edges.front()->getToJunction()) {
275 //                                depPos = it->edges.front()->getLength();
276 //                            } else {
277                             depPos = 0.;
278 //                            }
279                         }
280                         previous = new MSPerson::MSPersonStage_Walking(transportable->getID(), it->edges, bs, myDuration, mySpeed, depPos, localArrivalPos, myDepartPosLat);
281                         transportable->appendStage(previous, stageIndex++);
282                     } else if (vehicle != nullptr && it->line == vehicle->getID()) {
283                         if (bs == nullptr && it + 1 != result.end()) {
284                             // we have no defined endpoint and are in the middle of the trip, drive as far as possible
285                             localArrivalPos = it->edges.back()->getLength();
286                         }
287                         previous = new MSPerson::MSPersonStage_Driving(it->edges.back(), bs, localArrivalPos, std::vector<std::string>({ it->line }));
288                         transportable->appendStage(previous, stageIndex++);
289                         vehicle->replaceRouteEdges(it->edges, -1, 0, "person:" + transportable->getID(), true);
290                         vehicle->setArrivalPos(localArrivalPos);
291                         vehControl.addVehicle(vehPar->id, vehicle);
292                         carUsed = true;
293                     } else {
294                         previous = new MSPerson::MSPersonStage_Driving(it->edges.back(), bs, localArrivalPos, std::vector<std::string>({ it->line }), it->intended, TIME2STEPS(it->depart));
295                         transportable->appendStage(previous, stageIndex++);
296                     }
297                 }
298             }
299         } else {
300             // append stage so the GUI won't crash due to inconsistent state
301             transportable->appendStage(new MSPerson::MSPersonStage_Walking(transportable->getID(), ConstMSEdgeVector({ myOrigin, myDestination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat), stageIndex++);
302             if (MSGlobals::gCheckRoutes) {
303                 const std::string error = "No connection found between edge '" + myOrigin->getID() + "' and edge '" + (myDestinationStop != nullptr ? myDestinationStop->getID() : myDestination->getID()) + "' for person '" + transportable->getID() + "'.";
304                 transportable->myStep++;
305                 throw ProcessError(error);
306             } else {
307                 // pedestrian will teleport
308             }
309         }
310         if (vehicle != nullptr && !carUsed) {
311             vehControl.deleteVehicle(vehicle, true);
312         }
313     }
314 }
315 
316 
317 void
proceed(MSNet * net,MSTransportable * transportable,SUMOTime now,Stage *)318 MSTransportable::Stage_Trip::proceed(MSNet* net, MSTransportable* transportable, SUMOTime now, Stage* /* previous */) {
319     // just skip the stage, every interesting happens in setArrived
320     transportable->proceed(net, now);
321 }
322 
323 
324 void
tripInfoOutput(OutputDevice &,const MSTransportable * const) const325 MSTransportable::Stage_Trip::tripInfoOutput(OutputDevice&, const MSTransportable* const) const {
326 }
327 
328 
329 void
routeOutput(OutputDevice &,const bool) const330 MSTransportable::Stage_Trip::routeOutput(OutputDevice&, const bool /* withRouteLength */) const {
331 }
332 
333 
334 void
beginEventOutput(const MSTransportable &,SUMOTime,OutputDevice &) const335 MSTransportable::Stage_Trip::beginEventOutput(const MSTransportable&, SUMOTime, OutputDevice&) const {
336 }
337 
338 
339 void
endEventOutput(const MSTransportable &,SUMOTime,OutputDevice &) const340 MSTransportable::Stage_Trip::endEventOutput(const MSTransportable&, SUMOTime, OutputDevice&) const {
341 }
342 
343 
344 std::string
getStageSummary() const345 MSTransportable::Stage_Trip::getStageSummary() const {
346     return "trip from '" + myOrigin->getID() + "' to '" + getDestination()->getID() + "'";
347 }
348 
349 
350 
351 /* -------------------------------------------------------------------------
352 * MSTransportable::Stage_Waiting - methods
353 * ----------------------------------------------------------------------- */
Stage_Waiting(const MSEdge * destination,MSStoppingPlace * toStop,SUMOTime duration,SUMOTime until,double pos,const std::string & actType,const bool initial)354 MSTransportable::Stage_Waiting::Stage_Waiting(const MSEdge* destination, MSStoppingPlace* toStop,
355         SUMOTime duration, SUMOTime until, double pos, const std::string& actType,
356         const bool initial) :
357     MSTransportable::Stage(destination, toStop, SUMOVehicleParameter::interpretEdgePos(
358                                pos, destination->getLength(), SUMO_ATTR_DEPARTPOS, "stopping at " + destination->getID()),
359                            initial ? WAITING_FOR_DEPART : WAITING),
360     myWaitingDuration(duration),
361     myWaitingUntil(until),
362     myActType(actType) {
363 }
364 
365 
~Stage_Waiting()366 MSTransportable::Stage_Waiting::~Stage_Waiting() {}
367 
368 MSTransportable::Stage*
clone() const369 MSTransportable::Stage_Waiting::clone() const {
370     return new Stage_Waiting(myDestination, myDestinationStop, myWaitingDuration, myWaitingUntil, myArrivalPos, myActType, myType == WAITING_FOR_DEPART);
371 }
372 
373 SUMOTime
getUntil() const374 MSTransportable::Stage_Waiting::getUntil() const {
375     return myWaitingUntil;
376 }
377 
378 
379 Position
getPosition(SUMOTime) const380 MSTransportable::Stage_Waiting::getPosition(SUMOTime /* now */) const {
381     return getEdgePosition(myDestination, myArrivalPos,
382                            ROADSIDE_OFFSET * (MSNet::getInstance()->lefthand() ? -1 : 1));
383 }
384 
385 
386 double
getAngle(SUMOTime) const387 MSTransportable::Stage_Waiting::getAngle(SUMOTime /* now */) const {
388     return getEdgeAngle(myDestination, myArrivalPos) + M_PI / 2 * (MSNet::getInstance()->lefthand() ? -1 : 1);
389 }
390 
391 
392 void
proceed(MSNet * net,MSTransportable * transportable,SUMOTime now,Stage * previous)393 MSTransportable::Stage_Waiting::proceed(MSNet* net, MSTransportable* transportable, SUMOTime now, Stage* previous) {
394     myDeparted = now;
395     const SUMOTime until = MAX3(now, now + myWaitingDuration, myWaitingUntil);
396     if (myDestinationStop != nullptr) {
397         myDestinationStop->addTransportable(transportable);
398     }
399     if (dynamic_cast<MSPerson*>(transportable) != nullptr) {
400         previous->getEdge()->addPerson(transportable);
401         net->getPersonControl().setWaitEnd(until, transportable);
402     } else {
403         previous->getEdge()->addContainer(transportable);
404         net->getContainerControl().setWaitEnd(until, transportable);
405     }
406 }
407 
408 
409 void
tripInfoOutput(OutputDevice & os,const MSTransportable * const) const410 MSTransportable::Stage_Waiting::tripInfoOutput(OutputDevice& os, const MSTransportable* const) const {
411     if (myType != WAITING_FOR_DEPART) {
412         os.openTag("stop");
413         os.writeAttr("duration", time2string(myArrived - myDeparted));
414         os.writeAttr("arrival", time2string(myArrived));
415         os.writeAttr("arrivalPos", toString(myArrivalPos));
416         os.writeAttr("actType", toString(myActType));
417         os.closeTag();
418     }
419 }
420 
421 
422 void
routeOutput(OutputDevice & os,const bool) const423 MSTransportable::Stage_Waiting::routeOutput(OutputDevice& os, const bool /* withRouteLength */) const {
424     if (myType != WAITING_FOR_DEPART) {
425         // lane index is arbitrary
426         os.openTag("stop").writeAttr(SUMO_ATTR_LANE, getDestination()->getID() + "_0");
427         if (myWaitingDuration >= 0) {
428             os.writeAttr(SUMO_ATTR_DURATION, time2string(myWaitingDuration));
429         }
430         if (myWaitingUntil >= 0) {
431             os.writeAttr(SUMO_ATTR_UNTIL, time2string(myWaitingUntil));
432         }
433         os.closeTag();
434     }
435 }
436 
437 
438 void
beginEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const439 MSTransportable::Stage_Waiting::beginEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
440     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "actstart " + myActType)
441     .writeAttr("agent", p.getID()).writeAttr("link", getEdge()->getID()).closeTag();
442 }
443 
444 
445 void
endEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const446 MSTransportable::Stage_Waiting::endEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
447     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "actend " + myActType).writeAttr("agent", p.getID())
448     .writeAttr("link", getEdge()->getID()).closeTag();
449 }
450 
451 
452 SUMOTime
getWaitingTime(SUMOTime now) const453 MSTransportable::Stage_Waiting::getWaitingTime(SUMOTime now) const {
454     return now - myDeparted;
455 }
456 
457 
458 void
abort(MSTransportable * t)459 MSTransportable::Stage_Waiting::abort(MSTransportable* t) {
460     MSTransportableControl& tc = (dynamic_cast<MSPerson*>(t) != nullptr ?
461                                   MSNet::getInstance()->getPersonControl() :
462                                   MSNet::getInstance()->getContainerControl());
463     tc.abortWaiting(t);
464 }
465 
466 
467 std::string
getStageSummary() const468 MSTransportable::Stage_Waiting::getStageSummary() const {
469     std::string timeInfo;
470     if (myWaitingUntil >= 0) {
471         timeInfo += " until " + time2string(myWaitingUntil);
472     }
473     if (myWaitingDuration >= 0) {
474         timeInfo += " duration " + time2string(myWaitingDuration);
475     }
476     return "stopping at edge '" + getDestination()->getID() + "' " + timeInfo + " (" + myActType + ")";
477 }
478 
479 
480 /* -------------------------------------------------------------------------
481 * MSTransportable::Stage_Driving - methods
482 * ----------------------------------------------------------------------- */
Stage_Driving(const MSEdge * destination,MSStoppingPlace * toStop,const double arrivalPos,const std::vector<std::string> & lines,const std::string & intendedVeh,SUMOTime intendedDepart)483 MSTransportable::Stage_Driving::Stage_Driving(const MSEdge* destination,
484         MSStoppingPlace* toStop, const double arrivalPos, const std::vector<std::string>& lines,
485         const std::string& intendedVeh, SUMOTime intendedDepart) :
486     MSTransportable::Stage(destination, toStop, arrivalPos, DRIVING),
487     myLines(lines.begin(), lines.end()),
488     myVehicle(nullptr),
489     myVehicleID("NULL"),
490     myVehicleDistance(-1.),
491     myWaitingEdge(nullptr),
492     myStopWaitPos(Position::INVALID),
493     myIntendedVehicleID(intendedVeh),
494     myIntendedDepart(intendedDepart) {
495 }
496 
497 
~Stage_Driving()498 MSTransportable::Stage_Driving::~Stage_Driving() {}
499 
500 const MSEdge*
getEdge() const501 MSTransportable::Stage_Driving::getEdge() const {
502     if (myVehicle != nullptr) {
503         if (myVehicle->getLane() != nullptr) {
504             return &myVehicle->getLane()->getEdge();
505         }
506         return myVehicle->getEdge();
507     }
508     return myWaitingEdge;
509 }
510 
511 
512 const MSEdge*
getFromEdge() const513 MSTransportable::Stage_Driving::getFromEdge() const {
514     return myWaitingEdge;
515 }
516 
517 
518 double
getEdgePos(SUMOTime) const519 MSTransportable::Stage_Driving::getEdgePos(SUMOTime /* now */) const {
520     if (isWaiting4Vehicle()) {
521         return myWaitingPos;
522     }
523     // vehicle may already have passed the lane (check whether this is correct)
524     return MIN2(myVehicle->getPositionOnLane(), getEdge()->getLength());
525 }
526 
527 
528 Position
getPosition(SUMOTime) const529 MSTransportable::Stage_Driving::getPosition(SUMOTime /* now */) const {
530     if (isWaiting4Vehicle()) {
531         if (myStopWaitPos != Position::INVALID) {
532             return myStopWaitPos;
533         }
534         return getEdgePosition(myWaitingEdge, myWaitingPos,
535                                ROADSIDE_OFFSET * (MSNet::getInstance()->lefthand() ? -1 : 1));
536     }
537     return myVehicle->getPosition();
538 }
539 
540 
541 double
getAngle(SUMOTime) const542 MSTransportable::Stage_Driving::getAngle(SUMOTime /* now */) const {
543     if (!isWaiting4Vehicle()) {
544         MSVehicle* veh = dynamic_cast<MSVehicle*>(myVehicle);
545         if (veh != nullptr) {
546             return veh->getAngle();
547         } else {
548             return 0;
549         }
550     }
551     return getEdgeAngle(myWaitingEdge, myWaitingPos) + M_PI / 2. * (MSNet::getInstance()->lefthand() ? -1 : 1);
552 }
553 
554 
555 bool
isWaitingFor(const SUMOVehicle * vehicle) const556 MSTransportable::Stage_Driving::isWaitingFor(const SUMOVehicle* vehicle) const {
557     return (myLines.count(vehicle->getID()) > 0
558             || myLines.count(vehicle->getParameter().line) > 0
559             || (myLines.count("ANY") > 0 && vehicle->stopsAt(myDestinationStop)));
560 }
561 
562 
563 bool
isWaiting4Vehicle() const564 MSTransportable::Stage_Driving::isWaiting4Vehicle() const {
565     return myVehicle == nullptr;
566 }
567 
568 
569 SUMOTime
getWaitingTime(SUMOTime now) const570 MSTransportable::Stage_Driving::getWaitingTime(SUMOTime now) const {
571     return isWaiting4Vehicle() ? now - myWaitingSince : 0;
572 }
573 
574 
575 double
getSpeed() const576 MSTransportable::Stage_Driving::getSpeed() const {
577     return isWaiting4Vehicle() ? 0 : myVehicle->getSpeed();
578 }
579 
580 
581 ConstMSEdgeVector
getEdges() const582 MSTransportable::Stage_Driving::getEdges() const {
583     ConstMSEdgeVector result;
584     result.push_back(getFromEdge());
585     result.push_back(getDestination());
586     return result;
587 }
588 
589 void
setArrived(MSNet * net,MSTransportable * transportable,SUMOTime now)590 MSTransportable::Stage_Driving::setArrived(MSNet* net, MSTransportable* transportable, SUMOTime now) {
591     MSTransportable::Stage::setArrived(net, transportable, now);
592     if (myVehicle != nullptr) {
593         // distance was previously set to driven distance upon embarking
594         myVehicleDistance = myVehicle->getRoute().getDistanceBetween(
595                                 myVehicle->getDepartPos(), myVehicle->getPositionOnLane(),
596                                 myVehicle->getRoute().begin(),  myVehicle->getCurrentRouteEdge()) - myVehicleDistance;
597         if (myVehicle->isStopped()) {
598             myArrivalPos = myVehicle->getPositionOnLane();
599         }
600     } else {
601         myVehicleDistance = -1.;
602     }
603 }
604 
605 void
setVehicle(SUMOVehicle * v)606 MSTransportable::Stage_Driving::setVehicle(SUMOVehicle* v) {
607     myVehicle = v;
608     myVehicleID = v->getID();
609     myVehicleLine = v->getParameter().line;
610     myVehicleVClass = v->getVClass();
611     myVehicleDistance = myVehicle->getRoute().getDistanceBetween(
612                             myVehicle->getDepartPos(), myVehicle->getPositionOnLane(),
613                             myVehicle->getRoute().begin(),  myVehicle->getCurrentRouteEdge());
614 }
615 
616 void
abort(MSTransportable * t)617 MSTransportable::Stage_Driving::abort(MSTransportable* t) {
618     if (myVehicle != nullptr) {
619         // jumping out of a moving vehicle!
620         dynamic_cast<MSVehicle*>(myVehicle)->removeTransportable(t);
621     }
622 }
623 
624 
625 std::string
getWaitingDescription() const626 MSTransportable::Stage_Driving::getWaitingDescription() const {
627     return isWaiting4Vehicle() ? ("waiting for " + joinToString(myLines, ",")
628                                   + " at " + (myDestinationStop == nullptr
629                                           ? ("edge '" + myWaitingEdge->getID() + "'")
630                                           : ("busStop '" + myDestinationStop->getID() + "'"))
631                                  ) : "";
632 }
633 
634 
635 void
beginEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const636 MSTransportable::Stage_Driving::beginEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
637     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "arrival").writeAttr("agent", p.getID()).writeAttr("link", getEdge()->getID()).closeTag();
638 }
639 
640 
641 void
endEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const642 MSTransportable::Stage_Driving::endEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
643     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "arrival").writeAttr("agent", p.getID()).writeAttr("link", getEdge()->getID()).closeTag();
644 }
645 
646 
647 
648 /* -------------------------------------------------------------------------
649  * MSTransportable - methods
650  * ----------------------------------------------------------------------- */
MSTransportable(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportablePlan * plan)651 MSTransportable::MSTransportable(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportablePlan* plan)
652     : myParameter(pars), myVType(vtype), myPlan(plan) {
653     myStep = myPlan->begin();
654     // init devices
655     MSDevice::buildTransportableDevices(*this, myDevices);
656 }
657 
658 
~MSTransportable()659 MSTransportable::~MSTransportable() {
660     if (myStep != myPlan->end() && getCurrentStageType() == DRIVING) {
661         Stage_Driving* const stage = dynamic_cast<Stage_Driving*>(*myStep);
662         if (stage->getVehicle() != nullptr) {
663             stage->getVehicle()->removeTransportable(this);
664         }
665     }
666     if (myPlan != nullptr) {
667         for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
668             delete *i;
669         }
670         delete myPlan;
671         myPlan = nullptr;
672     }
673     delete myParameter;
674     if (myVType->isVehicleSpecific()) {
675         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
676     }
677 }
678 
679 const std::string&
getID() const680 MSTransportable::getID() const {
681     return myParameter->id;
682 }
683 
684 SUMOTime
getDesiredDepart() const685 MSTransportable::getDesiredDepart() const {
686     return myParameter->depart;
687 }
688 
689 void
setDeparted(SUMOTime now)690 MSTransportable::setDeparted(SUMOTime now) {
691     (*myStep)->setDeparted(now);
692 }
693 
694 double
getEdgePos() const695 MSTransportable::getEdgePos() const {
696     return (*myStep)->getEdgePos(MSNet::getInstance()->getCurrentTimeStep());
697 }
698 
699 Position
getPosition() const700 MSTransportable::getPosition() const {
701     return (*myStep)->getPosition(MSNet::getInstance()->getCurrentTimeStep());
702 }
703 
704 double
getAngle() const705 MSTransportable::getAngle() const {
706     return (*myStep)->getAngle(MSNet::getInstance()->getCurrentTimeStep());
707 }
708 
709 double
getWaitingSeconds() const710 MSTransportable::getWaitingSeconds() const {
711     return STEPS2TIME((*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep()));
712 }
713 
714 double
getSpeed() const715 MSTransportable::getSpeed() const {
716     return (*myStep)->getSpeed();
717 }
718 
719 
720 int
getNumRemainingStages() const721 MSTransportable::getNumRemainingStages() const {
722     return (int)(myPlan->end() - myStep);
723 }
724 
725 int
getNumStages() const726 MSTransportable::getNumStages() const {
727     return (int)myPlan->size();
728 }
729 
730 void
appendStage(Stage * stage,int next)731 MSTransportable::appendStage(Stage* stage, int next) {
732     // myStep is invalidated upon modifying myPlan
733     const int stepIndex = (int)(myStep - myPlan->begin());
734     if (next < 0) {
735         myPlan->push_back(stage);
736     } else {
737         if (stepIndex + next > (int)myPlan->size()) {
738             throw ProcessError("invalid index '" + toString(next) + "' for inserting new stage into plan of '" + getID() + "'");
739         }
740         myPlan->insert(myPlan->begin() + stepIndex + next, stage);
741     }
742     myStep = myPlan->begin() + stepIndex;
743 }
744 
745 
746 void
removeStage(int next)747 MSTransportable::removeStage(int next) {
748     assert(myStep + next < myPlan->end());
749     assert(next >= 0);
750     if (next > 0) {
751         // myStep is invalidated upon modifying myPlan
752         int stepIndex = (int)(myStep - myPlan->begin());
753         delete *(myStep + next);
754         myPlan->erase(myStep + next);
755         myStep = myPlan->begin() + stepIndex;
756     } else {
757         if (myStep + 1 == myPlan->end()) {
758             // stay in the simulation until the start of simStep to allow appending new stages (at the correct position)
759             appendStage(new Stage_Waiting(getEdge(), nullptr, 0, 0, getEdgePos(), "last stage removed", false));
760         }
761         (*myStep)->abort(this);
762         proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep());
763     }
764 }
765 
766 
767 void
setSpeed(double speed)768 MSTransportable::setSpeed(double speed) {
769     for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
770         (*i)->setSpeed(speed);
771     }
772 }
773 
774 
775 void
replaceVehicleType(MSVehicleType * type)776 MSTransportable::replaceVehicleType(MSVehicleType* type) {
777     if (myVType->isVehicleSpecific()) {
778         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
779     }
780     myVType = type;
781 }
782 
783 
784 MSVehicleType&
getSingularType()785 MSTransportable::getSingularType() {
786     if (myVType->isVehicleSpecific()) {
787         return *myVType;
788     }
789     MSVehicleType* type = myVType->buildSingularType(myVType->getID() + "@" + getID());
790     replaceVehicleType(type);
791     return *type;
792 }
793 
794 
795 PositionVector
getBoundingBox() const796 MSTransportable::getBoundingBox() const {
797     PositionVector centerLine;
798     const Position p = getPosition();
799     const double angle = getAngle();
800     const double length = getVehicleType().getLength();
801     const Position back = p + Position(-cos(angle) * length, -sin(angle) * length);
802     centerLine.push_back(p);
803     centerLine.push_back(back);
804     centerLine.move2side(0.5 * getVehicleType().getWidth());
805     PositionVector result = centerLine;
806     centerLine.move2side(-getVehicleType().getWidth());
807     result.append(centerLine.reverse(), POSITION_EPS);
808     //std::cout << " transp=" << getID() << " p=" << p << " angle=" << GeomHelper::naviDegree(angle) << " back=" << back << " result=" << result << "\n";
809     return result;
810 }
811 
812 
813 std::string
getStageSummary(int stageIndex) const814 MSTransportable::getStageSummary(int stageIndex) const {
815     assert(stageIndex < (int)myPlan->size());
816     assert(stageIndex >= 0);
817     return (*myPlan)[stageIndex]->getStageSummary();
818 }
819 
820 
821 bool
hasArrived() const822 MSTransportable::hasArrived() const {
823     return myStep == myPlan->end();
824 }
825 
826 bool
hasDeparted() const827 MSTransportable::hasDeparted() const {
828     return myPlan->size() > 0 && myPlan->front()->getDeparted() >= 0;
829 }
830 
831 
832 void
rerouteParkingArea(MSStoppingPlace * orig,MSStoppingPlace * replacement)833 MSTransportable::rerouteParkingArea(MSStoppingPlace* orig, MSStoppingPlace* replacement) {
834     // check whether the transportable was riding to the orignal stop
835     // @note: parkingArea can currently not be set as myDestinationStop so we
836     // check for stops on the edge instead
837     assert(getCurrentStageType() == DRIVING);
838     if (dynamic_cast<MSPerson*>(this) == nullptr) {
839         WRITE_WARNING("parkingAreaReroute not support for containers");
840         return;
841     }
842     if (getDestination() == &orig->getLane().getEdge()) {
843         Stage_Driving* const stage = dynamic_cast<Stage_Driving*>(*myStep);
844         assert(stage != 0);
845         assert(stage->getVehicle() != 0);
846         // adapt plan
847         stage->setDestination(&replacement->getLane().getEdge(), replacement);
848         if (myStep + 1 == myPlan->end()) {
849             return;
850         }
851         // if the next step is a walk, adapt the route
852         Stage* nextStage = *(myStep + 1);
853         if (nextStage->getStageType() == TRIP) {
854             dynamic_cast<MSTransportable::Stage_Trip*>(nextStage)->setOrigin(stage->getDestination());
855         } else if (nextStage->getStageType() == MOVING_WITHOUT_VEHICLE) {
856             Stage_Trip* newStage = new Stage_Trip(stage->getDestination(), nullptr, nextStage->getDestination(),
857                                                   nextStage->getDestinationStop(), -1, 0, "", -1, 1, 0, true, nextStage->getArrivalPos());
858             removeStage(1);
859             appendStage(newStage, 1);
860         }
861         // if the plan contains another ride with the same vehicle from the same
862         // parking area, adapt the preceeding walk to end at the replacement
863         // (ride origin is set implicitly from the walk destination)
864         for (auto it = myStep + 2; it != myPlan->end(); it++) {
865             const Stage* const futureStage = *it;
866             Stage* const prevStage = *(it - 1);
867             if (futureStage->getStageType() == DRIVING) {
868                 const MSPerson::MSPersonStage_Driving* const ds = dynamic_cast<const MSPerson::MSPersonStage_Driving* const>(futureStage);
869                 if (ds->getLines() == stage->getLines()
870                         && prevStage->getDestination() == &orig->getLane().getEdge()) {
871                     if (prevStage->getStageType() == TRIP) {
872                         dynamic_cast<MSTransportable::Stage_Trip*>(prevStage)->setDestination(stage->getDestination(), replacement);
873                     } else if (prevStage->getStageType() == MOVING_WITHOUT_VEHICLE) {
874                         Stage_Trip* newStage = new Stage_Trip(prevStage->getFromEdge(), nullptr, stage->getDestination(),
875                                                               replacement, -1, 0, "", -1, 1, 0, true, stage->getArrivalPos());
876                         int prevStageRelIndex = (int)(it - 1 - myStep);
877                         removeStage(prevStageRelIndex);
878                         appendStage(newStage, prevStageRelIndex);
879                     }
880                     break;
881                 }
882             }
883         }
884     }
885 }
886 
887 MSTransportableDevice*
getDevice(const std::type_info & type) const888 MSTransportable::getDevice(const std::type_info& type) const {
889     for (MSTransportableDevice* const dev : myDevices) {
890         if (typeid(*dev) == type) {
891             return dev;
892         }
893     }
894     return nullptr;
895 }
896 
897 double
getSlope() const898 MSTransportable::getSlope() const {
899     const MSEdge* edge = getEdge();
900     const double ep = getEdgePos();
901     const double gp = edge->getLanes()[0]->interpolateLanePosToGeometryPos(ep);
902     return edge->getLanes()[0]->getShape().slopeDegreeAtOffset(gp);
903 }
904 
905 SUMOTime
getWaitingTime() const906 MSTransportable::getWaitingTime() const {
907     return (*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep());
908 }
909 
910 double
getMaxSpeed() const911 MSTransportable::getMaxSpeed() const {
912     return getVehicleType().getMaxSpeed();
913 }
914 
915 SUMOVehicleClass
getVClass() const916 MSTransportable::getVClass() const {
917     return getVehicleType().getVehicleClass();
918 }
919 
920 /****************************************************************************/
921