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