Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2012-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 InductionLoop.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Mario Krumnow
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @date 30.05.2012
20 : ///
21 : // C++ TraCI client API implementation
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <microsim/output/MSDetectorControl.h>
26 : #include <microsim/output/MSInductLoop.h>
27 : #include <mesosim/MEInductLoop.h>
28 : #include <microsim/MSNet.h>
29 : #include <microsim/MSEdge.h>
30 : #include <libsumo/Helper.h>
31 : #include <libsumo/TraCIDefs.h>
32 : #include <libsumo/TraCIConstants.h>
33 : #include "InductionLoop.h"
34 :
35 :
36 : namespace libsumo {
37 : // ===========================================================================
38 : // static member initializations
39 : // ===========================================================================
40 : SubscriptionResults InductionLoop::mySubscriptionResults;
41 : ContextSubscriptionResults InductionLoop::myContextSubscriptionResults;
42 : NamedRTree* InductionLoop::myTree(nullptr);
43 :
44 :
45 : // ===========================================================================
46 : // member definitions
47 : // ===========================================================================
48 : std::vector<std::string>
49 459 : InductionLoop::getIDList() {
50 : std::vector<std::string> ids;
51 459 : MSNet::getInstance()->getDetectorControl().getTypedDetectors(SUMO_TAG_INDUCTION_LOOP).insertIDs(ids);
52 457 : return ids;
53 2 : }
54 :
55 :
56 : int
57 30 : InductionLoop::getIDCount() {
58 : std::vector<std::string> ids;
59 60 : return (int)MSNet::getInstance()->getDetectorControl().getTypedDetectors(SUMO_TAG_INDUCTION_LOOP).size();
60 30 : }
61 :
62 :
63 : double
64 25 : InductionLoop::getPosition(const std::string& loopID) {
65 25 : return getDetector(loopID)->getPosition();
66 : }
67 :
68 :
69 : std::string
70 25 : InductionLoop::getLaneID(const std::string& loopID) {
71 25 : return getDetector(loopID)->getLane()->getID();
72 : }
73 :
74 :
75 : int
76 3355 : InductionLoop::getLastStepVehicleNumber(const std::string& loopID) {
77 3355 : return (int)getDetector(loopID)->getEnteredNumber((int)DELTA_T);
78 : }
79 :
80 :
81 : double
82 148 : InductionLoop::getLastStepMeanSpeed(const std::string& loopID) {
83 148 : return getDetector(loopID)->getSpeed((int)DELTA_T);
84 : }
85 :
86 :
87 : std::vector<std::string>
88 1012 : InductionLoop::getLastStepVehicleIDs(const std::string& loopID) {
89 1012 : return getDetector(loopID)->getVehicleIDs((int)DELTA_T);
90 : }
91 :
92 :
93 : double
94 716 : InductionLoop::getLastStepOccupancy(const std::string& loopID) {
95 716 : return getDetector(loopID)->getOccupancy();
96 : }
97 :
98 :
99 : double
100 148 : InductionLoop::getLastStepMeanLength(const std::string& loopID) {
101 148 : return getDetector(loopID)->getVehicleLength((int)DELTA_T);
102 : }
103 :
104 :
105 : double
106 149 : InductionLoop::getTimeSinceDetection(const std::string& loopID) {
107 149 : return getDetector(loopID)->getTimeSinceLastDetection();
108 : }
109 :
110 : std::vector<libsumo::TraCIVehicleData>
111 52508 : InductionLoop::getVehicleData(const std::string& loopID) {
112 52508 : const std::vector<MSInductLoop::VehicleData> vd = getDetector(loopID)->collectVehiclesOnDet(SIMSTEP - DELTA_T, true, true);
113 : std::vector<libsumo::TraCIVehicleData> tvd;
114 58984 : for (const MSInductLoop::VehicleData& vdi : vd) {
115 6476 : tvd.push_back(libsumo::TraCIVehicleData());
116 6476 : tvd.back().id = vdi.idM;
117 6476 : tvd.back().length = vdi.lengthM;
118 6476 : tvd.back().entryTime = vdi.entryTimeM;
119 6476 : tvd.back().leaveTime = vdi.leaveTimeM;
120 6476 : tvd.back().typeID = vdi.typeIDM;
121 : }
122 52508 : return tvd;
123 52508 : }
124 :
125 :
126 : double
127 608 : InductionLoop::getIntervalOccupancy(const std::string& loopID) {
128 608 : if (MSGlobals::gUseMesoSim) {
129 120 : const MEInductLoop* det = getMEDetector(loopID);
130 : const auto& meanData = det->getMeanData();
131 120 : return meanData.getOccupancy(SIMSTEP - meanData.getResetTime(), det->getEdge().getNumLanes());
132 : } else {
133 488 : return getDetector(loopID)->getIntervalOccupancy();
134 : }
135 : }
136 :
137 :
138 : double
139 608 : InductionLoop::getIntervalMeanSpeed(const std::string& loopID) {
140 608 : if (MSGlobals::gUseMesoSim) {
141 120 : const MEInductLoop* det = getMEDetector(loopID);
142 : const auto& meanData = det->getMeanData();
143 120 : if (meanData.getSamples() != 0) {
144 69 : return meanData.getTravelledDistance() / meanData.getSamples();
145 : } else {
146 51 : const double defaultTravelTime = det->getEdge().getLength() / det->getEdge().getSpeedLimit();
147 51 : return meanData.getLaneLength() / defaultTravelTime;
148 : }
149 : } else {
150 488 : return getDetector(loopID)->getIntervalMeanSpeed();
151 : }
152 : }
153 :
154 :
155 : int
156 608 : InductionLoop::getIntervalVehicleNumber(const std::string& loopID) {
157 608 : if (MSGlobals::gUseMesoSim) {
158 120 : const auto& meanData = getMEDetector(loopID)->getMeanData();
159 120 : return meanData.nVehDeparted + meanData.nVehEntered;
160 : } else {
161 488 : return getDetector(loopID)->getIntervalVehicleNumber();
162 : }
163 : }
164 :
165 :
166 : std::vector<std::string>
167 608 : InductionLoop::getIntervalVehicleIDs(const std::string& loopID) {
168 608 : if (MSGlobals::gUseMesoSim) {
169 120 : WRITE_ERROR("getIntervalVehicleIDs not applicable for meso");
170 120 : return std::vector<std::string>();
171 : }
172 488 : return getDetector(loopID)->getIntervalVehicleIDs();
173 : }
174 :
175 :
176 : double
177 608 : InductionLoop::getLastIntervalOccupancy(const std::string& loopID) {
178 608 : if (MSGlobals::gUseMesoSim) {
179 120 : WRITE_ERROR("getLastIntervalOccupancy not applicable for meso");
180 120 : return INVALID_DOUBLE_VALUE;
181 : }
182 488 : return getDetector(loopID)->getIntervalOccupancy(true);
183 : }
184 :
185 :
186 : double
187 608 : InductionLoop::getLastIntervalMeanSpeed(const std::string& loopID) {
188 608 : if (MSGlobals::gUseMesoSim) {
189 120 : WRITE_ERROR("getLastIntervalMeanSpeed not applicable for meso");
190 120 : return INVALID_DOUBLE_VALUE;
191 : }
192 488 : return getDetector(loopID)->getIntervalMeanSpeed(true);
193 : }
194 :
195 :
196 : int
197 608 : InductionLoop::getLastIntervalVehicleNumber(const std::string& loopID) {
198 608 : if (MSGlobals::gUseMesoSim) {
199 120 : WRITE_ERROR("getLastIntervalVehicleNumber not applicable for meso");
200 120 : return INVALID_INT_VALUE;
201 : }
202 488 : return getDetector(loopID)->getIntervalVehicleNumber(true);
203 : }
204 :
205 :
206 : std::vector<std::string>
207 608 : InductionLoop::getLastIntervalVehicleIDs(const std::string& loopID) {
208 608 : if (MSGlobals::gUseMesoSim) {
209 120 : WRITE_ERROR("getLastIntervalVehicleIDs not applicable for meso");
210 120 : return std::vector<std::string>();
211 : }
212 488 : return getDetector(loopID)->getIntervalVehicleIDs(true);
213 : }
214 :
215 :
216 : void
217 20 : InductionLoop::overrideTimeSinceDetection(const std::string& loopID, double time) {
218 20 : getDetector(loopID)->overrideTimeSinceDetection(time);
219 20 : }
220 :
221 :
222 : MSInductLoop*
223 62407 : InductionLoop::getDetector(const std::string& id) {
224 124813 : MSInductLoop* il = dynamic_cast<MSInductLoop*>(MSNet::getInstance()->getDetectorControl().getTypedDetectors(SUMO_TAG_INDUCTION_LOOP).get(id));
225 62407 : if (il == nullptr) {
226 10 : throw TraCIException("Induction loop '" + id + "' is not known");
227 : }
228 62402 : return il;
229 : }
230 :
231 :
232 : MEInductLoop*
233 360 : InductionLoop::getMEDetector(const std::string& id) {
234 720 : MEInductLoop* il = dynamic_cast<MEInductLoop*>(MSNet::getInstance()->getDetectorControl().getTypedDetectors(SUMO_TAG_INDUCTION_LOOP).get(id));
235 360 : if (il == nullptr) {
236 0 : throw TraCIException("Induction loop '" + id + "' is not known");
237 : }
238 360 : return il;
239 : }
240 :
241 :
242 :
243 : std::string
244 48 : InductionLoop::getParameter(const std::string& loopID, const std::string& param) {
245 96 : return getDetector(loopID)->getParameter(param, "");
246 : }
247 :
248 :
249 16 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(InductionLoop)
250 :
251 :
252 : void
253 16 : InductionLoop::setParameter(const std::string& loopID, const std::string& name, const std::string& value) {
254 16 : getDetector(loopID)->setParameter(name, value);
255 16 : }
256 :
257 :
258 315 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(InductionLoop, INDUCTIONLOOP)
259 :
260 :
261 : NamedRTree*
262 372 : InductionLoop::getTree() {
263 372 : if (myTree == nullptr) {
264 13 : myTree = new NamedRTree();
265 52 : for (const auto& i : MSNet::getInstance()->getDetectorControl().getTypedDetectors(SUMO_TAG_INDUCTION_LOOP)) {
266 39 : MSInductLoop* il = static_cast<MSInductLoop*>(i.second);
267 39 : Position p = il->getLane()->getShape().positionAtOffset(il->getPosition());
268 39 : const float cmin[2] = {(float) p.x(), (float) p.y()};
269 39 : const float cmax[2] = {(float) p.x(), (float) p.y()};
270 39 : myTree->Insert(cmin, cmax, il);
271 : }
272 : }
273 372 : return myTree;
274 : }
275 :
276 : void
277 41428 : InductionLoop::cleanup() {
278 41428 : delete myTree;
279 41428 : myTree = nullptr;
280 41428 : }
281 :
282 : void
283 333 : InductionLoop::storeShape(const std::string& id, PositionVector& shape) {
284 333 : MSInductLoop* const il = getDetector(id);
285 333 : shape.push_back(il->getLane()->getShape().positionAtOffset(il->getPosition()));
286 333 : }
287 :
288 :
289 : std::shared_ptr<VariableWrapper>
290 270 : InductionLoop::makeWrapper() {
291 270 : return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
292 : }
293 :
294 :
295 : bool
296 32370 : InductionLoop::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
297 32370 : switch (variable) {
298 269 : case TRACI_ID_LIST:
299 269 : return wrapper->wrapStringList(objID, variable, getIDList());
300 22 : case ID_COUNT:
301 22 : return wrapper->wrapInt(objID, variable, getIDCount());
302 17 : case VAR_POSITION:
303 17 : return wrapper->wrapDouble(objID, variable, getPosition(objID));
304 17 : case VAR_LANE_ID:
305 34 : return wrapper->wrapString(objID, variable, getLaneID(objID));
306 2947 : case LAST_STEP_VEHICLE_NUMBER:
307 2947 : return wrapper->wrapInt(objID, variable, getLastStepVehicleNumber(objID));
308 104 : case LAST_STEP_MEAN_SPEED:
309 104 : return wrapper->wrapDouble(objID, variable, getLastStepMeanSpeed(objID));
310 556 : case LAST_STEP_VEHICLE_ID_LIST:
311 556 : return wrapper->wrapStringList(objID, variable, getLastStepVehicleIDs(objID));
312 388 : case LAST_STEP_OCCUPANCY:
313 388 : return wrapper->wrapDouble(objID, variable, getLastStepOccupancy(objID));
314 104 : case LAST_STEP_LENGTH:
315 104 : return wrapper->wrapDouble(objID, variable, getLastStepMeanLength(objID));
316 105 : case LAST_STEP_TIME_SINCE_DETECTION:
317 105 : return wrapper->wrapDouble(objID, variable, getTimeSinceDetection(objID));
318 368 : case VAR_INTERVAL_OCCUPANCY:
319 368 : return wrapper->wrapDouble(objID, variable, getIntervalOccupancy(objID));
320 368 : case VAR_INTERVAL_SPEED:
321 368 : return wrapper->wrapDouble(objID, variable, getIntervalMeanSpeed(objID));
322 368 : case VAR_INTERVAL_NUMBER:
323 368 : return wrapper->wrapInt(objID, variable, getIntervalVehicleNumber(objID));
324 368 : case VAR_INTERVAL_IDS:
325 368 : return wrapper->wrapStringList(objID, variable, getIntervalVehicleIDs(objID));
326 368 : case VAR_LAST_INTERVAL_OCCUPANCY:
327 368 : return wrapper->wrapDouble(objID, variable, getLastIntervalOccupancy(objID));
328 368 : case VAR_LAST_INTERVAL_SPEED:
329 368 : return wrapper->wrapDouble(objID, variable, getLastIntervalMeanSpeed(objID));
330 368 : case VAR_LAST_INTERVAL_NUMBER:
331 368 : return wrapper->wrapInt(objID, variable, getLastIntervalVehicleNumber(objID));
332 368 : case VAR_LAST_INTERVAL_IDS:
333 368 : return wrapper->wrapStringList(objID, variable, getLastIntervalVehicleIDs(objID));
334 24860 : case LAST_STEP_VEHICLE_DATA:
335 24860 : return wrapper->wrapVehicleDataVector(objID, variable, getVehicleData(objID));
336 24 : case libsumo::VAR_PARAMETER:
337 24 : paramData->readUnsignedByte();
338 48 : return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
339 8 : case libsumo::VAR_PARAMETER_WITH_KEY:
340 8 : paramData->readUnsignedByte();
341 16 : return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
342 : default:
343 : return false;
344 : }
345 : }
346 :
347 :
348 : }
349 :
350 :
351 : /****************************************************************************/
|