|
SUMO - Simulation of Urban MObility
|
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