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 <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