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.dev/sumo
3 // Copyright (C) 2006-2024 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_ERRORF(TL("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_ERRORF(TL("Detector '%' has no routes!?"), getID());
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 + (stepOffset * i / 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 occurrences 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 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define TL(string)
Definition: MsgHandler.h:315
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, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
const long long int VTYPEPARS_SPEEDFACTOR_SET
const long long int VTYPEPARS_VEHICLECLASS_SET
const std::string DEFAULT_VTYPE_ID
@ SVC_TRUCK
vehicle is a large transport vehicle
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ 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_PERIOD
@ 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:82
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:83
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:60
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:306
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
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 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:647
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:234
int getNumSuccessors() const
Returns the number of edges this edge is connected to.
Definition: ROEdge.cpp:251
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition: ROEdge.h:370
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.cpp:94
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.
long long int parametersSet
Information for the router which parameter were set.
Distribution_Parameterized speedFactor
The factor by which the maximum speed may deviate from the allowed max speed on the street.
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