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