1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file MSEdge.cpp
11 /// @author Christian Roessel
12 /// @author Jakob Erdmann
13 /// @author Christoph Sommer
14 /// @author Daniel Krajzewicz
15 /// @author Laura Bieker
16 /// @author Michael Behrisch
17 /// @author Sascha Krieg
18 /// @date Tue, 06 Mar 2001
19 /// @version $Id$
20 ///
21 // A road/street connecting two junctions
22 /****************************************************************************/
23
24
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #include <config.h>
29
30 #include <algorithm>
31 #include <iostream>
32 #include <cassert>
33 #include <utils/common/StringTokenizer.h>
34 #include <utils/options/OptionsCont.h>
35 #include <microsim/devices/MSRoutingEngine.h>
36 #include <mesosim/MELoop.h>
37 #include <mesosim/MESegment.h>
38 #include <mesosim/MEVehicle.h>
39 #include "MSInsertionControl.h"
40 #include "MSJunction.h"
41 #include "MSLane.h"
42 #include "MSLaneChanger.h"
43 #include "MSLaneChangerSublane.h"
44 #include "MSGlobals.h"
45 #include "MSNet.h"
46 #include "MSVehicle.h"
47 #include "MSLeaderInfo.h"
48 #include "MSContainer.h"
49 #include "MSEdgeWeightsStorage.h"
50 #include "MSEdge.h"
51
52 #define BEST_LANE_LOOKAHEAD 3000.0
53
54 // ===========================================================================
55 // static member definitions
56 // ===========================================================================
57 MSEdge::DictType MSEdge::myDict;
58 MSEdgeVector MSEdge::myEdges;
59
60
61 // ===========================================================================
62 // member method definitions
63 // ===========================================================================
MSEdge(const std::string & id,int numericalID,const SumoXMLEdgeFunc function,const std::string & streetName,const std::string & edgeType,int priority)64 MSEdge::MSEdge(const std::string& id, int numericalID,
65 const SumoXMLEdgeFunc function,
66 const std::string& streetName,
67 const std::string& edgeType,
68 int priority) :
69 Named(id), myNumericalID(numericalID), myLanes(nullptr),
70 myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
71 myLastFailedInsertionTime(-1),
72 myFromJunction(nullptr), myToJunction(nullptr),
73 myStreetName(streetName),
74 myEdgeType(edgeType),
75 myPriority(priority),
76 myWidth(0.),
77 myLength(0.),
78 myEmptyTraveltime(0.),
79 myTimePenalty(0.),
80 myAmDelayed(false),
81 myAmRoundabout(false),
82 myAmFringe(true),
83 myBidiEdge(nullptr)
84 { }
85
86
~MSEdge()87 MSEdge::~MSEdge() {
88 delete myLaneChanger;
89 for (auto i : myAllowed) {
90 if (i.second != myLanes) {
91 delete i.second;
92 }
93 }
94 for (auto i2 : myAllowedTargets) {
95 for (auto i1 : i2.second) {
96 if (i1.second != myLanes) {
97 delete i1.second;
98 }
99 }
100 }
101 delete myLanes;
102 }
103
104
105 void
initialize(const std::vector<MSLane * > * lanes)106 MSEdge::initialize(const std::vector<MSLane*>* lanes) {
107 assert(lanes != 0);
108 myLanes = lanes;
109 if (myFunction == EDGEFUNC_CONNECTOR) {
110 myCombinedPermissions = SVCAll;
111 }
112 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
113 myWidth += (*i)->getWidth();
114 }
115 double widthBefore = 0;
116 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
117 (*i)->setRightSideOnEdge(widthBefore, (int)mySublaneSides.size());
118 MSLeaderInfo ahead(*i);
119 for (int j = 0; j < ahead.numSublanes(); ++j) {
120 mySublaneSides.push_back(widthBefore + j * MSGlobals::gLateralResolution);
121 }
122 widthBefore += (*i)->getWidth();
123 }
124 }
125
126
recalcCache()127 void MSEdge::recalcCache() {
128 if (myLanes->empty()) {
129 return;
130 }
131 myLength = myLanes->front()->getLength();
132 myEmptyTraveltime = myLength / MAX2(getSpeedLimit(), NUMERICAL_EPS);
133
134 if (MSGlobals::gMesoTLSPenalty > 0 || MSGlobals::gMesoMinorPenalty > 0) {
135 // add tls penalties to the minimum travel time
136 SUMOTime minPenalty = -1;
137 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
138 MSLane* l = *i;
139 const MSLinkCont& lc = l->getLinkCont();
140 for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
141 MSLink* link = *j;
142 SUMOTime linkPenalty = link->getMesoTLSPenalty() + (link->havePriority() ? 0 : MSGlobals::gMesoMinorPenalty);
143 if (minPenalty == -1) {
144 minPenalty = linkPenalty;
145 } else {
146 minPenalty = MIN2(minPenalty, linkPenalty);
147 }
148 }
149 }
150 if (minPenalty > 0) {
151 myEmptyTraveltime += STEPS2TIME(minPenalty);
152 }
153 } else if (isInternal()) {
154 const MSLink* link = myLanes->front()->getIncomingLanes()[0].viaLink;
155 if (!link->isTLSControlled() && !link->havePriority()) {
156 myEmptyTraveltime += MSGlobals::gMinorPenalty;
157 myTimePenalty = MSGlobals::gMinorPenalty;
158 }
159 }
160 }
161
162
163 void
closeBuilding()164 MSEdge::closeBuilding() {
165 for (MSLane* const lane : *myLanes) {
166 for (MSLink* const link : lane->getLinkCont()) {
167 link->initParallelLinks();
168 MSLane* const toL = link->getLane();
169 MSLane* const viaL = link->getViaLane();
170 if (toL != nullptr) {
171 MSEdge& to = toL->getEdge();
172 if (std::find(mySuccessors.begin(), mySuccessors.end(), &to) == mySuccessors.end()) {
173 mySuccessors.push_back(&to);
174 myViaSuccessors.push_back(std::make_pair(&to, (viaL == nullptr ? nullptr : &viaL->getEdge())));
175 }
176 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
177 to.myPredecessors.push_back(this);
178 }
179 if (link->getDirection() != LINKDIR_TURN) {
180 myAmFringe = false;
181 }
182 }
183 if (viaL != nullptr) {
184 MSEdge& to = viaL->getEdge();
185 if (std::find(to.myPredecessors.begin(), to.myPredecessors.end(), this) == to.myPredecessors.end()) {
186 to.myPredecessors.push_back(this);
187 }
188 }
189 }
190 lane->checkBufferType();
191 }
192 std::sort(mySuccessors.begin(), mySuccessors.end(), by_id_sorter());
193 rebuildAllowedLanes();
194 recalcCache();
195 // segment building depends on the finished list of successors (for multi-queue)
196 if (MSGlobals::gUseMesoSim && !myLanes->empty()) {
197 MSGlobals::gMesoNet->buildSegmentsFor(*this, OptionsCont::getOptions());
198 }
199 }
200
201
202 void
buildLaneChanger()203 MSEdge::buildLaneChanger() {
204 if (!myLanes->empty()) {
205 const bool allowChanging = allowsLaneChanging();
206 if (MSGlobals::gLateralResolution > 0) {
207 // may always initiate sublane-change
208 myLaneChanger = new MSLaneChangerSublane(myLanes, allowChanging);
209 } else {
210 if (MSGlobals::gLaneChangeDuration > 0) {
211 myLaneChanger = new MSLaneChanger(myLanes, allowChanging);
212 } else if (myLanes->size() > 1 || canChangeToOpposite()) {
213 myLaneChanger = new MSLaneChanger(myLanes, allowChanging);
214 }
215 }
216 }
217 }
218
219
220 bool
allowsLaneChanging() const221 MSEdge::allowsLaneChanging() const {
222 if (isInternal()) {
223 // allow changing only if all links leading to this internal lane have priority
224 // or they are controlled by a traffic light
225 for (std::vector<MSLane*>::const_iterator it = myLanes->begin(); it != myLanes->end(); ++it) {
226 MSLane* pred = (*it)->getLogicalPredecessorLane();
227 MSLink* link = MSLinkContHelper::getConnectingLink(*pred, **it);
228 assert(link != 0);
229 LinkState state = link->getState();
230 if (state == LINKSTATE_MINOR
231 || state == LINKSTATE_EQUAL
232 || state == LINKSTATE_STOP
233 || state == LINKSTATE_ALLWAY_STOP
234 || state == LINKSTATE_DEADEND) {
235 return false;
236 }
237 }
238 }
239 return true;
240 }
241
242
243 void
addToAllowed(const SVCPermissions permissions,const std::vector<MSLane * > * allowedLanes,AllowedLanesCont & laneCont) const244 MSEdge::addToAllowed(const SVCPermissions permissions, const std::vector<MSLane*>* allowedLanes, AllowedLanesCont& laneCont) const {
245 // recheck whether we had this list to save memory
246 if (allowedLanes->empty()) {
247 delete allowedLanes;
248 allowedLanes = nullptr;
249 } else {
250 for (auto& allowed : laneCont) {
251 if (*allowed.second == *allowedLanes) {
252 delete allowedLanes;
253 allowedLanes = nullptr;
254 allowed.first |= permissions;
255 break;
256 }
257 }
258 }
259 if (allowedLanes != nullptr) {
260 laneCont.push_back(std::make_pair(permissions, allowedLanes));
261 }
262 }
263
264
265 void
rebuildAllowedLanes()266 MSEdge::rebuildAllowedLanes() {
267 // rebuild myMinimumPermissions and myCombinedPermissions
268 myMinimumPermissions = SVCAll;
269 myCombinedPermissions = 0;
270 for (MSLane* const lane : *myLanes) {
271 myMinimumPermissions &= lane->getPermissions();
272 myCombinedPermissions |= lane->getPermissions();
273 }
274 // rebuild myAllowed
275 for (const auto i : myAllowed) {
276 if (i.second != myLanes) {
277 delete i.second;
278 }
279 }
280 myAllowed.clear();
281 if (myCombinedPermissions != myMinimumPermissions) {
282 myAllowed.push_back(std::make_pair(SVC_IGNORING, myLanes));
283 for (SUMOVehicleClass vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass = (SUMOVehicleClass)(2 * (int)vclass)) {
284 if ((myCombinedPermissions & vclass) == vclass) {
285 std::vector<MSLane*>* allowedLanes = new std::vector<MSLane*>();
286 for (MSLane* const lane : *myLanes) {
287 if (lane->allowsVehicleClass(vclass)) {
288 allowedLanes->push_back(lane);
289 }
290 }
291 addToAllowed(vclass, allowedLanes, myAllowed);
292 }
293 }
294 }
295 rebuildAllowedTargets(false);
296 }
297
298
299 void
rebuildAllowedTargets(const bool updateVehicles)300 MSEdge::rebuildAllowedTargets(const bool updateVehicles) {
301 for (const auto i2 : myAllowedTargets) {
302 for (const auto i1 : i2.second) {
303 if (i1.second != myLanes) {
304 delete i1.second;
305 }
306 }
307 }
308 myAllowedTargets.clear();
309
310 for (const MSEdge* target : mySuccessors) {
311 bool universalMap = true; // whether the mapping for SVC_IGNORING is also valid for all vehicle classes
312 std::vector<MSLane*>* allLanes = new std::vector<MSLane*>();
313 // compute the mapping for SVC_IGNORING
314 for (MSLane* const lane : *myLanes) {
315 SVCPermissions combinedTargetPermissions = 0;
316 for (const MSLink* const link : lane->getLinkCont()) {
317 if (&link->getLane()->getEdge() == target) {
318 allLanes->push_back(lane);
319 combinedTargetPermissions |= link->getLane()->getPermissions();
320 }
321 }
322 if (combinedTargetPermissions == 0 || (lane->getPermissions() & combinedTargetPermissions) != lane->getPermissions()) {
323 universalMap = false;
324 }
325 }
326 if (universalMap) {
327 if (myAllowed.empty()) {
328 // we have no lane specific permissions
329 myAllowedTargets[target].push_back(std::make_pair(myMinimumPermissions, myLanes));
330 } else {
331 for (const auto i : myAllowed) {
332 // we cannot add the lane vectors directly because they are deleted separately (shared_ptr anyone?)
333 addToAllowed(i.first, new std::vector<MSLane*>(*i.second), myAllowedTargets[target]);
334 }
335 }
336 } else {
337 addToAllowed(SVC_IGNORING, allLanes, myAllowedTargets[target]);
338 // compute the vclass specific mapping
339 for (SUMOVehicleClass vclass = SVC_PRIVATE; vclass <= SUMOVehicleClass_MAX; vclass = (SUMOVehicleClass)(2 * (int)vclass)) {
340 if ((myCombinedPermissions & vclass) == vclass) {
341 std::vector<MSLane*>* allowedLanes = new std::vector<MSLane*>();
342 for (MSLane* const lane : *myLanes) {
343 if (lane->allowsVehicleClass(vclass)) {
344 for (const MSLink* const link : lane->getLinkCont()) {
345 if (link->getLane()->allowsVehicleClass(vclass) && &link->getLane()->getEdge() == target) {
346 allowedLanes->push_back(lane);
347 }
348 }
349 }
350 }
351 addToAllowed(vclass, allowedLanes, myAllowedTargets[target]);
352 }
353 }
354 }
355 }
356 if (updateVehicles) {
357 for (const MSLane* const lane : *myLanes) {
358 const MSLane::VehCont& vehs = lane->getVehiclesSecure();
359 for (MSVehicle* veh : vehs) {
360 veh->updateBestLanes(true);
361 }
362 lane->releaseVehicles();
363 }
364 }
365 myClassesSuccessorMap.clear();
366 }
367
368
369 // ------------ Access to the edge's lanes
370 MSLane*
leftLane(const MSLane * const lane) const371 MSEdge::leftLane(const MSLane* const lane) const {
372 return parallelLane(lane, 1);
373 }
374
375
376 MSLane*
rightLane(const MSLane * const lane) const377 MSEdge::rightLane(const MSLane* const lane) const {
378 return parallelLane(lane, -1);
379 }
380
381
382 MSLane*
parallelLane(const MSLane * const lane,int offset) const383 MSEdge::parallelLane(const MSLane* const lane, int offset) const {
384 const int index = (int)(find(myLanes->begin(), myLanes->end(), lane) - myLanes->begin());
385 if (index == (int)myLanes->size()) {
386 return nullptr;
387 }
388 const int resultIndex = index + offset;
389 if (resultIndex >= (int)myLanes->size() || resultIndex < 0) {
390 return nullptr;
391 } else {
392 return (*myLanes)[resultIndex];
393 }
394 }
395
396
397 const std::vector<MSLane*>*
allowedLanes(const MSEdge & destination,SUMOVehicleClass vclass) const398 MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass) const {
399 AllowedLanesByTarget::const_iterator i = myAllowedTargets.find(&destination);
400 if (i != myAllowedTargets.end()) {
401 for (const auto& allowed : i->second) {
402 if ((allowed.first & vclass) == vclass) {
403 return allowed.second;
404 }
405 }
406 }
407 return nullptr;
408 }
409
410
411 const std::vector<MSLane*>*
allowedLanes(SUMOVehicleClass vclass) const412 MSEdge::allowedLanes(SUMOVehicleClass vclass) const {
413 if ((myMinimumPermissions & vclass) == vclass) {
414 return myLanes;
415 } else {
416 if ((myCombinedPermissions & vclass) == vclass) {
417 for (const auto& allowed : myAllowed) {
418 if ((allowed.first & vclass) == vclass) {
419 return allowed.second;
420 }
421 }
422 }
423 return nullptr;
424 }
425 }
426
427
428 // ------------
429 SUMOTime
incVaporization(SUMOTime)430 MSEdge::incVaporization(SUMOTime) {
431 ++myVaporizationRequests;
432 return 0;
433 }
434
435
436 SUMOTime
decVaporization(SUMOTime)437 MSEdge::decVaporization(SUMOTime) {
438 --myVaporizationRequests;
439 return 0;
440 }
441
442
443 MSLane*
getFreeLane(const std::vector<MSLane * > * allowed,const SUMOVehicleClass vclass,double departPos) const444 MSEdge::getFreeLane(const std::vector<MSLane*>* allowed, const SUMOVehicleClass vclass, double departPos) const {
445 if (allowed == nullptr) {
446 allowed = allowedLanes(vclass);
447 }
448 MSLane* res = nullptr;
449 if (allowed != nullptr) {
450 double largestGap = 0;
451 MSLane* resByGap = nullptr;
452 double leastOccupancy = std::numeric_limits<double>::max();;
453 for (std::vector<MSLane*>::const_iterator i = allowed->begin(); i != allowed->end(); ++i) {
454 const double occupancy = (*i)->getBruttoOccupancy();
455 if (occupancy < leastOccupancy) {
456 res = (*i);
457 leastOccupancy = occupancy;
458 }
459 const MSVehicle* last = (*i)->getLastFullVehicle();
460 const double lastGap = (last != nullptr ? last->getPositionOnLane() : myLength) - departPos;
461 if (lastGap > largestGap) {
462 largestGap = lastGap;
463 resByGap = (*i);
464 }
465 }
466 if (resByGap != nullptr) {
467 //if (res != resByGap) std::cout << SIMTIME << " edge=" << getID() << " departPos=" << departPos << " res=" << Named::getIDSecure(res) << " resByGap=" << Named::getIDSecure(resByGap) << " largestGap=" << largestGap << "\n";
468 res = resByGap;
469 }
470 }
471 return res;
472 }
473
474
475 double
getDepartPosBound(const MSVehicle & veh,bool upper) const476 MSEdge::getDepartPosBound(const MSVehicle& veh, bool upper) const {
477 const SUMOVehicleParameter& pars = veh.getParameter();
478 double pos = getLength();
479 // determine the position
480 switch (pars.departPosProcedure) {
481 case DEPART_POS_GIVEN:
482 pos = pars.departPos;
483 if (pos < 0.) {
484 pos += myLength;
485 }
486 break;
487 case DEPART_POS_RANDOM:
488 // could be any position on the edge
489 break;
490 case DEPART_POS_RANDOM_FREE:
491 // could be any position on the edge due to multiple random attempts
492 break;
493 case DEPART_POS_FREE:
494 // many candidate positions, upper bound could be computed exactly
495 // with much effort
496 break;
497 case DEPART_POS_LAST:
498 if (upper) {
499 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
500 MSVehicle* last = (*i)->getLastFullVehicle();
501 if (last != nullptr) {
502 pos = MIN2(pos, last->getPositionOnLane());
503 }
504 }
505 } else {
506 pos = 0;
507 }
508 case DEPART_POS_BASE:
509 case DEPART_POS_DEFAULT:
510 break;
511 default:
512 pos = MIN2(pos, veh.getVehicleType().getLength());
513 break;
514 }
515 return pos;
516 }
517
518
519 MSLane*
getDepartLane(MSVehicle & veh) const520 MSEdge::getDepartLane(MSVehicle& veh) const {
521 switch (veh.getParameter().departLaneProcedure) {
522 case DEPART_LANE_GIVEN:
523 if ((int) myLanes->size() <= veh.getParameter().departLane || !(*myLanes)[veh.getParameter().departLane]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
524 return nullptr;
525 }
526 return (*myLanes)[veh.getParameter().departLane];
527 case DEPART_LANE_RANDOM:
528 return RandHelper::getRandomFrom(*allowedLanes(veh.getVehicleType().getVehicleClass()));
529 case DEPART_LANE_FREE:
530 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
531 case DEPART_LANE_ALLOWED_FREE:
532 if (veh.getRoute().size() == 1) {
533 return getFreeLane(nullptr, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
534 } else {
535 return getFreeLane(allowedLanes(**(veh.getRoute().begin() + 1), veh.getVehicleType().getVehicleClass()), veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
536 }
537 case DEPART_LANE_BEST_FREE: {
538 veh.updateBestLanes(false, myLanes->front());
539 const std::vector<MSVehicle::LaneQ>& bl = veh.getBestLanes();
540 double bestLength = -1;
541 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
542 if ((*i).length > bestLength) {
543 bestLength = (*i).length;
544 }
545 }
546 // beyond a certain length, all lanes are suitable
547 // however, we still need to check departPos to avoid unsuitable insertion
548 // (this is only possible in some cases)
549 double departPos = 0;
550 if (bestLength > BEST_LANE_LOOKAHEAD) {
551 departPos = getDepartPosBound(veh);
552 bestLength = MIN2(bestLength - departPos, BEST_LANE_LOOKAHEAD);
553 }
554 std::vector<MSLane*>* bestLanes = new std::vector<MSLane*>();
555 for (std::vector<MSVehicle::LaneQ>::const_iterator i = bl.begin(); i != bl.end(); ++i) {
556 if (((*i).length - departPos) >= bestLength) {
557 bestLanes->push_back((*i).lane);
558 }
559 }
560 MSLane* ret = getFreeLane(bestLanes, veh.getVehicleType().getVehicleClass(), getDepartPosBound(veh, false));
561 delete bestLanes;
562 return ret;
563 }
564 case DEPART_LANE_DEFAULT:
565 case DEPART_LANE_FIRST_ALLOWED:
566 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
567 if ((*i)->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
568 return *i;
569 }
570 }
571 return nullptr;
572 default:
573 break;
574 }
575 if (!(*myLanes)[0]->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
576 return nullptr;
577 }
578 return (*myLanes)[0];
579 }
580
581
582 bool
insertVehicle(SUMOVehicle & v,SUMOTime time,const bool checkOnly,const bool forceCheck) const583 MSEdge::insertVehicle(SUMOVehicle& v, SUMOTime time, const bool checkOnly, const bool forceCheck) const {
584 // when vaporizing, no vehicles are inserted, but checking needs to be successful to trigger removal
585 if (isVaporizing() || isTazConnector()) {
586 return checkOnly;
587 }
588 const SUMOVehicleParameter& pars = v.getParameter();
589 const MSVehicleType& type = v.getVehicleType();
590 if (pars.departSpeedProcedure == DEPART_SPEED_GIVEN && pars.departSpeed > getVehicleMaxSpeed(&v)) {
591 const std::vector<double>& speedFactorParams = type.getSpeedFactor().getParameter();
592 if (speedFactorParams[1] > 0.) {
593 v.setChosenSpeedFactor(type.computeChosenSpeedDeviation(nullptr, pars.departSpeed / getSpeedLimit()));
594 if (v.getChosenSpeedFactor() > speedFactorParams[0] + 2 * speedFactorParams[1]) {
595 // only warn for significant deviation
596 WRITE_WARNING("Choosing new speed factor " + toString(v.getChosenSpeedFactor()) + " for vehicle '" + pars.id + "' to match departure speed.");
597 }
598 } else {
599 throw ProcessError("Departure speed for vehicle '" + pars.id +
600 "' is too high for the departure edge '" + getID() + "'.");
601 }
602 }
603 if (MSGlobals::gUseMesoSim) {
604 if (!forceCheck && myLastFailedInsertionTime == time) {
605 return false;
606 }
607 double pos = 0.0;
608 switch (pars.departPosProcedure) {
609 case DEPART_POS_GIVEN:
610 if (pars.departPos >= 0.) {
611 pos = pars.departPos;
612 } else {
613 pos = pars.departPos + getLength();
614 }
615 if (pos < 0 || pos > getLength()) {
616 WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" +
617 v.getID() + "'. Inserting at lane end instead.");
618 pos = getLength();
619 }
620 break;
621 case DEPART_POS_RANDOM:
622 case DEPART_POS_RANDOM_FREE:
623 pos = RandHelper::rand(getLength());
624 break;
625 default:
626 break;
627 }
628 bool result = false;
629 MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this, pos);
630 MEVehicle* veh = static_cast<MEVehicle*>(&v);
631 if (pars.departPosProcedure == DEPART_POS_FREE) {
632 while (segment != nullptr && !result) {
633 if (checkOnly) {
634 result = segment->hasSpaceFor(veh, time, true);
635 } else {
636 result = segment->initialise(veh, time);
637 }
638 segment = segment->getNextSegment();
639 }
640 } else {
641 if (checkOnly) {
642 result = segment->hasSpaceFor(veh, time, true);
643 } else {
644 result = segment->initialise(veh, time);
645 }
646 }
647 return result;
648 }
649 if (checkOnly) {
650 switch (v.getParameter().departLaneProcedure) {
651 case DEPART_LANE_GIVEN:
652 case DEPART_LANE_DEFAULT:
653 case DEPART_LANE_FIRST_ALLOWED: {
654 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
655 if (insertionLane == nullptr) {
656 WRITE_WARNING("could not insert vehicle '" + v.getID() + "' on any lane of edge '" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()));
657 return false;
658 }
659 const double occupancy = insertionLane->getBruttoOccupancy();
660 return occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength;
661 }
662 default:
663 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
664 const double occupancy = (*i)->getBruttoOccupancy();
665 if (occupancy == 0 || occupancy * myLength + v.getVehicleType().getLengthWithGap() <= myLength) {
666 return true;
667 }
668 }
669 }
670 return false;
671 }
672 MSLane* insertionLane = getDepartLane(static_cast<MSVehicle&>(v));
673 if (insertionLane == nullptr) {
674 return false;
675 }
676
677 if (!forceCheck) {
678 if (myLastFailedInsertionTime == time) {
679 if (myFailedInsertionMemory.count(insertionLane->getIndex())) {
680 // A vehicle was already rejected for the proposed insertionLane in this timestep
681 return false;
682 }
683 } else {
684 // last rejection occurred in a previous timestep, clear cache
685 myFailedInsertionMemory.clear();
686 }
687 }
688
689 bool success = insertionLane->insertVehicle(static_cast<MSVehicle&>(v));
690
691 if (!success) {
692 myFailedInsertionMemory.insert(insertionLane->getIndex());
693 }
694 return success;
695 }
696
697
698 void
changeLanes(SUMOTime t)699 MSEdge::changeLanes(SUMOTime t) {
700 if (myLaneChanger == nullptr) {
701 return;
702 }
703 myLaneChanger->laneChange(t);
704 }
705
706
707
708 const MSEdge*
getInternalFollowingEdge(const MSEdge * followerAfterInternal) const709 MSEdge::getInternalFollowingEdge(const MSEdge* followerAfterInternal) const {
710 //@todo to be optimized
711 for (const MSLane* const l : *myLanes) {
712 for (const MSLink* const link : l->getLinkCont()) {
713 if (&link->getLane()->getEdge() == followerAfterInternal) {
714 if (link->getViaLane() != nullptr) {
715 return &link->getViaLane()->getEdge();
716 } else {
717 return nullptr; // network without internal links
718 }
719 }
720 }
721 }
722 return nullptr;
723 }
724
725 double
getInternalFollowingLengthTo(const MSEdge * followerAfterInternal) const726 MSEdge::getInternalFollowingLengthTo(const MSEdge* followerAfterInternal) const {
727 assert(followerAfterInternal != 0);
728 assert(!followerAfterInternal->isInternal());
729 double dist = 0.;
730 const MSEdge* edge = getInternalFollowingEdge(followerAfterInternal);
731 // Take into account non-internal lengths until next non-internal edge
732 while (edge != nullptr && edge->isInternal()) {
733 dist += edge->getLength();
734 edge = edge->getInternalFollowingEdge(followerAfterInternal);
735 }
736 return dist;
737 }
738
739 const MSEdge*
getNormalBefore() const740 MSEdge::getNormalBefore() const {
741 const MSEdge* result = this;
742 while (result->isInternal()) {
743 assert(result->getPredecessors().size() == 1);
744 result = result->getPredecessors().front();
745 }
746 return result;
747 }
748
749 double
getMeanSpeed() const750 MSEdge::getMeanSpeed() const {
751 double v = 0;
752 double no = 0;
753 if (MSGlobals::gUseMesoSim) {
754 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != nullptr; segment = segment->getNextSegment()) {
755 const int vehNo = segment->getCarNumber();
756 if (vehNo > 0) {
757 v += vehNo * segment->getMeanSpeed();
758 no += vehNo;
759 }
760 }
761 if (no == 0) {
762 return getLength() / myEmptyTraveltime; // may include tls-penalty
763 }
764 } else {
765 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
766 const double vehNo = (double)(*i)->getVehicleNumber();
767 v += vehNo * (*i)->getMeanSpeed();
768 no += vehNo;
769 }
770 if (myBidiEdge != nullptr) {
771 for (const MSLane* lane : myBidiEdge->getLanes()) {
772 const double vehNo = (double)lane->getVehicleNumber();
773 v += vehNo * lane->getMeanSpeed();
774 no += vehNo;
775 }
776 }
777 if (no == 0) {
778 return getSpeedLimit();
779 }
780 }
781 return v / no;
782 }
783
784
785 double
getCurrentTravelTime(double minSpeed) const786 MSEdge::getCurrentTravelTime(double minSpeed) const {
787 assert(minSpeed > 0);
788 if (!myAmDelayed) {
789 return myEmptyTraveltime;
790 }
791 return getLength() / MAX2(minSpeed, getMeanSpeed());
792 }
793
794
795 double
getRoutingSpeed() const796 MSEdge::getRoutingSpeed() const {
797 return MSRoutingEngine::getAssumedSpeed(this);
798 }
799
800
801
802 bool
dictionary(const std::string & id,MSEdge * ptr)803 MSEdge::dictionary(const std::string& id, MSEdge* ptr) {
804 DictType::iterator it = myDict.find(id);
805 if (it == myDict.end()) {
806 // id not in myDict.
807 myDict[id] = ptr;
808 while ((int)myEdges.size() < ptr->getNumericalID() + 1) {
809 myEdges.push_back(0);
810 }
811 myEdges[ptr->getNumericalID()] = ptr;
812 return true;
813 }
814 return false;
815 }
816
817
818 MSEdge*
dictionary(const std::string & id)819 MSEdge::dictionary(const std::string& id) {
820 DictType::iterator it = myDict.find(id);
821 if (it == myDict.end()) {
822 // id not in myDict.
823 return nullptr;
824 }
825 return it->second;
826 }
827
828
829 int
dictSize()830 MSEdge::dictSize() {
831 return (int)myDict.size();
832 }
833
834
835 const MSEdgeVector&
getAllEdges()836 MSEdge::getAllEdges() {
837 return myEdges;
838 }
839
840
841 void
clear()842 MSEdge::clear() {
843 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
844 delete (*i).second;
845 }
846 myDict.clear();
847 myEdges.clear();
848 }
849
850
851 void
insertIDs(std::vector<std::string> & into)852 MSEdge::insertIDs(std::vector<std::string>& into) {
853 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
854 into.push_back((*i).first);
855 }
856 }
857
858
859 void
parseEdgesList(const std::string & desc,ConstMSEdgeVector & into,const std::string & rid)860 MSEdge::parseEdgesList(const std::string& desc, ConstMSEdgeVector& into,
861 const std::string& rid) {
862 if (desc[0] == BinaryFormatter::BF_ROUTE) {
863 std::istringstream in(desc, std::ios::binary);
864 char c;
865 in >> c;
866 FileHelpers::readEdgeVector(in, into, rid);
867 } else {
868 StringTokenizer st(desc);
869 parseEdgesList(st.getVector(), into, rid);
870 }
871 }
872
873
874 void
parseEdgesList(const std::vector<std::string> & desc,ConstMSEdgeVector & into,const std::string & rid)875 MSEdge::parseEdgesList(const std::vector<std::string>& desc, ConstMSEdgeVector& into,
876 const std::string& rid) {
877 for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
878 const MSEdge* edge = MSEdge::dictionary(*i);
879 // check whether the edge exists
880 if (edge == nullptr) {
881 throw ProcessError("The edge '" + *i + "' within the route " + rid + " is not known."
882 + "\n The route can not be build.");
883 }
884 into.push_back(edge);
885 }
886 }
887
888
889 double
getDistanceTo(const MSEdge * other,const bool doBoundaryEstimate) const890 MSEdge::getDistanceTo(const MSEdge* other, const bool doBoundaryEstimate) const {
891 assert(this != other);
892 if (doBoundaryEstimate) {
893 return myBoundary.distanceTo2D(other->myBoundary);
894 }
895 if (isTazConnector()) {
896 if (other->isTazConnector()) {
897 return myBoundary.distanceTo2D(other->myBoundary);
898 }
899 return myBoundary.distanceTo2D(other->getLanes()[0]->getShape()[0]);
900 }
901 if (other->isTazConnector()) {
902 return other->myBoundary.distanceTo2D(getLanes()[0]->getShape()[-1]);
903 }
904 return getLanes()[0]->getShape()[-1].distanceTo2D(other->getLanes()[0]->getShape()[0]);
905 }
906
907
908 const Position
getStopPosition(const SUMOVehicleParameter::Stop & stop)909 MSEdge::getStopPosition(const SUMOVehicleParameter::Stop& stop) {
910 return MSLane::dictionary(stop.lane)->geometryPositionAtOffset((stop.endPos + stop.startPos) / 2.);
911 }
912
913
914 double
getSpeedLimit() const915 MSEdge::getSpeedLimit() const {
916 // @note lanes might have different maximum speeds in theory
917 return myLanes->empty() ? 1 : getLanes()[0]->getSpeedLimit();
918 }
919
920
921 double
getLengthGeometryFactor() const922 MSEdge::getLengthGeometryFactor() const {
923 return myLanes->empty() ? 1 : getLanes()[0]->getLengthGeometryFactor();
924 }
925
926 double
getVehicleMaxSpeed(const SUMOTrafficObject * const veh) const927 MSEdge::getVehicleMaxSpeed(const SUMOTrafficObject* const veh) const {
928 // @note lanes might have different maximum speeds in theory
929 return myLanes->empty() ? 1 : getLanes()[0]->getVehicleMaxSpeed(veh);
930 }
931
932
933 void
setMaxSpeed(double val) const934 MSEdge::setMaxSpeed(double val) const {
935 if (myLanes != nullptr) {
936 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
937 (*i)->setMaxSpeed(val);
938 }
939 }
940 }
941
942
943
944 std::vector<MSTransportable*>
getSortedPersons(SUMOTime timestep,bool includeRiding) const945 MSEdge::getSortedPersons(SUMOTime timestep, bool includeRiding) const {
946 std::vector<MSTransportable*> result(myPersons.begin(), myPersons.end());
947 if (includeRiding) {
948 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
949 const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
950 for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
951 const std::vector<MSTransportable*>& persons = (*j)->getPersons();
952 result.insert(result.end(), persons.begin(), persons.end());
953 }
954 (*i)->releaseVehicles();
955 }
956 }
957 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
958 return result;
959 }
960
961
962 std::vector<MSTransportable*>
getSortedContainers(SUMOTime timestep,bool) const963 MSEdge::getSortedContainers(SUMOTime timestep, bool /* includeRiding */) const {
964 std::vector<MSTransportable*> result(myContainers.begin(), myContainers.end());
965 sort(result.begin(), result.end(), transportable_by_position_sorter(timestep));
966 return result;
967 }
968
969
970 int
operator ()(const MSTransportable * const c1,const MSTransportable * const c2) const971 MSEdge::transportable_by_position_sorter::operator()(const MSTransportable* const c1, const MSTransportable* const c2) const {
972 const double pos1 = c1->getCurrentStage()->getEdgePos(myTime);
973 const double pos2 = c2->getCurrentStage()->getEdgePos(myTime);
974 if (pos1 != pos2) {
975 return pos1 < pos2;
976 }
977 return c1->getID() < c2->getID();
978 }
979
980
981 void
addSuccessor(MSEdge * edge,const MSEdge * via)982 MSEdge::addSuccessor(MSEdge* edge, const MSEdge* via) {
983 mySuccessors.push_back(edge);
984 myViaSuccessors.push_back(std::make_pair(edge, via));
985 if (isTazConnector() && edge->getFromJunction() != nullptr) {
986 myBoundary.add(edge->getFromJunction()->getPosition());
987 }
988
989 edge->myPredecessors.push_back(this);
990 if (edge->isTazConnector() && getToJunction() != nullptr) {
991 edge->myBoundary.add(getToJunction()->getPosition());
992 }
993 }
994
995
996 const MSEdgeVector&
getSuccessors(SUMOVehicleClass vClass) const997 MSEdge::getSuccessors(SUMOVehicleClass vClass) const {
998 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == EDGEFUNC_CONNECTOR) {
999 return mySuccessors;
1000 }
1001 #ifdef HAVE_FOX
1002 if (MSRoutingEngine::isParallel()) {
1003 MSRoutingEngine::lock();
1004 }
1005 #endif
1006 std::map<SUMOVehicleClass, MSEdgeVector>::iterator i = myClassesSuccessorMap.find(vClass);
1007 if (i == myClassesSuccessorMap.end()) {
1008 // instantiate vector
1009 myClassesSuccessorMap[vClass];
1010 i = myClassesSuccessorMap.find(vClass);
1011 // this vClass is requested for the first time. rebuild all successors
1012 for (MSEdgeVector::const_iterator it = mySuccessors.begin(); it != mySuccessors.end(); ++it) {
1013 if ((*it)->isTazConnector()) {
1014 i->second.push_back(*it);
1015 } else {
1016 const std::vector<MSLane*>* allowed = allowedLanes(**it, vClass);
1017 if (allowed != nullptr && allowed->size() > 0) {
1018 i->second.push_back(*it);
1019 }
1020 }
1021 }
1022 }
1023 // can use cached value
1024 #ifdef HAVE_FOX
1025 if (MSRoutingEngine::isParallel()) {
1026 MSRoutingEngine::unlock();
1027 }
1028 #endif
1029 return i->second;
1030 }
1031
1032
1033 const MSConstEdgePairVector&
getViaSuccessors(SUMOVehicleClass vClass) const1034 MSEdge::getViaSuccessors(SUMOVehicleClass vClass) const {
1035 if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == EDGEFUNC_CONNECTOR) {
1036 return myViaSuccessors;
1037 }
1038 #ifdef HAVE_FOX
1039 if (MSRoutingEngine::isParallel()) {
1040 MSRoutingEngine::lock();
1041 }
1042 #endif
1043 auto i = myClassesViaSuccessorMap.find(vClass);
1044 if (i != myClassesViaSuccessorMap.end()) {
1045 // can use cached value
1046 #ifdef HAVE_FOX
1047 if (MSRoutingEngine::isParallel()) {
1048 MSRoutingEngine::unlock();
1049 }
1050 #endif
1051 return i->second;
1052 }
1053 // instantiate vector
1054 MSConstEdgePairVector& result = myClassesViaSuccessorMap[vClass];
1055 // this vClass is requested for the first time. rebuild all successors
1056 for (const auto& viaPair : myViaSuccessors) {
1057 if (viaPair.first->isTazConnector()) {
1058 result.push_back(viaPair);
1059 } else {
1060 const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass);
1061 if (allowed != nullptr && allowed->size() > 0) {
1062 result.push_back(viaPair);
1063 }
1064 }
1065 }
1066 #ifdef HAVE_FOX
1067 if (MSRoutingEngine::isParallel()) {
1068 MSRoutingEngine::unlock();
1069 }
1070 #endif
1071 return result;
1072 }
1073
1074
1075 void
setJunctions(MSJunction * from,MSJunction * to)1076 MSEdge::setJunctions(MSJunction* from, MSJunction* to) {
1077 myFromJunction = from;
1078 myToJunction = to;
1079 if (!isTazConnector()) {
1080 myBoundary.add(from->getPosition());
1081 myBoundary.add(to->getPosition());
1082 }
1083 }
1084
1085
1086 bool
canChangeToOpposite()1087 MSEdge::canChangeToOpposite() {
1088 return (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr &&
1089 // do not change on curved internal lanes
1090 (!isInternal() || myLanes->back()->getIncomingLanes()[0].viaLink->getDirection() == LINKDIR_STRAIGHT));
1091 }
1092
1093
1094 const MSEdge*
getOppositeEdge() const1095 MSEdge::getOppositeEdge() const {
1096 if (!myLanes->empty() && myLanes->back()->getOpposite() != nullptr) {
1097 return &(myLanes->back()->getOpposite()->getEdge());
1098 } else {
1099 return nullptr;
1100 }
1101 }
1102
1103
1104 bool
hasMinorLink() const1105 MSEdge::hasMinorLink() const {
1106 for (std::vector<MSLane*>::const_iterator i = myLanes->begin(); i != myLanes->end(); ++i) {
1107 const MSLinkCont& lc = (*i)->getLinkCont();
1108 for (MSLinkCont::const_iterator j = lc.begin(); j != lc.end(); ++j) {
1109 if (!(*j)->havePriority()) {
1110 return true;
1111 }
1112 }
1113 }
1114 return false;
1115 }
1116
1117
checkAndRegisterBiDirEdge(const std::string & bidiID)1118 void MSEdge::checkAndRegisterBiDirEdge(const std::string& bidiID) {
1119 if (bidiID != "") {
1120 myBidiEdge = dictionary(bidiID);
1121 if (myBidiEdge == nullptr) {
1122 WRITE_ERROR("Bidi-edge '" + bidiID + "' does not exist");
1123 }
1124 return;
1125 }
1126 if (getFunction() != EDGEFUNC_NORMAL) {
1127 return;
1128 }
1129 ConstMSEdgeVector candidates = myToJunction->getOutgoing();
1130 for (ConstMSEdgeVector::const_iterator it = candidates.begin(); it != candidates.end(); it++) {
1131 if ((*it)->getToJunction() == myFromJunction) { //reverse edge
1132 if (myBidiEdge != nullptr && isSuperposable(*it)) {
1133 WRITE_WARNING("Ambiguous superposable edges between junction '" + myToJunction->getID() + "' and '" + myFromJunction->getID() + "'.");
1134 break;
1135 }
1136 myBidiEdge = isSuperposable(*it) ? *it : nullptr;
1137 }
1138 }
1139 }
1140
1141
isSuperposable(const MSEdge * other)1142 bool MSEdge::isSuperposable(const MSEdge* other) {
1143 if (other == nullptr || other->getLanes().size() != myLanes->size()) {
1144 return false;
1145 }
1146 std::vector<MSLane*>::const_iterator it1 = myLanes->begin();
1147 std::vector<MSLane*>::const_reverse_iterator it2 = other->getLanes().rbegin();
1148 do {
1149 if ((*it1)->getShape().reverse() != (*it2)->getShape()) {
1150 return false;
1151 }
1152 it1++;
1153 it2++;
1154 } while (it1 != myLanes->end());
1155
1156 return true;
1157 }
1158
1159
1160 /****************************************************************************/
1161