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