SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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.sourceforge.net/
13 // Copyright (C) 2001-2012 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>
44 #include "TraCIConstants.h"
45 #include "TraCIDijkstraRouter.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  std::string warning = ""; // additional description for response
66  // variable & id
67  int variable = inputStorage.readUnsignedByte();
68  std::string id = inputStorage.readString();
69  // check variable
70  if (variable != VAR_TIME_STEP
71  && variable != VAR_LOADED_VEHICLES_NUMBER && variable != VAR_LOADED_VEHICLES_IDS
72  && variable != VAR_DEPARTED_VEHICLES_NUMBER && variable != VAR_DEPARTED_VEHICLES_IDS
75  && variable != VAR_ARRIVED_VEHICLES_NUMBER && variable != VAR_ARRIVED_VEHICLES_IDS
76  && variable != VAR_DELTA_T && variable != VAR_NET_BOUNDING_BOX
77  && variable != VAR_MIN_EXPECTED_VEHICLES
78  && variable != POSITION_CONVERSION && variable != DISTANCE_REQUEST
79  ) {
80  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Get Simulation Variable: unsupported variable specified", outputStorage);
81  return false;
82  }
83  // begin response building
84  tcpip::Storage tempMsg;
85  // response-code, variableID, objectID
87  tempMsg.writeUnsignedByte(variable);
88  tempMsg.writeString(id);
89  // process request
90  switch (variable) {
91  case VAR_TIME_STEP:
93  tempMsg.writeInt(MSNet::getInstance()->getCurrentTimeStep());
94  break;
96  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
98  tempMsg.writeInt((int) ids.size());
99  }
100  break;
102  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
104  tempMsg.writeStringList(ids);
105  }
106  break;
108  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
110  tempMsg.writeInt((int) ids.size());
111  }
112  break;
114  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
116  tempMsg.writeStringList(ids);
117  }
118  break;
120  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
122  tempMsg.writeInt((int) ids.size());
123  }
124  break;
126  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
128  tempMsg.writeStringList(ids);
129  }
130  break;
132  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
134  tempMsg.writeInt((int) ids.size());
135  }
136  break;
138  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
140  tempMsg.writeStringList(ids);
141  }
142  break;
144  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
146  tempMsg.writeInt((int) ids.size());
147  }
148  break;
150  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
152  tempMsg.writeStringList(ids);
153  }
154  break;
155  case VAR_DELTA_T:
157  tempMsg.writeInt(DELTA_T);
158  break;
159  case VAR_NET_BOUNDING_BOX: {
162  tempMsg.writeDouble(b.xmin());
163  tempMsg.writeDouble(b.ymin());
164  tempMsg.writeDouble(b.xmax());
165  tempMsg.writeDouble(b.ymax());
166  break;
167  }
168  break;
170  const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
172  tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount());
173  }
174  break;
175  case POSITION_CONVERSION:
176  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
177  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a compound object.", outputStorage);
178  return false;
179  }
180  if (inputStorage.readInt() != 2) {
181  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a source position and a position type as parameter.", outputStorage);
182  return false;
183  }
184  if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
185  return false;
186  }
187  break;
188  case DISTANCE_REQUEST:
189  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
190  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires a compound object.", outputStorage);
191  return false;
192  }
193  if (inputStorage.readInt() != 3) {
194  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage);
195  return false;
196  }
197  if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
198  return false;
199  }
200  break;
201  default:
202  break;
203  }
204  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, warning, outputStorage);
205  server.writeResponseWithLength(outputStorage, tempMsg);
206  return true;
207 }
208 
209 
210 std::pair<MSLane*, SUMOReal>
212  std::pair<MSLane*, SUMOReal> result;
213  std::vector<std::string> allEdgeIds;
215 
216  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
217  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
218  const std::vector<MSLane*> &allLanes = MSEdge::dictionary((*itId))->getLanes();
219  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
220  const SUMOReal newDistance = (*itLane)->getShape().distance(pos);
221  if (newDistance < minDistance) {
222  minDistance = newDistance;
223  result.first = (*itLane);
224  }
225  }
226  }
227  // @todo this may be a place where 3D is required but 2D is delivered
228  result.second = result.first->getShape().nearest_position_on_line_to_point2D(pos, false);
229  return result;
230 }
231 
232 
233 const MSLane*
234 TraCIServerAPI_Simulation::getLaneChecking(std::string roadID, int laneIndex, SUMOReal pos) {
235  const MSEdge* edge = MSEdge::dictionary(roadID);
236  if (edge == 0) {
237  throw TraCIException("Unknown edge " + roadID);
238  }
239  if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
240  throw TraCIException("Invalid lane index for " + roadID);
241  }
242  const MSLane* lane = edge->getLanes()[laneIndex];
243  if (pos < 0 || pos > lane->getLength()) {
244  throw TraCIException("Position on lane invalid");
245  }
246  return lane;
247 }
248 
249 
250 bool
252  tcpip::Storage& outputStorage, int commandId) {
253  tcpip::Storage tmpResult;
254  std::pair<MSLane*, SUMOReal> roadPos;
255  Position cartesianPos;
256  Position geoPos;
257  SUMOReal z = 0;
258 
259  // actual position type that will be converted
260  int srcPosType = inputStorage.readUnsignedByte();
261 
262  switch (srcPosType) {
263  case POSITION_2D:
264  case POSITION_3D:
265  case POSITION_LAT_LON:
266  case POSITION_LAT_LON_ALT: {
267  SUMOReal x = inputStorage.readDouble();
268  SUMOReal y = inputStorage.readDouble();
269  if (srcPosType != POSITION_2D && srcPosType != POSITION_LAT_LON) {
270  z = inputStorage.readDouble();
271  }
272  geoPos.set(x, y);
273  cartesianPos.set(x, y);
274  if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) {
276  } else {
278  }
279  }
280  break;
281  case POSITION_ROADMAP: {
282  std::string roadID = inputStorage.readString();
283  SUMOReal pos = inputStorage.readDouble();
284  int laneIdx = inputStorage.readUnsignedByte();
285  try {
286  cartesianPos = geoPos = getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtLengthPosition(pos);
288  } catch (TraCIException& e) {
289  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
290  return false;
291  }
292  }
293  break;
294  default:
295  server.writeStatusCmd(commandId, RTYPE_ERR,
296  "Source position type not supported");
297  return false;
298  }
299 
300  int destPosType = inputStorage.readUnsignedByte();
301 
302  switch (destPosType) {
303  case POSITION_ROADMAP: {
304  if (commandId != CMD_POSITIONCONVERSION) {
305  // skip empty values
306  inputStorage.readString();
307  inputStorage.readDouble();
308  inputStorage.readUnsignedByte();
309  }
310  // convert road map to 3D position
311  roadPos = convertCartesianToRoadMap(cartesianPos);
312 
313  // write result that is added to response msg
315  tmpResult.writeString(roadPos.first->getEdge().getID());
316  tmpResult.writeDouble(roadPos.second);
317  const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes();
318  tmpResult.writeUnsignedByte((int)distance(lanes.begin(), find(lanes.begin(), lanes.end(), roadPos.first)));
319  }
320  break;
321  case POSITION_2D:
322  case POSITION_3D:
323  case POSITION_LAT_LON:
325  if (commandId != CMD_POSITIONCONVERSION) {
326  // skip empty values
327  inputStorage.readDouble();
328  inputStorage.readDouble();
329  if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) {
330  inputStorage.readDouble();
331  }
332  }
333  tmpResult.writeUnsignedByte(destPosType);
334  if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) {
335  tmpResult.writeDouble(geoPos.x());
336  tmpResult.writeDouble(geoPos.y());
337  } else {
338  tmpResult.writeDouble(cartesianPos.x());
339  tmpResult.writeDouble(cartesianPos.y());
340  }
341  if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) {
342  tmpResult.writeDouble(z);
343  }
344  break;
345  default:
346  server.writeStatusCmd(commandId, RTYPE_ERR,
347  "Destination position type not supported");
348  return false;
349  }
350  if (commandId == CMD_POSITIONCONVERSION) {
351  // add converted Position to response
352  outputStorage.writeUnsignedByte(1 + 1 + (int)tmpResult.size() + 1); // length
353  outputStorage.writeUnsignedByte(commandId); // command id
354  outputStorage.writeStorage(tmpResult); // position dependant part
355  outputStorage.writeUnsignedByte(destPosType); // destination type
356  } else {
357  outputStorage.writeStorage(tmpResult); // position dependant part
358  }
359  return true;
360 }
361 
362 /****************************************************************************/
363 
364 bool
366  tcpip::Storage& outputStorage, int commandId) {
367  Position pos1;
368  Position pos2;
369  std::pair<const MSLane*, SUMOReal> roadPos1;
370  std::pair<const MSLane*, SUMOReal> roadPos2;
371 
372  // read position 1
373  int posType = inputStorage.readUnsignedByte();
374  switch (posType) {
375  case POSITION_ROADMAP:
376  try {
377  std::string roadID = inputStorage.readString();
378  roadPos1.second = inputStorage.readDouble();
379  roadPos1.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second);
380  pos1 = roadPos1.first->getShape().positionAtLengthPosition(roadPos1.second);
381  } catch (TraCIException& e) {
382  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
383  return false;
384  }
385  break;
386  case POSITION_2D:
387  case POSITION_3D: {
388  SUMOReal p1x = inputStorage.readDouble();
389  SUMOReal p1y = inputStorage.readDouble();
390  pos1.set(p1x, p1y);
391  }
392  if (posType == POSITION_3D) {
393  inputStorage.readDouble(); // z value is ignored
394  }
395  roadPos1 = convertCartesianToRoadMap(pos1);
396  break;
397  default:
398  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
399  return false;
400  }
401 
402  // read position 2
403  posType = inputStorage.readUnsignedByte();
404  switch (posType) {
405  case POSITION_ROADMAP:
406  try {
407  std::string roadID = inputStorage.readString();
408  roadPos2.second = inputStorage.readDouble();
409  roadPos2.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second);
410  pos2 = roadPos2.first->getShape().positionAtLengthPosition(roadPos2.second);
411  } catch (TraCIException& e) {
412  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
413  return false;
414  }
415  break;
416  case POSITION_2D:
417  case POSITION_3D: {
418  SUMOReal p2x = inputStorage.readDouble();
419  SUMOReal p2y = inputStorage.readDouble();
420  pos2.set(p2x, p2y);
421  }
422  if (posType == POSITION_3D) {
423  inputStorage.readDouble(); // z value is ignored
424  }
425  roadPos2 = convertCartesianToRoadMap(pos2);
426  break;
427  default:
428  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
429  return false;
430  }
431 
432  // read distance type
433  int distType = inputStorage.readUnsignedByte();
434 
435  SUMOReal distance = 0.0;
436  if (distType == REQUEST_DRIVINGDIST) {
437  // compute driving distance
438  std::vector<const MSEdge*> edges;
440 
441  if ((roadPos1.first == roadPos2.first)
442  && (roadPos1.second <= roadPos2.second)) {
443  distance = roadPos2.second - roadPos1.second;
444  } else {
445  router.compute(&roadPos1.first->getEdge(), &roadPos2.first->getEdge(), NULL,
447  MSRoute route("", edges, false, RGBColor::DEFAULT_COLOR, std::vector<SUMOVehicleParameter::Stop>());
448  distance = route.getDistanceBetween(roadPos1.second, roadPos2.second,
449  &roadPos1.first->getEdge(), &roadPos2.first->getEdge());
450  }
451  } else {
452  // compute air distance (default)
453  // correct the distance type in case it was not valid
454  distType = REQUEST_AIRDIST;
455  distance = pos1.distanceTo(pos2);
456  }
457  // write response command
458  if (commandId == CMD_DISTANCEREQUEST) {
459  outputStorage.writeUnsignedByte(1 + 1 + 1 + 8); // length
460  outputStorage.writeUnsignedByte(commandId);
461  outputStorage.writeUnsignedByte(distType);
462  } else {
463  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
464  }
465  outputStorage.writeDouble(distance);
466  return true;
467 }
468 
469 #endif
470 
471 /****************************************************************************/