SUMO - Simulation of Urban MObility

MSInductLoop.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00012 // An unextended detector measuring at a fixed position on a fixed lane.
00013 /****************************************************************************/
00014 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00015 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00016 /****************************************************************************/
00017 //
00018 //   This file is part of SUMO.
00019 //   SUMO is free software: you can redistribute it and/or modify
00020 //   it under the terms of the GNU General Public License as published by
00021 //   the Free Software Foundation, either version 3 of the License, or
00022 //   (at your option) any later version.
00023 //
00024 /****************************************************************************/
00025 
00026 
00027 // ===========================================================================
00028 // included modules
00029 // ===========================================================================
00030 #ifdef _MSC_VER
00031 #include <windows_config.h>
00032 #else
00033 #include <config.h>
00034 #endif
00035 
00036 #include "MSInductLoop.h"
00037 #include <cassert>
00038 #include <numeric>
00039 #include <utility>
00040 #include <utils/common/WrappingCommand.h>
00041 #include <utils/common/ToString.h>
00042 #include <microsim/MSEventControl.h>
00043 #include <microsim/MSLane.h>
00044 #include <utils/common/MsgHandler.h>
00045 #include <utils/common/UtilExceptions.h>
00046 #include <utils/common/StringUtils.h>
00047 #include <utils/iodevices/OutputDevice.h>
00048 
00049 #ifdef CHECK_MEMORY_LEAKS
00050 #include <foreign/nvwa/debug_new.h>
00051 #endif // CHECK_MEMORY_LEAKS
00052 
00053 
00054 // ===========================================================================
00055 // method definitions
00056 // ===========================================================================
00057 MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
00058                            SUMOReal positionInMeters, bool splitByType) :
00059     MSMoveReminder(lane),
00060     MSDetectorFileOutput(id),
00061     myPosition(positionInMeters),
00062     myLastLeaveTime(0),
00063     myVehicleDataCont(),
00064     myVehiclesOnDet(), mySplitByType(splitByType) {
00065     assert(myPosition >= 0 && myPosition <= myLane->getLength());
00066     reset();
00067     myLastLeaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00068 }
00069 
00070 
00071 MSInductLoop::~MSInductLoop() {
00072 }
00073 
00074 
00075 void
00076 MSInductLoop::reset() {
00077     myDismissedVehicleNumber = 0;
00078     myLastVehicleDataCont = myVehicleDataCont;
00079     myVehicleDataCont.clear();
00080 }
00081 
00082 
00083 bool
00084 MSInductLoop::notifyMove(SUMOVehicle& veh, SUMOReal oldPos,
00085                          SUMOReal newPos, SUMOReal newSpeed) {
00086     if (newPos < myPosition) {
00087         // detector not reached yet
00088         return true;
00089     }
00090     if (newPos >= myPosition && oldPos < myPosition) {
00091         // entered the detector by move
00092         SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00093         if (newSpeed != 0) {
00094             if (myPosition > oldPos) {
00095                 entryTime += (myPosition - oldPos) / newSpeed;
00096             }
00097         }
00098         enterDetectorByMove(veh, entryTime);
00099     }
00100     if (newPos - veh.getVehicleType().getLengthWithGap() > myPosition && oldPos - veh.getVehicleType().getLengthWithGap() <= myPosition) {
00101         // vehicle passed the detector
00102         SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00103         leaveTime += (myPosition - oldPos + veh.getVehicleType().getLengthWithGap()) / newSpeed;
00104         leaveDetectorByMove(veh, leaveTime);
00105         return false;
00106     }
00107     // vehicle stays on the detector
00108     return true;
00109 }
00110 
00111 
00112 bool
00113 MSInductLoop::notifyLeave(SUMOVehicle& veh, SUMOReal /*lastPos*/, MSMoveReminder::Notification reason) {
00114     if (reason != MSMoveReminder::NOTIFICATION_JUNCTION) {
00115         // vehicle is on detector during lane change or arrival, or ...
00116         leaveDetectorByLaneChange(veh);
00117         return false;
00118     }
00119     return true;
00120 }
00121 
00122 
00123 bool
00124 MSInductLoop::notifyEnter(SUMOVehicle& veh, MSMoveReminder::Notification) {
00125     if (veh.getPositionOnLane() - veh.getVehicleType().getLengthWithGap() > myPosition) {
00126         // vehicle-front is beyond detector. Ignore
00127         return false;
00128     }
00129     // vehicle is in front of detector
00130     return true;
00131 }
00132 
00133 
00134 SUMOReal
00135 MSInductLoop::getCurrentSpeed() const {
00136     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
00137     return d.size() != 0
00138            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
00139            : -1;
00140 }
00141 
00142 
00143 SUMOReal
00144 MSInductLoop::getCurrentLength() const {
00145     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
00146     return d.size() != 0
00147            ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
00148            : -1;
00149 }
00150 
00151 
00152 SUMOReal
00153 MSInductLoop::getCurrentOccupancy() const {
00154     SUMOTime tbeg = MSNet::getInstance()->getCurrentTimeStep() - DELTA_T;
00155     std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
00156     if (d.size() == 0) {
00157         return -1;
00158     }
00159     SUMOReal occupancy = 0;
00160     for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
00161         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
00162         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
00163         occupancy += timeOnDetDuringInterval;
00164     }
00165     return occupancy / TS * (SUMOReal) 100.;
00166 }
00167 
00168 
00169 unsigned int
00170 MSInductLoop::getCurrentPassedNumber() const {
00171     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
00172     return (unsigned int) d.size();
00173 }
00174 
00175 
00176 std::vector<std::string>
00177 MSInductLoop::getCurrentVehicleIDs() const {
00178     std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
00179     std::vector<std::string> ret;
00180     for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
00181         ret.push_back((*i).idM);
00182     }
00183     return ret;
00184 }
00185 
00186 
00187 SUMOReal
00188 MSInductLoop::getTimestepsSinceLastDetection() const {
00189     if (myVehiclesOnDet.size() != 0) {
00190         // detector is occupied
00191         return 0;
00192     }
00193     return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
00194 }
00195 
00196 
00197 void
00198 MSInductLoop::writeXMLDetectorProlog(OutputDevice& dev) const {
00199     dev.writeXMLHeader("detector");
00200 }
00201 
00202 
00203 void
00204 MSInductLoop::writeXMLOutput(OutputDevice& dev,
00205                              SUMOTime startTime, SUMOTime stopTime) {
00206     writeTypedXMLOutput(dev, startTime, stopTime, "", myVehicleDataCont, myVehiclesOnDet);
00207     if (mySplitByType) {
00208         dev << ">\n";
00209         std::map<std::string, std::pair<VehicleDataCont, VehicleMap> > types;
00210         // collect / divide
00211         for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
00212             if (types.find((*i).typeIDM) == types.end()) {
00213                 types[(*i).typeIDM] = make_pair(VehicleDataCont(), VehicleMap());
00214             }
00215             types[(*i).typeIDM].first.push_back(*i);
00216         }
00217         for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
00218             const std::string& type = (*i).first->getVehicleType().getID();
00219             if (types.find(type) == types.end()) {
00220                 types[type] = make_pair(VehicleDataCont(), VehicleMap());
00221             }
00222             types[type].second[(*i).first] = (*i).second;
00223         }
00224         // write
00225         for (std::map<std::string, std::pair<VehicleDataCont, VehicleMap> >::const_iterator i = types.begin(); i != types.end(); ++i) {
00226             writeTypedXMLOutput(dev, startTime, stopTime, (*i).first, (*i).second.first, (*i).second.second);
00227             dev << "/>\n";
00228         }
00229         dev << "   </interval>\n";
00230     } else {
00231         dev << "/>\n";
00232     }
00233     reset();
00234 }
00235 
00236 void
00237 MSInductLoop::writeTypedXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime,
00238                                   const std::string& type, const VehicleDataCont& vdc, const VehicleMap& vm) {
00239     SUMOReal t(STEPS2TIME(stopTime - startTime));
00240     unsigned nVehCrossed = (unsigned) vdc.size();
00241     if (type == "") {
00242         nVehCrossed += myDismissedVehicleNumber;
00243     }
00244     SUMOReal flow = ((SUMOReal) vdc.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
00245     SUMOReal occupancy = 0;
00246     for (std::deque< VehicleData >::const_iterator i = vdc.begin(); i != vdc.end(); ++i) {
00247         SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
00248         timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
00249         occupancy += timeOnDetDuringInterval;
00250     }
00251     for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = vm.begin(); i != vm.end(); ++i) {
00252         SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
00253         occupancy += timeOnDetDuringInterval;
00254     }
00255     occupancy = occupancy / t * (SUMOReal) 100.;
00256     SUMOReal meanSpeed = vdc.size() != 0
00257                          ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) vdc.size()
00258                          : -1;
00259     SUMOReal meanLength = vdc.size() != 0
00260                           ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) vdc.size()
00261                           : -1;
00262     if (type != "") {
00263         dev << "      <typedInterval type=\"" + type + "\" ";
00264     } else {
00265         dev << "   <interval ";
00266     }
00267     dev << "begin=\"" << time2string(startTime) << "\" end=\"" <<
00268         time2string(stopTime) << "\" " << "id=\"" << StringUtils::escapeXML(getID()) << "\" ";
00269     dev << "nVehContrib=\"" << vdc.size() << "\" flow=\"" << flow <<
00270         "\" occupancy=\"" << occupancy << "\" speed=\"" << meanSpeed <<
00271         "\" length=\"" << meanLength <<
00272         "\" nVehEntered=\"" << nVehCrossed << "\"";
00273 }
00274 
00275 
00276 void
00277 MSInductLoop::enterDetectorByMove(SUMOVehicle& veh,
00278                                   SUMOReal entryTimestep) {
00279     myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
00280 }
00281 
00282 
00283 void
00284 MSInductLoop::leaveDetectorByMove(SUMOVehicle& veh,
00285                                   SUMOReal leaveTimestep) {
00286     VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
00287     if (it != myVehiclesOnDet.end()) {
00288         SUMOReal entryTimestep = it->second;
00289         myVehiclesOnDet.erase(it);
00290         assert(entryTimestep < leaveTimestep);
00291         myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLengthWithGap(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
00292         myLastOccupancy = leaveTimestep - entryTimestep;
00293     }
00294     myLastLeaveTime = leaveTimestep;
00295 }
00296 
00297 
00298 void
00299 MSInductLoop::leaveDetectorByLaneChange(SUMOVehicle& veh) {
00300     // Discard entry data
00301     myVehiclesOnDet.erase(&veh);
00302     myDismissedVehicleNumber++;
00303 }
00304 
00305 
00306 std::vector<MSInductLoop::VehicleData>
00307 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS) const {
00308     SUMOReal t = STEPS2TIME(tMS);
00309     std::vector<VehicleData> ret;
00310     for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
00311         if ((*i).leaveTimeM >= t) {
00312             ret.push_back(*i);
00313         }
00314     }
00315     for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
00316         if ((*i).leaveTimeM >= t) {
00317             ret.push_back(*i);
00318         }
00319     }
00320     SUMOTime ct = MSNet::getInstance()->getCurrentTimeStep();
00321     for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
00322         SUMOVehicle* v = (*i).first;
00323         VehicleData d(v->getID(), v->getVehicleType().getLengthWithGap(), (*i).second, STEPS2TIME(ct), v->getVehicleType().getID());
00324         d.speedM = v->getSpeed();
00325         ret.push_back(d);
00326     }
00327     return ret;
00328 }
00329 
00330 
00331 /****************************************************************************/
00332 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines