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