Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2014-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 MSPModel_Striping.cpp
15 : /// @author Jakob Erdmann
16 : /// @author Michael Behrisch
17 : /// @date Mon, 13 Jan 2014
18 : ///
19 : // The pedestrian following model (prototype)
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <cmath>
24 : #include <algorithm>
25 : #include <utils/common/RandHelper.h>
26 : #include <utils/geom/GeomHelper.h>
27 : #include <utils/options/OptionsCont.h>
28 : #include <utils/router/PedestrianRouter.h>
29 : #include <microsim/MSNet.h>
30 : #include <microsim/MSEdge.h>
31 : #include <microsim/MSEventControl.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSLink.h>
34 : #include <microsim/MSJunction.h>
35 : #include <microsim/MSStoppingPlace.h>
36 : #include <microsim/MSVehicleControl.h>
37 : #include <microsim/MSGlobals.h>
38 : #include <microsim/transportables/MSStage.h>
39 : #include <microsim/transportables/MSTransportableControl.h>
40 : #include "MSPModel_Striping.h"
41 :
42 :
43 : // ===========================================================================
44 : // DEBUGGING HELPERS
45 : // ===========================================================================
46 : //
47 : #define DEBUGID1 ""
48 : #define DEBUGID2 ""
49 : //#define DEBUGCOND(PED) (false)
50 : //#define DEBUGCOND(PED) ((PED).getPerson()->getID() == DEBUGID1 || (PED).getPerson()->getID() == DEBUGID2)
51 : #define DEBUGCOND(PED) ((PED).getPerson()->isSelected())
52 : #define DEBUGCOND2(LANE) ((LANE)->isSelected())
53 : //#define LOG_ALL 1
54 : //#define DEBUG_MOVETOXY
55 :
56 0 : void MSPModel_Striping::DEBUG_PRINT(const Obstacles& obs) {
57 0 : for (int i = 0; i < (int)obs.size(); ++i) {
58 : std::cout
59 0 : << "(" << obs[i].description
60 0 : << " x=(" << obs[i].xBack << "," << obs[i].xFwd
61 0 : << ") s=" << obs[i].speed
62 0 : << ") ";
63 : }
64 0 : std::cout << "\n";
65 0 : }
66 :
67 : // ===========================================================================
68 : // named (internal) constants
69 : // ===========================================================================
70 :
71 : // distances are comparable with lower values being "more important"
72 : const double MSPModel_Striping::DIST_FAR_AWAY(10000);
73 : const double MSPModel_Striping::DIST_BEHIND(1000);
74 : const double MSPModel_Striping::DIST_OVERLAP(-1);
75 :
76 : // ===========================================================================
77 : // static members
78 : // ===========================================================================
79 :
80 : MSPModel_Striping::WalkingAreaPaths MSPModel_Striping::myWalkingAreaPaths;
81 : std::map<const MSEdge*, std::vector<const MSLane*> > MSPModel_Striping::myWalkingAreaFoes;
82 : MSPModel_Striping::MinNextLengths MSPModel_Striping::myMinNextLengths;
83 :
84 : // model parameters (static to simplify access from class PState
85 : double MSPModel_Striping::stripeWidth;
86 : double MSPModel_Striping::dawdling;
87 : double MSPModel_Striping::minGapToVehicle;
88 : int MSPModel_Striping::myWalkingAreaDetail;
89 : SUMOTime MSPModel_Striping::jamTime;
90 : SUMOTime MSPModel_Striping::jamTimeCrossing;
91 : SUMOTime MSPModel_Striping::jamTimeNarrow;
92 : double MSPModel_Striping::jamFactor;
93 : bool MSPModel_Striping::myLegacyPosLat;
94 : const double MSPModel_Striping::LOOKAHEAD_SAMEDIR(4.0); // seconds
95 : const double MSPModel_Striping::LOOKAHEAD_ONCOMING(10.0); // seconds
96 : const double MSPModel_Striping::LOOKAHEAD_ONCOMING_DIST(10.0); // m
97 : const double MSPModel_Striping::LOOKAROUND_VEHICLES(60.0); // meters
98 : const double MSPModel_Striping::LATERAL_PENALTY(-1.); // meters
99 : const double MSPModel_Striping::OBSTRUCTED_PENALTY(-300000.); // meters
100 : const double MSPModel_Striping::INAPPROPRIATE_PENALTY(-20000.); // meters
101 : const double MSPModel_Striping::ONCOMING_CONFLICT_PENALTY(-1000.); // meters
102 : const double MSPModel_Striping::OBSTRUCTION_THRESHOLD(MSPModel_Striping::OBSTRUCTED_PENALTY * 0.5); // despite obstruction, additional utility may have been added
103 : const double MSPModel_Striping::SQUEEZE(0.7);
104 : double MSPModel_Striping::RESERVE_FOR_ONCOMING_FACTOR;
105 : double MSPModel_Striping::RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS;
106 : double MSPModel_Striping::RESERVE_FOR_ONCOMING_MAX;
107 : bool MSPModel_Striping::USE_NET_SPEEDS(false);
108 : const double MSPModel_Striping::MAX_WAIT_TOLERANCE(120.); // seconds
109 : const double MSPModel_Striping::LATERAL_SPEED_FACTOR(0.4);
110 : const double MSPModel_Striping::MIN_STARTUP_DIST(0.4); // meters
111 :
112 :
113 : // ===========================================================================
114 : // MSPModel_Striping method definitions
115 : // ===========================================================================
116 :
117 6083 : MSPModel_Striping::MSPModel_Striping(const OptionsCont& oc, MSNet* net) {
118 6083 : myWalkingAreaDetail = oc.getInt("pedestrian.striping.walkingarea-detail");
119 6083 : initWalkingAreaPaths(net);
120 : // configurable parameters
121 6083 : stripeWidth = oc.getFloat("pedestrian.striping.stripe-width");
122 6083 : MSVehicleType* defaultPedType = MSNet::getInstance()->getVehicleControl().getVType(DEFAULT_PEDTYPE_ID, nullptr, true);
123 6083 : if (defaultPedType != nullptr && defaultPedType->getWidth() > stripeWidth) {
124 12 : WRITE_WARNINGF(TL("Pedestrian vType '%' width % is larger than pedestrian.striping.stripe-width and this may cause collisions with vehicles."),
125 : DEFAULT_PEDTYPE_ID, defaultPedType->getWidth());
126 : }
127 :
128 6083 : dawdling = oc.getFloat("pedestrian.striping.dawdling");
129 6083 : minGapToVehicle = oc.getFloat("pedestrian.striping.mingap-to-vehicle");
130 6083 : RESERVE_FOR_ONCOMING_FACTOR = oc.getFloat("pedestrian.striping.reserve-oncoming");
131 6083 : RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS = oc.getFloat("pedestrian.striping.reserve-oncoming.junctions");
132 6083 : RESERVE_FOR_ONCOMING_MAX = oc.getFloat("pedestrian.striping.reserve-oncoming.max");
133 : // beginning with 1.20.0, sensible default speeds were set for crossings and walkingareas
134 6083 : USE_NET_SPEEDS = net->getNetworkVersion() >= MMVersion(1, 20);
135 :
136 6083 : jamTime = string2time(oc.getString("pedestrian.striping.jamtime"));
137 6083 : if (jamTime <= 0) {
138 4 : jamTime = SUMOTime_MAX;
139 : }
140 6083 : jamTimeCrossing = string2time(oc.getString("pedestrian.striping.jamtime.crossing"));
141 6083 : if (jamTimeCrossing <= 0) {
142 0 : jamTimeCrossing = SUMOTime_MAX;
143 : }
144 6083 : jamTimeNarrow = string2time(oc.getString("pedestrian.striping.jamtime.narrow"));
145 6083 : if (jamTimeNarrow <= 0) {
146 0 : jamTimeNarrow = SUMOTime_MAX;
147 : }
148 6083 : jamFactor = oc.getFloat("pedestrian.striping.jamfactor");
149 6083 : myLegacyPosLat = oc.getBool("pedestrian.striping.legacy-departposlat");
150 6083 : }
151 :
152 :
153 12146 : MSPModel_Striping::~MSPModel_Striping() {
154 : myWalkingAreaPaths.clear(); // need to recompute when lane pointers change
155 : myWalkingAreaFoes.clear();
156 : myMinNextLengths.clear();
157 12146 : }
158 :
159 :
160 : MSTransportableStateAdapter*
161 243922 : MSPModel_Striping::add(MSTransportable* transportable, MSStageMoving* stage, SUMOTime) {
162 243922 : if (!transportable->isPerson()) {
163 : // containers are not supported (TODO add a warning here?)
164 : return nullptr;
165 : }
166 : MSPerson* person = static_cast<MSPerson*>(transportable);
167 243922 : MSNet* net = MSNet::getInstance();
168 243922 : if (!myAmActive) {
169 4277 : net->getBeginOfTimestepEvents()->addEvent(new MovePedestrians(this), net->getCurrentTimeStep() + DELTA_T);
170 4277 : myAmActive = true;
171 : }
172 : assert(person->getCurrentStageType() == MSStageType::WALKING);
173 243922 : const MSLane* lane = stage->checkDepartLane(person->getEdge(), person->getVClass(), stage->getDepartLane(), person->getID());
174 243922 : if (lane == nullptr) {
175 8 : const char* error = TL("Person '%' could not find sidewalk on edge '%', time=%.");
176 16 : if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
177 24 : WRITE_WARNINGF(error, person->getID(), person->getEdge()->getID(), time2string(net->getCurrentTimeStep()));
178 8 : return nullptr;
179 : } else {
180 0 : throw ProcessError(TLF(error, person->getID(), person->getEdge()->getID(), time2string(net->getCurrentTimeStep())));
181 : }
182 : }
183 243914 : PState* ped = new PState(person, stage, lane);
184 243910 : myActiveLanes[lane].push_back(ped);
185 243910 : myNumActivePedestrians++;
186 243910 : return ped;
187 : }
188 :
189 :
190 : MSTransportableStateAdapter*
191 14 : MSPModel_Striping::loadState(MSTransportable* transportable, MSStageMoving* stage, std::istringstream& in) {
192 : MSPerson* person = static_cast<MSPerson*>(transportable);
193 14 : MSNet* net = MSNet::getInstance();
194 14 : if (!myAmActive) {
195 12 : net->getBeginOfTimestepEvents()->addEvent(new MovePedestrians(this), SIMSTEP);
196 12 : myAmActive = true;
197 : }
198 14 : PState* ped = new PState(person, stage, &in);
199 14 : myActiveLanes[ped->getLane()].push_back(ped);
200 14 : myNumActivePedestrians++;
201 14 : return ped;
202 : }
203 :
204 :
205 : int
206 8379379178 : MSPModel_Striping::numStripes(const MSLane* lane) {
207 8379379178 : return MAX2(1, (int)floor(lane->getWidth() / stripeWidth));
208 : }
209 :
210 :
211 : int
212 849589 : MSPModel_Striping::connectedDirection(const MSLane* from, const MSLane* to) {
213 849589 : if (from == nullptr || to == nullptr) {
214 0 : return UNDEFINED_DIRECTION;
215 849589 : } else if (from->getLinkTo(to) != nullptr) {
216 602108 : return FORWARD;
217 247481 : } else if (to->getLinkTo(from) != nullptr) {
218 247481 : return BACKWARD;
219 : } else {
220 0 : return UNDEFINED_DIRECTION;
221 : }
222 : }
223 :
224 :
225 : void
226 6083 : MSPModel_Striping::initWalkingAreaPaths(const MSNet*) {
227 6083 : if (myWalkingAreaPaths.size() > 0) {
228 : return;
229 : }
230 : // collect vehicle lanes that cross walkingareas
231 421279 : for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
232 415197 : const MSEdge* edge = *i;
233 415197 : if (!edge->isWalkingArea() && !edge->isCrossing()) {
234 768681 : for (MSLane* lane : edge->getLanes()) {
235 941025 : for (MSLink* link : lane->getLinkCont()) {
236 519040 : if (link->getWalkingAreaFoe() != nullptr) {
237 : // link is an exit link
238 2936 : myWalkingAreaFoes[&link->getWalkingAreaFoe()->getEdge()].push_back(link->getLaneBefore());
239 : //std::cout << " wa=" << link->getWalkingAreaFoe()->getEdge().getID() << " foe=" << link->getLaneBefore()->getID() << "\n";
240 : }
241 519040 : if (link->getWalkingAreaFoeExit() != nullptr) {
242 : // link is an exit link
243 3022 : myWalkingAreaFoes[&link->getWalkingAreaFoeExit()->getEdge()].push_back(link->getLaneBefore());
244 : //std::cout << " wa=" << link->getWalkingAreaFoeExit()->getEdge().getID() << " foe=" << link->getLaneBefore()->getID() << "\n";
245 : }
246 : }
247 : }
248 : }
249 : }
250 :
251 : // build walkingareaPaths
252 421279 : for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
253 415197 : insertWalkArePaths(*i, myWalkingAreaPaths);
254 : }
255 : }
256 :
257 :
258 : void
259 415197 : MSPModel_Striping::insertWalkArePaths(const MSEdge* edge, WalkingAreaPaths& into) {
260 415197 : if (edge->isWalkingArea()) {
261 60045 : const MSLane* walkingArea = getSidewalk<MSEdge, MSLane>(edge);
262 60045 : myMinNextLengths[walkingArea] = walkingArea->getLength();
263 : // build all possible paths across this walkingArea
264 : // gather all incident lanes
265 : std::vector<const MSLane*> lanes;
266 133626 : for (const MSEdge* in : edge->getPredecessors()) {
267 73581 : if (!in->isTazConnector()) {
268 69235 : lanes.push_back(getSidewalk<MSEdge, MSLane>(in));
269 69235 : if (lanes.back() == nullptr) {
270 0 : throw ProcessError("Invalid connection from edge '" + in->getID() + "' to walkingarea edge '" + edge->getID() + "'");
271 : }
272 : }
273 : }
274 133812 : for (const MSEdge* out : edge->getSuccessors()) {
275 73767 : if (!out->isTazConnector()) {
276 69421 : lanes.push_back(getSidewalk<MSEdge, MSLane>(out));
277 69421 : if (lanes.back() == nullptr) {
278 0 : throw ProcessError("Invalid connection from walkingarea edge '" + edge->getID() + "' to edge '" + out->getID() + "'");
279 : }
280 : }
281 : }
282 : // build all combinations
283 198701 : for (int j = 0; j < (int)lanes.size(); ++j) {
284 485516 : for (int k = 0; k < (int)lanes.size(); ++k) {
285 346860 : if (j != k) {
286 : // build the walkingArea
287 208204 : const MSLane* const from = lanes[j];
288 208204 : const MSLane* const to = lanes[k];
289 208204 : const int fromDir = from->getLinkTo(walkingArea) != nullptr ? FORWARD : BACKWARD;
290 208204 : const int toDir = walkingArea->getLinkTo(to) != nullptr ? FORWARD : BACKWARD;
291 208204 : PositionVector shape;
292 312563 : Position fromPos = from->getShape()[fromDir == FORWARD ? -1 : 0];
293 312049 : Position toPos = to->getShape()[toDir == FORWARD ? 0 : -1];
294 208204 : const double maxExtent = fromPos.distanceTo2D(toPos) / 4; // prevent sharp corners
295 208204 : const double extrapolateBy = MIN2(maxExtent, walkingArea->getWidth() / 2);
296 : // assemble shape
297 208204 : shape.push_back(fromPos);
298 208204 : if (extrapolateBy > POSITION_EPS) {
299 : PositionVector fromShp = from->getShape();
300 207194 : fromShp.extrapolate(extrapolateBy);
301 414388 : shape.push_back_noDoublePos(fromDir == FORWARD ? fromShp.back() : fromShp.front());
302 : PositionVector nextShp = to->getShape();
303 207194 : nextShp.extrapolate(extrapolateBy);
304 414388 : shape.push_back_noDoublePos(toDir == FORWARD ? nextShp.front() : nextShp.back());
305 207194 : }
306 208204 : shape.push_back_noDoublePos(toPos);
307 208204 : if (shape.size() < 2) {
308 : PositionVector fromShp = from->getShape();
309 554 : fromShp.extrapolate(1.5 * POSITION_EPS); // noDoublePos requires a difference of POSITION_EPS in at least one coordinate
310 1108 : shape.push_back_noDoublePos(fromDir == FORWARD ? fromShp.back() : fromShp.front());
311 : assert(shape.size() == 2);
312 208204 : } else if (myWalkingAreaDetail > 4) {
313 448 : shape = shape.bezier(myWalkingAreaDetail);
314 : }
315 : double angleOverride = INVALID_DOUBLE;
316 208204 : if (shape.size() >= 4 && shape.length() < walkingArea->getWidth()) {
317 53894 : const double aStart = shape.angleAt2D(0);
318 53894 : const double aEnd = shape.angleAt2D((int)shape.size() - 2);
319 53894 : if (fabs(aStart - aEnd) < DEG2RAD(10)) {
320 9032 : angleOverride = (aStart + aEnd) / 2;
321 : }
322 : }
323 208204 : if (fromDir == BACKWARD) {
324 : // will be walking backward on walkingArea
325 208718 : shape = shape.reverse();
326 : }
327 208204 : WalkingAreaPath wap = WalkingAreaPath(from, walkingArea, to, shape, fromDir, angleOverride);
328 208204 : into.insert(std::make_pair(std::make_pair(from, to), wap));
329 241311 : myMinNextLengths[walkingArea] = MIN2(myMinNextLengths[walkingArea], wap.length);
330 208204 : }
331 : }
332 : }
333 60045 : }
334 415197 : }
335 :
336 :
337 : const MSPModel_Striping::WalkingAreaPath*
338 6 : MSPModel_Striping::getArbitraryPath(const MSEdge* walkingArea) {
339 : assert(walkingArea->isWalkingArea());
340 : std::vector<const MSLane*> lanes;
341 18 : for (const MSEdge* const pred : walkingArea->getPredecessors()) {
342 12 : lanes.push_back(getSidewalk<MSEdge, MSLane>(pred));
343 : }
344 18 : for (const MSEdge* const succ : walkingArea->getSuccessors()) {
345 12 : lanes.push_back(getSidewalk<MSEdge, MSLane>(succ));
346 : }
347 6 : if (lanes.size() < 1) {
348 0 : throw ProcessError(TLF("Invalid walkingarea '%' does not allow continuation.", walkingArea->getID()));
349 : }
350 6 : return &myWalkingAreaPaths.find(std::make_pair(lanes.front(), lanes.back()))->second;
351 6 : }
352 :
353 : const MSPModel_Striping::WalkingAreaPath*
354 61 : MSPModel_Striping::guessPath(const MSEdge* walkingArea, const MSEdge* before, const MSEdge* after) {
355 : assert(walkingArea->isWalkingArea());
356 61 : const MSLane* swBefore = getSidewalk<MSEdge, MSLane>(before);
357 61 : const MSLane* swAfter = getSidewalk<MSEdge, MSLane>(after);
358 61 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(swBefore, swAfter));
359 61 : if (pathIt != myWalkingAreaPaths.end()) {
360 24 : return &pathIt->second;
361 : }
362 : const MSEdgeVector& preds = walkingArea->getPredecessors();
363 37 : const MSEdgeVector& succs = walkingArea->getSuccessors();
364 37 : bool useBefore = swBefore != nullptr && std::find(preds.begin(), preds.end(), before) != preds.end();
365 37 : bool useAfter = swAfter != nullptr && std::find(succs.begin(), succs.end(), after) != succs.end();
366 37 : if (useBefore) {
367 29 : if (useAfter) {
368 0 : return getWalkingAreaPath(walkingArea, swBefore, swAfter);
369 29 : } else if (succs.size() > 0) {
370 : // could also try to exploit direction
371 29 : return getWalkingAreaPath(walkingArea, swBefore, getSidewalk<MSEdge, MSLane>(succs.front()));
372 : }
373 8 : } else if (useAfter && preds.size() > 0) {
374 : // could also try to exploit direction
375 8 : return getWalkingAreaPath(walkingArea, getSidewalk<MSEdge, MSLane>(preds.front()), swAfter);
376 : }
377 0 : return getArbitraryPath(walkingArea);
378 : }
379 :
380 :
381 : const MSPModel_Striping::WalkingAreaPath*
382 834858 : MSPModel_Striping::getWalkingAreaPath(const MSEdge* walkingArea, const MSLane* before, const MSLane* after) {
383 : assert(walkingArea->isWalkingArea());
384 834858 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(before, after));
385 834858 : if (pathIt != myWalkingAreaPaths.end()) {
386 834818 : return &pathIt->second;
387 : } else {
388 : // this can happen in case of moveToXY where before can point anywhere
389 : const MSEdgeVector& preds = walkingArea->getPredecessors();
390 40 : if (preds.size() > 0) {
391 40 : const MSEdge* const pred = walkingArea->getPredecessors().front();
392 40 : const auto pathIt2 = myWalkingAreaPaths.find(std::make_pair(getSidewalk<MSEdge, MSLane>(pred), after));
393 : assert(pathIt2 != myWalkingAreaPaths.end());
394 40 : return &pathIt2->second;
395 : } else {
396 0 : return getArbitraryPath(walkingArea);
397 : }
398 : }
399 : }
400 :
401 :
402 :
403 : MSPModel_Striping::NextLaneInfo
404 1503905 : MSPModel_Striping::getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane) {
405 : const MSEdge* currentEdge = ¤tLane->getEdge();
406 1503905 : const MSJunction* junction = ped.getDirection() == FORWARD ? currentEdge->getToJunction() : currentEdge->getFromJunction();
407 1503905 : const MSEdge* nextRouteEdge = ped.getStage()->getNextRouteEdge();
408 1503905 : const MSLane* nextRouteLane = getSidewalk<MSEdge, MSLane>(nextRouteEdge, ped.getPerson()->getVClass());
409 : // result values
410 : const MSLane* nextLane = nextRouteLane;
411 1503905 : const MSLink* link = nullptr;
412 1503905 : int nextDir = UNDEFINED_DIRECTION;
413 :
414 : //if DEBUGCOND(ped) {
415 : // std::cout << " nextRouteLane=" << Named::getIDSecure(nextRouteLane) << " junction=" << junction->getID() << "\n";
416 : //}
417 1503905 : if (nextRouteLane == nullptr && nextRouteEdge != nullptr) {
418 56 : std::string error = "Person '" + ped.getPerson()->getID() + "' could not find sidewalk on edge '" + nextRouteEdge->getID() + "', time="
419 56 : + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".";
420 56 : if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
421 76 : WRITE_WARNING(error);
422 24 : nextRouteLane = nextRouteEdge->getLanes().front();
423 : } else {
424 4 : throw ProcessError(error);
425 : }
426 : }
427 :
428 1503901 : if (nextRouteLane != nullptr) {
429 1271681 : if (currentEdge->isInternal()) {
430 : assert(junction == currentEdge->getFromJunction());
431 23638 : nextDir = junction == nextRouteEdge->getFromJunction() ? FORWARD : BACKWARD;
432 23638 : if (nextDir == FORWARD) {
433 22663 : nextLane = currentLane->getLinkCont()[0]->getViaLaneOrLane();
434 : } else {
435 975 : nextLane = currentLane->getLogicalPredecessorLane();
436 : }
437 23638 : if DEBUGCOND(ped) {
438 0 : std::cout << " internal\n";
439 : }
440 1248043 : } else if (currentEdge->isCrossing()) {
441 33163 : nextDir = ped.getDirection();
442 33163 : if (nextDir == FORWARD) {
443 16848 : nextLane = currentLane->getLinkCont()[0]->getLane();
444 : } else {
445 16315 : nextLane = currentLane->getLogicalPredecessorLane();
446 : }
447 33163 : if DEBUGCOND(ped) {
448 0 : std::cout << " crossing\n";
449 : }
450 33163 : if (currentLane->isPriorityCrossing()) {
451 31130 : unregisterCrossingApproach(ped, currentLane);
452 : }
453 1214880 : } else if (currentEdge->isWalkingArea()) {
454 : ConstMSEdgeVector crossingRoute;
455 : // departPos can be 0 because the direction of the walkingArea does not matter
456 : // for the arrivalPos, we need to make sure that the route does not deviate across other junctions
457 849626 : const int nextRouteEdgeDir = nextRouteEdge->getFromJunction() == junction ? FORWARD : BACKWARD;
458 849626 : const double arrivalPos = (nextRouteEdge == ped.getStage()->getRoute().back()
459 849626 : ? ped.getStage()->getArrivalPos()
460 204835 : : (nextRouteEdgeDir == FORWARD ? 0 : nextRouteEdge->getLength()));
461 : SUMOAbstractRouter<MSEdge, SUMOVehicle>::Prohibitions prohibited;
462 849626 : if (prevLane != nullptr) {
463 849568 : prohibited[&prevLane->getEdge()].end = std::numeric_limits<double>::max();
464 : }
465 1699252 : MSNet::getInstance()->getPedestrianRouter(0, prohibited).compute(currentEdge, nextRouteEdge, 0, arrivalPos,
466 849626 : ped.getStage()->getMaxSpeed(ped.getPerson()),
467 849626 : 0, junction, ped.getPerson()->getVTypeParameter(), crossingRoute, true);
468 849626 : if DEBUGCOND(ped) {
469 : std::cout
470 : << " nre=" << nextRouteEdge->getID()
471 : << " nreDir=" << nextRouteEdgeDir
472 0 : << " aPos=" << arrivalPos
473 0 : << " crossingRoute=" << toString(crossingRoute)
474 0 : << "\n";
475 : }
476 849626 : if (crossingRoute.size() > 1) {
477 849589 : const MSEdge* nextEdge = crossingRoute[1];
478 849589 : nextLane = getSidewalk<MSEdge, MSLane>(crossingRoute[1], ped.getPerson()->getVClass());
479 : assert((nextEdge->getFromJunction() == junction || nextEdge->getToJunction() == junction));
480 : assert(nextLane != prevLane);
481 849589 : nextDir = connectedDirection(currentLane, nextLane);
482 849589 : if DEBUGCOND(ped) {
483 0 : std::cout << " nextDir=" << nextDir << "\n";
484 : }
485 : assert(nextDir != UNDEFINED_DIRECTION);
486 849589 : if (nextDir == FORWARD) {
487 602108 : link = currentLane->getLinkTo(nextLane);
488 : } else {
489 247481 : link = nextLane->getLinkTo(currentLane);
490 247481 : if (nextEdge->isCrossing() && link->getTLLogic() == nullptr) {
491 195219 : const MSLane* oppositeWalkingArea = nextLane->getLogicalPredecessorLane();
492 195219 : link = oppositeWalkingArea->getLinkTo(nextLane);
493 : }
494 : }
495 : assert(link != nullptr);
496 849589 : if (nextLane->isPriorityCrossing()) {
497 488017 : registerCrossingApproach(ped, nextLane, prevLane);
498 : }
499 : } else {
500 37 : if DEBUGCOND(ped) {
501 0 : std::cout << SIMTIME
502 0 : << " no route from '" << (currentEdge == nullptr ? "NULL" : currentEdge->getID())
503 0 : << "' to '" << (nextRouteEdge == nullptr ? "NULL" : nextRouteEdge->getID())
504 0 : << "\n";
505 : }
506 : // check if a direct connection exists (moving onto the walkingarea was the wrong choice)
507 37 : if (ped.getDirection() == FORWARD) {
508 24 : link = prevLane->getLinkTo(nextRouteLane);
509 : } else {
510 13 : link = nextRouteLane->getLinkTo(prevLane);
511 : }
512 37 : if (link != nullptr) {
513 : // leave direction as UNDEFINED_DIRECTION to signal that currentLane must be changed
514 : nextLane = link->getViaLaneOrLane();
515 : } else {
516 80 : WRITE_WARNING("Person '" + ped.getPerson()->getID() + "' could not find route across junction '" + junction->getID()
517 : + "' from walkingArea '" + currentEdge->getID()
518 : + "' to edge '" + nextRouteEdge->getID() + "', time=" +
519 : time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
520 : // error indicated by nextDir == UNDEFINED_DIRECTION
521 : nextLane = nextRouteLane;
522 : }
523 : }
524 1214880 : } else if (currentEdge == nextRouteEdge) {
525 : // strange loop in this route. No need to use walkingArea
526 8 : nextDir = -ped.getDirection();
527 : } else {
528 : // normal edge. by default use next / previous walking area
529 365246 : nextDir = ped.getDirection();
530 365246 : nextLane = getNextWalkingArea(currentLane, ped.getDirection(), link);
531 365246 : if (nextLane != nullptr) {
532 : // walking area found
533 326457 : if DEBUGCOND(ped) {
534 0 : std::cout << " next walkingArea " << (nextDir == FORWARD ? "forward" : "backward") << "\n";
535 : }
536 : } else {
537 : // walk forward by default
538 38789 : if (junction == nextRouteEdge->getToJunction()) {
539 3949 : nextDir = BACKWARD;
540 34840 : } else if (junction == nextRouteEdge->getFromJunction()) {
541 : nextDir = FORWARD;
542 : } else {
543 : // topological disconnect, find a direction that makes sense
544 : // for the future part of the route
545 212 : ConstMSEdgeVector futureRoute = ped.getStage()->getRoute();
546 212 : futureRoute.erase(futureRoute.begin(), futureRoute.begin() + ped.getStage()->getRoutePosition() + 1);
547 212 : int passedFwd = 0;
548 212 : int passedBwd = 0;
549 212 : canTraverse(FORWARD, futureRoute, passedFwd);
550 212 : canTraverse(BACKWARD, futureRoute, passedBwd);
551 212 : nextDir = (passedFwd >= passedBwd) ? FORWARD : BACKWARD;
552 212 : if DEBUGCOND(ped) {
553 0 : std::cout << " nextEdge=" << nextRouteEdge->getID() << " passedFwd=" << passedFwd << " passedBwd=" << passedBwd << " futureRoute=" << toString(futureRoute) << " nextDir=" << nextDir << "\n";
554 : }
555 212 : }
556 : // try to use a direct link as fallback
557 : // direct links only exist if built explicitly. They are used to model tl-controlled links if there are no crossings
558 38789 : if (ped.getDirection() == FORWARD) {
559 34315 : link = currentLane->getLinkTo(nextRouteLane);
560 34315 : if (link != nullptr) {
561 32640 : if DEBUGCOND(ped) {
562 0 : std::cout << " direct forward\n";
563 : }
564 32640 : nextLane = currentLane->getInternalFollowingLane(nextRouteLane);
565 : }
566 : } else {
567 4474 : link = nextRouteLane->getLinkTo(currentLane);
568 4474 : if (link != nullptr) {
569 3183 : if DEBUGCOND(ped) {
570 0 : std::cout << " direct backward\n";
571 : }
572 3183 : nextLane = nextRouteLane->getInternalFollowingLane(currentLane);
573 3183 : if (nextLane != nullptr) {
574 : // advance to the end of consecutive internal lanes
575 5317 : while (nextLane->getLinkCont()[0]->getViaLaneOrLane()->isInternal()) {
576 5 : nextLane = nextLane->getLinkCont()[0]->getViaLaneOrLane();
577 : }
578 : }
579 : }
580 : }
581 : }
582 364719 : if (nextLane == nullptr) {
583 : // no internal lane found
584 : nextLane = nextRouteLane;
585 8804 : if DEBUGCOND(ped) {
586 0 : std::cout << SIMTIME << " no next lane found for " << currentLane->getID() << " dir=" << ped.getDirection() << "\n";
587 : }
588 8804 : if (usingInternalLanesStatic() && currentLane->getLinkCont().size() > 0) {
589 0 : WRITE_WARNING("Person '" + ped.getPerson()->getID() + "' could not find route across junction '" + junction->getID()
590 : + "' from edge '" + currentEdge->getID()
591 : + "' to edge '" + nextRouteEdge->getID() + "', time=" +
592 : time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
593 : }
594 356442 : } else if (nextLane->getLength() <= POSITION_EPS) {
595 : // internal lane too short
596 : // most often this is due to a zero-size junction. However, if
597 : // the person needs to pass a crossing we cannot skip ahead
598 10955 : if ((nextLane->getCanonicalSuccessorLane() == nullptr
599 10947 : || !nextLane->getCanonicalSuccessorLane()->isCrossing())
600 32845 : && (nextLane->getLogicalPredecessorLane() == nullptr ||
601 10943 : !nextLane->getLogicalPredecessorLane()->isCrossing())) {
602 : //WRITE_WARNING("Person '" + ped.getID()
603 : // + "' skips short lane '" + nextLane->getID()
604 : // + "' length=" + toString(nextLane->getLength())
605 : // + " time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
606 : nextLane = nextRouteLane;
607 10955 : nextDir = nextRouteEdge->getFromJunction() == junction ? FORWARD : BACKWARD;
608 : }
609 : }
610 : }
611 : }
612 1503901 : if DEBUGCOND(ped) {
613 0 : std::cout << SIMTIME
614 : << " p=" << ped.getPerson()->getID()
615 : << " l=" << currentLane->getID()
616 0 : << " nl=" << (nextLane == nullptr ? "NULL" : nextLane->getID())
617 0 : << " nrl=" << (nextRouteLane == nullptr ? "NULL" : nextRouteLane->getID())
618 : << " d=" << nextDir
619 0 : << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
620 0 : << " pedDir=" << ped.getDirection()
621 0 : << "\n";
622 : }
623 : assert(nextLane != 0 || nextRouteLane == 0);
624 1503901 : return NextLaneInfo(nextLane, link, nextDir);
625 : }
626 :
627 :
628 : const MSLane*
629 365246 : MSPModel_Striping::getNextWalkingArea(const MSLane* currentLane, const int dir, const MSLink*& link) {
630 365246 : if (dir == FORWARD) {
631 365057 : for (const MSLink* const l : currentLane->getLinkCont()) {
632 330742 : if (l->getLane()->isWalkingArea()) {
633 270035 : link = l;
634 : return l->getLane();
635 : }
636 : }
637 : } else {
638 : const std::vector<MSLane::IncomingLaneInfo>& laneInfos = currentLane->getIncomingLanes();
639 67538 : for (std::vector<MSLane::IncomingLaneInfo>::const_iterator it = laneInfos.begin(); it != laneInfos.end(); ++it) {
640 63064 : if ((*it).lane->isWalkingArea()) {
641 56422 : link = (*it).viaLink;
642 56422 : return (*it).lane;
643 : }
644 : }
645 : }
646 : return nullptr;
647 : }
648 :
649 :
650 : MSPModel_Striping::Obstacles
651 71106446 : MSPModel_Striping::getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes) {
652 71106446 : const PState& ego = *static_cast<PState*>(pedestrians[egoIndex]);
653 71106446 : const int egoStripe = ego.stripe();
654 71106446 : Obstacles obs(stripes, Obstacle(ego.getDirection()));
655 71106446 : std::vector<bool> haveBlocker(stripes, false);
656 10795040390 : for (int index = egoIndex + 1; index < (int)pedestrians.size(); index++) {
657 10780633723 : const PState& p = *static_cast<PState*>(pedestrians[index]);
658 10780633723 : if DEBUGCOND(ego) {
659 0 : std::cout << SIMTIME << " ped=" << ego.getID() << " cur=" << egoStripe << " checking neighbor " << p.getID()
660 0 : << " nCur=" << p.stripe() << " nOth=" << p.otherStripe();
661 : }
662 10780633723 : if (!p.isWaitingToEnter() && !p.isJammed()) {
663 147680856 : const Obstacle o(p);
664 147680856 : if DEBUGCOND(ego) {
665 0 : std::cout << " dist=" << ego.distanceTo(o) << std::endl;
666 : }
667 147680856 : if (ego.distanceTo(o) == DIST_BEHIND) {
668 : break;
669 : }
670 90981077 : if (ego.distanceTo(o) == DIST_OVERLAP) {
671 90981077 : if (p.stripe() != egoStripe || p.getDirection() != ego.getDirection()) {
672 67485445 : obs[p.stripe()] = o;
673 67485445 : haveBlocker[p.stripe()] = true;
674 : } else {
675 : //std::cout << SIMTIME << " ignoring overlap between " << ego.getID() << " and " << p.getID() << " on stripe=" << egoStripe << "\n";
676 : }
677 90981077 : if (p.otherStripe() != egoStripe || p.getDirection() != ego.getDirection()) {
678 67485445 : obs[p.otherStripe()] = o;
679 67485445 : haveBlocker[p.otherStripe()] = true;
680 : } else {
681 : //std::cout << SIMTIME << " ignoring overlap between " << ego.getID() << " and " << p.getID() << " on stripe2=" << egoStripe << "\n";
682 : }
683 : } else {
684 0 : if (!haveBlocker[p.stripe()]) {
685 0 : obs[p.stripe()] = o;
686 : }
687 0 : if (!haveBlocker[p.otherStripe()]) {
688 0 : obs[p.otherStripe()] = o;
689 : }
690 : }
691 : }
692 : }
693 71106446 : if DEBUGCOND(ego) {
694 0 : std::cout << SIMTIME << " ped=" << ego.getPerson()->getID() << " neighObs=";
695 0 : DEBUG_PRINT(obs);
696 : }
697 71106446 : return obs;
698 0 : }
699 :
700 :
701 : int
702 3109180 : MSPModel_Striping::getStripeOffset(int origStripes, int destStripes, bool addRemainder) {
703 3109180 : int offset = (destStripes - origStripes) / 2;
704 3109180 : if (addRemainder) {
705 13342 : offset += (destStripes - origStripes) % 2;
706 : }
707 3109180 : return offset;
708 : }
709 :
710 :
711 : const MSPModel_Striping::Obstacles&
712 18404794 : MSPModel_Striping::getNextLaneObstacles(NextLanesObstacles& nextLanesObs, const
713 : MSLane* lane, const MSLane* nextLane, int stripes, int nextDir,
714 : double currentLength, int currentDir) {
715 : if (nextLanesObs.count(nextLane) == 0) {
716 2352263 : const double nextLength = nextLane->isWalkingArea() ? myMinNextLengths[nextLane] : nextLane->getLength();
717 : // figure out the which pedestrians are ahead on the next lane
718 2352263 : const int nextStripes = numStripes(nextLane);
719 : // do not move past the end of the next lane in a single step
720 4704526 : Obstacles obs(stripes, Obstacle(nextDir == FORWARD ? nextLength : 0, 0, OBSTACLE_NEXTEND, "nextEnd", 0));
721 :
722 2352263 : const int offset = getStripeOffset(nextStripes, stripes, currentDir != nextDir && nextStripes > stripes);
723 : //std::cout << SIMTIME << " getNextLaneObstacles"
724 : // << " nextLane=" << nextLane->getID()
725 : // << " nextLength=" << nextLength
726 : // << " nextDir=" << nextDir
727 : // << " currentLength=" << currentLength
728 : // << " currentDir=" << currentDir
729 : // << " stripes=" << stripes
730 : // << " nextStripes=" << nextStripes
731 : // << " offset=" << offset
732 : // << "\n";
733 2352263 : if (nextStripes < stripes) {
734 : // some stripes do not continue
735 2041323 : for (int ii = 0; ii < stripes; ++ii) {
736 1761870 : if (ii < offset || ii >= nextStripes + offset) {
737 2418408 : obs[ii] = Obstacle(nextDir == FORWARD ? 0 : nextLength, 0, OBSTACLE_END, "stripeEnd", 0);
738 : }
739 : }
740 : }
741 2352263 : Pedestrians& pedestrians = getPedestrians(nextLane);
742 2352263 : if (nextLane->isWalkingArea()) {
743 1211080 : transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
744 : // complex transformation into the coordinate system of the current lane
745 : // (pedestrians on next lane may walk at arbitrary angles relative to the current lane)
746 1211080 : double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
747 1211080 : if ((stripes - nextStripes) % 2 != 0) {
748 457699 : lateral_offset += 0.5 * stripeWidth;
749 : }
750 : nextDir = currentDir;
751 : // transform pedestrians into the current coordinate system
752 9051774 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
753 7840694 : const PState& p = *static_cast<PState*>(pedestrians[ii]);
754 7840694 : if (p.isWaitingToEnter() || p.isJammed()) {
755 2663777 : continue;
756 : }
757 5176917 : Position pPos = p.getPosition(*p.getStage(), -1);
758 5176917 : Position relPos = lane->getShape().transformToVectorCoordinates(pPos, true);
759 : if (relPos == Position::INVALID) {
760 0 : WRITE_WARNINGF("Could not map position % onto lane '%'", pPos, lane->getID());
761 : }
762 5176917 : const double newY = relPos.y() + lateral_offset;
763 : //if (p.getPerson()->getID() == "ped200") std::cout << " ped=" << p.getPerson()->getID() << " relX=" << relPos.x() << " relY=" << newY << " latOff=" << lateral_offset << " s=" << p.stripe(newY) << " os=" << p.otherStripe(newY) << "\n";
764 5176917 : if ((currentDir == FORWARD && relPos.x() >= lane->getLength()) || (currentDir == BACKWARD && relPos.x() < 0)) {
765 5175474 : addCloserObstacle(obs, relPos.x(), p.stripe(newY), stripes, p.getPerson()->getID(), p.getPerson()->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
766 5175474 : addCloserObstacle(obs, relPos.x(), p.otherStripe(newY), stripes, p.getPerson()->getID(), p.getPerson()->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
767 : }
768 : }
769 : } else {
770 : // simple transformation into the coordinate system of the current lane
771 : // (only need to worry about currentDir and nextDir)
772 : // XXX consider waitingToEnter on nextLane
773 1141183 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(nextDir));
774 35652142 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
775 34510959 : const PState& p = *static_cast<PState*>(pedestrians[ii]);
776 34510959 : if (p.isWaitingToEnter() || p.isJammed()) {
777 22968988 : continue;
778 : }
779 : double newY = p.getPosLat();
780 11541971 : Obstacle pObs(p);
781 11541971 : if (nextDir != currentDir) {
782 290461 : newY = (nextStripes - 1) * stripeWidth - newY;
783 290461 : pObs.speed *= -1;
784 : }
785 11541971 : newY += offset * stripeWidth;
786 11541971 : const int stripe = p.stripe(newY);
787 11541971 : if (stripe >= 0 && stripe < stripes) {
788 11541968 : obs[stripe] = pObs;
789 : }
790 11541971 : const int otherStripe = p.otherStripe(newY);
791 11541971 : if (otherStripe >= 0 && otherStripe < stripes) {
792 11541968 : obs[otherStripe] = pObs;
793 : }
794 : }
795 1141183 : if (nextLane->isCrossing()) {
796 : // add vehicle obstacles
797 329916 : const MSLink* crossingEntryLink = nextLane->getIncomingLanes().front().viaLink;
798 329916 : const bool prio = crossingEntryLink->havePriority() || crossingEntryLink->getTLLogic() != nullptr;
799 329916 : addCrossingVehs(nextLane, stripes, offset, nextDir, obs, prio, currentDir != nextDir);
800 : }
801 1141183 : if (nextLane->getVehicleNumberWithPartials() > 0) {
802 18641 : Obstacles vehObs = getVehicleObstacles(nextLane, nextDir);
803 18641 : PState::mergeObstacles(obs, vehObs, nextDir, offset);
804 18641 : }
805 1141183 : transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
806 : }
807 2352263 : nextLanesObs[nextLane] = obs;
808 2352263 : }
809 18404794 : return nextLanesObs[nextLane];
810 : }
811 :
812 : void
813 2352263 : MSPModel_Striping::transformToCurrentLanePositions(Obstacles& obs, int currentDir, int nextDir, double currentLength, double nextLength) {
814 13323054 : for (Obstacle& o : obs) {
815 10970791 : if (currentDir == FORWARD) {
816 7279730 : if (nextDir == FORWARD) {
817 6932733 : o.xFwd += currentLength;
818 6932733 : o.xBack += currentLength;
819 : } else {
820 346997 : const double tmp = o.xFwd;
821 346997 : o.xFwd = currentLength + nextLength - o.xBack;
822 346997 : o.xBack = currentLength + nextLength - tmp;
823 : }
824 : } else {
825 3691061 : if (nextDir == FORWARD) {
826 851818 : const double tmp = o.xFwd;
827 851818 : o.xFwd = -o.xBack;
828 851818 : o.xBack = -tmp;
829 : } else {
830 2839243 : o.xFwd -= nextLength;
831 2839243 : o.xBack -= nextLength;
832 : }
833 : }
834 : }
835 2352263 : }
836 :
837 :
838 : void
839 10350948 : MSPModel_Striping::addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type) {
840 10350948 : if (stripe >= 0 && stripe < numStripes) {
841 2401026 : if ((dir == FORWARD && x - width / 2. < obs[stripe].xBack) || (dir == BACKWARD && x + width / 2. > obs[stripe].xFwd)) {
842 2099796 : obs[stripe] = Obstacle(x, 0, type, id, width);
843 : }
844 : }
845 10350948 : }
846 :
847 : void
848 6258488 : MSPModel_Striping::moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
849 48451143 : for (ActiveLanes::iterator it_lane = myActiveLanes.begin(); it_lane != myActiveLanes.end(); ++it_lane) {
850 42192659 : const MSLane* lane = it_lane->first;
851 42192659 : Pedestrians& pedestrians = it_lane->second;
852 42192659 : if (pedestrians.size() == 0) {
853 32907056 : continue;
854 : }
855 : //std::cout << SIMTIME << ">>> lane=" << lane->getID() << " numPeds=" << pedestrians.size() << "\n";
856 9285603 : if (lane->isWalkingArea()) {
857 2095187 : const double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
858 2095187 : const double minY = stripeWidth * - 0.5 + NUMERICAL_EPS;
859 2095187 : const double maxY = stripeWidth * (numStripes(lane) - 0.5) - NUMERICAL_EPS;
860 : const WalkingAreaPath* debugPath = nullptr;
861 : // need to handle each walkingAreaPath separately and transform
862 : // coordinates beforehand
863 : std::set<const WalkingAreaPath*, walkingarea_path_sorter> paths;
864 19143411 : for (Pedestrians::iterator it = pedestrians.begin(); it != pedestrians.end(); ++it) {
865 17048224 : const PState* p = static_cast<PState*>(*it);
866 : assert(p->myWalkingAreaPath != 0);
867 17048224 : if (p->getDirection() == dir) {
868 8539649 : paths.insert(p->myWalkingAreaPath);
869 8539649 : if DEBUGCOND(*p) {
870 0 : debugPath = p->myWalkingAreaPath;
871 0 : std::cout << SIMTIME << " debugging WalkingAreaPath from=" << debugPath->from->getID() << " to=" << debugPath->to->getID() << " minY=" << minY << " maxY=" << maxY << " latOffset=" << lateral_offset << "\n";
872 : }
873 : }
874 : }
875 2095187 : const double usableWidth = (numStripes(lane) - 1) * stripeWidth;
876 3223330 : for (std::set<const WalkingAreaPath*, walkingarea_path_sorter>::iterator it = paths.begin(); it != paths.end(); ++it) {
877 1128143 : const WalkingAreaPath* path = *it;
878 : Pedestrians toDelete;
879 : Pedestrians transformedPeds;
880 1128143 : transformedPeds.reserve(pedestrians.size());
881 10629241 : for (Pedestrians::iterator it_p = pedestrians.begin(); it_p != pedestrians.end(); ++it_p) {
882 9501098 : PState* p = static_cast<PState*>(*it_p);
883 9501098 : if (p->myWalkingAreaPath == path) {
884 8539649 : transformedPeds.push_back(p);
885 8539649 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (untransformed), vecCoord="
886 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
887 961449 : } else if (p->myWalkingAreaPath->from == path->to && p->myWalkingAreaPath->to == path->from) {
888 43290 : if (p->myWalkingAreaPath->dir != path->dir) {
889 : // opposite direction is already in the correct coordinate system
890 39843 : transformedPeds.push_back(p);
891 39843 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (untransformed), vecCoord="
892 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
893 : } else {
894 : // x position must be reversed
895 3447 : PState* tp = new PState(*p);
896 3447 : tp->reverse(path->length, usableWidth);
897 3447 : toDelete.push_back(tp);
898 3447 : transformedPeds.push_back(tp);
899 3447 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (semi-transformed), vecCoord="
900 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
901 : }
902 : } else {
903 918159 : const Position relPos = path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1));
904 918159 : const double newY = relPos.y() + lateral_offset;
905 917055 : if (relPos != Position::INVALID && newY >= minY && newY <= maxY) {
906 256806 : PState* tp = new PState(*p);
907 256806 : tp->reset(relPos.x(), newY);
908 256806 : toDelete.push_back(tp);
909 256806 : transformedPeds.push_back(tp);
910 256806 : if (path == debugPath) {
911 0 : std::cout << " ped=" << p->getPerson()->getID() << " relX=" << relPos.x() << " relY=" << newY << " (transformed), vecCoord=" << relPos << "\n";
912 : }
913 : } else {
914 661353 : if (path == debugPath) {
915 0 : std::cout << " ped=" << p->getPerson()->getID() << " relX=" << relPos.x() << " relY=" << newY << " (invalid), vecCoord=" << relPos << "\n";
916 : }
917 : }
918 : }
919 : }
920 : auto itFoe = myWalkingAreaFoes.find(&lane->getEdge());
921 1128143 : if (itFoe != myWalkingAreaFoes.end()) {
922 : // add vehicle foes on paths which cross this walkingarea
923 : // translate the vehicle into a number of dummy-pedestrians
924 : // that occupy the same space
925 2265707 : for (const MSLane* foeLane : itFoe->second) {
926 184869 : for (auto itVeh = foeLane->anyVehiclesBegin(); itVeh != foeLane->anyVehiclesEnd(); ++itVeh) {
927 184869 : const MSVehicle* veh = *itVeh;
928 184869 : const double vehWidth = veh->getVehicleType().getWidth();
929 184869 : Boundary relCorners;
930 184869 : Position relFront = path->shape.transformToVectorCoordinates(veh->getPosition(), true);
931 184869 : Position relBack = path->shape.transformToVectorCoordinates(veh->getBackPosition(), true);
932 : if (relFront == Position::INVALID) {
933 0 : WRITE_WARNINGF("Could not vehicle '%' front position % onto walkingarea '%' path=%, time=%.",
934 : veh->getID(), veh->getPosition(), lane->getID(), path->shape, time2string(SIMSTEP));
935 : }
936 : if (relBack == Position::INVALID) {
937 0 : WRITE_WARNINGF("Could not vehicle '%' back position % onto walkingarea '%' path=%, time=%.",
938 : veh->getID(), veh->getBackPosition(), lane->getID(), path->shape, time2string(SIMSTEP));
939 : }
940 184869 : PositionVector relCenter;
941 184869 : relCenter.push_back(relFront);
942 184869 : relCenter.push_back(relBack);
943 184869 : relCenter.move2side(vehWidth / 2);
944 184869 : relCorners.add(relCenter[0]);
945 184869 : relCorners.add(relCenter[1]);
946 184869 : relCenter.move2side(-vehWidth);
947 184869 : relCorners.add(relCenter[0]);
948 184869 : relCorners.add(relCenter[1]);
949 : // persons should require less gap than the vehicles to prevent getting stuck
950 : // when a vehicles moves towards them
951 184869 : relCorners.growWidth(SAFETY_GAP / 2);
952 184869 : const double xWidth = relCorners.getWidth();
953 184869 : const double vehYmin = MAX2(minY - lateral_offset, relCorners.ymin());
954 184869 : const double vehYmax = MIN2(maxY - lateral_offset, relCorners.ymax());
955 184869 : const double xCenter = relCorners.getCenter().x();
956 : Position yMinPos(xCenter, vehYmin);
957 : Position yMaxPos(xCenter, vehYmax);
958 184869 : const bool addFront = addVehicleFoe(veh, lane, yMinPos, dir * xWidth, 0, lateral_offset, minY, maxY, toDelete, transformedPeds);
959 184869 : const bool addBack = addVehicleFoe(veh, lane, yMaxPos, dir * xWidth, 0, lateral_offset, minY, maxY, toDelete, transformedPeds);
960 184869 : if (path == debugPath) {
961 : std::cout << " veh=" << veh->getID()
962 0 : << " corners=" << relCorners
963 : << " xWidth=" << xWidth
964 0 : << " ymin=" << relCorners.ymin()
965 0 : << " ymax=" << relCorners.ymax()
966 : << " vehYmin=" << vehYmin
967 : << " vehYmax=" << vehYmax
968 0 : << "\n";
969 : }
970 184869 : if (addFront && addBack) {
971 : // add in-between positions
972 184869 : const double yDist = vehYmax - vehYmin;
973 421737 : for (double dist = stripeWidth; dist < yDist; dist += stripeWidth) {
974 236868 : const double relDist = dist / yDist;
975 236868 : Position between = (yMinPos * relDist) + (yMaxPos * (1 - relDist));
976 236868 : if (path == debugPath) {
977 0 : std::cout << " vehBetween=" << veh->getID() << " pos=" << between << "\n";
978 : }
979 236868 : addVehicleFoe(veh, lane, between, dir * xWidth, stripeWidth, lateral_offset, minY, maxY, toDelete, transformedPeds);
980 : }
981 : }
982 184869 : }
983 : }
984 : }
985 1128143 : moveInDirectionOnLane(transformedPeds, lane, currentTime, changedLane, dir, path == debugPath);
986 1128143 : arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
987 : // clean up
988 1893218 : for (Pedestrians::iterator it_p = toDelete.begin(); it_p != toDelete.end(); ++it_p) {
989 765075 : delete *it_p;
990 : }
991 1128143 : }
992 : } else {
993 7190416 : moveInDirectionOnLane(pedestrians, lane, currentTime, changedLane, dir, false);
994 7190416 : arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
995 : }
996 : }
997 6258484 : }
998 :
999 :
1000 : bool
1001 606606 : MSPModel_Striping::addVehicleFoe(const MSVehicle* veh, const MSLane* walkingarea, const Position& relPos, double xWidth, double yWidth, double lateral_offset,
1002 : double minY, double maxY, Pedestrians& toDelete, Pedestrians& transformedPeds) {
1003 : if (relPos != Position::INVALID) {
1004 606606 : const double newY = relPos.y() + lateral_offset;
1005 606606 : if (newY >= minY && newY <= maxY) {
1006 504822 : PState* tp = new PStateVehicle(veh, walkingarea, relPos.x(), newY, xWidth, yWidth);
1007 : //std::cout << SIMTIME << " addVehicleFoe=" << veh->getID() << " rx=" << relPos.x() << " ry=" << newY << " s=" << tp->stripe() << " o=" << tp->otherStripe() << "\n";
1008 504822 : toDelete.push_back(tp);
1009 504822 : transformedPeds.push_back(tp);
1010 : }
1011 606606 : return true;
1012 : } else {
1013 : return false;
1014 : }
1015 : }
1016 :
1017 : void
1018 8318559 : MSPModel_Striping::arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
1019 : // advance to the next lane / arrive at destination
1020 8318559 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
1021 : // can't use iterators because we do concurrent modification
1022 143177079 : for (int i = 0; i < (int)pedestrians.size(); i++) {
1023 134858524 : PState* const p = static_cast<PState*>(pedestrians[i]);
1024 134858524 : if (p->isRemoteControlled()) {
1025 27778 : continue;
1026 : }
1027 134830746 : if (p->getDirection() == dir && p->distToLaneEnd() < 0) {
1028 : // moveToNextLane may trigger re-insertion (for consecutive
1029 : // walks) so erase must be called first
1030 : pedestrians.erase(pedestrians.begin() + i);
1031 987732 : i--;
1032 987732 : p->moveToNextLane(currentTime);
1033 987728 : if (p->getLane() != nullptr) {
1034 756917 : changedLane.insert(p->getPerson());
1035 756917 : myActiveLanes[p->getLane()].push_back(p);
1036 : } else {
1037 : // end walking stage and destroy PState
1038 230811 : p->getStage()->moveToNextEdge(p->getPerson(), currentTime, dir);
1039 230811 : myNumActivePedestrians--;
1040 : }
1041 : }
1042 : }
1043 8318555 : }
1044 :
1045 :
1046 : void
1047 8318559 : MSPModel_Striping::moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir, bool debug) {
1048 8318559 : const int stripes = numStripes(lane);
1049 : //std::cout << " laneWidth=" << lane->getWidth() << " stripeWidth=" << stripeWidth << " stripes=" << stripes << "\n";
1050 16637118 : Obstacles obs(stripes, Obstacle(dir)); // continuously updated
1051 : NextLanesObstacles nextLanesObs; // continuously updated
1052 8318559 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
1053 :
1054 8318559 : Obstacles crossingVehs(stripes, Obstacle(dir));
1055 : bool hasCrossingVehObs = false;
1056 8318559 : if (lane->isCrossing()) {
1057 : // assume that vehicles will brake when already on the crossing
1058 611820 : hasCrossingVehObs = addCrossingVehs(lane, stripes, 0, dir, crossingVehs, true, false);
1059 : }
1060 :
1061 143019257 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
1062 134700698 : PState& p = *static_cast<PState*>(pedestrians[ii]);
1063 : UNUSED_PARAMETER(debug);
1064 : //if (debug) {
1065 : // std::cout << SIMTIME << " CHECKING d=" << dir << " p=" << p.getID() << " relX=" << p.myRelX << " xmin=" << p.getMinX() << " xmax=" << p.getMaxX() << " pdir=" << p.getDirection() << "\n";
1066 : //}
1067 134700698 : Obstacles currentObs = obs;
1068 134700698 : if (p.getDirection() != dir || changedLane.count(p.getPerson()) != 0 || p.getRemotePosition() != Position::INVALID) {
1069 63594252 : if (!p.isWaitingToEnter() && !p.isJammed()) {
1070 : //if DEBUGCOND(p) {
1071 : // std::cout << " obs=" << p.getPerson()->getID() << " y=" << p.getPosLat() << " stripe=" << p.stripe() << " oStripe=" << p.otherStripe() << "\n";
1072 : //}
1073 31153757 : Obstacle o(p);
1074 31153757 : if (p.getDirection() != dir && p.getSpeed(*p.getStage()) == 0.) {
1075 : // ensure recognition of oncoming
1076 8528189 : o.speed = (p.getDirection() == FORWARD ? 0.1 : -0.1);
1077 : }
1078 31153757 : if (o.closer(obs[p.stripe()], dir)) {
1079 31149452 : obs[p.stripe()] = o;
1080 : }
1081 31153757 : if (o.closer(obs[p.otherStripe()], dir)) {
1082 31149330 : obs[p.otherStripe()] = o;
1083 : }
1084 : }
1085 : continue;
1086 63594252 : }
1087 71106446 : if DEBUGCOND(p) {
1088 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " currentObs=";
1089 0 : gDebugFlag1 = true;
1090 0 : DEBUG_PRINT(currentObs);
1091 : }
1092 71106446 : const MSLane* nextLane = p.myNLI.lane;
1093 71106446 : const MSLink* link = p.myNLI.link;
1094 71106446 : const double dist = p.distToLaneEnd();
1095 : const double speed(p.getStage()->getConfiguredSpeed() >= 0
1096 71106446 : ? p.getStage()->getConfiguredSpeed()
1097 58915147 : : ((nextLane != nullptr && (USE_NET_SPEEDS || nextLane->isNormal() || nextLane->isInternal()))
1098 128611852 : ? nextLane->getVehicleMaxSpeed(p.getPerson())
1099 13490950 : : p.getStage()->getMaxSpeed(p.getPerson())));
1100 :
1101 :
1102 71106446 : if (nextLane != nullptr && dist <= LOOKAHEAD_ONCOMING_DIST) {
1103 18404794 : const double currentLength = (p.myWalkingAreaPath == nullptr ? lane->getLength() : p.myWalkingAreaPath->length);
1104 18404794 : const Obstacles& nextObs = getNextLaneObstacles(
1105 : nextLanesObs, lane, nextLane, stripes,
1106 : p.myNLI.dir, currentLength, dir);
1107 :
1108 18404794 : if DEBUGCOND(p) {
1109 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " nextObs=";
1110 0 : DEBUG_PRINT(nextObs);
1111 : }
1112 18404794 : p.mergeObstacles(currentObs, nextObs);
1113 : }
1114 71106446 : if DEBUGCOND(p) {
1115 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithNext=";
1116 0 : DEBUG_PRINT(currentObs);
1117 : }
1118 71106446 : p.mergeObstacles(currentObs, getNeighboringObstacles(pedestrians, ii, stripes));
1119 71106446 : if DEBUGCOND(p) {
1120 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithNeigh=";
1121 0 : DEBUG_PRINT(currentObs);
1122 : }
1123 : // time gap to pass the intersection ahead of a vehicle.
1124 71106446 : const double passingLength = p.getLength() + p.getPerson()->getTimegapCrossing() * speed;
1125 : // check link state
1126 71106446 : if DEBUGCOND(p) {
1127 0 : gDebugFlag1 = true; // get debug output from MSLink
1128 0 : std::cout << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
1129 0 : << " dist=" << dist << " d2=" << dist - p.getMinGap() << " la=" << LOOKAHEAD_SAMEDIR* speed << "\n";
1130 : }
1131 : if (link != nullptr
1132 : // only check close before junction, @todo we should take deceleration into account here
1133 57998888 : && dist - p.getMinGap() < LOOKAHEAD_SAMEDIR * speed
1134 : // persons move before vehicles so we subtract DELTA_TO because they cannot rely on vehicles having passed the intersection in the current time step
1135 83454927 : && (!link->opened(currentTime - DELTA_T, speed, speed, passingLength, p.getImpatience(), speed, 0, 0, nullptr, p.ignoreRed(link), p.getPerson())
1136 11688910 : || p.stopForYellow(link))) {
1137 : // prevent movement passed a closed link
1138 660489 : Obstacles closedLink(stripes, Obstacle(p.getEdgePos(0) + dir * (dist - NUMERICAL_EPS), 0, OBSTACLE_LINKCLOSED, "closedLink_" + link->getViaLaneOrLane()->getID(), 0));
1139 660489 : p.mergeObstacles(currentObs, closedLink);
1140 660489 : if DEBUGCOND(p) {
1141 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithTLS=";
1142 0 : DEBUG_PRINT(currentObs);
1143 : }
1144 : // consider rerouting over another crossing
1145 660489 : if (p.myWalkingAreaPath != nullptr) {
1146 : // @todo actually another path would be needed starting at the current position
1147 502727 : const MSLane* oldNext = p.myNLI.lane;
1148 502727 : p.myNLI = getNextLane(p, p.getLane(), p.myWalkingAreaPath->from);
1149 502727 : if (p.myNLI.lane != oldNext && oldNext->isPriorityCrossing()) {
1150 152 : unregisterCrossingApproach(p, oldNext);
1151 : }
1152 : }
1153 660489 : }
1154 71106446 : if DEBUGCOND(p) {
1155 0 : gDebugFlag1 = false;
1156 : }
1157 71106446 : if (&lane->getEdge() == p.getStage()->getDestination() && p.getStage()->getDestinationStop() != nullptr) {
1158 : Obstacles arrival;
1159 1386168 : if (p.getStage()->getDestinationStop()->getWaitingCapacity() > p.getStage()->getDestinationStop()->getNumWaitingPersons() ||
1160 : (!p.getStage()->getDestinationStop()->checkPersonCapacity())) {
1161 2568458 : arrival = Obstacles(stripes, Obstacle(p.getStage()->getArrivalPos() + dir * p.getMinGap(), 0, OBSTACLE_ARRIVALPOS, "arrival", 0));
1162 : } else {
1163 203878 : arrival = Obstacles(stripes, Obstacle(p.getStage()->getArrivalPos() - dir * p.getMinGap(), 0, OBSTACLE_ARRIVALPOS, "arrival_blocked", 0));
1164 : }
1165 1386168 : p.mergeObstacles(currentObs, arrival);
1166 1386168 : }
1167 :
1168 71106446 : if (lane->getVehicleNumberWithPartials() > 0) {
1169 : // react to vehicles on the same lane
1170 : // @todo: improve efficiency by using the same iterator for all pedestrians on this lane
1171 275864 : Obstacles vehObs = getVehicleObstacles(lane, dir, &p);
1172 275864 : p.mergeObstacles(currentObs, vehObs);
1173 275864 : if DEBUGCOND(p) {
1174 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithVehs=";
1175 0 : DEBUG_PRINT(currentObs);
1176 : }
1177 275864 : }
1178 71106446 : if (hasCrossingVehObs) {
1179 24832 : p.mergeObstacles(currentObs, crossingVehs);
1180 24832 : if DEBUGCOND(p) {
1181 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithVehs2=";
1182 0 : DEBUG_PRINT(currentObs);
1183 : }
1184 : }
1185 :
1186 : // walk, taking into account all obstacles
1187 71106446 : p.walk(currentObs);
1188 71106446 : gDebugFlag1 = false;
1189 71106446 : if (!p.isWaitingToEnter() && !p.isJammed()) {
1190 36029064 : Obstacle o(p);
1191 36029064 : if (o.closer(obs[p.stripe()], dir)) {
1192 36027509 : obs[p.stripe()] = o;
1193 : }
1194 36029064 : if (o.closer(obs[p.otherStripe()], dir)) {
1195 36027504 : obs[p.otherStripe()] = o;
1196 : }
1197 36029064 : if (MSGlobals::gCheck4Accidents && p.myWalkingAreaPath == nullptr && !p.isJammed()) {
1198 2936513965 : for (int coll = 0; coll < ii; ++coll) {
1199 2906309958 : PState& c = *static_cast<PState*>(pedestrians[coll]);
1200 2906309958 : if (!c.isWaitingToEnter() && c.myWalkingAreaPath == nullptr && !c.isJammed()) {
1201 1294872892 : if (c.stripe() == p.stripe() || p.stripe() == c.otherStripe() || p.otherStripe() == c.stripe() || p.otherStripe() == c.otherStripe()) {
1202 490601977 : Obstacle cObs(c);
1203 : // we check only for real collisions, no min gap violations
1204 490601977 : if (p.distanceTo(cObs, false) == DIST_OVERLAP) {
1205 1165868 : WRITE_WARNING("Collision of person '" + p.getPerson()->getID() + "' and person '" + c.getPerson()->getID()
1206 : + "', lane='" + lane->getID() + "', time=" + time2string(currentTime) + ".");
1207 : }
1208 : }
1209 : }
1210 : }
1211 : }
1212 : }
1213 : //std::cout << SIMTIME << p.getPerson()->getID() << " lane=" << lane->getID() << " x=" << p.myRelX << "\n";
1214 134700698 : }
1215 16637118 : }
1216 :
1217 :
1218 : void
1219 488017 : MSPModel_Striping::registerCrossingApproach(const PState& ped, const MSLane* crossing, const MSLane* beforeWA) {
1220 : // person has entered the walkingarea
1221 488017 : SUMOTime arrivalTime = SIMSTEP;
1222 : assert(ped.getLane()->isWalkingArea());
1223 488017 : const WalkingAreaPath* wa = getWalkingAreaPath(&ped.getLane()->getEdge(), beforeWA, crossing);
1224 488017 : const double speed = ped.getStage()->getMaxSpeed(ped.getPerson()) * (1 - dawdling / 2);
1225 488017 : arrivalTime += TIME2STEPS(wa->length / speed);
1226 488017 : SUMOTime leavingTime = arrivalTime + TIME2STEPS(crossing->getLength() / speed);
1227 488017 : crossing->getIncomingLanes()[0].viaLink->setApproachingPerson(ped.getPerson(), arrivalTime, leavingTime);
1228 488017 : if DEBUGCOND(ped) {
1229 0 : std::cout << SIMTIME << " register " << ped.getPerson()->getID() << " at crossing " << crossing->getID() << "\n";
1230 : }
1231 488017 : }
1232 :
1233 :
1234 : bool
1235 941736 : MSPModel_Striping::addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& obs, bool prio, bool flipY) {
1236 : bool hasCrossingVehObs = false;
1237 941736 : const MSLink* crossingExitLink = crossing->getLinkCont().front();
1238 941736 : gDebugFlag1 = DEBUGCOND2(crossing);
1239 941736 : const MSLink::LinkLeaders linkLeaders = crossingExitLink->getLeaderInfo(nullptr, crossing->getLength());
1240 941736 : gDebugFlag1 = false;
1241 941736 : if (linkLeaders.size() > 0) {
1242 215348 : for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
1243 : // the vehicle to enter the junction first has priority
1244 109771 : const MSVehicle* veh = (*it).vehAndGap.first;
1245 109771 : if (veh != nullptr) {
1246 109771 : Obstacle vo((*it).distToCrossing, 0, OBSTACLE_VEHICLE, veh->getID(), veh->getVehicleType().getWidth() + 2 * minGapToVehicle, veh);
1247 : // block entry to the crossing in walking direction but allow leaving it
1248 109771 : Obstacle voBlock = vo;
1249 109771 : if (dir == FORWARD) {
1250 61608 : voBlock.xBack = NUMERICAL_EPS;
1251 : } else {
1252 48163 : voBlock.xFwd = crossing->getLength() - NUMERICAL_EPS;
1253 : }
1254 : // when approaching a priority crossings, vehicles must be able
1255 : // to brake, otherwise the person must be able to cross in time
1256 109771 : const double distToCrossBeforeVeh = (dir == FORWARD ? vo.xFwd : crossing->getLength() - vo.xBack);
1257 : const double bGap = (prio
1258 111411 : ? veh->getCarFollowModel().brakeGap(veh->getSpeed(), veh->getCarFollowModel().getMaxDecel(), 0)
1259 1640 : : veh->getSpeed() * distToCrossBeforeVeh); // walking 1m/s
1260 : double vehYmin;
1261 : double vehYmax;
1262 : // relY increases from left to right (the other way around from vehicles)
1263 109771 : if ((*it).fromLeft()) {
1264 71329 : vehYmin = -(*it).vehAndGap.second + lateral_offset; // vehicle back
1265 71329 : vehYmax = vehYmin + veh->getVehicleType().getLength() + bGap + minGapToVehicle;
1266 71329 : vehYmin -= minGapToVehicle;
1267 : } else {
1268 38442 : vehYmax = crossing->getWidth() + (*it).vehAndGap.second - lateral_offset; // vehicle back
1269 38442 : vehYmin = vehYmax - veh->getVehicleType().getLength() - bGap - minGapToVehicle;
1270 38442 : vehYmax += minGapToVehicle;
1271 :
1272 : }
1273 439379 : for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax), stripes); ++s) {
1274 185966 : if ((dir == FORWARD && obs[s].xBack > vo.xBack)
1275 329945 : || (dir == BACKWARD && obs[s].xFwd < vo.xFwd)) {
1276 328176 : if (!prio && veh->getSpeed() > SUMO_const_haltingSpeed) {
1277 : // do not enter the crossing
1278 9257 : obs[s] = voBlock;
1279 : } else {
1280 318919 : obs[s] = vo;
1281 : }
1282 : hasCrossingVehObs = true;
1283 : }
1284 : }
1285 109771 : if (flipY) {
1286 24259 : Obstacles tmp = obs;
1287 174275 : for (int i = 0; i < (int)obs.size(); i++) {
1288 150016 : obs[i] = tmp[obs.size() - 1 - i];
1289 : }
1290 24259 : }
1291 109771 : if (DEBUGCOND2(crossing)) {
1292 0 : std::cout << SIMTIME
1293 : << " crossingVeh=" << veh->getID()
1294 : << " lane=" << crossing->getID()
1295 : << " prio=" << prio
1296 : << " latOffset=" << lateral_offset
1297 : << " dir=" << dir
1298 0 : << " flipY=" << flipY
1299 : << " stripes=" << stripes
1300 0 : << " dist=" << (*it).distToCrossing
1301 0 : << " gap=" << (*it).vehAndGap.second
1302 : << " brakeGap=" << bGap
1303 : << " fromLeft=" << (*it).fromLeft()
1304 : << " distToCrossBefore=" << distToCrossBeforeVeh
1305 : << " ymin=" << vehYmin
1306 : << " ymax=" << vehYmax
1307 : << " smin=" << PState::stripe(vehYmin)
1308 0 : << " smax=" << PState::stripe(vehYmax)
1309 0 : << "\n";
1310 0 : DEBUG_PRINT(obs);
1311 : }
1312 : }
1313 : }
1314 105577 : if (hasCrossingVehObs) {
1315 : // check whether the crossing is fully blocked
1316 71035 : const int reserved = getReserved((int)obs.size(), RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS);
1317 : bool allBlocked = true;
1318 :
1319 392074 : for (int i = 0; i < (int)obs.size(); i++) {
1320 348166 : const Obstacle& o = obs[i];
1321 348166 : if (o.type != OBSTACLE_VEHICLE && (
1322 54715 : (dir == FORWARD && i >= reserved) ||
1323 39198 : (dir == BACKWARD && i < (int)obs.size() - reserved))) {
1324 : allBlocked = false;
1325 : break;
1326 : }
1327 : }
1328 71035 : if (allBlocked) {
1329 43908 : if (DEBUGCOND2(crossing)) {
1330 0 : std::cout << SIMTIME << " crossing=" << crossing->getID() << " allBlocked\n";
1331 : }
1332 312069 : for (Obstacle& o : obs) {
1333 268161 : if (dir == FORWARD) {
1334 149329 : o.xBack = NUMERICAL_EPS;
1335 : } else {
1336 118832 : o.xFwd = crossing->getLength() - NUMERICAL_EPS;
1337 : }
1338 : }
1339 : }
1340 : }
1341 : }
1342 941736 : return hasCrossingVehObs;
1343 941736 : }
1344 :
1345 :
1346 : MSPModel_Striping::Obstacles
1347 294505 : MSPModel_Striping::getVehicleObstacles(const MSLane* lane, int dir, PState* ped) {
1348 294505 : const int stripes = numStripes(lane);
1349 589010 : Obstacles vehObs(stripes, Obstacle(dir));
1350 : int current = -1;
1351 : double minX = 0.;
1352 : double maxX = 0.;
1353 : double pRelY = -1.;
1354 : double pWidth = 0.;
1355 : std::string pID;
1356 294505 : bool debug = DEBUGCOND2(lane);
1357 294505 : if (ped != nullptr) {
1358 275864 : current = ped->stripe();
1359 275864 : minX = ped->getMinX();
1360 275864 : maxX = ped->getMaxX();
1361 : pRelY = ped->getPosLat();
1362 275864 : pWidth = ped->getPerson()->getVehicleType().getWidth();
1363 : pID = ped->getPerson()->getID();
1364 275864 : debug = DEBUGCOND(*ped);
1365 18641 : } else if (dir == BACKWARD) {
1366 : // checking vehicles on the next lane. Use entry point as reference
1367 : minX = lane->getLength();
1368 : maxX = lane->getLength();
1369 : }
1370 294505 : MSLane::AnyVehicleIterator begin = (dir == FORWARD ? lane->anyVehiclesUpstreamBegin() : lane->anyVehiclesBegin());
1371 : MSLane::AnyVehicleIterator end = (dir == FORWARD ? lane->anyVehiclesUpstreamEnd() : lane->anyVehiclesEnd());
1372 781919 : for (MSLane::AnyVehicleIterator it = begin; it != end; ++it) {
1373 487414 : const MSVehicle* veh = *it;
1374 487414 : const bool bidi = veh->getLane() == lane->getBidiLane();
1375 487414 : const double vehBack = veh->getBackPositionOnLane(lane);
1376 487414 : double vehFront = vehBack + veh->getVehicleType().getLength();
1377 : // ensure that vehicles are not blocked
1378 487414 : const double vehNextSpeed = veh->getWaitingTime() > DELTA_T ? 0 : MAX2(veh->getSpeed(), 1.0);
1379 487414 : const double clearance = SAFETY_GAP + vehNextSpeed * LOOKAHEAD_SAMEDIR;
1380 : // boundaries for range checking
1381 : double vehXMax;
1382 : double vehXMin;
1383 : double vehXMaxCheck;
1384 : double vehXMinCheck;
1385 487414 : if (bidi) {
1386 1617 : vehFront = vehBack - veh->getVehicleType().getLength();
1387 1617 : vehXMax = vehBack + SAFETY_GAP;
1388 1617 : vehXMin = vehFront - clearance;
1389 1617 : if (dir == FORWARD) {
1390 1617 : vehXMaxCheck = vehBack + NUMERICAL_EPS;
1391 1617 : vehXMinCheck = vehFront - LOOKAROUND_VEHICLES;
1392 : } else {
1393 0 : vehXMaxCheck = vehBack + LOOKAHEAD_SAMEDIR;
1394 : vehXMinCheck = vehFront - clearance;
1395 : }
1396 : } else {
1397 485797 : vehXMax = vehFront + clearance;
1398 485797 : vehXMin = vehBack - SAFETY_GAP;
1399 485797 : if (dir == FORWARD) {
1400 : vehXMaxCheck = vehFront + clearance;
1401 363616 : vehXMinCheck = vehBack - LOOKAHEAD_SAMEDIR;
1402 : } else {
1403 122181 : vehXMaxCheck = vehFront + LOOKAROUND_VEHICLES;
1404 122181 : vehXMinCheck = vehBack - NUMERICAL_EPS;
1405 : }
1406 : }
1407 487414 : if (debug) {
1408 0 : std::cout << SIMTIME << " ped=" << pID << " veh=" << veh->getID() << " check obstacle on lane=" << lane->getID()
1409 : << "\n"
1410 : << " vehXMin=" << vehXMin
1411 : << " vehXMax=" << vehXMax
1412 : << " vehXMinC=" << vehXMinCheck
1413 : << " vehXMaxC=" << vehXMaxCheck
1414 : << " minX=" << minX
1415 : << " maxX=" << maxX
1416 : << " bidi=" << bidi
1417 : << " vFront=" << vehFront
1418 : << " vBack=" << vehBack
1419 0 : << "\n";
1420 : }
1421 487414 : if (vehXMaxCheck > minX && vehXMinCheck && vehXMinCheck <= maxX) {
1422 370128 : Obstacle vo(vehBack, veh->getSpeed() * (bidi ? -1 : 1), OBSTACLE_VEHICLE, veh->getID(), 0, veh);
1423 : // moving vehicles block space along their path
1424 185418 : vo.xFwd = vehXMax;
1425 185418 : vo.xBack = vehXMin;
1426 : // relY increases from left to right (the other way around from vehicles)
1427 : // XXX lateral offset for partial vehicles
1428 185418 : const double posLat = veh->getLateralPositionOnLane() * (bidi ? -1 : 1);
1429 185418 : const double vehYmax = 0.5 * (lane->getWidth() + veh->getVehicleType().getWidth() - stripeWidth) - posLat;
1430 185418 : const double vehYmin = vehYmax - veh->getVehicleType().getWidth();
1431 804232 : for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax) + 1, stripes); ++s) {
1432 618814 : Obstacle prior = vehObs[s];
1433 : vehObs[s] = vo;
1434 618814 : if (s == current && vehFront + SAFETY_GAP < minX) {
1435 : // ignore if already overlapping while vehicle is still behind
1436 16132 : if (pRelY - pWidth < vehYmax &&
1437 15831 : pRelY + pWidth > vehYmin && dir == FORWARD) {
1438 9966 : if (debug) {
1439 0 : std::cout << " ignoring vehicle '" << veh->getID() << " on stripe " << s << " vehFrontSG=" << vehFront + SAFETY_GAP << " minX=" << minX << "\n";
1440 : }
1441 : if (dir == FORWARD) {
1442 : vehObs[s] = prior;
1443 : } else {
1444 : vehObs[s].xFwd = MIN2(vo.xFwd, vehFront + SAFETY_GAP);
1445 : }
1446 : }
1447 : }
1448 : }
1449 185418 : if (debug) {
1450 0 : std::cout << SIMTIME << " ped=" << pID << " veh=" << veh->getID() << " obstacle on lane=" << lane->getID()
1451 : << "\n"
1452 : << " ymin=" << vehYmin
1453 : << " ymax=" << vehYmax
1454 : << " smin=" << PState::stripe(vehYmin)
1455 0 : << " smax=" << PState::stripe(vehYmax)
1456 0 : << " relY=" << pRelY
1457 : << " current=" << current
1458 0 : << " vo.xFwd=" << vo.xFwd
1459 0 : << " vo.xBack=" << vo.xBack
1460 : << " vFront=" << vehFront
1461 : << " vBack=" << vehBack
1462 0 : << "\n";
1463 : }
1464 : }
1465 : }
1466 294505 : return vehObs;
1467 0 : }
1468 :
1469 :
1470 : // ===========================================================================
1471 : // MSPModel_Striping::Obstacle method definitions
1472 : // ===========================================================================
1473 88038069 : MSPModel_Striping::Obstacle::Obstacle(int dir, double dist) :
1474 88038069 : xFwd(dir * dist), // by default, far away when seen in dir
1475 88038069 : xBack(dir * dist), // by default, far away when seen in dir
1476 88038069 : speed(0),
1477 88038069 : type(OBSTACLE_NONE),
1478 88038069 : description("") {
1479 88038069 : }
1480 :
1481 :
1482 717007625 : MSPModel_Striping::Obstacle::Obstacle(const PState& ped) :
1483 717007625 : xFwd(ped.getMaxX()),
1484 717007625 : xBack(ped.getMinX()),
1485 717007625 : speed(ped.getDirection() * ped.getSpeed(*ped.getStage())),
1486 717007625 : type(ped.getOType()),
1487 717007625 : description(ped.getID()) {
1488 : assert(!ped.isWaitingToEnter());
1489 717007625 : if (type == OBSTACLE_VEHICLE) {
1490 539616 : vehicle = static_cast<const PStateVehicle&>(ped).getVehicle();
1491 : }
1492 717007625 : }
1493 :
1494 :
1495 : bool
1496 134365642 : MSPModel_Striping::Obstacle::closer(const Obstacle& o, int dir) {
1497 134365642 : if (dir == FORWARD) {
1498 72546076 : return xBack <= o.xBack;
1499 : } else {
1500 61819566 : return xFwd >= o.xFwd;
1501 : }
1502 : }
1503 :
1504 :
1505 : // ===========================================================================
1506 : // MSPModel_Striping::PState method definitions
1507 : // ===========================================================================
1508 243914 : MSPModel_Striping::PState::PState(MSPerson* person, MSStageMoving* stage, const MSLane* lane):
1509 : MSPModel_InteractingState(person, stage, lane),
1510 243914 : myWalkingAreaPath(nullptr) {
1511 : const MSEdge* currentEdge = &lane->getEdge();
1512 : const ConstMSEdgeVector& route = myStage->getRoute();
1513 : assert(!route.empty());
1514 243914 : myDir = FORWARD;
1515 243914 : if (route.size() == 1) {
1516 : // only a single edge, move towards end pos
1517 13472 : myDir = (myEdgePos <= myStage->getArrivalPos()) ? FORWARD : BACKWARD;
1518 230442 : } else if (route.front()->getFunction() != SumoXMLEdgeFunc::NORMAL) {
1519 : // start on an intersection
1520 6 : if (route.front()->isWalkingArea()) {
1521 6 : myWalkingAreaPath = getArbitraryPath(route.front());
1522 : }
1523 : } else {
1524 230436 : int passedFwd = 0;
1525 230436 : int passedBwd = 0;
1526 230436 : const bool mayStartForward = canTraverse(FORWARD, route, passedFwd) != UNDEFINED_DIRECTION;
1527 230436 : const bool mayStartBackward = canTraverse(BACKWARD, route, passedBwd) != UNDEFINED_DIRECTION;
1528 230436 : if DEBUGCOND(*this) {
1529 0 : std::cout << " initialize dir for " << myPerson->getID() << " forward=" << mayStartForward << " backward=" << mayStartBackward << "\n";
1530 : }
1531 230436 : if (mayStartForward && mayStartBackward) {
1532 : // figure out the best direction via routing
1533 : ConstMSEdgeVector crossingRoute;
1534 7437 : MSNet::getInstance()->getPedestrianRouter(0).compute(currentEdge, route.back(), myEdgePos, myStage->getArrivalPos(),
1535 2479 : myStage->getMaxSpeed(person), 0, nullptr, person->getVTypeParameter(), crossingRoute, true);
1536 2479 : if (crossingRoute.size() > 1) {
1537 : // route found
1538 2471 : const MSEdge* nextEdge = crossingRoute[1];
1539 2471 : if (nextEdge->getFromJunction() == currentEdge->getFromJunction() || nextEdge->getToJunction() == currentEdge->getFromJunction()) {
1540 1884 : myDir = BACKWARD;
1541 : }
1542 : }
1543 2479 : if DEBUGCOND(*this) {
1544 0 : std::cout << " crossingRoute=" << toString(crossingRoute) << "\n";
1545 : }
1546 230436 : } else if (!mayStartForward && !mayStartBackward) {
1547 156 : int lastDisconnect = passedFwd >= passedBwd ? passedFwd : passedBwd;
1548 : std::string dLoc;
1549 156 : if (route.size() > 2) {
1550 260 : dLoc = TLF(" between edge '%' and edge '%'", route[lastDisconnect - 1]->getID(), route[lastDisconnect]->getID());
1551 : }
1552 936 : WRITE_WARNINGF(TL("Person '%' walking from edge '%' to edge '%' has a disconnect%, time=%."),
1553 : myPerson->getID(), route.front()->getID(), route.back()->getID(), dLoc, SIMTIME);
1554 161 : myDir = passedFwd >= passedBwd ? FORWARD : BACKWARD;
1555 : } else {
1556 426023 : myDir = !mayStartBackward ? FORWARD : BACKWARD;
1557 : }
1558 : }
1559 243914 : if (myPosLat == UNSPECIFIED_POS_LAT || myLegacyPosLat) {
1560 243630 : if (myPosLat == UNSPECIFIED_POS_LAT) {
1561 243444 : myPosLat = 0;
1562 : }
1563 243630 : if (lane->getVehicleNumberWithPartials() > 0 && myPosLat == 0) {
1564 : // better start next to the road if nothing was specified
1565 2162 : myPosLat -= stripeWidth;
1566 : }
1567 243630 : if (myDir == FORWARD || lane->getPermissions() != SVC_PEDESTRIAN) {
1568 : // start at the right side of the sidewalk on shared roads
1569 207903 : myPosLat = stripeWidth * (numStripes(lane) - 1) - myPosLat;
1570 : }
1571 284 : } else if (myPosLat == RANDOM_POS_LAT) {
1572 20 : myPosLat = RandHelper::rand() * stripeWidth * (numStripes(lane) - 1);
1573 : } else {
1574 : // vehicle to striping coordinate system
1575 264 : myPosLat = posLatConversion(myPosLat, lane->getWidth());
1576 : }
1577 243914 : if DEBUGCOND(*this) {
1578 0 : std::cout << " added new pedestrian " << myPerson->getID() << " on " << lane->getID() << " myEdgePos=" << myEdgePos << " myPosLat=" << myPosLat << " dir=" << myDir << " route=" << toString(myStage->getRoute()) << "\n";
1579 : }
1580 :
1581 243914 : myNLI = getNextLane(*this, lane, nullptr);
1582 243910 : }
1583 :
1584 :
1585 14 : MSPModel_Striping::PState::PState(MSPerson* person, MSStageMoving* stage, std::istringstream* in) :
1586 : MSPModel_InteractingState(person, stage, nullptr),
1587 14 : myWalkingAreaPath(nullptr) {
1588 14 : if (in != nullptr) {
1589 : std::string laneID;
1590 : std::string wapLaneFrom;
1591 : std::string wapLaneTo;
1592 : std::string nextLaneID;
1593 : std::string nextLinkFrom;
1594 : std::string nextLinkTo;
1595 : int nextDir;
1596 :
1597 14 : (*in) >> laneID
1598 14 : >> myEdgePos >> myPosLat >> myDir >> mySpeed >> mySpeedLat >> myWaitingToEnter >> myWaitingTime
1599 14 : >> wapLaneFrom >> wapLaneTo
1600 14 : >> myAmJammed
1601 : >> nextLaneID
1602 : >> nextLinkFrom
1603 14 : >> nextLinkTo
1604 14 : >> nextDir;
1605 :
1606 :
1607 14 : myLane = MSLane::dictionary(laneID);
1608 14 : if (myLane == nullptr) {
1609 0 : throw ProcessError("Unknown lane '" + laneID + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1610 : }
1611 :
1612 : MSLane* nextLane = nullptr;
1613 14 : if (nextLaneID != "null") {
1614 13 : nextLane = MSLane::dictionary(nextLaneID);
1615 13 : if (nextLane == nullptr) {
1616 0 : throw ProcessError("Unknown next lane '" + nextLaneID + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1617 : }
1618 : }
1619 : const MSLink* link = nullptr;
1620 14 : if (nextLinkFrom != "null") {
1621 2 : MSLane* from = MSLane::dictionary(nextLinkFrom);
1622 2 : MSLane* to = MSLane::dictionary(nextLinkTo);
1623 2 : if (from == nullptr) {
1624 0 : throw ProcessError("Unknown link origin lane '" + nextLinkFrom + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1625 : }
1626 2 : if (to == nullptr) {
1627 0 : throw ProcessError("Unknown link destination lane '" + nextLinkTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1628 : }
1629 2 : link = from->getLinkTo(to);
1630 : }
1631 14 : myNLI = NextLaneInfo(nextLane, link, nextDir);
1632 :
1633 14 : if (wapLaneFrom != "null") {
1634 1 : MSLane* from = MSLane::dictionary(wapLaneFrom);
1635 1 : MSLane* to = MSLane::dictionary(wapLaneTo);
1636 1 : if (from == nullptr) {
1637 0 : throw ProcessError("Unknown walkingAreaPath origin lane '" + wapLaneFrom + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1638 : }
1639 1 : if (to == nullptr) {
1640 0 : throw ProcessError("Unknown walkingAreaPath destination lane '" + wapLaneTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1641 : }
1642 1 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(from, to));
1643 1 : if (pathIt != myWalkingAreaPaths.end()) {
1644 1 : myWalkingAreaPath = &pathIt->second;
1645 : } else {
1646 0 : throw ProcessError("Unknown walkingAreaPath from lane '" + wapLaneFrom + "' to lane '" + wapLaneTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1647 : }
1648 : }
1649 : }
1650 14 : }
1651 :
1652 :
1653 504822 : MSPModel_Striping::PState::PState() :
1654 504822 : MSPModel_InteractingState(nullptr, nullptr, nullptr) {}
1655 :
1656 :
1657 : void
1658 9 : MSPModel_Striping::PState::saveState(std::ostringstream& out) {
1659 9 : std::string wapLaneFrom = "null";
1660 9 : std::string wapLaneTo = "null";
1661 9 : if (myWalkingAreaPath != nullptr) {
1662 1 : wapLaneFrom = myWalkingAreaPath->from->getID();
1663 1 : wapLaneTo = myWalkingAreaPath->to->getID();
1664 : }
1665 9 : std::string nextLaneID = "null";
1666 9 : std::string nextLinkFrom = "null";
1667 9 : std::string nextLinkTo = "null";
1668 9 : if (myNLI.lane != nullptr) {
1669 : nextLaneID = myNLI.lane->getID();
1670 : }
1671 9 : if (myNLI.link != nullptr) {
1672 : nextLinkFrom = myNLI.link->getLaneBefore()->getID();
1673 2 : nextLinkTo = myNLI.link->getViaLaneOrLane()->getID();
1674 : }
1675 9 : out << " " << myLane->getID()
1676 18 : << " " << myEdgePos
1677 9 : << " " << myPosLat
1678 : << " " << myDir
1679 18 : << " " << mySpeed
1680 9 : << " " << mySpeedLat
1681 9 : << " " << myWaitingToEnter
1682 9 : << " " << myWaitingTime
1683 : << " " << wapLaneFrom
1684 : << " " << wapLaneTo
1685 9 : << " " << myAmJammed
1686 : << " " << nextLaneID
1687 : << " " << nextLinkFrom
1688 : << " " << nextLinkTo
1689 9 : << " " << myNLI.dir;
1690 9 : }
1691 :
1692 : double
1693 2303251246 : MSPModel_Striping::PState::getMinX(const bool includeMinGap) const {
1694 : // @todo speed should have an influence here because faster persons need more space
1695 2303251246 : if (myDir == FORWARD) {
1696 2134145958 : return myEdgePos - getLength();
1697 : }
1698 169105288 : return myEdgePos - (includeMinGap ? getMinGap() : 0.);
1699 : }
1700 :
1701 :
1702 : double
1703 2303251246 : MSPModel_Striping::PState::getMaxX(const bool includeMinGap) const {
1704 : // @todo speed should have an influence here because faster persons need more space
1705 2303251246 : if (myDir == FORWARD) {
1706 2134145958 : return myEdgePos + (includeMinGap ? getMinGap() : 0.);
1707 : }
1708 169105288 : return myEdgePos + getLength();
1709 : }
1710 :
1711 :
1712 : double
1713 2374357692 : MSPModel_Striping::PState::getLength() const {
1714 2374357692 : return myPerson->getVehicleType().getLength();
1715 : }
1716 :
1717 :
1718 : double
1719 1558447390 : MSPModel_Striping::PState::getMinGap() const {
1720 1558447390 : return myPerson->getVehicleType().getMinGap();
1721 : }
1722 :
1723 :
1724 : int
1725 8414695689 : MSPModel_Striping::PState::stripe(double relY) {
1726 8414695689 : return (int)floor(relY / stripeWidth + 0.5);
1727 : }
1728 :
1729 :
1730 : int
1731 3665377174 : MSPModel_Striping::PState::otherStripe(double relY) const {
1732 3665377174 : const int s = stripe(relY);
1733 3665377174 : const double offset = relY - s * stripeWidth;
1734 3665377174 : const double threshold = MAX2(NUMERICAL_EPS, stripeWidth - SQUEEZE * getWidth());
1735 : int result;
1736 3665377174 : if (offset > threshold) {
1737 504045 : result = s + 1;
1738 3664873129 : } else if (offset < -threshold) {
1739 426621 : result = s - 1;
1740 : } else {
1741 : result = s;
1742 : }
1743 : //std::cout.setf(std::ios::fixed , std::ios::floatfield);
1744 : //std::cout << std::setprecision(5);
1745 : //if DEBUGCOND(*this) std::cout << " otherStripe " << myPerson->getID() << " offset=" << offset << " threshold=" << threshold << " rawResult=" << result << "\n";
1746 3665377174 : return result;
1747 : }
1748 :
1749 : int
1750 4713743867 : MSPModel_Striping::PState::stripe() const {
1751 4713743867 : return MIN2(MAX2(0, stripe(myPosLat)), numStripes(myLane) - 1);
1752 : }
1753 :
1754 :
1755 : int
1756 3648659729 : MSPModel_Striping::PState::otherStripe() const {
1757 3648659729 : return MIN2(MAX2(0, otherStripe(myPosLat)), numStripes(myLane) - 1);
1758 : }
1759 :
1760 :
1761 : double
1762 144448159 : MSPModel_Striping::PState::distToLaneEnd() const {
1763 144448159 : if (myStage->getNextRouteEdge() == nullptr) {
1764 24803824 : return myDir * (myStage->getArrivalPos() - myEdgePos) - POSITION_EPS - (
1765 2223618 : (myWaitingTime > DELTA_T && (myStage->getDestinationStop() == nullptr ||
1766 : myStage->getDestinationStop()->getWaitingCapacity() > myStage->getDestinationStop()->getNumWaitingPersons()))
1767 27027442 : ? getMinGap() : 0);
1768 : } else {
1769 119644335 : const double length = myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length;
1770 119644335 : return myDir == FORWARD ? length - myEdgePos : myEdgePos;
1771 : }
1772 : }
1773 :
1774 :
1775 : bool
1776 987732 : MSPModel_Striping::PState::moveToNextLane(SUMOTime currentTime) {
1777 987732 : double dist = distToLaneEnd();
1778 987732 : if (DEBUGCOND(*this)) {
1779 0 : std::cout << SIMTIME << " ped=" << myPerson->getID() << " myEdgePos=" << myEdgePos << " dist=" << dist << "\n";
1780 : }
1781 987732 : if (dist <= 0) {
1782 : //if (ped.getPerson()->getID() == DEBUG1) {
1783 : // std::cout << SIMTIME << " addToLane x=" << ped.myEdgePos << " newDir=" << newDir << " newLane=" << newLane->getID() << " walkingAreaShape=" << walkingAreaShape << "\n";
1784 : //}
1785 : //std::cout << " changing to " << newLane->getID() << " myPosLat=" << ped.myPosLat << " oldStripes=" << numStripes(myLane) << " newStripes=" << numStripes(newLane);
1786 : //std::cout << " newY=" << ped.myPosLat << " myDir=" << ped.getDirection() << " newDir=" << newDir;
1787 987732 : const int oldDir = myDir;
1788 987732 : const MSLane* oldLane = myLane;
1789 987732 : myLane = myNLI.lane;
1790 987732 : myDir = myNLI.dir;
1791 987732 : const bool normalLane = (myLane == nullptr || myLane->getEdge().getFunction() == SumoXMLEdgeFunc::NORMAL || &myLane->getEdge() == myStage->getNextRouteEdge());
1792 987732 : if DEBUGCOND(*this) {
1793 0 : std::cout << SIMTIME
1794 0 : << " ped=" << myPerson->getID()
1795 : << " moveToNextLane old=" << oldLane->getID()
1796 0 : << " new=" << (myLane == nullptr ? "NULL" : myLane->getID())
1797 : << " oldDir=" << oldDir
1798 0 : << " newDir=" << myDir
1799 0 : << " myEdgePos=" << myEdgePos
1800 : << " dist=" << dist
1801 0 : << "\n";
1802 : }
1803 987732 : if (myLane == nullptr) {
1804 230811 : myEdgePos = myStage->getArrivalPos();
1805 : }
1806 : // moveToNextEdge might destroy the person and thus mess up the heap. Better check first
1807 987732 : if (myStage->getRouteStep() == myStage->getRoute().end() - 1) {
1808 230811 : myLane = nullptr;
1809 : } else {
1810 756921 : const bool arrived = myStage->moveToNextEdge(myPerson, currentTime, oldDir, normalLane ? nullptr : &myLane->getEdge());
1811 : UNUSED_PARAMETER(arrived);
1812 : assert(!arrived);
1813 : assert(myDir != UNDEFINED_DIRECTION);
1814 756921 : myNLI = getNextLane(*this, myLane, oldLane);
1815 : // reminders must be called after updated myNLI (to ensure that getNextEdgePtr returns the correct edge)
1816 756921 : myStage->activateEntryReminders(myPerson);
1817 : assert(myNLI.lane != oldLane); // do not turn around
1818 756921 : if DEBUGCOND(*this) {
1819 0 : std::cout << " nextLane=" << (myNLI.lane == nullptr ? "NULL" : myNLI.lane->getID()) << "\n";
1820 : }
1821 756921 : if (myLane->isWalkingArea()) {
1822 346841 : if (myNLI.dir != UNDEFINED_DIRECTION) {
1823 346804 : myWalkingAreaPath = getWalkingAreaPath(&myLane->getEdge(), oldLane, myNLI.lane);
1824 : assert(myWalkingAreaPath->shape.size() >= 2);
1825 346804 : if DEBUGCOND(*this) {
1826 0 : std::cout << " mWAPath shape=" << myWalkingAreaPath->shape << " length=" << myWalkingAreaPath->length << "\n";
1827 : }
1828 37 : } else if (myNLI.link != nullptr) {
1829 : // using direct connection (instead of using walkingarea)
1830 17 : myLane = myNLI.lane;
1831 : assert(!myLane->isWalkingArea());
1832 17 : myStage->moveToNextEdge(myPerson, currentTime, myDir, &myLane->getEdge());
1833 17 : myWalkingAreaPath = nullptr;
1834 17 : myNLI = getNextLane(*this, myLane, oldLane);
1835 : } else {
1836 : // disconnected route. move to the next edge
1837 40 : if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
1838 : // try to determine direction from topology, otherwise maintain current direction
1839 16 : const MSEdge* currRouteEdge = *myStage->getRouteStep();
1840 16 : const MSEdge* nextRouteEdge = myStage->getNextRouteEdge();
1841 : if ((nextRouteEdge->getToJunction() == currRouteEdge->getFromJunction())
1842 16 : || nextRouteEdge->getToJunction() == currRouteEdge->getToJunction()) {
1843 4 : myDir = BACKWARD;
1844 : } else if ((nextRouteEdge->getFromJunction() == currRouteEdge->getFromJunction())
1845 12 : || nextRouteEdge->getFromJunction() == currRouteEdge->getToJunction()) {
1846 12 : myDir = FORWARD;
1847 : }
1848 16 : myStage->moveToNextEdge(myPerson, currentTime, oldDir, nullptr);
1849 16 : myLane = myNLI.lane;
1850 : assert(myLane != 0);
1851 : assert(myLane->getEdge().getFunction() == SumoXMLEdgeFunc::NORMAL);
1852 16 : myNLI = getNextLane(*this, myLane, oldLane);
1853 16 : myWalkingAreaPath = nullptr;
1854 : } else {
1855 12 : throw ProcessError(TLF("Disconnected walk for person '%'.", myPerson->getID()));
1856 : }
1857 : }
1858 : } else {
1859 410080 : myWalkingAreaPath = nullptr;
1860 : }
1861 : // adapt x to fit onto the new lane
1862 : // (make sure we do not move past the end of the new lane since that
1863 : // lane was not checked for obstacles)
1864 756917 : const double newLength = (myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length);
1865 756917 : if (-dist > newLength) {
1866 : assert(OptionsCont::getOptions().getBool("ignore-route-errors"));
1867 : // should not happen because the end of myLane should have been an obstacle as well
1868 : // (only when the route is broken)
1869 1 : dist = -newLength;
1870 : }
1871 756917 : if (myDir == BACKWARD) {
1872 145858 : myEdgePos = newLength + dist;
1873 : } else {
1874 611059 : myEdgePos = -dist;
1875 : }
1876 756917 : if DEBUGCOND(*this) {
1877 0 : std::cout << SIMTIME << " update myEdgePos ped=" << myPerson->getID()
1878 : << " newLength=" << newLength
1879 : << " dist=" << dist
1880 0 : << " myEdgePos=" << myEdgePos
1881 0 : << "\n";
1882 : }
1883 : // adjust to change in direction
1884 756917 : if (myDir != oldDir) {
1885 32708 : myPosLat = (numStripes(oldLane) - 1) * stripeWidth - myPosLat;
1886 : }
1887 : // adjust to differences in sidewalk width
1888 1500620 : const int offset = getStripeOffset(numStripes(oldLane), numStripes(myLane), oldDir != myDir && numStripes(myLane) < numStripes(oldLane));
1889 756917 : myPosLat += offset * stripeWidth;
1890 756917 : if DEBUGCOND(*this) {
1891 0 : std::cout << SIMTIME << " transformY ped=" << myPerson->getID()
1892 0 : << " newLane=" << Named::getIDSecure(myLane)
1893 0 : << " newY=" << myPosLat
1894 0 : << " os=" << numStripes(oldLane) << " ns=" << numStripes(myLane)
1895 0 : << " od=" << oldDir << " nd=" << myDir
1896 0 : << " offset=" << offset << "\n";
1897 : }
1898 : }
1899 987728 : myAngle = std::numeric_limits<double>::max(); // see #9014
1900 987728 : return true;
1901 : } else {
1902 : return false;
1903 : }
1904 : }
1905 :
1906 :
1907 : int
1908 71177481 : MSPModel_Striping::getReserved(int stripes, double factor) {
1909 71177481 : return MIN2(
1910 71177481 : (int)floor(stripes * factor),
1911 71177481 : (int)floor(RESERVE_FOR_ONCOMING_MAX / stripeWidth));
1912 : }
1913 :
1914 : void
1915 71106446 : MSPModel_Striping::PState::walk(const Obstacles& obs) {
1916 71106446 : const int stripes = (int)obs.size();
1917 71106446 : const int sMax = stripes - 1;
1918 : assert(stripes == numStripes(myLane));
1919 : // account stage-specific max speed but also for normal lane speed limit
1920 : // (speed limits on crossings and walkingareas ignored due to #11527)
1921 71106446 : const double vMax = (myStage->getConfiguredSpeed() >= 0
1922 71106446 : ? myStage->getConfiguredSpeed()
1923 9173763 : : (USE_NET_SPEEDS || myLane->isNormal() || myLane->isInternal()
1924 79499229 : ? myLane->getVehicleMaxSpeed(myPerson)
1925 725935 : : myStage->getMaxSpeed(myPerson)));
1926 : // ultimate goal is to choose the preferred stripe (chosen)
1927 71106446 : const int current = stripe();
1928 71106446 : const int other = otherStripe();
1929 : // compute distances
1930 71106446 : std::vector<double> distance(stripes);
1931 307778547 : for (int i = 0; i < stripes; ++i) {
1932 236672101 : distance[i] = distanceTo(obs[i], obs[i].type == OBSTACLE_PED);
1933 : }
1934 : // compute utility for all stripes
1935 71106446 : std::vector<double> utility(stripes, 0);
1936 : // forbid stripes which are blocked and also all stripes behind them
1937 307778547 : for (int i = 0; i < stripes; ++i) {
1938 236672101 : if (distance[i] == DIST_OVERLAP) {
1939 108839656 : if (i == current && (!isWaitingToEnter() || stripe() != stripe(myPosLat))) {
1940 8070916 : utility[i] += OBSTRUCTED_PENALTY;
1941 : }
1942 108839656 : if (i < current) {
1943 149593957 : for (int j = 0; j <= i; ++j) {
1944 90945551 : utility[j] += OBSTRUCTED_PENALTY;
1945 : }
1946 : }
1947 108839656 : if (i > current) {
1948 69934483 : for (int j = i; j < stripes; ++j) {
1949 40299485 : utility[j] += OBSTRUCTED_PENALTY;
1950 : }
1951 : }
1952 : }
1953 : }
1954 : // forbid a portion of the leftmost stripes (in walking direction).
1955 : // lanes with stripes less than 1 / RESERVE_FOR_ONCOMING_FACTOR
1956 : // may still deadlock in heavy pedestrian traffic
1957 71106446 : const bool onJunction = myLane->isWalkingArea() || myLane->isCrossing();
1958 71106446 : const int reserved = getReserved(stripes, (onJunction ? RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS : RESERVE_FOR_ONCOMING_FACTOR));
1959 71106446 : if (myDir == FORWARD) {
1960 75066174 : for (int i = 0; i < reserved; ++i) {
1961 17835553 : utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1962 : }
1963 : } else {
1964 6903635 : for (int i = sMax; i > sMax - reserved; --i) {
1965 2829532 : utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1966 : }
1967 : }
1968 : // adapt utility based on obstacles
1969 307778547 : for (int i = 0; i < stripes; ++i) {
1970 236672101 : if (obs[i].speed * myDir < 0) {
1971 : // penalize evasion to the left unless the obstacle is a vehicle
1972 4450268 : if ((myDir == FORWARD || obs[i].type == OBSTACLE_VEHICLE) && i > 0) {
1973 857216 : utility[i - 1] -= 0.5;
1974 3593052 : } else if (myDir == BACKWARD && i < sMax) {
1975 589519 : utility[i + 1] -= 0.5;
1976 : }
1977 : }
1978 : // compute expected distance achievable by staying on this stripe for a time horizon
1979 236672101 : const double walkDist = MAX2(0., distance[i]); // disregard special distance flags
1980 236672101 : const double lookAhead = obs[i].speed * myDir >= 0 ? LOOKAHEAD_SAMEDIR : LOOKAHEAD_ONCOMING;
1981 236672101 : const double expectedDist = MIN2(vMax * LOOKAHEAD_SAMEDIR, walkDist + obs[i].speed * myDir * lookAhead);
1982 236672101 : if (expectedDist >= 0) {
1983 233555392 : utility[i] += expectedDist;
1984 : } else {
1985 : // let only the distance count
1986 3116709 : utility[i] += ONCOMING_CONFLICT_PENALTY + distance[i];
1987 : }
1988 : }
1989 : // discourage use of the leftmost stripe (in walking direction) if there are oncoming
1990 71106446 : if (myDir == FORWARD && obs[0].speed < 0) {
1991 1500929 : utility[0] += ONCOMING_CONFLICT_PENALTY;
1992 69605517 : } else if (myDir == BACKWARD && obs[sMax].speed > 0) {
1993 1506008 : utility[sMax] += ONCOMING_CONFLICT_PENALTY;
1994 : }
1995 : // penalize lateral movement (if the current stripe permits walking)
1996 71106446 : if (distance[current] > 0 && myWaitingTime == 0) {
1997 131110315 : for (int i = 0; i < stripes; ++i) {
1998 102674542 : utility[i] += abs(i - current) * LATERAL_PENALTY;
1999 : }
2000 : }
2001 : // walk on the right side on shared space
2002 71106446 : if (myLane->getPermissions() != SVC_PEDESTRIAN && myDir == BACKWARD) {
2003 2372940 : for (int i = 0; i < stripes; ++i) {
2004 1977634 : if (i <= current) {
2005 1884352 : utility[i] += (sMax - i + 1) * LATERAL_PENALTY;
2006 : }
2007 : }
2008 : }
2009 :
2010 : // select best stripe
2011 : int chosen = current;
2012 307778547 : for (int i = 0; i < stripes; ++i) {
2013 236672101 : if (utility[i] > utility[chosen] && utility[i] >= INAPPROPRIATE_PENALTY * 0.5) {
2014 : chosen = i;
2015 : }
2016 : }
2017 : // compute speed components along both axes
2018 71106446 : const int next = (chosen == current ? current : (chosen < current ? current - 1 : current + 1));
2019 71106446 : double xDist = MIN3(distance[current], distance[other], distance[next]);
2020 71106446 : if (next != chosen) {
2021 : // ensure that we do not collide with an obstacle in the stripe beyond
2022 : // next as this might become the 'other' stripe in the next step
2023 487583 : const int nextOther = chosen < current ? current - 2 : current + 2;
2024 487583 : xDist = MIN2(xDist, distance[nextOther]);
2025 : }
2026 : // XXX preferred gap differs between approaching a standing obstacle or a moving obstacle
2027 : const double preferredGap = NUMERICAL_EPS;
2028 71106446 : double xSpeed = MIN2(vMax, MAX2(0., DIST2SPEED(xDist - preferredGap)));
2029 71106446 : if (xSpeed < NUMERICAL_EPS) {
2030 : xSpeed = 0.;
2031 : }
2032 71106446 : if (DEBUGCOND(*this)) {
2033 0 : std::cout << " xSpeedPotential=" << xSpeed << "\n";
2034 : }
2035 : // avoid tiny steps
2036 : // XXX pressure from behind?
2037 71106446 : if (mySpeed == 0 && xDist < MIN_STARTUP_DIST &&
2038 : // unless walking towards a short lane
2039 32953419 : !(
2040 33237790 : (xDist == distance[current] && obs[current].type >= OBSTACLE_END)
2041 32953435 : || (xDist == distance[other] && obs[other].type >= OBSTACLE_END)
2042 32953419 : || (xDist == distance[next] && obs[next].type >= OBSTACLE_END))
2043 : ) {
2044 : xSpeed = 0;
2045 : }
2046 38153029 : if (xSpeed == 0) {
2047 40795958 : if (DEBUGCOND(*this)) {
2048 0 : std::cout << " sharedWA=" << (myWalkingAreaFoes.find(&myLane->getEdge()) != myWalkingAreaFoes.end())
2049 0 : << " vehObs=" << Named::getIDSecure(obs[current].vehicle)
2050 0 : << " vehWait=" << STEPS2TIME(obs[current].vehicle ? obs[current].vehicle->getWaitingTime() : 0)
2051 0 : << "\n";
2052 : }
2053 40795958 : if (myWaitingTime > ((myLane->isCrossing()
2054 : // treat shared walkingarea like a crossing to avoid deadlocking vehicles
2055 40791998 : || (myLane->isWalkingArea() && obs[current].vehicle != nullptr && obs[current].vehicle->getWaitingTime() > jamTimeCrossing
2056 81588239 : && myWalkingAreaFoes.find(&myLane->getEdge()) != myWalkingAreaFoes.end())) ? jamTimeCrossing : jamTime)
2057 40708942 : || (sMax == 0 && obs[0].speed * myDir < 0 && myWaitingTime > jamTimeNarrow)
2058 81476315 : || myAmJammed) {
2059 : // squeeze slowly through the crowd ignoring others
2060 9334342 : if (!myAmJammed) {
2061 97858 : MSNet::getInstance()->getPersonControl().registerJammed();
2062 391432 : WRITE_WARNINGF(TL("Person '%' is jammed on edge '%', time=%."),
2063 : myPerson->getID(), myStage->getEdge()->getID(), time2string(SIMSTEP));
2064 97858 : myAmJammed = true;
2065 : }
2066 9334342 : xSpeed = vMax * jamFactor;
2067 : }
2068 30310488 : } else if (myAmJammed && stripe(myPosLat) >= 0 && stripe(myPosLat) <= sMax && xDist >= MIN_STARTUP_DIST) {
2069 88797 : myAmJammed = false;
2070 : }
2071 : // dawdling
2072 71106446 : const double dawdle = MIN2(xSpeed, RandHelper::rand() * vMax * dawdling);
2073 71106446 : xSpeed -= dawdle;
2074 :
2075 : // XXX ensure that diagonal speed <= vMax
2076 : // avoid deadlocks on narrow sidewalks
2077 : //if (oncoming && xSpeed == 0 && myStage->getWaitingTime(currentTime) > TIME2STEPS(ONCOMIN_PATIENCE)) {
2078 : // if DEBUGCOND(*this) std::cout << " stepping aside to resolve oncoming deadlock\n";
2079 : // xSpeed = POSITION_EPS; // reset myWaitingTime
2080 : // if (myDir == FORWARD && chosen < sMax) {
2081 : // chosen += 1;
2082 : // } else if (myDir == BACKWARD && chosen > 0) {
2083 : // chosen -= 1;
2084 : // }
2085 : //}
2086 71106446 : const double maxYSpeed = MIN2(MAX2(vMax * LATERAL_SPEED_FACTOR, vMax - xSpeed), stripeWidth);
2087 : double ySpeed = 0;
2088 : double yDist = 0;
2089 71106446 : if (utility[next] > OBSTRUCTION_THRESHOLD && utility[chosen] > OBSTRUCTION_THRESHOLD) {
2090 : // don't move laterally if the stripes are blocked
2091 63084945 : yDist = (chosen * stripeWidth) - myPosLat;
2092 63084945 : if (fabs(yDist) > NUMERICAL_EPS) {
2093 2755210 : ySpeed = (yDist > 0 ?
2094 1264684 : MIN2(maxYSpeed, DIST2SPEED(yDist)) :
2095 1490526 : MAX2(-maxYSpeed, DIST2SPEED(yDist)));
2096 : }
2097 8021501 : } else if (utility[next] <= OBSTRUCTION_THRESHOLD && obs[next].type == OBSTACLE_VEHICLE
2098 : // still on the road
2099 9793 : && stripe() == stripe(myPosLat)
2100 : // only when the vehicle is moving on the same lane
2101 8026913 : && !(myLane->isCrossing() || myLane->isWalkingArea())) {
2102 : // step aside to let the vehicle pass
2103 3126 : int stepAsideDir = myDir;
2104 3126 : if (myLane->getEdge().getLanes().size() > 1 || current > sMax / 2) {
2105 : // always step to the right on multi-lane edges or when closer to
2106 : // the right side
2107 : stepAsideDir = FORWARD;
2108 : }
2109 3126 : myAmJammed = true; // ignore pedestrian-pedestrian collisions
2110 3126 : ySpeed = stepAsideDir * vMax;
2111 : }
2112 :
2113 : // DEBUG
2114 71106446 : if DEBUGCOND(*this) {
2115 0 : std::cout << SIMTIME
2116 0 : << " ped=" << myPerson->getID()
2117 0 : << " edge=" << myStage->getEdge()->getID()
2118 0 : << " x=" << myEdgePos
2119 0 : << " y=" << myPosLat
2120 : << " d=" << myDir
2121 0 : << " pvx=" << mySpeed
2122 : << " cur=" << current
2123 0 : << " cho=" << chosen
2124 0 : << " oth=" << other
2125 0 : << " nxt=" << next
2126 0 : << " vx=" << xSpeed
2127 : << " dawdle=" << dawdle
2128 : << " vy=" << ySpeed
2129 : << " xd=" << xDist
2130 : << " yd=" << yDist
2131 : << " vMax=" << vMax
2132 0 : << " wTime=" << myStage->getWaitingTime()
2133 0 : << " jammed=" << myAmJammed
2134 0 : << "\n";
2135 0 : if (DEBUGCOND(*this)) {
2136 0 : for (int i = 0; i < stripes; ++i) {
2137 0 : const Obstacle& o = obs[i];
2138 0 : std::cout << " util=" << utility[i] << " dist=" << distance[i] << " o=" << o.description;
2139 0 : if (o.description != "") {
2140 0 : std::cout << " xF=" << o.xFwd << " xB=" << o.xBack << " v=" << o.speed;
2141 : }
2142 0 : if (i == current) {
2143 0 : std::cout << " current";
2144 : }
2145 0 : if (i == other && i != current) {
2146 0 : std::cout << " other";
2147 : }
2148 0 : if (i == chosen) {
2149 0 : std::cout << " chosen";
2150 : }
2151 0 : if (i == next) {
2152 0 : std::cout << " next";
2153 : }
2154 0 : std::cout << "\n";
2155 : }
2156 : }
2157 : }
2158 71106446 : myEdgePos += SPEED2DIST(xSpeed * myDir);
2159 71106446 : myPosLat += SPEED2DIST(ySpeed);
2160 71106446 : mySpeedLat = ySpeed;
2161 71106446 : mySpeed = xSpeed;
2162 71106446 : if (xSpeed >= SUMO_const_haltingSpeed) {
2163 35288750 : myWaitingToEnter = false;
2164 35288750 : myWaitingTime = 0;
2165 : } else {
2166 35817696 : myWaitingTime += DELTA_T;
2167 35817696 : myTotalWaitingTime += DELTA_T;
2168 : }
2169 71106446 : myAngle = std::numeric_limits<double>::max(); // set on first access or via remote control
2170 71106446 : }
2171 :
2172 :
2173 : double
2174 12348481 : MSPModel_Striping::PState::getImpatience() const {
2175 12348481 : return MAX2(0., MIN2(1., myPerson->getVehicleType().getImpatience()
2176 12348481 : + STEPS2TIME(myStage->getWaitingTime()) / MAX_WAIT_TOLERANCE));
2177 : }
2178 :
2179 :
2180 : Position
2181 10959675 : MSPModel_Striping::PState::getPosition(const MSStageMoving& stage, SUMOTime) const {
2182 : if (myRemoteXYPos != Position::INVALID) {
2183 6275 : return myRemoteXYPos;
2184 : }
2185 10953400 : if (myLane == nullptr) {
2186 : // pedestrian has already finished
2187 229 : return Position::INVALID;
2188 : }
2189 10953171 : const double lateral_offset = -getLatOffset(); // the minus is hunting me in my dreams but seems to be here for historical reasons
2190 10953171 : if (myWalkingAreaPath == nullptr) {
2191 1116373 : return stage.getLanePosition(myLane, myEdgePos, lateral_offset);
2192 : } else {
2193 : //if DEBUGCOND(*this) {
2194 : // std::cout << SIMTIME
2195 : // << " getPosition (walkingArea)"
2196 : // << " p=" << myPerson->getID()
2197 : // << " x=" << myEdgePos
2198 : // << " y=" << myPosLat
2199 : // << " latOffset=" << lateral_offset
2200 : // << " shape=" << myWalkingAreaPath->shape
2201 : // << " pos=" << myWalkingAreaPath->shape.positionAtOffset(myEdgePos, lateral_offset)
2202 : // << "\n";
2203 : //}
2204 9836798 : if (myWalkingAreaPath->angleOverride == INVALID_DOUBLE) {
2205 9649247 : return myWalkingAreaPath->shape.positionAtOffset(myEdgePos, lateral_offset);
2206 : } else {
2207 187551 : const double rotationOffset = myDir == FORWARD ? 0 : DEG2RAD(180);
2208 187551 : return myWalkingAreaPath->shape.sidePositionAtAngle(myEdgePos, lateral_offset, myWalkingAreaPath->angleOverride + rotationOffset);
2209 : }
2210 : }
2211 : }
2212 :
2213 :
2214 : double
2215 2870167 : MSPModel_Striping::PState::getAngle(const MSStageMoving&, SUMOTime) const {
2216 2870167 : if (myAngle != std::numeric_limits<double>::max()) {
2217 : return myAngle;
2218 : }
2219 934464 : if (myLane == nullptr) {
2220 : // pedestrian has already finished
2221 : return 0;
2222 : }
2223 934233 : if (myWalkingAreaPath != nullptr && myWalkingAreaPath->angleOverride != INVALID_DOUBLE) {
2224 : return myWalkingAreaPath->angleOverride;
2225 : }
2226 883934 : const PositionVector& shp = myWalkingAreaPath == nullptr ? myLane->getShape() : myWalkingAreaPath->shape;
2227 883934 : double geomX = myWalkingAreaPath == nullptr ? myLane->interpolateLanePosToGeometryPos(myEdgePos) : myEdgePos;
2228 883934 : double angle = shp.rotationAtOffset(geomX) + (myDir == MSPModel::BACKWARD ? M_PI : 0);
2229 883934 : if (myDir == MSPModel::BACKWARD) {
2230 277079 : angle += atan2(mySpeedLat, MAX2(mySpeed, NUMERICAL_EPS));
2231 : } else { // myDir == MSPModel::FORWARD
2232 769399 : angle -= atan2(mySpeedLat, MAX2(mySpeed, NUMERICAL_EPS));
2233 : }
2234 883934 : if (angle > M_PI) {
2235 193571 : angle -= 2 * M_PI;
2236 : }
2237 883934 : myAngle = angle;
2238 883934 : return angle;
2239 : }
2240 :
2241 :
2242 : const MSEdge*
2243 166743 : MSPModel_Striping::PState::getNextEdge(const MSStageMoving&) const {
2244 166743 : return myNLI.lane == nullptr ? nullptr : &myNLI.lane->getEdge();
2245 : }
2246 :
2247 :
2248 : const MSLane*
2249 1686 : MSPModel_Striping::PState::getNextCrossing() const {
2250 1686 : return myNLI.lane != nullptr && myNLI.lane->isCrossing() ? myNLI.lane : nullptr;
2251 : }
2252 :
2253 :
2254 : void
2255 3447 : MSPModel_Striping::PState::reverse(const double pathLength, const double usableWidth) {
2256 3447 : myEdgePos = pathLength - myEdgePos;
2257 3447 : myPosLat = usableWidth - myPosLat;
2258 3447 : myDir = -myWalkingAreaPath->dir;
2259 3447 : mySpeedLat = -mySpeedLat;
2260 3447 : }
2261 :
2262 :
2263 : void
2264 256806 : MSPModel_Striping::PState::reset(const double edgePos, const double latPos) {
2265 256806 : myEdgePos = edgePos;
2266 256806 : myPosLat = latPos;
2267 256806 : myDir = UNDEFINED_DIRECTION; // only an obstacle, speed may be orthogonal to dir
2268 256806 : mySpeed = 0.;
2269 256806 : mySpeedLat = 0.;
2270 256806 : }
2271 :
2272 :
2273 : void
2274 19 : MSPModel_Striping::PState::moveTo(MSPerson* p, MSLane* lane, double lanePos, double lanePosLat, SUMOTime t) {
2275 : ConstMSEdgeVector newEdges; // keep route
2276 : int routeOffset = 0;
2277 : bool laneOnRoute = false;
2278 19 : const MSJunction* laneOnJunction = lane->isNormal() ? nullptr : lane->getEdge().getToJunction();
2279 19 : for (const MSEdge* edge : myStage->getRoute()) {
2280 : if (edge == &lane->getEdge()
2281 14 : || edge->getToJunction() == laneOnJunction
2282 19 : || edge->getFromJunction() == laneOnJunction) {
2283 : laneOnRoute = true;
2284 : break;
2285 : }
2286 0 : routeOffset++;
2287 : }
2288 19 : if (!laneOnRoute) {
2289 0 : throw ProcessError("Lane '" + lane->getID() + "' is not on the route of person '" + getID() + "'.");
2290 : }
2291 19 : Position pos = lane->geometryPositionAtOffset(lanePos, lanePosLat);
2292 19 : if (lane->isWalkingArea() && (myWalkingAreaPath == nullptr || myWalkingAreaPath->lane != lane)) {
2293 : // entered new walkingarea. Determine path to guess position
2294 9 : const MSEdge* prevEdge = myStage->getRoute()[routeOffset];
2295 9 : const MSEdge* nextEdge = routeOffset + 1 < (int)myStage->getRoute().size() ? myStage->getRoute()[routeOffset + 1] : nullptr;
2296 9 : const WalkingAreaPath* guessed = guessPath(&lane->getEdge(), prevEdge, nextEdge);
2297 9 : const double maxPos = guessed->shape.length() - NUMERICAL_EPS;
2298 9 : if (lanePos > maxPos + POSITION_EPS || lanePos < -POSITION_EPS) {
2299 0 : throw ProcessError("Lane position " + toString(lanePos) + " cannot be mapped onto walkingarea '" + lane->getID()
2300 0 : + "' (fromLane='" + guessed->from->getID()
2301 0 : + "' toLane='" + guessed->to->getID() + "') for person '" + getID() + "' time=" + time2string(t) + ".");
2302 : }
2303 : // give some slack
2304 9 : lanePos = MIN2(maxPos, MAX2(NUMERICAL_EPS, lanePos));
2305 9 : pos = guessed->shape.positionAtOffset(lanePos, lanePosLat);
2306 : }
2307 19 : const double angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
2308 19 : moveToXY(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, newEdges, t);
2309 19 : }
2310 :
2311 :
2312 : void
2313 14041 : MSPModel_Striping::PState::moveToXY(MSPerson* p, Position pos, MSLane* lane, double lanePos,
2314 : double lanePosLat, double angle, int routeOffset,
2315 : const ConstMSEdgeVector& edges, SUMOTime t) {
2316 14041 : MSPModel_Striping* pm = dynamic_cast<MSPModel_Striping*>(MSNet::getInstance()->getPersonControl().getMovementModel());
2317 : assert(p == myPerson);
2318 : assert(pm != nullptr);
2319 14041 : const double oldAngle = GeomHelper::naviDegree(getAngle(*myStage, t));
2320 : // person already walking in this step. undo this to obtain the previous position
2321 14041 : const double oldX = myEdgePos - SPEED2DIST(mySpeed * myDir);
2322 : const double tmp = myEdgePos;
2323 14041 : myEdgePos = oldX;
2324 14041 : Position oldPos = getPosition(*myStage, t);
2325 14041 : myEdgePos = tmp;
2326 : //if (oldPos == Position::INVALID) {
2327 : // oldPos = pos
2328 : //}
2329 14041 : myAngle = GeomHelper::fromNaviDegree(angle);
2330 : #ifdef DEBUG_MOVETOXY
2331 : std::cout << SIMTIME << " ped=" << p->getID()
2332 : << " moveToXY"
2333 : << " pos=" << pos
2334 : << " lane=" << lane->getID()
2335 : << " lanePos=" << lanePos
2336 : << " lanePosLat=" << lanePosLat
2337 : << " angle=" << angle
2338 : << " routeOffset=" << routeOffset
2339 : << " edges=" << toString(edges)
2340 : << " oldLane=" << Named::getIDSecure(myLane)
2341 : << " path=" << (myWalkingAreaPath == nullptr ? "null" : (myWalkingAreaPath->from->getID() + "->" + myWalkingAreaPath->to->getID())) << "\n";
2342 : #endif
2343 :
2344 14041 : if (lane != myLane && myLane != nullptr && lane != nullptr) {
2345 360 : pm->remove(this);
2346 : pm->registerActive();
2347 : }
2348 14041 : if (lane != nullptr &&
2349 10909 : fabs(lanePosLat) < (0.5 * (lane->getWidth() + p->getVehicleType().getWidth()) + SIDEWALK_OFFSET)) {
2350 10904 : myRemoteXYPos = Position::INVALID;
2351 10904 : const MSEdge* old = myStage->getEdge();
2352 10904 : const MSLane* oldLane = myLane;
2353 10904 : if (lane != myLane) {
2354 : // implicitly adds new active lane if necessary
2355 360 : pm->myActiveLanes[lane].push_back(this);
2356 : }
2357 10904 : if (edges.empty()) {
2358 : // map within route
2359 10854 : myStage->setRouteIndex(myPerson, routeOffset);
2360 : } else {
2361 50 : myStage->replaceRoute(myPerson, edges, routeOffset);
2362 : }
2363 10904 : if (!lane->getEdge().isNormal()) {
2364 496 : myStage->moveToNextEdge(myPerson, t, myDir, &lane->getEdge());
2365 : }
2366 :
2367 10904 : myLane = lane;
2368 10904 : const double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
2369 10904 : if (lane->isWalkingArea()) {
2370 242 : if (myWalkingAreaPath == nullptr || myWalkingAreaPath->lane != lane) {
2371 : // entered new walkingarea. Determine path
2372 52 : myWalkingAreaPath = guessPath(&lane->getEdge(), old, myStage->getNextRouteEdge());
2373 : #ifdef DEBUG_MOVETOXY
2374 : std::cout << " guessPath old=" << old->getID() << " next=" << Named::getIDSecure(myStage->getNextRouteEdge())
2375 : << " path=" << myWalkingAreaPath->from->getID() << "->" << myWalkingAreaPath->to->getID() << "\n";
2376 : #endif
2377 : }
2378 : // lanePos and lanePosLat are matched onto the circumference of the
2379 : // walkingarea. Use pos instead
2380 242 : const Position relPos = myWalkingAreaPath->shape.transformToVectorCoordinates(pos);
2381 : if (relPos == Position::INVALID) {
2382 0 : WRITE_WARNING("Could not map position " + toString(pos) + " onto lane '" + myLane->getID()
2383 : + "' (fromLane='" + myWalkingAreaPath->from->getID()
2384 : + "' toLane='" + myWalkingAreaPath->to->getID() + "') for person '" + getID() + "' time=" + time2string(t) + ".");
2385 0 : myRemoteXYPos = pos;
2386 : } else {
2387 242 : myEdgePos = relPos.x();
2388 242 : myPosLat = lateral_offset + relPos.y();
2389 : }
2390 : } else {
2391 10662 : myWalkingAreaPath = nullptr;
2392 10662 : myEdgePos = lanePos;
2393 10662 : myPosLat = lateral_offset - lanePosLat;
2394 10662 : lane->requireCollisionCheck();
2395 : }
2396 : // guess direction
2397 10904 : const double angleDiff = GeomHelper::getMinAngleDiff(angle, oldAngle);
2398 10904 : if (myStage->getNextRouteEdge() != nullptr) {
2399 6511 : if (myStage->getEdge()->getToJunction() == myStage->getNextRouteEdge()->getFromJunction() ||
2400 963 : myStage->getEdge()->getToJunction() == myStage->getNextRouteEdge()->getToJunction()) {
2401 4710 : myDir = FORWARD;
2402 : } else {
2403 838 : myDir = BACKWARD;
2404 : }
2405 : } else {
2406 : // guess from angle
2407 5356 : if (angleDiff <= 90) {
2408 : // keep direction
2409 5292 : if (myDir == UNDEFINED_DIRECTION) {
2410 0 : myDir = FORWARD;
2411 : }
2412 : } else {
2413 : // change direction
2414 64 : myDir = (myDir == BACKWARD) ? FORWARD : BACKWARD;
2415 : }
2416 : }
2417 : // update next lane info (after guessing direction)
2418 10904 : if (oldLane == nullptr || &oldLane->getEdge() != &myLane->getEdge()) {
2419 310 : const MSLane* sidewalk = getSidewalk<MSEdge, MSLane>(&myLane->getEdge(), p->getVClass());
2420 : // assume that we will eventually move back onto the sidewalk if
2421 : // there is one
2422 310 : myNLI = getNextLane(*this, sidewalk == nullptr ? myLane : sidewalk, nullptr);
2423 310 : myStage->activateEntryReminders(myPerson);
2424 : #ifdef DEBUG_MOVETOXY
2425 : std::cout << " myNLI=" << Named::getIDSecure(myNLI.lane) << " link=" << (myNLI.link == nullptr ? "NULL" : myNLI.link->getDescription()) << " dir=" << myNLI.dir << "\n";
2426 : #endif
2427 : }
2428 : #ifdef DEBUG_MOVETOXY
2429 : std::cout << " newRelPos=" << Position(myEdgePos, myPosLat) << " edge=" << myPerson->getEdge()->getID()
2430 : << " newPos=" << myPerson->getPosition()
2431 : << " latOffset=" << getLatOffset()
2432 : << " oldAngle=" << oldAngle << " angleDiff=" << angleDiff << " newDir=" << myDir << "\n";
2433 : #endif
2434 10904 : if (oldLane == myLane) {
2435 10544 : mySpeed = DIST2SPEED(fabs(oldX - myEdgePos));
2436 : } else {
2437 : //std::cout << SIMTIME << " oldX=" << oldX << " oldSpeed=" << mySpeed << " oldPos=" << oldPos << " pos=" << pos << " dist=" << oldPos.distanceTo2D(pos) << " oldLane=" << Named::getIDSecure(oldLane) << " lane=" << lane->getID() << "\n";
2438 360 : mySpeed = DIST2SPEED(oldPos.distanceTo2D(pos));
2439 : }
2440 : } else {
2441 : // map outside the network
2442 3137 : myRemoteXYPos = pos;
2443 3137 : mySpeed = DIST2SPEED(oldPos.distanceTo2D(pos));
2444 : }
2445 :
2446 14041 : }
2447 :
2448 :
2449 : double
2450 746828 : MSPModel_Striping::PState::getPathLength() const {
2451 746828 : if (myWalkingAreaPath != nullptr) {
2452 689914 : return myWalkingAreaPath->length;
2453 : } else {
2454 : return 0;
2455 : }
2456 : }
2457 :
2458 : double
2459 1586507373 : MSPModel_Striping::PState::distanceTo(const Obstacle& obs, const bool includeMinGap) const {
2460 : // check for overlap
2461 1586507373 : const double maxX = getMaxX(includeMinGap);
2462 1586507373 : const double minX = getMinX(includeMinGap);
2463 : //if (DEBUGCOND(*this)) {
2464 : // std::cout << std::setprecision(2) << " distanceTo=" << obs.description << " maxX=" << maxX << " minX=" << minX << " obs.xFwd=" << obs.xFwd << " obs.xBack=" << obs.xBack << "\n";
2465 : //}
2466 1586507373 : if ((obs.xFwd >= maxX && obs.xBack <= maxX) || (obs.xFwd <= maxX && obs.xFwd >= minX)) {
2467 : // avoid blocking by itself on looped route
2468 464710851 : return (obs.type == OBSTACLE_PED && obs.description == myPerson->getID()) ? DIST_FAR_AWAY : DIST_OVERLAP;
2469 : }
2470 1121796522 : if (myDir == FORWARD) {
2471 1010841956 : return obs.xFwd < minX ? DIST_BEHIND : obs.xBack - maxX;
2472 : } else {
2473 110954566 : return obs.xBack > maxX ? DIST_BEHIND : minX - obs.xFwd;
2474 : }
2475 : }
2476 :
2477 :
2478 : void
2479 91858593 : MSPModel_Striping::PState::mergeObstacles(Obstacles& into, const Obstacles& obs2) {
2480 402144274 : for (int i = 0; i < (int)into.size(); ++i) {
2481 310285681 : if (gDebugFlag1) {
2482 0 : std::cout << " i=" << i << " maxX=" << getMaxX(true) << " minX=" << getMinX(true)
2483 0 : << " into=" << into[i].description << " iDist=" << distanceTo(into[i], into[i].type == OBSTACLE_PED)
2484 0 : << " obs2=" << obs2[i].description << " oDist=" << distanceTo(obs2[i], obs2[i].type == OBSTACLE_PED) << "\n";
2485 : }
2486 310285681 : const double dO = distanceTo(obs2[i], obs2[i].type == OBSTACLE_PED);
2487 310285681 : const double dI = distanceTo(into[i], into[i].type == OBSTACLE_PED);
2488 310285681 : if (dO < dI) {
2489 : into[i] = obs2[i];
2490 : } else if (dO == dI
2491 77050120 : && into[i].type != OBSTACLE_PED
2492 33845065 : && into[i].type != OBSTACLE_VEHICLE
2493 297876171 : && (obs2[i].type == OBSTACLE_PED ||
2494 : obs2[i].type == OBSTACLE_VEHICLE)) {
2495 : into[i] = obs2[i];
2496 : }
2497 : }
2498 91858593 : }
2499 :
2500 : void
2501 18641 : MSPModel_Striping::PState::mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset) {
2502 146450 : for (int i = 0; i < (int)into.size(); ++i) {
2503 127809 : int i2 = i + offset;
2504 127809 : if (i2 >= 0 && i2 < (int)obs2.size()) {
2505 126473 : if (dir == FORWARD) {
2506 90460 : if (obs2[i2].xBack < into[i].xBack) {
2507 : into[i] = obs2[i2];
2508 : }
2509 : } else {
2510 36013 : if (obs2[i2].xFwd > into[i].xFwd) {
2511 : into[i] = obs2[i2];
2512 : }
2513 : }
2514 : }
2515 : }
2516 18641 : }
2517 :
2518 :
2519 : bool
2520 12348481 : MSPModel_Striping::PState::ignoreRed(const MSLink* link) const {
2521 12348481 : if (link->haveRed()) {
2522 614526 : const double ignoreRedTime = myPerson->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME, -1);
2523 614526 : if (ignoreRedTime >= 0) {
2524 40 : const double redDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
2525 40 : if (DEBUGCOND(*this)) {
2526 0 : std::cout << SIMTIME << " ignoreRedTime=" << ignoreRedTime << " redDuration=" << redDuration << "\n";
2527 : }
2528 40 : return ignoreRedTime > redDuration;
2529 : } else {
2530 : return false;
2531 : }
2532 : } else {
2533 : return false;
2534 : }
2535 : }
2536 :
2537 :
2538 : bool
2539 11688910 : MSPModel_Striping::PState::stopForYellow(const MSLink* link) const {
2540 : // main use case is at rail_crossing
2541 11688910 : if (link->haveYellow()) {
2542 918 : const double ignoreYellowTime = myPerson->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME, -1);
2543 918 : if (ignoreYellowTime >= 0) {
2544 0 : const double yellowDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
2545 0 : if (DEBUGCOND(*this)) {
2546 0 : std::cout << SIMTIME << " ignoreYellowTime=" << ignoreYellowTime << " yellowDuration=" << yellowDuration << "\n";
2547 : }
2548 0 : return ignoreYellowTime < yellowDuration;
2549 : } else {
2550 : return true;
2551 : }
2552 : } else {
2553 : return false;
2554 : }
2555 : }
2556 :
2557 : double
2558 3664358423 : MSPModel_Striping::PState::getWidth() const {
2559 3664358423 : return myPerson->getVehicleType().getWidth();
2560 : }
2561 :
2562 :
2563 : bool
2564 134858524 : MSPModel_Striping::PState::isRemoteControlled() const {
2565 134858524 : return myPerson->hasInfluencer() && myPerson->getInfluencer().isRemoteControlled();
2566 : }
2567 :
2568 : // ===========================================================================
2569 : // MSPModel_Striping::PStateVehicle method definitions
2570 : // ===========================================================================
2571 :
2572 504822 : MSPModel_Striping::PStateVehicle::PStateVehicle(const MSVehicle* veh, const MSLane* walkingarea, double relX, double relY, double xWidth, double yWidth):
2573 504822 : myVehicle(veh), myXWidth(xWidth), myYWidth(yWidth) {
2574 504822 : myLane = walkingarea; // to ensure correct limits when calling otherStripe()
2575 : // relX is the center but we want it to be the max value if the movement direction is forward
2576 : // and the min value otherwise (indicated by xWidth sign)
2577 504822 : myEdgePos = relX + xWidth / 2;
2578 504822 : myPosLat = relY;
2579 504822 : }
2580 :
2581 : const std::string&
2582 1970448 : MSPModel_Striping::PStateVehicle::getID() const {
2583 1970448 : return myVehicle->getID();
2584 : }
2585 :
2586 : double
2587 1018751 : MSPModel_Striping::PStateVehicle::getWidth() const {
2588 1018751 : return myYWidth;
2589 : }
2590 :
2591 : double
2592 539616 : MSPModel_Striping::PStateVehicle::getMinX(const bool /*includeMinGap*/) const {
2593 539616 : return myXWidth > 0 ? myEdgePos - myXWidth : myEdgePos;
2594 : }
2595 :
2596 : double
2597 539616 : MSPModel_Striping::PStateVehicle::getMaxX(const bool /*includeMinGap*/) const {
2598 539616 : return myXWidth > 0 ? myEdgePos : myEdgePos - myXWidth;
2599 : }
2600 :
2601 : // ===========================================================================
2602 : // MSPModel_Striping::MovePedestrians method definitions
2603 : // ===========================================================================
2604 :
2605 : SUMOTime
2606 3129246 : MSPModel_Striping::MovePedestrians::execute(SUMOTime currentTime) {
2607 : std::set<MSPerson*> changedLane;
2608 3129246 : myModel->moveInDirection(currentTime, changedLane, FORWARD);
2609 3129242 : myModel->moveInDirection(currentTime, changedLane, BACKWARD);
2610 : // DEBUG
2611 : #ifdef LOG_ALL
2612 : for (ActiveLanes::const_iterator it_lane = myModel->getActiveLanes().begin(); it_lane != myModel->getActiveLanes().end(); ++it_lane) {
2613 : const MSLane* lane = it_lane->first;
2614 : Pedestrians pedestrians = it_lane->second;
2615 : if (pedestrians.size() == 0) {
2616 : continue;
2617 : }
2618 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(FORWARD));
2619 : std::cout << SIMTIME << " lane=" << lane->getID();
2620 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
2621 : const PState& p = *pedestrians[ii];
2622 : std::cout << " (" << p.getPerson()->getID() << " " << p.myEdgePos << "," << p.myPosLat << " " << p.getDirection() << ")";
2623 : }
2624 : std::cout << "\n";
2625 : }
2626 : #endif
2627 3129242 : return DELTA_T;
2628 : }
|