Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSPerson.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @date Mon, 9 Jul 2001
20 : ///
21 : // The class for modelling person-movements
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <vector>
27 : #include <utils/iodevices/OutputDevice.h>
28 : #include <utils/options/OptionsCont.h>
29 : #include <utils/common/ToString.h>
30 : #include <utils/common/StringUtils.h>
31 : #include <utils/geom/GeomHelper.h>
32 : #include <utils/router/IntermodalNetwork.h>
33 : #include <microsim/MSNet.h>
34 : #include <microsim/MSEdge.h>
35 : #include <microsim/MSLane.h>
36 : #include <microsim/transportables/MSTransportableControl.h>
37 : #include <microsim/MSInsertionControl.h>
38 : #include <microsim/MSEventControl.h>
39 : #include <microsim/MSVehicle.h>
40 : #include <microsim/MSVehicleControl.h>
41 : #include <microsim/MSStoppingPlace.h>
42 : #include <microsim/MSRouteHandler.h>
43 : #include <microsim/devices/MSDevice_Taxi.h>
44 : #include <microsim/trigger/MSTriggeredRerouter.h>
45 : #include "MSPModel_Striping.h"
46 : #include "MSStageTrip.h"
47 : #include "MSStageWalking.h"
48 : #include "MSPerson.h"
49 :
50 :
51 : // ===========================================================================
52 : // method definitions
53 : // ===========================================================================
54 : /* -------------------------------------------------------------------------
55 : * MSPerson::MSPersonStage_Access - methods
56 : * ----------------------------------------------------------------------- */
57 4236 : MSPerson::MSPersonStage_Access::MSPersonStage_Access(const MSEdge* destination, MSStoppingPlace* toStop,
58 : const double arrivalPos, const double arrivalPosLat, const double dist, const bool isExit,
59 4236 : const Position& startPos, const Position& endPos) :
60 : MSStage(MSStageType::ACCESS, destination, toStop, arrivalPos, arrivalPosLat),
61 8472 : myDist(dist), myAmExit(isExit) {
62 4236 : myPath.push_back(startPos);
63 4236 : myPath.push_back(endPos);
64 4236 : }
65 :
66 :
67 8472 : MSPerson::MSPersonStage_Access::~MSPersonStage_Access() {}
68 :
69 : MSStage*
70 0 : MSPerson::MSPersonStage_Access::clone() const {
71 0 : return new MSPersonStage_Access(myDestination, myDestinationStop, myArrivalPos, myArrivalPosLat, myDist, myAmExit, myPath.front(), myPath.back());
72 : }
73 :
74 : void
75 4234 : MSPerson::MSPersonStage_Access::proceed(MSNet* net, MSTransportable* person, SUMOTime now, MSStage* previous) {
76 4234 : myDeparted = now;
77 4234 : if (myDist >= 0) {
78 4220 : myEstimatedArrival = now + TIME2STEPS(myDist / person->getMaxSpeed());
79 : } else {
80 14 : myEstimatedArrival = now + previous->getJumpDuration();
81 : }
82 : // TODO myEstimatedArrival is not a multiple of DELTA_T here. This might give a problem because the destination position will not be reached precisely
83 4234 : MSEdge* edge = myDestinationStop != nullptr ? &myDestinationStop->getLane().getEdge() : const_cast<MSEdge*>(myDestination);
84 4234 : net->getBeginOfTimestepEvents()->addEvent(new ProceedCmd(person, edge), myEstimatedArrival);
85 4234 : net->getPersonControl().startedAccess();
86 4234 : edge->addTransportable(person);
87 4234 : }
88 :
89 :
90 : std::string
91 19022 : MSPerson::MSPersonStage_Access::getStageDescription(const bool /* isPerson */) const {
92 19022 : return "access";
93 : }
94 :
95 :
96 : std::string
97 0 : MSPerson::MSPersonStage_Access::getStageSummary(const bool /* isPerson */) const {
98 0 : if (myDestination == nullptr) {
99 0 : return ("jump to edge '") + getDestination()->getID() + "'";
100 : } else {
101 0 : return (myAmExit ? "access from stop '" : "access to stop '") + getDestinationStop()->getID() + "'";
102 : }
103 : }
104 :
105 :
106 : Position
107 19891 : MSPerson::MSPersonStage_Access::getPosition(SUMOTime now) const {
108 19891 : return myPath.positionAtOffset(myPath.length() * (double)(now - myDeparted) / (double)(myEstimatedArrival - myDeparted));
109 : }
110 :
111 :
112 : double
113 19891 : MSPerson::MSPersonStage_Access::getAngle(SUMOTime /* now */) const {
114 19891 : return myPath.angleAt2D(0);
115 : }
116 :
117 :
118 : double
119 38044 : MSPerson::MSPersonStage_Access::getSpeed() const {
120 38044 : return myDist / STEPS2TIME(MAX2((SUMOTime)1, myEstimatedArrival - myDeparted));
121 : }
122 :
123 : void
124 2950 : MSPerson::MSPersonStage_Access::tripInfoOutput(OutputDevice& os, const MSTransportable* const) const {
125 5900 : os.openTag("access");
126 2950 : if (getDestinationStop() != nullptr) {
127 2942 : os.writeAttr("stop", getDestinationStop()->getID());
128 : }
129 2950 : os.writeAttr("depart", time2string(myDeparted));
130 2950 : os.writeAttr("arrival", myArrived >= 0 ? time2string(myArrived) : "-1");
131 2950 : os.writeAttr("duration", myArrived > 0 ? time2string(getDuration()) : "-1");
132 2950 : os.writeAttr("routeLength", myDist);
133 2950 : os.closeTag();
134 2950 : }
135 :
136 :
137 : SUMOTime
138 4204 : MSPerson::MSPersonStage_Access::ProceedCmd::execute(SUMOTime currentTime) {
139 4204 : MSNet::getInstance()->getPersonControl().endedAccess();
140 4204 : myStopEdge->removeTransportable(myPerson);
141 4204 : if (!myPerson->proceed(MSNet::getInstance(), currentTime)) {
142 54 : MSNet::getInstance()->getPersonControl().erase(myPerson);
143 : }
144 4204 : return 0;
145 : }
146 :
147 :
148 : void
149 2 : MSPerson::MSPersonStage_Access::saveState(std::ostringstream& out, MSTransportable* /*transportable*/) {
150 4 : out << " " << myDeparted << " " << myEstimatedArrival;
151 2 : }
152 :
153 :
154 : void
155 2 : MSPerson::MSPersonStage_Access::loadState(MSTransportable* person, std::istringstream& state) {
156 2 : state >> myDeparted;
157 2 : state >> myEstimatedArrival;
158 2 : MSNet* net = MSNet::getInstance();
159 2 : MSEdge* edge = myDestinationStop != nullptr ? &myDestinationStop->getLane().getEdge() : const_cast<MSEdge*>(myDestination);
160 2 : net->getBeginOfTimestepEvents()->addEvent(new ProceedCmd(person, edge), myEstimatedArrival);
161 2 : net->getPersonControl().startedAccess();
162 2 : edge->addTransportable(person);
163 2 : }
164 :
165 : /* -------------------------------------------------------------------------
166 : * MSPerson - methods
167 : * ----------------------------------------------------------------------- */
168 331420 : MSPerson::MSPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
169 : MSTransportable(pars, vtype, plan, true),
170 331420 : myInfluencer(nullptr),
171 662840 : myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
172 331660 : myTimegapCrossing(getFloatParam("pedestrian.timegap-crossing"))
173 331420 : { }
174 :
175 :
176 633115 : MSPerson::~MSPerson() {
177 331372 : delete myInfluencer;
178 633115 : }
179 :
180 :
181 : bool
182 521681 : MSPerson::checkAccess(const MSStage* const prior, const bool waitAtStop) {
183 : MSStoppingPlace* prevStop = prior->getDestinationStop();
184 521681 : if (!waitAtStop && prior->getStageType() == MSStageType::TRIP) {
185 164608 : prevStop = prior->getOriginStop();
186 : }
187 521681 : if (prevStop != nullptr) {
188 119626 : const MSEdge* const accessEdge = waitAtStop ? prior->getDestination() : (*myStep)->getFromEdge();
189 119626 : const MSStoppingPlace::Access* const access = prevStop->getAccess(accessEdge);
190 119626 : if (access != nullptr) {
191 4222 : const MSLane* const lane = accessEdge->getLanes()[0];
192 4222 : MSStage* newStage = nullptr;
193 4222 : if (waitAtStop) {
194 2072 : const MSEdge* const stopEdge = &prevStop->getLane().getEdge();
195 2072 : const double arrivalAtBs = (prevStop->getBeginLanePosition() + prevStop->getEndLanePosition()) / 2;
196 4144 : newStage = new MSPersonStage_Access(stopEdge, prevStop, arrivalAtBs, 0.0, access->length, false,
197 2072 : lane->geometryPositionAtOffset(access->endPos),
198 4144 : prevStop->getLane().geometryPositionAtOffset(arrivalAtBs));
199 : } else {
200 3850 : const bool useDoors = access->exit == MSStoppingPlace::AccessExit::DOORS ||
201 7250 : (OptionsCont::getOptions().getString("pedestrian.model") != "jupedsim" && access->exit == MSStoppingPlace::AccessExit::CARRIAGE);
202 2150 : if (access->exit == MSStoppingPlace::AccessExit::CARRIAGE) {
203 0 : const double startPos = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePos(0) : prior->getArrivalPos();
204 0 : const double startPosLat = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePosLat(0) : prior->getArrivalPosLat();
205 : // The start and end attributes of the access stage are equal in this case, but we need to compute the arrival position relatively
206 : // to the current lane and not the lane of the previous stage.
207 0 : const Position start = prevStop->getLane().geometryPositionAtOffset(startPos, startPosLat);
208 0 : const Position end = lane->getShape().transformToVectorCoordinates(start);
209 0 : newStage = new MSPersonStage_Access(accessEdge, prevStop, end.x(), -end.y(), access->length, true, start, start);
210 : } else {
211 2150 : const double startPos = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePos(0) : prior->getArrivalPos();
212 2150 : const Position& trainExit = prevStop->getLane().geometryPositionAtOffset(startPos);
213 2150 : const double arrivalPos = useDoors ? lane->getShape().nearest_offset_to_point2D(trainExit) : access->endPos;
214 : Position platformEntry = lane->geometryPositionAtOffset(arrivalPos);
215 2150 : if (useDoors) {
216 : // find the closer side of the platform to enter
217 900 : const double halfWidth = lane->getWidth() / 2. - MAX2(getVehicleType().getLength(), getVehicleType().getWidth()) / 2. - POSITION_EPS;
218 450 : platformEntry = lane->geometryPositionAtOffset(arrivalPos, halfWidth);
219 450 : const Position& plat2 = lane->geometryPositionAtOffset(arrivalPos, -halfWidth);
220 450 : if (trainExit.distanceSquaredTo2D(plat2) < trainExit.distanceSquaredTo2D(platformEntry)) {
221 356 : platformEntry = plat2;
222 : }
223 : }
224 2150 : newStage = new MSPersonStage_Access(accessEdge, prevStop, arrivalPos, 0.0, access->length, true,
225 2150 : trainExit, platformEntry);
226 : }
227 : }
228 4222 : newStage->setTrip(prior->getTrip());
229 4222 : myStep = myPlan->insert(myStep, newStage);
230 : return true;
231 : }
232 : }
233 517459 : if (prior->getJumpDuration() > 0) {
234 : // negative distance indicates jump
235 : MSStage* newStage = new MSPersonStage_Access(getDestination(), nullptr, getArrivalPos(), 0.0, -1, true,
236 28 : prior->getPosition(SIMSTEP), (*myStep)->getPosition(SIMSTEP));
237 14 : myStep = myPlan->insert(myStep, newStage);
238 : return true;
239 : }
240 : return false;
241 : }
242 :
243 :
244 : double
245 8 : MSPerson::getImpatience() const {
246 8 : return MAX2(0., MIN2(1., getVehicleType().getImpatience()
247 8 : + STEPS2TIME((*myStep)->getWaitingTime()) / MSPModel_Striping::MAX_WAIT_TOLERANCE));
248 : }
249 :
250 :
251 : bool
252 1156006 : MSPerson::isJammed() const {
253 1156006 : MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
254 1156006 : if (stage != nullptr) {
255 1156006 : return stage->getPState()->isJammed();
256 : }
257 : return false;
258 : }
259 :
260 :
261 : const std::string&
262 2633 : MSPerson::getNextEdge() const {
263 : // if (getCurrentStageType() == WALKING) {
264 : // MSStageWalking* walkingStage = dynamic_cast<MSStageWalking*>(*myStep);
265 : // assert(walkingStage != 0);
266 : // const MSEdge* nextEdge = walkingStage->getPedestrianState()->getNextEdge(*walkingStage);
267 : // if (nextEdge != 0) {
268 : // return nextEdge->getID();
269 : // }
270 : // }
271 : // return StringUtils::emptyString;
272 2633 : const MSEdge* nextEdge = getNextEdgePtr();
273 2633 : if (nextEdge != nullptr) {
274 2623 : return nextEdge->getID();
275 : }
276 : return StringUtils::emptyString;
277 : }
278 :
279 :
280 : const MSEdge*
281 166745 : MSPerson::getNextEdgePtr() const {
282 166745 : if (getCurrentStageType() == MSStageType::WALKING) {
283 166745 : MSStageWalking* walkingStage = dynamic_cast<MSStageWalking*>(*myStep);
284 : assert(walkingStage != nullptr);
285 166745 : return walkingStage->getPState()->getNextEdge(*walkingStage);
286 : }
287 : return nullptr;
288 : }
289 :
290 :
291 :
292 : void
293 1507 : MSPerson::replaceWalk(const ConstMSEdgeVector& newEdges, double departPos, int firstIndex, int nextIndex) {
294 : assert(nextIndex > firstIndex);
295 : //std::cout << SIMTIME << " reroute person " << getID()
296 : // << " newEdges=" << toString(newEdges)
297 : // << " firstIndex=" << firstIndex
298 : // << " nextIndex=" << nextIndex
299 : // << " departPos=" << getEdgePos()
300 : // << " arrivalPos=" << getNextStage(nextIndex - 1)->getArrivalPos()
301 : // << "\n";
302 1507 : MSStage* const toBeReplaced = getNextStage(nextIndex - 1);
303 : MSStageWalking* newStage = new MSStageWalking(getID(), newEdges,
304 : toBeReplaced->getDestinationStop(), -1,
305 : -1,
306 : departPos,
307 1507 : toBeReplaced->getArrivalPos(),
308 1507 : MSPModel::UNSPECIFIED_POS_LAT);
309 1507 : appendStage(newStage, nextIndex);
310 : // remove stages in reverse order so that proceed will only be called at the last removal
311 3019 : for (int i = nextIndex - 1; i >= firstIndex; i--) {
312 : //std::cout << " removeStage=" << i << "\n";
313 1512 : removeStage(i);
314 : }
315 1507 : }
316 :
317 :
318 : MSPerson::Influencer&
319 5885816 : MSPerson::getInfluencer() {
320 5885816 : if (myInfluencer == nullptr) {
321 226 : myInfluencer = new Influencer();
322 : }
323 5885816 : return *myInfluencer;
324 : }
325 :
326 :
327 : const MSPerson::Influencer*
328 0 : MSPerson::getInfluencer() const {
329 0 : return myInfluencer;
330 : }
331 :
332 :
333 :
334 : /* -------------------------------------------------------------------------
335 : * methods of MSPerson::Influencer
336 : * ----------------------------------------------------------------------- */
337 226 : MSPerson::Influencer::Influencer() {}
338 :
339 :
340 226 : MSPerson::Influencer::~Influencer() {}
341 :
342 :
343 : void
344 1957728 : MSPerson::Influencer::setRemoteControlled(Position xyPos, MSLane* l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector& route, SUMOTime t) {
345 1957728 : myRemoteXYPos = xyPos;
346 1957728 : myRemoteLane = l;
347 1957728 : myRemotePos = pos;
348 1957728 : myRemotePosLat = posLat;
349 1957728 : myRemoteAngle = angle;
350 1957728 : myRemoteEdgeOffset = edgeOffset;
351 1957728 : myRemoteRoute = route;
352 1957728 : myLastRemoteAccess = t;
353 1957728 : }
354 :
355 :
356 : bool
357 1970361 : MSPerson::Influencer::isRemoteControlled() const {
358 1970361 : return myLastRemoteAccess == MSNet::getInstance()->getCurrentTimeStep();
359 : }
360 :
361 :
362 : bool
363 0 : MSPerson::Influencer::isRemoteAffected(SUMOTime t) const {
364 0 : return myLastRemoteAccess >= t - TIME2STEPS(10);
365 : }
366 :
367 :
368 : void
369 1957727 : MSPerson::Influencer::postProcessRemoteControl(MSPerson* p) {
370 : /*
371 : std::cout << SIMTIME << " moveToXY person=" << p->getID()
372 : << " xyPos=" << myRemoteXYPos
373 : << " lane=" << Named::getIDSecure(myRemoteLane)
374 : << " pos=" << myRemotePos
375 : << " posLat=" << myRemotePosLat
376 : << " angle=" << myRemoteAngle
377 : << " eOf=" << myRemoteEdgeOffset
378 : << " route=" << toString(myRemoteRoute)
379 : << " aTime=" << time2string(myLastRemoteAccess)
380 : << "\n";
381 : */
382 1957727 : switch (p->getStageType(0)) {
383 : case MSStageType::WALKING: {
384 1957687 : MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
385 : assert(s != nullptr);
386 1957687 : s->getPState()->moveToXY(p, myRemoteXYPos, myRemoteLane, myRemotePos, myRemotePosLat,
387 1957687 : myRemoteAngle, myRemoteEdgeOffset, myRemoteRoute,
388 : MSNet::getInstance()->getCurrentTimeStep());
389 : }
390 1957687 : break;
391 : default:
392 : break;
393 : }
394 1957727 : }
395 :
396 :
397 : /****************************************************************************/
|