Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2014-2025 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 5408 : MSPModel_Striping::MSPModel_Striping(const OptionsCont& oc, MSNet* net) {
118 5408 : myWalkingAreaDetail = oc.getInt("pedestrian.striping.walkingarea-detail");
119 5408 : initWalkingAreaPaths(net);
120 : // configurable parameters
121 5408 : stripeWidth = oc.getFloat("pedestrian.striping.stripe-width");
122 5408 : MSVehicleType* defaultPedType = MSNet::getInstance()->getVehicleControl().getVType(DEFAULT_PEDTYPE_ID, nullptr, true);
123 5408 : 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 5408 : dawdling = oc.getFloat("pedestrian.striping.dawdling");
129 5408 : minGapToVehicle = oc.getFloat("pedestrian.striping.mingap-to-vehicle");
130 5408 : RESERVE_FOR_ONCOMING_FACTOR = oc.getFloat("pedestrian.striping.reserve-oncoming");
131 5408 : RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS = oc.getFloat("pedestrian.striping.reserve-oncoming.junctions");
132 5408 : 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 5408 : USE_NET_SPEEDS = net->getNetworkVersion() >= MMVersion(1, 20);
135 :
136 5408 : jamTime = string2time(oc.getString("pedestrian.striping.jamtime"));
137 5408 : if (jamTime <= 0) {
138 4 : jamTime = SUMOTime_MAX;
139 : }
140 5408 : jamTimeCrossing = string2time(oc.getString("pedestrian.striping.jamtime.crossing"));
141 5408 : if (jamTimeCrossing <= 0) {
142 0 : jamTimeCrossing = SUMOTime_MAX;
143 : }
144 5408 : jamTimeNarrow = string2time(oc.getString("pedestrian.striping.jamtime.narrow"));
145 5408 : if (jamTimeNarrow <= 0) {
146 0 : jamTimeNarrow = SUMOTime_MAX;
147 : }
148 5408 : jamFactor = oc.getFloat("pedestrian.striping.jamfactor");
149 5408 : myLegacyPosLat = oc.getBool("pedestrian.striping.legacy-departposlat");
150 5408 : }
151 :
152 :
153 10798 : MSPModel_Striping::~MSPModel_Striping() {
154 : myWalkingAreaPaths.clear(); // need to recompute when lane pointers change
155 : myWalkingAreaFoes.clear();
156 : myMinNextLengths.clear();
157 10798 : }
158 :
159 :
160 : MSTransportableStateAdapter*
161 243024 : MSPModel_Striping::add(MSTransportable* transportable, MSStageMoving* stage, SUMOTime) {
162 243024 : 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 243024 : MSNet* net = MSNet::getInstance();
168 243024 : if (!myAmActive) {
169 4006 : net->getBeginOfTimestepEvents()->addEvent(new MovePedestrians(this), net->getCurrentTimeStep() + DELTA_T);
170 4006 : myAmActive = true;
171 : }
172 : assert(person->getCurrentStageType() == MSStageType::WALKING);
173 243024 : const MSLane* lane = stage->checkDepartLane(person->getEdge(), person->getVClass(), stage->getDepartLane(), person->getID());
174 243024 : 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 243016 : PState* ped = new PState(person, stage, lane);
184 243012 : myActiveLanes[lane].push_back(ped);
185 243012 : myNumActivePedestrians++;
186 243012 : 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 7419370550 : MSPModel_Striping::numStripes(const MSLane* lane) {
207 7419370550 : return MAX2(1, (int)floor(lane->getWidth() / stripeWidth));
208 : }
209 :
210 :
211 : int
212 878631 : MSPModel_Striping::connectedDirection(const MSLane* from, const MSLane* to) {
213 878631 : if (from == nullptr || to == nullptr) {
214 0 : return UNDEFINED_DIRECTION;
215 878631 : } else if (from->getLinkTo(to) != nullptr) {
216 636607 : return FORWARD;
217 242024 : } else if (to->getLinkTo(from) != nullptr) {
218 242024 : return BACKWARD;
219 : } else {
220 0 : return UNDEFINED_DIRECTION;
221 : }
222 : }
223 :
224 :
225 : void
226 5408 : MSPModel_Striping::initWalkingAreaPaths(const MSNet*) {
227 5408 : if (myWalkingAreaPaths.size() > 0) {
228 : return;
229 : }
230 : // collect vehicle lanes that cross walkingareas
231 422222 : for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
232 416814 : const MSEdge* edge = *i;
233 416814 : if (!edge->isWalkingArea() && !edge->isCrossing()) {
234 746062 : for (MSLane* lane : edge->getLanes()) {
235 871923 : for (MSLink* link : lane->getLinkCont()) {
236 482700 : if (link->getWalkingAreaFoe() != nullptr) {
237 : // link is an exit link
238 2942 : myWalkingAreaFoes[&link->getWalkingAreaFoe()->getEdge()].push_back(link->getLaneBefore());
239 : //std::cout << " wa=" << link->getWalkingAreaFoe()->getEdge().getID() << " foe=" << link->getLaneBefore()->getID() << "\n";
240 : }
241 482700 : if (link->getWalkingAreaFoeExit() != nullptr) {
242 : // link is an exit link
243 3028 : 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 422222 : for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
253 416814 : insertWalkArePaths(*i, myWalkingAreaPaths);
254 : }
255 : }
256 :
257 :
258 : void
259 416814 : MSPModel_Striping::insertWalkArePaths(const MSEdge* edge, WalkingAreaPaths& into) {
260 416814 : if (edge->isWalkingArea()) {
261 52284 : const MSLane* walkingArea = getSidewalk<MSEdge, MSLane>(edge);
262 52284 : myMinNextLengths[walkingArea] = walkingArea->getLength();
263 : // build all possible paths across this walkingArea
264 : // gather all incident lanes
265 : std::vector<const MSLane*> lanes;
266 135428 : for (const MSEdge* in : edge->getPredecessors()) {
267 83144 : if (!in->isTazConnector()) {
268 60714 : lanes.push_back(getSidewalk<MSEdge, MSLane>(in));
269 60714 : if (lanes.back() == nullptr) {
270 0 : throw ProcessError("Invalid connection from edge '" + in->getID() + "' to walkingarea edge '" + edge->getID() + "'");
271 : }
272 : }
273 : }
274 135613 : for (const MSEdge* out : edge->getSuccessors()) {
275 83329 : if (!out->isTazConnector()) {
276 60899 : lanes.push_back(getSidewalk<MSEdge, MSLane>(out));
277 60899 : 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 173897 : for (int j = 0; j < (int)lanes.size(); ++j) {
284 429920 : for (int k = 0; k < (int)lanes.size(); ++k) {
285 308307 : if (j != k) {
286 : // build the walkingArea
287 186694 : const MSLane* const from = lanes[j];
288 186694 : const MSLane* const to = lanes[k];
289 186694 : const int fromDir = from->getLinkTo(walkingArea) != nullptr ? FORWARD : BACKWARD;
290 186694 : const int toDir = walkingArea->getLinkTo(to) != nullptr ? FORWARD : BACKWARD;
291 186694 : PositionVector shape;
292 280300 : Position fromPos = from->getShape()[fromDir == FORWARD ? -1 : 0];
293 279782 : Position toPos = to->getShape()[toDir == FORWARD ? 0 : -1];
294 186694 : const double maxExtent = fromPos.distanceTo2D(toPos) / 4; // prevent sharp corners
295 186694 : const double extrapolateBy = MIN2(maxExtent, walkingArea->getWidth() / 2);
296 : // assemble shape
297 186694 : shape.push_back(fromPos);
298 186694 : if (extrapolateBy > POSITION_EPS) {
299 : PositionVector fromShp = from->getShape();
300 185684 : fromShp.extrapolate(extrapolateBy);
301 371368 : shape.push_back_noDoublePos(fromDir == FORWARD ? fromShp.back() : fromShp.front());
302 : PositionVector nextShp = to->getShape();
303 185684 : nextShp.extrapolate(extrapolateBy);
304 371368 : shape.push_back_noDoublePos(toDir == FORWARD ? nextShp.front() : nextShp.back());
305 185684 : }
306 186694 : shape.push_back_noDoublePos(toPos);
307 186694 : 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 186694 : } else if (myWalkingAreaDetail > 4) {
313 448 : shape = shape.bezier(myWalkingAreaDetail);
314 : }
315 : double angleOverride = INVALID_DOUBLE;
316 186694 : if (shape.size() >= 4 && shape.length() < walkingArea->getWidth()) {
317 46848 : const double aStart = shape.angleAt2D(0);
318 46848 : const double aEnd = shape.angleAt2D((int)shape.size() - 2);
319 46848 : if (fabs(aStart - aEnd) < DEG2RAD(10)) {
320 7402 : angleOverride = (aStart + aEnd) / 2;
321 : }
322 : }
323 186694 : if (fromDir == BACKWARD) {
324 : // will be walking backward on walkingArea
325 187212 : shape = shape.reverse();
326 : }
327 186694 : WalkingAreaPath wap = WalkingAreaPath(from, walkingArea, to, shape, fromDir, angleOverride);
328 186694 : into.insert(std::make_pair(std::make_pair(from, to), wap));
329 216733 : myMinNextLengths[walkingArea] = MIN2(myMinNextLengths[walkingArea], wap.length);
330 186694 : }
331 : }
332 : }
333 52284 : }
334 416814 : }
335 :
336 :
337 : const MSPModel_Striping::WalkingAreaPath*
338 8 : MSPModel_Striping::getArbitraryPath(const MSEdge* walkingArea) {
339 : assert(walkingArea->isWalkingArea());
340 : std::vector<const MSLane*> lanes;
341 24 : for (const MSEdge* const pred : walkingArea->getPredecessors()) {
342 16 : lanes.push_back(getSidewalk<MSEdge, MSLane>(pred));
343 : }
344 24 : for (const MSEdge* const succ : walkingArea->getSuccessors()) {
345 16 : lanes.push_back(getSidewalk<MSEdge, MSLane>(succ));
346 : }
347 8 : if (lanes.size() < 1) {
348 0 : throw ProcessError(TLF("Invalid walkingarea '%' does not allow continuation.", walkingArea->getID()));
349 : }
350 8 : return &myWalkingAreaPaths.find(std::make_pair(lanes.front(), lanes.back()))->second;
351 8 : }
352 :
353 : const MSPModel_Striping::WalkingAreaPath*
354 65 : MSPModel_Striping::guessPath(const MSEdge* walkingArea, const MSEdge* before, const MSEdge* after) {
355 : assert(walkingArea->isWalkingArea());
356 65 : const MSLane* swBefore = getSidewalk<MSEdge, MSLane>(before);
357 65 : const MSLane* swAfter = getSidewalk<MSEdge, MSLane>(after);
358 65 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(swBefore, swAfter));
359 65 : if (pathIt != myWalkingAreaPaths.end()) {
360 25 : return &pathIt->second;
361 : }
362 : const MSEdgeVector& preds = walkingArea->getPredecessors();
363 40 : const MSEdgeVector& succs = walkingArea->getSuccessors();
364 40 : bool useBefore = swBefore != nullptr && std::find(preds.begin(), preds.end(), before) != preds.end();
365 40 : bool useAfter = swAfter != nullptr && std::find(succs.begin(), succs.end(), after) != succs.end();
366 40 : if (useBefore) {
367 30 : if (useAfter) {
368 0 : return getWalkingAreaPath(walkingArea, swBefore, swAfter);
369 30 : } else if (succs.size() > 0) {
370 : // could also try to exploit direction
371 30 : return getWalkingAreaPath(walkingArea, swBefore, getSidewalk<MSEdge, MSLane>(succs.front()));
372 : }
373 10 : } else if (useAfter && preds.size() > 0) {
374 : // could also try to exploit direction
375 10 : return getWalkingAreaPath(walkingArea, getSidewalk<MSEdge, MSLane>(preds.front()), swAfter);
376 : }
377 0 : return getArbitraryPath(walkingArea);
378 : }
379 :
380 :
381 : const MSPModel_Striping::WalkingAreaPath*
382 914821 : MSPModel_Striping::getWalkingAreaPath(const MSEdge* walkingArea, const MSLane* before, const MSLane* after) {
383 : assert(walkingArea->isWalkingArea());
384 914821 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(before, after));
385 914821 : if (pathIt != myWalkingAreaPaths.end()) {
386 914778 : 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 43 : if (preds.size() > 0) {
391 43 : const MSEdge* const pred = walkingArea->getPredecessors().front();
392 43 : const auto pathIt2 = myWalkingAreaPaths.find(std::make_pair(getSidewalk<MSEdge, MSLane>(pred), after));
393 : assert(pathIt2 != myWalkingAreaPaths.end());
394 43 : return &pathIt2->second;
395 : } else {
396 0 : return getArbitraryPath(walkingArea);
397 : }
398 : }
399 : }
400 :
401 :
402 :
403 : MSPModel_Striping::NextLaneInfo
404 1520172 : MSPModel_Striping::getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane) {
405 : const MSEdge* currentEdge = ¤tLane->getEdge();
406 1520172 : const MSJunction* junction = ped.getDirection() == FORWARD ? currentEdge->getToJunction() : currentEdge->getFromJunction();
407 1520172 : const MSEdge* nextRouteEdge = ped.getStage()->getNextRouteEdge();
408 1520172 : const MSLane* nextRouteLane = getSidewalk<MSEdge, MSLane>(nextRouteEdge, ped.getPerson()->getVClass());
409 : // result values
410 : const MSLane* nextLane = nextRouteLane;
411 1520172 : const MSLink* link = nullptr;
412 1520172 : int nextDir = UNDEFINED_DIRECTION;
413 :
414 : //if DEBUGCOND(ped) {
415 : // std::cout << " nextRouteLane=" << Named::getIDSecure(nextRouteLane) << " junction=" << junction->getID() << "\n";
416 : //}
417 1520172 : 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 1520168 : if (nextRouteLane != nullptr) {
429 1297592 : if (currentEdge->isInternal()) {
430 : assert(junction == currentEdge->getFromJunction());
431 21831 : nextDir = junction == nextRouteEdge->getFromJunction() ? FORWARD : BACKWARD;
432 21831 : if (nextDir == FORWARD) {
433 20853 : nextLane = currentLane->getLinkCont()[0]->getViaLaneOrLane();
434 : } else {
435 978 : nextLane = currentLane->getLogicalPredecessorLane();
436 : }
437 21831 : if DEBUGCOND(ped) {
438 0 : std::cout << " internal\n";
439 : }
440 1275761 : } else if (currentEdge->isCrossing()) {
441 36088 : nextDir = ped.getDirection();
442 36088 : if (nextDir == FORWARD) {
443 19889 : nextLane = currentLane->getLinkCont()[0]->getLane();
444 : } else {
445 16199 : nextLane = currentLane->getLogicalPredecessorLane();
446 : }
447 36088 : if DEBUGCOND(ped) {
448 0 : std::cout << " crossing\n";
449 : }
450 36088 : unregisterCrossingApproach(ped, currentLane);
451 1239673 : } else if (currentEdge->isWalkingArea()) {
452 : ConstMSEdgeVector crossingRoute;
453 : // departPos can be 0 because the direction of the walkingArea does not matter
454 : // for the arrivalPos, we need to make sure that the route does not deviate across other junctions
455 878668 : const int nextRouteEdgeDir = nextRouteEdge->getFromJunction() == junction ? FORWARD : BACKWARD;
456 878668 : const double arrivalPos = (nextRouteEdge == ped.getStage()->getRoute().back()
457 878668 : ? ped.getStage()->getArrivalPos()
458 199508 : : (nextRouteEdgeDir == FORWARD ? 0 : nextRouteEdge->getLength()));
459 : std::map<const MSEdge*, double> prohibited;
460 878668 : if (prevLane != nullptr) {
461 878605 : prohibited[&prevLane->getEdge()] = -1;
462 : }
463 1757336 : MSNet::getInstance()->getPedestrianRouter(0, prohibited).compute(currentEdge, nextRouteEdge, 0, arrivalPos,
464 878668 : ped.getStage()->getMaxSpeed(ped.getPerson()),
465 878668 : 0, junction, ped.getPerson()->getVTypeParameter(), crossingRoute, true);
466 878668 : if DEBUGCOND(ped) {
467 : std::cout
468 : << " nre=" << nextRouteEdge->getID()
469 : << " nreDir=" << nextRouteEdgeDir
470 0 : << " aPos=" << arrivalPos
471 0 : << " crossingRoute=" << toString(crossingRoute)
472 0 : << "\n";
473 : }
474 878668 : if (crossingRoute.size() > 1) {
475 878631 : const MSEdge* nextEdge = crossingRoute[1];
476 878631 : nextLane = getSidewalk<MSEdge, MSLane>(crossingRoute[1], ped.getPerson()->getVClass());
477 : assert((nextEdge->getFromJunction() == junction || nextEdge->getToJunction() == junction));
478 : assert(nextLane != prevLane);
479 878631 : nextDir = connectedDirection(currentLane, nextLane);
480 878631 : if DEBUGCOND(ped) {
481 0 : std::cout << " nextDir=" << nextDir << "\n";
482 : }
483 : assert(nextDir != UNDEFINED_DIRECTION);
484 878631 : if (nextDir == FORWARD) {
485 636607 : link = currentLane->getLinkTo(nextLane);
486 : } else {
487 242024 : link = nextLane->getLinkTo(currentLane);
488 242024 : if (nextEdge->isCrossing() && link->getTLLogic() == nullptr) {
489 190667 : const MSLane* oppositeWalkingArea = nextLane->getLogicalPredecessorLane();
490 190667 : link = oppositeWalkingArea->getLinkTo(nextLane);
491 : }
492 : }
493 : assert(link != nullptr);
494 878631 : if (nextLane->isCrossing()) {
495 575759 : registerCrossingApproach(ped, nextLane, prevLane);
496 : }
497 : } else {
498 37 : if DEBUGCOND(ped) {
499 0 : std::cout << SIMTIME
500 0 : << " no route from '" << (currentEdge == nullptr ? "NULL" : currentEdge->getID())
501 0 : << "' to '" << (nextRouteEdge == nullptr ? "NULL" : nextRouteEdge->getID())
502 0 : << "\n";
503 : }
504 : // check if a direct connection exists (moving onto the walkingarea was the wrong choice)
505 37 : if (ped.getDirection() == FORWARD) {
506 24 : link = prevLane->getLinkTo(nextRouteLane);
507 : } else {
508 13 : link = nextRouteLane->getLinkTo(prevLane);
509 : }
510 37 : if (link != nullptr) {
511 : // leave direction as UNDEFINED_DIRECTION to signal that currentLane must be changed
512 : nextLane = link->getViaLaneOrLane();
513 : } else {
514 80 : WRITE_WARNING("Person '" + ped.getPerson()->getID() + "' could not find route across junction '" + junction->getID()
515 : + "' from walkingArea '" + currentEdge->getID()
516 : + "' to edge '" + nextRouteEdge->getID() + "', time=" +
517 : time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
518 : // error indicated by nextDir == UNDEFINED_DIRECTION
519 : nextLane = nextRouteLane;
520 : }
521 : }
522 1239673 : } else if (currentEdge == nextRouteEdge) {
523 : // strange loop in this route. No need to use walkingArea
524 8 : nextDir = -ped.getDirection();
525 : } else {
526 : // normal edge. by default use next / previous walking area
527 360997 : nextDir = ped.getDirection();
528 360997 : nextLane = getNextWalkingArea(currentLane, ped.getDirection(), link);
529 360997 : if (nextLane != nullptr) {
530 : // walking area found
531 322827 : if DEBUGCOND(ped) {
532 0 : std::cout << " next walkingArea " << (nextDir == FORWARD ? "forward" : "backward") << "\n";
533 : }
534 : } else {
535 : // walk forward by default
536 38170 : if (junction == nextRouteEdge->getToJunction()) {
537 4033 : nextDir = BACKWARD;
538 34137 : } else if (junction == nextRouteEdge->getFromJunction()) {
539 : nextDir = FORWARD;
540 : } else {
541 : // topological disconnect, find a direction that makes sense
542 : // for the future part of the route
543 212 : ConstMSEdgeVector futureRoute = ped.getStage()->getRoute();
544 212 : futureRoute.erase(futureRoute.begin(), futureRoute.begin() + ped.getStage()->getRoutePosition() + 1);
545 212 : int passedFwd = 0;
546 212 : int passedBwd = 0;
547 212 : canTraverse(FORWARD, futureRoute, passedFwd);
548 212 : canTraverse(BACKWARD, futureRoute, passedBwd);
549 212 : nextDir = (passedFwd >= passedBwd) ? FORWARD : BACKWARD;
550 212 : if DEBUGCOND(ped) {
551 0 : std::cout << " nextEdge=" << nextRouteEdge->getID() << " passedFwd=" << passedFwd << " passedBwd=" << passedBwd << " futureRoute=" << toString(futureRoute) << " nextDir=" << nextDir << "\n";
552 : }
553 212 : }
554 : // try to use a direct link as fallback
555 : // direct links only exist if built explicitly. They are used to model tl-controlled links if there are no crossings
556 38170 : if (ped.getDirection() == FORWARD) {
557 33612 : link = currentLane->getLinkTo(nextRouteLane);
558 33612 : if (link != nullptr) {
559 31937 : if DEBUGCOND(ped) {
560 0 : std::cout << " direct forward\n";
561 : }
562 31937 : nextLane = currentLane->getInternalFollowingLane(nextRouteLane);
563 : }
564 : } else {
565 4558 : link = nextRouteLane->getLinkTo(currentLane);
566 4558 : if (link != nullptr) {
567 3267 : if DEBUGCOND(ped) {
568 0 : std::cout << " direct backward\n";
569 : }
570 3267 : nextLane = nextRouteLane->getInternalFollowingLane(currentLane);
571 3267 : if (nextLane != nullptr) {
572 : // advance to the end of consecutive internal lanes
573 5485 : while (nextLane->getLinkCont()[0]->getViaLaneOrLane()->isInternal()) {
574 5 : nextLane = nextLane->getLinkCont()[0]->getViaLaneOrLane();
575 : }
576 : }
577 : }
578 : }
579 : }
580 360470 : if (nextLane == nullptr) {
581 : // no internal lane found
582 : nextLane = nextRouteLane;
583 8804 : if DEBUGCOND(ped) {
584 0 : std::cout << SIMTIME << " no next lane found for " << currentLane->getID() << " dir=" << ped.getDirection() << "\n";
585 : }
586 8804 : if (usingInternalLanesStatic() && currentLane->getLinkCont().size() > 0) {
587 0 : WRITE_WARNING("Person '" + ped.getPerson()->getID() + "' could not find route across junction '" + junction->getID()
588 : + "' from edge '" + currentEdge->getID()
589 : + "' to edge '" + nextRouteEdge->getID() + "', time=" +
590 : time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
591 : }
592 352193 : } else if (nextLane->getLength() <= POSITION_EPS) {
593 : // internal lane too short
594 : // most often this is due to a zero-size junction. However, if
595 : // the person needs to pass a crossing we cannot skip ahead
596 11073 : if ((nextLane->getCanonicalSuccessorLane() == nullptr
597 11065 : || !nextLane->getCanonicalSuccessorLane()->getEdge().isCrossing())
598 33199 : && (nextLane->getLogicalPredecessorLane() == nullptr ||
599 11061 : !nextLane->getLogicalPredecessorLane()->getEdge().isCrossing())) {
600 : //WRITE_WARNING("Person '" + ped.getID()
601 : // + "' skips short lane '" + nextLane->getID()
602 : // + "' length=" + toString(nextLane->getLength())
603 : // + " time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
604 : nextLane = nextRouteLane;
605 11073 : nextDir = nextRouteEdge->getFromJunction() == junction ? FORWARD : BACKWARD;
606 : }
607 : }
608 : }
609 : }
610 1520168 : if DEBUGCOND(ped) {
611 0 : std::cout << SIMTIME
612 : << " p=" << ped.getPerson()->getID()
613 : << " l=" << currentLane->getID()
614 0 : << " nl=" << (nextLane == nullptr ? "NULL" : nextLane->getID())
615 0 : << " nrl=" << (nextRouteLane == nullptr ? "NULL" : nextRouteLane->getID())
616 : << " d=" << nextDir
617 0 : << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
618 0 : << " pedDir=" << ped.getDirection()
619 0 : << "\n";
620 : }
621 : assert(nextLane != 0 || nextRouteLane == 0);
622 1520168 : return NextLaneInfo(nextLane, link, nextDir);
623 : }
624 :
625 :
626 : const MSLane*
627 360997 : MSPModel_Striping::getNextWalkingArea(const MSLane* currentLane, const int dir, const MSLink*& link) {
628 360997 : if (dir == FORWARD) {
629 360555 : for (const MSLink* const l : currentLane->getLinkCont()) {
630 326943 : if (l->getLane()->getEdge().isWalkingArea()) {
631 267063 : link = l;
632 : return l->getLane();
633 : }
634 : }
635 : } else {
636 : const std::vector<MSLane::IncomingLaneInfo>& laneInfos = currentLane->getIncomingLanes();
637 67028 : for (std::vector<MSLane::IncomingLaneInfo>::const_iterator it = laneInfos.begin(); it != laneInfos.end(); ++it) {
638 62470 : if ((*it).lane->getEdge().isWalkingArea()) {
639 55764 : link = (*it).viaLink;
640 : return (*it).lane;
641 : }
642 : }
643 : }
644 : return nullptr;
645 : }
646 :
647 :
648 : MSPModel_Striping::Obstacles
649 65696538 : MSPModel_Striping::getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes) {
650 65696538 : const PState& ego = *static_cast<PState*>(pedestrians[egoIndex]);
651 65696538 : const int egoStripe = ego.stripe();
652 65696538 : Obstacles obs(stripes, Obstacle(ego.getDirection()));
653 65696538 : std::vector<bool> haveBlocker(stripes, false);
654 9968183143 : for (int index = egoIndex + 1; index < (int)pedestrians.size(); index++) {
655 9954619793 : const PState& p = *static_cast<PState*>(pedestrians[index]);
656 9954619793 : if DEBUGCOND(ego) {
657 0 : std::cout << SIMTIME << " ped=" << ego.getID() << " cur=" << egoStripe << " checking neighbor " << p.getID()
658 0 : << " nCur=" << p.stripe() << " nOth=" << p.otherStripe();
659 : }
660 9954619793 : if (!p.isWaitingToEnter() && !p.isJammed()) {
661 132532950 : const Obstacle o(p);
662 132532950 : if DEBUGCOND(ego) {
663 0 : std::cout << " dist=" << ego.distanceTo(o) << std::endl;
664 : }
665 132532950 : if (ego.distanceTo(o) == DIST_BEHIND) {
666 : break;
667 : }
668 80399762 : if (ego.distanceTo(o) == DIST_OVERLAP) {
669 80399762 : if (p.stripe() != egoStripe || p.getDirection() != ego.getDirection()) {
670 59814418 : obs[p.stripe()] = o;
671 59814418 : haveBlocker[p.stripe()] = true;
672 : } else {
673 : //std::cout << SIMTIME << " ignoring overlap between " << ego.getID() << " and " << p.getID() << " on stripe=" << egoStripe << "\n";
674 : }
675 80399762 : if (p.otherStripe() != egoStripe || p.getDirection() != ego.getDirection()) {
676 59814418 : obs[p.otherStripe()] = o;
677 59814418 : haveBlocker[p.otherStripe()] = true;
678 : } else {
679 : //std::cout << SIMTIME << " ignoring overlap between " << ego.getID() << " and " << p.getID() << " on stripe2=" << egoStripe << "\n";
680 : }
681 : } else {
682 0 : if (!haveBlocker[p.stripe()]) {
683 0 : obs[p.stripe()] = o;
684 : }
685 0 : if (!haveBlocker[p.otherStripe()]) {
686 0 : obs[p.otherStripe()] = o;
687 : }
688 : }
689 : }
690 : }
691 65696538 : if DEBUGCOND(ego) {
692 0 : std::cout << SIMTIME << " ped=" << ego.getPerson()->getID() << " neighObs=";
693 0 : DEBUG_PRINT(obs);
694 : }
695 65696538 : return obs;
696 0 : }
697 :
698 :
699 : int
700 3148224 : MSPModel_Striping::getStripeOffset(int origStripes, int destStripes, bool addRemainder) {
701 3148224 : int offset = (destStripes - origStripes) / 2;
702 3148224 : if (addRemainder) {
703 13195 : offset += (destStripes - origStripes) % 2;
704 : }
705 3148224 : return offset;
706 : }
707 :
708 :
709 : const MSPModel_Striping::Obstacles&
710 16717124 : MSPModel_Striping::getNextLaneObstacles(NextLanesObstacles& nextLanesObs, const
711 : MSLane* lane, const MSLane* nextLane, int stripes, int nextDir,
712 : double currentLength, int currentDir) {
713 : if (nextLanesObs.count(nextLane) == 0) {
714 2410964 : const double nextLength = nextLane->getEdge().isWalkingArea() ? myMinNextLengths[nextLane] : nextLane->getLength();
715 : // figure out the which pedestrians are ahead on the next lane
716 2410964 : const int nextStripes = numStripes(nextLane);
717 : // do not move past the end of the next lane in a single step
718 4821928 : Obstacles obs(stripes, Obstacle(nextDir == FORWARD ? nextLength : 0, 0, OBSTACLE_NEXTEND, "nextEnd", 0));
719 :
720 2410964 : const int offset = getStripeOffset(nextStripes, stripes, currentDir != nextDir && nextStripes > stripes);
721 : //std::cout << SIMTIME << " getNextLaneObstacles"
722 : // << " nextLane=" << nextLane->getID()
723 : // << " nextLength=" << nextLength
724 : // << " nextDir=" << nextDir
725 : // << " currentLength=" << currentLength
726 : // << " currentDir=" << currentDir
727 : // << " stripes=" << stripes
728 : // << " nextStripes=" << nextStripes
729 : // << " offset=" << offset
730 : // << "\n";
731 2410964 : if (nextStripes < stripes) {
732 : // some stripes do not continue
733 2097010 : for (int ii = 0; ii < stripes; ++ii) {
734 1809632 : if (ii < offset || ii >= nextStripes + offset) {
735 2490414 : obs[ii] = Obstacle(nextDir == FORWARD ? 0 : nextLength, 0, OBSTACLE_END, "stripeEnd", 0);
736 : }
737 : }
738 : }
739 2410964 : Pedestrians& pedestrians = getPedestrians(nextLane);
740 2410964 : if (nextLane->getEdge().isWalkingArea()) {
741 1233526 : transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
742 : // complex transformation into the coordinate system of the current lane
743 : // (pedestrians on next lane may walk at arbitrary angles relative to the current lane)
744 1233526 : double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
745 1233526 : if ((stripes - nextStripes) % 2 != 0) {
746 480409 : lateral_offset += 0.5 * stripeWidth;
747 : }
748 : nextDir = currentDir;
749 : // transform pedestrians into the current coordinate system
750 8220585 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
751 6987059 : const PState& p = *static_cast<PState*>(pedestrians[ii]);
752 6987059 : if (p.isWaitingToEnter() || p.isJammed()) {
753 2149763 : continue;
754 : }
755 4837296 : Position pPos = p.getPosition(*p.getStage(), -1);
756 4837296 : Position relPos = lane->getShape().transformToVectorCoordinates(pPos, true);
757 : if (relPos == Position::INVALID) {
758 0 : WRITE_WARNINGF("Could not map position % onto lane '%'", pPos, lane->getID());
759 : }
760 4837296 : const double newY = relPos.y() + lateral_offset;
761 : //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";
762 4837296 : if ((currentDir == FORWARD && relPos.x() >= lane->getLength()) || (currentDir == BACKWARD && relPos.x() < 0)) {
763 4835921 : addCloserObstacle(obs, relPos.x(), p.stripe(newY), stripes, p.getPerson()->getID(), p.getPerson()->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
764 4835921 : addCloserObstacle(obs, relPos.x(), p.otherStripe(newY), stripes, p.getPerson()->getID(), p.getPerson()->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
765 : }
766 : }
767 : } else {
768 : // simple transformation into the coordinate system of the current lane
769 : // (only need to worry about currentDir and nextDir)
770 : // XXX consider waitingToEnter on nextLane
771 1177438 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(nextDir));
772 33082270 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
773 31904832 : const PState& p = *static_cast<PState*>(pedestrians[ii]);
774 31904832 : if (p.isWaitingToEnter() || p.isJammed()) {
775 21018778 : continue;
776 : }
777 : double newY = p.getPosLat();
778 10886054 : Obstacle pObs(p);
779 10886054 : if (nextDir != currentDir) {
780 289123 : newY = (nextStripes - 1) * stripeWidth - newY;
781 289123 : pObs.speed *= -1;
782 : }
783 10886054 : newY += offset * stripeWidth;
784 10886054 : const int stripe = p.stripe(newY);
785 10886054 : if (stripe >= 0 && stripe < stripes) {
786 10886051 : obs[stripe] = pObs;
787 : }
788 10886054 : const int otherStripe = p.otherStripe(newY);
789 10886054 : if (otherStripe >= 0 && otherStripe < stripes) {
790 10886051 : obs[otherStripe] = pObs;
791 : }
792 : }
793 1177438 : if (nextLane->getEdge().isCrossing()) {
794 : // add vehicle obstacles
795 373390 : const MSLink* crossingEntryLink = nextLane->getIncomingLanes().front().viaLink;
796 373390 : const bool prio = crossingEntryLink->havePriority() || crossingEntryLink->getTLLogic() != nullptr;
797 373390 : addCrossingVehs(nextLane, stripes, offset, nextDir, obs, prio);
798 : }
799 1177438 : if (nextLane->getVehicleNumberWithPartials() > 0) {
800 18622 : Obstacles vehObs = getVehicleObstacles(nextLane, nextDir);
801 18622 : PState::mergeObstacles(obs, vehObs, nextDir, offset);
802 18622 : }
803 1177438 : transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
804 : }
805 2410964 : nextLanesObs[nextLane] = obs;
806 2410964 : }
807 16717124 : return nextLanesObs[nextLane];
808 : }
809 :
810 : void
811 2410964 : MSPModel_Striping::transformToCurrentLanePositions(Obstacles& obs, int currentDir, int nextDir, double currentLength, double nextLength) {
812 13746856 : for (Obstacle& o : obs) {
813 11335892 : if (currentDir == FORWARD) {
814 7673353 : if (nextDir == FORWARD) {
815 7329241 : o.xFwd += currentLength;
816 7329241 : o.xBack += currentLength;
817 : } else {
818 344112 : const double tmp = o.xFwd;
819 344112 : o.xFwd = currentLength + nextLength - o.xBack;
820 344112 : o.xBack = currentLength + nextLength - tmp;
821 : }
822 : } else {
823 3662539 : if (nextDir == FORWARD) {
824 845734 : const double tmp = o.xFwd;
825 845734 : o.xFwd = -o.xBack;
826 845734 : o.xBack = -tmp;
827 : } else {
828 2816805 : o.xFwd -= nextLength;
829 2816805 : o.xBack -= nextLength;
830 : }
831 : }
832 : }
833 2410964 : }
834 :
835 :
836 : void
837 9671842 : MSPModel_Striping::addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type) {
838 9671842 : if (stripe >= 0 && stripe < numStripes) {
839 2277315 : if ((dir == FORWARD && x - width / 2. < obs[stripe].xBack) || (dir == BACKWARD && x + width / 2. > obs[stripe].xFwd)) {
840 1982136 : obs[stripe] = Obstacle(x, 0, type, id, width);
841 : }
842 : }
843 9671842 : }
844 :
845 : void
846 18625906 : MSPModel_Striping::moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
847 145144308 : for (ActiveLanes::iterator it_lane = myActiveLanes.begin(); it_lane != myActiveLanes.end(); ++it_lane) {
848 126518406 : const MSLane* lane = it_lane->first;
849 126518406 : Pedestrians& pedestrians = it_lane->second;
850 126518406 : if (pedestrians.size() == 0) {
851 117063648 : continue;
852 : }
853 : //std::cout << SIMTIME << ">>> lane=" << lane->getID() << " numPeds=" << pedestrians.size() << "\n";
854 9454758 : if (lane->getEdge().isWalkingArea()) {
855 2175307 : const double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
856 2175307 : const double minY = stripeWidth * - 0.5 + NUMERICAL_EPS;
857 2175307 : const double maxY = stripeWidth * (numStripes(lane) - 0.5) - NUMERICAL_EPS;
858 : const WalkingAreaPath* debugPath = nullptr;
859 : // need to handle each walkingAreaPath separately and transform
860 : // coordinates beforehand
861 : std::set<const WalkingAreaPath*, walkingarea_path_sorter> paths;
862 17583599 : for (Pedestrians::iterator it = pedestrians.begin(); it != pedestrians.end(); ++it) {
863 15408292 : const PState* p = static_cast<PState*>(*it);
864 : assert(p->myWalkingAreaPath != 0);
865 15408292 : if (p->getDirection() == dir) {
866 7720898 : paths.insert(p->myWalkingAreaPath);
867 7720898 : if DEBUGCOND(*p) {
868 0 : debugPath = p->myWalkingAreaPath;
869 0 : std::cout << SIMTIME << " debugging WalkingAreaPath from=" << debugPath->from->getID() << " to=" << debugPath->to->getID() << " minY=" << minY << " maxY=" << maxY << " latOffset=" << lateral_offset << "\n";
870 : }
871 : }
872 : }
873 2175307 : const double usableWidth = (numStripes(lane) - 1) * stripeWidth;
874 3342856 : for (std::set<const WalkingAreaPath*, walkingarea_path_sorter>::iterator it = paths.begin(); it != paths.end(); ++it) {
875 1167549 : const WalkingAreaPath* path = *it;
876 : Pedestrians toDelete;
877 : Pedestrians transformedPeds;
878 1167549 : transformedPeds.reserve(pedestrians.size());
879 9833729 : for (Pedestrians::iterator it_p = pedestrians.begin(); it_p != pedestrians.end(); ++it_p) {
880 8666180 : PState* p = static_cast<PState*>(*it_p);
881 8666180 : if (p->myWalkingAreaPath == path) {
882 7720898 : transformedPeds.push_back(p);
883 7720898 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (untransformed), vecCoord="
884 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
885 945282 : } else if (p->myWalkingAreaPath->from == path->to && p->myWalkingAreaPath->to == path->from) {
886 42973 : if (p->myWalkingAreaPath->dir != path->dir) {
887 : // opposite direction is already in the correct coordinate system
888 39548 : transformedPeds.push_back(p);
889 39548 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (untransformed), vecCoord="
890 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
891 : } else {
892 : // x position must be reversed
893 3425 : PState* tp = new PState(*p);
894 3425 : tp->reverse(path->length, usableWidth);
895 3425 : toDelete.push_back(tp);
896 3425 : transformedPeds.push_back(tp);
897 3425 : if (path == debugPath) std::cout << " ped=" << p->getPerson()->getID() << " relX=" << p->getEdgePos(0) << " relY=" << p->getPosLat() << " (semi-transformed), vecCoord="
898 0 : << path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1)) << "\n";
899 : }
900 : } else {
901 902309 : const Position relPos = path->shape.transformToVectorCoordinates(p->getPosition(*p->getStage(), -1));
902 902309 : const double newY = relPos.y() + lateral_offset;
903 901627 : if (relPos != Position::INVALID && newY >= minY && newY <= maxY) {
904 243636 : PState* tp = new PState(*p);
905 243636 : tp->reset(relPos.x(), newY);
906 243636 : toDelete.push_back(tp);
907 243636 : transformedPeds.push_back(tp);
908 243636 : if (path == debugPath) {
909 0 : std::cout << " ped=" << p->getPerson()->getID() << " relX=" << relPos.x() << " relY=" << newY << " (transformed), vecCoord=" << relPos << "\n";
910 : }
911 : } else {
912 658673 : if (path == debugPath) {
913 0 : std::cout << " ped=" << p->getPerson()->getID() << " relX=" << relPos.x() << " relY=" << newY << " (invalid), vecCoord=" << relPos << "\n";
914 : }
915 : }
916 : }
917 : }
918 : auto itFoe = myWalkingAreaFoes.find(&lane->getEdge());
919 1167549 : if (itFoe != myWalkingAreaFoes.end()) {
920 : // add vehicle foes on paths which cross this walkingarea
921 : // translate the vehicle into a number of dummy-pedestrians
922 : // that occupy the same space
923 2261480 : for (const MSLane* foeLane : itFoe->second) {
924 180937 : for (auto itVeh = foeLane->anyVehiclesBegin(); itVeh != foeLane->anyVehiclesEnd(); ++itVeh) {
925 180937 : const MSVehicle* veh = *itVeh;
926 180937 : const double vehWidth = veh->getVehicleType().getWidth();
927 180937 : Boundary relCorners;
928 180937 : Position relFront = path->shape.transformToVectorCoordinates(veh->getPosition(), true);
929 180937 : Position relBack = path->shape.transformToVectorCoordinates(veh->getBackPosition(), true);
930 : if (relFront == Position::INVALID) {
931 0 : WRITE_WARNINGF("Could not vehicle '%' front position % onto walkingarea '%' path=%, time=%.",
932 : veh->getID(), veh->getPosition(), lane->getID(), path->shape, time2string(SIMSTEP));
933 : }
934 : if (relBack == Position::INVALID) {
935 0 : WRITE_WARNINGF("Could not vehicle '%' back position % onto walkingarea '%' path=%, time=%.",
936 : veh->getID(), veh->getBackPosition(), lane->getID(), path->shape, time2string(SIMSTEP));
937 : }
938 180937 : PositionVector relCenter;
939 180937 : relCenter.push_back(relFront);
940 180937 : relCenter.push_back(relBack);
941 180937 : relCenter.move2side(vehWidth / 2);
942 180937 : relCorners.add(relCenter[0]);
943 180937 : relCorners.add(relCenter[1]);
944 180937 : relCenter.move2side(-vehWidth);
945 180937 : relCorners.add(relCenter[0]);
946 180937 : relCorners.add(relCenter[1]);
947 : // persons should require less gap than the vehicles to prevent getting stuck
948 : // when a vehicles moves towards them
949 180937 : relCorners.growWidth(SAFETY_GAP / 2);
950 180937 : const double xWidth = relCorners.getWidth();
951 180937 : const double vehYmin = MAX2(minY - lateral_offset, relCorners.ymin());
952 180937 : const double vehYmax = MIN2(maxY - lateral_offset, relCorners.ymax());
953 180937 : const double xCenter = relCorners.getCenter().x();
954 : Position yMinPos(xCenter, vehYmin);
955 : Position yMaxPos(xCenter, vehYmax);
956 180937 : const bool addFront = addVehicleFoe(veh, lane, yMinPos, dir * xWidth, 0, lateral_offset, minY, maxY, toDelete, transformedPeds);
957 180937 : const bool addBack = addVehicleFoe(veh, lane, yMaxPos, dir * xWidth, 0, lateral_offset, minY, maxY, toDelete, transformedPeds);
958 180937 : if (path == debugPath) {
959 : std::cout << " veh=" << veh->getID()
960 0 : << " corners=" << relCorners
961 : << " xWidth=" << xWidth
962 0 : << " ymin=" << relCorners.ymin()
963 0 : << " ymax=" << relCorners.ymax()
964 : << " vehYmin=" << vehYmin
965 : << " vehYmax=" << vehYmax
966 0 : << "\n";
967 : }
968 180937 : if (addFront && addBack) {
969 : // add in-between positions
970 180937 : const double yDist = vehYmax - vehYmin;
971 413586 : for (double dist = stripeWidth; dist < yDist; dist += stripeWidth) {
972 232649 : const double relDist = dist / yDist;
973 232649 : Position between = (yMinPos * relDist) + (yMaxPos * (1 - relDist));
974 232649 : if (path == debugPath) {
975 0 : std::cout << " vehBetween=" << veh->getID() << " pos=" << between << "\n";
976 : }
977 232649 : addVehicleFoe(veh, lane, between, dir * xWidth, stripeWidth, lateral_offset, minY, maxY, toDelete, transformedPeds);
978 : }
979 : }
980 180937 : }
981 : }
982 : }
983 1167549 : moveInDirectionOnLane(transformedPeds, lane, currentTime, changedLane, dir, path == debugPath);
984 1167549 : arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
985 : // clean up
986 1910008 : for (Pedestrians::iterator it_p = toDelete.begin(); it_p != toDelete.end(); ++it_p) {
987 742459 : delete *it_p;
988 : }
989 1167549 : }
990 : } else {
991 7279451 : moveInDirectionOnLane(pedestrians, lane, currentTime, changedLane, dir, false);
992 7279451 : arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
993 : }
994 : }
995 18625902 : }
996 :
997 :
998 : bool
999 594523 : MSPModel_Striping::addVehicleFoe(const MSVehicle* veh, const MSLane* walkingarea, const Position& relPos, double xWidth, double yWidth, double lateral_offset,
1000 : double minY, double maxY, Pedestrians& toDelete, Pedestrians& transformedPeds) {
1001 : if (relPos != Position::INVALID) {
1002 594523 : const double newY = relPos.y() + lateral_offset;
1003 594523 : if (newY >= minY && newY <= maxY) {
1004 495398 : PState* tp = new PStateVehicle(veh, walkingarea, relPos.x(), newY, xWidth, yWidth);
1005 : //std::cout << SIMTIME << " addVehicleFoe=" << veh->getID() << " rx=" << relPos.x() << " ry=" << newY << " s=" << tp->stripe() << " o=" << tp->otherStripe() << "\n";
1006 495398 : toDelete.push_back(tp);
1007 495398 : transformedPeds.push_back(tp);
1008 : }
1009 594523 : return true;
1010 : } else {
1011 : return false;
1012 : }
1013 : }
1014 :
1015 : void
1016 8447000 : MSPModel_Striping::arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
1017 : // advance to the next lane / arrive at destination
1018 8447000 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
1019 : // can't use iterators because we do concurrent modification
1020 133290518 : for (int i = 0; i < (int)pedestrians.size(); i++) {
1021 124843522 : PState* const p = static_cast<PState*>(pedestrians[i]);
1022 124843522 : if (p->isRemoteControlled()) {
1023 27878 : continue;
1024 : }
1025 124815644 : if (p->getDirection() == dir && p->distToLaneEnd() < 0) {
1026 : // moveToNextLane may trigger re-insertion (for consecutive
1027 : // walks) so erase must be called first
1028 : pedestrians.erase(pedestrians.begin() + i);
1029 957498 : i--;
1030 957498 : p->moveToNextLane(currentTime);
1031 957494 : if (p->getLane() != nullptr) {
1032 737260 : changedLane.insert(p->getPerson());
1033 737260 : myActiveLanes[p->getLane()].push_back(p);
1034 : } else {
1035 : // end walking stage and destroy PState
1036 220234 : p->getStage()->moveToNextEdge(p->getPerson(), currentTime, dir);
1037 220234 : myNumActivePedestrians--;
1038 : }
1039 : }
1040 : }
1041 8446996 : }
1042 :
1043 :
1044 : void
1045 8447000 : MSPModel_Striping::moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir, bool debug) {
1046 8447000 : const int stripes = numStripes(lane);
1047 : //std::cout << " laneWidth=" << lane->getWidth() << " stripeWidth=" << stripeWidth << " stripes=" << stripes << "\n";
1048 16894000 : Obstacles obs(stripes, Obstacle(dir)); // continuously updated
1049 : NextLanesObstacles nextLanesObs; // continuously updated
1050 8447000 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
1051 :
1052 16894000 : Obstacles crossingVehs(stripes, Obstacle(dir));
1053 : bool hasCrossingVehObs = false;
1054 8447000 : if (lane->getEdge().isCrossing()) {
1055 : // assume that vehicles will brake when already on the crossing
1056 636634 : hasCrossingVehObs = addCrossingVehs(lane, stripes, 0, dir, crossingVehs, true);
1057 : }
1058 :
1059 133125971 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
1060 124678971 : PState& p = *static_cast<PState*>(pedestrians[ii]);
1061 : UNUSED_PARAMETER(debug);
1062 : //if (debug) {
1063 : // std::cout << SIMTIME << " CHECKING d=" << dir << " p=" << p.getID() << " relX=" << p.myRelX << " xmin=" << p.getMinX() << " xmax=" << p.getMaxX() << " pdir=" << p.getDirection() << "\n";
1064 : //}
1065 124678971 : Obstacles currentObs = obs;
1066 124678971 : if (p.getDirection() != dir || changedLane.count(p.getPerson()) != 0 || p.getRemotePosition() != Position::INVALID) {
1067 58982433 : if (!p.isWaitingToEnter() && !p.isJammed()) {
1068 : //if DEBUGCOND(p) {
1069 : // std::cout << " obs=" << p.getPerson()->getID() << " y=" << p.getPosLat() << " stripe=" << p.stripe() << " oStripe=" << p.otherStripe() << "\n";
1070 : //}
1071 29782055 : Obstacle o(p);
1072 29782055 : if (p.getDirection() != dir && p.getSpeed(*p.getStage()) == 0.) {
1073 : // ensure recognition of oncoming
1074 7503737 : o.speed = (p.getDirection() == FORWARD ? 0.1 : -0.1);
1075 : }
1076 29782055 : if (o.closer(obs[p.stripe()], dir)) {
1077 29777832 : obs[p.stripe()] = o;
1078 : }
1079 29782055 : if (o.closer(obs[p.otherStripe()], dir)) {
1080 29777671 : obs[p.otherStripe()] = o;
1081 : }
1082 : }
1083 : continue;
1084 58982433 : }
1085 65696538 : if DEBUGCOND(p) {
1086 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " currentObs=";
1087 0 : gDebugFlag1 = true;
1088 0 : DEBUG_PRINT(currentObs);
1089 : }
1090 65696538 : const MSLane* nextLane = p.myNLI.lane;
1091 65696538 : const MSLink* link = p.myNLI.link;
1092 65696538 : const double dist = p.distToLaneEnd();
1093 : const double speed(p.getStage()->getConfiguredSpeed() >= 0
1094 65696538 : ? p.getStage()->getConfiguredSpeed()
1095 53934562 : : ((nextLane != nullptr && (USE_NET_SPEEDS || nextLane->isNormal() || nextLane->isInternal()))
1096 118223476 : ? nextLane->getVehicleMaxSpeed(p.getPerson())
1097 13059474 : : p.getStage()->getMaxSpeed(p.getPerson())));
1098 :
1099 :
1100 65696538 : if (nextLane != nullptr && dist <= LOOKAHEAD_ONCOMING_DIST) {
1101 16717124 : const double currentLength = (p.myWalkingAreaPath == nullptr ? lane->getLength() : p.myWalkingAreaPath->length);
1102 16717124 : const Obstacles& nextObs = getNextLaneObstacles(
1103 : nextLanesObs, lane, nextLane, stripes,
1104 : p.myNLI.dir, currentLength, dir);
1105 :
1106 16717124 : if DEBUGCOND(p) {
1107 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " nextObs=";
1108 0 : DEBUG_PRINT(nextObs);
1109 : }
1110 16717124 : p.mergeObstacles(currentObs, nextObs);
1111 : }
1112 65696538 : if DEBUGCOND(p) {
1113 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithNext=";
1114 0 : DEBUG_PRINT(currentObs);
1115 : }
1116 65696538 : p.mergeObstacles(currentObs, getNeighboringObstacles(pedestrians, ii, stripes));
1117 65696538 : if DEBUGCOND(p) {
1118 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithNeigh=";
1119 0 : DEBUG_PRINT(currentObs);
1120 : }
1121 : // time gap to pass the intersection ahead of a vehicle.
1122 65696538 : const double passingLength = p.getLength() + p.getPerson()->getTimegapCrossing() * speed;
1123 : // check link state
1124 65696538 : if DEBUGCOND(p) {
1125 0 : gDebugFlag1 = true; // get debug output from MSLink
1126 0 : std::cout << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
1127 0 : << " dist=" << dist << " d2=" << dist - p.getMinGap() << " la=" << LOOKAHEAD_SAMEDIR* speed << "\n";
1128 : }
1129 : if (link != nullptr
1130 : // only check close before junction, @todo we should take deceleration into account here
1131 53036647 : && dist - p.getMinGap() < LOOKAHEAD_SAMEDIR * speed
1132 : // persons move before vehicles so we subtract DELTA_TO because they cannot rely on vehicles having passed the intersection in the current time step
1133 76954604 : && (!link->opened(currentTime - DELTA_T, speed, speed, passingLength, p.getImpatience(), speed, 0, 0, nullptr, p.ignoreRed(link), p.getPerson())
1134 10564135 : || p.stopForYellow(link))) {
1135 : // prevent movement passed a closed link
1136 694713 : Obstacles closedLink(stripes, Obstacle(p.getEdgePos(0) + dir * (dist - NUMERICAL_EPS), 0, OBSTACLE_LINKCLOSED, "closedLink_" + link->getViaLaneOrLane()->getID(), 0));
1137 694713 : p.mergeObstacles(currentObs, closedLink);
1138 694713 : if DEBUGCOND(p) {
1139 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithTLS=";
1140 0 : DEBUG_PRINT(currentObs);
1141 : }
1142 : // consider rerouting over another crossing
1143 694713 : if (p.myWalkingAreaPath != nullptr) {
1144 : // @todo actually another path would be needed starting at the current position
1145 539546 : const MSLane* oldNext = p.myNLI.lane;
1146 539546 : p.myNLI = getNextLane(p, p.getLane(), p.myWalkingAreaPath->from);
1147 539546 : if (p.myNLI.lane != oldNext) {
1148 154 : unregisterCrossingApproach(p, oldNext);
1149 : }
1150 : }
1151 694713 : }
1152 65696538 : if DEBUGCOND(p) {
1153 0 : gDebugFlag1 = false;
1154 : }
1155 65696538 : if (&lane->getEdge() == p.getStage()->getDestination() && p.getStage()->getDestinationStop() != nullptr) {
1156 : Obstacles arrival;
1157 1345288 : if (p.getStage()->getDestinationStop()->getWaitingCapacity() > p.getStage()->getDestinationStop()->getNumWaitingPersons() ||
1158 : (!p.getStage()->getDestinationStop()->checkPersonCapacity())) {
1159 2487194 : arrival = Obstacles(stripes, Obstacle(p.getStage()->getArrivalPos() + dir * p.getMinGap(), 0, OBSTACLE_ARRIVALPOS, "arrival", 0));
1160 : } else {
1161 203382 : arrival = Obstacles(stripes, Obstacle(p.getStage()->getArrivalPos() - dir * p.getMinGap(), 0, OBSTACLE_ARRIVALPOS, "arrival_blocked", 0));
1162 : }
1163 1345288 : p.mergeObstacles(currentObs, arrival);
1164 1345288 : }
1165 :
1166 65696538 : if (lane->getVehicleNumberWithPartials() > 0) {
1167 : // react to vehicles on the same lane
1168 : // @todo: improve efficiency by using the same iterator for all pedestrians on this lane
1169 270919 : Obstacles vehObs = getVehicleObstacles(lane, dir, &p);
1170 270919 : p.mergeObstacles(currentObs, vehObs);
1171 270919 : if DEBUGCOND(p) {
1172 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithVehs=";
1173 0 : DEBUG_PRINT(currentObs);
1174 : }
1175 270919 : }
1176 65696538 : if (hasCrossingVehObs) {
1177 23875 : p.mergeObstacles(currentObs, crossingVehs);
1178 23875 : if DEBUGCOND(p) {
1179 0 : std::cout << SIMTIME << " ped=" << p.getPerson()->getID() << " obsWithVehs2=";
1180 0 : DEBUG_PRINT(currentObs);
1181 : }
1182 : }
1183 :
1184 : // walk, taking into account all obstacles
1185 65696538 : p.walk(currentObs);
1186 65696538 : gDebugFlag1 = false;
1187 65696538 : if (!p.isWaitingToEnter() && !p.isJammed()) {
1188 34375856 : Obstacle o(p);
1189 34375856 : if (o.closer(obs[p.stripe()], dir)) {
1190 34374322 : obs[p.stripe()] = o;
1191 : }
1192 34375856 : if (o.closer(obs[p.otherStripe()], dir)) {
1193 34374317 : obs[p.otherStripe()] = o;
1194 : }
1195 34375856 : if (MSGlobals::gCheck4Accidents && p.myWalkingAreaPath == nullptr && !p.isJammed()) {
1196 2553107496 : for (int coll = 0; coll < ii; ++coll) {
1197 2524252805 : PState& c = *static_cast<PState*>(pedestrians[coll]);
1198 2524252805 : if (!c.isWaitingToEnter() && c.myWalkingAreaPath == nullptr && !c.isJammed()) {
1199 1148477443 : if (c.stripe() == p.stripe() || p.stripe() == c.otherStripe() || p.otherStripe() == c.stripe() || p.otherStripe() == c.otherStripe()) {
1200 441870846 : Obstacle cObs(c);
1201 : // we check only for real collisions, no min gap violations
1202 441870846 : if (p.distanceTo(cObs, false) == DIST_OVERLAP) {
1203 1024504 : WRITE_WARNING("Collision of person '" + p.getPerson()->getID() + "' and person '" + c.getPerson()->getID()
1204 : + "', lane='" + lane->getID() + "', time=" + time2string(currentTime) + ".");
1205 : }
1206 : }
1207 : }
1208 : }
1209 : }
1210 : }
1211 : //std::cout << SIMTIME << p.getPerson()->getID() << " lane=" << lane->getID() << " x=" << p.myRelX << "\n";
1212 124678971 : }
1213 16894000 : }
1214 :
1215 :
1216 : void
1217 575759 : MSPModel_Striping::registerCrossingApproach(const PState& ped, const MSLane* crossing, const MSLane* beforeWA) {
1218 : // person has entered the walkingarea
1219 575759 : SUMOTime arrivalTime = SIMSTEP;
1220 : assert(ped.getLane()->isWalkingArea());
1221 575759 : const WalkingAreaPath* wa = getWalkingAreaPath(&ped.getLane()->getEdge(), beforeWA, crossing);
1222 575759 : const double speed = ped.getStage()->getMaxSpeed(ped.getPerson()) * (1 - dawdling / 2);
1223 575759 : arrivalTime += TIME2STEPS(wa->length / speed);
1224 575759 : SUMOTime leavingTime = arrivalTime + TIME2STEPS(crossing->getLength() / speed);
1225 575759 : crossing->getIncomingLanes()[0].viaLink->setApproachingPerson(ped.getPerson(), arrivalTime, leavingTime);
1226 575759 : if DEBUGCOND(ped) {
1227 0 : std::cout << SIMTIME << " register " << ped.getPerson()->getID() << " at crossing " << crossing->getID() << "\n";
1228 : }
1229 575759 : }
1230 :
1231 :
1232 : bool
1233 1010024 : MSPModel_Striping::addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& obs, bool prio) {
1234 : bool hasCrossingVehObs = false;
1235 1010024 : const MSLink* crossingExitLink = crossing->getLinkCont().front();
1236 1010024 : gDebugFlag1 = DEBUGCOND2(crossing);
1237 1010024 : const MSLink::LinkLeaders linkLeaders = crossingExitLink->getLeaderInfo(nullptr, crossing->getLength());
1238 1010024 : gDebugFlag1 = false;
1239 1010024 : if (linkLeaders.size() > 0) {
1240 211598 : for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
1241 : // the vehicle to enter the junction first has priority
1242 107400 : const MSVehicle* veh = (*it).vehAndGap.first;
1243 107400 : if (veh != nullptr) {
1244 107400 : Obstacle vo((*it).distToCrossing, 0, OBSTACLE_VEHICLE, veh->getID(), veh->getVehicleType().getWidth() + 2 * minGapToVehicle, veh);
1245 : // block entry to the crossing in walking direction but allow leaving it
1246 107400 : Obstacle voBlock = vo;
1247 107400 : if (dir == FORWARD) {
1248 59703 : voBlock.xBack = NUMERICAL_EPS;
1249 : } else {
1250 47697 : voBlock.xFwd = crossing->getLength() - NUMERICAL_EPS;
1251 : }
1252 : // when approaching a priority crossings, vehicles must be able
1253 : // to brake, otherwise the person must be able to cross in time
1254 107400 : const double distToCrossBeforeVeh = (dir == FORWARD ? vo.xFwd : crossing->getLength() - vo.xBack);
1255 : const double bGap = (prio
1256 109031 : ? veh->getCarFollowModel().brakeGap(veh->getSpeed(), veh->getCarFollowModel().getMaxDecel(), 0)
1257 1631 : : veh->getSpeed() * distToCrossBeforeVeh); // walking 1m/s
1258 : double vehYmin;
1259 : double vehYmax;
1260 : // relY increases from left to right (the other way around from vehicles)
1261 107400 : if ((*it).fromLeft()) {
1262 70021 : vehYmin = -(*it).vehAndGap.second + lateral_offset; // vehicle back
1263 70021 : vehYmax = vehYmin + veh->getVehicleType().getLength() + bGap + minGapToVehicle;
1264 70021 : vehYmin -= minGapToVehicle;
1265 : } else {
1266 37379 : vehYmax = crossing->getWidth() + (*it).vehAndGap.second - lateral_offset; // vehicle back
1267 37379 : vehYmin = vehYmax - veh->getVehicleType().getLength() - bGap - minGapToVehicle;
1268 37379 : vehYmax += minGapToVehicle;
1269 :
1270 : }
1271 429641 : for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax), stripes); ++s) {
1272 179218 : if ((dir == FORWARD && obs[s].xBack > vo.xBack)
1273 322499 : || (dir == BACKWARD && obs[s].xFwd < vo.xFwd)) {
1274 321600 : if (!prio && veh->getSpeed() > SUMO_const_haltingSpeed) {
1275 : // do not enter the crossing
1276 9220 : obs[s] = voBlock;
1277 : } else {
1278 312380 : obs[s] = vo;
1279 : }
1280 : hasCrossingVehObs = true;
1281 : }
1282 : }
1283 107400 : if (DEBUGCOND2(crossing)) {
1284 0 : std::cout << SIMTIME
1285 : << " crossingVeh=" << veh->getID()
1286 : << " lane=" << crossing->getID()
1287 : << " prio=" << prio
1288 : << " latOffset=" << lateral_offset
1289 : << " dir=" << dir
1290 0 : << " stripes=" << stripes
1291 0 : << " dist=" << (*it).distToCrossing
1292 0 : << " gap=" << (*it).vehAndGap.second
1293 : << " brakeGap=" << bGap
1294 : << " fromLeft=" << (*it).fromLeft()
1295 : << " distToCrossBefore=" << distToCrossBeforeVeh
1296 : << " ymin=" << vehYmin
1297 : << " ymax=" << vehYmax
1298 : << " smin=" << PState::stripe(vehYmin)
1299 0 : << " smax=" << PState::stripe(vehYmax)
1300 0 : << "\n";
1301 0 : DEBUG_PRINT(obs);
1302 : }
1303 : }
1304 : }
1305 104198 : if (hasCrossingVehObs) {
1306 : // check whether the crossing is fully blocked
1307 69614 : const int reserved = getReserved((int)obs.size(), RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS);
1308 : bool allBlocked = true;
1309 :
1310 385592 : for (int i = 0; i < (int)obs.size(); i++) {
1311 342679 : const Obstacle& o = obs[i];
1312 342679 : if (o.type != OBSTACLE_VEHICLE && (
1313 49720 : (dir == FORWARD && i >= reserved) ||
1314 34430 : (dir == BACKWARD && i < (int)obs.size() - reserved))) {
1315 : allBlocked = false;
1316 : break;
1317 : }
1318 : }
1319 69614 : if (allBlocked) {
1320 42913 : if (DEBUGCOND2(crossing)) {
1321 0 : std::cout << SIMTIME << " crossing=" << crossing->getID() << " allBlocked\n";
1322 : }
1323 304790 : for (Obstacle& o : obs) {
1324 261877 : if (dir == FORWARD) {
1325 142329 : o.xBack = NUMERICAL_EPS;
1326 : } else {
1327 119548 : o.xFwd = crossing->getLength() - NUMERICAL_EPS;
1328 : }
1329 : }
1330 : }
1331 : }
1332 : }
1333 1010024 : return hasCrossingVehObs;
1334 1010024 : }
1335 :
1336 :
1337 : MSPModel_Striping::Obstacles
1338 289541 : MSPModel_Striping::getVehicleObstacles(const MSLane* lane, int dir, PState* ped) {
1339 289541 : const int stripes = numStripes(lane);
1340 579082 : Obstacles vehObs(stripes, Obstacle(dir));
1341 : int current = -1;
1342 : double minX = 0.;
1343 : double maxX = 0.;
1344 : double pRelY = -1.;
1345 : double pWidth = 0.;
1346 : std::string pID;
1347 289541 : bool debug = DEBUGCOND2(lane);
1348 289541 : if (ped != nullptr) {
1349 270919 : current = ped->stripe();
1350 270919 : minX = ped->getMinX();
1351 270919 : maxX = ped->getMaxX();
1352 : pRelY = ped->getPosLat();
1353 270919 : pWidth = ped->getPerson()->getVehicleType().getWidth();
1354 : pID = ped->getPerson()->getID();
1355 270919 : debug = DEBUGCOND(*ped);
1356 18622 : } else if (dir == BACKWARD) {
1357 : // checking vehicles on the next lane. Use entry point as reference
1358 : minX = lane->getLength();
1359 : maxX = lane->getLength();
1360 : }
1361 289541 : MSLane::AnyVehicleIterator begin = (dir == FORWARD ? lane->anyVehiclesUpstreamBegin() : lane->anyVehiclesBegin());
1362 : MSLane::AnyVehicleIterator end = (dir == FORWARD ? lane->anyVehiclesUpstreamEnd() : lane->anyVehiclesEnd());
1363 756046 : for (MSLane::AnyVehicleIterator it = begin; it != end; ++it) {
1364 466505 : const MSVehicle* veh = *it;
1365 466505 : const bool bidi = veh->getLane() == lane->getBidiLane();
1366 466505 : const double vehBack = veh->getBackPositionOnLane(lane);
1367 466505 : double vehFront = vehBack + veh->getVehicleType().getLength();
1368 : // ensure that vehicles are not blocked
1369 466505 : const double vehNextSpeed = veh->getWaitingTime() > DELTA_T ? 0 : MAX2(veh->getSpeed(), 1.0);
1370 466505 : const double clearance = SAFETY_GAP + vehNextSpeed * LOOKAHEAD_SAMEDIR;
1371 : // boundaries for range checking
1372 : double vehXMax;
1373 : double vehXMin;
1374 : double vehXMaxCheck;
1375 : double vehXMinCheck;
1376 466505 : if (bidi) {
1377 1617 : vehFront = vehBack - veh->getVehicleType().getLength();
1378 1617 : vehXMax = vehBack + SAFETY_GAP;
1379 1617 : vehXMin = vehFront - clearance;
1380 1617 : if (dir == FORWARD) {
1381 1617 : vehXMaxCheck = vehBack + NUMERICAL_EPS;
1382 1617 : vehXMinCheck = vehFront - LOOKAROUND_VEHICLES;
1383 : } else {
1384 0 : vehXMaxCheck = vehBack + LOOKAHEAD_SAMEDIR;
1385 : vehXMinCheck = vehFront - clearance;
1386 : }
1387 : } else {
1388 464888 : vehXMax = vehFront + clearance;
1389 464888 : vehXMin = vehBack - SAFETY_GAP;
1390 464888 : if (dir == FORWARD) {
1391 : vehXMaxCheck = vehFront + clearance;
1392 342689 : vehXMinCheck = vehBack - LOOKAHEAD_SAMEDIR;
1393 : } else {
1394 122199 : vehXMaxCheck = vehFront + LOOKAROUND_VEHICLES;
1395 122199 : vehXMinCheck = vehBack - NUMERICAL_EPS;
1396 : }
1397 : }
1398 466505 : if (debug) {
1399 0 : std::cout << SIMTIME << " ped=" << pID << " veh=" << veh->getID() << " check obstacle on lane=" << lane->getID()
1400 : << "\n"
1401 : << " vehXMin=" << vehXMin
1402 : << " vehXMax=" << vehXMax
1403 : << " vehXMinC=" << vehXMinCheck
1404 : << " vehXMaxC=" << vehXMaxCheck
1405 : << " minX=" << minX
1406 : << " maxX=" << maxX
1407 : << " bidi=" << bidi
1408 : << " vFront=" << vehFront
1409 : << " vBack=" << vehBack
1410 0 : << "\n";
1411 : }
1412 466505 : if (vehXMaxCheck > minX && vehXMinCheck && vehXMinCheck <= maxX) {
1413 350914 : Obstacle vo(vehBack, veh->getSpeed() * (bidi ? -1 : 1), OBSTACLE_VEHICLE, veh->getID(), 0, veh);
1414 : // moving vehicles block space along their path
1415 175811 : vo.xFwd = vehXMax;
1416 175811 : vo.xBack = vehXMin;
1417 : // relY increases from left to right (the other way around from vehicles)
1418 : // XXX lateral offset for partial vehicles
1419 175811 : const double posLat = veh->getLateralPositionOnLane() * (bidi ? -1 : 1);
1420 175811 : const double vehYmax = 0.5 * (lane->getWidth() + veh->getVehicleType().getWidth() - stripeWidth) - posLat;
1421 175811 : const double vehYmin = vehYmax - veh->getVehicleType().getWidth();
1422 755469 : for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax) + 1, stripes); ++s) {
1423 579658 : Obstacle prior = vehObs[s];
1424 : vehObs[s] = vo;
1425 579658 : if (s == current && vehFront + SAFETY_GAP < minX) {
1426 : // ignore if already overlapping while vehicle is still behind
1427 16724 : if (pRelY - pWidth < vehYmax &&
1428 16336 : pRelY + pWidth > vehYmin && dir == FORWARD) {
1429 10033 : if (debug) {
1430 0 : std::cout << " ignoring vehicle '" << veh->getID() << " on stripe " << s << " vehFrontSG=" << vehFront + SAFETY_GAP << " minX=" << minX << "\n";
1431 : }
1432 : if (dir == FORWARD) {
1433 : vehObs[s] = prior;
1434 : } else {
1435 : vehObs[s].xFwd = MIN2(vo.xFwd, vehFront + SAFETY_GAP);
1436 : }
1437 : }
1438 : }
1439 : }
1440 175811 : if (debug) {
1441 0 : std::cout << SIMTIME << " ped=" << pID << " veh=" << veh->getID() << " obstacle on lane=" << lane->getID()
1442 : << "\n"
1443 : << " ymin=" << vehYmin
1444 : << " ymax=" << vehYmax
1445 : << " smin=" << PState::stripe(vehYmin)
1446 0 : << " smax=" << PState::stripe(vehYmax)
1447 0 : << " relY=" << pRelY
1448 : << " current=" << current
1449 0 : << " vo.xFwd=" << vo.xFwd
1450 0 : << " vo.xBack=" << vo.xBack
1451 : << " vFront=" << vehFront
1452 : << " vBack=" << vehBack
1453 0 : << "\n";
1454 : }
1455 : }
1456 : }
1457 289541 : return vehObs;
1458 0 : }
1459 :
1460 :
1461 : // ===========================================================================
1462 : // MSPModel_Striping::Obstacle method definitions
1463 : // ===========================================================================
1464 82880079 : MSPModel_Striping::Obstacle::Obstacle(int dir, double dist) :
1465 82880079 : xFwd(dir * dist), // by default, far away when seen in dir
1466 82880079 : xBack(dir * dist), // by default, far away when seen in dir
1467 82880079 : speed(0),
1468 82880079 : type(OBSTACLE_NONE),
1469 82880079 : description("") {
1470 82880079 : }
1471 :
1472 :
1473 649447761 : MSPModel_Striping::Obstacle::Obstacle(const PState& ped) :
1474 649447761 : xFwd(ped.getMaxX()),
1475 649447761 : xBack(ped.getMinX()),
1476 649447761 : speed(ped.getDirection() * ped.getSpeed(*ped.getStage())),
1477 649447761 : type(ped.getOType()),
1478 649447761 : description(ped.getID()) {
1479 : assert(!ped.isWaitingToEnter());
1480 649447761 : if (type == OBSTACLE_VEHICLE) {
1481 529902 : vehicle = static_cast<const PStateVehicle&>(ped).getVehicle();
1482 : }
1483 649447761 : }
1484 :
1485 :
1486 : bool
1487 128315822 : MSPModel_Striping::Obstacle::closer(const Obstacle& o, int dir) {
1488 128315822 : if (dir == FORWARD) {
1489 69227236 : return xBack <= o.xBack;
1490 : } else {
1491 59088586 : return xFwd >= o.xFwd;
1492 : }
1493 : }
1494 :
1495 :
1496 : // ===========================================================================
1497 : // MSPModel_Striping::PState method definitions
1498 : // ===========================================================================
1499 243016 : MSPModel_Striping::PState::PState(MSPerson* person, MSStageMoving* stage, const MSLane* lane):
1500 : MSPModel_InteractingState(person, stage, lane),
1501 243016 : myWalkingAreaPath(nullptr) {
1502 : const MSEdge* currentEdge = &lane->getEdge();
1503 : const ConstMSEdgeVector& route = myStage->getRoute();
1504 : assert(!route.empty());
1505 243016 : myDir = FORWARD;
1506 243016 : if (route.size() == 1) {
1507 : // only a single edge, move towards end pos
1508 13270 : myDir = (myEdgePos <= myStage->getArrivalPos()) ? FORWARD : BACKWARD;
1509 229746 : } else if (route.front()->getFunction() != SumoXMLEdgeFunc::NORMAL) {
1510 : // start on an intersection
1511 8 : if (route.front()->isWalkingArea()) {
1512 8 : myWalkingAreaPath = getArbitraryPath(route.front());
1513 : }
1514 : } else {
1515 229738 : int passedFwd = 0;
1516 229738 : int passedBwd = 0;
1517 229738 : const bool mayStartForward = canTraverse(FORWARD, route, passedFwd) != UNDEFINED_DIRECTION;
1518 229738 : const bool mayStartBackward = canTraverse(BACKWARD, route, passedBwd) != UNDEFINED_DIRECTION;
1519 229738 : if DEBUGCOND(*this) {
1520 0 : std::cout << " initialize dir for " << myPerson->getID() << " forward=" << mayStartForward << " backward=" << mayStartBackward << "\n";
1521 : }
1522 229738 : if (mayStartForward && mayStartBackward) {
1523 : // figure out the best direction via routing
1524 : ConstMSEdgeVector crossingRoute;
1525 7380 : MSNet::getInstance()->getPedestrianRouter(0).compute(currentEdge, route.back(), myEdgePos, myStage->getArrivalPos(),
1526 2460 : myStage->getMaxSpeed(person), 0, nullptr, person->getVTypeParameter(), crossingRoute, true);
1527 2460 : if (crossingRoute.size() > 1) {
1528 : // route found
1529 2452 : const MSEdge* nextEdge = crossingRoute[1];
1530 2452 : if (nextEdge->getFromJunction() == currentEdge->getFromJunction() || nextEdge->getToJunction() == currentEdge->getFromJunction()) {
1531 1866 : myDir = BACKWARD;
1532 : }
1533 : }
1534 2460 : if DEBUGCOND(*this) {
1535 0 : std::cout << " crossingRoute=" << toString(crossingRoute) << "\n";
1536 : }
1537 229738 : } else if (!mayStartForward && !mayStartBackward) {
1538 157 : int lastDisconnect = passedFwd >= passedBwd ? passedFwd : passedBwd;
1539 : std::string dLoc;
1540 157 : if (route.size() > 2) {
1541 260 : dLoc = TLF(" between edge '%' and edge '%'", route[lastDisconnect - 1]->getID(), route[lastDisconnect]->getID());
1542 : }
1543 942 : WRITE_WARNINGF(TL("Person '%' walking from edge '%' to edge '%' has a disconnect%, time=%."),
1544 : myPerson->getID(), route.front()->getID(), route.back()->getID(), dLoc, SIMTIME);
1545 162 : myDir = passedFwd >= passedBwd ? FORWARD : BACKWARD;
1546 : } else {
1547 424847 : myDir = !mayStartBackward ? FORWARD : BACKWARD;
1548 : }
1549 : }
1550 243016 : if (myPosLat == UNSPECIFIED_POS_LAT || myLegacyPosLat) {
1551 242732 : if (myPosLat == UNSPECIFIED_POS_LAT) {
1552 242546 : myPosLat = 0;
1553 : }
1554 242732 : if (lane->getVehicleNumberWithPartials() > 0 && myPosLat == 0) {
1555 : // better start next to the road if nothing was specified
1556 2155 : myPosLat -= stripeWidth;
1557 : }
1558 242732 : if (myDir == FORWARD || lane->getPermissions() != SVC_PEDESTRIAN) {
1559 : // start at the right side of the sidewalk on shared roads
1560 207202 : myPosLat = stripeWidth * (numStripes(lane) - 1) - myPosLat;
1561 : }
1562 284 : } else if (myPosLat == RANDOM_POS_LAT) {
1563 20 : myPosLat = RandHelper::rand() * stripeWidth * (numStripes(lane) - 1);
1564 : } else {
1565 : // vehicle to striping coordinate system
1566 264 : myPosLat = posLatConversion(myPosLat, lane->getWidth());
1567 : }
1568 243016 : if DEBUGCOND(*this) {
1569 0 : std::cout << " added new pedestrian " << myPerson->getID() << " on " << lane->getID() << " myEdgePos=" << myEdgePos << " myPosLat=" << myPosLat << " dir=" << myDir << " route=" << toString(myStage->getRoute()) << "\n";
1570 : }
1571 :
1572 243016 : myNLI = getNextLane(*this, lane, nullptr);
1573 243012 : }
1574 :
1575 :
1576 14 : MSPModel_Striping::PState::PState(MSPerson* person, MSStageMoving* stage, std::istringstream* in) :
1577 : MSPModel_InteractingState(person, stage, nullptr),
1578 14 : myWalkingAreaPath(nullptr) {
1579 14 : if (in != nullptr) {
1580 : std::string laneID;
1581 : std::string wapLaneFrom;
1582 : std::string wapLaneTo;
1583 : std::string nextLaneID;
1584 : std::string nextLinkFrom;
1585 : std::string nextLinkTo;
1586 : int nextDir;
1587 :
1588 14 : (*in) >> laneID
1589 14 : >> myEdgePos >> myPosLat >> myDir >> mySpeed >> mySpeedLat >> myWaitingToEnter >> myWaitingTime
1590 14 : >> wapLaneFrom >> wapLaneTo
1591 14 : >> myAmJammed
1592 : >> nextLaneID
1593 : >> nextLinkFrom
1594 14 : >> nextLinkTo
1595 14 : >> nextDir;
1596 :
1597 :
1598 14 : myLane = MSLane::dictionary(laneID);
1599 14 : if (myLane == nullptr) {
1600 0 : throw ProcessError("Unknown lane '" + laneID + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1601 : }
1602 :
1603 : MSLane* nextLane = nullptr;
1604 14 : if (nextLaneID != "null") {
1605 13 : nextLane = MSLane::dictionary(nextLaneID);
1606 13 : if (nextLane == nullptr) {
1607 0 : throw ProcessError("Unknown next lane '" + nextLaneID + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1608 : }
1609 : }
1610 : const MSLink* link = nullptr;
1611 14 : if (nextLinkFrom != "null") {
1612 2 : MSLane* from = MSLane::dictionary(nextLinkFrom);
1613 2 : MSLane* to = MSLane::dictionary(nextLinkTo);
1614 2 : if (from == nullptr) {
1615 0 : throw ProcessError("Unknown link origin lane '" + nextLinkFrom + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1616 : }
1617 2 : if (to == nullptr) {
1618 0 : throw ProcessError("Unknown link destination lane '" + nextLinkTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1619 : }
1620 2 : link = from->getLinkTo(to);
1621 : }
1622 14 : myNLI = NextLaneInfo(nextLane, link, nextDir);
1623 :
1624 14 : if (wapLaneFrom != "null") {
1625 1 : MSLane* from = MSLane::dictionary(wapLaneFrom);
1626 1 : MSLane* to = MSLane::dictionary(wapLaneTo);
1627 1 : if (from == nullptr) {
1628 0 : throw ProcessError("Unknown walkingAreaPath origin lane '" + wapLaneFrom + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1629 : }
1630 1 : if (to == nullptr) {
1631 0 : throw ProcessError("Unknown walkingAreaPath destination lane '" + wapLaneTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1632 : }
1633 1 : const auto pathIt = myWalkingAreaPaths.find(std::make_pair(from, to));
1634 1 : if (pathIt != myWalkingAreaPaths.end()) {
1635 1 : myWalkingAreaPath = &pathIt->second;
1636 : } else {
1637 0 : throw ProcessError("Unknown walkingAreaPath from lane '" + wapLaneFrom + "' to lane '" + wapLaneTo + "' when loading walk for person '" + myPerson->getID() + "' from state.");
1638 : }
1639 : }
1640 : }
1641 14 : }
1642 :
1643 :
1644 495398 : MSPModel_Striping::PState::PState() :
1645 495398 : MSPModel_InteractingState(nullptr, nullptr, nullptr) {}
1646 :
1647 :
1648 : void
1649 9 : MSPModel_Striping::PState::saveState(std::ostringstream& out) {
1650 9 : std::string wapLaneFrom = "null";
1651 9 : std::string wapLaneTo = "null";
1652 9 : if (myWalkingAreaPath != nullptr) {
1653 1 : wapLaneFrom = myWalkingAreaPath->from->getID();
1654 1 : wapLaneTo = myWalkingAreaPath->to->getID();
1655 : }
1656 9 : std::string nextLaneID = "null";
1657 9 : std::string nextLinkFrom = "null";
1658 9 : std::string nextLinkTo = "null";
1659 9 : if (myNLI.lane != nullptr) {
1660 : nextLaneID = myNLI.lane->getID();
1661 : }
1662 9 : if (myNLI.link != nullptr) {
1663 : nextLinkFrom = myNLI.link->getLaneBefore()->getID();
1664 2 : nextLinkTo = myNLI.link->getViaLaneOrLane()->getID();
1665 : }
1666 9 : out << " " << myLane->getID()
1667 18 : << " " << myEdgePos
1668 9 : << " " << myPosLat
1669 : << " " << myDir
1670 18 : << " " << mySpeed
1671 9 : << " " << mySpeedLat
1672 9 : << " " << myWaitingToEnter
1673 9 : << " " << myWaitingTime
1674 : << " " << wapLaneFrom
1675 : << " " << wapLaneTo
1676 9 : << " " << myAmJammed
1677 : << " " << nextLaneID
1678 : << " " << nextLinkFrom
1679 : << " " << nextLinkTo
1680 9 : << " " << myNLI.dir;
1681 9 : }
1682 :
1683 : double
1684 2102052808 : MSPModel_Striping::PState::getMinX(const bool includeMinGap) const {
1685 : // @todo speed should have an influence here because faster persons need more space
1686 2102052808 : if (myDir == FORWARD) {
1687 1934783667 : return myEdgePos - getLength();
1688 : }
1689 167269141 : return myEdgePos - (includeMinGap ? getMinGap() : 0.);
1690 : }
1691 :
1692 :
1693 : double
1694 2102052808 : MSPModel_Striping::PState::getMaxX(const bool includeMinGap) const {
1695 : // @todo speed should have an influence here because faster persons need more space
1696 2102052808 : if (myDir == FORWARD) {
1697 1934783667 : return myEdgePos + (includeMinGap ? getMinGap() : 0.);
1698 : }
1699 167269141 : return myEdgePos + getLength();
1700 : }
1701 :
1702 :
1703 : double
1704 2167749346 : MSPModel_Striping::PState::getLength() const {
1705 2167749346 : return myPerson->getVehicleType().getLength();
1706 : }
1707 :
1708 :
1709 : double
1710 1408423499 : MSPModel_Striping::PState::getMinGap() const {
1711 1408423499 : return myPerson->getVehicleType().getMinGap();
1712 : }
1713 :
1714 :
1715 : int
1716 7450206720 : MSPModel_Striping::PState::stripe(double relY) {
1717 7450206720 : return (int)floor(relY / stripeWidth + 0.5);
1718 : }
1719 :
1720 :
1721 : int
1722 3236341412 : MSPModel_Striping::PState::otherStripe(double relY) const {
1723 3236341412 : const int s = stripe(relY);
1724 3236341412 : const double offset = relY - s * stripeWidth;
1725 3236341412 : const double threshold = MAX2(NUMERICAL_EPS, stripeWidth - SQUEEZE * getWidth());
1726 : int result;
1727 3236341412 : if (offset > threshold) {
1728 496421 : result = s + 1;
1729 3235844991 : } else if (offset < -threshold) {
1730 419816 : result = s - 1;
1731 : } else {
1732 : result = s;
1733 : }
1734 : //std::cout.setf(std::ios::fixed , std::ios::floatfield);
1735 : //std::cout << std::setprecision(5);
1736 : //if DEBUGCOND(*this) std::cout << " otherStripe " << myPerson->getID() << " offset=" << offset << " threshold=" << threshold << " rawResult=" << result << "\n";
1737 3236341412 : return result;
1738 : }
1739 :
1740 : int
1741 4181474070 : MSPModel_Striping::PState::stripe() const {
1742 4181474070 : return MIN2(MAX2(0, stripe(myPosLat)), numStripes(myLane) - 1);
1743 : }
1744 :
1745 :
1746 : int
1747 3220619437 : MSPModel_Striping::PState::otherStripe() const {
1748 3220619437 : return MIN2(MAX2(0, otherStripe(myPosLat)), numStripes(myLane) - 1);
1749 : }
1750 :
1751 :
1752 : double
1753 133579469 : MSPModel_Striping::PState::distToLaneEnd() const {
1754 133579469 : if (myStage->getNextRouteEdge() == nullptr) {
1755 23925083 : return myDir * (myStage->getArrivalPos() - myEdgePos) - POSITION_EPS - (
1756 2021241 : (myWaitingTime > DELTA_T && (myStage->getDestinationStop() == nullptr ||
1757 : myStage->getDestinationStop()->getWaitingCapacity() > myStage->getDestinationStop()->getNumWaitingPersons()))
1758 25946324 : ? getMinGap() : 0);
1759 : } else {
1760 109654386 : const double length = myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length;
1761 109654386 : return myDir == FORWARD ? length - myEdgePos : myEdgePos;
1762 : }
1763 : }
1764 :
1765 :
1766 : bool
1767 957498 : MSPModel_Striping::PState::moveToNextLane(SUMOTime currentTime) {
1768 957498 : double dist = distToLaneEnd();
1769 957498 : if (DEBUGCOND(*this)) {
1770 0 : std::cout << SIMTIME << " ped=" << myPerson->getID() << " myEdgePos=" << myEdgePos << " dist=" << dist << "\n";
1771 : }
1772 957498 : if (dist <= 0) {
1773 : //if (ped.getPerson()->getID() == DEBUG1) {
1774 : // std::cout << SIMTIME << " addToLane x=" << ped.myEdgePos << " newDir=" << newDir << " newLane=" << newLane->getID() << " walkingAreaShape=" << walkingAreaShape << "\n";
1775 : //}
1776 : //std::cout << " changing to " << newLane->getID() << " myPosLat=" << ped.myPosLat << " oldStripes=" << numStripes(myLane) << " newStripes=" << numStripes(newLane);
1777 : //std::cout << " newY=" << ped.myPosLat << " myDir=" << ped.getDirection() << " newDir=" << newDir;
1778 957498 : const int oldDir = myDir;
1779 957498 : const MSLane* oldLane = myLane;
1780 957498 : myLane = myNLI.lane;
1781 957498 : myDir = myNLI.dir;
1782 957498 : const bool normalLane = (myLane == nullptr || myLane->getEdge().getFunction() == SumoXMLEdgeFunc::NORMAL || &myLane->getEdge() == myStage->getNextRouteEdge());
1783 957498 : if DEBUGCOND(*this) {
1784 0 : std::cout << SIMTIME
1785 0 : << " ped=" << myPerson->getID()
1786 : << " moveToNextLane old=" << oldLane->getID()
1787 0 : << " new=" << (myLane == nullptr ? "NULL" : myLane->getID())
1788 : << " oldDir=" << oldDir
1789 0 : << " newDir=" << myDir
1790 0 : << " myEdgePos=" << myEdgePos
1791 : << " dist=" << dist
1792 0 : << "\n";
1793 : }
1794 957498 : if (myLane == nullptr) {
1795 220234 : myEdgePos = myStage->getArrivalPos();
1796 : }
1797 : // moveToNextEdge might destroy the person and thus mess up the heap. Better check first
1798 957498 : if (myStage->getRouteStep() == myStage->getRoute().end() - 1) {
1799 220234 : myLane = nullptr;
1800 : } else {
1801 737264 : const bool arrived = myStage->moveToNextEdge(myPerson, currentTime, oldDir, normalLane ? nullptr : &myLane->getEdge());
1802 : UNUSED_PARAMETER(arrived);
1803 : assert(!arrived);
1804 : assert(myDir != UNDEFINED_DIRECTION);
1805 737264 : myNLI = getNextLane(*this, myLane, oldLane);
1806 : // reminders must be called after updated myNLI (to ensure that getNextEdgePtr returns the correct edge)
1807 737264 : myStage->activateEntryReminders(myPerson);
1808 : assert(myNLI.lane != oldLane); // do not turn around
1809 737264 : if DEBUGCOND(*this) {
1810 0 : std::cout << " nextLane=" << (myNLI.lane == nullptr ? "NULL" : myNLI.lane->getID()) << "\n";
1811 : }
1812 737264 : if (myLane->getEdge().isWalkingArea()) {
1813 339059 : if (myNLI.dir != UNDEFINED_DIRECTION) {
1814 339022 : myWalkingAreaPath = getWalkingAreaPath(&myLane->getEdge(), oldLane, myNLI.lane);
1815 : assert(myWalkingAreaPath->shape.size() >= 2);
1816 339022 : if DEBUGCOND(*this) {
1817 0 : std::cout << " mWAPath shape=" << myWalkingAreaPath->shape << " length=" << myWalkingAreaPath->length << "\n";
1818 : }
1819 37 : } else if (myNLI.link != nullptr) {
1820 : // using direct connection (instead of using walkingarea)
1821 17 : myLane = myNLI.lane;
1822 : assert(!myLane->getEdge().isWalkingArea());
1823 17 : myStage->moveToNextEdge(myPerson, currentTime, myDir, &myLane->getEdge());
1824 17 : myWalkingAreaPath = nullptr;
1825 17 : myNLI = getNextLane(*this, myLane, oldLane);
1826 : } else {
1827 : // disconnected route. move to the next edge
1828 40 : if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
1829 : // try to determine direction from topology, otherwise maintain current direction
1830 16 : const MSEdge* currRouteEdge = *myStage->getRouteStep();
1831 16 : const MSEdge* nextRouteEdge = myStage->getNextRouteEdge();
1832 : if ((nextRouteEdge->getToJunction() == currRouteEdge->getFromJunction())
1833 16 : || nextRouteEdge->getToJunction() == currRouteEdge->getToJunction()) {
1834 4 : myDir = BACKWARD;
1835 : } else if ((nextRouteEdge->getFromJunction() == currRouteEdge->getFromJunction())
1836 12 : || nextRouteEdge->getFromJunction() == currRouteEdge->getToJunction()) {
1837 12 : myDir = FORWARD;
1838 : }
1839 16 : myStage->moveToNextEdge(myPerson, currentTime, oldDir, nullptr);
1840 16 : myLane = myNLI.lane;
1841 : assert(myLane != 0);
1842 : assert(myLane->getEdge().getFunction() == SumoXMLEdgeFunc::NORMAL);
1843 16 : myNLI = getNextLane(*this, myLane, oldLane);
1844 16 : myWalkingAreaPath = nullptr;
1845 : } else {
1846 12 : throw ProcessError(TLF("Disconnected walk for person '%'.", myPerson->getID()));
1847 : }
1848 : }
1849 : } else {
1850 398205 : myWalkingAreaPath = nullptr;
1851 : }
1852 : // adapt x to fit onto the new lane
1853 : // (make sure we do not move past the end of the new lane since that
1854 : // lane was not checked for obstacles)
1855 737260 : const double newLength = (myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length);
1856 737260 : if (-dist > newLength) {
1857 : assert(OptionsCont::getOptions().getBool("ignore-route-errors"));
1858 : // should not happen because the end of myLane should have been an obstacle as well
1859 : // (only when the route is broken)
1860 1 : dist = -newLength;
1861 : }
1862 737260 : if (myDir == BACKWARD) {
1863 143763 : myEdgePos = newLength + dist;
1864 : } else {
1865 593497 : myEdgePos = -dist;
1866 : }
1867 737260 : if DEBUGCOND(*this) {
1868 0 : std::cout << SIMTIME << " update myEdgePos ped=" << myPerson->getID()
1869 : << " newLength=" << newLength
1870 : << " dist=" << dist
1871 0 : << " myEdgePos=" << myEdgePos
1872 0 : << "\n";
1873 : }
1874 : // adjust to change in direction
1875 737260 : if (myDir != oldDir) {
1876 32394 : myPosLat = (numStripes(oldLane) - 1) * stripeWidth - myPosLat;
1877 : }
1878 : // adjust to differences in sidewalk width
1879 1461453 : const int offset = getStripeOffset(numStripes(oldLane), numStripes(myLane), oldDir != myDir && numStripes(myLane) < numStripes(oldLane));
1880 737260 : myPosLat += offset * stripeWidth;
1881 737260 : if DEBUGCOND(*this) {
1882 0 : std::cout << SIMTIME << " transformY ped=" << myPerson->getID()
1883 0 : << " newLane=" << Named::getIDSecure(myLane)
1884 0 : << " newY=" << myPosLat
1885 0 : << " os=" << numStripes(oldLane) << " ns=" << numStripes(myLane)
1886 0 : << " od=" << oldDir << " nd=" << myDir
1887 0 : << " offset=" << offset << "\n";
1888 : }
1889 : }
1890 957494 : myAngle = std::numeric_limits<double>::max(); // see #9014
1891 957494 : return true;
1892 : } else {
1893 : return false;
1894 : }
1895 : }
1896 :
1897 :
1898 : int
1899 65766152 : MSPModel_Striping::getReserved(int stripes, double factor) {
1900 65766152 : return MIN2(
1901 65766152 : (int)floor(stripes * factor),
1902 65766152 : (int)floor(RESERVE_FOR_ONCOMING_MAX / stripeWidth));
1903 : }
1904 :
1905 : void
1906 65696538 : MSPModel_Striping::PState::walk(const Obstacles& obs) {
1907 65696538 : const int stripes = (int)obs.size();
1908 65696538 : const int sMax = stripes - 1;
1909 : assert(stripes == numStripes(myLane));
1910 : // account stage-specific max speed but also for normal lane speed limit
1911 : // (speed limits on crossings and walkingareas ignored due to #11527)
1912 65696538 : const double vMax = (myStage->getConfiguredSpeed() >= 0
1913 65696538 : ? myStage->getConfiguredSpeed()
1914 9158486 : : (USE_NET_SPEEDS || myLane->isNormal() || myLane->isInternal()
1915 74074811 : ? myLane->getVehicleMaxSpeed(myPerson)
1916 725150 : : myStage->getMaxSpeed(myPerson)));
1917 : // ultimate goal is to choose the preferred stripe (chosen)
1918 65696538 : const int current = stripe();
1919 65696538 : const int other = otherStripe();
1920 : // compute distances
1921 65696538 : std::vector<double> distance(stripes);
1922 285895166 : for (int i = 0; i < stripes; ++i) {
1923 220198628 : distance[i] = distanceTo(obs[i], obs[i].type == OBSTACLE_PED);
1924 : }
1925 : // compute utility for all stripes
1926 65696538 : std::vector<double> utility(stripes, 0);
1927 : // forbid stripes which are blocked and also all stripes behind them
1928 285895166 : for (int i = 0; i < stripes; ++i) {
1929 220198628 : if (distance[i] == DIST_OVERLAP) {
1930 96162606 : if (i == current && (!isWaitingToEnter() || stripe() != stripe(myPosLat))) {
1931 6771754 : utility[i] += OBSTRUCTED_PENALTY;
1932 : }
1933 96162606 : if (i < current) {
1934 135137877 : for (int j = 0; j <= i; ++j) {
1935 82420108 : utility[j] += OBSTRUCTED_PENALTY;
1936 : }
1937 : }
1938 96162606 : if (i > current) {
1939 60565293 : for (int j = i; j < stripes; ++j) {
1940 35024328 : utility[j] += OBSTRUCTED_PENALTY;
1941 : }
1942 : }
1943 : }
1944 : }
1945 : // forbid a portion of the leftmost stripes (in walking direction).
1946 : // lanes with stripes less than 1 / RESERVE_FOR_ONCOMING_FACTOR
1947 : // may still deadlock in heavy pedestrian traffic
1948 65696538 : const bool onJunction = myLane->getEdge().isWalkingArea() || myLane->getEdge().isCrossing();
1949 65696538 : const int reserved = getReserved(stripes, (onJunction ? RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS : RESERVE_FOR_ONCOMING_FACTOR));
1950 65696538 : if (myDir == FORWARD) {
1951 69001042 : for (int i = 0; i < reserved; ++i) {
1952 16604935 : utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1953 : }
1954 : } else {
1955 6816111 : for (int i = sMax; i > sMax - reserved; --i) {
1956 2787080 : utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1957 : }
1958 : }
1959 : // adapt utility based on obstacles
1960 285895166 : for (int i = 0; i < stripes; ++i) {
1961 220198628 : if (obs[i].speed * myDir < 0) {
1962 : // penalize evasion to the left unless the obstacle is a vehicle
1963 4449301 : if ((myDir == FORWARD || obs[i].type == OBSTACLE_VEHICLE) && i > 0) {
1964 858214 : utility[i - 1] -= 0.5;
1965 3591087 : } else if (myDir == BACKWARD && i < sMax) {
1966 595240 : utility[i + 1] -= 0.5;
1967 : }
1968 : }
1969 : // compute expected distance achievable by staying on this stripe for a time horizon
1970 220198628 : const double walkDist = MAX2(0., distance[i]); // disregard special distance flags
1971 220198628 : const double lookAhead = obs[i].speed * myDir >= 0 ? LOOKAHEAD_SAMEDIR : LOOKAHEAD_ONCOMING;
1972 220198628 : const double expectedDist = MIN2(vMax * LOOKAHEAD_SAMEDIR, walkDist + obs[i].speed * myDir * lookAhead);
1973 220198628 : if (expectedDist >= 0) {
1974 217077449 : utility[i] += expectedDist;
1975 : } else {
1976 : // let only the distance count
1977 3121179 : utility[i] += ONCOMING_CONFLICT_PENALTY + distance[i];
1978 : }
1979 : }
1980 : // discourage use of the leftmost stripe (in walking direction) if there are oncoming
1981 65696538 : if (myDir == FORWARD && obs[0].speed < 0) {
1982 1494670 : utility[0] += ONCOMING_CONFLICT_PENALTY;
1983 64201868 : } else if (myDir == BACKWARD && obs[sMax].speed > 0) {
1984 1505439 : utility[sMax] += ONCOMING_CONFLICT_PENALTY;
1985 : }
1986 : // penalize lateral movement (if the current stripe permits walking)
1987 65696538 : if (distance[current] > 0 && myWaitingTime == 0) {
1988 128329956 : for (int i = 0; i < stripes; ++i) {
1989 100617393 : utility[i] += abs(i - current) * LATERAL_PENALTY;
1990 : }
1991 : }
1992 : // walk on the right side on shared space
1993 65696538 : if (myLane->getPermissions() != SVC_PEDESTRIAN && myDir == BACKWARD) {
1994 2334042 : for (int i = 0; i < stripes; ++i) {
1995 1945230 : if (i <= current) {
1996 1857452 : utility[i] += (sMax - i + 1) * LATERAL_PENALTY;
1997 : }
1998 : }
1999 : }
2000 :
2001 : // select best stripe
2002 : int chosen = current;
2003 285895166 : for (int i = 0; i < stripes; ++i) {
2004 220198628 : if (utility[i] > utility[chosen] && utility[i] >= INAPPROPRIATE_PENALTY * 0.5) {
2005 : chosen = i;
2006 : }
2007 : }
2008 : // compute speed components along both axes
2009 65696538 : const int next = (chosen == current ? current : (chosen < current ? current - 1 : current + 1));
2010 65696538 : double xDist = MIN3(distance[current], distance[other], distance[next]);
2011 65696538 : if (next != chosen) {
2012 : // ensure that we do not collide with an obstacle in the stripe beyond
2013 : // next as this might become the 'other' stripe in the next step
2014 477282 : const int nextOther = chosen < current ? current - 2 : current + 2;
2015 477282 : xDist = MIN2(xDist, distance[nextOther]);
2016 : }
2017 : // XXX preferred gap differs between approaching a standing obstacle or a moving obstacle
2018 : const double preferredGap = NUMERICAL_EPS;
2019 65696538 : double xSpeed = MIN2(vMax, MAX2(0., DIST2SPEED(xDist - preferredGap)));
2020 65696538 : if (xSpeed < NUMERICAL_EPS) {
2021 : xSpeed = 0.;
2022 : }
2023 65696538 : if (DEBUGCOND(*this)) {
2024 0 : std::cout << " xSpeedPotential=" << xSpeed << "\n";
2025 : }
2026 : // avoid tiny steps
2027 : // XXX pressure from behind?
2028 65696538 : if (mySpeed == 0 && xDist < MIN_STARTUP_DIST &&
2029 : // unless walking towards a short lane
2030 29636695 : !(
2031 29949512 : (xDist == distance[current] && obs[current].type >= OBSTACLE_END)
2032 29636711 : || (xDist == distance[other] && obs[other].type >= OBSTACLE_END)
2033 29636695 : || (xDist == distance[next] && obs[next].type >= OBSTACLE_END))
2034 : ) {
2035 : xSpeed = 0;
2036 : }
2037 36059845 : if (xSpeed == 0) {
2038 36226342 : if (DEBUGCOND(*this)) {
2039 0 : std::cout << " sharedWA=" << (myWalkingAreaFoes.find(&myLane->getEdge()) != myWalkingAreaFoes.end())
2040 0 : << " vehObs=" << Named::getIDSecure(obs[current].vehicle)
2041 0 : << " vehWait=" << STEPS2TIME(obs[current].vehicle ? obs[current].vehicle->getWaitingTime() : 0)
2042 0 : << "\n";
2043 : }
2044 36226342 : if (myWaitingTime > ((myLane->getEdge().isCrossing()
2045 : // treat shared walkingarea like a crossing to avoid deadlocking vehicles
2046 36222390 : || (myLane->getEdge().isWalkingArea() && obs[current].vehicle != nullptr && obs[current].vehicle->getWaitingTime() > jamTimeCrossing
2047 72449032 : && myWalkingAreaFoes.find(&myLane->getEdge()) != myWalkingAreaFoes.end())) ? jamTimeCrossing : jamTime)
2048 36150185 : || (sMax == 0 && obs[0].speed * myDir < 0 && myWaitingTime > jamTimeNarrow)
2049 72347942 : || myAmJammed) {
2050 : // squeeze slowly through the crowd ignoring others
2051 7829680 : if (!myAmJammed) {
2052 87888 : MSNet::getInstance()->getPersonControl().registerJammed();
2053 351552 : WRITE_WARNINGF(TL("Person '%' is jammed on edge '%', time=%."),
2054 : myPerson->getID(), myStage->getEdge()->getID(), time2string(SIMSTEP));
2055 87888 : myAmJammed = true;
2056 : }
2057 7829680 : xSpeed = vMax * jamFactor;
2058 : }
2059 29470196 : } else if (myAmJammed && stripe(myPosLat) >= 0 && stripe(myPosLat) <= sMax && xDist >= MIN_STARTUP_DIST) {
2060 78933 : myAmJammed = false;
2061 : }
2062 : // dawdling
2063 65696538 : const double dawdle = MIN2(xSpeed, RandHelper::rand() * vMax * dawdling);
2064 65696538 : xSpeed -= dawdle;
2065 :
2066 : // XXX ensure that diagonal speed <= vMax
2067 : // avoid deadlocks on narrow sidewalks
2068 : //if (oncoming && xSpeed == 0 && myStage->getWaitingTime(currentTime) > TIME2STEPS(ONCOMIN_PATIENCE)) {
2069 : // if DEBUGCOND(*this) std::cout << " stepping aside to resolve oncoming deadlock\n";
2070 : // xSpeed = POSITION_EPS; // reset myWaitingTime
2071 : // if (myDir == FORWARD && chosen < sMax) {
2072 : // chosen += 1;
2073 : // } else if (myDir == BACKWARD && chosen > 0) {
2074 : // chosen -= 1;
2075 : // }
2076 : //}
2077 65696538 : const double maxYSpeed = MIN2(MAX2(vMax * LATERAL_SPEED_FACTOR, vMax - xSpeed), stripeWidth);
2078 : double ySpeed = 0;
2079 : double yDist = 0;
2080 65696538 : if (utility[next] > OBSTRUCTION_THRESHOLD && utility[chosen] > OBSTRUCTION_THRESHOLD) {
2081 : // don't move laterally if the stripes are blocked
2082 58968318 : yDist = (chosen * stripeWidth) - myPosLat;
2083 58968318 : if (fabs(yDist) > NUMERICAL_EPS) {
2084 2685148 : ySpeed = (yDist > 0 ?
2085 1232532 : MIN2(maxYSpeed, DIST2SPEED(yDist)) :
2086 1452616 : MAX2(-maxYSpeed, DIST2SPEED(yDist)));
2087 : }
2088 6728220 : } else if (utility[next] <= OBSTRUCTION_THRESHOLD && obs[next].type == OBSTACLE_VEHICLE
2089 : // still on the road
2090 10585 : && stripe() == stripe(myPosLat)
2091 : // only when the vehicle is moving on the same lane
2092 6734061 : && !(myLane->getEdge().isCrossing() || myLane->getEdge().isWalkingArea())) {
2093 : // step aside to let the vehicle pass
2094 3457 : int stepAsideDir = myDir;
2095 3457 : if (myLane->getEdge().getLanes().size() > 1 || current > sMax / 2) {
2096 : // always step to the right on multi-lane edges or when closer to
2097 : // the right side
2098 : stepAsideDir = FORWARD;
2099 : }
2100 3457 : myAmJammed = true; // ignore pedestrian-pedestrian collisions
2101 3457 : ySpeed = stepAsideDir * vMax;
2102 : }
2103 :
2104 : // DEBUG
2105 65696538 : if DEBUGCOND(*this) {
2106 0 : std::cout << SIMTIME
2107 0 : << " ped=" << myPerson->getID()
2108 0 : << " edge=" << myStage->getEdge()->getID()
2109 0 : << " x=" << myEdgePos
2110 0 : << " y=" << myPosLat
2111 : << " d=" << myDir
2112 0 : << " pvx=" << mySpeed
2113 : << " cur=" << current
2114 0 : << " cho=" << chosen
2115 0 : << " oth=" << other
2116 0 : << " nxt=" << next
2117 0 : << " vx=" << xSpeed
2118 : << " dawdle=" << dawdle
2119 : << " vy=" << ySpeed
2120 : << " xd=" << xDist
2121 : << " yd=" << yDist
2122 : << " vMax=" << vMax
2123 0 : << " wTime=" << myStage->getWaitingTime()
2124 0 : << " jammed=" << myAmJammed
2125 0 : << "\n";
2126 0 : if (DEBUGCOND(*this)) {
2127 0 : for (int i = 0; i < stripes; ++i) {
2128 0 : const Obstacle& o = obs[i];
2129 0 : std::cout << " util=" << utility[i] << " dist=" << distance[i] << " o=" << o.description;
2130 0 : if (o.description != "") {
2131 0 : std::cout << " xF=" << o.xFwd << " xB=" << o.xBack << " v=" << o.speed;
2132 : }
2133 0 : if (i == current) {
2134 0 : std::cout << " current";
2135 : }
2136 0 : if (i == other && i != current) {
2137 0 : std::cout << " other";
2138 : }
2139 0 : if (i == chosen) {
2140 0 : std::cout << " chosen";
2141 : }
2142 0 : if (i == next) {
2143 0 : std::cout << " next";
2144 : }
2145 0 : std::cout << "\n";
2146 : }
2147 : }
2148 : }
2149 65696538 : myEdgePos += SPEED2DIST(xSpeed * myDir);
2150 65696538 : myPosLat += SPEED2DIST(ySpeed);
2151 65696538 : mySpeedLat = ySpeed;
2152 65696538 : mySpeed = xSpeed;
2153 65696538 : if (xSpeed >= SUMO_const_haltingSpeed) {
2154 33457812 : myWaitingToEnter = false;
2155 33457812 : myWaitingTime = 0;
2156 : } else {
2157 32238726 : myWaitingTime += DELTA_T;
2158 32238726 : myTotalWaitingTime += DELTA_T;
2159 : }
2160 65696538 : myAngle = std::numeric_limits<double>::max(); // set on first access or via remote control
2161 65696538 : }
2162 :
2163 :
2164 : double
2165 11258066 : MSPModel_Striping::PState::getImpatience() const {
2166 11258066 : return MAX2(0., MIN2(1., myPerson->getVehicleType().getImpatience()
2167 11258066 : + STEPS2TIME(myStage->getWaitingTime()) / MAX_WAIT_TOLERANCE));
2168 : }
2169 :
2170 :
2171 : Position
2172 10420211 : MSPModel_Striping::PState::getPosition(const MSStageMoving& stage, SUMOTime) const {
2173 : if (myRemoteXYPos != Position::INVALID) {
2174 6293 : return myRemoteXYPos;
2175 : }
2176 10413918 : if (myLane == nullptr) {
2177 : // pedestrian has already finished
2178 223 : return Position::INVALID;
2179 : }
2180 10413695 : const double lateral_offset = -getLatOffset(); // the minus is hunting me in my dreams but seems to be here for historical reasons
2181 10413695 : if (myWalkingAreaPath == nullptr) {
2182 1016932 : return stage.getLanePosition(myLane, myEdgePos, lateral_offset);
2183 : } else {
2184 : //if DEBUGCOND(*this) {
2185 : // std::cout << SIMTIME
2186 : // << " getPosition (walkingArea)"
2187 : // << " p=" << myPerson->getID()
2188 : // << " x=" << myEdgePos
2189 : // << " y=" << myPosLat
2190 : // << " latOffset=" << lateral_offset
2191 : // << " shape=" << myWalkingAreaPath->shape
2192 : // << " pos=" << myWalkingAreaPath->shape.positionAtOffset(myEdgePos, lateral_offset)
2193 : // << "\n";
2194 : //}
2195 9396763 : if (myWalkingAreaPath->angleOverride == INVALID_DOUBLE) {
2196 9209857 : return myWalkingAreaPath->shape.positionAtOffset(myEdgePos, lateral_offset);
2197 : } else {
2198 186906 : const double rotationOffset = myDir == FORWARD ? 0 : DEG2RAD(180);
2199 186906 : return myWalkingAreaPath->shape.sidePositionAtAngle(myEdgePos, lateral_offset, myWalkingAreaPath->angleOverride + rotationOffset);
2200 : }
2201 : }
2202 : }
2203 :
2204 :
2205 : double
2206 2709258 : MSPModel_Striping::PState::getAngle(const MSStageMoving&, SUMOTime) const {
2207 2709258 : if (myAngle != std::numeric_limits<double>::max()) {
2208 : return myAngle;
2209 : }
2210 825541 : if (myLane == nullptr) {
2211 : // pedestrian has already finished
2212 : return 0;
2213 : }
2214 825318 : if (myWalkingAreaPath != nullptr && myWalkingAreaPath->angleOverride != INVALID_DOUBLE) {
2215 : return myWalkingAreaPath->angleOverride;
2216 : }
2217 775673 : const PositionVector& shp = myWalkingAreaPath == nullptr ? myLane->getShape() : myWalkingAreaPath->shape;
2218 775673 : double geomX = myWalkingAreaPath == nullptr ? myLane->interpolateLanePosToGeometryPos(myEdgePos) : myEdgePos;
2219 775673 : double angle = shp.rotationAtOffset(geomX) + (myDir == MSPModel::BACKWARD ? M_PI : 0);
2220 775673 : if (myDir == MSPModel::BACKWARD) {
2221 238551 : angle += atan2(mySpeedLat, MAX2(mySpeed, NUMERICAL_EPS));
2222 : } else { // myDir == MSPModel::FORWARD
2223 679820 : angle -= atan2(mySpeedLat, MAX2(mySpeed, NUMERICAL_EPS));
2224 : }
2225 775673 : if (angle > M_PI) {
2226 171716 : angle -= 2 * M_PI;
2227 : }
2228 775673 : myAngle = angle;
2229 775673 : return angle;
2230 : }
2231 :
2232 :
2233 : const MSEdge*
2234 166320 : MSPModel_Striping::PState::getNextEdge(const MSStageMoving&) const {
2235 166320 : return myNLI.lane == nullptr ? nullptr : &myNLI.lane->getEdge();
2236 : }
2237 :
2238 :
2239 : const MSLane*
2240 1688 : MSPModel_Striping::PState::getNextCrossing() const {
2241 1688 : return myNLI.lane != nullptr && myNLI.lane->isCrossing() ? myNLI.lane : nullptr;
2242 : }
2243 :
2244 :
2245 : void
2246 3425 : MSPModel_Striping::PState::reverse(const double pathLength, const double usableWidth) {
2247 3425 : myEdgePos = pathLength - myEdgePos;
2248 3425 : myPosLat = usableWidth - myPosLat;
2249 3425 : myDir = -myWalkingAreaPath->dir;
2250 3425 : mySpeedLat = -mySpeedLat;
2251 3425 : }
2252 :
2253 :
2254 : void
2255 243636 : MSPModel_Striping::PState::reset(const double edgePos, const double latPos) {
2256 243636 : myEdgePos = edgePos;
2257 243636 : myPosLat = latPos;
2258 243636 : myDir = UNDEFINED_DIRECTION; // only an obstacle, speed may be orthogonal to dir
2259 243636 : mySpeed = 0.;
2260 243636 : mySpeedLat = 0.;
2261 243636 : }
2262 :
2263 :
2264 : void
2265 18 : MSPModel_Striping::PState::moveTo(MSPerson* p, MSLane* lane, double lanePos, double lanePosLat, SUMOTime t) {
2266 : ConstMSEdgeVector newEdges; // keep route
2267 : int routeOffset = 0;
2268 : bool laneOnRoute = false;
2269 18 : const MSJunction* laneOnJunction = lane->isNormal() ? nullptr : lane->getEdge().getToJunction();
2270 18 : for (const MSEdge* edge : myStage->getRoute()) {
2271 : if (edge == &lane->getEdge()
2272 14 : || edge->getToJunction() == laneOnJunction
2273 18 : || edge->getFromJunction() == laneOnJunction) {
2274 : laneOnRoute = true;
2275 : break;
2276 : }
2277 0 : routeOffset++;
2278 : }
2279 18 : if (!laneOnRoute) {
2280 0 : throw ProcessError("Lane '" + lane->getID() + "' is not on the route of person '" + getID() + "'.");
2281 : }
2282 18 : Position pos = lane->geometryPositionAtOffset(lanePos, lanePosLat);
2283 18 : if (lane->getEdge().isWalkingArea() && (myWalkingAreaPath == nullptr || myWalkingAreaPath->lane != lane)) {
2284 : // entered new walkingarea. Determine path to guess position
2285 10 : const MSEdge* prevEdge = myStage->getRoute()[routeOffset];
2286 10 : const MSEdge* nextEdge = routeOffset + 1 < (int)myStage->getRoute().size() ? myStage->getRoute()[routeOffset + 1] : nullptr;
2287 10 : const WalkingAreaPath* guessed = guessPath(&lane->getEdge(), prevEdge, nextEdge);
2288 10 : const double maxPos = guessed->shape.length() - NUMERICAL_EPS;
2289 10 : if (lanePos > maxPos + POSITION_EPS || lanePos < -POSITION_EPS) {
2290 0 : throw ProcessError("Lane position " + toString(lanePos) + " cannot be mapped onto walkingarea '" + lane->getID()
2291 0 : + "' (fromLane='" + guessed->from->getID()
2292 0 : + "' toLane='" + guessed->to->getID() + "') for person '" + getID() + "' time=" + time2string(t) + ".");
2293 : }
2294 : // give some slack
2295 10 : lanePos = MIN2(maxPos, MAX2(NUMERICAL_EPS, lanePos));
2296 10 : pos = guessed->shape.positionAtOffset(lanePos, lanePosLat);
2297 : }
2298 18 : const double angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
2299 18 : moveToXY(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, newEdges, t);
2300 18 : }
2301 :
2302 :
2303 : void
2304 14094 : MSPModel_Striping::PState::moveToXY(MSPerson* p, Position pos, MSLane* lane, double lanePos,
2305 : double lanePosLat, double angle, int routeOffset,
2306 : const ConstMSEdgeVector& edges, SUMOTime t) {
2307 14094 : MSPModel_Striping* pm = dynamic_cast<MSPModel_Striping*>(MSNet::getInstance()->getPersonControl().getMovementModel());
2308 : assert(p == myPerson);
2309 : assert(pm != nullptr);
2310 14094 : const double oldAngle = GeomHelper::naviDegree(getAngle(*myStage, t));
2311 : // person already walking in this step. undo this to obtain the previous position
2312 14094 : const double oldX = myEdgePos - SPEED2DIST(mySpeed * myDir);
2313 : const double tmp = myEdgePos;
2314 14094 : myEdgePos = oldX;
2315 14094 : Position oldPos = getPosition(*myStage, t);
2316 14094 : myEdgePos = tmp;
2317 : //if (oldPos == Position::INVALID) {
2318 : // oldPos = pos
2319 : //}
2320 14094 : myAngle = GeomHelper::fromNaviDegree(angle);
2321 : #ifdef DEBUG_MOVETOXY
2322 : std::cout << SIMTIME << " ped=" << p->getID()
2323 : << " moveToXY"
2324 : << " pos=" << pos
2325 : << " lane=" << lane->getID()
2326 : << " lanePos=" << lanePos
2327 : << " lanePosLat=" << lanePosLat
2328 : << " angle=" << angle
2329 : << " routeOffset=" << routeOffset
2330 : << " edges=" << toString(edges)
2331 : << " oldLane=" << Named::getIDSecure(myLane)
2332 : << " path=" << (myWalkingAreaPath == nullptr ? "null" : (myWalkingAreaPath->from->getID() + "->" + myWalkingAreaPath->to->getID())) << "\n";
2333 : #endif
2334 :
2335 14094 : if (lane != myLane && myLane != nullptr && lane != nullptr) {
2336 355 : pm->remove(this);
2337 : pm->registerActive();
2338 : }
2339 14094 : if (lane != nullptr &&
2340 10962 : fabs(lanePosLat) < (0.5 * (lane->getWidth() + p->getVehicleType().getWidth()) + SIDEWALK_OFFSET)) {
2341 10957 : myRemoteXYPos = Position::INVALID;
2342 10957 : const MSEdge* old = myStage->getEdge();
2343 10957 : const MSLane* oldLane = myLane;
2344 10957 : if (lane != myLane) {
2345 : // implicitly adds new active lane if necessary
2346 355 : pm->myActiveLanes[lane].push_back(this);
2347 : }
2348 10957 : if (edges.empty()) {
2349 : // map within route
2350 10908 : myStage->setRouteIndex(myPerson, routeOffset);
2351 : } else {
2352 49 : myStage->replaceRoute(myPerson, edges, routeOffset);
2353 : }
2354 10957 : if (!lane->getEdge().isNormal()) {
2355 524 : myStage->moveToNextEdge(myPerson, t, myDir, &lane->getEdge());
2356 : }
2357 :
2358 10957 : myLane = lane;
2359 10957 : const double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
2360 10957 : if (lane->getEdge().isWalkingArea()) {
2361 255 : if (myWalkingAreaPath == nullptr || myWalkingAreaPath->lane != lane) {
2362 : // entered new walkingarea. Determine path
2363 55 : myWalkingAreaPath = guessPath(&lane->getEdge(), old, myStage->getNextRouteEdge());
2364 : #ifdef DEBUG_MOVETOXY
2365 : std::cout << " guessPath old=" << old->getID() << " next=" << Named::getIDSecure(myStage->getNextRouteEdge())
2366 : << " path=" << myWalkingAreaPath->from->getID() << "->" << myWalkingAreaPath->to->getID() << "\n";
2367 : #endif
2368 : }
2369 : // lanePos and lanePosLat are matched onto the circumference of the
2370 : // walkingarea. Use pos instead
2371 255 : const Position relPos = myWalkingAreaPath->shape.transformToVectorCoordinates(pos);
2372 : if (relPos == Position::INVALID) {
2373 0 : WRITE_WARNING("Could not map position " + toString(pos) + " onto lane '" + myLane->getID()
2374 : + "' (fromLane='" + myWalkingAreaPath->from->getID()
2375 : + "' toLane='" + myWalkingAreaPath->to->getID() + "') for person '" + getID() + "' time=" + time2string(t) + ".");
2376 0 : myRemoteXYPos = pos;
2377 : } else {
2378 255 : myEdgePos = relPos.x();
2379 255 : myPosLat = lateral_offset + relPos.y();
2380 : }
2381 : } else {
2382 10702 : myWalkingAreaPath = nullptr;
2383 10702 : myEdgePos = lanePos;
2384 10702 : myPosLat = lateral_offset - lanePosLat;
2385 : lane->requireCollisionCheck();
2386 : }
2387 : // guess direction
2388 10957 : const double angleDiff = GeomHelper::getMinAngleDiff(angle, oldAngle);
2389 10957 : if (myStage->getNextRouteEdge() != nullptr) {
2390 6498 : if (myStage->getEdge()->getToJunction() == myStage->getNextRouteEdge()->getFromJunction() ||
2391 939 : myStage->getEdge()->getToJunction() == myStage->getNextRouteEdge()->getToJunction()) {
2392 4730 : myDir = FORWARD;
2393 : } else {
2394 829 : myDir = BACKWARD;
2395 : }
2396 : } else {
2397 : // guess from angle
2398 5398 : if (angleDiff <= 90) {
2399 : // keep direction
2400 5334 : if (myDir == UNDEFINED_DIRECTION) {
2401 0 : myDir = FORWARD;
2402 : }
2403 : } else {
2404 : // change direction
2405 64 : myDir = (myDir == BACKWARD) ? FORWARD : BACKWARD;
2406 : }
2407 : }
2408 : // update next lane info (after guessing direction)
2409 10957 : if (oldLane == nullptr || &oldLane->getEdge() != &myLane->getEdge()) {
2410 313 : const MSLane* sidewalk = getSidewalk<MSEdge, MSLane>(&myLane->getEdge(), p->getVClass());
2411 : // assume that we will eventually move back onto the sidewalk if
2412 : // there is one
2413 313 : myNLI = getNextLane(*this, sidewalk == nullptr ? myLane : sidewalk, nullptr);
2414 313 : myStage->activateEntryReminders(myPerson);
2415 : #ifdef DEBUG_MOVETOXY
2416 : std::cout << " myNLI=" << Named::getIDSecure(myNLI.lane) << " link=" << (myNLI.link == nullptr ? "NULL" : myNLI.link->getDescription()) << " dir=" << myNLI.dir << "\n";
2417 : #endif
2418 : }
2419 : #ifdef DEBUG_MOVETOXY
2420 : std::cout << " newRelPos=" << Position(myEdgePos, myPosLat) << " edge=" << myPerson->getEdge()->getID()
2421 : << " newPos=" << myPerson->getPosition()
2422 : << " latOffset=" << getLatOffset()
2423 : << " oldAngle=" << oldAngle << " angleDiff=" << angleDiff << " newDir=" << myDir << "\n";
2424 : #endif
2425 10957 : if (oldLane == myLane) {
2426 10602 : mySpeed = DIST2SPEED(fabs(oldX - myEdgePos));
2427 : } else {
2428 : //std::cout << SIMTIME << " oldX=" << oldX << " oldSpeed=" << mySpeed << " oldPos=" << oldPos << " pos=" << pos << " dist=" << oldPos.distanceTo2D(pos) << " oldLane=" << Named::getIDSecure(oldLane) << " lane=" << lane->getID() << "\n";
2429 355 : mySpeed = DIST2SPEED(oldPos.distanceTo2D(pos));
2430 : }
2431 : } else {
2432 : // map outside the network
2433 3137 : myRemoteXYPos = pos;
2434 3137 : mySpeed = DIST2SPEED(oldPos.distanceTo2D(pos));
2435 : }
2436 :
2437 14094 : }
2438 :
2439 :
2440 : double
2441 731245 : MSPModel_Striping::PState::getPathLength() const {
2442 731245 : if (myWalkingAreaPath != nullptr) {
2443 673162 : return myWalkingAreaPath->length;
2444 : } else {
2445 : return 0;
2446 : }
2447 : }
2448 :
2449 : double
2450 1452864030 : MSPModel_Striping::PState::distanceTo(const Obstacle& obs, const bool includeMinGap) const {
2451 : // check for overlap
2452 1452864030 : const double maxX = getMaxX(includeMinGap);
2453 1452864030 : const double minX = getMinX(includeMinGap);
2454 : //if (DEBUGCOND(*this)) {
2455 : // std::cout << std::setprecision(2) << " distanceTo=" << obs.description << " maxX=" << maxX << " minX=" << minX << " obs.xFwd=" << obs.xFwd << " obs.xBack=" << obs.xBack << "\n";
2456 : //}
2457 1452864030 : if ((obs.xFwd >= maxX && obs.xBack <= maxX) || (obs.xFwd <= maxX && obs.xFwd >= minX)) {
2458 : // avoid blocking by itself on looped route
2459 409605148 : return (obs.type == OBSTACLE_PED && obs.description == myPerson->getID()) ? DIST_FAR_AWAY : DIST_OVERLAP;
2460 : }
2461 1043258882 : if (myDir == FORWARD) {
2462 933469983 : return obs.xFwd < minX ? DIST_BEHIND : obs.xBack - maxX;
2463 : } else {
2464 109788899 : return obs.xBack > maxX ? DIST_BEHIND : minX - obs.xFwd;
2465 : }
2466 : }
2467 :
2468 :
2469 : void
2470 84748457 : MSPModel_Striping::PState::mergeObstacles(Obstacles& into, const Obstacles& obs2) {
2471 373679379 : for (int i = 0; i < (int)into.size(); ++i) {
2472 288930922 : if (gDebugFlag1) {
2473 0 : std::cout << " i=" << i << " maxX=" << getMaxX(true) << " minX=" << getMinX(true)
2474 0 : << " into=" << into[i].description << " iDist=" << distanceTo(into[i], into[i].type == OBSTACLE_PED)
2475 0 : << " obs2=" << obs2[i].description << " oDist=" << distanceTo(obs2[i], obs2[i].type == OBSTACLE_PED) << "\n";
2476 : }
2477 288930922 : const double dO = distanceTo(obs2[i], obs2[i].type == OBSTACLE_PED);
2478 288930922 : const double dI = distanceTo(into[i], into[i].type == OBSTACLE_PED);
2479 288930922 : if (dO < dI) {
2480 : into[i] = obs2[i];
2481 : } else if (dO == dI
2482 71307550 : && into[i].type != OBSTACLE_PED
2483 33781685 : && into[i].type != OBSTACLE_VEHICLE
2484 278061630 : && (obs2[i].type == OBSTACLE_PED ||
2485 : obs2[i].type == OBSTACLE_VEHICLE)) {
2486 : into[i] = obs2[i];
2487 : }
2488 : }
2489 84748457 : }
2490 :
2491 : void
2492 18622 : MSPModel_Striping::PState::mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset) {
2493 146338 : for (int i = 0; i < (int)into.size(); ++i) {
2494 127716 : int i2 = i + offset;
2495 127716 : if (i2 >= 0 && i2 < (int)obs2.size()) {
2496 126440 : if (dir == FORWARD) {
2497 91522 : if (obs2[i2].xBack < into[i].xBack) {
2498 : into[i] = obs2[i2];
2499 : }
2500 : } else {
2501 34918 : if (obs2[i2].xFwd > into[i].xFwd) {
2502 : into[i] = obs2[i2];
2503 : }
2504 : }
2505 : }
2506 : }
2507 18622 : }
2508 :
2509 :
2510 : bool
2511 11258066 : MSPModel_Striping::PState::ignoreRed(const MSLink* link) const {
2512 11258066 : if (link->haveRed()) {
2513 648950 : const double ignoreRedTime = myPerson->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME, -1);
2514 648950 : if (ignoreRedTime >= 0) {
2515 40 : const double redDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
2516 40 : if (DEBUGCOND(*this)) {
2517 0 : std::cout << SIMTIME << " ignoreRedTime=" << ignoreRedTime << " redDuration=" << redDuration << "\n";
2518 : }
2519 40 : return ignoreRedTime > redDuration;
2520 : } else {
2521 : return false;
2522 : }
2523 : } else {
2524 : return false;
2525 : }
2526 : }
2527 :
2528 :
2529 : bool
2530 10564135 : MSPModel_Striping::PState::stopForYellow(const MSLink* link) const {
2531 : // main use case is at rail_crossing
2532 10564135 : if (link->haveYellow()) {
2533 782 : const double ignoreYellowTime = myPerson->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME, -1);
2534 782 : if (ignoreYellowTime >= 0) {
2535 0 : const double yellowDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
2536 0 : if (DEBUGCOND(*this)) {
2537 0 : std::cout << SIMTIME << " ignoreYellowTime=" << ignoreYellowTime << " yellowDuration=" << yellowDuration << "\n";
2538 : }
2539 0 : return ignoreYellowTime < yellowDuration;
2540 : } else {
2541 : return true;
2542 : }
2543 : } else {
2544 : return false;
2545 : }
2546 : }
2547 :
2548 : double
2549 3235341582 : MSPModel_Striping::PState::getWidth() const {
2550 3235341582 : return myPerson->getVehicleType().getWidth();
2551 : }
2552 :
2553 :
2554 : bool
2555 124843522 : MSPModel_Striping::PState::isRemoteControlled() const {
2556 124843522 : return myPerson->hasInfluencer() && myPerson->getInfluencer().isRemoteControlled();
2557 : }
2558 :
2559 : // ===========================================================================
2560 : // MSPModel_Striping::PStateVehicle method definitions
2561 : // ===========================================================================
2562 :
2563 495398 : MSPModel_Striping::PStateVehicle::PStateVehicle(const MSVehicle* veh, const MSLane* walkingarea, double relX, double relY, double xWidth, double yWidth):
2564 495398 : myVehicle(veh), myXWidth(xWidth), myYWidth(yWidth) {
2565 495398 : myLane = walkingarea; // to ensure correct limits when calling otherStripe()
2566 : // relX is the center but we want it to be the max value if the movement direction is forward
2567 : // and the min value otherwise (indicated by xWidth sign)
2568 495398 : myEdgePos = relX + xWidth / 2;
2569 495398 : myPosLat = relY;
2570 495398 : }
2571 :
2572 : const std::string&
2573 1933972 : MSPModel_Striping::PStateVehicle::getID() const {
2574 1933972 : return myVehicle->getID();
2575 : }
2576 :
2577 : double
2578 999830 : MSPModel_Striping::PStateVehicle::getWidth() const {
2579 999830 : return myYWidth;
2580 : }
2581 :
2582 : double
2583 529902 : MSPModel_Striping::PStateVehicle::getMinX(const bool /*includeMinGap*/) const {
2584 529902 : return myXWidth > 0 ? myEdgePos - myXWidth : myEdgePos;
2585 : }
2586 :
2587 : double
2588 529902 : MSPModel_Striping::PStateVehicle::getMaxX(const bool /*includeMinGap*/) const {
2589 529902 : return myXWidth > 0 ? myEdgePos : myEdgePos - myXWidth;
2590 : }
2591 :
2592 : // ===========================================================================
2593 : // MSPModel_Striping::MovePedestrians method definitions
2594 : // ===========================================================================
2595 :
2596 : SUMOTime
2597 9312955 : MSPModel_Striping::MovePedestrians::execute(SUMOTime currentTime) {
2598 : std::set<MSPerson*> changedLane;
2599 9312955 : myModel->moveInDirection(currentTime, changedLane, FORWARD);
2600 9312951 : myModel->moveInDirection(currentTime, changedLane, BACKWARD);
2601 : // DEBUG
2602 : #ifdef LOG_ALL
2603 : for (ActiveLanes::const_iterator it_lane = myModel->getActiveLanes().begin(); it_lane != myModel->getActiveLanes().end(); ++it_lane) {
2604 : const MSLane* lane = it_lane->first;
2605 : Pedestrians pedestrians = it_lane->second;
2606 : if (pedestrians.size() == 0) {
2607 : continue;
2608 : }
2609 : sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(FORWARD));
2610 : std::cout << SIMTIME << " lane=" << lane->getID();
2611 : for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
2612 : const PState& p = *pedestrians[ii];
2613 : std::cout << " (" << p.getPerson()->getID() << " " << p.myEdgePos << "," << p.myPosLat << " " << p.getDirection() << ")";
2614 : }
2615 : std::cout << "\n";
2616 : }
2617 : #endif
2618 9312951 : return DELTA_T;
2619 : }
|