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-2019 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 = std::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  int vehicleIndex = 0;
312  if (insertionsOnly || flows.knows(myID)) {
313  // get the flows for this detector
314  const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
315  // go through the simulation seconds
316  int index = 0;
317  for (SUMOTime time = startTime; time < endTime; time += stepOffset, index++) {
318  // get own (departure flow)
319  assert(index < (int)mflows.size());
320  const FlowDef& srcFD = mflows[index]; // !!! check stepOffset
321  // get flows at end
322  RandomDistributor<int>* destDist = dists.find(time) != dists.end() ? dists.find(time)->second : 0;
323  // go through the cars
324  const int numCars = (int)((srcFD.qPKW + srcFD.qLKW) * scale);
325 
326 
327  std::vector<SUMOTime> departures;
328  if (oc.getBool("randomize-flows")) {
329  for (int i = 0; i < numCars; ++i) {
330  departures.push_back(time + RandHelper::rand(stepOffset));
331  }
332  std::sort(departures.begin(), departures.end());
333  } else {
334  for (int i = 0; i < numCars; ++i) {
335  departures.push_back(time + (SUMOTime)(stepOffset * i / (double)numCars));
336  }
337  }
338 
339  for (int car = 0; car < numCars; ++car) {
340  // get the vehicle parameter
341  double v = -1;
342  std::string vtype;
343  int destIndex = -1;
344  if (destDist != nullptr) {
345  if (destDist->getOverallProb() > 0) {
346  destIndex = destDist->get();
347  } else if (myRoutes->get().size() > 0) {
348  // equal probabilities. see writeEmitterDefinition()
349  destIndex = RandHelper::rand((int)myRoutes->get().size());
350  }
351  }
352  if (srcFD.isLKW >= 1) {
353  srcFD.isLKW = srcFD.isLKW - 1.;
354  v = srcFD.vLKW;
355  vtype = "LKW";
356  } else {
357  v = srcFD.vPKW;
358  vtype = "PKW";
359  }
360  // compute insertion speed
361  if (v <= 0 || v > 250) {
362  v = defaultSpeed;
363  } else {
364  v /= 3.6;
365  }
366  // compute the departure time
367  const SUMOTime ctime = departures[car];
368 
369  // write
371  out.writeAttr(SUMO_ATTR_ID, myID + "." + toString(vehicleIndex));
372  if (oc.getBool("vtype")) {
373  out.writeAttr(SUMO_ATTR_TYPE, vtype);
374  }
376  if (oc.isSet("departlane")) {
377  out.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
378  } else {
379  out.writeAttr(SUMO_ATTR_DEPARTLANE, StringUtils::toInt(myLaneID.substr(myLaneID.rfind("_") + 1)));
380  }
381  if (oc.isSet("departpos")) {
382  std::string posDesc = oc.getString("departpos");
383  if (posDesc.substr(0, 8) == "detector") {
384  double position = myPosition;
385  if (posDesc.length() > 8) {
386  if (posDesc[8] == '+') {
387  position += StringUtils::toDouble(posDesc.substr(9));
388  } else if (posDesc[8] == '-') {
389  position -= StringUtils::toDouble(posDesc.substr(9));
390  } else {
391  throw NumberFormatException("");
392  }
393  }
394  out.writeAttr(SUMO_ATTR_DEPARTPOS, position);
395  } else {
397  }
398  } else {
400  }
401  if (oc.isSet("departspeed")) {
402  out.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
403  } else {
405  }
406  if (oc.isSet("arrivallane")) {
407  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));
408  }
409  if (oc.isSet("arrivalpos")) {
410  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));
411  }
412  if (oc.isSet("arrivalspeed")) {
413  out.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));
414  }
415  if (destIndex >= 0) {
416  out.writeAttr(SUMO_ATTR_ROUTE, myRoutes->get()[destIndex].routename);
417  } else {
419  }
420  out.closeTag();
421  srcFD.isLKW += srcFD.fLKW;
422  vehicleIndex++;
423  }
424  }
425  }
426  if (getType() != SOURCE_DETECTOR) {
427  out.close();
428  }
429  return true;
430 }
431 
432 
433 bool
434 RODFDetector::writeRoutes(std::vector<std::string>& saved,
435  OutputDevice& out) {
436  if (myRoutes != nullptr) {
437  return myRoutes->save(saved, "", out);
438  }
439  return false;
440 }
441 
442 
443 void
445  const RODFDetectorFlows& flows,
446  SUMOTime startTime, SUMOTime endTime,
447  SUMOTime stepOffset, double defaultSpeed) {
449  out.writeXMLHeader("additional", "additional_file.xsd");
450  const std::vector<FlowDef>& mflows = flows.getFlowDefs(myID);
451  int index = 0;
452  for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
453  assert(index < (int)mflows.size());
454  const FlowDef& srcFD = mflows[index];
455  double speed = MAX2(srcFD.vLKW, srcFD.vPKW);
456  if (speed <= 0 || speed > 250) {
457  speed = defaultSpeed;
458  } else {
459  speed = (double)(speed / 3.6);
460  }
462  }
463  out.close();
464 }
465 
466 
467 
468 
469 
470 
471 
472 
473 
474 
476 
477 
479  for (std::vector<RODFDetector*>::iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
480  delete *i;
481  }
482 }
483 
484 
485 bool
487  if (myDetectorMap.find(dfd->getID()) != myDetectorMap.end()) {
488  return false;
489  }
490  myDetectorMap[dfd->getID()] = dfd;
491  myDetectors.push_back(dfd);
492  std::string edgeid = dfd->getLaneID().substr(0, dfd->getLaneID().rfind('_'));
493  if (myDetectorEdgeMap.find(edgeid) == myDetectorEdgeMap.end()) {
494  myDetectorEdgeMap[edgeid] = std::vector<RODFDetector*>();
495  }
496  myDetectorEdgeMap[edgeid].push_back(dfd);
497  return true; // !!!
498 }
499 
500 
501 bool
503  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
504  if ((*i)->getType() == TYPE_NOT_DEFINED) {
505  return false;
506  }
507  }
508  return true;
509 }
510 
511 
512 bool
514  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
515  if ((*i)->hasRoutes()) {
516  return true;
517  }
518  }
519  return false;
520 }
521 
522 
523 const std::vector< RODFDetector*>&
525  return myDetectors;
526 }
527 
528 
529 void
530 RODFDetectorCon::save(const std::string& file) const {
532  out.writeXMLHeader("detectors", "detectors_file.xsd");
533  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
534  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());
535  switch ((*i)->getType()) {
536  case BETWEEN_DETECTOR:
537  out.writeAttr(SUMO_ATTR_TYPE, "between");
538  break;
539  case SOURCE_DETECTOR:
540  out.writeAttr(SUMO_ATTR_TYPE, "source");
541  break;
542  case SINK_DETECTOR:
543  out.writeAttr(SUMO_ATTR_TYPE, "sink");
544  break;
545  case DISCARDED_DETECTOR:
546  out.writeAttr(SUMO_ATTR_TYPE, "discarded");
547  break;
548  default:
549  throw 1;
550  }
551  out.closeTag();
552  }
553  out.close();
554 }
555 
556 
557 void
558 RODFDetectorCon::saveAsPOIs(const std::string& file) const {
560  out.writeXMLHeader("additional", "additional_file.xsd");
561  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
563  switch ((*i)->getType()) {
564  case BETWEEN_DETECTOR:
565  out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::BLUE);
566  break;
567  case SOURCE_DETECTOR:
568  out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::GREEN);
569  break;
570  case SINK_DETECTOR:
571  out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::RED);
572  break;
573  case DISCARDED_DETECTOR:
574  out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
575  break;
576  default:
577  throw 1;
578  }
579  out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
580  }
581  out.close();
582 }
583 
584 
585 void
586 RODFDetectorCon::saveRoutes(const std::string& file) const {
588  out.writeXMLHeader("routes", "routes_file.xsd");
589  std::vector<std::string> saved;
590  // write for source detectors
591  bool lastWasSaved = true;
592  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
593  if ((*i)->getType() != SOURCE_DETECTOR) {
594  // do not build routes for other than sources
595  continue;
596  }
597  if (lastWasSaved) {
598  out << "\n";
599  }
600  lastWasSaved = (*i)->writeRoutes(saved, out);
601  }
602  out << "\n";
603  out.close();
604 }
605 
606 
607 const RODFDetector&
608 RODFDetectorCon::getDetector(const std::string& id) const {
609  return *(myDetectorMap.find(id)->second);
610 }
611 
612 
614 RODFDetectorCon::getModifiableDetector(const std::string& id) const {
615  return *(myDetectorMap.find(id)->second);
616 }
617 
618 
619 bool
620 RODFDetectorCon::knows(const std::string& id) const {
621  return myDetectorMap.find(id) != myDetectorMap.end();
622 }
623 
624 
625 void
626 RODFDetectorCon::writeEmitters(const std::string& file,
627  const RODFDetectorFlows& flows,
628  SUMOTime startTime, SUMOTime endTime,
629  SUMOTime stepOffset, const RODFNet& net,
630  bool writeCalibrators,
631  bool includeUnusedRoutes,
632  double scale,
633  bool insertionsOnly) {
634  // compute turn probabilities at detector
635  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
636  (*i)->computeSplitProbabilities(&net, *this, flows, startTime, endTime, stepOffset);
637  }
638  //
640  out.writeXMLHeader("additional", "additional_file.xsd");
641  // write vType(s)
642  const bool separateVTypeOutput = OptionsCont::getOptions().getString("vtype-output") != "";
643  OutputDevice& vTypeOut = separateVTypeOutput ? OutputDevice::getDevice(OptionsCont::getOptions().getString("vtype-output")) : out;
644  if (separateVTypeOutput) {
645  vTypeOut.writeXMLHeader("additional", "additional_file.xsd");
646  }
647  const bool forceDev = !OptionsCont::getOptions().isDefault("speeddev");
648  const double speedDev = OptionsCont::getOptions().getFloat("speeddev");
649  if (OptionsCont::getOptions().getBool("vtype")) {
650  // write separate types
652  setSpeedFactorAndDev(pkwType, net.getMaxSpeedFactorPKW(), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
654  pkwType.write(vTypeOut);
656  setSpeedFactorAndDev(lkwType, net.getMaxSpeedFactorLKW(), net.getAvgSpeedFactorLKW(), speedDev, forceDev);
658  lkwType.write(vTypeOut);
659  } else {
660  // patch default type
662  setSpeedFactorAndDev(type, MAX2(net.getMaxSpeedFactorPKW(), net.getMaxSpeedFactorLKW()), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
663  if (type.parametersSet != 0) {
664  type.write(vTypeOut);
665  }
666  }
667 
668 
669  for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
670  RODFDetector* det = *i;
671  // get file name for values (emitter/calibrator definition)
672  std::string escapedID = StringUtils::escapeXML(det->getID());
673  std::string defFileName;
674  if (det->getType() == SOURCE_DETECTOR) {
675  defFileName = file;
676  } else if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
677  defFileName = FileHelpers::getFilePath(file) + "calibrator_" + escapedID + ".def.xml";
678  } else {
679  defFileName = FileHelpers::getFilePath(file) + "other_" + escapedID + ".def.xml";
680  continue;
681  }
682  // try to write the definition
683  double defaultSpeed = net.getEdge(det->getEdgeID())->getSpeedLimit();
684  // ... compute routes' distribution over time
685  std::map<SUMOTime, RandomDistributor<int>* > dists;
686  if (!insertionsOnly && flows.knows(det->getID())) {
687  det->buildDestinationDistribution(*this, startTime, endTime, stepOffset, net, dists);
688  }
689  // ... write the definition
690  if (!det->writeEmitterDefinition(defFileName, dists, flows, startTime, endTime, stepOffset, includeUnusedRoutes, scale, insertionsOnly, defaultSpeed)) {
691  // skip if something failed... (!!!)
692  continue;
693  }
694  // ... clear temporary values
695  clearDists(dists);
696  // write the declaration into the file
697  if (writeCalibrators && det->getType() == BETWEEN_DETECTOR) {
698  out.openTag(SUMO_TAG_CALIBRATOR).writeAttr(SUMO_ATTR_ID, "calibrator_" + escapedID).writeAttr(SUMO_ATTR_POSITION, det->getPos());
699  out.writeAttr(SUMO_ATTR_LANE, det->getLaneID()).writeAttr(SUMO_ATTR_FRIENDLY_POS, true).writeAttr(SUMO_ATTR_FILE, defFileName).closeTag();
700  }
701  }
702  out.close();
703  if (separateVTypeOutput) {
704  vTypeOut.close();
705  }
706 }
707 
708 void
709 RODFDetectorCon::setSpeedFactorAndDev(SUMOVTypeParameter& type, double maxFactor, double avgFactor, double dev, bool forceDev) {
710  if (avgFactor > 1) {
711  // systematically low speeds can easily be caused by traffic
712  // conditions. Whereas elevated speeds probably reflect speeding
713  type.speedFactor.getParameter()[0] = avgFactor;
715  }
716  if (forceDev || (maxFactor > 1 && maxFactor > type.speedFactor.getParameter()[0] + NUMERICAL_EPS)) {
717  // setting a non-zero speed deviation causes the simulation to recompute
718  // individual speedFactors to match departSpeed (MSEdge::insertVehicle())
719  type.speedFactor.getParameter()[1] = dev;
721  } else {
722  type.speedFactor.getParameter()[1] = -1; // do not write speedDev, only simple speedFactor
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  std::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:192
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:339
bool detectorsHaveRoutes() const
long long int SUMOTime
Definition: SUMOTime.h:35
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:245
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
static double rand(std::mt19937 *rng=0)
Returns a random real number in [0, 1)
Definition: RandHelper.h:60
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:80
double getMaxSpeedFactorPKW() const
Definition: RODFNet.h:87
std::vector< double > & getParameter()
Returns the parameters of this distribution.
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:77
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:32
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:191
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
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:73
Base class for objects which have an id.
Definition: Named.h:57
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:245
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:134
void write(OutputDevice &dev) const
Writes the vtype.
trigger: the time of the step
static const RGBColor RED
named colors
Definition: RGBColor.h:190
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:90
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:145
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
Definition: FileHelpers.cpp:67
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:153
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