Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2017-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 Edge.cpp
15 : /// @author Gregor Laemmel
16 : /// @date 15.09.2017
17 : ///
18 : // C++ TraCI client API implementation
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <iterator>
23 : #include <microsim/MSEdge.h>
24 : #include <microsim/MSLane.h>
25 : #include <microsim/MSEdgeWeightsStorage.h>
26 : #include <microsim/transportables/MSTransportable.h>
27 : #include <microsim/MSVehicle.h>
28 : #include <microsim/MSInsertionControl.h>
29 : #include <libsumo/Helper.h>
30 : #include <libsumo/StorageHelper.h>
31 : #include <libsumo/TraCIDefs.h>
32 : #include <libsumo/TraCIConstants.h>
33 : #include <libsumo/Lane.h>
34 : #include <utils/emissions/HelpersHarmonoise.h>
35 : #include "Edge.h"
36 :
37 :
38 : namespace libsumo {
39 : // ===========================================================================
40 : // static member initializations
41 : // ===========================================================================
42 : SubscriptionResults Edge::mySubscriptionResults;
43 : ContextSubscriptionResults Edge::myContextSubscriptionResults;
44 :
45 :
46 : // ===========================================================================
47 : // static member definitions
48 : // ===========================================================================
49 : std::vector<std::string>
50 311 : Edge::getIDList() {
51 311 : MSNet::getInstance(); // just to check that we actually have a network
52 : std::vector<std::string> ids;
53 309 : MSEdge::insertIDs(ids);
54 309 : return ids;
55 0 : }
56 :
57 :
58 : int
59 16 : Edge::getIDCount() {
60 16 : return (int)getIDList().size();
61 : }
62 :
63 :
64 : double
65 114 : Edge::getAdaptedTraveltime(const std::string& edgeID, double time) {
66 114 : const MSEdge* e = getEdge(edgeID);
67 : double value;
68 114 : if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, time, value)) {
69 : return -1.;
70 : }
71 37 : return value;
72 : }
73 :
74 :
75 : double
76 54 : Edge::getEffort(const std::string& edgeID, double time) {
77 54 : const MSEdge* e = getEdge(edgeID);
78 : double value;
79 54 : if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingEffort(e, time, value)) {
80 : return -1.;
81 : }
82 27 : return value;
83 : }
84 :
85 :
86 : double
87 178 : Edge::getTraveltime(const std::string& edgeID) {
88 178 : return getEdge(edgeID)->getCurrentTravelTime();
89 : }
90 :
91 :
92 : MSEdge*
93 36746 : Edge::getEdge(const std::string& edgeID) {
94 36746 : MSEdge* e = MSEdge::dictionary(edgeID);
95 36746 : if (e == nullptr) {
96 8 : throw TraCIException("Edge '" + edgeID + "' is not known");
97 : }
98 36742 : return e;
99 : }
100 :
101 :
102 : double
103 14 : Edge::getWaitingTime(const std::string& edgeID) {
104 14 : return getEdge(edgeID)->getWaitingSeconds();
105 : }
106 :
107 :
108 : const std::vector<std::string>
109 18395 : Edge::getLastStepPersonIDs(const std::string& edgeID) {
110 : std::vector<std::string> personIDs;
111 18395 : std::vector<MSTransportable*> persons = getEdge(edgeID)->getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
112 18395 : personIDs.reserve(persons.size());
113 19034 : for (MSTransportable* p : persons) {
114 639 : personIDs.push_back(p->getID());
115 : }
116 18395 : return personIDs;
117 18395 : }
118 :
119 :
120 : const std::vector<std::string>
121 65 : Edge::getLastStepVehicleIDs(const std::string& edgeID) {
122 : std::vector<std::string> vehIDs;
123 380 : for (const SUMOVehicle* veh : getEdge(edgeID)->getVehicles()) {
124 315 : vehIDs.push_back(veh->getID());
125 63 : }
126 63 : return vehIDs;
127 2 : }
128 :
129 :
130 : double
131 17 : Edge::getCO2Emission(const std::string& edgeID) {
132 : double sum = 0;
133 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
134 33 : sum += lane->getEmissions<PollutantsInterface::CO2>();
135 : }
136 17 : return sum;
137 : }
138 :
139 :
140 : double
141 17 : Edge::getCOEmission(const std::string& edgeID) {
142 : double sum = 0;
143 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
144 33 : sum += lane->getEmissions<PollutantsInterface::CO>();
145 : }
146 17 : return sum;
147 : }
148 :
149 :
150 : double
151 17 : Edge::getHCEmission(const std::string& edgeID) {
152 : double sum = 0;
153 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
154 33 : sum += lane->getEmissions<PollutantsInterface::HC>();
155 : }
156 17 : return sum;
157 : }
158 :
159 :
160 : double
161 17 : Edge::getPMxEmission(const std::string& edgeID) {
162 : double sum = 0;
163 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
164 33 : sum += lane->getEmissions<PollutantsInterface::PM_X>();
165 : }
166 17 : return sum;
167 : }
168 :
169 :
170 : double
171 17 : Edge::getNOxEmission(const std::string& edgeID) {
172 : double sum = 0;
173 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
174 33 : sum += lane->getEmissions<PollutantsInterface::NO_X>();
175 : }
176 17 : return sum;
177 : }
178 :
179 :
180 : double
181 17 : Edge::getFuelConsumption(const std::string& edgeID) {
182 : double sum = 0;
183 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
184 33 : sum += lane->getEmissions<PollutantsInterface::FUEL>();
185 : }
186 17 : return sum;
187 : }
188 :
189 :
190 : double
191 17 : Edge::getNoiseEmission(const std::string& edgeID) {
192 : double sum = 0;
193 50 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
194 33 : sum += pow(10., (lane->getHarmonoise_NoiseEmissions() / 10.));
195 : }
196 17 : if (sum != 0) {
197 17 : return HelpersHarmonoise::sum(sum);
198 : }
199 : return sum;
200 : }
201 :
202 :
203 : double
204 13 : Edge::getElectricityConsumption(const std::string& edgeID) {
205 : double sum = 0;
206 42 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
207 29 : sum += lane->getEmissions<PollutantsInterface::ELEC>();
208 : }
209 13 : return sum;
210 : }
211 :
212 :
213 : int
214 661 : Edge::getLastStepVehicleNumber(const std::string& edgeID) {
215 661 : return getEdge(edgeID)->getVehicleNumber();
216 : }
217 :
218 :
219 : double
220 67 : Edge::getLastStepMeanSpeed(const std::string& edgeID) {
221 67 : return getEdge(edgeID)->getMeanSpeed();
222 : }
223 :
224 : double
225 8 : Edge::getMeanFriction(const std::string& edgeID) {
226 8 : return getEdge(edgeID)->getMeanFriction();
227 : }
228 :
229 :
230 : double
231 22 : Edge::getLastStepOccupancy(const std::string& edgeID) {
232 22 : return getEdge(edgeID)->getOccupancy();
233 : }
234 :
235 :
236 : int
237 17 : Edge::getLastStepHaltingNumber(const std::string& edgeID) {
238 : int result = 0;
239 32 : for (const SUMOVehicle* veh : getEdge(edgeID)->getVehicles()) {
240 15 : if (veh->getSpeed() < SUMO_const_haltingSpeed) {
241 4 : result++;
242 : }
243 17 : }
244 17 : return result;
245 : }
246 :
247 :
248 : double
249 17 : Edge::getLastStepLength(const std::string& edgeID) {
250 : double lengthSum = 0;
251 : int numVehicles = 0;
252 32 : for (const SUMOVehicle* veh : getEdge(edgeID)->getVehicles()) {
253 15 : numVehicles++;
254 15 : lengthSum += dynamic_cast<const MSBaseVehicle*>(veh)->getVehicleType().getLength();
255 17 : }
256 17 : if (numVehicles == 0) {
257 : return 0;
258 : }
259 15 : return lengthSum / numVehicles;
260 : }
261 :
262 :
263 : int
264 14 : Edge::getLaneNumber(const std::string& edgeID) {
265 14 : return (int)getEdge(edgeID)->getLanes().size();
266 : }
267 :
268 :
269 : std::string
270 14 : Edge::getStreetName(const std::string& edgeID) {
271 14 : return getEdge(edgeID)->getStreetName();
272 : }
273 :
274 :
275 : const std::vector<std::string>
276 58 : Edge::getPendingVehicles(const std::string& edgeID) {
277 58 : getEdge(edgeID); // validate edgeID
278 : std::vector<std::string> vehIDs;
279 70 : for (const SUMOVehicle* veh : MSNet::getInstance()->getInsertionControl().getPendingVehicles()) {
280 12 : if (veh->getEdge()->getID() == edgeID) {
281 12 : vehIDs.push_back(veh->getID());
282 : }
283 : }
284 58 : return vehIDs;
285 0 : }
286 :
287 :
288 : double
289 18 : Edge::getAngle(const std::string& edgeID, double relativePosition) {
290 18 : const std::vector<MSLane*>& lanes = getEdge(edgeID)->getLanes();
291 18 : return lanes.empty() ? libsumo::INVALID_DOUBLE_VALUE : Lane::getAngle(lanes.front()->getID(), relativePosition);
292 : }
293 :
294 : std::string
295 13 : Edge::getFromJunction(const std::string& edgeID) {
296 13 : return getEdge(edgeID)->getFromJunction()->getID();
297 : }
298 :
299 : std::string
300 13 : Edge::getToJunction(const std::string& edgeID) {
301 13 : return getEdge(edgeID)->getToJunction()->getID();
302 : }
303 :
304 : std::string
305 98 : Edge::getBidiEdge(const std::string& edgeID) {
306 98 : const MSEdge* bidi = getEdge(edgeID)->getBidiEdge();
307 98 : return bidi == nullptr ? "" : bidi->getID();
308 : }
309 :
310 : std::string
311 135 : Edge::getParameter(const std::string& edgeID, const std::string& param) {
312 270 : return getEdge(edgeID)->getParameter(param, "");
313 : }
314 :
315 :
316 102 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Edge)
317 :
318 :
319 : void
320 2 : Edge::setAllowed(const std::string& edgeID, std::string allowedClasses) {
321 2 : setAllowedSVCPermissions(edgeID, parseVehicleClasses(allowedClasses));
322 2 : }
323 :
324 :
325 : void
326 8 : Edge::setAllowed(const std::string& edgeID, std::vector<std::string> allowedClasses) {
327 8 : setAllowedSVCPermissions(edgeID, parseVehicleClasses(allowedClasses));
328 8 : }
329 :
330 :
331 : void
332 0 : Edge::setDisallowed(const std::string& edgeID, std::string disallowedClasses) {
333 0 : setAllowedSVCPermissions(edgeID, invertPermissions(parseVehicleClasses(disallowedClasses)));
334 0 : }
335 :
336 :
337 : void
338 0 : Edge::setDisallowed(const std::string& edgeID, std::vector<std::string> disallowedClasses) {
339 0 : setAllowedSVCPermissions(edgeID, invertPermissions(parseVehicleClasses(disallowedClasses)));
340 0 : }
341 :
342 :
343 : void
344 10 : Edge::setAllowedSVCPermissions(const std::string& edgeID, long long int permissions) {
345 10 : MSEdge* e = getEdge(edgeID);
346 20 : for (MSLane* lane : e->getLanes()) {
347 10 : lane->setPermissions(permissions, MSLane::CHANGE_PERMISSIONS_PERMANENT);
348 : }
349 10 : e->rebuildAllowedLanes(false, true);
350 10 : }
351 :
352 :
353 : void
354 85 : Edge::adaptTraveltime(const std::string& edgeID, double time, double beginSeconds, double endSeconds) {
355 85 : MSNet::getInstance()->getWeightsStorage().addTravelTime(getEdge(edgeID), beginSeconds, endSeconds, time);
356 84 : }
357 :
358 :
359 : void
360 18 : Edge::setEffort(const std::string& edgeID, double effort, double beginSeconds, double endSeconds) {
361 18 : MSNet::getInstance()->getWeightsStorage().addEffort(getEdge(edgeID), beginSeconds, endSeconds, effort);
362 17 : }
363 :
364 :
365 : void
366 21 : Edge::setMaxSpeed(const std::string& edgeID, double speed) {
367 21 : getEdge(edgeID)->setMaxSpeed(speed);
368 21 : }
369 :
370 : void
371 0 : Edge::setFriction(const std::string& edgeID, double friction) {
372 0 : for (MSLane* lane : getEdge(edgeID)->getLanes()) {
373 0 : lane->setFrictionCoefficient(friction);
374 : }
375 0 : }
376 :
377 : void
378 99 : Edge::setParameter(const std::string& edgeID, const std::string& name, const std::string& value) {
379 99 : getEdge(edgeID)->setParameter(name, value);
380 99 : }
381 :
382 :
383 8361 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Edge, EDGE)
384 :
385 :
386 : void
387 16406 : Edge::storeShape(const std::string& edgeID, PositionVector& shape) {
388 16406 : const MSEdge* const e = getEdge(edgeID);
389 32984 : for (const MSLane* lane : e->getLanes()) {
390 : copy(lane->getShape().begin(), lane->getShape().end(), back_inserter(shape));
391 : }
392 16406 : }
393 :
394 :
395 : std::shared_ptr<VariableWrapper>
396 270 : Edge::makeWrapper() {
397 270 : return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
398 : }
399 :
400 :
401 : bool
402 15050 : Edge::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
403 15050 : switch (variable) {
404 171 : case TRACI_ID_LIST:
405 171 : return wrapper->wrapStringList(objID, variable, getIDList());
406 14 : case ID_COUNT:
407 14 : return wrapper->wrapInt(objID, variable, getIDCount());
408 74 : case VAR_EDGE_TRAVELTIME:
409 148 : return wrapper->wrapDouble(objID, variable, getAdaptedTraveltime(objID, StoHelp::readTypedDouble(*paramData)));
410 38 : case VAR_EDGE_EFFORT:
411 76 : return wrapper->wrapDouble(objID, variable, getEffort(objID, StoHelp::readTypedDouble(*paramData)));
412 130 : case VAR_CURRENT_TRAVELTIME:
413 130 : return wrapper->wrapDouble(objID, variable, getTraveltime(objID));
414 12 : case VAR_WAITING_TIME:
415 12 : return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
416 13431 : case LAST_STEP_PERSON_ID_LIST:
417 13431 : return wrapper->wrapStringList(objID, variable, getLastStepPersonIDs(objID));
418 51 : case LAST_STEP_VEHICLE_ID_LIST:
419 51 : return wrapper->wrapStringList(objID, variable, getLastStepVehicleIDs(objID));
420 15 : case VAR_CO2EMISSION:
421 15 : return wrapper->wrapDouble(objID, variable, getCO2Emission(objID));
422 15 : case VAR_COEMISSION:
423 15 : return wrapper->wrapDouble(objID, variable, getCOEmission(objID));
424 15 : case VAR_HCEMISSION:
425 15 : return wrapper->wrapDouble(objID, variable, getHCEmission(objID));
426 15 : case VAR_PMXEMISSION:
427 15 : return wrapper->wrapDouble(objID, variable, getPMxEmission(objID));
428 15 : case VAR_NOXEMISSION:
429 15 : return wrapper->wrapDouble(objID, variable, getNOxEmission(objID));
430 15 : case VAR_FUELCONSUMPTION:
431 15 : return wrapper->wrapDouble(objID, variable, getFuelConsumption(objID));
432 15 : case VAR_NOISEEMISSION:
433 15 : return wrapper->wrapDouble(objID, variable, getNoiseEmission(objID));
434 11 : case VAR_ELECTRICITYCONSUMPTION:
435 11 : return wrapper->wrapDouble(objID, variable, getElectricityConsumption(objID));
436 639 : case LAST_STEP_VEHICLE_NUMBER:
437 639 : return wrapper->wrapInt(objID, variable, getLastStepVehicleNumber(objID));
438 45 : case LAST_STEP_MEAN_SPEED:
439 45 : return wrapper->wrapDouble(objID, variable, getLastStepMeanSpeed(objID));
440 8 : case VAR_FRICTION:
441 8 : return wrapper->wrapDouble(objID, variable, getMeanFriction(objID));
442 18 : case LAST_STEP_OCCUPANCY:
443 18 : return wrapper->wrapDouble(objID, variable, getLastStepOccupancy(objID));
444 15 : case LAST_STEP_VEHICLE_HALTING_NUMBER:
445 15 : return wrapper->wrapInt(objID, variable, getLastStepHaltingNumber(objID));
446 15 : case LAST_STEP_LENGTH:
447 15 : return wrapper->wrapDouble(objID, variable, getLastStepLength(objID));
448 12 : case VAR_LANE_INDEX:
449 12 : return wrapper->wrapInt(objID, variable, getLaneNumber(objID));
450 12 : case VAR_NAME:
451 24 : return wrapper->wrapString(objID, variable, getStreetName(objID));
452 38 : case VAR_PENDING_VEHICLES:
453 38 : return wrapper->wrapStringList(objID, variable, getPendingVehicles(objID));
454 14 : case VAR_ANGLE:
455 28 : return wrapper->wrapDouble(objID, variable, getAngle(objID, StoHelp::readTypedDouble(*paramData)));
456 11 : case FROM_JUNCTION:
457 22 : return wrapper->wrapString(objID, variable, getFromJunction(objID));
458 11 : case TO_JUNCTION:
459 22 : return wrapper->wrapString(objID, variable, getToJunction(objID));
460 62 : case VAR_BIDI:
461 124 : return wrapper->wrapString(objID, variable, getBidiEdge(objID));
462 60 : case VAR_PARAMETER:
463 120 : return wrapper->wrapString(objID, variable, getParameter(objID, StoHelp::readTypedString(*paramData)));
464 47 : case VAR_PARAMETER_WITH_KEY:
465 94 : return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, StoHelp::readTypedString(*paramData)));
466 : default:
467 : return false;
468 : }
469 : }
470 :
471 : }
472 :
473 :
474 : /****************************************************************************/
|