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"
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  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Get Simulation Variable: unsupported variable specified", outputStorage);
80  return false;
81  }
82  // begin response building
83  tcpip::Storage tempMsg;
84  // response-code, variableID, objectID
86  tempMsg.writeUnsignedByte(variable);
87  tempMsg.writeString(id);
88  // process request
89  switch (variable) {
90  case VAR_TIME_STEP:
92  tempMsg.writeInt(MSNet::getInstance()->getCurrentTimeStep());
93  break;
95  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
97  tempMsg.writeInt((int) ids.size());
98  }
99  break;
101  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second;
103  tempMsg.writeStringList(ids);
104  }
105  break;
107  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
109  tempMsg.writeInt((int) ids.size());
110  }
111  break;
113  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second;
115  tempMsg.writeStringList(ids);
116  }
117  break;
119  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
121  tempMsg.writeInt((int) ids.size());
122  }
123  break;
125  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second;
127  tempMsg.writeStringList(ids);
128  }
129  break;
131  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
133  tempMsg.writeInt((int) ids.size());
134  }
135  break;
137  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second;
139  tempMsg.writeStringList(ids);
140  }
141  break;
143  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
145  tempMsg.writeInt((int) ids.size());
146  }
147  break;
149  const std::vector<std::string>& ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second;
151  tempMsg.writeStringList(ids);
152  }
153  break;
154  case VAR_DELTA_T:
156  tempMsg.writeInt(DELTA_T);
157  break;
158  case VAR_NET_BOUNDING_BOX: {
161  tempMsg.writeDouble(b.xmin());
162  tempMsg.writeDouble(b.ymin());
163  tempMsg.writeDouble(b.xmax());
164  tempMsg.writeDouble(b.ymax());
165  break;
166  }
167  break;
170  tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount());
171  break;
172  case POSITION_CONVERSION:
173  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
174  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a compound object.", outputStorage);
175  return false;
176  }
177  if (inputStorage.readInt() != 2) {
178  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a source position and a position type as parameter.", outputStorage);
179  return false;
180  }
181  if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
182  return false;
183  }
184  break;
185  case DISTANCE_REQUEST:
186  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
187  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires a compound object.", outputStorage);
188  return false;
189  }
190  if (inputStorage.readInt() != 3) {
191  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage);
192  return false;
193  }
194  if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) {
195  return false;
196  }
197  break;
198  case VAR_BUS_STOP_WAITING: {
199  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
200  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of persons at busstop requires a string.", outputStorage);
201  return false;
202  }
203  std::string id = inputStorage.readString();
205  if (s == 0) {
206  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Unknown bus stop '" + id + "'.", outputStorage);
207  return false;
208  }
210  tempMsg.writeInt(s->getPersonNumber());
211  break;
212  }
213  default:
214  break;
215  }
216  server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, "", outputStorage);
217  server.writeResponseWithLength(outputStorage, tempMsg);
218  return true;
219 }
220 
221 
222 std::pair<MSLane*, SUMOReal>
224  std::pair<MSLane*, SUMOReal> result;
225  std::vector<std::string> allEdgeIds;
227 
228  allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames();
229  for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) {
230  const std::vector<MSLane*>& allLanes = MSEdge::dictionary((*itId))->getLanes();
231  for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) {
232  const SUMOReal newDistance = (*itLane)->getShape().distance(pos);
233  if (newDistance < minDistance) {
234  minDistance = newDistance;
235  result.first = (*itLane);
236  }
237  }
238  }
239  // @todo this may be a place where 3D is required but 2D is delivered
240  result.second = result.first->getShape().nearest_position_on_line_to_point2D(pos, false);
241  return result;
242 }
243 
244 
245 const MSLane*
246 TraCIServerAPI_Simulation::getLaneChecking(std::string roadID, int laneIndex, SUMOReal pos) {
247  const MSEdge* edge = MSEdge::dictionary(roadID);
248  if (edge == 0) {
249  throw TraCIException("Unknown edge " + roadID);
250  }
251  if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) {
252  throw TraCIException("Invalid lane index for " + roadID);
253  }
254  const MSLane* lane = edge->getLanes()[laneIndex];
255  if (pos < 0 || pos > lane->getLength()) {
256  throw TraCIException("Position on lane invalid");
257  }
258  return lane;
259 }
260 
261 
262 bool
264  tcpip::Storage& outputStorage, int commandId) {
265  std::pair<MSLane*, SUMOReal> roadPos;
266  Position cartesianPos;
267  Position geoPos;
268  SUMOReal z = 0;
269 
270  // actual position type that will be converted
271  int srcPosType = inputStorage.readUnsignedByte();
272 
273  switch (srcPosType) {
274  case POSITION_2D:
275  case POSITION_3D:
276  case POSITION_LAT_LON:
277  case POSITION_LAT_LON_ALT: {
278  SUMOReal x = inputStorage.readDouble();
279  SUMOReal y = inputStorage.readDouble();
280  if (srcPosType != POSITION_2D && srcPosType != POSITION_LAT_LON) {
281  z = inputStorage.readDouble();
282  }
283  geoPos.set(x, y);
284  cartesianPos.set(x, y);
285  if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) {
287  } else {
289  }
290  }
291  break;
292  case POSITION_ROADMAP: {
293  std::string roadID = inputStorage.readString();
294  SUMOReal pos = inputStorage.readDouble();
295  int laneIdx = inputStorage.readUnsignedByte();
296  try {
297  cartesianPos = geoPos = getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtLengthPosition(pos);
299  } catch (TraCIException& e) {
300  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
301  return false;
302  }
303  }
304  break;
305  default:
306  server.writeStatusCmd(commandId, RTYPE_ERR, "Source position type not supported");
307  return false;
308  }
309 
310  int type = inputStorage.readUnsignedByte();
311  if (type != TYPE_UBYTE) {
312  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type must be of type ubyte.");
313  return false;
314  }
315  int destPosType = inputStorage.readUnsignedByte();
316 
317  switch (destPosType) {
318  case POSITION_ROADMAP: {
319  // convert road map to 3D position
320  roadPos = convertCartesianToRoadMap(cartesianPos);
321  // write result that is added to response msg
322  outputStorage.writeUnsignedByte(POSITION_ROADMAP);
323  outputStorage.writeString(roadPos.first->getEdge().getID());
324  outputStorage.writeDouble(roadPos.second);
325  const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes();
326  outputStorage.writeUnsignedByte((int)distance(lanes.begin(), find(lanes.begin(), lanes.end(), roadPos.first)));
327  }
328  break;
329  case POSITION_2D:
330  case POSITION_3D:
331  case POSITION_LAT_LON:
333  outputStorage.writeUnsignedByte(destPosType);
334  if (destPosType == POSITION_LAT_LON || destPosType == POSITION_LAT_LON_ALT) {
335  outputStorage.writeDouble(geoPos.x());
336  outputStorage.writeDouble(geoPos.y());
337  } else {
338  outputStorage.writeDouble(cartesianPos.x());
339  outputStorage.writeDouble(cartesianPos.y());
340  }
341  if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) {
342  outputStorage.writeDouble(z);
343  }
344  break;
345  default:
346  server.writeStatusCmd(commandId, RTYPE_ERR, "Destination position type not supported");
347  return false;
348  }
349  return true;
350 }
351 
352 /****************************************************************************/
353 
354 bool
356  tcpip::Storage& outputStorage, int commandId) {
357  Position pos1;
358  Position pos2;
359  std::pair<const MSLane*, SUMOReal> roadPos1;
360  std::pair<const MSLane*, SUMOReal> roadPos2;
361 
362  // read position 1
363  int posType = inputStorage.readUnsignedByte();
364  switch (posType) {
365  case POSITION_ROADMAP:
366  try {
367  std::string roadID = inputStorage.readString();
368  roadPos1.second = inputStorage.readDouble();
369  roadPos1.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second);
370  pos1 = roadPos1.first->getShape().positionAtLengthPosition(roadPos1.second);
371  } catch (TraCIException& e) {
372  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
373  return false;
374  }
375  break;
376  case POSITION_2D:
377  case POSITION_3D: {
378  SUMOReal p1x = inputStorage.readDouble();
379  SUMOReal p1y = inputStorage.readDouble();
380  pos1.set(p1x, p1y);
381  }
382  if (posType == POSITION_3D) {
383  inputStorage.readDouble(); // z value is ignored
384  }
385  roadPos1 = convertCartesianToRoadMap(pos1);
386  break;
387  default:
388  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
389  return false;
390  }
391 
392  // read position 2
393  posType = inputStorage.readUnsignedByte();
394  switch (posType) {
395  case POSITION_ROADMAP:
396  try {
397  std::string roadID = inputStorage.readString();
398  roadPos2.second = inputStorage.readDouble();
399  roadPos2.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second);
400  pos2 = roadPos2.first->getShape().positionAtLengthPosition(roadPos2.second);
401  } catch (TraCIException& e) {
402  server.writeStatusCmd(commandId, RTYPE_ERR, e.what());
403  return false;
404  }
405  break;
406  case POSITION_2D:
407  case POSITION_3D: {
408  SUMOReal p2x = inputStorage.readDouble();
409  SUMOReal p2y = inputStorage.readDouble();
410  pos2.set(p2x, p2y);
411  }
412  if (posType == POSITION_3D) {
413  inputStorage.readDouble(); // z value is ignored
414  }
415  roadPos2 = convertCartesianToRoadMap(pos2);
416  break;
417  default:
418  server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request");
419  return false;
420  }
421 
422  // read distance type
423  int distType = inputStorage.readUnsignedByte();
424 
425  SUMOReal distance = 0.0;
426  if (distType == REQUEST_DRIVINGDIST) {
427  // compute driving distance
428  if ((roadPos1.first == roadPos2.first) && (roadPos1.second <= roadPos2.second)) {
429  // same edge
430  distance = roadPos2.second - roadPos1.second;
431  } else {
432  MSEdgeVector newRoute;
434  &roadPos1.first->getEdge(), &roadPos2.first->getEdge(), 0, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
435  MSRoute route("", newRoute, false, 0, std::vector<SUMOVehicleParameter::Stop>());
436  distance = route.getDistanceBetween(roadPos1.second, roadPos2.second, &roadPos1.first->getEdge(), &roadPos2.first->getEdge());
437  }
438  } else {
439  // compute air distance (default)
440  distance = pos1.distanceTo(pos2);
441  }
442  // write response command
443  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
444  outputStorage.writeDouble(distance);
445  return true;
446 }
447 
448 #endif
449 
450 /****************************************************************************/