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-sim.org/
14 // Copyright (C) 2001-2013 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 // static member variables
62 // ===========================================================================
63 std::map<std::string, std::vector<MSLane*> > TraCIServerAPI_Vehicle::gVTDMap;
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
77  && variable != VAR_POSITION && variable != VAR_ANGLE
78  && variable != VAR_ROAD_ID && variable != VAR_LANE_ID && variable != VAR_LANE_INDEX
79  && variable != VAR_TYPE && variable != VAR_ROUTE_ID && variable != VAR_COLOR
80  && variable != VAR_LANEPOSITION
81  && variable != VAR_CO2EMISSION && variable != VAR_COEMISSION
82  && variable != VAR_HCEMISSION && variable != VAR_PMXEMISSION
83  && variable != VAR_NOXEMISSION && variable != VAR_FUELCONSUMPTION && variable != VAR_NOISEEMISSION
84  && variable != VAR_PERSON_NUMBER
85  && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT
86  && variable != VAR_ROUTE_VALID && variable != VAR_EDGES
87  && variable != VAR_SIGNALS && variable != VAR_DISTANCE
88  && variable != VAR_LENGTH && variable != VAR_MAXSPEED && variable != VAR_VEHICLECLASS
89  && variable != VAR_SPEED_FACTOR && variable != VAR_SPEED_DEVIATION
90  && variable != VAR_ALLOWED_SPEED && variable != VAR_EMISSIONCLASS
91  && variable != VAR_WIDTH && variable != VAR_MINGAP && variable != VAR_SHAPECLASS
92  && variable != VAR_ACCEL && variable != VAR_DECEL && variable != VAR_IMPERFECTION
93  && variable != VAR_TAU && variable != VAR_BEST_LANES && variable != DISTANCE_REQUEST
94  && variable != ID_COUNT && variable != VAR_STOPSTATE && variable != VAR_WAITING_TIME
95  ) {
96  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Get Vehicle Variable: unsupported variable specified", outputStorage);
97  }
98  // begin response building
99  tcpip::Storage tempMsg;
100  // response-code, variableID, objectID
102  tempMsg.writeUnsignedByte(variable);
103  tempMsg.writeString(id);
104  // process request
105  if (variable == ID_LIST || variable == ID_COUNT) {
106  std::vector<std::string> ids;
108  for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
109  if ((*i).second->isOnRoad()) {
110  ids.push_back((*i).first);
111  }
112  }
113  if (variable == ID_LIST) {
115  tempMsg.writeStringList(ids);
116  } else {
118  tempMsg.writeInt((int) ids.size());
119  }
120  } else {
122  if (sumoVehicle == 0) {
123  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Vehicle '" + id + "' is not known", outputStorage);
124  }
125  MSVehicle* v = dynamic_cast<MSVehicle*>(sumoVehicle);
126  if (v == 0) {
127  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Vehicle '" + id + "' is not a micro-simulation vehicle", outputStorage);
128  }
129  const bool onRoad = v->isOnRoad();
130  switch (variable) {
131  case VAR_SPEED:
133  tempMsg.writeDouble(onRoad ? v->getSpeed() : INVALID_DOUBLE_VALUE);
134  break;
138  break;
139  case VAR_POSITION:
141  tempMsg.writeDouble(onRoad ? v->getPosition().x() : INVALID_DOUBLE_VALUE);
142  tempMsg.writeDouble(onRoad ? v->getPosition().y() : INVALID_DOUBLE_VALUE);
143  break;
144  case VAR_ANGLE:
146  tempMsg.writeDouble(onRoad ? v->getAngle() : INVALID_DOUBLE_VALUE);
147  break;
148  case VAR_ROAD_ID:
150  tempMsg.writeString(onRoad ? v->getLane()->getEdge().getID() : "");
151  break;
152  case VAR_LANE_ID:
154  tempMsg.writeString(onRoad ? v->getLane()->getID() : "");
155  break;
156  case VAR_LANE_INDEX:
158  if (onRoad) {
159  const std::vector<MSLane*>& lanes = v->getLane()->getEdge().getLanes();
160  tempMsg.writeInt((int)std::distance(lanes.begin(), std::find(lanes.begin(), lanes.end(), v->getLane())));
161  } else {
162  tempMsg.writeInt(INVALID_INT_VALUE);
163  }
164  break;
165  case VAR_TYPE:
167  tempMsg.writeString(v->getVehicleType().getID());
168  break;
169  case VAR_ROUTE_ID:
171  tempMsg.writeString(v->getRoute().getID());
172  break;
173  case VAR_COLOR:
174  tempMsg.writeUnsignedByte(TYPE_COLOR);
175  tempMsg.writeUnsignedByte(v->getParameter().color.red());
176  tempMsg.writeUnsignedByte(v->getParameter().color.green());
177  tempMsg.writeUnsignedByte(v->getParameter().color.blue());
178  tempMsg.writeUnsignedByte(v->getParameter().color.alpha());
179  break;
180  case VAR_LANEPOSITION:
182  tempMsg.writeDouble(onRoad ? v->getPositionOnLane() : INVALID_DOUBLE_VALUE);
183  break;
184  case VAR_CO2EMISSION:
186  tempMsg.writeDouble(onRoad ? v->getHBEFA_CO2Emissions() : INVALID_DOUBLE_VALUE);
187  break;
188  case VAR_COEMISSION:
190  tempMsg.writeDouble(onRoad ? v->getHBEFA_COEmissions() : INVALID_DOUBLE_VALUE);
191  break;
192  case VAR_HCEMISSION:
194  tempMsg.writeDouble(onRoad ? v->getHBEFA_HCEmissions() : INVALID_DOUBLE_VALUE);
195  break;
196  case VAR_PMXEMISSION:
198  tempMsg.writeDouble(onRoad ? v->getHBEFA_PMxEmissions() : INVALID_DOUBLE_VALUE);
199  break;
200  case VAR_NOXEMISSION:
202  tempMsg.writeDouble(onRoad ? v->getHBEFA_NOxEmissions() : INVALID_DOUBLE_VALUE);
203  break;
204  case VAR_FUELCONSUMPTION:
207  break;
208  case VAR_NOISEEMISSION:
211  break;
212  case VAR_PERSON_NUMBER:
214  tempMsg.writeInt(v->getPersonNumber());
215  break;
216  case VAR_WAITING_TIME:
218  tempMsg.writeDouble(v->getWaitingSeconds());
219  break;
220  case VAR_EDGE_TRAVELTIME: {
221  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
222  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Retrieval of travel time requires a compound object.", outputStorage);
223  }
224  if (inputStorage.readInt() != 2) {
225  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Retrieval of travel time requires time, and edge as parameter.", outputStorage);
226  }
227  // time
228  SUMOTime time = 0;
229  if (!server.readTypeCheckingInt(inputStorage, time)) {
230  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of travel time requires the referenced time as first parameter.", outputStorage);
231  }
232  // edge
233  std::string edgeID;
234  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
235  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of travel time requires the referenced edge as second parameter.", outputStorage);
236  }
237  MSEdge* edge = MSEdge::dictionary(edgeID);
238  if (edge == 0) {
239  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
240  }
241  // retrieve
243  SUMOReal value;
244  if (!v->getWeightsStorage().retrieveExistingTravelTime(edge, 0, time, value)) {
246  } else {
247  tempMsg.writeDouble(value);
248  }
249 
250  }
251  break;
252  case VAR_EDGE_EFFORT: {
253  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
254  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Retrieval of travel time requires a compound object.", outputStorage);
255  }
256  if (inputStorage.readInt() != 2) {
257  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Retrieval of travel time requires time, and edge as parameter.", outputStorage);
258  }
259  // time
260  SUMOTime time = 0;
261  if (!server.readTypeCheckingInt(inputStorage, time)) {
262  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of effort requires the referenced time as first parameter.", outputStorage);
263  }
264  // edge
265  std::string edgeID;
266  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
267  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of effort requires the referenced edge as second parameter.", outputStorage);
268  }
269  MSEdge* edge = MSEdge::dictionary(edgeID);
270  if (edge == 0) {
271  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
272  }
273  // retrieve
275  SUMOReal value;
276  if (!v->getWeightsStorage().retrieveExistingEffort(edge, 0, time, value)) {
278  } else {
279  tempMsg.writeDouble(value);
280  }
281 
282  }
283  break;
284  case VAR_ROUTE_VALID: {
285  std::string msg;
286  tempMsg.writeUnsignedByte(TYPE_UBYTE);
287  tempMsg.writeUnsignedByte(v->hasValidRoute(msg));
288  }
289  break;
290  case VAR_EDGES: {
291  const MSRoute& r = v->getRoute();
293  tempMsg.writeInt(r.size());
294  for (MSRouteIterator i = r.begin(); i != r.end(); ++i) {
295  tempMsg.writeString((*i)->getID());
296  }
297  }
298  break;
299  case VAR_SIGNALS:
301  tempMsg.writeInt(v->getSignals());
302  break;
303  case VAR_BEST_LANES: {
305  tcpip::Storage tempContent;
306  unsigned int cnt = 0;
307  tempContent.writeUnsignedByte(TYPE_INTEGER);
308  const std::vector<MSVehicle::LaneQ>& bestLanes = onRoad ? v->getBestLanes() : std::vector<MSVehicle::LaneQ>();
309  tempContent.writeInt((int) bestLanes.size());
310  ++cnt;
311  for (std::vector<MSVehicle::LaneQ>::const_iterator i = bestLanes.begin(); i != bestLanes.end(); ++i) {
312  const MSVehicle::LaneQ& lq = *i;
313  tempContent.writeUnsignedByte(TYPE_STRING);
314  tempContent.writeString(lq.lane->getID());
315  ++cnt;
316  tempContent.writeUnsignedByte(TYPE_DOUBLE);
317  tempContent.writeDouble(lq.length);
318  ++cnt;
319  tempContent.writeUnsignedByte(TYPE_DOUBLE);
320  tempContent.writeDouble(lq.nextOccupation);
321  ++cnt;
322  tempContent.writeUnsignedByte(TYPE_BYTE);
323  tempContent.writeByte(lq.bestLaneOffset);
324  ++cnt;
325  tempContent.writeUnsignedByte(TYPE_UBYTE);
326  lq.allowsContinuation ? tempContent.writeUnsignedByte(1) : tempContent.writeUnsignedByte(0);
327  ++cnt;
328  std::vector<std::string> bestContIDs;
329  for (std::vector<MSLane*>::const_iterator j = lq.bestContinuations.begin(); j != lq.bestContinuations.end(); ++j) {
330  bestContIDs.push_back((*j)->getID());
331  }
332  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
333  tempContent.writeStringList(bestContIDs);
334  ++cnt;
335  }
336  tempMsg.writeInt((int) cnt);
337  tempMsg.writeStorage(tempContent);
338  }
339  break;
340  case VAR_STOPSTATE: {
341  char b = (
342  1 * (v->isStopped() ? 1 : 0) +
343  2 * (v->isParking() ? 1 : 0) +
344  4 * (v->isStoppedTriggered() ? 1 : 0));
345  tempMsg.writeUnsignedByte(TYPE_UBYTE);
346  tempMsg.writeUnsignedByte(b);
347  }
348  break;
349  case VAR_DISTANCE: {
351  SUMOReal distance = onRoad ? v->getRoute().getDistanceBetween(0, v->getPositionOnLane(), v->getRoute().getEdges()[0], &v->getLane()->getEdge()) : INVALID_DOUBLE_VALUE;
352  if (distance == std::numeric_limits<SUMOReal>::max()) {
353  distance = INVALID_DOUBLE_VALUE;
354  }
355  tempMsg.writeDouble(distance);
356  }
357  break;
358  case DISTANCE_REQUEST:
359  if (!commandDistanceRequest(server, inputStorage, tempMsg, v)) {
360  return false;
361  }
362  break;
363  case VAR_ALLOWED_SPEED:
365  tempMsg.writeDouble(onRoad ? v->getLane()->getVehicleMaxSpeed(v) : INVALID_DOUBLE_VALUE);
366  break;
367  case VAR_SPEED_FACTOR:
369  tempMsg.writeDouble(v->getChosenSpeedFactor());
370  break;
371  default:
373  break;
374  }
375  }
376  server.writeStatusCmd(CMD_GET_VEHICLE_VARIABLE, RTYPE_OK, "", outputStorage);
377  server.writeResponseWithLength(outputStorage, tempMsg);
378  return true;
379 }
380 
381 
382 bool
384  tcpip::Storage& outputStorage) {
385  std::string warning = ""; // additional description for response
386  // variable
387  int variable = inputStorage.readUnsignedByte();
388  if (variable != CMD_STOP && variable != CMD_CHANGELANE
389  && variable != CMD_SLOWDOWN && variable != CMD_CHANGETARGET && variable != CMD_RESUME
390  && variable != VAR_TYPE && variable != VAR_ROUTE_ID && variable != VAR_ROUTE
391  && variable != VAR_EDGE_TRAVELTIME && variable != VAR_EDGE_EFFORT
392  && variable != CMD_REROUTE_TRAVELTIME && variable != CMD_REROUTE_EFFORT
393  && variable != VAR_SIGNALS && variable != VAR_MOVE_TO
394  && variable != VAR_LENGTH && variable != VAR_MAXSPEED && variable != VAR_VEHICLECLASS
395  && variable != VAR_SPEED_FACTOR && variable != VAR_EMISSIONCLASS
396  && variable != VAR_WIDTH && variable != VAR_MINGAP && variable != VAR_SHAPECLASS
397  && variable != VAR_ACCEL && variable != VAR_DECEL && variable != VAR_IMPERFECTION
398  && variable != VAR_TAU && variable != VAR_LANECHANGE_MODE
399  && variable != VAR_SPEED && variable != VAR_SPEEDSETMODE && variable != VAR_COLOR
400  && variable != ADD && variable != REMOVE
401  && variable != VAR_MOVE_TO_VTD
402  ) {
403  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Change Vehicle State: unsupported variable specified", outputStorage);
404  }
405  // id
406  std::string id = inputStorage.readString();
407  const bool shouldExist = variable != ADD;
409  if (sumoVehicle == 0) {
410  if (shouldExist) {
411  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Vehicle '" + id + "' is not known", outputStorage);
412  }
413  }
414  MSVehicle* v = dynamic_cast<MSVehicle*>(sumoVehicle);
415  if (v == 0 && shouldExist) {
416  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Vehicle '" + id + "' is not a micro-simulation vehicle", outputStorage);
417  }
418  switch (variable) {
419  case CMD_STOP: {
420  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
421  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Stop needs a compound object description.", outputStorage);
422  }
423  int compoundSize = inputStorage.readInt();
424  if (compoundSize != 4 && compoundSize != 5) {
425  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Stop needs a compound object description of four of five items.", outputStorage);
426  }
427  // read road map position
428  std::string roadId;
429  if (!server.readTypeCheckingString(inputStorage, roadId)) {
430  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The first stop parameter must be the edge id given as a string.", outputStorage);
431  }
432  double pos = 0;
433  if (!server.readTypeCheckingDouble(inputStorage, pos)) {
434  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The second stop parameter must be the position along the edge given as a double.", outputStorage);
435  }
436  int laneIndex = 0;
437  if (!server.readTypeCheckingByte(inputStorage, laneIndex)) {
438  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The third stop parameter must be the lane index given as a byte.", outputStorage);
439  }
440  // waitTime
441  SUMOTime waitTime = 0;
442  if (!server.readTypeCheckingInt(inputStorage, waitTime)) {
443  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "The fourth stop parameter must be the waiting time given as an integer.", outputStorage);
444  }
445  // optional stop flags
446  bool parking = false;
447  bool triggered = false;
448  if (compoundSize == 5) {
449  int stopFlags;
450  if (!server.readTypeCheckingByte(inputStorage, stopFlags)) {
451  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The fifth stop parameter must be a byte indicating its parking/triggered status.", outputStorage);
452  }
453  parking = ((stopFlags & 1) != 0);
454  triggered = ((stopFlags & 2) != 0);
455  }
456  // check
457  if (pos < 0) {
458  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Position on lane must not be negative", outputStorage);
459  }
460  // get the actual lane that is referenced by laneIndex
461  MSEdge* road = MSEdge::dictionary(roadId);
462  if (road == 0) {
463  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Unable to retrieve road with given id", outputStorage);
464  }
465  const std::vector<MSLane*>& allLanes = road->getLanes();
466  if ((laneIndex < 0) || laneIndex >= (int)(allLanes.size())) {
467  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "No lane existing with such id on the given road", outputStorage);
468  }
469  // Forward command to vehicle
470  if (!v->addTraciStop(allLanes[laneIndex], pos, 0, waitTime, parking, triggered)) {
471  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Vehicle is too close or behind the stop on " + allLanes[laneIndex]->getID(), outputStorage);
472  }
473  }
474  break;
475  case CMD_RESUME: {
476  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
477  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Resuming requires a compound object.", outputStorage);
478  return false;
479  }
480  if (inputStorage.readInt() != 0) {
481  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Resuming should obtain an empty compound object.", outputStorage);
482  return false;
483  }
484  if (!static_cast<MSVehicle*>(v)->resumeFromStopping()) {
485  MSVehicle::Stop& sto = (static_cast<MSVehicle*>(v))->getNextStop();
486  std::ostringstream strs;
487  strs << "reached: " << sto.reached;
488  strs << ", duration:" << sto.duration;
489  strs << ", edge:" << (*sto.edge)->getID();
490  strs << ", startPos: " << sto.startPos;
491  std::string posStr = strs.str();
492  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_ERR, "Failed to resume a non parking vehicle: " + v->getID() + ", " + posStr, outputStorage);
493  return false;
494  }
495  }
496  break;
497  case CMD_CHANGELANE: {
498  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
499  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Lane change needs a compound object description.", outputStorage);
500  }
501  if (inputStorage.readInt() != 2) {
502  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Lane change needs a compound object description of two items.", outputStorage);
503  }
504  // Lane ID
505  int laneIndex = 0;
506  if (!server.readTypeCheckingByte(inputStorage, laneIndex)) {
507  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The first lane change parameter must be the lane index given as a byte.", outputStorage);
508  }
509  // stickyTime
510  SUMOTime stickyTime = 0;
511  if (!server.readTypeCheckingInt(inputStorage, stickyTime)) {
512  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The second lane change parameter must be the duration given as an integer.", outputStorage);
513  }
514  if ((laneIndex < 0) || (laneIndex >= (int)(v->getEdge()->getLanes().size()))) {
515  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "No lane existing with given id on the current road", outputStorage);
516  }
517  // Forward command to vehicle
518  std::vector<std::pair<SUMOTime, unsigned int> > laneTimeLine;
519  laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), laneIndex));
520  laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + stickyTime, laneIndex));
521  v->getInfluencer().setLaneTimeLine(laneTimeLine);
522  }
523  break;
524  case CMD_SLOWDOWN: {
525  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
526  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Slow down needs a compound object description.", outputStorage);
527  }
528  if (inputStorage.readInt() != 2) {
529  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Slow down needs a compound object description of two items.", outputStorage);
530  }
531  double newSpeed = 0;
532  if (!server.readTypeCheckingDouble(inputStorage, newSpeed)) {
533  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The first slow down parameter must be the speed given as a double.", outputStorage);
534  }
535  if (newSpeed < 0) {
536  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Speed must not be negative", outputStorage);
537  }
538  SUMOTime duration = 0;
539  if (!server.readTypeCheckingInt(inputStorage, duration)) {
540  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The second slow down parameter must be the duration given as an integer.", outputStorage);
541  }
542  if (duration < 0) {
543  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid time interval", outputStorage);
544  }
545  std::vector<std::pair<SUMOTime, SUMOReal> > speedTimeLine;
546  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), v->getSpeed()));
547  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + duration, newSpeed));
548  v->getInfluencer().setSpeedTimeLine(speedTimeLine);
549  }
550  break;
551  case CMD_CHANGETARGET: {
552  std::string edgeID;
553  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
554  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Change target requires a string containing the id of the new destination edge as parameter.", outputStorage);
555  }
556  const MSEdge* destEdge = MSEdge::dictionary(edgeID);
557  if (destEdge == 0) {
558  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Can not retrieve road with ID " + edgeID, outputStorage);
559  }
560  // build a new route between the vehicle's current edge and destination edge
561  MSEdgeVector newRoute;
562  const MSEdge* currentEdge = v->getEdge();
564  currentEdge, destEdge, (const MSVehicle * const) v, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
565  // replace the vehicle's route by the new one
566  if (!v->replaceRouteEdges(newRoute, v->getLane() == 0)) {
567  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Route replacement failed for " + v->getID(), outputStorage);
568  }
569  }
570  break;
571  case VAR_TYPE: {
572  std::string vTypeID;
573  if (!server.readTypeCheckingString(inputStorage, vTypeID)) {
574  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The vehicle type id must be given as a string.", outputStorage);
575  }
576  MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(vTypeID);
577  if (vehicleType == 0) {
578  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The vehicle type '" + vTypeID + "' is not known.", outputStorage);
579  }
580  v->replaceVehicleType(vehicleType);
581  }
582  break;
583  case VAR_ROUTE_ID: {
584  std::string rid;
585  if (!server.readTypeCheckingString(inputStorage, rid)) {
586  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The route id must be given as a string.", outputStorage);
587  }
588  const MSRoute* r = MSRoute::dictionary(rid);
589  if (r == 0) {
590  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The route '" + rid + "' is not known.", outputStorage);
591  }
592  if (!v->replaceRoute(r, v->getLane() == 0)) {
593  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Route replacement failed for " + v->getID(), outputStorage);
594  }
595  }
596  break;
597  case VAR_ROUTE: {
598  std::vector<std::string> edgeIDs;
599  if (!server.readTypeCheckingStringList(inputStorage, edgeIDs)) {
600  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "A route must be defined as a list of edge ids.", outputStorage);
601  }
602  std::vector<const MSEdge*> edges;
603  MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
604  if (!v->replaceRouteEdges(edges, v->getLane() == 0)) {
605  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Route replacement failed for " + v->getID(), outputStorage);
606  }
607  }
608  break;
609  case VAR_EDGE_TRAVELTIME: {
610  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
611  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires a compound object.", outputStorage);
612  }
613  int parameterCount = inputStorage.readInt();
614  if (parameterCount == 4) {
615  // begin time
616  SUMOTime begTime = 0, endTime = 0;
617  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
618  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 4 parameters requires the begin time as first parameter.", outputStorage);
619  }
620  // begin time
621  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
622  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 4 parameters requires the end time as second parameter.", outputStorage);
623  }
624  // edge
625  std::string edgeID;
626  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
627  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 4 parameters requires the referenced edge as third parameter.", outputStorage);
628  }
629  MSEdge* edge = MSEdge::dictionary(edgeID);
630  if (edge == 0) {
631  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
632  }
633  // value
634  double value = 0;
635  if (!server.readTypeCheckingDouble(inputStorage, value)) {
636  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 4 parameters requires the travel time as double as fourth parameter.", outputStorage);
637  }
638  // retrieve
639  v->getWeightsStorage().addTravelTime(edge, begTime, endTime, value);
640  } else if (parameterCount == 2) {
641  // edge
642  std::string edgeID;
643  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
644  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 2 parameters requires the referenced edge as first parameter.", outputStorage);
645  }
646  MSEdge* edge = MSEdge::dictionary(edgeID);
647  if (edge == 0) {
648  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
649  }
650  // value
651  double value = 0;
652  if (!server.readTypeCheckingDouble(inputStorage, value)) {
653  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 2 parameters requires the travel time as second parameter.", outputStorage);
654  }
655  // retrieve
656  while (v->getWeightsStorage().knowsTravelTime(edge)) {
658  }
659  v->getWeightsStorage().addTravelTime(edge, 0, SUMOTime_MAX, value);
660  } else if (parameterCount == 1) {
661  // edge
662  std::string edgeID;
663  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
664  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time using 1 parameter requires the referenced edge as first parameter.", outputStorage);
665  }
666  MSEdge* edge = MSEdge::dictionary(edgeID);
667  if (edge == 0) {
668  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
669  }
670  // retrieve
671  while (v->getWeightsStorage().knowsTravelTime(edge)) {
673  }
674  } else {
675  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting travel time requires 1, 2, or 4 parameters.", outputStorage);
676  }
677  }
678  break;
679  case VAR_EDGE_EFFORT: {
680  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
681  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires a compound object.", outputStorage);
682  }
683  int parameterCount = inputStorage.readInt();
684  if (parameterCount == 4) {
685  // begin time
686  SUMOTime begTime = 0, endTime = 0;
687  if (!server.readTypeCheckingInt(inputStorage, begTime)) {
688  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 4 parameters requires the begin time as first parameter.", outputStorage);
689  }
690  // begin time
691  if (!server.readTypeCheckingInt(inputStorage, endTime)) {
692  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 4 parameters requires the end time as second parameter.", outputStorage);
693  }
694  // edge
695  std::string edgeID;
696  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
697  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 4 parameters requires the referenced edge as third parameter.", outputStorage);
698  }
699  MSEdge* edge = MSEdge::dictionary(edgeID);
700  if (edge == 0) {
701  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
702  }
703  // value
704  double value = 0;
705  if (!server.readTypeCheckingDouble(inputStorage, value)) {
706  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 4 parameters requires the travel time as fourth parameter.", outputStorage);
707  }
708  // retrieve
709  v->getWeightsStorage().addEffort(edge, begTime, endTime, value);
710  } else if (parameterCount == 2) {
711  // edge
712  std::string edgeID;
713  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
714  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 2 parameters requires the referenced edge as first parameter.", outputStorage);
715  }
716  MSEdge* edge = MSEdge::dictionary(edgeID);
717  if (edge == 0) {
718  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
719  }
720  // value
721  double value = 0;
722  if (!server.readTypeCheckingDouble(inputStorage, value)) {
723  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 2 parameters requires the travel time as second parameter.", outputStorage);
724  }
725  // retrieve
726  while (v->getWeightsStorage().knowsEffort(edge)) {
727  v->getWeightsStorage().removeEffort(edge);
728  }
729  v->getWeightsStorage().addEffort(edge, 0, SUMOTime_MAX, value);
730  } else if (parameterCount == 1) {
731  // edge
732  std::string edgeID;
733  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
734  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort using 1 parameter requires the referenced edge as first parameter.", outputStorage);
735  }
736  MSEdge* edge = MSEdge::dictionary(edgeID);
737  if (edge == 0) {
738  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Referenced edge '" + edgeID + "' is not known.", outputStorage);
739  }
740  // retrieve
741  while (v->getWeightsStorage().knowsEffort(edge)) {
742  v->getWeightsStorage().removeEffort(edge);
743  }
744  } else {
745  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting effort requires 1, 2, or 4 parameters.", outputStorage);
746  }
747  }
748  break;
749  case CMD_REROUTE_TRAVELTIME: {
750  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
751  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Rerouting requires a compound object.", outputStorage);
752  }
753  if (inputStorage.readInt() != 0) {
754  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Rerouting should obtain an empty compound object.", outputStorage);
755  }
756  v->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterTT());
757  }
758  break;
759  case CMD_REROUTE_EFFORT: {
760  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
761  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Rerouting requires a compound object.", outputStorage);
762  }
763  if (inputStorage.readInt() != 0) {
764  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Rerouting should obtain an empty compound object.", outputStorage);
765  }
766  v->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterEffort());
767  }
768  break;
769  case VAR_SIGNALS: {
770  int signals = 0;
771  if (!server.readTypeCheckingInt(inputStorage, signals)) {
772  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting signals requires an integer.", outputStorage);
773  }
774  v->switchOffSignal(0x0fffffff);
775  v->switchOnSignal(signals);
776  }
777  break;
778  case VAR_MOVE_TO: {
779  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
780  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting position requires a compound object.", outputStorage);
781  }
782  if (inputStorage.readInt() != 2) {
783  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting position should obtain the lane id and the position.", outputStorage);
784  }
785  // lane ID
786  std::string laneID;
787  if (!server.readTypeCheckingString(inputStorage, laneID)) {
788  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The first parameter for setting a position must be the lane ID given as a string.", outputStorage);
789  }
790  // position on lane
791  double position = 0;
792  if (!server.readTypeCheckingDouble(inputStorage, position)) {
793  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The second parameter for setting a position must be the position given as a double.", outputStorage);
794  }
795  // process
796  MSLane* l = MSLane::dictionary(laneID);
797  if (l == 0) {
798  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Unknown lane '" + laneID + "'.", outputStorage);
799  }
800  MSEdge& destinationEdge = l->getEdge();
801  if (!v->willPass(&destinationEdge)) {
802  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Vehicle '" + laneID + "' may be set onto an edge to pass only.", outputStorage);
803  }
806  while (v->getEdge() != &destinationEdge) {
807  const MSEdge* nextEdge = v->succEdge(1);
808  // let the vehicle move to the next edge
809  if (v->enterLaneAtMove(nextEdge->getLanes()[0], true)) {
811  continue;
812  }
813  }
814  l->forceVehicleInsertion(v, position);
815  }
816  break;
817  case VAR_SPEED: {
818  double speed = 0;
819  if (!server.readTypeCheckingDouble(inputStorage, speed)) {
820  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting speed requires a double.", outputStorage);
821  }
822  std::vector<std::pair<SUMOTime, SUMOReal> > speedTimeLine;
823  if (speed >= 0) {
824  speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), speed));
825  speedTimeLine.push_back(std::make_pair(SUMOTime_MAX, speed));
826  }
827  v->getInfluencer().setSpeedTimeLine(speedTimeLine);
828  }
829  break;
830  case VAR_SPEEDSETMODE: {
831  int speedMode = 0;
832  if (!server.readTypeCheckingInt(inputStorage, speedMode)) {
833  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting speed mode requires an integer.", outputStorage);
834  }
835  v->getInfluencer().setConsiderSafeVelocity((speedMode & 1) != 0);
836  v->getInfluencer().setConsiderMaxAcceleration((speedMode & 2) != 0);
837  v->getInfluencer().setConsiderMaxDeceleration((speedMode & 4) != 0);
838  }
839  break;
840  case VAR_LANECHANGE_MODE: {
841  int laneChangeMode = 0;
842  if (!server.readTypeCheckingInt(inputStorage, laneChangeMode)) {
843  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting lane change mode requires an integer.", outputStorage);
844  }
845  v->getInfluencer().setLaneChangeMode(laneChangeMode);
846  }
847  break;
848  case VAR_COLOR: {
849  RGBColor col;
850  if (!server.readTypeCheckingColor(inputStorage, col)) {
851  return server.writeErrorStatusCmd(CMD_SET_POLYGON_VARIABLE, "The color must be given using the according type.", outputStorage);
852  }
853  v->getParameter().color.set(col.red(), col.green(), col.blue(), col.alpha());
855  }
856  break;
857  case ADD: {
858  if (v != 0) {
859  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The vehicle " + id + " to add already exists.", outputStorage);
860  }
861  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
862  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Adding a vehicle requires a compound object.", outputStorage);
863  }
864  if (inputStorage.readInt() != 6) {
865  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Adding a vehicle needs six parameters.", outputStorage);
866  }
867  SUMOVehicleParameter vehicleParams;
868  vehicleParams.id = id;
869 
870  std::string vTypeID;
871  if (!server.readTypeCheckingString(inputStorage, vTypeID)) {
872  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "First parameter (type) requires a string.", outputStorage);
873  }
874  MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(vTypeID);
875  if (!vehicleType) {
876  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid type '" + vTypeID + "' for vehicle '" + id + "'", outputStorage);
877  }
878 
879  std::string routeID;
880  if (!server.readTypeCheckingString(inputStorage, routeID)) {
881  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Second parameter (route) requires a string.", outputStorage);
882  }
883  const MSRoute* route = MSRoute::dictionary(routeID);
884  if (!route) {
885  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid route '" + routeID + "' for vehicle: '" + id + "'", outputStorage);
886  }
887 
888  if (!server.readTypeCheckingInt(inputStorage, vehicleParams.depart)) {
889  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Third parameter (depart) requires an integer.", outputStorage);
890  }
891  if (vehicleParams.depart < 0) {
892  const int proc = static_cast<int>(-vehicleParams.depart);
893  if (proc >= static_cast<int>(DEPART_DEF_MAX)) {
894  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid departure time.", outputStorage);
895  }
896  vehicleParams.departProcedure = (DepartDefinition)proc;
897  }
898 
899  double pos;
900  if (!server.readTypeCheckingDouble(inputStorage, pos)) {
901  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Fourth parameter (position) requires a double.", outputStorage);
902  }
903  vehicleParams.departPos = pos;
904  if (vehicleParams.departPos < 0) {
905  const int proc = static_cast<int>(-vehicleParams.departPos);
906  if (proc >= static_cast<int>(DEPART_POS_DEF_MAX)) {
907  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid departure position.", outputStorage);
908  }
909  vehicleParams.departPosProcedure = (DepartPosDefinition)proc;
910  } else {
911  vehicleParams.departPosProcedure = DEPART_POS_GIVEN;
912  }
913 
914  double speed;
915  if (!server.readTypeCheckingDouble(inputStorage, speed)) {
916  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Fifth parameter (speed) requires a double.", outputStorage);
917  }
918  vehicleParams.departSpeed = speed;
919  if (vehicleParams.departSpeed < 0) {
920  const int proc = static_cast<int>(-vehicleParams.departSpeed);
921  if (proc >= static_cast<int>(DEPART_SPEED_DEF_MAX)) {
922  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid departure speed.", outputStorage);
923  }
924  vehicleParams.departSpeedProcedure = (DepartSpeedDefinition)proc;
925  } else {
927  }
928 
929  if (!server.readTypeCheckingByte(inputStorage, vehicleParams.departLane)) {
930  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Sixth parameter (lane) requires a byte.", outputStorage);
931  }
932 
933  if (vehicleParams.departLane < 0) {
934  const int proc = static_cast<int>(-vehicleParams.departLane);
935  if (proc >= static_cast<int>(DEPART_LANE_DEF_MAX)) {
936  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Invalid departure lane.", outputStorage);
937  }
938  vehicleParams.departLaneProcedure = (DepartLaneDefinition)proc;
939  } else {
940  vehicleParams.departLaneProcedure = DEPART_LANE_GIVEN;
941  }
942 
944  *params = vehicleParams;
945  try {
946  SUMOVehicle* vehicle = MSNet::getInstance()->getVehicleControl().buildVehicle(params, route, vehicleType);
947  MSNet::getInstance()->getVehicleControl().addVehicle(vehicleParams.id, vehicle);
949  } catch (ProcessError& e) {
950  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, e.what(), outputStorage);
951  }
952  }
953  break;
954  case REMOVE: {
955  int why = 0;
956  if (!server.readTypeCheckingByte(inputStorage, why)) {
957  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Removing a vehicle requires a byte.", outputStorage);
958  }
960  switch (why) {
961  case REMOVE_TELEPORT:
962  // XXX semantics unclear
963  // n = MSMoveReminder::NOTIFICATION_TELEPORT;
965  break;
966  case REMOVE_PARKING:
967  // XXX semantics unclear
968  // n = MSMoveReminder::NOTIFICATION_PARKING;
970  break;
971  case REMOVE_ARRIVED:
973  break;
974  case REMOVE_VAPORIZED:
976  break;
979  break;
980  default:
981  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Unknown removal status.", outputStorage);
982  }
983  if (v->hasDeparted()) {
984  v->onRemovalFromNet(n);
985  if (v->getLane() != 0) {
986  v->getLane()->removeVehicle(v, n);
987  }
989  }
990  }
991  break;
992  case VAR_MOVE_TO_VTD: {
993  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
994  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting VTD vehicle requires a compound object.", outputStorage);
995  }
996  if (inputStorage.readInt() != 4) {
997  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting VTD vehicle should obtain: edgeID, lane, x, y.", outputStorage);
998  }
999  // edge ID
1000  std::string edgeID;
1001  if (!server.readTypeCheckingString(inputStorage, edgeID)) {
1002  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The first parameter for setting a VTD vehicle must be the edge ID given as a string.", outputStorage);
1003  }
1004  // lane index
1005  int laneNum = 0;
1006  if (!server.readTypeCheckingInt(inputStorage, laneNum)) {
1007  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The second parameter for setting a VTD vehicle must be lane given as an int.", outputStorage);
1008  }
1009  // x
1010  double x = 0, y = 0;
1011  if (!server.readTypeCheckingDouble(inputStorage, x)) {
1012  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The third parameter for setting a VTD vehicle must be the x-position given as a double.", outputStorage);
1013  }
1014  // y
1015  if (!server.readTypeCheckingDouble(inputStorage, y)) {
1016  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "The fourth parameter for setting a VTD vehicle must be the y-position given as a double.", outputStorage);
1017  }
1018  // process
1019  if (!v->isOnRoad()) {
1020  break;
1021  }
1022  std::string origID = edgeID + " " + toString(laneNum);
1023  if (laneNum < 0) {
1024  edgeID = '-' + edgeID;
1025  laneNum = -laneNum;
1026  }
1027  Position pos(x, y);
1028 
1029  Position vehPos = v->getPosition();
1030  v->getBestLanes();
1031  bool report = server.vtdDebug();
1032  if (report) {
1033  std::cout << std::endl << "begin vehicle " << v->getID() << " vehPos:" << vehPos << " lane:" << v->getLane()->getID() << std::endl;
1034  }
1035  if (report) {
1036  std::cout << " want pos:" << pos << " edge:" << edgeID << " laneNum:" << laneNum << std::endl;
1037  }
1038 
1039  MSEdgeVector edgesA, edgesB, edgesC;
1040  MSLane* laneA, *laneB, *laneC;
1041  laneA = laneB = laneC = 0;
1042  SUMOReal lanePosA, lanePosB, lanePosC;
1043  SUMOReal bestDistanceA, bestDistanceB, bestDistanceC;
1044  bestDistanceA = bestDistanceB = bestDistanceC = 1000.;//pos.distanceSquaredTo2D(vehPos);
1045  int routeOffsetA, routeOffsetB, routeOffsetC;
1046  routeOffsetA = routeOffsetB = routeOffsetC = 0;
1047  // case a): edge/lane is known and matches route
1048  bool aFound = vtdMap_matchingEdgeLane(pos, origID, *v, server.vtdDebug(), bestDistanceA, &laneA, lanePosA, routeOffsetA, edgesA);
1049  // case b): position is at route, should be somewhere near to it
1050  bool bFound = vtdMap_matchingRoutePosition(pos, origID, *v, server.vtdDebug(), bestDistanceB, &laneB, lanePosB, routeOffsetB, edgesB);
1051  // case c) nearest matching lane
1052  bool cFound = vtdMap_matchingNearest(pos, origID, *v, server, server.vtdDebug(), bestDistanceC, &laneC, lanePosC, routeOffsetC, edgesC);
1053  //
1054  SUMOReal maxRouteDistance = 50;
1055  if (cFound && (bestDistanceA > maxRouteDistance && bestDistanceC > maxRouteDistance)) {
1056  // both route-based approach yield in a position too far away from the submitted --> new route!?
1057  server.setVTDControlled(v, laneC, lanePosC, routeOffsetC, edgesC);
1058  } else {
1059  // use the best we have
1060  if (bFound) {
1061  server.setVTDControlled(v, laneB, lanePosB, routeOffsetB, edgesB);
1062  } else if (aFound) {
1063  server.setVTDControlled(v, laneA, lanePosA, routeOffsetA, edgesA);
1064  } else if (cFound) {
1065  server.setVTDControlled(v, laneC, lanePosC, routeOffsetC, edgesC);
1066  } else {
1067  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Could not map vehicle.", outputStorage);
1068  }
1069  }
1070  }
1071  break;
1072  case VAR_SPEED_FACTOR: {
1073  double factor = 0;
1074  if (!server.readTypeCheckingDouble(inputStorage, factor)) {
1075  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, "Setting speed factor requires a double.", outputStorage);
1076  }
1077  v->setChosenSpeedFactor(factor);
1078  }
1079  break;
1080  default:
1081  try {
1082  if (!TraCIServerAPI_VehicleType::setVariable(CMD_SET_VEHICLE_VARIABLE, variable, getSingularType(v), server, inputStorage, outputStorage)) {
1083  return false;
1084  }
1085  } catch (ProcessError& e) {
1086  return server.writeErrorStatusCmd(CMD_SET_VEHICLE_VARIABLE, e.what(), outputStorage);
1087  }
1088  break;
1089  }
1090  server.writeStatusCmd(CMD_SET_VEHICLE_VARIABLE, RTYPE_OK, warning, outputStorage);
1091  return true;
1092 }
1093 
1094 
1095 bool
1096 TraCIServerAPI_Vehicle::vtdMap_matchingEdgeLane(const Position& pos, const std::string& origID, MSVehicle& v, bool report,
1097  SUMOReal& bestDistance, MSLane** lane, SUMOReal& lanePos, int& routeOffset, MSEdgeVector& edges) {
1098  UNUSED_PARAMETER(edges);
1099  const std::map<std::string, std::vector<MSLane*> >& vtdMap = getOrBuildVTDMap();
1100  if (vtdMap.find(origID) == vtdMap.end()) {
1101  if (report) {
1102  std::cout << " a failed - lane not in map" << std::endl;
1103  }
1104  return false;
1105  }
1106  const std::vector<MSLane*>& lanes = vtdMap.find(origID)->second;
1107  for (std::vector<MSLane*>::const_iterator i = lanes.begin(); i != lanes.end() && bestDistance > POSITION_EPS; ++i) {
1108  MSLane* l = *i;
1109  SUMOReal dist = l->getShape().distance(pos);
1110  if (report) {
1111  std::cout << " a at lane " << l->getID() << " dist:" << dist << " best:" << bestDistance << std::endl;
1112  }
1113  if (dist < bestDistance) {
1114  bestDistance = dist;
1115  *lane = l;
1116  }
1117  }
1118  MSLane* pni = *lane;
1119  while (pni != 0 && pni->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL && pni->getIncomingLanes().size() != 0) {
1120  pni = pni->getIncomingLanes()[0].lane;
1121  }
1122  if (pni == 0 || pni->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
1123  // not found
1124  if (report) {
1125  std::cout << " a failed - no incoming lane" << std::endl;
1126  }
1127  return false;
1128  }
1129  const MSEdgeVector& tedges = v.getRoute().getEdges();
1130  MSEdgeVector::const_iterator p = std::find(tedges.begin() + v.getRoutePosition(), tedges.end(), &pni->getEdge());
1131  if (p != tedges.end()) {
1132  lanePos = MAX2(SUMOReal(0), MIN2(SUMOReal((*lane)->getLength() - POSITION_EPS), (*lane)->getShape().nearest_offset_to_point2D(pos, false)));
1133  routeOffset = (int)(std::distance(tedges.begin(), p) - v.getRoutePosition());
1134  if (report) {
1135  std::cout << " a ok lane:" << (*lane)->getID() << " lanePos:" << lanePos << " routeOffset:" << routeOffset << std::endl;
1136  }
1137  return true;
1138  }
1139  if (report) {
1140  std::cout << " a failed - route position beyond route length" << std::endl;
1141  }
1142  return false;
1143 }
1144 
1145 
1146 bool
1147 TraCIServerAPI_Vehicle::vtdMap_matchingRoutePosition(const Position& pos, const std::string& origID, MSVehicle& v, bool report,
1148  SUMOReal& bestDistance, MSLane** lane, SUMOReal& lanePos, int& routeOffset, MSEdgeVector& edges) {
1149  UNUSED_PARAMETER(edges);
1150  UNUSED_PARAMETER(origID);
1151  int lastBestRouteEdge = 0;
1152  int lastRouteEdge = 0;
1153  MSLane* bestRouteLane = 0;
1154  const std::vector<MSLane*>& bestLaneConts = v.getBestLanesContinuation(v.getLane());
1155  for (std::vector<MSLane*>::const_iterator i = bestLaneConts.begin(); i != bestLaneConts.end() && bestDistance > POSITION_EPS; ++i) {
1156  MSEdge& e = (*i)->getEdge();
1157  if (i != bestLaneConts.begin() && e.getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
1158  ++lastRouteEdge;
1159  }
1160  const std::vector<MSLane*>& lanes = e.getLanes();
1161  for (std::vector<MSLane*>::const_iterator k = lanes.begin(); k != lanes.end() && bestDistance > POSITION_EPS; ++k) {
1162  MSLane* cl = *k;
1163  SUMOReal dist = cl->getShape().distance(pos);
1164  if (report) {
1165  std::cout << " b at lane " << cl->getID() << " dist:" << dist << " best:" << bestDistance << std::endl;
1166  }
1167  if (dist < bestDistance) {
1168  bestDistance = dist;
1169  *lane = cl;
1170  lastBestRouteEdge = lastRouteEdge;
1172  bestRouteLane = *i;
1173  } else {
1174  bestRouteLane = *lane;
1175  }
1176  }
1177  }
1178  }
1179  if (bestRouteLane == 0) {
1180  if (report) {
1181  std::cout << " b failed - no best route lane" << std::endl;
1182  }
1183  return false;
1184  }
1185  lanePos = MAX2(SUMOReal(0), MIN2(SUMOReal(bestRouteLane->getLength() - POSITION_EPS), bestRouteLane->getShape().nearest_offset_to_point2D(pos, false)));
1186  routeOffset = lastBestRouteEdge;
1187  if (report) {
1188  std::cout << " b ok lane " << bestRouteLane->getID() << " lanePos:" << lanePos << " best:" << lastBestRouteEdge << std::endl;
1189  }
1190  return true;
1191 }
1192 
1193 
1194 bool
1195 TraCIServerAPI_Vehicle::vtdMap_matchingNearest(const Position& pos, const std::string& origID, MSVehicle& v, TraCIServer& server, bool report,
1196  SUMOReal& bestDistance, MSLane** lane, SUMOReal& lanePos, int& routeOffset, MSEdgeVector& edges) {
1197  UNUSED_PARAMETER(bestDistance);
1198  unsigned int r = 0;
1199  SUMOReal minDist = 1 << (11);
1200  MSLane* minDistLane = 0;
1201  MSLane* nameMatchingLane = 0;
1202  SUMOReal minDistNameMatchingLane = 1 << (11);
1203  for (; minDistLane == 0 && r < 10 && nameMatchingLane == 0; ++r) {
1204  std::set<std::string> into;
1205  PositionVector shape;
1206  shape.push_back(pos);
1207  server.collectObjectsInRange(CMD_GET_EDGE_VARIABLE, shape, 1 << r, into);
1208  for (std::set<std::string>::const_iterator j = into.begin(); j != into.end(); ++j) {
1209  MSEdge* e = MSEdge::dictionary(*j);
1210  const std::vector<MSLane*>& lanes = e->getLanes();
1211  for (std::vector<MSLane*>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
1212  MSLane* lane = *k;
1213  SUMOReal dist = lane->getShape().distance(pos);
1214  if (lane->knowsParameter("origId")) {
1215  if (lane->getParameter("origId", "") == origID) {
1216  if (dist < minDistNameMatchingLane) {
1217  minDistNameMatchingLane = dist;
1218  nameMatchingLane = lane;
1219  }
1220  }
1221  }
1222  if (dist < minDist) {
1223  minDist = dist;
1224  minDistLane = lane;
1225  }
1226  }
1227  }
1228  }
1229  *lane = nameMatchingLane != 0 ? nameMatchingLane : minDistLane;
1230  if (lane == 0) {
1231  if (report) {
1232  std::cout << " c failed - no matching lane" << std::endl;
1233  }
1234  return false;
1235  }
1236  lanePos = (*lane)->interpolateGeometryPosToLanePos((*lane)->getShape().nearest_offset_to_point2D(pos, false));
1237  if (*lane == v.getLane()) {
1238  routeOffset = 0;
1239  if (report) {
1240  std::cout << " c ok, on same lane" << std::endl;
1241  }
1242  return true;
1243  }
1244  MSEdge& destinationEdge = (*lane)->getEdge();
1245  MSEdge* routePos = &destinationEdge;
1246  while (routePos->getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL) {
1247  routePos = &routePos->getLanes()[0]->getLogicalPredecessorLane()->getEdge();
1248  }
1249  r = 0;
1250  const MSRoute& route = v.getRoute();
1251  unsigned int c = v.getRoutePosition();
1252  unsigned int l = (int)route.getEdges().size();
1253  unsigned int rindex = 0;
1254  bool found = false;
1255  while (!found && ((int)(c - r) >= 0 || c + r < l)) {
1256  if ((int)(c - r) >= 0 && route[c - r] == routePos) {
1257  rindex = c - r;
1258  found = true;
1259  }
1260  if (c + r < l && route[c + r] == routePos) {
1261  rindex = c + r;
1262  found = true;
1263  }
1264  ++r;
1265  }
1266  if (found) {
1267  // the matching lane is part of the route
1268  routeOffset = rindex - v.getRoutePosition();
1269  if (report) {
1270  std::cout << " c ok, on a different edge of same route" << std::endl;
1271  }
1272  return true;
1273  }
1274  // build new route
1275  MSLane* firstLane = *lane;
1276  if (destinationEdge.getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
1277  edges.push_back(&destinationEdge);
1278  } else {
1279  firstLane = (*lane)->getLogicalPredecessorLane();
1280  edges.push_back(&firstLane->getEdge());
1281  }
1282  const MSLinkCont& lc = firstLane->getLinkCont();
1283  if (lc.size() != 0 && lc[0]->getLane() != 0) {
1284  edges.push_back(&lc[0]->getLane()->getEdge());
1285  }
1286  if (report) {
1287  std::cout << " c ok, on a different route" << std::endl;
1288  }
1289  return true;
1290 }
1291 
1292 
1293 bool
1295  tcpip::Storage& outputStorage, const MSVehicle* v) {
1296  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
1297  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of distance requires a compound object.", outputStorage);
1298  }
1299  if (inputStorage.readInt() != 2) {
1300  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Retrieval of distance requires position and distance type as parameter.", outputStorage);
1301  }
1302 
1303  Position pos;
1304  std::pair<const MSLane*, SUMOReal> roadPos;
1305 
1306  // read position
1307  int posType = inputStorage.readUnsignedByte();
1308  switch (posType) {
1309  case POSITION_ROADMAP:
1310  try {
1311  std::string roadID = inputStorage.readString();
1312  roadPos.second = inputStorage.readDouble();
1313  roadPos.first = TraCIServerAPI_Simulation::getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos.second);
1314  pos = roadPos.first->getShape().positionAtOffset(roadPos.second);
1315  } catch (TraCIException& e) {
1316  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, e.what(), outputStorage);
1317  }
1318  break;
1319  case POSITION_2D:
1320  case POSITION_3D: {
1321  const double p1x = inputStorage.readDouble();
1322  const double p1y = inputStorage.readDouble();
1323  pos.set(p1x, p1y);
1324  }
1325  if (posType == POSITION_3D) {
1326  inputStorage.readDouble(); // z value is ignored
1327  }
1329  break;
1330  default:
1331  return server.writeErrorStatusCmd(CMD_GET_VEHICLE_VARIABLE, "Unknown position format used for distance request", outputStorage);
1332  }
1333 
1334  // read distance type
1335  int distType = inputStorage.readUnsignedByte();
1336 
1337  SUMOReal distance = INVALID_DOUBLE_VALUE;
1338  if (v->isOnRoad()) {
1339  if (distType == REQUEST_DRIVINGDIST) {
1340  distance = v->getRoute().getDistanceBetween(v->getPositionOnLane(), roadPos.second,
1341  v->getEdge(), &roadPos.first->getEdge());
1342  if (distance == std::numeric_limits<SUMOReal>::max()) {
1343  distance = INVALID_DOUBLE_VALUE;
1344  }
1345  } else {
1346  // compute air distance (default)
1347  distance = v->getPosition().distanceTo(pos);
1348  }
1349  }
1350  // write response command
1351  outputStorage.writeUnsignedByte(TYPE_DOUBLE);
1352  outputStorage.writeDouble(distance);
1353  return true;
1354 }
1355 
1356 
1357 // ------ helper functions ------
1358 bool
1359 TraCIServerAPI_Vehicle::getPosition(const std::string& id, Position& p) {
1360  MSVehicle* v = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(id));
1361  if (v == 0) {
1362  return false;
1363  }
1364  p = v->getPosition();
1365  return true;
1366 }
1367 
1368 
1371  const MSVehicleType& oType = veh->getVehicleType();
1372  std::string newID = oType.getID().find('@') == std::string::npos ? oType.getID() + "@" + veh->getID() : oType.getID();
1373  MSVehicleType* type = MSVehicleType::build(newID, &oType);
1374  static_cast<MSVehicle*>(veh)->replaceVehicleType(type);
1375  return *type;
1376 }
1377 
1378 
1379 #include <microsim/MSEdgeControl.h>
1380 
1381 const std::map<std::string, std::vector<MSLane*> >&
1383  if (gVTDMap.size() == 0) {
1384  const std::vector<MSEdge*>& edges = MSNet::getInstance()->getEdgeControl().getEdges();
1385  for (std::vector<MSEdge*>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
1386  const std::vector<MSLane*>& lanes = (*i)->getLanes();
1387  for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1388  if ((*j)->knowsParameter("origId")) {
1389  std::string origID = (*j)->getParameter("origId", "");
1390  if (gVTDMap.find(origID) == gVTDMap.end()) {
1391  gVTDMap[origID] = std::vector<MSLane*>();
1392  }
1393  gVTDMap[origID].push_back(*j);
1394  }
1395  }
1396  }
1397  if (gVTDMap.size() == 0) {
1398  gVTDMap["unknown"] = std::vector<MSLane*>();
1399  }
1400  }
1401  return gVTDMap;
1402 }
1403 
1404 
1405 #endif
1406 
1407 
1408 /****************************************************************************/
1409