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-sim.org/
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 // method definitions
54 // ===========================================================================
55 bool
57  tcpip::Storage& outputStorage) {
58  // variable & id
59  int variable = inputStorage.readUnsignedByte();
60  std::string id = inputStorage.readString();
61  // check variable
62  if (variable != VAR_TIME_STEP
63  && variable != VAR_LOADED_VEHICLES_NUMBER && variable != VAR_LOADED_VEHICLES_IDS
64  && variable != VAR_DEPARTED_VEHICLES_NUMBER && variable != VAR_DEPARTED_VEHICLES_IDS
67  && variable != VAR_ARRIVED_VEHICLES_NUMBER && variable != VAR_ARRIVED_VEHICLES_IDS
68  && variable != VAR_DELTA_T && variable != VAR_NET_BOUNDING_BOX
69  && variable != VAR_MIN_EXPECTED_VEHICLES
70  && variable != POSITION_CONVERSION && variable != DISTANCE_REQUEST
71  && variable != VAR_BUS_STOP_WAITING
76  ) {
77  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Get Simulation Variable: unsupported variable specified", outputStorage);
78  }
79  // begin response building
80  tcpip::Storage tempMsg;
81  // response-code, variableID, objectID
83  tempMsg.writeUnsignedByte(variable);
84  tempMsg.writeString(id);
85  // process request
86  switch (variable) {
87  case VAR_TIME_STEP:
89  tempMsg.writeInt(MSNet::getInstance()->getCurrentTimeStep());
90  break;
93  break;
95  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
97  tempMsg.writeStringList(ids);
98  }
99  break;
102  break;
105  break;
108  break;
111  break;
114  break;
117  break;
120  break;
123  break;
126  break;
129  break;
132  break;
135  break;
138  break;
141  break;
144  break;
147  break;
148  case VAR_DELTA_T:
150  tempMsg.writeInt(DELTA_T);
151  break;
152  case VAR_NET_BOUNDING_BOX: {
155  tempMsg.writeDouble(b.xmin());
156  tempMsg.writeDouble(b.ymin());
157  tempMsg.writeDouble(b.xmax());
158  tempMsg.writeDouble(b.ymax());
159  break;
160  }
161  break;
164  tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount());
165  break;
166  case POSITION_CONVERSION:
167  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
168  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a compound object.", outputStorage);
169  }
170  if (inputStorage.readInt() != 2) {
171  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Position conversion requires a source position and a position type as parameter.", outputStorage);
172  }
173  if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
174  return false;
175  }
176  break;
177  case DISTANCE_REQUEST:
178  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
179  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires a compound object.", outputStorage);
180  }
181  if (inputStorage.readInt() != 3) {
182  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage);
183  }
184  if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
185  return false;
186  }
187  break;
188  case VAR_BUS_STOP_WAITING: {
189  std::string id;
190  if (!server.readTypeCheckingString(inputStorage, id)) {
191  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Retrieval of persons at busstop requires a string.", outputStorage);
192  }
194  if (s == 0) {
195  return server.writeErrorStatusCmd(CMD_GET_SIM_VARIABLE, "Unknown bus stop '" + id + "'.", outputStorage);
196  }
198  tempMsg.writeInt(s->getPersonNumber());
199  break;
200  }
201  default:
202  break;
203  }
204  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, "", outputStorage);
205  server.writeResponseWithLength(outputStorage, tempMsg);
206  return true;
207 }
208 
209 
210 bool
212  tcpip::Storage& outputStorage) {
213  std::string warning = ""; // additional description for response
214  // variable
215  int variable = inputStorage.readUnsignedByte();
216  if (variable != CMD_CLEAR_PENDING_VEHICLES) {
217  return server.writeErrorStatusCmd(CMD_SET_SIM_VARIABLE, "Set Simulation Variable: unsupported variable specified", outputStorage);
218  }
219  // id
220  std::string id = inputStorage.readString();
221  // process
222  switch (variable) {
224  //clear any pending vehicle insertions
225  std::string route;
226  if (!server.readTypeCheckingString(inputStorage, route)) {
227  return server.writeErrorStatusCmd(CMD_SET_SIM_VARIABLE, "A string is needed for clearing pending vehicles.", outputStorage);
228  }
230  }
231  break;
232  default:
233  break;
234  }
235  server.writeStatusCmd(CMD_SET_SIM_VARIABLE, RTYPE_OK, warning, outputStorage);
236  return true;
237 }
238 
239 
240 void
242  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(state)->second;
243  outputStorage.writeUnsignedByte(TYPE_INTEGER);
244  outputStorage.writeInt((int) ids.size());
245 }
246 
247 
248 void
250  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(state)->second;
251  outputStorage.writeUnsignedByte(TYPE_STRINGLIST);
252  outputStorage.writeStringList(ids);
253 }
254 
255 
256 std::pair<MSLane*, SUMOReal>
258  std::pair<MSLane*, SUMOReal> result;
259  std::vector<std::string> allEdgeIds;
261 
262  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
263  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
264  const std::vector<MSLane*>& allLanes = MSEdge::dictionary((*itId))->getLanes();
265  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
266  const SUMOReal newDistance = (*itLane)->getShape().distance(pos);
267  if (newDistance < minDistance) {
268  minDistance = newDistance;
269  result.first = (*itLane);
270  }
271  }
272  }
273  // @todo this may be a place where 3D is required but 2D is delivered
274  result.second = result.first->getShape().nearest_offset_to_point2D(pos, false);
275  return result;
276 }
277 
278 
279 const MSLane*
280 TraCIServerAPI_Simulation::getLaneChecking(std::string roadID, int laneIndex, SUMOReal pos) {
281  const MSEdge* edge = MSEdge::dictionary(roadID);
282  if (edge == 0) {
283  throw TraCIException("Unknown edge " + roadID);
284  }
285  if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
286  throw TraCIException("Invalid lane index for " + roadID);
287  }
288  const MSLane* lane = edge->getLanes()[laneIndex];
289  if (pos < 0 || pos > lane->getLength()) {
290  throw TraCIException("Position on lane invalid");
291  }
292  return lane;
293 }
294 
295 
296 bool
298  tcpip::Storage& outputStorage, int commandId) {
299  std::pair<MSLane*, SUMOReal> roadPos;
300  Position cartesianPos;
301  Position geoPos;
302  SUMOReal z = 0;
303 
304  // actual position type that will be converted
305  int srcPosType = inputStorage.readUnsignedByte();
306 
307  switch (srcPosType) {
308  case POSITION_2D:
309  case POSITION_3D:
310  case POSITION_LON_LAT:
311  case POSITION_LON_LAT_ALT: {
312  SUMOReal x = inputStorage.readDouble();
313  SUMOReal y = inputStorage.readDouble();
314  if (srcPosType != POSITION_2D && srcPosType != POSITION_LON_LAT) {
315  z = inputStorage.readDouble();
316  }
317  geoPos.set(x, y);
318  cartesianPos.set(x, y);
319  if (srcPosType == POSITION_LON_LAT || srcPosType == POSITION_LON_LAT_ALT) {
321  } else {
323  }
324  }
325  break;
326  case POSITION_ROADMAP: {
327  std::string roadID = inputStorage.readString();
328  SUMOReal pos = inputStorage.readDouble();
329  int laneIdx = inputStorage.readUnsignedByte();
330  try {
331  cartesianPos = geoPos = getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtOffset(pos);
333  } catch (TraCIException& e) {
334  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
335  return false;
336  }
337  }
338  break;
339  default:
340  server.writeStatusCmd(commandId, RTYPE_ERR, "Source position type not supported");
341  return false;
342  }
343 
344  int destPosType = 0;
345  if (!server.readTypeCheckingUnsignedByte(inputStorage, destPosType)) {
346  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type must be of type ubyte.");
347  return false;
348  }
349 
350  switch (destPosType) {
351  case POSITION_ROADMAP: {
352  // convert road map to 3D position
353  roadPos = convertCartesianToRoadMap(cartesianPos);
354  // write result that is added to response msg
355  outputStorage.writeUnsignedByte(POSITION_ROADMAP);
356  outputStorage.writeString(roadPos.first->getEdge().getID());
357  outputStorage.writeDouble(roadPos.second);
358  const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes();
359  outputStorage.writeUnsignedByte((int)distance(lanes.begin(), find(lanes.begin(), lanes.end(), roadPos.first)));
360  }
361  break;
362  case POSITION_2D:
363  case POSITION_3D:
364  case POSITION_LON_LAT:
366  outputStorage.writeUnsignedByte(destPosType);
367  if (destPosType == POSITION_LON_LAT || destPosType == POSITION_LON_LAT_ALT) {
368  outputStorage.writeDouble(geoPos.x());
369  outputStorage.writeDouble(geoPos.y());
370  } else {
371  outputStorage.writeDouble(cartesianPos.x());
372  outputStorage.writeDouble(cartesianPos.y());
373  }
374  if (destPosType != POSITION_2D && destPosType != POSITION_LON_LAT) {
375  outputStorage.writeDouble(z);
376  }
377  break;
378  default:
379  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type not supported");
380  return false;
381  }
382  return true;
383 }
384 
385 /****************************************************************************/
386 
387 bool
389  tcpip::Storage& outputStorage, int commandId) {
390  Position pos1;
391  Position pos2;
392  std::pair<const MSLane*, SUMOReal> roadPos1;
393  std::pair<const MSLane*, SUMOReal> roadPos2;
394 
395  // read position 1
396  int posType = inputStorage.readUnsignedByte();
397  switch (posType) {
398  case POSITION_ROADMAP:
399  try {
400  std::string roadID = inputStorage.readString();
401  roadPos1.second = inputStorage.readDouble();
402  roadPos1.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second);
403  pos1 = roadPos1.first->getShape().positionAtOffset(roadPos1.second);
404  } catch (TraCIException& e) {
405  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
406  return false;
407  }
408  break;
409  case POSITION_2D:
410  case POSITION_3D: {
411  SUMOReal p1x = inputStorage.readDouble();
412  SUMOReal p1y = inputStorage.readDouble();
413  pos1.set(p1x, p1y);
414  }
415  if (posType == POSITION_3D) {
416  inputStorage.readDouble(); // z value is ignored
417  }
418  roadPos1 = convertCartesianToRoadMap(pos1);
419  break;
420  default:
421  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
422  return false;
423  }
424 
425  // read position 2
426  posType = inputStorage.readUnsignedByte();
427  switch (posType) {
428  case POSITION_ROADMAP:
429  try {
430  std::string roadID = inputStorage.readString();
431  roadPos2.second = inputStorage.readDouble();
432  roadPos2.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second);
433  pos2 = roadPos2.first->getShape().positionAtOffset(roadPos2.second);
434  } catch (TraCIException& e) {
435  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
436  return false;
437  }
438  break;
439  case POSITION_2D:
440  case POSITION_3D: {
441  SUMOReal p2x = inputStorage.readDouble();
442  SUMOReal p2y = inputStorage.readDouble();
443  pos2.set(p2x, p2y);
444  }
445  if (posType == POSITION_3D) {
446  inputStorage.readDouble(); // z value is ignored
447  }
448  roadPos2 = convertCartesianToRoadMap(pos2);
449  break;
450  default:
451  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
452  return false;
453  }
454 
455  // read distance type
456  int distType = inputStorage.readUnsignedByte();
457 
458  SUMOReal distance = 0.0;
459  if (distType == REQUEST_DRIVINGDIST) {
460  // compute driving distance
461  if ((roadPos1.first == roadPos2.first) && (roadPos1.second <= roadPos2.second)) {
462  // same edge
463  distance = roadPos2.second - roadPos1.second;
464  } else {
465  MSEdgeVector newRoute;
467  &roadPos1.first->getEdge(), &roadPos2.first->getEdge(), 0, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
468  MSRoute route("", newRoute, false, 0, std::vector<SUMOVehicleParameter::Stop>());
469  distance = route.getDistanceBetween(roadPos1.second, roadPos2.second, &roadPos1.first->getEdge(), &roadPos2.first->getEdge());
470  }
471  } else {
472  // compute air distance (default)
473  distance = pos1.distanceTo(pos2);
474  }
475  // write response command
476  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
477  outputStorage.writeDouble(distance);
478  return true;
479 }
480 
481 
482 #endif
483 
484 /****************************************************************************/