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 <string>
00031 #include <iostream>
00032 #include <microsim/MSNet.h>
00033 #include <microsim/output/MSInductLoop.h>
00034 #include <microsim/output/MSE2Collector.h>
00035 #include <microsim/output/MS_E2_ZS_CollectorOverLanes.h>
00036 #include <microsim/output/MSVTypeProbe.h>
00037 #include <microsim/output/MSRouteProbe.h>
00038 #include <microsim/output/MSMeanData_Net.h>
00039 #include <microsim/output/MSMeanData_HBEFA.h>
00040 #include <microsim/output/MSMeanData_Harmonoise.h>
00041 #include <microsim/MSGlobals.h>
00042 #include <microsim/actions/Command_SaveTLCoupledDet.h>
00043 #include <microsim/actions/Command_SaveTLCoupledLaneDet.h>
00044 #include <utils/common/UtilExceptions.h>
00045 #include <utils/common/FileHelpers.h>
00046 #include <utils/common/StringUtils.h>
00047 #include <utils/common/StringTokenizer.h>
00048 #include <utils/common/TplConvert.h>
00049 #include "NLDetectorBuilder.h"
00050 #include <microsim/output/MSDetectorControl.h>
00051
00052 #ifdef _MESSAGES
00053 #include <microsim/output/MSMsgInductLoop.h>
00054 #endif
00055
00056 #ifdef HAVE_MESOSIM
00057 #include <mesosim/MEInductLoop.h>
00058 #include <mesosim/MELoop.h>
00059 #endif
00060
00061 #ifdef CHECK_MEMORY_LEAKS
00062 #include <foreign/nvwa/debug_new.h>
00063 #endif // CHECK_MEMORY_LEAKS
00064
00065
00066
00067
00068
00069
00070
00071
00072 NLDetectorBuilder::E3DetectorDefinition::E3DetectorDefinition(const std::string &id,
00073 OutputDevice& device, MetersPerSecond haltingSpeedThreshold,
00074 SUMOTime haltingTimeThreshold, int splInterval) throw()
00075 : myID(id), myDevice(device),
00076 myHaltingSpeedThreshold(haltingSpeedThreshold),
00077 myHaltingTimeThreshold(haltingTimeThreshold),
00078 mySampleInterval(splInterval) {}
00079
00080
00081 NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() throw() {}
00082
00083
00084 #ifdef _MESSAGES
00085 void
00086 NLDetectorBuilder::buildMsgDetector(const std::string &id,
00087 const std::string &lane, SUMOReal pos, int splInterval,
00088 const std::string &msg,
00089 OutputDevice& device, bool friendlyPos) throw(InvalidArgument) {
00090 if (splInterval<0) {
00091 throw InvalidArgument("Negative sampling frequency (in e4-detector '" + id + "').");
00092 }
00093 if (splInterval==0) {
00094 throw InvalidArgument("Sampling frequency must not be zero (in e4-detector '" + id + "').");
00095 }
00096 if (msg == "") {
00097 throw InvalidArgument("No Message given (in e4-detector '" + id + "').");
00098 }
00099 MSLane *clane = getLaneChecking(lane, id);
00100 if (pos<0) {
00101 pos = clane->getLength() + pos;
00102 }
00103 pos = getPositionChecking(pos, clane, friendlyPos, id);
00104 MSMsgInductLoop *msgloop = createMsgInductLoop(id, msg, clane, pos);
00105 myNet.getDetectorControl().add(msgloop, device, splInterval);
00106 }
00107 #endif
00108
00109
00110
00111
00112
00113 NLDetectorBuilder::NLDetectorBuilder(MSNet &net) throw()
00114 : myNet(net), myE3Definition(0) {}
00115
00116
00117 NLDetectorBuilder::~NLDetectorBuilder() throw() {}
00118
00119
00120 void
00121 NLDetectorBuilder::buildInductLoop(const std::string &id,
00122 const std::string &lane, SUMOReal pos, int splInterval,
00123 OutputDevice& device, bool friendlyPos) throw(InvalidArgument) {
00124 if (splInterval<0) {
00125 throw InvalidArgument("Negative sampling frequency (in e1-detector '" + id + "').");
00126 }
00127 if (splInterval==0) {
00128 throw InvalidArgument("Sampling frequency must not be zero (in e1-detector '" + id + "').");
00129 }
00130
00131 MSLane *clane = getLaneChecking(lane, id);
00132 if (pos<0) {
00133 pos = clane->getLength() + pos;
00134 }
00135 #ifdef HAVE_MESOSIM
00136 if (!MSGlobals::gUseMesoSim) {
00137 #endif
00138
00139 pos = getPositionChecking(pos, clane, friendlyPos, id);
00140
00141 MSInductLoop *loop = createInductLoop(id, clane, pos);
00142
00143 myNet.getDetectorControl().add(loop, device, splInterval);
00144 #ifdef HAVE_MESOSIM
00145 } else {
00146 if (pos<0) {
00147 pos = clane->getLength() + pos;
00148 }
00149 MESegment *s = MSGlobals::gMesoNet->getSegmentForEdge(clane->getEdge());
00150 MESegment *prev = s;
00151 SUMOReal cpos = 0;
00152 while (cpos+prev->getLength()<pos&&s!=0) {
00153 prev = s;
00154 cpos += s->getLength();
00155 s = s->getNextSegment();
00156 }
00157 SUMOReal rpos = pos-cpos;
00158 if (rpos>prev->getLength()||rpos<0) {
00159 if (friendlyPos) {
00160 rpos = prev->getLength() - (SUMOReal) 0.1;
00161 } else {
00162 throw InvalidArgument("The position of detector '" + id + "' lies beyond the lane's '" + lane + "' length.");
00163 }
00164 }
00165 MEInductLoop *loop =
00166 createMEInductLoop(id, prev, rpos);
00167 myNet.getDetectorControl().add(loop, device, splInterval);
00168 }
00169 #endif
00170 }
00171
00172
00173 void
00174 NLDetectorBuilder::buildE2Detector(const std::string &id,
00175 const std::string &lane, SUMOReal pos, SUMOReal length,
00176 bool cont, int splInterval,
00177 OutputDevice& device,
00178 SUMOTime haltingTimeThreshold,
00179 MetersPerSecond haltingSpeedThreshold,
00180 SUMOReal jamDistThreshold, bool friendlyPos) throw(InvalidArgument) {
00181 if (splInterval<0) {
00182 throw InvalidArgument("Negative sampling frequency (in e2-detector '" + id + "').");
00183 }
00184 if (splInterval==0) {
00185 throw InvalidArgument("Sampling frequency must not be zero (in e2-detector '" + id + "').");
00186 }
00187 MSLane *clane = getLaneChecking(lane, id);
00188
00189 MSDetectorFileOutput *det = 0;
00190 if (!cont) {
00191 convUncontE2PosLength(id, clane, pos, length, friendlyPos);
00192 det = buildSingleLaneE2Det(id, DU_USER_DEFINED,
00193 clane, pos, length,
00194 haltingTimeThreshold, haltingSpeedThreshold,
00195 jamDistThreshold);
00196 myNet.getDetectorControl().add(
00197 static_cast<MSE2Collector*>(det), device, splInterval);
00198 } else {
00199 convContE2PosLength(id, clane, pos, length, friendlyPos);
00200 det = buildMultiLaneE2Det(id, DU_USER_DEFINED,
00201 clane, pos, length,
00202 haltingTimeThreshold, haltingSpeedThreshold,
00203 jamDistThreshold);
00204 myNet.getDetectorControl().add(
00205 static_cast<MS_E2_ZS_CollectorOverLanes*>(det), device, splInterval);
00206 }
00207 }
00208
00209
00210 void
00211 NLDetectorBuilder::buildE2Detector(const std::string &id,
00212 const std::string &lane, SUMOReal pos, SUMOReal length,
00213 bool cont,
00214 MSTLLogicControl::TLSLogicVariants &tlls,
00215 OutputDevice& device,
00216 SUMOTime haltingTimeThreshold,
00217 MetersPerSecond haltingSpeedThreshold,
00218 SUMOReal jamDistThreshold, bool friendlyPos) throw(InvalidArgument) {
00219 if (tlls.getActive()==0) {
00220 throw InvalidArgument("The detector '" + id + "' refers to the unknown lsa.");
00221 }
00222 MSLane *clane = getLaneChecking(lane, id);
00223
00224 MSDetectorFileOutput *det = 0;
00225 if (!cont) {
00226 convUncontE2PosLength(id, clane, pos, length, friendlyPos);
00227 det = buildSingleLaneE2Det(id, DU_USER_DEFINED,
00228 clane, pos, length,
00229 haltingTimeThreshold, haltingSpeedThreshold,
00230 jamDistThreshold);
00231 myNet.getDetectorControl().add(
00232 static_cast<MSE2Collector*>(det));
00233 } else {
00234 convContE2PosLength(id, clane, pos, length, friendlyPos);
00235 det = buildMultiLaneE2Det(id, DU_USER_DEFINED,
00236 clane, pos, length,
00237 haltingTimeThreshold, haltingSpeedThreshold,
00238 jamDistThreshold);
00239 myNet.getDetectorControl().add(
00240 static_cast<MS_E2_ZS_CollectorOverLanes*>(det));
00241 }
00242
00243 new Command_SaveTLCoupledDet(tlls, det,
00244 myNet.getCurrentTimeStep(), device);
00245 }
00246
00247
00248 void
00249 NLDetectorBuilder::buildE2Detector(const std::string &id,
00250 const std::string &lane, SUMOReal pos, SUMOReal length,
00251 bool cont,
00252 MSTLLogicControl::TLSLogicVariants &tlls,
00253 const std::string &tolane,
00254 OutputDevice& device,
00255 SUMOTime haltingTimeThreshold,
00256 MetersPerSecond haltingSpeedThreshold,
00257 SUMOReal jamDistThreshold, bool friendlyPos) throw(InvalidArgument) {
00258 if (tlls.getActive()==0) {
00259 throw InvalidArgument("The detector '" + id + "' refers to the unknown lsa.");
00260 }
00261 MSLane *clane = getLaneChecking(lane, id);
00262 MSLane *ctoLane = getLaneChecking(tolane, id);
00263 MSLink *link = MSLinkContHelper::getConnectingLink(*clane, *ctoLane);
00264 if (link==0) {
00265 throw InvalidArgument(
00266 "The detector output can not be build as no connection between lanes '"
00267 + lane + "' and '" + tolane + "' exists.");
00268 }
00269 if (pos<0) {
00270 pos = -pos;
00271 }
00272
00273 MSDetectorFileOutput *det = 0;
00274 if (!cont) {
00275 convUncontE2PosLength(id, clane, pos, length, friendlyPos);
00276 det = buildSingleLaneE2Det(id, DU_USER_DEFINED,
00277 clane, pos, length,
00278 haltingTimeThreshold, haltingSpeedThreshold,
00279 jamDistThreshold);
00280 myNet.getDetectorControl().add(static_cast<MSE2Collector*>(det));
00281 } else {
00282 convContE2PosLength(id, clane, pos, length, friendlyPos);
00283 det = buildMultiLaneE2Det(id, DU_USER_DEFINED,
00284 clane, pos, length,
00285 haltingTimeThreshold, haltingSpeedThreshold,
00286 jamDistThreshold);
00287 myNet.getDetectorControl().add(static_cast<MS_E2_ZS_CollectorOverLanes*>(det));
00288 }
00289
00290 new Command_SaveTLCoupledLaneDet(tlls, det, myNet.getCurrentTimeStep(), device, link);
00291 }
00292
00293
00294 void
00295 NLDetectorBuilder::convUncontE2PosLength(const std::string &id, MSLane *clane,
00296 SUMOReal &pos, SUMOReal &length,
00297 bool friendlyPos) throw(InvalidArgument) {
00298
00299 pos = getPositionChecking(pos, clane, friendlyPos, id);
00300
00301 if (length<0) {
00302 length = clane->getLength() + length;
00303 }
00304 if (length+pos>clane->getLength()) {
00305 if (friendlyPos) {
00306 length = clane->getLength() - pos - (SUMOReal) 0.1;
00307 } else {
00308 throw InvalidArgument("The length of detector '" + id + "' lies beyond the lane's '" + clane->getID() + "' length.");
00309 }
00310 }
00311 if (length<0) {
00312 if (friendlyPos) {
00313 length = (SUMOReal) 0.1;
00314 } else {
00315 throw InvalidArgument("The length of detector '" + id + "' is almost 0.");
00316 }
00317 }
00318 }
00319
00320
00321 void
00322 NLDetectorBuilder::convContE2PosLength(const std::string &id, MSLane * clane,
00323 SUMOReal &pos, SUMOReal &length,
00324 bool friendlyPos) throw(InvalidArgument) {
00325
00326 pos = getPositionChecking(pos, clane, friendlyPos, id);
00327
00328 }
00329
00330
00331 void
00332 NLDetectorBuilder::beginE3Detector(const std::string &id,
00333 OutputDevice& device, int splInterval,
00334 MetersPerSecond haltingSpeedThreshold,
00335 SUMOTime haltingTimeThreshold) throw(InvalidArgument) {
00336 if (splInterval<0) {
00337 throw InvalidArgument("Negative sampling frequency (in e3-detector '" + id + "').");
00338 }
00339 if (splInterval==0) {
00340 throw InvalidArgument("Sampling frequency must not be zero (in e3-detector '" + id + "').");
00341 }
00342 myE3Definition = new E3DetectorDefinition(id, device,
00343 haltingSpeedThreshold, haltingTimeThreshold,
00344 splInterval);
00345 }
00346
00347
00348 void
00349 NLDetectorBuilder::addE3Entry(const std::string &lane,
00350 SUMOReal pos, bool friendlyPos) throw(InvalidArgument) {
00351 if (myE3Definition==0) {
00352 return;
00353 }
00354 MSLane *clane = getLaneChecking(lane, myE3Definition->myID);
00355
00356 pos = getPositionChecking(pos, clane, friendlyPos, myE3Definition->myID);
00357
00358 myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
00359 }
00360
00361
00362 void
00363 NLDetectorBuilder::addE3Exit(const std::string &lane,
00364 SUMOReal pos, bool friendlyPos) throw(InvalidArgument) {
00365 if (myE3Definition==0) {
00366 return;
00367 }
00368 MSLane *clane = getLaneChecking(lane, myE3Definition->myID);
00369
00370 pos = getPositionChecking(pos, clane, friendlyPos, myE3Definition->myID);
00371
00372 myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
00373 }
00374
00375
00376 std::string
00377 NLDetectorBuilder::getCurrentE3ID() const throw() {
00378 if (myE3Definition==0) {
00379 return "<unknown>";
00380 }
00381 return myE3Definition->myID;
00382 }
00383
00384
00385 void
00386 NLDetectorBuilder::endE3Detector() throw(InvalidArgument) {
00387 if (myE3Definition==0) {
00388 return;
00389 }
00390 MSE3Collector *det = createE3Detector(myE3Definition->myID,
00391 myE3Definition->myEntries, myE3Definition->myExits,
00392 myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold);
00393
00394 myNet.getDetectorControl().add(
00395 static_cast<MSE3Collector*>(det), myE3Definition->myDevice, myE3Definition->mySampleInterval);
00396
00397 delete myE3Definition;
00398 myE3Definition = 0;
00399 }
00400
00401
00402 void
00403 NLDetectorBuilder::buildVTypeProbe(const std::string &id,
00404 const std::string &vtype, SUMOTime frequency,
00405 OutputDevice& device) throw(InvalidArgument) {
00406 if (frequency<0) {
00407 throw InvalidArgument("Negative frequency (in vtypeprobe '" + id + "').");
00408 }
00409 if (frequency==0) {
00410 throw InvalidArgument("Frequency must not be zero (in vtypeprobe '" + id + "').");
00411 }
00412 new MSVTypeProbe(id, vtype, device, frequency);
00413 }
00414
00415
00416 void
00417 NLDetectorBuilder::buildRouteProbe(const std::string &id, const std::string &edge,
00418 SUMOTime frequency, SUMOTime begin,
00419 OutputDevice& device) throw(InvalidArgument) {
00420 if (frequency<=0) {
00421 throw InvalidArgument("Frequency must be larger than zero (in routeprobe '" + id + "').");
00422 }
00423 MSEdge *e = MSEdge::dictionary(edge);
00424 if (e==0) {
00425 throw InvalidArgument("The edge with the id '" + edge + "' is not known (in routeprobe '" + id + "').");
00426 }
00427 MSRouteProbe *probe = new MSRouteProbe(id, e, begin);
00428
00429 myNet.getDetectorControl().add(probe, device, frequency, begin);
00430 }
00431
00432
00433
00434 MSE2Collector *
00435 NLDetectorBuilder::buildSingleLaneE2Det(const std::string &id,
00436 DetectorUsage usage,
00437 MSLane *lane, SUMOReal pos, SUMOReal length,
00438 SUMOTime haltingTimeThreshold,
00439 MetersPerSecond haltingSpeedThreshold,
00440 SUMOReal jamDistThreshold) throw() {
00441 return createSingleLaneE2Detector(id, usage, lane, pos,
00442 length, haltingTimeThreshold, haltingSpeedThreshold,
00443 jamDistThreshold);
00444 }
00445
00446
00447 MS_E2_ZS_CollectorOverLanes *
00448 NLDetectorBuilder::buildMultiLaneE2Det(const std::string &id, DetectorUsage usage,
00449 MSLane *lane, SUMOReal pos, SUMOReal length,
00450 SUMOTime haltingTimeThreshold,
00451 MetersPerSecond haltingSpeedThreshold,
00452 SUMOReal jamDistThreshold) throw() {
00453 MS_E2_ZS_CollectorOverLanes *ret = createMultiLaneE2Detector(id, usage,
00454 lane, pos, haltingTimeThreshold, haltingSpeedThreshold,
00455 jamDistThreshold);
00456 ret->init(lane, length);
00457 return ret;
00458 }
00459
00460 #ifdef _MESSAGES
00461 MSMsgInductLoop *
00462 NLDetectorBuilder::createMsgInductLoop(const std::string &id, const std::string &msg,
00463 MSLane *lane, SUMOReal pos) throw() {
00464 return new MSMsgInductLoop(id, msg, lane, pos);
00465 }
00466 #endif
00467
00468
00469 MSInductLoop *
00470 NLDetectorBuilder::createInductLoop(const std::string &id,
00471 MSLane *lane, SUMOReal pos) throw() {
00472 return new MSInductLoop(id, lane, pos);
00473 }
00474
00475
00476 #ifdef HAVE_MESOSIM
00477 MEInductLoop *
00478 NLDetectorBuilder::createMEInductLoop(const std::string &id,
00479 MESegment *s, SUMOReal pos) throw() {
00480 return new MEInductLoop(id, s, pos);
00481 }
00482 #endif
00483
00484
00485 MSE2Collector *
00486 NLDetectorBuilder::createSingleLaneE2Detector(const std::string &id,
00487 DetectorUsage usage, MSLane *lane, SUMOReal pos, SUMOReal length,
00488 SUMOTime haltingTimeThreshold,
00489 MetersPerSecond haltingSpeedThreshold,
00490 SUMOReal jamDistThreshold) throw() {
00491 return new MSE2Collector(id, usage, lane, pos, length,
00492 haltingTimeThreshold, haltingSpeedThreshold,
00493 jamDistThreshold);
00494
00495 }
00496
00497
00498 MS_E2_ZS_CollectorOverLanes *
00499 NLDetectorBuilder::createMultiLaneE2Detector(const std::string &id,
00500 DetectorUsage usage, MSLane *lane, SUMOReal pos,
00501 SUMOTime haltingTimeThreshold,
00502 MetersPerSecond haltingSpeedThreshold,
00503 SUMOReal jamDistThreshold) throw() {
00504 return new MS_E2_ZS_CollectorOverLanes(id, usage, lane, pos,
00505 haltingTimeThreshold, haltingSpeedThreshold,
00506 jamDistThreshold);
00507 }
00508
00509
00510 MSE3Collector *
00511 NLDetectorBuilder::createE3Detector(const std::string &id,
00512 const CrossSectionVector &entries,
00513 const CrossSectionVector &exits,
00514 MetersPerSecond haltingSpeedThreshold,
00515 SUMOTime haltingTimeThreshold) throw() {
00516 return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold);
00517 }
00518
00519
00520 MSLane *
00521 NLDetectorBuilder::getLaneChecking(const std::string &id,
00522 const std::string &detid) throw(InvalidArgument) {
00523
00524 MSLane *clane = MSLane::dictionary(id);
00525 if (clane==0) {
00526 throw InvalidArgument("The lane with the id '" + id + "' is not known (while building detector '" + detid + "').");
00527 }
00528 return clane;
00529 }
00530
00531
00532 SUMOReal
00533 NLDetectorBuilder::getPositionChecking(SUMOReal pos, MSLane *lane, bool friendlyPos,
00534 const std::string &detid) throw(InvalidArgument) {
00535
00536 if (pos<0) {
00537 pos = lane->getLength() + pos;
00538 }
00539
00540 if (pos>lane->getLength()) {
00541 if (friendlyPos) {
00542 pos = lane->getLength() - (SUMOReal) 0.1;
00543 } else {
00544 throw InvalidArgument("The position of detector '" + detid + "' lies beyond the lane's '" + lane->getID() + "' length.");
00545 }
00546 }
00547 if (pos<0) {
00548 if (friendlyPos) {
00549 pos = (SUMOReal) 0.1;
00550 } else {
00551 throw InvalidArgument("The position of detector '" + detid + "' lies beyond the lane's '" + lane->getID() + "' length.");
00552 }
00553 }
00554 return pos;
00555 }
00556
00557
00558 void
00559 NLDetectorBuilder::createEdgeLaneMeanData(const std::string &id, SUMOTime frequency,
00560 SUMOTime begin, SUMOTime end, const std::string &type,
00561 const bool useLanes, const bool withEmpty, const bool withInternal, const bool trackVehicles,
00562 const SUMOReal maxTravelTime, const SUMOReal minSamples,
00563 const SUMOReal haltSpeed, const std::string &vTypes,
00564 OutputDevice& device) throw(InvalidArgument) {
00565 if (begin < 0) {
00566 throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
00567 }
00568 if (end < 0) {
00569 end = SUMOTime_MAX;
00570 }
00571 if (end <= begin) {
00572 throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
00573 }
00574 std::set<std::string> vt;
00575 StringTokenizer st(vTypes);
00576 while (st.hasNext()) {
00577 vt.insert(st.next());
00578 }
00579 MSMeanData *det = 0;
00580 if (type==""||type=="performance"||type=="traffic") {
00581 det = new MSMeanData_Net(id, begin, end, useLanes, withEmpty, trackVehicles,
00582 maxTravelTime, minSamples, haltSpeed, vt);
00583 } else if (type=="hbefa") {
00584 det = new MSMeanData_HBEFA(id, begin, end, useLanes, withEmpty, trackVehicles,
00585 maxTravelTime, minSamples, vt);
00586 } else if (type=="harmonoise") {
00587 det = new MSMeanData_Harmonoise(id, begin, end, useLanes, withEmpty, trackVehicles,
00588 maxTravelTime, minSamples, vt);
00589 } else {
00590 throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
00591 }
00592 if (det!=0) {
00593 det->init(MSNet::getInstance()->getEdgeControl().getEdges(), withInternal);
00594 if (frequency < 0) {
00595 frequency = end - begin;
00596 }
00597 MSNet::getInstance()->getDetectorControl().addDetectorAndInterval(det, &device, frequency);
00598 }
00599 }
00600
00601
00602