Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-2026 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 1408 : 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 1408 : int detectPersons, bool openEntry, bool expectArrival) :
70 1408 : myID(id), myDevice(device),
71 1408 : myHaltingSpeedThreshold(haltingSpeedThreshold),
72 1408 : myHaltingTimeThreshold(haltingTimeThreshold),
73 1408 : mySampleInterval(splInterval),
74 1408 : myName(name),
75 1408 : myVehicleTypes(vTypes),
76 1408 : myNextEdges(nextEdges),
77 1408 : myDetectPersons(detectPersons),
78 1408 : myOpenEntry(openEntry),
79 1408 : myExpectArrival(expectArrival) {
80 1408 : }
81 :
82 :
83 2816 : NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
84 :
85 :
86 : /* -------------------------------------------------------------------------
87 : * NLDetectorBuilder-methods
88 : * ----------------------------------------------------------------------- */
89 41274 : NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
90 41274 : : myNet(net), myE3Definition(nullptr) {}
91 :
92 :
93 41274 : NLDetectorBuilder::~NLDetectorBuilder() {
94 41274 : delete myE3Definition;
95 41274 : }
96 :
97 :
98 : Parameterised*
99 24571 : 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 24571 : checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
107 : // get and check the lane
108 24565 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
109 : // get and check the position
110 24546 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
111 24540 : if (length < 0) {
112 0 : throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
113 24540 : } else if (length > 0 && pos + length > clane->getLength()) {
114 6 : if (friendlyPos) {
115 : length = MIN2(length, clane->getLength());
116 6 : pos = clane->getLength() - length;
117 : } else {
118 0 : 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 24540 : MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true);
123 : // add the file output
124 24534 : myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
125 24528 : return loop;
126 : }
127 :
128 :
129 : Parameterised*
130 1039 : 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 : int detectPersons) {
137 : // get and check the lane
138 1039 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
139 : // get and check the position
140 1035 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
141 : // build the loop
142 1031 : MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges, detectPersons);
143 : // add the file output
144 1027 : myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
145 1027 : return loop;
146 : }
147 :
148 :
149 : Parameterised*
150 3816 : NLDetectorBuilder::buildE2Detector(const std::string& id, MSLane* lane, double pos, double endPos, double length,
151 : const std::string& device, SUMOTime frequency,
152 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
153 : const std::string name, const std::string& vTypes,
154 : const std::string& nextEdges,
155 : int detectPersons, bool friendlyPos, bool showDetector,
156 : MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
157 :
158 : bool tlsGiven = tlls != nullptr;
159 : bool toLaneGiven = toLane != nullptr;
160 : bool posGiven = pos != std::numeric_limits<double>::max();
161 : bool endPosGiven = endPos != std::numeric_limits<double>::max();
162 :
163 : assert(posGiven || endPosGiven);
164 :
165 : // Check positioning
166 3816 : if (posGiven) {
167 2710 : if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
168 5 : std::stringstream ss;
169 : ss << "The given position (=" << pos << ") for detector '" << id
170 : << "' does not lie on the given lane '" << lane->getID()
171 : << "' with length " << lane->getLength();
172 5 : if (friendlyPos) {
173 1 : double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
174 : ss << " (adjusting to new position " << newPos;
175 1 : WRITE_WARNING(ss.str());
176 : pos = newPos;
177 : } else {
178 4 : ss << " (0 <= pos < lane->getLength() is required)";
179 12 : throw InvalidArgument(ss.str());
180 : }
181 5 : }
182 : }
183 3812 : if (endPosGiven) {
184 1135 : if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
185 0 : std::stringstream ss;
186 : ss << "The given end position (=" << endPos << ") for detector '" << id
187 : << "' does not lie on the given lane '" << lane->getID()
188 : << "' with length " << lane->getLength();
189 0 : if (friendlyPos) {
190 0 : double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
191 : ss << " (adjusting to new position " << newEndPos;
192 0 : WRITE_WARNING(ss.str());
193 : pos = newEndPos;
194 : } else {
195 0 : ss << " (0 <= pos < lane->getLength() is required)";
196 0 : throw InvalidArgument(ss.str());
197 : }
198 0 : }
199 : }
200 :
201 : MSE2Collector* det = nullptr;
202 3812 : if (tlsGiven) {
203 : // Detector connected to TLS
204 554 : det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
205 554 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
206 : // add the file output (XXX: Where's the corresponding delete?)
207 554 : if (toLaneGiven) {
208 : // Detector also associated to specific link
209 : const MSLane* const lastLane = det->getLastLane();
210 8 : const MSLink* const link = lastLane->getLinkTo(toLane);
211 8 : if (link == nullptr) {
212 : throw InvalidArgument(
213 0 : "The detector '" + id + "' cannot be build as no connection between lanes '"
214 0 : + lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
215 : }
216 8 : new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
217 : } else {
218 : // detector for tls but without specific link
219 546 : new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
220 : }
221 : } else {
222 : // User specified detector for xml-output
223 3258 : checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
224 3254 : det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
225 3254 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
226 : }
227 3804 : return det;
228 : }
229 :
230 :
231 : Parameterised*
232 252 : NLDetectorBuilder::buildE2Detector(const std::string& id, std::vector<MSLane*> lanes, double pos, double endPos,
233 : const std::string& device, SUMOTime frequency,
234 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
235 : const std::string name, const std::string& vTypes,
236 : const std::string& nextEdges,
237 : int detectPersons, bool friendlyPos, bool showDetector,
238 : MSTLLogicControl::TLSLogicVariants* tlls, MSLane* toLane) {
239 :
240 : bool tlsGiven = tlls != nullptr;
241 : bool toLaneGiven = toLane != nullptr;
242 : assert(pos != std::numeric_limits<double>::max());
243 : assert(endPos != std::numeric_limits<double>::max());
244 : assert(lanes.size() != 0);
245 :
246 252 : const MSLane* const firstLane = lanes[0];
247 252 : const MSLane* const lastLane = lanes.back();
248 :
249 : // Check positioning
250 252 : if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
251 1 : std::stringstream ss;
252 : ss << "The given position (=" << pos << ") for detector '" << id
253 : << "' does not lie on the given lane '" << firstLane->getID()
254 : << "' with length " << firstLane->getLength();
255 1 : if (friendlyPos) {
256 1 : double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
257 : ss << " (adjusting to new position " << newPos;
258 1 : WRITE_WARNING(ss.str());
259 : pos = newPos;
260 : } else {
261 0 : ss << " (0 <= pos < lane->getLength() is required)";
262 0 : throw InvalidArgument(ss.str());
263 : }
264 1 : }
265 252 : if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
266 1 : std::stringstream ss;
267 : ss << "The given end position (=" << endPos << ") for detector '" << id
268 : << "' does not lie on the given lane '" << lastLane->getID()
269 : << "' with length " << lastLane->getLength();
270 1 : if (friendlyPos) {
271 1 : double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
272 : ss << " (adjusting to new position " << newEndPos;
273 1 : WRITE_WARNING(ss.str());
274 : pos = newEndPos;
275 : } else {
276 0 : ss << " (0 <= pos < lane->getLength() is required)";
277 0 : throw InvalidArgument(ss.str());
278 : }
279 1 : }
280 :
281 : MSE2Collector* det = nullptr;
282 252 : if (tlsGiven) {
283 : // Detector connected to TLS
284 3 : det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
285 3 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
286 : // add the file output (XXX: Where's the corresponding delete?)
287 3 : if (toLaneGiven) {
288 : // Detector also associated to specific link
289 : const MSLane* const lastDetLane = det->getLastLane();
290 0 : const MSLink* const link = lastDetLane->getLinkTo(toLane);
291 0 : if (link == nullptr) {
292 : throw InvalidArgument(
293 0 : "The detector '" + id + "' cannot be build as no connection between lanes '"
294 0 : + lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
295 : }
296 0 : new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
297 : } else {
298 : // detector for tls but without specific link
299 3 : new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
300 : }
301 : } else {
302 : // User specified detector for xml-output
303 249 : checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
304 :
305 255 : det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
306 243 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
307 : }
308 246 : return det;
309 : }
310 :
311 :
312 :
313 : Parameterised*
314 1412 : NLDetectorBuilder::beginE3Detector(const std::string& id,
315 : const std::string& device, SUMOTime splInterval,
316 : double haltingSpeedThreshold,
317 : SUMOTime haltingTimeThreshold,
318 : const std::string name,
319 : const std::string& vTypes,
320 : const std::string& nextEdges,
321 : int detectPersons, bool openEntry, bool expectArrival) {
322 1412 : checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
323 2816 : myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
324 1408 : return myE3Definition;
325 : }
326 :
327 :
328 : void
329 1738 : NLDetectorBuilder::addE3Entry(const std::string& lane,
330 : double pos, bool friendlyPos) {
331 1738 : if (myE3Definition == nullptr) {
332 : return;
333 : }
334 1710 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
335 : // get and check the position
336 1706 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
337 : // build and save the entry
338 1702 : myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
339 : }
340 :
341 :
342 : void
343 1702 : NLDetectorBuilder::addE3Exit(const std::string& lane,
344 : double pos, bool friendlyPos) {
345 1702 : if (myE3Definition == nullptr) {
346 : return;
347 : }
348 1674 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
349 : // get and check the position
350 1670 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
351 : // build and save the exit
352 1666 : myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
353 : }
354 :
355 :
356 : std::string
357 10440 : NLDetectorBuilder::getCurrentE3ID() const {
358 10440 : if (myE3Definition == nullptr) {
359 168 : return "<unknown>";
360 : }
361 : return myE3Definition->myID;
362 : }
363 :
364 :
365 : void
366 1436 : NLDetectorBuilder::endE3Detector() {
367 1436 : if (myE3Definition == nullptr) {
368 : return;
369 : }
370 : // If E3 own entry or exit detectors
371 1408 : if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
372 : // create E3 detector
373 4200 : MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
374 1400 : myE3Definition->myEntries, myE3Definition->myExits,
375 1400 : myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
376 : myE3Definition->myName,
377 1400 : myE3Definition->myVehicleTypes,
378 1400 : myE3Definition->myNextEdges,
379 : myE3Definition->myDetectPersons,
380 1400 : myE3Definition->myOpenEntry,
381 1400 : myE3Definition->myExpectArrival);
382 1400 : det->updateParameters(myE3Definition->getParametersMap());
383 : // add to net
384 1400 : myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
385 : } else {
386 40 : 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)")
387 : }
388 : // clean up
389 1400 : delete myE3Definition;
390 1400 : myE3Definition = nullptr;
391 : }
392 :
393 :
394 : void
395 108 : NLDetectorBuilder::buildVTypeProbe(const std::string& id,
396 : const std::string& vtype, SUMOTime frequency,
397 : const std::string& device) {
398 108 : checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
399 96 : new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
400 90 : }
401 :
402 :
403 : void
404 479 : NLDetectorBuilder::buildRouteProbe(const std::string& id, const std::string& edge,
405 : SUMOTime frequency, SUMOTime begin,
406 : const std::string& device,
407 : const std::string& vTypes) {
408 479 : checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
409 479 : MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
410 1437 : MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
411 : // add the file output
412 479 : myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
413 479 : }
414 :
415 :
416 : MSDetectorFileOutput*
417 27011 : NLDetectorBuilder::createInductLoop(const std::string& id,
418 : MSLane* lane, double pos,
419 : double length,
420 : const std::string name,
421 : const std::string& vTypes,
422 : const std::string& nextEdges,
423 : int detectPersons,
424 : bool /*show*/) {
425 27011 : if (MSGlobals::gUseMesoSim) {
426 567 : return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
427 : }
428 53647 : return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
429 : }
430 :
431 :
432 : MSDetectorFileOutput*
433 908 : NLDetectorBuilder::createInstantInductLoop(const std::string& id,
434 : MSLane* lane, double pos, const std::string& od,
435 : const std::string name, const std::string& vTypes,
436 : const std::string& nextEdges,
437 : int detectPersons) {
438 1819 : return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges, detectPersons);
439 : }
440 :
441 :
442 : MSE2Collector*
443 5669 : NLDetectorBuilder::createE2Detector(const std::string& id,
444 : DetectorUsage usage, MSLane* lane, double pos, double endPos, double length,
445 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
446 : const std::string name, const std::string& vTypes,
447 : const std::string& nextEdges,
448 : int detectPersons, bool /* showDetector */) {
449 17007 : return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
450 : }
451 :
452 : MSE2Collector*
453 246 : NLDetectorBuilder::createE2Detector(const std::string& id,
454 : DetectorUsage usage, std::vector<MSLane*> lanes, double pos, double endPos,
455 : SUMOTime haltingTimeThreshold, double haltingSpeedThreshold, double jamDistThreshold,
456 : const std::string name, const std::string& vTypes,
457 : const std::string& nextEdges,
458 : int detectPersons, bool /* showDetector */) {
459 502 : return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
460 : }
461 :
462 : MSDetectorFileOutput*
463 1233 : NLDetectorBuilder::createE3Detector(const std::string& id,
464 : const CrossSectionVector& entries,
465 : const CrossSectionVector& exits,
466 : double haltingSpeedThreshold,
467 : SUMOTime haltingTimeThreshold,
468 : const std::string name, const std::string& vTypes,
469 : const std::string& nextEdges,
470 : int detectPersons,
471 : bool openEntry,
472 : bool expectArrival) {
473 3699 : return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
474 : }
475 :
476 :
477 : double
478 28957 : NLDetectorBuilder::getPositionChecking(double pos, MSLane* lane, bool friendlyPos,
479 : SumoXMLTag tag,
480 : const std::string& detid) {
481 : // check whether it is given from the end
482 28957 : if (pos < 0) {
483 2324 : pos += lane->getLength();
484 : }
485 : // check whether it is on the lane
486 28957 : if (pos > lane->getLength()) {
487 525 : if (friendlyPos) {
488 : pos = lane->getLength();
489 : } else {
490 54 : throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
491 : }
492 : }
493 28939 : if (pos < 0) {
494 178 : if (friendlyPos) {
495 : pos = 0.;
496 : } else {
497 0 : throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
498 : }
499 : }
500 28939 : return pos;
501 : }
502 :
503 :
504 : void
505 23326 : NLDetectorBuilder::createEdgeLaneMeanData(const std::string& id, SUMOTime frequency,
506 : SUMOTime begin, SUMOTime end, const std::string& type,
507 : const bool useLanes, const std::string& excludeEmpty,
508 : const bool withInternal, const bool trackVehicles, const int detectPersons,
509 : const double maxTravelTime, const double minSamples,
510 : const double haltSpeed, const std::string& vTypes,
511 : const std::string& writeAttributes,
512 : std::vector<MSEdge*> edges,
513 : AggregateType aggregate,
514 : const std::string& device) {
515 23326 : if (begin < 0) {
516 108 : throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
517 : }
518 23290 : if (end < 0) {
519 : end = SUMOTime_MAX;
520 : }
521 23290 : if (end <= begin) {
522 108 : throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
523 : }
524 46508 : checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
525 : MSMeanData* det = nullptr;
526 23254 : if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::DEFAULT)) ||
527 23254 : (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::TRAFFIC)) ||
528 23185 : (type == "performance")) {
529 : det = new MSMeanData_Net(id, begin, end, useLanes, excludeEmpty,
530 21927 : withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
531 1327 : } else if ((type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::EMISSIONS)) || (type == "hbefa")) {
532 891 : if (type == "hbefa") {
533 24 : WRITE_WARNING(TL("The netstate type 'hbefa' is deprecated. Please use the type 'emissions' instead."));
534 : }
535 : det = new MSMeanData_Emissions(id, begin, end, useLanes, excludeEmpty,
536 891 : withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
537 436 : } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::HARMONOISE)) {
538 : det = new MSMeanData_Harmonoise(id, begin, end, useLanes, excludeEmpty,
539 410 : withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
540 26 : } else if (type == SUMOXMLDefinitions::MeanDataTypes.getString(MeanDataType::AMITRAN)) {
541 : det = new MSMeanData_Amitran(id, begin, end, useLanes, excludeEmpty,
542 26 : withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
543 : } else {
544 0 : throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
545 : }
546 : if (det != nullptr) {
547 23254 : if (frequency < 0) {
548 19548 : frequency = end - begin;
549 : } else {
550 11118 : checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
551 : }
552 23254 : MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
553 : }
554 23254 : }
555 :
556 :
557 :
558 :
559 : // ------ Value checking/adapting methods ------
560 : MSEdge*
561 479 : NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
562 : const std::string& detid) {
563 : // get and check the lane
564 479 : MSEdge* edge = MSEdge::dictionary(edgeID);
565 479 : if (edge == nullptr) {
566 0 : throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
567 : }
568 479 : return edge;
569 : }
570 :
571 :
572 : MSLane*
573 32439 : NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
574 : const std::string& detid) {
575 : // get and check the lane
576 32439 : MSLane* lane = MSLane::dictionary(laneID);
577 32439 : if (lane == nullptr) {
578 156 : throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
579 : }
580 32400 : return lane;
581 : }
582 :
583 :
584 : void
585 30077 : NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
586 30077 : if (splInterval < 0) {
587 60 : throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
588 : }
589 30057 : if (splInterval == 0) {
590 18 : throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
591 : }
592 60102 : checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
593 30051 : }
594 :
595 :
596 : /****************************************************************************/
|