SUMO - Simulation of Urban MObility
TraCIServerAPI_Edge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // APIs for getting/setting edge values via TraCI
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
15 // Copyright (C) 2002-2014 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #ifndef NO_TRACI
37 
38 #include <utils/common/StdDefs.h>
39 #include <microsim/MSNet.h>
40 #include <microsim/MSEdgeControl.h>
41 #include <microsim/MSEdge.h>
42 #include <microsim/MSLane.h>
43 #include <microsim/MSVehicle.h>
44 #include "TraCIConstants.h"
45 #include "TraCIServerAPI_Edge.h"
48 
49 #ifdef CHECK_MEMORY_LEAKS
50 #include <foreign/nvwa/debug_new.h>
51 #endif // CHECK_MEMORY_LEAKS
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 bool
59  tcpip::Storage& outputStorage) {
60  // variable & id
61  int variable = inputStorage.readUnsignedByte();
62  std::string id = inputStorage.readString();
63  // check variable
64  if (variable != ID_LIST && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT && variable != VAR_CURRENT_TRAVELTIME
65  && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION
66  && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION && variable != VAR_WAITING_TIME
67  && variable != LAST_STEP_VEHICLE_NUMBER && variable != LAST_STEP_MEAN_SPEED && variable != LAST_STEP_OCCUPANCY
68  && variable != LAST_STEP_VEHICLE_HALTING_NUMBER && variable != LAST_STEP_LENGTH
69  && variable != LAST_STEP_VEHICLE_ID_LIST && variable != ID_COUNT) {
70  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "Get Edge Variable: unsupported variable specified", outputStorage);
71  }
72  // begin response building
73  tcpip::Storage tempMsg;
74  // response-code, variableID, objectID
76  tempMsg.writeUnsignedByte(variable);
77  tempMsg.writeString(id);
78  // process request
79  if (variable == ID_LIST) {
80  std::vector<std::string> ids;
81  MSEdge::insertIDs(ids);
83  tempMsg.writeStringList(ids);
84  } else if (variable == ID_COUNT) {
85  std::vector<std::string> ids;
86  MSEdge::insertIDs(ids);
88  tempMsg.writeInt((int) ids.size());
89  } else {
90  MSEdge* e = MSEdge::dictionary(id);
91  if (e == 0) {
92  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "Edge '" + id + "' is not known", outputStorage);
93  }
94  switch (variable) {
95  case VAR_EDGE_TRAVELTIME: {
96  // time
97  SUMOTime time = 0;
98  if (!server.readTypeCheckingInt(inputStorage, time)) {
99  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The message must contain the time definition.", outputStorage);
100  }
102  SUMOReal value;
103  if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, time, value)) {
104  tempMsg.writeDouble(-1);
105  } else {
106  tempMsg.writeDouble(value);
107  }
108  }
109  break;
110  case VAR_EDGE_EFFORT: {
111  // time
112  SUMOTime time = 0;
113  if (!server.readTypeCheckingInt(inputStorage, time)) {
114  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The message must contain the time definition.", outputStorage);
115  }
117  SUMOReal value;
118  if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingEffort(e, time, value)) {
119  tempMsg.writeDouble(-1);
120  } else {
121  tempMsg.writeDouble(value);
122  }
123  }
124  break;
127  tempMsg.writeDouble(e->getCurrentTravelTime());
128  break;
129  case VAR_WAITING_TIME: {
130  SUMOReal wtime = 0;
131  const std::vector<MSLane*>& lanes = e->getLanes();
132  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
133  wtime += (*i)->getWaitingSeconds();
134  }
136  tempMsg.writeDouble(wtime);
137  }
138  break;
140  std::vector<std::string> vehIDs;
141  const std::vector<MSLane*>& lanes = e->getLanes();
142  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
143  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
144  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
145  vehIDs.push_back((*j)->getID());
146  }
147  (*i)->releaseVehicles();
148  }
150  tempMsg.writeStringList(vehIDs);
151  }
152  break;
153  case VAR_CO2EMISSION: {
154  SUMOReal sum = 0;
155  const std::vector<MSLane*>& lanes = e->getLanes();
156  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
157  sum += (*i)->getCO2Emissions();
158  }
160  tempMsg.writeDouble(sum);
161  }
162  break;
163  case VAR_COEMISSION: {
164  SUMOReal sum = 0;
165  const std::vector<MSLane*>& lanes = e->getLanes();
166  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
167  sum += (*i)->getCOEmissions();
168  }
170  tempMsg.writeDouble(sum);
171  }
172  break;
173  case VAR_HCEMISSION: {
174  SUMOReal sum = 0;
175  const std::vector<MSLane*>& lanes = e->getLanes();
176  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
177  sum += (*i)->getHCEmissions();
178  }
180  tempMsg.writeDouble(sum);
181  }
182  break;
183  case VAR_PMXEMISSION: {
184  SUMOReal sum = 0;
185  const std::vector<MSLane*>& lanes = e->getLanes();
186  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
187  sum += (*i)->getPMxEmissions();
188  }
190  tempMsg.writeDouble(sum);
191  }
192  break;
193  case VAR_NOXEMISSION: {
194  SUMOReal sum = 0;
195  const std::vector<MSLane*>& lanes = e->getLanes();
196  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
197  sum += (*i)->getNOxEmissions();
198  }
200  tempMsg.writeDouble(sum);
201  }
202  break;
203  case VAR_FUELCONSUMPTION: {
204  SUMOReal sum = 0;
205  const std::vector<MSLane*>& lanes = e->getLanes();
206  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
207  sum += (*i)->getFuelConsumption();
208  }
210  tempMsg.writeDouble(sum);
211  }
212  break;
213  case VAR_NOISEEMISSION: {
214  SUMOReal sum = 0;
215  const std::vector<MSLane*>& lanes = e->getLanes();
216  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
217  sum += (SUMOReal) pow(10., ((*i)->getHarmonoise_NoiseEmissions() / 10.));
218  }
220  if (sum != 0) {
221  tempMsg.writeDouble(HelpersHarmonoise::sum(sum));
222  } else {
223  tempMsg.writeDouble(0);
224  }
225  }
226  break;
228  int sum = 0;
229  const std::vector<MSLane*>& lanes = e->getLanes();
230  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
231  sum += (*i)->getVehicleNumber();
232  }
234  tempMsg.writeInt(sum);
235  }
236  break;
237  case LAST_STEP_MEAN_SPEED: {
238  SUMOReal sum = 0;
239  const std::vector<MSLane*>& lanes = e->getLanes();
240  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
241  sum += (*i)->getMeanSpeed();
242  }
244  tempMsg.writeDouble(sum / (SUMOReal) lanes.size());
245  }
246  break;
247  case LAST_STEP_OCCUPANCY: {
248  SUMOReal sum = 0;
249  const std::vector<MSLane*>& lanes = e->getLanes();
250  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
251  sum += (*i)->getNettoOccupancy();
252  }
254  tempMsg.writeDouble(sum / (SUMOReal) lanes.size());
255  }
256  break;
258  int halting = 0;
259  const std::vector<MSLane*>& lanes = e->getLanes();
260  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
261  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
262  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
263  if ((*j)->getSpeed() < SUMO_const_haltingSpeed) {
264  ++halting;
265  }
266  }
267  (*i)->releaseVehicles();
268  }
270  tempMsg.writeInt(halting);
271  }
272  break;
273  case LAST_STEP_LENGTH: {
274  SUMOReal lengthSum = 0;
275  int noVehicles = 0;
276  const std::vector<MSLane*>& lanes = e->getLanes();
277  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
278  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
279  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
280  lengthSum += (*j)->getVehicleType().getLength();
281  }
282  noVehicles += (int) vehs.size();
283  (*i)->releaseVehicles();
284  }
286  if (noVehicles == 0) {
287  tempMsg.writeDouble(0);
288  } else {
289  tempMsg.writeDouble(lengthSum / (SUMOReal) noVehicles);
290  }
291  }
292  break;
293  default:
294  break;
295  }
296  }
297  server.writeStatusCmd(CMD_GET_EDGE_VARIABLE, RTYPE_OK, "", outputStorage);
298  server.writeResponseWithLength(outputStorage, tempMsg);
299  return true;
300 }
301 
302 
303 bool
305  tcpip::Storage& outputStorage) {
306  std::string warning = ""; // additional description for response
307  // variable
308  int variable = inputStorage.readUnsignedByte();
309  if (variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT && variable != VAR_MAXSPEED) {
310  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Change Edge State: unsupported variable specified", outputStorage);
311  }
312  // id
313  std::string id = inputStorage.readString();
314  MSEdge* e = MSEdge::dictionary(id);
315  if (e == 0) {
316  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Edge '" + id + "' is not known", outputStorage);
317  }
318  // process
319  switch (variable) {
320  case LANE_ALLOWED: {
321  // read and set allowed vehicle classes
322  std::vector<std::string> classes;
323  if (!server.readTypeCheckingStringList(inputStorage, classes)) {
324  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Allowed vehicle classes must be given as a list of strings.", outputStorage);
325  }
326  SVCPermissions permissions = parseVehicleClasses(classes);
327  const std::vector<MSLane*>& lanes = e->getLanes();
328  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
329  (*i)->setPermissions(permissions);
330  }
331  e->rebuildAllowedLanes();
332  }
333  break;
334  case LANE_DISALLOWED: {
335  // read and set disallowed vehicle classes
336  std::vector<std::string> classes;
337  if (!server.readTypeCheckingStringList(inputStorage, classes)) {
338  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Not allowed vehicle classes must be given as a list of strings.", outputStorage);
339  }
340  SVCPermissions permissions = ~parseVehicleClasses(classes); // negation yields allowed
341  const std::vector<MSLane*>& lanes = e->getLanes();
342  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
343  (*i)->setPermissions(permissions);
344  }
345  e->rebuildAllowedLanes();
346  }
347  break;
348  case VAR_EDGE_TRAVELTIME: {
349  // read and set travel time
350  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
351  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires a compound object.", outputStorage);
352  }
353  int parameterCount = inputStorage.readInt();
354  if (parameterCount == 3) {
355  // bound by time
356  SUMOTime begTime = 0, endTime = 0;
357  double value = 0;
358  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
359  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The first variable must be the begin time given as int.", outputStorage);
360  }
361  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
362  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The second variable must be the end time given as int.", outputStorage);
363  }
364  if (!server.readTypeCheckingDouble(inputStorage, value)) {
365  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The third variable must be the value given as double", outputStorage);
366  }
367  MSNet::getInstance()->getWeightsStorage().addTravelTime(e, begTime, endTime, value);
368  } else if (parameterCount == 1) {
369  // unbound
370  double value = 0;
371  if (!server.readTypeCheckingDouble(inputStorage, value)) {
372  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The variable must be the value given as double", outputStorage);
373  }
375  } else {
376  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires either begin time, end time, and value, or only value as parameter.", outputStorage);
377  }
378  }
379  break;
380  case VAR_EDGE_EFFORT: {
381  // read and set effort
382  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
383  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires a compound object.", outputStorage);
384  }
385  int parameterCount = inputStorage.readInt();
386  if (parameterCount == 3) {
387  // bound by time
388  SUMOTime begTime = 0, endTime = 0;
389  double value = 0;
390  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
391  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The first variable must be the begin time given as int.", outputStorage);
392  }
393  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
394  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The second variable must be the end time given as int.", outputStorage);
395  }
396  if (!server.readTypeCheckingDouble(inputStorage, value)) {
397  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The third variable must be the value given as double", outputStorage);
398  }
399  MSNet::getInstance()->getWeightsStorage().addEffort(e, begTime, endTime, value);
400  } else if (parameterCount == 1) {
401  // unbound
402  double value = 0;
403  if (!server.readTypeCheckingDouble(inputStorage, value)) {
404  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The variable must be the value given as double", outputStorage);
405  }
407  } else {
408  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires either begin time, end time, and value, or only value as parameter.", outputStorage);
409  }
410  }
411  break;
412  case VAR_MAXSPEED: {
413  // read and set max. speed
414  double value = 0;
415  if (!server.readTypeCheckingDouble(inputStorage, value)) {
416  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The speed must be given as a double.", outputStorage);
417  }
418  const std::vector<MSLane*>& lanes = e->getLanes();
419  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
420  (*i)->setMaxSpeed(value);
421  }
422  }
423  break;
424  default:
425  break;
426  }
427  server.writeStatusCmd(CMD_SET_EDGE_VARIABLE, RTYPE_OK, warning, outputStorage);
428  return true;
429 }
430 
431 
432 bool
433 TraCIServerAPI_Edge::getShape(const std::string& id, PositionVector& shape) {
434  MSEdge* e = MSEdge::dictionary(id);
435  if (e == 0) {
436  return false;
437  }
438  const std::vector<MSLane*>& lanes = e->getLanes();
439  shape.push_back(lanes.front()->getShape());
440  if (lanes.size() > 1) {
441  shape.push_back(lanes.back()->getShape().reverse());
442  }
443  return true;
444 }
445 
446 #endif
447 
448 
449 /****************************************************************************/
450 
#define LAST_STEP_MEAN_SPEED
static void insertIDs(std::vector< std::string > &into)
Inserts IDs of all known edges into the given vector.
Definition: MSEdge.cpp:528
#define VAR_CO2EMISSION
#define TYPE_COMPOUND
#define VAR_CURRENT_TRAVELTIME
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:173
#define RTYPE_OK
#define VAR_WAITING_TIME
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:88
SUMOReal getCurrentTravelTime(const SUMOReal minSpeed=0.00001) const
Computes and returns the current travel time for this edge.
Definition: MSEdge.cpp:445
bool readTypeCheckingInt(tcpip::Storage &inputStorage, int &into)
Reads the value type and an int, verifying the type.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
#define TYPE_STRINGLIST
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
static bool dictionary(const std::string &id, MSEdge *edge)
Inserts edge into the static dictionary Returns true if the key id isn't already in the dictionary...
Definition: MSEdge.cpp:473
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xca: Change Edge State)
virtual void writeUnsignedByte(int)
#define CMD_SET_EDGE_VARIABLE
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
#define VAR_NOISEEMISSION
#define VAR_FUELCONSUMPTION
void addEffort(const MSEdge *const e, SUMOReal begin, SUMOReal end, SUMOReal value)
Adds an effort information for an edge and a time span.
virtual void writeInt(int)
virtual int readUnsignedByte()
#define LAST_STEP_LENGTH
void addTravelTime(const MSEdge *const e, SUMOReal begin, SUMOReal end, SUMOReal value)
Adds a travel time information for an edge and a time span.
#define VAR_NOXEMISSION
A road/street connecting two junctions.
Definition: MSEdge.h:74
#define LANE_ALLOWED
void rebuildAllowedLanes()
Definition: MSEdge.cpp:173
virtual int readInt()
A list of positions.
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
virtual void writeStringList(const std::vector< std::string > &s)
#define VAR_PMXEMISSION
#define CMD_SET_VEHICLE_VARIABLE
virtual std::string readString()
#define CMD_GET_EDGE_VARIABLE
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
#define VAR_EDGE_EFFORT
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:74
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
#define LAST_STEP_VEHICLE_NUMBER
#define VAR_EDGE_TRAVELTIME
void push_back(const PositionVector &p)
Appends all positions from the given vector.
#define VAR_COEMISSION
static bool getShape(const std::string &id, PositionVector &shape)
Returns the named edge's shape.
virtual void writeString(const std::string &s)
#define LAST_STEP_VEHICLE_ID_LIST
#define LANE_DISALLOWED
#define SUMOTime_MAX
Definition: SUMOTime.h:44
#define TYPE_DOUBLE
const SUMOReal SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:54
static SUMOReal sum(SUMOReal val)
Computes the resulting noise.
virtual void writeDouble(double)
#define SUMOReal
Definition: config.h:215
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
#define LAST_STEP_OCCUPANCY
#define VAR_MAXSPEED
#define ID_COUNT
#define TYPE_INTEGER
#define ID_LIST
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xaa: Get Edge Variable)
#define LAST_STEP_VEHICLE_HALTING_NUMBER
#define VAR_HCEMISSION
#define RESPONSE_GET_EDGE_VARIABLE
MSEdgeWeightsStorage & getWeightsStorage()
Returns the net's internal edge travel times/efforts container.
Definition: MSNet.cpp:636