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