SUMO - Simulation of Urban MObility
TraCIServer.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2007-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
25 // TraCI server used to control sumo by a remote TraCI client (e.g., ns2)
26 /****************************************************************************/
27 
28 // ===========================================================================
29 // included modules
30 // ===========================================================================
31 #include <config.h>
32 
33 #ifdef HAVE_VERSION_H
34 #include <version.h>
35 #endif
36 
37 #ifdef HAVE_PYTHON
38 #include <Python.h>
39 #endif
40 
41 #include <string>
42 #include <cmath>
43 #include <map>
44 #include <iostream>
45 #include <algorithm>
46 #include <foreign/tcpip/socket.h>
47 #include <foreign/tcpip/storage.h>
48 #include <utils/common/SUMOTime.h>
56 #include <utils/xml/XMLSubSys.h>
57 #include <microsim/MSNet.h>
58 #include <microsim/MSVehicle.h>
59 #include <microsim/MSEdge.h>
62 #include <microsim/MSJunction.h>
63 #include <microsim/MSEdgeControl.h>
64 #include <microsim/MSLane.h>
65 #include <microsim/MSGlobals.h>
67 #include <libsumo/Simulation.h>
68 #include <libsumo/Subscription.h>
69 #include "TraCIConstants.h"
70 #include "TraCIServer.h"
73 #include "TraCIServerAPI_Lane.h"
77 #include "TraCIServerAPI_Vehicle.h"
79 #include "TraCIServerAPI_Route.h"
80 #include "TraCIServerAPI_POI.h"
81 #include "TraCIServerAPI_Polygon.h"
82 #include "TraCIServerAPI_Edge.h"
84 #include "TraCIServerAPI_Person.h"
85 
86 
87 // ===========================================================================
88 // debug constants
89 // ===========================================================================
90 //#define DEBUG_MULTI_CLIENTS
91 //#define DEBUG_SUBSCRIPTIONS
92 //#define DEBUG_SUBSCRIPTION_FILTERS
93 
94 
95 // ===========================================================================
96 // static member definitions
97 // ===========================================================================
100 
101 
102 // ===========================================================================
103 // method definitions
104 // ===========================================================================
105 void
106 TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
111 }
112 
113 
114 bool
115 TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
118  return true;
119 }
120 
121 
122 bool
123 TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
125  myWrapperStorage.writeInt(value);
126  return true;
127 }
128 
129 
130 bool
131 TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
134  return true;
135 }
136 
137 
138 bool
139 TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
142  return true;
143 }
144 
145 
146 bool
147 TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
148  const bool includeZ = variable == VAR_POSITION3D;
152  if (includeZ) {
154  }
155  return true;
156 }
157 
158 
159 bool
160 TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
166  return true;
167 }
168 
169 
172  return myWrapperStorage;
173 }
174 
175 
176 
177 TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
178  : myServerSocket(nullptr), myTargetTime(begin), myAmEmbedded(port == 0), myLastContextSubscription(nullptr) {
179 #ifdef DEBUG_MULTI_CLIENTS
180  std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
181 #endif
182  myVehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>();
183  myVehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>();
184  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>();
185  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>();
186  myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>();
187  myVehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>();
188  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_PARKING] = std::vector<std::string>();
189  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_PARKING] = std::vector<std::string>();
190  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_STOP] = std::vector<std::string>();
191  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_STOP] = std::vector<std::string>();
192  myVehicleStateChanges[MSNet::VEHICLE_STATE_COLLISION] = std::vector<std::string>();
193  myVehicleStateChanges[MSNet::VEHICLE_STATE_EMERGENCYSTOP] = std::vector<std::string>();
194 
198 
220 
222 
223  myDoCloseConnection = false;
224 
225  // display warning if internal lanes are not used
227  WRITE_WARNING("Starting TraCI without using internal lanes!");
228  MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
229  MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
230  }
231 
232  if (!myAmEmbedded) {
233  try {
234  WRITE_MESSAGE("***Starting server on port " + toString(port) + " ***");
235  myServerSocket = new tcpip::Socket(port);
236  while ((int)mySockets.size() < numClients) {
237  int index = (int)mySockets.size() + MAX_ORDER + 1;
238  mySockets[index] = new SocketInfo(myServerSocket->accept(true), begin);
239  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>();
240  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>();
241  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>();
242  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>();
243  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>();
244  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>();
245  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_PARKING] = std::vector<std::string>();
246  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_PARKING] = std::vector<std::string>();
247  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_STOP] = std::vector<std::string>();
248  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_STOP] = std::vector<std::string>();
249  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_COLLISION] = std::vector<std::string>();
250  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_EMERGENCYSTOP] = std::vector<std::string>();
251  }
252  // When got here, all clients have connected
253  if (numClients > 1) {
255  }
256  // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommandsUntilSimStep()
257  myCurrentSocket = mySockets.begin();
258  } catch (tcpip::SocketException& e) {
259  throw ProcessError(e.what());
260  }
261  }
262 }
263 
264 
266  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
267  delete myCurrentSocket->second;
268  }
269  delete myServerSocket;
270  cleanup();
271 }
272 
273 
274 // ---------- Initialisation and Shutdown
275 void
276 TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
277  if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0
278 #ifdef HAVE_PYTHON
279  || OptionsCont::getOptions().isSet("python-script")
280 #endif
281  )) {
282  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
283  OptionsCont::getOptions().getInt("remote-port"),
284  OptionsCont::getOptions().getInt("num-clients"));
285  for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
286  myInstance->myExecutors[i->first] = i->second;
287  }
288  }
289  if (myInstance != nullptr) {
290  // maybe net was deleted and built again
293  }
294 }
295 
296 
297 void
299  if (myInstance == nullptr) {
300  return;
301  }
302  delete myInstance;
303  myInstance = nullptr;
304  myDoCloseConnection = true;
305 }
306 
307 
308 bool
310  return myDoCloseConnection;
311 }
312 
313 
314 // ---------- Initialisation and Shutdown
315 
316 
317 void
318 TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
319  if (!myDoCloseConnection) {
320  myVehicleStateChanges[to].push_back(vehicle->getID());
321  if (!myAmEmbedded) {
322  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
323  i->second->vehicleStateChanges[to].push_back(vehicle->getID());
324  }
325  }
326  }
327 }
328 
329 
330 void
332 #ifdef DEBUG_MULTI_CLIENTS
333  std::cout << "Checking client order requests." << std::endl;
334 #endif
335  // check for SET_ORDER commands queued by connected clients
336  // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
337  myCurrentSocket = mySockets.begin();
338  while (myCurrentSocket != mySockets.end()) {
339 #ifdef DEBUG_MULTI_CLIENTS
340  std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
341 #endif
342 // bool clientUnordered = true;
343 #ifdef _MSC_VER
344 #pragma warning(push)
345 #pragma warning(disable: 4127) // do not warn about constant conditional expression
346 #endif
347  while (true) {
348 #ifdef _MSC_VER
349 #pragma warning(pop)
350 #endif
352  myCurrentSocket->second->socket->receiveExact(myInputStorage);
353  int commandStart, commandLength;
354  int commandId = readCommandID(commandStart, commandLength);
355 #ifdef DEBUG_MULTI_CLIENTS
356  std::cout << " received command " << commandId << std::endl;
357 #endif
358  // Whether the received command is a permitted command for the initialization phase.
359  // Currently, getVersion and setOrder are permitted.
360  bool initCommand = commandId == CMD_SETORDER || commandId == CMD_GETVERSION;
361  if (initCommand) {
362 #ifdef DEBUG_MULTI_CLIENTS
363  std::cout << " Init command. Sending response." << std::endl;
364 #endif
365  // reset input storage to initial state before reading the commandId
366  // (ugly, but we can't just reset the store's iter_ from here)
367  // Giving the commandId to dispatch command didn't work either
368  tcpip::Storage tmp;
371  myInputStorage.writeUnsignedByte(commandLength);
374 
375  // Handle initialization command completely
376  dispatchCommand();
377  myCurrentSocket->second->socket->sendExact(myOutputStorage);
379  } else {
380 #ifdef DEBUG_MULTI_CLIENTS
381  std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
382 #endif
383  throw ProcessError("Execution order (CMD_SETORDER) was not set for all TraCI clients in pre-execution phase.");
384  }
385  if (commandId == CMD_SETORDER) {
386  // This is what we have waited for.
387  break;
388  }
389  }
390  ++myCurrentSocket;
391  }
392 }
393 
394 
395 void
397  // Process reordering requests
398  if (mySocketReorderRequests.size() > 0) {
399  // process reordering requests
400  std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
401  std::map<int, SocketInfo*>::iterator j;
402 #ifdef DEBUG_MULTI_CLIENTS
403  std::cout << SIMTIME << " Current socket ordering:\n";
404  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
405  std::cout << " " << j->first << ": " << j->second->socket << "\n";
406  }
407  std::cout << "Reordering requests:\n";
408  for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
409  std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
410  }
411  i = mySocketReorderRequests.begin();
412 #endif
413  while (i != mySocketReorderRequests.end()) {
414  j = mySockets.begin();
415  while (j != mySockets.end()) {
416  if (j->second->socket == i->second->socket) {
417  break;
418  } else {
419  j++;
420  }
421  }
422  assert(j != mySockets.end());
423  mySockets.erase(j);
424  mySockets[i->first] = i->second;
425  ++i;
426  }
427  mySocketReorderRequests.clear();
428 #ifdef DEBUG_MULTI_CLIENTS
429  std::cout << "New socket ordering:\n";
430  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
431  std::cout << " " << j->first << ": " << j->second->socket << "\n";
432  }
433  std::cout << std::endl;
434 #endif
435  }
436 }
437 
438 
439 SUMOTime
441 #ifdef DEBUG_MULTI_CLIENTS
442  std::cout << "\n Determining new target time..." << std::endl;
443  if (mySockets.size() == 0) {
444  std::cout << " All clients have disconnected." << std::endl;
445  }
446 #endif
447  std::map<int, SocketInfo*>::const_iterator i;
448  SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
449  for (i = mySockets.begin(); i != mySockets.end(); ++i) {
450 #ifdef DEBUG_MULTI_CLIENTS
451  std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
452 #endif
453  targetTime = MIN2(targetTime, i->second->targetTime);
454  }
455 #ifdef DEBUG_MULTI_CLIENTS
456  std::cout << std::endl;
457 #endif
458  return targetTime;
459 }
460 
461 
462 // send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
463 void
465 #ifdef DEBUG_MULTI_CLIENTS
466  std::cout << "\n Sending subscription results to clients:\n";
467 #endif
468  std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
469  while (i != mySockets.end()) {
470  if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
471  // this client will become active before the next SUMO step. Provide subscription results.
472  i->second->socket->sendExact(myOutputStorage);
473 #ifdef DEBUG_MULTI_CLIENTS
474  std::cout << i->second->socket << "\n";
475 #endif
476  }
477  ++i;
478  }
479 #ifdef DEBUG_MULTI_CLIENTS
480  std::cout << std::endl;
481 #endif
482 }
483 
484 
485 void
487 #ifdef DEBUG_MULTI_CLIENTS
488  std::cout << SIMTIME << " processCommandsUntilSimStep(step = " << step << "):\n" << std::endl;
489 #endif
490  try {
491  const bool firstStep = myCurrentSocket != mySockets.end();
492  // update client order if requested
494  if (!firstStep) {
495  // This is the entry point after performing a SUMO step (block is skipped before first SUMO step since then no simulation results have to be sent)
496  // update subscription results
498  // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
499  sendOutputToAll();
501  }
502 
503  // determine minimal next target time among clients
505 
506  if (myAmEmbedded || step < myTargetTime) {
507 #ifdef DEBUG_MULTI_CLIENTS
508  if (step < myTargetTime) {
509  std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommandsUntilSimStep()." << std::endl;
510  }
511 #endif
512  return;
513  }
514 
515  // Simulation should run until
516  // 1. end time reached or
517  // 2. got CMD_CLOSE or
518  // 3. got CMD_LOAD or
519  // 4. Client closes socket connection
520  while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep())) {
521 #ifdef DEBUG_MULTI_CLIENTS
522  std::cout << " Next target time: " << myTargetTime << std::endl;
523 #endif
524  // Iterate over clients and process communication for the ones with target time == myTargetTime
525  myCurrentSocket = mySockets.begin();
526  while (myCurrentSocket != mySockets.end()) {
527 #ifdef DEBUG_MULTI_CLIENTS
528  std::cout << " current socket: " << myCurrentSocket->second->socket
529  << " with target time " << myCurrentSocket->second->targetTime
530  << std::endl;
531 #endif
532 
533  if (myCurrentSocket->second->targetTime > myTargetTime) {
534  // this client must wait
535 #ifdef DEBUG_MULTI_CLIENTS
536  std::cout << " skipping client " << myCurrentSocket->second->socket
537  << " with target time " << myCurrentSocket->second->targetTime << std::endl;
538 #endif
539  myCurrentSocket++;
540  continue;
541  }
542  bool done = false;
543  bool closed = false;
544  bool load = false;
545  while (!done && !closed && !load) {
546  if (!myInputStorage.valid_pos()) {
547  // have read request completely, send response if adequate
548  if (myOutputStorage.size() > 0) {
549 #ifdef DEBUG_MULTI_CLIENTS
550  std::cout << " sending response..." << std::endl;
551 #endif
552  // send response to previous query
553  myCurrentSocket->second->socket->sendExact(myOutputStorage);
555  } else {
556 #ifdef DEBUG_MULTI_CLIENTS
557  std::cout << " No input and no output stored (This is the next client)." << std::endl;
558 #endif
559  }
560 #ifdef DEBUG_MULTI_CLIENTS
561  std::cout << " resetting input storage and reading next command..." << std::endl;
562 #endif
563  // Read next request
565  myCurrentSocket->second->socket->receiveExact(myInputStorage);
566  }
567 
569  // dispatch command
570  const int cmd = dispatchCommand();
571 #ifdef DEBUG_MULTI_CLIENTS
572  std::cout << " Received command " << cmd << std::endl;
573 #endif
574  if (cmd == CMD_SIMSTEP) {
575 #ifdef DEBUG_MULTI_CLIENTS
576  std::cout << " Received command SIM_STEP, end turn for client " << myCurrentSocket->second->socket << std::endl;
577 #endif
578  done = true;
579  } else if (cmd == CMD_LOAD) {
580 #ifdef DEBUG_MULTI_CLIENTS
581  std::cout << " Received command LOAD." << std::endl;
582 #endif
583  load = true;
584  } else if (cmd == CMD_CLOSE) {
585 #ifdef DEBUG_MULTI_CLIENTS
586  std::cout << " Received command CLOSE." << std::endl;
587 #endif
588  closed = true;
589  }
590  }
591  }
592  if (done) {
593  // Clear vehicleStateChanges for this client -> For subsequent TraCI stepping
594  // that is performed within this SUMO step, no updates on vehicle states
595  // belonging to the last SUMO simulation step will be received by this client.
596  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myCurrentSocket->second->vehicleStateChanges.begin(); i != myCurrentSocket->second->vehicleStateChanges.end(); ++i) {
597  (*i).second.clear();
598  }
599  myCurrentSocket++;
600  } else if (load) {
601  myCurrentSocket = mySockets.end();
602  } else {
603  assert(closed);
604  // remove current socket and increment to next socket in ordering
606  }
607  }
608  if (!myLoadArgs.empty()) {
609 #ifdef DEBUG_MULTI_CLIENTS
610  std::cout << " Breaking loop to load new simulation." << std::endl;
611 #endif
612  break;
613  } else if (myDoCloseConnection) {
614 #ifdef DEBUG_MULTI_CLIENTS
615  std::cout << " Breaking loop because last client closed connection." << std::endl;
616 #endif
617  break;
618  }
619  SUMOTime nextT = nextTargetTime();
620  // minimal target time among clients should have been increased during the last loop through mySockets
621  // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
622  // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
623  // the next call is then usually simulationStep(step=1000) leading to no further increase
624  // and thus a failing assertion here.
625  //assert(myTargetTime < nextT || myDoCloseConnection);
626  myTargetTime = nextT;
627  }
628  // All clients are done with the current time step
629  // Reset myVehicleStateChanges
630  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); ++i) {
631  (*i).second.clear();
632  }
633  } catch (std::invalid_argument& e) {
634  throw ProcessError(e.what());
635  } catch (libsumo::TraCIException& e) {
636  throw ProcessError(e.what());
637  } catch (tcpip::SocketException& e) {
638  throw ProcessError(e.what());
639  }
640 }
641 
642 
643 void
645  mySubscriptions.clear();
646  myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
647  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
648  myCurrentSocket->second->targetTime = myTargetTime;
649  }
653  std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i;
654  for (i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); i++) {
655  i->second.clear();
656  }
657  myCurrentSocket = mySockets.begin();
658 }
659 
660 
661 #ifdef HAVE_PYTHON
662 // ===========================================================================
663 // python functions (traciemb module)
664 // ===========================================================================
665 static PyObject*
666 traciemb_execute(PyObject* /* self */, PyObject* args) {
667  const char* msg;
668  int size;
669  if (!PyArg_ParseTuple(args, "s#", &msg, &size)) {
670  return NULL;
671  }
672  std::string result = TraCIServer::execute(std::string(msg, size));
673  return Py_BuildValue("s#", result.c_str(), result.size());
674 }
675 
676 static PyMethodDef EmbMethods[] = {
677  {
678  "execute", traciemb_execute, METH_VARARGS,
679  "Execute the given TraCI command and return the result."
680  },
681  {NULL, NULL, 0, NULL}
682 };
683 
684 
685 std::string
686 TraCIServer::execute(std::string cmd) {
687  try {
688  assert(myInstance != 0);
691  for (std::string::iterator i = cmd.begin(); i != cmd.end(); ++i) {
693  }
695  return std::string(myInstance->myOutputStorage.begin(), myInstance->myOutputStorage.end());
696  } catch (std::invalid_argument& e) {
697  throw ProcessError(e.what());
698  } catch (libsumo::TraCIException& e) {
699  throw ProcessError(e.what());
700  } catch (tcpip::SocketException& e) {
701  throw ProcessError(e.what());
702  }
703 }
704 
705 
706 void
707 TraCIServer::runEmbedded(std::string pyFile) {
708  PyObject* pName, *pModule;
709  Py_Initialize();
710  Py_InitModule("traciemb", EmbMethods);
711  if (pyFile.length() > 3 && !pyFile.compare(pyFile.length() - 3, 3, ".py")) {
712  PyObject* sys_path, *path;
713  char pathstr[] = "path";
714  sys_path = PySys_GetObject(pathstr);
715  if (sys_path == NULL || !PyList_Check(sys_path)) {
716  throw ProcessError("Could not access python sys.path!");
717  }
718  path = PyString_FromString(FileHelpers::getFilePath(pyFile).c_str());
719  PyList_Insert(sys_path, 0, path);
720  Py_DECREF(path);
721  FILE* pFile = fopen(pyFile.c_str(), "r");
722  if (pFile == NULL) {
723  throw ProcessError("Failed to load \"" + pyFile + "\"!");
724  }
725  PyRun_SimpleFile(pFile, pyFile.c_str());
726  fclose(pFile);
727  } else {
728  pName = PyString_FromString(pyFile.c_str());
729  /* Error checking of pName left out */
730  pModule = PyImport_Import(pName);
731  Py_DECREF(pName);
732  if (pModule == NULL) {
733  PyErr_Print();
734  throw ProcessError("Failed to load \"" + pyFile + "\"!");
735  }
736  }
737  Py_Finalize();
738 }
739 #endif
740 
741 
742 std::map<int, TraCIServer::SocketInfo*>::iterator
744 #ifdef DEBUG_MULTI_CLIENTS
745  std::cout << " Removing socket " << myCurrentSocket->second->socket
746  << " (order " << myCurrentSocket->first << ")" << std::endl;
747 #endif
748 
749  if (mySockets.size() == 1) {
750  // Last client has disconnected
751  delete myCurrentSocket->second->socket;
752  mySockets.clear();
753  myCurrentSocket = mySockets.end();
754  return myCurrentSocket;
755  }
756 
757  const int currOrder = myCurrentSocket->first;
758  delete myCurrentSocket->second->socket;
759  myCurrentSocket++;
760  if (myCurrentSocket != mySockets.end()) {
761  const int nextOrder = myCurrentSocket->first;
762  mySockets.erase(currOrder);
763  myCurrentSocket = mySockets.find(nextOrder);
764  } else {
765  mySockets.erase(currOrder);
766  myCurrentSocket = mySockets.end();
767  }
768  return myCurrentSocket;
769 }
770 
771 
772 int
773 TraCIServer::readCommandID(int& commandStart, int& commandLength) {
774  commandStart = myInputStorage.position();
775  commandLength = myInputStorage.readUnsignedByte();
776  if (commandLength == 0) {
777  commandLength = myInputStorage.readInt();
778  }
780 }
781 
782 
783 int
785  int commandStart, commandLength;
786  int commandId = readCommandID(commandStart, commandLength);
787 #ifdef DEBUG_MULTI_CLIENTS
788  std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
789  << ", commandId = " << commandId << std::endl;
790 #endif
791  bool success = false;
792  // dispatch commands
793  if (myExecutors.find(commandId) != myExecutors.end()) {
794  success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
795  } else {
796  switch (commandId) {
797  case CMD_GETVERSION:
798  success = commandGetVersion();
799  break;
800  case CMD_LOAD: {
801  std::vector<std::string> args;
803  return writeErrorStatusCmd(CMD_LOAD, "A load command needs a list of string arguments.", myOutputStorage);
804  }
805 #ifdef DEBUG_MULTI_CLIENTS
806  std::cout << " commandId == CMD_LOAD"
807  << ", args = " << toString(args) << std::endl;
808 #endif
809  try {
810  myLoadArgs = args;
811  success = true;
813  // XXX: This only cares for the client that issued the load command.
814  // Multiclient-load functionality is still to be implemented. Refs #3146.
815  myCurrentSocket->second->socket->sendExact(myOutputStorage);
817  } catch (libsumo::TraCIException& e) {
818  return writeErrorStatusCmd(CMD_LOAD, e.what(), myOutputStorage);
819  }
820  break;
821  }
822  case CMD_SIMSTEP: {
823  const double nextT = myInputStorage.readDouble();
824  if (myAmEmbedded) {
825  if (nextT == 0.) {
827  } else {
828  myTargetTime = TIME2STEPS(nextT);
829  }
830  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); ++i) {
831  (*i).second.clear();
832  }
833  while (MSNet::getInstance()->getCurrentTimeStep() < myTargetTime) {
835  }
837  } else {
838  if (nextT == 0.) {
839  myCurrentSocket->second->targetTime += DELTA_T;
840  } else {
841  myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
842  }
843 #ifdef DEBUG_MULTI_CLIENTS
844  std::cout << " commandId == CMD_SIMSTEP"
845  << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
846 #endif
847  if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
848  // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
849  // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommandsUntilSimStep()
851  }
852  }
853  return commandId;
854  }
855  case CMD_CLOSE:
857  myCurrentSocket->second->socket->sendExact(myOutputStorage);
859  if (mySockets.size() == 1) {
860  // Last client has closed connection
861  myDoCloseConnection = true;
862  }
863  success = true;
864  break;
865  case CMD_SETORDER: {
866  const int order = myInputStorage.readInt();
867 #ifdef DEBUG_MULTI_CLIENTS
868  std::cout << " commandId == CMD_SETORDER"
869  << ", order index is " << order << std::endl;
870 #endif
871  if (order > MAX_ORDER) {
872  return writeErrorStatusCmd(CMD_SETORDER, "A set order command needs an int argument below " + toString(MAX_ORDER) + ".", myOutputStorage);
873  }
874  if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
875  return writeErrorStatusCmd(CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
876  }
877  // memorize reorder request (will only take effect in the next step)
878  mySocketReorderRequests[order] = myCurrentSocket->second;
879  success = true;
881  break;
882  }
898  success = addObjectVariableSubscription(commandId, false);
899  break;
915  success = addObjectVariableSubscription(commandId, true);
916  break;
918  success = addSubscriptionFilter();
919  break;
920  default:
921  if (commandId == CMD_GET_GUI_VARIABLE || commandId == CMD_SET_GUI_VARIABLE) {
922  writeStatusCmd(commandId, RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
923  } else {
924  writeStatusCmd(commandId, RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
925  }
926  }
927  }
928  if (!success) {
929  while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
931  }
932  }
933  if ((int)myInputStorage.position() != commandStart + commandLength) {
934  std::ostringstream msg;
935  msg << "Wrong position in requestMessage after dispatching command.";
936  msg << " Expected command length was " << commandLength;
937  msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
938  writeStatusCmd(commandId, RTYPE_ERR, msg.str());
939  myDoCloseConnection = true;
940  }
941  return commandId;
942 }
943 
944 
945 // ---------- Server-internal command handling
946 bool
948  std::string sumoVersion = VERSION_STRING;
949  // Prepare response
950  tcpip::Storage answerTmp;
951  answerTmp.writeInt(TRACI_VERSION);
952  answerTmp.writeString(std::string("SUMO ") + sumoVersion);
953  // When we get here, the response is stored in answerTmp -> put into myOutputStorage
955  // command length
956  myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
957  // command type
959  // and the parameter dependant part
960  myOutputStorage.writeStorage(answerTmp);
961  return true;
962 }
963 
964 
965 void
968 #ifdef DEBUG_MULTI_CLIENTS
969  std::cout << " postProcessSimulationStep() at time " << t << std::endl;
970 #endif
972  int noActive = 0;
973  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
974  const libsumo::Subscription& s = *i;
978  if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
979  i = mySubscriptions.erase(i);
980  continue;
981  }
982  ++i;
983  if (s.beginTime > t) {
984  continue;
985  }
986  ++noActive;
987  }
989 #ifdef DEBUG_SUBSCRIPTIONS
990  std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
991  << "\n Nr. of active subscriptions = " << noActive << std::endl;
992 #endif
993  mySubscriptionCache.writeInt(noActive);
994 #ifdef DEBUG_SUBSCRIPTIONS
995  std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
996 #endif
997  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
998  const libsumo::Subscription& s = *i;
999  if (s.beginTime > t) {
1000  ++i;
1001  continue;
1002  }
1003  tcpip::Storage into;
1004  std::string errors;
1005  bool ok = processSingleSubscription(s, into, errors);
1006 #ifdef DEBUG_SUBSCRIPTIONS
1007  std::cout << " Size of into-store for subscription " << s.id
1008  << ": " << into.size() << std::endl;
1009 #endif
1011  if (ok) {
1012  ++i;
1013  } else {
1014  i = mySubscriptions.erase(i);
1015  }
1016  }
1018 #ifdef DEBUG_SUBSCRIPTIONS
1019  std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1020 #endif
1021 }
1022 
1023 
1024 void
1026 #ifdef DEBUG_MULTI_CLIENTS
1027  std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1028  << " (-> intermediate TraCI step)."
1029  << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1030  << std::endl;
1031 #endif
1033 
1034 // NOTE: the commented code would send an empty response
1035 // myOutputStorage.writeInt(0);
1036 // myCurrentSocket->second->socket->sendExact(myOutputStorage);
1037 // myOutputStorage.reset();
1039  // send results to active client
1040  myCurrentSocket->second->socket->sendExact(myOutputStorage);
1042 }
1043 
1044 
1045 void
1046 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1047  writeStatusCmd(commandId, status, description, myOutputStorage);
1048 }
1049 
1050 
1051 void
1052 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1053  if (status == RTYPE_ERR) {
1054  WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1055  } else if (status == RTYPE_NOTIMPLEMENTED) {
1056  WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1057  }
1058  outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1059  outputStorage.writeUnsignedByte(commandId); // command type
1060  outputStorage.writeUnsignedByte(status); // status
1061  outputStorage.writeString(description); // description
1062 }
1063 
1064 
1065 bool
1066 TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1067  writeStatusCmd(commandId, RTYPE_ERR, description, outputStorage);
1068  return false;
1069 }
1070 
1071 
1072 void
1074  tcpip::Storage writeInto;
1075  std::string errors;
1076  libsumo::Subscription* modifiedSubscription = nullptr;
1077  if (processSingleSubscription(s, writeInto, errors)) {
1079  writeStatusCmd(s.commandId, RTYPE_ERR, "Subscription has ended.");
1080  } else {
1081  bool needNewSubscription = true;
1083  if (s.commandId == o.commandId && s.id == o.id &&
1084  s.beginTime == o.beginTime && s.endTime == o.endTime &&
1085  s.contextDomain == o.contextDomain && s.range == o.range) {
1086  std::vector<std::vector<unsigned char> >::const_iterator k = s.parameters.begin();
1087  for (std::vector<int>::const_iterator j = s.variables.begin(); j != s.variables.end(); ++j, ++k) {
1088  const int offset = (int)(std::find(o.variables.begin(), o.variables.end(), *j) - o.variables.begin());
1089  if (offset == (int)o.variables.size() || o.parameters[offset] != *k) {
1090  o.variables.push_back(*j);
1091  o.parameters.push_back(*k);
1092  }
1093  }
1094  needNewSubscription = false;
1095  modifiedSubscription = &o;
1096  break;
1097  }
1098  }
1099  if (needNewSubscription) {
1100  mySubscriptions.push_back(s);
1101  modifiedSubscription = &mySubscriptions.back();
1102  // Add new subscription to subscription cache (note: seems a bit inefficient)
1104  // copy new subscription into cache
1105  int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1106  tcpip::Storage tmp;
1107  tmp.writeInt(noActive);
1108  while (mySubscriptionCache.valid_pos()) {
1110  }
1111  tmp.writeStorage(writeInto);
1114  }
1115  }
1117  }
1118  if (modifiedSubscription != nullptr && isVehicleToVehicleContextSubscription(*modifiedSubscription)) {
1119  // Set last modified vehicle context subscription active for filter modifications
1120  myLastContextSubscription = modifiedSubscription;
1121  } else {
1122  // adding other subscriptions deactivates the activation for filter addition
1123  myLastContextSubscription = nullptr;
1124  }
1125  } else {
1126  writeStatusCmd(s.commandId, RTYPE_ERR, "Could not add subscription (" + errors + ").");
1127  }
1128  myOutputStorage.writeStorage(writeInto);
1129 }
1130 
1131 
1132 void
1133 TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1134  bool found = false;
1135  std::vector<libsumo::Subscription>::iterator j;
1136  for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1137  if (j->id == id && j->commandId == commandId && (domain < 0 || j->contextDomain == domain)) {
1138  j = mySubscriptions.erase(j);
1139  if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1140  // Remove also reference for filter additions
1141  myLastContextSubscription = nullptr;
1142  }
1143  found = true;
1144  continue;
1145  }
1146  ++j;
1147  }
1148  // try unsubscribe
1149  if (found) {
1150  writeStatusCmd(commandId, RTYPE_OK, "");
1151  } else {
1152  writeStatusCmd(commandId, RTYPE_ERR, "The subscription to remove was not found.");
1153  }
1154 }
1155 
1156 bool
1159 }
1160 
1161 
1162 bool
1164  std::string& errors) {
1165  bool ok = true;
1166  tcpip::Storage outputStorage;
1167  const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1168  std::set<std::string> objIDs;
1169  if (s.contextDomain > 0) {
1171  PositionVector shape;
1174  }
1176  } else {
1177  objIDs.insert(s.id);
1178  }
1179  const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == TRACI_ID_LIST ? 0 : (int)s.variables.size();
1180  int skipped = 0;
1181  for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1182  if (s.contextDomain > 0) {
1183  //if (centralObject(s, *j)) {
1184  // skipped++;
1185  // continue;
1186  //}
1187  outputStorage.writeString(*j);
1188  }
1189  if (numVars > 0) {
1190  std::vector<std::vector<unsigned char> >::const_iterator k = s.parameters.begin();
1191  for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1192  tcpip::Storage message;
1193  message.writeUnsignedByte(*i);
1194  message.writeString(*j);
1195  message.writePacket(*k);
1196  tcpip::Storage tmpOutput;
1197  if (myExecutors.find(getCommandId) != myExecutors.end()) {
1198  ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1199  } else {
1200  writeStatusCmd(s.commandId, RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1201  ok = false;
1202  }
1203  // copy response part
1204  if (ok) {
1205  int length = tmpOutput.readUnsignedByte();
1206  while (--length > 0) {
1207  tmpOutput.readUnsignedByte();
1208  }
1209  int lengthLength = 1;
1210  length = tmpOutput.readUnsignedByte();
1211  if (length == 0) {
1212  lengthLength = 5;
1213  length = tmpOutput.readInt();
1214  }
1215  //read responseType
1216  tmpOutput.readUnsignedByte();
1217  int variable = tmpOutput.readUnsignedByte();
1218  std::string id = tmpOutput.readString();
1219  outputStorage.writeUnsignedByte(variable);
1220  outputStorage.writeUnsignedByte(RTYPE_OK);
1221  length -= (lengthLength + 1 + 4 + (int)id.length());
1222  while (--length > 0) {
1223  outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1224  }
1225  } else {
1226  //read length
1227  tmpOutput.readUnsignedByte();
1228  //read cmd
1229  tmpOutput.readUnsignedByte();
1230  //read status
1231  tmpOutput.readUnsignedByte();
1232  std::string msg = tmpOutput.readString();
1233  outputStorage.writeUnsignedByte(*i);
1234  outputStorage.writeUnsignedByte(RTYPE_ERR);
1235  outputStorage.writeUnsignedByte(TYPE_STRING);
1236  outputStorage.writeString(msg);
1237  errors = errors + msg;
1238  }
1239  }
1240  }
1241  }
1242  int length = (1 + 4) + 1 + (4 + (int)(s.id.length())) + 1 + (int)outputStorage.size();
1243  if (s.contextDomain > 0) {
1244  length += 4;
1245  }
1246  writeInto.writeUnsignedByte(0); // command length -> extended
1247  writeInto.writeInt(length);
1248  writeInto.writeUnsignedByte(s.commandId + 0x10);
1249  writeInto.writeString(s.id);
1250  if (s.contextDomain > 0) {
1251  writeInto.writeUnsignedByte(s.contextDomain);
1252  }
1253  writeInto.writeUnsignedByte(numVars);
1254  if (s.contextDomain > 0) {
1255  writeInto.writeInt((int)objIDs.size() - skipped);
1256  }
1257  if (s.contextDomain == 0 || objIDs.size() != 0) {
1258  writeInto.writeStorage(outputStorage);
1259  }
1260  return ok;
1261 }
1262 
1263 
1264 bool
1265 TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1266  const double beginTime = myInputStorage.readDouble();
1267  const double endTime = myInputStorage.readDouble();
1268  const SUMOTime begin = beginTime == INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1269  const SUMOTime end = endTime == INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1270  const std::string id = myInputStorage.readString();
1271  const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1272  const double range = hasContext ? myInputStorage.readDouble() : 0.;
1273  const int num = myInputStorage.readUnsignedByte();
1274  std::vector<int> variables;
1275  std::vector<std::vector<unsigned char> > parameters;
1276  for (int i = 0; i < num; ++i) {
1277  const int varID = myInputStorage.readUnsignedByte();
1278  variables.push_back(varID);
1279  parameters.push_back(std::vector<unsigned char>());
1280  for (int j = 0; j < myParameterSizes[varID]; j++) {
1281  parameters.back().push_back(myInputStorage.readChar());
1282  }
1283  }
1284  // check subscribe/unsubscribe
1285  if (variables.size() == 0) {
1286  removeSubscription(commandId, id, -1);
1287  return true;
1288  }
1289  // process subscription
1290  libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1292  return true;
1293 }
1294 
1295 
1296 
1297 bool
1299  bool success = true;
1300  if (myLastContextSubscription == nullptr) {
1301  WRITE_WARNING("addSubscriptionFilter: No previous vehicle context subscription exists to apply the context filter.");
1302  return true;
1303  }
1304  // Read filter type
1305  int filterType = myInputStorage.readUnsignedByte();
1306 
1307  // dispatch according to filter type
1308  switch (filterType) {
1309  case FILTER_TYPE_NONE:
1310  // Remove all filters
1311  removeFilters();
1312  break;
1313  case FILTER_TYPE_LANES: {
1314  // Read relative lanes to consider for context filter
1315  int nrLanes = (int)myInputStorage.readByte();
1316  std::vector<int> lanes;
1317  for (int i = 0; i < nrLanes; ++i) {
1318  lanes.push_back((int) myInputStorage.readByte());
1319  }
1321  }
1322  break;
1324  // Add no-opposite filter
1326  break;
1328  myInputStorage.readByte(); // read type double
1329  double dist = myInputStorage.readDouble();
1331  }
1332  break;
1334  myInputStorage.readByte(); // read type double
1335  double dist = myInputStorage.readDouble();
1337  }
1338  break;
1339  case FILTER_TYPE_LEAD_FOLLOW: {
1340  // Read relative lanes to consider for context filter
1342  }
1343  break;
1344  case FILTER_TYPE_TURN:
1346  break;
1347  case FILTER_TYPE_VCLASS: {
1348  myInputStorage.readByte(); // read type stringlist
1350  addSubscriptionFilterVClass(vClasses);
1351  }
1352  break;
1353  case FILTER_TYPE_VTYPE: {
1354  myInputStorage.readByte(); // read type stringlist
1355  std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1356  std::set<std::string> vTypesSet;
1357  vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1358  addSubscriptionFilterVType(vTypesSet);
1359  }
1360  break;
1361  default:
1362  writeStatusCmd(filterType, RTYPE_NOTIMPLEMENTED, "'" + toString(filterType) + "' is no valid filter type code.");
1363  success = false;
1364  }
1365 
1366  if (success) {
1367  // acknowledge filter addition
1369  }
1370 
1371  return success;
1372 }
1373 
1374 
1375 void
1377 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1378  std::cout << "Removing filters" << std::endl;
1379 #endif
1381 }
1382 
1383 void
1385 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1386  std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1387 #endif
1390 }
1391 
1392 void
1394 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1395  std::cout << "Adding no opposite filter" << std::endl;
1396 #endif
1398 }
1399 
1400 void
1402 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1403  std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1404 #endif
1407 }
1408 
1409 void
1411 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1412  std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1413 #endif
1416 }
1417 
1418 void
1420 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1421  std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1422 #endif
1424 }
1425 
1426 void
1428 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1429  std::cout << "Adding turn-maneuver filter" << std::endl;
1430 #endif
1432 }
1433 
1434 void
1436 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1437  std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1438 #endif
1441 }
1442 
1443 void
1444 TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1445 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1446  std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1447 #endif
1450 }
1451 
1452 void
1454  if (tempMsg.size() < 254) {
1455  outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1456  } else {
1457  outputStorage.writeUnsignedByte(0); // command length -> extended
1458  outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1459  }
1460  outputStorage.writeStorage(tempMsg);
1461 }
1462 
1463 
1464 void
1466  outputStorage.writeUnsignedByte(TYPE_POLYGON);
1467  if (shape.size() < 256) {
1468  outputStorage.writeUnsignedByte((int)shape.size());
1469  } else {
1470  outputStorage.writeUnsignedByte(0);
1471  outputStorage.writeInt((int)shape.size());
1472  }
1473  for (const libsumo::TraCIPosition& pos : shape) {
1474  outputStorage.writeDouble(pos.x);
1475  outputStorage.writeDouble(pos.y);
1476  }
1477 }
1478 
1479 
1480 bool
1482  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
1483  return false;
1484  }
1485  into = inputStorage.readInt();
1486  return true;
1487 }
1488 
1489 
1490 bool
1492  if (inputStorage.readUnsignedByte() != TYPE_DOUBLE) {
1493  return false;
1494  }
1495  into = inputStorage.readDouble();
1496  return true;
1497 }
1498 
1499 
1500 bool
1501 TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
1502  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
1503  return false;
1504  }
1505  into = inputStorage.readString();
1506  return true;
1507 }
1508 
1509 
1510 bool
1511 TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
1512  if (inputStorage.readUnsignedByte() != TYPE_STRINGLIST) {
1513  return false;
1514  }
1515  into = inputStorage.readStringList();
1516  return true;
1517 }
1518 
1519 
1520 bool
1522  if (inputStorage.readUnsignedByte() != TYPE_COLOR) {
1523  return false;
1524  }
1525  into.r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1526  into.g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1527  into.b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1528  into.a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1529  return true;
1530 }
1531 
1532 
1533 bool
1535  if (inputStorage.readUnsignedByte() != POSITION_2D) {
1536  return false;
1537  }
1538  into.x = inputStorage.readDouble();
1539  into.y = inputStorage.readDouble();
1540  into.z = 0;
1541  return true;
1542 }
1543 
1544 
1545 bool
1547  if (inputStorage.readByte() != TYPE_BYTE) {
1548  return false;
1549  }
1550  into = inputStorage.readByte();
1551  return true;
1552 }
1553 
1554 
1555 bool
1557  if (inputStorage.readUnsignedByte() != TYPE_UBYTE) {
1558  return false;
1559  }
1560  into = inputStorage.readUnsignedByte();
1561  return true;
1562 }
1563 
1564 
1565 bool
1567  if (inputStorage.readUnsignedByte() != TYPE_POLYGON) {
1568  return false;
1569  }
1570  into.clear();
1571  int size = inputStorage.readUnsignedByte();
1572  if (size == 0) {
1573  size = inputStorage.readInt();
1574  }
1575  PositionVector shape;
1576  for (int i = 0; i < size; ++i) {
1577  double x = inputStorage.readDouble();
1578  double y = inputStorage.readDouble();
1579  if (std::isnan(x) || std::isnan(y)) {
1580  throw libsumo::TraCIException("NaN-Value in shape");
1581  }
1582  into.push_back(Position(x, y));
1583  }
1584  return true;
1585 }
1586 
1587 
1588 void
1590  myTargetTime = targetTime;
1591  for (auto& s : mySockets) {
1592  s.second->targetTime = targetTime;
1593  }
1594 }
1595 
1596 bool
1597 TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1598  return (s.id == objID && s.commandId + 32 == s.contextDomain);
1599 }
1600 
1601 /****************************************************************************/
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa3: Get Lane Variable)
The vehicle has departed (was inserted into the network)
Definition: MSNet.h:498
#define FILTER_TYPE_NONE
unsigned char g
Definition: TraCIDefs.h:139
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
void addSubscriptionFilterDownstreamDistance(double dist)
#define CMD_SUBSCRIBE_VEHICLE_CONTEXT
#define CMD_SUBSCRIBE_LANE_VARIABLE
tcpip::Storage mySubscriptionCache
The last timestep&#39;s subscription results.
Definition: TraCIServer.h:376
bool readTypeCheckingColor(tcpip::Storage &inputStorage, libsumo::TraCIColor &into)
Reads the value type and a color, verifying the type.
#define FILTER_TYPE_VCLASS
#define CMD_SUBSCRIBE_LANEAREA_VARIABLE
Representation of a subscription.
Definition: Subscription.h:65
long long int SUMOTime
Definition: SUMOTime.h:36
double range
The range of the context.
Definition: Subscription.h:98
static void applySubscriptionFilters(const Subscription &s, std::set< std::string > &objIDs)
Filter the given ID-Set (which was obtained from an R-Tree search) according to the filters set by th...
Definition: Helper.cpp:437
#define CMD_GET_TL_VARIABLE
#define CMD_SUBSCRIBE_JUNCTION_CONTEXT
StorageType::const_iterator end() const
Definition: storage.h:118
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc3: Change Lane State)
bool wrapString(const std::string &objID, const int variable, const std::string &value)
#define CMD_GET_VEHICLE_VARIABLE
bool processSingleSubscription(const libsumo::Subscription &s, tcpip::Storage &writeInto, std::string &errors)
virtual ~TraCIServer()
Destructor.
#define CMD_SUBSCRIBE_SIM_CONTEXT
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)
#define CMD_GET_INDUCTIONLOOP_VARIABLE
#define CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE
bool wrapInt(const std::string &objID, const int variable, const int value)
#define TYPE_UBYTE
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
#define RTYPE_OK
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa9: Get Junction Variable)
#define CMD_GET_LANEAREA_VARIABLE
#define CMD_GET_PERSON_VARIABLE
virtual double readDouble()
tcpip::Storage myOutputStorage
The storage to write to.
Definition: TraCIServer.h:370
#define TYPE_POLYGON
void initialiseSubscription(libsumo::Subscription &s)
#define TRACI_VERSION
void postProcessSimulationStep()
Handles subscriptions to send after a simstep2 command.
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc2: Change Traffic Lights State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xab: Get Simulation Variable)
#define MAX_ORDER
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:165
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Route State)
std::vector< std::string > myLoadArgs
Definition: TraCIServer.h:387
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
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
#define POSITION_3D
tcpip::Storage myInputStorage
The storage to read from.
Definition: TraCIServer.h:367
SUMOTime beginTime
The begin time of the subscription.
Definition: Subscription.h:92
#define CMD_GET_POLYGON_VARIABLE
virtual void writePacket(unsigned char *packet, int length)
#define CMD_SUBSCRIBE_JUNCTION_VARIABLE
bool centralObject(const libsumo::Subscription &s, const std::string &objID)
check whether a found objID refers to the central object of a context subscription ...
void cleanup()
clean up subscriptions
#define CMD_SUBSCRIBE_ROUTE_CONTEXT
bool readTypeCheckingPolygon(tcpip::Storage &inputStorage, PositionVector &into)
Reads the value type and a polygon, verifying the type.
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
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
#define CMD_SET_GUI_VARIABLE
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()
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:838
#define CMD_GET_ROUTE_VARIABLE
#define CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
virtual void writeInt(int)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
#define VAR_POSITION3D
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
#define TYPE_STRING
#define SIMTIME
Definition: SUMOTime.h:65
virtual int readUnsignedByte()
SUMOTime endTime
The end time of the subscription.
Definition: Subscription.h:94
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)
std::string id
The id of the object that is subscribed.
Definition: Subscription.h:86
static bool myDoCloseConnection
Whether the connection was set to be to close.
Definition: TraCIServer.h:348
std::map< int, SocketInfo * >::iterator removeCurrentSocket()
removes myCurrentSocket from mySockets and returns an iterator pointing to the next member according ...
void addSubscriptionFilterVClass(SVCPermissions vClasses)
The vehicles starts to stop.
Definition: MSNet.h:512
std::map< int, CmdExecutor > myExecutors
Map of commandIds -> their executors; applicable if the executor applies to the method footprint...
Definition: TraCIServer.h:382
#define CMD_SET_TL_VARIABLE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get AreaDetector Variable)
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:84
#define CMD_SUBSCRIBE_LANE_CONTEXT
#define CMD_SUBSCRIBE_SIM_VARIABLE
void removeSubscription(int commandId, const std::string &identity, int domain)
unsigned char b
Definition: TraCIDefs.h:139
#define CMD_GET_VEHICLETYPE_VARIABLE
#define INVALID_DOUBLE_VALUE
Definition: TraCIDefs.h:42
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:101
static void close()
request termination of connection
bool addObjectVariableSubscription(const int commandId, const bool hasContext)
#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 TRACI_ID_LIST
#define CMD_SUBSCRIBE_GUI_CONTEXT
#define CMD_LOAD
#define FILTER_TYPE_UPSTREAM_DIST
The vehicle got a new route.
Definition: MSNet.h:506
The vehicle arrived at his destination (is deleted)
Definition: MSNet.h:504
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
The vehicles starts to park.
Definition: MSNet.h:508
The vehicle is involved in a collision.
Definition: MSNet.h:516
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xce: Change Person State)
#define FILTER_TYPE_LANES
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual int readInt()
int contextDomain
The domain ID of the context.
Definition: Subscription.h:96
void addSubscriptionFilterNoOpposite()
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
Definition: Subscription.h:105
The vehicle had to brake harder than permitted.
Definition: MSNet.h:518
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:776
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
#define CMD_GET_POI_VARIABLE
int filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:111
#define CMD_SUBSCRIBE_MULTIENTRYEXIT_VARIABLE
A list of positions.
#define CMD_SUBSCRIBE_MULTIENTRYEXIT_CONTEXT
#define FILTER_TYPE_LEAD_FOLLOW
#define CMD_SET_VEHICLETYPE_VARIABLE
virtual void writeByte(int)
bool wrapStringList(const std::string &objID, const int variable, const std::vector< std::string > &value)
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
unsigned char a
Definition: TraCIDefs.h:139
virtual void writeStringList(const std::vector< std::string > &s)
#define STEPS2TIME(x)
Definition: SUMOTime.h:58
#define CMD_SUBSCRIBE_GUI_VARIABLE
#define CMD_GET_LANE_VARIABLE
#define CMD_SUBSCRIBE_LANEAREA_CONTEXT
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:263
#define FILTER_TYPE_NOOPPOSITE
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:42
T MIN2(T a, T b)
Definition: StdDefs.h:70
void addSubscriptionFilterUpstreamDistance(double dist)
bool addSubscriptionFilter()
The vehicle started to teleport.
Definition: MSNet.h:500
tcpip::Storage & getWrapperStorage()
#define CMD_GET_SIM_VARIABLE
virtual std::string readString()
#define CMD_GET_EDGE_VARIABLE
libsumo::Subscription * myLastContextSubscription
The last modified context subscription (the one to add a filter to, see (), currently only for vehicl...
Definition: TraCIServer.h:393
virtual unsigned int position() const
void addSubscriptionFilterTurn()
#define CMD_GET_GUI_VARIABLE
void addSubscriptionFilterLeadFollow()
bool isVehicleToVehicleContextSubscription(const libsumo::Subscription &s)
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
unsigned char r
Definition: TraCIDefs.h:139
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
#define CMD_SET_POI_VARIABLE
void removeFilters()
int readCommandID(int &commandStart, int &commandLength)
Reads the next command ID from the input storage.
#define CMD_SUBSCRIBE_POLYGON_VARIABLE
static TraCIServer * myInstance
Singleton instance of the server.
Definition: TraCIServer.h:345
#define CMD_SUBSCRIBE_TL_CONTEXT
The vehicle ends to park.
Definition: MSNet.h:510
#define CMD_SUBSCRIBE_EDGE_CONTEXT
#define FILTER_TYPE_VTYPE
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
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition: socket.cpp:260
#define CMD_SUBSCRIBE_PERSON_VARIABLE
bool readTypeCheckingUnsignedByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and an unsigned byte, verifying the type.
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:62
void sendOutputToAll() const
send out subscription results (actually just the content of myOutputStorage) to clients which will ac...
TraCIServer(const SUMOTime begin, const int port, const int numClients)
Constructor.
virtual void writeStorage(tcpip::Storage &store)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xae: Get Person Variable)
void sendSingleSimStepResponse()
sends an empty response to a simstep command to the current client. (This applies to a situation wher...
#define VAR_LEADER
#define CMD_SET_SIM_VARIABLE
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
Definition: Subscription.h:109
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
Definition: Subscription.h:107
std::vector< std::vector< unsigned char > > parameters
The parameters for the subscribed variables.
Definition: Subscription.h:90
StorageType::size_type size() const
Definition: storage.h:115
#define CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE
bool wrapColor(const std::string &objID, const int variable, const libsumo::TraCIColor &value)
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
#define FILTER_TYPE_DOWNSTREAM_DIST
#define VERSION_STRING
Definition: config.h:207
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:494
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:379
The vehicle was built, but has not yet departed.
Definition: MSNet.h:496
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
void processCommandsUntilSimStep(SUMOTime step)
process all commands until the next SUMO simulation step. It is guaranteed that t->getTargetTime() >=...
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa2: Get Traffic Lights Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc5: Change Vehicle Type State)
void processReorderingRequests()
checks for and processes reordering requests (relevant for multiple clients)
#define CMD_SET_POLYGON_VARIABLE
static void openSocket(const std::map< int, CmdExecutor > &execs)
Initialises the server.
void writePositionVector(tcpip::Storage &outputStorage, const libsumo::TraCIPositionVector &shape)
virtual void writeString(const std::string &s)
#define RTYPE_NOTIMPLEMENTED
#define SUMOTime_MAX
Definition: SUMOTime.h:37
#define CMD_ADD_SUBSCRIPTION_FILTER
#define TYPE_DOUBLE
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:59
std::vector< TraCIPosition > TraCIPositionVector
Definition: TraCIDefs.h:145
#define CMD_SUBSCRIBE_VEHICLE_VARIABLE
bool wrapPosition(const std::string &objID, const int variable, const libsumo::TraCIPosition &value)
#define CMD_SUBSCRIBE_PERSON_CONTEXT
static void collectObjectsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition: Helper.cpp:378
std::map< int, SocketInfo * >::iterator myCurrentSocket
The currently active client socket.
Definition: TraCIServer.h:361
std::vector< int > variables
The subscribed variables.
Definition: Subscription.h:88
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
SUMOTime nextTargetTime() const
get the minimal next target time among all clients
#define TYPE_BYTE
StorageType::const_iterator begin() const
Definition: storage.h:117
#define CMD_SET_LANE_VARIABLE
void setTargetTime(SUMOTime targetTime)
Sets myTargetTime on server and sockets to the given value.
#define CMD_GET_MULTIENTRYEXIT_VARIABLE
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:113
SUMOTime myTargetTime
The time step to reach until processing the next commands.
Definition: TraCIServer.h:364
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get Route Variable)
std::vector< libsumo::Subscription > mySubscriptions
The list of known, still valid subscriptions.
Definition: TraCIServer.h:390
The vehicle ends to stop.
Definition: MSNet.h:514
bool readTypeCheckingPosition2D(tcpip::Storage &inputStorage, libsumo::TraCIPosition &into)
Reads the value type and a 2D position, verifying the type.
virtual void writeDouble(double)
#define CMD_SETORDER
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get MeMeDetector Variable)
void addSubscriptionFilterLanes(std::vector< int > lanes)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa8: Get Polygon Variable)
int dispatchCommand()
Handles command, writes response to myOutputStorage.
#define CMD_SUBSCRIBE_TL_VARIABLE
tcpip::Storage myWrapperStorage
A temporary storage to let the wrapper write to.
Definition: TraCIServer.h:373
std::map< int, SocketInfo * > mySockets
The socket connections to the clients the first component (index) determines the client&#39;s order (lowe...
Definition: TraCIServer.h:355
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
std::map< int, SocketInfo * > mySocketReorderRequests
This stores the setOrder(int) requests of the clients.
Definition: TraCIServer.h:358
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
Definition: FileHelpers.cpp:65
void initWrapper(const int domainID, const int variable, const std::string &objID)
#define CMD_SET_PERSON_VARIABLE
#define FILTER_TYPE_TURN
static void findObjectShape(int domain, const std::string &id, PositionVector &shape)
Definition: Helper.cpp:345
void simulationStep()
Performs a single simulation step.
Definition: MSNet.cpp:441
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:242
A 3D-position.
Definition: TraCIDefs.h:107
#define RTYPE_ERR
#define TYPE_INTEGER
#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)
void addSubscriptionFilterVType(std::set< std::string > vTypes)
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:402
The vehicle ended being teleported.
Definition: MSNet.h:502
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
#define CMD_SIMSTEP
virtual int readByte()
bool readTypeCheckingByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and a byte, verifying the type.
bool wrapDouble(const std::string &objID, const int variable, const double value)
tcpip::Socket * myServerSocket
The server socket.
Definition: TraCIServer.h:351
#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)
std::vector< int > filterLanes
lanes specified by the lanes filter
Definition: Subscription.h:103
std::map< int, int > myParameterSizes
Map of variable ids to the size of the parameter in bytes.
Definition: TraCIServer.h:385
void checkClientOrdering()
Called once after connection of all clients for executing SET_ORDER (and possibly prior GET_VERSION) ...