Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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"
34#include <router/ROEdge.h>
35#include "RODFEdge.h"
36#include "RODFRouteDesc.h"
37#include "RODFRouteCont.h"
38#include "RODFDetectorFlow.h"
44#include "RODFNet.h"
48
49
50// ===========================================================================
51// method definitions
52// ===========================================================================
53RODFDetector::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
58RODFDetector::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) {
63 }
64}
65
66
70
71
72void
76
77
78double
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
89void
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
164void
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
218const std::vector<RODFRouteDesc>&
220 return myRoutes->get();
221}
222
223
224void
228
229
230void
234
235
236const std::set<const RODFDetector*>&
240
241
242const std::set<const RODFDetector*>&
246
247
248
249void
251 delete myRoutes;
252 myRoutes = routes;
253}
254
255
256void
258 if (myRoutes == nullptr) {
259 myRoutes = new RODFRouteCont();
260 }
262}
263
264
265bool
267 return myRoutes != nullptr && myRoutes->get().size() != 0;
268}
269
270
271bool
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
431bool
432RODFDetector::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
441void
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
483bool
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
499bool
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
510bool
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
521const std::vector< RODFDetector*>&
525
526
527void
528RODFDetectorCon::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) {
532 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());
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;
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
555void
556RODFDetectorCon::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;
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
583void
584RODFDetectorCon::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
605const RODFDetector&
606RODFDetectorCon::getDetector(const std::string& id) const {
607 return *(myDetectorMap.find(id)->second);
608}
609
610
612RODFDetectorCon::getModifiableDetector(const std::string& id) const {
613 return *(myDetectorMap.find(id)->second);
614}
615
616
617bool
618RODFDetectorCon::knows(const std::string& id) const {
619 return myDetectorMap.find(id) != myDetectorMap.end();
620}
621
622
623void
624RODFDetectorCon::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
706void
707RODFDetectorCon::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
725void
726RODFDetectorCon::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;
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
757int
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
801void
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
823void
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) {
831 out.openTag(SUMO_TAG_REROUTER).writeAttr(SUMO_ATTR_ID, "endrerouter_" + StringUtils::escapeXML(det->getID())).writeAttr(SUMO_ATTR_EDGES, det->getLaneID());
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
839void
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
870void
871RODFDetectorCon::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
897void
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
942const 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
953void
955 for (std::map<SUMOTime, RandomDistributor<int>* >::iterator i = dists.begin(); i != dists.end(); ++i) {
956 delete (*i).second;
957 }
958}
959
960
961void
962RODFDetectorCon::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
975std::string
979
980/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define TL(string)
Definition MsgHandler.h:315
RODFDetectorType
Numerical representation of different detector types.
@ BETWEEN_DETECTOR
An in-between detector.
@ SINK_DETECTOR
@ SOURCE_DETECTOR
A source detector.
@ DISCARDED_DETECTOR
A detector which had to be discarded (!!!)
@ TYPE_NOT_DEFINED
A not yet defined detector.
std::vector< ROEdge * > ROEdgeVector
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.
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.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
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"
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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.
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
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
void guessEmptyFlows(RODFDetectorFlows &flows)
bool detectorsHaveCompleteTypes() const
void saveRoutes(const std::string &file) const
std::vector< RODFDetector * > myDetectors
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.
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.
void setType(RODFDetectorType type)
void addPriorDetector(const RODFDetector *det)
bool hasRoutes() const
double myPosition
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
void addRoutes(RODFRouteCont *routes)
const std::vector< std::map< RODFEdge *, double > > & getSplitProbabilities() const
RODFDetectorType getType() const
Returns the type of the detector.
std::vector< std::map< RODFEdge *, double > > mySplitProbabilities
void writeSingleSpeedTrigger(const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, double defaultSpeed)
std::map< std::string, RODFEdge * > myRoute2Edge
std::string getEdgeID() const
Returns the id of the edge this detector is placed on.
~RODFDetector()
Destructor.
std::string myLaneID
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
const std::string & getLaneID() const
Returns the id of the lane this detector is placed on.
RODFDetectorType myType
std::set< const RODFDetector * > myPriorDetectors
void addFollowingDetector(const RODFDetector *det)
const std::set< const RODFDetector * > & getFollowerDetectors() const
std::set< const RODFDetector * > myFollowingDetectors
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.
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:72
double getSpeedLimit() const
Returns the speed allowed on this edge.
Definition ROEdge.h:239
int getNumSuccessors() const
Returns the number of edges this edge is connected to.
Definition ROEdge.cpp:271
const ROEdgeVector & getPredecessors() const
Returns the edge at the given position from the list of incoming edges.
Definition ROEdge.h:375
ROEdge * getEdge(const std::string &name) const
Retrieves an edge from the network.
Definition RONet.h:158
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Represents a generic random distribution.
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.
A route within the DFROUTER.
std::string routename
The name of the route.
ROEdgeVector edges2Pass
The edges the route is made of.