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