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-2013 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"
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 
52 // ===========================================================================
53 // used namespaces
54 // ===========================================================================
55 using namespace traci;
56 
57 
58 // ===========================================================================
59 // method definitions
60 // ===========================================================================
61 bool
63  tcpip::Storage& outputStorage) {
64  // variable & id
65  int variable = inputStorage.readUnsignedByte();
66  std::string id = inputStorage.readString();
67  // check variable
68  if (variable != VAR_TIME_STEP
69  && variable != VAR_LOADED_VEHICLES_NUMBER && variable != VAR_LOADED_VEHICLES_IDS
70  && variable != VAR_DEPARTED_VEHICLES_NUMBER && variable != VAR_DEPARTED_VEHICLES_IDS
73  && variable != VAR_ARRIVED_VEHICLES_NUMBER && variable != VAR_ARRIVED_VEHICLES_IDS
74  && variable != VAR_DELTA_T && variable != VAR_NET_BOUNDING_BOX
75  && variable != VAR_MIN_EXPECTED_VEHICLES
76  && variable != POSITION_CONVERSION && variable != DISTANCE_REQUEST
77  && variable != VAR_BUS_STOP_WAITING
78  ) {
79  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Get Simulation Variable: unsupported variable specified", outputStorage);
80  }
81  // begin response building
82  tcpip::Storage tempMsg;
83  // response-code, variableID, objectID
85  tempMsg.writeUnsignedByte(variable);
86  tempMsg.writeString(id);
87  // process request
88  switch (variable) {
89  case VAR_TIME_STEP:
91  tempMsg.writeInt(MSNet::getInstance()->getCurrentTimeStep());
92  break;
94  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
96  tempMsg.writeInt((int) ids.size());
97  }
98  break;
100  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
102  tempMsg.writeStringList(ids);
103  }
104  break;
106  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
108  tempMsg.writeInt((int) ids.size());
109  }
110  break;
112  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
114  tempMsg.writeStringList(ids);
115  }
116  break;
118  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
120  tempMsg.writeInt((int) ids.size());
121  }
122  break;
124  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
126  tempMsg.writeStringList(ids);
127  }
128  break;
130  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
132  tempMsg.writeInt((int) ids.size());
133  }
134  break;
136  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
138  tempMsg.writeStringList(ids);
139  }
140  break;
142  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
144  tempMsg.writeInt((int) ids.size());
145  }
146  break;
148  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
150  tempMsg.writeStringList(ids);
151  }
152  break;
153  case VAR_DELTA_T:
155  tempMsg.writeInt(DELTA_T);
156  break;
157  case VAR_NET_BOUNDING_BOX: {
160  tempMsg.writeDouble(b.xmin());
161  tempMsg.writeDouble(b.ymin());
162  tempMsg.writeDouble(b.xmax());
163  tempMsg.writeDouble(b.ymax());
164  break;
165  }
166  break;
169  tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount());
170  break;
171  case POSITION_CONVERSION:
172  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
173  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a compound object.", outputStorage);
174  }
175  if (inputStorage.readInt() != 2) {
176  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a source position and a position type as parameter.", outputStorage);
177  }
178  if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
179  return false;
180  }
181  break;
182  case DISTANCE_REQUEST:
183  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
184  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires a compound object.", outputStorage);
185  }
186  if (inputStorage.readInt() != 3) {
187  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage);
188  }
189  if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
190  return false;
191  }
192  break;
193  case VAR_BUS_STOP_WAITING: {
194  std::string id;
195  if (!server.readTypeCheckingString(inputStorage, id)) {
196  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of persons at busstop requires a string.", outputStorage);
197  }
199  if (s == 0) {
200  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Unknown bus stop '" + id + "'.", outputStorage);
201  }
203  tempMsg.writeInt(s->getPersonNumber());
204  break;
205  }
206  default:
207  break;
208  }
209  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, "", outputStorage);
210  server.writeResponseWithLength(outputStorage, tempMsg);
211  return true;
212 }
213 
214 
215 std::pair<MSLane*, SUMOReal>
217  std::pair<MSLane*, SUMOReal> result;
218  std::vector<std::string> allEdgeIds;
220 
221  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
222  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
223  const std::vector<MSLane*>& allLanes = MSEdge::dictionary((*itId))->getLanes();
224  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
225  const SUMOReal newDistance = (*itLane)->getShape().distance(pos);
226  if (newDistance < minDistance) {
227  minDistance = newDistance;
228  result.first = (*itLane);
229  }
230  }
231  }
232  // @todo this may be a place where 3D is required but 2D is delivered
233  result.second = result.first->getShape().nearest_offset_to_point2D(pos, false);
234  return result;
235 }
236 
237 
238 const MSLane*
239 TraCIServerAPI_Simulation::getLaneChecking(std::string roadID, int laneIndex, SUMOReal pos) {
240  const MSEdge* edge = MSEdge::dictionary(roadID);
241  if (edge == 0) {
242  throw TraCIException("Unknown edge " + roadID);
243  }
244  if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
245  throw TraCIException("Invalid lane index for " + roadID);
246  }
247  const MSLane* lane = edge->getLanes()[laneIndex];
248  if (pos < 0 || pos > lane->getLength()) {
249  throw TraCIException("Position on lane invalid");
250  }
251  return lane;
252 }
253 
254 
255 bool
257  tcpip::Storage& outputStorage, int commandId) {
258  std::pair<MSLane*, SUMOReal> roadPos;
259  Position cartesianPos;
260  Position geoPos;
261  SUMOReal z = 0;
262 
263  // actual position type that will be converted
264  int srcPosType = inputStorage.readUnsignedByte();
265 
266  switch (srcPosType) {
267  case POSITION_2D:
268  case POSITION_3D:
269  case POSITION_LAT_LON:
270  case POSITION_LAT_LON_ALT: {
271  SUMOReal x = inputStorage.readDouble();
272  SUMOReal y = inputStorage.readDouble();
273  if (srcPosType != POSITION_2D && srcPosType != POSITION_LAT_LON) {
274  z = inputStorage.readDouble();
275  }
276  geoPos.set(x, y);
277  cartesianPos.set(x, y);
278  if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) {
280  } else {
282  }
283  }
284  break;
285  case POSITION_ROADMAP: {
286  std::string roadID = inputStorage.readString();
287  SUMOReal pos = inputStorage.readDouble();
288  int laneIdx = inputStorage.readUnsignedByte();
289  try {
290  cartesianPos = geoPos = getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtOffset(pos);
292  } catch (TraCIException& e) {
293  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
294  return false;
295  }
296  }
297  break;
298  default:
299  server.writeStatusCmd(commandId, RTYPE_ERR, "Source position type not supported");
300  return false;
301  }
302 
303  int destPosType = 0;
304  if (!server.readTypeCheckingUnsignedByte(inputStorage, destPosType)) {
305  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type must be of type ubyte.");
306  return false;
307  }
308 
309  switch (destPosType) {
310  case POSITION_ROADMAP: {
311  // convert road map to 3D position
312  roadPos = convertCartesianToRoadMap(cartesianPos);
313  // write result that is added to response msg
314  outputStorage.writeUnsignedByte(POSITION_ROADMAP);
315  outputStorage.writeString(roadPos.first->getEdge().getID());
316  outputStorage.writeDouble(roadPos.second);
317  const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes();
318  outputStorage.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  outputStorage.writeUnsignedByte(destPosType);
326  if (destPosType == POSITION_LAT_LON || destPosType == POSITION_LAT_LON_ALT) {
327  outputStorage.writeDouble(geoPos.x());
328  outputStorage.writeDouble(geoPos.y());
329  } else {
330  outputStorage.writeDouble(cartesianPos.x());
331  outputStorage.writeDouble(cartesianPos.y());
332  }
333  if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) {
334  outputStorage.writeDouble(z);
335  }
336  break;
337  default:
338  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type not supported");
339  return false;
340  }
341  return true;
342 }
343 
344 /****************************************************************************/
345 
346 bool
348  tcpip::Storage& outputStorage, int commandId) {
349  Position pos1;
350  Position pos2;
351  std::pair<const MSLane*, SUMOReal> roadPos1;
352  std::pair<const MSLane*, SUMOReal> roadPos2;
353 
354  // read position 1
355  int posType = inputStorage.readUnsignedByte();
356  switch (posType) {
357  case POSITION_ROADMAP:
358  try {
359  std::string roadID = inputStorage.readString();
360  roadPos1.second = inputStorage.readDouble();
361  roadPos1.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second);
362  pos1 = roadPos1.first->getShape().positionAtOffset(roadPos1.second);
363  } catch (TraCIException& e) {
364  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
365  return false;
366  }
367  break;
368  case POSITION_2D:
369  case POSITION_3D: {
370  SUMOReal p1x = inputStorage.readDouble();
371  SUMOReal p1y = inputStorage.readDouble();
372  pos1.set(p1x, p1y);
373  }
374  if (posType == POSITION_3D) {
375  inputStorage.readDouble(); // z value is ignored
376  }
377  roadPos1 = convertCartesianToRoadMap(pos1);
378  break;
379  default:
380  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
381  return false;
382  }
383 
384  // read position 2
385  posType = inputStorage.readUnsignedByte();
386  switch (posType) {
387  case POSITION_ROADMAP:
388  try {
389  std::string roadID = inputStorage.readString();
390  roadPos2.second = inputStorage.readDouble();
391  roadPos2.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second);
392  pos2 = roadPos2.first->getShape().positionAtOffset(roadPos2.second);
393  } catch (TraCIException& e) {
394  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
395  return false;
396  }
397  break;
398  case POSITION_2D:
399  case POSITION_3D: {
400  SUMOReal p2x = inputStorage.readDouble();
401  SUMOReal p2y = inputStorage.readDouble();
402  pos2.set(p2x, p2y);
403  }
404  if (posType == POSITION_3D) {
405  inputStorage.readDouble(); // z value is ignored
406  }
407  roadPos2 = convertCartesianToRoadMap(pos2);
408  break;
409  default:
410  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
411  return false;
412  }
413 
414  // read distance type
415  int distType = inputStorage.readUnsignedByte();
416 
417  SUMOReal distance = 0.0;
418  if (distType == REQUEST_DRIVINGDIST) {
419  // compute driving distance
420  if ((roadPos1.first == roadPos2.first) && (roadPos1.second <= roadPos2.second)) {
421  // same edge
422  distance = roadPos2.second - roadPos1.second;
423  } else {
424  MSEdgeVector newRoute;
426  &roadPos1.first->getEdge(), &roadPos2.first->getEdge(), 0, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
427  MSRoute route("", newRoute, false, 0, std::vector<SUMOVehicleParameter::Stop>());
428  distance = route.getDistanceBetween(roadPos1.second, roadPos2.second, &roadPos1.first->getEdge(), &roadPos2.first->getEdge());
429  }
430  } else {
431  // compute air distance (default)
432  distance = pos1.distanceTo(pos2);
433  }
434  // write response command
435  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
436  outputStorage.writeDouble(distance);
437  return true;
438 }
439 
440 #endif
441 
442 /****************************************************************************/