SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TraCIServer.cpp
Go to the documentation of this file.
1 /****************************************************************************/
16 /****************************************************************************/
17 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
18 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
19 /****************************************************************************/
20 //
21 // This file is part of SUMO.
22 // SUMO is free software: you can redistribute it and/or modify
23 // it under the terms of the GNU General Public License as published by
24 // the Free Software Foundation, either version 3 of the License, or
25 // (at your option) any later version.
26 //
27 /****************************************************************************/
28 
29 // ===========================================================================
30 // included modules
31 // ===========================================================================
32 #ifdef _MSC_VER
33 #include <windows_config.h>
34 #else
35 #include <config.h>
36 #endif
37 
38 #ifdef HAVE_VERSION_H
39 #include <version.h>
40 #endif
41 
42 #ifndef NO_TRACI
43 
44 #ifdef HAVE_PYTHON
45 #include <Python.h>
46 #endif
47 
48 #include <string>
49 #include <map>
50 #include <iostream>
51 #include <foreign/tcpip/socket.h>
52 #include <foreign/tcpip/storage.h>
53 #include <utils/common/SUMOTime.h>
63 #include <utils/shapes/Polygon.h>
64 #include <utils/xml/XMLSubSys.h>
65 #include <microsim/MSNet.h>
67 #include <microsim/MSVehicle.h>
68 #include <microsim/MSEdge.h>
70 #include <microsim/MSJunction.h>
71 #include <microsim/MSEdgeControl.h>
72 #include <microsim/MSLane.h>
73 #include <microsim/MSGlobals.h>
75 #include "TraCIConstants.h"
76 #include "TraCIServer.h"
79 #include "TraCIServerAPI_Lane.h"
82 
83 #include "TraCIServerAPI_TLS.h"
84 #include "TraCIServerAPI_Vehicle.h"
86 #include "TraCIServerAPI_Route.h"
87 #include "TraCIServerAPI_POI.h"
88 #include "TraCIServerAPI_Polygon.h"
89 #include "TraCIServerAPI_Edge.h"
91 
92 #ifdef CHECK_MEMORY_LEAKS
93 #include <foreign/nvwa/debug_new.h>
94 #endif // CHECK_MEMORY_LEAKS
95 
96 
97 // ===========================================================================
98 // static member definitions
99 // ===========================================================================
102 
103 
104 // ===========================================================================
105 // method definitions
106 // ===========================================================================
107 TraCIServer::TraCIServer(const SUMOTime begin, const int port)
108  : mySocket(0), myTargetTime(begin), myDoingSimStep(false), myAmEmbedded(port == 0), myLaneTree(0) {
109 
110  myVehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>();
111  myVehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>();
112  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>();
113  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>();
114  myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>();
115  myVehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>();
116  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_PARKING] = std::vector<std::string>();
117  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_PARKING] = std::vector<std::string>();
118  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_STOP] = std::vector<std::string>();
119  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_STOP] = std::vector<std::string>();
121 
125 
145 
146  myDoCloseConnection = false;
147 
148  // display warning if internal lanes are not used
150  WRITE_WARNING("Starting TraCI without using internal lanes!");
151  MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
152  MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
153  }
154 
155  if (!myAmEmbedded) {
156  try {
157  WRITE_MESSAGE("***Starting server on port " + toString(port) + " ***");
158  mySocket = new tcpip::Socket(port);
159  mySocket->accept();
160  // When got here, a client has connected
161  } catch (tcpip::SocketException& e) {
162  throw ProcessError(e.what());
163  }
164  }
165 }
166 
167 
170  if (mySocket != NULL) {
171  mySocket->close();
172  delete mySocket;
173  }
174  for (std::map<int, NamedRTree*>::const_iterator i = myObjects.begin(); i != myObjects.end(); ++i) {
175  delete(*i).second;
176  }
177  delete myLaneTree;
178 }
179 
180 
181 // ---------- Initialisation and Shutdown
182 void
183 TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
184  if (myInstance == 0) {
185  if (!myDoCloseConnection && OptionsCont::getOptions().getInt("remote-port") != 0) {
186  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
187  OptionsCont::getOptions().getInt("remote-port"));
188  for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
189  myInstance->myExecutors[i->first] = i->second;
190  }
191  }
192  }
193 }
194 
195 
196 void
198  if (myInstance != 0) {
199  delete myInstance;
200  myInstance = 0;
201  myDoCloseConnection = true;
202  }
203 }
204 
205 
206 bool
208  return myDoCloseConnection;
209 }
210 
211 
212 void
214  myVTDControlledVehicles[v->getID()] = v;
215  v->getInfluencer().setVTDControlled(true, l, pos, edgeOffset, route);
216 }
217 
218 void
220  for (std::map<std::string, MSVehicle*>::const_iterator i = myVTDControlledVehicles.begin(); i != myVTDControlledVehicles.end(); ++i) {
221  if (MSNet::getInstance()->getVehicleControl().getVehicle((*i).first) != 0) {
222  (*i).second->getInfluencer().postProcessVTD((*i).second);
223  } else {
224  WRITE_WARNING("Vehicle '" + (*i).first + "' was removed though being controlled by VTD");
225  }
226  }
227  myVTDControlledVehicles.clear();
228 }
229 
230 
231 bool
233  return true;
234 }
235 
236 
237 // ---------- Initialisation and Shutdown
238 
239 
240 void
242  if (!myDoCloseConnection) {
243  myVehicleStateChanges[to].push_back(vehicle->getID());
244  }
245 }
246 
247 
248 void
250  try {
251  if (myInstance == 0) {
252  if (!myDoCloseConnection && OptionsCont::getOptions().getInt("remote-port") != 0) {
253  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
254  OptionsCont::getOptions().getInt("remote-port"));
255  } else {
256  return;
257  }
258  }
259  if (myInstance->myAmEmbedded || step < myInstance->myTargetTime) {
260  return;
261  }
262  // Simulation should run until
263  // 1. end time reached or
264  // 2. got CMD_CLOSE or
265  // 3. Client closes socket connection
266  if (myInstance->myDoingSimStep) {
268  myInstance->myDoingSimStep = false;
269  }
270  while (!myDoCloseConnection) {
272  if (myInstance->myOutputStorage.size() > 0) {
273  // send out all answers as one storage
275  }
278  // Read a message
280  }
282  // dispatch each command
283  int cmd = myInstance->dispatchCommand();
284  if (cmd == CMD_SIMSTEP2) {
285  myInstance->myDoingSimStep = true;
286  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myInstance->myVehicleStateChanges.begin(); i != myInstance->myVehicleStateChanges.end(); ++i) {
287  (*i).second.clear();
288  }
289  return;
290  }
291  }
292  }
294  // send out all answers as one storage
296  }
297  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myInstance->myVehicleStateChanges.begin(); i != myInstance->myVehicleStateChanges.end(); ++i) {
298  (*i).second.clear();
299  }
300  } catch (std::invalid_argument& e) {
301  throw ProcessError(e.what());
302  } catch (TraCIException& e) {
303  throw ProcessError(e.what());
304  } catch (tcpip::SocketException& e) {
305  throw ProcessError(e.what());
306  }
307  if (myInstance != NULL) {
308  delete myInstance;
309  myInstance = 0;
310  myDoCloseConnection = true;
311  }
312 }
313 
314 
315 
316 
317 #ifdef HAVE_PYTHON
318 // ===========================================================================
319 // python functions (traciemb module)
320 // ===========================================================================
321 static PyObject*
322 traciemb_execute(PyObject* /* self */, PyObject* args) {
323  const char* msg;
324  int size;
325  if (!PyArg_ParseTuple(args, "s#", &msg, &size)) {
326  return NULL;
327  }
328  std::string result = TraCIServer::execute(std::string(msg, size));
329  return Py_BuildValue("s#", result.c_str(), result.size());
330 }
331 
332 static PyMethodDef EmbMethods[] = {
333  {
334  "execute", traciemb_execute, METH_VARARGS,
335  "Execute the given TraCI command and return the result."
336  },
337  {NULL, NULL, 0, NULL}
338 };
339 
340 
341 std::string
342 TraCIServer::execute(std::string cmd) {
343  try {
344  if (myInstance == 0) {
345  if (!myDoCloseConnection) {
346  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")));
347  } else {
348  return "";
349  }
350  }
353  for (std::string::iterator i = cmd.begin(); i != cmd.end(); ++i) {
355  }
357  return std::string(myInstance->myOutputStorage.begin(), myInstance->myOutputStorage.end());
358  } catch (std::invalid_argument& e) {
359  throw ProcessError(e.what());
360  } catch (TraCIException& e) {
361  throw ProcessError(e.what());
362  } catch (tcpip::SocketException& e) {
363  throw ProcessError(e.what());
364  }
365 }
366 
367 
368 void
369 TraCIServer::runEmbedded(std::string pyFile) {
370  PyObject* pName, *pModule;
371  Py_Initialize();
372  Py_InitModule("traciemb", EmbMethods);
373  if (pyFile.length() > 3 && !pyFile.compare(pyFile.length() - 3, 3, ".py")) {
374  PyObject* sys_path, *path;
375  char pathstr[] = "path";
376  sys_path = PySys_GetObject(pathstr);
377  if (sys_path == NULL || !PyList_Check(sys_path)) {
378  throw ProcessError("Could not access python sys.path!");
379  }
380  path = PyString_FromString(FileHelpers::getFilePath(pyFile).c_str());
381  PyList_Insert(sys_path, 0, path);
382  Py_DECREF(path);
383  FILE* pFile = fopen(pyFile.c_str(), "r");
384  if (pFile == NULL) {
385  throw ProcessError("Failed to load \"" + pyFile + "\"!");
386  }
387  PyRun_SimpleFile(pFile, pyFile.c_str());
388  fclose(pFile);
389  } else {
390  pName = PyString_FromString(pyFile.c_str());
391  /* Error checking of pName left out */
392  pModule = PyImport_Import(pName);
393  Py_DECREF(pName);
394  if (pModule == NULL) {
395  PyErr_Print();
396  throw ProcessError("Failed to load \"" + pyFile + "\"!");
397  }
398  }
399  Py_Finalize();
400 }
401 #endif
402 
403 
404 int
406  unsigned int commandStart = myInputStorage.position();
407  unsigned int commandLength = myInputStorage.readUnsignedByte();
408  if (commandLength == 0) {
409  commandLength = myInputStorage.readInt();
410  }
411 
412  int commandId = myInputStorage.readUnsignedByte();
413  bool success = false;
414  // dispatch commands
415  if (myExecutors.find(commandId) != myExecutors.end()) {
416  success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
417  } else {
418  switch (commandId) {
419  case CMD_GETVERSION:
420  success = commandGetVersion();
421  break;
422  case CMD_SIMSTEP2: {
423  SUMOTime nextT = myInputStorage.readInt();
424  success = true;
425  if (nextT != 0) {
426  myTargetTime = nextT;
427  } else {
429  }
430  if (myAmEmbedded) {
433  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myInstance->myVehicleStateChanges.begin(); i != myInstance->myVehicleStateChanges.end(); ++i) {
434  (*i).second.clear();
435  }
436  }
437  return commandId;
438  }
439  case CMD_CLOSE:
440  success = commandCloseConnection();
441  break;
455  success = addObjectVariableSubscription(commandId);
456  break;
470  success = addObjectContextSubscription(commandId);
471  break;
472  default:
473  writeStatusCmd(commandId, RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
474  }
475  }
476  if (!success) {
477  while (myInputStorage.valid_pos() && myInputStorage.position() < commandStart + commandLength) {
479  }
480  }
481  if (myInputStorage.position() != commandStart + commandLength) {
482  std::ostringstream msg;
483  msg << "Wrong position in requestMessage after dispatching command.";
484  msg << " Expected command length was " << commandLength;
485  msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
486  writeStatusCmd(commandId, RTYPE_ERR, msg.str());
487  myDoCloseConnection = true;
488  }
489  return commandId;
490 }
491 
492 
493 // ---------- Server-internal command handling
494 bool
496  std::string sumoVersion = VERSION_STRING;
497  // Prepare response
498  tcpip::Storage answerTmp;
499  answerTmp.writeInt(TRACI_VERSION);
500  answerTmp.writeString(std::string("SUMO ") + sumoVersion);
501  // When we get here, the response is stored in answerTmp -> put into myOutputStorage
503  // command length
504  myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
505  // command type
507  // and the parameter dependant part
508  myOutputStorage.writeStorage(answerTmp);
509  return true;
510 }
511 
512 
513 bool
515  myDoCloseConnection = true;
516  // write answer
518  return true;
519 }
520 
521 
522 void
526  int noActive = 0;
527  for (std::vector<Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
528  const Subscription& s = *i;
531  if ((s.endTime < t) || isArrivedVehicle) {
532  i = mySubscriptions.erase(i);
533  continue;
534  }
535  ++i;
536  if (s.beginTime > t) {
537  continue;
538  }
539  ++noActive;
540  }
541  myOutputStorage.writeInt(noActive);
542  for (std::vector<Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
543  const Subscription& s = *i;
544  if (s.beginTime > t) {
545  ++i;
546  continue;
547  }
548  tcpip::Storage into;
549  std::string errors;
550  bool ok = processSingleSubscription(s, into, errors);
552  if (ok) {
553  ++i;
554  } else {
555  i = mySubscriptions.erase(i);
556  }
557  }
558 }
559 
560 
561 void
562 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
563  writeStatusCmd(commandId, status, description, myOutputStorage);
564 }
565 
566 
567 void
568 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
569  if (status == RTYPE_ERR) {
570  WRITE_ERROR("Answered with error to command " + toString(commandId) + ": " + description);
571  } else if (status == RTYPE_NOTIMPLEMENTED) {
572  WRITE_ERROR("Requested command not implemented (" + toString(commandId) + "): " + description);
573  }
574  outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
575  outputStorage.writeUnsignedByte(commandId); // command type
576  outputStorage.writeUnsignedByte(status); // status
577  outputStorage.writeString(description); // description
578 }
579 
580 
581 bool
582 TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
583  writeStatusCmd(commandId, RTYPE_ERR, description, outputStorage);
584  return false;
585 }
586 
587 
588 void
590  tcpip::Storage writeInto;
591  std::string errors;
592  if (processSingleSubscription(s, writeInto, errors)) {
594  writeStatusCmd(s.commandId, RTYPE_ERR, "Subscription has ended.");
595  } else {
596  mySubscriptions.push_back(s);
598  }
599  } else {
600  writeStatusCmd(s.commandId, RTYPE_ERR, "Could not add subscription (" + errors + ").");
601  }
602  myOutputStorage.writeStorage(writeInto);
603 }
604 
605 
606 void
607 TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
608  bool found = false;
609  for (std::vector<Subscription>::iterator j = mySubscriptions.begin(); j != mySubscriptions.end();) {
610  if ((*j).id == id && (*j).commandId == commandId && (domain < 0 || (*j).contextDomain == domain)) {
611  j = mySubscriptions.erase(j);
612  found = true;
613  continue;
614  }
615  ++j;
616  }
617  // try unsubscribe
618  if (found) {
619  writeStatusCmd(commandId, RTYPE_OK, "");
620  } else {
621  writeStatusCmd(commandId, RTYPE_OK, "The subscription to remove was not found.");
622  }
623 }
624 
625 
626 bool
627 TraCIServer::findObjectShape(int domain, const std::string& id, PositionVector& shape) {
628  Position p;
629  switch (domain) {
632  shape.push_back(p);
633  return true;
634  }
635  break;
637  break;
639  break;
641  if (TraCIServerAPI_Lane::getShape(id, shape)) {
642  return true;
643  }
644  break;
647  shape.push_back(p);
648  return true;
649  }
650  break;
652  break;
654  break;
656  if (TraCIServerAPI_POI::getPosition(id, p)) {
657  shape.push_back(p);
658  return true;
659  }
660  return false;
662  if (TraCIServerAPI_Polygon::getShape(id, shape)) {
663  return true;
664  }
665  break;
668  shape.push_back(p);
669  return true;
670  }
671  break;
673  if (TraCIServerAPI_Edge::getShape(id, shape)) {
674  return true;
675  }
676  break;
678  return false;
680  break;
681  default:
682  break;
683  }
684  return false;
685 }
686 
687 void
688 TraCIServer::collectObjectsInRange(int domain, const PositionVector& shape, SUMOReal range, std::set<std::string>& into) {
689  // build the look-up tree if not yet existing
690  if (myObjects.find(domain) == myObjects.end()) {
691  switch (domain) {
694  break;
703  break;
706  break;
709  break;
712  break;
713  default:
714  break;
715  }
716  }
717  const Boundary b = shape.getBoxBoundary().grow(range);
718  const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
719  const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
720  switch (domain) {
725  Named::StoringVisitor sv(into);
726  myObjects[domain]->Search(cmin, cmax, sv);
727  }
728  break;
732  TraCIServerAPI_Lane::StoringVisitor sv(into, shape, range, domain);
733  myLaneTree->Search(cmin, cmax, sv);
734  }
735  break;
736  default:
737  break;
738  }
739 }
740 
741 
742 bool
744  std::string& errors) {
745  bool ok = true;
746  tcpip::Storage outputStorage;
747  const int getCommandId = s.contextVars ? s.contextDomain : s.commandId - 0x30;
748  std::set<std::string> objIDs;
749  if (s.contextVars) {
750  PositionVector shape;
751  if (!findObjectShape(s.commandId, s.id, shape)) {
752  return false;
753  }
754  collectObjectsInRange(s.contextDomain, shape, s.range, objIDs);
755  } else {
756  objIDs.insert(s.id);
757  }
758  const int numVars = s.contextVars && s.variables.size() == 1 && s.variables[0] == ID_LIST ? 0 : (int)s.variables.size();
759  for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
760  if (s.contextVars) {
761  outputStorage.writeString(*j);
762  }
763  if (numVars > 0) {
764  for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i) {
765  tcpip::Storage message;
766  message.writeUnsignedByte(*i);
767  message.writeString(*j);
768  tcpip::Storage tmpOutput;
769  if (myExecutors.find(getCommandId) != myExecutors.end()) {
770  ok &= myExecutors[getCommandId](*this, message, tmpOutput);
771  } else {
772  writeStatusCmd(s.commandId, RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
773  ok = false;
774  }
775  // copy response part
776  if (ok) {
777  int length = tmpOutput.readUnsignedByte();
778  while (--length > 0) {
779  tmpOutput.readUnsignedByte();
780  }
781  int lengthLength = 1;
782  length = tmpOutput.readUnsignedByte();
783  if (length == 0) {
784  lengthLength = 5;
785  length = tmpOutput.readInt();
786  }
787  //read responseType
788  tmpOutput.readUnsignedByte();
789  int variable = tmpOutput.readUnsignedByte();
790  std::string id = tmpOutput.readString();
791  outputStorage.writeUnsignedByte(variable);
792  outputStorage.writeUnsignedByte(RTYPE_OK);
793  length -= (lengthLength + 1 + 4 + (int)id.length());
794  while (--length > 0) {
795  outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
796  }
797  } else {
798  //read length
799  tmpOutput.readUnsignedByte();
800  //read cmd
801  tmpOutput.readUnsignedByte();
802  //read status
803  tmpOutput.readUnsignedByte();
804  std::string msg = tmpOutput.readString();
805  outputStorage.writeUnsignedByte(*i);
806  outputStorage.writeUnsignedByte(RTYPE_ERR);
807  outputStorage.writeUnsignedByte(TYPE_STRING);
808  outputStorage.writeString(msg);
809  errors = errors + msg;
810  }
811  }
812  }
813  }
814  unsigned int length = (1 + 4) + 1 + (4 + (int)(s.id.length())) + 1 + (int)outputStorage.size();
815  if (s.contextVars) {
816  length += 4;
817  }
818  writeInto.writeUnsignedByte(0); // command length -> extended
819  writeInto.writeInt(length);
820  writeInto.writeUnsignedByte(s.commandId + 0x10);
821  writeInto.writeString(s.id);
822  if (s.contextVars) {
823  writeInto.writeUnsignedByte(s.contextDomain);
824  }
825  writeInto.writeUnsignedByte(numVars);
826  if (s.contextVars) {
827  writeInto.writeInt((int)objIDs.size());
828  }
829  if (!s.contextVars || objIDs.size() != 0) {
830  writeInto.writeStorage(outputStorage);
831  }
832  return ok;
833 }
834 
835 
836 bool
838  SUMOTime beginTime = myInputStorage.readInt();
839  SUMOTime endTime = myInputStorage.readInt();
840  std::string id = myInputStorage.readString();
841  int no = myInputStorage.readUnsignedByte();
842  std::vector<int> variables;
843  for (int i = 0; i < no; ++i) {
844  variables.push_back(myInputStorage.readUnsignedByte());
845  }
846  // check subscribe/unsubscribe
847  if (variables.size() == 0) {
848  removeSubscription(commandId, id, -1);
849  return true;
850  }
851  // process subscription
852  Subscription s(commandId, id, variables, beginTime, endTime, false, 0, 0);
854  return true;
855 }
856 
857 
858 bool
860  SUMOTime beginTime = myInputStorage.readInt();
861  SUMOTime endTime = myInputStorage.readInt();
862  std::string id = myInputStorage.readString();
863  int domain = myInputStorage.readUnsignedByte();
865  int no = myInputStorage.readUnsignedByte();
866  std::vector<int> variables;
867  for (int i = 0; i < no; ++i) {
868  variables.push_back(myInputStorage.readUnsignedByte());
869  }
870  // check subscribe/unsubscribe
871  if (variables.size() == 0) {
872  removeSubscription(commandId, id, -1);
873  return true;
874  }
875  Subscription s(commandId, id, variables, beginTime, endTime, true, domain, range);
877  return true;
878 }
879 
880 
881 void
883  if (tempMsg.size() < 254) {
884  outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
885  } else {
886  outputStorage.writeUnsignedByte(0); // command length -> extended
887  outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
888  }
889  outputStorage.writeStorage(tempMsg);
890 }
891 
892 
893 bool
895  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
896  return false;
897  }
898  into = inputStorage.readInt();
899  return true;
900 }
901 
902 
903 bool
905  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
906  return false;
907  }
908  into = inputStorage.readDouble();
909  return true;
910 }
911 
912 
913 bool
914 TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
915  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
916  return false;
917  }
918  into = inputStorage.readString();
919  return true;
920 }
921 
922 
923 bool
924 TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
925  if (inputStorage.readUnsignedByte() != TYPE_STRINGLIST) {
926  return false;
927  }
928  into = inputStorage.readStringList();
929  return true;
930 }
931 
932 
933 bool
935  if (inputStorage.readUnsignedByte() != TYPE_COLOR) {
936  return false;
937  }
938  unsigned char r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
939  unsigned char g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
940  unsigned char b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
941  unsigned char a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
942  into.set(r, g, b, a);
943  return true;
944 }
945 
946 
947 bool
949  if (inputStorage.readUnsignedByte() != POSITION_2D) {
950  return false;
951  }
952  SUMOReal x = inputStorage.readDouble();
953  SUMOReal y = inputStorage.readDouble();
954  into.set(x, y, 0);
955  return true;
956 }
957 
958 
959 bool
961  if (inputStorage.readUnsignedByte() != TYPE_BOUNDINGBOX) {
962  return false;
963  }
964  const SUMOReal xmin = inputStorage.readDouble();
965  const SUMOReal ymin = inputStorage.readDouble();
966  const SUMOReal xmax = inputStorage.readDouble();
967  const SUMOReal ymax = inputStorage.readDouble();
968  into.set(xmin, ymin, xmax, ymax);
969  return true;
970 }
971 
972 
973 bool
975  if (inputStorage.readUnsignedByte() != TYPE_BYTE) {
976  return false;
977  }
978  into = inputStorage.readByte();
979  return true;
980 }
981 
982 
983 bool
985  if (inputStorage.readUnsignedByte() != TYPE_UBYTE) {
986  return false;
987  }
988  into = inputStorage.readUnsignedByte();
989  return true;
990 }
991 
992 
993 bool
995  if (inputStorage.readUnsignedByte() != TYPE_POLYGON) {
996  return false;
997  }
998  into.clear();
999  unsigned int noEntries = inputStorage.readUnsignedByte();
1000  PositionVector shape;
1001  for (unsigned int i = 0; i < noEntries; ++i) {
1002  SUMOReal x = inputStorage.readDouble();
1003  SUMOReal y = inputStorage.readDouble();
1004  into.push_back(Position(x, y));
1005  }
1006  return true;
1007 }
1008 
1009 #endif
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa3: Get Lane Variable)
bool processSingleSubscription(const TraCIServer::Subscription &s, tcpip::Storage &writeInto, std::string &errors)
The vehicle has departed (was inserted into the network)
Definition: MSNet.h:411
bool myDoingSimStep
Whether a step is currently done.
Definition: TraCIServer.h:320
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:71
tcpip::Socket * mySocket
The socket on which server is listening on.
Definition: TraCIServer.h:307
#define CMD_SUBSCRIBE_VEHICLE_CONTEXT
#define CMD_SUBSCRIBE_LANE_VARIABLE
bool findObjectShape(int domain, const std::string &id, PositionVector &shape)
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
bool contextVars
Whether the subscription is a context subscription (variable subscription otherwise) ...
Definition: TraCIServer.h:362
#define CMD_GET_TL_VARIABLE
void collectObjectsInRange(int domain, const PositionVector &shape, SUMOReal range, std::set< std::string > &into)
#define CMD_SUBSCRIBE_JUNCTION_CONTEXT
void removeVehicleStateListener(VehicleStateListener *listener)
Removes a vehicle states listener.
Definition: MSNet.cpp:659
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc3: Change Lane State)
#define CMD_GET_VEHICLE_VARIABLE
virtual ~TraCIServer()
Destructor.
#define CMD_SUBSCRIBE_SIM_CONTEXT
virtual int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const CONTEXT &c) const
DK 15.10.2008 - begin.
bool commandGetVersion()
Returns the TraCI-version.
#define CMD_SUBSCRIBE_VEHICLETYPE_CONTEXT
#define CMD_CLOSE
virtual std::vector< std::string > readStringList()
#define POSITION_2D
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc4: Change Vehicle State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc7: Change PoI State)
bool receiveExact(Storage &)
Receive a complete TraCI message from Socket::socket_.
#define CMD_GET_INDUCTIONLOOP_VARIABLE
bool readTypeCheckingColor(tcpip::Storage &inputStorage, RGBColor &into)
Reads the value type and a color, verifying the type.
static NamedRTree * getTree()
Returns a tree filled with junction instances.
static NamedRTree * getTree()
Returns a tree filled with polygon instances.
SUMOReal ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:124
#define CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE
static void fill(RTREE &into)
Fills the given RTree with lane instances.
Definition: MSLane.cpp:852
virtual unsigned int position() const
#define TYPE_UBYTE
#define RTYPE_OK
SUMOTime beginTime
The begin time of the subscription.
Definition: TraCIServer.h:358
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa9: Get Junction Variable)
virtual double readDouble()
tcpip::Storage myOutputStorage
The storage to writeto.
Definition: TraCIServer.h:316
#define TYPE_POLYGON
void accept()
Wait for a incoming connection to port_.
SUMOReal xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:112
StorageType::size_type size() const
Definition: storage.h:115
#define TRACI_VERSION
static bool getPosition(const std::string &id, Position &p)
Returns the named vehicle&#39;s position.
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xab: Get Simulation Variable)
bool readTypeCheckingInt(tcpip::Storage &inputStorage, int &into)
Reads the value type and an int, verifying the type.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:150
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Route State)
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
#define TYPE_COLOR
#define TYPE_STRINGLIST
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
virtual bool valid_pos()
#define CMD_SUBSCRIBE_POLYGON_CONTEXT
tcpip::Storage myInputStorage
The storage to read from.
Definition: TraCIServer.h:313
#define CMD_GET_POLYGON_VARIABLE
#define CMD_SUBSCRIBE_JUNCTION_VARIABLE
Representation of a subscription.
Definition: TraCIServer.h:334
#define CMD_SUBSCRIBE_ROUTE_CONTEXT
bool readTypeCheckingPolygon(tcpip::Storage &inputStorage, PositionVector &into)
Reads the value type and a polygon, verifying the type.
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xca: Change Edge State)
virtual void writeUnsignedByte(int)
#define CMD_SET_EDGE_VARIABLE
SUMOTime getCurrentTimeStep() const
Returns the current simulation step (in s)
Definition: MSNet.cpp:502
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
#define CMD_SUBSCRIBE_EDGE_VARIABLE
virtual unsigned char readChar()
SUMOReal xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:118
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:651
#define CMD_GET_ROUTE_VARIABLE
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
#define CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
virtual void writeInt(int)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
#define TYPE_STRING
virtual int readUnsignedByte()
virtual void writeChar(unsigned char)
#define CMD_SUBSCRIBE_POI_VARIABLE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa4: Get Vehicle Variable)
static bool getPosition(const std::string &id, Position &p)
Returns the named inductive loop&#39;s position.
static bool myDoCloseConnection
Whether the connection was set to be to close.
Definition: TraCIServer.h:304
void postProcessVTD()
The vehicles starts to stop.
Definition: MSNet.h:425
std::map< int, CmdExecutor > myExecutors
Map of commandIds -&gt; their executors; applicable if the executor applies to the method footprint...
Definition: TraCIServer.h:326
#define CMD_SET_TL_VARIABLE
void set(SUMOReal xmin, SUMOReal ymin, SUMOReal xmax, SUMOReal ymax)
Sets the boundary to the given values.
Definition: Boundary.cpp:240
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to)
Called if a vehicle changes its state.
bool readTypeCheckingBoundary(tcpip::Storage &inputStorage, Boundary &into)
Reads the value type and a 2D bounding box, verifying the type.
static NamedRTree * getTree()
Returns a tree filled with PoI instances.
#define CMD_SUBSCRIBE_LANE_CONTEXT
#define CMD_SUBSCRIBE_SIM_VARIABLE
void removeSubscription(int commandId, const std::string &identity, int domain)
#define CMD_GET_VEHICLETYPE_VARIABLE
static void close()
request termination of connection
#define CMD_SET_ROUTE_VARIABLE
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcb: Set Simulation Variable)
#define CMD_GETVERSION
#define CMD_GET_AREAL_DETECTOR_VARIABLE
#define CMD_SUBSCRIBE_GUI_CONTEXT
Allows to store the object; used as context while traveling the rtree in TraCI.
The vehicle got a new route.
Definition: MSNet.h:419
The vehicle arrived at his destination (is deleted)
Definition: MSNet.h:417
StorageType::const_iterator end() const
Definition: storage.h:118
The vehicles starts to park.
Definition: MSNet.h:421
int commandId
commandIdArg The command id of the subscription
Definition: TraCIServer.h:352
std::vector< Subscription > mySubscriptions
The list of known, still valid subscriptions.
Definition: TraCIServer.h:371
Representation of a vehicle.
Definition: SUMOVehicle.h:63
SUMOReal range
The range of the context.
Definition: TraCIServer.h:366
virtual int readInt()
bool commandCloseConnection()
Indicates the connection as being closed.
std::vector< const MSEdge * > MSEdgeVector
Definition: MSPerson.h:53
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
std::string id
The id of the object that is subscribed.
Definition: TraCIServer.h:354
#define CMD_GET_POI_VARIABLE
void set(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
assigns new values
Definition: RGBColor.cpp:85
A list of positions.
std::vector< int > variables
The subscribed variables.
Definition: TraCIServer.h:356
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:253
#define CMD_SET_VEHICLETYPE_VARIABLE
#define CMD_SUBSCRIBE_MULTI_ENTRY_EXIT_DETECTOR_VARIABLE
#define TYPE_BOUNDINGBOX
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
void setVTDControlled(bool c, MSLane *l, SUMOReal pos, int edgeOffset, const MSEdgeVector &route)
Definition: MSVehicle.h:901
#define CMD_SUBSCRIBE_GUI_VARIABLE
#define CMD_GET_LANE_VARIABLE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa5: Get Vehicle Type Variable)
#define CMD_SET_VEHICLE_VARIABLE
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:48
void postProcessSimulationStep2()
Handles subscriptions to send after a simstep2 command.
The vehicle started to teleport.
Definition: MSNet.h:413
RTree< MSLane *, MSLane, float, 2, TraCIServerAPI_Lane::StoringVisitor > * myLaneTree
A storage of lanes.
Definition: TraCIServer.h:380
#define CMD_GET_SIM_VARIABLE
virtual std::string readString()
void setVTDControlled(MSVehicle *v, MSLane *l, SUMOReal pos, int edgeOffset, MSEdgeVector route)
#define CMD_GET_EDGE_VARIABLE
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:70
#define CMD_SET_POI_VARIABLE
#define CMD_SUBSCRIBE_POLYGON_VARIABLE
static TraCIServer * myInstance
Singleton instance of the server.
Definition: TraCIServer.h:301
static bool getPosition(const std::string &id, Position &p)
Returns the named PoI&#39;s position.
TraCIServer(const SUMOTime begin, const int port=0)
Constructor.
#define CMD_SUBSCRIBE_TL_CONTEXT
The vehicle ends to park.
Definition: MSNet.h:423
#define CMD_SUBSCRIBE_EDGE_CONTEXT
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa0: Get Induction Loop Variable)
#define CMD_GET_JUNCTION_VARIABLE
bool addObjectVariableSubscription(int commandId)
bool readTypeCheckingUnsignedByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and an unsigned byte, verifying the type.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:51
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:74
virtual void writeStorage(tcpip::Storage &store)
#define CMD_SET_SIM_VARIABLE
#define CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
#define VERSION_STRING
Definition: config.h:227
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:407
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa7: Get PoI Variable)
const bool myAmEmbedded
Whether the server runs in embedded mode.
Definition: TraCIServer.h:323
bool readTypeCheckingPosition2D(tcpip::Storage &inputStorage, Position &into)
Reads the value type and a 2D position, verifying the type.
The vehicle was built, but has not yet departed.
Definition: MSNet.h:409
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:201
static void processCommandsUntilSimStep(SUMOTime step)
process all commands until a simulation step is wanted
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc5: Change Vehicle Type State)
void push_back(const PositionVector &p)
Appends all positions from the given vector.
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:85
#define CMD_SET_POLYGON_VARIABLE
static void openSocket(const std::map< int, CmdExecutor > &execs)
Initialises the server.
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:200
static bool getShape(const std::string &id, PositionVector &shape)
Returns the named edge&#39;s shape.
virtual void writeString(const std::string &s)
#define RTYPE_NOTIMPLEMENTED
Influencer & getInfluencer()
Returns the velocity/lane influencer.
Definition: MSVehicle.cpp:2187
#define CMD_GET_MULTI_ENTRY_EXIT_DETECTOR_VARIABLE
virtual const char * what() const
Definition: socket.h:70
#define TYPE_DOUBLE
static bool getPosition(const std::string &id, Position &p)
Returns the named junction&#39;s position.
#define CMD_SUBSCRIBE_VEHICLE_VARIABLE
void sendExact(const Storage &)
#define TYPE_BYTE
#define CMD_SET_LANE_VARIABLE
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:89
void set(SUMOReal x, SUMOReal y)
Definition: Position.h:78
SUMOTime myTargetTime
The time step to reach until processing the next commands.
Definition: TraCIServer.h:310
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get Route Variable)
static NamedRTree * getTree()
Returns a tree filled with inductive loop instances.
The vehicle ends to stop.
Definition: MSNet.h:427
std::map< int, NamedRTree * > myObjects
A storage of objects.
Definition: TraCIServer.h:377
StorageType::const_iterator begin() const
Definition: storage.h:117
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
std::map< std::string, MSVehicle * > myVTDControlledVehicles
Definition: TraCIServer.h:328
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa8: Get Polygon Variable)
int dispatchCommand()
#define CMD_SUBSCRIBE_MULTI_ENTRY_EXIT_DETECTOR_CONTEXT
void visit(const TraCIServerAPI_Lane::StoringVisitor &cont) const
Callback for visiting the lane when traversing an RTree.
Definition: MSLane.h:726
#define CMD_SUBSCRIBE_TL_VARIABLE
#define SUMOReal
Definition: config.h:215
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc2: Change Traffic Lights State)
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
SUMOReal ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:130
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
Definition: FileHelpers.cpp:75
#define DELTA_T
Definition: SUMOTime.h:50
void simulationStep()
Performs a single simulation step.
Definition: MSNet.cpp:349
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get MeMeDetector Variable)
bool vtdDebug() const
int contextDomain
The domain ID of the context.
Definition: TraCIServer.h:364
bool addObjectContextSubscription(int commandId)
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:197
#define RTYPE_ERR
void initialiseSubscription(const Subscription &s)
#define TYPE_INTEGER
#define CMD_SIMSTEP2
#define ID_LIST
#define CMD_SUBSCRIBE_POI_CONTEXT
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xaa: Get Edge Variable)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
static bool wasClosed()
check whether close was requested
std::map< MSNet::VehicleState, std::vector< std::string > > myVehicleStateChanges
Changes in the states of simulated vehicles.
Definition: TraCIServer.h:374
The vehicle ended being teleported.
Definition: MSNet.h:415
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
virtual int readByte()
static bool getShape(const std::string &id, PositionVector &shape)
Returns the named polygons&#39;s shape.
bool readTypeCheckingByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and a byte, verifying the type.
void close()
Definition: socket.cpp:347
SUMOTime endTime
The end time of the subscription.
Definition: TraCIServer.h:360
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa2: Get Traffic Lights Variable)
#define CMD_SUBSCRIBE_ROUTE_VARIABLE
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc8: Change Polygon State)
static bool getShape(const std::string &id, PositionVector &shape)
Returns the named lane&#39;s shape.
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get AreaDetector Variable)
const std::string & getID() const
Returns the name of the vehicle.