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