Eclipse 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-2019 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 #include <string>
38 #include <cmath>
39 #include <map>
40 #include <iostream>
41 #include <algorithm>
42 #include <foreign/tcpip/socket.h>
43 #include <foreign/tcpip/storage.h>
44 #include <utils/common/SUMOTime.h>
52 #include <utils/xml/XMLSubSys.h>
53 #include <microsim/MSNet.h>
54 #include <microsim/MSVehicle.h>
55 #include <microsim/MSEdge.h>
58 #include <microsim/MSJunction.h>
59 #include <microsim/MSEdgeControl.h>
60 #include <microsim/MSLane.h>
61 #include <microsim/MSGlobals.h>
63 #include <libsumo/Simulation.h>
64 #include <libsumo/Subscription.h>
65 #include <libsumo/TraCIConstants.h>
66 #include "TraCIServer.h"
69 #include "TraCIServerAPI_Lane.h"
73 #include "TraCIServerAPI_Vehicle.h"
75 #include "TraCIServerAPI_Route.h"
76 #include "TraCIServerAPI_POI.h"
77 #include "TraCIServerAPI_Polygon.h"
78 #include "TraCIServerAPI_Edge.h"
80 #include "TraCIServerAPI_Person.h"
81 
82 
83 // ===========================================================================
84 // debug constants
85 // ===========================================================================
86 //#define DEBUG_MULTI_CLIENTS
87 //#define DEBUG_SUBSCRIPTIONS
88 //#define DEBUG_SUBSCRIPTION_FILTERS
89 //#define DEBUG_RAW_INPUT
90 
91 
92 // ===========================================================================
93 // static member definitions
94 // ===========================================================================
97 
98 
99 // ===========================================================================
100 // method definitions
101 // ===========================================================================
102 void
103 TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
108 }
109 
110 
111 bool
112 TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
115  return true;
116 }
117 
118 
119 bool
120 TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
122  myWrapperStorage.writeInt(value);
123  return true;
124 }
125 
126 
127 bool
128 TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
131  return true;
132 }
133 
134 
135 bool
136 TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
139  return true;
140 }
141 
142 
143 bool
144 TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
145  const bool includeZ = variable == libsumo::VAR_POSITION3D;
149  if (includeZ) {
151  }
152  return true;
153 }
154 
155 
156 bool
157 TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
163  return true;
164 }
165 
166 
167 bool
168 TraCIServer::wrapRoadPosition(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIRoadPosition& /* value */) {
169  // this is currently only a placeholder to allow vehicle.subscribeLeader to work with libsumo
170  return false;
171 }
172 
173 
176  return myWrapperStorage;
177 }
178 
179 
180 
181 TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
182  : myServerSocket(nullptr), myTargetTime(begin), myLastContextSubscription(nullptr) {
183 #ifdef DEBUG_MULTI_CLIENTS
184  std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
185 #endif
186  myVehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>();
187  myVehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>();
188  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>();
189  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>();
190  myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>();
191  myVehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>();
192  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_PARKING] = std::vector<std::string>();
193  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_PARKING] = std::vector<std::string>();
194  myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_STOP] = std::vector<std::string>();
195  myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_STOP] = std::vector<std::string>();
196  myVehicleStateChanges[MSNet::VEHICLE_STATE_COLLISION] = std::vector<std::string>();
197  myVehicleStateChanges[MSNet::VEHICLE_STATE_EMERGENCYSTOP] = std::vector<std::string>();
198 
202 
224 
226 
227  myDoCloseConnection = false;
228 
229  // display warning if internal lanes are not used
231  WRITE_WARNING("Starting TraCI without using internal lanes!");
232  MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
233  MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
234  }
235 
236  try {
237  WRITE_MESSAGE("***Starting server on port " + toString(port) + " ***");
238  myServerSocket = new tcpip::Socket(port);
239  if (numClients > 1) {
240  WRITE_MESSAGE(" waiting for " + toString(numClients) + " clients...");
241  }
242  while ((int)mySockets.size() < numClients) {
243  int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
244  mySockets[index] = new SocketInfo(myServerSocket->accept(true), begin);
245  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>();
246  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>();
247  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>();
248  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>();
249  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>();
250  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>();
251  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_PARKING] = std::vector<std::string>();
252  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_PARKING] = std::vector<std::string>();
253  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_STOP] = std::vector<std::string>();
254  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_STOP] = std::vector<std::string>();
255  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_COLLISION] = std::vector<std::string>();
256  mySockets[index]->vehicleStateChanges[MSNet::VEHICLE_STATE_EMERGENCYSTOP] = std::vector<std::string>();
257  if (numClients > 1) {
258  WRITE_MESSAGE(" client connected");
259  }
260  }
261  // When got here, all clients have connected
262  if (numClients > 1) {
264  }
265  // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommandsUntilSimStep()
266  myCurrentSocket = mySockets.begin();
267  } catch (tcpip::SocketException& e) {
268  throw ProcessError(e.what());
269  }
270 }
271 
272 
274  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
275  delete myCurrentSocket->second;
276  }
277  delete myServerSocket;
278  cleanup();
279 }
280 
281 
282 // ---------- Initialisation and Shutdown
283 void
284 TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
285  if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
286  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
287  OptionsCont::getOptions().getInt("remote-port"),
288  OptionsCont::getOptions().getInt("num-clients"));
289  for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
290  myInstance->myExecutors[i->first] = i->second;
291  }
292  }
293  if (myInstance != nullptr) {
294  // maybe net was deleted and built again
297  }
298 }
299 
300 
301 void
303  if (myInstance == nullptr) {
304  return;
305  }
306  delete myInstance;
307  myInstance = nullptr;
308  myDoCloseConnection = true;
309 }
310 
311 
312 bool
314  return myDoCloseConnection;
315 }
316 
317 
318 // ---------- Initialisation and Shutdown
319 
320 
321 void
322 TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
323  if (!myDoCloseConnection) {
324  myVehicleStateChanges[to].push_back(vehicle->getID());
325  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
326  i->second->vehicleStateChanges[to].push_back(vehicle->getID());
327  }
328  }
329 }
330 
331 
332 void
334 #ifdef DEBUG_MULTI_CLIENTS
335  std::cout << "Checking client order requests." << std::endl;
336 #endif
337  // check for SET_ORDER commands queued by connected clients
338  // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
339  myCurrentSocket = mySockets.begin();
340  while (myCurrentSocket != mySockets.end()) {
341 #ifdef DEBUG_MULTI_CLIENTS
342  std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
343 #endif
344 // bool clientUnordered = true;
345 #ifdef _MSC_VER
346 #pragma warning(push)
347 #pragma warning(disable: 4127) // do not warn about constant conditional expression
348 #endif
349  while (true) {
350 #ifdef _MSC_VER
351 #pragma warning(pop)
352 #endif
354  myCurrentSocket->second->socket->receiveExact(myInputStorage);
355  int commandStart, commandLength;
356  int commandId = readCommandID(commandStart, commandLength);
357 #ifdef DEBUG_MULTI_CLIENTS
358  std::cout << " received command " << commandId << std::endl;
359 #endif
360  // Whether the received command is a permitted command for the initialization phase.
361  // Currently, getVersion and setOrder are permitted.
362  bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
363  if (initCommand) {
364 #ifdef DEBUG_MULTI_CLIENTS
365  std::cout << " Init command. Sending response." << std::endl;
366 #endif
367  // reset input storage to initial state before reading the commandId
368  // (ugly, but we can't just reset the store's iter_ from here)
369  // Giving the commandId to dispatch command didn't work either
370  tcpip::Storage tmp;
373  // we don't know whether the command was set with extended
374  // length syntax or not so we hardcode the length here (#5037)
378 
379  // Handle initialization command completely
380  dispatchCommand();
381  myCurrentSocket->second->socket->sendExact(myOutputStorage);
383  } else {
384 #ifdef DEBUG_MULTI_CLIENTS
385  std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
386 #endif
387  throw ProcessError("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase.");
388  }
389  if (commandId == libsumo::CMD_SETORDER) {
390  // This is what we have waited for.
391  break;
392  }
393  }
394  ++myCurrentSocket;
395  }
396 }
397 
398 
399 void
401  // Process reordering requests
402  if (mySocketReorderRequests.size() > 0) {
403  // process reordering requests
404  std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
405  std::map<int, SocketInfo*>::iterator j;
406 #ifdef DEBUG_MULTI_CLIENTS
407  std::cout << SIMTIME << " Current socket ordering:\n";
408  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
409  std::cout << " " << j->first << ": " << j->second->socket << "\n";
410  }
411  std::cout << "Reordering requests:\n";
412  for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
413  std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
414  }
415  i = mySocketReorderRequests.begin();
416 #endif
417  while (i != mySocketReorderRequests.end()) {
418  j = mySockets.begin();
419  while (j != mySockets.end()) {
420  if (j->second->socket == i->second->socket) {
421  break;
422  } else {
423  j++;
424  }
425  }
426  assert(j != mySockets.end());
427  mySockets.erase(j);
428  mySockets[i->first] = i->second;
429  ++i;
430  }
431  mySocketReorderRequests.clear();
432 #ifdef DEBUG_MULTI_CLIENTS
433  std::cout << "New socket ordering:\n";
434  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
435  std::cout << " " << j->first << ": " << j->second->socket << "\n";
436  }
437  std::cout << std::endl;
438 #endif
439  }
440 }
441 
442 
443 SUMOTime
445 #ifdef DEBUG_MULTI_CLIENTS
446  std::cout << "\n Determining new target time..." << std::endl;
447  if (mySockets.size() == 0) {
448  std::cout << " All clients have disconnected." << std::endl;
449  }
450 #endif
451  std::map<int, SocketInfo*>::const_iterator i;
452  SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
453  for (i = mySockets.begin(); i != mySockets.end(); ++i) {
454 #ifdef DEBUG_MULTI_CLIENTS
455  std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
456 #endif
457  targetTime = MIN2(targetTime, i->second->targetTime);
458  }
459 #ifdef DEBUG_MULTI_CLIENTS
460  std::cout << std::endl;
461 #endif
462  return targetTime;
463 }
464 
465 
466 // send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
467 void
469 #ifdef DEBUG_MULTI_CLIENTS
470  std::cout << "\n Sending subscription results to clients:\n";
471 #endif
472  std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
473  while (i != mySockets.end()) {
474  if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
475  // this client will become active before the next SUMO step. Provide subscription results.
476  i->second->socket->sendExact(myOutputStorage);
477 #ifdef DEBUG_MULTI_CLIENTS
478  std::cout << i->second->socket << "\n";
479 #endif
480  }
481  ++i;
482  }
483 #ifdef DEBUG_MULTI_CLIENTS
484  std::cout << std::endl;
485 #endif
486 }
487 
488 
489 void
491 #ifdef DEBUG_MULTI_CLIENTS
492  std::cout << SIMTIME << " processCommandsUntilSimStep(step = " << step << "):\n" << std::endl;
493 #endif
494  try {
495  const bool firstStep = myCurrentSocket != mySockets.end();
496  // update client order if requested
498  if (!firstStep) {
499  // 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)
500  // update subscription results
502  // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
503  sendOutputToAll();
505  }
506 
507  // determine minimal next target time among clients
509 
510  if (step < myTargetTime) {
511 #ifdef DEBUG_MULTI_CLIENTS
512  if (step < myTargetTime) {
513  std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommandsUntilSimStep()." << std::endl;
514  }
515 #endif
516  return;
517  }
518 
519  // Simulation should run until
520  // 1. end time reached or
521  // 2. got libsumo::CMD_CLOSE or
522  // 3. got libsumo::CMD_LOAD or
523  // 4. Client closes socket connection
524  while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep())) {
525 #ifdef DEBUG_MULTI_CLIENTS
526  std::cout << " Next target time: " << myTargetTime << std::endl;
527 #endif
528  // Iterate over clients and process communication for the ones with target time == myTargetTime
529  myCurrentSocket = mySockets.begin();
530  while (myCurrentSocket != mySockets.end()) {
531 #ifdef DEBUG_MULTI_CLIENTS
532  std::cout << " current socket: " << myCurrentSocket->second->socket
533  << " with target time " << myCurrentSocket->second->targetTime
534  << std::endl;
535 #endif
536 
537  if (myCurrentSocket->second->targetTime > myTargetTime) {
538  // this client must wait
539 #ifdef DEBUG_MULTI_CLIENTS
540  std::cout << " skipping client " << myCurrentSocket->second->socket
541  << " with target time " << myCurrentSocket->second->targetTime << std::endl;
542 #endif
543  myCurrentSocket++;
544  continue;
545  }
546  bool done = false;
547  bool closed = false;
548  bool load = false;
549  while (!done && !closed && !load) {
550  if (!myInputStorage.valid_pos()) {
551  // have read request completely, send response if adequate
552  if (myOutputStorage.size() > 0) {
553 #ifdef DEBUG_MULTI_CLIENTS
554  std::cout << " sending response..." << std::endl;
555 #endif
556  // send response to previous query
557  myCurrentSocket->second->socket->sendExact(myOutputStorage);
559  } else {
560 #ifdef DEBUG_MULTI_CLIENTS
561  std::cout << " No input and no output stored (This is the next client)." << std::endl;
562 #endif
563  }
564 #ifdef DEBUG_MULTI_CLIENTS
565  std::cout << " resetting input storage and reading next command..." << std::endl;
566 #endif
567  // Read next request
569  myCurrentSocket->second->socket->receiveExact(myInputStorage);
570  }
571 
573  // dispatch command
574  const int cmd = dispatchCommand();
575 #ifdef DEBUG_MULTI_CLIENTS
576  std::cout << " Received command " << cmd << std::endl;
577 #endif
578  if (cmd == libsumo::CMD_SIMSTEP) {
579 #ifdef DEBUG_MULTI_CLIENTS
580  std::cout << " Received command SIM_STEP, end turn for client " << myCurrentSocket->second->socket << std::endl;
581 #endif
582  done = true;
583  } else if (cmd == libsumo::CMD_LOAD) {
584 #ifdef DEBUG_MULTI_CLIENTS
585  std::cout << " Received command LOAD." << std::endl;
586 #endif
587  load = true;
588  } else if (cmd == libsumo::CMD_CLOSE) {
589 #ifdef DEBUG_MULTI_CLIENTS
590  std::cout << " Received command CLOSE." << std::endl;
591 #endif
592  closed = true;
593  }
594  }
595  }
596  if (done) {
597  // Clear vehicleStateChanges for this client -> For subsequent TraCI stepping
598  // that is performed within this SUMO step, no updates on vehicle states
599  // belonging to the last SUMO simulation step will be received by this client.
600  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myCurrentSocket->second->vehicleStateChanges.begin(); i != myCurrentSocket->second->vehicleStateChanges.end(); ++i) {
601  (*i).second.clear();
602  }
603  myCurrentSocket++;
604  } else if (load) {
605  myCurrentSocket = mySockets.end();
606  } else {
607  assert(closed);
608  // remove current socket and increment to next socket in ordering
610  }
611  }
612  if (!myLoadArgs.empty()) {
613 #ifdef DEBUG_MULTI_CLIENTS
614  std::cout << " Breaking loop to load new simulation." << std::endl;
615 #endif
616  break;
617  } else if (myDoCloseConnection) {
618 #ifdef DEBUG_MULTI_CLIENTS
619  std::cout << " Breaking loop because last client closed connection." << std::endl;
620 #endif
621  break;
622  }
623  SUMOTime nextT = nextTargetTime();
624  // minimal target time among clients should have been increased during the last loop through mySockets
625  // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
626  // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
627  // the next call is then usually simulationStep(step=1000) leading to no further increase
628  // and thus a failing assertion here.
629  //assert(myTargetTime < nextT || myDoCloseConnection);
630  myTargetTime = nextT;
631  }
632  // All clients are done with the current time step
633  // Reset myVehicleStateChanges
634  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); ++i) {
635  (*i).second.clear();
636  }
637  } catch (std::invalid_argument& e) {
638  throw ProcessError(e.what());
639  } catch (libsumo::TraCIException& e) {
640  throw ProcessError(e.what());
641  } catch (tcpip::SocketException& e) {
642  throw ProcessError(e.what());
643  }
644 }
645 
646 
647 void
649  mySubscriptions.clear();
650  myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
651  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
652  myCurrentSocket->second->targetTime = myTargetTime;
653  }
657  std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i;
658  for (i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); i++) {
659  i->second.clear();
660  }
661  myCurrentSocket = mySockets.begin();
662 }
663 
664 
665 std::map<int, TraCIServer::SocketInfo*>::iterator
667 #ifdef DEBUG_MULTI_CLIENTS
668  std::cout << " Removing socket " << myCurrentSocket->second->socket
669  << " (order " << myCurrentSocket->first << ")" << std::endl;
670 #endif
671 
672  if (mySockets.size() == 1) {
673  // Last client has disconnected
674  delete myCurrentSocket->second->socket;
675  mySockets.clear();
676  myCurrentSocket = mySockets.end();
677  return myCurrentSocket;
678  }
679 
680  const int currOrder = myCurrentSocket->first;
681  delete myCurrentSocket->second->socket;
682  myCurrentSocket++;
683  if (myCurrentSocket != mySockets.end()) {
684  const int nextOrder = myCurrentSocket->first;
685  mySockets.erase(currOrder);
686  myCurrentSocket = mySockets.find(nextOrder);
687  } else {
688  mySockets.erase(currOrder);
689  myCurrentSocket = mySockets.end();
690  }
691  return myCurrentSocket;
692 }
693 
694 
695 int
696 TraCIServer::readCommandID(int& commandStart, int& commandLength) {
697  commandStart = myInputStorage.position();
698  commandLength = myInputStorage.readUnsignedByte();
699  if (commandLength == 0) {
700  commandLength = myInputStorage.readInt();
701  }
702 #ifdef DEBUG_RAW_INPUT
703  std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
704  for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
705  std::cout << (int)*it << " ";
706  }
707  std::cout << "\n";
708 #endif
710 }
711 
712 
713 int
715  int commandStart, commandLength;
716  int commandId = readCommandID(commandStart, commandLength);
717 #ifdef DEBUG_MULTI_CLIENTS
718  std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
719  << ", commandId = " << commandId << std::endl;
720 #endif
721  bool success = false;
722  // dispatch commands
723  if (myExecutors.find(commandId) != myExecutors.end()) {
724  success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
725  } else {
726  switch (commandId) {
728  success = commandGetVersion();
729  break;
730  case libsumo::CMD_LOAD: {
731  std::vector<std::string> args;
733  return writeErrorStatusCmd(libsumo::CMD_LOAD, "A load command needs a list of string arguments.", myOutputStorage);
734  }
735 #ifdef DEBUG_MULTI_CLIENTS
736  std::cout << " commandId == libsumo::CMD_LOAD"
737  << ", args = " << toString(args) << std::endl;
738 #endif
739  try {
740  myLoadArgs = args;
741  success = true;
743  // XXX: This only cares for the client that issued the load command.
744  // Multiclient-load functionality is still to be implemented. Refs #3146.
745  myCurrentSocket->second->socket->sendExact(myOutputStorage);
747  } catch (libsumo::TraCIException& e) {
749  }
750  break;
751  }
752  case libsumo::CMD_SIMSTEP: {
753  const double nextT = myInputStorage.readDouble();
754  if (nextT == 0.) {
755  myCurrentSocket->second->targetTime += DELTA_T;
756  } else {
757  myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
758  }
759 #ifdef DEBUG_MULTI_CLIENTS
760  std::cout << " commandId == libsumo::CMD_SIMSTEP"
761  << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
762 #endif
763  if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
764  // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
765  // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommandsUntilSimStep()
767  }
768  return commandId;
769  }
770  case libsumo::CMD_CLOSE:
772  myCurrentSocket->second->socket->sendExact(myOutputStorage);
774  if (mySockets.size() == 1) {
775  // Last client has closed connection
776  myDoCloseConnection = true;
777  }
778  success = true;
779  break;
780  case libsumo::CMD_SETORDER: {
781  const int order = myInputStorage.readInt();
782 #ifdef DEBUG_MULTI_CLIENTS
783  std::cout << " commandId == libsumo::CMD_SETORDER"
784  << ", order index is " << order << std::endl;
785 #endif
786  if (order > libsumo::MAX_ORDER) {
787  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
788  }
789  if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
790  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
791  }
792  // memorize reorder request (will only take effect in the next step)
793  mySocketReorderRequests[order] = myCurrentSocket->second;
794  success = true;
796  break;
797  }
813  success = addObjectVariableSubscription(commandId, false);
814  break;
830  success = addObjectVariableSubscription(commandId, true);
831  break;
833  success = addSubscriptionFilter();
834  break;
835  default:
836  if (commandId == libsumo::CMD_GET_GUI_VARIABLE || commandId == libsumo::CMD_SET_GUI_VARIABLE) {
837  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
838  } else {
839  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
840  }
841  }
842  }
843  if (!success) {
844  while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
846  }
847  }
848  if ((int)myInputStorage.position() != commandStart + commandLength) {
849  std::ostringstream msg;
850  msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
851  msg << " Expected command length was " << commandLength;
852  msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
853  writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
854  myDoCloseConnection = true;
855  }
856  return commandId;
857 }
858 
859 
860 // ---------- Server-internal command handling
861 bool
863  std::string sumoVersion = VERSION_STRING;
864  // Prepare response
865  tcpip::Storage answerTmp;
866  answerTmp.writeInt(libsumo::TRACI_VERSION);
867  answerTmp.writeString(std::string("SUMO ") + sumoVersion);
868  // When we get here, the response is stored in answerTmp -> put into myOutputStorage
870  // command length
871  myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
872  // command type
874  // and the parameter dependant part
875  myOutputStorage.writeStorage(answerTmp);
876  return true;
877 }
878 
879 
880 void
883 #ifdef DEBUG_MULTI_CLIENTS
884  std::cout << " postProcessSimulationStep() at time " << t << std::endl;
885 #endif
887  int noActive = 0;
888  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
889  const libsumo::Subscription& s = *i;
893  if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
894  i = mySubscriptions.erase(i);
895  continue;
896  }
897  ++i;
898  if (s.beginTime > t) {
899  continue;
900  }
901  ++noActive;
902  }
904 #ifdef DEBUG_SUBSCRIPTIONS
905  std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
906  << "\n Nr. of active subscriptions = " << noActive << std::endl;
907 #endif
908  mySubscriptionCache.writeInt(noActive);
909 #ifdef DEBUG_SUBSCRIPTIONS
910  std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
911 #endif
912  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
913  const libsumo::Subscription& s = *i;
914  if (s.beginTime > t) {
915  ++i;
916  continue;
917  }
918  tcpip::Storage into;
919  std::string errors;
920  bool ok = processSingleSubscription(s, into, errors);
921 #ifdef DEBUG_SUBSCRIPTIONS
922  std::cout << " Size of into-store for subscription " << s.id
923  << ": " << into.size() << std::endl;
924 #endif
926  if (ok) {
927  ++i;
928  } else {
929  i = mySubscriptions.erase(i);
930  }
931  }
933 #ifdef DEBUG_SUBSCRIPTIONS
934  std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
935 #endif
936 }
937 
938 
939 void
941 #ifdef DEBUG_MULTI_CLIENTS
942  std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
943  << " (-> intermediate TraCI step)."
944  << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
945  << std::endl;
946 #endif
948 
949 // NOTE: the commented code would send an empty response
950 // myOutputStorage.writeInt(0);
951 // myCurrentSocket->second->socket->sendExact(myOutputStorage);
952 // myOutputStorage.reset();
954  // send results to active client
955  myCurrentSocket->second->socket->sendExact(myOutputStorage);
957 }
958 
959 
960 void
961 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
962  writeStatusCmd(commandId, status, description, myOutputStorage);
963 }
964 
965 
966 void
967 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
968  if (status == libsumo::RTYPE_ERR) {
969  WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
970  } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
971  WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
972  }
973  outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
974  outputStorage.writeUnsignedByte(commandId); // command type
975  outputStorage.writeUnsignedByte(status); // status
976  outputStorage.writeString(description); // description
977 }
978 
979 
980 bool
981 TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
982  writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
983  return false;
984 }
985 
986 
987 void
989  tcpip::Storage writeInto;
990  std::string errors;
991  libsumo::Subscription* modifiedSubscription = nullptr;
992  if (processSingleSubscription(s, writeInto, errors)) {
994  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
995  } else {
996  bool needNewSubscription = true;
998  if (s.commandId == o.commandId && s.id == o.id &&
999  s.beginTime == o.beginTime && s.endTime == o.endTime &&
1000  s.contextDomain == o.contextDomain && s.range == o.range) {
1001  std::vector<std::vector<unsigned char> >::const_iterator k = s.parameters.begin();
1002  for (std::vector<int>::const_iterator j = s.variables.begin(); j != s.variables.end(); ++j, ++k) {
1003  const int offset = (int)(std::find(o.variables.begin(), o.variables.end(), *j) - o.variables.begin());
1004  if (offset == (int)o.variables.size() || o.parameters[offset] != *k) {
1005  o.variables.push_back(*j);
1006  o.parameters.push_back(*k);
1007  }
1008  }
1009  needNewSubscription = false;
1010  modifiedSubscription = &o;
1011  break;
1012  }
1013  }
1014  if (needNewSubscription) {
1015  mySubscriptions.push_back(s);
1016  modifiedSubscription = &mySubscriptions.back();
1017  // Add new subscription to subscription cache (note: seems a bit inefficient)
1019  // copy new subscription into cache
1020  int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1021  tcpip::Storage tmp;
1022  tmp.writeInt(noActive);
1023  while (mySubscriptionCache.valid_pos()) {
1025  }
1026  tmp.writeStorage(writeInto);
1029  }
1030  }
1032  }
1033  if (modifiedSubscription != nullptr && isVehicleToVehicleContextSubscription(*modifiedSubscription)) {
1034  // Set last modified vehicle context subscription active for filter modifications
1035  myLastContextSubscription = modifiedSubscription;
1036  } else {
1037  // adding other subscriptions deactivates the activation for filter addition
1038  myLastContextSubscription = nullptr;
1039  }
1040  } else {
1041  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1042  }
1043  myOutputStorage.writeStorage(writeInto);
1044 }
1045 
1046 
1047 void
1048 TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1049  bool found = false;
1050  std::vector<libsumo::Subscription>::iterator j;
1051  for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1052  if (j->id == id && j->commandId == commandId && (domain < 0 || j->contextDomain == domain)) {
1053  j = mySubscriptions.erase(j);
1054  if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1055  // Remove also reference for filter additions
1056  myLastContextSubscription = nullptr;
1057  }
1058  found = true;
1059  continue;
1060  }
1061  ++j;
1062  }
1063  // try unsubscribe
1064  if (found) {
1065  writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1066  } else {
1067  writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1068  }
1069 }
1070 
1071 bool
1074 }
1075 
1076 
1077 bool
1079  std::string& errors) {
1080  bool ok = true;
1081  tcpip::Storage outputStorage;
1082  const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1083  std::set<std::string> objIDs;
1084  if (s.contextDomain > 0) {
1086  PositionVector shape;
1089  }
1091  } else {
1092  objIDs.insert(s.id);
1093  }
1094  const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1095  int skipped = 0;
1096  for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1097  if (s.contextDomain > 0) {
1098  //if (centralObject(s, *j)) {
1099  // skipped++;
1100  // continue;
1101  //}
1102  outputStorage.writeString(*j);
1103  }
1104  if (numVars > 0) {
1105  std::vector<std::vector<unsigned char> >::const_iterator k = s.parameters.begin();
1106  for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1107  tcpip::Storage message;
1108  message.writeUnsignedByte(*i);
1109  message.writeString(*j);
1110  message.writePacket(*k);
1111  tcpip::Storage tmpOutput;
1112  if (myExecutors.find(getCommandId) != myExecutors.end()) {
1113  ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1114  } else {
1115  writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1116  ok = false;
1117  }
1118  // copy response part
1119  if (ok) {
1120  int length = tmpOutput.readUnsignedByte();
1121  while (--length > 0) {
1122  tmpOutput.readUnsignedByte();
1123  }
1124  int lengthLength = 1;
1125  length = tmpOutput.readUnsignedByte();
1126  if (length == 0) {
1127  lengthLength = 5;
1128  length = tmpOutput.readInt();
1129  }
1130  //read responseType
1131  tmpOutput.readUnsignedByte();
1132  int variable = tmpOutput.readUnsignedByte();
1133  std::string id = tmpOutput.readString();
1134  outputStorage.writeUnsignedByte(variable);
1135  outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1136  length -= (lengthLength + 1 + 4 + (int)id.length());
1137  while (--length > 0) {
1138  outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1139  }
1140  } else {
1141  //read length
1142  tmpOutput.readUnsignedByte();
1143  //read cmd
1144  tmpOutput.readUnsignedByte();
1145  //read status
1146  tmpOutput.readUnsignedByte();
1147  std::string msg = tmpOutput.readString();
1148  outputStorage.writeUnsignedByte(*i);
1149  outputStorage.writeUnsignedByte(libsumo::RTYPE_ERR);
1150  outputStorage.writeUnsignedByte(libsumo::TYPE_STRING);
1151  outputStorage.writeString(msg);
1152  errors = errors + msg;
1153  }
1154  }
1155  }
1156  }
1157  int length = (1 + 4) + 1 + (4 + (int)(s.id.length())) + 1 + (int)outputStorage.size();
1158  if (s.contextDomain > 0) {
1159  length += 4;
1160  }
1161  writeInto.writeUnsignedByte(0); // command length -> extended
1162  writeInto.writeInt(length);
1163  writeInto.writeUnsignedByte(s.commandId + 0x10);
1164  writeInto.writeString(s.id);
1165  if (s.contextDomain > 0) {
1166  writeInto.writeUnsignedByte(s.contextDomain);
1167  }
1168  writeInto.writeUnsignedByte(numVars);
1169  if (s.contextDomain > 0) {
1170  writeInto.writeInt((int)objIDs.size() - skipped);
1171  }
1172  if (s.contextDomain == 0 || objIDs.size() != 0) {
1173  writeInto.writeStorage(outputStorage);
1174  }
1175  return ok;
1176 }
1177 
1178 
1179 bool
1180 TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1181  const double beginTime = myInputStorage.readDouble();
1182  const double endTime = myInputStorage.readDouble();
1183  const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1184  const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1185  const std::string id = myInputStorage.readString();
1186  const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1187  const double range = hasContext ? myInputStorage.readDouble() : 0.;
1188  const int num = myInputStorage.readUnsignedByte();
1189  std::vector<int> variables;
1190  std::vector<std::vector<unsigned char> > parameters;
1191  for (int i = 0; i < num; ++i) {
1192  const int varID = myInputStorage.readUnsignedByte();
1193  variables.push_back(varID);
1194  parameters.push_back(std::vector<unsigned char>());
1195  for (int j = 0; j < myParameterSizes[varID]; j++) {
1196  parameters.back().push_back(myInputStorage.readChar());
1197  }
1198  }
1199  // check subscribe/unsubscribe
1200  if (variables.size() == 0) {
1201  removeSubscription(commandId, id, -1);
1202  return true;
1203  }
1204  // process subscription
1205  libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1207  return true;
1208 }
1209 
1210 
1211 
1212 bool
1214  bool success = true;
1215  if (myLastContextSubscription == nullptr) {
1216  WRITE_WARNING("addSubscriptionFilter: No previous vehicle context subscription exists to apply the context filter.");
1217  return true;
1218  }
1219  // Read filter type
1220  int filterType = myInputStorage.readUnsignedByte();
1221 
1222  // dispatch according to filter type
1223  switch (filterType) {
1225  // Remove all filters
1226  removeFilters();
1227  break;
1229  // Read relative lanes to consider for context filter
1230  int nrLanes = (int)myInputStorage.readByte();
1231  std::vector<int> lanes;
1232  for (int i = 0; i < nrLanes; ++i) {
1233  lanes.push_back((int) myInputStorage.readByte());
1234  }
1236  }
1237  break;
1239  // Add no-opposite filter
1241  break;
1243  myInputStorage.readByte(); // read type double
1244  double dist = myInputStorage.readDouble();
1246  }
1247  break;
1249  myInputStorage.readByte(); // read type double
1250  double dist = myInputStorage.readDouble();
1252  }
1253  break;
1255  // Read relative lanes to consider for context filter
1257  }
1258  break;
1261  break;
1263  myInputStorage.readByte(); // read type stringlist
1265  addSubscriptionFilterVClass(vClasses);
1266  }
1267  break;
1269  myInputStorage.readByte(); // read type stringlist
1270  std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1271  std::set<std::string> vTypesSet;
1272  vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1273  addSubscriptionFilterVType(vTypesSet);
1274  }
1275  break;
1276  default:
1277  writeStatusCmd(filterType, libsumo::RTYPE_NOTIMPLEMENTED, "'" + toString(filterType) + "' is no valid filter type code.");
1278  success = false;
1279  }
1280 
1281  if (success) {
1282  // acknowledge filter addition
1284  }
1285 
1286  return success;
1287 }
1288 
1289 
1290 void
1292 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1293  std::cout << "Removing filters" << std::endl;
1294 #endif
1296 }
1297 
1298 void
1300 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1301  std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1302 #endif
1305 }
1306 
1307 void
1309 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1310  std::cout << "Adding no opposite filter" << std::endl;
1311 #endif
1313 }
1314 
1315 void
1317 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1318  std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1319 #endif
1322 }
1323 
1324 void
1326 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1327  std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1328 #endif
1331 }
1332 
1333 void
1335 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1336  std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1337 #endif
1339 }
1340 
1341 void
1343 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1344  std::cout << "Adding turn-maneuver filter" << std::endl;
1345 #endif
1347 }
1348 
1349 void
1351 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1352  std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1353 #endif
1356 }
1357 
1358 void
1359 TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1360 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1361  std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1362 #endif
1365 }
1366 
1367 void
1369  if (tempMsg.size() < 254) {
1370  outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1371  } else {
1372  outputStorage.writeUnsignedByte(0); // command length -> extended
1373  outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1374  }
1375  outputStorage.writeStorage(tempMsg);
1376 }
1377 
1378 
1379 void
1382  if (shape.size() < 256) {
1383  outputStorage.writeUnsignedByte((int)shape.size());
1384  } else {
1385  outputStorage.writeUnsignedByte(0);
1386  outputStorage.writeInt((int)shape.size());
1387  }
1388  for (const libsumo::TraCIPosition& pos : shape) {
1389  outputStorage.writeDouble(pos.x);
1390  outputStorage.writeDouble(pos.y);
1391  }
1392 }
1393 
1394 
1395 bool
1397  if (inputStorage.readUnsignedByte() != libsumo::TYPE_INTEGER) {
1398  return false;
1399  }
1400  into = inputStorage.readInt();
1401  return true;
1402 }
1403 
1404 
1405 bool
1407  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLE) {
1408  return false;
1409  }
1410  into = inputStorage.readDouble();
1411  return true;
1412 }
1413 
1414 
1415 bool
1416 TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
1417  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRING) {
1418  return false;
1419  }
1420  into = inputStorage.readString();
1421  return true;
1422 }
1423 
1424 
1425 bool
1426 TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
1427  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRINGLIST) {
1428  return false;
1429  }
1430  into = inputStorage.readStringList();
1431  return true;
1432 }
1433 
1434 
1435 bool
1436 TraCIServer::readTypeCheckingDoubleList(tcpip::Storage& inputStorage, std::vector<double>& into) {
1437  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLELIST) {
1438  return false;
1439  }
1440  into = inputStorage.readDoubleList();
1441  return true;
1442 }
1443 
1444 
1445 bool
1447  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COLOR) {
1448  return false;
1449  }
1450  into.r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1451  into.g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1452  into.b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1453  into.a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1454  return true;
1455 }
1456 
1457 
1458 bool
1460  if (inputStorage.readUnsignedByte() != libsumo::POSITION_2D) {
1461  return false;
1462  }
1463  into.x = inputStorage.readDouble();
1464  into.y = inputStorage.readDouble();
1465  into.z = 0;
1466  return true;
1467 }
1468 
1469 
1470 bool
1472  if (inputStorage.readByte() != libsumo::TYPE_BYTE) {
1473  return false;
1474  }
1475  into = inputStorage.readByte();
1476  return true;
1477 }
1478 
1479 
1480 bool
1482  if (inputStorage.readUnsignedByte() != libsumo::TYPE_UBYTE) {
1483  return false;
1484  }
1485  into = inputStorage.readUnsignedByte();
1486  return true;
1487 }
1488 
1489 
1490 bool
1492  if (inputStorage.readUnsignedByte() != libsumo::TYPE_POLYGON) {
1493  return false;
1494  }
1495  into.clear();
1496  int size = inputStorage.readUnsignedByte();
1497  if (size == 0) {
1498  size = inputStorage.readInt();
1499  }
1500  PositionVector shape;
1501  for (int i = 0; i < size; ++i) {
1502  double x = inputStorage.readDouble();
1503  double y = inputStorage.readDouble();
1504  if (std::isnan(x) || std::isnan(y)) {
1505  throw libsumo::TraCIException("NaN-Value in shape.");
1506  }
1507  into.push_back(Position(x, y));
1508  }
1509  return true;
1510 }
1511 
1512 
1513 void
1515  myTargetTime = targetTime;
1516  for (auto& s : mySockets) {
1517  s.second->targetTime = targetTime;
1518  }
1519 }
1520 
1521 
1522 bool
1523 TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1524  return (s.id == objID && s.commandId + 32 == s.contextDomain);
1525 }
1526 
1527 
1528 /****************************************************************************/
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:540
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:72
void addSubscriptionFilterDownstreamDistance(double dist)
TRACI_CONST int TYPE_COLOR
TRACI_CONST int CMD_SET_POLYGON_VARIABLE
tcpip::Storage mySubscriptionCache
The last timestep&#39;s subscription results.
Definition: TraCIServer.h:374
bool readTypeCheckingColor(tcpip::Storage &inputStorage, libsumo::TraCIColor &into)
Reads the value type and a color, verifying the type.
virtual std::vector< double > readDoubleList()
Representation of a subscription.
Definition: Subscription.h:65
long long int SUMOTime
Definition: SUMOTime.h:35
TRACI_CONST int POSITION_3D
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:484
TRACI_CONST int CMD_GET_TL_VARIABLE
StorageType::const_iterator end() const
Definition: storage.h:121
TRACI_CONST int CMD_SUBSCRIBE_ROUTE_CONTEXT
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)
An edgeId, position and laneIndex.
Definition: TraCIDefs.h:122
bool processSingleSubscription(const libsumo::Subscription &s, tcpip::Storage &writeInto, std::string &errors)
virtual ~TraCIServer()
Destructor.
TRACI_CONST int CMD_GET_LANE_VARIABLE
bool commandGetVersion()
Returns the TraCI-version.
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
TRACI_CONST int CMD_SUBSCRIBE_PERSON_VARIABLE
TRACI_CONST int VAR_LEADER
virtual std::vector< std::string > readStringList()
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc4: Change Vehicle State)
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_VARIABLE
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc7: Change PoI State)
TRACI_CONST int CMD_GET_LANEAREA_VARIABLE
TRACI_CONST int FILTER_TYPE_VCLASS
TRACI_CONST int RTYPE_OK
TRACI_CONST int CMD_ADD_SUBSCRIPTION_FILTER
TRACI_CONST int CMD_GET_ROUTE_VARIABLE
TRACI_CONST int CMD_GET_VEHICLETYPE_VARIABLE
TRACI_CONST int CMD_CLOSE
bool wrapInt(const std::string &objID, const int variable, const int value)
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
TRACI_CONST int CMD_SET_VEHICLE_VARIABLE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa9: Get Junction Variable)
TRACI_CONST int TYPE_DOUBLELIST
virtual double readDouble()
tcpip::Storage myOutputStorage
The storage to write to.
Definition: TraCIServer.h:368
TRACI_CONST int CMD_GET_PERSON_VARIABLE
void initialiseSubscription(libsumo::Subscription &s)
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)
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:168
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:382
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.
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
virtual bool valid_pos()
tcpip::Storage myInputStorage
The storage to read from.
Definition: TraCIServer.h:365
SUMOTime beginTime
The begin time of the subscription.
Definition: Subscription.h:92
TRACI_CONST int CMD_SET_SIM_VARIABLE
virtual void writePacket(unsigned char *packet, int length)
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
bool readTypeCheckingPolygon(tcpip::Storage &inputStorage, PositionVector &into)
Reads the value type and a polygon, verifying the type.
#define TIME2STEPS(x)
Definition: SUMOTime.h:59
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xca: Change Edge State)
bool wrapRoadPosition(const std::string &objID, const int variable, const libsumo::TraCIRoadPosition &value)
virtual void writeUnsignedByte(int)
TRACI_CONST int CMD_SET_POI_VARIABLE
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
TRACI_CONST int FILTER_TYPE_NOOPPOSITE
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_PERSON_CONTEXT
virtual unsigned char readChar()
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:865
TRACI_CONST int RTYPE_ERR
virtual void writeInt(int)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
#define SIMTIME
Definition: SUMOTime.h:64
virtual int readUnsignedByte()
SUMOTime endTime
The end time of the subscription.
Definition: Subscription.h:94
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:346
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:554
TRACI_CONST int TYPE_INTEGER
TRACI_CONST int CMD_GET_POI_VARIABLE
TRACI_CONST int CMD_SET_TL_VARIABLE
std::map< int, CmdExecutor > myExecutors
Map of commandIds -> their executors; applicable if the executor applies to the method footprint...
Definition: TraCIServer.h:377
TRACI_CONST int TYPE_BYTE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get AreaDetector Variable)
TRACI_CONST int FILTER_TYPE_VTYPE
TRACI_CONST int TRACI_ID_LIST
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:84
void removeSubscription(int commandId, const std::string &identity, int domain)
TRACI_CONST int CMD_GET_SIM_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_VARIABLE
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:101
static void close()
request termination of connection
TRACI_CONST int FILTER_TYPE_NONE
TRACI_CONST int CMD_SUBSCRIBE_SIM_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_CONTEXT
bool addObjectVariableSubscription(const int commandId, const bool hasContext)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcb: Set Simulation Variable)
TRACI_CONST int CMD_SUBSCRIBE_EDGE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POI_CONTEXT
The vehicle got a new route.
Definition: MSNet.h:548
The vehicle arrived at his destination (is deleted)
Definition: MSNet.h:546
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
The vehicles starts to park.
Definition: MSNet.h:550
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_VARIABLE
The vehicle is involved in a collision.
Definition: MSNet.h:558
TRACI_CONST int CMD_SET_PERSON_VARIABLE
TRACI_CONST int TYPE_POLYGON
TRACI_CONST int CMD_SUBSCRIBE_SIM_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POI_VARIABLE
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xce: Change Person State)
Representation of a vehicle.
Definition: SUMOVehicle.h:61
bool readTypeCheckingDoubleList(tcpip::Storage &inputStorage, std::vector< double > &into)
Reads the value type and a double list, verifying the type.
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:560
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:798
TRACI_CONST int CMD_GET_VEHICLE_VARIABLE
TRACI_CONST int FILTER_TYPE_UPSTREAM_DIST
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
int filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:111
A list of positions.
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_CONTEXT
TRACI_CONST int CMD_SET_VEHICLETYPE_VARIABLE
virtual void writeByte(int)
bool wrapStringList(const std::string &objID, const int variable, const std::vector< std::string > &value)
TRACI_CONST int CMD_SETORDER
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
TRACI_CONST int FILTER_TYPE_LEAD_FOLLOW
virtual void writeStringList(const std::vector< std::string > &s)
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_VARIABLE
TRACI_CONST int CMD_GET_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_GETVERSION
TRACI_CONST int CMD_SUBSCRIBE_VEHICLETYPE_CONTEXT
TRACI_CONST int CMD_SET_LANE_VARIABLE
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:284
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa5: Get Vehicle Type Variable)
SUMOTime string2time(const std::string &r)
Definition: SUMOTime.cpp:42
TRACI_CONST int TYPE_DOUBLE
T MIN2(T a, T b)
Definition: StdDefs.h:74
void addSubscriptionFilterUpstreamDistance(double dist)
bool addSubscriptionFilter()
TRACI_CONST int FILTER_TYPE_TURN
The vehicle started to teleport.
Definition: MSNet.h:542
tcpip::Storage & getWrapperStorage()
TRACI_CONST int TYPE_STRINGLIST
virtual std::string readString()
libsumo::Subscription * myLastContextSubscription
The last modified context subscription (the one to add a filter to, see (), currently only for vehicl...
Definition: TraCIServer.h:388
virtual unsigned int position() const
void addSubscriptionFilterTurn()
TRACI_CONST int TYPE_STRING
TRACI_CONST int CMD_SUBSCRIBE_TL_CONTEXT
void addSubscriptionFilterLeadFollow()
bool isVehicleToVehicleContextSubscription(const libsumo::Subscription &s)
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:69
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
void removeFilters()
int readCommandID(int &commandStart, int &commandLength)
Reads the next command ID from the input storage.
TRACI_CONST int CMD_SUBSCRIBE_GUI_VARIABLE
static TraCIServer * myInstance
Singleton instance of the server.
Definition: TraCIServer.h:343
TRACI_CONST int VAR_POSITION3D
The vehicle ends to park.
Definition: MSNet.h:552
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa0: Get Induction Loop Variable)
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition: socket.cpp:260
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...
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:118
TRACI_CONST int CMD_SUBSCRIBE_MULTIENTRYEXIT_VARIABLE
bool wrapColor(const std::string &objID, const int variable, const libsumo::TraCIColor &value)
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
TRACI_CONST int CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
#define VERSION_STRING
Definition: config.h:207
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:536
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa7: Get PoI Variable)
TRACI_CONST int TRACI_VERSION
The vehicle was built, but has not yet departed.
Definition: MSNet.h:538
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:245
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)
TRACI_CONST int CMD_SUBSCRIBE_GUI_CONTEXT
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)
static void openSocket(const std::map< int, CmdExecutor > &execs)
Initialises the server.
void writePositionVector(tcpip::Storage &outputStorage, const libsumo::TraCIPositionVector &shape)
TRACI_CONST int MAX_ORDER
virtual void writeString(const std::string &s)
#define SUMOTime_MAX
Definition: SUMOTime.h:36
TRACI_CONST int CMD_SUBSCRIBE_LANE_CONTEXT
TRACI_CONST int CMD_GET_GUI_VARIABLE
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:58
std::vector< TraCIPosition > TraCIPositionVector
Definition: TraCIDefs.h:150
bool wrapPosition(const std::string &objID, const int variable, const libsumo::TraCIPosition &value)
static void collectObjectsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition: Helper.cpp:425
TRACI_CONST int FILTER_TYPE_DOWNSTREAM_DIST
TRACI_CONST int CMD_SUBSCRIBE_TL_VARIABLE
TRACI_CONST int CMD_SET_EDGE_VARIABLE
std::map< int, SocketInfo * >::iterator myCurrentSocket
The currently active client socket.
Definition: TraCIServer.h:359
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
StorageType::const_iterator begin() const
Definition: storage.h:120
void setTargetTime(SUMOTime targetTime)
Sets myTargetTime on server and sockets to the given value.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:118
SUMOTime myTargetTime
The time step to reach until processing the next commands.
Definition: TraCIServer.h:362
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:385
The vehicle ends to stop.
Definition: MSNet.h:556
TRACI_CONST int CMD_SUBSCRIBE_ROUTE_VARIABLE
bool readTypeCheckingPosition2D(tcpip::Storage &inputStorage, libsumo::TraCIPosition &into)
Reads the value type and a 2D position, verifying the type.
TRACI_CONST int TYPE_UBYTE
virtual void writeDouble(double)
TRACI_CONST int CMD_SUBSCRIBE_LANE_VARIABLE
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.
TRACI_CONST int FILTER_TYPE_LANES
TRACI_CONST int CMD_SIMSTEP
TRACI_CONST int CMD_GET_JUNCTION_VARIABLE
tcpip::Storage myWrapperStorage
A temporary storage to let the wrapper write to.
Definition: TraCIServer.h:371
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:353
TRACI_CONST int CMD_LOAD
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:356
TRACI_CONST int POSITION_2D
void initWrapper(const int domainID, const int variable, const std::string &objID)
TRACI_CONST int CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE
TRACI_CONST int CMD_GET_INDUCTIONLOOP_VARIABLE
static void findObjectShape(int domain, const std::string &id, PositionVector &shape)
Definition: Helper.cpp:392
TRACI_CONST int CMD_SUBSCRIBE_MULTIENTRYEXIT_CONTEXT
TRACI_CONST int CMD_GET_EDGE_VARIABLE
TRACI_CONST int RTYPE_NOTIMPLEMENTED
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:240
A 3D-position.
Definition: TraCIDefs.h:110
TRACI_CONST double INVALID_DOUBLE_VALUE
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:397
The vehicle ended being teleported.
Definition: MSNet.h:544
TRACI_CONST int CMD_SUBSCRIBE_EDGE_CONTEXT
TRACI_CONST int CMD_SET_ROUTE_VARIABLE
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)
TRACI_CONST int CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE
tcpip::Socket * myServerSocket
The server socket.
Definition: TraCIServer.h:349
TRACI_CONST int CMD_GET_POLYGON_VARIABLE
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc8: Change Polygon State)
TRACI_CONST int CMD_SET_GUI_VARIABLE
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:380
void checkClientOrdering()
Called once after connection of all clients for executing SET_ORDER (and possibly prior GET_VERSION) ...