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