Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file 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_Tripinfo.h>
44 : #include <microsim/devices/MSDevice_Taxi.h>
45 : #include <microsim/trigger/MSTriggeredRerouter.h>
46 : #include "MSPModel_Striping.h"
47 : #include "MSStageTrip.h"
48 : #include "MSStageWalking.h"
49 : #include "MSPerson.h"
50 :
51 :
52 : // ===========================================================================
53 : // method definitions
54 : // ===========================================================================
55 : /* -------------------------------------------------------------------------
56 : * MSPerson::MSPersonStage_Access - methods
57 : * ----------------------------------------------------------------------- */
58 4135 : MSPerson::MSPersonStage_Access::MSPersonStage_Access(const MSEdge* destination, MSStoppingPlace* toStop,
59 : const double arrivalPos, const double arrivalPosLat, const double dist, const bool isExit,
60 4135 : const Position& startPos, const Position& endPos) :
61 : MSStage(MSStageType::ACCESS, destination, toStop, arrivalPos, arrivalPosLat),
62 8270 : myDist(dist), myAmExit(isExit) {
63 4135 : myPath.push_back(startPos);
64 4135 : myPath.push_back(endPos);
65 4135 : }
66 :
67 :
68 8270 : MSPerson::MSPersonStage_Access::~MSPersonStage_Access() {}
69 :
70 : MSStage*
71 0 : MSPerson::MSPersonStage_Access::clone() const {
72 0 : return new MSPersonStage_Access(myDestination, myDestinationStop, myArrivalPos, myArrivalPosLat, myDist, myAmExit, myPath.front(), myPath.back());
73 : }
74 :
75 : void
76 4135 : MSPerson::MSPersonStage_Access::proceed(MSNet* net, MSTransportable* person, SUMOTime now, MSStage* /* previous */) {
77 4135 : myDeparted = now;
78 4135 : myEstimatedArrival = now + TIME2STEPS(myDist / person->getMaxSpeed());
79 : // TODO myEstimatedArrival is not a multiple of DELTA_T here. This might give a problem because the destination position will not be reached precisely
80 4135 : net->getBeginOfTimestepEvents()->addEvent(new ProceedCmd(person, &myDestinationStop->getLane().getEdge()), myEstimatedArrival);
81 4135 : net->getPersonControl().startedAccess();
82 4135 : myDestinationStop->getLane().getEdge().addTransportable(person);
83 4135 : }
84 :
85 :
86 : std::string
87 0 : MSPerson::MSPersonStage_Access::getStageDescription(const bool /* isPerson */) const {
88 0 : return "access";
89 : }
90 :
91 :
92 : std::string
93 0 : MSPerson::MSPersonStage_Access::getStageSummary(const bool /* isPerson */) const {
94 0 : return (myAmExit ? "access from stop '" : "access to stop '") + getDestinationStop()->getID() + "'";
95 : }
96 :
97 :
98 : Position
99 19786 : MSPerson::MSPersonStage_Access::getPosition(SUMOTime now) const {
100 19786 : return myPath.positionAtOffset(myPath.length() * (double)(now - myDeparted) / (double)(myEstimatedArrival - myDeparted));
101 : }
102 :
103 :
104 : double
105 19786 : MSPerson::MSPersonStage_Access::getAngle(SUMOTime /* now */) const {
106 19786 : return myPath.angleAt2D(0);
107 : }
108 :
109 :
110 : double
111 18942 : MSPerson::MSPersonStage_Access::getSpeed() const {
112 18942 : return myDist / STEPS2TIME(MAX2((SUMOTime)1, myEstimatedArrival - myDeparted));
113 : }
114 :
115 : void
116 2879 : MSPerson::MSPersonStage_Access::tripInfoOutput(OutputDevice& os, const MSTransportable* const) const {
117 5758 : os.openTag("access");
118 2879 : os.writeAttr("stop", getDestinationStop()->getID());
119 5758 : os.writeAttr("depart", time2string(myDeparted));
120 5758 : os.writeAttr("arrival", myArrived >= 0 ? time2string(myArrived) : "-1");
121 5758 : os.writeAttr("duration", myArrived > 0 ? time2string(getDuration()) : "-1");
122 2879 : os.writeAttr("routeLength", myDist);
123 2879 : os.closeTag();
124 2879 : }
125 :
126 :
127 : SUMOTime
128 4103 : MSPerson::MSPersonStage_Access::ProceedCmd::execute(SUMOTime currentTime) {
129 4103 : MSNet::getInstance()->getPersonControl().endedAccess();
130 4103 : myStopEdge->removeTransportable(myPerson);
131 4103 : if (!myPerson->proceed(MSNet::getInstance(), currentTime)) {
132 53 : MSNet::getInstance()->getPersonControl().erase(myPerson);
133 : }
134 4103 : return 0;
135 : }
136 :
137 :
138 : /* -------------------------------------------------------------------------
139 : * MSPerson - methods
140 : * ----------------------------------------------------------------------- */
141 310459 : MSPerson::MSPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan, const double speedFactor) :
142 : MSTransportable(pars, vtype, plan, true),
143 310459 : myInfluencer(nullptr),
144 620918 : myChosenSpeedFactor(pars->speedFactor < 0 ? speedFactor : pars->speedFactor),
145 310526 : myTimegapCrossing(getFloatParam("pedestrian.timegap-crossing"))
146 310459 : { }
147 :
148 :
149 592065 : MSPerson::~MSPerson() {
150 310413 : delete myInfluencer;
151 592065 : }
152 :
153 :
154 : bool
155 526101 : MSPerson::checkAccess(const MSStage* const prior, const bool waitAtStop) {
156 : MSStoppingPlace* prevStop = prior->getDestinationStop();
157 526101 : if (!waitAtStop && prior->getStageType() == MSStageType::TRIP) {
158 204946 : prevStop = prior->getOriginStop();
159 : }
160 526101 : if (prevStop != nullptr) {
161 57893 : const MSEdge* const accessEdge = waitAtStop ? prior->getDestination() : (*myStep)->getFromEdge();
162 57893 : const MSStoppingPlace::Access* const access = prevStop->getAccess(accessEdge);
163 57893 : if (access != nullptr) {
164 4135 : const MSLane* const lane = accessEdge->getLanes()[0];
165 4135 : MSStage* newStage = nullptr;
166 4135 : if (waitAtStop) {
167 2028 : const MSEdge* const stopEdge = &prevStop->getLane().getEdge();
168 2028 : const double arrivalAtBs = (prevStop->getBeginLanePosition() + prevStop->getEndLanePosition()) / 2;
169 2028 : newStage = new MSPersonStage_Access(stopEdge, prevStop, arrivalAtBs, 0.0, access->length, false,
170 2028 : lane->geometryPositionAtOffset(access->endPos),
171 4056 : prevStop->getLane().geometryPositionAtOffset(arrivalAtBs));
172 : } else {
173 3764 : const bool useDoors = access->exit == MSStoppingPlace::AccessExit::DOORS ||
174 7078 : (OptionsCont::getOptions().getString("pedestrian.model") != "jupedsim" && access->exit == MSStoppingPlace::AccessExit::CARRIAGE);
175 2107 : if (access->exit == MSStoppingPlace::AccessExit::CARRIAGE) {
176 0 : const double startPos = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePos(0) : prior->getArrivalPos();
177 0 : const double startPosLat = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePosLat(0) : prior->getArrivalPosLat();
178 : // The start and end attributes of the access stage are equal in this case, but we need to compute the arrival position relatively
179 : // to the current lane and not the lane of the previous stage.
180 0 : const Position start = prevStop->getLane().geometryPositionAtOffset(startPos, startPosLat);
181 0 : const Position end = lane->getShape().transformToVectorCoordinates(start);
182 0 : newStage = new MSPersonStage_Access(accessEdge, prevStop, end.x(), -end.y(), access->length, true, start, start);
183 : } else {
184 2107 : const double startPos = prior->getStageType() == MSStageType::TRIP ? prior->getEdgePos(0) : prior->getArrivalPos();
185 2107 : const Position& trainExit = prevStop->getLane().geometryPositionAtOffset(startPos);
186 2107 : const double arrivalPos = useDoors ? lane->getShape().nearest_offset_to_point2D(trainExit) : access->endPos;
187 : Position platformEntry = lane->geometryPositionAtOffset(arrivalPos);
188 2107 : if (useDoors) {
189 : // find the closer side of the platform to enter
190 900 : const double halfWidth = lane->getWidth() / 2. - MAX2(getVehicleType().getLength(), getVehicleType().getWidth()) / 2. - POSITION_EPS;
191 450 : platformEntry = lane->geometryPositionAtOffset(arrivalPos, halfWidth);
192 450 : const Position& plat2 = lane->geometryPositionAtOffset(arrivalPos, -halfWidth);
193 450 : if (trainExit.distanceSquaredTo2D(plat2) < trainExit.distanceSquaredTo2D(platformEntry)) {
194 356 : platformEntry = plat2;
195 : }
196 : }
197 2107 : newStage = new MSPersonStage_Access(accessEdge, prevStop, arrivalPos, 0.0, access->length, true,
198 2107 : trainExit, platformEntry);
199 : }
200 : }
201 4135 : newStage->setTrip(prior->getTrip());
202 4135 : myStep = myPlan->insert(myStep, newStage);
203 : return true;
204 : }
205 : }
206 : return false;
207 : }
208 :
209 :
210 : double
211 0 : MSPerson::getImpatience() const {
212 0 : return MAX2(0., MIN2(1., getVehicleType().getImpatience()
213 0 : + STEPS2TIME((*myStep)->getWaitingTime(SIMSTEP)) / MSPModel_Striping::MAX_WAIT_TOLERANCE));
214 : }
215 :
216 : const std::string&
217 2625 : MSPerson::getNextEdge() const {
218 : // if (getCurrentStageType() == WALKING) {
219 : // MSStageWalking* walkingStage = dynamic_cast<MSStageWalking*>(*myStep);
220 : // assert(walkingStage != 0);
221 : // const MSEdge* nextEdge = walkingStage->getPedestrianState()->getNextEdge(*walkingStage);
222 : // if (nextEdge != 0) {
223 : // return nextEdge->getID();
224 : // }
225 : // }
226 : // return StringUtils::emptyString;
227 2625 : const MSEdge* nextEdge = getNextEdgePtr();
228 2625 : if (nextEdge != nullptr) {
229 2623 : return nextEdge->getID();
230 : }
231 : return StringUtils::emptyString;
232 : }
233 :
234 :
235 : const MSEdge*
236 166313 : MSPerson::getNextEdgePtr() const {
237 166313 : if (getCurrentStageType() == MSStageType::WALKING) {
238 166313 : MSStageWalking* walkingStage = dynamic_cast<MSStageWalking*>(*myStep);
239 : assert(walkingStage != nullptr);
240 166313 : return walkingStage->getPState()->getNextEdge(*walkingStage);
241 : }
242 : return nullptr;
243 : }
244 :
245 :
246 :
247 : void
248 1507 : MSPerson::replaceWalk(const ConstMSEdgeVector& newEdges, double departPos, int firstIndex, int nextIndex) {
249 : assert(nextIndex > firstIndex);
250 : //std::cout << SIMTIME << " reroute person " << getID()
251 : // << " newEdges=" << toString(newEdges)
252 : // << " firstIndex=" << firstIndex
253 : // << " nextIndex=" << nextIndex
254 : // << " departPos=" << getEdgePos()
255 : // << " arrivalPos=" << getNextStage(nextIndex - 1)->getArrivalPos()
256 : // << "\n";
257 1507 : MSStage* const toBeReplaced = getNextStage(nextIndex - 1);
258 : MSStageWalking* newStage = new MSStageWalking(getID(), newEdges,
259 : toBeReplaced->getDestinationStop(), -1,
260 : -1,
261 : departPos,
262 1507 : toBeReplaced->getArrivalPos(),
263 1507 : MSPModel::UNSPECIFIED_POS_LAT);
264 1507 : appendStage(newStage, nextIndex);
265 : // remove stages in reverse order so that proceed will only be called at the last removal
266 3019 : for (int i = nextIndex - 1; i >= firstIndex; i--) {
267 : //std::cout << " removeStage=" << i << "\n";
268 1512 : removeStage(i);
269 : }
270 1507 : }
271 :
272 :
273 : MSPerson::Influencer&
274 43485 : MSPerson::getInfluencer() {
275 43485 : if (myInfluencer == nullptr) {
276 107 : myInfluencer = new Influencer();
277 : }
278 43485 : return *myInfluencer;
279 : }
280 :
281 :
282 : const MSPerson::Influencer*
283 0 : MSPerson::getInfluencer() const {
284 0 : return myInfluencer;
285 : }
286 :
287 :
288 :
289 : /* -------------------------------------------------------------------------
290 : * methods of MSPerson::Influencer
291 : * ----------------------------------------------------------------------- */
292 107 : MSPerson::Influencer::Influencer() {}
293 :
294 :
295 107 : MSPerson::Influencer::~Influencer() {}
296 :
297 :
298 : void
299 10340 : MSPerson::Influencer::setRemoteControlled(Position xyPos, MSLane* l, double pos, double posLat, double angle, int edgeOffset, const ConstMSEdgeVector& route, SUMOTime t) {
300 10340 : myRemoteXYPos = xyPos;
301 10340 : myRemoteLane = l;
302 10340 : myRemotePos = pos;
303 10340 : myRemotePosLat = posLat;
304 10340 : myRemoteAngle = angle;
305 10340 : myRemoteEdgeOffset = edgeOffset;
306 10340 : myRemoteRoute = route;
307 10340 : myLastRemoteAccess = t;
308 10340 : }
309 :
310 :
311 : bool
312 22805 : MSPerson::Influencer::isRemoteControlled() const {
313 22805 : return myLastRemoteAccess == MSNet::getInstance()->getCurrentTimeStep();
314 : }
315 :
316 :
317 : bool
318 0 : MSPerson::Influencer::isRemoteAffected(SUMOTime t) const {
319 0 : return myLastRemoteAccess >= t - TIME2STEPS(10);
320 : }
321 :
322 :
323 : void
324 10340 : MSPerson::Influencer::postProcessRemoteControl(MSPerson* p) {
325 : /*
326 : std::cout << SIMTIME << " moveToXY person=" << p->getID()
327 : << " xyPos=" << myRemoteXYPos
328 : << " lane=" << Named::getIDSecure(myRemoteLane)
329 : << " pos=" << myRemotePos
330 : << " posLat=" << myRemotePosLat
331 : << " angle=" << myRemoteAngle
332 : << " eOf=" << myRemoteEdgeOffset
333 : << " route=" << toString(myRemoteRoute)
334 : << " aTime=" << time2string(myLastRemoteAccess)
335 : << "\n";
336 : */
337 10340 : switch (p->getStageType(0)) {
338 : case MSStageType::WALKING: {
339 10300 : MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
340 : assert(s != nullptr);
341 10300 : s->getPState()->moveToXY(p, myRemoteXYPos, myRemoteLane, myRemotePos, myRemotePosLat,
342 10300 : myRemoteAngle, myRemoteEdgeOffset, myRemoteRoute,
343 : MSNet::getInstance()->getCurrentTimeStep());
344 : }
345 10300 : break;
346 : default:
347 : break;
348 : }
349 10340 : }
350 :
351 :
352 : /****************************************************************************/
|