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