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