SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NLDetectorBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // Builds detectors for microsim
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
15 // Copyright (C) 2002-2014 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include <string>
37 #include <iostream>
38 #include <microsim/MSNet.h>
39 #include <microsim/MSLane.h>
40 #include <microsim/MSEdge.h>
51 #include <microsim/MSGlobals.h>
59 #include "NLDetectorBuilder.h"
61 
62 #ifdef HAVE_INTERNAL
63 #include <mesosim/MEInductLoop.h>
64 #include <mesosim/MELoop.h>
65 #include <mesosim/MESegment.h>
66 #endif
67 
68 #ifdef CHECK_MEMORY_LEAKS
69 #include <foreign/nvwa/debug_new.h>
70 #endif // CHECK_MEMORY_LEAKS
71 
72 
73 // ===========================================================================
74 // method definitions
75 // ===========================================================================
76 /* -------------------------------------------------------------------------
77  * NLDetectorBuilder::E3DetectorDefinition-methods
78  * ----------------------------------------------------------------------- */
80  const std::string& device, SUMOReal haltingSpeedThreshold,
81  SUMOTime haltingTimeThreshold, int splInterval)
82  : myID(id), myDevice(device),
83  myHaltingSpeedThreshold(haltingSpeedThreshold),
84  myHaltingTimeThreshold(haltingTimeThreshold),
85  mySampleInterval(splInterval) {}
86 
87 
89 
90 
91 /* -------------------------------------------------------------------------
92  * NLDetectorBuilder-methods
93  * ----------------------------------------------------------------------- */
95  : myNet(net), myE3Definition(0) {}
96 
97 
99 
100 
101 void
103  const std::string& lane, SUMOReal pos, int splInterval,
104  const std::string& device, bool friendlyPos, bool splitByType) {
105  checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
106  // get and check the lane
107  MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
108  if (!MSGlobals::gUseMesoSim) {
109  // get and check the position
110  pos = getPositionChecking(pos, clane, friendlyPos, id);
111  // build the loop
112  MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, splitByType);
113  // add the file output
114  myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
115  } else {
116 #ifdef HAVE_INTERNAL
117  if (pos < 0) {
118  pos = clane->getLength() + pos;
119  }
120  MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(clane->getEdge());
121  MESegment* prev = s;
122  SUMOReal cpos = 0;
123  while (cpos + prev->getLength() < pos && s != 0) {
124  prev = s;
125  cpos += s->getLength();
126  s = s->getNextSegment();
127  }
128  SUMOReal rpos = pos - cpos; //-prev->getLength();
129  if (rpos > prev->getLength() || rpos < 0) {
130  if (friendlyPos) {
131  rpos = prev->getLength() - (SUMOReal) 0.1;
132  } else {
133  throw InvalidArgument("The position of detector '" + id + "' lies beyond the lane's '" + lane + "' length.");
134  }
135  }
136  MEInductLoop* loop =
137  createMEInductLoop(id, prev, rpos);
138  myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
139 #endif
140  }
141 }
142 
143 
144 void
146  const std::string& lane, SUMOReal pos,
147  const std::string& device, bool friendlyPos) {
148  // get and check the lane
150  // get and check the position
151  pos = getPositionChecking(pos, clane, friendlyPos, id);
152  // build the loop
153  MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device);
154  // add the file output
156 }
157 
158 
159 void
161  const std::string& lane, SUMOReal pos, SUMOReal length,
162  bool cont, int splInterval,
163  const std::string& device,
164  SUMOTime haltingTimeThreshold,
165  SUMOReal haltingSpeedThreshold,
166  SUMOReal jamDistThreshold, bool friendlyPos) {
167  checkSampleInterval(splInterval, SUMO_TAG_E2DETECTOR, id);
168  MSLane* clane = getLaneChecking(lane, SUMO_TAG_E2DETECTOR, id);
169  // check whether the detector may lie over more than one lane
170  MSDetectorFileOutput* det = 0;
171  if (!cont) {
172  convUncontE2PosLength(id, clane, pos, length, friendlyPos);
173  det = buildSingleLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
174  myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, splInterval);
175  } else {
176  convContE2PosLength(id, clane, pos, length, friendlyPos);
177  det = buildMultiLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
178  myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, splInterval);
179  }
180 }
181 
182 
183 void
185  const std::string& lane, SUMOReal pos, SUMOReal length,
186  bool cont,
188  const std::string& device,
189  SUMOTime haltingTimeThreshold,
190  SUMOReal haltingSpeedThreshold,
191  SUMOReal jamDistThreshold, bool friendlyPos) {
192  if (tlls.getActive() == 0) {
193  throw InvalidArgument("The detector '" + id + "' refers to the unknown lsa.");
194  }
195  MSLane* clane = getLaneChecking(lane, SUMO_TAG_E2DETECTOR, id);
196  // check whether the detector may lie over more than one lane
197  MSDetectorFileOutput* det = 0;
198  if (!cont) {
199  convUncontE2PosLength(id, clane, pos, length, friendlyPos);
200  det = buildSingleLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
202  } else {
203  convContE2PosLength(id, clane, pos, length, friendlyPos);
204  det = buildMultiLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
206  }
207  // add the file output
209 }
210 
211 
212 void
214  const std::string& lane, SUMOReal pos, SUMOReal length,
215  bool cont,
217  const std::string& tolane,
218  const std::string& device,
219  SUMOTime haltingTimeThreshold,
220  SUMOReal haltingSpeedThreshold,
221  SUMOReal jamDistThreshold, bool friendlyPos) {
222  if (tlls.getActive() == 0) {
223  throw InvalidArgument("The detector '" + id + "' refers to the unknown lsa.");
224  }
225  MSLane* clane = getLaneChecking(lane, SUMO_TAG_E2DETECTOR, id);
226  MSLane* ctoLane = getLaneChecking(tolane, SUMO_TAG_E2DETECTOR, id);
227  MSLink* link = MSLinkContHelper::getConnectingLink(*clane, *ctoLane);
228  if (link == 0) {
229  throw InvalidArgument(
230  "The detector output can not be build as no connection between lanes '"
231  + lane + "' and '" + tolane + "' exists.");
232  }
233  if (pos < 0) {
234  pos = -pos;
235  }
236  // check whether the detector may lie over more than one lane
237  MSDetectorFileOutput* det = 0;
238  if (!cont) {
239  convUncontE2PosLength(id, clane, pos, length, friendlyPos);
240  det = buildSingleLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
242  } else {
243  convContE2PosLength(id, clane, pos, length, friendlyPos);
244  det = buildMultiLaneE2Det(id, DU_USER_DEFINED, clane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
246  }
247  // add the file output
249 }
250 
251 
252 void
253 NLDetectorBuilder::convUncontE2PosLength(const std::string& id, MSLane* clane,
254  SUMOReal& pos, SUMOReal& length,
255  bool friendlyPos) {
256  // get and check the position
257  pos = getPositionChecking(pos, clane, friendlyPos, id);
258  // check length
259  if (length < 0) {
260  length = clane->getLength() + length;
261  }
262  if (length + pos > clane->getLength()) {
263  if (friendlyPos) {
264  length = clane->getLength() - pos - (SUMOReal) 0.1;
265  } else {
266  throw InvalidArgument("The length of detector '" + id + "' lies beyond the lane's '" + clane->getID() + "' length.");
267  }
268  }
269  if (length < 0) {
270  if (friendlyPos) {
271  length = (SUMOReal) 0.1;
272  } else {
273  throw InvalidArgument("The length of detector '" + id + "' is almost 0.");
274  }
275  }
276 }
277 
278 
279 void
280 NLDetectorBuilder::convContE2PosLength(const std::string& id, MSLane* clane,
281  SUMOReal& pos, SUMOReal& /*length*/,
282  bool friendlyPos) {
283  // get and check the position
284  pos = getPositionChecking(pos, clane, friendlyPos, id);
285  // length will be kept as is
286 }
287 
288 
289 void
291  const std::string& device, int splInterval,
292  SUMOReal haltingSpeedThreshold,
293  SUMOTime haltingTimeThreshold) {
294  checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
295  myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval);
296 }
297 
298 
299 void
300 NLDetectorBuilder::addE3Entry(const std::string& lane,
301  SUMOReal pos, bool friendlyPos) {
302  if (myE3Definition == 0) {
303  return;
304  }
306  // get and check the position
307  pos = getPositionChecking(pos, clane, friendlyPos, myE3Definition->myID);
308  // build and save the entry
309  myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
310 }
311 
312 
313 void
314 NLDetectorBuilder::addE3Exit(const std::string& lane,
315  SUMOReal pos, bool friendlyPos) {
316  if (myE3Definition == 0) {
317  return;
318  }
320  // get and check the position
321  pos = getPositionChecking(pos, clane, friendlyPos, myE3Definition->myID);
322  // build and save the exit
323  myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
324 }
325 
326 
327 std::string
329  if (myE3Definition == 0) {
330  return "<unknown>";
331  }
332  return myE3Definition->myID;
333 }
334 
335 
336 void
338  if (myE3Definition == 0) {
339  return;
340  }
344  // add to net
346  // clean up
347  delete myE3Definition;
348  myE3Definition = 0;
349 }
350 
351 
352 void
354  const std::string& vtype, SUMOTime frequency,
355  const std::string& device) {
357  new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
358 }
359 
360 
361 void
362 NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
363  SUMOTime frequency, SUMOTime begin,
364  const std::string& device) {
367  MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency));
368  // add the file output
369  myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
370 }
371 
372 
373 // -------------------
376  DetectorUsage usage,
377  MSLane* lane, SUMOReal pos, SUMOReal length,
378  SUMOTime haltingTimeThreshold,
379  SUMOReal haltingSpeedThreshold,
380  SUMOReal jamDistThreshold) {
381  return createSingleLaneE2Detector(id, usage, lane, pos,
382  length, haltingTimeThreshold, haltingSpeedThreshold,
383  jamDistThreshold);
384 }
385 
386 
389  MSLane* lane, SUMOReal pos, SUMOReal length,
390  SUMOTime haltingTimeThreshold,
391  SUMOReal haltingSpeedThreshold,
392  SUMOReal jamDistThreshold) {
394  lane, pos, haltingTimeThreshold, haltingSpeedThreshold,
395  jamDistThreshold);
396  static_cast<MS_E2_ZS_CollectorOverLanes*>(ret)->init(lane, length);
397  return ret;
398 }
399 
400 
403  MSLane* lane, SUMOReal pos, bool splitByType) {
404  return new MSInductLoop(id, lane, pos, splitByType);
405 }
406 
407 
410  MSLane* lane, SUMOReal pos, const std::string& od) {
411  return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos);
412 }
413 
414 
415 #ifdef HAVE_INTERNAL
416 MEInductLoop*
417 NLDetectorBuilder::createMEInductLoop(const std::string& id,
418  MESegment* s, SUMOReal pos) {
419  return new MEInductLoop(id, s, pos);
420 }
421 #endif
422 
423 
426  DetectorUsage usage, MSLane* lane, SUMOReal pos, SUMOReal length,
427  SUMOTime haltingTimeThreshold, SUMOReal haltingSpeedThreshold, SUMOReal jamDistThreshold) {
428  return new MSE2Collector(id, usage, lane, pos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
429 }
430 
431 
434  DetectorUsage usage, MSLane* lane, SUMOReal pos,
435  SUMOTime haltingTimeThreshold, SUMOReal haltingSpeedThreshold, SUMOReal jamDistThreshold) {
436  return new MS_E2_ZS_CollectorOverLanes(id, usage, lane, pos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold);
437 }
438 
439 
442  const CrossSectionVector& entries,
443  const CrossSectionVector& exits,
444  SUMOReal haltingSpeedThreshold,
445  SUMOTime haltingTimeThreshold) {
446  return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold);
447 }
448 
449 
450 SUMOReal
452  const std::string& detid) {
453  // check whether it is given from the end
454  if (pos < 0) {
455  pos = lane->getLength() + pos;
456  }
457  // check whether it is on the lane
458  if (pos > lane->getLength()) {
459  if (friendlyPos) {
460  pos = lane->getLength() - (SUMOReal) 0.1;
461  } else {
462  throw InvalidArgument("The position of detector '" + detid + "' lies beyond the lane's '" + lane->getID() + "' length.");
463  }
464  }
465  if (pos < 0) {
466  if (friendlyPos) {
467  pos = (SUMOReal) 0.1;
468  } else {
469  throw InvalidArgument("The position of detector '" + detid + "' lies beyond the lane's '" + lane->getID() + "' length.");
470  }
471  }
472  return pos;
473 }
474 
475 
476 void
477 NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
478  SUMOTime begin, SUMOTime end, const std::string& type,
479  const bool useLanes, const bool withEmpty, const bool printDefaults,
480  const bool withInternal, const bool trackVehicles,
481  const SUMOReal maxTravelTime, const SUMOReal minSamples,
482  const SUMOReal haltSpeed, const std::string& vTypes,
483  const std::string& device) {
484  if (begin < 0) {
485  throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
486  }
487  if (end < 0) {
488  end = SUMOTime_MAX;
489  }
490  if (end <= begin) {
491  throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
492  }
493  std::set<std::string> vt;
494  StringTokenizer st(vTypes);
495  while (st.hasNext()) {
496  vt.insert(st.next());
497  }
498  MSMeanData* det = 0;
499  if (type == "" || type == "performance" || type == "traffic") {
500  det = new MSMeanData_Net(id, begin, end, useLanes, withEmpty,
501  printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, haltSpeed, vt);
502  } else if (type == "emissions" || type == "hbefa") {
503  if (type == "hbefa") {
504  WRITE_WARNING("The netstate type 'hbefa' is deprecated. Please use the type 'emissions' instead.");
505  }
506  det = new MSMeanData_Emissions(id, begin, end, useLanes, withEmpty,
507  printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vt);
508  } else if (type == "harmonoise") {
509  det = new MSMeanData_Harmonoise(id, begin, end, useLanes, withEmpty,
510  printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vt);
511  } else if (type == "amitran") {
512  det = new MSMeanData_Amitran(id, begin, end, useLanes, withEmpty,
513  printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, haltSpeed, vt);
514  } else {
515  throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
516  }
517  if (det != 0) {
518  if (frequency < 0) {
519  frequency = end - begin;
520  }
521  MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
522  }
523 }
524 
525 
526 
527 
528 // ------ Value checking/adapting methods ------
529 MSEdge*
530 NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
531  const std::string& detid) {
532  // get and check the lane
533  MSEdge* edge = MSEdge::dictionary(edgeID);
534  if (edge == 0) {
535  throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
536  }
537  return edge;
538 }
539 
540 
541 MSLane*
542 NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
543  const std::string& detid) {
544  // get and check the lane
545  MSLane* lane = MSLane::dictionary(laneID);
546  if (lane == 0) {
547  throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
548  }
549  return lane;
550 }
551 
552 
553 void
554 NLDetectorBuilder::checkSampleInterval(int splInterval, SumoXMLTag type, const std::string& id) {
555  if (splInterval < 0) {
556  throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
557  }
558  if (splInterval == 0) {
559  throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
560  }
561 }
562 
563 
564 /****************************************************************************/
565