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-2014 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 // method definitions
55 // ===========================================================================
56 bool
58  tcpip::Storage& outputStorage) {
59  // variable & id
60  int variable = inputStorage.readUnsignedByte();
61  std::string id = inputStorage.readString();
62  // check variable
63  if (variable != ID_LIST && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT && variable != VAR_CURRENT_TRAVELTIME
64  && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION
65  && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION && variable != VAR_WAITING_TIME
66  && variable != LAST_STEP_VEHICLE_NUMBER && variable != LAST_STEP_MEAN_SPEED && variable != LAST_STEP_OCCUPANCY
67  && variable != LAST_STEP_VEHICLE_HALTING_NUMBER && variable != LAST_STEP_LENGTH
68  && variable != LAST_STEP_VEHICLE_ID_LIST && variable != ID_COUNT) {
69  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "Get Edge Variable: unsupported variable specified", outputStorage);
70  }
71  // begin response building
72  tcpip::Storage tempMsg;
73  // response-code, variableID, objectID
75  tempMsg.writeUnsignedByte(variable);
76  tempMsg.writeString(id);
77  // process request
78  if (variable == ID_LIST) {
79  std::vector<std::string> ids;
80  MSEdge::insertIDs(ids);
82  tempMsg.writeStringList(ids);
83  } else if (variable == ID_COUNT) {
84  std::vector<std::string> ids;
85  MSEdge::insertIDs(ids);
87  tempMsg.writeInt((int) ids.size());
88  } else {
89  MSEdge* e = MSEdge::dictionary(id);
90  if (e == 0) {
91  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "Edge '" + id + "' is not known", outputStorage);
92  }
93  switch (variable) {
94  case VAR_EDGE_TRAVELTIME: {
95  // time
96  SUMOTime time = 0;
97  if (!server.readTypeCheckingInt(inputStorage, time)) {
98  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The message must contain the time definition.", outputStorage);
99  }
101  SUMOReal value;
102  if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, 0, time, value)) {
103  tempMsg.writeDouble(-1);
104  } else {
105  tempMsg.writeDouble(value);
106  }
107  }
108  break;
109  case VAR_EDGE_EFFORT: {
110  // time
111  SUMOTime time = 0;
112  if (!server.readTypeCheckingInt(inputStorage, time)) {
113  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The message must contain the time definition.", outputStorage);
114  }
116  SUMOReal value;
117  if (!MSNet::getInstance()->getWeightsStorage().retrieveExistingEffort(e, 0, time, value)) {
118  tempMsg.writeDouble(-1);
119  } else {
120  tempMsg.writeDouble(value);
121  }
122  }
123  break;
126  tempMsg.writeDouble(e->getCurrentTravelTime());
127  break;
128  case VAR_WAITING_TIME: {
129  SUMOReal wtime = 0;
130  const std::vector<MSLane*>& lanes = e->getLanes();
131  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
132  wtime += (*i)->getWaitingSeconds();
133  }
135  tempMsg.writeDouble(wtime);
136  }
137  break;
139  std::vector<std::string> vehIDs;
140  const std::vector<MSLane*>& lanes = e->getLanes();
141  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
142  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
143  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
144  vehIDs.push_back((*j)->getID());
145  }
146  (*i)->releaseVehicles();
147  }
149  tempMsg.writeStringList(vehIDs);
150  }
151  break;
152  case VAR_CO2EMISSION: {
153  SUMOReal sum = 0;
154  const std::vector<MSLane*>& lanes = e->getLanes();
155  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
156  sum += (*i)->getCO2Emissions();
157  }
159  tempMsg.writeDouble(sum);
160  }
161  break;
162  case VAR_COEMISSION: {
163  SUMOReal sum = 0;
164  const std::vector<MSLane*>& lanes = e->getLanes();
165  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
166  sum += (*i)->getCOEmissions();
167  }
169  tempMsg.writeDouble(sum);
170  }
171  break;
172  case VAR_HCEMISSION: {
173  SUMOReal sum = 0;
174  const std::vector<MSLane*>& lanes = e->getLanes();
175  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
176  sum += (*i)->getHCEmissions();
177  }
179  tempMsg.writeDouble(sum);
180  }
181  break;
182  case VAR_PMXEMISSION: {
183  SUMOReal sum = 0;
184  const std::vector<MSLane*>& lanes = e->getLanes();
185  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
186  sum += (*i)->getPMxEmissions();
187  }
189  tempMsg.writeDouble(sum);
190  }
191  break;
192  case VAR_NOXEMISSION: {
193  SUMOReal sum = 0;
194  const std::vector<MSLane*>& lanes = e->getLanes();
195  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
196  sum += (*i)->getNOxEmissions();
197  }
199  tempMsg.writeDouble(sum);
200  }
201  break;
202  case VAR_FUELCONSUMPTION: {
203  SUMOReal sum = 0;
204  const std::vector<MSLane*>& lanes = e->getLanes();
205  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
206  sum += (*i)->getFuelConsumption();
207  }
209  tempMsg.writeDouble(sum);
210  }
211  break;
212  case VAR_NOISEEMISSION: {
213  SUMOReal sum = 0;
214  const std::vector<MSLane*>& lanes = e->getLanes();
215  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
216  sum += (SUMOReal) pow(10., ((*i)->getHarmonoise_NoiseEmissions() / 10.));
217  }
219  if (sum != 0) {
220  tempMsg.writeDouble(HelpersHarmonoise::sum(sum));
221  } else {
222  tempMsg.writeDouble(0);
223  }
224  }
225  break;
227  int sum = 0;
228  const std::vector<MSLane*>& lanes = e->getLanes();
229  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
230  sum += (*i)->getVehicleNumber();
231  }
233  tempMsg.writeInt(sum);
234  }
235  break;
236  case LAST_STEP_MEAN_SPEED: {
237  SUMOReal sum = 0;
238  const std::vector<MSLane*>& lanes = e->getLanes();
239  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
240  sum += (*i)->getMeanSpeed();
241  }
243  tempMsg.writeDouble(sum / (SUMOReal) lanes.size());
244  }
245  break;
246  case LAST_STEP_OCCUPANCY: {
247  SUMOReal sum = 0;
248  const std::vector<MSLane*>& lanes = e->getLanes();
249  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
250  sum += (*i)->getNettoOccupancy();
251  }
253  tempMsg.writeDouble(sum / (SUMOReal) lanes.size());
254  }
255  break;
257  int halting = 0;
258  const std::vector<MSLane*>& lanes = e->getLanes();
259  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
260  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
261  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
262  if ((*j)->getSpeed() < SUMO_const_haltingSpeed) {
263  ++halting;
264  }
265  }
266  (*i)->releaseVehicles();
267  }
269  tempMsg.writeInt(halting);
270  }
271  break;
272  case LAST_STEP_LENGTH: {
273  SUMOReal lengthSum = 0;
274  int noVehicles = 0;
275  const std::vector<MSLane*>& lanes = e->getLanes();
276  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
277  const MSLane::VehCont& vehs = (*i)->getVehiclesSecure();
278  for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
279  lengthSum += (*j)->getVehicleType().getLength();
280  }
281  noVehicles += (int) vehs.size();
282  (*i)->releaseVehicles();
283  }
285  if (noVehicles == 0) {
286  tempMsg.writeDouble(0);
287  } else {
288  tempMsg.writeDouble(lengthSum / (SUMOReal) noVehicles);
289  }
290  }
291  break;
292  default:
293  break;
294  }
295  }
296  server.writeStatusCmd(CMD_GET_EDGE_VARIABLE, RTYPE_OK, "", outputStorage);
297  server.writeResponseWithLength(outputStorage, tempMsg);
298  return true;
299 }
300 
301 
302 bool
304  tcpip::Storage& outputStorage) {
305  std::string warning = ""; // additional description for response
306  // variable
307  int variable = inputStorage.readUnsignedByte();
308  if (variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT && variable != VAR_MAXSPEED) {
309  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Change Edge State: unsupported variable specified", outputStorage);
310  }
311  // id
312  std::string id = inputStorage.readString();
313  MSEdge* e = MSEdge::dictionary(id);
314  if (e == 0) {
315  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Edge '" + id + "' is not known", outputStorage);
316  }
317  // process
318  switch (variable) {
319  case LANE_ALLOWED: {
320  // read and set allowed vehicle classes
321  std::vector<std::string> classes;
322  if (!server.readTypeCheckingStringList(inputStorage, classes)) {
323  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Allowed vehicle classes must be given as a list of strings.", outputStorage);
324  }
325  SVCPermissions permissions = parseVehicleClasses(classes);
326  const std::vector<MSLane*>& lanes = e->getLanes();
327  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
328  (*i)->setPermissions(permissions);
329  }
330  e->rebuildAllowedLanes();
331  }
332  break;
333  case LANE_DISALLOWED: {
334  // read and set disallowed vehicle classes
335  std::vector<std::string> classes;
336  if (!server.readTypeCheckingStringList(inputStorage, classes)) {
337  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "Not allowed vehicle classes must be given as a list of strings.", outputStorage);
338  }
339  SVCPermissions permissions = ~parseVehicleClasses(classes); // negation yields allowed
340  const std::vector<MSLane*>& lanes = e->getLanes();
341  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
342  (*i)->setPermissions(permissions);
343  }
344  e->rebuildAllowedLanes();
345  }
346  break;
347  case VAR_EDGE_TRAVELTIME: {
348  // read and set travel time
349  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
350  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires a compound object.", outputStorage);
351  }
352  int parameterCount = inputStorage.readInt();
353  if (parameterCount == 3) {
354  // bound by time
355  SUMOTime begTime = 0, endTime = 0;
356  double value = 0;
357  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
358  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The first variable must be the begin time given as int.", outputStorage);
359  }
360  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
361  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The second variable must be the end time given as int.", outputStorage);
362  }
363  if (!server.readTypeCheckingDouble(inputStorage, value)) {
364  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The third variable must be the value given as double", outputStorage);
365  }
366  MSNet::getInstance()->getWeightsStorage().addTravelTime(e, begTime, endTime, value);
367  } else if (parameterCount == 1) {
368  // unbound
369  double value = 0;
370  if (!server.readTypeCheckingDouble(inputStorage, value)) {
371  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The variable must be the value given as double", outputStorage);
372  }
374  } else {
375  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires either begin time, end time, and value, or only value as parameter.", outputStorage);
376  }
377  }
378  break;
379  case VAR_EDGE_EFFORT: {
380  // read and set effort
381  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
382  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires a compound object.", outputStorage);
383  }
384  int parameterCount = inputStorage.readInt();
385  if (parameterCount == 3) {
386  // bound by time
387  SUMOTime begTime = 0, endTime = 0;
388  double value = 0;
389  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
390  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The first variable must be the begin time given as int.", outputStorage);
391  }
392  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
393  return server.writeErrorStatusCmd(CMD_GET_EDGE_VARIABLE, "The second variable must be the end time given as int.", outputStorage);
394  }
395  if (!server.readTypeCheckingDouble(inputStorage, value)) {
396  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The third variable must be the value given as double", outputStorage);
397  }
398  MSNet::getInstance()->getWeightsStorage().addEffort(e, begTime, endTime, value);
399  } else if (parameterCount == 1) {
400  // unbound
401  double value = 0;
402  if (!server.readTypeCheckingDouble(inputStorage, value)) {
403  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The variable must be the value given as double", outputStorage);
404  }
406  } else {
407  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires either begin time, end time, and value, or only value as parameter.", outputStorage);
408  }
409  }
410  break;
411  case VAR_MAXSPEED: {
412  // read and set max. speed
413  double value = 0;
414  if (!server.readTypeCheckingDouble(inputStorage, value)) {
415  return server.writeErrorStatusCmd(CMD_SET_EDGE_VARIABLE, "The speed must be given as a double.", outputStorage);
416  }
417  const std::vector<MSLane*>& lanes = e->getLanes();
418  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
419  (*i)->setMaxSpeed(value);
420  }
421  }
422  break;
423  default:
424  break;
425  }
426  server.writeStatusCmd(CMD_SET_EDGE_VARIABLE, RTYPE_OK, warning, outputStorage);
427  return true;
428 }
429 
430 
431 bool
432 TraCIServerAPI_Edge::getShape(const std::string& id, PositionVector& shape) {
433  MSEdge* e = MSEdge::dictionary(id);
434  if (e == 0) {
435  return false;
436  }
437  const std::vector<MSLane*>& lanes = e->getLanes();
438  shape.push_back(lanes.front()->getShape());
439  if (lanes.size() > 1) {
440  shape.push_back(lanes.back()->getShape().reverse());
441  }
442  return true;
443 }
444 
445 #endif
446 
447 
448 /****************************************************************************/
449 
#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:520
#define VAR_CO2EMISSION
#define TYPE_COMPOUND
#define VAR_CURRENT_TRAVELTIME
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
#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:437
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:154
#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:465
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:73
#define LANE_ALLOWED
void rebuildAllowedLanes()
Definition: MSEdge.cpp:165
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. ...
#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:53
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:620