1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2017-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    Edge.cpp
11 /// @author  Gregor Laemmel
12 /// @date    15.09.2017
13 /// @version $Id$
14 ///
15 // C++ TraCI client API implementation
16 /****************************************************************************/
17 
18 #include <iterator>
19 #include <microsim/MSEdge.h>
20 #include <microsim/MSLane.h>
21 #include <microsim/MSEdgeWeightsStorage.h>
22 #include <microsim/MSTransportable.h>
23 #include <microsim/MSVehicle.h>
24 #include <libsumo/TraCIDefs.h>
25 #include <libsumo/TraCIConstants.h>
26 #include <utils/emissions/HelpersHarmonoise.h>
27 #include "Edge.h"
28 
29 
30 namespace libsumo {
31 // ===========================================================================
32 // static member initializations
33 // ===========================================================================
34 SubscriptionResults Edge::mySubscriptionResults;
35 ContextSubscriptionResults Edge::myContextSubscriptionResults;
36 
37 
38 // ===========================================================================
39 // static member definitions
40 // ===========================================================================
41 std::vector<std::string>
getIDList()42 Edge::getIDList() {
43     std::vector<std::string> ids;
44     MSEdge::insertIDs(ids);
45     return ids;
46 }
47 
48 
49 int
getIDCount()50 Edge::getIDCount() {
51     return (int)getIDList().size();
52 }
53 
54 
55 double
getAdaptedTraveltime(const std::string & id,double time)56 Edge::getAdaptedTraveltime(const std::string& id, double time) {
57     const MSEdge* e = getEdge(id);
58     double value;
59     if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, time, value)) {
60         return -1.;
61     }
62     return value;
63 }
64 
65 
66 double
getEffort(const std::string & id,double time)67 Edge::getEffort(const std::string& id, double time) {
68     const MSEdge* e = getEdge(id);
69     double value;
70     if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingEffort(e, time, value)) {
71         return -1.;
72     }
73     return value;
74 }
75 
76 
77 double
getTraveltime(const std::string & id)78 Edge::getTraveltime(const std::string& id) {
79     return getEdge(id)->getCurrentTravelTime();
80 }
81 
82 
83 MSEdge*
getEdge(const std::string & id)84 Edge::getEdge(const std::string& id) {
85     MSEdge* e = MSEdge::dictionary(id);
86     if (e == nullptr) {
87         throw TraCIException("Edge '" + id + "' is not known");
88     }
89     return e;
90 }
91 
92 
93 double
getWaitingTime(const std::string & id)94 Edge::getWaitingTime(const std::string& id) {
95     double wtime = 0;
96     for (MSLane* lane : getEdge(id)->getLanes()) {
97         wtime += lane->getWaitingSeconds();
98     }
99     return wtime;
100 }
101 
102 
103 const std::vector<std::string>
getLastStepPersonIDs(const std::string & id)104 Edge::getLastStepPersonIDs(const std::string& id) {
105     std::vector<std::string> personIDs;
106     std::vector<MSTransportable*> persons = getEdge(id)->getSortedPersons(MSNet::getInstance()->getCurrentTimeStep(), true);
107     personIDs.reserve(persons.size());
108     for (MSTransportable* p : persons) {
109         personIDs.push_back(p->getID());
110     }
111     return personIDs;
112 }
113 
114 
115 const std::vector<std::string>
getLastStepVehicleIDs(const std::string & id)116 Edge::getLastStepVehicleIDs(const std::string& id) {
117     std::vector<std::string> vehIDs;
118     for (MSLane* lane : getEdge(id)->getLanes()) {
119         const MSLane::VehCont& vehs = lane->getVehiclesSecure();
120         for (auto veh : vehs) {
121             vehIDs.push_back(veh->getID());
122         }
123         lane->releaseVehicles();
124     }
125     return vehIDs;
126 }
127 
128 
129 double
getCO2Emission(const std::string & id)130 Edge::getCO2Emission(const std::string& id) {
131     double sum = 0;
132     for (MSLane* lane : getEdge(id)->getLanes()) {
133         sum += lane->getCO2Emissions();
134     }
135     return sum;
136 }
137 
138 
139 double
getCOEmission(const std::string & id)140 Edge::getCOEmission(const std::string& id) {
141     double sum = 0;
142     for (MSLane* lane : getEdge(id)->getLanes()) {
143         sum += lane->getCOEmissions();
144     }
145     return sum;
146 }
147 
148 
149 double
getHCEmission(const std::string & id)150 Edge::getHCEmission(const std::string& id) {
151     double sum = 0;
152     for (MSLane* lane : getEdge(id)->getLanes()) {
153         sum += lane->getHCEmissions();
154     }
155     return sum;
156 }
157 
158 
159 double
getPMxEmission(const std::string & id)160 Edge::getPMxEmission(const std::string& id) {
161     double sum = 0;
162     for (MSLane* lane : getEdge(id)->getLanes()) {
163         sum += lane->getPMxEmissions();
164     }
165     return sum;
166 }
167 
168 
169 double
getNOxEmission(const std::string & id)170 Edge::getNOxEmission(const std::string& id) {
171     double sum = 0;
172     for (MSLane* lane : getEdge(id)->getLanes()) {
173         sum += lane->getNOxEmissions();
174     }
175     return sum;
176 }
177 
178 
179 double
getFuelConsumption(const std::string & id)180 Edge::getFuelConsumption(const std::string& id) {
181     double sum = 0;
182     for (MSLane* lane : getEdge(id)->getLanes()) {
183         sum += lane->getFuelConsumption();
184     }
185     return sum;
186 }
187 
188 
189 double
getNoiseEmission(const std::string & id)190 Edge::getNoiseEmission(const std::string& id) {
191     double sum = 0;
192     for (MSLane* lane : getEdge(id)->getLanes()) {
193         sum += pow(10., (lane->getHarmonoise_NoiseEmissions() / 10.));
194     }
195     if (sum != 0) {
196         return HelpersHarmonoise::sum(sum);
197     }
198     return sum;
199 }
200 
201 
202 double
getElectricityConsumption(const std::string & id)203 Edge::getElectricityConsumption(const std::string& id) {
204     double sum = 0;
205     for (MSLane* lane : getEdge(id)->getLanes()) {
206         sum += lane->getElectricityConsumption();
207     }
208     return sum;
209 }
210 
211 
212 int
getLastStepVehicleNumber(const std::string & id)213 Edge::getLastStepVehicleNumber(const std::string& id) {
214     int sum = 0;
215     for (MSLane* lane : getEdge(id)->getLanes()) {
216         sum += lane->getVehicleNumber();
217     }
218     return sum;
219 }
220 
221 
222 double
getLastStepMeanSpeed(const std::string & id)223 Edge::getLastStepMeanSpeed(const std::string& id) {
224     return getEdge(id)->getMeanSpeed();
225 }
226 
227 
228 double
getLastStepOccupancy(const std::string & id)229 Edge::getLastStepOccupancy(const std::string& id) {
230     double sum = 0;
231     const std::vector<MSLane*>& lanes = getEdge(id)->getLanes();
232     for (auto lane : lanes) {
233         sum += lane->getNettoOccupancy();
234     }
235     return sum / (double)lanes.size();
236 }
237 
238 
239 int
getLastStepHaltingNumber(const std::string & id)240 Edge::getLastStepHaltingNumber(const std::string& id) {
241     int halting = 0;
242     for (MSLane* lane : getEdge(id)->getLanes()) {
243         const MSLane::VehCont& vehs = lane->getVehiclesSecure();
244         for (auto veh : vehs) {
245             if (veh->getSpeed() < SUMO_const_haltingSpeed) {
246                 ++halting;
247             }
248         }
249         lane->releaseVehicles();
250     }
251     return halting;
252 }
253 
254 
255 double
getLastStepLength(const std::string & id)256 Edge::getLastStepLength(const std::string& id) {
257     double lengthSum = 0;
258     int noVehicles = 0;
259     for (MSLane* lane : getEdge(id)->getLanes()) {
260         const MSLane::VehCont& vehs = lane->getVehiclesSecure();
261         for (auto veh : vehs) {
262             lengthSum += veh->getVehicleType().getLength();
263         }
264         noVehicles += (int)vehs.size();
265         lane->releaseVehicles();
266     }
267     if (noVehicles == 0) {
268         return 0;
269     }
270     return lengthSum / (double)noVehicles;
271 }
272 
273 
274 int
getLaneNumber(const std::string & id)275 Edge::getLaneNumber(const std::string& id) {
276     return (int)getEdge(id)->getLanes().size();
277 }
278 
279 
280 std::string
getStreetName(const std::string & id)281 Edge::getStreetName(const std::string& id) {
282     return getEdge(id)->getStreetName();
283 }
284 
285 
286 std::string
getParameter(const std::string & id,const std::string & paramName)287 Edge::getParameter(const std::string& id, const std::string& paramName) {
288     return getEdge(id)->getParameter(paramName, "");
289 }
290 
291 
292 void
setAllowedVehicleClasses(const std::string & id,std::vector<std::string> classes)293 Edge::setAllowedVehicleClasses(const std::string& id, std::vector<std::string> classes) {
294     SVCPermissions permissions = parseVehicleClasses(classes);
295     setAllowedSVCPermissions(id, permissions);
296 }
297 
298 
299 void
setDisallowedVehicleClasses(const std::string & id,std::vector<std::string> classes)300 Edge::setDisallowedVehicleClasses(const std::string& id, std::vector<std::string> classes) {
301     SVCPermissions permissions = invertPermissions(parseVehicleClasses(classes));
302     setAllowedSVCPermissions(id, permissions);
303 }
304 
305 
306 void
setAllowedSVCPermissions(const std::string & id,int permissions)307 Edge::setAllowedSVCPermissions(const std::string& id, int permissions) {
308     MSEdge* e = getEdge(id);
309     for (MSLane* lane : e->getLanes()) {
310         lane->setPermissions(permissions, MSLane::CHANGE_PERMISSIONS_PERMANENT);
311     }
312     e->rebuildAllowedLanes();
313     for (MSEdge* const pred : e->getPredecessors()) {
314         pred->rebuildAllowedTargets();
315     }
316 }
317 
318 
319 void
adaptTraveltime(const std::string & id,double value,double begTime,double endTime)320 Edge::adaptTraveltime(const std::string& id, double value, double begTime, double endTime) {
321     MSNet::getInstance()->getWeightsStorage().addTravelTime(getEdge(id), begTime, endTime, value);
322 }
323 
324 
325 void
setEffort(const std::string & id,double value,double begTime,double endTime)326 Edge::setEffort(const std::string& id, double value, double begTime, double endTime) {
327     MSNet::getInstance()->getWeightsStorage().addEffort(getEdge(id), begTime, endTime, value);
328 }
329 
330 
331 void
setMaxSpeed(const std::string & id,double value)332 Edge::setMaxSpeed(const std::string& id, double value) {
333     for (MSLane* lane : getEdge(id)->getLanes()) {
334         lane->setMaxSpeed(value);
335     }
336 }
337 
338 
339 void
setParameter(const std::string & id,const std::string & name,const std::string & value)340 Edge::setParameter(const std::string& id, const std::string& name, const std::string& value) {
341     getEdge(id)->setParameter(name, value);
342 }
343 
344 
LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Edge,EDGE)345 LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Edge, EDGE)
346 
347 
348 void
349 Edge::storeShape(const std::string& id, PositionVector& shape) {
350     const MSEdge* const e = getEdge(id);
351     const std::vector<MSLane*>& lanes = e->getLanes();
352     shape = lanes.front()->getShape();
353     if (lanes.size() > 1) {
354         copy(lanes.back()->getShape().begin(), lanes.back()->getShape().end(), back_inserter(shape));
355     }
356 }
357 
358 
359 std::shared_ptr<VariableWrapper>
makeWrapper()360 Edge::makeWrapper() {
361     return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
362 }
363 
364 
365 bool
handleVariable(const std::string & objID,const int variable,VariableWrapper * wrapper)366 Edge::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper) {
367     switch (variable) {
368         case TRACI_ID_LIST:
369             return wrapper->wrapStringList(objID, variable, getIDList());
370         case ID_COUNT:
371             return wrapper->wrapInt(objID, variable, getIDCount());
372         case VAR_CURRENT_TRAVELTIME:
373             return wrapper->wrapDouble(objID, variable, getTraveltime(objID));
374         case VAR_WAITING_TIME:
375             return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
376         case LAST_STEP_PERSON_ID_LIST:
377             return wrapper->wrapStringList(objID, variable, getLastStepPersonIDs(objID));
378         case LAST_STEP_VEHICLE_ID_LIST:
379             return wrapper->wrapStringList(objID, variable, getLastStepVehicleIDs(objID));
380         case VAR_CO2EMISSION:
381             return wrapper->wrapDouble(objID, variable, getCO2Emission(objID));
382         case VAR_COEMISSION:
383             return wrapper->wrapDouble(objID, variable, getCOEmission(objID));
384         case VAR_HCEMISSION:
385             return wrapper->wrapDouble(objID, variable, getHCEmission(objID));
386         case VAR_PMXEMISSION:
387             return wrapper->wrapDouble(objID, variable, getPMxEmission(objID));
388         case VAR_NOXEMISSION:
389             return wrapper->wrapDouble(objID, variable, getNOxEmission(objID));
390         case VAR_FUELCONSUMPTION:
391             return wrapper->wrapDouble(objID, variable, getFuelConsumption(objID));
392         case VAR_NOISEEMISSION:
393             return wrapper->wrapDouble(objID, variable, getNoiseEmission(objID));
394         case VAR_ELECTRICITYCONSUMPTION:
395             return wrapper->wrapDouble(objID, variable, getElectricityConsumption(objID));
396         case LAST_STEP_VEHICLE_NUMBER:
397             return wrapper->wrapInt(objID, variable, getLastStepVehicleNumber(objID));
398         case LAST_STEP_MEAN_SPEED:
399             return wrapper->wrapDouble(objID, variable, getLastStepMeanSpeed(objID));
400         case LAST_STEP_OCCUPANCY:
401             return wrapper->wrapDouble(objID, variable, getLastStepOccupancy(objID));
402         case LAST_STEP_VEHICLE_HALTING_NUMBER:
403             return wrapper->wrapInt(objID, variable, getLastStepHaltingNumber(objID));
404         case LAST_STEP_LENGTH:
405             return wrapper->wrapDouble(objID, variable, getLastStepLength(objID));
406         case VAR_LANE_INDEX:
407             return wrapper->wrapInt(objID, variable, getLaneNumber(objID));
408         case VAR_NAME:
409             return wrapper->wrapString(objID, variable, getStreetName(objID));
410         default:
411             return false;
412     }
413 }
414 
415 
416 }
417 
418 
419 /****************************************************************************/
420