Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netload/NLDetectorBuilder.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2002-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 NLDetectorBuilder.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Laura Bieker
17
/// @author Clemens Honomichl
18
/// @author Michael Behrisch
19
/// @author Christian Roessel
20
/// @author Jakob Erdmann
21
/// @date Mon, 15 Apr 2002
22
///
23
// Builds detectors for microsim
24
/****************************************************************************/
25
#include <config.h>
26
27
#include <string>
28
#include <iostream>
29
#include <microsim/MSNet.h>
30
#include <microsim/MSLane.h>
31
#include <microsim/MSEdge.h>
32
#include <microsim/output/MSInductLoop.h>
33
#include <microsim/output/MSE2Collector.h>
34
// #include <microsim/output/MSMultiLaneE2Collector.h>
35
#include <microsim/output/MSVTypeProbe.h>
36
#include <microsim/output/MSRouteProbe.h>
37
#include <microsim/output/MSMeanData_Net.h>
38
#include <microsim/output/MSMeanData_Emissions.h>
39
#include <microsim/output/MSMeanData_Harmonoise.h>
40
#include <microsim/output/MSMeanData_Amitran.h>
41
#include <microsim/output/MSInstantInductLoop.h>
42
#include <microsim/MSGlobals.h>
43
#include <microsim/actions/Command_SaveTLCoupledDet.h>
44
#include <microsim/actions/Command_SaveTLCoupledLaneDet.h>
45
#include <utils/common/UtilExceptions.h>
46
#include <utils/common/FileHelpers.h>
47
#include <utils/common/StringUtils.h>
48
#include <utils/common/StringTokenizer.h>
49
#include <utils/common/StringUtils.h>
50
#include "NLDetectorBuilder.h"
51
#include <microsim/output/MSDetectorControl.h>
52
53
#include <mesosim/MEInductLoop.h>
54
#include <mesosim/MELoop.h>
55
#include <mesosim/MESegment.h>
56
57
58
// ===========================================================================
59
// method definitions
60
// ===========================================================================
61
/* -------------------------------------------------------------------------
62
* NLDetectorBuilder::E3DetectorDefinition-methods
63
* ----------------------------------------------------------------------- */
64
NLDetectorBuilder::E3DetectorDefinition::E3DetectorDefinition(const std::string& id,
65
const std::string& device, double haltingSpeedThreshold,
66
SUMOTime haltingTimeThreshold, SUMOTime splInterval,
67
const std::string name, const std::string& vTypes,
68
const std::string& nextEdges,
69
int detectPersons, bool openEntry, bool expectArrival) :
70
myID(id), myDevice(device),
71
myHaltingSpeedThreshold(haltingSpeedThreshold),
72
myHaltingTimeThreshold(haltingTimeThreshold),
73
mySampleInterval(splInterval),
74
myName(name),
75
myVehicleTypes(vTypes),
76
myNextEdges(nextEdges),
77
myDetectPersons(detectPersons),
78
myOpenEntry(openEntry),
79
myExpectArrival(expectArrival) {
80
}
81
82
83
NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
84
85
86
/* -------------------------------------------------------------------------
87
* NLDetectorBuilder-methods
88
* ----------------------------------------------------------------------- */
89
NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
90
: myNet(net), myE3Definition(nullptr) {}
91
92
93
NLDetectorBuilder::~NLDetectorBuilder() {
94
delete myE3Definition;
95
}
96
97
98
Parameterised*
99
NLDetectorBuilder::buildInductLoop(const std::string& id,
100
const std::string& lane, double pos, double length, SUMOTime splInterval,
101
const std::string& device, bool friendlyPos,
102
const std::string name,
103
const std::string& vTypes,
104
const std::string& nextEdges,
105
int detectPersons) {
106
checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
107
// get and check the lane
108
MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
109
// get and check the position
110
pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
111
if (length < 0) {
112
throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
113
} else if (length > 0 && pos + length > clane->getLength()) {
114
if (friendlyPos) {
115
length = MIN2(length, clane->getLength());
116
pos = clane->getLength() - length;
117
} else {
118
throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' puts it beyond the lane's '" + clane->getID() + "' end.");
119
}
120
}
121
// build the loop
122
MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true);
123
// add the file output
124
myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
125
return loop;
126
}
127
128
129
Parameterised*
130
NLDetectorBuilder::buildInstantInductLoop(const std::string& id,
131
const std::string& lane, double pos,
132
const std::string& device, bool friendlyPos,
133
const std::string name,
134
const std::string& vTypes,
135
const std::string& nextEdges) {
136
// get and check the lane
137
MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
138
// get and check the position
139
pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
140
// build the loop
141
MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges);
142
// add the file output
143
myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
144
return loop;
145
}
146
147
148
Parameterised*
149
NLDetectorBuilder::buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,
150
const std::string& device, SUMOTime frequency,
151
SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
152
const std::string name, const std::string& vTypes,
153
const std::string& nextEdges,
154
int detectPersons, bool friendlyPos, bool showDetector,
155
MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
156
157
bool tlsGiven = tlls != nullptr;
158
bool toLaneGiven = toLane != nullptr;
159
bool posGiven = pos != std::numeric_limits<double>::max();
160
bool endPosGiven = endPos != std::numeric_limits<double>::max();
161
162
assert(posGiven || endPosGiven);
163
164
// Check positioning
165
if (posGiven) {
166
if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
167
std::stringstream ss;
168
ss << "The given position (=" << pos << ") for detector '" << id
169
<< "' does not lie on the given lane '" << lane->getID()
170
<< "' with length " << lane->getLength();
171
if (friendlyPos) {
172
double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
173
ss << " (adjusting to new position " << newPos;
174
WRITE_WARNING(ss.str());
175
pos = newPos;
176
} else {
177
ss << " (0 <= pos < lane->getLength() is required)";
178
throw InvalidArgument(ss.str());
179
}
180
}
181
}
182
if (endPosGiven) {
183
if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
184
std::stringstream ss;
185
ss << "The given end position (=" << endPos << ") for detector '" << id
186
<< "' does not lie on the given lane '" << lane->getID()
187
<< "' with length " << lane->getLength();
188
if (friendlyPos) {
189
double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
190
ss << " (adjusting to new position " << newEndPos;
191
WRITE_WARNING(ss.str());
192
pos = newEndPos;
193
} else {
194
ss << " (0 <= pos < lane->getLength() is required)";
195
throw InvalidArgument(ss.str());
196
}
197
}
198
}
199
200
MSE2Collector* det = nullptr;
201
if (tlsGiven) {
202
// Detector connected to TLS
203
det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
204
myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
205
// add the file output (XXX: Where's the corresponding delete?)
206
if (toLaneGiven) {
207
// Detector also associated to specific link
208
const MSLane* const lastLane = det->getLastLane();
209
const MSLink* const link = lastLane->getLinkTo(toLane);
210
if (link == nullptr) {
211
throw InvalidArgument(
212
"The detector '" + id + "' cannot be build as no connection between lanes '"
213
+ lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
214
}
215
new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
216
} else {
217
// detector for tls but without specific link
218
new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
219
}
220
} else {
221
// User specified detector for xml-output
222
checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
223
det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
224
myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
225
}
226
return det;
227
}
228
229
230
Parameterised*
231
NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,
232
const std::string& device, SUMOTime frequency,
233
SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
234
const std::string name, const std::string& vTypes,
235
const std::string& nextEdges,
236
int detectPersons, bool friendlyPos, bool showDetector,
237
MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
238
239
bool tlsGiven = tlls != nullptr;
240
bool toLaneGiven = toLane != nullptr;
241
assert(pos != std::numeric_limits<double>::max());
242
assert(endPos != std::numeric_limits<double>::max());
243
assert(lanes.size() != 0);
244
245
const MSLane* const firstLane = lanes[0];
246
const MSLane* const lastLane = lanes.back();
247
248
// Check positioning
249
if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
250
std::stringstream ss;
251
ss << "The given position (=" << pos << ") for detector '" << id
252
<< "' does not lie on the given lane '" << firstLane->getID()
253
<< "' with length " << firstLane->getLength();
254
if (friendlyPos) {
255
double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
256
ss << " (adjusting to new position " << newPos;
257
WRITE_WARNING(ss.str());
258
pos = newPos;
259
} else {
260
ss << " (0 <= pos < lane->getLength() is required)";
261
throw InvalidArgument(ss.str());
262
}
263
}
264
if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
265
std::stringstream ss;
266
ss << "The given end position (=" << endPos << ") for detector '" << id
267
<< "' does not lie on the given lane '" << lastLane->getID()
268
<< "' with length " << lastLane->getLength();
269
if (friendlyPos) {
270
double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
271
ss << " (adjusting to new position " << newEndPos;
272
WRITE_WARNING(ss.str());
273
pos = newEndPos;
274
} else {
275
ss << " (0 <= pos < lane->getLength() is required)";
276
throw InvalidArgument(ss.str());
277
}
278
}
279
280
MSE2Collector* det = nullptr;
281
if (tlsGiven) {
282
// Detector connected to TLS
283
det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
284
myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
285
// add the file output (XXX: Where's the corresponding delete?)
286
if (toLaneGiven) {
287
// Detector also associated to specific link
288
const MSLane* const lastDetLane = det->getLastLane();
289
const MSLink* const link = lastDetLane->getLinkTo(toLane);
290
if (link == nullptr) {
291
throw InvalidArgument(
292
"The detector '" + id + "' cannot be build as no connection between lanes '"
293
+ lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
294
}
295
new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
296
} else {
297
// detector for tls but without specific link
298
new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
299
}
300
} else {
301
// User specified detector for xml-output
302
checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
303
304
det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
305
myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
306
}
307
return det;
308
}
309
310
311
312
Parameterised*
313
NLDetectorBuilder::beginE3Detector(const std::string& id,
314
const std::string& device, SUMOTime splInterval,
315
double haltingSpeedThreshold,
316
SUMOTime haltingTimeThreshold,
317
const std::string name,
318
const std::string& vTypes,
319
const std::string& nextEdges,
320
int detectPersons, bool openEntry, bool expectArrival) {
321
checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
322
myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
323
return myE3Definition;
324
}
325
326
327
void
328
NLDetectorBuilder::addE3Entry(const std::string& lane,
329
double pos, bool friendlyPos) {
330
if (myE3Definition == nullptr) {
331
return;
332
}
333
MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
334
// get and check the position
335
pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
336
// build and save the entry
337
myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
338
}
339
340
341
void
342
NLDetectorBuilder::addE3Exit(const std::string& lane,
343
double pos, bool friendlyPos) {
344
if (myE3Definition == nullptr) {
345
return;
346
}
347
MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
348
// get and check the position
349
pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
350
// build and save the exit
351
myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
352
}
353
354
355
std::string
356
NLDetectorBuilder::getCurrentE3ID() const {
357
if (myE3Definition == nullptr) {
358
return "<unknown>";
359
}
360
return myE3Definition->myID;
361
}
362
363
364
void
365
NLDetectorBuilder::endE3Detector() {
366
if (myE3Definition == nullptr) {
367
return;
368
}
369
// If E3 own entry or exit detectors
370
if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
371
// create E3 detector
372
MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
373
myE3Definition->myEntries, myE3Definition->myExits,
374
myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
375
myE3Definition->myName,
376
myE3Definition->myVehicleTypes,
377
myE3Definition->myNextEdges,
378
myE3Definition->myDetectPersons,
379
myE3Definition->myOpenEntry,
380
myE3Definition->myExpectArrival);
381
det->updateParameters(myE3Definition->getParametersMap());
382
// add to net
383
myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
384
} else {
385
WRITE_WARNING(toString(SUMO_TAG_E3DETECTOR) + " with id = '" + myE3Definition->myID + "' will not be created because is empty (no " + toString(SUMO_TAG_DET_ENTRY) + " or " + toString(SUMO_TAG_DET_EXIT) + " was defined)")
386
}
387
// clean up
388
delete myE3Definition;
389
myE3Definition = nullptr;
390
}
391
392
393
void
394
NLDetectorBuilder::buildVTypeProbe(const std::string& id,
395
const std::string& vtype, SUMOTime frequency,
396
const std::string& device) {
397
checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
398
new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
399
}
400
401
402
void
403
NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
404
SUMOTime frequency, SUMOTime begin,
405
const std::string& device,
406
const std::string& vTypes) {
407
checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
408
MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
409
MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
410
// add the file output
411
myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
412
}
413
414
415
MSDetectorFileOutput*
416
NLDetectorBuilder::createInductLoop(const std::string& id,
417
MSLane* lane, double pos,
418
double length,
419
const std::string name,
420
const std::string& vTypes,
421
const std::string& nextEdges,
422
int detectPersons,
423
bool /*show*/) {
424
if (MSGlobals::gUseMesoSim) {
425
return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
426
}
427
return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
428
}
429
430
431
MSDetectorFileOutput*
432
NLDetectorBuilder::createInstantInductLoop(const std::string& id,
433
MSLane* lane, double pos, const std::string& od,
434
const std::string name, const std::string& vTypes,
435
const std::string& nextEdges) {
436
return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges);
437
}
438
439
440
MSE2Collector*
441
NLDetectorBuilder::createE2Detector(const std::string& id,
442
DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,
443
SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
444
const std::string name, const std::string& vTypes,
445
const std::string& nextEdges,
446
int detectPersons, bool /* showDetector */) {
447
return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
448
}
449
450
MSE2Collector*
451
NLDetectorBuilder::createE2Detector(const std::string& id,
452
DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,
453
SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
454
const std::string name, const std::string& vTypes,
455
const std::string& nextEdges,
456
int detectPersons, bool /* showDetector */) {
457
return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
458
}
459
460
MSDetectorFileOutput*
461
NLDetectorBuilder::createE3Detector(const std::string& id,
462
const CrossSectionVector& entries,
463
const CrossSectionVector& exits,
464
double haltingSpeedThreshold,
465
SUMOTime haltingTimeThreshold,
466
const std::string name, const std::string& vTypes,
467
const std::string& nextEdges,
468
int detectPersons,
469
bool openEntry,
470
bool expectArrival) {
471
return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
472
}
473
474
475
double
476
NLDetectorBuilder::getPositionChecking(double pos, MSLane* lane, bool friendlyPos,
477
SumoXMLTag tag,
478
const std::string& detid) {
479
// check whether it is given from the end
480
if (pos < 0) {
481
pos += lane->getLength();
482
}
483
// check whether it is on the lane
484
if (pos > lane->getLength()) {
485
if (friendlyPos) {
486
pos = lane->getLength();
487
} else {
488
throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
489
}
490
}
491
if (pos < 0) {
492
if (friendlyPos) {
493
pos = 0.;
494
} else {
495
throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
496
}
497
}
498
return pos;
499
}
500
501
502
void
503
NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
504
SUMOTime begin, SUMOTime end, const std::string& type,
505
const bool useLanes, const bool withEmpty, const bool printDefaults,
506
const bool withInternal, const bool trackVehicles, const int detectPersons,
507
const double maxTravelTime, const double minSamples,
508
const double haltSpeed, const std::string& vTypes,
509
const std::string& writeAttributes,
510
std::vector<MSEdge*> edges,
511
bool aggregate,
512
const std::string& device) {
513
if (begin < 0) {
514
throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
515
}
516
if (end < 0) {
517
end = SUMOTime_MAX;
518
}
519
if (end <= begin) {
520
throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
521
}
522
checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
523
MSMeanData* det = nullptr;
524
if (type == "" || type == "performance" || type == "traffic") {
525
det = new MSMeanData_Net(id, begin, end, useLanes, withEmpty,
526
printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
527
} else if (type == "emissions" || type == "hbefa") {
528
if (type == "hbefa") {
529
WRITE_WARNING(TL("The netstate type 'hbefa' is deprecated. Please use the type 'emissions' instead."));
530
}
531
det = new MSMeanData_Emissions(id, begin, end, useLanes, withEmpty,
532
printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
533
} else if (type == "harmonoise") {
534
det = new MSMeanData_Harmonoise(id, begin, end, useLanes, withEmpty,
535
printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
536
} else if (type == "amitran") {
537
det = new MSMeanData_Amitran(id, begin, end, useLanes, withEmpty,
538
printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
539
} else {
540
throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
541
}
542
if (det != nullptr) {
543
if (frequency < 0) {
544
frequency = end - begin;
545
} else {
546
checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
547
}
548
MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
549
}
550
}
551
552
553
554
555
// ------ Value checking/adapting methods ------
556
MSEdge*
557
NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
558
const std::string& detid) {
559
// get and check the lane
560
MSEdge* edge = MSEdge::dictionary(edgeID);
561
if (edge == nullptr) {
562
throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
563
}
564
return edge;
565
}
566
567
568
MSLane*
569
NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
570
const std::string& detid) {
571
// get and check the lane
572
MSLane* lane = MSLane::dictionary(laneID);
573
if (lane == nullptr) {
574
throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
575
}
576
return lane;
577
}
578
579
580
void
581
NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
582
if (splInterval < 0) {
583
throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
584
}
585
if (splInterval == 0) {
586
throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
587
}
588
checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
589
}
590
591
592
/****************************************************************************/
593
594