Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/dfrouter/RODFDetector.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2006-2025 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
/****************************************************************************/
14
/// @file RODFDetector.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Eric Nicolay
17
/// @author Jakob Erdmann
18
/// @author Sascha Krieg
19
/// @author Michael Behrisch
20
/// @author Laura Bieker
21
/// @author Melanie Knocke
22
/// @date Thu, 16.03.2006
23
///
24
// Class representing a detector within the DFROUTER
25
/****************************************************************************/
26
#include <config.h>
27
28
#include <cassert>
29
#include "RODFDetector.h"
30
#include <utils/common/FileHelpers.h>
31
#include <utils/common/MsgHandler.h>
32
#include <utils/common/UtilExceptions.h>
33
#include <utils/common/ToString.h>
34
#include <router/ROEdge.h>
35
#include "RODFEdge.h"
36
#include "RODFRouteDesc.h"
37
#include "RODFRouteCont.h"
38
#include "RODFDetectorFlow.h"
39
#include <utils/vehicle/SUMOVTypeParameter.h>
40
#include <utils/distribution/RandomDistributor.h>
41
#include <utils/common/StdDefs.h>
42
#include <utils/common/StringUtils.h>
43
#include <utils/geom/GeomHelper.h>
44
#include "RODFNet.h"
45
#include <utils/iodevices/OutputDevice.h>
46
#include <utils/common/StringUtils.h>
47
#include <utils/options/OptionsCont.h>
48
49
50
// ===========================================================================
51
// method definitions
52
// ===========================================================================
53
RODFDetector::RODFDetector(const std::string& id, const std::string& laneID,
54
double pos, const RODFDetectorType type)
55
: Named(id), myLaneID(laneID), myPosition(pos), myType(type), myRoutes(nullptr) {}
56
57
58
RODFDetector::RODFDetector(const std::string& id, const RODFDetector& f)
59
: Named(id), myLaneID(f.myLaneID), myPosition(f.myPosition),
60
myType(f.myType), myRoutes(nullptr) {
61
if (f.myRoutes != nullptr) {
62
myRoutes = new RODFRouteCont(*(f.myRoutes));
63
}
64
}
65
66
67
RODFDetector::~RODFDetector() {
68
delete myRoutes;
69
}
70
71
72
void
73
RODFDetector::setType(RODFDetectorType type) {
74
myType = type;
75
}
76
77
78
double
79
RODFDetector::computeDistanceFactor(const RODFRouteDesc& rd) const {
80
double distance = rd.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(rd.edges2Pass.back()->getToJunction()->getPosition());
81
double length = 0;
82
for (ROEdgeVector::const_iterator i = rd.edges2Pass.begin(); i != rd.edges2Pass.end(); ++i) {
83
length += (*i)->getLength();
84
}
85
return (distance / length);
86
}
87
88
89
void
90
RODFDetector::computeSplitProbabilities(const RODFNet* net, const RODFDetectorCon& detectors,
91
const RODFDetectorFlows& flows,
92
SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset) {
93
if (myRoutes == nullptr) {
94
return;
95
}
96
// compute edges to determine split probabilities
97
const std::vector<RODFRouteDesc>& routes = myRoutes->get();
98
std::vector<RODFEdge*> nextDetEdges;
99
std::set<ROEdge*> preSplitEdges;
100
for (std::vector<RODFRouteDesc>::const_iterator i = routes.begin(); i != routes.end(); ++i) {
101
const RODFRouteDesc& rd = *i;
102
bool hadSplit = false;
103
for (ROEdgeVector::const_iterator j = rd.edges2Pass.begin(); j != rd.edges2Pass.end(); ++j) {
104
if (hadSplit && net->hasDetector(*j)) {
105
if (find(nextDetEdges.begin(), nextDetEdges.end(), *j) == nextDetEdges.end()) {
106
nextDetEdges.push_back(static_cast<RODFEdge*>(*j));
107
}
108
myRoute2Edge[rd.routename] = static_cast<RODFEdge*>(*j);
109
break;
110
}
111
if (!hadSplit) {
112
preSplitEdges.insert(*j);
113
}
114
if ((*j)->getNumSuccessors() > 1) {
115
hadSplit = true;
116
}
117
}
118
}
119
std::map<ROEdge*, double> inFlows;
120
if (OptionsCont::getOptions().getBool("respect-concurrent-inflows")) {
121
for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
122
std::set<ROEdge*> seen(preSplitEdges);
123
ROEdgeVector pending;
124
pending.push_back(*i);
125
seen.insert(*i);
126
while (!pending.empty()) {
127
ROEdge* e = pending.back();
128
pending.pop_back();
129
for (ROEdgeVector::const_iterator it = e->getPredecessors().begin(); it != e->getPredecessors().end(); it++) {
130
ROEdge* e2 = *it;
131
if (e2->getNumSuccessors() == 1 && seen.count(e2) == 0) {
132
if (net->hasDetector(e2)) {
133
inFlows[*i] += detectors.getAggFlowFor(e2, 0, 0, flows);
134
} else {
135
pending.push_back(e2);
136
}
137
seen.insert(e2);
138
}
139
}
140
}
141
}
142
}
143
// compute the probabilities to use a certain direction
144
int index = 0;
145
for (SUMOTime time = startTime; time < endTime; time += stepOffset, ++index) {
146
mySplitProbabilities.push_back(std::map<RODFEdge*, double>());
147
double overallProb = 0;
148
// retrieve the probabilities
149
for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
150
double flow = detectors.getAggFlowFor(*i, time, 60, flows) - inFlows[*i];
151
overallProb += flow;
152
mySplitProbabilities[index][*i] = flow;
153
}
154
// norm probabilities
155
if (overallProb > 0) {
156
for (std::vector<RODFEdge*>::const_iterator i = nextDetEdges.begin(); i != nextDetEdges.end(); ++i) {
157
mySplitProbabilities[index][*i] = mySplitProbabilities[index][*i] / overallProb;
158
}
159
}
160
}
161
}
162
163
164
void
165
RODFDetector::buildDestinationDistribution(const RODFDetectorCon& detectors,
166
SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset,
167
const RODFNet& net,
168
std::map<SUMOTime, RandomDistributor<int>* >& into) const {
169
if (myRoutes == nullptr) {
170
if (myType != DISCARDED_DETECTOR && myType != BETWEEN_DETECTOR) {
171
WRITE_ERRORF(TL("Missing routes for detector '%'."), myID);
172
}
173
return;
174
}
175
std::vector<RODFRouteDesc>& descs = myRoutes->get();
176
// iterate through time (in output interval steps)
177
for (SUMOTime time = startTime; time < endTime; time += stepOffset) {
178
into[time] = new RandomDistributor<int>();
179
std::map<ROEdge*, double> flowMap;
180
// iterate through the routes
181
int index = 0;
182
for (std::vector<RODFRouteDesc>::iterator ri = descs.begin(); ri != descs.end(); ++ri, index++) {
183
double prob = 1.;
184
for (ROEdgeVector::iterator j = (*ri).edges2Pass.begin(); j != (*ri).edges2Pass.end() && prob > 0;) {
185
if (!net.hasDetector(*j)) {
186
++j;
187
continue;
188
}
189
const RODFDetector& det = detectors.getAnyDetectorForEdge(static_cast<RODFEdge*>(*j));
190
const std::vector<std::map<RODFEdge*, double> >& probs = det.getSplitProbabilities();
191
if (probs.size() == 0) {
192
prob = 0;
193
++j;
194
continue;
195
}
196
const std::map<RODFEdge*, double>& tprobs = probs[(int)((time - startTime) / stepOffset)];
197
RODFEdge* splitEdge = nullptr;
198
for (std::map<RODFEdge*, double>::const_iterator k = tprobs.begin(); k != tprobs.end(); ++k) {
199
if (find(j, (*ri).edges2Pass.end(), (*k).first) != (*ri).edges2Pass.end()) {
200
prob *= (*k).second;
201
splitEdge = (*k).first;
202
break;
203
}
204
}
205
if (splitEdge != nullptr) {
206
j = std::find(j, (*ri).edges2Pass.end(), splitEdge);
207
} else {
208
++j;
209
}
210
}
211
into[time]->add(index, prob);
212
(*ri).overallProb = prob;
213
}
214
}
215
}
216
217
218
const std::vector<RODFRouteDesc>&
219
RODFDetector::getRouteVector() const {
220
return myRoutes->get();
221
}
222
223
224
void
225
RODFDetector::addPriorDetector(const RODFDetector* det) {
226
myPriorDetectors.insert(det);
227
}
228
229
230
void
231
RODFDetector::addFollowingDetector(const RODFDetector* det) {
232
myFollowingDetectors.insert(det);
233
}
234
235
236
const std::set<const RODFDetector*>&
237
RODFDetector::getPriorDetectors() const {
238
return myPriorDetectors;
239
}
240
241
242
const std::set<const RODFDetector*>&
243
RODFDetector::getFollowerDetectors() const {
244
return myFollowingDetectors;
245
}
246
247
248
249
void
250
RODFDetector::addRoutes(RODFRouteCont* routes) {
251
delete myRoutes;
252
myRoutes = routes;
253
}
254
255
256
void
257
RODFDetector::addRoute(RODFRouteDesc& nrd) {
258
if (myRoutes == nullptr) {
259
myRoutes = new RODFRouteCont();
260
}
261
myRoutes->addRouteDesc(nrd);
262
}
263
264
265
bool
266
RODFDetector::hasRoutes() const {
267
return myRoutes != nullptr && myRoutes->get().size() != 0;
268
}
269
270
271
bool
272
RODFDetector::writeEmitterDefinition(const std::string& file,
273
const std::map<SUMOTime, RandomDistributor<int>* >& dists,
274
const RODFDetectorFlows& flows,
275
SUMOTime startTime, SUMOTime endTime,
276
SUMOTime stepOffset,
277
bool includeUnusedRoutes,
278
double scale,
279
bool insertionsOnly,
280
double defaultSpeed) const {
281
OutputDevice& out = OutputDevice::getDevice(file);
282
OptionsCont& oc = OptionsCont::getOptions();
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();
289
out.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, myID);
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) {
298
out.openTag(SUMO_TAG_ROUTE).writeAttr(SUMO_ATTR_REFID, (*i).routename).writeAttr(SUMO_ATTR_PROB, 1.0).closeTag();
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
368
out.openTag(SUMO_TAG_VEHICLE);
369
out.writeAttr(SUMO_ATTR_ID, myID + "." + toString(vehicleIndex));
370
if (oc.getBool("vtype")) {
371
out.writeAttr(SUMO_ATTR_TYPE, vtype);
372
}
373
out.writeAttr(SUMO_ATTR_DEPART, time2string(ctime));
374
if (oc.isSet("departlane")) {
375
out.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));
376
} else {
377
out.writeAttr(SUMO_ATTR_DEPARTLANE, SUMOXMLDefinitions::getIndexFromLane(myLaneID));
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 {
394
out.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, posDesc);
395
}
396
} else {
397
out.writeAttr(SUMO_ATTR_DEPARTPOS, myPosition);
398
}
399
if (oc.isSet("departspeed")) {
400
out.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));
401
} else {
402
out.writeAttr(SUMO_ATTR_DEPARTSPEED, v);
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 {
416
out.writeAttr(SUMO_ATTR_ROUTE, myID);
417
}
418
out.closeTag();
419
srcFD.isLKW += srcFD.fLKW;
420
vehicleIndex++;
421
}
422
}
423
}
424
if (getType() != SOURCE_DETECTOR) {
425
out.close();
426
}
427
return true;
428
}
429
430
431
bool
432
RODFDetector::writeRoutes(std::vector<std::string>& saved,
433
OutputDevice& out) {
434
if (myRoutes != nullptr) {
435
return myRoutes->save(saved, "", out);
436
}
437
return false;
438
}
439
440
441
void
442
RODFDetector::writeSingleSpeedTrigger(const std::string& file,
443
const RODFDetectorFlows& flows,
444
SUMOTime startTime, SUMOTime endTime,
445
SUMOTime stepOffset, double defaultSpeed) {
446
OutputDevice& out = OutputDevice::getDevice(file);
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
}
459
out.openTag(SUMO_TAG_STEP).writeAttr(SUMO_ATTR_TIME, time2string(t)).writeAttr(SUMO_ATTR_SPEED, speed).closeTag();
460
}
461
out.close();
462
}
463
464
465
466
467
468
469
470
471
472
473
RODFDetectorCon::RODFDetectorCon() {}
474
475
476
RODFDetectorCon::~RODFDetectorCon() {
477
for (std::vector<RODFDetector*>::iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
478
delete *i;
479
}
480
}
481
482
483
bool
484
RODFDetectorCon::addDetector(RODFDetector* dfd) {
485
if (myDetectorMap.find(dfd->getID()) != myDetectorMap.end()) {
486
return false;
487
}
488
myDetectorMap[dfd->getID()] = dfd;
489
myDetectors.push_back(dfd);
490
const std::string edgeid = SUMOXMLDefinitions::getEdgeIDFromLane(dfd->getLaneID());
491
if (myDetectorEdgeMap.find(edgeid) == myDetectorEdgeMap.end()) {
492
myDetectorEdgeMap[edgeid] = std::vector<RODFDetector*>();
493
}
494
myDetectorEdgeMap[edgeid].push_back(dfd);
495
return true; // !!!
496
}
497
498
499
bool
500
RODFDetectorCon::detectorsHaveCompleteTypes() const {
501
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
502
if ((*i)->getType() == TYPE_NOT_DEFINED) {
503
return false;
504
}
505
}
506
return true;
507
}
508
509
510
bool
511
RODFDetectorCon::detectorsHaveRoutes() const {
512
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
513
if ((*i)->hasRoutes()) {
514
return true;
515
}
516
}
517
return false;
518
}
519
520
521
const std::vector< RODFDetector*>&
522
RODFDetectorCon::getDetectors() const {
523
return myDetectors;
524
}
525
526
527
void
528
RODFDetectorCon::save(const std::string& file) const {
529
OutputDevice& out = OutputDevice::getDevice(file);
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;
543
case DISCARDED_DETECTOR:
544
out.writeAttr(SUMO_ATTR_TYPE, "discarded");
545
break;
546
default:
547
throw 1;
548
}
549
out.closeTag();
550
}
551
out.close();
552
}
553
554
555
void
556
RODFDetectorCon::saveAsPOIs(const std::string& file) const {
557
OutputDevice& out = OutputDevice::getDevice(file);
558
out.writeXMLHeader("additional", "additional_file.xsd");
559
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
560
out.openTag(SUMO_TAG_POI).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML((*i)->getID()));
561
switch ((*i)->getType()) {
562
case BETWEEN_DETECTOR:
563
out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::BLUE);
564
break;
565
case SOURCE_DETECTOR:
566
out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::GREEN);
567
break;
568
case SINK_DETECTOR:
569
out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor::RED);
570
break;
571
case DISCARDED_DETECTOR:
572
out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
573
break;
574
default:
575
throw 1;
576
}
577
out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
578
}
579
out.close();
580
}
581
582
583
void
584
RODFDetectorCon::saveRoutes(const std::string& file) const {
585
OutputDevice& out = OutputDevice::getDevice(file);
586
out.writeXMLHeader("routes", "routes_file.xsd");
587
std::vector<std::string> saved;
588
// write for source detectors
589
bool lastWasSaved = true;
590
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
591
if ((*i)->getType() != SOURCE_DETECTOR) {
592
// do not build routes for other than sources
593
continue;
594
}
595
if (lastWasSaved) {
596
out << "\n";
597
}
598
lastWasSaved = (*i)->writeRoutes(saved, out);
599
}
600
out << "\n";
601
out.close();
602
}
603
604
605
const RODFDetector&
606
RODFDetectorCon::getDetector(const std::string& id) const {
607
return *(myDetectorMap.find(id)->second);
608
}
609
610
611
RODFDetector&
612
RODFDetectorCon::getModifiableDetector(const std::string& id) const {
613
return *(myDetectorMap.find(id)->second);
614
}
615
616
617
bool
618
RODFDetectorCon::knows(const std::string& id) const {
619
return myDetectorMap.find(id) != myDetectorMap.end();
620
}
621
622
623
void
624
RODFDetectorCon::writeEmitters(const std::string& file,
625
const RODFDetectorFlows& flows,
626
SUMOTime startTime, SUMOTime endTime,
627
SUMOTime stepOffset, const RODFNet& net,
628
bool writeCalibrators,
629
bool includeUnusedRoutes,
630
double scale,
631
bool insertionsOnly) {
632
// compute turn probabilities at detector
633
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
634
(*i)->computeSplitProbabilities(&net, *this, flows, startTime, endTime, stepOffset);
635
}
636
//
637
OutputDevice& out = OutputDevice::getDevice(file);
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
649
SUMOVTypeParameter pkwType = SUMOVTypeParameter("PKW", SVC_PASSENGER);
650
setSpeedFactorAndDev(pkwType, net.getMaxSpeedFactorPKW(), net.getAvgSpeedFactorPKW(), speedDev, forceDev);
651
pkwType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
652
pkwType.write(vTypeOut);
653
SUMOVTypeParameter lkwType = SUMOVTypeParameter("LKW", SVC_TRUCK);
654
setSpeedFactorAndDev(lkwType, net.getMaxSpeedFactorLKW(), net.getAvgSpeedFactorLKW(), speedDev, forceDev);
655
lkwType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
656
lkwType.write(vTypeOut);
657
} else {
658
// patch default type
659
SUMOVTypeParameter type = SUMOVTypeParameter(DEFAULT_VTYPE_ID, SVC_PASSENGER);
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());
697
out.writeAttr(SUMO_ATTR_LANE, det->getLaneID()).writeAttr(SUMO_ATTR_FRIENDLY_POS, true).writeAttr(SUMO_ATTR_FILE, defFileName).closeTag();
698
}
699
}
700
out.close();
701
if (separateVTypeOutput) {
702
vTypeOut.close();
703
}
704
}
705
706
void
707
RODFDetectorCon::setSpeedFactorAndDev(SUMOVTypeParameter& type, double maxFactor, double avgFactor, double dev, bool forceDev) {
708
if (avgFactor > 1) {
709
// systematically low speeds can easily be caused by traffic
710
// conditions. Whereas elevated speeds probably reflect speeding
711
type.speedFactor.setParameter(0, avgFactor);
712
type.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
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.setParameter(1, dev);
718
type.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
719
} else {
720
type.speedFactor.setParameter(1, -1.); // do not write speedDev, only simple speedFactor
721
}
722
}
723
724
725
void
726
RODFDetectorCon::writeEmitterPOIs(const std::string& file,
727
const RODFDetectorFlows& flows) {
728
OutputDevice& out = OutputDevice::getDevice(file);
729
out.writeXMLHeader("additional", "additional_file.xsd");
730
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
731
RODFDetector* det = *i;
732
double flow = flows.getFlowSumSecure(det->getID());
733
const unsigned char col = static_cast<unsigned char>(128 * flow / flows.getMaxDetectorFlow() + 128);
734
out.openTag(SUMO_TAG_POI).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML((*i)->getID()) + ":" + toString(flow));
735
switch ((*i)->getType()) {
736
case BETWEEN_DETECTOR:
737
out.writeAttr(SUMO_ATTR_TYPE, "between_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, 0, col, 255));
738
break;
739
case SOURCE_DETECTOR:
740
out.writeAttr(SUMO_ATTR_TYPE, "source_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(0, col, 0, 255));
741
break;
742
case SINK_DETECTOR:
743
out.writeAttr(SUMO_ATTR_TYPE, "sink_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(col, 0, 0, 255));
744
break;
745
case DISCARDED_DETECTOR:
746
out.writeAttr(SUMO_ATTR_TYPE, "discarded_detector_position").writeAttr(SUMO_ATTR_COLOR, RGBColor(51, 51, 51, 255));
747
break;
748
default:
749
throw 1;
750
}
751
out.writeAttr(SUMO_ATTR_LANE, (*i)->getLaneID()).writeAttr(SUMO_ATTR_POSITION, (*i)->getPos()).closeTag();
752
}
753
out.close();
754
}
755
756
757
int
758
RODFDetectorCon::getAggFlowFor(const ROEdge* edge, SUMOTime time, SUMOTime period,
759
const RODFDetectorFlows&) const {
760
UNUSED_PARAMETER(period);
761
UNUSED_PARAMETER(time);
762
if (edge == nullptr) {
763
return 0;
764
}
765
// double stepOffset = 60; // !!!
766
// double startTime = 0; // !!!
767
// cout << edge->getID() << endl;
768
assert(myDetectorEdgeMap.find(edge->getID()) != myDetectorEdgeMap.end());
769
const std::vector<FlowDef>& flows = static_cast<const RODFEdge*>(edge)->getFlows();
770
double agg = 0;
771
for (std::vector<FlowDef>::const_iterator i = flows.begin(); i != flows.end(); ++i) {
772
const FlowDef& srcFD = *i;
773
if (srcFD.qLKW >= 0) {
774
agg += srcFD.qLKW;
775
}
776
if (srcFD.qPKW >= 0) {
777
agg += srcFD.qPKW;
778
}
779
}
780
return (int) agg;
781
/* !!! make this time variable
782
if (flows.size()!=0) {
783
double agg = 0;
784
int beginIndex = (int)((time/stepOffset) - startTime); // !!! falsch!!!
785
for (SUMOTime t=0; t<period&&beginIndex<flows.size(); t+=(SUMOTime) stepOffset) {
786
const FlowDef &srcFD = flows[beginIndex++];
787
if (srcFD.qLKW>=0) {
788
agg += srcFD.qLKW;
789
}
790
if (srcFD.qPKW>=0) {
791
agg += srcFD.qPKW;
792
}
793
}
794
return (int) agg;
795
}
796
*/
797
// return -1;
798
}
799
800
801
void
802
RODFDetectorCon::writeSpeedTrigger(const RODFNet* const net,
803
const std::string& file,
804
const RODFDetectorFlows& flows,
805
SUMOTime startTime, SUMOTime endTime,
806
SUMOTime stepOffset) {
807
OutputDevice& out = OutputDevice::getDevice(file);
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";
814
out.openTag(SUMO_TAG_VSS).writeAttr(SUMO_ATTR_ID, StringUtils::escapeXML(det->getID())).writeAttr(SUMO_ATTR_LANES, det->getLaneID()).writeAttr(SUMO_ATTR_FILE, filename).closeTag();
815
double defaultSpeed = net != nullptr ? net->getEdge(det->getEdgeID())->getSpeedLimit() : (double) 200.;
816
det->writeSingleSpeedTrigger(filename, flows, startTime, endTime, stepOffset, defaultSpeed);
817
}
818
}
819
out.close();
820
}
821
822
823
void
824
RODFDetectorCon::writeEndRerouterDetectors(const std::string& file) {
825
OutputDevice& out = OutputDevice::getDevice(file);
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
839
void
840
RODFDetectorCon::writeValidationDetectors(const std::string& file,
841
bool includeSources,
842
bool singleFile, bool friendly) {
843
OutputDevice& out = OutputDevice::getDevice(file);
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
}
853
out.openTag(SUMO_TAG_E1DETECTOR).writeAttr(SUMO_ATTR_ID, "validation_" + StringUtils::escapeXML(det->getID())).writeAttr(SUMO_ATTR_LANE, det->getLaneID());
854
out.writeAttr(SUMO_ATTR_POSITION, pos).writeAttr(SUMO_ATTR_PERIOD, 60);
855
if (friendly) {
856
out.writeAttr(SUMO_ATTR_FRIENDLY_POS, true);
857
}
858
if (!singleFile) {
859
out.writeAttr(SUMO_ATTR_FILE, "validation_det_" + StringUtils::escapeXML(det->getID()) + ".xml");
860
} else {
861
out.writeAttr(SUMO_ATTR_FILE, "validation_dets.xml");
862
}
863
out.closeTag();
864
}
865
}
866
out.close();
867
}
868
869
870
void
871
RODFDetectorCon::removeDetector(const std::string& id) {
872
//
873
std::map<std::string, RODFDetector*>::iterator ri1 = myDetectorMap.find(id);
874
RODFDetector* oldDet = (*ri1).second;
875
myDetectorMap.erase(ri1);
876
//
877
std::vector<RODFDetector*>::iterator ri2 =
878
std::find(myDetectors.begin(), myDetectors.end(), oldDet);
879
myDetectors.erase(ri2);
880
//
881
bool found = false;
882
for (std::map<std::string, std::vector<RODFDetector*> >::iterator rr3 = myDetectorEdgeMap.begin(); !found && rr3 != myDetectorEdgeMap.end(); ++rr3) {
883
std::vector<RODFDetector*>& dets = (*rr3).second;
884
for (std::vector<RODFDetector*>::iterator ri3 = dets.begin(); !found && ri3 != dets.end();) {
885
if (*ri3 == oldDet) {
886
found = true;
887
ri3 = dets.erase(ri3);
888
} else {
889
++ri3;
890
}
891
}
892
}
893
delete oldDet;
894
}
895
896
897
void
898
RODFDetectorCon::guessEmptyFlows(RODFDetectorFlows& flows) {
899
// routes must be built (we have ensured this in main)
900
// detector followers/prior must be build (we have ensured this in main)
901
//
902
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
903
RODFDetector* det = *i;
904
const std::set<const RODFDetector*>& prior = det->getPriorDetectors();
905
const std::set<const RODFDetector*>& follower = det->getFollowerDetectors();
906
int noFollowerWithRoutes = 0;
907
int noPriorWithRoutes = 0;
908
// count occurrences of detectors with/without routes
909
std::set<const RODFDetector*>::const_iterator j;
910
for (j = prior.begin(); j != prior.end(); ++j) {
911
if (flows.knows((*j)->getID())) {
912
++noPriorWithRoutes;
913
}
914
}
915
for (j = follower.begin(); j != follower.end(); ++j) {
916
if (flows.knows((*j)->getID())) {
917
++noFollowerWithRoutes;
918
}
919
}
920
921
// do not process detectors which have no routes
922
if (!flows.knows(det->getID())) {
923
continue;
924
}
925
926
// plain case: all of the prior detectors have routes
927
if (noPriorWithRoutes == (int)prior.size()) {
928
// the number of vehicles is the sum of all vehicles on prior
929
continue;
930
}
931
932
// plain case: all of the follower detectors have routes
933
if (noFollowerWithRoutes == (int)follower.size()) {
934
// the number of vehicles is the sum of all vehicles on follower
935
continue;
936
}
937
938
}
939
}
940
941
942
const RODFDetector&
943
RODFDetectorCon::getAnyDetectorForEdge(const RODFEdge* const edge) const {
944
for (std::vector<RODFDetector*>::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
945
if ((*i)->getEdgeID() == edge->getID()) {
946
return **i;
947
}
948
}
949
throw 1;
950
}
951
952
953
void
954
RODFDetectorCon::clearDists(std::map<SUMOTime, RandomDistributor<int>* >& dists) const {
955
for (std::map<SUMOTime, RandomDistributor<int>* >::iterator i = dists.begin(); i != dists.end(); ++i) {
956
delete (*i).second;
957
}
958
}
959
960
961
void
962
RODFDetectorCon::mesoJoin(const std::string& nid,
963
const std::vector<std::string>& oldids) {
964
// build the new detector
965
const RODFDetector& first = getDetector(*(oldids.begin()));
966
RODFDetector* newDet = new RODFDetector(nid, first);
967
addDetector(newDet);
968
// delete previous
969
for (std::vector<std::string>::const_iterator i = oldids.begin(); i != oldids.end(); ++i) {
970
removeDetector(*i);
971
}
972
}
973
974
975
std::string
976
RODFDetector::getEdgeID() const {
977
return SUMOXMLDefinitions::getEdgeIDFromLane(myLaneID);
978
}
979
980
/****************************************************************************/
981
982