Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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 try {
1015 const std::vector<std::string> args = StoHelp::readTypedStringList(myInputStorage, "A load command needs a list of string arguments.");
1016#ifdef DEBUG_MULTI_CLIENTS
1017 std::cout << " commandId == libsumo::CMD_LOAD"
1018 << ", args = " << toString(args) << std::endl;
1019#endif
1020 myLoadArgs = args;
1021 success = true;
1023 // XXX: This only cares for the client that issued the load command.
1024 // Multiclient-load functionality is still to be implemented. Refs #3146.
1025 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1026 myCurrentSocket = mySockets.end();
1028 } catch (libsumo::TraCIException& e) {
1030 }
1031 break;
1032 }
1034 myCurrentSocket->second->executeMove = true;
1036 success = true;
1038 break;
1039 case libsumo::CMD_SIMSTEP: {
1040 const double nextT = myInputStorage.readDouble();
1041 if (nextT == 0.) {
1042 myCurrentSocket->second->targetTime += DELTA_T;
1043 } else {
1044 myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
1045 }
1046 myCurrentSocket->second->executeMove = false;
1047#ifdef DEBUG_MULTI_CLIENTS
1048 std::cout << " commandId == libsumo::CMD_SIMSTEP"
1049 << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
1050#endif
1051 if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
1052 // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
1053 // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommands()
1055 }
1056 // Clear vehicleStateChanges and transportableStateChanges for this client
1057 // -> For subsequent TraCI stepping
1058 // that is performed within this SUMO step, no updates on vehicle states
1059 // belonging to the last SUMO simulation step will be received by this client.
1060 for (auto& item : myCurrentSocket->second->vehicleStateChanges) {
1061 item.second.clear();
1062 }
1063 for (auto& item : myCurrentSocket->second->transportableStateChanges) {
1064 item.second.clear();
1065 }
1067 return commandId;
1068 }
1069 case libsumo::CMD_CLOSE:
1071 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1073 if (mySockets.size() == 1) {
1074 // Last client has closed connection
1075 myDoCloseConnection = true;
1076 }
1077 // remove current socket and increment to next socket in ordering
1079 success = true;
1080 break;
1081 case libsumo::CMD_SETORDER: {
1082 const int order = myInputStorage.readInt();
1083#ifdef DEBUG_MULTI_CLIENTS
1084 std::cout << " commandId == libsumo::CMD_SETORDER"
1085 << ", order index is " << order << std::endl;
1086#endif
1087 if (order > libsumo::MAX_ORDER) {
1088 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
1089 }
1090 if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
1091 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
1092 }
1093 // memorize reorder request (will only take effect in the next step)
1095 success = true;
1097 break;
1098 }
1123 success = addObjectVariableSubscription(commandId, false);
1124 break;
1149 success = addObjectVariableSubscription(commandId, true);
1150 break;
1152 success = addSubscriptionFilter();
1153 break;
1154 default:
1155 if (commandId == libsumo::CMD_GET_GUI_VARIABLE || commandId == libsumo::CMD_SET_GUI_VARIABLE) {
1156 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1157 } else {
1158 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
1159 }
1160 }
1161 }
1162 if (!success) {
1163 while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
1165 }
1166 }
1167 if ((int)myInputStorage.position() != commandStart + commandLength) {
1168 std::ostringstream msg;
1169 msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
1170 msg << " Expected command length was " << commandLength;
1171 msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
1172 writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
1173 myDoCloseConnection = true;
1174 }
1175 return commandId;
1176}
1177
1178
1179// ---------- Server-internal command handling
1180bool
1182 // Prepare response
1183 tcpip::Storage answerTmp;
1185 answerTmp.writeString("SUMO " VERSION_STRING);
1186 // When we get here, the response is stored in answerTmp -> put into myOutputStorage
1188 // command length
1189 myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
1190 // command type
1192 // and the parameter dependant part
1193 myOutputStorage.writeStorage(answerTmp);
1194 return true;
1195}
1196
1197
1198void
1201#ifdef DEBUG_MULTI_CLIENTS
1202 std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
1203#endif
1205 int noActive = 0;
1206 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1207 const libsumo::Subscription& s = *i;
1210
1212 if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
1213 i = mySubscriptions.erase(i);
1214 continue;
1215 }
1216 ++i;
1217 if (s.beginTime > t) {
1218 continue;
1219 }
1220 ++noActive;
1221 }
1223#ifdef DEBUG_SUBSCRIPTIONS
1224 std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
1225 << "\n Nr. of active subscriptions = " << noActive << std::endl;
1226#endif
1227 mySubscriptionCache.writeInt(noActive);
1228#ifdef DEBUG_SUBSCRIPTIONS
1229 std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
1230#endif
1231 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1232 const libsumo::Subscription& s = *i;
1233 if (s.beginTime > t) {
1234 ++i;
1235 continue;
1236 }
1237 tcpip::Storage into;
1238 std::string errors;
1239 bool ok = processSingleSubscription(s, into, errors);
1240#ifdef DEBUG_SUBSCRIPTIONS
1241 std::cout << " Size of into-store for subscription " << s.id
1242 << ": " << into.size() << std::endl;
1243#endif
1245 if (ok) {
1246 ++i;
1247 } else {
1248 i = mySubscriptions.erase(i);
1249 }
1250 }
1252#ifdef DEBUG_SUBSCRIPTIONS
1253 std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1254#endif
1255}
1256
1257
1258void
1260#ifdef DEBUG_MULTI_CLIENTS
1261 std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1262 << " (-> intermediate TraCI step)."
1263 << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1264 << std::endl;
1265#endif
1267
1268// NOTE: the commented code would send an empty response
1269// myOutputStorage.writeInt(0);
1270// myCurrentSocket->second->socket->sendExact(myOutputStorage);
1271// myOutputStorage.reset();
1273 // send results to active client
1274 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1276}
1277
1278
1279void
1280TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1281 writeStatusCmd(commandId, status, description, myOutputStorage);
1282}
1283
1284
1285void
1286TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1287 if (status == libsumo::RTYPE_ERR) {
1288 WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1289 } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1290 WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1291 }
1292 outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1293 outputStorage.writeUnsignedByte(commandId); // command type
1294 outputStorage.writeUnsignedByte(status); // status
1295 outputStorage.writeString(description); // description
1296}
1297
1298
1299bool
1300TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1301 writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1302 return false;
1303}
1304
1305
1306void
1308 tcpip::Storage writeInto;
1309 std::string errors;
1310 libsumo::Subscription* modifiedSubscription = nullptr;
1311 try {
1312 if (processSingleSubscription(s, writeInto, errors)) {
1314 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1315 } else {
1316 if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1317 // Add new subscription to subscription cache (note: seems a bit inefficient)
1319 // copy new subscription into cache
1320 int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1321 tcpip::Storage tmp;
1322 tmp.writeInt(noActive);
1323 while (mySubscriptionCache.valid_pos()) {
1325 }
1326 tmp.writeStorage(writeInto);
1329 }
1330 }
1332 }
1333 if (modifiedSubscription != nullptr && (
1334 modifiedSubscription->isVehicleToVehicleContextSubscription()
1335 || modifiedSubscription->isVehicleToPersonContextSubscription())) {
1336 // Set last modified vehicle context subscription active for filter modifications
1337 myLastContextSubscription = modifiedSubscription;
1338 } else {
1339 // adding other subscriptions deactivates the activation for filter addition
1340 myLastContextSubscription = nullptr;
1341 }
1342 } else {
1343 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1344 }
1345 } catch (libsumo::TraCIException& e) {
1347 }
1348 myOutputStorage.writeStorage(writeInto);
1349}
1350
1351
1352void
1353TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1354 bool found = false;
1355 std::vector<libsumo::Subscription>::iterator j;
1356 for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1357 if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1358 j = mySubscriptions.erase(j);
1359 if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1360 // Remove also reference for filter additions
1361 myLastContextSubscription = nullptr;
1362 }
1363 found = true;
1364 continue;
1365 }
1366 ++j;
1367 }
1368 // try unsubscribe
1369 if (found) {
1370 writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1371 } else {
1372 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1373 }
1374}
1375
1376
1377bool
1379 std::string& errors) {
1380 bool ok = true;
1381 tcpip::Storage outputStorage;
1382 const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1383 std::set<std::string> objIDs;
1384 if (s.contextDomain > 0) {
1386 PositionVector shape;
1389 }
1391 } else {
1392 objIDs.insert(s.id);
1393 }
1394 const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1395 int skipped = 0;
1396 for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1397 if (s.contextDomain > 0) {
1398 //if (centralObject(s, *j)) {
1399 // skipped++;
1400 // continue;
1401 //}
1402 outputStorage.writeString(*j);
1403 }
1404 if (numVars > 0) {
1405 std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1406 for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1407 tcpip::Storage message;
1408 message.writeUnsignedByte(*i);
1409 message.writeString(*j);
1410 // TODO check why writeStorage fails here (probably some kind of invalid iterator)
1411 for (const auto& v :** k) {
1412 message.writeChar(v);
1413 }
1414 tcpip::Storage tmpOutput;
1415 try {
1416 if (myExecutors.find(getCommandId) != myExecutors.end()) {
1417 ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1418 } else {
1419 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1420 ok = false;
1421 }
1422 } catch (const std::invalid_argument&) {
1423 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1424 ok = false;
1425 }
1426 // copy response part
1427 if (ok) {
1428 int length = tmpOutput.readUnsignedByte();
1429 while (--length > 0) {
1430 tmpOutput.readUnsignedByte();
1431 }
1432 int lengthLength = 1;
1433 length = tmpOutput.readUnsignedByte();
1434 if (length == 0) {
1435 lengthLength = 5;
1436 length = tmpOutput.readInt();
1437 }
1438 //read responseType
1439 tmpOutput.readUnsignedByte();
1440 int variable = tmpOutput.readUnsignedByte();
1441 std::string id = tmpOutput.readString();
1442 outputStorage.writeUnsignedByte(variable);
1443 outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1444 length -= (lengthLength + 1 + 4 + (int)id.length());
1445 while (--length > 0) {
1446 outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1447 }
1448 } else {
1449 //read length
1450 tmpOutput.readUnsignedByte();
1451 //read cmd
1452 tmpOutput.readUnsignedByte();
1453 //read status
1454 tmpOutput.readUnsignedByte();
1455 std::string msg = tmpOutput.readString();
1456 outputStorage.writeUnsignedByte(*i);
1459 outputStorage.writeString(msg);
1460 errors = errors + msg;
1461 }
1462 }
1463 }
1464 }
1465 int length = (1 + 4) + 1 + (4 + (int)s.id.length()) + 1 + (int)outputStorage.size();
1466 if (s.contextDomain > 0) {
1467 length += 1 + 4; // context domain and number of objects
1468 }
1469 // we always write extended command length here for backward compatibility
1470 writeInto.writeUnsignedByte(0); // command length -> extended
1471 writeInto.writeInt(length);
1472 writeInto.writeUnsignedByte(s.commandId + 0x10);
1473 writeInto.writeString(s.id);
1474 if (s.contextDomain > 0) {
1475 writeInto.writeUnsignedByte(s.contextDomain);
1476 }
1477 writeInto.writeUnsignedByte(numVars);
1478 if (s.contextDomain > 0) {
1479 writeInto.writeInt((int)objIDs.size() - skipped);
1480 }
1481 if (s.contextDomain == 0 || objIDs.size() != 0) {
1482 writeInto.writeStorage(outputStorage);
1483 }
1484 return ok;
1485}
1486
1487
1488bool
1489TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1490 const double beginTime = myInputStorage.readDouble();
1491 const double endTime = myInputStorage.readDouble();
1492 const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1493 const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1494 const std::string id = myInputStorage.readString();
1495 const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1496 double range = hasContext ? myInputStorage.readDouble() : 0.;
1497 if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
1498 range = std::numeric_limits<double>::max();
1499 }
1500 const int num = myInputStorage.readUnsignedByte();
1501 std::vector<int> variables;
1502 std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1503 for (int i = 0; i < num; ++i) {
1504 const int varID = myInputStorage.readUnsignedByte();
1505 variables.push_back(varID);
1506 parameters.push_back(std::make_shared<tcpip::Storage>());
1507 if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1508 if (!myInputStorage.valid_pos()) {
1509 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Missing parameter for subscription " + toHex(commandId, 2));
1510 return false;
1511 }
1512 int count = 1;
1513 while (count-- > 0) {
1514 const int parType = myInputStorage.readUnsignedByte();
1515 parameters.back()->writeUnsignedByte(parType);
1516 if (parType == libsumo::TYPE_DOUBLE) {
1517 parameters.back()->writeDouble(myInputStorage.readDouble());
1518 } else if (parType == libsumo::TYPE_INTEGER) {
1519 parameters.back()->writeInt(myInputStorage.readInt());
1520 } else if (parType == libsumo::TYPE_STRING) {
1521 parameters.back()->writeString(myInputStorage.readString());
1522 } else if (parType == libsumo::TYPE_BYTE) {
1523 parameters.back()->writeByte(myInputStorage.readByte());
1524 } else if (parType == libsumo::TYPE_UBYTE) {
1525 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1526 } else if (parType == libsumo::POSITION_2D) {
1527 parameters.back()->writeDouble(myInputStorage.readDouble());
1528 parameters.back()->writeDouble(myInputStorage.readDouble());
1529 if (varID == libsumo::DISTANCE_REQUEST) {
1530 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1531 break;
1532 }
1533 } else if (parType == libsumo::POSITION_3D) {
1534 parameters.back()->writeDouble(myInputStorage.readDouble());
1535 parameters.back()->writeDouble(myInputStorage.readDouble());
1536 parameters.back()->writeDouble(myInputStorage.readDouble());
1537 if (varID == libsumo::DISTANCE_REQUEST) {
1538 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1539 break;
1540 }
1541 } else if (parType == libsumo::POSITION_ROADMAP) {
1542 parameters.back()->writeString(myInputStorage.readString());
1543 parameters.back()->writeDouble(myInputStorage.readDouble());
1544 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1545 if (varID == libsumo::DISTANCE_REQUEST) {
1546 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1547 break;
1548 }
1549 } else if (parType == libsumo::TYPE_COMPOUND) {
1550 count = myInputStorage.readInt();
1551 parameters.back()->writeInt(count);
1552 } else {
1553 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Invalid parameter for subscription " + toHex(commandId, 2));
1554 return false;
1555 }
1556 }
1557 }
1558 }
1559 // check subscribe/unsubscribe
1560 if (variables.empty()) {
1561 removeSubscription(commandId, id, domain);
1562 return true;
1563 }
1564 // process subscription
1565 libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1567 return true;
1568}
1569
1570
1571
1572bool
1574 bool success = true;
1575 // Read filter type
1576 int filterType = myInputStorage.readUnsignedByte();
1577
1578 if (myLastContextSubscription == nullptr) {
1580 "No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1581 return false;
1582 }
1583
1584 // dispatch according to filter type
1585 switch (filterType) {
1587 // Remove all filters
1588 removeFilters();
1589 break;
1591 // Read relative lanes to consider for context filter
1592 int nrLanes = (int)myInputStorage.readByte();
1593 std::vector<int> lanes;
1594 for (int i = 0; i < nrLanes; ++i) {
1595 lanes.push_back((int) myInputStorage.readByte());
1596 }
1598 }
1599 break;
1601 // Add no-opposite filter
1603 break;
1605 myInputStorage.readByte(); // read type double
1606 double dist = myInputStorage.readDouble();
1608 }
1609 break;
1611 myInputStorage.readByte(); // read type double
1612 double dist = myInputStorage.readDouble();
1614 }
1615 break;
1617 // Read relative lanes to consider for context filter
1619 }
1620 break;
1622 myInputStorage.readByte(); // read type double
1623 double dist = myInputStorage.readDouble();
1625 }
1626 break;
1628 myInputStorage.readByte(); // read type stringlist
1631 }
1632 break;
1634 myInputStorage.readByte(); // read type stringlist
1635 std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1636 std::set<std::string> vTypesSet;
1637 vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1638 addSubscriptionFilterVType(vTypesSet);
1639 }
1640 break;
1642 myInputStorage.readByte(); // read type double
1643 double angle = myInputStorage.readDouble();
1645 }
1646 break;
1648 myInputStorage.readByte(); // read type double
1649 double dist = myInputStorage.readDouble();
1651 }
1652 break;
1653 default:
1655 "'" + toString(filterType) + "' is no valid filter type code.");
1656 success = false;
1657 }
1658
1659 if (success) {
1660 // acknowledge filter addition
1662 }
1663
1664 return success;
1665}
1666
1667
1668void
1670#ifdef DEBUG_SUBSCRIPTION_FILTERS
1671 std::cout << "Removing filters" << std::endl;
1672#endif
1674}
1675
1676void
1678#ifdef DEBUG_SUBSCRIPTION_FILTERS
1679 std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1680#endif
1683}
1684
1685void
1687#ifdef DEBUG_SUBSCRIPTION_FILTERS
1688 std::cout << "Adding no opposite filter" << std::endl;
1689#endif
1691}
1692
1693void
1695#ifdef DEBUG_SUBSCRIPTION_FILTERS
1696 std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1697#endif
1700}
1701
1702void
1704#ifdef DEBUG_SUBSCRIPTION_FILTERS
1705 std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1706#endif
1709}
1710
1711void
1713#ifdef DEBUG_SUBSCRIPTION_FILTERS
1714 std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1715#endif
1717}
1718
1719void
1721#ifdef DEBUG_SUBSCRIPTION_FILTERS
1722 std::cout << "Adding turn-maneuver filter" << std::endl;
1723#endif
1726}
1727
1728void
1730#ifdef DEBUG_SUBSCRIPTION_FILTERS
1731 std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1732#endif
1735}
1736
1737void
1738TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1739#ifdef DEBUG_SUBSCRIPTION_FILTERS
1740 std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1741#endif
1744}
1745
1746void
1748#ifdef DEBUG_SUBSCRIPTION_FILTERS
1749 std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1750#endif
1753}
1754
1755void
1757#ifdef DEBUG_SUBSCRIPTION_FILTERS
1758 std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1759#endif
1762}
1763
1764void
1766 if (tempMsg.size() < 254) {
1767 outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1768 } else {
1769 outputStorage.writeUnsignedByte(0); // command length -> extended
1770 outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1771 }
1772 outputStorage.writeStorage(tempMsg);
1773}
1774
1775
1776void
1778 myTargetTime = targetTime;
1779 for (auto& s : mySockets) {
1780 s.second->targetTime = targetTime;
1781 s.second->executeMove = false;
1782 for (auto& stateChange : s.second->vehicleStateChanges) {
1783 stateChange.second.clear();
1784 }
1785 for (auto& stateChange : s.second->transportableStateChanges) {
1786 stateChange.second.clear();
1787 }
1788 }
1789 mySubscriptions.clear();
1791}
1792
1793
1794bool
1795TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1796 return (s.id == objID && s.commandId + 32 == s.contextDomain);
1797}
1798
1799
1800/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
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:80
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:626
@ 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:187
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition MSNet.cpp:1325
void addTransportableStateListener(TransportableStateListener *listener)
Adds a transportable states listener.
Definition MSNet.cpp:1353
TransportableState
Definition of a transportable state.
Definition MSNet.h:703
@ 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:1257
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 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 wrapInt(const std::string &objID, const int variable, const int value)
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 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) ...
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() >=...
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 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)
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)
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 std::vector< std::string > readTypedStringList(tcpip::Storage &ret, const std::string &error="")
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
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