Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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-2025 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>
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>
59#include <microsim/MSLane.h>
60#include <microsim/MSGlobals.h>
62#include <libsumo/Helper.h>
64#include <libsumo/Simulation.h>
67#include "TraCIServer.h"
70#include "TraCIServerAPI_Lane.h"
77#include "TraCIServerAPI_POI.h"
79#include "TraCIServerAPI_Edge.h"
91
92
93// ===========================================================================
94// debug constants
95// ===========================================================================
96//#define DEBUG_MULTI_CLIENTS
97//#define DEBUG_SUBSCRIPTIONS
98//#define DEBUG_SUBSCRIPTION_FILTERS
99//#define DEBUG_RAW_INPUT
100
101
102// ===========================================================================
103// static member definitions
104// ===========================================================================
107
108
109// ===========================================================================
110// method definitions
111// ===========================================================================
112void
113TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
118}
119
120
121bool
122TraCIServer::wrapConnectionVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIConnection>& value) {
123 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 8);
124 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
125 for (const libsumo::TraCIConnection& c : value) {
127 StoHelp::writeTypedString(myWrapperStorage, c.approachedInternal);
134 }
135 return true;
136}
137
138
139bool
140TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
143 return true;
144}
145
146
147bool
148TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
151 return true;
152}
153
154
155bool
156TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
159 return true;
160}
161
162
163bool
164TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
167 return true;
168}
169
170
171bool
172TraCIServer::wrapDoubleList(const std::string& /* objID */, const int /* variable */, const std::vector<double>& value) {
175 return true;
176}
177
178
179bool
180TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
181 const bool includeZ = variable == libsumo::VAR_POSITION3D;
185 if (includeZ) {
187 }
188 return true;
189}
190
191
192bool
193TraCIServer::wrapPositionVector(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIPositionVector& shape) {
195 if (shape.value.size() < 256) {
196 myWrapperStorage.writeUnsignedByte((int)shape.value.size());
197 } else {
199 myWrapperStorage.writeInt((int)shape.value.size());
200 }
201 for (const libsumo::TraCIPosition& pos : shape.value) {
204 }
205 return true;
206}
207
208
209bool
210TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
216 return true;
217}
218
219
220bool
221TraCIServer::wrapStringDoublePair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, double>& value) {
225 return true;
226}
227
228
229bool
230TraCIServer::wrapStringDoublePairList(const std::string& /* objID */, const int /* variable */, const std::vector<std::pair<std::string, double> >& value) {
231 StoHelp::writeCompound(myWrapperStorage, (int)value.size());
232 for (const auto& p : value) {
235 }
236 return true;
237}
238
239
240bool
241TraCIServer::wrapStringPair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, std::string>& value) {
245 return true;
246}
247
248
249bool
250TraCIServer::wrapIntPair(const std::string& /* objID */, const int /* variable */, const std::pair<int, int>& value) {
254 return true;
255}
256
257
258bool
259TraCIServer::wrapStage(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIStage& value) {
261 return true;
262}
263
264
265bool
266TraCIServer::wrapReservationVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIReservation>& value) {
267 StoHelp::writeCompound(myWrapperStorage, (int)value.size());
268 for (const libsumo::TraCIReservation& r : value) {
280 }
281 return true;
282}
283
284
285bool
286TraCIServer::wrapLogicVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCILogic>& value) {
287 StoHelp::writeCompound(myWrapperStorage, (int)value.size());
288 for (const libsumo::TraCILogic& logic : value) {
292 StoHelp::writeTypedInt(myWrapperStorage, logic.currentPhaseIndex);
293 StoHelp::writeCompound(myWrapperStorage, (int)logic.phases.size());
294 for (const std::shared_ptr<libsumo::TraCIPhase>& phase : logic.phases) {
300 StoHelp::writeCompound(myWrapperStorage, (int)phase->next.size());
301 for (int n : phase->next) {
303 }
305 }
306 StoHelp::writeCompound(myWrapperStorage, (int)logic.subParameter.size());
307 for (const auto& item : logic.subParameter) {
308 StoHelp::writeTypedStringList(myWrapperStorage, std::vector<std::string> {item.first, item.second});
309 }
310 }
311 return true;
312}
313
314
315bool
316TraCIServer::wrapLinkVectorVector(const std::string& /* objID */, const int /* variable */, const std::vector<std::vector<libsumo::TraCILink> >& value) {
317 int cnt = 1;
318 for (const std::vector<libsumo::TraCILink>& sublinks : value) {
319 cnt += (int)sublinks.size() + 1;
320 }
322 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
323 for (const std::vector<libsumo::TraCILink>& sublinks : value) {
325 for (const libsumo::TraCILink& link : sublinks) {
326 StoHelp::writeTypedStringList(myWrapperStorage, std::vector<std::string>({ link.fromLane, link.toLane, link.viaLane }));
327 }
328 }
329 return true;
330}
331
332
333bool
334TraCIServer::wrapSignalConstraintVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCISignalConstraint>& value) {
335 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 5);
336 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
337 for (const auto& c : value) {
339 }
340 return true;
341}
342
343
344bool
345TraCIServer::wrapJunctionFoeVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIJunctionFoe>& value) {
346 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 9);
347 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
348 for (const auto& c : value) {
358 }
359 return true;
360}
361
362
363bool
364TraCIServer::wrapNextStopDataVector(const std::string& /* objID */, const int variable, const std::vector<libsumo::TraCINextStopData>& value) {
365 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 4);
366 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
367 const bool full = variable == libsumo::VAR_NEXT_STOPS2;
368 for (const auto& s : value) {
369 const int legacyStopFlags = (s.stopFlags << 1) + (s.arrival >= 0 ? 1 : 0);
373 StoHelp::writeTypedInt(myWrapperStorage, full ? s.stopFlags : legacyStopFlags);
376 if (full) {
387 }
388 }
389 return true;
390}
391
392
393bool
394TraCIServer::wrapVehicleDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIVehicleData>& value) {
395 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 5);
396 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
397 for (const libsumo::TraCIVehicleData& vd : value) {
403 }
404 return true;
405}
406
407
408bool
409TraCIServer::wrapBestLanesDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIBestLanesData>& value) {
410 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 6);
411 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
412 for (const libsumo::TraCIBestLanesData& bld : value) {
416 StoHelp::writeTypedByte(myWrapperStorage, bld.bestLaneOffset);
417 StoHelp::writeTypedUnsignedByte(myWrapperStorage, bld.allowsContinuation ? 1 : 0);
418 StoHelp::writeTypedStringList(myWrapperStorage, bld.continuationLanes);
419 }
420 return true;
421}
422
423
424bool
425TraCIServer::wrapNextTLSDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCINextTLSData>& value) {
426 StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 4);
427 StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
428 for (const libsumo::TraCINextTLSData& tlsd : value) {
433 }
434 return true;
435}
436
437
442
443
444
445TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
446 : myTargetTime(begin), myLastContextSubscription(nullptr) {
447#ifdef DEBUG_MULTI_CLIENTS
448 std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
449#endif
450 myVehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
451 myVehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
454 myVehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
455 myVehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
457 myVehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
459 myVehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
460 myVehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
461 myVehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
462 myVehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
463
468
475
513 //myExecutors[libsumo::CMD_SET_MEANDATA_VARIABLE] = &TraCIServerAPI_MeanData::processSet;
516
546 myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_NEXT_STOPS)); // this is just a dummy to trigger an error
549 myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER));
550 myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER_WITH_KEY));
551
552 myDoCloseConnection = false;
553
554 // display warning if internal lanes are not used
555 // TODO this may be redundant to the warning in NLBuilder::build
557 WRITE_WARNING(TL("Starting TraCI without using internal lanes!"));
558 MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
559 MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
560 }
561
562 try {
563 WRITE_MESSAGEF(TL("***Starting server on port % ***"), toString(port));
564 tcpip::Socket serverSocket(port);
565 if (numClients > 1) {
566 WRITE_MESSAGEF(TL(" waiting for % clients..."), toString(numClients));
567 }
568 while ((int)mySockets.size() < numClients) {
569 int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
570 mySockets[index] = new SocketInfo(serverSocket.accept(true), begin);
571 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
572 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
573 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
574 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
575 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
576 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
577 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
578 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
579 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
580 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
581 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
582 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
583 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
584
585 mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
586 mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
587 mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
588 mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
589 if (numClients > 1) {
590 WRITE_MESSAGE(TL(" client connected"));
591 }
592 }
593 // When got here, all clients have connected
594 if (numClients > 1) {
596 }
597 // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommands()
598 myCurrentSocket = mySockets.begin();
599 } catch (tcpip::SocketException& e) {
600 throw ProcessError(e.what());
601 }
602}
603
604
606 for (const auto& socket : mySockets) {
607 delete socket.second;
608 }
609 // there is no point in calling cleanup() here, it does not free any pointers and will only modify members which get deleted anyway
610}
611
612
613// ---------- Initialisation and Shutdown
614void
615TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
616 if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
617 myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
618 OptionsCont::getOptions().getInt("remote-port"),
619 OptionsCont::getOptions().getInt("num-clients"));
620 for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
621 myInstance->myExecutors[i->first] = i->second;
622 }
623 }
624 if (myInstance != nullptr) {
625 // maybe net was deleted and built again
629 }
630}
631
632
633void
635 if (myInstance == nullptr) {
636 return;
637 }
638 delete myInstance;
639 myInstance = nullptr;
640 myDoCloseConnection = true;
641}
642
643
644bool
648
649
650// ---------- Initialisation and Shutdown
651
652
653void
654TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
655 if (!myDoCloseConnection) {
656 myVehicleStateChanges[to].push_back(vehicle->getID());
657 for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
658 i->second->vehicleStateChanges[to].push_back(vehicle->getID());
659 }
660 }
661}
662
663
664void
665TraCIServer::transportableStateChanged(const MSTransportable* const transportable, MSNet::TransportableState to, const std::string& /*info*/) {
666 if (!myDoCloseConnection) {
667 myTransportableStateChanges[to].push_back(transportable->getID());
668 for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
669 i->second->transportableStateChanges[to].push_back(transportable->getID());
670 }
671 }
672}
673
674
675void
677#ifdef DEBUG_MULTI_CLIENTS
678 std::cout << "Checking client order requests." << std::endl;
679#endif
680 // check for SET_ORDER commands queued by connected clients
681 // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
682 myCurrentSocket = mySockets.begin();
683 while (myCurrentSocket != mySockets.end()) {
684#ifdef DEBUG_MULTI_CLIENTS
685 std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
686#endif
687// bool clientUnordered = true;
688 while (true) {
690 myCurrentSocket->second->socket->receiveExact(myInputStorage);
691 int commandStart, commandLength;
692 int commandId = readCommandID(commandStart, commandLength);
693#ifdef DEBUG_MULTI_CLIENTS
694 std::cout << " received command " << commandId << std::endl;
695#endif
696 // Whether the received command is a permitted command for the initialization phase.
697 // Currently, getVersion and setOrder are permitted.
698 bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
699 if (initCommand) {
700#ifdef DEBUG_MULTI_CLIENTS
701 std::cout << " Init command. Sending response." << std::endl;
702#endif
703 // reset input storage to initial state before reading the commandId
704 // (ugly, but we can't just reset the store's iter_ from here)
705 // Giving the commandId to dispatch command didn't work either
706 tcpip::Storage tmp;
709 // we don't know whether the command was set with extended
710 // length syntax or not so we hardcode the length here (#5037)
714
715 // Handle initialization command completely
717 myCurrentSocket->second->socket->sendExact(myOutputStorage);
719 } else {
720#ifdef DEBUG_MULTI_CLIENTS
721 std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
722#endif
723 throw ProcessError(TL("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase."));
724 }
725 if (commandId == libsumo::CMD_SETORDER) {
726 // This is what we have waited for.
727 break;
728 }
729 }
731 }
732}
733
734
735void
737 // Process reordering requests
738 if (mySocketReorderRequests.size() > 0) {
739 // process reordering requests
740 std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
741 std::map<int, SocketInfo*>::iterator j;
742#ifdef DEBUG_MULTI_CLIENTS
743 std::cout << SIMTIME << " Current socket ordering:\n";
744 for (j = mySockets.begin(); j != mySockets.end(); ++j) {
745 std::cout << " " << j->first << ": " << j->second->socket << "\n";
746 }
747 std::cout << "Reordering requests:\n";
748 for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
749 std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
750 }
751 i = mySocketReorderRequests.begin();
752#endif
753 while (i != mySocketReorderRequests.end()) {
754 j = mySockets.begin();
755 while (j != mySockets.end()) {
756 if (j->second->socket == i->second->socket) {
757 break;
758 } else {
759 j++;
760 }
761 }
762 assert(j != mySockets.end());
763 mySockets.erase(j);
764 mySockets[i->first] = i->second;
765 ++i;
766 }
768#ifdef DEBUG_MULTI_CLIENTS
769 std::cout << "New socket ordering:\n";
770 for (j = mySockets.begin(); j != mySockets.end(); ++j) {
771 std::cout << " " << j->first << ": " << j->second->socket << "\n";
772 }
773 std::cout << std::endl;
774#endif
775 }
776}
777
778
781#ifdef DEBUG_MULTI_CLIENTS
782 std::cout << "\n Determining new target time..." << std::endl;
783 if (mySockets.size() == 0) {
784 std::cout << " All clients have disconnected." << std::endl;
785 }
786#endif
787 std::map<int, SocketInfo*>::const_iterator i;
788 SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
789 for (i = mySockets.begin(); i != mySockets.end(); ++i) {
790#ifdef DEBUG_MULTI_CLIENTS
791 std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
792#endif
793 targetTime = MIN2(targetTime, i->second->targetTime);
794 }
795#ifdef DEBUG_MULTI_CLIENTS
796 std::cout << std::endl;
797#endif
798 return targetTime;
799}
800
801
802// send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
803void
805#ifdef DEBUG_MULTI_CLIENTS
806 std::cout << "\n Sending subscription results to clients:\n";
807#endif
808 std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
809 while (i != mySockets.end()) {
810 if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
811 // this client will become active before the next SUMO step. Provide subscription results.
812 i->second->socket->sendExact(myOutputStorage);
813#ifdef DEBUG_MULTI_CLIENTS
814 std::cout << i->second->socket << "\n";
815#endif
816 }
817 ++i;
818 }
819#ifdef DEBUG_MULTI_CLIENTS
820 std::cout << std::endl;
821#endif
822}
823
824
825int
826TraCIServer::processCommands(const SUMOTime step, const bool afterMove) {
827#ifdef DEBUG_MULTI_CLIENTS
828 std::cout << SIMTIME << " processCommands(step = " << step << "):\n" << std::endl;
829#endif
830 try {
831 int finalCmd = 0;
832 const bool firstStep = myCurrentSocket != mySockets.end();
833 // update client order if requested
835 if (!firstStep && !afterMove) {
836 // 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)
837 // update subscription results
839 // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
842 }
843
844 // determine minimal next target time among clients
846
847 if (step < myTargetTime) {
848#ifdef DEBUG_MULTI_CLIENTS
849 std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommands()." << std::endl;
850#endif
851 return finalCmd;
852 }
853
854 // Simulation should run until
855 // 1. end time reached or
856 // 2. got libsumo::CMD_CLOSE or
857 // 3. got libsumo::CMD_LOAD or
858 // 4. Client closes socket connection
859 while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep()) && finalCmd != libsumo::CMD_EXECUTEMOVE) {
860#ifdef DEBUG_MULTI_CLIENTS
861 std::cout << " Next target time: " << myTargetTime << std::endl;
862#endif
863 // Iterate over clients and process communication for the ones with target time == myTargetTime
864 myCurrentSocket = mySockets.begin();
865 while (myCurrentSocket != mySockets.end()) {
866#ifdef DEBUG_MULTI_CLIENTS
867 std::cout << " current socket: " << myCurrentSocket->second->socket
868 << " with target time=" << myCurrentSocket->second->targetTime
869 << std::endl;
870#endif
871
872 if (myCurrentSocket->second->targetTime > myTargetTime || (afterMove && !myCurrentSocket->second->executeMove)) {
873 // this client must wait
874#ifdef DEBUG_MULTI_CLIENTS
875 std::cout << " skipping client " << myCurrentSocket->second->socket
876 << " with target time=" << myCurrentSocket->second->targetTime << std::endl;
877#endif
879 continue;
880 }
881 finalCmd = 0;
882 while (finalCmd == 0) {
883 if (!myInputStorage.valid_pos()) {
884 // have read request completely, send response if adequate
885 if (myOutputStorage.size() > 0) {
886 // send response to previous query
887 myCurrentSocket->second->socket->sendExact(myOutputStorage);
889 }
890#ifdef DEBUG_MULTI_CLIENTS
891 std::cout << " resetting input storage and reading next command..." << std::endl;
892#endif
893 // Read next request
895 myCurrentSocket->second->socket->receiveExact(myInputStorage);
896 }
897
899 const int cmd = dispatchCommand();
901 finalCmd = cmd;
902 }
903 }
904 }
905 }
906 if (!myLoadArgs.empty()) {
907#ifdef DEBUG_MULTI_CLIENTS
908 std::cout << " Breaking loop to load new simulation." << std::endl;
909#endif
910 break;
911 } else if (myDoCloseConnection) {
912#ifdef DEBUG_MULTI_CLIENTS
913 std::cout << " Breaking loop because last client closed connection." << std::endl;
914#endif
915 break;
916 }
917 SUMOTime nextT = nextTargetTime();
918 // minimal target time among clients should have been increased during the last loop through mySockets
919 // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
920 // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
921 // the next call is then usually simulationStep(step=1000) leading to no further increase
922 // and thus a failing assertion here.
923 //assert(myTargetTime < nextT || myDoCloseConnection);
924 myTargetTime = nextT;
925 }
926 // All clients are done with the current time step
927 // Reset myVehicleStateChanges and myTransportableStateChanges
928 for (auto& item : myVehicleStateChanges) {
929 item.second.clear();
930 }
931 for (auto& item : myTransportableStateChanges) {
932 item.second.clear();
933 }
934 return finalCmd;
935 } catch (std::invalid_argument& e) {
936 throw ProcessError(e.what());
937 } catch (libsumo::TraCIException& e) {
938 throw ProcessError(e.what());
939 } catch (tcpip::SocketException& e) {
940 throw ProcessError(e.what());
941 }
942}
943
944
945void
947 mySubscriptions.clear();
948 myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
950 myCurrentSocket->second->targetTime = myTargetTime;
951 myCurrentSocket->second->executeMove = false;
952 }
956 for (auto& i : myVehicleStateChanges) {
957 i.second.clear();
958 }
959 for (auto& i : myTransportableStateChanges) {
960 i.second.clear();
961 }
962 myCurrentSocket = mySockets.begin();
963}
964
965
966std::map<int, TraCIServer::SocketInfo*>::iterator
968#ifdef DEBUG_MULTI_CLIENTS
969 std::cout << " Removing socket " << myCurrentSocket->second->socket
970 << " (order " << myCurrentSocket->first << ")" << std::endl;
971#endif
972 delete myCurrentSocket->second;
974 return myCurrentSocket;
975}
976
977
978int
979TraCIServer::readCommandID(int& commandStart, int& commandLength) {
980 commandStart = myInputStorage.position();
981 commandLength = myInputStorage.readUnsignedByte();
982 if (commandLength == 0) {
983 commandLength = myInputStorage.readInt();
984 }
985#ifdef DEBUG_RAW_INPUT
986 std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
987 for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
988 std::cout << (int)*it << " ";
989 }
990 std::cout << "\n";
991#endif
993}
994
995
996int
998 int commandStart, commandLength;
999 int commandId = readCommandID(commandStart, commandLength);
1000#ifdef DEBUG_MULTI_CLIENTS
1001 std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
1002 << ", commandId = " << commandId << std::endl;
1003#endif
1004 bool success = false;
1005 // dispatch commands
1006 if (myExecutors.find(commandId) != myExecutors.end()) {
1007 success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
1008 } else {
1009 switch (commandId) {
1011 success = commandGetVersion();
1012 break;
1013 case libsumo::CMD_LOAD: {
1014 std::vector<std::string> args;
1016 return writeErrorStatusCmd(libsumo::CMD_LOAD, "A load command needs a list of string arguments.", myOutputStorage);
1017 }
1018#ifdef DEBUG_MULTI_CLIENTS
1019 std::cout << " commandId == libsumo::CMD_LOAD"
1020 << ", args = " << toString(args) << std::endl;
1021#endif
1022 try {
1023 myLoadArgs = args;
1024 success = true;
1026 // XXX: This only cares for the client that issued the load command.
1027 // Multiclient-load functionality is still to be implemented. Refs #3146.
1028 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1029 myCurrentSocket = mySockets.end();
1031 } catch (libsumo::TraCIException& e) {
1033 }
1034 break;
1035 }
1037 myCurrentSocket->second->executeMove = true;
1039 success = true;
1041 break;
1042 case libsumo::CMD_SIMSTEP: {
1043 const double nextT = myInputStorage.readDouble();
1044 if (nextT == 0.) {
1045 myCurrentSocket->second->targetTime += DELTA_T;
1046 } else {
1047 myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
1048 }
1049 myCurrentSocket->second->executeMove = false;
1050#ifdef DEBUG_MULTI_CLIENTS
1051 std::cout << " commandId == libsumo::CMD_SIMSTEP"
1052 << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
1053#endif
1054 if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
1055 // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
1056 // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommands()
1058 }
1059 // Clear vehicleStateChanges and transportableStateChanges for this client
1060 // -> For subsequent TraCI stepping
1061 // that is performed within this SUMO step, no updates on vehicle states
1062 // belonging to the last SUMO simulation step will be received by this client.
1063 for (auto& item : myCurrentSocket->second->vehicleStateChanges) {
1064 item.second.clear();
1065 }
1066 for (auto& item : myCurrentSocket->second->transportableStateChanges) {
1067 item.second.clear();
1068 }
1070 return commandId;
1071 }
1072 case libsumo::CMD_CLOSE:
1074 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1076 if (mySockets.size() == 1) {
1077 // Last client has closed connection
1078 myDoCloseConnection = true;
1079 }
1080 // remove current socket and increment to next socket in ordering
1082 success = true;
1083 break;
1084 case libsumo::CMD_SETORDER: {
1085 const int order = myInputStorage.readInt();
1086#ifdef DEBUG_MULTI_CLIENTS
1087 std::cout << " commandId == libsumo::CMD_SETORDER"
1088 << ", order index is " << order << std::endl;
1089#endif
1090 if (order > libsumo::MAX_ORDER) {
1091 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
1092 }
1093 if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
1094 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
1095 }
1096 // memorize reorder request (will only take effect in the next step)
1098 success = true;
1100 break;
1101 }
1126 success = addObjectVariableSubscription(commandId, false);
1127 break;
1152 success = addObjectVariableSubscription(commandId, true);
1153 break;
1155 success = addSubscriptionFilter();
1156 break;
1157 default:
1158 if (commandId == libsumo::CMD_GET_GUI_VARIABLE || commandId == libsumo::CMD_SET_GUI_VARIABLE) {
1159 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1160 } else {
1161 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
1162 }
1163 }
1164 }
1165 if (!success) {
1166 while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
1168 }
1169 }
1170 if ((int)myInputStorage.position() != commandStart + commandLength) {
1171 std::ostringstream msg;
1172 msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
1173 msg << " Expected command length was " << commandLength;
1174 msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
1175 writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
1176 myDoCloseConnection = true;
1177 }
1178 return commandId;
1179}
1180
1181
1182// ---------- Server-internal command handling
1183bool
1185 // Prepare response
1186 tcpip::Storage answerTmp;
1188 answerTmp.writeString("SUMO " VERSION_STRING);
1189 // When we get here, the response is stored in answerTmp -> put into myOutputStorage
1191 // command length
1192 myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
1193 // command type
1195 // and the parameter dependant part
1196 myOutputStorage.writeStorage(answerTmp);
1197 return true;
1198}
1199
1200
1201void
1204#ifdef DEBUG_MULTI_CLIENTS
1205 std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
1206#endif
1208 int noActive = 0;
1209 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1210 const libsumo::Subscription& s = *i;
1213
1215 if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
1216 i = mySubscriptions.erase(i);
1217 continue;
1218 }
1219 ++i;
1220 if (s.beginTime > t) {
1221 continue;
1222 }
1223 ++noActive;
1224 }
1226#ifdef DEBUG_SUBSCRIPTIONS
1227 std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
1228 << "\n Nr. of active subscriptions = " << noActive << std::endl;
1229#endif
1230 mySubscriptionCache.writeInt(noActive);
1231#ifdef DEBUG_SUBSCRIPTIONS
1232 std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
1233#endif
1234 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1235 const libsumo::Subscription& s = *i;
1236 if (s.beginTime > t) {
1237 ++i;
1238 continue;
1239 }
1240 tcpip::Storage into;
1241 std::string errors;
1242 bool ok = processSingleSubscription(s, into, errors);
1243#ifdef DEBUG_SUBSCRIPTIONS
1244 std::cout << " Size of into-store for subscription " << s.id
1245 << ": " << into.size() << std::endl;
1246#endif
1248 if (ok) {
1249 ++i;
1250 } else {
1251 i = mySubscriptions.erase(i);
1252 }
1253 }
1255#ifdef DEBUG_SUBSCRIPTIONS
1256 std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1257#endif
1258}
1259
1260
1261void
1263#ifdef DEBUG_MULTI_CLIENTS
1264 std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1265 << " (-> intermediate TraCI step)."
1266 << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1267 << std::endl;
1268#endif
1270
1271// NOTE: the commented code would send an empty response
1272// myOutputStorage.writeInt(0);
1273// myCurrentSocket->second->socket->sendExact(myOutputStorage);
1274// myOutputStorage.reset();
1276 // send results to active client
1277 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1279}
1280
1281
1282void
1283TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1284 writeStatusCmd(commandId, status, description, myOutputStorage);
1285}
1286
1287
1288void
1289TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1290 if (status == libsumo::RTYPE_ERR) {
1291 WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1292 } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1293 WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1294 }
1295 outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1296 outputStorage.writeUnsignedByte(commandId); // command type
1297 outputStorage.writeUnsignedByte(status); // status
1298 outputStorage.writeString(description); // description
1299}
1300
1301
1302bool
1303TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1304 writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1305 return false;
1306}
1307
1308
1309void
1311 tcpip::Storage writeInto;
1312 std::string errors;
1313 libsumo::Subscription* modifiedSubscription = nullptr;
1314 try {
1315 if (processSingleSubscription(s, writeInto, errors)) {
1317 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1318 } else {
1319 if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1320 // Add new subscription to subscription cache (note: seems a bit inefficient)
1322 // copy new subscription into cache
1323 int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1324 tcpip::Storage tmp;
1325 tmp.writeInt(noActive);
1326 while (mySubscriptionCache.valid_pos()) {
1328 }
1329 tmp.writeStorage(writeInto);
1332 }
1333 }
1335 }
1336 if (modifiedSubscription != nullptr && (
1337 modifiedSubscription->isVehicleToVehicleContextSubscription()
1338 || modifiedSubscription->isVehicleToPersonContextSubscription())) {
1339 // Set last modified vehicle context subscription active for filter modifications
1340 myLastContextSubscription = modifiedSubscription;
1341 } else {
1342 // adding other subscriptions deactivates the activation for filter addition
1343 myLastContextSubscription = nullptr;
1344 }
1345 } else {
1346 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1347 }
1348 } catch (libsumo::TraCIException& e) {
1350 }
1351 myOutputStorage.writeStorage(writeInto);
1352}
1353
1354
1355void
1356TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1357 bool found = false;
1358 std::vector<libsumo::Subscription>::iterator j;
1359 for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1360 if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1361 j = mySubscriptions.erase(j);
1362 if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1363 // Remove also reference for filter additions
1364 myLastContextSubscription = nullptr;
1365 }
1366 found = true;
1367 continue;
1368 }
1369 ++j;
1370 }
1371 // try unsubscribe
1372 if (found) {
1373 writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1374 } else {
1375 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1376 }
1377}
1378
1379
1380bool
1382 std::string& errors) {
1383 bool ok = true;
1384 tcpip::Storage outputStorage;
1385 const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1386 std::set<std::string> objIDs;
1387 if (s.contextDomain > 0) {
1389 PositionVector shape;
1392 }
1394 } else {
1395 objIDs.insert(s.id);
1396 }
1397 const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1398 int skipped = 0;
1399 for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1400 if (s.contextDomain > 0) {
1401 //if (centralObject(s, *j)) {
1402 // skipped++;
1403 // continue;
1404 //}
1405 outputStorage.writeString(*j);
1406 }
1407 if (numVars > 0) {
1408 std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1409 for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1410 tcpip::Storage message;
1411 message.writeUnsignedByte(*i);
1412 message.writeString(*j);
1413 // TODO check why writeStorage fails here (probably some kind of invalid iterator)
1414 for (const auto& v :** k) {
1415 message.writeChar(v);
1416 }
1417 tcpip::Storage tmpOutput;
1418 try {
1419 if (myExecutors.find(getCommandId) != myExecutors.end()) {
1420 ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1421 } else {
1422 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1423 ok = false;
1424 }
1425 } catch (const std::invalid_argument&) {
1426 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1427 ok = false;
1428 }
1429 // copy response part
1430 if (ok) {
1431 int length = tmpOutput.readUnsignedByte();
1432 while (--length > 0) {
1433 tmpOutput.readUnsignedByte();
1434 }
1435 int lengthLength = 1;
1436 length = tmpOutput.readUnsignedByte();
1437 if (length == 0) {
1438 lengthLength = 5;
1439 length = tmpOutput.readInt();
1440 }
1441 //read responseType
1442 tmpOutput.readUnsignedByte();
1443 int variable = tmpOutput.readUnsignedByte();
1444 std::string id = tmpOutput.readString();
1445 outputStorage.writeUnsignedByte(variable);
1446 outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1447 length -= (lengthLength + 1 + 4 + (int)id.length());
1448 while (--length > 0) {
1449 outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1450 }
1451 } else {
1452 //read length
1453 tmpOutput.readUnsignedByte();
1454 //read cmd
1455 tmpOutput.readUnsignedByte();
1456 //read status
1457 tmpOutput.readUnsignedByte();
1458 std::string msg = tmpOutput.readString();
1459 outputStorage.writeUnsignedByte(*i);
1462 outputStorage.writeString(msg);
1463 errors = errors + msg;
1464 }
1465 }
1466 }
1467 }
1468 int length = (1 + 4) + 1 + (4 + (int)s.id.length()) + 1 + (int)outputStorage.size();
1469 if (s.contextDomain > 0) {
1470 length += 1 + 4; // context domain and number of objects
1471 }
1472 // we always write extended command length here for backward compatibility
1473 writeInto.writeUnsignedByte(0); // command length -> extended
1474 writeInto.writeInt(length);
1475 writeInto.writeUnsignedByte(s.commandId + 0x10);
1476 writeInto.writeString(s.id);
1477 if (s.contextDomain > 0) {
1478 writeInto.writeUnsignedByte(s.contextDomain);
1479 }
1480 writeInto.writeUnsignedByte(numVars);
1481 if (s.contextDomain > 0) {
1482 writeInto.writeInt((int)objIDs.size() - skipped);
1483 }
1484 if (s.contextDomain == 0 || objIDs.size() != 0) {
1485 writeInto.writeStorage(outputStorage);
1486 }
1487 return ok;
1488}
1489
1490
1491bool
1492TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1493 const double beginTime = myInputStorage.readDouble();
1494 const double endTime = myInputStorage.readDouble();
1495 const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1496 const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1497 const std::string id = myInputStorage.readString();
1498 const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1499 double range = hasContext ? myInputStorage.readDouble() : 0.;
1500 if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
1501 range = std::numeric_limits<double>::max();
1502 }
1503 const int num = myInputStorage.readUnsignedByte();
1504 std::vector<int> variables;
1505 std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1506 for (int i = 0; i < num; ++i) {
1507 const int varID = myInputStorage.readUnsignedByte();
1508 variables.push_back(varID);
1509 parameters.push_back(std::make_shared<tcpip::Storage>());
1510 if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1511 if (!myInputStorage.valid_pos()) {
1512 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Missing parameter for subscription " + toHex(commandId, 2));
1513 return false;
1514 }
1515 int count = 1;
1516 while (count-- > 0) {
1517 const int parType = myInputStorage.readUnsignedByte();
1518 parameters.back()->writeUnsignedByte(parType);
1519 if (parType == libsumo::TYPE_DOUBLE) {
1520 parameters.back()->writeDouble(myInputStorage.readDouble());
1521 } else if (parType == libsumo::TYPE_INTEGER) {
1522 parameters.back()->writeInt(myInputStorage.readInt());
1523 } else if (parType == libsumo::TYPE_STRING) {
1524 parameters.back()->writeString(myInputStorage.readString());
1525 } else if (parType == libsumo::TYPE_BYTE) {
1526 parameters.back()->writeByte(myInputStorage.readByte());
1527 } else if (parType == libsumo::TYPE_UBYTE) {
1528 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1529 } else if (parType == libsumo::POSITION_2D) {
1530 parameters.back()->writeDouble(myInputStorage.readDouble());
1531 parameters.back()->writeDouble(myInputStorage.readDouble());
1532 if (varID == libsumo::DISTANCE_REQUEST) {
1533 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1534 break;
1535 }
1536 } else if (parType == libsumo::POSITION_3D) {
1537 parameters.back()->writeDouble(myInputStorage.readDouble());
1538 parameters.back()->writeDouble(myInputStorage.readDouble());
1539 parameters.back()->writeDouble(myInputStorage.readDouble());
1540 if (varID == libsumo::DISTANCE_REQUEST) {
1541 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1542 break;
1543 }
1544 } else if (parType == libsumo::POSITION_ROADMAP) {
1545 parameters.back()->writeString(myInputStorage.readString());
1546 parameters.back()->writeDouble(myInputStorage.readDouble());
1547 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1548 if (varID == libsumo::DISTANCE_REQUEST) {
1549 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1550 break;
1551 }
1552 } else if (parType == libsumo::TYPE_COMPOUND) {
1553 count = myInputStorage.readInt();
1554 parameters.back()->writeInt(count);
1555 } else {
1556 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Invalid parameter for subscription " + toHex(commandId, 2));
1557 return false;
1558 }
1559 }
1560 }
1561 }
1562 // check subscribe/unsubscribe
1563 if (variables.empty()) {
1564 removeSubscription(commandId, id, domain);
1565 return true;
1566 }
1567 // process subscription
1568 libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1570 return true;
1571}
1572
1573
1574
1575bool
1577 bool success = true;
1578 // Read filter type
1579 int filterType = myInputStorage.readUnsignedByte();
1580
1581 if (myLastContextSubscription == nullptr) {
1583 "No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1584 return false;
1585 }
1586
1587 // dispatch according to filter type
1588 switch (filterType) {
1590 // Remove all filters
1591 removeFilters();
1592 break;
1594 // Read relative lanes to consider for context filter
1595 int nrLanes = (int)myInputStorage.readByte();
1596 std::vector<int> lanes;
1597 for (int i = 0; i < nrLanes; ++i) {
1598 lanes.push_back((int) myInputStorage.readByte());
1599 }
1601 }
1602 break;
1604 // Add no-opposite filter
1606 break;
1608 myInputStorage.readByte(); // read type double
1609 double dist = myInputStorage.readDouble();
1611 }
1612 break;
1614 myInputStorage.readByte(); // read type double
1615 double dist = myInputStorage.readDouble();
1617 }
1618 break;
1620 // Read relative lanes to consider for context filter
1622 }
1623 break;
1625 myInputStorage.readByte(); // read type double
1626 double dist = myInputStorage.readDouble();
1628 }
1629 break;
1631 myInputStorage.readByte(); // read type stringlist
1634 }
1635 break;
1637 myInputStorage.readByte(); // read type stringlist
1638 std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1639 std::set<std::string> vTypesSet;
1640 vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1641 addSubscriptionFilterVType(vTypesSet);
1642 }
1643 break;
1645 myInputStorage.readByte(); // read type double
1646 double angle = myInputStorage.readDouble();
1648 }
1649 break;
1651 myInputStorage.readByte(); // read type double
1652 double dist = myInputStorage.readDouble();
1654 }
1655 break;
1656 default:
1658 "'" + toString(filterType) + "' is no valid filter type code.");
1659 success = false;
1660 }
1661
1662 if (success) {
1663 // acknowledge filter addition
1665 }
1666
1667 return success;
1668}
1669
1670
1671void
1673#ifdef DEBUG_SUBSCRIPTION_FILTERS
1674 std::cout << "Removing filters" << std::endl;
1675#endif
1677}
1678
1679void
1681#ifdef DEBUG_SUBSCRIPTION_FILTERS
1682 std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1683#endif
1686}
1687
1688void
1690#ifdef DEBUG_SUBSCRIPTION_FILTERS
1691 std::cout << "Adding no opposite filter" << std::endl;
1692#endif
1694}
1695
1696void
1698#ifdef DEBUG_SUBSCRIPTION_FILTERS
1699 std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1700#endif
1703}
1704
1705void
1707#ifdef DEBUG_SUBSCRIPTION_FILTERS
1708 std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1709#endif
1712}
1713
1714void
1716#ifdef DEBUG_SUBSCRIPTION_FILTERS
1717 std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1718#endif
1720}
1721
1722void
1724#ifdef DEBUG_SUBSCRIPTION_FILTERS
1725 std::cout << "Adding turn-maneuver filter" << std::endl;
1726#endif
1729}
1730
1731void
1733#ifdef DEBUG_SUBSCRIPTION_FILTERS
1734 std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1735#endif
1738}
1739
1740void
1741TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1742#ifdef DEBUG_SUBSCRIPTION_FILTERS
1743 std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1744#endif
1747}
1748
1749void
1751#ifdef DEBUG_SUBSCRIPTION_FILTERS
1752 std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1753#endif
1756}
1757
1758void
1760#ifdef DEBUG_SUBSCRIPTION_FILTERS
1761 std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1762#endif
1765}
1766
1767void
1769 if (tempMsg.size() < 254) {
1770 outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1771 } else {
1772 outputStorage.writeUnsignedByte(0); // command length -> extended
1773 outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1774 }
1775 outputStorage.writeStorage(tempMsg);
1776}
1777
1778
1779void
1782 if (shape.value.size() < 256) {
1783 outputStorage.writeUnsignedByte((int)shape.value.size());
1784 } else {
1785 outputStorage.writeUnsignedByte(0);
1786 outputStorage.writeInt((int)shape.value.size());
1787 }
1788 for (const libsumo::TraCIPosition& pos : shape.value) {
1789 outputStorage.writeDouble(pos.x);
1790 outputStorage.writeDouble(pos.y);
1791 }
1792}
1793
1794
1795bool
1797 if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLE) {
1798 return false;
1799 }
1800 into = inputStorage.readDouble();
1801 return true;
1802}
1803
1804
1805bool
1806TraCIServer::readTypeCheckingString(tcpip::Storage& inputStorage, std::string& into) {
1807 if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRING) {
1808 return false;
1809 }
1810 into = inputStorage.readString();
1811 return true;
1812}
1813
1814
1815bool
1816TraCIServer::readTypeCheckingStringList(tcpip::Storage& inputStorage, std::vector<std::string>& into) {
1817 if (inputStorage.readUnsignedByte() != libsumo::TYPE_STRINGLIST) {
1818 return false;
1819 }
1820 into = inputStorage.readStringList();
1821 return true;
1822}
1823
1824
1825bool
1826TraCIServer::readTypeCheckingDoubleList(tcpip::Storage& inputStorage, std::vector<double>& into) {
1827 if (inputStorage.readUnsignedByte() != libsumo::TYPE_DOUBLELIST) {
1828 return false;
1829 }
1830 into = inputStorage.readDoubleList();
1831 return true;
1832}
1833
1834
1835bool
1837 if (inputStorage.readUnsignedByte() != libsumo::TYPE_COLOR) {
1838 return false;
1839 }
1840 into.r = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1841 into.g = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1842 into.b = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1843 into.a = static_cast<unsigned char>(inputStorage.readUnsignedByte());
1844 return true;
1845}
1846
1847
1848bool
1850 if (inputStorage.readUnsignedByte() != libsumo::POSITION_2D) {
1851 return false;
1852 }
1853 into.x = inputStorage.readDouble();
1854 into.y = inputStorage.readDouble();
1855 into.z = 0;
1856 return true;
1857}
1858
1859
1860bool
1862 if (inputStorage.readByte() != libsumo::TYPE_BYTE) {
1863 return false;
1864 }
1865 into = inputStorage.readByte();
1866 return true;
1867}
1868
1869
1870bool
1872 if (inputStorage.readUnsignedByte() != libsumo::TYPE_UBYTE) {
1873 return false;
1874 }
1875 into = inputStorage.readUnsignedByte();
1876 return true;
1877}
1878
1879
1880bool
1882 if (inputStorage.readUnsignedByte() != libsumo::TYPE_POLYGON) {
1883 return false;
1884 }
1885 into.clear();
1886 int size = inputStorage.readUnsignedByte();
1887 if (size == 0) {
1888 size = inputStorage.readInt();
1889 }
1890 PositionVector shape;
1891 for (int i = 0; i < size; ++i) {
1892 double x = inputStorage.readDouble();
1893 double y = inputStorage.readDouble();
1894 if (std::isnan(x) || std::isnan(y)) {
1895 throw libsumo::TraCIException("NaN-Value in shape.");
1896 }
1897 into.push_back(Position(x, y));
1898 }
1899 return true;
1900}
1901
1902
1903void
1905 myTargetTime = targetTime;
1906 for (auto& s : mySockets) {
1907 s.second->targetTime = targetTime;
1908 s.second->executeMove = false;
1909 for (auto& stateChange : s.second->vehicleStateChanges) {
1910 stateChange.second.clear();
1911 }
1912 for (auto& stateChange : s.second->transportableStateChanges) {
1913 stateChange.second.clear();
1914 }
1915 }
1916 mySubscriptions.clear();
1918}
1919
1920
1921bool
1922TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1923 return (s.id == objID && s.commandId + 32 == s.contextDomain);
1924}
1925
1926
1927/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:290
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:289
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
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:106
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition MSGlobals.h:81
VehicleState
Definition of a vehicle state.
Definition MSNet.h:613
@ 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:186
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:325
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition MSNet.cpp:1269
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition MSNet.cpp:1297
TransportableState
Definition of a transportable state.
Definition MSNet.h:690
@ 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:1201
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
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
const std::string & getID() const
Returns the id.
Definition Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
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:62
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.
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.
std::map< int, SocketInfo * > mySockets
The socket connections to the clients the first component (index) determines the client's order (lowe...
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 wrapIntPair(const std::string &objID, const int variable, const std::pair< int, int > &value)
bool wrapReservationVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCIReservation > &value)
bool centralObject(const libsumo::Subscription &s, const std::string &objID)
check whether a found objID refers to the central object of a context subscription
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.
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.
void removeSubscription(int commandId, const std::string &identity, int domain)
bool wrapStage(const std::string &objID, const int variable, const libsumo::TraCIStage &value)
bool wrapDouble(const std::string &objID, const int variable, const double value)
tcpip::Storage mySubscriptionCache
The last timestep's subscription results.
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.
bool wrapConnectionVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCIConnection > &value)
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...
bool wrapSignalConstraintVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCISignalConstraint > &value)
void cleanup()
clean up subscriptions
static void close()
request termination of connection
void postProcessSimulationStep()
Handles subscriptions to send after a simstep2 command.
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
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.
virtual ~TraCIServer()
Destructor.
bool wrapNextStopDataVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCINextStopData > &value)
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.
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.
std::vector< libsumo::Subscription > mySubscriptions
The list of known, still valid subscriptions.
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)
bool wrapStringDoublePairList(const std::string &objID, const int variable, const std::vector< std::pair< std::string, double > > &value)
TraCIServer(const SUMOTime begin, const int port, const int numClients)
Constructor.
tcpip::Storage myInputStorage
The storage to read from.
bool wrapLogicVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCILogic > &value)
bool wrapNextTLSDataVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCINextTLSData > &value)
libsumo::Subscription * myLastContextSubscription
The last modified context subscription (the one to add a filter to, see @addSubscriptionFilter(),...
std::map< int, SocketInfo * >::iterator myCurrentSocket
The currently active client socket.
bool wrapVehicleDataVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCIVehicleData > &value)
void addSubscriptionFilterVClass(SVCPermissions vClasses)
static TraCIServer * myInstance
Singleton instance of the server.
std::map< int, SocketInfo * > mySocketReorderRequests
This stores the setOrder(int) requests of the clients.
bool addSubscriptionFilter()
std::set< std::pair< int, int > > myParameterized
Set of variables which have parameters.
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 wrapBestLanesDataVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCIBestLanesData > &value)
bool wrapLinkVectorVector(const std::string &objID, const int variable, const std::vector< std::vector< libsumo::TraCILink > > &value)
bool wrapJunctionFoeVector(const std::string &objID, const int variable, const std::vector< libsumo::TraCIJunctionFoe > &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:757
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:907
static void collectObjectIDsInRange(int domain, const PositionVector &shape, double range, std::set< std::string > &into)
Definition Helper.cpp:827
static bool needNewSubscription(libsumo::Subscription &s, std::vector< Subscription > &subscriptions, libsumo::Subscription *&modifiedSubscription)
Definition Helper.cpp:197
static void writeConstraint(tcpip::Storage &content, const libsumo::TraCISignalConstraint &c)
static void writeTypedDouble(tcpip::Storage &content, double value)
static void writeStage(tcpip::Storage &content, const libsumo::TraCIStage &stage)
static void writeTypedUnsignedByte(tcpip::Storage &content, int value)
static void writeCompound(tcpip::Storage &content, int size)
static void writeTypedInt(tcpip::Storage &content, int value)
static void writeTypedStringList(tcpip::Storage &content, const std::vector< std::string > &value)
static void writeTypedByte(tcpip::Storage &content, int value)
static void writeTypedString(tcpip::Storage &content, const std::string &value)
Representation of a subscription.
double filterUpstreamDist
Upstream distance specified by the upstream distance filter.
int commandId
commandIdArg The command id of the subscription
std::set< std::string > filterVTypes
vTypes specified by the vTypes filter
double filterFieldOfVisionOpeningAngle
Opening angle (in deg) specified by the field of vision filter.
std::vector< int > filterLanes
lanes specified by the lanes filter
std::string id
The id of the object that is subscribed.
SUMOTime endTime
The end time of the subscription.
int contextDomain
The domain ID of the context.
double filterFoeDistToJunction
Foe distance to junction specified by the turn filter.
bool isVehicleToVehicleContextSubscription() const
SUMOTime beginTime
The begin time of the subscription.
std::vector< int > variables
The subscribed variables.
SVCPermissions filterVClasses
vClasses specified by the vClasses filter,
bool isVehicleToPersonContextSubscription() const
double filterDownstreamDist
Downstream distance specified by the downstream distance filter.
double filterLateralDist
Lateral distance specified by the lateral distance filter.
int activeFilters
Active filters for the subscription (bitset,.
double range
The range of the context.
std::vector< std::shared_ptr< tcpip::Storage > > parameters
The parameters for the subscribed variables.
An error which allows to continue.
Definition TraCIDefs.h:145
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition socket.cpp:234
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
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 VAR_EDGES
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 POSITION_ROADMAP
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 TL_BLOCKING_VEHICLES
TRACI_CONST int VAR_SECURE_GAP
TRACI_CONST int CMD_SUBSCRIBE_JUNCTION_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_VEHICLE_CONTEXT
TRACI_CONST int VAR_EDGE_TRAVELTIME
TRACI_CONST int CMD_GET_REROUTER_VARIABLE
TRACI_CONST int LANE_CHANGES
TRACI_CONST int CMD_GET_VEHICLE_VARIABLE
TRACI_CONST int VAR_TAXI_RESERVATIONS
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 VAR_FOLLOW_SPEED
TRACI_CONST int TL_PRIORITY_VEHICLES
TRACI_CONST int CMD_EXECUTEMOVE
TRACI_CONST int CMD_SUBSCRIBE_TL_CONTEXT
TRACI_CONST int FILTER_TYPE_FIELD_OF_VISION
TRACI_CONST int VAR_ANGLE
TRACI_CONST int TYPE_COMPOUND
TRACI_CONST int CMD_SUBSCRIBE_ROUTEPROBE_VARIABLE
TRACI_CONST int CMD_SET_REROUTER_VARIABLE
TRACI_CONST int VAR_EDGE_EFFORT
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 VAR_STAGE
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 VAR_PERSON_NUMBER
TRACI_CONST int CMD_SET_POLYGON_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_BUSSTOP_CONTEXT
TRACI_CONST int VAR_STOP_PARAMETER
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 VAR_TAXI_FLEET
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 TL_CONSTRAINT_BYFOE
TRACI_CONST int CMD_SET_MULTIENTRYEXIT_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_POLYGON_VARIABLE
TRACI_CONST int VAR_STOP_SPEED
TRACI_CONST int CMD_SUBSCRIBE_PERSON_CONTEXT
TRACI_CONST int CMD_GET_VEHICLETYPE_VARIABLE
TRACI_CONST int CMD_SUBSCRIBE_CHARGINGSTATION_CONTEXT
TRACI_CONST int TL_CONSTRAINT
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 VAR_NEXT_STOPS2
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
TRACI_CONST int DISTANCE_REQUEST
@ SUBS_FILTER_LEAD_FOLLOW
@ SUBS_FILTER_UPSTREAM_DIST
@ SUBS_FILTER_VTYPE
@ SUBS_FILTER_NO_RTREE
@ SUBS_FILTER_LANES
@ SUBS_FILTER_NOOPPOSITE
@ SUBS_FILTER_DOWNSTREAM_DIST
@ SUBS_FILTER_LATERAL_DIST
@ SUBS_FILTER_TURN
@ SUBS_FILTER_VCLASS
@ SUBS_FILTER_NONE
@ SUBS_FILTER_FIELD_OF_VISION
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_CHANGELANE
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 VAR_NEIGHBORS
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 VAR_FOES
TRACI_CONST int CMD_SET_BUSSTOP_VARIABLE
TRACI_CONST int SPLIT_TAXI_RESERVATIONS
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 TL_RIVAL_VEHICLES
TRACI_CONST int VAR_NEXT_STOPS
TRACI_CONST int CMD_SUBSCRIBE_VARIABLESPEEDSIGN_VARIABLE
A 2D or 3D-position, for 2D positions z == INVALID_DOUBLE_VALUE.
Definition TraCIDefs.h:179
A list of positions.
Definition TraCIDefs.h:240
std::vector< TraCIPosition > value
Definition TraCIDefs.h:250
mirrors MSInductLoop::VehicleData
Definition TraCIDefs.h:522