SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TraCIServerAPI_Vehicle.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // APIs for getting/setting vehicle values via TraCI
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
14 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #ifndef NO_TRACI
36 
37 #include <microsim/MSNet.h>
39 #include <microsim/MSVehicle.h>
40 #include <microsim/MSLane.h>
41 #include <microsim/MSEdge.h>
50 #include "TraCIConstants.h"
52 #include "TraCIServerAPI_Vehicle.h"
54 
55 #ifdef CHECK_MEMORY_LEAKS
56 #include <foreign/nvwa/debug_new.h>
57 #endif // CHECK_MEMORY_LEAKS
58 
59 
60 // ===========================================================================
61 // used namespaces
62 // ===========================================================================
63 using namespace traci;
64 
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
69 bool
71  tcpip::Storage& outputStorage) {
72  // variable & id
73  int variable = inputStorage.readUnsignedByte();
74  std::string id = inputStorage.readString();
75  // check variable
76  if (variable != ID_LIST && variable != VAR_SPEED && variable != VAR_SPEED_WITHOUT_TRACI && variable != VAR_POSITION && variable != VAR_ANGLE
77  && variable != VAR_ROAD_ID && variable != VAR_LANE_ID && variable != VAR_LANE_INDEX
78  && variable != VAR_TYPE && variable != VAR_ROUTE_ID && variable != VAR_COLOR
79  && variable != VAR_LANEPOSITION
80  && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION
81  && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION
82  && variable != VAR_PERSON_NUMBER
83  && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT
84  && variable != VAR_ROUTE_VALID && variable != VAR_EDGES
85  && variable != VAR_SIGNALS
86  && variable != VAR_LENGTH && variable != VAR_MAXSPEED && variable != VAR_VEHICLECLASS
87  && variable != VAR_SPEED_FACTOR && variable != VAR_SPEED_DEVIATION && variable != VAR_EMISSIONCLASS
88  && variable != VAR_WIDTH && variable != VAR_MINGAP && variable != VAR_SHAPECLASS
89  && variable != VAR_ACCEL && variable != VAR_DECEL && variable != VAR_IMPERFECTION
90  && variable != VAR_TAU && variable != VAR_BEST_LANES && variable != DISTANCE_REQUEST
91  && variable != ID_COUNT
92  ) {
93  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Get Vehicle Variable: unsupported variable specified", outputStorage);
94  return false;
95  }
96  // begin response building
97  tcpip::Storage tempMsg;
98  // response-code, variableID, objectID
100  tempMsg.writeUnsignedByte(variable);
101  tempMsg.writeString(id);
102  // process request
103  if (variable == ID_LIST || variable == ID_COUNT) {
104  std::vector<std::string> ids;
106  for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
107  if ((*i).second->isOnRoad()) {
108  ids.push_back((*i).first);
109  }
110  }
111  if (variable == ID_LIST) {
113  tempMsg.writeStringList(ids);
114  } else {
116  tempMsg.writeInt((int) ids.size());
117  }
118  } else {
120  if (sumoVehicle == 0) {
121  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Vehicle '" + id + "' is not known", outputStorage);
122  return false;
123  }
124  MSVehicle* v = dynamic_cast<MSVehicle*>(sumoVehicle);
125  if (v == 0) {
127  RTYPE_ERR, "Vehicle '" + id + "' is not a micro-simulation vehicle", outputStorage);
128  return false;
129  }
130  const bool onRoad = v->isOnRoad();
131  switch (variable) {
132  case VAR_SPEED:
134  tempMsg.writeDouble(onRoad ? v->getSpeed() : INVALID_DOUBLE_VALUE);
135  break;
139  break;
140  case VAR_POSITION:
142  tempMsg.writeDouble(onRoad ? v->getPosition().x() : INVALID_DOUBLE_VALUE);
143  tempMsg.writeDouble(onRoad ? v->getPosition().y() : INVALID_DOUBLE_VALUE);
144  break;
145  case VAR_ANGLE:
147  tempMsg.writeDouble(onRoad ? v->getAngle() : INVALID_DOUBLE_VALUE);
148  break;
149  case VAR_ROAD_ID:
151  tempMsg.writeString(onRoad ? v->getLane()->getEdge().getID() : "");
152  break;
153  case VAR_LANE_ID:
155  tempMsg.writeString(onRoad ? v->getLane()->getID() : "");
156  break;
157  case VAR_LANE_INDEX:
159  if (onRoad) {
160  const std::vector<MSLane*>& lanes = v->getLane()->getEdge().getLanes();
161  tempMsg.writeInt((int)std::distance(lanes.begin(), std::find(lanes.begin(), lanes.end(), v->getLane())));
162  } else {
163  tempMsg.writeInt(INVALID_INT_VALUE);
164  }
165  break;
166  case VAR_TYPE:
168  tempMsg.writeString(v->getVehicleType().getID());
169  break;
170  case VAR_ROUTE_ID:
172  tempMsg.writeString(v->getRoute().getID());
173  break;
174  case VAR_COLOR:
175  tempMsg.writeUnsignedByte(TYPE_COLOR);
176  tempMsg.writeUnsignedByte(static_cast<int>(v->getParameter().color.red() * 255. + 0.5));
177  tempMsg.writeUnsignedByte(static_cast<int>(v->getParameter().color.green() * 255. + 0.5));
178  tempMsg.writeUnsignedByte(static_cast<int>(v->getParameter().color.blue() * 255. + 0.5));
179  tempMsg.writeUnsignedByte(255);
180  break;
181  case VAR_LANEPOSITION:
183  tempMsg.writeDouble(onRoad ? v->getPositionOnLane() : INVALID_DOUBLE_VALUE);
184  break;
185  case VAR_CO2EMISSION:
188  break;
189  case VAR_COEMISSION:
192  break;
193  case VAR_HCEMISSION:
196  break;
197  case VAR_PMXEMISSION:
200  break;
201  case VAR_NOXEMISSION:
204  break;
205  case VAR_FUELCONSUMPTION:
208  break;
209  case VAR_NOISEEMISSION:
212  break;
213  case VAR_PERSON_NUMBER:
215  tempMsg.writeInt(v->getPersonNumber());
216  break;
217  case VAR_EDGE_TRAVELTIME: {
218  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
219  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires a compound object.", outputStorage);
220  return false;
221  }
222  if (inputStorage.readInt() != 2) {
223  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires time, and edge as parameter.", outputStorage);
224  return false;
225  }
226  // time
227  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
228  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires the referenced time as first parameter.", outputStorage);
229  return false;
230  }
231  SUMOTime time = inputStorage.readInt();
232  // edge
233  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
234  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires the referenced edge as second parameter.", outputStorage);
235  return false;
236  }
237  std::string edgeID = inputStorage.readString();
238  MSEdge* edge = MSEdge::dictionary(edgeID);
239  if (edge == 0) {
240  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
241  return false;
242  }
243  // retrieve
245  SUMOReal value;
246  if (!v->getWeightsStorage().retrieveExistingTravelTime(edge, 0, time, value)) {
248  } else {
249  tempMsg.writeDouble(value);
250  }
251 
252  }
253  break;
254  case VAR_EDGE_EFFORT: {
255  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
256  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires a compound object.", outputStorage);
257  return false;
258  }
259  if (inputStorage.readInt() != 2) {
260  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of travel time requires time, and edge as parameter.", outputStorage);
261  return false;
262  }
263  // time
264  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
265  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of effort requires the referenced time as first parameter.", outputStorage);
266  return false;
267  }
268  SUMOTime time = inputStorage.readInt();
269  // edge
270  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
271  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of effort requires the referenced edge as second parameter.", outputStorage);
272  return false;
273  }
274  std::string edgeID = inputStorage.readString();
275  MSEdge* edge = MSEdge::dictionary(edgeID);
276  if (edge == 0) {
277  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
278  return false;
279  }
280  // retrieve
282  SUMOReal value;
283  if (!v->getWeightsStorage().retrieveExistingEffort(edge, 0, time, value)) {
285  } else {
286  tempMsg.writeDouble(value);
287  }
288 
289  }
290  break;
291  case VAR_ROUTE_VALID: {
292  std::string msg;
293  tempMsg.writeUnsignedByte(TYPE_UBYTE);
294  tempMsg.writeUnsignedByte(v->hasValidRoute(msg));
295  }
296  break;
297  case VAR_EDGES: {
298  const MSRoute& r = v->getRoute();
300  tempMsg.writeInt(r.size());
301  for (MSRouteIterator i = r.begin(); i != r.end(); ++i) {
302  tempMsg.writeString((*i)->getID());
303  }
304  }
305  break;
306  case VAR_SIGNALS:
308  tempMsg.writeInt(v->getSignals());
309  break;
310  case VAR_BEST_LANES: {
312  tcpip::Storage tempContent;
313  unsigned int cnt = 0;
314  tempContent.writeUnsignedByte(TYPE_INTEGER);
315  const std::vector<MSVehicle::LaneQ>& bestLanes = onRoad ? v->getBestLanes() : std::vector<MSVehicle::LaneQ>();
316  tempContent.writeInt((int) bestLanes.size());
317  ++cnt;
318  for (std::vector<MSVehicle::LaneQ>::const_iterator i = bestLanes.begin(); i != bestLanes.end(); ++i) {
319  const MSVehicle::LaneQ& lq = *i;
320  tempContent.writeUnsignedByte(TYPE_STRING);
321  tempContent.writeString(lq.lane->getID());
322  ++cnt;
323  tempContent.writeUnsignedByte(TYPE_DOUBLE);
324  tempContent.writeDouble(lq.length);
325  ++cnt;
326  tempContent.writeUnsignedByte(TYPE_DOUBLE);
327  tempContent.writeDouble(lq.nextOccupation);
328  ++cnt;
329  tempContent.writeUnsignedByte(TYPE_BYTE);
330  tempContent.writeByte(lq.bestLaneOffset);
331  ++cnt;
332  tempContent.writeUnsignedByte(TYPE_UBYTE);
333  lq.allowsContinuation ? tempContent.writeUnsignedByte(1) : tempContent.writeUnsignedByte(0);
334  ++cnt;
335  std::vector<std::string> bestContIDs;
336  for (std::vector<MSLane*>::const_iterator j = lq.bestContinuations.begin(); j != lq.bestContinuations.end(); ++j) {
337  bestContIDs.push_back((*j)->getID());
338  }
339  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
340  tempContent.writeStringList(bestContIDs);
341  ++cnt;
342  }
343  tempMsg.writeInt((int) cnt);
344  tempMsg.writeStorage(tempContent);
345  }
346  break;
347  case DISTANCE_REQUEST:
348  if (!commandDistanceRequest(server, inputStorage, tempMsg, v)) {
349  return false;
350  }
351  break;
352  default:
354  break;
355  }
356  }
357  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_OK, "", outputStorage);
358  server.writeResponseWithLength(outputStorage, tempMsg);
359  return true;
360 }
361 
362 
363 bool
365  tcpip::Storage& outputStorage) {
366  std::string warning = ""; // additional description for response
367  // variable
368  int variable = inputStorage.readUnsignedByte();
369  if (variable != CMD_STOP && variable != CMD_CHANGELANE
370  && variable != CMD_SLOWDOWN && variable != CMD_CHANGETARGET
371  && variable != VAR_ROUTE_ID && variable != VAR_ROUTE
372  && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT
373  && variable != CMD_REROUTE_TRAVELTIME && variable != CMD_REROUTE_EFFORT
374  && variable != VAR_SIGNALS && variable != VAR_MOVE_TO
375  && variable != VAR_LENGTH && variable != VAR_MAXSPEED && variable != VAR_VEHICLECLASS
376  && variable != VAR_SPEED_FACTOR && variable != VAR_SPEED_DEVIATION && variable != VAR_EMISSIONCLASS
377  && variable != VAR_WIDTH && variable != VAR_MINGAP && variable != VAR_SHAPECLASS
378  && variable != VAR_ACCEL && variable != VAR_DECEL && variable != VAR_IMPERFECTION
379  && variable != VAR_TAU
380  && variable != VAR_SPEED && variable != VAR_SPEEDSETMODE && variable != VAR_COLOR
381  && variable != ADD && variable != REMOVE
382  && variable != VAR_MOVE_TO_VTD
383  ) {
384  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Change Vehicle State: unsupported variable specified", outputStorage);
385  return false;
386  }
387  // id
388  std::string id = inputStorage.readString();
389  const bool shouldExist = variable != ADD;
391  if (sumoVehicle == 0) {
392  if (shouldExist) {
393  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Vehicle '" + id + "' is not known", outputStorage);
394  return false;
395  }
396  }
397  MSVehicle* v = dynamic_cast<MSVehicle*>(sumoVehicle);
398  if (v == 0 && shouldExist) {
400  RTYPE_ERR, "Vehicle '" + id + "' is not a micro-simulation vehicle", outputStorage);
401  return false;
402  }
403  int valueDataType = inputStorage.readUnsignedByte();
404  switch (variable) {
405  case CMD_STOP: {
406  if (valueDataType != TYPE_COMPOUND) {
407  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Stop needs a compound object description.", outputStorage);
408  return false;
409  }
410  if (inputStorage.readInt() != 4) {
411  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Stop needs a compound object description of four items.", outputStorage);
412  return false;
413  }
414  // read road map position
415  valueDataType = inputStorage.readUnsignedByte();
416  if (valueDataType != TYPE_STRING) {
417  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The first stop parameter must be the edge id given as a string.", outputStorage);
418  return false;
419  }
420  std::string roadId = inputStorage.readString();
421  valueDataType = inputStorage.readUnsignedByte();
422  if (valueDataType != TYPE_DOUBLE) {
423  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The second stop parameter must be the position along the edge given as a double.", outputStorage);
424  return false;
425  }
426  SUMOReal pos = inputStorage.readDouble();
427  valueDataType = inputStorage.readUnsignedByte();
428  if (valueDataType != TYPE_BYTE) {
429  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The third stop parameter must be the lane index given as a byte.", outputStorage);
430  return false;
431  }
432  int laneIndex = inputStorage.readByte();
433  // waitTime
434  valueDataType = inputStorage.readUnsignedByte();
435  if (valueDataType != TYPE_INTEGER) {
436  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The fourth stop parameter must be the waiting time given as an integer.", outputStorage);
437  return false;
438  }
439  SUMOTime waitTime = inputStorage.readInt();
440  // check
441  if (pos < 0) {
442  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Position on lane must not be negative", outputStorage);
443  return false;
444  }
445  // get the actual lane that is referenced by laneIndex
446  MSEdge* road = MSEdge::dictionary(roadId);
447  if (road == 0) {
448  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Unable to retrieve road with given id", outputStorage);
449  return false;
450  }
451  const std::vector<MSLane*>& allLanes = road->getLanes();
452  if ((laneIndex < 0) || laneIndex >= (int)(allLanes.size())) {
453  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "No lane existing with such id on the given road", outputStorage);
454  return false;
455  }
456  // Forward command to vehicle
457  if (!v->addTraciStop(allLanes[laneIndex], pos, 0, waitTime)) {
458  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Vehicle is too close or behind the stop on " + allLanes[laneIndex]->getID(), outputStorage);
459  return false;
460  }
461  }
462  break;
463  case CMD_CHANGELANE: {
464  if (valueDataType != TYPE_COMPOUND) {
465  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Lane change needs a compound object description.", outputStorage);
466  return false;
467  }
468  if (inputStorage.readInt() != 2) {
469  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Lane change needs a compound object description of two items.", outputStorage);
470  return false;
471  }
472  // Lane ID
473  valueDataType = inputStorage.readUnsignedByte();
474  if (valueDataType != TYPE_BYTE) {
475  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The first lane change parameter must be the lane index given as a byte.", outputStorage);
476  return false;
477  }
478  int laneIndex = inputStorage.readByte();
479  // stickyTime
480  valueDataType = inputStorage.readUnsignedByte();
481  if (valueDataType != TYPE_INTEGER) {
482  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The second lane change parameter must be the duration given as an integer.", outputStorage);
483  return false;
484  }
485  SUMOTime stickyTime = inputStorage.readInt();
486  if ((laneIndex < 0) || (laneIndex >= (int)(v->getEdge()->getLanes().size()))) {
487  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "No lane existing with given id on the current road", outputStorage);
488  return false;
489  }
490  // Forward command to vehicle
491  std::vector<std::pair<SUMOTime, unsigned int> > laneTimeLine;
492  laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), laneIndex));
493  laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + stickyTime, laneIndex));
494  v->getInfluencer().setLaneTimeLine(laneTimeLine);
496  *v->getEdge(), v->getLaneIndex());
498  }
499  break;
500  case CMD_SLOWDOWN: {
501  if (valueDataType != TYPE_COMPOUND) {
502  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Slow down needs a compound object description.", outputStorage);
503  return false;
504  }
505  if (inputStorage.readInt() != 2) {
506  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Slow down needs a compound object description of two items.", outputStorage);
507  return false;
508  }
509  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
510  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The first slow down parameter must be the speed given as a double.", outputStorage);
511  return false;
512  }
513  SUMOReal newSpeed = MAX2(inputStorage.readDouble(), 0.0);
514  if (newSpeed < 0) {
515  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Speed must not be negative", outputStorage);
516  return false;
517  }
518  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
519  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The second slow down parameter must be the duration given as an integer.", outputStorage);
520  return false;
521  }
522  SUMOTime duration = inputStorage.readInt();
523  if (duration < 0) {
524  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid time interval", outputStorage);
525  return false;
526  }
527  std::vector<std::pair<SUMOTime, SUMOReal> > speedTimeLine;
528  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), v->getSpeed()));
529  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + duration, newSpeed));
530  v->getInfluencer().setSpeedTimeLine(speedTimeLine);
531  }
532  break;
533  case CMD_CHANGETARGET: {
534  if (valueDataType != TYPE_STRING) {
535  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Change target requires a string containing the id of the new destination edge as parameter.", outputStorage);
536  return false;
537  }
538  std::string edgeID = inputStorage.readString();
539  const MSEdge* destEdge = MSEdge::dictionary(edgeID);
540  if (destEdge == 0) {
541  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Can not retrieve road with ID " + edgeID, outputStorage);
542  return false;
543  }
544  // build a new route between the vehicle's current edge and destination edge
545  MSEdgeVector newRoute;
546  const MSEdge* currentEdge = v->getEdge();
548  currentEdge, destEdge, (const MSVehicle * const) v, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
549  // replace the vehicle's route by the new one
550  if (!v->replaceRouteEdges(newRoute)) {
551  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Route replacement failed for " + v->getID(), outputStorage);
552  return false;
553  }
554  }
555  break;
556  case VAR_ROUTE_ID: {
557  if (valueDataType != TYPE_STRING) {
558  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The route id must be given as a string.", outputStorage);
559  return false;
560  }
561  std::string rid = inputStorage.readString();
562  const MSRoute* r = MSRoute::dictionary(rid);
563  if (r == 0) {
564  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The route '" + rid + "' is not known.", outputStorage);
565  return false;
566  }
567  if (!v->replaceRoute(r)) {
568  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Route replacement failed for " + v->getID(), outputStorage);
569  return false;
570  }
571  }
572  break;
573  case VAR_ROUTE: {
574  if (valueDataType != TYPE_STRINGLIST) {
575  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "A route must be defined as a list of edge ids.", outputStorage);
576  return false;
577  }
578  std::vector<std::string> edgeIDs = inputStorage.readStringList();
579  std::vector<const MSEdge*> edges;
580  MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
581  if (!v->replaceRouteEdges(edges)) {
582  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Route replacement failed for " + v->getID(), outputStorage);
583  return false;
584  }
585  }
586  break;
587  case VAR_EDGE_TRAVELTIME: {
588  if (valueDataType != TYPE_COMPOUND) {
589  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time requires a compound object.", outputStorage);
590  return false;
591  }
592  int parameterCount = inputStorage.readInt();
593  if (parameterCount == 4) {
594  // begin time
595  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
596  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 4 parameters requires the begin time as first parameter.", outputStorage);
597  return false;
598  }
599  SUMOTime begTime = inputStorage.readInt();
600  // begin time
601  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
602  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 4 parameters requires the end time as second parameter.", outputStorage);
603  return false;
604  }
605  SUMOTime endTime = inputStorage.readInt();
606  // edge
607  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
608  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 4 parameters requires the referenced edge as third parameter.", outputStorage);
609  return false;
610  }
611  std::string edgeID = inputStorage.readString();
612  MSEdge* edge = MSEdge::dictionary(edgeID);
613  if (edge == 0) {
614  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
615  return false;
616  }
617  // value
618  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
619  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 4 parameters requires the travel time as fourth parameter.", outputStorage);
620  return false;
621  }
622  SUMOReal value = inputStorage.readDouble();
623  // retrieve
624  v->getWeightsStorage().addTravelTime(edge, begTime, endTime, value);
625  } else if (parameterCount == 2) {
626  // edge
627  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
628  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 2 parameters requires the referenced edge as first parameter.", outputStorage);
629  return false;
630  }
631  std::string edgeID = inputStorage.readString();
632  MSEdge* edge = MSEdge::dictionary(edgeID);
633  if (edge == 0) {
634  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
635  return false;
636  }
637  // value
638  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
639  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 2 parameters requires the travel time as second parameter.", outputStorage);
640  return false;
641  }
642  SUMOReal value = inputStorage.readDouble();
643  // retrieve
644  while (v->getWeightsStorage().knowsTravelTime(edge)) {
646  }
647  v->getWeightsStorage().addTravelTime(edge, 0, SUMOTime_MAX, value);
648  } else if (parameterCount == 1) {
649  // edge
650  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
651  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time using 1 parameter requires the referenced edge as first parameter.", outputStorage);
652  return false;
653  }
654  std::string edgeID = inputStorage.readString();
655  MSEdge* edge = MSEdge::dictionary(edgeID);
656  if (edge == 0) {
657  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
658  return false;
659  }
660  // retrieve
661  while (v->getWeightsStorage().knowsTravelTime(edge)) {
663  }
664  } else {
665  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting travel time requires 1, 2, or 4 parameters.", outputStorage);
666  return false;
667  }
668  }
669  break;
670  case VAR_EDGE_EFFORT: {
671  if (valueDataType != TYPE_COMPOUND) {
672  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort requires a compound object.", outputStorage);
673  return false;
674  }
675  int parameterCount = inputStorage.readInt();
676  if (parameterCount == 4) {
677  // begin time
678  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
679  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 4 parameters requires the begin time as first parameter.", outputStorage);
680  return false;
681  }
682  SUMOTime begTime = inputStorage.readInt();
683  // begin time
684  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
685  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 4 parameters requires the end time as second parameter.", outputStorage);
686  return false;
687  }
688  SUMOTime endTime = inputStorage.readInt();
689  // edge
690  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
691  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 4 parameters requires the referenced edge as third parameter.", outputStorage);
692  return false;
693  }
694  std::string edgeID = inputStorage.readString();
695  MSEdge* edge = MSEdge::dictionary(edgeID);
696  if (edge == 0) {
697  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
698  return false;
699  }
700  // value
701  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
702  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 4 parameters requires the travel time as fourth parameter.", outputStorage);
703  return false;
704  }
705  SUMOReal value = inputStorage.readDouble();
706  // retrieve
707  v->getWeightsStorage().addEffort(edge, begTime, endTime, value);
708  } else if (parameterCount == 2) {
709  // edge
710  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
711  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 2 parameters requires the referenced edge as first parameter.", outputStorage);
712  return false;
713  }
714  std::string edgeID = inputStorage.readString();
715  MSEdge* edge = MSEdge::dictionary(edgeID);
716  if (edge == 0) {
717  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
718  return false;
719  }
720  // value
721  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
722  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 2 parameters requires the travel time as second parameter.", outputStorage);
723  return false;
724  }
725  SUMOReal value = inputStorage.readDouble();
726  // retrieve
727  while (v->getWeightsStorage().knowsEffort(edge)) {
728  v->getWeightsStorage().removeEffort(edge);
729  }
730  v->getWeightsStorage().addEffort(edge, 0, SUMOTime_MAX, value);
731  } else if (parameterCount == 1) {
732  // edge
733  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
734  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort using 1 parameter requires the referenced edge as first parameter.", outputStorage);
735  return false;
736  }
737  std::string edgeID = inputStorage.readString();
738  MSEdge* edge = MSEdge::dictionary(edgeID);
739  if (edge == 0) {
740  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
741  return false;
742  }
743  // retrieve
744  while (v->getWeightsStorage().knowsEffort(edge)) {
745  v->getWeightsStorage().removeEffort(edge);
746  }
747  } else {
748  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting effort requires 1, 2, or 4 parameters.", outputStorage);
749  return false;
750  }
751  }
752  break;
753  case CMD_REROUTE_TRAVELTIME: {
754  if (valueDataType != TYPE_COMPOUND) {
755  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Rerouting requires a compound object.", outputStorage);
756  return false;
757  }
758  if (inputStorage.readInt() != 0) {
759  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Rerouting should obtain an empty compound object.", outputStorage);
760  return false;
761  }
762  v->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterTT());
763  }
764  break;
765  case CMD_REROUTE_EFFORT: {
766  if (valueDataType != TYPE_COMPOUND) {
767  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Rerouting requires a compound object.", outputStorage);
768  return false;
769  }
770  if (inputStorage.readInt() != 0) {
771  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Rerouting should obtain an empty compound object.", outputStorage);
772  return false;
773  }
774  v->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterEffort());
775  }
776  break;
777  case VAR_SIGNALS:
778  if (valueDataType != TYPE_INTEGER) {
779  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting signals requires an integer.", outputStorage);
780  return false;
781  }
782  v->switchOffSignal(0x0fffffff);
783  v->switchOnSignal(inputStorage.readInt());
784  break;
785  case VAR_MOVE_TO: {
786  if (valueDataType != TYPE_COMPOUND) {
787  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting position requires a compound object.", outputStorage);
788  return false;
789  }
790  if (inputStorage.readInt() != 2) {
791  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting position should obtain the lane id and the position.", outputStorage);
792  return false;
793  }
794  // lane ID
795  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
796  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The first parameter for setting a position must be the lane ID given as a string.", outputStorage);
797  return false;
798  }
799  std::string laneID = inputStorage.readString();
800  // position on lane
801  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
802  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The second parameter for setting a position must be the position given as a double.", outputStorage);
803  return false;
804  }
805  SUMOReal position = inputStorage.readDouble();
806  // process
807  MSLane* l = MSLane::dictionary(laneID);
808  if (l == 0) {
809  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Unknown lane '" + laneID + "'.", outputStorage);
810  return false;
811  }
812  MSEdge& destinationEdge = l->getEdge();
813  if (!v->willPass(&destinationEdge)) {
814  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Vehicle '" + laneID + "' may be set onto an edge to pass only.", outputStorage);
815  return false;
816  }
818  v->getLane()->removeVehicle(v);
819  while (v->getEdge() != &destinationEdge) {
820  const MSEdge* nextEdge = v->succEdge(1);
821  // let the vehicle move to the next edge
822  if (v->enterLaneAtMove(nextEdge->getLanes()[0], true)) {
824  continue;
825  }
826  }
827  l->forceVehicleInsertion(v, position);
828  }
829  break;
830  case VAR_SPEED: {
831  if (valueDataType != TYPE_DOUBLE) {
832  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting speed requires a double.", outputStorage);
833  return false;
834  }
835  SUMOReal speed = inputStorage.readDouble();
836  std::vector<std::pair<SUMOTime, SUMOReal> > speedTimeLine;
837  if (speed >= 0) {
838  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), speed));
839  speedTimeLine.push_back(std::make_pair(SUMOTime_MAX, speed));
840  }
841  v->getInfluencer().setSpeedTimeLine(speedTimeLine);
842  }
843  break;
844  case VAR_SPEEDSETMODE: {
845  if (valueDataType != TYPE_INTEGER) {
846  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting speed requires a double.", outputStorage);
847  return false;
848  }
849  int speedMode = inputStorage.readInt();
850  v->getInfluencer().setConsiderSafeVelocity((speedMode & 1) != 0);
851  v->getInfluencer().setConsiderMaxAcceleration((speedMode & 2) != 0);
852  v->getInfluencer().setConsiderMaxDeceleration((speedMode & 4) != 0);
853  }
854  break;
855  case VAR_COLOR: {
856  if (valueDataType != TYPE_COLOR) {
857  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The color must be given using the according type.", outputStorage);
858  return false;
859  }
860  SUMOReal r = (SUMOReal) inputStorage.readUnsignedByte() / 255.;
861  SUMOReal g = (SUMOReal) inputStorage.readUnsignedByte() / 255.;
862  SUMOReal b = (SUMOReal) inputStorage.readUnsignedByte() / 255.;
863  inputStorage.readUnsignedByte(); // skip alpha level
864  v->getParameter().color.set(r, g, b);
866  }
867  break;
868  case ADD: {
869  if (v != 0) {
870  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The vehicle " + id + " to add already exists.", outputStorage);
871  return false;
872  }
873  if (valueDataType != TYPE_COMPOUND) {
874  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Adding a vehicle requires a compound object.", outputStorage);
875  return false;
876  }
877  if (inputStorage.readInt() != 6) {
878  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Adding a vehicle needs six parameters.", outputStorage);
879  return false;
880  }
881  SUMOVehicleParameter vehicleParams;
882  vehicleParams.id = id;
883 
884  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
885  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "First parameter (type) requires a string.", outputStorage);
886  return false;
887  }
888  std::string vTypeID = inputStorage.readString();
889  MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(vTypeID);
890  if (!vehicleType) {
891  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid type '" + vTypeID + "' for vehicle '" + id + "'");
892  return false;
893  }
894 
895  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
896  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Second parameter (route) requires a string.", outputStorage);
897  return false;
898  }
899  const std::string routeID = inputStorage.readString();
900  const MSRoute* route = MSRoute::dictionary(routeID);
901  if (!route) {
902  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid route '" + routeID + "' for vehicle: '" + id + "'");
903  return false;
904  }
905 
906  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
907  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Third parameter (depart) requires an integer.", outputStorage);
908  return false;
909  }
910  vehicleParams.depart = inputStorage.readInt();
911  if (vehicleParams.depart < 0) {
912  const int proc = static_cast<int>(-vehicleParams.depart);
913  if (proc >= static_cast<int>(DEPART_DEF_MAX)) {
914  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid departure time.", outputStorage);
915  return false;
916  }
917  vehicleParams.departProcedure = (DepartDefinition)proc;
918  }
919 
920  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
921  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Fourth parameter (position) requires a double.", outputStorage);
922  return false;
923  }
924  vehicleParams.departPos = inputStorage.readDouble();
925  if (vehicleParams.departPos < 0) {
926  const int proc = static_cast<int>(-vehicleParams.departPos);
927  if (proc >= static_cast<int>(DEPART_POS_DEF_MAX)) {
928  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid departure position.", outputStorage);
929  return false;
930  }
931  vehicleParams.departPosProcedure = (DepartPosDefinition)proc;
932  } else {
933  vehicleParams.departPosProcedure = DEPART_POS_GIVEN;
934  }
935 
936  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
937  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Fifth parameter (speed) requires a double.", outputStorage);
938  return false;
939  }
940  vehicleParams.departSpeed = inputStorage.readDouble();
941  if (vehicleParams.departSpeed < 0) {
942  const int proc = static_cast<int>(-vehicleParams.departSpeed);
943  if (proc >= static_cast<int>(DEPART_SPEED_DEF_MAX)) {
944  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid departure speed.", outputStorage);
945  return false;
946  }
947  vehicleParams.departSpeedProcedure = (DepartSpeedDefinition)proc;
948  } else {
950  }
951 
952  if (inputStorage.readUnsignedByte() != TYPE_BYTE) {
953  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Sixth parameter (lane) requires a byte.", outputStorage);
954  return false;
955  }
956  vehicleParams.departLane = inputStorage.readByte();
957  if (vehicleParams.departLane < 0) {
958  const int proc = static_cast<int>(-vehicleParams.departLane);
959  if (proc >= static_cast<int>(DEPART_LANE_DEF_MAX)) {
960  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Invalid departure lane.", outputStorage);
961  return false;
962  }
963  vehicleParams.departLaneProcedure = (DepartLaneDefinition)proc;
964  } else {
965  vehicleParams.departLaneProcedure = DEPART_LANE_GIVEN;
966  }
967 
969  *params = vehicleParams;
970  try {
971  SUMOVehicle* vehicle = MSNet::getInstance()->getVehicleControl().buildVehicle(params, route, vehicleType);
972  MSNet::getInstance()->getVehicleControl().addVehicle(vehicleParams.id, vehicle);
974  } catch (ProcessError& e) {
975  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, e.what(), outputStorage);
976  return false;
977  }
978  }
979  break;
980  case REMOVE: {
981  if (valueDataType != TYPE_BYTE) {
982  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Removing a vehicle requires an int.", outputStorage);
983  return false;
984  }
985  int why = (int) inputStorage.readByte();
987  switch (why) {
988  case REMOVE_TELEPORT:
990  break;
991  case REMOVE_PARKING:
993  break;
994  case REMOVE_ARRIVED:
996  break;
997  case REMOVE_VAPORIZED:
999  break;
1002  break;
1003  default:
1004  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Unknown removal status.", outputStorage);
1005  return false;
1006  }
1007  v->onRemovalFromNet(n);
1008  v->getLane()->removeVehicle(v);
1010  }
1011  break;
1012  case VAR_MOVE_TO_VTD: {
1013  if (valueDataType != TYPE_COMPOUND) {
1014  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting VTD vehicle requires a compound object.", outputStorage);
1015  return false;
1016  }
1017  if (inputStorage.readInt() != 4) {
1018  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Setting VTD vehicle should obtain: edgeID, lane, x, y.", outputStorage);
1019  return false;
1020  }
1021  // edge ID
1022  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
1023  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The first parameter for setting a VTD vehicle must be the edge ID given as a string.", outputStorage);
1024  return false;
1025  }
1026  std::string edgeID = inputStorage.readString();
1027  // lane index
1028  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
1029  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The second parameter for setting a VTD vehicle must be lane given as an int.", outputStorage);
1030  return false;
1031  }
1032  int laneNum = inputStorage.readInt();
1033  // x
1034  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
1035  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The third parameter for setting a VTD vehicle must be the x-position given as a double.", outputStorage);
1036  return false;
1037  }
1038  SUMOReal x = inputStorage.readDouble();
1039  // y
1040  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
1041  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The fourth parameter for setting a VTD vehicle must be the y-position given as a double.", outputStorage);
1042  return false;
1043  }
1044  SUMOReal y = inputStorage.readDouble();
1045  //if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
1046  // server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "The fifth parameter for setting a VTD vehicle must be the speed given as a double.", outputStorage);
1047  // return false;
1048  //}
1049  //SUMOReal speed = inputStorage.readDouble();
1050  // process
1051  if (!v->isOnRoad()) {
1052  break;
1053  }
1054  std::string origID = edgeID + " " + toString(laneNum);
1055  if (laneNum < 0) {
1056  edgeID = '-' + edgeID;
1057  laneNum = -laneNum;
1058  }
1059  //
1060  Position pos(x, y);
1061  unsigned int r = 0;
1062  SUMOReal minDist = 1 << (11);
1063  MSLane* minDistLane = 0;
1064  MSLane* nameMatchingLane = 0;
1065  SUMOReal minDistNameMatchingLane = 1 << (11);
1066  for (; minDistLane == 0 && r < 10 && nameMatchingLane == 0; ++r) {
1067  std::set<std::string> into;
1068  PositionVector shape;
1069  shape.push_back(pos);
1070  server.collectObjectsInRange(CMD_GET_EDGE_VARIABLE, shape, 1 << r, into);
1071  for (std::set<std::string>::const_iterator j = into.begin(); j != into.end(); ++j) {
1072  MSEdge* e = MSEdge::dictionary(*j);
1073  const std::vector<MSLane*>& lanes = e->getLanes();
1074  for (std::vector<MSLane*>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
1075  MSLane* lane = *k;
1076  bool nameMatches = false;
1077  SUMOReal dist = lane->getShape().distance(pos);
1078  if (lane->knowsParameter("origId")) {
1079  if (lane->getParameter("origId", "") == origID) {
1080  nameMatches = true;
1081  if (dist < minDistNameMatchingLane) {
1082  minDistNameMatchingLane = dist;
1083  nameMatchingLane = lane;
1084  }
1085  }
1086  }
1087  if (dist < minDist) {
1088  minDist = dist;
1089  minDistLane = lane;
1090  }
1091  }
1092  }
1093  }
1094  MSLane* lane = nameMatchingLane != 0 ? nameMatchingLane : minDistLane;
1095  if (lane != v->getLane()) {
1096  MSEdge& destinationEdge = lane->getEdge();
1097  MSEdge* routePos = &destinationEdge;
1098  while (routePos->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
1099  routePos = &routePos->getLanes()[0]->getLogicalPredecessorLane()->getEdge();
1100  }
1101  r = 0;
1102  const MSRoute& route = v->getRoute();
1103  unsigned int c = v->getRoutePosition();
1104  unsigned int l = (int)route.getEdges().size();
1105  unsigned int rindex = 0;
1106  bool found = false;
1107  while (!found && ((int)(c - r) >= 0 || c + r < l)) {
1108  if ((int)(c - r) >= 0 && route[c - r] == routePos) {
1109  rindex = c - r;
1110  found = true;
1111  }
1112  if (c + r < l && route[c + r] == routePos) {
1113  rindex = c + r;
1114  found = true;
1115  }
1116  ++r;
1117  }
1118  if (v->isOnRoad()) {
1119  v->getLane()->removeVehicle(v);
1121  }
1122  if (!found) {
1123  MSEdgeVector edges;
1124  MSLane* firstLane = lane;
1125  if (destinationEdge.getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
1126  edges.push_back(&destinationEdge);
1127  } else {
1128  firstLane = lane->getLogicalPredecessorLane();
1129  edges.push_back(&firstLane->getEdge());
1130  }
1131  const MSLinkCont& lc = firstLane->getLinkCont();
1132  if (lc.size() != 0 && lc[0]->getLane() != 0) {
1133  edges.push_back(&lc[0]->getLane()->getEdge());
1134  }
1135  v->replaceRouteEdges(edges, true);
1136  } else {
1137  v->resetRoutePosition(rindex);
1138  }
1139  } else {
1141  v->getLane()->removeVehicle(v);
1142  }
1143  /*
1144  std::vector<std::pair<SUMOTime, SUMOReal> > speedTimeLine;
1145  if (speed >= 0) {
1146  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), speed));
1147  speedTimeLine.push_back(std::make_pair(SUMOTime_MAX, speed));
1148  }
1149  v->getInfluencer().setSpeedTimeLine(speedTimeLine);
1150  */
1151 
1152  const SUMOReal position = lane->interpolateGeometryPosToLanePos(
1153  lane->getShape().nearest_position_on_line_to_point2D(pos, false));
1154  lane->forceVehicleInsertion(v, position);
1155  //v->getInfluencer().setPosition(position);
1156  v->getBestLanes(true, lane);
1157  }
1158  break;
1159  default:
1160  try {
1162  getSingularType(v), server, inputStorage, outputStorage)) {
1163  return false;
1164  }
1165  } catch (ProcessError& e) {
1166  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, e.what(), outputStorage);
1167  return false;
1168  }
1169  break;
1170  }
1171  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_OK, warning, outputStorage);
1172  return true;
1173 }
1174 
1175 
1176 bool
1178  tcpip::Storage& outputStorage, const MSVehicle* v) {
1179  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
1180  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of distance requires a compound object.", outputStorage);
1181  return false;
1182  }
1183  if (inputStorage.readInt() != 2) {
1184  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Retrieval of distance requires position and distance type as parameter.", outputStorage);
1185  return false;
1186  }
1187 
1188  Position pos;
1189  std::pair<const MSLane*, SUMOReal> roadPos;
1190 
1191  // read position
1192  int posType = inputStorage.readUnsignedByte();
1193  switch (posType) {
1194  case POSITION_ROADMAP:
1195  try {
1196  std::string roadID = inputStorage.readString();
1197  roadPos.second = inputStorage.readDouble();
1198  roadPos.first = TraCIServerAPI_Simulation::getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos.second);
1199  pos = roadPos.first->getShape().positionAtLengthPosition(roadPos.second);
1200  } catch (TraCIException& e) {
1202  return false;
1203  }
1204  break;
1205  case POSITION_2D:
1206  case POSITION_3D: {
1207  const double p1x = inputStorage.readDouble();
1208  const double p1y = inputStorage.readDouble();
1209  pos.set(p1x, p1y);
1210  }
1211  if (posType == POSITION_3D) {
1212  inputStorage.readDouble(); // z value is ignored
1213  }
1215  break;
1216  default:
1217  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_ERR, "Unknown position format used for distance request");
1218  return false;
1219  }
1220 
1221  // read distance type
1222  int distType = inputStorage.readUnsignedByte();
1223 
1224  SUMOReal distance = INVALID_DOUBLE_VALUE;
1225  if (v->isOnRoad()) {
1226  if (distType == REQUEST_DRIVINGDIST) {
1227  distance = v->getRoute().getDistanceBetween(v->getPositionOnLane(), roadPos.second,
1228  v->getEdge(), &roadPos.first->getEdge());
1229  if (distance == std::numeric_limits<SUMOReal>::max()) {
1230  distance = INVALID_DOUBLE_VALUE;
1231  }
1232  } else {
1233  // compute air distance (default)
1234  distance = v->getPosition().distanceTo(pos);
1235  }
1236  }
1237  // write response command
1238  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
1239  outputStorage.writeDouble(distance);
1240  return true;
1241 }
1242 
1243 
1244 // ------ helper functions ------
1245 bool
1246 TraCIServerAPI_Vehicle::getPosition(const std::string& id, Position& p) {
1247  MSVehicle* v = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(id));
1248  if (v == 0) {
1249  return false;
1250  }
1251  p = v->getPosition();
1252  return true;
1253 }
1254 
1255 
1258  const MSVehicleType& oType = veh->getVehicleType();
1259  std::string newID = oType.getID().find('@') == std::string::npos ? oType.getID() + "@" + veh->getID() : oType.getID();
1260  MSVehicleType* type = MSVehicleType::build(newID, &oType);
1261  static_cast<MSVehicle*>(veh)->replaceVehicleType(type);
1262  return *type;
1263 }
1264 
1265 
1266 #endif
1267 
1268 
1269 /****************************************************************************/
1270