MSInductLoop.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // An unextended detector measuring at a fixed position on a fixed lane.
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 // ===========================================================================
00022 // included modules
00023 // ===========================================================================
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 
00030 #include "MSInductLoop.h"
00031 #include <cassert>
00032 #include <numeric>
00033 #include <utility>
00034 #include <utils/common/WrappingCommand.h>
00035 #include <utils/common/ToString.h>
00036 #include <microsim/MSEventControl.h>
00037 #include <microsim/MSLane.h>
00038 #include <utils/common/MsgHandler.h>
00039 #include <utils/common/UtilExceptions.h>
00040 #include <utils/common/StringUtils.h>
00041 #include <utils/iodevices/OutputDevice.h>
00042 
00043 #ifdef CHECK_MEMORY_LEAKS
00044 #include <foreign/nvwa/debug_new.h>
00045 #endif // CHECK_MEMORY_LEAKS
00046 
00047 
00048 // ===========================================================================
00049 // method definitions
00050 // ===========================================================================
00051 MSInductLoop::MSInductLoop(const std::string& id,
00052                            MSLane * const lane,
00053                            SUMOReal positionInMeters) throw()
00054         : MSMoveReminder(lane), Named(id), myCurrentVehicle(0),
00055         myPosition(positionInMeters), myLastLeaveTime(0),
00056         myVehiclesOnDet(), myVehicleDataCont() {
00057     assert(myPosition >= 0 && myPosition <= myLane->getLength());
00058     reset();
00059     myLastLeaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00060 }
00061 
00062 
00063 MSInductLoop::~MSInductLoop() throw() {
00064     if (myCurrentVehicle!=0) {
00065         myCurrentVehicle->quitRemindedLeft(this);
00066     }
00067     myCurrentVehicle = 0;
00068 }
00069 
00070 
00071 void
00072 MSInductLoop::reset() throw() {
00073     myDismissedVehicleNumber = 0;
00074     myLastVehicleDataCont = myVehicleDataCont;
00075     myVehicleDataCont.clear();
00076 }
00077 
00078 
00079 bool
00080 MSInductLoop::isStillActive(MSVehicle& veh, SUMOReal oldPos,
00081                             SUMOReal newPos, SUMOReal newSpeed) throw() {
00082     if (newPos < myPosition) {
00083         // detector not reached yet
00084         return true;
00085     }
00086     if (myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end()) {
00087         // entered the detector by move
00088         SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00089         if (newSpeed!=0) {
00090             entryTime += (myPosition - oldPos) / newSpeed;
00091         }
00092         if (newPos - veh.getVehicleType().getLength() > myPosition) {
00093             // entered and passed detector in a single timestep
00094             SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00095             leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
00096             enterDetectorByMove(veh, entryTime);
00097             leaveDetectorByMove(veh, leaveTime);
00098             return false;
00099         }
00100         // entered detector, but not passed
00101         enterDetectorByMove(veh, entryTime);
00102         return true;
00103     } else {
00104         // vehicle has been on the detector the previous timestep
00105         if (newPos - veh.getVehicleType().getLength() >= myPosition) {
00106             // vehicle passed the detector
00107             SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00108             leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
00109             leaveDetectorByMove(veh, leaveTime);
00110             return false;
00111         }
00112         // vehicle stays on the detector
00113         return true;
00114     }
00115 }
00116 
00117 
00118 void
00119 MSInductLoop::notifyLeave(MSVehicle& veh, bool isArrival, bool isLaneChange) throw() {
00120     if (veh.getPositionOnLane() > myPosition && veh.getPositionOnLane() - veh.getVehicleType().getLength() <= myPosition) {
00121         // vehicle is on detector during lane change
00122         leaveDetectorByLaneChange(veh);
00123     }
00124 }
00125 
00126 
00127 bool
00128 MSInductLoop::notifyEnter(MSVehicle& veh, bool, bool) throw() {
00129     if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myPosition) {
00130         // vehicle-front is beyond detector. Ignore
00131         return false;
00132     }
00133     // vehicle is in front of detector
00134     return true;
00135 }
00136 
00137 
00138 SUMOReal
00139 MSInductLoop::getCurrentSpeed() const throw() {
00140     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00141     return d.size()!=0
00142            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
00143            : -1;
00144 }
00145 
00146 
00147 SUMOReal
00148 MSInductLoop::getCurrentLength() const throw() {
00149     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00150     return d.size()!=0
00151            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
00152            : -1;
00153 }
00154 
00155 
00156 SUMOReal
00157 MSInductLoop::getCurrentOccupancy() const throw() {
00158     SUMOTime tbeg = MSNet::getInstance()->getCurrentTimeStep()-DELTA_T;
00159     std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
00160     if(d.size()==0) {
00161         return -1;
00162     }
00163     SUMOReal occupancy = 0;
00164     for(std::vector< VehicleData >::const_iterator i=d.begin(); i!=d.end(); ++i) {
00165         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
00166         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
00167         occupancy += timeOnDetDuringInterval;
00168     }
00169     return occupancy / TS * (SUMOReal) 100.;
00170 }
00171 
00172 
00173 SUMOReal
00174 MSInductLoop::getCurrentPassedNumber() const throw() {
00175     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00176     return (SUMOReal) d.size();
00177 }
00178 
00179 
00180 std::vector<std::string>
00181 MSInductLoop::getCurrentVehicleIDs() const throw() {
00182     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00183     std::vector<std::string> ret;
00184     for (std::vector<VehicleData>::iterator i=d.begin(); i!=d.end(); ++i) {
00185         ret.push_back((*i).idM);
00186     }
00187     return ret;
00188 }
00189 
00190 
00191 unsigned
00192 MSInductLoop::getNVehContributed() const throw() {
00193     return (unsigned int) collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T).size();
00194 }
00195 
00196 
00197 SUMOReal
00198 MSInductLoop::getTimestepsSinceLastDetection() const throw() {
00199     if (myVehiclesOnDet.size() != 0) {
00200         // detector is occupied
00201         return 0;
00202     }
00203     return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
00204 }
00205 
00206 
00207 void
00208 MSInductLoop::writeXMLDetectorProlog(OutputDevice &dev) const throw(IOError) {
00209     dev.writeXMLHeader("detector");
00210 }
00211 
00212 
00213 void
00214 MSInductLoop::writeXMLOutput(OutputDevice &dev,
00215                              SUMOTime startTime, SUMOTime stopTime) throw(IOError) {
00216     SUMOReal t(STEPS2TIME(stopTime-startTime));
00217     unsigned nVehCrossed = (unsigned) myVehicleDataCont.size() + myDismissedVehicleNumber;
00218     SUMOReal flow = ((SUMOReal) myVehicleDataCont.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
00219     SUMOReal occupancy = 0;
00220     for(std::deque< VehicleData >::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00221         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
00222         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
00223         occupancy += timeOnDetDuringInterval;
00224     }
00225     for(std::map< MSVehicle*, SUMOReal >::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00226         SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
00227         occupancy += timeOnDetDuringInterval;
00228     }
00229     occupancy = occupancy / t * (SUMOReal) 100.;
00230     SUMOReal meanSpeed = myVehicleDataCont.size()!=0
00231                          ? accumulate(myVehicleDataCont.begin(), myVehicleDataCont.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) myVehicleDataCont.size()
00232                          : -1;
00233     SUMOReal meanLength = myVehicleDataCont.size()!=0
00234                           ? accumulate(myVehicleDataCont.begin(), myVehicleDataCont.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) myVehicleDataCont.size()
00235                           : -1;
00236     dev<<"   <interval begin=\""<<time2string(startTime)<<"\" end=\""<<
00237     time2string(stopTime)<<"\" "<<"id=\""<<StringUtils::escapeXML(getID())<<"\" ";
00238     dev<<"nVehContrib=\""<<myVehicleDataCont.size()<<"\" flow=\""<<flow<<
00239     "\" occupancy=\""<<occupancy<<"\" speed=\""<<meanSpeed<<
00240     "\" length=\""<<meanLength<<
00241     "\" nVehEntered=\""<<nVehCrossed<<"\"/>\n";
00242     reset();
00243 }
00244 
00245 
00246 void
00247 MSInductLoop::enterDetectorByMove(MSVehicle& veh,
00248                                   SUMOReal entryTimestep) throw() {
00249     myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
00250     veh.quitRemindedEntered(this);
00251     if (myCurrentVehicle!=0&&myCurrentVehicle!=&veh) {
00252         // in fact, this is an error - a second vehicle is on the detector
00253         //  before the first one leaves... (collision)
00254         // Still, this seems to happen, but should not be handled herein.
00255         //  we will inform the user, etc., but continue as nothing had happened
00256         MsgHandler::getWarningInstance()->inform("Collision on e1-detector '" + getID() + "'.\n Vehicle '" + myCurrentVehicle->getID() +
00257                 "' was aready at detector as '" + veh.getID() + "' entered.");
00258         leaveDetectorByMove(*myCurrentVehicle, entryTimestep);
00259     }
00260     myCurrentVehicle = &veh;
00261 }
00262 
00263 
00264 void
00265 MSInductLoop::leaveDetectorByMove(MSVehicle& veh,
00266                                   SUMOReal leaveTimestep) throw() {
00267     VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
00268     assert(it != myVehiclesOnDet.end());
00269     SUMOReal entryTimestep = it->second;
00270     myVehiclesOnDet.erase(it);
00271     assert(entryTimestep < leaveTimestep);
00272     myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep));
00273     myLastOccupancy = leaveTimestep - entryTimestep;
00274     myLastLeaveTime = leaveTimestep;
00275     myCurrentVehicle = 0;
00276     veh.quitRemindedLeft(this);
00277 }
00278 
00279 
00280 void
00281 MSInductLoop::leaveDetectorByLaneChange(MSVehicle& veh) throw() {
00282     // Discard entry data
00283     myVehiclesOnDet.erase(&veh);
00284     myDismissedVehicleNumber++;
00285     myCurrentVehicle = 0;
00286     veh.quitRemindedLeft(this);
00287 }
00288 
00289 
00290 void
00291 MSInductLoop::removeOnTripEnd(MSVehicle *veh) throw() {
00292     myCurrentVehicle = 0;
00293     myVehiclesOnDet.erase(veh);
00294 }
00295 
00296 
00297 std::vector<MSInductLoop::VehicleData>
00298 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS) const throw() {
00299     SUMOReal t = STEPS2TIME(tMS);
00300     std::vector<VehicleData> ret;
00301     for (VehicleDataCont::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00302         if ((*i).leaveTimeM>=t) {
00303             ret.push_back(*i);
00304         }
00305     }
00306     for (VehicleDataCont::const_iterator i=myLastVehicleDataCont.begin(); i!=myLastVehicleDataCont.end(); ++i) {
00307         if ((*i).leaveTimeM>=t) {
00308             ret.push_back(*i);
00309         }
00310     }
00311     SUMOTime ct = MSNet::getInstance()->getCurrentTimeStep();
00312     for (VehicleMap::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00313         MSVehicle *v = (*i).first;
00314         VehicleData d(v->getID(), v->getVehicleType().getLength(), (*i).second, STEPS2TIME(ct));
00315         d.speedM = v->getSpeed();
00316         ret.push_back(d);
00317     }
00318     return ret;
00319 }
00320 
00321 
00322 /****************************************************************************/
00323 

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