SUMO - Simulation of Urban MObility
TraCIServerAPI_Simulation.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // APIs for getting/setting edge values via TraCI
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #ifndef NO_TRACI
35 
36 #include <utils/common/StdDefs.h>
38 #include <microsim/MSNet.h>
39 #include <microsim/MSEdgeControl.h>
41 #include <microsim/MSEdge.h>
42 #include <microsim/MSLane.h>
43 #include <microsim/MSVehicle.h>
45 #include <traci-server/lib/TraCI.h>
46 #include "TraCIConstants.h"
48 
49 
50 // ===========================================================================
51 // method definitions
52 // ===========================================================================
53 bool
55  tcpip::Storage& outputStorage) {
56  // variable & id
57  int variable = inputStorage.readUnsignedByte();
58  std::string id = inputStorage.readString();
59  // check variable
60  if (variable != VAR_TIME_STEP
61  && variable != VAR_LOADED_VEHICLES_NUMBER && variable != VAR_LOADED_VEHICLES_IDS
62  && variable != VAR_DEPARTED_VEHICLES_NUMBER && variable != VAR_DEPARTED_VEHICLES_IDS
65  && variable != VAR_ARRIVED_VEHICLES_NUMBER && variable != VAR_ARRIVED_VEHICLES_IDS
66  && variable != VAR_DELTA_T && variable != VAR_NET_BOUNDING_BOX
67  && variable != VAR_MIN_EXPECTED_VEHICLES
68  && variable != POSITION_CONVERSION && variable != DISTANCE_REQUEST
69  && variable != VAR_BUS_STOP_WAITING
74  ) {
75  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Get Simulation Variable: unsupported variable " + toHex(variable, 2) + " 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  switch (variable) {
85  case VAR_TIME_STEP:
87  tempMsg.writeInt((int)MSNet::getInstance()->getCurrentTimeStep());
88  break;
91  break;
93  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
95  tempMsg.writeStringList(ids);
96  }
97  break;
100  break;
103  break;
106  break;
109  break;
112  break;
115  break;
118  break;
121  break;
124  break;
127  break;
130  break;
133  break;
136  break;
139  break;
142  break;
145  break;
146  case VAR_DELTA_T:
148  tempMsg.writeInt((int)DELTA_T);
149  break;
150  case VAR_NET_BOUNDING_BOX: {
153  tempMsg.writeDouble(b.xmin());
154  tempMsg.writeDouble(b.ymin());
155  tempMsg.writeDouble(b.xmax());
156  tempMsg.writeDouble(b.ymax());
157  break;
158  }
159  break;
162  tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount());
163  break;
164  case POSITION_CONVERSION:
165  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
166  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a compound object.", outputStorage);
167  }
168  if (inputStorage.readInt() != 2) {
169  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a source position and a position type as parameter.", outputStorage);
170  }
171  if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
172  return false;
173  }
174  break;
175  case DISTANCE_REQUEST:
176  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
177  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires a compound object.", outputStorage);
178  }
179  if (inputStorage.readInt() != 3) {
180  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage);
181  }
182  if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
183  return false;
184  }
185  break;
186  case VAR_BUS_STOP_WAITING: {
187  std::string id;
188  if (!server.readTypeCheckingString(inputStorage, id)) {
189  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of persons at busstop requires a string.", outputStorage);
190  }
192  if (s == 0) {
193  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Unknown bus stop '" + id + "'.", outputStorage);
194  }
196  tempMsg.writeInt(s->getTransportableNumber());
197  break;
198  }
199  default:
200  break;
201  }
202  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, "", outputStorage);
203  server.writeResponseWithLength(outputStorage, tempMsg);
204  return true;
205 }
206 
207 
208 bool
210  tcpip::Storage& outputStorage) {
211  std::string warning = ""; // additional description for response
212  // variable
213  int variable = inputStorage.readUnsignedByte();
214  if (variable != CMD_CLEAR_PENDING_VEHICLES
215  && variable != CMD_SAVE_SIMSTATE) {
216  return server.writeErrorStatusCmd(CMD_SET_SIM_VARIABLE, "Set Simulation Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
217  }
218  // id
219  std::string id = inputStorage.readString();
220  // process
221  switch (variable) {
223  //clear any pending vehicle insertions
224  std::string route;
225  if (!server.readTypeCheckingString(inputStorage, route)) {
226  return server.writeErrorStatusCmd(CMD_SET_SIM_VARIABLE, "A string is needed for clearing pending vehicles.", outputStorage);
227  }
229  }
230  break;
231  case CMD_SAVE_SIMSTATE: {
232  //save current simulation state
233  std::string file;
234  if (!server.readTypeCheckingString(inputStorage, file)) {
235  return server.writeErrorStatusCmd(CMD_SET_SIM_VARIABLE, "A string is needed for saving simulation state.", outputStorage);
236  }
237  MSStateHandler::saveState(file, MSNet::getInstance()->getCurrentTimeStep());
238  }
239  break;
240  default:
241  break;
242  }
243  server.writeStatusCmd(CMD_SET_SIM_VARIABLE, RTYPE_OK, warning, outputStorage);
244  return true;
245 }
246 
247 
248 void
250  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(state)->second;
251  outputStorage.writeUnsignedByte(TYPE_INTEGER);
252  outputStorage.writeInt((int) ids.size());
253 }
254 
255 
256 void
258  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(state)->second;
259  outputStorage.writeUnsignedByte(TYPE_STRINGLIST);
260  outputStorage.writeStringList(ids);
261 }
262 
263 
264 std::pair<MSLane*, double>
266  std::pair<MSLane*, double> result;
267  std::vector<std::string> allEdgeIds;
268  double minDistance = std::numeric_limits<double>::max();
269 
270  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
271  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
272  const std::vector<MSLane*>& allLanes = MSEdge::dictionary((*itId))->getLanes();
273  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
274  const double newDistance = (*itLane)->getShape().distance2D(pos);
275  if (newDistance < minDistance) {
276  minDistance = newDistance;
277  result.first = (*itLane);
278  }
279  }
280  }
281  // @todo this may be a place where 3D is required but 2D is delivered
282  result.second = result.first->getShape().nearest_offset_to_point2D(pos, false);
283  return result;
284 }
285 
286 
287 bool
289  tcpip::Storage& outputStorage, int commandId) {
290  std::pair<MSLane*, double> roadPos;
291  Position cartesianPos;
292  Position geoPos;
293  double z = 0;
294 
295  // actual position type that will be converted
296  int srcPosType = inputStorage.readUnsignedByte();
297 
298  switch (srcPosType) {
299  case POSITION_2D:
300  case POSITION_3D:
301  case POSITION_LON_LAT:
302  case POSITION_LON_LAT_ALT: {
303  double x = inputStorage.readDouble();
304  double y = inputStorage.readDouble();
305  if (srcPosType != POSITION_2D && srcPosType != POSITION_LON_LAT) {
306  z = inputStorage.readDouble();
307  }
308  geoPos.set(x, y);
309  cartesianPos.set(x, y);
310  if (srcPosType == POSITION_LON_LAT || srcPosType == POSITION_LON_LAT_ALT) {
312  } else {
314  }
315  }
316  break;
317  case POSITION_ROADMAP: {
318  std::string roadID = inputStorage.readString();
319  double pos = inputStorage.readDouble();
320  int laneIdx = inputStorage.readUnsignedByte();
321  try {
322  // convert edge,offset,laneIdx to cartesian position
323  cartesianPos = geoPos = TraCI::getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtOffset(pos);
324  z = cartesianPos.z();
326  } catch (TraCIException& e) {
327  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
328  return false;
329  }
330  }
331  break;
332  default:
333  server.writeStatusCmd(commandId, RTYPE_ERR, "Source position type not supported");
334  return false;
335  }
336 
337  int destPosType = 0;
338  if (!server.readTypeCheckingUnsignedByte(inputStorage, destPosType)) {
339  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type must be of type ubyte.");
340  return false;
341  }
342 
343  switch (destPosType) {
344  case POSITION_ROADMAP: {
345  // convert cartesion position to edge,offset,lane_index
346  roadPos = convertCartesianToRoadMap(cartesianPos);
347  // write result that is added to response msg
348  outputStorage.writeUnsignedByte(POSITION_ROADMAP);
349  outputStorage.writeString(roadPos.first->getEdge().getID());
350  outputStorage.writeDouble(roadPos.second);
351  const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes();
352  outputStorage.writeUnsignedByte((int)distance(lanes.begin(), find(lanes.begin(), lanes.end(), roadPos.first)));
353  }
354  break;
355  case POSITION_2D:
356  case POSITION_3D:
357  case POSITION_LON_LAT:
359  outputStorage.writeUnsignedByte(destPosType);
360  if (destPosType == POSITION_LON_LAT || destPosType == POSITION_LON_LAT_ALT) {
361  outputStorage.writeDouble(geoPos.x());
362  outputStorage.writeDouble(geoPos.y());
363  } else {
364  outputStorage.writeDouble(cartesianPos.x());
365  outputStorage.writeDouble(cartesianPos.y());
366  }
367  if (destPosType != POSITION_2D && destPosType != POSITION_LON_LAT) {
368  outputStorage.writeDouble(z);
369  }
370  break;
371  default:
372  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type not supported");
373  return false;
374  }
375  return true;
376 }
377 
378 /****************************************************************************/
379 
380 bool
382  tcpip::Storage& outputStorage, int commandId) {
383  Position pos1;
384  Position pos2;
385  std::pair<const MSLane*, double> roadPos1;
386  std::pair<const MSLane*, double> roadPos2;
387 
388  // read position 1
389  int posType = inputStorage.readUnsignedByte();
390  switch (posType) {
391  case POSITION_ROADMAP:
392  try {
393  std::string roadID = inputStorage.readString();
394  roadPos1.second = inputStorage.readDouble();
395  roadPos1.first = TraCI::getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second);
396  pos1 = roadPos1.first->getShape().positionAtOffset(roadPos1.second);
397  } catch (TraCIException& e) {
398  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
399  return false;
400  }
401  break;
402  case POSITION_2D:
403  case POSITION_3D: {
404  double p1x = inputStorage.readDouble();
405  double p1y = inputStorage.readDouble();
406  pos1.set(p1x, p1y);
407  }
408  if (posType == POSITION_3D) {
409  inputStorage.readDouble();// z value is ignored
410  }
411  roadPos1 = convertCartesianToRoadMap(pos1);
412  break;
413  default:
414  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
415  return false;
416  }
417 
418  // read position 2
419  posType = inputStorage.readUnsignedByte();
420  switch (posType) {
421  case POSITION_ROADMAP:
422  try {
423  std::string roadID = inputStorage.readString();
424  roadPos2.second = inputStorage.readDouble();
425  roadPos2.first = TraCI::getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second);
426  pos2 = roadPos2.first->getShape().positionAtOffset(roadPos2.second);
427  } catch (TraCIException& e) {
428  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
429  return false;
430  }
431  break;
432  case POSITION_2D:
433  case POSITION_3D: {
434  double p2x = inputStorage.readDouble();
435  double p2y = inputStorage.readDouble();
436  pos2.set(p2x, p2y);
437  }
438  if (posType == POSITION_3D) {
439  inputStorage.readDouble();// z value is ignored
440  }
441  roadPos2 = convertCartesianToRoadMap(pos2);
442  break;
443  default:
444  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
445  return false;
446  }
447 
448  // read distance type
449  int distType = inputStorage.readUnsignedByte();
450 
451  double distance = 0.0;
452  if (distType == REQUEST_DRIVINGDIST) {
453  // compute driving distance
454  if ((roadPos1.first == roadPos2.first) && (roadPos1.second <= roadPos2.second)) {
455  // same edge
456  distance = roadPos2.second - roadPos1.second;
457  } else {
458  ConstMSEdgeVector newRoute;
460  &roadPos1.first->getEdge(), &roadPos2.first->getEdge(), 0, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
461  MSRoute route("", newRoute, false, 0, std::vector<SUMOVehicleParameter::Stop>());
462  distance = route.getDistanceBetween(roadPos1.second, roadPos2.second, &roadPos1.first->getEdge(), &roadPos2.first->getEdge());
463  }
464  } else {
465  // compute air distance (default)
466  distance = pos1.distanceTo(pos2);
467  }
468  // write response command
469  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
470  outputStorage.writeDouble(distance);
471  return true;
472 }
473 
474 
475 #endif
476 
477 /****************************************************************************/
The vehicle has departed (was inserted into the network)
Definition: MSNet.h:580
#define CMD_CLEAR_PENDING_VEHICLES
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:138
#define VAR_TIME_STEP
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:132
#define REQUEST_DRIVINGDIST
static void writeVehicleStateIDs(TraCIServer &server, tcpip::Storage &outputStorage, MSNet::VehicleState state)
double z() const
Returns the z-position.
Definition: Position.h:73
#define TYPE_COMPOUND
const Boundary & getConvBoundary() const
Returns the converted boundary.
#define POSITION_2D
A lane area vehicles can halt at.
#define VAR_PARKING_STARTING_VEHICLES_IDS
#define VAR_STOP_ENDING_VEHICLES_IDS
#define VAR_PARKING_ENDING_VEHICLES_NUMBER
#define POSITION_LON_LAT_ALT
double y() const
Returns the y-position.
Definition: Position.h:68
#define RTYPE_OK
#define POSITION_ROADMAP
#define DISTANCE_REQUEST
virtual double readDouble()
double getDistanceBetween(double fromPos, double toPos, const MSEdge *fromEdge, const MSEdge *toEdge, bool includeInternal=true) const
Compute the distance between 2 given edges on this route, including the length of internal lanes...
Definition: MSRoute.cpp:281
double x() const
Returns the x-position.
Definition: Position.h:63
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E *> &into)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
#define VAR_LOADED_VEHICLES_IDS
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xab: Get Simulation Variable)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
#define TYPE_STRINGLIST
const PositionVector & getShape() const
Returns this lane&#39;s shape.
Definition: MSLane.h:426
#define RESPONSE_GET_SIM_VARIABLE
#define POSITION_3D
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:728
#define VAR_TELEPORT_STARTING_VEHICLES_IDS
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:78
int getTransportableNumber() const
Returns the number of transportables waiting on this stop.
virtual void writeUnsignedByte(int)
void set(double x, double y)
set positions x and y
Definition: Position.h:93
#define POSITION_LON_LAT
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_LOADED_VEHICLES_NUMBER
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
#define VAR_STOP_STARTING_VEHICLES_NUMBER
static void writeVehicleStateNumber(TraCIServer &server, tcpip::Storage &outputStorage, MSNet::VehicleState state)
virtual void writeInt(int)
virtual int readUnsignedByte()
std::vector< std::string > getEdgeNames() const
Returns the list of names of all known edges.
The vehicles starts to stop.
Definition: MSNet.h:594
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
#define POSITION_CONVERSION
#define CMD_SAVE_SIMSTATE
#define VAR_DEPARTED_VEHICLES_NUMBER
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcb: Set Simulation Variable)
#define max(a, b)
Definition: polyfonts.c:65
#define VAR_MIN_EXPECTED_VEHICLES
The vehicle arrived at his destination (is deleted)
Definition: MSNet.h:586
The vehicles starts to park.
Definition: MSNet.h:590
virtual int readInt()
static const MSLane * getLaneChecking(const std::string &edgeID, int laneIndex, double pos)
Definition: TraCI.cpp:169
#define VAR_STOP_STARTING_VEHICLES_IDS
#define VAR_NET_BOUNDING_BOX
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
#define VAR_TELEPORT_STARTING_VEHICLES_NUMBER
#define TYPE_BOUNDINGBOX
virtual void writeStringList(const std::vector< std::string > &s)
static bool commandPositionConversion(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage, int commandId)
#define VAR_TELEPORT_ENDING_VEHICLES_IDS
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:257
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:126
The vehicle started to teleport.
Definition: MSNet.h:582
#define CMD_GET_SIM_VARIABLE
virtual std::string readString()
#define VAR_DEPARTED_VEHICLES_IDS
void clearPendingVehicles(std::string &route)
clears out all pending vehicles from a route, "" for all routes
The vehicle ends to park.
Definition: MSNet.h:592
bool readTypeCheckingUnsignedByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and an unsigned byte, verifying the type.
#define VAR_DELTA_T
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:74
#define CMD_SET_SIM_VARIABLE
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:576
static bool commandDistanceRequest(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage, int commandId)
The vehicle was built, but has not yet departed.
Definition: MSNet.h:578
#define VAR_ARRIVED_VEHICLES_NUMBER
virtual void writeString(const std::string &s)
#define TYPE_DOUBLE
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:66
#define VAR_STOP_ENDING_VEHICLES_NUMBER
MSInsertionControl & getInsertionControl()
Returns the insertion control.
Definition: MSNet.h:363
const std::map< MSNet::VehicleState, std::vector< std::string > > & getVehicleStateChanges() const
Definition: TraCIServer.h:161
#define VAR_PARKING_ENDING_VEHICLES_IDS
The vehicle ends to stop.
Definition: MSNet.h:596
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
static std::pair< MSLane *, double > convertCartesianToRoadMap(Position pos)
virtual void writeDouble(double)
#define VAR_TELEPORT_ENDING_VEHICLES_NUMBER
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:240
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition: MSNet.h:353
#define VAR_PARKING_STARTING_VEHICLES_NUMBER
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector()) const
Definition: MSNet.cpp:925
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:144
#define RTYPE_ERR
#define TYPE_INTEGER
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
#define VAR_ARRIVED_VEHICLES_IDS
MSStoppingPlace * getBusStop(const std::string &id) const
Returns the named bus stop.
Definition: MSNet.cpp:827
The vehicle ended being teleported.
Definition: MSNet.h:584
#define VAR_BUS_STOP_WAITING
static void saveState(const std::string &file, SUMOTime step)
Saves the current state.