00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00050
00051 MSInductLoop::MSInductLoop(const std::string& id,
00052 MSLane * const lane,
00053 SUMOReal positionInMeters) throw()
00054 : MSMoveReminder(lane), Named(id), myCurrentVehicle(0),
00055 myPosition(positionInMeters), myLastLeaveTime(0),
00056 myVehiclesOnDet(), myVehicleDataCont() {
00057 assert(myPosition >= 0 && myPosition <= myLane->getLength());
00058 reset();
00059 myLastLeaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00060 }
00061
00062
00063 MSInductLoop::~MSInductLoop() throw() {
00064 if (myCurrentVehicle!=0) {
00065 myCurrentVehicle->quitRemindedLeft(this);
00066 }
00067 myCurrentVehicle = 0;
00068 }
00069
00070
00071 void
00072 MSInductLoop::reset() throw() {
00073 myDismissedVehicleNumber = 0;
00074 myLastVehicleDataCont = myVehicleDataCont;
00075 myVehicleDataCont.clear();
00076 }
00077
00078
00079 bool
00080 MSInductLoop::isStillActive(MSVehicle& veh, SUMOReal oldPos,
00081 SUMOReal newPos, SUMOReal newSpeed) throw() {
00082 if (newPos < myPosition) {
00083
00084 return true;
00085 }
00086 if (myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end()) {
00087
00088 SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00089 if (newSpeed!=0) {
00090 entryTime += (myPosition - oldPos) / newSpeed;
00091 }
00092 if (newPos - veh.getVehicleType().getLength() > myPosition) {
00093
00094 SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00095 leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
00096 enterDetectorByMove(veh, entryTime);
00097 leaveDetectorByMove(veh, leaveTime);
00098 return false;
00099 }
00100
00101 enterDetectorByMove(veh, entryTime);
00102 return true;
00103 } else {
00104
00105 if (newPos - veh.getVehicleType().getLength() >= myPosition) {
00106
00107 SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
00108 leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
00109 leaveDetectorByMove(veh, leaveTime);
00110 return false;
00111 }
00112
00113 return true;
00114 }
00115 }
00116
00117
00118 void
00119 MSInductLoop::notifyLeave(MSVehicle& veh, bool isArrival, bool isLaneChange) throw() {
00120 if (veh.getPositionOnLane() > myPosition && veh.getPositionOnLane() - veh.getVehicleType().getLength() <= myPosition) {
00121
00122 leaveDetectorByLaneChange(veh);
00123 }
00124 }
00125
00126
00127 bool
00128 MSInductLoop::notifyEnter(MSVehicle& veh, bool, bool) throw() {
00129 if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myPosition) {
00130
00131 return false;
00132 }
00133
00134 return true;
00135 }
00136
00137
00138 SUMOReal
00139 MSInductLoop::getCurrentSpeed() const throw() {
00140 std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00141 return d.size()!=0
00142 ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
00143 : -1;
00144 }
00145
00146
00147 SUMOReal
00148 MSInductLoop::getCurrentLength() const throw() {
00149 std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00150 return d.size()!=0
00151 ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
00152 : -1;
00153 }
00154
00155
00156 SUMOReal
00157 MSInductLoop::getCurrentOccupancy() const throw() {
00158 SUMOTime tbeg = MSNet::getInstance()->getCurrentTimeStep()-DELTA_T;
00159 std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
00160 if(d.size()==0) {
00161 return -1;
00162 }
00163 SUMOReal occupancy = 0;
00164 for(std::vector< VehicleData >::const_iterator i=d.begin(); i!=d.end(); ++i) {
00165 SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
00166 timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
00167 occupancy += timeOnDetDuringInterval;
00168 }
00169 return occupancy / TS * (SUMOReal) 100.;
00170 }
00171
00172
00173 SUMOReal
00174 MSInductLoop::getCurrentPassedNumber() const throw() {
00175 std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00176 return (SUMOReal) d.size();
00177 }
00178
00179
00180 std::vector<std::string>
00181 MSInductLoop::getCurrentVehicleIDs() const throw() {
00182 std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T);
00183 std::vector<std::string> ret;
00184 for (std::vector<VehicleData>::iterator i=d.begin(); i!=d.end(); ++i) {
00185 ret.push_back((*i).idM);
00186 }
00187 return ret;
00188 }
00189
00190
00191 unsigned
00192 MSInductLoop::getNVehContributed() const throw() {
00193 return (unsigned int) collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep()-DELTA_T).size();
00194 }
00195
00196
00197 SUMOReal
00198 MSInductLoop::getTimestepsSinceLastDetection() const throw() {
00199 if (myVehiclesOnDet.size() != 0) {
00200
00201 return 0;
00202 }
00203 return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
00204 }
00205
00206
00207 void
00208 MSInductLoop::writeXMLDetectorProlog(OutputDevice &dev) const throw(IOError) {
00209 dev.writeXMLHeader("detector");
00210 }
00211
00212
00213 void
00214 MSInductLoop::writeXMLOutput(OutputDevice &dev,
00215 SUMOTime startTime, SUMOTime stopTime) throw(IOError) {
00216 SUMOReal t(STEPS2TIME(stopTime-startTime));
00217 unsigned nVehCrossed = (unsigned) myVehicleDataCont.size() + myDismissedVehicleNumber;
00218 SUMOReal flow = ((SUMOReal) myVehicleDataCont.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
00219 SUMOReal occupancy = 0;
00220 for(std::deque< VehicleData >::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00221 SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
00222 timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
00223 occupancy += timeOnDetDuringInterval;
00224 }
00225 for(std::map< MSVehicle*, SUMOReal >::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00226 SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
00227 occupancy += timeOnDetDuringInterval;
00228 }
00229 occupancy = occupancy / t * (SUMOReal) 100.;
00230 SUMOReal meanSpeed = myVehicleDataCont.size()!=0
00231 ? accumulate(myVehicleDataCont.begin(), myVehicleDataCont.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) myVehicleDataCont.size()
00232 : -1;
00233 SUMOReal meanLength = myVehicleDataCont.size()!=0
00234 ? accumulate(myVehicleDataCont.begin(), myVehicleDataCont.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) myVehicleDataCont.size()
00235 : -1;
00236 dev<<" <interval begin=\""<<time2string(startTime)<<"\" end=\""<<
00237 time2string(stopTime)<<"\" "<<"id=\""<<StringUtils::escapeXML(getID())<<"\" ";
00238 dev<<"nVehContrib=\""<<myVehicleDataCont.size()<<"\" flow=\""<<flow<<
00239 "\" occupancy=\""<<occupancy<<"\" speed=\""<<meanSpeed<<
00240 "\" length=\""<<meanLength<<
00241 "\" nVehEntered=\""<<nVehCrossed<<"\"/>\n";
00242 reset();
00243 }
00244
00245
00246 void
00247 MSInductLoop::enterDetectorByMove(MSVehicle& veh,
00248 SUMOReal entryTimestep) throw() {
00249 myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
00250 veh.quitRemindedEntered(this);
00251 if (myCurrentVehicle!=0&&myCurrentVehicle!=&veh) {
00252
00253
00254
00255
00256 MsgHandler::getWarningInstance()->inform("Collision on e1-detector '" + getID() + "'.\n Vehicle '" + myCurrentVehicle->getID() +
00257 "' was aready at detector as '" + veh.getID() + "' entered.");
00258 leaveDetectorByMove(*myCurrentVehicle, entryTimestep);
00259 }
00260 myCurrentVehicle = &veh;
00261 }
00262
00263
00264 void
00265 MSInductLoop::leaveDetectorByMove(MSVehicle& veh,
00266 SUMOReal leaveTimestep) throw() {
00267 VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
00268 assert(it != myVehiclesOnDet.end());
00269 SUMOReal entryTimestep = it->second;
00270 myVehiclesOnDet.erase(it);
00271 assert(entryTimestep < leaveTimestep);
00272 myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep));
00273 myLastOccupancy = leaveTimestep - entryTimestep;
00274 myLastLeaveTime = leaveTimestep;
00275 myCurrentVehicle = 0;
00276 veh.quitRemindedLeft(this);
00277 }
00278
00279
00280 void
00281 MSInductLoop::leaveDetectorByLaneChange(MSVehicle& veh) throw() {
00282
00283 myVehiclesOnDet.erase(&veh);
00284 myDismissedVehicleNumber++;
00285 myCurrentVehicle = 0;
00286 veh.quitRemindedLeft(this);
00287 }
00288
00289
00290 void
00291 MSInductLoop::removeOnTripEnd(MSVehicle *veh) throw() {
00292 myCurrentVehicle = 0;
00293 myVehiclesOnDet.erase(veh);
00294 }
00295
00296
00297 std::vector<MSInductLoop::VehicleData>
00298 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS) const throw() {
00299 SUMOReal t = STEPS2TIME(tMS);
00300 std::vector<VehicleData> ret;
00301 for (VehicleDataCont::const_iterator i=myVehicleDataCont.begin(); i!=myVehicleDataCont.end(); ++i) {
00302 if ((*i).leaveTimeM>=t) {
00303 ret.push_back(*i);
00304 }
00305 }
00306 for (VehicleDataCont::const_iterator i=myLastVehicleDataCont.begin(); i!=myLastVehicleDataCont.end(); ++i) {
00307 if ((*i).leaveTimeM>=t) {
00308 ret.push_back(*i);
00309 }
00310 }
00311 SUMOTime ct = MSNet::getInstance()->getCurrentTimeStep();
00312 for (VehicleMap::const_iterator i=myVehiclesOnDet.begin(); i!=myVehiclesOnDet.end(); ++i) {
00313 MSVehicle *v = (*i).first;
00314 VehicleData d(v->getID(), v->getVehicleType().getLength(), (*i).second, STEPS2TIME(ct));
00315 d.speedM = v->getSpeed();
00316 ret.push_back(d);
00317 }
00318 return ret;
00319 }
00320
00321
00322
00323