SUMO - Simulation of Urban MObility
MSPModel_Striping.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2014-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // The pedestrian following model (prototype)
17 /****************************************************************************/
18 
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23 
24 #include <cmath>
25 #include <algorithm>
27 #include <utils/geom/GeomHelper.h>
30 #include <microsim/MSNet.h>
31 #include <microsim/MSEdge.h>
33 #include <microsim/MSLane.h>
34 #include <microsim/MSJunction.h>
35 #include <microsim/MSGlobals.h>
37 #include "MSPModel_Striping.h"
38 
39 
40 // ===========================================================================
41 // DEBUGGING HELPERS
42 // ===========================================================================
43 //
44 #define DEBUGID1 ""
45 #define DEBUGID2 ""
46 //#define DEBUGCOND(PED) (false)
47 //#define DEBUGCOND(PED) ((PED).myPerson->getID() == DEBUGID1 || (PED).myPerson->getID() == DEBUGID2)
48 #define DEBUGCOND(PED) ((PED).myPerson->isSelected())
49 #define DEBUGCOND2(LANE) ((LANE)->isSelected())
50 //#define LOG_ALL 1
51 
53  for (int i = 0; i < (int)obs.size(); ++i) {
54  std::cout
55  << "(" << obs[i].description
56  << " x=(" << obs[i].xBack << "," << obs[i].xFwd
57  << ") s=" << obs[i].speed
58  << ") ";
59  }
60  std::cout << "\n";
61 }
62 
63 // ===========================================================================
64 // named (internal) constants
65 // ===========================================================================
66 
67 // distances are comparable with lower values being "more important"
68 const double MSPModel_Striping::DIST_FAR_AWAY(10000);
69 const double MSPModel_Striping::DIST_BEHIND(1000);
70 const double MSPModel_Striping::DIST_OVERLAP(-1);
71 
72 // ===========================================================================
73 // static members
74 // ===========================================================================
75 
79 
80 
81 // model parameters (static to simplify access from class PState
85 const double MSPModel_Striping::LOOKAHEAD_SAMEDIR(4.0); // seconds
86 const double MSPModel_Striping::LOOKAHEAD_ONCOMING(10.0); // seconds
87 const double MSPModel_Striping::LOOKAROUND_VEHICLES(60.0); // meters
88 const double MSPModel_Striping::LATERAL_PENALTY(-1.); // meters
89 const double MSPModel_Striping::OBSTRUCTED_PENALTY(-300000.); // meters
90 const double MSPModel_Striping::INAPPROPRIATE_PENALTY(-20000.); // meters
91 const double MSPModel_Striping::ONCOMING_CONFLICT_PENALTY(-1000.); // meters
92 const double MSPModel_Striping::OBSTRUCTION_THRESHOLD(MSPModel_Striping::OBSTRUCTED_PENALTY * 0.5); // despite obstruction, additional utility may have been added
93 const double MSPModel_Striping::SQUEEZE(0.7);
96 const double MSPModel_Striping::MAX_WAIT_TOLERANCE(120.); // seconds
98 const double MSPModel_Striping::MIN_STARTUP_DIST(0.4); // meters
99 
100 #define MINGAP_TO_VEHICLE 0.25
101 
102 
103 // ===========================================================================
104 // MSPModel_Striping method definitions
105 // ===========================================================================
106 
111  // configurable parameters
112  stripeWidth = oc.getFloat("pedestrian.striping.stripe-width");
113  dawdling = oc.getFloat("pedestrian.striping.dawdling");
114 
115  jamTime = string2time(oc.getString("pedestrian.striping.jamtime"));
116  if (jamTime <= 0) {
118  }
119 }
120 
121 
123 }
124 
125 
129  const MSLane* lane = getSidewalk<MSEdge, MSLane>(person->getEdge());
130  if (lane == nullptr) {
131  std::string error = "Person '" + person->getID() + "' could not find sidewalk on edge '" + person->getEdge()->getID() + "', time="
132  + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".";
133  if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
134  WRITE_WARNING(error);
135  return nullptr;
136  } else {
137  throw ProcessError(error);
138  }
139  }
140  PState* ped = new PState(person, stage, lane);
141  myActiveLanes[lane].push_back(ped);
143  return ped;
144 }
145 
146 
147 void
149  PState* ped = dynamic_cast<PState*>(pState);
150  assert(ped != 0);
151  myActiveLanes[lane].push_back(ped);
152 }
153 
154 
155 void
157  const MSLane* lane = dynamic_cast<PState*>(state)->myLane;
158  Pedestrians& pedestrians = myActiveLanes[lane];
159  for (Pedestrians::iterator it = pedestrians.begin(); it != pedestrians.end(); ++it) {
160  if (*it == state) {
161  pedestrians.erase(it);
162  return;
163  }
164  }
165 }
166 
167 
168 bool
169 MSPModel_Striping::blockedAtDist(const MSLane* lane, double vehSide, double vehWidth,
170  double oncomingGap, std::vector<const MSPerson*>* collectBlockers) {
171  const Pedestrians& pedestrians = getPedestrians(lane);
172  for (Pedestrians::const_iterator it_ped = pedestrians.begin(); it_ped != pedestrians.end(); ++it_ped) {
173  const PState& ped = **it_ped;
174  const double leaderFrontDist = (ped.myDir == FORWARD ? vehSide - ped.myRelX : ped.myRelX - vehSide);
175  const double leaderBackDist = leaderFrontDist + ped.getLength();
176  if DEBUGCOND(ped) {
177  std::cout << SIMTIME << " lane=" << lane->getID() << " dir=" << ped.myDir << " pX=" << ped.myRelX << " pL=" << ped.getLength()
178  << " vehSide=" << vehSide
179  << " vehWidth=" << vehWidth
180  << " lBD=" << leaderBackDist
181  << " lFD=" << leaderFrontDist
182  << "\n";
183  }
184  if (leaderBackDist >= -vehWidth
185  && (leaderFrontDist < 0
186  // give right of way to (close) approaching pedestrians unless they are standing
187  || (leaderFrontDist <= oncomingGap && ped.myWaitingTime < TIME2STEPS(2.0)))) {
188  // found one pedestrian that is not completely past the crossing point
189  //std::cout << SIMTIME << " blocking pedestrian foeLane=" << lane->getID() << " ped=" << ped.myPerson->getID() << " dir=" << ped.myDir << " pX=" << ped.myRelX << " pL=" << ped.getLength() << " fDTC=" << distToCrossing << " lBD=" << leaderBackDist << "\n";
190  if (collectBlockers == nullptr) {
191  return true;
192  } else {
193  collectBlockers->push_back(ped.myPerson);
194  }
195  }
196  }
197  if (collectBlockers == nullptr) {
198  return false;
199  } else {
200  return collectBlockers->size() > 0;
201  }
202 }
203 
204 
205 bool
207  return getPedestrians(lane).size() > 0;
208 }
209 
210 
211 bool
213  return usingInternalLanesStatic();
214 }
215 
216 bool
219 }
220 
222 MSPModel_Striping::nextBlocking(const MSLane* lane, double minPos, double minRight, double maxLeft, double stopTime) {
223  PersonDist result((const MSPerson*)nullptr, -1);
224  double closest = std::numeric_limits<double>::max();
225  const Pedestrians& pedestrians = getPedestrians(lane);
226  for (Pedestrians::const_iterator it_ped = pedestrians.begin(); it_ped != pedestrians.end(); ++it_ped) {
227  const PState& ped = **it_ped;
228  // account for distance covered by oncoming pedestrians
229  double relX2 = ped.myRelX - (ped.myDir == FORWARD ? 0 : stopTime * ped.myPerson->getVehicleType().getMaxSpeed());
230  if (ped.myRelX > minPos && (result.first == 0 || closest > relX2)) {
231  const double center = lane->getWidth() - (ped.myRelY + stripeWidth * 0.5);
232  const double halfWidth = 0.5 * ped.myPerson->getVehicleType().getWidth();
233  const bool overlap = (center + halfWidth > minRight && center - halfWidth < maxLeft);
234  if DEBUGCOND(ped) {
235  std::cout << " nextBlocking lane=" << lane->getID()
236  << " minPos=" << minPos << " minRight=" << minRight << " maxLeft=" << maxLeft
237  << " stopTime=" << stopTime
238  << " pedY=" << ped.myRelY
239  << " pedX=" << ped.myRelX
240  << " relX2=" << relX2
241  << " center=" << center
242  << " pedLeft=" << center + halfWidth
243  << " pedRight=" << center - halfWidth
244  << " overlap=" << overlap
245  << "\n";
246  }
247  if (overlap) {
248  closest = relX2;
249  result.first = ped.myPerson;
250  result.second = relX2 - minPos - (ped.myDir == FORWARD ? ped.myPerson->getVehicleType().getLength() : 0);
251  }
252  }
253  }
254  return result;
255 }
256 
257 
260  ActiveLanes::iterator it = myActiveLanes.find(lane);
261  if (it != myActiveLanes.end()) {
262  //std::cout << " found lane=" << lane->getID() << " n=" << it->second.size() << "\n";
263  return (it->second);
264  } else {
265  return noPedestrians;
266  }
267 }
268 
269 
270 void
272  myActiveLanes.clear();
274  myWalkingAreaPaths.clear(); // need to recompute when lane pointers change
275  myMinNextLengths.clear();
276 }
277 
278 
279 int
281  return (int)floor(lane->getWidth() / stripeWidth);
282 }
283 
284 int
286  if (from == nullptr || to == nullptr) {
287  return UNDEFINED_DIRECTION;
288  } else if (MSLinkContHelper::getConnectingLink(*from, *to)) {
289  return FORWARD;
290  } else if (MSLinkContHelper::getConnectingLink(*to, *from)) {
291  return BACKWARD;
292  } else {
293  return UNDEFINED_DIRECTION;
294  }
295 }
296 
297 
298 void
300  if (myWalkingAreaPaths.size() > 0) {
301  return;
302  }
303  for (MSEdgeVector::const_iterator i = MSEdge::getAllEdges().begin(); i != MSEdge::getAllEdges().end(); ++i) {
304  const MSEdge* edge = *i;
305  if (edge->isWalkingArea()) {
306  const MSLane* walkingArea = getSidewalk<MSEdge, MSLane>(edge);
307  myMinNextLengths[walkingArea] = walkingArea->getLength();
308  // build all possible paths across this walkingArea
309  // gather all incident lanes
310  std::vector<const MSLane*> lanes;
311  const MSEdgeVector& incoming = edge->getPredecessors();
312  for (int j = 0; j < (int)incoming.size(); ++j) {
313  lanes.push_back(getSidewalk<MSEdge, MSLane>(incoming[j]));
314  }
315  const MSEdgeVector& outgoing = edge->getSuccessors();
316  for (int j = 0; j < (int)outgoing.size(); ++j) {
317  lanes.push_back(getSidewalk<MSEdge, MSLane>(outgoing[j]));
318  }
319  // build all combinations
320  for (int j = 0; j < (int)lanes.size(); ++j) {
321  for (int k = 0; k < (int)lanes.size(); ++k) {
322  if (j != k) {
323  // build the walkingArea
324  const MSLane* from = lanes[j];
325  const MSLane* to = lanes[k];
326  const int fromDir = MSLinkContHelper::getConnectingLink(*from, *walkingArea) != nullptr ? FORWARD : BACKWARD;
327  const int toDir = MSLinkContHelper::getConnectingLink(*walkingArea, *to) != nullptr ? FORWARD : BACKWARD;
328  PositionVector shape;
329  Position fromPos = from->getShape()[fromDir == FORWARD ? -1 : 0];
330  Position toPos = to->getShape()[toDir == FORWARD ? 0 : -1];
331  const double maxExtent = fromPos.distanceTo2D(toPos) / 4; // prevent sharp corners
332  const double extrapolateBy = MIN2(maxExtent, walkingArea->getWidth() / 2);
333  // assemble shape
334  shape.push_back(fromPos);
335  if (extrapolateBy > POSITION_EPS) {
336  PositionVector fromShp = from->getShape();
337  fromShp.extrapolate(extrapolateBy);
338  shape.push_back_noDoublePos(fromDir == FORWARD ? fromShp.back() : fromShp.front());
339  PositionVector nextShp = to->getShape();
340  nextShp.extrapolate(extrapolateBy);
341  shape.push_back_noDoublePos(toDir == FORWARD ? nextShp.front() : nextShp.back());
342  }
343  shape.push_back_noDoublePos(toPos);
344  if (shape.size() < 2) {
345  PositionVector fromShp = from->getShape();
346  fromShp.extrapolate(1.5 * POSITION_EPS); // noDoublePos requires a difference of POSITION_EPS in at least one coordinate
347  shape.push_back_noDoublePos(fromDir == FORWARD ? fromShp.back() : fromShp.front());
348  assert(shape.size() == 2);
349  }
350  if (fromDir == BACKWARD) {
351  // will be walking backward on walkingArea
352  shape = shape.reverse();
353  }
354  WalkingAreaPath wap = WalkingAreaPath(from, walkingArea, to, shape);
355  myWalkingAreaPaths[std::make_pair(from, to)] = wap;
356  myMinNextLengths[walkingArea] = MIN2(myMinNextLengths[walkingArea], wap.length);
357  }
358  }
359  }
360  }
361  }
362 }
363 
364 
367  assert(walkingArea->isWalkingArea());
368  std::vector<const MSLane*> lanes;
369  const MSEdgeVector& incoming = walkingArea->getPredecessors();
370  for (int j = 0; j < (int)incoming.size(); ++j) {
371  lanes.push_back(getSidewalk<MSEdge, MSLane>(incoming[j]));
372  }
373  const MSEdgeVector& outgoing = walkingArea->getSuccessors();
374  for (int j = 0; j < (int)outgoing.size(); ++j) {
375  lanes.push_back(getSidewalk<MSEdge, MSLane>(outgoing[j]));
376  }
377  if (lanes.size() < 1) {
378  throw ProcessError("Invalid walkingarea '" + walkingArea->getID() + "' does not allow continuation.");
379  }
380  return &myWalkingAreaPaths[std::make_pair(lanes.front(), lanes.back())];
381 }
382 
383 
385 MSPModel_Striping::getNextLane(const PState& ped, const MSLane* currentLane, const MSLane* prevLane) {
386  const MSEdge* currentEdge = &currentLane->getEdge();
387  const MSJunction* junction = ped.myDir == FORWARD ? currentEdge->getToJunction() : currentEdge->getFromJunction();
388  const MSEdge* nextRouteEdge = ped.myStage->getNextRouteEdge();
389  const MSLane* nextRouteLane = getSidewalk<MSEdge, MSLane>(nextRouteEdge);
390  // result values
391  const MSLane* nextLane = nextRouteLane;
392  MSLink* link = nullptr;
393  int nextDir = UNDEFINED_DIRECTION;
394 
395  if (nextRouteLane == nullptr && nextRouteEdge != nullptr) {
396  std::string error = "Person '" + ped.myPerson->getID() + "' could not find sidewalk on edge '" + nextRouteEdge->getID() + "', time="
397  + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".";
398  if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
399  WRITE_WARNING(error);
400  nextRouteLane = nextRouteEdge->getLanes().front();
401  } else {
402  throw ProcessError(error);
403  }
404  }
405 
406  if (nextRouteLane != nullptr) {
407  if (currentEdge->isInternal()) {
408  assert(junction == currentEdge->getFromJunction());
409  nextDir = junction == nextRouteEdge->getFromJunction() ? FORWARD : BACKWARD;
410  if (nextDir == FORWARD) {
411  nextLane = currentLane->getLinkCont()[0]->getViaLaneOrLane();
412  } else {
413  nextLane = currentLane->getLogicalPredecessorLane();
414  }
415  if DEBUGCOND(ped) {
416  std::cout << " internal\n";
417  }
418  } else if (currentEdge->isCrossing()) {
419  nextDir = ped.myDir;
420  if (ped.myDir == FORWARD) {
421  nextLane = currentLane->getLinkCont()[0]->getLane();
422  } else {
423  nextLane = currentLane->getLogicalPredecessorLane();
424  }
425  if DEBUGCOND(ped) {
426  std::cout << " crossing\n";
427  }
428  } else if (currentEdge->isWalkingArea()) {
429  ConstMSEdgeVector crossingRoute;
430  // departPos can be 0 because the direction of the walkingArea does not matter
431  // for the arrivalPos, we need to make sure that the route does not deviate across other junctions
432  const int nextRouteEdgeDir = nextRouteEdge->getFromJunction() == junction ? FORWARD : BACKWARD;
433  const double arrivalPos = (nextRouteEdge == ped.myStage->getRoute().back()
434  ? ped.myStage->getArrivalPos()
435  : (nextRouteEdgeDir == FORWARD ? 0 : nextRouteEdge->getLength()));
436  MSEdgeVector prohibited;
437  if (prevLane != nullptr) {
438  prohibited.push_back(&prevLane->getEdge());
439  }
440  MSNet::getInstance()->getPedestrianRouter(prohibited).compute(currentEdge, nextRouteEdge, 0, arrivalPos, ped.myStage->getMaxSpeed(ped.myPerson), 0, junction, crossingRoute, true);
441  if DEBUGCOND(ped) {
442  std::cout
443  << " nre=" << nextRouteEdge->getID()
444  << " nreDir=" << nextRouteEdgeDir
445  << " aPos=" << arrivalPos
446  << " crossingRoute=" << toString(crossingRoute)
447  << "\n";
448  }
449  if (crossingRoute.size() > 1) {
450  const MSEdge* nextEdge = crossingRoute[1];
451  nextLane = getSidewalk<MSEdge, MSLane>(crossingRoute[1]);
452  assert((nextEdge->getFromJunction() == junction || nextEdge->getToJunction() == junction));
453  assert(nextLane != prevLane);
454  nextDir = connectedDirection(currentLane, nextLane);
455  if DEBUGCOND(ped) {
456  std::cout << " nextDir=" << nextDir << "\n";
457  }
458  assert(nextDir != UNDEFINED_DIRECTION);
459  if (nextDir == FORWARD) {
460  link = MSLinkContHelper::getConnectingLink(*currentLane, *nextLane);
461  } else {
462  link = MSLinkContHelper::getConnectingLink(*nextLane, *currentLane);
463  if (nextEdge->isCrossing() && link->getTLLogic() == nullptr) {
464  const MSLane* oppositeWalkingArea = nextLane->getLogicalPredecessorLane();
465  link = MSLinkContHelper::getConnectingLink(*oppositeWalkingArea, *nextLane);
466  }
467  }
468  assert(link != 0);
469  } else {
470  if DEBUGCOND(ped) {
471  std::cout << SIMTIME
472  << " no route from '" << (currentEdge == nullptr ? "NULL" : currentEdge->getID())
473  << "' to '" << (nextRouteEdge == nullptr ? "NULL" : nextRouteEdge->getID())
474  << "\n";
475  }
476  WRITE_WARNING("Person '" + ped.myPerson->getID() + "' could not find route across junction '" + junction->getID()
477  + "' from walkingArea '" + currentEdge->getID()
478  + "' to edge '" + nextRouteEdge->getID() + "', time=" +
479  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
480  // error indicated by nextDir == UNDEFINED_DIRECTION
481  nextLane = nextRouteLane;
482  }
483  } else if (currentEdge == nextRouteEdge) {
484  // strange loop in this route. No need to use walkingArea
485  nextDir = -ped.myDir;
486  } else {
487  // normal edge. by default use next / previous walking area
488  nextDir = ped.myDir;
489  nextLane = getNextWalkingArea(currentLane, ped.myDir, link);
490  if (nextLane != nullptr) {
491  // walking area found
492  if DEBUGCOND(ped) {
493  std::cout << " next walkingArea " << (nextDir == FORWARD ? "forward" : "backward") << "\n";
494  }
495  } else {
496  // walk forward by default
497  nextDir = junction == nextRouteEdge->getToJunction() ? BACKWARD : FORWARD;
498  // try to use a direct link as fallback
499  // direct links only exist if built explicitly. They are used to model tl-controlled links if there are no crossings
500  if (ped.myDir == FORWARD) {
501  link = MSLinkContHelper::getConnectingLink(*currentLane, *nextRouteLane);
502  if (link != nullptr) {
503  if DEBUGCOND(ped) {
504  std::cout << " direct forward\n";
505  }
506  nextLane = MSLinkContHelper::getInternalFollowingLane(currentLane, nextRouteLane);
507  }
508  } else {
509  link = MSLinkContHelper::getConnectingLink(*nextRouteLane, *currentLane);
510  if (link != nullptr) {
511  if DEBUGCOND(ped) {
512  std::cout << " direct backward\n";
513  }
514  nextLane = MSLinkContHelper::getInternalFollowingLane(nextRouteLane, currentLane);
515  if (nextLane != nullptr) {
516  // advance to the end of consecutive internal lanes
517  while (nextLane->getLinkCont()[0]->getViaLaneOrLane()->isInternal()) {
518  nextLane = nextLane->getLinkCont()[0]->getViaLaneOrLane();
519  }
520  }
521  }
522  }
523  }
524  if (nextLane == nullptr) {
525  // no internal lane found
526  nextLane = nextRouteLane;
527  if DEBUGCOND(ped) {
528  std::cout << SIMTIME << " no next lane found for " << currentLane->getID() << " dir=" << ped.myDir << "\n";
529  }
530  if (usingInternalLanesStatic() && currentLane->getLinkCont().size() > 0) {
531  WRITE_WARNING("Person '" + ped.myPerson->getID() + "' could not find route across junction '" + junction->getID()
532  + "' from edge '" + currentEdge->getID()
533  + "' to edge '" + nextRouteEdge->getID() + "', time=" +
534  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
535  }
536  } else if (nextLane->getLength() <= POSITION_EPS) {
537  // internal lane too short
538  nextLane = nextRouteLane;
539  }
540  }
541  }
542  if DEBUGCOND(ped) {
543  std::cout << SIMTIME
544  << " p=" << ped.myPerson->getID()
545  << " l=" << currentLane->getID()
546  << " nl=" << (nextLane == nullptr ? "NULL" : nextLane->getID())
547  << " nrl=" << (nextRouteLane == nullptr ? "NULL" : nextRouteLane->getID())
548  << " d=" << nextDir
549  << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
550  << " pedDir=" << ped.myDir
551  << "\n";
552  }
553  assert(nextLane != 0 || nextRouteLane == 0);
554  return NextLaneInfo(nextLane, link, nextDir);
555 }
556 
557 
558 const MSLane*
559 MSPModel_Striping::getNextWalkingArea(const MSLane* currentLane, const int dir, MSLink*& link) {
560  if (dir == FORWARD) {
561  const MSLinkCont& links = currentLane->getLinkCont();
562  for (MSLinkCont::const_iterator it = links.begin(); it != links.end(); ++it) {
563  if ((*it)->getLane()->getEdge().isWalkingArea()) {
564  link = *it;
565  return (*it)->getLane();
566  }
567  }
568  } else {
569  const std::vector<MSLane::IncomingLaneInfo>& laneInfos = currentLane->getIncomingLanes();
570  for (std::vector<MSLane::IncomingLaneInfo>::const_iterator it = laneInfos.begin(); it != laneInfos.end(); ++it) {
571  if ((*it).lane->getEdge().isWalkingArea()) {
572  link = (*it).viaLink;
573  return (*it).lane;
574  }
575  }
576  }
577  return nullptr;
578 }
579 
580 
582 MSPModel_Striping::getNeighboringObstacles(const Pedestrians& pedestrians, int egoIndex, int stripes) {
583  const PState& ego = *pedestrians[egoIndex];
584  Obstacles obs(stripes, Obstacle(ego.myDir));
585  std::vector<bool> haveBlocker(stripes, false);
586  for (int index = egoIndex + 1; index < (int)pedestrians.size(); index++) {
587  const PState& p = *pedestrians[index];
588  if DEBUGCOND(ego) {
589  std::cout << SIMTIME << " ped=" << ego.myPerson->getID() << " checking neighbor " << p.myPerson->getID();
590  }
591  if (!p.myWaitingToEnter) {
592  const Obstacle o(p);
593  if DEBUGCOND(ego) {
594  std::cout << " dist=" << ego.distanceTo(o) << std::endl;
595  }
596  if (ego.distanceTo(o) == DIST_BEHIND) {
597  break;
598  }
599  if (ego.distanceTo(o) == DIST_OVERLAP) {
600  obs[p.stripe()] = o;
601  obs[p.otherStripe()] = o;
602  haveBlocker[p.stripe()] = true;
603  haveBlocker[p.otherStripe()] = true;
604  }
605  if (!haveBlocker[p.stripe()]) {
606  obs[p.stripe()] = o;
607  }
608  if (!haveBlocker[p.otherStripe()]) {
609  obs[p.otherStripe()] = o;
610  }
611  }
612  }
613  if DEBUGCOND(ego) {
614  std::cout << SIMTIME << " ped=" << ego.myPerson->getID() << " neighObs=";
615  DEBUG_PRINT(obs);
616  }
617  return obs;
618 }
619 
620 
621 int
622 MSPModel_Striping::getStripeOffset(int origStripes, int destStripes, bool addRemainder) {
623  int offset = (destStripes - origStripes) / 2;
624  if (addRemainder) {
625  offset += (destStripes - origStripes) % 2;
626  }
627  return offset;
628 }
629 
630 
633  MSLane* lane, const MSLane* nextLane, int stripes, int nextDir,
634  double currentLength, int currentDir) {
635  if (nextLanesObs.count(nextLane) == 0) {
636  const double nextLength = nextLane->getEdge().isWalkingArea() ? myMinNextLengths[nextLane] : nextLane->getLength();
637  // figure out the which pedestrians are ahead on the next lane
638  const int nextStripes = numStripes(nextLane);
639  // do not move past the end of the next lane in a single step
640  Obstacles obs(stripes, Obstacle(nextDir == FORWARD ? nextLength : 0, 0, OBSTACLE_NEXTEND, "nextEnd", 0));
641 
642  const int offset = getStripeOffset(nextStripes, stripes, currentDir != nextDir && nextStripes > stripes);
643  //std::cout << SIMTIME << " getNextLaneObstacles"
644  // << " nextLane=" << nextLane->getID()
645  // << " nextLength=" << nextLength
646  // << " nextDir=" << nextDir
647  // << " currentLength=" << currentLength
648  // << " currentDir=" << currentDir
649  // << " stripes=" << stripes
650  // << " nextStripes=" << nextStripes
651  // << " offset=" << offset
652  // << "\n";
653  if (nextStripes < stripes) {
654  // some stripes do not continue
655  for (int ii = 0; ii < stripes; ++ii) {
656  if (ii < offset || ii >= nextStripes + offset) {
657  obs[ii] = Obstacle(nextDir == FORWARD ? 0 : nextLength, 0, OBSTACLE_END, "stripeEnd", 0);
658  }
659  }
660  }
661  Pedestrians& pedestrians = getPedestrians(nextLane);
662  if (nextLane->getEdge().isWalkingArea()) {
663  transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
664  // complex transformation into the coordinate system of the current lane
665  // (pedestrians on next lane may walk at arbitrary angles relative to the current lane)
666  double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
667  if ((stripes - nextStripes) % 2 != 0) {
668  lateral_offset += 0.5 * stripeWidth;
669  }
670  nextDir = currentDir;
671  // transform pedestrians into the current coordinate system
672  for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
673  PState& p = *pedestrians[ii];
674  if (p.myWaitingToEnter || p.myAmJammed) {
675  continue;
676  }
677  Position relPos = lane->getShape().transformToVectorCoordinates(p.getPosition(*p.myStage, -1), true);
678  const double newY = relPos.y() + lateral_offset;
679  //if (p.myPerson->getID() == "ped200") std::cout << " ped=" << p.myPerson->getID() << " relX=" << relPos.x() << " relY=" << newY << " latOff=" << lateral_offset << " s=" << p.stripe(newY) << " os=" << p.otherStripe(newY) << "\n";
680  if ((currentDir == FORWARD && relPos.x() >= lane->getLength()) || (currentDir == BACKWARD && relPos.x() < 0)) {
681  addCloserObstacle(obs, relPos.x(), p.stripe(newY), stripes, p.myPerson->getID(), p.myPerson->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
682  addCloserObstacle(obs, relPos.x(), p.otherStripe(newY), stripes, p.myPerson->getID(), p.myPerson->getVehicleType().getWidth(), currentDir, OBSTACLE_PED);
683  }
684  }
685  } else {
686  // simple transformation into the coordinate system of the current lane
687  // (only need to worry about currentDir and nextDir)
688  // XXX consider waitingToEnter on nextLane
689  sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(nextDir));
690  for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
691  const PState& p = *pedestrians[ii];
692  if (p.myWaitingToEnter || p.myAmJammed) {
693  continue;
694  }
695  double newY = p.myRelY;
696  Obstacle pObs(p);
697  if (nextDir != currentDir) {
698  newY = (nextStripes - 1) * stripeWidth - newY;
699  pObs.speed *= -1;
700  }
701  newY += offset * stripeWidth;
702  const int stripe = p.stripe(newY);
703  if (stripe >= 0 && stripe < stripes) {
704  obs[stripe] = pObs;
705  }
706  const int otherStripe = p.otherStripe(newY);
707  if (otherStripe >= 0 && otherStripe < stripes) {
708  obs[otherStripe] = pObs;
709  }
710  }
711  if (nextLane->getEdge().isCrossing()) {
712  // add vehicle obstacles
713  const MSLink* crossingEntryLink = nextLane->getIncomingLanes().front().viaLink;
714  const bool prio = crossingEntryLink->havePriority() || crossingEntryLink->getTLLogic() != nullptr;
715  addCrossingVehs(nextLane, stripes, offset, nextDir, obs, prio);
716  }
717  if (nextLane->getVehicleNumberWithPartials() > 0) {
718  Obstacles vehObs = getVehicleObstacles(nextLane, nextDir);
719  PState::mergeObstacles(obs, vehObs, nextDir, offset);
720  }
721  transformToCurrentLanePositions(obs, currentDir, nextDir, currentLength, nextLength);
722  }
723  nextLanesObs[nextLane] = obs;
724  }
725  return nextLanesObs[nextLane];
726 }
727 
728 void
729 MSPModel_Striping::transformToCurrentLanePositions(Obstacles& obs, int currentDir, int nextDir, double currentLength, double nextLength) {
730  for (int ii = 0; ii < (int)obs.size(); ++ii) {
731  Obstacle& o = obs[ii];
732  if (currentDir == FORWARD) {
733  if (nextDir == FORWARD) {
734  o.xFwd += currentLength;
735  o.xBack += currentLength;
736  } else {
737  const double tmp = o.xFwd;
738  o.xFwd = currentLength + nextLength - o.xBack;
739  o.xBack = currentLength + nextLength - tmp;
740  }
741  } else {
742  if (nextDir == FORWARD) {
743  const double tmp = o.xFwd;
744  o.xFwd = -o.xBack;
745  o.xBack = -tmp;
746  } else {
747  o.xFwd -= nextLength;
748  o.xBack -= nextLength;
749  }
750  }
751  }
752 }
753 
754 
755 void
756 MSPModel_Striping::addCloserObstacle(Obstacles& obs, double x, int stripe, int numStripes, const std::string& id, double width, int dir, ObstacleType type) {
757  if (stripe >= 0 && stripe < numStripes) {
758  if ((dir == FORWARD && x - width / 2. < obs[stripe].xBack) || (dir == BACKWARD && x + width / 2. > obs[stripe].xFwd)) {
759  obs[stripe] = Obstacle(x, 0, type, id, width);
760  }
761  }
762 }
763 
764 void
765 MSPModel_Striping::moveInDirection(SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
766  for (ActiveLanes::iterator it_lane = myActiveLanes.begin(); it_lane != myActiveLanes.end(); ++it_lane) {
767  const MSLane* lane = it_lane->first;
768  Pedestrians& pedestrians = it_lane->second;
769  if (pedestrians.size() == 0) {
770  continue;
771  }
772  //std::cout << SIMTIME << ">>> lane=" << lane->getID() << " numPeds=" << pedestrians.size() << "\n";
773  if (lane->getEdge().isWalkingArea()) {
774  const double lateral_offset = (lane->getWidth() - stripeWidth) * 0.5;
775  const double minY = stripeWidth * - 0.5 + NUMERICAL_EPS;
776  const double maxY = stripeWidth * (numStripes(lane) - 0.5) - NUMERICAL_EPS;
777  const WalkingAreaPath* debugPath = nullptr;
778  // need to handle each walkingAreaPath seperately and transform
779  // coordinates beforehand
780  std::set<const WalkingAreaPath*, walkingarea_path_sorter> paths;
781  for (Pedestrians::iterator it = pedestrians.begin(); it != pedestrians.end(); ++it) {
782  const PState* p = *it;
783  assert(p->myWalkingAreaPath != 0);
784  if (p->myDir == dir) {
785  paths.insert(p->myWalkingAreaPath);
786  if DEBUGCOND(*p) {
787  debugPath = p->myWalkingAreaPath;
788  std::cout << SIMTIME << " debugging WalkingAreaPath from=" << debugPath->from->getID() << " to=" << debugPath->to->getID() << "\n";
789  }
790  }
791  }
792  for (std::set<const WalkingAreaPath*, walkingarea_path_sorter>::iterator it = paths.begin(); it != paths.end(); ++it) {
793  const WalkingAreaPath* path = *it;
794  Pedestrians toDelete;
795  Pedestrians transformedPeds;
796  transformedPeds.reserve(pedestrians.size());
797  for (Pedestrians::iterator it_p = pedestrians.begin(); it_p != pedestrians.end(); ++it_p) {
798  PState* p = *it_p;
799  if (p->myWalkingAreaPath == path
800  // opposite direction is already in the correct coordinate system
801  || (p->myWalkingAreaPath->from == path->to && p->myWalkingAreaPath->to == path->from)) {
802  transformedPeds.push_back(p);
803  if (path == debugPath) std::cout << " ped=" << p->myPerson->getID() << " relX=" << p->myRelX << " relY=" << p->myRelY << " (untransformed), vecCoord="
804  << path->shape.transformToVectorCoordinates(p->getPosition(*p->myStage, -1)) << "\n";
805  } else {
806  const Position relPos = path->shape.transformToVectorCoordinates(p->getPosition(*p->myStage, -1));
807  const double newY = relPos.y() + lateral_offset;
808  if (relPos != Position::INVALID && newY >= minY && newY <= maxY) {
809  PState* tp = new PState(*p);
810  tp->myRelX = relPos.x();
811  tp->myRelY = newY;
812  // only an obstacle, speed may be orthogonal to dir
813  tp->myDir = !dir;
814  tp->mySpeed = 0;
815  toDelete.push_back(tp);
816  transformedPeds.push_back(tp);
817  if (path == debugPath) {
818  std::cout << " ped=" << p->myPerson->getID() << " relX=" << relPos.x() << " relY=" << newY << " (transformed), vecCoord=" << relPos << "\n";
819  }
820  } else {
821  if (path == debugPath) {
822  std::cout << " ped=" << p->myPerson->getID() << " relX=" << relPos.x() << " relY=" << newY << " (invalid), vecCoord=" << relPos << "\n";
823  }
824  }
825  }
826  }
827  moveInDirectionOnLane(transformedPeds, lane, currentTime, changedLane, dir);
828  arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
829  // clean up
830  for (Pedestrians::iterator it_p = toDelete.begin(); it_p != toDelete.end(); ++it_p) {
831  delete *it_p;
832  }
833  }
834  } else {
835  moveInDirectionOnLane(pedestrians, lane, currentTime, changedLane, dir);
836  arriveAndAdvance(pedestrians, currentTime, changedLane, dir);
837  }
838  }
839 }
840 
841 
842 void
843 MSPModel_Striping::arriveAndAdvance(Pedestrians& pedestrians, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
844  // advance to the next lane / arrive at destination
845  sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
846  // can't use iterators because we do concurrent modification
847  for (int i = 0; i < (int)pedestrians.size(); i++) {
848  PState* const p = pedestrians[i];
849  if (p->myDir == dir && p->distToLaneEnd() < 0) {
850  // moveToNextLane may trigger re-insertion (for consecutive
851  // walks) so erase must be called first
852  pedestrians.erase(pedestrians.begin() + i);
853  i--;
854  p->moveToNextLane(currentTime);
855  if (p->myLane != nullptr) {
856  changedLane.insert(p->myPerson);
857  myActiveLanes[p->myLane].push_back(p);
858  } else {
859  // end walking stage and destroy PState
860  p->myStage->moveToNextEdge(p->myPerson, currentTime);
862  }
863  }
864  }
865 }
866 
867 
868 void
869 MSPModel_Striping::moveInDirectionOnLane(Pedestrians& pedestrians, const MSLane* lane, SUMOTime currentTime, std::set<MSPerson*>& changedLane, int dir) {
870  const int stripes = numStripes(lane);
871  //std::cout << " laneWidth=" << lane->getWidth() << " stripeWidth=" << stripeWidth << " stripes=" << stripes << "\n";
872  Obstacles obs(stripes, Obstacle(dir)); // continously updated
873  NextLanesObstacles nextLanesObs; // continously updated
874  sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(dir));
875 
876  Obstacles crossingVehs(stripes, Obstacle(dir));
877  bool hasCrossingVehObs = false;
878  if (lane->getEdge().isCrossing()) {
879  // assume that vehicles will brake when already on the crossing
880  hasCrossingVehObs = addCrossingVehs(lane, stripes, 0, dir, crossingVehs, true);
881  }
882 
883  for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
884  PState& p = *pedestrians[ii];
885  //std::cout << SIMTIME << "CHECKING" << p.myPerson->getID() << "\n";
886  Obstacles currentObs = obs;
887  if (p.myDir != dir || changedLane.count(p.myPerson) != 0) {
888  if (!p.myWaitingToEnter) {
889  //if DEBUGCOND(p) {
890  // std::cout << " obs=" << p.myPerson->getID() << " y=" << p.myRelY << " stripe=" << p.stripe() << " oStripe=" << p.otherStripe() << "\n";
891  //}
892  Obstacle o(p);
893  if (p.myDir != dir && p.mySpeed == 0) {
894  // ensure recognition of oncoming
895  o.speed = (p.myDir == FORWARD ? 0.1 : -0.1);
896  }
897  obs[p.stripe()] = o;
898  obs[p.otherStripe()] = o;
899  }
900  continue;
901  }
902  if DEBUGCOND(p) {
903  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " currentObs=";
904  gDebugFlag1 = true;
905  DEBUG_PRINT(currentObs);
906  }
907  const MSLane* nextLane = p.myNLI.lane;
908  const MSLink* link = p.myNLI.link;
909  const double dist = p.distToLaneEnd();
910  const double speed = p.myStage->getMaxSpeed(p.myPerson);
911  if (nextLane != nullptr && dist <= LOOKAHEAD_ONCOMING) {
912  const double currentLength = (p.myWalkingAreaPath == nullptr ? lane->getLength() : p.myWalkingAreaPath->length);
913  const Obstacles& nextObs = getNextLaneObstacles(
914  nextLanesObs, lane, nextLane, stripes,
915  p.myNLI.dir, currentLength, dir);
916 
917  if DEBUGCOND(p) {
918  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " nextObs=";
919  DEBUG_PRINT(nextObs);
920  }
921  p.mergeObstacles(currentObs, nextObs);
922  }
923  if DEBUGCOND(p) {
924  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " obsWithNext=";
925  DEBUG_PRINT(currentObs);
926  }
927  p.mergeObstacles(currentObs, getNeighboringObstacles(pedestrians, ii, stripes));
928  if DEBUGCOND(p) {
929  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " obsWithNeigh=";
930  DEBUG_PRINT(currentObs);
931  }
932  // time gap to pass the intersection ahead of a vehicle.
933  const double passingClearanceTime = 2;
934  const double passingLength = p.getLength() + passingClearanceTime * speed;
935  // check link state
936  if DEBUGCOND(p) {
937  gDebugFlag1 = true;
938  std::cout << " link=" << (link == nullptr ? "NULL" : link->getViaLaneOrLane()->getID())
939  << " dist=" << dist << " d2=" << dist - p.getMinGap() << " la=" << LOOKAHEAD_SAMEDIR* speed
940  << " opened=" << (link == nullptr ? "NULL" : toString(link->opened(currentTime - DELTA_T, speed, speed, passingLength, p.getImpatience(currentTime), speed, 0, 0, nullptr, p.ignoreRed(link)))) << "\n";
941  gDebugFlag1 = false;
942  }
943  if (link != nullptr
944  // only check close before junction, @todo we should take deceleration into account here
945  && dist - p.getMinGap() < LOOKAHEAD_SAMEDIR * speed
946  // persons move before vehicles so we subtract DELTA_TO because they cannot rely on vehicles having passed the intersection in the current time step
947  && !link->opened(currentTime - DELTA_T, speed, speed, passingLength, p.getImpatience(currentTime), speed, 0, 0, nullptr, p.ignoreRed(link))) {
948  // prevent movement passed a closed link
949  Obstacles closedLink(stripes, Obstacle(p.myRelX + dir * (dist + NUMERICAL_EPS), 0, OBSTACLE_LINKCLOSED, "closedLink_" + link->getViaLaneOrLane()->getID(), 0));
950  p.mergeObstacles(currentObs, closedLink);
951  if DEBUGCOND(p) {
952  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " obsWitTLS=";
953  DEBUG_PRINT(currentObs);
954  }
955  // consider rerouting over another crossing
956  if (p.myWalkingAreaPath != nullptr) {
957  // @todo actually another path would be needed starting at the current position
959  }
960  }
961  if (&lane->getEdge() == p.myStage->getDestination() && p.myStage->getDestinationStop() != nullptr) {
962  Obstacles arrival(stripes, Obstacle(p.myStage->getArrivalPos() + dir * p.getMinGap(), 0, OBSTACLE_ARRIVALPOS, "arrival", 0));
963  p.mergeObstacles(currentObs, arrival);
964  }
965 
966  if (lane->getVehicleNumberWithPartials() > 0) {
967  // react to vehicles on the same lane
968  // @todo: improve efficiency by using the same iterator for all pedestrians on this lane
969  Obstacles vehObs = getVehicleObstacles(lane, dir, &p);
970  p.mergeObstacles(currentObs, vehObs);
971  if DEBUGCOND(p) {
972  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " obsWithVehs=";
973  DEBUG_PRINT(currentObs);
974  }
975  }
976  if (hasCrossingVehObs) {
977  p.mergeObstacles(currentObs, crossingVehs);
978  if DEBUGCOND(p) {
979  std::cout << SIMTIME << " ped=" << p.myPerson->getID() << " obsWithVehs2=";
980  DEBUG_PRINT(currentObs);
981  }
982  }
983 
984  // walk, taking into account all obstacles
985  p.walk(currentObs, currentTime);
986  gDebugFlag1 = false;
987  if (!p.myWaitingToEnter && !p.myAmJammed) {
988  Obstacle o(p);
989  obs[p.stripe()] = o;
990  obs[p.otherStripe()] = o;
991  if (MSGlobals::gCheck4Accidents && p.myWalkingAreaPath == nullptr && !p.myAmJammed) {
992  for (int coll = 0; coll < ii; ++coll) {
993  PState& c = *pedestrians[coll];
994  if (!c.myWaitingToEnter && c.myWalkingAreaPath == nullptr && !c.myAmJammed) {
995  if (c.stripe() == p.stripe() || p.stripe() == c.otherStripe() || p.otherStripe() == c.stripe() || p.otherStripe() == c.otherStripe()) {
996  Obstacle cObs(c);
997  // we check only for real collisions, no min gap violations
998  if (p.distanceTo(cObs, false) == DIST_OVERLAP) {
999  WRITE_WARNING("Collision of person '" + p.myPerson->getID() + "' and person '" + c.myPerson->getID()
1000  + "', lane='" + lane->getID() + "', time=" + time2string(currentTime) + ".");
1001  }
1002  }
1003  }
1004  }
1005  }
1006  }
1007  //std::cout << SIMTIME << p.myPerson->getID() << " lane=" << lane->getID() << " x=" << p.myRelX << "\n";
1008  }
1009 }
1010 
1011 bool
1012 MSPModel_Striping::addCrossingVehs(const MSLane* crossing, int stripes, double lateral_offset, int dir, Obstacles& obs, bool prio) {
1013  bool hasCrossingVehObs = false;
1014  const MSLink* crossingExitLink = crossing->getLinkCont().front();
1015  gDebugFlag1 = DEBUGCOND2(crossing);
1016  const MSLink::LinkLeaders linkLeaders = crossingExitLink->getLeaderInfo(nullptr, crossing->getLength());
1017  gDebugFlag1 = false;
1018  if (linkLeaders.size() > 0) {
1019  for (MSLink::LinkLeaders::const_iterator it = linkLeaders.begin(); it != linkLeaders.end(); ++it) {
1020  // the vehicle to enter the junction first has priority
1021  const MSVehicle* veh = (*it).vehAndGap.first;
1022  if (veh != nullptr) {
1023  Obstacle vo((*it).distToCrossing, 0, OBSTACLE_VEHICLE, veh->getID(), veh->getVehicleType().getWidth() + 2 * MINGAP_TO_VEHICLE);
1024  // block entry to the crossing in walking direction but allow leaving it
1025  Obstacle voBlock = vo;
1026  if (dir == FORWARD) {
1027  voBlock.xBack = NUMERICAL_EPS;
1028  } else {
1029  voBlock.xFwd = crossing->getLength() - NUMERICAL_EPS;
1030  }
1031  // when approaching a priority crossings, vehicles must be able
1032  // to brake, otherwise the person must be able to cross in time
1033  const double distToCrossBeforeVeh = (dir == FORWARD ? vo.xFwd : crossing->getLength() - vo.xBack);
1034  const double bGap = (prio
1035  ? veh->getCarFollowModel().brakeGap(veh->getSpeed(), veh->getCarFollowModel().getMaxDecel(), 0)
1036  : veh->getSpeed() * distToCrossBeforeVeh); // walking 1m/s
1037  double vehYmin;
1038  double vehYmax;
1039  // relY increases from left to right (the other way around from vehicles)
1040  if ((*it).fromLeft) {
1041  vehYmin = -(*it).vehAndGap.second + lateral_offset; // vehicle back
1042  vehYmax = vehYmin + veh->getVehicleType().getLength() + bGap + MINGAP_TO_VEHICLE;
1043  vehYmin -= MINGAP_TO_VEHICLE;
1044  } else {
1045  vehYmax = crossing->getWidth() + (*it).vehAndGap.second - lateral_offset; // vehicle back
1046  vehYmin = vehYmax - veh->getVehicleType().getLength() - bGap - MINGAP_TO_VEHICLE;
1047  vehYmax += MINGAP_TO_VEHICLE;
1048 
1049  }
1050  for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax), stripes); ++s) {
1051  if ((dir == FORWARD && obs[s].xBack > vo.xBack)
1052  || (dir == BACKWARD && obs[s].xFwd < vo.xFwd)) {
1053  if (!prio && veh->getSpeed() > SUMO_const_haltingSpeed) {
1054  // do not enter the crossing
1055  obs[s] = voBlock;
1056  } else {
1057  obs[s] = vo;
1058  }
1059  hasCrossingVehObs = true;
1060  }
1061  }
1062  if (DEBUGCOND2(crossing)) {
1063  std::cout << SIMTIME
1064  << " crossingVeh=" << veh->getID()
1065  << " lane=" << crossing->getID()
1066  << " prio=" << prio
1067  << " latOffset=" << lateral_offset
1068  << " dir=" << dir
1069  << " stripes=" << stripes
1070  << " dist=" << (*it).distToCrossing
1071  << " gap=" << (*it).vehAndGap.second
1072  << " brakeGap=" << bGap
1073  << " fromLeft=" << (*it).fromLeft
1074  << " distToCrossBefore=" << distToCrossBeforeVeh
1075  << " ymin=" << vehYmin
1076  << " ymax=" << vehYmax
1077  << " smin=" << PState::stripe(vehYmin)
1078  << " smax=" << PState::stripe(vehYmax)
1079  << "\n";
1080  DEBUG_PRINT(obs);
1081  }
1082  }
1083  }
1084  }
1085  return hasCrossingVehObs;
1086 }
1087 
1088 
1091  const int stripes = numStripes(lane);
1092  Obstacles vehObs(stripes, Obstacle(dir));
1093  int current = -1;
1094  double minX = 0.;
1095  double maxX = 0.;
1096  double pRelY = -1.;
1097  double pWidth = 0.;
1098  std::string pID;
1099  bool debug = DEBUGCOND2(lane);
1100  if (ped != nullptr) {
1101  current = ped->stripe();
1102  minX = ped->getMinX();
1103  maxX = ped->getMaxX();
1104  pRelY = ped->myRelY;
1105  pWidth = ped->myPerson->getVehicleType().getWidth();
1106  pID = ped->myPerson->getID();
1107  debug = DEBUGCOND(*ped);
1108  } else if (dir == BACKWARD) {
1109  // checking vehicles on the next lane. Use entry point as reference
1110  minX = lane->getLength();
1111  maxX = lane->getLength();
1112  }
1113  MSLane::AnyVehicleIterator begin = (dir == FORWARD ? lane->anyVehiclesUpstreamBegin() : lane->anyVehiclesBegin());
1114  MSLane::AnyVehicleIterator end = (dir == FORWARD ? lane->anyVehiclesUpstreamEnd() : lane->anyVehiclesEnd());
1115  for (MSLane::AnyVehicleIterator it = begin; it != end; ++it) {
1116  const MSVehicle* veh = *it;
1117  const double vehBack = veh->getBackPositionOnLane(lane);
1118  const double vehFront = vehBack + veh->getVehicleType().getLength();
1119  // ensure that vehicles are not blocked
1120  const double vehNextSpeed = MAX2(veh->getSpeed(), 1.0);
1121  const double clearance = SAFETY_GAP + vehNextSpeed * LOOKAHEAD_SAMEDIR;
1122  if ((dir == FORWARD && vehFront + clearance > minX && vehBack <= maxX + LOOKAHEAD_SAMEDIR)
1123  || (dir == BACKWARD && vehBack < maxX && vehFront >= minX - LOOKAROUND_VEHICLES)) {
1124  Obstacle vo(vehBack, veh->getSpeed(), OBSTACLE_VEHICLE, veh->getID(), 0);
1125  // moving vehicles block space along their path
1126  vo.xFwd += veh->getVehicleType().getLength() + clearance;
1127  vo.xBack -= SAFETY_GAP;
1128  // relY increases from left to right (the other way around from vehicles)
1129  // XXX lateral offset for partial vehicles
1130  const double vehYmax = 0.5 * (lane->getWidth() + veh->getVehicleType().getWidth() - stripeWidth) - veh->getLateralPositionOnLane();
1131  const double vehYmin = vehYmax - veh->getVehicleType().getWidth();
1132  for (int s = MAX2(0, PState::stripe(vehYmin)); s < MIN2(PState::stripe(vehYmax) + 1, stripes); ++s) {
1133  vehObs[s] = vo;
1134  if (s == current && vehFront + SAFETY_GAP < minX) {
1135  // ignore if aleady overlapping while vehicle is still behind
1136  if (pRelY - pWidth < vehYmax &&
1137  pRelY + pWidth > vehYmin && dir == FORWARD) {
1138  if (debug) {
1139  std::cout << " ignoring vehicle on stripe " << s << "\n";
1140  }
1141  if (dir == FORWARD) {
1142  vehObs[s] = Obstacle(dir);
1143  } else {
1144  vehObs[s].xFwd = MIN2(vo.xFwd, vehFront + SAFETY_GAP);
1145  }
1146  }
1147  }
1148  }
1149  if (debug) {
1150  std::cout << SIMTIME << " ped=" << pID << " veh=" << veh->getID() << " obstacle on lane=" << lane->getID()
1151  << "\n"
1152  << " ymin=" << vehYmin
1153  << " ymax=" << vehYmax
1154  << " smin=" << PState::stripe(vehYmin)
1155  << " smax=" << PState::stripe(vehYmax)
1156  << " relY=" << pRelY
1157  << " current=" << current
1158  << "\n";
1159  }
1160  }
1161  }
1162  return vehObs;
1163 }
1164 
1165 
1166 // ===========================================================================
1167 // MSPModel_Striping::Obstacle method definitions
1168 // ===========================================================================
1170  xFwd(dir * dist), // by default, far away when seen in dir
1171  xBack(dir * dist), // by default, far away when seen in dir
1172  speed(0),
1173  type(OBSTACLE_NONE),
1174  description("") {
1175 }
1176 
1177 
1179  xFwd(ped.getMaxX()),
1180  xBack(ped.getMinX()),
1181  speed(ped.myDir * ped.mySpeed),
1182  type(OBSTACLE_PED),
1183  description(ped.myPerson->getID()) {
1184  assert(!ped.myWaitingToEnter);
1185 }
1186 
1187 
1188 // ===========================================================================
1189 // MSPModel_Striping::PState method definitions
1190 // ===========================================================================
1191 
1192 
1194  myPerson(person),
1195  myStage(stage),
1196  myLane(lane),
1197  myRelX(stage->getDepartPos()),
1198  myRelY(stage->getDepartPosLat()),
1199  myDir(FORWARD),
1200  mySpeed(0),
1201  myWaitingToEnter(true),
1202  myWaitingTime(0),
1203  myWalkingAreaPath(nullptr),
1204  myAmJammed(false),
1205  myRemoteXYPos(Position::INVALID),
1206  myAngle(std::numeric_limits<double>::max()) {
1207  const MSEdge* currentEdge = &lane->getEdge();
1208  const ConstMSEdgeVector& route = myStage->getRoute();
1209  assert(!route.empty());
1210  if (route.size() == 1) {
1211  // only a single edge, move towards end pos
1213  } else if (route.front()->getFunction() != EDGEFUNC_NORMAL) {
1214  // start on an intersection
1215  myDir = FORWARD;
1216  if (route.front()->isWalkingArea()) {
1217  myWalkingAreaPath = getArbitraryPath(route.front());
1218  }
1219  } else {
1220  const bool mayStartForward = canTraverse(FORWARD, route) != UNDEFINED_DIRECTION;
1221  const bool mayStartBackward = canTraverse(BACKWARD, route) != UNDEFINED_DIRECTION;
1222  if DEBUGCOND(*this) {
1223  std::cout << " initialize dir for " << myPerson->getID() << " forward=" << mayStartForward << " backward=" << mayStartBackward << "\n";
1224  }
1225  if (mayStartForward && mayStartBackward) {
1226  // figure out the best direction via routing
1227  ConstMSEdgeVector crossingRoute;
1228  MSNet::getInstance()->getPedestrianRouter().compute(currentEdge, route.back(), myRelX, myStage->getArrivalPos(), myStage->getMaxSpeed(person), 0, nullptr, crossingRoute, true);
1229  if (crossingRoute.size() > 1) {
1230  // route found
1231  const MSEdge* nextEdge = crossingRoute[1];
1232  if (nextEdge->getFromJunction() == currentEdge->getFromJunction() || nextEdge->getToJunction() == currentEdge->getFromJunction()) {
1233  myDir = BACKWARD;
1234  }
1235  }
1236  if DEBUGCOND(*this) {
1237  std::cout << " crossingRoute=" << toString(crossingRoute) << "\n";
1238  }
1239  } else {
1240  myDir = !mayStartBackward ? FORWARD : BACKWARD;
1241  }
1242  }
1243  if (lane->getVehicleNumberWithPartials() > 0 && myRelY == 0) {
1244  // better start next to the road if nothing was specified
1245  myRelY -= stripeWidth;
1246  }
1247  if (myDir == FORWARD) {
1248  // start at the right side of the sidewalk
1249  myRelY = stripeWidth * (numStripes(lane) - 1) - myRelY;
1250  }
1251  if DEBUGCOND(*this) {
1252  std::cout << " added new pedestrian " << myPerson->getID() << " on " << lane->getID() << " myRelX=" << myRelX << " myRelY=" << myRelY << " dir=" << myDir << " route=" << toString(myStage->getRoute()) << "\n";
1253  }
1254 
1255  myNLI = getNextLane(*this, lane, nullptr);
1256 }
1257 
1258 
1259 double
1260 MSPModel_Striping::PState::getMinX(const bool includeMinGap) const {
1261  // @todo speed should have an influence here because faster persons need more space
1262  if (myDir == FORWARD) {
1263  return myRelX - getLength();
1264  }
1265  return myRelX - (includeMinGap ? getMinGap() : 0.);
1266 }
1267 
1268 
1269 double
1270 MSPModel_Striping::PState::getMaxX(const bool includeMinGap) const {
1271  // @todo speed should have an influence here because faster persons need more space
1272  if (myDir == FORWARD) {
1273  return myRelX + (includeMinGap ? getMinGap() : 0.);
1274  }
1275  return myRelX + getLength();
1276 }
1277 
1278 
1279 double
1281  return myPerson->getVehicleType().getLength();
1282 }
1283 
1284 
1285 double
1287  return myPerson->getVehicleType().getMinGap();
1288 }
1289 
1290 
1291 int
1293  return (int)floor(relY / stripeWidth + 0.5);
1294 }
1295 
1296 
1297 int
1299  const int s = stripe(relY);
1300  const double offset = relY - s * stripeWidth;
1301  const double threshold = MAX2(NUMERICAL_EPS, stripeWidth - SQUEEZE * myPerson->getVehicleType().getWidth());
1302  int result;
1303  if (offset > threshold) {
1304  result = s + 1;
1305  } else if (offset < -threshold) {
1306  result = s - 1;
1307  } else {
1308  result = s;
1309  }
1310  //std::cout.setf(std::ios::fixed , std::ios::floatfield);
1311  //std::cout << std::setprecision(5);
1312  //if DEBUGCOND(*this) std::cout << " otherStripe " << myPerson->getID() << " offset=" << offset << " threshold=" << threshold << " rawResult=" << result << "\n";
1313  return result;
1314 }
1315 
1316 int
1318  return MIN2(MAX2(0, stripe(myRelY)), numStripes(myLane) - 1);
1319 }
1320 
1321 
1322 int
1324  return MIN2(MAX2(0, otherStripe(myRelY)), numStripes(myLane) - 1);
1325 }
1326 
1327 
1328 double
1330  if (myStage->getNextRouteEdge() == nullptr) {
1331  return myDir * (myStage->getArrivalPos() - myRelX) - POSITION_EPS;
1332  } else {
1333  const double length = myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length;
1334  return myDir == FORWARD ? length - myRelX : myRelX;
1335  }
1336 }
1337 
1338 
1339 bool
1341  double dist = distToLaneEnd();
1342  if (DEBUGCOND(*this)) {
1343  std::cout << SIMTIME << " ped=" << myPerson->getID() << " myRelX=" << myRelX << " dist=" << dist << "\n";
1344  }
1345  if (dist <= 0) {
1346  //if (ped.myPerson->getID() == DEBUG1) {
1347  // std::cout << SIMTIME << " addToLane x=" << ped.myRelX << " newDir=" << newDir << " newLane=" << newLane->getID() << " walkingAreaShape=" << walkingAreaShape << "\n";
1348  //}
1349  //std::cout << " changing to " << newLane->getID() << " myRelY=" << ped.myRelY << " oldStripes=" << numStripes(myLane) << " newStripes=" << numStripes(newLane);
1350  //std::cout << " newY=" << ped.myRelY << " myDir=" << ped.myDir << " newDir=" << newDir;
1351  const int oldDir = myDir;
1352  const MSLane* oldLane = myLane;
1353  myLane = myNLI.lane;
1354  myDir = myNLI.dir;
1355  const bool normalLane = (myLane == nullptr || myLane->getEdge().getFunction() == EDGEFUNC_NORMAL || &myLane->getEdge() == myStage->getNextRouteEdge());
1356  if DEBUGCOND(*this) {
1357  std::cout << SIMTIME
1358  << " ped=" << myPerson->getID()
1359  << " moveToNextLane old=" << oldLane->getID()
1360  << " new=" << (myLane == nullptr ? "NULL" : myLane->getID())
1361  << " oldDir=" << oldDir
1362  << " newDir=" << myDir
1363  << " myRelX=" << myRelX
1364  << " dist=" << dist
1365  << "\n";
1366  }
1367  if (myLane == nullptr) {
1369  }
1370  // moveToNextEdge might destroy the person and thus mess up the heap. Better check first
1371  if (myStage->getRouteStep() == myStage->getRoute().end() - 1) {
1372  myLane = nullptr;
1373  } else {
1374  const bool arrived = myStage->moveToNextEdge(myPerson, currentTime, normalLane ? nullptr : &myLane->getEdge());
1375  UNUSED_PARAMETER(arrived);
1376  assert(!arrived);
1377  assert(myDir != UNDEFINED_DIRECTION);
1378  myNLI = getNextLane(*this, myLane, oldLane);
1379  assert(myNLI.lane != oldLane); // do not turn around
1380  if DEBUGCOND(*this) {
1381  std::cout << " nextLane=" << (myNLI.lane == nullptr ? "NULL" : myNLI.lane->getID()) << "\n";
1382  }
1383  if (myLane->getEdge().isWalkingArea()) {
1384  if (myNLI.dir != UNDEFINED_DIRECTION) {
1385  myWalkingAreaPath = &myWalkingAreaPaths[std::make_pair(oldLane, myNLI.lane)];
1386  assert(myWalkingAreaPath->from != 0);
1387  assert(myWalkingAreaPath->to != 0);
1388  assert(myWalkingAreaPath->shape.size() >= 2);
1389  if DEBUGCOND(*this) {
1390  std::cout << " mWAPath shape=" << myWalkingAreaPath->shape << " length=" << myWalkingAreaPath->length << "\n";
1391  }
1392  } else {
1393  // disconnnected route. move to the next edge
1394  if (OptionsCont::getOptions().getBool("ignore-route-errors")) {
1395  // try to determine direction from topology, otherwise maintain current direction
1396  const MSEdge* currRouteEdge = myStage->getRouteEdge();
1397  const MSEdge* nextRouteEdge = myStage->getNextRouteEdge();
1398  if ((nextRouteEdge->getToJunction() == currRouteEdge->getFromJunction())
1399  || nextRouteEdge->getToJunction() == currRouteEdge->getToJunction()) {
1400  myDir = BACKWARD;
1401  } else if ((nextRouteEdge->getFromJunction() == currRouteEdge->getFromJunction())
1402  || nextRouteEdge->getFromJunction() == currRouteEdge->getToJunction()) {
1403  myDir = FORWARD;
1404  }
1405  myStage->moveToNextEdge(myPerson, currentTime, nullptr);
1406  myLane = myNLI.lane;
1407  assert(myLane != 0);
1408  assert(myLane->getEdge().getFunction() == EDGEFUNC_NORMAL);
1409  myNLI = getNextLane(*this, myLane, oldLane);
1410  myWalkingAreaPath = nullptr;
1411  } else {
1412  throw ProcessError("Disconnected walk for person '" + myPerson->getID() + "'.");
1413  }
1414  }
1415  } else {
1416  myWalkingAreaPath = nullptr;
1417  }
1418  // adapt x to fit onto the new lane
1419  // (make sure we do not move past the end of the new lane since that
1420  // lane was not checked for obstacles)
1421  const double newLength = (myWalkingAreaPath == nullptr ? myLane->getLength() : myWalkingAreaPath->length);
1422  if (-dist > newLength) {
1423  assert(OptionsCont::getOptions().getBool("ignore-route-errors"));
1424  // should not happen because the end of myLane should have been an obstacle as well
1425  // (only when the route is broken)
1426  dist = -newLength;
1427  }
1428  if (myDir == BACKWARD) {
1429  myRelX = newLength + dist;
1430  } else {
1431  myRelX = -dist;
1432  }
1433  if DEBUGCOND(*this) {
1434  std::cout << SIMTIME << " update myRelX ped=" << myPerson->getID()
1435  << " newLength=" << newLength
1436  << " dist=" << dist
1437  << " myRelX=" << myRelX
1438  << "\n";
1439  }
1440  // adjust to change in direction
1441  if (myDir != oldDir) {
1442  myRelY = (numStripes(oldLane) - 1) * stripeWidth - myRelY;
1443  }
1444  // adjust to differences in sidewalk width
1445  const int offset = getStripeOffset(numStripes(oldLane), numStripes(myLane), oldDir != myDir && numStripes(myLane) < numStripes(oldLane));
1446  myRelY += offset * stripeWidth;
1447  if DEBUGCOND(*this) {
1448  std::cout << SIMTIME << " transformY ped=" << myPerson->getID()
1449  << " newLane=" << Named::getIDSecure(myLane)
1450  << " newY=" << myRelY
1451  << " os=" << numStripes(oldLane) << " ns=" << numStripes(myLane)
1452  << " od=" << oldDir << " nd=" << myDir
1453  << " offset=" << offset << "\n";
1454  }
1455  }
1456  return true;
1457  } else {
1458  return false;
1459  }
1460 }
1461 
1462 
1463 void
1465  myAngle = std::numeric_limits<double>::max(); // set on first access or via remote control
1466  const int stripes = (int)obs.size();
1467  const int sMax = stripes - 1;
1468  assert(stripes == numStripes(myLane));
1469  const double vMax = myStage->getMaxSpeed(myPerson);
1470  // ultimate goal is to choose the prefered stripe (chosen)
1471  const int current = stripe();
1472  const int other = otherStripe();
1473  // compute distances
1474  std::vector<double> distance(stripes);
1475  for (int i = 0; i < stripes; ++i) {
1476  distance[i] = distanceTo(obs[i], obs[i].type == OBSTACLE_PED);
1477  }
1478  // compute utility for all stripes
1479  std::vector<double> utility(stripes, 0);
1480  // forbid stripes which are blocked and also all stripes behind them
1481  for (int i = 0; i < stripes; ++i) {
1482  if (distance[i] == DIST_OVERLAP) {
1483  if (i == current && (!myWaitingToEnter || stripe() != stripe(myRelY))) {
1484  utility[i] += OBSTRUCTED_PENALTY;
1485  }
1486  if (i < current) {
1487  for (int j = 0; j <= i; ++j) {
1488  utility[j] += OBSTRUCTED_PENALTY;
1489  }
1490  }
1491  if (i > current) {
1492  for (int j = i; j < stripes; ++j) {
1493  utility[j] += OBSTRUCTED_PENALTY;
1494  }
1495  }
1496  }
1497  }
1498  // forbid a portion of the leftmost stripes (in walking direction).
1499  // lanes with stripes less than 1 / RESERVE_FOR_ONCOMING_FACTOR
1500  // may still deadlock in heavy pedestrian traffic
1501  const bool onJunction = myLane->getEdge().isWalkingArea() || myLane->getEdge().isCrossing();
1502  const int reserved = (int)floor(stripes * (onJunction ? RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS : RESERVE_FOR_ONCOMING_FACTOR));
1503  if (myDir == FORWARD) {
1504  for (int i = 0; i < reserved; ++i) {
1505  utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1506  }
1507  } else {
1508  for (int i = sMax; i > sMax - reserved; --i) {
1509  utility[i] += INAPPROPRIATE_PENALTY * (i == current ? 0.5 : 1);
1510  }
1511  }
1512  // adapt utility based on obstacles
1513  for (int i = 0; i < stripes; ++i) {
1514  if (obs[i].speed * myDir < 0) {
1515  // penalize evasion to the left
1516  if (myDir == FORWARD && i > 0) {
1517  utility[i - 1] -= 0.5;
1518  } else if (myDir == BACKWARD && i < sMax) {
1519  utility[i + 1] -= 0.5;
1520  }
1521  }
1522  // compute expected distance achievable by staying on this stripe for a time horizon
1523  const double walkDist = MAX2(0., distance[i]); // disregard special distance flags
1524  const double lookAhead = obs[i].speed * myDir >= 0 ? LOOKAHEAD_SAMEDIR : LOOKAHEAD_ONCOMING;
1525  const double expectedDist = MIN2(vMax * LOOKAHEAD_SAMEDIR, walkDist + obs[i].speed * myDir * lookAhead);
1526  if (DEBUGCOND(*this)) {
1527  std::cout << " util=" << utility[i] << " exp=" << expectedDist << " dist=" << distance[i] << "\n";
1528  }
1529  if (expectedDist >= 0) {
1530  utility[i] += expectedDist;
1531  } else {
1532  // let only the distance count
1533  utility[i] += ONCOMING_CONFLICT_PENALTY + distance[i];
1534  }
1535  }
1536  // discourage use of the leftmost lane (in walking direction) if there are oncoming
1537  if (myDir == FORWARD && obs[0].speed < 0) {
1538  utility[0] += ONCOMING_CONFLICT_PENALTY;
1539  } else if (myDir == BACKWARD && obs[sMax].speed > 0) {
1540  utility[sMax] += ONCOMING_CONFLICT_PENALTY;
1541  }
1542  // penalize lateral movement (if the current stripe permits walking)
1543  if (distance[current] > 0 && myWaitingTime == 0) {
1544  for (int i = 0; i < stripes; ++i) {
1545  utility[i] += abs(i - current) * LATERAL_PENALTY;
1546  }
1547  }
1548 
1549  // select best stripe
1550  int chosen = current;
1551  for (int i = 0; i < stripes; ++i) {
1552  if (utility[chosen] < utility[i]) {
1553  chosen = i;
1554  }
1555  }
1556  // compute speed components along both axes
1557  const int next = (chosen == current ? current : (chosen < current ? current - 1 : current + 1));
1558  const double xDist = MIN3(distance[current], distance[other], distance[next]);
1559  // XXX preferred gap differs between approaching a standing obstacle or a moving obstacle
1560  const double preferredGap = NUMERICAL_EPS;
1561  double xSpeed = MIN2(vMax, MAX2(0., DIST2SPEED(xDist - preferredGap)));
1562  if (xSpeed < NUMERICAL_EPS) {
1563  xSpeed = 0.;
1564  }
1565  if (DEBUGCOND(*this)) {
1566  std::cout << " xSpeedPotential=" << xSpeed << "\n";
1567  }
1568  // avoid tiny steps
1569  // XXX pressure from behind?
1570  if (mySpeed == 0 && xDist < MIN_STARTUP_DIST &&
1571  // unless walking towards a short lane
1572  !(
1573  (xDist == distance[current] && obs[current].type >= OBSTACLE_END)
1574  || (xDist == distance[other] && obs[other].type >= OBSTACLE_END)
1575  || (xDist == distance[next] && obs[next].type >= OBSTACLE_END))
1576  ) {
1577  xSpeed = 0;
1578  }
1579  if (xSpeed == 0) {
1580  if (myWaitingTime > jamTime || myAmJammed) {
1581  // squeeze slowly through the crowd ignoring others
1582  if (!myAmJammed) {
1584  WRITE_WARNING("Person '" + myPerson->getID()
1585  + "' is jammed on edge '" + myStage->getEdge()->getID()
1586  + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
1587  myAmJammed = true;
1588  }
1589  xSpeed = vMax / 4;
1590  }
1591  } else if (stripe(myRelY) >= 0 && stripe(myRelY) <= sMax) {
1592  myAmJammed = false;
1593  }
1594  // dawdling
1595  const double dawdle = MIN2(xSpeed, RandHelper::rand() * vMax * dawdling);
1596  xSpeed -= dawdle;
1597 
1598  // XXX ensure that diagonal speed <= vMax
1599  // avoid deadlocks on narrow sidewalks
1600  //if (oncoming && xSpeed == 0 && myStage->getWaitingTime(currentTime) > TIME2STEPS(ONCOMIN_PATIENCE)) {
1601  // if DEBUGCOND(*this) std::cout << " stepping asside to resolve oncoming deadlock\n";
1602  // xSpeed = POSITION_EPS; // reset myWaitingTime
1603  // if (myDir == FORWARD && chosen < sMax) {
1604  // chosen += 1;
1605  // } else if (myDir == BACKWARD && chosen > 0) {
1606  // chosen -= 1;
1607  // }
1608  //}
1609  const double maxYSpeed = MIN2(MAX2(vMax * LATERAL_SPEED_FACTOR, vMax - xSpeed), stripeWidth);
1610  double ySpeed = 0;
1611  double yDist = 0;
1612  if (utility[next] > OBSTRUCTION_THRESHOLD && utility[chosen] > OBSTRUCTION_THRESHOLD) {
1613  // don't move laterally if the stripes are blocked
1614  yDist = (chosen * stripeWidth) - myRelY;
1615  if (fabs(yDist) > NUMERICAL_EPS) {
1616  ySpeed = (yDist > 0 ?
1617  MIN2(maxYSpeed, DIST2SPEED(yDist)) :
1618  MAX2(-maxYSpeed, DIST2SPEED(yDist)));
1619  }
1620  } else if (utility[next] <= OBSTRUCTION_THRESHOLD && obs[next].type == OBSTACLE_VEHICLE
1621  // still on the road
1622  && stripe() == stripe(myRelY)
1623  // only when the vehicle is moving on the same lane
1624  && !myLane->getEdge().isCrossing()) {
1625  // step aside to let the vehicle pass
1626  myRelY += myDir * vMax;
1627  }
1628  // DEBUG
1629  if DEBUGCOND(*this) {
1630  std::cout << SIMTIME
1631  << " ped=" << myPerson->getID()
1632  << " edge=" << myStage->getEdge()->getID()
1633  << " x=" << myRelX
1634  << " y=" << myRelY
1635  << " d=" << myDir
1636  << " pvx=" << mySpeed
1637  << " cur=" << current
1638  << " cho=" << chosen
1639  << " oth=" << other
1640  << " nxt=" << next
1641  << " vx=" << xSpeed
1642  << " dawdle=" << dawdle
1643  << " vy=" << ySpeed
1644  << " xd=" << xDist
1645  << " yd=" << yDist
1646  << " vMax=" << myStage->getMaxSpeed(myPerson)
1647  << " wTime=" << myStage->getWaitingTime(currentTime)
1648  << " jammed=" << myAmJammed
1649  << "\n distance=" << toString(distance)
1650  << "\n utility=" << toString(utility)
1651  << "\n";
1652  DEBUG_PRINT(obs);
1653  }
1654  myRelX += SPEED2DIST(xSpeed * myDir);
1655  myRelY += SPEED2DIST(ySpeed);
1656  mySpeed = xSpeed;
1657  if (xSpeed >= SUMO_const_haltingSpeed) {
1658  myWaitingToEnter = false;
1659  myWaitingTime = 0;
1660  } else {
1662  }
1663 }
1664 
1665 
1666 double
1668  return MAX2(0., MIN2(1., myPerson->getVehicleType().getImpatience()
1670 }
1671 
1672 
1673 double
1675  return myRelX;
1676 }
1677 
1678 
1679 Position
1681  if (myLane == nullptr) {
1682  // pedestrian has already finished
1683  return Position::INVALID;
1684  }
1685  const double lateral_offset = myRelY + (stripeWidth - myLane->getWidth()) * 0.5;
1686  if (myWalkingAreaPath == nullptr) {
1687  return stage.getLanePosition(myLane, myRelX, lateral_offset);
1688  } else {
1689  //if DEBUGCOND(*this) {
1690  // std::cout << SIMTIME
1691  // << " getPosition (walkingArea)"
1692  // << " p=" << myPerson->getID()
1693  // << " x=" << myRelX
1694  // << " y=" << myRelY
1695  // << " latOffset=" << lateral_offset
1696  // << " shape=" << myWalkingAreaPath->shape
1697  // << " pos=" << myWalkingAreaPath->shape.positionAtOffset(myRelX, lateral_offset)
1698  // << "\n";
1699  //}
1700  return myWalkingAreaPath->shape.positionAtOffset(myRelX, lateral_offset);
1701  }
1702 }
1703 
1704 
1705 double
1707  if (myAngle != std::numeric_limits<double>::max()) {
1708  return myAngle;
1709  }
1710  if (myLane == nullptr) {
1711  // pedestrian has already finished
1712  return 0;
1713  }
1714  const PositionVector& shp = myWalkingAreaPath == nullptr ? myLane->getShape() : myWalkingAreaPath->shape;
1715  double angle = shp.rotationAtOffset(myRelX) + (myDir == MSPModel::BACKWARD ? M_PI : 0);
1716  if (angle > M_PI) {
1717  angle -= 2 * M_PI;
1718  }
1719  myAngle = angle;
1720  return angle;
1721 }
1722 
1723 
1724 SUMOTime
1726  return myWaitingTime;
1727 }
1728 
1729 
1730 double
1732  return mySpeed;
1733 }
1734 
1735 
1736 const MSEdge*
1738  return myNLI.lane == nullptr ? nullptr : &myNLI.lane->getEdge();
1739 }
1740 
1741 void
1743  double lanePosLat, double angle, int routeOffset,
1744  const ConstMSEdgeVector& edges, SUMOTime t) {
1745  UNUSED_PARAMETER(p);
1746  assert(p == myPerson);
1747  myAngle = angle;
1749  /*
1750  std::cout << " MSPModel_Striping::PState::moveToXY"
1751  << " pos=" << pos
1752  << " lane=" << lane->getID()
1753  << " lanePos=" << lanePos
1754  << " lanePosLat=" << lanePosLat
1755  << " angle=" << angle
1756  << " routeOffset=" << routeOffset
1757  << " myRelX=" << myRelX << " myRelY=" << myRelY;
1758  */
1759  //std::cout << " newX=" << myRelX << " newY=" << myRelY << "\n";
1760  if (lane != nullptr) {
1762  const MSLane* sidewalk = getSidewalk<MSEdge, MSLane>(&lane->getEdge());
1763  if (lane != sidewalk) {
1764  MSPModel_Striping* pm = dynamic_cast<MSPModel_Striping*>(MSPModel::getModel());
1765  assert(pm != 0);
1766  // add a new active lane
1767  pm->remove(this);
1768  pm->add(this, lane);
1769  }
1770  if (edges.empty()) {
1771  // map within route
1772  myStage->setRouteIndex(myPerson, routeOffset);
1773  if (lane->getEdge().isInternal()) {
1774  myStage->moveToNextEdge(myPerson, t, &lane->getEdge());
1775  }
1776  } else {
1777  // map to new edge
1778  }
1779  myLane = lane;
1780  myRelX = lanePos;
1781  myRelY = (myLane->getWidth() - stripeWidth) * 0.5 - lanePosLat;
1782  } else {
1783  // map outside the network
1784  myRemoteXYPos = pos;
1785  }
1786 
1787 }
1788 
1789 
1790 
1791 double
1792 MSPModel_Striping::PState::distanceTo(const Obstacle& obs, const bool includeMinGap) const {
1793  // check for overlap
1794  const double maxX = getMaxX(includeMinGap);
1795  const double minX = getMinX(includeMinGap);
1796  //if (DEBUGCOND(*this)) {
1797  // std::cout << std::setprecision(2) << " distanceTo=" << obs.description << " maxX=" << maxX << " minX=" << minX << " obs.xFwd=" << obs.xFwd << " obs.xBack=" << obs.xBack << "\n";
1798  //}
1799  if ((obs.xFwd >= maxX && obs.xBack <= maxX) || (obs.xFwd <= maxX && obs.xFwd >= minX)) {
1800  // avoid blocking by itself on looped route
1801  return (obs.type == OBSTACLE_PED && obs.description == myPerson->getID()) ? DIST_FAR_AWAY : DIST_OVERLAP;
1802  }
1803  if (myDir == FORWARD) {
1804  return obs.xFwd < minX ? DIST_BEHIND : obs.xBack - maxX;
1805  } else {
1806  return obs.xBack > maxX ? DIST_BEHIND : minX - obs.xFwd;
1807  }
1808 }
1809 
1810 
1811 void
1813  for (int i = 0; i < (int)into.size(); ++i) {
1814  if (gDebugFlag1) {
1815  std::cout << " i=" << i
1816  << " into=" << into[i].description << " iDist=" << distanceTo(into[i])
1817  << " obs2=" << obs2[i].description << " oDist=" << distanceTo(obs2[i]) << "\n";
1818  }
1819  const double dO = distanceTo(obs2[i]);
1820  const double dI = distanceTo(into[i]);
1821  if (dO < dI) {
1822  into[i] = obs2[i];
1823  } else if (dO == dI
1824  && into[i].type != OBSTACLE_PED
1825  && into[i].type != OBSTACLE_VEHICLE
1826  && (obs2[i].type == OBSTACLE_PED ||
1827  obs2[i].type == OBSTACLE_VEHICLE)) {
1828  into[i] = obs2[i];
1829  }
1830  }
1831 }
1832 
1833 void
1834 MSPModel_Striping::PState::mergeObstacles(Obstacles& into, const Obstacles& obs2, int dir, int offset) {
1835  for (int i = 0; i < (int)into.size(); ++i) {
1836  int i2 = i + offset;
1837  if (i2 >= 0 && i2 < (int)obs2.size()) {
1838  if (dir == FORWARD) {
1839  if (obs2[i2].xBack < into[i].xBack) {
1840  into[i] = obs2[i2];
1841  }
1842  } else {
1843  if (obs2[i2].xFwd > into[i].xFwd) {
1844  into[i] = obs2[i2];
1845  }
1846  }
1847  }
1848  }
1849 }
1850 
1851 
1852 bool
1854  if (link->haveRed()) {
1855  const double ignoreRedTime = myPerson->getVehicleType().getParameter().getJMParam(SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME, -1);
1856  if (ignoreRedTime >= 0) {
1857  const double redDuration = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - link->getLastStateChange());
1858  if (DEBUGCOND(*this)) {
1859  std::cout << SIMTIME << " ignoreRedTime=" << ignoreRedTime << " redDuration=" << redDuration << "\n";
1860  }
1861  return ignoreRedTime > redDuration;
1862  } else {
1863  return false;
1864  }
1865  } else {
1866  return false;
1867  }
1868 }
1869 
1870 // ===========================================================================
1871 // MSPModel_Striping::MovePedestrians method definitions
1872 // ===========================================================================
1873 //
1874 
1875 SUMOTime
1877  std::set<MSPerson*> changedLane;
1878  myModel->moveInDirection(currentTime, changedLane, FORWARD);
1879  myModel->moveInDirection(currentTime, changedLane, BACKWARD);
1880  // DEBUG
1881 #ifdef LOG_ALL
1882  for (ActiveLanes::const_iterator it_lane = myModel->getActiveLanes().begin(); it_lane != myModel->getActiveLanes().end(); ++it_lane) {
1883  const MSLane* lane = it_lane->first;
1884  Pedestrians pedestrians = it_lane->second;
1885  if (pedestrians.size() == 0) {
1886  continue;
1887  }
1888  sort(pedestrians.begin(), pedestrians.end(), by_xpos_sorter(FORWARD));
1889  std::cout << SIMTIME << " lane=" << lane->getID();
1890  for (int ii = 0; ii < (int)pedestrians.size(); ++ii) {
1891  const PState& p = *pedestrians[ii];
1892  std::cout << " (" << p.myPerson->getID() << " " << p.myRelX << "," << p.myRelY << " " << p.myDir << ")";
1893  }
1894  std::cout << "\n";
1895  }
1896 #endif
1897  return DELTA_T;
1898 }
1899 
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:785
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:32
static NextLaneInfo getNextLane(const PState &ped, const MSLane *currentLane, const MSLane *prevLane)
computes the successor lane for the given pedestrian and sets the link as well as the direction to us...
#define DIST2SPEED(x)
Definition: SUMOTime.h:50
double getImpatience(SUMOTime now) const
returns the impatience
MSLane * getLogicalPredecessorLane() const
get the most likely precedecessor lane (sorted using by_connections_to_sorter). The result is cached ...
Definition: MSLane.cpp:2407
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver&#39;s reaction time tau (i...
Definition: MSCFModel.h:313
void moveInDirection(SUMOTime currentTime, std::set< MSPerson *> &changedLane, int dir)
move all pedestrians forward and advance to the next lane if applicable
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:79
long long int SUMOTime
Definition: SUMOTime.h:36
double getJMParam(const SumoXMLAttr attr, const double defaultValue) const
Returns the named value from the map, or the default if it is not contained there.
static const double LATERAL_SPEED_FACTOR
static const double SQUEEZE
#define SPEED2DIST(x)
Definition: SUMOTime.h:48
MSPerson::MSPersonStage_Walking * myStage
static const double DIST_BEHIND
void moveInDirectionOnLane(Pedestrians &pedestrians, const MSLane *lane, SUMOTime currentTime, std::set< MSPerson *> &changedLane, int dir)
move pedestrians forward on one lane
static const double LOOKAHEAD_ONCOMING
static int numStripes(const MSLane *lane)
return the maximum number of pedestrians walking side by side
static Obstacles getNeighboringObstacles(const Pedestrians &pedestrians, int egoIndex, int stripes)
Obstacle(int dir, double dist=DIST_FAR_AWAY)
create No-Obstacle
const MSEdge * getEdge() const
Returns the current edge.
double getMinGap() const
return the minimum gap of the pedestrian
sorts the persons by position on the lane. If dir is forward, higher x positions come first...
static WalkingAreaPath * getArbitraryPath(const MSEdge *walkingArea)
return an arbitrary path across the given walkingArea
static const MSLane * getNextWalkingArea(const MSLane *currentLane, const int dir, MSLink *&link)
return the next walkingArea in the given direction
bool ignoreRed(const MSLink *link) const
whether the pedestrian may ignore a red light
static int connectedDirection(const MSLane *from, const MSLane *to)
returns the direction in which these lanes are connectioned or 0 if they are not
WalkingAreaPath * myWalkingAreaPath
the current walkingAreaPath or 0
static const double MIN_STARTUP_DIST
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:244
The pedestrian following model.
information regarding surround Pedestrians (and potentially other things)
const MSEdge * getDestination() const
returns the destination edge
const MSEdgeVector & getPredecessors() const
Definition: MSEdge.h:338
The base class for an intersection.
Definition: MSJunction.h:61
double y() const
Returns the y-position.
Definition: Position.h:62
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
#define INVALID
PState(MSPerson *person, MSPerson::MSPersonStage_Walking *stage, const MSLane *lane)
const MSEdge * getEdge() const
Returns the current edge.
Definition: MSPerson.cpp:88
AnyVehicleIterator is a structure, which manages the iteration through all vehicles on the lane...
Definition: MSLane.h:107
static const int FORWARD
Definition: MSPModel.h:100
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
double x() const
Returns the x-position.
Definition: Position.h:57
void registerJammed()
register a jammed transportable
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:162
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
T MAX2(T a, T b)
Definition: StdDefs.h:76
void remove(PedestrianState *state)
remove the specified person from the pedestrian simulation
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:514
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:456
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:71
PositionVector reverse() const
reverse position vector
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:72
bool usingInternalLanes()
whether movements on intersections are modelled /
std::map< std::pair< const MSLane *, const MSLane * >, WalkingAreaPath > WalkingAreaPaths
const std::string & getID() const
Returns the id.
Definition: Named.h:78
bool moveToNextLane(SUMOTime currentTime)
return whether this pedestrian has passed the end of the current lane and update myRelX if so ...
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
Position getLanePosition(const MSLane *lane, double at, double offset) const
get position on lane at length at with orthogonal offset
void moveToXY(MSPerson *p, Position pos, MSLane *lane, double lanePos, double lanePosLat, double angle, int routeOffset, const ConstMSEdgeVector &edges, SUMOTime t)
try to move person to the given position
static bool usingInternalLanesStatic()
static MSPModel * myModel
Definition: MSPModel.h:122
double getLength() const
return the length of the edge
Definition: MSEdge.h:568
double getMaxX(const bool includeMinGap=true) const
return the maximum position on the lane
static WalkingAreaPaths myWalkingAreaPaths
store for walkinArea elements
const MSJunction * getToJunction() const
Definition: MSEdge.h:347
double getLength() const
return the length of the pedestrian
#define MINGAP_TO_VEHICLE
static const double LATERAL_PENALTY
double getWidth() const
Returns the lane&#39;s width.
Definition: MSLane.h:530
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:33
PersonDist nextBlocking(const MSLane *lane, double minPos, double minRight, double maxLeft, double stopTime=0)
returns the next pedestrian beyond minPos that is laterally between minRight and maxLeft or 0 ...
double mySpeed
the current walking speed
static const double OBSTRUCTION_THRESHOLD
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
The simulated network and simulation perfomer.
Definition: MSNet.h:84
bool myAmJammed
whether the person is jammed
int getVehicleNumberWithPartials() const
Returns the number of vehicles on this lane (including partial occupators)
Definition: MSLane.h:387
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
#define SIMTIME
Definition: SUMOTime.h:65
static Pedestrians noPedestrians
empty pedestrian vector
static bool gCheck4Accidents
Definition: MSGlobals.h:76
void mergeObstacles(Obstacles &into, const Obstacles &obs2)
replace obstacles in the first vector with obstacles from the second if they are closer to me ...
NextLaneInfo myNLI
information about the upcoming lane
static const double RESERVE_FOR_ONCOMING_FACTOR_JUNCTIONS
A road/street connecting two junctions.
Definition: MSEdge.h:75
Pedestrians & getPedestrians(const MSLane *lane)
retrieves the pedestian vector for the given lane (may be empty)
static int canTraverse(int dir, const ConstMSEdgeVector &route)
Definition: MSPModel.cpp:92
static bool addCrossingVehs(const MSLane *crossing, int stripes, double lateral_offset, int dir, Obstacles &crossingVehs, bool prio)
add vehicles driving across
const MSCFModel & getCarFollowModel() const
Returns the vehicle&#39;s car following model definition.
Definition: MSVehicle.h:891
double xFwd
maximal position on the current lane in forward direction
static const int UNDEFINED_DIRECTION
Definition: MSPModel.h:105
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
SUMOTime execute(SUMOTime currentTime)
Executes the command.
static const double OBSTRUCTED_PENALTY
static const double DIST_OVERLAP
static MSPModel * getModel()
Definition: MSPModel.cpp:59
#define DEBUGCOND2(LANE)
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:776
void walk(const Obstacles &obs, SUMOTime currentTime)
perform position update
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
static int getStripeOffset(int origStripes, int destStripes, bool addRemainder)
static Obstacles getVehicleObstacles(const MSLane *lane, int dir, PState *ped=0)
retrieve vehicle obstacles on the given lane
A list of positions.
double compute(const E *from, const E *to, double departPos, double arrivalPos, double speed, SUMOTime msTime, const N *onlyNode, std::vector< const E *> &into, bool allEdges=false)
Builds the route between the given edges using the minimum effort at the given time The definition of...
double myRelY
the orthogonal shift on the current lane
Position myRemoteXYPos
remote-controlled position
double xBack
maximal position on the current lane in backward direction
double myRelX
the advancement along the current lane
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:409
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
double myAngle
cached angle
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
double getSpeed(const MSPerson::MSPersonStage_Walking &stage) const
return the current speed of the person
static double fromNaviDegree(const double angle)
Definition: GeomHelper.cpp:197
Position getPosition(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const
return the network coordinate of the person
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:263
double distToLaneEnd() const
the absolute distance to the end of the lane in walking direction (or to the arrivalPos) ...
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
double getMaxSpeed() const
Get vehicle&#39;s maximum speed [m/s].
static double dawdling
T MIN2(T a, T b)
Definition: StdDefs.h:70
AnyVehicleIterator anyVehiclesEnd() const
end iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:418
AnyVehicleIterator anyVehiclesBegin() const
begin iterator for iterating over all vehicles touching this lane in downstream direction ...
Definition: MSLane.h:412
#define POSITION_EPS
Definition: config.h:172
const std::string & getID() const
returns the id of the transportable
double getMaxSpeed(const MSTransportable *const person) const
accessors to be used by MSPModel
Definition: MSPerson.cpp:349
bool hasInternalLinks() const
return whether the network contains internal links
Definition: MSNet.h:605
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
double getMinGap() const
Get the free space in front of vehicles of this class.
std::map< const MSLane *, Obstacles, lane_by_numid_sorter > NextLanesObstacles
double getMaxDecel() const
Get the vehicle type&#39;s maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:218
AnyVehicleIterator anyVehiclesUpstreamBegin() const
begin iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:424
double getArrivalPos() const
Definition: MSPerson.h:154
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition: MSEdge.h:230
bool isInternal() const
return whether this edge is an internal edge
Definition: MSEdge.h:225
SUMOTime myWaitingTime
the consecutive time spent at speed 0
const ConstMSEdgeVector & getRoute() const
Definition: MSPerson.h:168
int myDir
the walking direction on the current lane (1 forward, -1 backward)
static const double LOOKAHEAD_SAMEDIR
const SUMOVTypeParameter & getParameter() const
MSPedestrianRouter & getPedestrianRouter(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:934
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double speed
speed relative to lane direction (positive means in the same direction)
const Obstacles & getNextLaneObstacles(NextLanesObstacles &nextLanesObs, const MSLane *lane, const MSLane *nextLane, int stripes, int nextDir, double currentLength, int currentDir)
void cleanupHelper()
remove state at simulation end
PedestrianState * add(MSPerson *person, MSPerson::MSPersonStage_Walking *stage, SUMOTime now)
register the given person as a pedestrian
static const double RESERVE_FOR_ONCOMING_FACTOR
double getLateralPositionOnLane() const
Get the vehicle&#39;s lateral position on the lane.
Definition: MSVehicle.h:440
void arriveAndAdvance(Pedestrians &pedestrians, SUMOTime currentTime, std::set< MSPerson *> &changedLane, int dir)
handle arrivals and lane advancement
static void transformToCurrentLanePositions(Obstacles &o, int currentDir, int nextDir, double currentLength, double nextLength)
abstract base class for managing callbacks to retrieve various state information from the model ...
Definition: MSPModel.h:128
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
std::pair< const MSPerson *, double > PersonDist
Definition: MSPModel.h:38
bool hasPedestrians(const MSLane *lane)
whether the given lane has pedestrians on it
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:981
const std::vector< const MSEdge * >::iterator getRouteStep() const
Definition: MSPerson.h:158
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
std::map< const MSLane *, double > MinNextLengths
ObstacleType type
whether this obstacle denotes a border or a pedestrian
static const double DIST_FAR_AWAY
double getEdgePos(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const
abstract methods inherited from PedestrianState
static const double ONCOMING_CONFLICT_PENALTY
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
const MSEdge * getNextEdge(const MSPerson::MSPersonStage_Walking &stage) const
return the list of internal edges if the pedestrian is on an intersection
std::vector< PState * > Pedestrians
SUMOTime getWaitingTime(SUMOTime now) const
the time this transportable spent waiting
Definition: MSPerson.cpp:122
#define SUMOTime_MAX
Definition: SUMOTime.h:37
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
static double stripeWidth
model parameters
static const double INAPPROPRIATE_PENALTY
bool myWaitingToEnter
whether the pedestrian is waiting to start its walk
#define M_PI
Definition: odrSpiral.cpp:40
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition: MSEdge.cpp:821
const MSJunction * getFromJunction() const
Definition: MSEdge.h:343
double distanceTo(const Obstacle &obs, const bool includeMinGap=true) const
bool moveToNextEdge(MSPerson *person, SUMOTime currentTime, MSEdge *nextInternal=nullptr)
move forward and return whether the person arrived
Definition: MSPerson.cpp:315
A storage for options typed value containers)
Definition: OptionsCont.h:92
Container for pedestrian state and individual position update function.
std::vector< Obstacle > Obstacles
double getLength() const
Get vehicle&#39;s length [m].
AnyVehicleIterator anyVehiclesUpstreamEnd() const
end iterator for iterating over all vehicles touching this lane in upstream direction ...
Definition: MSLane.h:430
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:60
#define DEBUGCOND(PED)
static const int BACKWARD
Definition: MSPModel.h:104
bool isWalkingArea() const
return whether this edge is walking area
Definition: MSEdge.h:244
const MSVehicleType & getVehicleType() const
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle&#39;s position relative to the given lane.
Definition: MSVehicle.cpp:3701
const MSEdge * getRouteEdge() const
Definition: MSPerson.h:162
static const double SAFETY_GAP
Definition: MSPModel.h:108
double getMinX(const bool includeMinGap=true) const
return the minimum position on the lane
T MIN3(T a, T b, T c)
Definition: StdDefs.h:83
#define NUMERICAL_EPS
Definition: config.h:148
void push_back_noDoublePos(const Position &p)
insert in back a non double position
static void DEBUG_PRINT(const Obstacles &obs)
double getImpatience() const
Returns this type&#39;s impatience.
static void addCloserObstacle(Obstacles &obs, double x, int stripe, int numStripes, const std::string &id, double width, int dir, ObstacleType type)
const MSEdge * getNextRouteEdge() const
Definition: MSPerson.h:165
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:71
static SUMOTime jamTime
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1975
int myNumActivePedestrians
the total number of active pedestrians
double getAngle(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const
return the direction in which the person faces in degrees
static MinNextLengths myMinNextLengths
double getSpeed() const
Returns the vehicle&#39;s current speed.
Definition: MSVehicle.h:483
std::string description
the id / description of the obstacle
SUMOTime getWaitingTime(const MSPerson::MSPersonStage_Walking &stage, SUMOTime now) const
return the time the person spent standing
static void initWalkingAreaPaths(const MSNet *net)
MSPModel_Striping(const OptionsCont &oc, MSNet *net)
Constructor (it should not be necessary to construct more than one instance)
const std::string & getID() const
Returns the name of the vehicle.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const double MAX_WAIT_TOLERANCE
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
ActiveLanes myActiveLanes
store of all lanes which have pedestrians on them
const MSLane * myLane
the current lane of this pedestrian
Position transformToVectorCoordinates(const Position &p, bool extend=false) const
return position p within the length-wise coordinate system defined by this position vector...
bool blockedAtDist(const MSLane *lane, double vehSide, double vehWidth, double oncomingGap, std::vector< const MSPerson *> *collectBlockers)
whether a pedestrian is blocking the crossing of lane for the given vehicle bondaries ...
SumoXMLEdgeFunc getFunction() const
Returns the edge type (SumoXMLEdgeFunc)
Definition: MSEdge.h:220
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:285
static const double LOOKAROUND_VEHICLES
StageType getCurrentStageType() const
the current stage type of the transportable
void setRouteIndex(MSPerson *person, int routeOffset)
place person on a previously passed edge
Definition: MSPerson.cpp:340