SUMO - Simulation of Urban MObility

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 (C) 2001-2011 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, MSLane* const lane,
00052                            SUMOReal positionInMeters, bool splitByType) throw() :
00053     MSMoveReminder(lane),
00054     MSDetectorFileOutput(id),
00055     myPosition(positionInMeters),
00056     myLastLeaveTime(0),
00057     myVehicleDataCont(),
00058     myVehiclesOnDet(), mySplitByType(splitByType) {
00059     assert(myPosition >= 0 && myPosition <= myLane->getLength());
00060     reset();
00061     myLastLeaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00062 }
00063 
00064 
00065 MSInductLoop::~MSInductLoop() throw() {
00066 }
00067 
00068 
00069 void
00070 MSInductLoop::reset() throw() {
00071     myDismissedVehicleNumber = 0;
00072     myLastVehicleDataCont = myVehicleDataCont;
00073     myVehicleDataCont.clear();
00074 }
00075 
00076 
00077 bool
00078 MSInductLoop::notifyMove(SUMOVehicle& veh, SUMOReal oldPos,
00079                          SUMOReal newPos, SUMOReal newSpeed) throw() {
00080     if (newPos < myPosition) {
00081         // detector not reached yet
00082         return true;
00083     }
00084     if (newPos >= myPosition && oldPos < myPosition) {
00085         // entered the detector by move
00086         SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00087         if (newSpeed!=0) {
00088             if (myPosition>oldPos) {
00089                 entryTime += (myPosition - oldPos) / newSpeed;
00090             }
00091         }
00092         enterDetectorByMove(veh, entryTime);
00093     }
00094     if (newPos - veh.getVehicleType().getLengthWithGap() > myPosition && oldPos - veh.getVehicleType().getLengthWithGap() <= myPosition) {
00095         // vehicle passed the detector
00096         SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00097         leaveTime += (myPosition - oldPos + veh.getVehicleType().getLengthWithGap()) / newSpeed;
00098         leaveDetectorByMove(veh, leaveTime);
00099         return false;
00100     }
00101     // vehicle stays on the detector
00102     return true;
00103 }
00104 
00105 
00106 bool
00107 MSInductLoop::notifyLeave(SUMOVehicle& veh, SUMOReal /*lastPos*/, MSMoveReminder::Notification reason) throw() {
00108     if (reason != MSMoveReminder::NOTIFICATION_JUNCTION) {
00109         // vehicle is on detector during lane change or arrival, or ...
00110         leaveDetectorByLaneChange(veh);
00111         return false;
00112     }
00113     return true;
00114 }
00115 
00116 
00117 bool
00118 MSInductLoop::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification) throw() {
00119     if (veh.getPositionOnLane() - veh.getVehicleType().getLengthWithGap() > myPosition) {
00120         // vehicle-front is beyond detector. Ignore
00121         return false;
00122     }
00123     // vehicle is in front of detector
00124     return true;
00125 }
00126 
00127 
00128 SUMOReal
00129 MSInductLoop::getCurrentSpeed() const throw() {
00130     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00131     return d.size()!=0
00132            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
00133            : -1;
00134 }
00135 
00136 
00137 SUMOReal
00138 MSInductLoop::getCurrentLength() const throw() {
00139     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00140     return d.size()!=0
00141            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
00142            : -1;
00143 }
00144 
00145 
00146 SUMOReal
00147 MSInductLoop::getCurrentOccupancy() const throw() {
00148     SUMOTime tbeg = MSNet::getInstance()->getCurrentTimeStep()-DELTA_T;
00149     std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
00150     if (d.size()==0) {
00151         return -1;
00152     }
00153     SUMOReal occupancy = 0;
00154     for (std::vector< VehicleData >::const_iterator i=d.begin(); i!=d.end(); ++i) {
00155         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
00156         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
00157         occupancy += timeOnDetDuringInterval;
00158     }
00159     return occupancy / TS *(SUMOReal) 100.;
00160 }
00161 
00162 
00163 unsigned int
00164 MSInductLoop::getCurrentPassedNumber() const throw() {
00165     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00166     return (unsigned int) d.size();
00167 }
00168 
00169 
00170 std::vector<std::string>
00171 MSInductLoop::getCurrentVehicleIDs() const throw() {
00172     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00173     std::vector<std::string> ret;
00174     for (std::vector<VehicleData>::iterator i=d.begin(); i!=d.end(); ++i) {
00175         ret.push_back((*i).idM);
00176     }
00177     return ret;
00178 }
00179 
00180 
00181 SUMOReal
00182 MSInductLoop::getTimestepsSinceLastDetection() const throw() {
00183     if (myVehiclesOnDet.size() != 0) {
00184         // detector is occupied
00185         return 0;
00186     }
00187     return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
00188 }
00189 
00190 
00191 void
00192 MSInductLoop::writeXMLDetectorProlog(OutputDevice& dev) const throw(IOError) {
00193     dev.writeXMLHeader("detector");
00194 }
00195 
00196 
00197 void
00198 MSInductLoop::writeXMLOutput(OutputDevice& dev,
00199                              SUMOTime startTime, SUMOTime stopTime) throw(IOError) {
00200     writeTypedXMLOutput(dev, startTime, stopTime, "", myVehicleDataCont, myVehiclesOnDet);
00201     if (mySplitByType) {
00202         dev << ">\n";
00203         std::map<std::string, std::pair<VehicleDataCont, VehicleMap> > types;
00204         // collect / divide
00205         for (std::deque< VehicleData >::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00206             if (types.find((*i).typeIDM)==types.end()) {
00207                 types[(*i).typeIDM] = make_pair(VehicleDataCont(), VehicleMap());
00208             }
00209             types[(*i).typeIDM].first.push_back(*i);
00210         }
00211         for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00212             const std::string& type = (*i).first->getVehicleType().getID();
00213             if (types.find(type)==types.end()) {
00214                 types[type] = make_pair(VehicleDataCont(), VehicleMap());
00215             }
00216             types[type].second[(*i).first] = (*i).second;
00217         }
00218         // write
00219         for (std::map<std::string, std::pair<VehicleDataCont, VehicleMap> >::const_iterator i=types.begin(); i!=types.end(); ++i) {
00220             writeTypedXMLOutput(dev, startTime, stopTime, (*i).first, (*i).second.first, (*i).second.second);
00221             dev << "/>\n";
00222         }
00223         dev << "   </interval>\n";
00224     } else {
00225         dev << "/>\n";
00226     }
00227     reset();
00228 }
00229 
00230 void
00231 MSInductLoop::writeTypedXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime,
00232                                   const std::string& type, const VehicleDataCont& vdc, const VehicleMap& vm) throw(IOError) {
00233     SUMOReal t(STEPS2TIME(stopTime-startTime));
00234     unsigned nVehCrossed = (unsigned) vdc.size();
00235     if (type=="") {
00236         nVehCrossed += myDismissedVehicleNumber;
00237     }
00238     SUMOReal flow = ((SUMOReal) vdc.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
00239     SUMOReal occupancy = 0;
00240     for (std::deque< VehicleData >::const_iterator i=vdc.begin(); i!=vdc.end(); ++i) {
00241         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
00242         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
00243         occupancy += timeOnDetDuringInterval;
00244     }
00245     for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i=vm.begin(); i!=vm.end(); ++i) {
00246         SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
00247         occupancy += timeOnDetDuringInterval;
00248     }
00249     occupancy = occupancy / t * (SUMOReal) 100.;
00250     SUMOReal meanSpeed = vdc.size()!=0
00251                          ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) vdc.size()
00252                          : -1;
00253     SUMOReal meanLength = vdc.size()!=0
00254                           ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) vdc.size()
00255                           : -1;
00256     if (type!="") {
00257         dev << "      <typedInterval type=\"" + type + "\" ";
00258     } else {
00259         dev << "   <interval ";
00260     }
00261     dev<<"begin=\""<<time2string(startTime)<<"\" end=\""<<
00262        time2string(stopTime)<<"\" "<<"id=\""<<StringUtils::escapeXML(getID())<<"\" ";
00263     dev<<"nVehContrib=\""<<vdc.size()<<"\" flow=\""<<flow<<
00264        "\" occupancy=\""<<occupancy<<"\" speed=\""<<meanSpeed<<
00265        "\" length=\""<<meanLength<<
00266        "\" nVehEntered=\""<<nVehCrossed<<"\"";
00267 }
00268 
00269 
00270 void
00271 MSInductLoop::enterDetectorByMove(SUMOVehicle& veh,
00272                                   SUMOReal entryTimestep) throw() {
00273     myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
00274 }
00275 
00276 
00277 void
00278 MSInductLoop::leaveDetectorByMove(SUMOVehicle& veh,
00279                                   SUMOReal leaveTimestep) throw() {
00280     VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
00281     if (it!=myVehiclesOnDet.end()) {
00282         SUMOReal entryTimestep = it->second;
00283         myVehiclesOnDet.erase(it);
00284         assert(entryTimestep < leaveTimestep);
00285         myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLengthWithGap(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
00286         myLastOccupancy = leaveTimestep - entryTimestep;
00287     }
00288     myLastLeaveTime = leaveTimestep;
00289 }
00290 
00291 
00292 void
00293 MSInductLoop::leaveDetectorByLaneChange(SUMOVehicle& veh) throw() {
00294     // Discard entry data
00295     myVehiclesOnDet.erase(&veh);
00296     myDismissedVehicleNumber++;
00297 }
00298 
00299 
00300 std::vector<MSInductLoop::VehicleData>
00301 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS) const throw() {
00302     SUMOReal t = STEPS2TIME(tMS);
00303     std::vector<VehicleData> ret;
00304     for (VehicleDataCont::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00305         if ((*i).leaveTimeM>=t) {
00306             ret.push_back(*i);
00307         }
00308     }
00309     for (VehicleDataCont::const_iterator i=myLastVehicleDataCont.begin(); i!=myLastVehicleDataCont.end(); ++i) {
00310         if ((*i).leaveTimeM>=t) {
00311             ret.push_back(*i);
00312         }
00313     }
00314     SUMOTime ct = MSNet::getInstance()->getCurrentTimeStep();
00315     for (VehicleMap::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00316         SUMOVehicle* v = (*i).first;
00317         VehicleData d(v->getID(), v->getVehicleType().getLengthWithGap(), (*i).second, STEPS2TIME(ct), v->getVehicleType().getID());
00318         d.speedM = v->getSpeed();
00319         ret.push_back(d);
00320     }
00321     return ret;
00322 }
00323 
00324 
00325 /****************************************************************************/
00326 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines