Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2002-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 : /****************************************************************************/
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 1369 : 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 1369 : int detectPersons, bool openEntry, bool expectArrival) :
70 1369 : myID(id), myDevice(device),
71 1369 : myHaltingSpeedThreshold(haltingSpeedThreshold),
72 1369 : myHaltingTimeThreshold(haltingTimeThreshold),
73 1369 : mySampleInterval(splInterval),
74 1369 : myName(name),
75 1369 : myVehicleTypes(vTypes),
76 1369 : myNextEdges(nextEdges),
77 1369 : myDetectPersons(detectPersons),
78 1369 : myOpenEntry(openEntry),
79 1369 : myExpectArrival(expectArrival) {
80 1369 : }
81 :
82 :
83 2738 : NLDetectorBuilder::E3DetectorDefinition::~E3DetectorDefinition() {}
84 :
85 :
86 : /* -------------------------------------------------------------------------
87 : * NLDetectorBuilder-methods
88 : * ----------------------------------------------------------------------- */
89 43044 : NLDetectorBuilder::NLDetectorBuilder(MSNet& net)
90 43044 : : myNet(net), myE3Definition(nullptr) {}
91 :
92 :
93 43044 : NLDetectorBuilder::~NLDetectorBuilder() {
94 43044 : delete myE3Definition;
95 43044 : }
96 :
97 :
98 : Parameterised*
99 20986 : 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 20986 : checkSampleInterval(splInterval, SUMO_TAG_E1DETECTOR, id);
107 : // get and check the lane
108 20980 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E1DETECTOR, id);
109 : // get and check the position
110 20961 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_E1DETECTOR, id);
111 20955 : if (length < 0) {
112 0 : throw InvalidArgument("The length of " + toString(SUMO_TAG_E1DETECTOR) + " '" + id + "' cannot be negative");
113 20955 : } 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 20955 : MSDetectorFileOutput* loop = createInductLoop(id, clane, pos, length, name, vTypes, nextEdges, detectPersons, true);
123 : // add the file output
124 20949 : myNet.getDetectorControl().add(SUMO_TAG_INDUCTION_LOOP, loop, device, splInterval);
125 20943 : return loop;
126 : }
127 :
128 :
129 : Parameterised*
130 855 : 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 855 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
138 : // get and check the position
139 851 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_INSTANT_INDUCTION_LOOP, id);
140 : // build the loop
141 847 : MSDetectorFileOutput* loop = createInstantInductLoop(id, clane, pos, device, name, vTypes, nextEdges);
142 : // add the file output
143 843 : myNet.getDetectorControl().add(SUMO_TAG_INSTANT_INDUCTION_LOOP, loop);
144 843 : return loop;
145 : }
146 :
147 :
148 : Parameterised*
149 3021 : 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 3021 : if (posGiven) {
166 2449 : if (pos >= lane->getLength() || (pos < 0 && -pos > lane->getLength())) {
167 7 : 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 7 : if (friendlyPos) {
172 3 : double newPos = pos > 0 ? lane->getLength() - POSITION_EPS : 0.;
173 : ss << " (adjusting to new position " << newPos;
174 3 : WRITE_WARNING(ss.str());
175 : pos = newPos;
176 : } else {
177 4 : ss << " (0 <= pos < lane->getLength() is required)";
178 8 : throw InvalidArgument(ss.str());
179 : }
180 7 : }
181 : }
182 3017 : if (endPosGiven) {
183 594 : if (endPos > lane->getLength() || (endPos <= 0 && -endPos >= lane->getLength())) {
184 0 : 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 0 : if (friendlyPos) {
189 0 : double newEndPos = endPos > 0 ? lane->getLength() : POSITION_EPS;
190 : ss << " (adjusting to new position " << newEndPos;
191 0 : WRITE_WARNING(ss.str());
192 : pos = newEndPos;
193 : } else {
194 0 : ss << " (0 <= pos < lane->getLength() is required)";
195 0 : throw InvalidArgument(ss.str());
196 : }
197 0 : }
198 : }
199 :
200 : MSE2Collector* det = nullptr;
201 3017 : if (tlsGiven) {
202 : // Detector connected to TLS
203 554 : det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
204 554 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
205 : // add the file output (XXX: Where's the corresponding delete?)
206 554 : if (toLaneGiven) {
207 : // Detector also associated to specific link
208 : const MSLane* const lastLane = det->getLastLane();
209 8 : const MSLink* const link = lastLane->getLinkTo(toLane);
210 8 : if (link == nullptr) {
211 : throw InvalidArgument(
212 0 : "The detector '" + id + "' cannot be build as no connection between lanes '"
213 0 : + lastLane->getID() + "' and '" + toLane->getID() + "' exists.");
214 : }
215 8 : new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
216 : } else {
217 : // detector for tls but without specific link
218 546 : new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
219 : }
220 : } else {
221 : // User specified detector for xml-output
222 2463 : checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
223 2459 : det = createE2Detector(id, DU_USER_DEFINED, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
224 2459 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
225 : }
226 3009 : return det;
227 : }
228 :
229 :
230 : Parameterised*
231 244 : 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 244 : const MSLane* const firstLane = lanes[0];
246 244 : const MSLane* const lastLane = lanes.back();
247 :
248 : // Check positioning
249 244 : if (pos >= firstLane->getLength() || (pos < 0 && -pos > firstLane->getLength())) {
250 1 : 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 1 : if (friendlyPos) {
255 1 : double newPos = pos > 0 ? firstLane->getLength() - POSITION_EPS : 0.;
256 : ss << " (adjusting to new position " << newPos;
257 1 : WRITE_WARNING(ss.str());
258 : pos = newPos;
259 : } else {
260 0 : ss << " (0 <= pos < lane->getLength() is required)";
261 0 : throw InvalidArgument(ss.str());
262 : }
263 1 : }
264 244 : if (endPos > lastLane->getLength() || (endPos <= 0 && -endPos >= lastLane->getLength())) {
265 1 : 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 1 : if (friendlyPos) {
270 1 : double newEndPos = endPos > 0 ? lastLane->getLength() : POSITION_EPS;
271 : ss << " (adjusting to new position " << newEndPos;
272 1 : WRITE_WARNING(ss.str());
273 : pos = newEndPos;
274 : } else {
275 0 : ss << " (0 <= pos < lane->getLength() is required)";
276 0 : throw InvalidArgument(ss.str());
277 : }
278 1 : }
279 :
280 : MSE2Collector* det = nullptr;
281 244 : if (tlsGiven) {
282 : // Detector connected to TLS
283 5 : det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
284 5 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det);
285 : // add the file output (XXX: Where's the corresponding delete?)
286 5 : if (toLaneGiven) {
287 : // Detector also associated to specific link
288 : const MSLane* const lastDetLane = det->getLastLane();
289 0 : const MSLink* const link = lastDetLane->getLinkTo(toLane);
290 0 : if (link == nullptr) {
291 : throw InvalidArgument(
292 0 : "The detector '" + id + "' cannot be build as no connection between lanes '"
293 0 : + lastDetLane->getID() + "' and '" + toLane->getID() + "' exists.");
294 : }
295 0 : new Command_SaveTLCoupledLaneDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device), link);
296 : } else {
297 : // detector for tls but without specific link
298 5 : new Command_SaveTLCoupledDet(*tlls, det, myNet.getCurrentTimeStep(), OutputDevice::getDevice(device));
299 : }
300 : } else {
301 : // User specified detector for xml-output
302 239 : checkSampleInterval(frequency, SUMO_TAG_E2DETECTOR, id);
303 :
304 245 : det = createE2Detector(id, DU_USER_DEFINED, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons, showDetector);
305 233 : myNet.getDetectorControl().add(SUMO_TAG_LANE_AREA_DETECTOR, det, device, frequency);
306 : }
307 238 : return det;
308 : }
309 :
310 :
311 :
312 : Parameterised*
313 1373 : 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 1373 : checkSampleInterval(splInterval, SUMO_TAG_E3DETECTOR, id);
322 2738 : myE3Definition = new E3DetectorDefinition(id, device, haltingSpeedThreshold, haltingTimeThreshold, splInterval, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
323 1369 : return myE3Definition;
324 : }
325 :
326 :
327 : void
328 1691 : NLDetectorBuilder::addE3Entry(const std::string& lane,
329 : double pos, bool friendlyPos) {
330 1691 : if (myE3Definition == nullptr) {
331 : return;
332 : }
333 1663 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
334 : // get and check the position
335 1659 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_ENTRY, myE3Definition->myID);
336 : // build and save the entry
337 1655 : myE3Definition->myEntries.push_back(MSCrossSection(clane, pos));
338 : }
339 :
340 :
341 : void
342 1655 : NLDetectorBuilder::addE3Exit(const std::string& lane,
343 : double pos, bool friendlyPos) {
344 1655 : if (myE3Definition == nullptr) {
345 : return;
346 : }
347 1627 : MSLane* clane = getLaneChecking(lane, SUMO_TAG_E3DETECTOR, myE3Definition->myID);
348 : // get and check the position
349 1623 : pos = getPositionChecking(pos, clane, friendlyPos, SUMO_TAG_DET_EXIT, myE3Definition->myID);
350 : // build and save the exit
351 1619 : myE3Definition->myExits.push_back(MSCrossSection(clane, pos));
352 : }
353 :
354 :
355 : std::string
356 10158 : NLDetectorBuilder::getCurrentE3ID() const {
357 10158 : if (myE3Definition == nullptr) {
358 168 : return "<unknown>";
359 : }
360 : return myE3Definition->myID;
361 : }
362 :
363 :
364 : void
365 1397 : NLDetectorBuilder::endE3Detector() {
366 1397 : if (myE3Definition == nullptr) {
367 : return;
368 : }
369 : // If E3 own entry or exit detectors
370 1369 : if (myE3Definition->myEntries.size() > 0 || myE3Definition->myExits.size() > 0) {
371 : // create E3 detector
372 4083 : MSDetectorFileOutput* det = createE3Detector(myE3Definition->myID,
373 1361 : myE3Definition->myEntries, myE3Definition->myExits,
374 1361 : myE3Definition->myHaltingSpeedThreshold, myE3Definition->myHaltingTimeThreshold,
375 : myE3Definition->myName,
376 1361 : myE3Definition->myVehicleTypes,
377 1361 : myE3Definition->myNextEdges,
378 : myE3Definition->myDetectPersons,
379 1361 : myE3Definition->myOpenEntry,
380 1361 : myE3Definition->myExpectArrival);
381 1361 : det->updateParameters(myE3Definition->getParametersMap());
382 : // add to net
383 1361 : myNet.getDetectorControl().add(SUMO_TAG_ENTRY_EXIT_DETECTOR, det, myE3Definition->myDevice, myE3Definition->mySampleInterval);
384 : } else {
385 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)")
386 : }
387 : // clean up
388 1361 : delete myE3Definition;
389 1361 : myE3Definition = nullptr;
390 : }
391 :
392 :
393 : void
394 108 : NLDetectorBuilder::buildVTypeProbe(const std::string& id,
395 : const std::string& vtype, SUMOTime frequency,
396 : const std::string& device) {
397 108 : checkSampleInterval(frequency, SUMO_TAG_VTYPEPROBE, id);
398 96 : new MSVTypeProbe(id, vtype, OutputDevice::getDevice(device), frequency);
399 90 : }
400 :
401 :
402 : void
403 458 : 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 458 : checkSampleInterval(frequency, SUMO_TAG_ROUTEPROBE, id);
408 458 : MSEdge* e = getEdgeChecking(edge, SUMO_TAG_ROUTEPROBE, id);
409 1374 : MSRouteProbe* probe = new MSRouteProbe(id, e, id + "_" + toString(begin), id + "_" + toString(begin - frequency), vTypes);
410 : // add the file output
411 458 : myNet.getDetectorControl().add(SUMO_TAG_ROUTEPROBE, probe, device, frequency, begin);
412 458 : }
413 :
414 :
415 : MSDetectorFileOutput*
416 23346 : 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 23346 : if (MSGlobals::gUseMesoSim) {
425 567 : return new MEInductLoop(id, MSGlobals::gMesoNet->getSegmentForEdge(lane->getEdge(), pos), pos, name, vTypes, nextEdges, detectPersons);
426 : }
427 46317 : return new MSInductLoop(id, lane, pos, length, name, vTypes, nextEdges, detectPersons, false);
428 : }
429 :
430 :
431 : MSDetectorFileOutput*
432 725 : 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 1453 : return new MSInstantInductLoop(id, OutputDevice::getDevice(od), lane, pos, name, vTypes, nextEdges);
437 : }
438 :
439 :
440 : MSE2Collector*
441 5017 : 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 15051 : return new MSE2Collector(id, usage, lane, pos, endPos, length, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
448 : }
449 :
450 : MSE2Collector*
451 238 : 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 486 : return new MSE2Collector(id, usage, lanes, pos, endPos, haltingTimeThreshold, haltingSpeedThreshold, jamDistThreshold, name, vTypes, nextEdges, detectPersons);
458 : }
459 :
460 : MSDetectorFileOutput*
461 1196 : 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 3588 : return new MSE3Collector(id, entries, exits, haltingSpeedThreshold, haltingTimeThreshold, name, vTypes, nextEdges, detectPersons, openEntry, expectArrival);
472 : }
473 :
474 :
475 : double
476 25094 : 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 25094 : if (pos < 0) {
481 2193 : pos += lane->getLength();
482 : }
483 : // check whether it is on the lane
484 25094 : if (pos > lane->getLength()) {
485 540 : if (friendlyPos) {
486 : pos = lane->getLength();
487 : } else {
488 36 : throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies beyond the lane's '" + lane->getID() + "' end.");
489 : }
490 : }
491 25076 : if (pos < 0) {
492 178 : if (friendlyPos) {
493 : pos = 0.;
494 : } else {
495 0 : throw InvalidArgument("The position of " + toString(tag) + " '" + detid + "' lies before the lane's '" + lane->getID() + "' begin.");
496 : }
497 : }
498 25076 : return pos;
499 : }
500 :
501 :
502 : void
503 4351 : 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 4351 : if (begin < 0) {
514 72 : throw InvalidArgument("Negative begin time for meandata dump '" + id + "'.");
515 : }
516 4315 : if (end < 0) {
517 : end = SUMOTime_MAX;
518 : }
519 4315 : if (end <= begin) {
520 72 : throw InvalidArgument("End before or at begin for meandata dump '" + id + "'.");
521 : }
522 8558 : checkStepLengthMultiple(begin, " for meandata dump '" + id + "'");
523 : MSMeanData* det = nullptr;
524 4279 : if (type == "" || type == "performance" || type == "traffic") {
525 : det = new MSMeanData_Net(id, begin, end, useLanes, withEmpty,
526 2974 : printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
527 1305 : } else if (type == "emissions" || type == "hbefa") {
528 873 : if (type == "hbefa") {
529 24 : 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 873 : printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
533 432 : } else if (type == "harmonoise") {
534 : det = new MSMeanData_Harmonoise(id, begin, end, useLanes, withEmpty,
535 408 : printDefaults, withInternal, trackVehicles, maxTravelTime, minSamples, vTypes, writeAttributes, edges, aggregate);
536 24 : } else if (type == "amitran") {
537 : det = new MSMeanData_Amitran(id, begin, end, useLanes, withEmpty,
538 24 : printDefaults, withInternal, trackVehicles, detectPersons, maxTravelTime, minSamples, haltSpeed, vTypes, writeAttributes, edges, aggregate);
539 : } else {
540 0 : throw InvalidArgument("Invalid type '" + type + "' for meandata dump '" + id + "'.");
541 : }
542 : if (det != nullptr) {
543 4279 : if (frequency < 0) {
544 666 : frequency = end - begin;
545 : } else {
546 10839 : checkStepLengthMultiple(frequency, " for meandata dump '" + id + "'");
547 : }
548 4279 : MSNet::getInstance()->getDetectorControl().add(det, device, frequency, begin);
549 : }
550 4279 : }
551 :
552 :
553 :
554 :
555 : // ------ Value checking/adapting methods ------
556 : MSEdge*
557 458 : NLDetectorBuilder::getEdgeChecking(const std::string& edgeID, SumoXMLTag type,
558 : const std::string& detid) {
559 : // get and check the lane
560 458 : MSEdge* edge = MSEdge::dictionary(edgeID);
561 458 : if (edge == nullptr) {
562 0 : throw InvalidArgument("The lane with the id '" + edgeID + "' is not known (while building " + toString(type) + " '" + detid + "').");
563 : }
564 458 : return edge;
565 : }
566 :
567 :
568 : MSLane*
569 28292 : NLDetectorBuilder::getLaneChecking(const std::string& laneID, SumoXMLTag type,
570 : const std::string& detid) {
571 : // get and check the lane
572 28292 : MSLane* lane = MSLane::dictionary(laneID);
573 28292 : if (lane == nullptr) {
574 120 : throw InvalidArgument("The lane with the id '" + laneID + "' is not known (while building " + toString(type) + " '" + detid + "').");
575 : }
576 28252 : return lane;
577 : }
578 :
579 :
580 : void
581 25627 : NLDetectorBuilder::checkSampleInterval(SUMOTime splInterval, SumoXMLTag type, const std::string& id) {
582 25627 : if (splInterval < 0) {
583 40 : throw InvalidArgument("Negative sampling frequency (in " + toString(type) + " '" + id + "').");
584 : }
585 25607 : if (splInterval == 0) {
586 12 : throw InvalidArgument("Sampling frequency must not be zero (in " + toString(type) + " '" + id + "').");
587 : }
588 51202 : checkStepLengthMultiple(splInterval, " (in " + toString(type) + " '" + id + "')");
589 25601 : }
590 :
591 :
592 : /****************************************************************************/
|