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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
28 // TraCI server used to control sumo by a remote TraCI client (e.g., ns2)
29 /****************************************************************************/
30 #include <config.h>
31 
32 #ifdef HAVE_VERSION_H
33 #include <version.h>
34 #endif
35 
36 #include <string>
37 #include <cmath>
38 #include <map>
39 #include <iostream>
40 #include <algorithm>
41 #include <foreign/tcpip/socket.h>
42 #include <foreign/tcpip/storage.h>
43 #include <utils/common/SUMOTime.h>
51 #include <utils/xml/XMLSubSys.h>
52 #include <microsim/MSNet.h>
53 #include <microsim/MSVehicle.h>
54 #include <microsim/MSEdge.h>
57 #include <microsim/MSJunction.h>
58 #include <microsim/MSEdgeControl.h>
59 #include <microsim/MSLane.h>
60 #include <microsim/MSGlobals.h>
62 #include <libsumo/Simulation.h>
63 #include <libsumo/Subscription.h>
64 #include <libsumo/TraCIConstants.h>
65 #include "TraCIServer.h"
68 #include "TraCIServerAPI_Lane.h"
72 #include "TraCIServerAPI_Vehicle.h"
74 #include "TraCIServerAPI_Route.h"
75 #include "TraCIServerAPI_POI.h"
76 #include "TraCIServerAPI_Polygon.h"
77 #include "TraCIServerAPI_Edge.h"
79 #include "TraCIServerAPI_Person.h"
81 #include "TraCIServerAPI_BusStop.h"
89 
90 
91 // ===========================================================================
92 // debug constants
93 // ===========================================================================
94 //#define DEBUG_MULTI_CLIENTS
95 //#define DEBUG_SUBSCRIPTIONS
96 //#define DEBUG_SUBSCRIPTION_FILTERS
97 //#define DEBUG_RAW_INPUT
98 
99 
100 // ===========================================================================
101 // static member definitions
102 // ===========================================================================
105 
106 
107 // ===========================================================================
108 // method definitions
109 // ===========================================================================
110 void
111 TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
116 }
117 
118 
119 bool
120 TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
123  return true;
124 }
125 
126 
127 bool
128 TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
130  myWrapperStorage.writeInt(value);
131  return true;
132 }
133 
134 
135 bool
136 TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
139  return true;
140 }
141 
142 
143 bool
144 TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
147  return true;
148 }
149 
150 
151 bool
152 TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
153  const bool includeZ = variable == libsumo::VAR_POSITION3D;
157  if (includeZ) {
159  }
160  return true;
161 }
162 
163 
164 bool
165 TraCIServer::wrapPositionVector(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIPositionVector& shape) {
167  if (shape.value.size() < 256) {
168  myWrapperStorage.writeUnsignedByte((int)shape.value.size());
169  } else {
171  myWrapperStorage.writeInt((int)shape.value.size());
172  }
173  for (const libsumo::TraCIPosition& pos : shape.value) {
176  }
177  return true;
178 }
179 
180 
181 bool
182 TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
188  return true;
189 }
190 
191 
192 bool
193 TraCIServer::wrapStringDoublePair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, double>& value) {
197  myWrapperStorage.writeString(value.first);
199  myWrapperStorage.writeDouble(value.second);
200  return true;
201 }
202 
203 
204 bool
205 TraCIServer::wrapStringPair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, std::string>& value) {
209  myWrapperStorage.writeString(value.first);
211  myWrapperStorage.writeString(value.second);
212  return true;
213 }
214 
215 
218  return myWrapperStorage;
219 }
220 
221 
222 
223 TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
224  : myTargetTime(begin), myLastContextSubscription(nullptr) {
225 #ifdef DEBUG_MULTI_CLIENTS
226  std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
227 #endif
228  myVehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
229  myVehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
231  myVehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
232  myVehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
233  myVehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
234  myVehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
235  myVehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
236  myVehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
237  myVehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
238  myVehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
239  myVehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
240  myVehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
241 
246 
253 
291  //myExecutors[libsumo::CMD_SET_MEANDATA_VARIABLE] = &TraCIServerAPI_MeanData::processSet;
294 
297  myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER));
298  myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER_WITH_KEY));
299 
300  myDoCloseConnection = false;
301 
302  // display warning if internal lanes are not used
304  WRITE_WARNING("Starting TraCI without using internal lanes!");
305  MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
306  MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
307  }
308 
309  try {
310  WRITE_MESSAGE("***Starting server on port " + toString(port) + " ***");
311  tcpip::Socket serverSocket(port);
312  if (numClients > 1) {
313  WRITE_MESSAGE(" waiting for " + toString(numClients) + " clients...");
314  }
315  while ((int)mySockets.size() < numClients) {
316  int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
317  mySockets[index] = new SocketInfo(serverSocket.accept(true), begin);
318  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
319  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
320  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
321  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
322  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
323  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
324  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
325  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
326  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
327  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
328  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
329  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
330  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
331 
332  mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
333  mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
334  mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
335  mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
336  if (numClients > 1) {
337  WRITE_MESSAGE(" client connected");
338  }
339  }
340  // When got here, all clients have connected
341  if (numClients > 1) {
343  }
344  // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommandsUntilSimStep()
345  myCurrentSocket = mySockets.begin();
346  } catch (tcpip::SocketException& e) {
347  throw ProcessError(e.what());
348  }
349 }
350 
351 
353  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
354  delete myCurrentSocket->second;
355  }
356  cleanup();
357 }
358 
359 
360 // ---------- Initialisation and Shutdown
361 void
362 TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
363  if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
364  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
365  OptionsCont::getOptions().getInt("remote-port"),
366  OptionsCont::getOptions().getInt("num-clients"));
367  for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
368  myInstance->myExecutors[i->first] = i->second;
369  }
370  }
371  if (myInstance != nullptr) {
372  // maybe net was deleted and built again
376  }
377 }
378 
379 
380 void
382  if (myInstance == nullptr) {
383  return;
384  }
385  delete myInstance;
386  myInstance = nullptr;
387  myDoCloseConnection = true;
388 }
389 
390 
391 bool
393  return myDoCloseConnection;
394 }
395 
396 
397 // ---------- Initialisation and Shutdown
398 
399 
400 void
401 TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
402  if (!myDoCloseConnection) {
403  myVehicleStateChanges[to].push_back(vehicle->getID());
404  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
405  i->second->vehicleStateChanges[to].push_back(vehicle->getID());
406  }
407  }
408 }
409 
410 
411 void
412 TraCIServer::transportableStateChanged(const MSTransportable* const transportable, MSNet::TransportableState to, const std::string& /*info*/) {
413  if (!myDoCloseConnection) {
414  myTransportableStateChanges[to].push_back(transportable->getID());
415  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
416  i->second->transportableStateChanges[to].push_back(transportable->getID());
417  }
418  }
419 }
420 
421 
422 void
424 #ifdef DEBUG_MULTI_CLIENTS
425  std::cout << "Checking client order requests." << std::endl;
426 #endif
427  // check for SET_ORDER commands queued by connected clients
428  // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
429  myCurrentSocket = mySockets.begin();
430  while (myCurrentSocket != mySockets.end()) {
431 #ifdef DEBUG_MULTI_CLIENTS
432  std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
433 #endif
434 // bool clientUnordered = true;
435 #ifdef _MSC_VER
436 #pragma warning(push)
437 #pragma warning(disable: 4127) // do not warn about constant conditional expression
438 #endif
439  while (true) {
440 #ifdef _MSC_VER
441 #pragma warning(pop)
442 #endif
444  myCurrentSocket->second->socket->receiveExact(myInputStorage);
445  int commandStart, commandLength;
446  int commandId = readCommandID(commandStart, commandLength);
447 #ifdef DEBUG_MULTI_CLIENTS
448  std::cout << " received command " << commandId << std::endl;
449 #endif
450  // Whether the received command is a permitted command for the initialization phase.
451  // Currently, getVersion and setOrder are permitted.
452  bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
453  if (initCommand) {
454 #ifdef DEBUG_MULTI_CLIENTS
455  std::cout << " Init command. Sending response." << std::endl;
456 #endif
457  // reset input storage to initial state before reading the commandId
458  // (ugly, but we can't just reset the store's iter_ from here)
459  // Giving the commandId to dispatch command didn't work either
460  tcpip::Storage tmp;
463  // we don't know whether the command was set with extended
464  // length syntax or not so we hardcode the length here (#5037)
468 
469  // Handle initialization command completely
470  dispatchCommand();
471  myCurrentSocket->second->socket->sendExact(myOutputStorage);
473  } else {
474 #ifdef DEBUG_MULTI_CLIENTS
475  std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
476 #endif
477  throw ProcessError("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase.");
478  }
479  if (commandId == libsumo::CMD_SETORDER) {
480  // This is what we have waited for.
481  break;
482  }
483  }
484  ++myCurrentSocket;
485  }
486 }
487 
488 
489 void
491  // Process reordering requests
492  if (mySocketReorderRequests.size() > 0) {
493  // process reordering requests
494  std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
495  std::map<int, SocketInfo*>::iterator j;
496 #ifdef DEBUG_MULTI_CLIENTS
497  std::cout << SIMTIME << " Current socket ordering:\n";
498  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
499  std::cout << " " << j->first << ": " << j->second->socket << "\n";
500  }
501  std::cout << "Reordering requests:\n";
502  for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
503  std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
504  }
505  i = mySocketReorderRequests.begin();
506 #endif
507  while (i != mySocketReorderRequests.end()) {
508  j = mySockets.begin();
509  while (j != mySockets.end()) {
510  if (j->second->socket == i->second->socket) {
511  break;
512  } else {
513  j++;
514  }
515  }
516  assert(j != mySockets.end());
517  mySockets.erase(j);
518  mySockets[i->first] = i->second;
519  ++i;
520  }
521  mySocketReorderRequests.clear();
522 #ifdef DEBUG_MULTI_CLIENTS
523  std::cout << "New socket ordering:\n";
524  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
525  std::cout << " " << j->first << ": " << j->second->socket << "\n";
526  }
527  std::cout << std::endl;
528 #endif
529  }
530 }
531 
532 
533 SUMOTime
535 #ifdef DEBUG_MULTI_CLIENTS
536  std::cout << "\n Determining new target time..." << std::endl;
537  if (mySockets.size() == 0) {
538  std::cout << " All clients have disconnected." << std::endl;
539  }
540 #endif
541  std::map<int, SocketInfo*>::const_iterator i;
542  SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
543  for (i = mySockets.begin(); i != mySockets.end(); ++i) {
544 #ifdef DEBUG_MULTI_CLIENTS
545  std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
546 #endif
547  targetTime = MIN2(targetTime, i->second->targetTime);
548  }
549 #ifdef DEBUG_MULTI_CLIENTS
550  std::cout << std::endl;
551 #endif
552  return targetTime;
553 }
554 
555 
556 // send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
557 void
559 #ifdef DEBUG_MULTI_CLIENTS
560  std::cout << "\n Sending subscription results to clients:\n";
561 #endif
562  std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
563  while (i != mySockets.end()) {
564  if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
565  // this client will become active before the next SUMO step. Provide subscription results.
566  i->second->socket->sendExact(myOutputStorage);
567 #ifdef DEBUG_MULTI_CLIENTS
568  std::cout << i->second->socket << "\n";
569 #endif
570  }
571  ++i;
572  }
573 #ifdef DEBUG_MULTI_CLIENTS
574  std::cout << std::endl;
575 #endif
576 }
577 
578 
579 void
581 #ifdef DEBUG_MULTI_CLIENTS
582  std::cout << SIMTIME << " processCommandsUntilSimStep(step = " << step << "):\n" << std::endl;
583 #endif
584  try {
585  const bool firstStep = myCurrentSocket != mySockets.end();
586  // update client order if requested
588  if (!firstStep) {
589  // 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)
590  // update subscription results
592  // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
593  sendOutputToAll();
595  }
596 
597  // determine minimal next target time among clients
599 
600  if (step < myTargetTime) {
601 #ifdef DEBUG_MULTI_CLIENTS
602  if (step < myTargetTime) {
603  std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommandsUntilSimStep()." << std::endl;
604  }
605 #endif
606  return;
607  }
608 
609  // Simulation should run until
610  // 1. end time reached or
611  // 2. got libsumo::CMD_CLOSE or
612  // 3. got libsumo::CMD_LOAD or
613  // 4. Client closes socket connection
614  while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep())) {
615 #ifdef DEBUG_MULTI_CLIENTS
616  std::cout << " Next target time: " << myTargetTime << std::endl;
617 #endif
618  // Iterate over clients and process communication for the ones with target time == myTargetTime
619  myCurrentSocket = mySockets.begin();
620  while (myCurrentSocket != mySockets.end()) {
621 #ifdef DEBUG_MULTI_CLIENTS
622  std::cout << " current socket: " << myCurrentSocket->second->socket
623  << " with target time=" << myCurrentSocket->second->targetTime
624  << std::endl;
625 #endif
626 
627  if (myCurrentSocket->second->targetTime > myTargetTime) {
628  // this client must wait
629 #ifdef DEBUG_MULTI_CLIENTS
630  std::cout << " skipping client " << myCurrentSocket->second->socket
631  << " with target time=" << myCurrentSocket->second->targetTime << std::endl;
632 #endif
633  myCurrentSocket++;
634  continue;
635  }
636  bool done = false;
637  bool closed = false;
638  bool load = false;
639  while (!done && !closed && !load) {
640  if (!myInputStorage.valid_pos()) {
641  // have read request completely, send response if adequate
642  if (myOutputStorage.size() > 0) {
643 #ifdef DEBUG_MULTI_CLIENTS
644  std::cout << " sending response..." << std::endl;
645 #endif
646  // send response to previous query
647  myCurrentSocket->second->socket->sendExact(myOutputStorage);
649  } else {
650 #ifdef DEBUG_MULTI_CLIENTS
651  std::cout << " No input and no output stored (This is the next client)." << std::endl;
652 #endif
653  }
654 #ifdef DEBUG_MULTI_CLIENTS
655  std::cout << " resetting input storage and reading next command..." << std::endl;
656 #endif
657  // Read next request
659  myCurrentSocket->second->socket->receiveExact(myInputStorage);
660  }
661 
663  // dispatch command
664  const int cmd = dispatchCommand();
665 #ifdef DEBUG_MULTI_CLIENTS
666  std::cout << " Received command " << cmd << std::endl;
667 #endif
668  if (cmd == libsumo::CMD_SIMSTEP) {
669 #ifdef DEBUG_MULTI_CLIENTS
670  std::cout << " Received command SIM_STEP, end turn for client " << myCurrentSocket->second->socket << std::endl;
671 #endif
672  done = true;
673  } else if (cmd == libsumo::CMD_LOAD) {
674 #ifdef DEBUG_MULTI_CLIENTS
675  std::cout << " Received command LOAD." << std::endl;
676 #endif
677  load = true;
678  } else if (cmd == libsumo::CMD_CLOSE) {
679 #ifdef DEBUG_MULTI_CLIENTS
680  std::cout << " Received command CLOSE." << std::endl;
681 #endif
682  closed = true;
683  }
684  }
685  }
686  if (done) {
687  // Clear vehicleStateChanges and transportableStateChanges for this client
688  // -> For subsequent TraCI stepping
689  // that is performed within this SUMO step, no updates on vehicle states
690  // belonging to the last SUMO simulation step will be received by this client.
691  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myCurrentSocket->second->vehicleStateChanges.begin(); i != myCurrentSocket->second->vehicleStateChanges.end(); ++i) {
692  (*i).second.clear();
693  }
694  for (std::map<MSNet::TransportableState, std::vector<std::string> >::iterator i = myCurrentSocket->second->transportableStateChanges.begin(); i != myCurrentSocket->second->transportableStateChanges.end(); ++i) {
695  (*i).second.clear();
696  }
697  myCurrentSocket++;
698  } else if (load) {
699  myCurrentSocket = mySockets.end();
700  } else {
701  assert(closed);
702  // remove current socket and increment to next socket in ordering
704  }
705  }
706  if (!myLoadArgs.empty()) {
707 #ifdef DEBUG_MULTI_CLIENTS
708  std::cout << " Breaking loop to load new simulation." << std::endl;
709 #endif
710  break;
711  } else if (myDoCloseConnection) {
712 #ifdef DEBUG_MULTI_CLIENTS
713  std::cout << " Breaking loop because last client closed connection." << std::endl;
714 #endif
715  break;
716  }
717  SUMOTime nextT = nextTargetTime();
718  // minimal target time among clients should have been increased during the last loop through mySockets
719  // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
720  // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
721  // the next call is then usually simulationStep(step=1000) leading to no further increase
722  // and thus a failing assertion here.
723  //assert(myTargetTime < nextT || myDoCloseConnection);
724  myTargetTime = nextT;
725  }
726  // All clients are done with the current time step
727  // Reset myVehicleStateChanges and myTransportableStateChanges
728  for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i = myVehicleStateChanges.begin(); i != myVehicleStateChanges.end(); ++i) {
729  (*i).second.clear();
730  }
731  for (std::map<MSNet::TransportableState, std::vector<std::string> >::iterator i = myTransportableStateChanges.begin(); i != myTransportableStateChanges.end(); ++i) {
732  (*i).second.clear();
733  }
734  } catch (std::invalid_argument& e) {
735  throw ProcessError(e.what());
736  } catch (libsumo::TraCIException& e) {
737  throw ProcessError(e.what());
738  } catch (tcpip::SocketException& e) {
739  throw ProcessError(e.what());
740  }
741 }
742 
743 
744 void
746  mySubscriptions.clear();
747  myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
748  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
749  myCurrentSocket->second->targetTime = myTargetTime;
750  }
754  for (auto& i : myVehicleStateChanges) {
755  i.second.clear();
756  }
757  for (auto& i : myTransportableStateChanges) {
758  i.second.clear();
759  }
760  myCurrentSocket = mySockets.begin();
761 }
762 
763 
764 std::map<int, TraCIServer::SocketInfo*>::iterator
766 #ifdef DEBUG_MULTI_CLIENTS
767  std::cout << " Removing socket " << myCurrentSocket->second->socket
768  << " (order " << myCurrentSocket->first << ")" << std::endl;
769 #endif
770 
771  if (mySockets.size() == 1) {
772  // Last client has disconnected
773  delete myCurrentSocket->second->socket;
774  mySockets.clear();
775  myCurrentSocket = mySockets.end();
776  return myCurrentSocket;
777  }
778 
779  const int currOrder = myCurrentSocket->first;
780  delete myCurrentSocket->second->socket;
781  myCurrentSocket++;
782  if (myCurrentSocket != mySockets.end()) {
783  const int nextOrder = myCurrentSocket->first;
784  mySockets.erase(currOrder);
785  myCurrentSocket = mySockets.find(nextOrder);
786  } else {
787  mySockets.erase(currOrder);
788  myCurrentSocket = mySockets.end();
789  }
790  return myCurrentSocket;
791 }
792 
793 
794 int
795 TraCIServer::readCommandID(int& commandStart, int& commandLength) {
796  commandStart = myInputStorage.position();
797  commandLength = myInputStorage.readUnsignedByte();
798  if (commandLength == 0) {
799  commandLength = myInputStorage.readInt();
800  }
801 #ifdef DEBUG_RAW_INPUT
802  std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
803  for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
804  std::cout << (int)*it << " ";
805  }
806  std::cout << "\n";
807 #endif
809 }
810 
811 
812 int
814  int commandStart, commandLength;
815  int commandId = readCommandID(commandStart, commandLength);
816 #ifdef DEBUG_MULTI_CLIENTS
817  std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
818  << ", commandId = " << commandId << std::endl;
819 #endif
820  bool success = false;
821  // dispatch commands
822  if (myExecutors.find(commandId) != myExecutors.end()) {
823  success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
824  } else {
825  switch (commandId) {
827  success = commandGetVersion();
828  break;
829  case libsumo::CMD_LOAD: {
830  std::vector<std::string> args;
832  return writeErrorStatusCmd(libsumo::CMD_LOAD, "A load command needs a list of string arguments.", myOutputStorage);
833  }
834 #ifdef DEBUG_MULTI_CLIENTS
835  std::cout << " commandId == libsumo::CMD_LOAD"
836  << ", args = " << toString(args) << std::endl;
837 #endif
838  try {
839  myLoadArgs = args;
840  success = true;
842  // XXX: This only cares for the client that issued the load command.
843  // Multiclient-load functionality is still to be implemented. Refs #3146.
844  myCurrentSocket->second->socket->sendExact(myOutputStorage);
846  } catch (libsumo::TraCIException& e) {
848  }
849  break;
850  }
851  case libsumo::CMD_SIMSTEP: {
852  const double nextT = myInputStorage.readDouble();
853  if (nextT == 0.) {
854  myCurrentSocket->second->targetTime += DELTA_T;
855  } else {
856  myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
857  }
858 #ifdef DEBUG_MULTI_CLIENTS
859  std::cout << " commandId == libsumo::CMD_SIMSTEP"
860  << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
861 #endif
862  if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
863  // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
864  // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommandsUntilSimStep()
866  }
867  return commandId;
868  }
869  case libsumo::CMD_CLOSE:
871  myCurrentSocket->second->socket->sendExact(myOutputStorage);
873  if (mySockets.size() == 1) {
874  // Last client has closed connection
875  myDoCloseConnection = true;
876  }
877  success = true;
878  break;
879  case libsumo::CMD_SETORDER: {
880  const int order = myInputStorage.readInt();
881 #ifdef DEBUG_MULTI_CLIENTS
882  std::cout << " commandId == libsumo::CMD_SETORDER"
883  << ", order index is " << order << std::endl;
884 #endif
885  if (order > libsumo::MAX_ORDER) {
886  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
887  }
888  if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
889  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
890  }
891  // memorize reorder request (will only take effect in the next step)
892  mySocketReorderRequests[order] = myCurrentSocket->second;
893  success = true;
895  break;
896  }
912  success = addObjectVariableSubscription(commandId, false);
913  break;
929  success = addObjectVariableSubscription(commandId, true);
930  break;
932  success = addSubscriptionFilter();
933  break;
934  default:
935  if (commandId == libsumo::CMD_GET_GUI_VARIABLE || commandId == libsumo::CMD_SET_GUI_VARIABLE) {
936  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
937  } else {
938  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
939  }
940  }
941  }
942  if (!success) {
943  while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
945  }
946  }
947  if ((int)myInputStorage.position() != commandStart + commandLength) {
948  std::ostringstream msg;
949  msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
950  msg << " Expected command length was " << commandLength;
951  msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
952  writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
953  myDoCloseConnection = true;
954  }
955  return commandId;
956 }
957 
958 
959 // ---------- Server-internal command handling
960 bool
962  // Prepare response
963  tcpip::Storage answerTmp;
964  answerTmp.writeInt(libsumo::TRACI_VERSION);
965  answerTmp.writeString("SUMO " VERSION_STRING);
966  // When we get here, the response is stored in answerTmp -> put into myOutputStorage
968  // command length
969  myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
970  // command type
972  // and the parameter dependant part
973  myOutputStorage.writeStorage(answerTmp);
974  return true;
975 }
976 
977 
978 void
981 #ifdef DEBUG_MULTI_CLIENTS
982  std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
983 #endif
985  int noActive = 0;
986  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
987  const libsumo::Subscription& s = *i;
990 
992  if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
993  i = mySubscriptions.erase(i);
994  continue;
995  }
996  ++i;
997  if (s.beginTime > t) {
998  continue;
999  }
1000  ++noActive;
1001  }
1003 #ifdef DEBUG_SUBSCRIPTIONS
1004  std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
1005  << "\n Nr. of active subscriptions = " << noActive << std::endl;
1006 #endif
1007  mySubscriptionCache.writeInt(noActive);
1008 #ifdef DEBUG_SUBSCRIPTIONS
1009  std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
1010 #endif
1011  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1012  const libsumo::Subscription& s = *i;
1013  if (s.beginTime > t) {
1014  ++i;
1015  continue;
1016  }
1017  tcpip::Storage into;
1018  std::string errors;
1019  bool ok = processSingleSubscription(s, into, errors);
1020 #ifdef DEBUG_SUBSCRIPTIONS
1021  std::cout << " Size of into-store for subscription " << s.id
1022  << ": " << into.size() << std::endl;
1023 #endif
1025  if (ok) {
1026  ++i;
1027  } else {
1028  i = mySubscriptions.erase(i);
1029  }
1030  }
1032 #ifdef DEBUG_SUBSCRIPTIONS
1033  std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1034 #endif
1035 }
1036 
1037 
1038 void
1040 #ifdef DEBUG_MULTI_CLIENTS
1041  std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1042  << " (-> intermediate TraCI step)."
1043  << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1044  << std::endl;
1045 #endif
1047 
1048 // NOTE: the commented code would send an empty response
1049 // myOutputStorage.writeInt(0);
1050 // myCurrentSocket->second->socket->sendExact(myOutputStorage);
1051 // myOutputStorage.reset();
1053  // send results to active client
1054  myCurrentSocket->second->socket->sendExact(myOutputStorage);
1056 }
1057 
1058 
1059 void
1060 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1061  writeStatusCmd(commandId, status, description, myOutputStorage);
1062 }
1063 
1064 
1065 void
1066 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1067  if (status == libsumo::RTYPE_ERR) {
1068  WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1069  } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1070  WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1071  }
1072  outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1073  outputStorage.writeUnsignedByte(commandId); // command type
1074  outputStorage.writeUnsignedByte(status); // status
1075  outputStorage.writeString(description); // description
1076 }
1077 
1078 
1079 bool
1080 TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1081  writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1082  return false;
1083 }
1084 
1085 
1086 void
1088  tcpip::Storage writeInto;
1089  std::string errors;
1090  libsumo::Subscription* modifiedSubscription = nullptr;
1091  if (processSingleSubscription(s, writeInto, errors)) {
1093  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1094  } else {
1095  if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1096  // Add new subscription to subscription cache (note: seems a bit inefficient)
1098  // copy new subscription into cache
1099  int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1100  tcpip::Storage tmp;
1101  tmp.writeInt(noActive);
1102  while (mySubscriptionCache.valid_pos()) {
1104  }
1105  tmp.writeStorage(writeInto);
1108  }
1109  }
1111  }
1112  if (modifiedSubscription != nullptr && (
1113  modifiedSubscription->isVehicleToVehicleContextSubscription()
1114  || modifiedSubscription->isVehicleToPersonContextSubscription())) {
1115  // Set last modified vehicle context subscription active for filter modifications
1116  myLastContextSubscription = modifiedSubscription;
1117  } else {
1118  // adding other subscriptions deactivates the activation for filter addition
1119  myLastContextSubscription = nullptr;
1120  }
1121  } else {
1122  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1123  }
1124  myOutputStorage.writeStorage(writeInto);
1125 }
1126 
1127 
1128 void
1129 TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1130  bool found = false;
1131  std::vector<libsumo::Subscription>::iterator j;
1132  for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1133  if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1134  j = mySubscriptions.erase(j);
1135  if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1136  // Remove also reference for filter additions
1137  myLastContextSubscription = nullptr;
1138  }
1139  found = true;
1140  continue;
1141  }
1142  ++j;
1143  }
1144  // try unsubscribe
1145  if (found) {
1146  writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1147  } else {
1148  writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1149  }
1150 }
1151 
1152 
1153 bool
1155  std::string& errors) {
1156  bool ok = true;
1157  tcpip::Storage outputStorage;
1158  const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1159  std::set<std::string> objIDs;
1160  if (s.contextDomain > 0) {
1162  PositionVector shape;
1165  }
1167  } else {
1168  objIDs.insert(s.id);
1169  }
1170  const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1171  int skipped = 0;
1172  for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1173  if (s.contextDomain > 0) {
1174  //if (centralObject(s, *j)) {
1175  // skipped++;
1176  // continue;
1177  //}
1178  outputStorage.writeString(*j);
1179  }
1180  if (numVars > 0) {
1181  std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1182  for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1183  tcpip::Storage message;
1184  message.writeUnsignedByte(*i);
1185  message.writeString(*j);
1186  // TODO check why writeStorage fails here (probably some kind of invalid iterator)
1187  for (const auto& v :** k) {
1188  message.writeChar(v);
1189  }
1190  tcpip::Storage tmpOutput;
1191  if (myExecutors.find(getCommandId) != myExecutors.end()) {
1192  ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1193  } else {
1194  writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1195  ok = false;
1196  }
1197  // copy response part
1198  if (ok) {
1199  int length = tmpOutput.readUnsignedByte();
1200  while (--length > 0) {
1201  tmpOutput.readUnsignedByte();
1202  }
1203  int lengthLength = 1;
1204  length = tmpOutput.readUnsignedByte();
1205  if (length == 0) {
1206  lengthLength = 5;
1207  length = tmpOutput.readInt();
1208  }
1209  //read responseType
1210  tmpOutput.readUnsignedByte();
1211  int variable = tmpOutput.readUnsignedByte();
1212  std::string id = tmpOutput.readString();
1213  outputStorage.writeUnsignedByte(variable);
1214  outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1215  length -= (lengthLength + 1 + 4 + (int)id.length());
1216  while (--length > 0) {
1217  outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1218  }
1219  } else {
1220  //read length
1221  tmpOutput.readUnsignedByte();
1222  //read cmd
1223  tmpOutput.readUnsignedByte();
1224  //read status
1225  tmpOutput.readUnsignedByte();
1226  std::string msg = tmpOutput.readString();
1227  outputStorage.writeUnsignedByte(*i);
1228  outputStorage.writeUnsignedByte(libsumo::RTYPE_ERR);
1229  outputStorage.writeUnsignedByte(libsumo::TYPE_STRING);
1230  outputStorage.writeString(msg);
1231  errors = errors + msg;
1232  }
1233  }
1234  }
1235  }
1236  int length = (1 + 4) + 1 + (4 + (int)(s.id.length())) + 1 + (int)outputStorage.size();
1237  if (s.contextDomain > 0) {
1238  length += 4;
1239  }
1240  writeInto.writeUnsignedByte(0); // command length -> extended
1241  writeInto.writeInt(length);
1242  writeInto.writeUnsignedByte(s.commandId + 0x10);
1243  writeInto.writeString(s.id);
1244  if (s.contextDomain > 0) {
1245  writeInto.writeUnsignedByte(s.contextDomain);
1246  }
1247  writeInto.writeUnsignedByte(numVars);
1248  if (s.contextDomain > 0) {
1249  writeInto.writeInt((int)objIDs.size() - skipped);
1250  }
1251  if (s.contextDomain == 0 || objIDs.size() != 0) {
1252  writeInto.writeStorage(outputStorage);
1253  }
1254  return ok;
1255 }
1256 
1257 
1258 bool
1259 TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1260  const double beginTime = myInputStorage.readDouble();
1261  const double endTime = myInputStorage.readDouble();
1262  const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1263  const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1264  const std::string id = myInputStorage.readString();
1265  const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1266  const double range = hasContext ? myInputStorage.readDouble() : 0.;
1267  const int num = myInputStorage.readUnsignedByte();
1268  std::vector<int> variables;
1269  std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1270  for (int i = 0; i < num; ++i) {
1271  const int varID = myInputStorage.readUnsignedByte();
1272  variables.push_back(varID);
1273  parameters.push_back(std::make_shared<tcpip::Storage>());
1274  if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1275  const int parType = myInputStorage.readUnsignedByte();
1276  parameters.back()->writeUnsignedByte(parType);
1277  if (parType == libsumo::TYPE_DOUBLE) {
1278  parameters.back()->writeDouble(myInputStorage.readDouble());
1279  } else if (parType == libsumo::TYPE_STRING) {
1280  parameters.back()->writeString(myInputStorage.readString());
1281  } else {
1282  // Error!
1283  }
1284  }
1285  }
1286  // check subscribe/unsubscribe
1287  if (variables.empty()) {
1288  removeSubscription(commandId, id, domain);
1289  return true;
1290  }
1291  // process subscription
1292  libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1294  return true;
1295 }
1296 
1297 
1298 
1299 bool
1301  bool success = true;
1302  // Read filter type
1303  int filterType = myInputStorage.readUnsignedByte();
1304 
1305  if (myLastContextSubscription == nullptr) {
1306  writeStatusCmd(filterType, libsumo::RTYPE_ERR, "No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1307  return false;
1308  }
1309 
1310  // dispatch according to filter type
1311  switch (filterType) {
1313  // Remove all filters
1314  removeFilters();
1315  break;
1317  // Read relative lanes to consider for context filter
1318  int nrLanes = (int)myInputStorage.readByte();
1319  std::vector<int> lanes;
1320  for (int i = 0; i < nrLanes; ++i) {
1321  lanes.push_back((int) myInputStorage.readByte());
1322  }
1324  }
1325  break;
1327  // Add no-opposite filter
1329  break;
1331  myInputStorage.readByte(); // read type double
1332  double dist = myInputStorage.readDouble();
1334  }
1335  break;
1337  myInputStorage.readByte(); // read type double
1338  double dist = myInputStorage.readDouble();
1340  }
1341  break;
1343  // Read relative lanes to consider for context filter
1345  }
1346  break;
1348  myInputStorage.readByte(); // read type double
1349  double dist = myInputStorage.readDouble();
1351  }
1352  break;
1354  myInputStorage.readByte(); // read type stringlist
1356  addSubscriptionFilterVClass(vClasses);
1357  }
1358  break;
1360  myInputStorage.readByte(); // read type stringlist
1361  std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1362  std::set<std::string> vTypesSet;
1363  vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1364  addSubscriptionFilterVType(vTypesSet);
1365  }
1366  break;
1368  myInputStorage.readByte(); // read type double
1369  double angle = myInputStorage.readDouble();
1371  }
1372  break;
1374  myInputStorage.readByte(); // read type double
1375  double dist = myInputStorage.readDouble();
1377  }
1378  break;
1379  default:
1380  writeStatusCmd(filterType, libsumo::RTYPE_NOTIMPLEMENTED, "'" + toString(filterType) + "' is no valid filter type code.");
1381  success = false;
1382  }
1383 
1384  if (success) {
1385  // acknowledge filter addition
1387  }
1388 
1389  return success;
1390 }
1391 
1392 
1393 void
1395 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1396  std::cout << "Removing filters" << std::endl;
1397 #endif
1399 }
1400 
1401 void
1403 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1404  std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1405 #endif
1408 }
1409 
1410 void
1412 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1413  std::cout << "Adding no opposite filter" << std::endl;
1414 #endif
1416 }
1417 
1418 void
1420 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1421  std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1422 #endif
1425 }
1426 
1427 void
1429 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1430  std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1431 #endif
1434 }
1435 
1436 void
1438 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1439  std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1440 #endif
1442 }
1443 
1444 void
1446 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1447  std::cout << "Adding turn-maneuver filter" << std::endl;
1448 #endif
1451 }
1452 
1453 void
1455 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1456  std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1457 #endif
1460 }
1461 
1462 void
1463 TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1464 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1465  std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1466 #endif
1469 }
1470 
1471 void
1473 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1474  std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1475 #endif
1478 }
1479 
1480 void
1482 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1483  std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1484 #endif
1487 }
1488 
1489 void
1491  if (tempMsg.size() < 254) {
1492  outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1493  } else {
1494  outputStorage.writeUnsignedByte(0); // command length -> extended
1495  outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1496  }
1497  outputStorage.writeStorage(tempMsg);
1498 }
1499 
1500 
1501 void
1504  if (shape.value.size() < 256) {
1505  outputStorage.writeUnsignedByte((int)shape.value.size());
1506  } else {
1507  outputStorage.writeUnsignedByte(0);
1508  outputStorage.writeInt((int)shape.value.size());
1509  }
1510  for (const libsumo::TraCIPosition& pos : shape.value) {
1511  outputStorage.writeDouble(pos.x);
1512  outputStorage.writeDouble(pos.y);
1513  }
1514 }
1515 
1516 
1517 bool
1519  if (inputStorage.readUnsignedByte() != libsumo::TYPE_INTEGER) {
1520  return false;
1521  }
1522  into = inputStorage.readInt();
1523  return true;
1524 }
1525 
1526 
1527 bool
1529  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLE) {
1530  return false;
1531  }
1532  into = inputStorage.readDouble();
1533  return true;
1534 }
1535 
1536 
1537 bool
1538 TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
1539  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRING) {
1540  return false;
1541  }
1542  into = inputStorage.readString();
1543  return true;
1544 }
1545 
1546 
1547 bool
1548 TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
1549  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRINGLIST) {
1550  return false;
1551  }
1552  into = inputStorage.readStringList();
1553  return true;
1554 }
1555 
1556 
1557 bool
1558 TraCIServer::readTypeCheckingDoubleList(tcpip::Storage& inputStorage, std::vector<double>& into) {
1559  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLELIST) {
1560  return false;
1561  }
1562  into = inputStorage.readDoubleList();
1563  return true;
1564 }
1565 
1566 
1567 bool
1569  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COLOR) {
1570  return false;
1571  }
1572  into.r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1573  into.g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1574  into.b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1575  into.a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1576  return true;
1577 }
1578 
1579 
1580 bool
1582  if (inputStorage.readUnsignedByte() != libsumo::POSITION_2D) {
1583  return false;
1584  }
1585  into.x = inputStorage.readDouble();
1586  into.y = inputStorage.readDouble();
1587  into.z = 0;
1588  return true;
1589 }
1590 
1591 
1592 bool
1594  if (inputStorage.readByte() != libsumo::TYPE_BYTE) {
1595  return false;
1596  }
1597  into = inputStorage.readByte();
1598  return true;
1599 }
1600 
1601 
1602 bool
1604  if (inputStorage.readUnsignedByte() != libsumo::TYPE_UBYTE) {
1605  return false;
1606  }
1607  into = inputStorage.readUnsignedByte();
1608  return true;
1609 }
1610 
1611 
1612 bool
1614  if (inputStorage.readUnsignedByte() != libsumo::TYPE_POLYGON) {
1615  return false;
1616  }
1617  into.clear();
1618  int size = inputStorage.readUnsignedByte();
1619  if (size == 0) {
1620  size = inputStorage.readInt();
1621  }
1622  PositionVector shape;
1623  for (int i = 0; i < size; ++i) {
1624  double x = inputStorage.readDouble();
1625  double y = inputStorage.readDouble();
1626  if (std::isnan(x) || std::isnan(y)) {
1627  throw libsumo::TraCIException("NaN-Value in shape.");
1628  }
1629  into.push_back(Position(x, y));
1630  }
1631  return true;
1632 }
1633 
1634 
1635 void
1637  myTargetTime = targetTime;
1638  for (auto& s : mySockets) {
1639  s.second->targetTime = targetTime;
1640  for (auto& stateChange : s.second->vehicleStateChanges) {
1641  stateChange.second.clear();
1642  }
1643  for (auto& stateChange : s.second->transportableStateChanges) {
1644  stateChange.second.clear();
1645  }
1646  }
1647  mySubscriptions.clear();
1649 }
1650 
1651 
1652 bool
1653 TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1654  return (s.id == objID && s.commandId + 32 == s.contextDomain);
1655 }
1656 
1657 
1658 /****************************************************************************/
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:282
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define STEPS2TIME(x)
Definition: SUMOTime.h:53
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define SIMTIME
Definition: SUMOTime.h:60
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
T MIN2(T a, T b)
Definition: StdDefs.h:74
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:56
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static bool gUseMesoSim
Definition: MSGlobals.h:94
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:72
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:594
@ ENDING_PARKING
The vehicle ends to park.
@ STARTING_STOP
The vehicles starts to stop.
@ BUILT
The vehicle was built, but has not yet departed.
@ STARTING_PARKING
The vehicles starts to park.
@ NEWROUTE
The vehicle got a new route.
@ STARTING_TELEPORT
The vehicle started to teleport.
@ ENDING_STOP
The vehicle ends to stop.
@ ENDING_TELEPORT
The vehicle ended being teleported.
@ ARRIVED
The vehicle arrived at his destination (is deleted)
@ DEPARTED
The vehicle has departed (was inserted into the network)
@ COLLISION
The vehicle is involved in a collision.
@ EMERGENCYSTOP
The vehicle had to brake harder than permitted.
@ MANEUVERING
Vehicle maneuvering either entering or exiting a parking space.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:1127
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition: MSNet.cpp:1155
TransportableState
Definition of a transportable state.
Definition: MSNet.h:671
@ CONTAINER_DEPARTED
The transportable container has departed (was inserted into the network)
@ PERSON_DEPARTED
The transportable person has departed (was inserted into the network)
@ PERSON_ARRIVED
The transportable person arrived at his destination (is deleted)
@ CONTAINER_ARRIVED
The transportable container arrived at his destination (is deleted)
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1059
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:117
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
A list of positions.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change BusStop State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get BusStop Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Calibrator State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get Calibrator Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get ChargingStation Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change ChargingStation State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xca: Change Edge State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xaa: Get Edge Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa0: Get Induction Loop Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc0: Set Induction Loop Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc9: Set Junction Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa9: Get Junction Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get AreaDetector Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcd: Set AreaDetector Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa3: Get Lane Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc3: Change Lane State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get MeanData Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc1: Set MeMeDetector Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa1: Get MeMeDetector Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get OverheadWire Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change OverheadWire State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc7: Change PoI State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa7: Get PoI Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change ParkingArea State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get ParkingArea Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xae: Get Person Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xce: Change Person State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc8: Change Polygon State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa8: Get Polygon Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get Rerouter Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Rerouter State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Route State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get Route Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change RouteProbe State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get RouteProbe Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcb: Set Simulation Variable)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xab: Get Simulation Variable)
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 0xc2: Change Traffic Lights State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change VariableSpeedSign State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa6: Get VariableSpeedSign Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc4: Change Vehicle State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa4: Get Vehicle Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc5: Change Vehicle Type State)
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa5: Get Vehicle Type Variable)
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:59
void addSubscriptionFilterDownstreamDistance(double dist)
static bool myDoCloseConnection
Whether the connection was set to be to close.
Definition: TraCIServer.h:359
bool wrapStringDoublePair(const std::string &objID, const int variable, const std::pair< std::string, double > &value)
tcpip::Storage myWrapperStorage
A temporary storage to let the wrapper write to.
Definition: TraCIServer.h:381
std::map< int, SocketInfo * > mySockets
The socket connections to the clients the first component (index) determines the client's order (lowe...
Definition: TraCIServer.h:363
void addSubscriptionFilterLateralDistance(double dist)
Filter only vehicles within the given lateral distance.
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
static bool wasClosed()
check whether close was requested
void addSubscriptionFilterTurn(double dist)
bool centralObject(const libsumo::Subscription &s, const std::string &objID)
check whether a found objID refers to the central object of a context subscription
std::map< int, SocketInfo * >::iterator myCurrentSocket
The currently active client socket.
Definition: TraCIServer.h:369
bool wrapPositionVector(const std::string &objID, const int variable, const libsumo::TraCIPositionVector &value)
void addSubscriptionFilterVType(std::set< std::string > vTypes)
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
bool wrapInt(const std::string &objID, const int variable, const int value)
bool readTypeCheckingByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and a byte, verifying the type.
std::map< int, SocketInfo * >::iterator removeCurrentSocket()
removes myCurrentSocket from mySockets and returns an iterator pointing to the next member according ...
tcpip::Storage myOutputStorage
The storage to write to.
Definition: TraCIServer.h:378
bool addObjectVariableSubscription(const int commandId, const bool hasContext)
void addSubscriptionFilterUpstreamDistance(double dist)
void stateLoaded(SUMOTime targetTime)
updates myTargetTime and resets vehicle state changes after loading a simulation state
void addSubscriptionFilterLeadFollow()
void addSubscriptionFilterNoOpposite()
tcpip::Storage & getWrapperStorage()
SUMOTime nextTargetTime() const
get the minimal next target time among all clients
std::map< MSNet::TransportableState, std::vector< std::string > > myTransportableStateChanges
Changes in the states of simulated transportables.
Definition: TraCIServer.h:416
void removeSubscription(int commandId, const std::string &identity, int domain)
bool wrapDouble(const std::string &objID, const int variable, const double value)
tcpip::Storage mySubscriptionCache
The last timestep's subscription results.
Definition: TraCIServer.h:384
bool readTypeCheckingUnsignedByte(tcpip::Storage &inputStorage, int &into)
Reads the value type and an unsigned byte, verifying the type.
bool wrapColor(const std::string &objID, const int variable, const libsumo::TraCIColor &value)
bool wrapString(const std::string &objID, const int variable, const std::string &value)
int dispatchCommand()
Handles command, writes response to myOutputStorage.
void initWrapper(const int domainID, const int variable, const std::string &objID)
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
void checkClientOrdering()
Called once after connection of all clients for executing SET_ORDER (and possibly prior GET_VERSION) ...
bool readTypeCheckingPosition2D(tcpip::Storage &inputStorage, libsumo::TraCIPosition &into)
Reads the value type and a 2D position, verifying the type.
void processReorderingRequests()
checks for and processes reordering requests (relevant for multiple clients)
void sendOutputToAll() const
send out subscription results (actually just the content of myOutputStorage) to clients which will ac...
void cleanup()
clean up subscriptions
static void close()
request termination of connection
void processCommandsUntilSimStep(SUMOTime step)
process all commands until the next SUMO simulation step. It is guaranteed that t->getTargetTime() >=...
void postProcessSimulationStep()
Handles subscriptions to send after a simstep2 command.
bool readTypeCheckingInt(tcpip::Storage &inputStorage, int &into)
Reads the value type and an int, verifying the type.
bool commandGetVersion()
Returns the TraCI-version.
bool wrapPosition(const std::string &objID, const int variable, const libsumo::TraCIPosition &value)
static void openSocket(const std::map< int, CmdExecutor > &execs)
Initialises the server.
std::vector< std::string > myLoadArgs
Definition: TraCIServer.h:392
void removeFilters()
void addSubscriptionFilterLanes(std::vector< int > lanes)
bool readTypeCheckingDoubleList(tcpip::Storage &inputStorage, std::vector< double > &into)
Reads the value type and a double list, verifying the type.
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
SUMOTime myTargetTime
The time step to reach until processing the next commands.
Definition: TraCIServer.h:372
virtual ~TraCIServer()
Destructor.
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
void writePositionVector(tcpip::Storage &outputStorage, const libsumo::TraCIPositionVector &shape)
bool wrapStringPair(const std::string &objID, const int variable, const std::pair< std::string, std::string > &value)
std::map< MSNet::VehicleState, std::vector< std::string > > myVehicleStateChanges
Changes in the states of simulated vehicles.
Definition: TraCIServer.h:407
int readCommandID(int &commandStart, int &commandLength)
Reads the next command ID from the input storage.
void sendSingleSimStepResponse()
sends an empty response to a simstep command to the current client. (This applies to a situation wher...
std::map< int, CmdExecutor > myExecutors
Map of commandIds -> their executors; applicable if the executor applies to the method footprint.
Definition: TraCIServer.h:387
std::vector< libsumo::Subscription > mySubscriptions
The list of known, still valid subscriptions.
Definition: TraCIServer.h:395
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
TraCIServer(const SUMOTime begin, const int port, const int numClients)
Constructor.
tcpip::Storage myInputStorage
The storage to read from.
Definition: TraCIServer.h:375
libsumo::Subscription * myLastContextSubscription
The last modified context subscription (the one to add a filter to, see @addSubscriptionFilter(),...
Definition: TraCIServer.h:398
void addSubscriptionFilterVClass(SVCPermissions vClasses)
static TraCIServer * myInstance
Singleton instance of the server.
Definition: TraCIServer.h:356
std::map< int, SocketInfo * > mySocketReorderRequests
This stores the setOrder(int) requests of the clients.
Definition: TraCIServer.h:366
bool addSubscriptionFilter()
std::set< std::pair< int, int > > myParameterized
Set of variables which have parameters.
Definition: TraCIServer.h:390
void transportableStateChanged(const MSTransportable *const transportable, MSNet::TransportableState to, const std::string &info="")
Called if a transportable changes its state.
bool processSingleSubscription(const libsumo::Subscription &s, tcpip::Storage &writeInto, std::string &errors)
void initialiseSubscription(libsumo::Subscription &s)
bool readTypeCheckingPolygon(tcpip::Storage &inputStorage, PositionVector &into)
Reads the value type and a polygon, verifying the type.
void addSubscriptionFilterFieldOfVision(double openingAngle)
Filter only vehicles within field of vision.
bool wrapStringList(const std::string &objID, const int variable, const std::vector< std::string > &value)
bool readTypeCheckingColor(tcpip::Storage &inputStorage, libsumo::TraCIColor &into)
Reads the value type and a color, verifying the type.
static void findObjectShape(int domain, const std::string &id, PositionVector &shape)
Definition: Helper.cpp:733
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:814
static void collectObjectIDsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition: Helper.cpp:766
static bool needNewSubscription(libsumo::Subscription &s, std::vector< Subscription > &subscriptions, libsumo::Subscription *&modifiedSubscription)
Definition: Helper.cpp:208
Representation of a subscription.
Definition: Subscription.h:69
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
Definition: Subscription.h:136
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:113
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
Definition: Subscription.h:140
double filterFieldOfVisionOpeningAngle
Opening angle (in deg) specified by the field of vision filter.
Definition: Subscription.h:144
std::vector< int > filterLanes
lanes specified by the lanes filter
Definition: Subscription.h:132
std::string id
The id of the object that is subscribed.
Definition: Subscription.h:115
int filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:142
SUMOTime endTime
The end time of the subscription.
Definition: Subscription.h:123
int contextDomain
The domain ID of the context.
Definition: Subscription.h:125
double filterFoeDistToJunction
Foe distance to junction specified by the turn filter.
Definition: Subscription.h:138
bool isVehicleToVehicleContextSubscription() const
Definition: Subscription.h:104
SUMOTime beginTime
The begin time of the subscription.
Definition: Subscription.h:121
std::vector< int > variables
The subscribed variables.
Definition: Subscription.h:117
bool isVehicleToPersonContextSubscription() const
Definition: Subscription.h:108
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
Definition: Subscription.h:134
double filterLateralDist
Lateral distance specified by the lateral distance filter.
Definition: Subscription.h:146
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:130
double range
The range of the context.
Definition: Subscription.h:127
std::vector< std::shared_ptr< tcpip::Storage > > parameters
The parameters for the subscribed variables.
Definition: Subscription.h:119
An error which allows to continue.
Definition: TraCIDefs.h:130
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition: socket.cpp:261
StorageType::const_iterator begin() const
Definition: storage.h:121
virtual unsigned char readChar()
Definition: storage.cpp:102
virtual std::string readString()
Definition: storage.cpp:180
virtual void writeString(const std::string &s)
Definition: storage.cpp:197
virtual unsigned int position() const
Definition: storage.cpp:76
virtual void writeInt(int)
Definition: storage.cpp:321
StorageType::const_iterator end() const
Definition: storage.h:122
virtual void writeDouble(double)
Definition: storage.cpp:354
virtual int readUnsignedByte()
Definition: storage.cpp:155
virtual void writeStringList(const std::vector< std::string > &s)
Definition: storage.cpp:247
virtual void writeChar(unsigned char)
Definition: storage.cpp:116
void reset()
Definition: storage.cpp:85
virtual void writeUnsignedByte(int)
Definition: storage.cpp:165
StorageType::size_type size() const
Definition: storage.h:119
virtual bool valid_pos()
Definition: storage.cpp:69
virtual void writeByte(int)
Definition: storage.cpp:140
virtual void writeStorage(tcpip::Storage &store)
Definition: storage.cpp:388
virtual int readByte()
Definition: storage.cpp:128
virtual std::vector< std::string > readStringList()
Definition: storage.cpp:211
virtual double readDouble()
Definition: storage.cpp:362
virtual int readInt()
Definition: storage.cpp:311
virtual std::vector< double > readDoubleList()
Definition: storage.cpp:229
TRACI_CONST double INVALID_DOUBLE_VALUE
TRACI_CONST int TYPE_COLOR
TRACI_CONST int CMD_SUBSCRIBE_SIM_VARIABLE
TRACI_CONST int FILTER_TYPE_DOWNSTREAM_DIST
TRACI_CONST int CMD_LOAD
TRACI_CONST int CMD_SET_JUNCTION_VARIABLE
TRACI_CONST int POSITION_3D
TRACI_CONST int CMD_GET_CHARGINGSTATION_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_EDGE_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE
TRACI_CONST int RTYPE_NOTIMPLEMENTED
TRACI_CONST int CMD_SUBSCRIBE_LANE_CONTEXT
TRACI_CONST int FILTER_TYPE_NOOPPOSITE
TRACI_CONST int CMD_SET_OVERHEADWIRE_VARIABLE
TRACI_CONST int TRACI_ID_LIST
TRACI_CONST int CMD_GET_PARKINGAREA_VARIABLE
TRACI_CONST int CMD_GET_POI_VARIABLE
TRACI_CONST int CMD_GET_TL_VARIABLE
TRACI_CONST int CMD_SET_EDGE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_CONTEXT
TRACI_CONST int CMD_GET_REROUTER_VARIABLE
TRACI_CONST int CMD_GET_VEHICLE_VARIABLE
TRACI_CONST int CMD_SET_CALIBRATOR_VARIABLE
TRACI_CONST int CMD_GET_EDGE_VARIABLE
TRACI_CONST int CMD_GET_CALIBRATOR_VARIABLE
TRACI_CONST int MAX_ORDER
TRACI_CONST int CMD_SUBSCRIBE_TL_CONTEXT
TRACI_CONST int FILTER_TYPE_FIELD_OF_VISION
TRACI_CONST int TYPE_COMPOUND
TRACI_CONST int CMD_SET_REROUTER_VARIABLE
TRACI_CONST int CMD_GET_PERSON_VARIABLE
TRACI_CONST int CMD_SET_VARIABLESPEEDSIGN_VARIABLE
TRACI_CONST int TYPE_UBYTE
TRACI_CONST int CMD_SUBSCRIBE_GUI_VARIABLE
TRACI_CONST int CMD_SET_POI_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_ROUTE_CONTEXT
TRACI_CONST int CMD_GET_ROUTEPROBE_VARIABLE
TRACI_CONST int CMD_GET_LANEAREA_VARIABLE
TRACI_CONST int CMD_SET_POLYGON_VARIABLE
TRACI_CONST int POSITION_2D
TRACI_CONST int CMD_GET_BUSSTOP_VARIABLE
TRACI_CONST int VAR_LEADER
TRACI_CONST int CMD_CLOSE
TRACI_CONST int TYPE_POLYGON
TRACI_CONST int CMD_GET_ROUTE_VARIABLE
TRACI_CONST int CMD_SET_ROUTE_VARIABLE
TRACI_CONST int CMD_SETORDER
TRACI_CONST int FILTER_TYPE_VTYPE
TRACI_CONST int TYPE_STRINGLIST
TRACI_CONST int CMD_SET_SIM_VARIABLE
TRACI_CONST int TYPE_INTEGER
TRACI_CONST int CMD_ADD_SUBSCRIPTION_FILTER
TRACI_CONST int CMD_GET_MEANDATA_VARIABLE
TRACI_CONST int CMD_GET_JUNCTION_VARIABLE
TRACI_CONST int CMD_SET_VEHICLE_VARIABLE
TRACI_CONST int CMD_SET_GUI_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_ROUTE_VARIABLE
TRACI_CONST int TRACI_VERSION
TRACI_CONST int CMD_GET_VARIABLESPEEDSIGN_VARIABLE
TRACI_CONST int VAR_PARAMETER
TRACI_CONST int CMD_SET_VEHICLETYPE_VARIABLE
TRACI_CONST int CMD_SET_PERSON_VARIABLE
TRACI_CONST int CMD_GET_SIM_VARIABLE
TRACI_CONST int CMD_SET_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_PERSON_CONTEXT
TRACI_CONST int CMD_GET_VEHICLETYPE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_CONTEXT
TRACI_CONST int CMD_SET_CHARGINGSTATION_VARIABLE
TRACI_CONST int CMD_SET_LANE_VARIABLE
TRACI_CONST int FILTER_TYPE_LEAD_FOLLOW
TRACI_CONST int CMD_SUBSCRIBE_GUI_CONTEXT
TRACI_CONST int CMD_SET_PARKINGAREA_VARIABLE
TRACI_CONST int CMD_GET_LANE_VARIABLE
TRACI_CONST int CMD_SET_LANEAREA_VARIABLE
TRACI_CONST int VAR_POSITION3D
TRACI_CONST int CMD_GET_GUI_VARIABLE
TRACI_CONST int VAR_PARAMETER_WITH_KEY
TRACI_CONST int FILTER_TYPE_UPSTREAM_DIST
TRACI_CONST int TYPE_DOUBLELIST
TRACI_CONST int CMD_GET_POLYGON_VARIABLE
TRACI_CONST int FILTER_TYPE_TURN
TRACI_CONST int CMD_SUBSCRIBE_MULTIENTRYEXIT_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_VARIABLE
TRACI_CONST int CMD_GET_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_POI_VARIABLE
TRACI_CONST int TYPE_DOUBLE
@ SUBS_FILTER_LEAD_FOLLOW
Definition: Subscription.h:48
@ SUBS_FILTER_UPSTREAM_DIST
Definition: Subscription.h:46
@ SUBS_FILTER_VTYPE
Definition: Subscription.h:54
@ SUBS_FILTER_NO_RTREE
Definition: Subscription.h:61
@ SUBS_FILTER_LANES
Definition: Subscription.h:40
@ SUBS_FILTER_NOOPPOSITE
Definition: Subscription.h:42
@ SUBS_FILTER_DOWNSTREAM_DIST
Definition: Subscription.h:44
@ SUBS_FILTER_LATERAL_DIST
Definition: Subscription.h:59
@ SUBS_FILTER_TURN
Definition: Subscription.h:50
@ SUBS_FILTER_VCLASS
Definition: Subscription.h:52
@ SUBS_FILTER_NONE
Definition: Subscription.h:38
@ SUBS_FILTER_FIELD_OF_VISION
Definition: Subscription.h:57
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_VARIABLE
TRACI_CONST int TYPE_BYTE
TRACI_CONST int CMD_SUBSCRIBE_POI_CONTEXT
TRACI_CONST int CMD_SET_INDUCTIONLOOP_VARIABLE
TRACI_CONST int CMD_SET_TL_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_SIM_CONTEXT
TRACI_CONST int FILTER_TYPE_VCLASS
TRACI_CONST int CMD_SUBSCRIBE_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_GETVERSION
TRACI_CONST int RTYPE_ERR
TRACI_CONST int CMD_SIMSTEP
TRACI_CONST int FILTER_TYPE_NONE
TRACI_CONST int CMD_SUBSCRIBE_VEHICLETYPE_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_LANE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_PERSON_VARIABLE
TRACI_CONST int RTYPE_OK
TRACI_CONST int CMD_GET_INDUCTIONLOOP_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_TL_VARIABLE
TRACI_CONST int CMD_GET_OVERHEADWIRE_VARIABLE
TRACI_CONST int VAR_FOLLOWER
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_CONTEXT
TRACI_CONST int FILTER_TYPE_LANES
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_CONTEXT
TRACI_CONST int CMD_SET_ROUTEPROBE_VARIABLE
TRACI_CONST int CMD_SET_BUSSTOP_VARIABLE
TRACI_CONST int FILTER_TYPE_LATERAL_DIST
TRACI_CONST int CMD_SUBSCRIBE_EDGE_VARIABLE
TRACI_CONST int TYPE_STRING
A 3D-position.
Definition: TraCIDefs.h:164
A list of positions.
Definition: TraCIDefs.h:207
std::vector< TraCIPosition > value
Definition: TraCIDefs.h:217