MSVehicle.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Representation of a vehicle in the micro simulation
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 // ===========================================================================
00021 // included modules
00022 // ===========================================================================
00023 #ifdef _MSC_VER
00024 #include <windows_config.h>
00025 #else
00026 #include <config.h>
00027 #endif
00028 
00029 #include "MSLane.h"
00030 #include "MSVehicle.h"
00031 #include "MSEdge.h"
00032 #include "MSVehicleType.h"
00033 #include "MSNet.h"
00034 #include "MSRoute.h"
00035 #include "MSLinkCont.h"
00036 #include "MSVehicleQuitReminded.h"
00037 #include <utils/common/StringUtils.h>
00038 #include <utils/common/StdDefs.h>
00039 #include <microsim/MSVehicleControl.h>
00040 #include <microsim/MSGlobals.h>
00041 #include <iostream>
00042 #include <cassert>
00043 #include <cmath>
00044 #include <cstdlib>
00045 #include <algorithm>
00046 #include <map>
00047 #include "MSMoveReminder.h"
00048 #include <utils/options/OptionsCont.h>
00049 #include "MSLCM_DK2004.h"
00050 #include <utils/common/ToString.h>
00051 #include <utils/common/FileHelpers.h>
00052 #include <utils/iodevices/OutputDevice.h>
00053 #include <utils/iodevices/BinaryInputDevice.h>
00054 #include "trigger/MSBusStop.h"
00055 #include <utils/common/DijkstraRouterTT.h>
00056 #include "MSPerson.h"
00057 #include <utils/common/RandHelper.h>
00058 #include "devices/MSDevice_Routing.h"
00059 #include <microsim/devices/MSDevice_HBEFA.h>
00060 #include "MSEdgeWeightsStorage.h"
00061 #include <utils/common/HelpersHBEFA.h>
00062 #include <utils/common/HelpersHarmonoise.h>
00063 
00064 #ifdef _MESSAGES
00065 #include "MSMessageEmitter.h"
00066 #endif
00067 
00068 #ifdef HAVE_MESOSIM
00069 #include <mesosim/MESegment.h>
00070 #include <mesosim/MELoop.h>
00071 #include "MSGlobals.h"
00072 #endif
00073 
00074 #ifdef CHECK_MEMORY_LEAKS
00075 #include <foreign/nvwa/debug_new.h>
00076 #endif // CHECK_MEMORY_LEAKS
00077 
00078 //#define DEBUG_VEHICLE_GUI_SELECTION 1
00079 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00080 #include <utils/gui/div/GUIGlobalSelection.h>
00081 #include <guisim/GUIVehicle.h>
00082 #include <guisim/GUILane.h>
00083 #endif
00084 
00085 #define BUS_STOP_OFFSET 0.5
00086 
00087 
00088 // ===========================================================================
00089 // static value definitions
00090 // ===========================================================================
00091 std::vector<MSLane*> MSVehicle::myEmptyLaneVector;
00092 
00093 
00094 // ===========================================================================
00095 // method definitions
00096 // ===========================================================================
00097 /* -------------------------------------------------------------------------
00098  * methods of MSVehicle::State
00099  * ----------------------------------------------------------------------- */
00100 MSVehicle::State::State(const State& state) {
00101     myPos = state.myPos;
00102     mySpeed = state.mySpeed;
00103 }
00104 
00105 
00106 MSVehicle::State&
00107 MSVehicle::State::operator=(const State& state) {
00108     myPos   = state.myPos;
00109     mySpeed = state.mySpeed;
00110     return *this;
00111 }
00112 
00113 
00114 bool
00115 MSVehicle::State::operator!=(const State& state) {
00116     return (myPos   != state.myPos ||
00117             mySpeed != state.mySpeed);
00118 }
00119 
00120 
00121 SUMOReal
00122 MSVehicle::State::pos() const {
00123     return myPos;
00124 }
00125 
00126 
00127 MSVehicle::State::State(SUMOReal pos, SUMOReal speed) :
00128         myPos(pos), mySpeed(speed) {}
00129 
00130 
00131 /* -------------------------------------------------------------------------
00132  * MSVehicle-methods
00133  * ----------------------------------------------------------------------- */
00134 MSVehicle::~MSVehicle() throw() {
00135     // remove move reminder
00136     for (QuitRemindedVector::iterator i=myQuitReminded.begin(); i!=myQuitReminded.end(); ++i) {
00137         (*i)->removeOnTripEnd(this);
00138     }
00139     // delete the route
00140     if (!myRoute->inFurtherUse()) {
00141         MSRoute::erase(myRoute->getID());
00142     }
00143     // delete values in CORN
00144     if (myPointerCORNMap.find(MSCORN::CORN_P_VEH_OLDROUTE)!=myPointerCORNMap.end()) {
00145         ReplacedRoutesVector *v = (ReplacedRoutesVector*) myPointerCORNMap[MSCORN::CORN_P_VEH_OLDROUTE];
00146         for (ReplacedRoutesVector::iterator i=v->begin(); i!=v->end(); ++i) {
00147             delete(*i).route;
00148         }
00149         delete v;
00150     }
00151     if (myPointerCORNMap.find(MSCORN::CORN_P_VEH_DEPART_INFO)!=myPointerCORNMap.end()) {
00152         DepartArrivalInformation *i = (DepartArrivalInformation*) myPointerCORNMap[MSCORN::CORN_P_VEH_DEPART_INFO];
00153         delete i;
00154     }
00155     if (myPointerCORNMap.find(MSCORN::CORN_P_VEH_ARRIVAL_INFO)!=myPointerCORNMap.end()) {
00156         DepartArrivalInformation *i = (DepartArrivalInformation*) myPointerCORNMap[MSCORN::CORN_P_VEH_ARRIVAL_INFO];
00157         delete i;
00158     }
00159     //
00160     delete myParameter;
00161     delete myLaneChangeModel;
00162     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
00163         delete(*dev);
00164     }
00165     myDevices.clear();
00166     // persons
00167     if (hasCORNPointerValue(MSCORN::CORN_P_VEH_PASSENGER)) {
00168         std::vector<MSPerson*> *persons = (std::vector<MSPerson*>*) myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER];
00169         for (std::vector<MSPerson*>::iterator i=persons->begin(); i!=persons->end(); ++i) {
00170             (*i)->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep());
00171         }
00172         delete persons;
00173     }
00174     // other
00175     delete myEdgeWeights;
00176     for (std::vector<MSLane*>::iterator i=myFurtherLanes.begin(); i!=myFurtherLanes.end(); ++i) {
00177         (*i)->resetPartialOccupation(this);
00178     }
00179     for (DriveItemVector::iterator i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end(); ++i) {
00180         if ((*i).myLink!=0) {
00181             (*i).myLink->removeApproaching(this);
00182         }
00183     }
00184     myFurtherLanes.clear();
00185 }
00186 
00187 
00188 MSVehicle::MSVehicle(SUMOVehicleParameter* pars,
00189                      const MSRoute* route,
00190                      const MSVehicleType* type,
00191                      int vehicleIndex) throw(ProcessError) :
00192         myLastLaneChangeOffset(0),
00193         myTarget(0),
00194         myWaitingTime(0),
00195         myParameter(pars),
00196         myRoute(route),
00197         myState(0, 0), //
00198         myIndividualMaxSpeed(0.0),
00199         myHasIndividualMaxSpeed(false),
00200         myReferenceSpeed(-1.0),
00201         myLane(0),
00202         myType(type),
00203         myLastBestLanesEdge(0),
00204         myCurrEdge(myRoute->begin()),
00205         myMoveReminders(0),
00206         myOldLaneMoveReminders(0),
00207         myOldLaneMoveReminderOffsets(0),
00208         myArrivalPos(pars->arrivalPos),
00209         myPreDawdleAcceleration(0),
00210         myEdgeWeights(0)
00211 #ifndef NO_TRACI
00212         ,adaptingSpeed(false),
00213         isLastAdaption(false),
00214         speedBeforeAdaption(0),
00215         speedWithoutTraciInfluence(0),
00216         timeBeforeAdaption(0),
00217         speedReduction(0),
00218         adaptDuration(0),
00219         timeBeforeLaneChange(0),
00220         laneChangeStickyTime(0),
00221         laneChangeConstraintActive(false),
00222         myDestinationLane(0)
00223 #endif
00224 {
00225     for (std::vector<SUMOVehicleParameter::Stop>::iterator i=pars->stops.begin(); i!=pars->stops.end(); ++i) {
00226         if (!addStop(*i)) {
00227             throw ProcessError("Stop for vehicle '" + pars->id +
00228                                "' on lane '" + i->lane + "' is not downstream the current route.");
00229         }
00230     }
00231     for (std::vector<SUMOVehicleParameter::Stop>::const_iterator i=route->getStops().begin(); i!=route->getStops().end(); ++i) {
00232         if (!addStop(*i)) {
00233             throw ProcessError("Stop for vehicle '" + pars->id +
00234                                "' on lane '" + i->lane + "' is not downstream the current route.");
00235         }
00236     }
00237 #ifdef _MESSAGES
00238     myLCMsgEmitter = MSNet::getInstance()->getMsgEmitter("lanechange");
00239     myBMsgEmitter = MSNet::getInstance()->getMsgEmitter("break");
00240     myHBMsgEmitter = MSNet::getInstance()->getMsgEmitter("heartbeat");
00241 #endif
00242     // build arrival definition
00243     SUMOReal lastLaneLength = (myRoute->getLastEdge()->getLanes())[0]->getLength();
00244     if (myArrivalPos < 0) {
00245         myArrivalPos += lastLaneLength; // !!! validate!
00246     }
00247     if (myArrivalPos<0) {
00248         myArrivalPos = 0;
00249     }
00250     if (myArrivalPos>lastLaneLength) {
00251         myArrivalPos = lastLaneLength;
00252     }
00253     MSDevice_Routing::buildVehicleDevices(*this, myDevices);
00254     myLaneChangeModel = new MSLCM_DK2004(*this);
00255     // init devices
00256     MSDevice_HBEFA::buildVehicleDevices(*this, myDevices);
00257     // init CORN containers
00258     if (MSCORN::wished(MSCORN::CORN_VEH_WAITINGTIME)) {
00259         myIntCORNMap[MSCORN::CORN_VEH_WAITINGTIME] = 0;
00260     }
00261     if ((*myCurrEdge)->getDepartLane(*this) == 0) {
00262         throw ProcessError("Invalid departlane definition for vehicle '" + pars->id + "'");
00263     }
00264 }
00265 
00266 
00267 // ------------ interaction with the route
00268 void
00269 MSVehicle::onTryEmit() throw() {
00270     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
00271         (*dev)->onTryEmit();
00272     }
00273 }
00274 
00275 
00276 void
00277 MSVehicle::onDepart() throw() {
00278     // check whether the vehicle's departure time shall be saved
00279     if (MSCORN::wished(MSCORN::CORN_VEH_DEPART_TIME)) {
00280         myIntCORNMap[MSCORN::CORN_VEH_DEPART_TIME] = (int) MSNet::getInstance()->getCurrentTimeStep();
00281     }
00282     // check whether the vehicle's verbose departure information shall be saved
00283     if (MSCORN::wished(MSCORN::CORN_VEH_DEPART_INFO)) {
00284         DepartArrivalInformation *i = new DepartArrivalInformation();
00285         i->time = MSNet::getInstance()->getCurrentTimeStep();
00286         i->lane = myLane;
00287         i->pos = myState.pos();
00288         i->speed = myState.speed();
00289         myPointerCORNMap[MSCORN::CORN_P_VEH_DEPART_INFO] = (void*) i;
00290     }
00291     if (hasCORNPointerValue(MSCORN::CORN_P_VEH_PASSENGER)) {
00292         std::vector<MSPerson*> *persons = (std::vector<MSPerson*>*) myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER];
00293         for (std::vector<MSPerson*>::iterator i=persons->begin(); i!=persons->end(); ++i) {
00294             (*i)->setDeparted(MSNet::getInstance()->getCurrentTimeStep());
00295         }
00296     }
00297     // inform the vehicle control
00298     MSNet::getInstance()->getVehicleControl().vehicleEmitted(*this);
00299 }
00300 
00301 
00302 void
00303 MSVehicle::onRemovalFromNet(bool forTeleporting) throw() {
00304     // check whether the vehicle's verbose arrival information shall be saved
00305     if (!forTeleporting && MSCORN::wished(MSCORN::CORN_VEH_ARRIVAL_INFO)) {
00306         DepartArrivalInformation *i = new DepartArrivalInformation();
00307         i->time = MSNet::getInstance()->getCurrentTimeStep();
00308         i->lane = myLane;
00309         i->pos = myState.pos();
00310         i->speed = myState.speed();
00311         myPointerCORNMap[MSCORN::CORN_P_VEH_ARRIVAL_INFO] = (void*) i;
00312     }
00313     SUMOReal pspeed = myState.mySpeed;
00314     SUMOReal pos = myState.myPos;
00315     SUMOReal oldPos = pos - SPEED2DIST(pspeed);
00316     // process reminder
00317     workOnMoveReminders(oldPos, pos, pspeed);
00318     // remove from structures to be informed about it
00319     for (QuitRemindedVector::iterator i=myQuitReminded.begin(); i!=myQuitReminded.end(); ++i) {
00320         (*i)->removeOnTripEnd(this);
00321     }
00322     myQuitReminded.clear();
00323     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
00324         (*dev)->onRemovalFromNet();
00325     }
00326     for (DriveItemVector::iterator i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end(); ++i) {
00327         if ((*i).myLink!=0) {
00328             (*i).myLink->removeApproaching(this);
00329         }
00330     }
00331     leaveLane(true);
00332 }
00333 
00334 
00335 // ------------ interaction with the route
00336 const MSEdge*
00337 MSVehicle::succEdge(unsigned int nSuccs) const throw() {
00338     if (hasSuccEdge(nSuccs)) {
00339         return *(myCurrEdge + nSuccs);
00340     } else {
00341         return 0;
00342     }
00343 }
00344 
00345 
00346 bool
00347 MSVehicle::moveRoutePointer(const MSEdge* targetEdge) throw() {
00348     // vaporizing edge?
00349     if (targetEdge->isVaporizing()) {
00350         // yep, let's do the vaporization...
00351         setWasVaporized(false);
00352         return true;
00353     }
00354     // internal edge?
00355     if (targetEdge->getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL) {
00356         // yep, let's continue driving
00357         return false;
00358     }
00359     if (MSCORN::wished(MSCORN::CORN_VEH_SAVE_EDGE_EXIT)) {
00360         if (myPointerCORNMap.find(MSCORN::CORN_P_VEH_EXIT_TIMES)==myPointerCORNMap.end()) {
00361             myPointerCORNMap[MSCORN::CORN_P_VEH_EXIT_TIMES] = new std::vector<SUMOTime>();
00362         }
00363         ((std::vector<SUMOTime>*) myPointerCORNMap[MSCORN::CORN_P_VEH_EXIT_TIMES])->push_back(MSNet::getInstance()->getCurrentTimeStep());
00364     }
00365     // search for the target in the vehicle's route. Usually there is
00366     // only one iteration. Only for very short edges a vehicle can
00367     // "jump" over one ore more edges in one timestep.
00368     MSRouteIterator edgeIt = myCurrEdge;
00369     while (*edgeIt != targetEdge) {
00370         ++edgeIt;
00371         assert(edgeIt != myRoute->end());
00372     }
00373     myCurrEdge = edgeIt;
00374     // Check if destination-edge is reached. Update allowedLanes makes
00375     // only sense if destination isn't reached.
00376     MSRouteIterator destination = myRoute->end() - 1;
00377     return myCurrEdge == destination && getPositionOnLane() > myArrivalPos - POSITION_EPS;
00378 }
00379 
00380 
00381 bool
00382 MSVehicle::ends() const throw() {
00383     return myCurrEdge==myRoute->end()-1 && myState.myPos > myArrivalPos - POSITION_EPS;
00384 }
00385 
00386 
00387 const MSRoute &
00388 MSVehicle::getRoute(int index) const throw() {
00389     if (index==0) {
00390         return *myRoute;
00391     }
00392     --index; // only prior routes are stored
00393     std::map<MSCORN::Pointer, void*>::const_iterator i = myPointerCORNMap.find(MSCORN::CORN_P_VEH_OLDROUTE);
00394     assert(i!=myPointerCORNMap.end());
00395     const ReplacedRoutesVector * const v = (const ReplacedRoutesVector * const)(*i).second;
00396     assert((int) v->size()>index);
00397     return *((*v)[index].route);
00398 }
00399 
00400 
00401 bool
00402 MSVehicle::replaceRoute(const MSEdgeVector &edges, SUMOTime simTime, bool onInit) throw() {
00403     // assert the vehicle may continue (must not be "teleported" or whatever to another position)
00404     if (!onInit && find(edges.begin(), edges.end(), *myCurrEdge)==edges.end()) {
00405         return false;
00406     }
00407 
00408     // build a new one
00409     // build a new id, first
00410     std::string id = getID();
00411     if (id[0]!='!') {
00412         id = "!" + id;
00413     }
00414     if (myRoute->getID().find("!var#")!=std::string::npos) {
00415         id = myRoute->getID().substr(0, myRoute->getID().rfind("!var#")+4) + toString(myIntCORNMap[MSCORN::CORN_VEH_NUMBERROUTE] + 1);
00416     } else {
00417         id = id + "!var#1";
00418     }
00419     // build the route
00420     MSRoute *newRoute = new MSRoute(id, edges, false, myRoute->getColor(), myRoute->getStops());
00421     // and add it to the container (!!!what for? It will never be used again!?)
00422     if (!MSRoute::dictionary(id, newRoute)) {
00423         delete newRoute;
00424         return false;
00425     }
00426 
00427     // save information about the current edge
00428     const MSEdge *currentEdge = *myCurrEdge;
00429 
00430     // ... maybe the route information shall be saved for output?
00431     if (MSCORN::wished(MSCORN::CORN_VEH_SAVEREROUTING)) {
00432         RouteReplaceInfo rri(*myCurrEdge, simTime, new MSRoute(*myRoute));//new MSRoute("!", myRoute->getEdges(), false));
00433         if (myPointerCORNMap.find(MSCORN::CORN_P_VEH_OLDROUTE)==myPointerCORNMap.end()) {
00434             myPointerCORNMap[MSCORN::CORN_P_VEH_OLDROUTE] = new ReplacedRoutesVector();
00435         }
00436         ((ReplacedRoutesVector*) myPointerCORNMap[MSCORN::CORN_P_VEH_OLDROUTE])->push_back(rri);
00437     }
00438 
00439     // check whether the old route may be deleted (is not used by anyone else)
00440     if (!myRoute->inFurtherUse()) {
00441         MSRoute::erase(myRoute->getID());
00442     }
00443 
00444     // assign new route
00445     myRoute = newRoute;
00446     // rebuild in-vehicle route information
00447     if (onInit) {
00448         myCurrEdge = myRoute->begin();
00449     } else {
00450         myCurrEdge = myRoute->find(currentEdge);
00451     }
00452     myLastBestLanesEdge = 0;
00453     // update arrival definition
00454     myArrivalPos = myParameter->arrivalPos;
00455     SUMOReal lastLaneLength = (myRoute->getLastEdge()->getLanes())[0]->getLength();
00456     if (myArrivalPos < 0) {
00457         myArrivalPos += lastLaneLength; // !!! validate!
00458     }
00459     if (myArrivalPos<0) {
00460         myArrivalPos = 0;
00461     }
00462     if (myArrivalPos>lastLaneLength) {
00463         myArrivalPos = lastLaneLength;
00464     }
00465     // save information that the vehicle was rerouted
00466     //  !!! refactor the CORN-stuff
00467     myIntCORNMap[MSCORN::CORN_VEH_LASTREROUTEOFFSET] = 0;
00468     myIntCORNMap[MSCORN::CORN_VEH_NUMBERROUTE] = myIntCORNMap[MSCORN::CORN_VEH_NUMBERROUTE] + 1;
00469     // recheck stops
00470     for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end();) {
00471         if (find(edges.begin(), edges.end(), &iter->lane->getEdge())==edges.end()) {
00472             iter = myStops.erase(iter);
00473         } else {
00474             ++iter;
00475         }
00476     }
00477     return true;
00478 }
00479 
00480 
00481 bool
00482 MSVehicle::willPass(const MSEdge * const edge) const throw() {
00483     return find(myCurrEdge, myRoute->end(), edge)!=myRoute->end();
00484 }
00485 
00486 
00487 void
00488 MSVehicle::reroute(SUMOTime t, SUMOAbstractRouter<MSEdge, SUMOVehicle> &router, bool withTaz) throw() {
00489     // check whether to reroute
00490     std::vector<const MSEdge*> edges;
00491     if (withTaz && MSEdge::dictionary(myParameter->fromTaz+"-source") && MSEdge::dictionary(myParameter->toTaz)) {
00492         router.compute(MSEdge::dictionary(myParameter->fromTaz+"-source"), MSEdge::dictionary(myParameter->toTaz), (const MSVehicle * const) this, t, edges);
00493         if (edges.size() >= 2) {
00494             edges.erase(edges.begin());
00495             edges.pop_back();
00496         }
00497     } else {
00498         router.compute(*myCurrEdge, myRoute->getLastEdge(), (const MSVehicle * const) this, t, edges);
00499     }
00500     if (edges.empty()) {
00501         WRITE_WARNING("No route for vehicle '" + getID() + "' found.");
00502         return;
00503     }
00504     // check whether the new route is the same as the prior
00505     MSRouteIterator ri = myCurrEdge;
00506     std::vector<const MSEdge*>::iterator ri2 = edges.begin();
00507     while (ri!=myRoute->end()&&ri2!=edges.end()&&*ri==*ri2) {
00508         ++ri;
00509         ++ri2;
00510     }
00511     if (ri!=myRoute->end()||ri2!=edges.end()) {
00512         replaceRoute(edges, MSNet::getInstance()->getCurrentTimeStep(), withTaz);
00513     }
00514 }
00515 
00516 
00517 MSEdgeWeightsStorage &
00518 MSVehicle::getWeightsStorage() throw() {
00519     if (myEdgeWeights==0) {
00520         myEdgeWeights = new MSEdgeWeightsStorage();
00521     }
00522     return *myEdgeWeights;
00523 }
00524 
00525 
00526 bool
00527 MSVehicle::hasValidRoute(std::string &msg) const throw() {
00528     MSRouteIterator last = myRoute->end() - 1;
00529     // check connectivity, first
00530     for (MSRouteIterator e=myCurrEdge; e!=last; ++e) {
00531         if ((*e)->allowedLanes(**(e+1), myType->getVehicleClass())==0) {
00532             msg = "No connection between '" + (*e)->getID() + "' and '" + (*(e+1))->getID() + "'.";
00533             return false;
00534         }
00535     }
00536     last = myRoute->end();
00537     // check usable lanes, then
00538     for (MSRouteIterator e=myCurrEdge; e!=last; ++e) {
00539         if ((*e)->prohibits(this)) {
00540             msg = "Edge '" + (*e)->getID() + "' prohibits.";
00541             return false;
00542         }
00543     }
00544     return true;
00545 }
00546 
00547 
00548 // ------------ Retrieval of CORN values
00549 int
00550 MSVehicle::getCORNIntValue(MSCORN::Function f) const throw() {
00551     return myIntCORNMap.find(f)->second;
00552 }
00553 
00554 
00555 void *
00556 MSVehicle::getCORNPointerValue(MSCORN::Pointer p) const throw() {
00557     return myPointerCORNMap.find(p)->second;
00558 }
00559 
00560 
00561 bool
00562 MSVehicle::hasCORNIntValue(MSCORN::Function f) const throw() {
00563     return myIntCORNMap.find(f)!=myIntCORNMap.end();
00564 }
00565 
00566 
00567 bool
00568 MSVehicle::hasCORNPointerValue(MSCORN::Pointer p) const throw() {
00569     return myPointerCORNMap.find(p)!=myPointerCORNMap.end();
00570 }
00571 
00572 
00573 
00574 
00575 // ------------ Interaction with move reminders
00576 SUMOReal
00577 MSVehicle::getPositionOnActiveMoveReminderLane(const MSLane * const searchedLane) const throw() {
00578     if (searchedLane==myLane) {
00579         return myState.myPos;
00580     }
00581     std::vector< MSMoveReminder* >::const_iterator rem = myOldLaneMoveReminders.begin();
00582     std::vector<SUMOReal>::const_iterator off = myOldLaneMoveReminderOffsets.begin();
00583     for (; rem!=myOldLaneMoveReminders.end()&&off!=myOldLaneMoveReminderOffsets.end(); ++rem, ++off) {
00584         if ((*rem)->getLane()==searchedLane) {
00585             return (*off) + myState.myPos;
00586         }
00587     }
00588     return -1;
00589 }
00590 
00591 
00592 void
00593 MSVehicle::workOnMoveReminders(SUMOReal oldPos, SUMOReal newPos, SUMOReal newSpeed) throw() {
00594     // This erasure-idiom works for all stl-sequence-containers
00595     // See Meyers: Effective STL, Item 9
00596     for (std::vector< MSMoveReminder* >::iterator rem=myMoveReminders.begin(); rem!=myMoveReminders.end();) {
00597         if (!(*rem)->isStillActive(*this, oldPos, newPos, newSpeed)) {
00598             rem = myMoveReminders.erase(rem);
00599         } else {
00600             ++rem;
00601         }
00602     }
00603     OffsetVector::iterator off=myOldLaneMoveReminderOffsets.begin();
00604     for (std::vector< MSMoveReminder* >::iterator rem=myOldLaneMoveReminders.begin(); rem!=myOldLaneMoveReminders.end();) {
00605         SUMOReal oldLaneLength = *off;
00606         if (!(*rem)->isStillActive(*this, oldLaneLength+oldPos, oldLaneLength+newPos, newSpeed)) {
00607             rem = myOldLaneMoveReminders.erase(rem);
00608             off = myOldLaneMoveReminderOffsets.erase(off);
00609         } else {
00610             ++rem;
00611             ++off;
00612         }
00613     }
00614 }
00615 
00616 
00617 void
00618 MSVehicle::adaptLaneEntering2MoveReminder(const MSLane &enteredLane) throw() {
00619     // save the old work reminders, patching the position information
00620     //  add the information about the new offset to the old lane reminders
00621     SUMOReal oldLaneLength = myLane->getLength();
00622     OffsetVector::iterator i;
00623     for (i=myOldLaneMoveReminderOffsets.begin(); i!=myOldLaneMoveReminderOffsets.end(); ++i) {
00624         (*i) += oldLaneLength;
00625     }
00626     for (size_t j=0; j<myMoveReminders.size(); j++) {
00627         myOldLaneMoveReminderOffsets.push_back(oldLaneLength);
00628     }
00629     copy(myMoveReminders.begin(), myMoveReminders.end(), back_inserter(myOldLaneMoveReminders));
00630     assert(myOldLaneMoveReminders.size()==myOldLaneMoveReminderOffsets.size());
00631     // get new move reminder
00632     myMoveReminders = enteredLane.getMoveReminders();
00633 }
00634 
00635 
00636 void
00637 MSVehicle::activateReminders(bool isEmit, bool isLaneChange) throw() {
00638     // This erasure-idiom works for all stl-sequence-containers
00639     // See Meyers: Effective STL, Item 9
00640     for (std::vector< MSMoveReminder* >::iterator rem=myMoveReminders.begin(); rem!=myMoveReminders.end();) {
00641         if (!(*rem)->notifyEnter(*this, isEmit, isLaneChange)) {
00642             rem = myMoveReminders.erase(rem);
00643         } else {
00644             ++rem;
00645         }
00646     }
00647 }
00648 
00649 
00650 // ------------
00651 bool
00652 MSVehicle::addStop(const SUMOVehicleParameter::Stop &stopPar, SUMOTime untilOffset) throw() {
00653     Stop stop;
00654     stop.lane = MSLane::dictionary(stopPar.lane);
00655     stop.busstop = MSNet::getInstance()->getBusStop(stopPar.busstop);
00656     stop.pos = stopPar.pos;
00657     stop.duration = stopPar.duration;
00658     stop.until = stopPar.until;
00659     if (stop.until != -1) {
00660         stop.until += untilOffset;
00661     }
00662     stop.reached = false;
00663     MSRouteIterator stopEdge = myRoute->find(&stop.lane->getEdge(), myCurrEdge);
00664     if (myCurrEdge > stopEdge || (myCurrEdge == stopEdge && myState.myPos > stop.pos - getCarFollowModel().brakeGap(myState.mySpeed))) {
00665         // do not add the stop if the vehicle is already behind it or cannot break
00666         return false;
00667     }
00668     // check whether the stop lies at the end of a route
00669     std::list<Stop>::iterator iter = myStops.begin();
00670     MSRouteIterator last = myRoute->begin();
00671     if (myStops.size()>0) {
00672         last = myRoute->find(&myStops.back().lane->getEdge());
00673         last = myRoute->find(&stop.lane->getEdge(), last);
00674         if (last!=myRoute->end()) {
00675             iter = myStops.end();
00676             stopEdge = last;
00677         }
00678     }
00679     while ((iter != myStops.end()) && (myRoute->find(&iter->lane->getEdge()) <= stopEdge)) {
00680         iter++;
00681     }
00682     while ((iter != myStops.end())
00683             && (stop.pos > iter->pos)
00684             && (myRoute->find(&iter->lane->getEdge()) == stopEdge)) {
00685         iter++;
00686     }
00687     myStops.insert(iter, stop);
00688     return true;
00689 }
00690 
00691 
00692 bool
00693 MSVehicle::isStopped() {
00694     return !myStops.empty() && myStops.begin()->reached && myStops.begin()->duration>0;
00695 }
00696 
00697 
00698 SUMOReal
00699 MSVehicle::processNextStop(SUMOReal currentVelocity) throw() {
00700     if (myStops.empty()) {
00701         // no stops; pass
00702         return currentVelocity;
00703     }
00704     if (myStops.begin()->reached) {
00705         // ok, we have already reached the next stop
00706         if (myStops.begin()->duration==0) {
00707             // ... and have waited as long as needed
00708             if (myStops.begin()->busstop!=0) {
00709                 // inform bus stop about leaving it
00710                 myStops.begin()->busstop->leaveFrom(this);
00711             }
00712             // the current stop is no longer valid
00713             MSNet::getInstance()->getVehicleControl().removeWaiting(&myLane->getEdge(), this);
00714             if (hasCORNPointerValue(MSCORN::CORN_P_VEH_PASSENGER)) {
00715                 std::vector<MSPerson*> *persons = (std::vector<MSPerson*>*) myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER];
00716                 for (std::vector<MSPerson*>::iterator i=persons->begin(); i!=persons->end(); ++i) {
00717                     (*i)->setDeparted(MSNet::getInstance()->getCurrentTimeStep());
00718                 }
00719             }
00720             myStops.pop_front();
00721             // maybe the next stop is on the same edge; let's rebuild best lanes
00722             getBestLanes(true);
00723             // continue as wished...
00724         } else {
00725             // we have to wait some more time
00726             myStops.begin()->duration -= DELTA_T;
00727             return 0;
00728         }
00729     } else {
00730         // is the next stop on the current lane?
00731         if (myStops.begin()->lane==myLane) {
00732             Stop &bstop = *myStops.begin();
00733             // get the stopping position
00734             SUMOReal endPos = bstop.pos;
00735 //          SUMOReal offset = 0.1;
00736             bool busStopsMustHaveSpace = true;
00737             if (bstop.busstop!=0) {
00738                 // on bus stops, we have to wait for free place if they are in use...
00739 //              offset = BUS_STOP_OFFSET;
00740                 endPos = bstop.busstop->getLastFreePos();
00741                 if (endPos-5.<bstop.busstop->getBeginLanePosition()) { // !!! explicite offset
00742                     busStopsMustHaveSpace = false;
00743                 }
00744             }
00745 //            if (myState.pos()>=endPos-offset&&busStopsMustHaveSpace) {
00746             if (myState.pos()>=endPos-BUS_STOP_OFFSET&&busStopsMustHaveSpace) {
00747                 // ok, we may stop (have reached the stop)
00748                 MSNet::getInstance()->getPersonControl().checkWaiting(&myLane->getEdge(), this);
00749                 MSNet::getInstance()->getVehicleControl().addWaiting(&myLane->getEdge(), this);
00750                 if (hasCORNPointerValue(MSCORN::CORN_P_VEH_PASSENGER)) {
00751                     std::vector<MSPerson*> *persons = (std::vector<MSPerson*>*) myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER];
00752                     for (std::vector<MSPerson*>::iterator i=persons->begin(); i!=persons->end();) {
00753                         if (&(*i)->getDestination() == &myLane->getEdge()) {
00754                             (*i)->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep());
00755                             i = persons->erase(i);
00756                         } else {
00757                             ++i;
00758                         }
00759                     }
00760                 }
00761                 bstop.reached = true;
00762                 // compute stopping time
00763                 if (bstop.until>=0) {
00764                     if (bstop.duration==-1) {
00765                         bstop.duration = bstop.until - MSNet::getInstance()->getCurrentTimeStep();
00766                     } else {
00767                         bstop.duration = MAX2(bstop.duration, bstop.until - MSNet::getInstance()->getCurrentTimeStep());
00768                     }
00769                 }
00770                 if (bstop.busstop!=0) {
00771                     // let the bus stop know the vehicle
00772                     bstop.busstop->enter(this, myState.pos(), myState.pos()-myType->getLength());
00773                 }
00774             }
00775             // decelerate
00776             // !!! should not v be 0 when we have reached the stop?
00777             return getCarFollowModel().ffeS(this, endPos-myState.pos());
00778         }
00779     }
00780     return currentVelocity;
00781 }
00782 
00783 
00784 bool
00785 MSVehicle::moveRegardingCritical(SUMOTime t, const MSLane* const lane,
00786                                  const MSVehicle * const pred,
00787                                  const MSVehicle * const neigh,
00788                                  SUMOReal lengthsInFront) throw() {
00789 #ifdef _MESSAGES
00790     if (myHBMsgEmitter != 0) {
00791         if (isOnRoad()) {
00792             SUMOReal timeStep = MSNet::getInstance()->getCurrentTimeStep();
00793             myHBMsgEmitter->writeHeartBeatEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
00794         }
00795     }
00796 #endif
00797 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00798     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
00799         int bla = 0;
00800     }
00801 #endif
00802     myTarget = 0;
00803     for (DriveItemVector::iterator i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end(); ++i) {
00804         if ((*i).myLink!=0) {
00805             (*i).myLink->removeApproaching(this);
00806         }
00807     }
00808     myLFLinkLanes.clear();
00809     const MSCFModel &cfModel = getCarFollowModel();
00810     // check whether the vehicle is not on an appropriate lane
00811     if (!myLane->appropriate(this)) {
00812         // decelerate to lane end when yes
00813         SUMOReal vWish = MIN2(cfModel.ffeS(this, myLane->getLength()-myState.myPos), myLane->getMaxSpeed());
00814         if (pred!=0) {
00815             // interaction with leader if one exists on same lane
00816             SUMOReal gap = gap2pred(*pred);
00817             if (MSGlobals::gCheck4Accidents && gap<0) {
00818                 // collision occured!
00819                 return true;
00820             }
00821             vWish = MIN2(vWish, cfModel.ffeV(this, pred));
00822         } else {
00823             // (potential) interaction with a vehicle extending partially into this lane
00824             MSVehicle *predP = myLane->getPartialOccupator();
00825             if (predP!=0) {
00826                 SUMOReal gap = myLane->getPartialOccupatorEnd() - myState.myPos;
00827                 if (MSGlobals::gCheck4Accidents && gap<0) {
00828                     // collision occured!
00829                     return true;
00830                 }
00831                 vWish = MIN2(vWish, cfModel.ffeV(this, gap, predP->getSpeed()));
00832             }
00833         }
00834         // interaction with left-lane leader (do not overtake right)
00835         cfModel.leftVehicleVsafe(this, neigh, vWish);
00836         // check whether the vehicle wants to stop somewhere
00837         if (!myStops.empty()&& &myStops.begin()->lane->getEdge()==&lane->getEdge()) {
00838             SUMOReal seen = lane->getLength() - myState.pos();
00839             SUMOReal vsafeStop = cfModel.ffeS(this, seen-(lane->getLength()-myStops.begin()->pos));
00840             vWish = MIN2(vWish, vsafeStop);
00841         }
00842         vWish = MAX2((SUMOReal) 0, vWish);
00843         myLFLinkLanes.push_back(DriveProcessItem(0, vWish, vWish, false, 0, 0));
00844     } else {
00845         // compute other values as in move
00846         SUMOReal vBeg = MIN2(cfModel.maxNextSpeed(myState.mySpeed), lane->getMaxSpeed());//vaccel( myState.mySpeed, lane->maxSpeed() );
00847         if (pred!=0) {
00848             SUMOReal gap = gap2pred(*pred);
00849             if (MSGlobals::gCheck4Accidents && gap<0) {
00850                 // collision occured!
00851                 return true;
00852             }
00853             SUMOReal vSafe = cfModel.ffeV(this, gap, pred->getSpeed());
00854             //  the vehicle is bound by the lane speed and must not drive faster
00855             //  than vsafe to the next vehicle
00856             vBeg = MIN2(vBeg, vSafe);
00857         } else {
00858             // (potential) interaction with a vehicle extending partially into this lane
00859             MSVehicle *predP = myLane->getPartialOccupator();
00860             if (predP!=0) {
00861                 SUMOReal gap = myLane->getPartialOccupatorEnd() - myState.myPos;
00862                 if (MSGlobals::gCheck4Accidents && gap<0) {
00863                     // collision occured!
00864                     return true;
00865                 }
00866                 vBeg = MIN2(vBeg, cfModel.ffeV(this, gap, predP->getSpeed()));
00867             }
00868         }
00869         cfModel.leftVehicleVsafe(this, neigh, vBeg); // from left-lane leader (do not overtake right)
00870         // check whether the driver wants to let someone in
00871         // set next links, computing possible speeds
00872         vsafeCriticalCont(t, vBeg, lengthsInFront);
00873     }
00874     //@ to be optimized (move to somewhere else)
00875     if (hasCORNIntValue(MSCORN::CORN_VEH_LASTREROUTEOFFSET)) {
00876         myIntCORNMap[MSCORN::CORN_VEH_LASTREROUTEOFFSET] = myIntCORNMap[MSCORN::CORN_VEH_LASTREROUTEOFFSET] + 1;
00877     }
00878     //@ to be optimized (move to somewhere else)
00879     checkRewindLinkLanes(lengthsInFront);
00880     return false;
00881 }
00882 
00883 
00884 void
00885 MSVehicle::moveFirstChecked() {
00886 #ifdef DEBUG_VEHICLE_GUI_SELECTION
00887     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
00888         int bla = 0;
00889     }
00890 #endif
00891     myTarget = 0;
00892     // save old v for optional acceleration computation
00893     SUMOReal oldV = myState.mySpeed;
00894     // get vsafe
00895     SUMOReal vSafe = 0;
00896 
00897     assert(myLFLinkLanes.size()!=0);
00898     DriveItemVector::iterator i;
00899     bool cont = true;
00900     SUMOTime t = MSNet::getInstance()->getCurrentTimeStep();
00901     for (i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end()&&cont; ++i) {
00902         MSLink *link = (*i).myLink;
00903         bool onLinkEnd = link==0;
00904         // the vehicle must change the lane on one of the next lanes
00905         if (!onLinkEnd) {
00906             if (link->opened((*i).myArrivalTime, (*i).myArrivalSpeed)) {
00907                 vSafe = (*i).myVLinkPass;
00908             } else {
00909                 bool yellow = link->getState()==MSLink::LINKSTATE_TL_YELLOW_MAJOR||link->getState()==MSLink::LINKSTATE_TL_YELLOW_MINOR;
00910                 if (vSafe<getCarFollowModel().getSpeedAfterMaxDecel(myState.mySpeed)&&yellow) {
00911                     vSafe = (*i).myVLinkPass;
00912                 } else {
00913                     vSafe = (*i).myVLinkWait;
00914                     cont = false;
00915                 }
00916             }
00917         } else {
00918             vSafe = (*i).myVLinkWait;
00919             cont = false;
00920             break;
00921         }
00922     }
00923 
00924     SUMOReal vNext = getCarFollowModel().moveHelper(this, myLane, vSafe);
00925     vNext = MAX2(vNext, (SUMOReal) 0.);
00926     // visit waiting time
00927     if (vNext<=0.1) {
00928         myWaitingTime += DELTA_T;
00929         if (MSCORN::wished(MSCORN::CORN_VEH_WAITINGTIME)) {
00930             myIntCORNMap[MSCORN::CORN_VEH_WAITINGTIME]++;
00931         }
00932     } else {
00933         myWaitingTime = 0;
00934     }
00935     // call reminders after vNext is set
00936     SUMOReal pos = myState.myPos;
00937 #ifndef NO_TRACI
00938     speedWithoutTraciInfluence = MIN2(vNext, myType->getMaxSpeed());
00939 #endif
00940     vNext = MIN2(vNext, getMaxSpeed());
00941 
00942 #ifdef _MESSAGES
00943     if (myHBMsgEmitter != 0) {
00944         if (isOnRoad()) {
00945             SUMOReal timeStep = MSNet::getInstance()->getCurrentTimeStep();
00946             myHBMsgEmitter->writeHeartBeatEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
00947         }
00948     }
00949     if (myBMsgEmitter!=0) {
00950         if (vNext < oldV) {
00951             SUMOReal timeStep = MSNet::getInstance()->getCurrentTimeStep();
00952             myBMsgEmitter->writeBreakEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), getPosition().x(), getPosition().y());
00953         }
00954     }
00955 #endif
00956     // update position and speed
00957     myState.myPos += SPEED2DIST(vNext);
00958     myState.mySpeed = vNext;
00959     myTarget = 0;
00960     std::vector<MSLane*> passedLanes;
00961     for (std::vector<MSLane*>::reverse_iterator i=myFurtherLanes.rbegin(); i!=myFurtherLanes.rend(); ++i) {
00962         passedLanes.push_back(*i);
00963     }
00964     if (passedLanes.size()==0||passedLanes.back()!=myLane) {
00965         passedLanes.push_back(myLane);
00966     }
00967     // move on lane(s)
00968     if (myState.myPos<=myLane->getLength()) {
00969         // we are staying at our lane
00970         //  there is no need to go over succeeding lanes
00971         workOnMoveReminders(pos, pos + SPEED2DIST(vNext), vNext);
00972     } else {
00973         // we are moving at least to the next lane (maybe pass even more than one)
00974         MSLane *approachedLane = myLane;
00975         // move the vehicle forward
00976         SUMOReal driven = myState.myPos>approachedLane->getLength()
00977                           ? approachedLane->getLength() - pos
00978                           : myState.myPos - pos;
00979         for (i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end() && myState.myPos>approachedLane->getLength(); ++i) {
00980             if (approachedLane!=myLane) {
00981                 leaveLaneAtMove(driven);
00982             }
00983             MSLink *link = (*i).myLink;
00984             // check whether the vehicle was allowed to enter lane
00985             //  otherwise it is decelareted and we do not need to test for it's
00986             //  approach on the following lanes when a lane changing is performed
00987             assert(approachedLane!=0);
00988             myState.myPos -= approachedLane->getLength();
00989             assert(myState.myPos>0);
00990             if (approachedLane!=myLane) {
00991                 enterLaneAtMove(approachedLane, driven);
00992                 driven += approachedLane->getLength();
00993             }
00994             // proceed to the next lane
00995             if (link!=0) {
00996 #ifdef HAVE_INTERNAL_LANES
00997                 approachedLane = link->getViaLane();
00998                 if (approachedLane==0) {
00999                     approachedLane = link->getLane();
01000                 }
01001 #else
01002                 approachedLane = link->getLane();
01003 #endif
01004             }
01005             passedLanes.push_back(approachedLane);
01006         }
01007         myTarget = approachedLane;
01008     }
01009     // clear previously set information
01010     for (std::vector<MSLane*>::iterator i=myFurtherLanes.begin(); i!=myFurtherLanes.end(); ++i) {
01011         (*i)->resetPartialOccupation(this);
01012     }
01013     myFurtherLanes.clear();
01014     if (myState.myPos-getVehicleType().getLength()<0&&passedLanes.size()>0) {
01015         SUMOReal leftLength = getVehicleType().getLength()-myState.myPos;
01016         std::vector<MSLane*>::reverse_iterator i=passedLanes.rbegin() + 1;
01017         while (leftLength>0&&i!=passedLanes.rend()) {
01018             myFurtherLanes.push_back(*i);
01019             leftLength -= (*i)->setPartialOccupation(this, leftLength);
01020             ++i;
01021         }
01022     }
01023     assert(myTarget==0||myTarget->getLength()>=myState.myPos);
01024     setBlinkerInformation();
01025 }
01026 
01027 void
01028 MSVehicle::checkRewindLinkLanes(SUMOReal lengthsInFront) throw() {
01029 #ifdef DEBUG_VEHICLE_GUI_SELECTION
01030     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
01031         int bla = 0;
01032     }
01033 #endif
01034 #ifdef HAVE_INTERNAL_LANES
01035     if (MSGlobals::gUsingInternalLanes) {
01036         int removalBegin = -1;
01037         bool hadVehicle = false;
01038         SUMOReal seenLanes = 0;
01039         SUMOReal seenSpace = -lengthsInFront;
01040         MSLane *nextSeenNonInternal = 0;
01041         MSLane *approachedLane = myLane;
01042         int lastLinkToInternal = -1;
01043         MSVehicle *leader = 0;
01044 
01045         for (unsigned int i=0; i<myLFLinkLanes.size()&&removalBegin<0; ++i) {
01046             // skip unset links
01047             DriveProcessItem &item = myLFLinkLanes[i];
01048             if (item.myLink==0) {
01049                 continue;
01050             }
01051             if (approachedLane->getEdge().getPurpose()!=MSEdge::EDGEFUNCTION_INTERNAL) {
01052                 lastLinkToInternal = i;
01053             }
01054 
01055             //
01056 
01057             // get the next lane, determine whether it is an internal lane
01058             approachedLane = item.myLink->getViaLane();
01059             bool nextIsInternal = true;
01060             if (approachedLane==0) {
01061                 approachedLane = item.myLink->getLane();
01062                 nextIsInternal = false;
01063             }
01064             MSEdge::EdgeBasicFunction ef = approachedLane->getEdge().getPurpose();
01065             hadVehicle |= approachedLane->getVehicleNumber()!=0;
01066             nextIsInternal &= item.myLink->isCrossing();
01067             //
01068             if (nextIsInternal) {
01069                 // the free place on internal lanes is not counted - vehicles must keep them free
01070                 seenSpace = seenSpace - approachedLane->getVehLenSum();
01071                 if (leader==0&&approachedLane->getLastVehicle()!=0) {
01072                     leader = approachedLane->getLastVehicle();
01073                     seenSpace += leader->getCarFollowModel().brakeGap(leader->getSpeed());
01074                 }
01075             } else {
01076                 MSVehicle *pred = approachedLane->getLastVehicle();
01077                 bool nextDisallows1 = /*myState.mySpeed<.1 &&*/ pred!=0 && seenSpace<.1;
01078                 if (nextDisallows1) {
01079                     SUMOReal brakeGap = pred->getVehicleType().getCarFollowModel().brakeGap(pred->getSpeed());
01080                     nextDisallows1 &= pred->getPositionOnLane()+brakeGap < pred->getVehicleType().getLength();
01081                 }
01082                 // the free space on plain lanes is counted
01083                 // !!!: on longer lanes, only the place some meters in front... (next extension)
01084                 seenSpace = seenSpace + approachedLane->getLength() - approachedLane->getVehLenSum();
01085                 if (leader==0&&approachedLane->getLastVehicle()!=0) {
01086                     leader = approachedLane->getLastVehicle();
01087                     seenSpace += leader->getCarFollowModel().brakeGap(leader->getSpeed());
01088                 }
01089                 seenLanes += approachedLane->getLength();
01090                 // we also do not want the vehicle continue if there is not enough place
01091                 //  behind the last vehicle on the approached lane (and we are currently standing)
01092                 bool nextDisallows2 = /*myState.mySpeed<.1 &&*/ approachedLane->getLastVehicle()!=0 && approachedLane->getLastVehicle()->getSpeed()<.1;
01093                 if (nextDisallows2) {
01094                     nextDisallows2 &= approachedLane->getLastVehicle()->getPositionOnLane() < approachedLane->getLastVehicle()->getVehicleType().getLength();
01095                 }
01096                 if ((nextDisallows1||nextDisallows2)&&lastLinkToInternal>=0) {
01097                     removalBegin = lastLinkToInternal;
01098                 }
01099                 nextSeenNonInternal = approachedLane;
01100             }
01101             // now we check whether the vehicle should not continue because
01102             //  there is no space on approached lanes
01103             // - we must have seen at least one vehicle
01104             // - we must have seen at least as much place as the vehicle would need
01105             // - the seen space must be enough for our vehicle
01106             // - we should have seen at least one non-internal lane before
01107             SUMOReal impatienceCorrection = MAX2(0, myWaitingTime);
01108             if (hadVehicle&&seenLanes>getVehicleType().getLength()&&seenSpace<getVehicleType().getLength()-impatienceCorrection/10.&&nextSeenNonInternal!=0) {
01109                 removalBegin = lastLinkToInternal;
01110             }
01111         }
01112         if (removalBegin!=-1) {
01113             myLFLinkLanes[removalBegin].myVLinkPass = myLFLinkLanes[removalBegin].myVLinkWait;
01114             myLFLinkLanes[removalBegin].mySetRequest = false;
01115             if (removalBegin+1<(int)myLFLinkLanes.size()) {
01116                 myLFLinkLanes.erase(myLFLinkLanes.begin()+removalBegin+1, myLFLinkLanes.end());
01117             }
01118         }
01119     }
01120 #endif
01121     for (DriveItemVector::iterator i=myLFLinkLanes.begin(); i!=myLFLinkLanes.end(); ++i) {
01122         if ((*i).myLink!=0&&(*i).mySetRequest/*&&(*i).myArrivalTime+20<MSNet::getInstance()->getCurrentTimeStep()*/) {
01123             (*i).myLink->setApproaching(this, (*i).myArrivalTime, (*i).myArrivalSpeed);
01124         }
01125     }
01126 }
01127 
01128 
01129 
01130 void
01131 MSVehicle::vsafeCriticalCont(SUMOTime t, SUMOReal boundVSafe, SUMOReal lengthsInFront) {
01132 #ifdef DEBUG_VEHICLE_GUI_SELECTION
01133     if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
01134         int bla = 0;
01135     }
01136 #endif
01137     const MSCFModel &cfModel = getCarFollowModel();
01138     // the vehicle may have just to look into the next lane
01139     //  compute this information and use it only once in the next loop
01140     SUMOReal seen = myLane->getLength() - myState.myPos;
01141     // !!! Why is the brake gap accounted? !!!
01142     if (this!=myLane->getFirstVehicle() && seen - cfModel.brakeGap(myState.mySpeed) > 0) {
01143         // not "reaching critical"
01144         myLFLinkLanes.push_back(DriveProcessItem(0, boundVSafe, boundVSafe, false, 0, 0));
01145         return;
01146     }
01147 
01148     MSLane *nextLane = myLane;
01149     // compute the way the vehicle would drive if it would use the current speed and then
01150     //  decelerate
01151     SUMOReal maxV = cfModel.maxNextSpeed(myState.mySpeed);
01152     SUMOReal dist = SPEED2DIST(maxV) + cfModel.brakeGap(maxV);//myState.mySpeed);
01153     SUMOReal vLinkPass = boundVSafe;
01154     SUMOReal vLinkWait = vLinkPass;
01155     const std::vector<MSLane*> &bestLaneConts = getBestLanesContinuation();
01156 #ifdef HAVE_INTERNAL_LANES
01157     bool hadNonInternal = false;
01158     bool lastInnerHadPriority = false;
01159     bool passingInner = false;
01160 #endif
01161 
01162     unsigned int view = 1;
01163     // loop over following lanes
01164     while (true) {
01165         // process stops
01166         if (!myStops.empty()&& &myStops.begin()->lane->getEdge()==&nextLane->getEdge()) {
01167             SUMOReal vsafeStop = cfModel.ffeS(this, seen-(nextLane->getLength()-myStops.begin()->pos));
01168             vLinkPass = MIN2(vLinkPass, vsafeStop);
01169             vLinkWait = MIN2(vLinkWait, vsafeStop);
01170         }
01171 
01172         // get the next link used
01173         MSLinkCont::const_iterator link = myLane->succLinkSec(*this, view, *nextLane, bestLaneConts);
01174         // and the length of the currently investigated lane
01175         SUMOReal laneLength = nextLane->getLength();
01176 
01177         // check whether the lane is a dead end
01178         //  (should be valid only on further loop iterations
01179         if (nextLane->isLinkEnd(link)) {
01180             // the vehicle will not drive further
01181             SUMOReal laneEndVSafe = cfModel.ffeS(this, seen);
01182             myLFLinkLanes.push_back(DriveProcessItem(0, MIN2(vLinkPass, laneEndVSafe), MIN2(vLinkPass, laneEndVSafe), false, 0, 0));
01183             return;
01184         }
01185         // the link was passed
01186         vLinkWait = vLinkPass;
01187 
01188 
01189         // needed to let vehicles wait for all overlapping vehicles in front
01190         const MSLinkCont &lc = nextLane->getLinkCont();
01191 
01192         // get the following lane
01193 #ifdef HAVE_INTERNAL_LANES
01194         passingInner = nextLane->getEdge().getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL;
01195         bool nextInternal = false;
01196         nextLane = (*link)->getViaLane();
01197         if (nextLane==0) {
01198             nextLane = (*link)->getLane();
01199             hadNonInternal = true;
01200             passingInner = false;
01201         } else {
01202             nextInternal = true;
01203             passingInner &= nextLane->getEdge().getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL;
01204         }
01205 #else
01206         nextLane = (*link)->getLane();
01207 #endif
01208 
01209         // compute the velocity to use when the link is not blocked by oter vehicles
01210         //  the vehicle shall be not faster when reaching the next lane than allowed
01211         SUMOReal vmaxNextLane = MAX2(cfModel.ffeV(this, seen, nextLane->getMaxSpeed()), nextLane->getMaxSpeed());
01212 
01213         // the vehicle shall keep a secure distance to its predecessor
01214         //  (or approach the lane end if the predeccessor is too near)
01215         SUMOReal vsafePredNextLane = 100000;
01216         std::pair<MSVehicle*, SUMOReal> lastOnNext = nextLane->getLastVehicleInformation();
01217         if (lastOnNext.first!=0) {
01218             if (seen+lastOnNext.second>0) {
01219                 vsafePredNextLane = cfModel.ffeV(this, seen+lastOnNext.second, lastOnNext.first->getSpeed());
01220             }
01221         }
01222 #ifdef DEBUG_VEHICLE_GUI_SELECTION
01223         if (gSelected.isSelected(GLO_VEHICLE, static_cast<const GUIVehicle*>(this)->getGlID())) {
01224             int bla = 0;
01225         }
01226 #endif
01227         // compute the velocity to use when the link may be used
01228         vLinkPass = MIN3(vLinkPass, vmaxNextLane, vsafePredNextLane);
01229 
01230         // if the link may not be used (is blocked by another vehicle) then let the
01231         //  vehicle decelerate until the end of the street
01232         vLinkWait = MIN3(vLinkPass, vLinkWait, cfModel.ffeS(this, seen));
01233 
01234         bool yellow = (*link)->getState()==MSLink::LINKSTATE_TL_YELLOW_MAJOR||(*link)->getState()==MSLink::LINKSTATE_TL_YELLOW_MINOR;
01235         if (yellow&&SPEED2DIST(vLinkWait)+myState.myPos<laneLength) {
01236             myLFLinkLanes.push_back(DriveProcessItem(*link, vLinkWait, vLinkWait, false, 0, 0));
01237             return;
01238         }
01239         // behaviour in front of not priorised intersections (waiting for priorised foe vehicles)
01240         bool setRequest = false;
01241         bool mayPass = (*link)->havePriority() || (passingInner&&lastInnerHadPriority);
01242         if (!mayPass) {
01243             // The vehicle will not pass a red light
01244             if ((*link)->getState()==MSLink::LINKSTATE_TL_RED) {
01245                 vLinkPass = vLinkWait;
01246             }
01247             // The vehicle may pass if it already has passed the decision point which is at
01248             //  Also, after reaching this point, the speed should not be reduced
01249             // Up to this time it is decelearating in order to watch out for foe traffic
01250             if (seen>cfModel.getMaxDecel()) {
01251                 vLinkPass = vLinkWait;
01252 //                SUMOReal vDecel2Brake = cfModel.ffeV(this, seen-cfModel.getMaxDecel(), cfModel.getMaxDecel());
01253 //                vLinkPass = MIN2(vLinkPass, MAX2(vDecel2Brake, cfModel.getMaxDecel()));
01254 //                vLinkWait = MIN2(vLinkWait, MAX2(vDecel2Brake, cfModel.getMaxDecel()));
01255             }
01256         }
01257         lastInnerHadPriority = (*link)->havePriority();
01258         // process stops
01259         if (!myStops.empty()&& &myStops.begin()->lane->getEdge()==&nextLane->getEdge()) {
01260             SUMOReal vsafeStop = cfModel.ffeS(this, seen+myStops.begin()->pos);
01261             vLinkPass = MIN2(vLinkPass, vsafeStop);
01262             vLinkWait = MIN2(vLinkWait, vsafeStop);
01263             setRequest = false;
01264         } else {
01265             setRequest |= ((*link)->getState()!=MSLink::LINKSTATE_TL_RED&&(vLinkPass>0&&dist-seen>0));
01266         }
01267         // the next condition matches the previously one used for determining the difference
01268         //  between critical/non-critical vehicles. Though, one should assume that a vehicle
01269         //  should want to move over an intersection even though it could brake before it!?
01270         setRequest &= dist-seen>0;
01271         SUMOTime arrivalTime = 0;
01272         SUMOTime leaveTime = 0;
01273         if (setRequest) {
01274             arrivalTime = t + TIME2STEPS(seen / vLinkPass);
01275         }
01276         myLFLinkLanes.push_back(DriveProcessItem(*link, vLinkPass, vLinkWait, setRequest, arrivalTime, vLinkPass));
01277         seen += nextLane->getLength();
01278         if ((vLinkPass<=0||seen>dist)&&hadNonInternal) {
01279             return;
01280         }
01281 #ifdef HAVE_INTERNAL_LANES
01282         if (!nextInternal) {
01283             view++;
01284         }
01285 #else
01286         view++;
01287 #endif
01288     }
01289 }
01290 
01291 
01292 Position2D
01293 MSVehicle::getPosition() const {
01294     if (myLane==0) {
01295         return Position2D(-1000, -1000);
01296     }
01297     return myLane->getShape().positionAtLengthPosition(myState.pos());
01298 }
01299 
01300 
01301 const std::string &
01302 MSVehicle::getID() const throw() {
01303     return myParameter->id;
01304 }
01305 
01306 
01307 void
01308 MSVehicle::enterLaneAtMove(MSLane* enteredLane, SUMOReal driven) {
01309 #ifndef NO_TRACI
01310     // remove all Stops that were added by Traci and were not reached for any reason
01311     while (!myStops.empty()&&myStops.begin()->lane==myLane) {
01312         myStops.pop_front();
01313     }
01314 #endif
01315     // move mover reminder one lane further
01316     adaptLaneEntering2MoveReminder(*enteredLane);
01317     // set the entered lane as the current lane
01318     myLane = enteredLane;
01319     // proceed in route
01320     MSEdge &enteredEdge = enteredLane->getEdge();
01321     // internal edges are not a part of the route...
01322     if (enteredEdge.getPurpose()!=MSEdge::EDGEFUNCTION_INTERNAL) {
01323         // we may have to skip edges, as the vehicle may have past them in one step
01324         //  (and, of course, at least one edge is passed)
01325         MSRouteIterator edgeIt = myCurrEdge;
01326         while (*edgeIt != &enteredEdge) {
01327             ++edgeIt;
01328             assert(edgeIt != myRoute->end());
01329         }
01330         myCurrEdge = edgeIt;
01331     }
01332 
01333     // may be optimized: compute only, if the current or the next have more than one lane...!!!
01334     getBestLanes(true);
01335     activateReminders(false, false);
01336     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
01337         (*dev)->enterLaneAtMove(enteredLane, driven);
01338     }
01339 
01340 #ifndef NO_TRACI
01341     checkForLaneChanges();
01342 #endif
01343 }
01344 
01345 
01346 void
01347 MSVehicle::enterLaneAtLaneChange(MSLane* enteredLane) {
01348 #ifdef _MESSAGES
01349     if (myLCMsgEmitter!=0) {
01350         SUMOReal timeStep = MSNet::getInstance()->getCurrentTimeStep();
01351         myLCMsgEmitter->writeLaneChangeEvent(myParameter->id, timeStep, myLane, myState.pos(), myState.speed(), enteredLane, getPosition().x(), getPosition().y());
01352     }
01353 #endif
01354     MSLane *myPriorLane = myLane;
01355     myLane = enteredLane;
01356     // switch to and activate the new lane's reminders
01357     // keep OldLaneReminders
01358     myMoveReminders = enteredLane->getMoveReminders();
01359     activateReminders(false, true);
01360     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
01361         (*dev)->enterLaneAtLaneChange(enteredLane);
01362     }
01363     SUMOReal leftLength = myState.myPos-getVehicleType().getLength();
01364     if (leftLength<0) {
01365         // we have to rebuild "further lanes"
01366         const MSRoute &route = getRoute();
01367         MSRouteIterator i = myCurrEdge;
01368         MSLane *lane = myLane;
01369         while (i!=route.begin()&&leftLength>0) {
01370             const MSEdge * const prev = *(--i);
01371             const std::vector<MSLane::IncomingLaneInfo> &incomingLanes = lane->getIncomingLanes();
01372             for (std::vector<MSLane::IncomingLaneInfo>::const_iterator j=incomingLanes.begin(); j!=incomingLanes.end(); ++j) {
01373                 if (&(*j).lane->getEdge()==prev) {
01374 #ifdef HAVE_INTERNAL_LANES
01375                     (*j).lane->setPartialOccupation(this, leftLength);
01376 #else
01377                     leftLength -= (*j).length;
01378                     (*j).lane->setPartialOccupation(this, leftLength);
01379 #endif
01380                     leftLength -= (*j).lane->getLength();
01381                     break;
01382                 }
01383             }
01384         }
01385     }
01386 #ifndef NO_TRACI
01387     // check if further changes are necessary
01388     checkForLaneChanges();
01389 #endif
01390 }
01391 
01392 
01393 void
01394 MSVehicle::enterLaneAtEmit(MSLane* enteredLane, SUMOReal pos, SUMOReal speed) {
01395     myState = State(pos, speed);
01396     assert(myState.myPos >= 0);
01397     assert(myState.mySpeed >= 0);
01398     myWaitingTime = 0;
01399     myLane = enteredLane;
01400     // set and activate the new lane's reminders
01401     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
01402         (*dev)->enterLaneAtEmit(enteredLane, myState);
01403     }
01404     std::string msg;
01405     if (!hasValidRoute(msg)) {
01406         throw ProcessError("Vehicle '" + getID() + "' has no valid route. " + msg);
01407     }
01408     myMoveReminders = enteredLane->getMoveReminders();
01409     activateReminders(true, false);
01410     // build the list of lanes the vehicle is lapping into
01411     SUMOReal leftLength = myType->getLength() - pos;
01412     MSLane *clane = enteredLane;
01413     while (leftLength>0) {
01414         const std::vector<MSLane::IncomingLaneInfo> &incoming = clane->getIncomingLanes();
01415         if (incoming.size()==0) {
01416             break;
01417         }
01418         clane = incoming[0].lane; // !!! just an approximation
01419         myFurtherLanes.push_back(clane);
01420         leftLength -= (clane)->setPartialOccupation(this, leftLength);
01421     }
01422 }
01423 
01424 
01425 void
01426 MSVehicle::leaveLaneAtMove(SUMOReal driven) {
01427     std::vector< MSMoveReminder* >::iterator rem;
01428     for (rem=myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
01429         (*rem)->notifyLeave(*this, false, false);
01430     }
01431     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
01432         (*dev)->leaveLaneAtMove(driven);
01433     }
01434 }
01435 
01436 
01437 void
01438 MSVehicle::leaveLane(bool isArrival) {
01439     for (std::vector< MSDevice* >::iterator dev=myDevices.begin(); dev != myDevices.end(); ++dev) {
01440         (*dev)->leaveLane();
01441     }
01442     // dismiss the old lane's reminders
01443     SUMOReal savePos = myState.myPos; // have to do this due to SUMOReal-precision errors
01444     std::vector< MSMoveReminder* >::iterator rem;
01445     for (rem=myMoveReminders.begin(); rem != myMoveReminders.end(); ++rem) {
01446         (*rem)->notifyLeave(*this, isArrival, !isArrival);
01447     }
01448     std::vector<SUMOReal>::iterator off = myOldLaneMoveReminderOffsets.begin();
01449     for (rem=myOldLaneMoveReminders.begin(); rem!=myOldLaneMoveReminders.end(); ++rem, ++off) {
01450         myState.myPos += (*off);
01451         (*rem)->notifyLeave(*this, isArrival, !isArrival);
01452         myState.myPos -= (*off);
01453     }
01454     myState.myPos = savePos; // have to do this due to SUMOReal-precision errors
01455     myMoveReminders.clear();
01456     myOldLaneMoveReminders.clear();
01457     myOldLaneMoveReminderOffsets.clear();
01458     for (std::vector<MSLane*>::iterator i=myFurtherLanes.begin(); i!=myFurtherLanes.end(); ++i) {
01459         (*i)->resetPartialOccupation(this);
01460     }
01461     myFurtherLanes.clear();
01462 }
01463 
01464 
01465 const MSEdge * const
01466     MSVehicle::getEdge() const {
01467     return *myCurrEdge;
01468 }
01469 
01470 
01471 MSLane *
01472 MSVehicle::getTargetLane() const {
01473     return myTarget;
01474 }
01475 
01476 
01477 const MSLane &
01478 MSVehicle::getLane() const {
01479     return *myLane;
01480 }
01481 
01482 
01483 MSAbstractLaneChangeModel &
01484 MSVehicle::getLaneChangeModel() {
01485     return *myLaneChangeModel;
01486 }
01487 
01488 
01489 const MSAbstractLaneChangeModel &
01490 MSVehicle::getLaneChangeModel() const {
01491     return *myLaneChangeModel;
01492 }
01493 
01494 
01495 void
01496 MSVehicle::quitRemindedEntered(MSVehicleQuitReminded *r) {
01497     myQuitReminded.push_back(r);
01498 }
01499 
01500 
01501 void
01502 MSVehicle::quitRemindedLeft(MSVehicleQuitReminded *r) {
01503     QuitRemindedVector::iterator i = find(myQuitReminded.begin(), myQuitReminded.end(), r);
01504     if (i!=myQuitReminded.end()) {
01505         myQuitReminded.erase(i);
01506     }
01507 }
01508 
01509 
01510 void
01511 MSVehicle::rebuildContinuationsFor(LaneQ &oq, MSLane *l, MSRouteIterator ce, int seen) const {
01512     // check whether the end of iteration was reached
01513     ++ce;
01514     // we end if one of the following cases is true:
01515     // a) we have examined the next edges for 3000m (foresight distance)
01516     //     but only if we have at least examined the next edge
01517     // b) if we have examined 8 edges in front (!!! this may be shorted)
01518     // c) if the route does not continue after the seen edges
01519     if ((seen>4 && oq.length+l->getLength()>3000) || seen>8 || ce==myRoute->end()) {
01520         // ok, we have rebuilt this so far... do not have to go any further
01521         return;
01522     }
01523     // we must go further...
01524     // get the list of allowed lanes
01525     const std::vector<MSLane*> *allowed = 0;
01526     if (ce!=myRoute->end()&&ce+1!=myRoute->end()) {
01527         allowed = (*ce)->allowedLanes(**(ce+1), myType->getVehicleClass());
01528     }
01529     // determined recursively what the best lane is
01530     //  save the best lane for later usage
01531     LaneQ best;
01532     best.length = 0;
01533     const std::vector<MSLane*> &lanes = (*ce)->getLanes();
01534     const MSLinkCont &lc = l->getLinkCont();
01535     bool gotOne = false;
01536     // we go through all connections of the lane to examine
01537     for (MSLinkCont::const_iterator k=lc.begin(); k!=lc.end(); ++k) {
01538         // prese values
01539         LaneQ q;
01540         MSLane *qqq = (*k)->getLane();
01541         if (qqq==0) {
01542             q.occupied = 0;
01543             q.length = 0;
01544             continue;
01545         }
01546         q.occupied = qqq->getVehLenSum();
01547         q.length = qqq->getLength();
01548         q.joined.push_back(qqq);
01549 
01550 
01551         if (!myStops.empty()&& &(myStops.front().lane->getEdge())==&qqq->getEdge()) {
01552             if (myStops.front().lane==qqq) {
01553                 gotOne = true;
01554                 if (allowed==0||find(allowed->begin(), allowed->end(), (*k)->getLane())!=allowed->end()) {
01555                     rebuildContinuationsFor(q, qqq, ce, seen+1);
01556                 }
01557             } else {
01558                 q.occupied = qqq->getVehLenSum();
01559                 const Stop &s = myStops.front();
01560                 SUMOReal endPos = s.pos;
01561                 if (s.busstop!=0) {
01562                     // on bus stops, we have to wait for free place if they are in use...
01563                     endPos = s.busstop->getLastFreePos();
01564                 }
01565                 q.length = endPos;
01566             }
01567         } else {
01568             // check whether the lane is allowed for route continuation (has a link to the next
01569             //  edge in route)
01570             if (allowed==0||find(allowed->begin(), allowed->end(), (*k)->getLane())!=allowed->end()) {
01571                 // yes -> compute the best lane combination for consecutive lanes
01572                 gotOne = true;
01573                 rebuildContinuationsFor(q, qqq, ce, seen+1);
01574             } else {
01575                 // no -> if the lane belongs to an edge not in our route,
01576                 //  reset values to zero (otherwise the lane but not its continuations)
01577                 //  will still be regarded
01578                 if (&(*k)->getLane()->getEdge()!=*ce) {
01579                     q.occupied = 0;
01580                     q.length = 0;
01581                 }
01582             }
01583         }
01584         // set best lane information
01585         if (q.length>best.length) {
01586             best = q;
01587         }
01588     }
01589     // check whether we need to change the lane on this edge in any case
01590     if (!gotOne) {
01591         // yes, that's the case - we are on an edge on which we have to change
01592         //  the lane no matter which lanes we are using so far.
01593         // we have to tell the vehicle the best lane so far...
01594         // the assumption is that we only have to find the first one
01595         //  - because the vehicle has to change lanes, it will do this into
01596         //  the proper direction as the lanes moving the the proper edge are
01597         //  lying side by side
01598         const std::vector<MSLane*> &lanes = (*ce)->getLanes();
01599         bool oneFound = false;
01600         int bestPos = 0;
01601         MSLane *next = 0;
01602         // we go over the next edge's lanes and determine the first that may be used
01603         for (std::vector<MSLane*>::const_iterator i=lanes.begin(); !oneFound&&i!=lanes.end();) {
01604             if (allowed!=0 && find(allowed->begin(), allowed->end(), *i)!=allowed->end()) {
01605                 oneFound = true;
01606                 next = *i;
01607             } else {
01608                 ++i;
01609                 ++bestPos;
01610             }
01611         }
01612         // ... it is now stored in next and its position in bestPos
01613         if (oneFound) {
01614             // ok, we have found a best lane
01615             //  (in fact, this should be the case if the route is valid, nonetheless...)
01616             // now let's say that the best lane is the nearest one to the found
01617             int bestDistance = -100;
01618             MSLane *bestL = 0;
01619             // go over all lanes of current edge
01620             const std::vector<MSLane*> &clanes = l->getEdge().getLanes();
01621             for (std::vector<MSLane*>::const_iterator i=clanes.begin(); i!=clanes.end(); ++i) {
01622                 // go over all connected lanes
01623                 for (MSLinkCont::const_iterator k=lc.begin(); k!=lc.end(); ++k) {
01624                     if ((*k)->getLane()==0) {
01625                         continue;
01626                     }
01627                     // the best lane must be on the proper edge
01628                     if (&(*k)->getLane()->getEdge()==*ce) {
01629                         std::vector<MSLane*>::const_iterator l=find(lanes.begin(), lanes.end(), (*k)->getLane());
01630                         if (l!=lanes.end()) {
01631                             int pos = (int)distance(lanes.begin(), l);
01632                             int cdist = abs(pos-bestPos);
01633                             if (bestDistance==-100||bestDistance>cdist) {
01634                                 bestDistance = cdist;
01635                                 bestL = *i;
01636                             }
01637                         }
01638                     }
01639                 }
01640             }
01641             if (bestL==l) {
01642                 best.occupied = next->getVehLenSum();
01643                 best.length = next->getLength();
01644             } else {
01645                 best.occupied = 0;
01646                 best.length = 0;
01647                 best.joined.clear();
01648             }
01649         }
01650     }
01651     oq.length += best.length;
01652     oq.occupied += best.occupied;
01653     copy(best.joined.begin(), best.joined.end(), back_inserter(oq.joined));
01654 }
01655 
01656 
01657 
01658 const std::vector<MSVehicle::LaneQ> &
01659 MSVehicle::getBestLanes(bool forceRebuild, MSLane *startLane) const throw() {
01660     if (startLane==0) {
01661         startLane = myLane;
01662     }
01663     if (myLastBestLanesEdge==&startLane->getEdge()&&!forceRebuild) {
01664         std::vector<LaneQ> &lanes = *myBestLanes.begin();
01665         std::vector<LaneQ>::iterator i;
01666         for (i=lanes.begin(); i!=lanes.end(); ++i) {
01667             SUMOReal v = 0;
01668             for (std::vector<MSLane*>::const_iterator j=(*i).joined.begin(); j!=(*i).joined.end(); ++j) {
01669                 v += (*j)->getVehLenSum();
01670             }
01671             (*i).v = v;
01672             if ((*i).lane==startLane) {
01673                 myCurrentLaneInBestLanes = i;
01674             }
01675         }
01676         return *myBestLanes.begin();
01677     }
01678     myLastBestLanesEdge = &startLane->getEdge();
01679     myBestLanes.clear();
01680     myBestLanes.push_back(std::vector<LaneQ>());
01681     const std::vector<MSLane*> &lanes = (*myCurrEdge)->getLanes();
01682     MSRouteIterator ce = myCurrEdge;
01683     int seen = 0;
01684     const std::vector<MSLane*> *allowed = 0;
01685     if (ce!=myRoute->end()&&ce+1!=myRoute->end()) {
01686         allowed = (*ce)->allowedLanes(**(ce+1), myType->getVehicleClass());
01687     }
01688     for (std::vector<MSLane*>::const_iterator i=lanes.begin(); i!=lanes.end(); ++i) {
01689         LaneQ q;
01690         q.lane = *i;
01691         q.length = 0;//q.lane->getLength();
01692         q.occupied = 0;//q.lane->getVehLenSum();
01693         if (!myStops.empty()&& &myStops.front().lane->getEdge()==&q.lane->getEdge()) {
01694             if (myStops.front().lane==q.lane) {
01695                 q.allowsContinuation = allowed==0||find(allowed->begin(), allowed->end(), q.lane)!=allowed->end();
01696                 q.length += q.lane->getLength();
01697                 q.occupied += q.lane->getVehLenSum();
01698             } else {
01699                 q.allowsContinuation = false;
01700                 q.occupied = q.lane->getVehLenSum();
01701                 const Stop &s = myStops.front();
01702                 SUMOReal endPos = s.pos;
01703                 if (s.busstop!=0) {
01704                     // on bus stops, we have to wait for free place if they are in use...
01705                     endPos = s.busstop->getLastFreePos();
01706                 }
01707                 q.length = endPos;
01708             }
01709         } else {
01710             q.allowsContinuation = allowed==0||find(allowed->begin(), allowed->end(), q.lane)!=allowed->end();
01711         }
01712         myBestLanes[0].push_back(q);
01713     }
01714     if (ce!=myRoute->end()) {
01715         for (std::vector<MSVehicle::LaneQ>::iterator i=myBestLanes.begin()->begin(); i!=myBestLanes.begin()->end(); ++i) {
01716             if ((*i).allowsContinuation) {
01717                 rebuildContinuationsFor((*i), (*i).lane, ce, seen);
01718                 (*i).length += (*i).lane->getLength();
01719                 (*i).occupied += (*i).lane->getVehLenSum();
01720             }
01721         }
01722     }
01723     SUMOReal best = 0;
01724     int index = 0;
01725     int run = 0;
01726     for (std::vector<MSVehicle::LaneQ>::iterator i=myBestLanes.begin()->begin(); i!=myBestLanes.begin()->end(); ++i, ++run) {
01727         if (best<(*i).length) {
01728             best = (*i).length;
01729             index = run;
01730         }
01731         if ((*i).lane==startLane) {
01732             myCurrentLaneInBestLanes = i;
01733         }
01734     }
01735     run = 0;
01736     for (std::vector<MSVehicle::LaneQ>::iterator i=myBestLanes.begin()->begin(); i!=myBestLanes.begin()->end(); ++i, ++run) {
01737         (*i).bestLaneOffset =  index - run;
01738     }
01739 
01740     return *myBestLanes.begin();
01741 }
01742 
01743 
01744 void
01745 MSVehicle::writeXMLRoute(OutputDevice &os, int index) const {
01746     // check if a previous route shall be written
01747     os.openTag("route");
01748     if (index>=0) {
01749         std::map<MSCORN::Pointer, void*>::const_iterator i = myPointerCORNMap.find(MSCORN::CORN_P_VEH_OLDROUTE);
01750         assert(i!=myPointerCORNMap.end());
01751         const ReplacedRoutesVector *v = (const ReplacedRoutesVector *)(*i).second;
01752         assert((int) v->size()>index);
01753         // write edge on which the vehicle was when the route was valid
01754         os << " replacedOnEdge=\"" << (*v)[index].edge->getID();
01755         // write the time at which the route was replaced
01756         os << "\" replacedAtTime=\"" << time2string((*v)[index].time) << "\" probability=\"0\" edges=\"";
01757         // get the route
01758         for (int i=0; i<index; ++i) {
01759             (*v)[i].route->writeEdgeIDs(os, (*v)[i].edge);
01760         }
01761         (*v)[index].route->writeEdgeIDs(os);
01762     } else {
01763         os << " edges=\"";
01764         if (hasCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE)) {
01765             int noReroutes = getCORNIntValue(MSCORN::CORN_VEH_NUMBERROUTE);
01766             std::map<MSCORN::Pointer, void*>::const_iterator it = myPointerCORNMap.find(MSCORN::CORN_P_VEH_OLDROUTE);
01767             assert(it!=myPointerCORNMap.end());
01768             const ReplacedRoutesVector *v = (const ReplacedRoutesVector *)(*it).second;
01769             assert((int) v->size()==noReroutes);
01770             for (int i=0; i<noReroutes; ++i) {
01771                 (*v)[i].route->writeEdgeIDs(os, (*v)[i].edge);
01772             }
01773         }
01774         myRoute->writeEdgeIDs(os);
01775         if (hasCORNPointerValue(MSCORN::CORN_P_VEH_EXIT_TIMES)) {
01776             os << "\" exitTimes=\"";
01777             const std::vector<SUMOTime> *exits = (const std::vector<SUMOTime> *)getCORNPointerValue(MSCORN::CORN_P_VEH_EXIT_TIMES);
01778             for (std::vector<SUMOTime>::const_iterator it = exits->begin(); it != exits->end(); ++it) {
01779                 if (it != exits->begin()) {
01780                     os << " ";
01781                 }
01782                 os << time2string(*it);
01783             }
01784         }
01785     }
01786     (os << "\"").closeTag(true);
01787 }
01788 
01789 
01790 void
01791 MSVehicle::saveState(std::ostream &os) {
01792     FileHelpers::writeString(os, myParameter->id);
01793     FileHelpers::writeFloat(os, myLastLaneChangeOffset);
01794     FileHelpers::writeFloat(os, myWaitingTime);
01795     FileHelpers::writeInt(os, myParameter->repetitionNumber);
01796     FileHelpers::writeFloat(os, myParameter->repetitionOffset);
01797     FileHelpers::writeString(os, myRoute->getID());
01798     FileHelpers::writeTime(os, myParameter->depart);
01799     FileHelpers::writeString(os, myType->getID());
01800     FileHelpers::writeUInt(os, myRoute->posInRoute(myCurrEdge));
01801     if (hasCORNIntValue(MSCORN::CORN_VEH_DEPART_TIME)) {
01802         FileHelpers::writeInt(os, getCORNIntValue(MSCORN::CORN_VEH_DEPART_TIME));
01803     } else {
01804         FileHelpers::writeInt(os, -1);
01805     }
01806 #ifdef HAVE_MESOSIM
01807     // !!! several things may be missing
01808     if (mySegment==0) {
01809         FileHelpers::writeUInt(os, 0);
01810     } else {
01811         FileHelpers::writeUInt(os, mySegment->getIndex());
01812     }
01813     FileHelpers::writeUInt(os, getQueIndex());
01814     FileHelpers::writeTime(os, myEventTime);
01815     FileHelpers::writeTime(os, myLastEntryTime);
01816 #endif
01817 }
01818 
01819 
01820 
01821 
01822 void
01823 MSVehicle::removeOnTripEnd(MSVehicle *veh) throw() {
01824     quitRemindedLeft(veh);
01825 }
01826 
01827 
01828 
01829 const std::vector<MSLane*> &
01830 MSVehicle::getBestLanesContinuation() const throw() {
01831     if (myBestLanes.empty()||myBestLanes[0].empty()||myLane->getEdge().getPurpose()==MSEdge::EDGEFUNCTION_INTERNAL) {
01832         return myEmptyLaneVector;
01833     }
01834     return (*myCurrentLaneInBestLanes).joined;
01835 }
01836 
01837 
01838 const std::vector<MSLane*> &
01839 MSVehicle::getBestLanesContinuation(const MSLane * const l) const throw() {
01840     for (std::vector<std::vector<LaneQ> >::const_iterator i=myBestLanes.begin(); i!=myBestLanes.end(); ++i) {
01841         if ((*i).size()!=0&&(*i)[0].lane==l) {
01842             return (*i)[0].joined;
01843         }
01844     }
01845     return myEmptyLaneVector;
01846 }
01847 
01848 
01849 
01850 SUMOReal
01851 MSVehicle::getDistanceToPosition(SUMOReal destPos, const MSEdge* destEdge) {
01852 #ifdef DEBUG_VEHICLE_GUI_SELECTION
01853     SUMOReal distance = 1000000.;
01854 #else
01855     SUMOReal distance = std::numeric_limits<SUMOReal>::max();
01856 #endif
01857     if (isOnRoad() && destEdge != NULL) {
01858         if (&myLane->getEdge() == *myCurrEdge) {
01859             // vehicle is on a normal edge
01860             distance = myRoute->getDistanceBetween(getPositionOnLane(), destPos, *myCurrEdge, destEdge);
01861         } else {
01862             // vehicle is on inner junction edge
01863             distance = myLane->getLength() - getPositionOnLane();
01864             distance += myRoute->getDistanceBetween(0, destPos, *(myCurrEdge+1), destEdge);
01865         }
01866     }
01867     return distance;
01868 }
01869 
01870 void
01871 MSVehicle::setWasVaporized(bool onDepart) {
01872     if (MSCORN::wished(MSCORN::CORN_VEH_VAPORIZED)) {
01873         myIntCORNMap[MSCORN::CORN_VEH_VAPORIZED] = onDepart ? 1 : 0;
01874     }
01875 }
01876 
01877 
01878 SUMOReal
01879 MSVehicle::getHBEFA_CO2Emissions() const throw() {
01880     return HelpersHBEFA::computeCO2(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01881 }
01882 
01883 
01884 SUMOReal
01885 MSVehicle::getHBEFA_COEmissions() const throw() {
01886     return HelpersHBEFA::computeCO(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01887 }
01888 
01889 
01890 SUMOReal
01891 MSVehicle::getHBEFA_HCEmissions() const throw() {
01892     return HelpersHBEFA::computeHC(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01893 }
01894 
01895 
01896 SUMOReal
01897 MSVehicle::getHBEFA_NOxEmissions() const throw() {
01898     return HelpersHBEFA::computeNOx(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01899 }
01900 
01901 
01902 SUMOReal
01903 MSVehicle::getHBEFA_PMxEmissions() const throw() {
01904     return HelpersHBEFA::computePMx(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01905 }
01906 
01907 
01908 SUMOReal
01909 MSVehicle::getHBEFA_FuelConsumption() const throw() {
01910     return HelpersHBEFA::computeFuel(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01911 }
01912 
01913 
01914 SUMOReal
01915 MSVehicle::getHarmonoise_NoiseEmissions() const throw() {
01916     return HelpersHarmonoise::computeNoise(myType->getEmissionClass(), myState.speed(), myPreDawdleAcceleration);
01917 }
01918 
01919 
01920 void
01921 MSVehicle::addPerson(MSPerson* person) throw() {
01922     if (!hasCORNPointerValue(MSCORN::CORN_P_VEH_PASSENGER)) {
01923         myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER] = new std::vector<MSPerson*>();
01924     }
01925     ((std::vector<MSPerson*>*) myPointerCORNMap[MSCORN::CORN_P_VEH_PASSENGER])->push_back(person);
01926 }
01927 
01928 
01929 #ifndef NO_TRACI
01930 
01931 bool
01932 MSVehicle::startSpeedAdaption(float newSpeed, SUMOTime duration, SUMOTime currentTime) {
01933     if (newSpeed < 0 || duration <= 0/* || newSpeed >= getSpeed()*/) {
01934         return false;
01935     }
01936     speedBeforeAdaption = getSpeed();
01937     timeBeforeAdaption = currentTime;
01938     adaptDuration = duration;
01939     speedReduction = MAX2((SUMOReal) 0.0f, (SUMOReal)(speedBeforeAdaption - newSpeed));
01940     adaptingSpeed = true;
01941     return true;
01942 }
01943 
01944 
01945 void
01946 MSVehicle::adaptSpeed() {
01947     SUMOReal maxSpeed = 0;
01948     SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
01949     if (!adaptingSpeed) {
01950         return;
01951     }
01952     if (isLastAdaption) {
01953         unsetIndividualMaxSpeed();
01954         adaptingSpeed = false;
01955         isLastAdaption = false;
01956         return;
01957     }
01958     if (currentTime <= timeBeforeAdaption + adaptDuration) {
01959         maxSpeed = speedBeforeAdaption - (speedReduction / adaptDuration)
01960                    * (currentTime - timeBeforeAdaption);
01961     } else {
01962         maxSpeed = speedBeforeAdaption - speedReduction;
01963         isLastAdaption = true;
01964     }
01965     setIndividualMaxSpeed(maxSpeed);
01966 }
01967 
01968 
01969 void
01970 MSVehicle::checkLaneChangeConstraint(SUMOTime time) {
01971     if (!laneChangeConstraintActive) {
01972         return;
01973     }
01974     if ((time - timeBeforeLaneChange) >= laneChangeStickyTime) {
01975         laneChangeConstraintActive = false;
01976     }
01977 }
01978 
01979 
01980 void
01981 MSVehicle::startLaneChange(unsigned lane, SUMOTime stickyTime) {
01982     if (lane < 0) {
01983         return;
01984     }
01985     timeBeforeLaneChange = MSNet::getInstance()->getCurrentTimeStep();
01986     laneChangeStickyTime = stickyTime;
01987     myDestinationLane = lane;
01988     laneChangeConstraintActive = true;
01989     checkForLaneChanges();
01990 }
01991 
01992 
01993 void
01994 MSVehicle::checkForLaneChanges() {
01995     MSLane* tmpLane;
01996     unsigned currentLaneIndex = 0;
01997     if (!laneChangeConstraintActive) {
01998         myLaneChangeModel->requestLaneChange(REQUEST_NONE);
01999         return;
02000     }
02001     if ((unsigned int)(*myCurrEdge)->getLanes().size() <= myDestinationLane) {
02002         laneChangeConstraintActive = false;
02003         return;
02004     }
02005     tmpLane = myLane;
02006     while ((tmpLane =tmpLane->getRightLane()) != NULL) {
02007         currentLaneIndex++;
02008     }
02009     if (currentLaneIndex > myDestinationLane) {
02010         myLaneChangeModel->requestLaneChange(REQUEST_RIGHT);
02011     } else if (currentLaneIndex < myDestinationLane) {
02012         myLaneChangeModel->requestLaneChange(REQUEST_LEFT);
02013     } else {
02014         myLaneChangeModel->requestLaneChange(REQUEST_HOLD);
02015     }
02016 }
02017 
02018 
02019 void
02020 MSVehicle::processTraCICommands(SUMOTime time) {
02021     // check for applied lane changing constraints
02022     checkLaneChangeConstraint(time);
02023     // change speed in case of previous "slowDown" command
02024     adaptSpeed();
02025 }
02026 
02027 
02028 bool
02029 MSVehicle::addTraciStop(MSLane* lane, SUMOReal pos, SUMOReal radius, SUMOTime duration) {
02030     //if the stop exists update the duration
02031     for (std::list<Stop>::iterator iter = myStops.begin(); iter != myStops.end(); iter++) {
02032         if (iter->lane == lane && fabs(iter->pos - pos) < POSITION_EPS) {
02033             if (duration == 0 && !iter->reached) {
02034                 myStops.erase(iter);
02035             } else {
02036                 iter->duration = duration;
02037             }
02038             return true;
02039         }
02040     }
02041 
02042     SUMOVehicleParameter::Stop newStop;
02043     newStop.lane = lane->getID();
02044     newStop.pos = pos;
02045     newStop.duration = duration;
02046     newStop.until = -1;
02047     newStop.busstop = MSNet::getInstance()->getBusStopID(lane, pos);
02048     return addStop(newStop);
02049 }
02050 
02051 
02052 #endif
02053 
02054 
02055 /****************************************************************************/

Generated on Wed May 5 00:06:32 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6