Eclipse SUMO - Simulation of Urban MObility
MESegment.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // A single mesoscopic segment (cell)
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <algorithm>
23 #include <limits>
24 #include <utils/common/StdDefs.h>
25 #include <microsim/MSGlobals.h>
26 #include <microsim/MSEdge.h>
27 #include <microsim/MSJunction.h>
28 #include <microsim/MSNet.h>
29 #include <microsim/MSLane.h>
30 #include <microsim/MSVehicle.h>
39 #include "MEVehicle.h"
40 #include "MELoop.h"
41 #include "MESegment.h"
42 
43 #define DEFAULT_VEH_LENGTH_WITH_GAP (SUMOVTypeParameter::getDefault().length + SUMOVTypeParameter::getDefault().minGap)
44 // avoid division by zero when driving very slowly
45 #define MESO_MIN_SPEED (0.05)
46 // divide tau by lane number unless we have multiple queues
47 #define SCALED_TAU(x) (multiQueue ? x : (SUMOTime)(x / parent.getLanes().size()))
48 
49 //#define DEBUG_OPENED
50 //#define DEBUG_JAMTHRESHOLD
51 //#define DEBUG_COND (getID() == "blocker")
52 //#define DEBUG_COND (true)
53 #define DEBUG_COND (myEdge.isSelected())
54 #define DEBUG_COND2(obj) ((obj != 0 && (obj)->isSelected()))
55 
56 
57 // ===========================================================================
58 // static member defintion
59 // ===========================================================================
60 MSEdge MESegment::myDummyParent("MESegmentDummyParent", -1, SumoXMLEdgeFunc::UNKNOWN, "", "", -1, 0);
61 MESegment MESegment::myVaporizationTarget("vaporizationTarget");
62 const double MESegment::DO_NOT_PATCH_JAM_THRESHOLD(std::numeric_limits<double>::max());
63 
64 
65 // ===========================================================================
66 // MESegment::Queue method definitions
67 // ===========================================================================
68 MEVehicle*
71  assert(std::find(myVehicles.begin(), myVehicles.end(), v) != myVehicles.end());
72  if (v == myVehicles.back()) {
73  myVehicles.pop_back();
74  if (myVehicles.empty()) {
75  myOccupancy = 0.;
76  } else {
77  return myVehicles.back();
78  }
79  } else {
80  myVehicles.erase(std::find(myVehicles.begin(), myVehicles.end(), v));
81  }
82  return nullptr;
83 }
84 
85 
86 // ===========================================================================
87 // MESegment method definitions
88 // ===========================================================================
89 MESegment::MESegment(const std::string& id,
90  const MSEdge& parent, MESegment* next,
91  const double length, const double speed,
92  const int idx,
93  const bool multiQueue,
94  const MSNet::MesoEdgeType& edgeType):
95  Named(id), myEdge(parent), myNextSegment(next),
96  myLength(length), myIndex(idx),
98  myHeadwayCapacity(length / DEFAULT_VEH_LENGTH_WITH_GAP * parent.getLanes().size())/* Eissfeldt p. 69 */,
99  myCapacity(length * parent.getLanes().size()),
100  myQueueCapacity(multiQueue ? length : length * parent.getLanes().size()),
101  myNumVehicles(0),
103  myMeanSpeed(speed),
105 
106  if (multiQueue) {
107  const std::vector<MSLane*>& lanes = parent.getLanes();
108  for (MSLane* const l : lanes) {
109  myQueues.push_back(Queue(l->getPermissions()));
110  }
111  if (next == nullptr) {
112  for (const MSEdge* const edge : parent.getSuccessors()) {
113  const std::vector<MSLane*>* const allowed = parent.allowedLanes(*edge);
114  assert(allowed != nullptr);
115  assert(allowed->size() > 0);
116  for (MSLane* const l : *allowed) {
117  std::vector<MSLane*>::const_iterator it = std::find(lanes.begin(), lanes.end(), l);
118  myFollowerMap[edge] |= (1 << distance(lanes.begin(), it));
119  }
120  }
121  }
122  } else {
123  myQueues.push_back(Queue(parent.getPermissions()));
124  }
125 
126  initSegment(edgeType, parent);
127 }
128 
129 void
130 MESegment::initSegment(const MSNet::MesoEdgeType& edgeType, const MSEdge& parent) {
131 
132  const bool multiQueue = myQueues.size() > 1;
133 
134  // Eissfeldt p. 90 and 151 ff.
135  myTau_ff = SCALED_TAU(edgeType.tauff);
136  myTau_fj = SCALED_TAU(edgeType.taufj);
137  myTau_jf = SCALED_TAU(edgeType.taujf);
138  myTau_jj = SCALED_TAU(edgeType.taujj);
139 
140  myJunctionControl = myNextSegment == nullptr && (edgeType.junctionControl || MELoop::isEnteringRoundabout(parent));
141  myTLSPenalty = ((edgeType.tlsPenalty > 0 || edgeType.tlsFlowPenalty > 0) &&
142  // only apply to the last segment of a tls-controlled edge
143  myNextSegment == nullptr && (
147 
148  // only apply to the last segment of an uncontrolled edge that has at least 1 minor link
149  myCheckMinorPenalty = (edgeType.minorPenalty > 0 &&
150  myNextSegment == nullptr &&
154  parent.hasMinorLink());
155  myMinorPenalty = edgeType.minorPenalty;
156  myOvertaking = edgeType.overtaking && myCapacity > myLength;
157 
158  //std::cout << getID() << " myMinorPenalty=" << myMinorPenalty << " myTLSPenalty=" << myTLSPenalty << " myJunctionControl=" << myJunctionControl << " myOvertaking=" << myOvertaking << "\n";
159 
161 }
162 
163 MESegment::MESegment(const std::string& id):
164  Named(id),
165  myEdge(myDummyParent), // arbitrary edge needed to supply the needed reference
166  myNextSegment(nullptr), myLength(0), myIndex(0),
167  myTau_ff(0), myTau_fj(0), myTau_jf(0), myTau_jj(0),
168  myTLSPenalty(false),
169  myCheckMinorPenalty(false),
170  myMinorPenalty(0),
171  myJunctionControl(false),
172  myOvertaking(false),
173  myTau_length(1),
174  myHeadwayCapacity(0), myCapacity(0), myQueueCapacity(0) {
175 }
176 
177 
178 
179 void
181  if (jamThresh == DO_NOT_PATCH_JAM_THRESHOLD) {
182  return;
183  }
184  if (jamThresh < 0) {
185  // compute based on speed
187  } else {
188  // compute based on specified percentage
189  myJamThreshold = jamThresh * myCapacity;
190  }
191 
192  // update coefficients for the jam-jam headway function
193  // this function models the effect that "empty space" needs to move
194  // backwards through the downstream segment before the upstream segment may
195  // send annother vehicle.
196  // this allows jams to clear and move upstream.
197  // the headway function f(x) depends on the number of vehicles in the
198  // downstream segment x
199  // f is a linear function that passes through the following fixed points:
200  // f(n_jam_threshold) = tau_jf_withLength (for continuity)
201  // f(myHeadwayCapacity) = myTau_jj * myHeadwayCapacity
202 
204  if (myJamThreshold < myCapacity) {
205  // jamming is possible
206  const double n_jam_threshold = myHeadwayCapacity * myJamThreshold / myCapacity; // number of vehicles above which the segment is jammed
207  // solving f(x) = a * x + b
208  myA = (STEPS2TIME(myTau_jj) * myHeadwayCapacity - STEPS2TIME(tau_jf_withLength)) / (myHeadwayCapacity - n_jam_threshold);
210 
211  // note that the original Eissfeldt model (p. 69) used different fixed points
212  // f(n_jam_threshold) = n_jam_threshold * myTau_jj
213  // f(myHeadwayCapacity) = myTau_jf * myHeadwayCapacity
214  //
215  // However, this systematically underestimates the backpropagation speed of the jam front (see #2244)
216  } else {
217  // dummy values. Should not be used
218  myA = 0;
219  myB = STEPS2TIME(tau_jf_withLength);
220  }
221 }
222 
223 
224 double
225 MESegment::jamThresholdForSpeed(double speed, double jamThresh) const {
226  // vehicles driving freely at maximum speed should not jam
227  // we compute how many vehicles could possible enter the segment until the first vehicle leaves
228  // and multiply by the space these vehicles would occupy
229  // the jamThresh parameter is scale the resulting value
230  if (speed == 0) {
231  return std::numeric_limits<double>::max(); // never jam. Irrelevant at speed 0 anyway
232  }
233 #ifdef DEBUG_JAMTHRESHOLD
234  if (true || DEBUG_COND) {
235  std::cout << "jamThresholdForSpeed seg=" << getID() << " speed=" << speed << " jamThresh=" << jamThresh << " ffVehs=" << std::ceil(myLength / (-jamThresh * speed * STEPS2TIME(tauWithVehLength(myTau_ff, DEFAULT_VEH_LENGTH_WITH_GAP)))) << " thresh=" << std::ceil(myLength / (-jamThresh * speed * STEPS2TIME(tauWithVehLength(myTau_ff, DEFAULT_VEH_LENGTH_WITH_GAP)))) * DEFAULT_VEH_LENGTH_WITH_GAP
236  << "\n";
237  }
238 #endif
240 }
241 
242 
243 void
245  myDetectorData.push_back(data);
246  for (const Queue& q : myQueues) {
247  for (MEVehicle* const v : q.getVehicles()) {
248  v->addReminder(data);
249  }
250  }
251 }
252 
253 
254 void
256  std::vector<MSMoveReminder*>::iterator it = std::find(myDetectorData.begin(), myDetectorData.end(), data);
257  if (it != myDetectorData.end()) {
258  myDetectorData.erase(it);
259  }
260  for (const Queue& q : myQueues) {
261  for (MEVehicle* const v : q.getVehicles()) {
262  v->removeReminder(data);
263  }
264  }
265 }
266 
267 
268 void
270  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
271  for (const Queue& q : myQueues) {
272  SUMOTime earliestExitTime = currentTime;
273  for (std::vector<MEVehicle*>::const_reverse_iterator i = q.getVehicles().rbegin(); i != q.getVehicles().rend(); ++i) {
274  const SUMOTime exitTime = MAX2(earliestExitTime, (*i)->getEventTime());
275  (*i)->updateDetectorForWriting(&data, currentTime, exitTime);
276  earliestExitTime = exitTime + tauWithVehLength(myTau_ff, (*i)->getVehicleType().getLengthWithGap());
277  }
278  }
279 }
280 
281 
282 SUMOTime
283 MESegment::hasSpaceFor(const MEVehicle* const veh, const SUMOTime entryTime, int& qIdx, const bool init) const {
284  qIdx = 0;
285  if (myNumVehicles == 0 && myQueues.size() == 1) {
286  // we have always space for at least one vehicle
287  return entryTime;
288  }
289  SUMOTime earliestEntry = SUMOTime_MAX;
290  const SUMOVehicleClass svc = veh->getVClass();
291  int minSize = std::numeric_limits<int>::max();
292  const MSEdge* const succ = myNextSegment == nullptr ? veh->succEdge(1) : nullptr;
293  for (int i = 0; i < (int)myQueues.size(); i++) {
294  const Queue& q = myQueues[i];
295  const double newOccupancy = q.size() == 0 ? 0. : q.getOccupancy() + veh->getVehicleType().getLengthWithGap();
296  if (newOccupancy <= myQueueCapacity) { // we must ensure that occupancy remains below capacity
297  if (succ == nullptr || myFollowerMap.count(succ) == 0 || ((myFollowerMap.find(succ)->second & (1 << i)) != 0)) {
298  if (q.allows(svc) && q.size() < minSize) {
299  if (init) {
300  // regular insertions and initial insertions must respect different constraints:
301  // - regular insertions must respect entryBlockTime
302  // - initial insertions should not cause additional jamming
303  // - inserted vehicle should be able to continue at the current speed
305  if (newOccupancy <= myJamThreshold) {
306  qIdx = i;
307  minSize = q.size();
308  }
309  } else {
310  if (newOccupancy <= jamThresholdForSpeed(getMeanSpeed(false), -1)) {
311  qIdx = i;
312  minSize = q.size();
313  }
314  }
315  } else if (entryTime >= q.getEntryBlockTime()) {
316  qIdx = i;
317  minSize = q.size();
318  } else {
319  earliestEntry = MIN2(earliestEntry, q.getEntryBlockTime());
320  }
321  }
322  }
323  }
324  }
325  if (minSize == std::numeric_limits<int>::max()) {
326  return earliestEntry;
327  }
328  return entryTime;
329 }
330 
331 
332 bool
334  int qIdx = 0;
335  if (hasSpaceFor(veh, time, qIdx, true) == time) {
336  receive(veh, qIdx, time, true);
337  // we can check only after insertion because insertion may change the route via devices
338  std::string msg;
339  if (MSGlobals::gCheckRoutes && !veh->hasValidRoute(msg)) {
340  throw ProcessError("Vehicle '" + veh->getID() + "' has no valid route. " + msg);
341  }
342  return true;
343  }
344  return false;
345 }
346 
347 
348 double
349 MESegment::getMeanSpeed(bool useCached) const {
350  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
351  if (currentTime != myLastMeanSpeedUpdate || !useCached) {
352  myLastMeanSpeedUpdate = currentTime;
353  double v = 0;
354  int count = 0;
355  for (const Queue& q : myQueues) {
356  const SUMOTime tau = q.getOccupancy() < myJamThreshold ? myTau_ff : myTau_jf;
357  SUMOTime earliestExitTime = currentTime;
358  count += q.size();
359  for (std::vector<MEVehicle*>::const_reverse_iterator veh = q.getVehicles().rbegin(); veh != q.getVehicles().rend(); ++veh) {
360  v += (*veh)->getConservativeSpeed(earliestExitTime); // earliestExitTime is updated!
361  earliestExitTime += tauWithVehLength(tau, (*veh)->getVehicleType().getLengthWithGap());
362  }
363  }
364  if (count == 0) {
366  } else {
367  myMeanSpeed = v / (double) count;
368  }
369  }
370  return myMeanSpeed;
371 }
372 
373 
374 void
376  for (const Queue& q : myQueues) {
377  for (const MEVehicle* const veh : q.getVehicles()) {
378  MSXMLRawOut::writeVehicle(of, *veh);
379  }
380  }
381 }
382 
383 
384 MEVehicle*
386  Queue& q = myQueues[v->getQueIndex()];
387  // One could be tempted to do v->setSegment(next); here but position on lane will be invalid if next == 0
388  v->updateDetectors(leaveTime, true, reason);
389  myNumVehicles--;
390  myEdge.lock();
391  MEVehicle* nextLeader = q.remove(v);
392  myEdge.unlock();
393  return nextLeader;
394 }
395 
396 
397 SUMOTime
399  // since we do not know which queue will be used we give a conservative estimate
400  SUMOTime earliestLeave = earliestEntry;
401  SUMOTime latestEntry = -1;
402  for (const Queue& q : myQueues) {
403  earliestLeave = MAX2(earliestLeave, q.getBlockTime());
404  latestEntry = MAX2(latestEntry, q.getEntryBlockTime());
405  }
406  if (myEdge.getSpeedLimit() == 0) {
407  return MAX2(earliestEntry, latestEntry); // FIXME: This line is just an adhoc-fix to avoid division by zero (Leo)
408  } else {
409  return MAX3(earliestEntry, earliestLeave - TIME2STEPS(myLength / myEdge.getSpeedLimit()), latestEntry);
410  }
411 }
412 
413 
414 MSLink*
415 MESegment::getLink(const MEVehicle* veh, bool penalty) const {
416  if (myJunctionControl || penalty) {
417  const MSEdge* const nextEdge = veh->succEdge(1);
418  if (nextEdge == nullptr) {
419  return nullptr;
420  }
421  // try to find any link leading to our next edge, start with the lane pointed to by the que index
422  const MSLane* const bestLane = myEdge.getLanes()[veh->getQueIndex()];
423  for (MSLink* const link : bestLane->getLinkCont()) {
424  if (&link->getLane()->getEdge() == nextEdge) {
425  return link;
426  }
427  }
428  // this is for the non-multique case, maybe we should use caching here !!!
429  for (const MSLane* const lane : myEdge.getLanes()) {
430  if (lane != bestLane) {
431  for (MSLink* const link : lane->getLinkCont()) {
432  if (&link->getLane()->getEdge() == nextEdge) {
433  return link;
434  }
435  }
436  }
437  }
438  }
439  return nullptr;
440 }
441 
442 
443 bool
444 MESegment::isOpen(const MEVehicle* veh) const {
445 #ifdef DEBUG_OPENED
446  if (DEBUG_COND || DEBUG_COND2(veh)) {
447  gDebugFlag1 = true;
448  std::cout << SIMTIME << " opened seg=" << getID() << " veh=" << Named::getIDSecure(veh)
449  << " tlsPenalty=" << myTLSPenalty;
450  const MSLink* link = getLink(veh);
451  if (link == 0) {
452  std::cout << " link=0";
453  } else {
454  std::cout << " prio=" << link->havePriority()
455  << " override=" << limitedControlOverride(link)
456  << " isOpen=" << link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
459  << " et=" << veh->getEventTime()
460  << " v=" << veh->getSpeed()
461  << " vLeave=" << veh->estimateLeaveSpeed(link)
462  << " impatience=" << veh->getImpatience()
463  << " tWait=" << veh->getWaitingTime();
464  }
465  std::cout << "\n";
466  gDebugFlag1 = false;
467  }
468 #endif
469  if (myTLSPenalty) {
470  // XXX should limited control take precedence over tls penalty?
471  return true;
472  }
473  const MSLink* link = getLink(veh);
474  return (link == nullptr
475  || link->havePriority()
476  || limitedControlOverride(link)
477  || link->opened(veh->getEventTime(), veh->getSpeed(), veh->estimateLeaveSpeed(link),
480 }
481 
482 
483 bool
485  assert(link != nullptr);
487  return false;
488  }
489  // if the target segment of this link is not saturated junction control is disabled
490  const MSEdge& targetEdge = link->getLane()->getEdge();
491  const MESegment* target = MSGlobals::gMesoNet->getSegmentForEdge(targetEdge);
492  return (target->getBruttoOccupancy() * 2 < target->myJamThreshold) && !targetEdge.isRoundabout();
493 }
494 
495 
496 void
497 MESegment::send(MEVehicle* veh, MESegment* const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason) {
498  Queue& q = myQueues[veh->getQueIndex()];
499  assert(isInvalid(next) || time >= q.getBlockTime());
500  MSLink* const link = getLink(veh);
501  if (link != nullptr) {
502  link->removeApproaching(veh);
503  }
504  MEVehicle* lc = removeCar(veh, time, reason); // new leaderCar
505  q.setBlockTime(time);
506  if (!isInvalid(next)) {
507  const bool nextFree = next->myQueues[nextQIdx].getOccupancy() <= next->myJamThreshold;
508  const SUMOTime tau = (q.getOccupancy() <= myJamThreshold
509  ? (nextFree ? myTau_ff : myTau_fj)
510  : (nextFree ? myTau_jf : TIME2STEPS(myA * q.size() + myB)));
512  if (myTLSPenalty) {
513  const MSLink* const tllink = getLink(veh, true);
514  if (tllink != nullptr && tllink->isTLSControlled()) {
515  assert(tllink->getGreenFraction() > 0);
517  }
518  }
520  }
521  if (lc != nullptr) {
522  lc->setEventTime(MAX2(lc->getEventTime(), q.getBlockTime()));
524  }
525  if (veh->isStopped()) {
526  veh->processStop();
527  }
528 }
529 
530 
531 bool
534 }
535 
536 
537 void
539  for (std::vector<MSMoveReminder*>::const_iterator i = myDetectorData.begin(); i != myDetectorData.end(); ++i) {
540  veh->addReminder(*i);
541  }
542 }
543 
544 
545 void
546 MESegment::receive(MEVehicle* veh, const int qIdx, SUMOTime time, const bool isDepart, const bool isTeleport, const bool newEdge) {
547  const double speed = isDepart ? -1 : MAX2(veh->getSpeed(), MESO_MIN_SPEED); // on the previous segment
548  veh->setSegment(this); // for arrival checking
549  veh->setLastEntryTime(time);
551  if (!isDepart && (
552  // arrival on entering a new edge
553  (newEdge && veh->moveRoutePointer())
554  // arrival on entering a new segment
555  || veh->hasArrived())) {
556  // route has ended
557  veh->setEventTime(time + TIME2STEPS(myLength / speed)); // for correct arrival speed
558  addReminders(veh);
560  veh->updateDetectors(time, true,
563  return;
564  }
565  assert(veh->getEdge() == &getEdge());
566  // route continues
567  const double maxSpeedOnEdge = veh->getEdge()->getVehicleMaxSpeed(veh);
568  const double uspeed = MAX2(maxSpeedOnEdge, MESO_MIN_SPEED);
569  Queue& q = myQueues[qIdx];
570  std::vector<MEVehicle*>& cars = q.getModifiableVehicles();
571  MEVehicle* newLeader = nullptr; // first vehicle in the current queue
572  SUMOTime tleave = MAX2(veh->checkStop(time) + TIME2STEPS(myLength / uspeed) + getLinkPenalty(veh), q.getBlockTime());
573  if (veh->isStopped()) {
574  myEdge.addWaiting(veh);
575  }
576  myEdge.lock();
577  if (cars.empty()) {
578  cars.push_back(veh);
579  newLeader = veh;
580  } else {
581  SUMOTime leaderOut = cars[0]->getEventTime();
582  if (!isDepart && leaderOut > tleave && overtake()) {
583  if (cars.size() == 1) {
585  newLeader = veh;
586  }
587  cars.insert(cars.begin() + 1, veh);
588  } else {
589  tleave = MAX2(leaderOut + tauWithVehLength(myTau_ff, cars[0]->getVehicleType().getLengthWithGap()), tleave);
590  cars.insert(cars.begin(), veh);
591  }
592  }
593  myEdge.unlock();
594  myNumVehicles++;
595  if (!isDepart && !isTeleport) {
596  // departs and teleports could take place anywhere on the edge so they should not block regular flow
597  // the -1 facilitates interleaving of multiple streams
599  }
600  veh->setEventTime(tleave);
601  veh->setSegment(this, qIdx);
603  addReminders(veh);
604  if (isDepart) {
605  veh->onDepart();
607  } else if (newEdge) {
609  } else {
611  }
612  if (newLeader != nullptr) {
613  MSGlobals::gMesoNet->addLeaderCar(newLeader, getLink(newLeader));
614  }
615 }
616 
617 
618 bool
620  for (const Queue& q : myQueues) {
621  if (q.size() > 0) {
622  for (MEVehicle* const veh : q.getVehicles()) {
623  if (filter->vehicleApplies(*veh)) {
626  return true;
627  }
628  }
629  }
630  }
631  return false;
632 }
633 
634 
635 void
636 MESegment::setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector<MEVehicle*>& vehs) {
637  MEVehicle* v = vehs.back();
638  v->updateDetectors(currentTime, false);
639  SUMOTime newEvent = MAX2(newArrival(v, newSpeed, currentTime), blockTime);
640  if (v->getEventTime() != newEvent) {
642  v->setEventTime(newEvent);
644  }
645  for (std::vector<MEVehicle*>::const_reverse_iterator i = vehs.rbegin() + 1; i != vehs.rend(); ++i) {
646  (*i)->updateDetectors(currentTime, false);
647  newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff);
648  //newEvent = MAX2(newArrival(*i, newSpeed, currentTime), newEvent + myTau_ff + (SUMOTime)((*(i - 1))->getVehicleType().getLength() / myTau_length));
649  (*i)->setEventTime(newEvent);
650  }
651 }
652 
653 
654 SUMOTime
655 MESegment::newArrival(const MEVehicle* const v, double newSpeed, SUMOTime currentTime) {
656  // since speed is only an upper bound pos may be to optimistic
657  const double pos = MIN2(myLength, STEPS2TIME(currentTime - v->getLastEntryTime()) * v->getSpeed());
658  // traveltime may not be 0
659  return currentTime + MAX2(TIME2STEPS((myLength - pos) / newSpeed), SUMOTime(1));
660 }
661 
662 
663 void
664 MESegment::setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh) {
665  recomputeJamThreshold(jamThresh);
666  //myTau_length = MAX2(MESO_MIN_SPEED, newSpeed) * myEdge.getLanes().size() / TIME2STEPS(1);
667  for (const Queue& q : myQueues) {
668  if (q.size() != 0) {
669  setSpeedForQueue(newSpeed, currentTime, q.getBlockTime(), q.getVehicles());
670  }
671  }
672 }
673 
674 
675 SUMOTime
677  SUMOTime result = SUMOTime_MAX;
678  for (const Queue& q : myQueues) {
679  if (q.size() != 0 && q.getVehicles().back()->getEventTime() < result) {
680  result = q.getVehicles().back()->getEventTime();
681  }
682  }
683  if (result < SUMOTime_MAX) {
684  return result;
685  }
686  return -1;
687 }
688 
689 
690 void
692  bool write = false;
693  for (const Queue& q : myQueues) {
694  if (q.getBlockTime() != -1 || !q.getVehicles().empty()) {
695  write = true;
696  break;
697  }
698  }
699  if (write) {
701  for (const Queue& q : myQueues) {
702  out.openTag(SUMO_TAG_VIEWSETTINGS_VEHICLES).writeAttr(SUMO_ATTR_TIME, toString<SUMOTime>(q.getBlockTime()));
703  out.writeAttr(SUMO_ATTR_VALUE, q.getVehicles());
704  out.closeTag();
705  }
706  out.closeTag();
707  }
708 }
709 
710 
711 void
713  for (Queue& q : myQueues) {
714  q.getModifiableVehicles().clear();
715  }
716 }
717 
718 void
719 MESegment::loadState(const std::vector<std::string>& vehIds, MSVehicleControl& vc, const SUMOTime block, const int queIdx) {
720  Queue& q = myQueues[queIdx];
721  for (const std::string& id : vehIds) {
722  MEVehicle* v = static_cast<MEVehicle*>(vc.getVehicle(id));
723  // vehicle could be removed due to options
724  if (v != nullptr) {
725  assert(v->getSegment() == this);
726  q.getModifiableVehicles().push_back(v);
727  myNumVehicles++;
729  }
730  }
731  if (q.size() != 0) {
732  // add the last vehicle of this queue
733  // !!! one question - what about the previously added vehicle? Is it stored twice?
734  MEVehicle* veh = q.getVehicles().back();
736  }
737  q.setBlockTime(block);
739 }
740 
741 
742 std::vector<const MEVehicle*>
744  std::vector<const MEVehicle*> result;
745  for (const Queue& q : myQueues) {
746  result.insert(result.end(), q.getVehicles().begin(), q.getVehicles().end());
747  }
748  return result;
749 }
750 
751 
752 bool
754  for (const Queue& q : myQueues) {
755  if (q.size() > 0 && q.getVehicles().back()->getWaitingTime() > 0) {
756  return true;
757  }
758  }
759  return false;
760 }
761 
762 
763 double
765  return 3600 * getCarNumber() * getMeanSpeed() / myLength;
766 }
767 
768 
769 SUMOTime
771  const MSLink* link = getLink(veh, myTLSPenalty || myCheckMinorPenalty);
772  if (link != nullptr) {
773  SUMOTime result = 0;
774  if (link->isTLSControlled()) {
775  result += link->getMesoTLSPenalty();
776  }
777  // minor tls links may get an additional penalty
778  if (!link->havePriority() &&
779  // do not apply penalty on top of tLSPenalty
780  !myTLSPenalty &&
781  // do not apply penalty if limited control is active
783  result += myMinorPenalty;
784  }
785  return result;
786  } else {
787  return 0;
788  }
789 }
790 
791 
792 double
794  double result = 0;
795  for (const Queue& q : myQueues) {
796  // @note: only the leader currently accumulates waitingTime but this might change in the future
797  for (const MEVehicle* veh : q.getVehicles()) {
798  result += veh->getWaitingSeconds();
799  }
800  }
801  return result;
802 }
803 
804 
805 /****************************************************************************/
#define MESO_MIN_SPEED
Definition: MESegment.cpp:45
#define DEFAULT_VEH_LENGTH_WITH_GAP
Definition: MESegment.cpp:43
#define SCALED_TAU(x)
Definition: MESegment.cpp:47
#define DEBUG_COND
Definition: MESegment.cpp:53
#define DEBUG_COND2(obj)
Definition: MESegment.cpp:54
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SUMOTime_MAX
Definition: SUMOTime.h:32
#define SUMOTime_MIN
Definition: SUMOTime.h:33
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SUMO_TAG_VIEWSETTINGS_VEHICLES
@ SUMO_TAG_SEGMENT
segment of a lane
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_ID
@ SUMO_ATTR_TIME
trigger: the time of the step
bool gDebugFlag1
global utility flags for debugging
Definition: StdDefs.cpp:31
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
T MAX3(T a, T b, T c)
Definition: StdDefs.h:93
static bool isEnteringRoundabout(const MSEdge &e)
whether the given edge is entering a roundabout
Definition: MELoop.cpp:319
SUMOTime changeSegment(MEVehicle *veh, SUMOTime leaveTime, MESegment *const toSegment, MSMoveReminder::Notification reason, const bool ignoreLink=false) const
change to the next segment this handles combinations of the following cases: (ending / continuing rou...
Definition: MELoop.cpp:79
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition: MELoop.cpp:302
void addLeaderCar(MEVehicle *veh, MSLink *link)
Adds the given car to the leading vehicles.
Definition: MELoop.cpp:203
void removeLeaderCar(MEVehicle *v)
Removes the given car from the leading vehicles.
Definition: MELoop.cpp:215
int size() const
Definition: MESegment.h:52
void setOccupancy(const double occ)
Definition: MESegment.h:65
MEVehicle * remove(MEVehicle *v)
Definition: MESegment.cpp:69
void setBlockTime(SUMOTime t)
Definition: MESegment.h:85
SUMOTime getBlockTime() const
Definition: MESegment.h:82
double myOccupancy
The occupied space (in m) in the queue.
Definition: MESegment.h:96
bool allows(SUMOVehicleClass vclass) const
Definition: MESegment.h:68
void setEntryBlockTime(SUMOTime entryBlockTime)
set the next time at which a vehicle may enter this queue
Definition: MESegment.h:78
double getOccupancy() const
Definition: MESegment.h:62
const std::vector< MEVehicle * > & getVehicles() const
Definition: MESegment.h:55
std::vector< MEVehicle * > myVehicles
Definition: MESegment.h:93
SUMOTime getEntryBlockTime() const
return the next time at which a vehicle may enter this queue
Definition: MESegment.h:73
std::vector< MEVehicle * > & getModifiableVehicles()
Definition: MESegment.h:59
A single mesoscopic segment (cell)
Definition: MESegment.h:47
void addReminders(MEVehicle *veh) const
add this lanes MoveReminders to the given vehicle
Definition: MESegment.cpp:538
double myQueueCapacity
The number of lanes represented by the queue * the length of the lane.
Definition: MESegment.h:523
bool overtake()
Definition: MESegment.cpp:532
SUMOTime myTau_ff
The time headway parameters, see the Eissfeldt thesis.
Definition: MESegment.h:493
bool initialise(MEVehicle *veh, SUMOTime time)
Inserts (emits) vehicle into the segment.
Definition: MESegment.cpp:333
std::vector< Queue > myQueues
The car queues. Vehicles are inserted in the front and removed in the back.
Definition: MESegment.h:532
double getBruttoOccupancy() const
Returns the occupany of the segment (the sum of the vehicle lengths + minGaps)
Definition: MESegment.h:224
SUMOTime myLastHeadway
the last headway
Definition: MESegment.h:541
bool limitedControlOverride(const MSLink *link) const
whether the given link may be passed because the option meso-junction-control.limited is set
Definition: MESegment.cpp:484
bool isOpen(const MEVehicle *veh) const
Returns whether the vehicle may use the next link.
Definition: MESegment.cpp:444
void initSegment(const MSNet::MesoEdgeType &edgeType, const MSEdge &parent)
set model parameters (may be updated from additional file after network loading is complete)
Definition: MESegment.cpp:130
void clearState()
Remove all vehicles before quick-loading state.
Definition: MESegment.cpp:712
void receive(MEVehicle *veh, const int qIdx, SUMOTime time, const bool isDepart=false, const bool isTeleport=false, const bool newEdge=false)
Adds the vehicle to the segment, adapting its parameters.
Definition: MESegment.cpp:546
SUMOTime getLinkPenalty(const MEVehicle *veh) const
Returns the penalty time for passing a link (if using gMesoTLSPenalty > 0 or gMesoMinorPenalty > 0)
Definition: MESegment.cpp:770
void writeVehicles(OutputDevice &of) const
Definition: MESegment.cpp:375
std::map< const MSEdge *, int > myFollowerMap
The follower edge to allowed que index mapping for multi queue segments.
Definition: MESegment.h:538
MSLink * getLink(const MEVehicle *veh, bool tlsPenalty=false) const
Returns the link the given car will use when passing the next junction.
Definition: MESegment.cpp:415
const double myCapacity
The number of lanes represented by the queue * the length of the lane.
Definition: MESegment.h:520
int myNumVehicles
The cached value for the number of vehicles.
Definition: MESegment.h:535
void setSpeedForQueue(double newSpeed, SUMOTime currentTime, SUMOTime blockTime, const std::vector< MEVehicle * > &vehs)
Definition: MESegment.cpp:636
SUMOTime hasSpaceFor(const MEVehicle *const veh, const SUMOTime entryTime, int &qIdx, const bool init=false) const
Returns whether the given vehicle would still fit into the segment.
Definition: MESegment.cpp:283
SUMOTime tauWithVehLength(SUMOTime tau, double lengthWithGap) const
convert net time gap (leader back to follower front) to gross time gap (leader front to follower fron...
Definition: MESegment.h:472
void removeDetector(MSMoveReminder *data)
Removes a data collector for a detector from this segment.
Definition: MESegment.cpp:255
void saveState(OutputDevice &out) const
Saves the state of this segment into the given stream.
Definition: MESegment.cpp:691
void prepareDetectorForWriting(MSMoveReminder &data)
Updates data of a detector for all vehicle queues.
Definition: MESegment.cpp:269
static MESegment myVaporizationTarget
Definition: MESegment.h:546
double myJamThreshold
The space (in m) which needs to be occupied before the segment is considered jammed.
Definition: MESegment.h:526
const int myIndex
Running number of the segment in the edge.
Definition: MESegment.h:487
double myB
Definition: MESegment.h:496
void send(MEVehicle *veh, MESegment *const next, const int nextQIdx, SUMOTime time, const MSMoveReminder::Notification reason)
Removes the vehicle from the segment, adapting its parameters.
Definition: MESegment.cpp:497
SUMOTime myMinorPenalty
Definition: MESegment.h:503
double myMeanSpeed
the mean speed on this segment. Updated at event time or on demand
Definition: MESegment.h:549
bool myCheckMinorPenalty
penalty for minor links
Definition: MESegment.h:502
std::vector< MSMoveReminder * > myDetectorData
The data collection for all kinds of detectors.
Definition: MESegment.h:529
double jamThresholdForSpeed(double speed, double jamThresh) const
compute jam threshold for the given speed and jam-threshold option
Definition: MESegment.cpp:225
SUMOTime myLastMeanSpeedUpdate
the time at which myMeanSpeed was last updated
Definition: MESegment.h:552
SUMOTime myTau_jf
Definition: MESegment.h:493
MESegment * myNextSegment
The next segment of this edge, 0 if this is the last segment of this edge.
Definition: MESegment.h:481
const MSEdge & getEdge() const
Returns the edge this segment belongs to.
Definition: MESegment.h:325
bool hasBlockedLeader() const
whether a leader in any queue is blocked
Definition: MESegment.cpp:753
double getWaitingSeconds() const
Get the waiting time for vehicles in all queues.
Definition: MESegment.cpp:793
const double myLength
The segment's length.
Definition: MESegment.h:484
SUMOTime getEventTime() const
Returns the (planned) time at which the next vehicle leaves this segment.
Definition: MESegment.cpp:676
const MSEdge & myEdge
The microsim edge this segment belongs to.
Definition: MESegment.h:478
MEVehicle * removeCar(MEVehicle *v, SUMOTime leaveTime, const MSMoveReminder::Notification reason)
Removes the given car from the edge's que.
Definition: MESegment.cpp:385
std::vector< const MEVehicle * > getVehicles() const
returns all vehicles (for debugging)
Definition: MESegment.cpp:743
void addDetector(MSMoveReminder *data)
Adds a data collector for a detector to this segment.
Definition: MESegment.cpp:244
static MSEdge myDummyParent
Definition: MESegment.h:545
void recomputeJamThreshold(double jamThresh)
compute a value for myJamThreshold if jamThresh is negative, compute a value which allows free flow a...
Definition: MESegment.cpp:180
double myA
slope and axis offset for the jam-jam headway function
Definition: MESegment.h:496
double getMeanSpeed() const
wrapper to satisfy the FunctionBinding signature
Definition: MESegment.h:260
int getCarNumber() const
Returns the total number of cars on the segment.
Definition: MESegment.h:180
void setSpeed(double newSpeed, SUMOTime currentTime, double jamThresh=DO_NOT_PATCH_JAM_THRESHOLD)
reset mySpeed and patch the speed of all vehicles in it. Also set/recompute myJamThreshold
Definition: MESegment.cpp:664
void loadState(const std::vector< std::string > &vehIDs, MSVehicleControl &vc, const SUMOTime blockTime, const int queIdx)
Loads the state of this segment with the given parameters.
Definition: MESegment.cpp:719
const double myHeadwayCapacity
The capacity of the segment in number of cars, used only in time headway calculation This parameter h...
Definition: MESegment.h:517
double myTau_length
Headway parameter for computing gross time headyway from net time headway, length and edge speed.
Definition: MESegment.h:513
SUMOTime myTau_jj
Definition: MESegment.h:493
SUMOTime newArrival(const MEVehicle *const v, double newSpeed, SUMOTime currentTime)
compute the new arrival time when switching speed
Definition: MESegment.cpp:655
bool myJunctionControl
Whether junction control is enabled.
Definition: MESegment.h:506
bool myTLSPenalty
Whether tls penalty is enabled.
Definition: MESegment.h:499
static const double DO_NOT_PATCH_JAM_THRESHOLD
Definition: MESegment.h:435
double getFlow() const
returns flow based on headway
Definition: MESegment.cpp:764
static bool isInvalid(const MESegment *segment)
whether the given segment is 0 or encodes vaporization
Definition: MESegment.h:409
SUMOTime getNextInsertionTime(SUMOTime earliestEntry) const
return a time after earliestEntry at which a vehicle may be inserted at full speed
Definition: MESegment.cpp:398
bool myOvertaking
Whether overtaking is permitted on this segment.
Definition: MESegment.h:509
bool vaporizeAnyCar(SUMOTime currentTime, const MSDetectorFileOutput *filter)
tries to remove any car from this segment
Definition: MESegment.cpp:619
SUMOTime myTau_fj
Definition: MESegment.h:493
MESegment(const std::string &id, const MSEdge &parent, MESegment *next, const double length, const double speed, const int idx, const bool multiQueue, const MSNet::MesoEdgeType &edgeTyp)
constructor
Definition: MESegment.cpp:89
A vehicle from the mesoscopic point of view.
Definition: MEVehicle.h:42
double estimateLeaveSpeed(const MSLink *link) const
Returns the vehicle's estimated speed after driving accross the link.
Definition: MEVehicle.cpp:123
void processStop()
ends the current stop and performs loading/unloading
Definition: MEVehicle.cpp:254
bool hasArrived() const
Returns whether this vehicle has already arived (reached the arrivalPosition on its final edge)
Definition: MEVehicle.cpp:157
bool moveRoutePointer()
Update when the vehicle enters a new edge in the move step.
Definition: MEVehicle.cpp:139
SUMOTime checkStop(SUMOTime time)
Returns until when to stop at the current segment and sets the information that the stop has been rea...
Definition: MEVehicle.cpp:213
void updateDetectors(SUMOTime currentTime, const bool isLeave, const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_JUNCTION)
Updates all vehicle detectors.
Definition: MEVehicle.cpp:323
SUMOTime getLastEntryTime() const
Returns the time the vehicle entered the current segment.
Definition: MEVehicle.h:261
void setEventTime(SUMOTime t, bool hasDelay=true)
Sets the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:207
MESegment * getSegment() const
Returns the current segment the vehicle is on.
Definition: MEVehicle.h:237
void setLastEntryTime(SUMOTime t)
Sets the entry time for the current segment.
Definition: MEVehicle.h:253
int getQueIndex() const
Returns the index of the que the vehicle is in.
Definition: MEVehicle.h:245
SUMOTime getWaitingTime() const
Returns the duration for which the vehicle was blocked.
Definition: MEVehicle.h:284
virtual void setSegment(MESegment *s, int idx=0)
Sets the current segment the vehicle is at together with its que.
Definition: MEVehicle.h:228
SUMOTime getEventTime() const
Returns the (planned) time at which the vehicle leaves his current cell.
Definition: MEVehicle.h:219
void setBlockTime(const SUMOTime t)
Sets the time at which the vehicle was blocked.
Definition: MEVehicle.h:269
double getSpeed() const
Returns the vehicle's estimated speed assuming no delays.
Definition: MEVehicle.cpp:107
double getImpatience() const
Returns this vehicles impatience.
const MSEdge * succEdge(int nSuccs) const
Returns the nSuccs'th successor of edge the vehicle is currently at.
void addReminder(MSMoveReminder *rem)
Adds a MoveReminder dynamically.
const MSEdge * getEdge() const
Returns the edge the vehicle is currently at.
bool hasValidRoute(std::string &msg, const MSRoute *route=0) const
Validates the current or given route.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
virtual void activateReminders(const MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
"Activates" all current move reminder
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
void onDepart()
Called when the vehicle is inserted into the network.
bool isStopped() const
Returns whether the vehicle is at a stop.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition: MSCFModel.h:216
Base of value-generating classes (detectors)
bool vehicleApplies(const SUMOTrafficObject &veh) const
Checks whether the detector measures vehicles of the given type.
A road/street connecting two junctions.
Definition: MSEdge.h:77
virtual void unlock() const
release exclusive access to the mesoscopic state
Definition: MSEdge.h:724
SVCPermissions getPermissions() const
Returns the combined permissions of all lanes of this edge.
Definition: MSEdge.h:594
const std::vector< MSLane * > * allowedLanes(const MSEdge &destination, SUMOVehicleClass vclass=SVC_IGNORING) const
Get the allowed lanes to reach the destination-edge.
Definition: MSEdge.cpp:366
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:166
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is retured; should pro...
Definition: MSEdge.cpp:919
bool isRoundabout() const
Definition: MSEdge.h:674
bool isVaporizing() const
Returns whether vehicles on this edge shall be vaporized.
Definition: MSEdge.h:408
void addWaiting(SUMOVehicle *vehicle) const
Adds a vehicle to the list of waiting vehicles.
Definition: MSEdge.cpp:1159
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:931
bool hasMinorLink() const
whether any lane has a minor link
Definition: MSEdge.cpp:1102
const MSJunction * getToJunction() const
Definition: MSEdge.h:392
virtual void lock() const
grant exclusive access to the mesoscopic state
Definition: MSEdge.h:721
const MSEdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges, restricted by vClass.
Definition: MSEdge.cpp:1013
static bool gCheckRoutes
Definition: MSGlobals.h:76
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition: MSGlobals.h:94
static bool gMesoLimitedJunctionControl
Definition: MSGlobals.h:91
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:130
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:640
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:673
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_VAPORIZED_CALIBRATOR
The vehicle got removed by a calibrator.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_VAPORIZED_VAPORIZER
The vehicle got vaporized with a vaporizer.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:171
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:371
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:313
The class responsible for building and deletion of vehicles.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
void scheduleVehicleRemoval(SUMOVehicle *veh, bool checkDuplicate=false)
Removes a vehicle after it has ended.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
static void writeVehicle(OutputDevice &of, const MSBaseVehicle &veh)
Writes the dump of the given vehicle into the given device.
Base class for objects which have an id.
Definition: Named.h:53
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:66
const std::string & getID() const
Returns the id.
Definition: Named.h:73
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:239
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static double rand(std::mt19937 *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:51
edge type specific meso parameters
Definition: MSNet.h:117
bool junctionControl
Definition: MSNet.h:123
double jamThreshold
Definition: MSNet.h:122
SUMOTime taufj
Definition: MSNet.h:119
SUMOTime tauff
Definition: MSNet.h:118
SUMOTime taujj
Definition: MSNet.h:121
double tlsPenalty
Definition: MSNet.h:124
SUMOTime minorPenalty
Definition: MSNet.h:126
double tlsFlowPenalty
Definition: MSNet.h:125
SUMOTime taujf
Definition: MSNet.h:120