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.dev/sumo
3 // Copyright (C) 2007-2024 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 <libsumo/Helper.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"
82 #include "TraCIServerAPI_BusStop.h"
90 
91 
92 // ===========================================================================
93 // debug constants
94 // ===========================================================================
95 //#define DEBUG_MULTI_CLIENTS
96 //#define DEBUG_SUBSCRIPTIONS
97 //#define DEBUG_SUBSCRIPTION_FILTERS
98 //#define DEBUG_RAW_INPUT
99 
100 
101 // ===========================================================================
102 // static member definitions
103 // ===========================================================================
106 
107 
108 // ===========================================================================
109 // method definitions
110 // ===========================================================================
111 void
112 TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
117 }
118 
119 
120 bool
121 TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
124  return true;
125 }
126 
127 
128 bool
129 TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
131  myWrapperStorage.writeInt(value);
132  return true;
133 }
134 
135 
136 bool
137 TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
140  return true;
141 }
142 
143 
144 bool
145 TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
148  return true;
149 }
150 
151 
152 bool
153 TraCIServer::wrapDoubleList(const std::string& /* objID */, const int /* variable */, const std::vector<double>& value) {
156  return true;
157 }
158 
159 
160 bool
161 TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
162  const bool includeZ = variable == libsumo::VAR_POSITION3D;
164  myWrapperStorage.writeDouble(value.x);
165  myWrapperStorage.writeDouble(value.y);
166  if (includeZ) {
167  myWrapperStorage.writeDouble(value.z);
168  }
169  return true;
170 }
171 
172 
173 bool
174 TraCIServer::wrapPositionVector(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIPositionVector& shape) {
176  if (shape.value.size() < 256) {
177  myWrapperStorage.writeUnsignedByte((int)shape.value.size());
178  } else {
180  myWrapperStorage.writeInt((int)shape.value.size());
181  }
182  for (const libsumo::TraCIPosition& pos : shape.value) {
185  }
186  return true;
187 }
188 
189 
190 bool
191 TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
197  return true;
198 }
199 
200 
201 bool
202 TraCIServer::wrapStringDoublePair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, double>& value) {
206  myWrapperStorage.writeString(value.first);
208  myWrapperStorage.writeDouble(value.second);
209  return true;
210 }
211 
212 
213 bool
214 TraCIServer::wrapStringPair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, std::string>& value) {
218  myWrapperStorage.writeString(value.first);
220  myWrapperStorage.writeString(value.second);
221  return true;
222 }
223 
224 
227  return myWrapperStorage;
228 }
229 
230 
231 
232 TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
233  : myTargetTime(begin), myLastContextSubscription(nullptr) {
234 #ifdef DEBUG_MULTI_CLIENTS
235  std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
236 #endif
237  myVehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
238  myVehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
240  myVehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
241  myVehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
242  myVehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
243  myVehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
244  myVehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
245  myVehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
246  myVehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
247  myVehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
248  myVehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
249  myVehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
250 
255 
262 
300  //myExecutors[libsumo::CMD_SET_MEANDATA_VARIABLE] = &TraCIServerAPI_MeanData::processSet;
303 
306  myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER));
307  myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER_WITH_KEY));
308 
309  myDoCloseConnection = false;
310 
311  // display warning if internal lanes are not used
312  // TODO this may be redundant to the warning in NLBuilder::build
314  WRITE_WARNING(TL("Starting TraCI without using internal lanes!"));
315  MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
316  MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
317  }
318 
319  try {
320  WRITE_MESSAGEF(TL("***Starting server on port % ***"), toString(port));
321  tcpip::Socket serverSocket(port);
322  if (numClients > 1) {
323  WRITE_MESSAGEF(TL(" waiting for % clients..."), toString(numClients));
324  }
325  while ((int)mySockets.size() < numClients) {
326  int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
327  mySockets[index] = new SocketInfo(serverSocket.accept(true), begin);
328  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
329  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
330  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
331  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
332  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
333  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
334  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
335  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
336  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
337  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
338  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
339  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
340  mySockets[index]->vehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
341 
342  mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
343  mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
344  mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
345  mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
346  if (numClients > 1) {
347  WRITE_MESSAGE(TL(" client connected"));
348  }
349  }
350  // When got here, all clients have connected
351  if (numClients > 1) {
353  }
354  // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommands()
355  myCurrentSocket = mySockets.begin();
356  } catch (tcpip::SocketException& e) {
357  throw ProcessError(e.what());
358  }
359 }
360 
361 
363  for (const auto& socket : mySockets) {
364  delete socket.second;
365  }
366  // there is no point in calling cleanup() here, it does not free any pointers and will only modify members which get deleted anyway
367 }
368 
369 
370 // ---------- Initialisation and Shutdown
371 void
372 TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
373  if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
374  myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
375  OptionsCont::getOptions().getInt("remote-port"),
376  OptionsCont::getOptions().getInt("num-clients"));
377  for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
378  myInstance->myExecutors[i->first] = i->second;
379  }
380  }
381  if (myInstance != nullptr) {
382  // maybe net was deleted and built again
386  }
387 }
388 
389 
390 void
392  if (myInstance == nullptr) {
393  return;
394  }
395  delete myInstance;
396  myInstance = nullptr;
397  myDoCloseConnection = true;
398 }
399 
400 
401 bool
403  return myDoCloseConnection;
404 }
405 
406 
407 // ---------- Initialisation and Shutdown
408 
409 
410 void
411 TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
412  if (!myDoCloseConnection) {
413  myVehicleStateChanges[to].push_back(vehicle->getID());
414  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
415  i->second->vehicleStateChanges[to].push_back(vehicle->getID());
416  }
417  }
418 }
419 
420 
421 void
422 TraCIServer::transportableStateChanged(const MSTransportable* const transportable, MSNet::TransportableState to, const std::string& /*info*/) {
423  if (!myDoCloseConnection) {
424  myTransportableStateChanges[to].push_back(transportable->getID());
425  for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
426  i->second->transportableStateChanges[to].push_back(transportable->getID());
427  }
428  }
429 }
430 
431 
432 void
434 #ifdef DEBUG_MULTI_CLIENTS
435  std::cout << "Checking client order requests." << std::endl;
436 #endif
437  // check for SET_ORDER commands queued by connected clients
438  // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
439  myCurrentSocket = mySockets.begin();
440  while (myCurrentSocket != mySockets.end()) {
441 #ifdef DEBUG_MULTI_CLIENTS
442  std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
443 #endif
444 // bool clientUnordered = true;
445  while (true) {
447  myCurrentSocket->second->socket->receiveExact(myInputStorage);
448  int commandStart, commandLength;
449  int commandId = readCommandID(commandStart, commandLength);
450 #ifdef DEBUG_MULTI_CLIENTS
451  std::cout << " received command " << commandId << std::endl;
452 #endif
453  // Whether the received command is a permitted command for the initialization phase.
454  // Currently, getVersion and setOrder are permitted.
455  bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
456  if (initCommand) {
457 #ifdef DEBUG_MULTI_CLIENTS
458  std::cout << " Init command. Sending response." << std::endl;
459 #endif
460  // reset input storage to initial state before reading the commandId
461  // (ugly, but we can't just reset the store's iter_ from here)
462  // Giving the commandId to dispatch command didn't work either
463  tcpip::Storage tmp;
466  // we don't know whether the command was set with extended
467  // length syntax or not so we hardcode the length here (#5037)
471 
472  // Handle initialization command completely
473  dispatchCommand();
474  myCurrentSocket->second->socket->sendExact(myOutputStorage);
476  } else {
477 #ifdef DEBUG_MULTI_CLIENTS
478  std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
479 #endif
480  throw ProcessError(TL("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase."));
481  }
482  if (commandId == libsumo::CMD_SETORDER) {
483  // This is what we have waited for.
484  break;
485  }
486  }
487  ++myCurrentSocket;
488  }
489 }
490 
491 
492 void
494  // Process reordering requests
495  if (mySocketReorderRequests.size() > 0) {
496  // process reordering requests
497  std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
498  std::map<int, SocketInfo*>::iterator j;
499 #ifdef DEBUG_MULTI_CLIENTS
500  std::cout << SIMTIME << " Current socket ordering:\n";
501  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
502  std::cout << " " << j->first << ": " << j->second->socket << "\n";
503  }
504  std::cout << "Reordering requests:\n";
505  for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
506  std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
507  }
508  i = mySocketReorderRequests.begin();
509 #endif
510  while (i != mySocketReorderRequests.end()) {
511  j = mySockets.begin();
512  while (j != mySockets.end()) {
513  if (j->second->socket == i->second->socket) {
514  break;
515  } else {
516  j++;
517  }
518  }
519  assert(j != mySockets.end());
520  mySockets.erase(j);
521  mySockets[i->first] = i->second;
522  ++i;
523  }
524  mySocketReorderRequests.clear();
525 #ifdef DEBUG_MULTI_CLIENTS
526  std::cout << "New socket ordering:\n";
527  for (j = mySockets.begin(); j != mySockets.end(); ++j) {
528  std::cout << " " << j->first << ": " << j->second->socket << "\n";
529  }
530  std::cout << std::endl;
531 #endif
532  }
533 }
534 
535 
536 SUMOTime
538 #ifdef DEBUG_MULTI_CLIENTS
539  std::cout << "\n Determining new target time..." << std::endl;
540  if (mySockets.size() == 0) {
541  std::cout << " All clients have disconnected." << std::endl;
542  }
543 #endif
544  std::map<int, SocketInfo*>::const_iterator i;
545  SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
546  for (i = mySockets.begin(); i != mySockets.end(); ++i) {
547 #ifdef DEBUG_MULTI_CLIENTS
548  std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
549 #endif
550  targetTime = MIN2(targetTime, i->second->targetTime);
551  }
552 #ifdef DEBUG_MULTI_CLIENTS
553  std::cout << std::endl;
554 #endif
555  return targetTime;
556 }
557 
558 
559 // send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
560 void
562 #ifdef DEBUG_MULTI_CLIENTS
563  std::cout << "\n Sending subscription results to clients:\n";
564 #endif
565  std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
566  while (i != mySockets.end()) {
567  if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
568  // this client will become active before the next SUMO step. Provide subscription results.
569  i->second->socket->sendExact(myOutputStorage);
570 #ifdef DEBUG_MULTI_CLIENTS
571  std::cout << i->second->socket << "\n";
572 #endif
573  }
574  ++i;
575  }
576 #ifdef DEBUG_MULTI_CLIENTS
577  std::cout << std::endl;
578 #endif
579 }
580 
581 
582 int
583 TraCIServer::processCommands(const SUMOTime step, const bool afterMove) {
584 #ifdef DEBUG_MULTI_CLIENTS
585  std::cout << SIMTIME << " processCommands(step = " << step << "):\n" << std::endl;
586 #endif
587  try {
588  int finalCmd = 0;
589  const bool firstStep = myCurrentSocket != mySockets.end();
590  // update client order if requested
592  if (!firstStep && !afterMove) {
593  // 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)
594  // update subscription results
596  // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
597  sendOutputToAll();
599  }
600 
601  // determine minimal next target time among clients
603 
604  if (step < myTargetTime) {
605 #ifdef DEBUG_MULTI_CLIENTS
606  std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommands()." << std::endl;
607 #endif
608  return finalCmd;
609  }
610 
611  // Simulation should run until
612  // 1. end time reached or
613  // 2. got libsumo::CMD_CLOSE or
614  // 3. got libsumo::CMD_LOAD or
615  // 4. Client closes socket connection
616  while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep()) && finalCmd != libsumo::CMD_EXECUTEMOVE) {
617 #ifdef DEBUG_MULTI_CLIENTS
618  std::cout << " Next target time: " << myTargetTime << std::endl;
619 #endif
620  // Iterate over clients and process communication for the ones with target time == myTargetTime
621  myCurrentSocket = mySockets.begin();
622  while (myCurrentSocket != mySockets.end()) {
623 #ifdef DEBUG_MULTI_CLIENTS
624  std::cout << " current socket: " << myCurrentSocket->second->socket
625  << " with target time=" << myCurrentSocket->second->targetTime
626  << std::endl;
627 #endif
628 
629  if (myCurrentSocket->second->targetTime > myTargetTime || (afterMove && !myCurrentSocket->second->executeMove)) {
630  // this client must wait
631 #ifdef DEBUG_MULTI_CLIENTS
632  std::cout << " skipping client " << myCurrentSocket->second->socket
633  << " with target time=" << myCurrentSocket->second->targetTime << std::endl;
634 #endif
635  myCurrentSocket++;
636  continue;
637  }
638  finalCmd = 0;
639  while (finalCmd == 0) {
640  if (!myInputStorage.valid_pos()) {
641  // have read request completely, send response if adequate
642  if (myOutputStorage.size() > 0) {
643  // send response to previous query
644  myCurrentSocket->second->socket->sendExact(myOutputStorage);
646  }
647 #ifdef DEBUG_MULTI_CLIENTS
648  std::cout << " resetting input storage and reading next command..." << std::endl;
649 #endif
650  // Read next request
652  myCurrentSocket->second->socket->receiveExact(myInputStorage);
653  }
654 
656  const int cmd = dispatchCommand();
657  if (cmd == libsumo::CMD_SIMSTEP || cmd == libsumo::CMD_LOAD || cmd == libsumo::CMD_EXECUTEMOVE || cmd == libsumo::CMD_CLOSE) {
658  finalCmd = cmd;
659  }
660  }
661  }
662  }
663  if (!myLoadArgs.empty()) {
664 #ifdef DEBUG_MULTI_CLIENTS
665  std::cout << " Breaking loop to load new simulation." << std::endl;
666 #endif
667  break;
668  } else if (myDoCloseConnection) {
669 #ifdef DEBUG_MULTI_CLIENTS
670  std::cout << " Breaking loop because last client closed connection." << std::endl;
671 #endif
672  break;
673  }
674  SUMOTime nextT = nextTargetTime();
675  // minimal target time among clients should have been increased during the last loop through mySockets
676  // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
677  // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
678  // the next call is then usually simulationStep(step=1000) leading to no further increase
679  // and thus a failing assertion here.
680  //assert(myTargetTime < nextT || myDoCloseConnection);
681  myTargetTime = nextT;
682  }
683  // All clients are done with the current time step
684  // Reset myVehicleStateChanges and myTransportableStateChanges
685  for (auto& item : myVehicleStateChanges) {
686  item.second.clear();
687  }
688  for (auto& item : myTransportableStateChanges) {
689  item.second.clear();
690  }
691  return finalCmd;
692  } catch (std::invalid_argument& e) {
693  throw ProcessError(e.what());
694  } catch (libsumo::TraCIException& e) {
695  throw ProcessError(e.what());
696  } catch (tcpip::SocketException& e) {
697  throw ProcessError(e.what());
698  }
699 }
700 
701 
702 void
704  mySubscriptions.clear();
705  myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
706  for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
707  myCurrentSocket->second->targetTime = myTargetTime;
708  myCurrentSocket->second->executeMove = false;
709  }
713  for (auto& i : myVehicleStateChanges) {
714  i.second.clear();
715  }
716  for (auto& i : myTransportableStateChanges) {
717  i.second.clear();
718  }
719  myCurrentSocket = mySockets.begin();
720 }
721 
722 
723 std::map<int, TraCIServer::SocketInfo*>::iterator
725 #ifdef DEBUG_MULTI_CLIENTS
726  std::cout << " Removing socket " << myCurrentSocket->second->socket
727  << " (order " << myCurrentSocket->first << ")" << std::endl;
728 #endif
729  delete myCurrentSocket->second;
731  return myCurrentSocket;
732 }
733 
734 
735 int
736 TraCIServer::readCommandID(int& commandStart, int& commandLength) {
737  commandStart = myInputStorage.position();
738  commandLength = myInputStorage.readUnsignedByte();
739  if (commandLength == 0) {
740  commandLength = myInputStorage.readInt();
741  }
742 #ifdef DEBUG_RAW_INPUT
743  std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
744  for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
745  std::cout << (int)*it << " ";
746  }
747  std::cout << "\n";
748 #endif
750 }
751 
752 
753 int
755  int commandStart, commandLength;
756  int commandId = readCommandID(commandStart, commandLength);
757 #ifdef DEBUG_MULTI_CLIENTS
758  std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
759  << ", commandId = " << commandId << std::endl;
760 #endif
761  bool success = false;
762  // dispatch commands
763  if (myExecutors.find(commandId) != myExecutors.end()) {
764  success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
765  } else {
766  switch (commandId) {
768  success = commandGetVersion();
769  break;
770  case libsumo::CMD_LOAD: {
771  std::vector<std::string> args;
773  return writeErrorStatusCmd(libsumo::CMD_LOAD, "A load command needs a list of string arguments.", myOutputStorage);
774  }
775 #ifdef DEBUG_MULTI_CLIENTS
776  std::cout << " commandId == libsumo::CMD_LOAD"
777  << ", args = " << toString(args) << std::endl;
778 #endif
779  try {
780  myLoadArgs = args;
781  success = true;
783  // XXX: This only cares for the client that issued the load command.
784  // Multiclient-load functionality is still to be implemented. Refs #3146.
785  myCurrentSocket->second->socket->sendExact(myOutputStorage);
786  myCurrentSocket = mySockets.end();
788  } catch (libsumo::TraCIException& e) {
790  }
791  break;
792  }
794  myCurrentSocket->second->executeMove = true;
795  myCurrentSocket++;
796  success = true;
798  break;
799  case libsumo::CMD_SIMSTEP: {
800  const double nextT = myInputStorage.readDouble();
801  if (nextT == 0.) {
802  myCurrentSocket->second->targetTime += DELTA_T;
803  } else {
804  myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
805  }
806  myCurrentSocket->second->executeMove = false;
807 #ifdef DEBUG_MULTI_CLIENTS
808  std::cout << " commandId == libsumo::CMD_SIMSTEP"
809  << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
810 #endif
811  if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
812  // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
813  // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommands()
815  }
816  // Clear vehicleStateChanges and transportableStateChanges for this client
817  // -> For subsequent TraCI stepping
818  // that is performed within this SUMO step, no updates on vehicle states
819  // belonging to the last SUMO simulation step will be received by this client.
820  for (auto& item : myCurrentSocket->second->vehicleStateChanges) {
821  item.second.clear();
822  }
823  for (auto& item : myCurrentSocket->second->transportableStateChanges) {
824  item.second.clear();
825  }
826  myCurrentSocket++;
827  return commandId;
828  }
829  case libsumo::CMD_CLOSE:
831  myCurrentSocket->second->socket->sendExact(myOutputStorage);
833  if (mySockets.size() == 1) {
834  // Last client has closed connection
835  myDoCloseConnection = true;
836  }
837  // remove current socket and increment to next socket in ordering
839  success = true;
840  break;
841  case libsumo::CMD_SETORDER: {
842  const int order = myInputStorage.readInt();
843 #ifdef DEBUG_MULTI_CLIENTS
844  std::cout << " commandId == libsumo::CMD_SETORDER"
845  << ", order index is " << order << std::endl;
846 #endif
847  if (order > libsumo::MAX_ORDER) {
848  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
849  }
850  if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
851  return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
852  }
853  // memorize reorder request (will only take effect in the next step)
854  mySocketReorderRequests[order] = myCurrentSocket->second;
855  success = true;
857  break;
858  }
883  success = addObjectVariableSubscription(commandId, false);
884  break;
909  success = addObjectVariableSubscription(commandId, true);
910  break;
912  success = addSubscriptionFilter();
913  break;
914  default:
915  if (commandId == libsumo::CMD_GET_GUI_VARIABLE || commandId == libsumo::CMD_SET_GUI_VARIABLE) {
916  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
917  } else {
918  writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
919  }
920  }
921  }
922  if (!success) {
923  while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
925  }
926  }
927  if ((int)myInputStorage.position() != commandStart + commandLength) {
928  std::ostringstream msg;
929  msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
930  msg << " Expected command length was " << commandLength;
931  msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
932  writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
933  myDoCloseConnection = true;
934  }
935  return commandId;
936 }
937 
938 
939 // ---------- Server-internal command handling
940 bool
942  // Prepare response
943  tcpip::Storage answerTmp;
944  answerTmp.writeInt(libsumo::TRACI_VERSION);
945  answerTmp.writeString("SUMO " VERSION_STRING);
946  // When we get here, the response is stored in answerTmp -> put into myOutputStorage
948  // command length
949  myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
950  // command type
952  // and the parameter dependant part
953  myOutputStorage.writeStorage(answerTmp);
954  return true;
955 }
956 
957 
958 void
961 #ifdef DEBUG_MULTI_CLIENTS
962  std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
963 #endif
965  int noActive = 0;
966  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
967  const libsumo::Subscription& s = *i;
970 
972  if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
973  i = mySubscriptions.erase(i);
974  continue;
975  }
976  ++i;
977  if (s.beginTime > t) {
978  continue;
979  }
980  ++noActive;
981  }
983 #ifdef DEBUG_SUBSCRIPTIONS
984  std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
985  << "\n Nr. of active subscriptions = " << noActive << std::endl;
986 #endif
987  mySubscriptionCache.writeInt(noActive);
988 #ifdef DEBUG_SUBSCRIPTIONS
989  std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
990 #endif
991  for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
992  const libsumo::Subscription& s = *i;
993  if (s.beginTime > t) {
994  ++i;
995  continue;
996  }
997  tcpip::Storage into;
998  std::string errors;
999  bool ok = processSingleSubscription(s, into, errors);
1000 #ifdef DEBUG_SUBSCRIPTIONS
1001  std::cout << " Size of into-store for subscription " << s.id
1002  << ": " << into.size() << std::endl;
1003 #endif
1005  if (ok) {
1006  ++i;
1007  } else {
1008  i = mySubscriptions.erase(i);
1009  }
1010  }
1012 #ifdef DEBUG_SUBSCRIPTIONS
1013  std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1014 #endif
1015 }
1016 
1017 
1018 void
1020 #ifdef DEBUG_MULTI_CLIENTS
1021  std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1022  << " (-> intermediate TraCI step)."
1023  << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1024  << std::endl;
1025 #endif
1027 
1028 // NOTE: the commented code would send an empty response
1029 // myOutputStorage.writeInt(0);
1030 // myCurrentSocket->second->socket->sendExact(myOutputStorage);
1031 // myOutputStorage.reset();
1033  // send results to active client
1034  myCurrentSocket->second->socket->sendExact(myOutputStorage);
1036 }
1037 
1038 
1039 void
1040 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1041  writeStatusCmd(commandId, status, description, myOutputStorage);
1042 }
1043 
1044 
1045 void
1046 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1047  if (status == libsumo::RTYPE_ERR) {
1048  WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1049  } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1050  WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1051  }
1052  outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1053  outputStorage.writeUnsignedByte(commandId); // command type
1054  outputStorage.writeUnsignedByte(status); // status
1055  outputStorage.writeString(description); // description
1056 }
1057 
1058 
1059 bool
1060 TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1061  writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1062  return false;
1063 }
1064 
1065 
1066 void
1068  tcpip::Storage writeInto;
1069  std::string errors;
1070  libsumo::Subscription* modifiedSubscription = nullptr;
1071  try {
1072  if (processSingleSubscription(s, writeInto, errors)) {
1074  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1075  } else {
1076  if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1077  // Add new subscription to subscription cache (note: seems a bit inefficient)
1079  // copy new subscription into cache
1080  int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1081  tcpip::Storage tmp;
1082  tmp.writeInt(noActive);
1083  while (mySubscriptionCache.valid_pos()) {
1085  }
1086  tmp.writeStorage(writeInto);
1089  }
1090  }
1092  }
1093  if (modifiedSubscription != nullptr && (
1094  modifiedSubscription->isVehicleToVehicleContextSubscription()
1095  || modifiedSubscription->isVehicleToPersonContextSubscription())) {
1096  // Set last modified vehicle context subscription active for filter modifications
1097  myLastContextSubscription = modifiedSubscription;
1098  } else {
1099  // adding other subscriptions deactivates the activation for filter addition
1100  myLastContextSubscription = nullptr;
1101  }
1102  } else {
1103  writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1104  }
1105  } catch (libsumo::TraCIException& e) {
1107  }
1108  myOutputStorage.writeStorage(writeInto);
1109 }
1110 
1111 
1112 void
1113 TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1114  bool found = false;
1115  std::vector<libsumo::Subscription>::iterator j;
1116  for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1117  if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1118  j = mySubscriptions.erase(j);
1119  if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1120  // Remove also reference for filter additions
1121  myLastContextSubscription = nullptr;
1122  }
1123  found = true;
1124  continue;
1125  }
1126  ++j;
1127  }
1128  // try unsubscribe
1129  if (found) {
1130  writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1131  } else {
1132  writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1133  }
1134 }
1135 
1136 
1137 bool
1139  std::string& errors) {
1140  bool ok = true;
1141  tcpip::Storage outputStorage;
1142  const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1143  std::set<std::string> objIDs;
1144  if (s.contextDomain > 0) {
1146  PositionVector shape;
1149  }
1151  } else {
1152  objIDs.insert(s.id);
1153  }
1154  const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1155  int skipped = 0;
1156  for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1157  if (s.contextDomain > 0) {
1158  //if (centralObject(s, *j)) {
1159  // skipped++;
1160  // continue;
1161  //}
1162  outputStorage.writeString(*j);
1163  }
1164  if (numVars > 0) {
1165  std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1166  for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1167  tcpip::Storage message;
1168  message.writeUnsignedByte(*i);
1169  message.writeString(*j);
1170  // TODO check why writeStorage fails here (probably some kind of invalid iterator)
1171  for (const auto& v :** k) {
1172  message.writeChar(v);
1173  }
1174  tcpip::Storage tmpOutput;
1175  if (myExecutors.find(getCommandId) != myExecutors.end()) {
1176  ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1177  } else {
1178  writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1179  ok = false;
1180  }
1181  // copy response part
1182  if (ok) {
1183  int length = tmpOutput.readUnsignedByte();
1184  while (--length > 0) {
1185  tmpOutput.readUnsignedByte();
1186  }
1187  int lengthLength = 1;
1188  length = tmpOutput.readUnsignedByte();
1189  if (length == 0) {
1190  lengthLength = 5;
1191  length = tmpOutput.readInt();
1192  }
1193  //read responseType
1194  tmpOutput.readUnsignedByte();
1195  int variable = tmpOutput.readUnsignedByte();
1196  std::string id = tmpOutput.readString();
1197  outputStorage.writeUnsignedByte(variable);
1198  outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1199  length -= (lengthLength + 1 + 4 + (int)id.length());
1200  while (--length > 0) {
1201  outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1202  }
1203  } else {
1204  //read length
1205  tmpOutput.readUnsignedByte();
1206  //read cmd
1207  tmpOutput.readUnsignedByte();
1208  //read status
1209  tmpOutput.readUnsignedByte();
1210  std::string msg = tmpOutput.readString();
1211  outputStorage.writeUnsignedByte(*i);
1212  outputStorage.writeUnsignedByte(libsumo::RTYPE_ERR);
1213  outputStorage.writeUnsignedByte(libsumo::TYPE_STRING);
1214  outputStorage.writeString(msg);
1215  errors = errors + msg;
1216  }
1217  }
1218  }
1219  }
1220  int length = (1 + 4) + 1 + (4 + (int)s.id.length()) + 1 + (int)outputStorage.size();
1221  if (s.contextDomain > 0) {
1222  length += 1 + 4; // context domain and number of objects
1223  }
1224  // we always write extended command length here for backward compatibility
1225  writeInto.writeUnsignedByte(0); // command length -> extended
1226  writeInto.writeInt(length);
1227  writeInto.writeUnsignedByte(s.commandId + 0x10);
1228  writeInto.writeString(s.id);
1229  if (s.contextDomain > 0) {
1230  writeInto.writeUnsignedByte(s.contextDomain);
1231  }
1232  writeInto.writeUnsignedByte(numVars);
1233  if (s.contextDomain > 0) {
1234  writeInto.writeInt((int)objIDs.size() - skipped);
1235  }
1236  if (s.contextDomain == 0 || objIDs.size() != 0) {
1237  writeInto.writeStorage(outputStorage);
1238  }
1239  return ok;
1240 }
1241 
1242 
1243 bool
1244 TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1245  const double beginTime = myInputStorage.readDouble();
1246  const double endTime = myInputStorage.readDouble();
1247  const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1248  const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1249  const std::string id = myInputStorage.readString();
1250  const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1251  double range = hasContext ? myInputStorage.readDouble() : 0.;
1252  if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
1253  range = std::numeric_limits<double>::max();
1254  }
1255  const int num = myInputStorage.readUnsignedByte();
1256  std::vector<int> variables;
1257  std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1258  for (int i = 0; i < num; ++i) {
1259  const int varID = myInputStorage.readUnsignedByte();
1260  variables.push_back(varID);
1261  parameters.push_back(std::make_shared<tcpip::Storage>());
1262  if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1263  const int parType = myInputStorage.readUnsignedByte();
1264  parameters.back()->writeUnsignedByte(parType);
1265  if (parType == libsumo::TYPE_DOUBLE) {
1266  parameters.back()->writeDouble(myInputStorage.readDouble());
1267  } else if (parType == libsumo::TYPE_STRING) {
1268  parameters.back()->writeString(myInputStorage.readString());
1269  } else {
1270  // Error!
1271  }
1272  }
1273  }
1274  // check subscribe/unsubscribe
1275  if (variables.empty()) {
1276  removeSubscription(commandId, id, domain);
1277  return true;
1278  }
1279  // process subscription
1280  libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1282  return true;
1283 }
1284 
1285 
1286 
1287 bool
1289  bool success = true;
1290  // Read filter type
1291  int filterType = myInputStorage.readUnsignedByte();
1292 
1293  if (myLastContextSubscription == nullptr) {
1295  "No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1296  return false;
1297  }
1298 
1299  // dispatch according to filter type
1300  switch (filterType) {
1302  // Remove all filters
1303  removeFilters();
1304  break;
1306  // Read relative lanes to consider for context filter
1307  int nrLanes = (int)myInputStorage.readByte();
1308  std::vector<int> lanes;
1309  for (int i = 0; i < nrLanes; ++i) {
1310  lanes.push_back((int) myInputStorage.readByte());
1311  }
1313  }
1314  break;
1316  // Add no-opposite filter
1318  break;
1320  myInputStorage.readByte(); // read type double
1321  double dist = myInputStorage.readDouble();
1323  }
1324  break;
1326  myInputStorage.readByte(); // read type double
1327  double dist = myInputStorage.readDouble();
1329  }
1330  break;
1332  // Read relative lanes to consider for context filter
1334  }
1335  break;
1337  myInputStorage.readByte(); // read type double
1338  double dist = myInputStorage.readDouble();
1340  }
1341  break;
1343  myInputStorage.readByte(); // read type stringlist
1345  addSubscriptionFilterVClass(vClasses);
1346  }
1347  break;
1349  myInputStorage.readByte(); // read type stringlist
1350  std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1351  std::set<std::string> vTypesSet;
1352  vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1353  addSubscriptionFilterVType(vTypesSet);
1354  }
1355  break;
1357  myInputStorage.readByte(); // read type double
1358  double angle = myInputStorage.readDouble();
1360  }
1361  break;
1363  myInputStorage.readByte(); // read type double
1364  double dist = myInputStorage.readDouble();
1366  }
1367  break;
1368  default:
1370  "'" + toString(filterType) + "' is no valid filter type code.");
1371  success = false;
1372  }
1373 
1374  if (success) {
1375  // acknowledge filter addition
1377  }
1378 
1379  return success;
1380 }
1381 
1382 
1383 void
1385 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1386  std::cout << "Removing filters" << std::endl;
1387 #endif
1389 }
1390 
1391 void
1393 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1394  std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1395 #endif
1398 }
1399 
1400 void
1402 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1403  std::cout << "Adding no opposite filter" << std::endl;
1404 #endif
1406 }
1407 
1408 void
1410 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1411  std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1412 #endif
1415 }
1416 
1417 void
1419 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1420  std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1421 #endif
1424 }
1425 
1426 void
1428 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1429  std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1430 #endif
1432 }
1433 
1434 void
1436 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1437  std::cout << "Adding turn-maneuver filter" << std::endl;
1438 #endif
1441 }
1442 
1443 void
1445 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1446  std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1447 #endif
1450 }
1451 
1452 void
1453 TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1454 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1455  std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1456 #endif
1459 }
1460 
1461 void
1463 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1464  std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1465 #endif
1468 }
1469 
1470 void
1472 #ifdef DEBUG_SUBSCRIPTION_FILTERS
1473  std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1474 #endif
1477 }
1478 
1479 void
1481  if (tempMsg.size() < 254) {
1482  outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1483  } else {
1484  outputStorage.writeUnsignedByte(0); // command length -> extended
1485  outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1486  }
1487  outputStorage.writeStorage(tempMsg);
1488 }
1489 
1490 
1491 void
1494  if (shape.value.size() < 256) {
1495  outputStorage.writeUnsignedByte((int)shape.value.size());
1496  } else {
1497  outputStorage.writeUnsignedByte(0);
1498  outputStorage.writeInt((int)shape.value.size());
1499  }
1500  for (const libsumo::TraCIPosition& pos : shape.value) {
1501  outputStorage.writeDouble(pos.x);
1502  outputStorage.writeDouble(pos.y);
1503  }
1504 }
1505 
1506 
1507 bool
1509  if (inputStorage.readUnsignedByte() != libsumo::TYPE_INTEGER) {
1510  return false;
1511  }
1512  into = inputStorage.readInt();
1513  return true;
1514 }
1515 
1516 
1517 bool
1519  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLE) {
1520  return false;
1521  }
1522  into = inputStorage.readDouble();
1523  return true;
1524 }
1525 
1526 
1527 bool
1528 TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
1529  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRING) {
1530  return false;
1531  }
1532  into = inputStorage.readString();
1533  return true;
1534 }
1535 
1536 
1537 bool
1538 TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
1539  if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRINGLIST) {
1540  return false;
1541  }
1542  into = inputStorage.readStringList();
1543  return true;
1544 }
1545 
1546 
1547 bool
1548 TraCIServer::readTypeCheckingDoubleList(tcpip::Storage& inputStorage, std::vector<double>& into) {
1549  if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLELIST) {
1550  return false;
1551  }
1552  into = inputStorage.readDoubleList();
1553  return true;
1554 }
1555 
1556 
1557 bool
1559  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COLOR) {
1560  return false;
1561  }
1562  into.r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1563  into.g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1564  into.b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1565  into.a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1566  return true;
1567 }
1568 
1569 
1570 bool
1572  if (inputStorage.readUnsignedByte() != libsumo::POSITION_2D) {
1573  return false;
1574  }
1575  into.x = inputStorage.readDouble();
1576  into.y = inputStorage.readDouble();
1577  into.z = 0;
1578  return true;
1579 }
1580 
1581 
1582 bool
1584  if (inputStorage.readByte() != libsumo::TYPE_BYTE) {
1585  return false;
1586  }
1587  into = inputStorage.readByte();
1588  return true;
1589 }
1590 
1591 
1592 bool
1594  if (inputStorage.readUnsignedByte() != libsumo::TYPE_UBYTE) {
1595  return false;
1596  }
1597  into = inputStorage.readUnsignedByte();
1598  return true;
1599 }
1600 
1601 
1602 bool
1604  if (inputStorage.readUnsignedByte() != libsumo::TYPE_POLYGON) {
1605  return false;
1606  }
1607  into.clear();
1608  int size = inputStorage.readUnsignedByte();
1609  if (size == 0) {
1610  size = inputStorage.readInt();
1611  }
1612  PositionVector shape;
1613  for (int i = 0; i < size; ++i) {
1614  double x = inputStorage.readDouble();
1615  double y = inputStorage.readDouble();
1616  if (std::isnan(x) || std::isnan(y)) {
1617  throw libsumo::TraCIException("NaN-Value in shape.");
1618  }
1619  into.push_back(Position(x, y));
1620  }
1621  return true;
1622 }
1623 
1624 
1625 void
1627  myTargetTime = targetTime;
1628  for (auto& s : mySockets) {
1629  s.second->targetTime = targetTime;
1630  s.second->executeMove = false;
1631  for (auto& stateChange : s.second->vehicleStateChanges) {
1632  stateChange.second.clear();
1633  }
1634  for (auto& stateChange : s.second->transportableStateChanges) {
1635  stateChange.second.clear();
1636  }
1637  }
1638  mySubscriptions.clear();
1640 }
1641 
1642 
1643 bool
1644 TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1645  return (s.id == objID && s.commandId + 32 == s.contextDomain);
1646 }
1647 
1648 
1649 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:46
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SUMOTime_MAX
Definition: SUMOTime.h:34
#define SIMTIME
Definition: SUMOTime.h:62
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long 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:76
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:103
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:78
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:602
@ 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:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:1241
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition: MSNet.cpp:1269
TransportableState
Definition of a transportable state.
Definition: MSNet.h:679
@ 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:1173
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:154
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:79
const std::string & getID() const
Returns the id.
Definition: Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
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:361
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:383
std::map< int, SocketInfo * > mySockets
The socket connections to the clients the first component (index) determines the client's order (lowe...
Definition: TraCIServer.h:365
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:371
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:380
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:418
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:386
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.
bool wrapDoubleList(const std::string &objID, const int variable, const std::vector< double > &value)
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 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:394
void removeFilters()
void addSubscriptionFilterLanes(std::vector< int > lanes)
int processCommands(const SUMOTime step, const bool afterMove=false)
process all commands until the next SUMO simulation step. It is guaranteed that t->getTargetTime() >=...
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:374
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:409
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:389
std::vector< libsumo::Subscription > mySubscriptions
The list of known, still valid subscriptions.
Definition: TraCIServer.h:397
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:377
libsumo::Subscription * myLastContextSubscription
The last modified context subscription (the one to add a filter to, see @addSubscriptionFilter(),...
Definition: TraCIServer.h:400
void addSubscriptionFilterVClass(SVCPermissions vClasses)
static TraCIServer * myInstance
Singleton instance of the server.
Definition: TraCIServer.h:358
std::map< int, SocketInfo * > mySocketReorderRequests
This stores the setOrder(int) requests of the clients.
Definition: TraCIServer.h:368
bool addSubscriptionFilter()
std::set< std::pair< int, int > > myParameterized
Set of variables which have parameters.
Definition: TraCIServer.h:392
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:734
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:884
static void collectObjectIDsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition: Helper.cpp:804
static bool needNewSubscription(libsumo::Subscription &s, std::vector< Subscription > &subscriptions, libsumo::Subscription *&modifiedSubscription)
Definition: Helper.cpp:178
Representation of a subscription.
Definition: Subscription.h:70
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
Definition: Subscription.h:137
int commandId
commandIdArg The command id of the subscription
Definition: Subscription.h:114
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
Definition: Subscription.h:141
double filterFieldOfVisionOpeningAngle
Opening angle (in deg) specified by the field of vision filter.
Definition: Subscription.h:145
std::vector< int > filterLanes
lanes specified by the lanes filter
Definition: Subscription.h:133
std::string id
The id of the object that is subscribed.
Definition: Subscription.h:116
SUMOTime endTime
The end time of the subscription.
Definition: Subscription.h:124
int contextDomain
The domain ID of the context.
Definition: Subscription.h:126
double filterFoeDistToJunction
Foe distance to junction specified by the turn filter.
Definition: Subscription.h:139
bool isVehicleToVehicleContextSubscription() const
Definition: Subscription.h:105
SUMOTime beginTime
The begin time of the subscription.
Definition: Subscription.h:122
std::vector< int > variables
The subscribed variables.
Definition: Subscription.h:118
SVCPermissions filterVClasses
vClasses specified by the vClasses filter,
Definition: Subscription.h:143
bool isVehicleToPersonContextSubscription() const
Definition: Subscription.h:109
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
Definition: Subscription.h:135
double filterLateralDist
Lateral distance specified by the lateral distance filter.
Definition: Subscription.h:147
int activeFilters
Active filters for the subscription (bitset,.
Definition: Subscription.h:131
double range
The range of the context.
Definition: Subscription.h:128
std::vector< std::shared_ptr< tcpip::Storage > > parameters
The parameters for the subscribed variables.
Definition: Subscription.h:120
An error which allows to continue.
Definition: TraCIDefs.h:144
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition: socket.cpp:269
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 writeDoubleList(const std::vector< double > &s)
Definition: storage.cpp:262
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 CMD_SUBSCRIBE_BUSSTOP_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_PARKINGAREA_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_EXECUTEMOVE
TRACI_CONST int CMD_SUBSCRIBE_TL_CONTEXT
TRACI_CONST int FILTER_TYPE_FIELD_OF_VISION
TRACI_CONST int TYPE_COMPOUND
TRACI_CONST int CMD_SUBSCRIBE_ROUTEPROBE_VARIABLE
TRACI_CONST int CMD_SET_REROUTER_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_MEANDATA_CONTEXT
TRACI_CONST int CMD_GET_PERSON_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_REROUTER_CONTEXT
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_SUBSCRIBE_OVERHEADWIRE_VARIABLE
TRACI_CONST int CMD_SET_POLYGON_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_BUSSTOP_CONTEXT
TRACI_CONST int POSITION_2D
TRACI_CONST int CMD_GET_BUSSTOP_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_ROUTEPROBE_CONTEXT
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 CMD_SUBSCRIBE_OVERHEADWIRE_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_CALIBRATOR_CONTEXT
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_CHARGINGSTATION_CONTEXT
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 CMD_SUBSCRIBE_PARKINGAREA_CONTEXT
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_REROUTER_VARIABLE
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:49
@ SUBS_FILTER_UPSTREAM_DIST
Definition: Subscription.h:47
@ SUBS_FILTER_VTYPE
Definition: Subscription.h:55
@ SUBS_FILTER_NO_RTREE
Definition: Subscription.h:62
@ SUBS_FILTER_LANES
Definition: Subscription.h:41
@ SUBS_FILTER_NOOPPOSITE
Definition: Subscription.h:43
@ SUBS_FILTER_DOWNSTREAM_DIST
Definition: Subscription.h:45
@ SUBS_FILTER_LATERAL_DIST
Definition: Subscription.h:60
@ SUBS_FILTER_TURN
Definition: Subscription.h:51
@ SUBS_FILTER_VCLASS
Definition: Subscription.h:53
@ SUBS_FILTER_NONE
Definition: Subscription.h:39
@ SUBS_FILTER_FIELD_OF_VISION
Definition: Subscription.h:58
TRACI_CONST int CMD_SUBSCRIBE_LANEAREA_VARIABLE
TRACI_CONST int TYPE_BYTE
TRACI_CONST int CMD_SUBSCRIBE_POI_CONTEXT
TRACI_CONST int CMD_SUBSCRIBE_CALIBRATOR_VARIABLE
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_SUBSCRIBE_CHARGINGSTATION_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 CMD_SUBSCRIBE_VARIABLESPEEDSIGN_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 CMD_SUBSCRIBE_MEANDATA_VARIABLE
TRACI_CONST int FILTER_TYPE_LATERAL_DIST
TRACI_CONST int CMD_SUBSCRIBE_EDGE_VARIABLE
TRACI_CONST int TYPE_STRING
TRACI_CONST int CMD_SUBSCRIBE_VARIABLESPEEDSIGN_VARIABLE
A 2D or 3D-position, for 2D positions z == INVALID_DOUBLE_VALUE.
Definition: TraCIDefs.h:178
A list of positions.
Definition: TraCIDefs.h:234
std::vector< TraCIPosition > value
Definition: TraCIDefs.h:244