SUMO - Simulation of Urban MObility
RODFDetector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2006-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
21 // Class representing a detector within the DFROUTER
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #include <config.h>
29 
30 #include <cassert>
31 #include "RODFDetector.h"
35 #include <utils/common/ToString.h>
36 #include <router/ROEdge.h>
37 #include "RODFEdge.h"
38 #include "RODFRouteDesc.h"
39 #include "RODFRouteCont.h"
40 #include "RODFDetectorFlow.h"
43 #include <utils/common/StdDefs.h>
45 #include <utils/geom/GeomHelper.h>
46 #include "RODFNet.h"
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 RODFDetector::RODFDetector(const std::string& id, const std::string& laneID,
56  double pos, const RODFDetectorType type)
57  : Named(id), myLaneID(laneID), myPosition(pos), myType(type), myRoutes(nullptr) {}
58 
59 
60 RODFDetector::RODFDetector(const std::string& id, const RODFDetector& f)
62  myType(f.myType), myRoutes(nullptr) {
63  if (f.myRoutes != nullptr) {
64  myRoutes = new RODFRouteCont(*(f.myRoutes));
65  }
66 }
67 
68 
70  delete myRoutes;
71 }
72 
73 
74 void
76  myType = type;
77 }
78 
79 
80 double
82  double distance = rd.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(rd.edges2Pass.back()->getToJunction()->getPosition());
83  double length = 0;
84  for (ROEdgeVector::const_iterator i = rd.edges2Pass.begin(); i != rd.edges2Pass.end(); ++i) {
85  length += (*i)->getLength();
86  }
87  return (distance / length);
88 }
89 
90 
91 void
93  const RODFDetectorFlows& flows,
94  SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset) {
95  if (myRoutes == nullptr) {
96  return;
97  }
98  // compute edges to determine split probabilities
99  const std::vector<RODFRouteDesc>& routes = myRoutes->get();
100  std::vector<RODFEdge*> nextDetEdges;
101  std::set<ROEdge*> preSplitEdges;
102  for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
103  const RODFRouteDesc& rd = *i;
104  bool hadSplit = false;
105  for (ROEdgeVector::const_iterator j = rd.edges2Pass.begin(); j != rd.edges2Pass.end(); ++j) {
106  if (hadSplit && net->hasDetector(*j)) {
107  if (find(nextDetEdges.begin(), nextDetEdges.end(), *j) == nextDetEdges.end()) {
108  nextDetEdges.push_back(static_cast<RODFEdge*>(*j));
109  }
110  myRoute2Edge[rd.routename] = static_cast<RODFEdge*>(*j);
111  break;
112  }
113  if (!hadSplit) {
114  preSplitEdges.insert(*j);
115  }
116  if ((*j)->getNumSuccessors() > 1) {
117  hadSplit = true;
118  }
119  }
120  }
121  std::map<ROEdge*, double> inFlows;
122  if (OptionsCont::getOptions().getBool("respect-concurrent-inflows")) {
123  for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
124  std::set<ROEdge*> seen(preSplitEdges);
125  ROEdgeVector pending;
126  pending.push_back(*i);
127  seen.insert(*i);
128  while (!pending.empty()) {
129  ROEdge* e = pending.back();
130  pending.pop_back();
131  for (ROEdgeVector::const_iterator it = e->getPredecessors().begin(); it != e->getPredecessors().end(); it++) {
132  ROEdge* e2 = *it;
133  if (e2->getNumSuccessors() == 1 && seen.count(e2) == 0) {
134  if (net->hasDetector(e2)) {
135  inFlows[*i] += detectors.getAggFlowFor(e2, 0, 0, flows);
136  } else {
137  pending.push_back(e2);
138  }
139  seen.insert(e2);
140  }
141  }
142  }
143  }
144  }
145  // compute the probabilities to use a certain direction
146  int index = 0;
147  for (SUMOTime time = startTime; time < endTime; time += stepOffset, ++index) {
148  mySplitProbabilities.push_back(std::map<RODFEdge*, double>());
149  double overallProb = 0;
150  // retrieve the probabilities
151  for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
152  double flow = detectors.getAggFlowFor(*i, time, 60, flows) - inFlows[*i];
153  overallProb += flow;
154  mySplitProbabilities[index][*i] = flow;
155  }
156  // norm probabilities
157  if (overallProb > 0) {
158  for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
159  mySplitProbabilities[index][*i] = mySplitProbabilities[index][*i] / overallProb;
160  }
161  }
162  }
163 }
164 
165 
166 void
168  SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset,
169  const RODFNet& net,
170  std::map<SUMOTime, RandomDistributor<int>* >& into) const {
171  if (myRoutes == nullptr) {
173  WRITE_ERROR("Missing routes for detector '" + myID + "'.");
174  }
175  return;
176  }
177  std::vector<RODFRouteDesc>& descs = myRoutes->get();
178  // iterate through time (in output interval steps)
179  for (SUMOTime time = startTime; time < endTime; time += stepOffset) {
180  into[time] = new RandomDistributor<int>();
181  std::map<ROEdge*, double> flowMap;
182  // iterate through the routes
183  int index = 0;
184  for (std::vector<RODFRouteDesc>::iterator ri = descs.begin(); ri != descs.end(); ++ri, index++) {
185  double prob = 1.;
186  for (ROEdgeVector::iterator j = (*ri).edges2Pass.begin(); j != (*ri).edges2Pass.end() && prob > 0;) {
187  if (!net.hasDetector(*j)) {
188  ++j;
189  continue;
190  }
191  const RODFDetector& det = detectors.getAnyDetectorForEdge(static_cast<RODFEdge*>(*j));
192  const std::vector<std::map<RODFEdge*, double> >& probs = det.getSplitProbabilities();
193  if (probs.size() == 0) {
194  prob = 0;
195  ++j;
196  continue;
197  }
198  const std::map<RODFEdge*, double>& tprobs = probs[(int)((time - startTime) / stepOffset)];
199  RODFEdge* splitEdge = nullptr;
200  for (std::map<RODFEdge*, double>::const_iterator k = tprobs.begin(); k != tprobs.end(); ++k) {
201  if (find(j, (*ri).edges2Pass.end(), (*k).first) != (*ri).edges2Pass.end()) {
202  prob *= (*k).second;
203  splitEdge = (*k).first;
204  break;
205  }
206  }
207  if (splitEdge != nullptr) {
208  j = find(j, (*ri).edges2Pass.end(), splitEdge);
209  } else {
210  ++j;
211  }
212  }
213  into[time]->add(index, prob);
214  (*ri).overallProb = prob;
215  }
216  }
217 }
218 
219 
220 const std::vector<RODFRouteDesc>&
222  return myRoutes->get();
223 }
224 
225 
226 void
228  myPriorDetectors.insert(det);
229 }
230 
231 
232 void
234  myFollowingDetectors.insert(det);
235 }
236 
237 
238 const std::set<const RODFDetector*>&
240  return myPriorDetectors;
241 }
242 
243 
244 const std::set<const RODFDetector*>&
246  return myFollowingDetectors;
247 }
248 
249 
250 
251 void
253  delete myRoutes;
254  myRoutes = routes;
255 }
256 
257 
258 void
260  if (myRoutes == nullptr) {
261  myRoutes = new RODFRouteCont();
262  }
263  myRoutes->addRouteDesc(nrd);
264 }
265 
266 
267 bool
269  return myRoutes != nullptr && myRoutes->get().size() != 0;
270 }
271 
272 
273 bool
274 RODFDetector::writeEmitterDefinition(const std::string& file,
275  const std::map<SUMOTime, RandomDistributor<int>* >& dists,
276  const RODFDetectorFlows& flows,
277  SUMOTime startTime, SUMOTime endTime,
278  SUMOTime stepOffset,
279  bool includeUnusedRoutes,
280  double scale,
281  bool insertionsOnly,
282  double defaultSpeed) const {
285  if (getType() != SOURCE_DETECTOR) {
286  out.writeXMLHeader("additional", "additional_file.xsd");
287  }
288  // routes
289  if (myRoutes != nullptr && myRoutes->get().size() != 0) {
290  const std::vector<RODFRouteDesc>& routes = myRoutes->get();
292  bool isEmptyDist = true;
293  for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
294  if ((*i).overallProb > 0) {
295  isEmptyDist = false;
296  }
297  }
298  for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
299  if (isEmptyDist) {
301  } else if ((*i).overallProb > 0 || includeUnusedRoutes) {
302  out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, (*i).overallProb).closeTag();
303  }
304  }
305  out.closeTag(); // routeDistribution
306  } else {
307  WRITE_ERROR("Detector '" + getID() + "' has no routes!?");
308  return false;
309  }
310  // insertions
311  if (insertionsOnly || flows.knows(myID)) {
312  // get the flows for this detector
313  const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
314  // go through the simulation seconds
315  int index = 0;
316  for (SUMOTime time = startTime; time < endTime; time += stepOffset, index++) {
317  // get own (departure flow)
318  assert(index < (int)mflows.size());
319  const FlowDef& srcFD = mflows[index]; // !!! check stepOffset
320  // get flows at end
321  RandomDistributor<int>* destDist = dists.find(time) != dists.end() ? dists.find(time)->second : 0;
322  // go through the cars
323  const int numCars = (int)((srcFD.qPKW + srcFD.qLKW) * scale);
324 
325 
326  std::vector<SUMOTime> departures;
327  if (oc.getBool("randomize-flows")) {
328  for (int i = 0; i < numCars; ++i) {
329  departures.push_back(time + RandHelper::rand(stepOffset));
330  }
331  std::sort(departures.begin(), departures.end());
332  } else {
333  for (int i = 0; i < numCars; ++i) {
334  departures.push_back(time + (SUMOTime)(stepOffset * i / (double)numCars));
335  }
336  }
337 
338  for (int car = 0; car < numCars; ++car) {
339  // get the vehicle parameter
340  double v = -1;
341  std::string vtype;
342  int destIndex = -1;
343  if (destDist != nullptr) {
344  if (destDist->getOverallProb() > 0) {
345  destIndex = destDist->get();
346  } else if (myRoutes->get().size() > 0) {
347  // equal probabilities. see writeEmitterDefinition()
348  destIndex = RandHelper::rand((int)myRoutes->get().size());
349  }
350  }
351  if (srcFD.isLKW >= 1) {
352  srcFD.isLKW = srcFD.isLKW - 1.;
353  v = srcFD.vLKW;
354  vtype = "LKW";
355  } else {
356  v = srcFD.vPKW;
357  vtype = "PKW";
358  }
359  // compute insertion speed
360  if (v <= 0 || v > 250) {
361  v = defaultSpeed;
362  } else {
363  v /= 3.6;
364  }
365  // compute the departure time
366  const SUMOTime ctime = departures[car];
367 
368  // write
370  if (getType() == SOURCE_DETECTOR) {
371  out.writeAttr(SUMO_ATTR_ID, "emitter_" + myID + "_" + toString(ctime));
372  } else {
373  out.writeAttr(SUMO_ATTR_ID, "calibrator_" + myID + "_" + toString(ctime));
374  }
375  if (oc.getBool("vtype")) {
376  out.writeAttr(SUMO_ATTR_TYPE, vtype);
377  }
379  if (oc.isSet("departlane")) {
380  out.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
381  } else {
382  out.writeAttr(SUMO_ATTR_DEPARTLANE, StringUtils::toInt(myLaneID.substr(myLaneID.rfind("_") + 1)));
383  }
384  if (oc.isSet("departpos")) {
385  std::string posDesc = oc.getString("departpos");
386  if (posDesc.substr(0, 8) == "detector") {
387  double position = myPosition;
388  if (posDesc.length() > 8) {
389  if (posDesc[8] == '+') {
390  position += StringUtils::toDouble(posDesc.substr(9));
391  } else if (posDesc[8] == '-') {
392  position -= StringUtils::toDouble(posDesc.substr(9));
393  } else {
394  throw NumberFormatException("");
395  }
396  }
397  out.writeAttr(SUMO_ATTR_DEPARTPOS, position);
398  } else {
400  }
401  } else {
403  }
404  if (oc.isSet("departspeed")) {
405  out.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
406  } else {
408  }
409  if (oc.isSet("arrivallane")) {
410  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
411  }
412  if (oc.isSet("arrivalpos")) {
413  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
414  }
415  if (oc.isSet("arrivalspeed")) {
416  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
417  }
418  if (destIndex >= 0) {
419  out.writeAttr(SUMO_ATTR_ROUTE, myRoutes->get()[destIndex].routename);
420  } else {
422  }
423  out.closeTag();
424  srcFD.isLKW += srcFD.fLKW;
425  }
426  }
427  }
428  if (getType() != SOURCE_DETECTOR) {
429  out.close();
430  }
431  return true;
432 }
433 
434 
435 bool
436 RODFDetector::writeRoutes(std::vector<std::string>& saved,
437  OutputDevice& out) {
438  if (myRoutes != nullptr) {
439  return myRoutes->save(saved, "", out);
440  }
441  return false;
442 }
443 
444 
445 void
447  const RODFDetectorFlows& flows,
448  SUMOTime startTime, SUMOTime endTime,
449  SUMOTime stepOffset, double defaultSpeed) {
451  out.writeXMLHeader("additional", "additional_file.xsd");
452  const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
453  int index = 0;
454  for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
455  assert(index < (int)mflows.size());
456  const FlowDef& srcFD = mflows[index];
457  double speed = MAX2(srcFD.vLKW, srcFD.vPKW);
458  if (speed <= 0 || speed > 250) {
459  speed = defaultSpeed;
460  } else {
461  speed = (double)(speed / 3.6);
462  }
464  }
465  out.close();
466 }
467 
468 
469 
470 
471 
472 
473 
474 
475 
476 
478 
479 
481  for (std::vector<RODFDetector*>::iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
482  delete *i;
483  }
484 }
485 
486 
487 bool
489  if (myDetectorMap.find(dfd->getID()) != myDetectorMap.end()) {
490  return false;
491  }
492  myDetectorMap[dfd->getID()] = dfd;
493  myDetectors.push_back(dfd);
494  std::string edgeid = dfd->getLaneID().substr(0, dfd->getLaneID().rfind('_'));
495  if (myDetectorEdgeMap.find(edgeid) == myDetectorEdgeMap.end()) {
496  myDetectorEdgeMap[edgeid] = std::vector<RODFDetector*>();
497  }
498  myDetectorEdgeMap[edgeid].push_back(dfd);
499  return true; // !!!
500 }
501 
502 
503 bool
505  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
506  if ((*i)->getType() == TYPE_NOT_DEFINED) {
507  return false;
508  }
509  }
510  return true;
511 }
512 
513 
514 bool
516  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
517  if ((*i)->hasRoutes()) {
518  return true;
519  }
520  }
521  return false;
522 }
523 
524 
525 const std::vector< RODFDetector*>&
527  return myDetectors;
528 }
529 
530 
531 void
532 RODFDetectorCon::save(const std::string& file) const {
534  out.writeXMLHeader("detectors", "detectors_file.xsd");
535  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
536  out.openTag(SUMO_TAG_DETECTOR_DEFINITION).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML((*i)->getID())).writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos());
537  switch ((*i)->getType()) {
538  case BETWEEN_DETECTOR:
539  out.writeAttr(SUMO_ATTR_TYPE, "between");
540  break;
541  case SOURCE_DETECTOR:
542  out.writeAttr(SUMO_ATTR_TYPE, "source");
543  break;
544  case SINK_DETECTOR:
545  out.writeAttr(SUMO_ATTR_TYPE, "sink");
546  break;
547  case DISCARDED_DETECTOR:
548  out.writeAttr(SUMO_ATTR_TYPE, "discarded");
549  break;
550  default:
551  throw 1;
552  }
553  out.closeTag();
554  }
555  out.close();
556 }
557 
558 
559 void
560 RODFDetectorCon::saveAsPOIs(const std::string& file) const {
562  out.writeXMLHeader("additional", "additional_file.xsd");
563  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
565  switch ((*i)->getType()) {
566  case BETWEEN_DETECTOR:
567  out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::BLUE);
568  break;
569  case SOURCE_DETECTOR:
570  out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::GREEN);
571  break;
572  case SINK_DETECTOR:
573  out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::RED);
574  break;
575  case DISCARDED_DETECTOR:
576  out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
577  break;
578  default:
579  throw 1;
580  }
581  out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
582  }
583  out.close();
584 }
585 
586 
587 void
588 RODFDetectorCon::saveRoutes(const std::string& file) const {
590  out.writeXMLHeader("routes", "routes_file.xsd");
591  std::vector<std::string> saved;
592  // write for source detectors
593  bool lastWasSaved = true;
594  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
595  if ((*i)->getType() != SOURCE_DETECTOR) {
596  // do not build routes for other than sources
597  continue;
598  }
599  if (lastWasSaved) {
600  out << "\n";
601  }
602  lastWasSaved = (*i)->writeRoutes(saved, out);
603  }
604  out << "\n";
605  out.close();
606 }
607 
608 
609 const RODFDetector&
610 RODFDetectorCon::getDetector(const std::string& id) const {
611  return *(myDetectorMap.find(id)->second);
612 }
613 
614 
616 RODFDetectorCon::getModifiableDetector(const std::string& id) const {
617  return *(myDetectorMap.find(id)->second);
618 }
619 
620 
621 bool
622 RODFDetectorCon::knows(const std::string& id) const {
623  return myDetectorMap.find(id) != myDetectorMap.end();
624 }
625 
626 
627 void
628 RODFDetectorCon::writeEmitters(const std::string& file,
629  const RODFDetectorFlows& flows,
630  SUMOTime startTime, SUMOTime endTime,
631  SUMOTime stepOffset, const RODFNet& net,
632  bool writeCalibrators,
633  bool includeUnusedRoutes,
634  double scale,
635  bool insertionsOnly) {
636  // compute turn probabilities at detector
637  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
638  (*i)->computeSplitProbabilities(&net, *this, flows, startTime, endTime, stepOffset);
639  }
640  //
642  out.writeXMLHeader("additional", "additional_file.xsd");
643  // write vType(s)
644  const bool separateVTypeOutput = OptionsCont::getOptions().getString("vtype-output") != "";
645  OutputDevice& vTypeOut = separateVTypeOutput ? OutputDevice::getDevice(OptionsCont::getOptions().getString("vtype-output")) : out;
646  if (separateVTypeOutput) {
647  vTypeOut.writeXMLHeader("additional", "additional_file.xsd");
648  }
649  const bool forceDev = !OptionsCont::getOptions().isDefault("speeddev");
650  const double speedDev = OptionsCont::getOptions().getFloat("speeddev");
651  if (OptionsCont::getOptions().getBool("vtype")) {
652  // write separate types
654  setSpeedFactorAndDev(pkwType, net.getMaxSpeedFactorPKW(), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
656  pkwType.write(vTypeOut);
658  setSpeedFactorAndDev(lkwType, net.getMaxSpeedFactorLKW(), net.getAvgSpeedFactorLKW(), speedDev, forceDev);
660  lkwType.write(vTypeOut);
661  } else {
662  // patch default type
664  setSpeedFactorAndDev(type, MAX2(net.getMaxSpeedFactorPKW(), net.getMaxSpeedFactorLKW()), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
665  if (type.parametersSet != 0) {
666  type.write(vTypeOut);
667  }
668  }
669 
670 
671  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
672  RODFDetector* det = *i;
673  // get file name for values (emitter/calibrator definition)
674  std::string escapedID = StringUtils::escapeXML(det->getID());
675  std::string defFileName;
676  if (det->getType() == SOURCE_DETECTOR) {
677  defFileName = file;
678  } else if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
679  defFileName = FileHelpers::getFilePath(file) + "calibrator_" + escapedID + ".def.xml";
680  } else {
681  defFileName = FileHelpers::getFilePath(file) + "other_" + escapedID + ".def.xml";
682  continue;
683  }
684  // try to write the definition
685  double defaultSpeed = net.getEdge(det->getEdgeID())->getSpeedLimit();
686  // ... compute routes' distribution over time
687  std::map<SUMOTime, RandomDistributor<int>* > dists;
688  if (!insertionsOnly && flows.knows(det->getID())) {
689  det->buildDestinationDistribution(*this, startTime, endTime, stepOffset, net, dists);
690  }
691  // ... write the definition
692  if (!det->writeEmitterDefinition(defFileName, dists, flows, startTime, endTime, stepOffset, includeUnusedRoutes, scale, insertionsOnly, defaultSpeed)) {
693  // skip if something failed... (!!!)
694  continue;
695  }
696  // ... clear temporary values
697  clearDists(dists);
698  // write the declaration into the file
699  if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
700  out.openTag(SUMO_TAG_CALIBRATOR).writeAttr(SUMO_ATTR_ID, "calibrator_" + escapedID).writeAttr(SUMO_ATTR_POSITION, det->getPos());
701  out.writeAttr(SUMO_ATTR_LANE, det->getLaneID()).writeAttr(SUMO_ATTR_FRIENDLY_POS, true).writeAttr(SUMO_ATTR_FILE, defFileName).closeTag();
702  }
703  }
704  out.close();
705  if (separateVTypeOutput) {
706  vTypeOut.close();
707  }
708 }
709 
710 void
711 RODFDetectorCon::setSpeedFactorAndDev(SUMOVTypeParameter& type, double maxFactor, double avgFactor, double dev, bool forceDev) {
712  if (avgFactor > 1) {
713  // systematically low speeds can easily be caused by traffic
714  // conditions. Whereas elevated speeds probably reflect speeding
715  type.speedFactor.getParameter()[0] = avgFactor;
717  }
718  if (forceDev || (maxFactor > 1 && maxFactor > type.speedFactor.getParameter()[0] + NUMERICAL_EPS)) {
719  // setting a non-zero speed deviation causes the simulation to recompute
720  // individual speedFactors to match departSpeed (MSEdge::insertVehicle())
721  type.speedFactor.getParameter()[1] = dev;
723  }
724 }
725 
726 
727 void
728 RODFDetectorCon::writeEmitterPOIs(const std::string& file,
729  const RODFDetectorFlows& flows) {
731  out.writeXMLHeader("additional", "additional_file.xsd");
732  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
733  RODFDetector* det = *i;
734  double flow = flows.getFlowSumSecure(det->getID());
735  const unsigned char col = static_cast<unsigned char>(128 * flow / flows.getMaxDetectorFlow() + 128);
736  out.openTag(SUMO_TAG_POI).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML((*i)->getID()) + ":" + toString(flow));
737  switch ((*i)->getType()) {
738  case BETWEEN_DETECTOR:
739  out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, 0, col, 255));
740  break;
741  case SOURCE_DETECTOR:
742  out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, col, 0, 255));
743  break;
744  case SINK_DETECTOR:
745  out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(col, 0, 0, 255));
746  break;
747  case DISCARDED_DETECTOR:
748  out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
749  break;
750  default:
751  throw 1;
752  }
753  out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
754  }
755  out.close();
756 }
757 
758 
759 int
761  const RODFDetectorFlows&) const {
762  UNUSED_PARAMETER(period);
763  UNUSED_PARAMETER(time);
764  if (edge == nullptr) {
765  return 0;
766  }
767 // double stepOffset = 60; // !!!
768 // double startTime = 0; // !!!
769 // cout << edge->getID() << endl;
770  assert(myDetectorEdgeMap.find(edge->getID()) != myDetectorEdgeMap.end());
771  const std::vector<FlowDef>& flows = static_cast<const RODFEdge*>(edge)->getFlows();
772  double agg = 0;
773  for (std::vector<FlowDef>::const_iterator i = flows.begin(); i != flows.end(); ++i) {
774  const FlowDef& srcFD = *i;
775  if (srcFD.qLKW >= 0) {
776  agg += srcFD.qLKW;
777  }
778  if (srcFD.qPKW >= 0) {
779  agg += srcFD.qPKW;
780  }
781  }
782  return (int) agg;
783  /* !!! make this time variable
784  if (flows.size()!=0) {
785  double agg = 0;
786  int beginIndex = (int)((time/stepOffset) - startTime); // !!! falsch!!!
787  for (SUMOTime t=0; t<period&&beginIndex<flows.size(); t+=(SUMOTime) stepOffset) {
788  const FlowDef &srcFD = flows[beginIndex++];
789  if (srcFD.qLKW>=0) {
790  agg += srcFD.qLKW;
791  }
792  if (srcFD.qPKW>=0) {
793  agg += srcFD.qPKW;
794  }
795  }
796  return (int) agg;
797  }
798  */
799 // return -1;
800 }
801 
802 
803 void
805  const std::string& file,
806  const RODFDetectorFlows& flows,
807  SUMOTime startTime, SUMOTime endTime,
808  SUMOTime stepOffset) {
810  out.writeXMLHeader("additional", "additional_file.xsd");
811  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
812  RODFDetector* det = *i;
813  // write the declaration into the file
814  if (det->getType() == SINK_DETECTOR && flows.knows(det->getID())) {
815  std::string filename = FileHelpers::getFilePath(file) + "vss_" + det->getID() + ".def.xml";
817  double defaultSpeed = net != nullptr ? net->getEdge(det->getEdgeID())->getSpeedLimit() : (double) 200.;
818  det->writeSingleSpeedTrigger(filename, flows, startTime, endTime, stepOffset, defaultSpeed);
819  }
820  }
821  out.close();
822 }
823 
824 
825 void
828  out.writeXMLHeader("additional", "additional_file.xsd");
829  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
830  RODFDetector* det = *i;
831  // write the declaration into the file
832  if (det->getType() == SINK_DETECTOR) {
834  out.writeAttr(SUMO_ATTR_POSITION, 0.).writeAttr(SUMO_ATTR_FILE, "endrerouter_" + det->getID() + ".def.xml").closeTag();
835  }
836  }
837  out.close();
838 }
839 
840 
841 void
843  bool includeSources,
844  bool singleFile, bool friendly) {
846  out.writeXMLHeader("additional", "additional_file.xsd");
847  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
848  RODFDetector* det = *i;
849  // write the declaration into the file
850  if (det->getType() != SOURCE_DETECTOR || includeSources) {
851  double pos = det->getPos();
852  if (det->getType() == SOURCE_DETECTOR) {
853  pos += 1;
854  }
857  if (friendly) {
859  }
860  if (!singleFile) {
861  out.writeAttr(SUMO_ATTR_FILE, "validation_det_" + StringUtils::escapeXML(det->getID()) + ".xml");
862  } else {
863  out.writeAttr(SUMO_ATTR_FILE, "validation_dets.xml");
864  }
865  out.closeTag();
866  }
867  }
868  out.close();
869 }
870 
871 
872 void
873 RODFDetectorCon::removeDetector(const std::string& id) {
874  //
875  std::map<std::string, RODFDetector*>::iterator ri1 = myDetectorMap.find(id);
876  RODFDetector* oldDet = (*ri1).second;
877  myDetectorMap.erase(ri1);
878  //
879  std::vector<RODFDetector*>::iterator ri2 =
880  find(myDetectors.begin(), myDetectors.end(), oldDet);
881  myDetectors.erase(ri2);
882  //
883  bool found = false;
884  for (std::map<std::string, std::vector<RODFDetector*> >::iterator rr3 = myDetectorEdgeMap.begin(); !found && rr3 != myDetectorEdgeMap.end(); ++rr3) {
885  std::vector<RODFDetector*>& dets = (*rr3).second;
886  for (std::vector<RODFDetector*>::iterator ri3 = dets.begin(); !found && ri3 != dets.end();) {
887  if (*ri3 == oldDet) {
888  found = true;
889  ri3 = dets.erase(ri3);
890  } else {
891  ++ri3;
892  }
893  }
894  }
895  delete oldDet;
896 }
897 
898 
899 void
901  // routes must be built (we have ensured this in main)
902  // detector followers/prior must be build (we have ensured this in main)
903  //
904  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
905  RODFDetector* det = *i;
906  const std::set<const RODFDetector*>& prior = det->getPriorDetectors();
907  const std::set<const RODFDetector*>& follower = det->getFollowerDetectors();
908  int noFollowerWithRoutes = 0;
909  int noPriorWithRoutes = 0;
910  // count occurences of detectors with/without routes
911  std::set<const RODFDetector*>::const_iterator j;
912  for (j = prior.begin(); j != prior.end(); ++j) {
913  if (flows.knows((*j)->getID())) {
914  ++noPriorWithRoutes;
915  }
916  }
917  for (j = follower.begin(); j != follower.end(); ++j) {
918  if (flows.knows((*j)->getID())) {
919  ++noFollowerWithRoutes;
920  }
921  }
922 
923  // do not process detectors which have no routes
924  if (!flows.knows(det->getID())) {
925  continue;
926  }
927 
928  // plain case: all of the prior detectors have routes
929  if (noPriorWithRoutes == (int)prior.size()) {
930  // the number of vehicles is the sum of all vehicles on prior
931  continue;
932  }
933 
934  // plain case: all of the follower detectors have routes
935  if (noFollowerWithRoutes == (int)follower.size()) {
936  // the number of vehicles is the sum of all vehicles on follower
937  continue;
938  }
939 
940  }
941 }
942 
943 
944 const RODFDetector&
946  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
947  if ((*i)->getEdgeID() == edge->getID()) {
948  return **i;
949  }
950  }
951  throw 1;
952 }
953 
954 
955 void
957  for (std::map<SUMOTime, RandomDistributor<int>* >::iterator i = dists.begin(); i != dists.end(); ++i) {
958  delete(*i).second;
959  }
960 }
961 
962 
963 void
964 RODFDetectorCon::mesoJoin(const std::string& nid,
965  const std::vector<std::string>& oldids) {
966  // build the new detector
967  const RODFDetector& first = getDetector(*(oldids.begin()));
968  RODFDetector* newDet = new RODFDetector(nid, first);
969  addDetector(newDet);
970  // delete previous
971  for (std::vector<std::string>::const_iterator i = oldids.begin(); i != oldids.end(); ++i) {
972  removeDetector(*i);
973  }
974 }
975 
976 
977 /****************************************************************************/
double getFlowSumSecure(const std::string &id) const
RODFDetector & getModifiableDetector(const std::string &id) const
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
static const RGBColor BLUE
Definition: RGBColor.h:186
void close()
Closes the device and removes it from the dictionary.
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition: ROEdge.h:341
bool detectorsHaveRoutes() const
long long int SUMOTime
Definition: SUMOTime.h:36
bool writeEmitterDefinition(const std::string &file, const std::map< SUMOTime, RandomDistributor< int > * > &dists, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, bool includeUnusedRoutes, double scale, bool insertionsOnly, double defaultSpeed) const
void addRoute(RODFRouteDesc &nrd)
std::string getEdgeID() const
Returns the id of the edge this detector is placed on.
Definition: RODFDetector.h:127
void removeDetector(const std::string &id)
void saveRoutes(const std::string &file) const
int getNumSuccessors() const
Returns the number of edges this edge is connected to.
Definition: ROEdge.cpp:235
RODFDetectorType
Numerical representation of different detector types.
Definition: RODFDetector.h:59
void save(const std::string &file) const
A calibrator placed over edge.
Structure representing possible vehicle parameter.
distribution of a route
bool addDetector(RODFDetector *dfd)
double getAvgSpeedFactorPKW() const
Definition: RODFNet.h:95
void addRoutes(RODFRouteCont *routes)
A source detector.
Definition: RODFDetector.h:70
const RODFDetector & getDetector(const std::string &id) const
std::vector< double > & getParameter()
Returns the parameters of this distribution.
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:61
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
ROEdgeVector edges2Pass
The edges the route is made of.
Definition: RODFRouteDesc.h:49
T MAX2(T a, T b)
Definition: StdDefs.h:76
double getMaxSpeedFactorPKW() const
Definition: RODFNet.h:87
int getAggFlowFor(const ROEdge *edge, SUMOTime time, SUMOTime period, const RODFDetectorFlows &flows) const
void addPriorDetector(const RODFDetector *det)
bool hasDetector(ROEdge *edge) const
Definition: RODFNet.cpp:656
begin/end of the description of a Point of interest
const std::vector< RODFDetector * > & getDetectors() const
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:78
void writeSpeedTrigger(const RODFNet *const net, const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset)
RODFDetectorType getType() const
Returns the type of the detector.
Definition: RODFDetector.h:144
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
const std::vector< RODFRouteDesc > & getRouteVector() const
bool knows(const std::string &det_id) const
const std::string DEFAULT_VTYPE_ID
RODFDetector(const std::string &id, const std::string &laneID, double pos, const RODFDetectorType type)
Constructor.
std::vector< RODFRouteDesc > & get()
Returns the container of stored routes.
A container for flows.
A container for RODFDetectors.
Definition: RODFDetector.h:221
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:33
const std::set< const RODFDetector * > & getFollowerDetectors() const
begin/end of the description of a route
void computeSplitProbabilities(const RODFNet *net, const RODFDetectorCon &detectors, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset)
RODFRouteCont * myRoutes
Definition: RODFDetector.h:201
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
vehicle is a large transport vehicle
A not yet defined detector.
Definition: RODFDetector.h:61
double getMaxDetectorFlow() const
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool hasRoutes() const
bool writeRoutes(std::vector< std::string > &saved, OutputDevice &out)
double getMaxSpeedFactorLKW() const
Definition: RODFNet.h:91
static const RGBColor GREEN
Definition: RGBColor.h:185
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
std::vector< std::map< RODFEdge *, double > > mySplitProbabilities
Definition: RODFDetector.h:203
An in-between detector.
Definition: RODFDetector.h:67
const std::vector< std::map< RODFEdge *, double > > & getSplitProbabilities() const
Definition: RODFDetector.h:188
OutputDevice & writeNonEmptyAttr(const SumoXMLAttr attr, const std::string &val)
writes a string attribute only if it is not the empty string and not the string "default" ...
Definition: OutputDevice.h:289
bool knows(const std::string &id) const
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter ...
T get(std::mt19937 *which=0) const
Draw a sample of the distribution.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
const std::set< const RODFDetector * > & getPriorDetectors() const
std::vector< ROEdge * > ROEdgeVector
Definition: RODFRouteDesc.h:36
double computeDistanceFactor(const RODFRouteDesc &rd) const
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
A detector which had to be discarded (!!!)
Definition: RODFDetector.h:64
const RODFDetector & getAnyDetectorForEdge(const RODFEdge *const edge) const
A DFROUTER-network.
Definition: RODFNet.h:45
definition of a detector
void writeValidationDetectors(const std::string &file, bool includeSources, bool singleFile, bool friendly)
void setSpeedFactorAndDev(SUMOVTypeParameter &type, double maxFactor, double avgFactor, double dev, bool forceDev)
~RODFDetector()
Destructor.
void clearDists(std::map< SUMOTime, RandomDistributor< int > * > &dists) const
Clears the given distributions map, deleting the timed distributions.
std::string myLaneID
Definition: RODFDetector.h:198
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter...
void saveAsPOIs(const std::string &file) const
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
Definition of the traffic during a certain time containing the flows and speeds.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double qPKW
vehicle is a passenger car (a "normal" car)
A route within the DFROUTER.
Definition: RODFRouteDesc.h:47
double getAvgSpeedFactorLKW() const
Definition: RODFNet.h:99
A basic edge for routing applications.
Definition: ROEdge.h:72
Base class for objects which have an id.
Definition: Named.h:58
const int VTYPEPARS_SPEEDFACTOR_SET
void writeEmitters(const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, const RODFNet &net, bool writeCalibrators, bool includeUnusedRoutes, double scale, bool insertionsOnly)
int parametersSet
Information for the router which parameter were set.
const std::string & getLaneID() const
Returns the id of the lane this detector is placed on.
Definition: RODFDetector.h:119
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
void writeSingleSpeedTrigger(const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, double defaultSpeed)
bool detectorsHaveCompleteTypes() const
std::string myID
The name of the object.
Definition: Named.h:130
void write(OutputDevice &dev) const
Writes the vtype.
trigger: the time of the step
static const RGBColor RED
named colors
Definition: RGBColor.h:184
RODFDetectorType myType
Definition: RODFDetector.h:200
std::map< std::string, RODFEdge * > myRoute2Edge
Definition: RODFDetector.h:204
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
void guessEmptyFlows(RODFDetectorFlows &flows)
double qLKW
Class representing a detector within the DFROUTER.
Definition: RODFDetector.h:82
A storage for options typed value containers)
Definition: OptionsCont.h:92
A container for DFROUTER-routes.
Definition: RODFRouteCont.h:56
double getOverallProb() const
Return the sum of the probabilites assigned to the members.
std::string routename
The name of the route.
Definition: RODFRouteDesc.h:51
void buildDestinationDistribution(const RODFDetectorCon &detectors, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, const RODFNet &net, std::map< SUMOTime, RandomDistributor< int > * > &into) const
const std::vector< FlowDef > & getFlowDefs(const std::string &id) const
void writeEmitterPOIs(const std::string &file, const RODFDetectorFlows &flows)
description of a vehicle
void setType(RODFDetectorType type)
std::set< const RODFDetector * > myPriorDetectors
Definition: RODFDetector.h:202
A variable speed sign.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
#define NUMERICAL_EPS
Definition: config.h:148
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
Definition: FileHelpers.cpp:65
std::set< const RODFDetector * > myFollowingDetectors
Definition: RODFDetector.h:202
double myPosition
Definition: RODFDetector.h:199
void writeEndRerouterDetectors(const std::string &file)
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition: RONet.h:157
void mesoJoin(const std::string &nid, const std::vector< std::string > &oldids)
void addRouteDesc(RODFRouteDesc &desc)
Adds a route to the container.
const int VTYPEPARS_VEHICLECLASS_SET
A color information.
void addFollowingDetector(const RODFDetector *det)
Distribution_Parameterized speedFactor
The factor by which the maximum speed may deviate from the allowed max speed on the street...
double getPos() const
Returns the position at which the detector lies.
Definition: RODFDetector.h:135
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool save(std::vector< std::string > &saved, const std::string &prependix, OutputDevice &out)
Saves routes.
trigger: a step description