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    MSPerson.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @author  Laura Bieker
15 /// @date    Mon, 9 Jul 2001
16 /// @version $Id$
17 ///
18 // The class for modelling person-movements
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <vector>
29 #include <utils/iodevices/OutputDevice.h>
30 #include <utils/options/OptionsCont.h>
31 #include <utils/common/ToString.h>
32 #include <utils/common/StringUtils.h>
33 #include <utils/geom/GeomHelper.h>
34 #include <utils/router/IntermodalNetwork.h>
35 #include <microsim/MSNet.h>
36 #include <microsim/MSEdge.h>
37 #include <microsim/MSLane.h>
38 #include "MSPerson.h"
39 #include <microsim/MSTransportableControl.h>
40 #include <microsim/MSInsertionControl.h>
41 #include <microsim/MSEventControl.h>
42 #include <microsim/MSVehicle.h>
43 #include <microsim/MSVehicleControl.h>
44 #include <microsim/MSStoppingPlace.h>
45 #include <microsim/devices/MSDevice_Tripinfo.h>
46 #include "MSPModel.h"
47 
48 // ===========================================================================
49 // static value definitions
50 // ===========================================================================
51 DummyState MSPerson::myDummyState;
52 
53 /* -------------------------------------------------------------------------
54  * MSPerson::MSPersonStage_Walking - methods
55  * ----------------------------------------------------------------------- */
MSPersonStage_Walking(const std::string & personID,const ConstMSEdgeVector & route,MSStoppingPlace * toStop,SUMOTime walkingTime,double speed,double departPos,double arrivalPos,double departPosLat)56 MSPerson::MSPersonStage_Walking::MSPersonStage_Walking(const std::string& personID,
57         const ConstMSEdgeVector& route,
58         MSStoppingPlace* toStop,
59         SUMOTime walkingTime, double speed,
60         double departPos, double arrivalPos, double departPosLat) :
61     MSTransportable::Stage(route.back(), toStop,
62                            SUMOVehicleParameter::interpretEdgePos(arrivalPos, route.back()->getLength(), SUMO_ATTR_ARRIVALPOS,
63                                    "person '" + personID + "' walking to " + route.back()->getID()),
64                            MOVING_WITHOUT_VEHICLE),
65     myWalkingTime(walkingTime),
66     myRoute(route),
67     myCurrentInternalEdge(nullptr),
68     myDepartPos(departPos),
69     myDepartPosLat(departPosLat),
70     mySpeed(speed),
71     myPedestrianState(&myDummyState) {
72     myDepartPos = SUMOVehicleParameter::interpretEdgePos(departPos, route.front()->getLength(), SUMO_ATTR_DEPARTPOS,
73                   "person '" + personID + "' walking from " + route.front()->getID());
74     if (walkingTime > 0) {
75         mySpeed = computeAverageSpeed();
76     }
77 }
78 
79 
~MSPersonStage_Walking()80 MSPerson::MSPersonStage_Walking::~MSPersonStage_Walking() {
81     if (myPedestrianState != &myDummyState) {
82         delete myPedestrianState;
83     }
84 }
85 
86 MSTransportable::Stage*
clone() const87 MSPerson::MSPersonStage_Walking::clone() const {
88     return new MSPersonStage_Walking("dummyID", myRoute, myDestinationStop, myWalkingTime, mySpeed, myDepartPos, myArrivalPos, myDepartPosLat);
89 }
90 
91 const MSEdge*
getEdge() const92 MSPerson::MSPersonStage_Walking::getEdge() const {
93     if (myCurrentInternalEdge != nullptr) {
94         return myCurrentInternalEdge;
95     } else {
96         return *myRouteStep;
97     }
98 }
99 
100 
101 const MSEdge*
getFromEdge() const102 MSPerson::MSPersonStage_Walking::getFromEdge() const {
103     return myRoute.front();
104 }
105 
106 
107 double
getEdgePos(SUMOTime now) const108 MSPerson::MSPersonStage_Walking::getEdgePos(SUMOTime now) const {
109     return myPedestrianState == nullptr ? -1 : myPedestrianState->getEdgePos(*this, now);
110 }
111 
112 
113 Position
getPosition(SUMOTime now) const114 MSPerson::MSPersonStage_Walking::getPosition(SUMOTime now) const {
115     return myPedestrianState->getPosition(*this, now);
116 }
117 
118 
119 double
getAngle(SUMOTime now) const120 MSPerson::MSPersonStage_Walking::getAngle(SUMOTime now) const {
121     return myPedestrianState->getAngle(*this, now);
122 }
123 
124 
125 SUMOTime
getWaitingTime(SUMOTime now) const126 MSPerson::MSPersonStage_Walking::getWaitingTime(SUMOTime now) const {
127     return myPedestrianState->getWaitingTime(*this, now);
128 }
129 
130 
131 double
getSpeed() const132 MSPerson::MSPersonStage_Walking::getSpeed() const {
133     return myPedestrianState->getSpeed(*this);
134 }
135 
136 
137 ConstMSEdgeVector
getEdges() const138 MSPerson::MSPersonStage_Walking::getEdges() const {
139     return myRoute;
140 }
141 
142 
143 void
proceed(MSNet * net,MSTransportable * person,SUMOTime now,Stage * previous)144 MSPerson::MSPersonStage_Walking::proceed(MSNet* net, MSTransportable* person, SUMOTime now, Stage* previous) {
145     myDeparted = now;
146     myRouteStep = myRoute.begin();
147     myLastEdgeEntryTime = now;
148     if (myWalkingTime == 0) {
149         if (!person->proceed(net, now)) {
150             MSNet::getInstance()->getPersonControl().erase(person);
151         }
152         return;
153     }
154     if (previous->getEdgePos(now) >= 0 && previous->getEdge() == *myRouteStep) {
155         myDepartPos = previous->getEdgePos(now);
156         if (myWalkingTime > 0) {
157             mySpeed = computeAverageSpeed();
158         }
159     }
160     myPedestrianState = MSPModel::getModel()->add(dynamic_cast<MSPerson*>(person), this, now);
161     if (myPedestrianState == nullptr) {
162         MSNet::getInstance()->getPersonControl().erase(person);
163         return;
164     }
165     const MSEdge* edge = *myRouteStep;
166     const MSLane* lane = getSidewalk<MSEdge, MSLane>(getEdge());
167     if (lane != nullptr) {
168         for (MSMoveReminder* rem : lane->getMoveReminders()) {
169             rem->notifyEnter(*person, MSMoveReminder::NOTIFICATION_DEPARTED, lane);
170         }
171     }
172     edge->addPerson(person);
173 }
174 
175 
176 void
abort(MSTransportable *)177 MSPerson::MSPersonStage_Walking::abort(MSTransportable*) {
178     MSPModel::getModel()->remove(myPedestrianState);
179 }
180 
181 
182 void
setSpeed(double speed)183 MSPerson::MSPersonStage_Walking::setSpeed(double speed) {
184     mySpeed = speed;
185 }
186 
187 
188 double
computeAverageSpeed() const189 MSPerson::MSPersonStage_Walking::computeAverageSpeed() const {
190     return walkDistance() / STEPS2TIME(myWalkingTime + 1); // avoid systematic rounding errors
191 }
192 
193 
194 double
walkDistance() const195 MSPerson::MSPersonStage_Walking::walkDistance() const {
196     double length = 0;
197     for (const MSEdge* edge : myRoute) {
198         length += edge->getLength();
199     }
200     if (myRoute.size() > 1 && MSPModel::getModel()->usingInternalLanes()) {
201         // use lower bound for distance to pass the intersection
202         for (ConstMSEdgeVector::const_iterator i = myRoute.begin(); i != myRoute.end() - 1; ++i) {
203             const MSEdge* fromEdge = *i;
204             const MSEdge* toEdge = *(i + 1);
205             const MSLane* from = getSidewalk<MSEdge, MSLane>(fromEdge);
206             const MSLane* to = getSidewalk<MSEdge, MSLane>(toEdge);
207             Position fromPos;
208             Position toPos;
209             if (from != nullptr && to != nullptr) {
210                 if (fromEdge->getToJunction() == toEdge->getFromJunction()) {
211                     fromPos = from->getShape().back();
212                     toPos = to->getShape().front();
213                 } else if (fromEdge->getToJunction() == toEdge->getToJunction()) {
214                     fromPos = from->getShape().back();
215                     toPos = to->getShape().back();
216                 } else if (fromEdge->getFromJunction() == toEdge->getFromJunction()) {
217                     fromPos = from->getShape().front();
218                     toPos = to->getShape().front();
219                 } else if (fromEdge->getFromJunction() == toEdge->getToJunction()) {
220                     fromPos = from->getShape().front();
221                     toPos = to->getShape().back();
222                 }
223                 length += fromPos.distanceTo2D(toPos);
224             }
225         }
226     }
227     // determine walking direction for depart and arrival
228     const int departFwdArrivalDir = MSPModel::canTraverse(MSPModel::FORWARD, myRoute);
229     const int departBwdArrivalDir = MSPModel::canTraverse(MSPModel::BACKWARD, myRoute);
230     const bool mayStartForward = departFwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
231     const bool mayStartBackward = departBwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
232     const double lengthFwd = (length - myDepartPos - (
233                                   departFwdArrivalDir == MSPModel::BACKWARD
234                                   ? myArrivalPos
235                                   : myRoute.back()->getLength() - myArrivalPos));
236     const double lengthBwd = (length - (myRoute.front()->getLength() - myDepartPos) - (
237                                   departBwdArrivalDir == MSPModel::BACKWARD
238                                   ? myArrivalPos
239                                   : myRoute.back()->getLength() - myArrivalPos));
240 
241     if (myRoute.size() == 1) {
242         if (myDepartPos > myArrivalPos) {
243             length = lengthBwd;
244         } else {
245             length = lengthFwd;
246         }
247     } else {
248         if (mayStartForward && mayStartBackward) {
249             length = lengthFwd < lengthBwd ? lengthFwd : lengthBwd;
250         } else if (mayStartForward) {
251             length = lengthFwd;
252         } else if (mayStartBackward) {
253             length = lengthBwd;
254         } else {
255             length = lengthFwd;
256         }
257     }
258     //std::cout << SIMTIME << " route=" << toString(myRoute)
259     //    << " depPos=" << myDepartPos << " arPos=" << myArrivalPos
260     //    << " dFwdADir=" << departFwdArrivalDir
261     //    << " dBwdADir=" << departBwdArrivalDir
262     //    << " lengthFwd=" << lengthFwd
263     //    << " lengthBwd=" << lengthBwd
264     //    << "\n";
265 
266     return MAX2(POSITION_EPS, length);
267 }
268 
269 
270 void
tripInfoOutput(OutputDevice & os,const MSTransportable * const person) const271 MSPerson::MSPersonStage_Walking::tripInfoOutput(OutputDevice& os, const MSTransportable* const person) const {
272     const double distance = walkDistance();
273     const double maxSpeed = getMaxSpeed(person);
274     const SUMOTime duration = myArrived - myDeparted;
275     const SUMOTime timeLoss = myArrived == -1 ? 0 : duration - TIME2STEPS(distance / maxSpeed);
276     MSDevice_Tripinfo::addPedestrianData(distance, duration, timeLoss);
277     os.openTag("walk");
278     os.writeAttr("depart", time2string(myDeparted));
279     os.writeAttr("departPos", myDepartPos);
280     os.writeAttr("arrival", time2string(myArrived));
281     os.writeAttr("arrivalPos", myArrivalPos);
282     os.writeAttr("duration", time2string(duration));
283     os.writeAttr("routeLength", distance);
284     os.writeAttr("timeLoss", time2string(timeLoss));
285     os.writeAttr("maxSpeed", maxSpeed);
286     os.closeTag();
287 }
288 
289 
290 void
routeOutput(OutputDevice & os,const bool withRouteLength) const291 MSPerson::MSPersonStage_Walking::routeOutput(OutputDevice& os, const bool withRouteLength) const {
292     os.openTag("walk").writeAttr(SUMO_ATTR_EDGES, myRoute);
293     std::string comment = "";
294     if (myDestinationStop != nullptr) {
295         os.writeAttr(SUMO_ATTR_BUS_STOP, myDestinationStop->getID());
296         if (myDestinationStop->getMyName() != "") {
297             comment =  " <!-- " + StringUtils::escapeXML(myDestinationStop->getMyName(), true) + " -->";
298         }
299     }
300     if (myWalkingTime > 0) {
301         os.writeAttr(SUMO_ATTR_DURATION, time2string(myWalkingTime));
302     } else if (mySpeed > 0) {
303         os.writeAttr(SUMO_ATTR_SPEED, mySpeed);
304     }
305     if (withRouteLength) {
306         os.writeAttr("routeLength", walkDistance());
307     }
308     os.closeTag(comment);
309 }
310 
311 
312 void
beginEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const313 MSPerson::MSPersonStage_Walking::beginEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
314     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "departure")
315     .writeAttr("agent", p.getID()).writeAttr("link", myRoute.front()->getID()).closeTag();
316 }
317 
318 
319 void
endEventOutput(const MSTransportable & p,SUMOTime t,OutputDevice & os) const320 MSPerson::MSPersonStage_Walking::endEventOutput(const MSTransportable& p, SUMOTime t, OutputDevice& os) const {
321     os.openTag("event").writeAttr("time", time2string(t)).writeAttr("type", "arrival")
322     .writeAttr("agent", p.getID()).writeAttr("link", myRoute.back()->getID()).closeTag();
323 }
324 
325 
326 bool
moveToNextEdge(MSPerson * person,SUMOTime currentTime,MSEdge * nextInternal)327 MSPerson::MSPersonStage_Walking::moveToNextEdge(MSPerson* person, SUMOTime currentTime, MSEdge* nextInternal) {
328     ((MSEdge*)getEdge())->removePerson(person);
329     const MSLane* lane = getSidewalk<MSEdge, MSLane>(getEdge());
330     const bool arrived = myRouteStep == myRoute.end() - 1;
331     if (lane != nullptr) {
332         for (MSMoveReminder* rem : lane->getMoveReminders()) {
333             rem->updateDetector(*person, 0.0, lane->getLength(), myLastEdgeEntryTime, currentTime, currentTime, true);
334             rem->notifyLeave(*person,
335                              arrived ? getArrivalPos() : lane->getLength(),
336                              arrived ? MSMoveReminder::NOTIFICATION_ARRIVED : MSMoveReminder::NOTIFICATION_JUNCTION);
337         }
338     }
339     myLastEdgeEntryTime = currentTime;
340     //std::cout << SIMTIME << " moveToNextEdge person=" << person->getID() << "\n";
341     if (arrived) {
342         if (myDestinationStop != nullptr) {
343             myDestinationStop->addTransportable(person);
344         }
345         if (!person->proceed(MSNet::getInstance(), currentTime)) {
346             MSNet::getInstance()->getPersonControl().erase(person);
347         }
348         //std::cout << " end walk. myRouteStep=" << (*myRouteStep)->getID() << "\n";
349         return true;
350     } else {
351         if (nextInternal == nullptr) {
352             ++myRouteStep;
353             myCurrentInternalEdge = nullptr;
354         } else {
355             myCurrentInternalEdge = nextInternal;
356         }
357         const MSLane* nextLane = getSidewalk<MSEdge, MSLane>(getEdge());
358         if (nextLane != nullptr) {
359             for (MSMoveReminder* rem : nextLane->getMoveReminders()) {
360                 rem->notifyEnter(*person, MSMoveReminder::NOTIFICATION_JUNCTION, nextLane);
361             }
362         }
363         ((MSEdge*) getEdge())->addPerson(person);
364         return false;
365     }
366 }
367 
368 void
setRouteIndex(MSPerson * person,int routeOffset)369 MSPerson::MSPersonStage_Walking::setRouteIndex(MSPerson* person, int routeOffset) {
370     assert(routeOffset >= 0);
371     assert(routeOffset < (int)myRoute.size());
372     ((MSEdge*)getEdge())->removePerson(person);
373     myRouteStep = myRoute.begin() + routeOffset;
374     ((MSEdge*)getEdge())->addPerson(person);
375 }
376 
377 double
getMaxSpeed(const MSTransportable * const person) const378 MSPerson::MSPersonStage_Walking::getMaxSpeed(const MSTransportable* const person) const {
379     return mySpeed > 0 ? mySpeed : person->getVehicleType().getMaxSpeed() * person->getSpeedFactor();
380 }
381 
382 std::string
getStageSummary() const383 MSPerson::MSPersonStage_Walking::getStageSummary() const {
384     const std::string dest = (getDestinationStop() == nullptr ?
385                               " edge '" + getDestination()->getID() + "'" :
386                               " stop '" + getDestinationStop()->getID() + "'" + (
387                                   getDestinationStop()->getMyName() != "" ? " (" + getDestinationStop()->getMyName() + ")" : ""));
388     return "walking to " + dest;
389 }
390 
391 
392 /* -------------------------------------------------------------------------
393 * MSPerson::MSPersonStage_Driving - methods
394 * ----------------------------------------------------------------------- */
MSPersonStage_Driving(const MSEdge * destination,MSStoppingPlace * toStop,const double arrivalPos,const std::vector<std::string> & lines,const std::string & intendedVeh,SUMOTime intendedDepart)395 MSPerson::MSPersonStage_Driving::MSPersonStage_Driving(const MSEdge* destination,
396         MSStoppingPlace* toStop, const double arrivalPos, const std::vector<std::string>& lines,
397         const std::string& intendedVeh, SUMOTime intendedDepart) :
398     MSTransportable::Stage_Driving(destination, toStop,
399                                    SUMOVehicleParameter::interpretEdgePos(
400                                        arrivalPos, destination->getLength(), SUMO_ATTR_ARRIVALPOS, "person riding to " + destination->getID()),
401                                    lines,
402                                    intendedVeh, intendedDepart) {
403 }
404 
405 
~MSPersonStage_Driving()406 MSPerson::MSPersonStage_Driving::~MSPersonStage_Driving() {}
407 
408 MSTransportable::Stage*
clone() const409 MSPerson::MSPersonStage_Driving::clone() const {
410     return new MSPersonStage_Driving(myDestination, myDestinationStop, myArrivalPos, std::vector<std::string>(myLines.begin(), myLines.end()),
411                                      myIntendedVehicleID, myIntendedDepart);
412 }
413 
414 void
proceed(MSNet * net,MSTransportable * person,SUMOTime now,Stage * previous)415 MSPerson::MSPersonStage_Driving::proceed(MSNet* net, MSTransportable* person, SUMOTime now, Stage* previous) {
416     const MSStoppingPlace* start = (previous->getStageType() == TRIP
417                                     ? previous->getOriginStop()
418                                     : previous->getDestinationStop());
419 
420     if (start != nullptr) {
421         // the arrival stop may have an access point
422         myWaitingEdge = &start->getLane().getEdge();
423         myStopWaitPos = start->getWaitPosition(person);
424         myWaitingPos = start->getWaitingPositionOnLane(person);
425     } else {
426         myWaitingEdge = previous->getEdge();
427         myStopWaitPos = Position::INVALID;
428         myWaitingPos = previous->getEdgePos(now);
429     }
430     myWaitingSince = now;
431     SUMOVehicle* availableVehicle = net->getVehicleControl().getWaitingVehicle(person, myWaitingEdge, myWaitingPos);
432     if (availableVehicle != nullptr && availableVehicle->getParameter().departProcedure == DEPART_TRIGGERED && !availableVehicle->hasDeparted()) {
433         setVehicle(availableVehicle);
434         myVehicle->addPerson(person);
435         net->getInsertionControl().add(myVehicle);
436         net->getVehicleControl().removeWaiting(myWaitingEdge, myVehicle);
437         net->getVehicleControl().unregisterOneWaiting(true);
438     } else {
439         net->getPersonControl().addWaiting(myWaitingEdge, person);
440         myWaitingEdge->addPerson(person);
441     }
442 }
443 
444 
445 std::string
getStageDescription() const446 MSPerson::MSPersonStage_Driving::getStageDescription() const {
447     return isWaiting4Vehicle() ? "waiting for " + joinToString(myLines, ",") : "driving";
448 }
449 
450 
451 std::string
getStageSummary() const452 MSPerson::MSPersonStage_Driving::getStageSummary() const {
453     const std::string dest = (getDestinationStop() == nullptr ?
454                               " edge '" + getDestination()->getID() + "'" :
455                               " stop '" + getDestinationStop()->getID() + "'" + (
456                                   getDestinationStop()->getMyName() != "" ? " (" + getDestinationStop()->getMyName() + ")" : ""));
457     const std::string intended = myIntendedVehicleID != "" ?
458                                  " (vehicle " + myIntendedVehicleID + " at time " + time2string(myIntendedDepart) + ")" :
459                                  "";
460     return isWaiting4Vehicle() ?
461            "waiting for " + joinToString(myLines, ",") + intended + " then drive to " + dest :
462            "driving to " + dest;
463 }
464 
465 
466 void
tripInfoOutput(OutputDevice & os,const MSTransportable * const) const467 MSPerson::MSPersonStage_Driving::tripInfoOutput(OutputDevice& os, const MSTransportable* const) const {
468     const SUMOTime waitingTime = myDeparted - myWaitingSince;
469     const SUMOTime duration = myArrived - myDeparted;
470     MSDevice_Tripinfo::addRideData(myVehicleDistance, duration, myVehicleVClass, myVehicleLine, waitingTime);
471     os.openTag("ride");
472     os.writeAttr("waitingTime", time2string(waitingTime));
473     os.writeAttr("vehicle", myVehicleID);
474     os.writeAttr("depart", time2string(myDeparted));
475     os.writeAttr("arrival", time2string(myArrived));
476     os.writeAttr("arrivalPos", toString(myArrivalPos));
477     os.writeAttr("duration", myArrived > 0 ? time2string(duration) : "-1");
478     os.writeAttr("routeLength", myVehicleDistance);
479     os.closeTag();
480 }
481 
482 
483 void
routeOutput(OutputDevice & os,const bool withRouteLength) const484 MSPerson::MSPersonStage_Driving::routeOutput(OutputDevice& os, const bool withRouteLength) const {
485     os.openTag("ride");
486     if (getFromEdge() != nullptr) {
487         os.writeAttr(SUMO_ATTR_FROM, getFromEdge()->getID());
488     }
489     os.writeAttr(SUMO_ATTR_TO, getDestination()->getID());
490     std::string comment = "";
491     if (myDestinationStop != nullptr) {
492         os.writeAttr(SUMO_ATTR_BUS_STOP, myDestinationStop->getID());
493         if (myDestinationStop->getMyName() != "") {
494             comment = " <!-- " + StringUtils::escapeXML(myDestinationStop->getMyName()) + " -->";
495         }
496     }
497     os.writeAttr(SUMO_ATTR_LINES, myLines);
498     if (myIntendedVehicleID != "") {
499         os.writeAttr(SUMO_ATTR_INTENDED, myIntendedVehicleID);
500     }
501     if (myIntendedDepart >= 0) {
502         os.writeAttr(SUMO_ATTR_DEPART, time2string(myIntendedDepart));
503     }
504     if (withRouteLength) {
505         os.writeAttr("routeLength", myVehicleDistance);
506     }
507     os.closeTag(comment);
508 }
509 
510 
511 /* -------------------------------------------------------------------------
512 * MSPerson::MSPersonStage_Access - methods
513 * ----------------------------------------------------------------------- */
MSPersonStage_Access(const MSEdge * destination,MSStoppingPlace * toStop,const double arrivalPos,const double dist,const bool isExit)514 MSPerson::MSPersonStage_Access::MSPersonStage_Access(const MSEdge* destination, MSStoppingPlace* toStop,
515         const double arrivalPos, const double dist, const bool isExit) :
516     MSTransportable::Stage(destination, toStop, arrivalPos, ACCESS),
517     myDist(dist), myAmExit(isExit) {
518     myPath.push_back(destination->getLanes()[0]->geometryPositionAtOffset(myDestinationStop->getAccessPos(destination)));
519     myPath.push_back(toStop->getLane().geometryPositionAtOffset((toStop->getEndLanePosition() + toStop->getBeginLanePosition()) / 2));
520     if (isExit) {
521         myPath = myPath.reverse();
522     }
523 }
524 
525 
~MSPersonStage_Access()526 MSPerson::MSPersonStage_Access::~MSPersonStage_Access() {}
527 
528 MSTransportable::Stage*
clone() const529 MSPerson::MSPersonStage_Access::clone() const {
530     return new MSPersonStage_Access(myDestination, myDestinationStop, myArrivalPos, myDist, myAmExit);
531 }
532 
533 void
proceed(MSNet * net,MSTransportable * person,SUMOTime now,Stage *)534 MSPerson::MSPersonStage_Access::proceed(MSNet* net, MSTransportable* person, SUMOTime now, Stage* /* previous */) {
535     myDeparted = now;
536     myEstimatedArrival = now + TIME2STEPS(myDist / person->getVehicleType().getMaxSpeed());
537     net->getBeginOfTimestepEvents()->addEvent(new ProceedCmd(person, &myDestinationStop->getLane().getEdge()), myEstimatedArrival);
538     myDestinationStop->getLane().getEdge().addPerson(person);
539 }
540 
541 
542 std::string
getStageDescription() const543 MSPerson::MSPersonStage_Access::getStageDescription() const {
544     return "access";
545 }
546 
547 
548 std::string
getStageSummary() const549 MSPerson::MSPersonStage_Access::getStageSummary() const {
550     return (myAmExit ? "access from stop '" : "access to stop '") + getDestinationStop()->getID() + "'";
551 }
552 
553 
554 Position
getPosition(SUMOTime now) const555 MSPerson::MSPersonStage_Access::getPosition(SUMOTime now) const {
556     return myPath.positionAtOffset(myPath.length() * (now - myDeparted) / (myEstimatedArrival - myDeparted));
557 }
558 
559 
560 double
getAngle(SUMOTime) const561 MSPerson::MSPersonStage_Access::getAngle(SUMOTime /* now */) const {
562     return myPath.angleAt2D(0);
563 }
564 
565 
566 void
tripInfoOutput(OutputDevice & os,const MSTransportable * const) const567 MSPerson::MSPersonStage_Access::tripInfoOutput(OutputDevice& os, const MSTransportable* const) const {
568     os.openTag("access");
569     os.writeAttr("stop", getDestinationStop()->getID());
570     os.writeAttr("duration", myArrived > 0 ? time2string(myArrived - myDeparted) : "-1");
571     os.writeAttr("routeLength", myDist);
572     os.closeTag();
573 }
574 
575 
576 SUMOTime
execute(SUMOTime currentTime)577 MSPerson::MSPersonStage_Access::ProceedCmd::execute(SUMOTime currentTime) {
578     myStopEdge->removePerson(myPerson);
579     if (!myPerson->proceed(MSNet::getInstance(), currentTime)) {
580         MSNet::getInstance()->getPersonControl().erase(myPerson);
581     }
582     return 0;
583 }
584 
585 
586 /* -------------------------------------------------------------------------
587  * MSPerson - methods
588  * ----------------------------------------------------------------------- */
MSPerson(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportable::MSTransportablePlan * plan,const double speedFactor)589 MSPerson::MSPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
590     MSTransportable(pars, vtype, plan),
591     myInfluencer(nullptr), myChosenSpeedFactor(speedFactor) {
592 }
593 
594 
~MSPerson()595 MSPerson::~MSPerson() {
596 }
597 
598 
599 bool
proceed(MSNet * net,SUMOTime time)600 MSPerson::proceed(MSNet* net, SUMOTime time) {
601     MSTransportable::Stage* prior = *myStep;
602     prior->setArrived(net, this, time);
603     /*
604     if(myWriteEvents) {
605         (*myStep)->endEventOutput(*this, time, OutputDevice::getDeviceByOption("person-event-output"));
606     }
607     */
608     //if (getID() == "ego") {
609     //    std::cout << time2string(time) << " person=" << getID() << " proceed priorStep=" << myStep - myPlan->begin() << " planSize=" << myPlan->size() << "\n";
610     //}
611     // must be done before increasing myStep to avoid invalid state for rendering
612     prior->getEdge()->removePerson(this);
613     myStep++;
614     if (prior->getStageType() == MOVING_WITHOUT_VEHICLE) {
615         MSStoppingPlace* const bs = prior->getDestinationStop();
616         if (bs != nullptr) {
617             const double accessDist = bs->getAccessDistance(prior->getDestination());
618             if (accessDist > 0.) {
619                 const double arrivalAtBs = (bs->getBeginLanePosition() + bs->getEndLanePosition()) / 2;
620                 myStep = myPlan->insert(myStep, new MSPersonStage_Access(prior->getDestination(), bs, arrivalAtBs, accessDist, false));
621             }
622         }
623     }
624     if (myStep != myPlan->end()) {
625         if ((*myStep)->getStageType() == MOVING_WITHOUT_VEHICLE && (prior->getStageType() != ACCESS || prior->getDestination() != (*myStep)->getFromEdge())) {
626             MSStoppingPlace* const prevStop = prior->getDestinationStop();
627             if (prevStop != nullptr && prior->getStageType() != TRIP) {
628                 const double accessDist = prevStop->getAccessDistance((*myStep)->getFromEdge());
629                 if (accessDist > 0.) {
630                     myStep = myPlan->insert(myStep, new MSPersonStage_Access((*myStep)->getFromEdge(), prevStop, prevStop->getAccessPos((*myStep)->getFromEdge()), accessDist, true));
631                 }
632             }
633         }
634         (*myStep)->proceed(net, this, time, prior);
635         /*
636         if(myWriteEvents) {
637             (*myStep)->beginEventOutput(*this, time, OutputDevice::getDeviceByOption("person-event-output"));
638         }
639         */
640         return true;
641     } else {
642         return false;
643     }
644 }
645 
646 
647 const std::string&
getNextEdge() const648 MSPerson::getNextEdge() const {
649 //    if (getCurrentStageType() == MOVING_WITHOUT_VEHICLE) {
650 //        MSPersonStage_Walking* walkingStage =  dynamic_cast<MSPersonStage_Walking*>(*myStep);
651 //        assert(walkingStage != 0);
652 //        const MSEdge* nextEdge = walkingStage->getPedestrianState()->getNextEdge(*walkingStage);
653 //        if (nextEdge != 0) {
654 //            return nextEdge->getID();
655 //        }
656 //    }
657 //    return StringUtils::emptyString;
658     const MSEdge* nextEdge = getNextEdgePtr();
659     if (nextEdge != nullptr) {
660         return nextEdge->getID();
661     }
662     return StringUtils::emptyString;
663 }
664 
665 
666 const MSEdge*
getNextEdgePtr() const667 MSPerson::getNextEdgePtr() const {
668     if (getCurrentStageType() == MOVING_WITHOUT_VEHICLE) {
669         MSPersonStage_Walking* walkingStage =  dynamic_cast<MSPersonStage_Walking*>(*myStep);
670         assert(walkingStage != 0);
671         return walkingStage->getPedestrianState()->getNextEdge(*walkingStage);
672 
673     }
674     return nullptr;
675 }
676 
677 
678 
679 void
tripInfoOutput(OutputDevice & os) const680 MSPerson::tripInfoOutput(OutputDevice& os) const {
681     os.openTag("personinfo");
682     os.writeAttr("id", getID());
683     os.writeAttr("depart", time2string(getDesiredDepart()));
684     os.writeAttr("type", getVehicleType().getID());
685     for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
686         (*i)->tripInfoOutput(os, this);
687     }
688     os.closeTag();
689 }
690 
691 
692 void
routeOutput(OutputDevice & os,const bool withRouteLength) const693 MSPerson::routeOutput(OutputDevice& os, const bool withRouteLength) const {
694     const std::string typeID = getVehicleType().getID() != DEFAULT_PEDTYPE_ID ? getVehicleType().getID() : "";
695     myParameter->write(os, OptionsCont::getOptions(), SUMO_TAG_PERSON, typeID);
696     if (hasArrived()) {
697         os.writeAttr("arrival", time2string(MSNet::getInstance()->getCurrentTimeStep()));
698     }
699     for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
700         (*i)->routeOutput(os, withRouteLength);
701     }
702     os.closeTag();
703     os.lf();
704 }
705 
706 
707 void
reroute(ConstMSEdgeVector & newEdges,double departPos,int firstIndex,int nextIndex)708 MSPerson::reroute(ConstMSEdgeVector& newEdges, double departPos, int firstIndex, int nextIndex) {
709     assert(nextIndex > firstIndex);
710     //std::cout << SIMTIME << " reroute person " << getID()
711     //    << "  newEdges=" << toString(newEdges)
712     //    << " firstIndex=" << firstIndex
713     //    << " nextIndex=" << nextIndex
714     //    << " departPos=" << getEdgePos()
715     //    << " arrivalPos=" <<  getNextStage(nextIndex - 1)->getArrivalPos()
716     //    << "\n";
717     MSPerson::MSPersonStage_Walking* newStage = new MSPerson::MSPersonStage_Walking(getID(), newEdges,
718             getNextStage(nextIndex - 1)->getDestinationStop(), -1,
719             -1,
720             departPos,
721             getNextStage(nextIndex - 1)->getArrivalPos(),
722             0);
723     appendStage(newStage, nextIndex);
724     // remove stages in reverse order so that proceed will only be called at the last removal
725     for (int i = nextIndex - 1; i >= firstIndex; i--) {
726         //std::cout << " removeStage=" << i << "\n";
727         removeStage(i);
728     }
729 }
730 
731 
732 MSPerson::Influencer&
getInfluencer()733 MSPerson::getInfluencer() {
734     if (myInfluencer == nullptr) {
735         myInfluencer = new Influencer();
736     }
737     return *myInfluencer;
738 }
739 
740 
741 const MSPerson::Influencer*
getInfluencer() const742 MSPerson::getInfluencer() const {
743     return myInfluencer;
744 }
745 
746 
747 
748 /* -------------------------------------------------------------------------
749  * methods of MSPerson::Influencer
750  * ----------------------------------------------------------------------- */
Influencer()751 MSPerson::Influencer::Influencer() {}
752 
753 
~Influencer()754 MSPerson::Influencer::~Influencer() {}
755 
756 
757 void
setRemoteControlled(Position xyPos,MSLane * l,double pos,double posLat,double angle,int edgeOffset,const ConstMSEdgeVector & route,SUMOTime t)758 MSPerson::Influencer::setRemoteControlled(Position xyPos, MSLane* l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector& route, SUMOTime t) {
759     myRemoteXYPos = xyPos;
760     myRemoteLane = l;
761     myRemotePos = pos;
762     myRemotePosLat = posLat;
763     myRemoteAngle = angle;
764     myRemoteEdgeOffset = edgeOffset;
765     myRemoteRoute = route;
766     myLastRemoteAccess = t;
767 }
768 
769 
770 bool
isRemoteControlled() const771 MSPerson::Influencer::isRemoteControlled() const {
772     return myLastRemoteAccess == MSNet::getInstance()->getCurrentTimeStep();
773 }
774 
775 
776 bool
isRemoteAffected(SUMOTime t) const777 MSPerson::Influencer::isRemoteAffected(SUMOTime t) const {
778     return myLastRemoteAccess >= t - TIME2STEPS(10);
779 }
780 
781 
782 void
postProcessRemoteControl(MSPerson * p)783 MSPerson::Influencer::postProcessRemoteControl(MSPerson* p) {
784     /*
785     std::cout << SIMTIME << " moveToXY person=" << p->getID()
786         << " xyPos=" << myRemoteXYPos
787         << " lane=" << Named::getIDSecure(myRemoteLane)
788         << " pos=" << myRemotePos
789         << " posLat=" << myRemotePosLat
790         << " angle=" << myRemoteAngle
791         << " eOf=" << myRemoteEdgeOffset
792         << " route=" << toString(myRemoteRoute)
793         << " aTime=" << time2string(myLastRemoteAccess)
794         << "\n";
795         */
796     switch (p->getStageType(0)) {
797         case MOVING_WITHOUT_VEHICLE: {
798             MSPersonStage_Walking* s = dynamic_cast<MSPerson::MSPersonStage_Walking*>(p->getCurrentStage());
799             assert(s != 0);
800             s->getPedestrianState()->moveToXY(p, myRemoteXYPos, myRemoteLane, myRemotePos, myRemotePosLat, myRemoteAngle, myRemoteEdgeOffset, myRemoteRoute,
801                                               MSNet::getInstance()->getCurrentTimeStep());
802         }
803         break;
804         default:
805             break;
806     }
807 }
808 
809 
810 /****************************************************************************/
811