SUMO - Simulation of Urban MObility
MSLane.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00013 // Representation of a lane in the micro simulation
00014 /****************************************************************************/
00015 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00016 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00017 /****************************************************************************/
00018 //
00019 //   This file is part of SUMO.
00020 //   SUMO is free software: you can redistribute it and/or modify
00021 //   it under the terms of the GNU General Public License as published by
00022 //   the Free Software Foundation, either version 3 of the License, or
00023 //   (at your option) any later version.
00024 //
00025 /****************************************************************************/
00026 
00027 
00028 // ===========================================================================
00029 // included modules
00030 // ===========================================================================
00031 #ifdef _MSC_VER
00032 #include <windows_config.h>
00033 #else
00034 #include <config.h>
00035 #endif
00036 
00037 #include <utils/common/UtilExceptions.h>
00038 #include <utils/common/StdDefs.h>
00039 #include "MSVehicle.h"
00040 #include "MSNet.h"
00041 #include "MSVehicleType.h"
00042 #include "MSEdge.h"
00043 #include "MSEdgeControl.h"
00044 #include "MSJunction.h"
00045 #include "MSLogicJunction.h"
00046 #include "MSLink.h"
00047 #include "MSLane.h"
00048 #include "MSVehicleTransfer.h"
00049 #include "MSGlobals.h"
00050 #include "MSVehicleControl.h"
00051 #include <cmath>
00052 #include <bitset>
00053 #include <iostream>
00054 #include <cassert>
00055 #include <functional>
00056 #include <algorithm>
00057 #include <iterator>
00058 #include <exception>
00059 #include <climits>
00060 #include <set>
00061 #include <utils/common/MsgHandler.h>
00062 #include <utils/common/ToString.h>
00063 #include <utils/options/OptionsCont.h>
00064 #include <utils/common/HelpersHarmonoise.h>
00065 #include <utils/geom/Line.h>
00066 #include <utils/geom/GeomHelper.h>
00067 
00068 #ifdef CHECK_MEMORY_LEAKS
00069 #include <foreign/nvwa/debug_new.h>
00070 #endif // CHECK_MEMORY_LEAKS
00071 
00072 
00073 // ===========================================================================
00074 // static member definitions
00075 // ===========================================================================
00076 MSLane::DictType MSLane::myDict;
00077 
00078 
00079 // ===========================================================================
00080 // member method definitions
00081 // ===========================================================================
00082 MSLane::MSLane(const std::string& id, SUMOReal maxSpeed, SUMOReal length, MSEdge* const edge,
00083                unsigned int numericalID, const PositionVector& shape, SUMOReal width,
00084                SVCPermissions permissions) :
00085     Named(id),
00086     myShape(shape), myNumericalID(numericalID),
00087     myVehicles(), myLength(length), myWidth(width), myEdge(edge), myMaxSpeed(maxSpeed),
00088     myPermissions(permissions),
00089     myLogicalPredecessorLane(0),
00090     myVehicleLengthSum(0), myInlappingVehicleEnd(10000), myInlappingVehicle(0) {
00091 }
00092 
00093 
00094 MSLane::~MSLane() {
00095     for (MSLinkCont::iterator i = myLinks.begin(); i != myLinks.end(); ++i) {
00096         delete *i;
00097     }
00098 }
00099 
00100 
00101 void
00102 MSLane::initialize(MSLinkCont* links) {
00103     myLinks = *links;
00104     delete links;
00105 }
00106 
00107 
00108 void
00109 MSLane::addLink(MSLink* link) {
00110     myLinks.push_back(link);
00111 }
00112 
00113 
00114 // ------ interaction with MSMoveReminder ------
00115 void
00116 MSLane::addMoveReminder(MSMoveReminder* rem) {
00117     myMoveReminders.push_back(rem);
00118     for (VehCont::iterator veh = myVehicles.begin(); veh != myVehicles.end(); ++veh) {
00119         (*veh)->addReminder(rem);
00120     }
00121 }
00122 
00123 
00124 
00125 // ------ Vehicle emission ------
00126 void
00127 MSLane::incorporateVehicle(MSVehicle* veh, SUMOReal pos, SUMOReal speed, const MSLane::VehCont::iterator& at, MSMoveReminder::Notification notification) {
00128     bool wasInactive = myVehicles.size() == 0;
00129     veh->enterLaneAtInsertion(this, pos, speed, notification);
00130     if (at == myVehicles.end()) {
00131         // vehicle will be the first on the lane
00132         myVehicles.push_back(veh);
00133     } else {
00134         myVehicles.insert(at, veh);
00135     }
00136     myVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
00137     if (wasInactive) {
00138         MSNet::getInstance()->getEdgeControl().gotActive(this);
00139     }
00140 }
00141 
00142 
00143 bool
00144 MSLane::pWagGenericInsertion(MSVehicle& veh, SUMOReal mspeed, SUMOReal maxPos, SUMOReal minPos) {
00145     SUMOReal xIn = maxPos;
00146     SUMOReal vIn = mspeed;
00147     SUMOReal leaderDecel;
00148     if (myVehicles.size() != 0) {
00149         MSVehicle* leader = myVehicles.front();
00150         xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
00151         vIn = leader->getSpeed();
00152         leaderDecel = leader->getCarFollowModel().getMaxDecel();
00153     } else {
00154         veh.getBestLanes(true, this);
00155         SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
00156         std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
00157         if (leader.first != 0) {
00158             xIn = getLength() + leader.second - veh.getVehicleType().getMinGap();
00159             vIn = leader.first->getSpeed();
00160             leaderDecel = leader.first->getCarFollowModel().getMaxDecel();
00161         } else {
00162             incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
00163             return true;
00164         }
00165     }
00166     const SUMOReal vHlp = 0.5 * (vIn + mspeed);
00167     SUMOReal x2 = xIn;// have seen leader length already - skCar::lCar;
00168     SUMOReal x1 = x2 - 100.0;
00169     SUMOReal x = 0;
00170     for (int i = 0; i <= 10; i++) {
00171         x = 0.5 * (x1 + x2);
00172         SUMOReal vSafe = veh.getCarFollowModel().followSpeed(&veh, vHlp, xIn - x, vIn, leaderDecel);
00173         if (vSafe < vHlp) {
00174             x2 = x;
00175         } else {
00176             x1 = x;
00177         }
00178     }
00179     if (x < minPos) {
00180         return false;
00181     } else if (x > maxPos) {
00182         x = maxPos;
00183     }
00184     incorporateVehicle(&veh, x, vHlp, myVehicles.begin());
00185     return true;
00186 }
00187 
00188 
00189 bool
00190 MSLane::pWagSimpleInsertion(MSVehicle& veh, SUMOReal mspeed, SUMOReal maxPos, SUMOReal minPos) {
00191     SUMOReal xIn = maxPos;
00192     SUMOReal vIn = mspeed;
00193     if (myVehicles.size() != 0) {
00194         MSVehicle* leader = myVehicles.front();
00195         xIn = leader->getPositionOnLane() - leader->getVehicleType().getLength() - veh.getVehicleType().getMinGap();
00196         vIn = leader->getSpeed();
00197     } else {
00198         veh.getBestLanes(true, this);
00199         SUMOReal brakeGap = veh.getCarFollowModel().brakeGap(mspeed);
00200         std::pair<MSVehicle* const, SUMOReal> leader = getLeaderOnConsecutive(brakeGap, 0, mspeed, veh, veh.getBestLanesContinuation(this));
00201         if (leader.first != 0) {
00202             xIn = getLength() + leader.second - veh.getVehicleType().getMinGap();
00203             vIn = leader.first->getSpeed();
00204         } else {
00205             incorporateVehicle(&veh, maxPos, mspeed, myVehicles.end());
00206             return true;
00207         }
00208     }
00209     const SUMOReal vHlp = 0.5 * (mspeed + vIn);
00210     xIn = xIn - vHlp * veh.getCarFollowModel().getHeadwayTime() - veh.getVehicleType().getMinGap();
00211     if (xIn < minPos) {
00212         return false;
00213     } else if (xIn > maxPos) {
00214         xIn = maxPos;
00215     }
00216     incorporateVehicle(&veh, xIn, vHlp, myVehicles.begin());
00217     return true;
00218 }
00219 
00220 
00221 bool
00222 MSLane::maxSpeedGapInsertion(MSVehicle& veh, SUMOReal mspeed) {
00223     if (myVehicles.size() == 0) {
00224         return isInsertionSuccess(&veh, mspeed, myLength / 2, true);
00225     }
00226     // go through the lane, look for free positions (starting after the last vehicle)
00227     MSLane::VehCont::iterator predIt = myVehicles.begin();
00228     SUMOReal maxSpeed = 0;
00229     SUMOReal maxPos = 0;
00230     MSLane::VehCont::iterator maxIt = myVehicles.begin();
00231     while (predIt != myVehicles.end()) {
00232         // get leader (may be zero) and follower
00233         const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
00234         const MSVehicle* follower = *predIt;
00235         SUMOReal leaderRearPos = getLength();
00236         SUMOReal leaderSpeed = mspeed;
00237         if (leader != 0) {
00238             leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
00239             if (leader == getPartialOccupator()) {
00240                 leaderRearPos = getPartialOccupatorEnd();
00241             }
00242             leaderSpeed = leader->getSpeed();
00243         }
00244         const SUMOReal nettoGap = leaderRearPos - follower->getPositionOnLane() - veh.getVehicleType().getLengthWithGap();
00245         if (nettoGap > 0) {
00246             const SUMOReal tau = veh.getCarFollowModel().getHeadwayTime();
00247             const SUMOReal tauDecel = tau * veh.getCarFollowModel().getMaxDecel();
00248             const SUMOReal fSpeed = follower->getSpeed();
00249             const SUMOReal lhs = nettoGap/tau + tauDecel - fSpeed - fSpeed*fSpeed/(2*tauDecel) + leaderSpeed*leaderSpeed/(2*tauDecel);
00250             if (lhs >= sqrt(tauDecel * tauDecel + leaderSpeed * leaderSpeed)) {
00251                 const SUMOReal frontGap = (lhs * lhs - tauDecel * tauDecel - leaderSpeed * leaderSpeed) / (2*veh.getCarFollowModel().getMaxDecel());
00252                 const SUMOReal currentMaxSpeed = lhs - tauDecel;
00253                 if (MIN2(currentMaxSpeed, mspeed) > maxSpeed) {
00254                     maxSpeed = currentMaxSpeed;
00255                     maxPos = leaderRearPos + frontGap;
00256                     maxIt = predIt+1;
00257                 }
00258             }
00259         }
00260         ++predIt;
00261     }
00262     if (maxSpeed > 0) {
00263         incorporateVehicle(&veh, maxPos, maxSpeed, maxIt);
00264         return true;
00265     }
00266     return false;
00267 }
00268 
00269 
00270 bool
00271 MSLane::freeInsertion(MSVehicle& veh, SUMOReal mspeed,
00272                       MSMoveReminder::Notification notification) {
00273     bool adaptableSpeed = true;
00274     if (myVehicles.size() == 0) {
00275         if (isInsertionSuccess(&veh, mspeed, 0, adaptableSpeed, notification)) {
00276             return true;
00277         }
00278     } else {
00279         // check whether the vehicle can be put behind the last one if there is such
00280         MSVehicle* leader = myVehicles.back();
00281         SUMOReal leaderPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
00282         SUMOReal speed = mspeed;
00283         if (adaptableSpeed) {
00284             speed = leader->getSpeed();
00285         }
00286         SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
00287         if (leaderPos - frontGapNeeded >= 0) {
00288             SUMOReal tspeed = MIN2(veh.getCarFollowModel().followSpeed(&veh, mspeed, frontGapNeeded, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()), mspeed);
00289             // check whether we can insert our vehicle behind the last vehicle on the lane
00290             if (isInsertionSuccess(&veh, tspeed, 0, adaptableSpeed, notification)) {
00291                 return true;
00292             }
00293         }
00294     }
00295     // go through the lane, look for free positions (starting after the last vehicle)
00296     MSLane::VehCont::iterator predIt = myVehicles.begin();
00297     while (predIt != myVehicles.end()) {
00298         // get leader (may be zero) and follower
00299         const MSVehicle* leader = predIt != myVehicles.end() - 1 ? *(predIt + 1) : getPartialOccupator();
00300         const MSVehicle* follower = *predIt;
00301 
00302         // patch speed if allowed
00303         SUMOReal speed = mspeed;
00304         if (adaptableSpeed && leader != 0) {
00305             speed = MIN2(leader->getSpeed(), mspeed);
00306         }
00307 
00308         // compute the space needed to not collide with leader
00309         SUMOReal frontMax = getLength();
00310         if (leader != 0) {
00311             SUMOReal leaderRearPos = leader->getPositionOnLane() - leader->getVehicleType().getLength();
00312             if (leader == getPartialOccupator()) {
00313                 leaderRearPos = getPartialOccupatorEnd();
00314             }
00315             SUMOReal frontGapNeeded = veh.getCarFollowModel().getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel()) + veh.getVehicleType().getMinGap();
00316             frontMax = leaderRearPos - frontGapNeeded;
00317         }
00318         // compute the space needed to not let the follower collide
00319         const SUMOReal followPos = follower->getPositionOnLane();
00320         const SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), veh.getSpeed(), veh.getCarFollowModel().getMaxDecel());
00321         const SUMOReal backMin = followPos + backGapNeeded + veh.getVehicleType().getLengthWithGap();
00322 
00323         // check whether there is enough room (given some extra space for rounding errors)
00324         if (frontMax > 0 && backMin + POSITION_EPS < frontMax) {
00325             // try to insert vehicle (should be always ok)
00326             if (isInsertionSuccess(&veh, speed, backMin + POSITION_EPS, adaptableSpeed, notification)) {
00327                 return true;
00328             }
00329         }
00330         ++predIt;
00331     }
00332     // first check at lane's begin
00333     return false;
00334 }
00335 
00336 
00337 bool
00338 MSLane::insertVehicle(MSVehicle& veh) {
00339     SUMOReal pos = 0;
00340     SUMOReal speed = 0;
00341     bool patchSpeed = true; // whether the speed shall be adapted to infrastructure/traffic in front
00342 
00343     // determine the speed
00344     const SUMOVehicleParameter& pars = veh.getParameter();
00345     switch (pars.departSpeedProcedure) {
00346         case DEPART_SPEED_GIVEN:
00347             speed = pars.departSpeed;
00348             patchSpeed = false;
00349             break;
00350         case DEPART_SPEED_RANDOM:
00351             speed = RandHelper::rand(MIN2(veh.getMaxSpeed(), getMaxSpeed()));
00352             patchSpeed = true; // !!!(?)
00353             break;
00354         case DEPART_SPEED_MAX:
00355             speed = MIN2(veh.getMaxSpeed(), getMaxSpeed());
00356             patchSpeed = true; // !!!(?)
00357             break;
00358         case DEPART_SPEED_DEFAULT:
00359         default:
00360             // speed = 0 was set before
00361             patchSpeed = false; // !!!(?)
00362             break;
00363     }
00364 
00365     // determine the position
00366     switch (pars.departPosProcedure) {
00367         case DEPART_POS_GIVEN:
00368             pos = pars.departPos;
00369             if (pos < 0.) {
00370                 pos += myLength;
00371             }
00372             break;
00373         case DEPART_POS_RANDOM:
00374             pos = RandHelper::rand(getLength());
00375             break;
00376         case DEPART_POS_RANDOM_FREE: {
00377             for (unsigned int i = 0; i < 10; i++) {
00378                 // we will try some random positions ...
00379                 pos = RandHelper::rand(getLength());
00380                 if (isInsertionSuccess(&veh, speed, pos, patchSpeed)) {
00381                     return true;
00382                 }
00383             }
00384             // ... and if that doesn't work, we put the vehicle to the free position
00385             return freeInsertion(veh, speed);
00386         }
00387         break;
00388         case DEPART_POS_FREE:
00389             return freeInsertion(veh, speed);
00390         case DEPART_POS_PWAG_SIMPLE:
00391             return pWagSimpleInsertion(veh, speed, getLength(), 0.0);
00392         case DEPART_POS_PWAG_GENERIC:
00393             return pWagGenericInsertion(veh, speed, getLength(), 0.0);
00394         case DEPART_POS_MAX_SPEED_GAP:
00395             return maxSpeedGapInsertion(veh, speed);
00396         case DEPART_POS_BASE:
00397         case DEPART_POS_DEFAULT:
00398         default:
00399             pos = MIN2(static_cast<SUMOReal>(veh.getVehicleType().getLength() + POSITION_EPS), myLength);
00400             break;
00401     }
00402     // try to insert
00403     return isInsertionSuccess(&veh, speed, pos, patchSpeed);
00404 }
00405 
00406 
00407 bool
00408 MSLane::isInsertionSuccess(MSVehicle* aVehicle,
00409                            SUMOReal speed, SUMOReal pos, bool patchSpeed,
00410                            MSMoveReminder::Notification notification) {
00411     if (pos < 0 || pos > myLength) {
00412         // we may not start there
00413         WRITE_WARNING("Invalid departPos " + toString(pos) + " given for vehicle '" + 
00414                 aVehicle->getID() + "'. Inserting at lane end instead.");
00415         pos = myLength;
00416     }
00417     aVehicle->getBestLanes(true, this);
00418     const MSCFModel& cfModel = aVehicle->getCarFollowModel();
00419     const std::vector<MSLane*> &bestLaneConts = aVehicle->getBestLanesContinuation(this);
00420     std::vector<MSLane*>::const_iterator ri = bestLaneConts.begin();
00421     SUMOReal seen = getLength() - pos;
00422     SUMOReal dist = cfModel.brakeGap(speed);
00423     const MSRoute& r = aVehicle->getRoute();
00424     MSRouteIterator ce = r.begin();
00425     MSLane* currentLane = this;
00426     MSLane* nextLane = this;
00427     SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
00428     while (seen < dist && ri != bestLaneConts.end()) {
00429         // get the next link used...
00430         MSLinkCont::const_iterator link = currentLane->succLinkSec(*aVehicle, 1, *currentLane, bestLaneConts);
00431         // ...and the next used lane (including internal)
00432         if (!currentLane->isLinkEnd(link) && (*link)->opened(arrivalTime, speed, aVehicle->getVehicleType().getLength()) && (*link)->getState() != LINKSTATE_TL_RED) { // red may have priority?
00433 #ifdef HAVE_INTERNAL_LANES
00434             bool nextInternal = false;
00435             nextLane = (*link)->getViaLane();
00436             if (nextLane == 0) {
00437                 nextLane = (*link)->getLane();
00438             } else {
00439                 nextInternal = true;
00440             }
00441 #else
00442             nextLane = (*link)->getLane();
00443 #endif
00444         } else {
00445             break;
00446         }
00447         // check how next lane effects the journey
00448         if (nextLane != 0) {
00449             arrivalTime += TIME2STEPS(nextLane->getLength() / speed);
00450             SUMOReal gap = 0;
00451             MSVehicle* leader = currentLane->getPartialOccupator();
00452             if (leader != 0) {
00453                 gap = seen + currentLane->getPartialOccupatorEnd() - currentLane->getLength();
00454             } else {
00455                 // check leader on next lane
00456                 leader = nextLane->getLastVehicle();
00457                 if (leader != 0) {
00458                     gap = seen + leader->getPositionOnLane() - leader->getVehicleType().getLength() -  aVehicle->getVehicleType().getMinGap();
00459                 }
00460             }
00461             if (leader != 0) {
00462                 if (gap < 0) {
00463                     return false;
00464                 }
00465                 const SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
00466                 if (nspeed < speed) {
00467                     if (patchSpeed) {
00468                         speed = MIN2(nspeed, speed);
00469                         dist = cfModel.brakeGap(speed);
00470                     } else {
00471                         // we may not drive with the given velocity - we crash into the leader
00472                         return false;
00473                     }
00474                 }
00475             }
00476             // check next lane's maximum velocity
00477             const SUMOReal nspeed = nextLane->getMaxSpeed();
00478             if (nspeed < speed) {
00479                 // patch speed if needed
00480                 if (patchSpeed) {
00481                     speed = MIN2(cfModel.freeSpeed(aVehicle, speed, seen, nspeed), speed);
00482                     dist = cfModel.brakeGap(speed);
00483                 } else {
00484                     // we may not drive with the given velocity - we would be too fast on the next lane
00485                     return false;
00486                 }
00487             }
00488             // check traffic on next junctions
00489             const SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
00490 #ifdef HAVE_INTERNAL_LANES
00491             const SUMOTime leaveTime = (*link)->getViaLane() == 0 ? arrivalTime + TIME2STEPS((*link)->getLength() * speed) : arrivalTime + TIME2STEPS((*link)->getViaLane()->getLength() * speed);
00492 #else
00493             const SUMOTime leaveTime = arrivalTime + TIME2STEPS((*link)->getLength() * speed);
00494 #endif
00495             if ((*link)->hasApproachingFoe(arrivalTime, leaveTime)) {
00496                 SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, seen, 0, 0);
00497                 if (nspeed < speed) {
00498                     if (patchSpeed) {
00499                         speed = MIN2(nspeed, speed);
00500                         dist = cfModel.brakeGap(speed);
00501                     } else {
00502                         // we may not drive with the given velocity - we crash into the leader
00503                         return false;
00504                     }
00505                 }
00506             } else {
00507                 // we can only drive to the end of the current lane...
00508                 SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, seen, 0, 0);
00509                 if (nspeed < speed) {
00510                     if (patchSpeed) {
00511                         speed = MIN2(nspeed, speed);
00512                         dist = cfModel.brakeGap(speed);
00513                     } else {
00514                         // we may not drive with the given velocity - we crash into the leader
00515                         return false;
00516                     }
00517                 }
00518             }
00519             seen += nextLane->getLength();
00520             ++ce;
00521             ++ri;
00522             currentLane = nextLane;
00523         }
00524     }
00525     if (seen < dist) {
00526         SUMOReal nspeed = cfModel.followSpeed(aVehicle, speed, seen, 0, 0);
00527         if (nspeed < speed) {
00528             if (patchSpeed) {
00529                 speed = MIN2(nspeed, speed);
00530                 dist = cfModel.brakeGap(speed);
00531             } else {
00532                 // we may not drive with the given velocity - we crash into the leader
00533                 WRITE_ERROR("Vehicle '" + aVehicle->getID() + "' will not be able to depart using given velocity!");
00534                 // !!! we probably should do something else...
00535                 return false;
00536             }
00537         }
00538     }
00539 
00540     // get the pointer to the vehicle next in front of the given position
00541     MSLane::VehCont::iterator predIt = find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos));
00542     if (predIt != myVehicles.end()) {
00543         // ok, there is one (a leader)
00544         MSVehicle* leader = *predIt;
00545         SUMOReal frontGapNeeded = cfModel.getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
00546         SUMOReal gap = MSVehicle::gap(leader->getPositionOnLane(), leader->getVehicleType().getLength(), pos + aVehicle->getVehicleType().getMinGap());
00547         if (gap < frontGapNeeded) {
00548             // too close to the leader on this lane
00549             return false;
00550         }
00551     }
00552 
00553     // check back vehicle
00554     if (predIt != myVehicles.begin()) {
00555         // there is direct follower on this lane
00556         MSVehicle* follower = *(predIt - 1);
00557         SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), aVehicle->getSpeed(), cfModel.getMaxDecel());
00558         SUMOReal gap = MSVehicle::gap(pos, aVehicle->getVehicleType().getLength(), follower->getPositionOnLane() + follower->getVehicleType().getMinGap());
00559         if (gap < backGapNeeded) {
00560             // too close to the follower on this lane
00561             return false;
00562         }
00563     } else {
00564         // check approaching vehicle (consecutive follower)
00565         SUMOReal lspeed = getMaxSpeed();
00566         // in order to look back, we'd need the minimum braking ability of vehicles in the net...
00567         //  we'll assume it to be 4m/s^2
00568         //   !!!revisit
00569         SUMOReal dist = lspeed * lspeed / (2.*4.) + SPEED2DIST(lspeed);
00570         std::pair<const MSVehicle* const, SUMOReal> approaching = getFollowerOnConsecutive(dist, 0, speed, pos - aVehicle->getVehicleType().getLengthWithGap(), 4.5);
00571         if (approaching.first != 0) {
00572             const MSVehicle* const follower = approaching.first;
00573             SUMOReal backGapNeeded = follower->getCarFollowModel().getSecureGap(follower->getSpeed(), aVehicle->getSpeed(), cfModel.getMaxDecel());
00574             SUMOReal gap = approaching.second -approaching.first->getVehicleType().getMinGap() - pos - aVehicle->getVehicleType().getLength();
00575             if (gap < backGapNeeded) {
00576                 // too close to the consecutive follower
00577                 return false;
00578             }
00579         }
00580         // check for in-lapping vehicle
00581         MSVehicle* leader = getPartialOccupator();
00582         if (leader != 0) {
00583             SUMOReal frontGapNeeded = cfModel.getSecureGap(speed, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
00584             SUMOReal gap = getPartialOccupatorEnd() - pos - aVehicle->getVehicleType().getMinGap();
00585             if (gap <= frontGapNeeded) {
00586                 // too close to the leader on this lane
00587                 return false;
00588             }
00589         }
00590     }
00591 
00592     // may got negative while adaptation
00593     if (speed < 0) {
00594         return false;
00595     }
00596     // enter
00597     incorporateVehicle(aVehicle, pos, speed, predIt, notification);
00598     return true;
00599 }
00600 
00601 
00602 void
00603 MSLane::forceVehicleInsertion(MSVehicle* veh, SUMOReal pos) {
00604     incorporateVehicle(veh, pos, veh->getSpeed(), find_if(myVehicles.begin(), myVehicles.end(), bind2nd(VehPosition(), pos)));
00605 }
00606 
00607 
00608 // ------ Handling vehicles lapping into lanes ------
00609 SUMOReal
00610 MSLane::setPartialOccupation(MSVehicle* v, SUMOReal leftVehicleLength) {
00611     myInlappingVehicle = v;
00612     if (leftVehicleLength > myLength) {
00613         myInlappingVehicleEnd = 0;
00614     } else {
00615         myInlappingVehicleEnd = myLength - leftVehicleLength;
00616     }
00617     return myLength;
00618 }
00619 
00620 
00621 void
00622 MSLane::resetPartialOccupation(MSVehicle* v) {
00623     if (v == myInlappingVehicle) {
00624         myInlappingVehicleEnd = 10000;
00625     }
00626     myInlappingVehicle = 0;
00627 }
00628 
00629 
00630 std::pair<MSVehicle*, SUMOReal>
00631 MSLane::getLastVehicleInformation() const {
00632     if (myVehicles.size() != 0) {
00633         // the last vehicle is the one in scheduled by this lane
00634         MSVehicle* last = *myVehicles.begin();
00635         const SUMOReal pos = last->getPositionOnLane() - last->getVehicleType().getLength();
00636         return std::make_pair(last, pos);
00637     }
00638     if (myInlappingVehicle != 0) {
00639         // the last one is a vehicle extending into this lane
00640         return std::make_pair(myInlappingVehicle, myInlappingVehicleEnd);
00641     }
00642     return std::make_pair<MSVehicle*, SUMOReal>(0, 0);
00643 }
00644 
00645 
00646 // ------  ------
00647 bool
00648 MSLane::moveCritical(SUMOTime t) {
00649     myLeftVehLength = myVehicleLengthSum;
00650     assert(myVehicles.size() != 0);
00651     std::vector<MSVehicle*> collisions;
00652     VehCont::iterator lastBeforeEnd = myVehicles.end() - 1;
00653     VehCont::iterator veh;
00654     // Move all next vehicles beside the first
00655     for (veh = myVehicles.begin(); veh != lastBeforeEnd;) {
00656         myLeftVehLength -= (*veh)->getVehicleType().getLengthWithGap();
00657         VehCont::const_iterator pred(veh + 1);
00658         if ((*veh)->moveRegardingCritical(t, this, *pred, 0, myLeftVehLength)) {
00659             collisions.push_back(*veh);
00660         }
00661         ++veh;
00662     }
00663     myLeftVehLength -= (*veh)->getVehicleType().getLengthWithGap();
00664     if ((*veh)->moveRegardingCritical(t, this, 0, 0, myLeftVehLength)) {
00665         collisions.push_back(*veh);
00666     }
00667     assert((*veh)->getPositionOnLane() <= myLength);
00668     assert((*veh)->getLane() == this);
00669     // deal with collisions
00670     for (std::vector<MSVehicle*>::iterator i = collisions.begin(); i != collisions.end(); ++i) {
00671         WRITE_WARNING("Teleporting vehicle '" + (*i)->getID() + "'; collision, lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
00672         myVehicleLengthSum -= (*i)->getVehicleType().getLengthWithGap();
00673         myVehicles.erase(find(myVehicles.begin(), myVehicles.end(), *i));
00674         MSVehicleTransfer::getInstance()->addVeh(t, *i);
00675     }
00676     return myVehicles.size() == 0;
00677 }
00678 
00679 
00680 void
00681 MSLane::detectCollisions(SUMOTime timestep) {
00682     if (myVehicles.size() < 2) {
00683         return;
00684     }
00685 
00686     VehCont::iterator lastVeh = myVehicles.end() - 1;
00687     for (VehCont::iterator veh = myVehicles.begin(); veh != lastVeh;) {
00688         VehCont::iterator pred = veh + 1;
00689         SUMOReal gap = (*pred)->getPositionOnLane() - (*pred)->getVehicleType().getLength() - (*veh)->getPositionOnLane() - (*veh)->getVehicleType().getMinGap();
00690         if (gap < 0) {
00691             MSVehicle* vehV = *veh;
00692             WRITE_WARNING("Teleporting vehicle '" + vehV->getID() + "'; collision, lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
00693             myVehicleLengthSum -= vehV->getVehicleType().getLengthWithGap();
00694             MSVehicleTransfer::getInstance()->addVeh(timestep, vehV);
00695             veh = myVehicles.erase(veh); // remove current vehicle
00696             lastVeh = myVehicles.end() - 1;
00697             if (veh == myVehicles.end()) {
00698                 break;
00699             }
00700         } else {
00701             ++veh;
00702         }
00703     }
00704 }
00705 
00706 
00707 SUMOReal
00708 getMaxSpeedRegardingNextLanes(MSVehicle& veh, SUMOReal speed, SUMOReal pos) {
00709     MSRouteIterator next = veh.getRoute().begin();
00710     const MSCFModel& cfModel = veh.getCarFollowModel();
00711     MSLane* currentLane = (*next)->getLanes()[0];
00712     SUMOReal seen = currentLane->getLength() - pos;
00713     SUMOReal dist = SPEED2DIST(speed) + cfModel.brakeGap(speed);
00714     SUMOReal tspeed = speed;
00715     while (seen < dist && next != veh.getRoute().end() - 1) {
00716         ++next;
00717         MSLane* nextLane = (*next)->getLanes()[0];
00718         tspeed = MIN2(cfModel.freeSpeed(&veh, tspeed, seen, nextLane->getMaxSpeed()), nextLane->getMaxSpeed());
00719         dist = SPEED2DIST(tspeed) + cfModel.brakeGap(tspeed);
00720         seen += nextLane->getMaxSpeed();
00721     }
00722     return tspeed;
00723 }
00724 
00725 
00726 bool
00727 MSLane::setCritical(SUMOTime t, std::vector<MSLane*> &into) {
00728     // move critical vehicles
00729     for (VehCont::iterator i = myVehicles.begin(); i != myVehicles.end();) {
00730         MSVehicle* veh = *i;
00731         bool moved = veh->moveChecked();
00732         MSLane* target = veh->getLane();
00733         SUMOReal length = veh->getVehicleType().getLengthWithGap();
00734         if (veh->ends()) {
00735             // vehicle has reached its arrival position
00736             veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_ARRIVED);
00737             MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
00738         } else if (target != 0 && moved) {
00739             if (target->getEdge().isVaporizing()) {
00740                 // vehicle has reached a vaporizing edge
00741                 veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_VAPORIZED);
00742                 MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
00743             } else {
00744                 // vehicle has entered a new lane
00745                 target->myVehBuffer.push_back(veh);
00746                 SUMOReal pspeed = veh->getSpeed();
00747                 SUMOReal oldPos = veh->getPositionOnLane() - SPEED2DIST(veh->getSpeed());
00748                 veh->workOnMoveReminders(oldPos, veh->getPositionOnLane(), pspeed);
00749                 into.push_back(target);
00750             }
00751         } else if (veh->isParking()) {
00752             // vehicle started to park
00753             veh->leaveLane(MSMoveReminder::NOTIFICATION_JUNCTION);
00754             MSVehicleTransfer::getInstance()->addVeh(t, veh);
00755         } else if (veh->getPositionOnLane() > getLength()) {
00756             // for any reasons the vehicle is beyond its lane... error
00757             WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; beyond lane (2), targetLane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
00758             MSVehicleTransfer::getInstance()->addVeh(t, veh);
00759         } else {
00760             ++i;
00761             continue;
00762         }
00763         myVehicleLengthSum -= length;
00764         i = myVehicles.erase(i);
00765     }
00766     if (myVehicles.size() > 0) {
00767         if (MSGlobals::gTimeToGridlock > 0
00768                 && !(*(myVehicles.end() - 1))->isStopped()
00769                 && (*(myVehicles.end() - 1))->getWaitingTime() > MSGlobals::gTimeToGridlock) {
00770             MSVehicle* veh = *(myVehicles.end() - 1);
00771             myVehicleLengthSum -= veh->getVehicleType().getLengthWithGap();
00772             myVehicles.erase(myVehicles.end() - 1);
00773             WRITE_WARNING("Teleporting vehicle '" + veh->getID() + "'; waited too long, lane='" + getID() + "', time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
00774             MSVehicleTransfer::getInstance()->addVeh(t, veh);
00775         }
00776     }
00777     return myVehicles.size() == 0;
00778 }
00779 
00780 
00781 bool
00782 MSLane::dictionary(std::string id, MSLane* ptr) {
00783     DictType::iterator it = myDict.find(id);
00784     if (it == myDict.end()) {
00785         // id not in myDict.
00786         myDict.insert(DictType::value_type(id, ptr));
00787         return true;
00788     }
00789     return false;
00790 }
00791 
00792 
00793 MSLane*
00794 MSLane::dictionary(std::string id) {
00795     DictType::iterator it = myDict.find(id);
00796     if (it == myDict.end()) {
00797         // id not in myDict.
00798         return 0;
00799     }
00800     return it->second;
00801 }
00802 
00803 
00804 void
00805 MSLane::clear() {
00806     for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
00807         delete(*i).second;
00808     }
00809     myDict.clear();
00810 }
00811 
00812 
00813 void
00814 MSLane::insertIDs(std::vector<std::string> &into) {
00815     for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) {
00816         into.push_back((*i).first);
00817     }
00818 }
00819 
00820 
00821 bool
00822 MSLane::appropriate(const MSVehicle* veh) {
00823     if (myEdge->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
00824         return true;
00825     }
00826     MSLinkCont::const_iterator link = succLinkSec(*veh, 1, *this, veh->getBestLanesContinuation());
00827     return (link != myLinks.end());
00828 }
00829 
00830 
00831 bool
00832 MSLane::integrateNewVehicle(SUMOTime) {
00833     bool wasInactive = myVehicles.size() == 0;
00834     sort(myVehBuffer.begin(), myVehBuffer.end(), vehicle_position_sorter());
00835     for (std::vector<MSVehicle*>::const_iterator i = myVehBuffer.begin(); i != myVehBuffer.end(); ++i) {
00836         MSVehicle* veh = *i;
00837         myVehicles.push_front(veh);
00838         myVehicleLengthSum += veh->getVehicleType().getLengthWithGap();
00839     }
00840     myVehBuffer.clear();
00841     return wasInactive && myVehicles.size() != 0;
00842 }
00843 
00844 
00845 bool
00846 MSLane::isLinkEnd(MSLinkCont::const_iterator& i) const {
00847     return i == myLinks.end();
00848 }
00849 
00850 
00851 bool
00852 MSLane::isLinkEnd(MSLinkCont::iterator& i) {
00853     return i == myLinks.end();
00854 }
00855 
00856 
00857 MSVehicle*
00858 MSLane::getLastVehicle() const {
00859     if (myVehicles.size() == 0) {
00860         return 0;
00861     }
00862     return *myVehicles.begin();
00863 }
00864 
00865 
00866 const MSVehicle*
00867 MSLane::getFirstVehicle() const {
00868     if (myVehicles.size() == 0) {
00869         return 0;
00870     }
00871     return *(myVehicles.end() - 1);
00872 }
00873 
00874 
00875 MSLinkCont::const_iterator
00876 MSLane::succLinkSec(const SUMOVehicle& veh, unsigned int nRouteSuccs,
00877                     const MSLane& succLinkSource, const std::vector<MSLane*> &conts) const {
00878     const MSEdge* nRouteEdge = veh.succEdge(nRouteSuccs);
00879     // check whether the vehicle tried to look beyond its route
00880     if (nRouteEdge == 0) {
00881         // return end (no succeeding link) if so
00882         return succLinkSource.myLinks.end();
00883     }
00884     // a link may be used if
00885     //  1) there is a destination lane ((*link)->getLane()!=0)
00886     //  2) the destination lane belongs to the next edge in route ((*link)->getLane()->myEdge == nRouteEdge)
00887     //  3) the destination lane allows the vehicle's class ((*link)->getLane()->allowsVehicleClass(veh.getVehicleClass()))
00888 
00889     // at first, we'll assume we have the continuations of our route in "conts" (built in "getBestLanes")
00890     //  "conts" stores the best continuations of our current lane
00891     MSLinkCont::const_iterator link;
00892     if (nRouteSuccs > 0 && conts.size() >= nRouteSuccs && nRouteSuccs > 0) {
00893         // we go through the links in our list and return the matching one
00894         for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end() ; ++link) {
00895             if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
00896                 // we should use the link if it connects us to the best lane
00897                 if ((*link)->getLane() == conts[nRouteSuccs - 1]) {
00898                     return link;
00899                 }
00900             }
00901         }
00902     }
00903 
00904     // ok, we were not able to use the conts for any reason
00905     //  we will now collect allowed links, at first
00906     // collect allowed links
00907     std::vector<MSLinkCont::const_iterator> valid;
00908     for (link = succLinkSource.myLinks.begin(); link != succLinkSource.myLinks.end() ; ++link) {
00909         if ((*link)->getLane() != 0 && (*link)->getLane()->myEdge == nRouteEdge && (*link)->getLane()->allowsVehicleClass(veh.getVehicleType().getVehicleClass())) {
00910             valid.push_back(link);
00911         }
00912     }
00913     // if no valid link was found...
00914     if (valid.size() == 0) {
00915         // ... return end (no succeeding link)
00916         return succLinkSource.myLinks.end();
00917     }
00918     // if there is only one valid link, let's use it...
00919     if (valid.size() == 1) {
00920         return *(valid.begin());
00921     }
00922     // if the next edge is the route end, then we may return an arbitary link
00923     // also, if there is no allowed lane on the edge following the current one (recheck?)
00924     const MSEdge* nRouteEdge2 = veh.succEdge(nRouteSuccs + 1);
00925     const std::vector<MSLane*> *next_allowed = nRouteEdge->allowedLanes(*nRouteEdge2, veh.getVehicleType().getVehicleClass());
00926     if (nRouteEdge2 == 0 || next_allowed == 0) {
00927         return *(valid.begin());
00928     }
00929     // now let's determine which link is the best
00930     // in fact, we do not know it, here...
00931     for (std::vector<MSLinkCont::const_iterator>::iterator i = valid.begin(); i != valid.end(); ++i) {
00932         if (find(next_allowed->begin(), next_allowed->end(), (**i)->getLane()) != next_allowed->end()) {
00933             return *i;
00934         }
00935     }
00936     return *(valid.begin());
00937 }
00938 
00939 
00940 
00941 const MSLinkCont&
00942 MSLane::getLinkCont() const {
00943     return myLinks;
00944 }
00945 
00946 
00947 void
00948 MSLane::swapAfterLaneChange(SUMOTime) {
00949     myVehicles = myTmpVehicles;
00950     myTmpVehicles.clear();
00951 }
00952 
00953 
00954 
00955 
00956 GUILaneWrapper*
00957 MSLane::buildLaneWrapper(unsigned int) {
00958     throw "Only within the gui-version";
00959 }
00960 
00961 
00962 MSVehicle*
00963 MSLane::removeVehicle(MSVehicle* remVehicle) {
00964     for (MSLane::VehCont::iterator it = myVehicles.begin(); it < myVehicles.end(); it++) {
00965         if (remVehicle->getID() == (*it)->getID()) {
00966             remVehicle->leaveLane(MSMoveReminder::NOTIFICATION_ARRIVED);
00967             myVehicles.erase(it);
00968             myVehicleLengthSum -= remVehicle->getVehicleType().getLengthWithGap();
00969             break;
00970         }
00971     }
00972     return remVehicle;
00973 }
00974 
00975 
00976 MSLane*
00977 MSLane::getLeftLane() const {
00978     return myEdge->leftLane(this);
00979 }
00980 
00981 
00982 MSLane*
00983 MSLane::getRightLane() const {
00984     return myEdge->rightLane(this);
00985 }
00986 
00987 
00988 void
00989 MSLane::addIncomingLane(MSLane* lane, MSLink* viaLink) {
00990     IncomingLaneInfo ili;
00991     ili.lane = lane;
00992     ili.viaLink = viaLink;
00993     ili.length = lane->getLength();
00994     myIncomingLanes.push_back(ili);
00995 }
00996 
00997 
00998 void
00999 MSLane::addApproachingLane(MSLane* lane) {
01000     MSEdge* approachingEdge = &lane->getEdge();
01001     if (myApproachingLanes.find(approachingEdge) == myApproachingLanes.end()) {
01002         myApproachingLanes[approachingEdge] = std::vector<MSLane*>();
01003     }
01004     myApproachingLanes[approachingEdge].push_back(lane);
01005 }
01006 
01007 
01008 bool
01009 MSLane::isApproachedFrom(MSEdge* const edge) {
01010     return myApproachingLanes.find(edge) != myApproachingLanes.end();
01011 }
01012 
01013 
01014 bool
01015 MSLane::isApproachedFrom(MSEdge* const edge, MSLane* const lane) {
01016     std::map<MSEdge*, std::vector<MSLane*> >::const_iterator i = myApproachingLanes.find(edge);
01017     if (i == myApproachingLanes.end()) {
01018         return false;
01019     }
01020     const std::vector<MSLane*> &lanes = (*i).second;
01021     return find(lanes.begin(), lanes.end(), lane) != lanes.end();
01022 }
01023 
01024 
01025 class by_second_sorter {
01026 public:
01027     inline int operator()(const std::pair<const MSVehicle* , SUMOReal> &p1, const std::pair<const MSVehicle* , SUMOReal> &p2) const {
01028         return p1.second < p2.second;
01029     }
01030 };
01031 
01032 std::pair<MSVehicle* const, SUMOReal>
01033 MSLane::getFollowerOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal leaderSpeed,
01034                                  SUMOReal backOffset, SUMOReal predMaxDecel) const {
01035     // ok, a vehicle has not noticed the lane about itself;
01036     //  iterate as long as necessary to search for an approaching one
01037     std::set<MSLane*> visited;
01038     std::vector<std::pair<MSVehicle*, SUMOReal> > possible;
01039     std::vector<MSLane::IncomingLaneInfo> newFound;
01040     std::vector<MSLane::IncomingLaneInfo> toExamine = myIncomingLanes;
01041     while (toExamine.size() != 0) {
01042         for (std::vector<MSLane::IncomingLaneInfo>::iterator i = toExamine.begin(); i != toExamine.end(); ++i) {
01043             /*
01044             if ((*i).viaLink->getState()==LINKSTATE_TL_RED) {
01045                 continue;
01046             }
01047             */
01048             MSLane* next = (*i).lane;
01049             if (next->getFirstVehicle() != 0) {
01050                 MSVehicle* v = (MSVehicle*) next->getFirstVehicle();
01051                 SUMOReal agap = (*i).length - v->getPositionOnLane() + backOffset;
01052                 if (agap <= v->getCarFollowModel().getSecureGap(v->getCarFollowModel().maxNextSpeed(v->getSpeed()), leaderSpeed, predMaxDecel)) {
01053                     possible.push_back(std::make_pair(v, (*i).length - v->getPositionOnLane() - v->getVehicleType().getMinGap()+ seen));
01054                 }
01055             } else {
01056                 if ((*i).length + seen < dist) {
01057                     const std::vector<MSLane::IncomingLaneInfo> &followers = next->getIncomingLanes();
01058                     for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j = followers.begin(); j != followers.end(); ++j) {
01059                         if (visited.find((*j).lane) == visited.end()) {
01060                             visited.insert((*j).lane);
01061                             MSLane::IncomingLaneInfo ili;
01062                             ili.lane = (*j).lane;
01063                             ili.length = (*j).length + (*i).length;
01064                             ili.viaLink = (*j).viaLink;
01065                             newFound.push_back(ili);
01066                         }
01067                     }
01068                 }
01069             }
01070         }
01071         toExamine.clear();
01072         swap(newFound, toExamine);
01073     }
01074     if (possible.size() == 0) {
01075         return std::pair<MSVehicle * const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
01076     }
01077     sort(possible.begin(), possible.end(), by_second_sorter());
01078     return *(possible.begin());
01079 }
01080 
01081 
01082 std::pair<MSVehicle* const, SUMOReal>
01083 MSLane::getLeaderOnConsecutive(SUMOReal dist, SUMOReal seen, SUMOReal speed, const MSVehicle& veh,
01084                                const std::vector<MSLane*> &bestLaneConts) const {
01085     if (seen > dist) {
01086         return std::pair<MSVehicle * const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
01087     }
01088     unsigned int view = 1;
01089     // loop over following lanes
01090     const MSLane* targetLane = this;
01091     MSVehicle* leader = targetLane->getPartialOccupator();
01092     if (leader != 0) {
01093         return std::pair<MSVehicle * const, SUMOReal>(leader, seen - targetLane->getPartialOccupatorEnd());
01094     }
01095     const MSLane* nextLane = targetLane;
01096     SUMOTime arrivalTime = MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(seen / speed);
01097     while (true) {
01098         // get the next link used
01099         MSLinkCont::const_iterator link = targetLane->succLinkSec(veh, view, *nextLane, bestLaneConts);
01100         if (nextLane->isLinkEnd(link) || !(*link)->opened(arrivalTime, speed, veh.getVehicleType().getLength()) || (*link)->getState() == LINKSTATE_TL_RED) {
01101             return std::pair<MSVehicle * const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
01102         }
01103 #ifdef HAVE_INTERNAL_LANES
01104         bool nextInternal = false;
01105         nextLane = (*link)->getViaLane();
01106         if (nextLane == 0) {
01107             nextLane = (*link)->getLane();
01108         } else {
01109             nextInternal = true;
01110         }
01111 #else
01112         nextLane = (*link)->getLane();
01113 #endif
01114         if (nextLane == 0) {
01115             return std::pair<MSVehicle * const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
01116         }
01117         arrivalTime += TIME2STEPS(nextLane->getLength() / speed);
01118         MSVehicle* leader = nextLane->getLastVehicle();
01119         if (leader != 0) {
01120             return std::pair<MSVehicle * const, SUMOReal>(leader, seen + leader->getPositionOnLane() - leader->getVehicleType().getLength());
01121         } else {
01122             leader = nextLane->getPartialOccupator();
01123             if (leader != 0) {
01124                 return std::pair<MSVehicle * const, SUMOReal>(leader, seen + nextLane->getPartialOccupatorEnd());
01125             }
01126         }
01127         if (nextLane->getMaxSpeed() < speed) {
01128             dist = veh.getCarFollowModel().brakeGap(nextLane->getMaxSpeed());
01129         }
01130         seen += nextLane->getLength();
01131         if (seen > dist) {
01132             return std::pair<MSVehicle * const, SUMOReal>(static_cast<MSVehicle*>(0), -1);
01133         }
01134 #ifdef HAVE_INTERNAL_LANES
01135         if (!nextInternal) {
01136             view++;
01137         }
01138 #else
01139         view++;
01140 #endif
01141     }
01142 }
01143 
01144 
01145 MSLane*
01146 MSLane::getLogicalPredecessorLane() const {
01147     if (myLogicalPredecessorLane != 0) {
01148         return myLogicalPredecessorLane;
01149     }
01150     if (myLogicalPredecessorLane == 0) {
01151         std::vector<MSEdge*> pred = myEdge->getIncomingEdges();
01152         // get only those edges which connect to this lane
01153         for (std::vector<MSEdge*>::iterator i = pred.begin(); i != pred.end();) {
01154             std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(*i));
01155             if (j == myIncomingLanes.end()) {
01156                 i = pred.erase(i);
01157             } else {
01158                 ++i;
01159             }
01160         }
01161         // get the edge with the most connections to this lane's edge
01162         if (pred.size() != 0) {
01163             std::sort(pred.begin(), pred.end(), by_connections_to_sorter(&getEdge()));
01164             MSEdge* best = *pred.begin();
01165             std::vector<IncomingLaneInfo>::const_iterator j = find_if(myIncomingLanes.begin(), myIncomingLanes.end(), edge_finder(best));
01166             myLogicalPredecessorLane = (*j).lane;
01167         }
01168     }
01169     return myLogicalPredecessorLane;
01170 }
01171 
01172 
01173 void
01174 MSLane::leftByLaneChange(MSVehicle* v) {
01175     myVehicleLengthSum -= v->getVehicleType().getLengthWithGap();
01176 }
01177 
01178 
01179 void
01180 MSLane::enteredByLaneChange(MSVehicle* v) {
01181     myVehicleLengthSum += v->getVehicleType().getLengthWithGap();
01182 }
01183 
01184 
01185 // ------------ Current state retrieval
01186 SUMOReal
01187 MSLane::getOccupancy() const {
01188     return myVehicleLengthSum / myLength;
01189 }
01190 
01191 
01192 SUMOReal
01193 MSLane::getVehLenSum() const {
01194     return myVehicleLengthSum;
01195 }
01196 
01197 
01198 SUMOReal
01199 MSLane::getMeanSpeed() const {
01200     if (myVehicles.size() == 0) {
01201         return myMaxSpeed;
01202     }
01203     SUMOReal v = 0;
01204     const MSLane::VehCont& vehs = getVehiclesSecure();
01205     for (VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01206         v += (*i)->getSpeed();
01207     }
01208     SUMOReal ret = v / (SUMOReal) myVehicles.size();
01209     releaseVehicles();
01210     return ret;
01211 }
01212 
01213 
01214 SUMOReal
01215 MSLane::getHBEFA_CO2Emissions() const {
01216     SUMOReal ret = 0;
01217     const MSLane::VehCont& vehs = getVehiclesSecure();
01218     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01219         ret += (*i)->getHBEFA_CO2Emissions();
01220     }
01221     releaseVehicles();
01222     return ret;
01223 }
01224 
01225 
01226 SUMOReal
01227 MSLane::getHBEFA_COEmissions() const {
01228     SUMOReal ret = 0;
01229     const MSLane::VehCont& vehs = getVehiclesSecure();
01230     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01231         ret += (*i)->getHBEFA_COEmissions();
01232     }
01233     releaseVehicles();
01234     return ret;
01235 }
01236 
01237 
01238 SUMOReal
01239 MSLane::getHBEFA_PMxEmissions() const {
01240     SUMOReal ret = 0;
01241     const MSLane::VehCont& vehs = getVehiclesSecure();
01242     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01243         ret += (*i)->getHBEFA_PMxEmissions();
01244     }
01245     releaseVehicles();
01246     return ret;
01247 }
01248 
01249 
01250 SUMOReal
01251 MSLane::getHBEFA_NOxEmissions() const {
01252     SUMOReal ret = 0;
01253     const MSLane::VehCont& vehs = getVehiclesSecure();
01254     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01255         ret += (*i)->getHBEFA_NOxEmissions();
01256     }
01257     releaseVehicles();
01258     return ret;
01259 }
01260 
01261 
01262 SUMOReal
01263 MSLane::getHBEFA_HCEmissions() const {
01264     SUMOReal ret = 0;
01265     const MSLane::VehCont& vehs = getVehiclesSecure();
01266     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01267         ret += (*i)->getHBEFA_HCEmissions();
01268     }
01269     releaseVehicles();
01270     return ret;
01271 }
01272 
01273 
01274 SUMOReal
01275 MSLane::getHBEFA_FuelConsumption() const {
01276     SUMOReal ret = 0;
01277     const MSLane::VehCont& vehs = getVehiclesSecure();
01278     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01279         ret += (*i)->getHBEFA_FuelConsumption();
01280     }
01281     releaseVehicles();
01282     return ret;
01283 }
01284 
01285 
01286 SUMOReal
01287 MSLane::getHarmonoise_NoiseEmissions() const {
01288     SUMOReal ret = 0;
01289     const MSLane::VehCont& vehs = getVehiclesSecure();
01290     if (vehs.size() == 0) {
01291         releaseVehicles();
01292         return 0;
01293     }
01294     for (MSLane::VehCont::const_iterator i = vehs.begin(); i != vehs.end(); ++i) {
01295         SUMOReal sv = (*i)->getHarmonoise_NoiseEmissions();
01296         ret += (SUMOReal) pow(10., (sv / 10.));
01297     }
01298     releaseVehicles();
01299     return HelpersHarmonoise::sum(ret);
01300 }
01301 
01302 
01303 bool
01304 MSLane::VehPosition::operator()(const MSVehicle* cmp, SUMOReal pos) const {
01305     return cmp->getPositionOnLane() >= pos;
01306 }
01307 
01308 
01309 int 
01310 MSLane::vehicle_position_sorter::operator()(MSVehicle* v1, MSVehicle* v2) const {
01311     return v1->getPositionOnLane() > v2->getPositionOnLane();
01312 }
01313 
01314 MSLane::by_connections_to_sorter::by_connections_to_sorter(const MSEdge* const e) : 
01315     myEdge(e), 
01316     myLaneDir(e->getLanes()[0]->getShape().getBegLine().atan2PositiveAngle()) 
01317 { }
01318 
01319 
01320 int 
01321 MSLane::by_connections_to_sorter::operator()(const MSEdge* const e1, const MSEdge* const e2) const {
01322     const std::vector<MSLane*>* ae1 = e1->allowedLanes(*myEdge);
01323     const std::vector<MSLane*>* ae2 = e2->allowedLanes(*myEdge);
01324     SUMOReal s1 = 0;
01325     if (ae1 != 0 && ae1->size() != 0) {
01326         s1 = (SUMOReal) ae1->size() + GeomHelper::getMinAngleDiff((*ae1)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / PI / 2.;
01327     }
01328     SUMOReal s2 = 0;
01329     if (ae2 != 0 && ae2->size() != 0) {
01330         s2 = (SUMOReal) ae2->size() + GeomHelper::getMinAngleDiff((*ae2)[0]->getShape().getBegLine().atan2PositiveAngle(), myLaneDir) / PI / 2.;
01331     }
01332     return s1 < s2;
01333 }
01334 
01335 /****************************************************************************/
01336 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines