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/libsumo.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
472
491 //myExecutors[libsumo::CMD_SET_MEANDATA_VARIABLE] = &TraCIServerAPI_MeanData::processSet;
493
523 myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_NEXT_STOPS)); // this is just a dummy to trigger an error
526 myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER));
527 myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER_WITH_KEY));
528
529 myDoCloseConnection = false;
530
531 // display warning if internal lanes are not used
532 // TODO this may be redundant to the warning in NLBuilder::build
534 WRITE_WARNING(TL("Starting TraCI without using internal lanes!"));
535 MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
536 MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
537 }
538
539 try {
540 WRITE_MESSAGEF(TL("***Starting server on port % ***"), toString(port));
541 tcpip::Socket serverSocket(port);
542 if (numClients > 1) {
543 WRITE_MESSAGEF(TL(" waiting for % clients..."), toString(numClients));
544 }
545 while ((int)mySockets.size() < numClients) {
546 int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
547 mySockets[index] = new SocketInfo(serverSocket.accept(true), begin);
548 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
549 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
550 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
551 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
552 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
553 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
554 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
555 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
556 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
557 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
558 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
559 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
560 mySockets[index]->vehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
561
562 mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
563 mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
564 mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
565 mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
566 if (numClients > 1) {
567 WRITE_MESSAGE(TL(" client connected"));
568 }
569 }
570 // When got here, all clients have connected
571 if (numClients > 1) {
573 }
574 // set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommands()
575 myCurrentSocket = mySockets.begin();
576 } catch (tcpip::SocketException& e) {
577 throw ProcessError(e.what());
578 }
579}
580
581
583 for (const auto& socket : mySockets) {
584 delete socket.second;
585 }
586 // there is no point in calling cleanup() here, it does not free any pointers and will only modify members which get deleted anyway
587}
588
589
590// ---------- Initialisation and Shutdown
591void
592TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
593 if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
594 myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
595 OptionsCont::getOptions().getInt("remote-port"),
596 OptionsCont::getOptions().getInt("num-clients"));
597 for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
598 myInstance->myExecutors[i->first] = i->second;
599 }
600 }
601 if (myInstance != nullptr) {
602 // maybe net was deleted and built again
606 }
607}
608
609
610void
612 if (myInstance == nullptr) {
613 return;
614 }
615 delete myInstance;
616 myInstance = nullptr;
617 myDoCloseConnection = true;
618}
619
620
621bool
625
626
627// ---------- Initialisation and Shutdown
628
629
630void
631TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
632 if (!myDoCloseConnection) {
633 myVehicleStateChanges[to].push_back(vehicle->getID());
634 for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
635 i->second->vehicleStateChanges[to].push_back(vehicle->getID());
636 }
637 }
638}
639
640
641void
642TraCIServer::transportableStateChanged(const MSTransportable* const transportable, MSNet::TransportableState to, const std::string& /*info*/) {
643 if (!myDoCloseConnection) {
644 myTransportableStateChanges[to].push_back(transportable->getID());
645 for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
646 i->second->transportableStateChanges[to].push_back(transportable->getID());
647 }
648 }
649}
650
651
652void
654#ifdef DEBUG_MULTI_CLIENTS
655 std::cout << "Checking client order requests." << std::endl;
656#endif
657 // check for SET_ORDER commands queued by connected clients
658 // In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
659 myCurrentSocket = mySockets.begin();
660 while (myCurrentSocket != mySockets.end()) {
661#ifdef DEBUG_MULTI_CLIENTS
662 std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
663#endif
664// bool clientUnordered = true;
665 while (true) {
667 myCurrentSocket->second->socket->receiveExact(myInputStorage);
668 int commandStart, commandLength;
669 int commandId = readCommandID(commandStart, commandLength);
670#ifdef DEBUG_MULTI_CLIENTS
671 std::cout << " received command " << commandId << std::endl;
672#endif
673 // Whether the received command is a permitted command for the initialization phase.
674 // Currently, getVersion and setOrder are permitted.
675 bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
676 if (initCommand) {
677#ifdef DEBUG_MULTI_CLIENTS
678 std::cout << " Init command. Sending response." << std::endl;
679#endif
680 // reset input storage to initial state before reading the commandId
681 // (ugly, but we can't just reset the store's iter_ from here)
682 // Giving the commandId to dispatch command didn't work either
683 tcpip::Storage tmp;
686 // we don't know whether the command was set with extended
687 // length syntax or not so we hardcode the length here (#5037)
691
692 // Handle initialization command completely
694 myCurrentSocket->second->socket->sendExact(myOutputStorage);
696 } else {
697#ifdef DEBUG_MULTI_CLIENTS
698 std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
699#endif
700 throw ProcessError(TL("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase."));
701 }
702 if (commandId == libsumo::CMD_SETORDER) {
703 // This is what we have waited for.
704 break;
705 }
706 }
708 }
709}
710
711
712void
714 // Process reordering requests
715 if (mySocketReorderRequests.size() > 0) {
716 // process reordering requests
717 std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
718 std::map<int, SocketInfo*>::iterator j;
719#ifdef DEBUG_MULTI_CLIENTS
720 std::cout << SIMTIME << " Current socket ordering:\n";
721 for (j = mySockets.begin(); j != mySockets.end(); ++j) {
722 std::cout << " " << j->first << ": " << j->second->socket << "\n";
723 }
724 std::cout << "Reordering requests:\n";
725 for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
726 std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
727 }
728 i = mySocketReorderRequests.begin();
729#endif
730 while (i != mySocketReorderRequests.end()) {
731 j = mySockets.begin();
732 while (j != mySockets.end()) {
733 if (j->second->socket == i->second->socket) {
734 break;
735 } else {
736 j++;
737 }
738 }
739 assert(j != mySockets.end());
740 mySockets.erase(j);
741 mySockets[i->first] = i->second;
742 ++i;
743 }
745#ifdef DEBUG_MULTI_CLIENTS
746 std::cout << "New socket ordering:\n";
747 for (j = mySockets.begin(); j != mySockets.end(); ++j) {
748 std::cout << " " << j->first << ": " << j->second->socket << "\n";
749 }
750 std::cout << std::endl;
751#endif
752 }
753}
754
755
758#ifdef DEBUG_MULTI_CLIENTS
759 std::cout << "\n Determining new target time..." << std::endl;
760 if (mySockets.size() == 0) {
761 std::cout << " All clients have disconnected." << std::endl;
762 }
763#endif
764 std::map<int, SocketInfo*>::const_iterator i;
765 SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
766 for (i = mySockets.begin(); i != mySockets.end(); ++i) {
767#ifdef DEBUG_MULTI_CLIENTS
768 std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
769#endif
770 targetTime = MIN2(targetTime, i->second->targetTime);
771 }
772#ifdef DEBUG_MULTI_CLIENTS
773 std::cout << std::endl;
774#endif
775 return targetTime;
776}
777
778
779// send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
780void
782#ifdef DEBUG_MULTI_CLIENTS
783 std::cout << "\n Sending subscription results to clients:\n";
784#endif
785 std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
786 while (i != mySockets.end()) {
787 if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
788 // this client will become active before the next SUMO step. Provide subscription results.
789 i->second->socket->sendExact(myOutputStorage);
790#ifdef DEBUG_MULTI_CLIENTS
791 std::cout << i->second->socket << "\n";
792#endif
793 }
794 ++i;
795 }
796#ifdef DEBUG_MULTI_CLIENTS
797 std::cout << std::endl;
798#endif
799}
800
801
802int
803TraCIServer::processCommands(const SUMOTime step, const bool afterMove) {
804#ifdef DEBUG_MULTI_CLIENTS
805 std::cout << SIMTIME << " processCommands(step = " << step << "):\n" << std::endl;
806#endif
807 try {
808 int finalCmd = 0;
809 const bool firstStep = myCurrentSocket != mySockets.end();
810 // update client order if requested
812 if (!firstStep && !afterMove) {
813 // 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)
814 // update subscription results
816 // Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
819 }
820
821 // determine minimal next target time among clients
823
824 if (step < myTargetTime) {
825#ifdef DEBUG_MULTI_CLIENTS
826 std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommands()." << std::endl;
827#endif
828 return finalCmd;
829 }
830
831 // Simulation should run until
832 // 1. end time reached or
833 // 2. got libsumo::CMD_CLOSE or
834 // 3. got libsumo::CMD_LOAD or
835 // 4. Client closes socket connection
836 while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep()) && finalCmd != libsumo::CMD_EXECUTEMOVE) {
837#ifdef DEBUG_MULTI_CLIENTS
838 std::cout << " Next target time: " << myTargetTime << std::endl;
839#endif
840 // Iterate over clients and process communication for the ones with target time == myTargetTime
841 myCurrentSocket = mySockets.begin();
842 while (myCurrentSocket != mySockets.end()) {
843#ifdef DEBUG_MULTI_CLIENTS
844 std::cout << " current socket: " << myCurrentSocket->second->socket
845 << " with target time=" << myCurrentSocket->second->targetTime
846 << std::endl;
847#endif
848
849 if (myCurrentSocket->second->targetTime > myTargetTime || (afterMove && !myCurrentSocket->second->executeMove)) {
850 // this client must wait
851#ifdef DEBUG_MULTI_CLIENTS
852 std::cout << " skipping client " << myCurrentSocket->second->socket
853 << " with target time=" << myCurrentSocket->second->targetTime << std::endl;
854#endif
856 continue;
857 }
858 finalCmd = 0;
859 while (finalCmd == 0) {
860 if (!myInputStorage.valid_pos()) {
861 // have read request completely, send response if adequate
862 if (myOutputStorage.size() > 0) {
863 // send response to previous query
864 myCurrentSocket->second->socket->sendExact(myOutputStorage);
866 }
867#ifdef DEBUG_MULTI_CLIENTS
868 std::cout << " resetting input storage and reading next command..." << std::endl;
869#endif
870 // Read next request
872 myCurrentSocket->second->socket->receiveExact(myInputStorage);
873 }
874
876 const int cmd = dispatchCommand();
878 finalCmd = cmd;
879 }
880 }
881 }
882 }
883 if (!myLoadArgs.empty()) {
884#ifdef DEBUG_MULTI_CLIENTS
885 std::cout << " Breaking loop to load new simulation." << std::endl;
886#endif
887 break;
888 } else if (myDoCloseConnection) {
889#ifdef DEBUG_MULTI_CLIENTS
890 std::cout << " Breaking loop because last client closed connection." << std::endl;
891#endif
892 break;
893 }
894 SUMOTime nextT = nextTargetTime();
895 // minimal target time among clients should have been increased during the last loop through mySockets
896 // XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
897 // leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
898 // the next call is then usually simulationStep(step=1000) leading to no further increase
899 // and thus a failing assertion here.
900 //assert(myTargetTime < nextT || myDoCloseConnection);
901 myTargetTime = nextT;
902 }
903 // All clients are done with the current time step
904 // Reset myVehicleStateChanges and myTransportableStateChanges
905 for (auto& item : myVehicleStateChanges) {
906 item.second.clear();
907 }
908 for (auto& item : myTransportableStateChanges) {
909 item.second.clear();
910 }
911 return finalCmd;
912 } catch (std::invalid_argument& e) {
913 throw ProcessError(e.what());
914 } catch (libsumo::TraCIException& e) {
915 throw ProcessError(e.what());
916 } catch (tcpip::SocketException& e) {
917 throw ProcessError(e.what());
918 }
919}
920
921
922bool
923TraCIServer::processGet(const int commandID, tcpip::Storage& inputStorage, tcpip::Storage& outputStorage) {
924 const int variable = inputStorage.readUnsignedByte();
925 const std::string id = inputStorage.readString();
926 initWrapper(commandID + 0x10, variable, id);
927 try {
928 switch (commandID) {
930 if (!libsumo::InductionLoop::handleVariable(id, variable, this, &inputStorage)) {
931 throw libsumo::TraCIException("Get Induction Loop Variable: unsupported variable " + toHex(variable, 2) + " specified");
932 }
933 break;
935 if (!libsumo::MultiEntryExit::handleVariable(id, variable, this, &inputStorage)) {
936 throw libsumo::TraCIException("Get Multi Entry Exit Detector Variable: unsupported variable " + toHex(variable, 2) + " specified");
937 }
938 break;
940 if (!libsumo::TrafficLight::handleVariable(id, variable, this, &inputStorage)) {
941 switch (variable) {
943 StoHelp::readCompound(inputStorage, 3, "A compound object of size 3 is needed for swapping constraints.");
944 const std::string tripId = StoHelp::readTypedString(inputStorage, "The tripId must be given as a string.");
945 const std::string foeSignal = StoHelp::readTypedString(inputStorage, "The foeSignal id must be given as a string.");
946 const std::string foeId = StoHelp::readTypedString(inputStorage, "The foe tripId must be given as a string.");
947 wrapSignalConstraintVector(id, variable, libsumo::TrafficLight::swapConstraints(id, tripId, foeSignal, foeId));
948 break;
949 }
950 default:
951 throw libsumo::TraCIException("Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified");
952 }
953 }
954 break;
956 if (!libsumo::Lane::handleVariable(id, variable, this, &inputStorage)) {
957 throw libsumo::TraCIException("Get Lane Variable: unsupported variable " + toHex(variable, 2) + " specified");
958 }
959 break;
961 if (!libsumo::Vehicle::handleVariable(id, variable, this, &inputStorage)) {
962 throw libsumo::TraCIException("Get Vehicle Variable: unsupported variable " + toHex(variable, 2) + " specified");
963 }
964 break;
966 if (!libsumo::VehicleType::handleVariable(id, variable, this, &inputStorage)) {
967 throw libsumo::TraCIException("Get Vehicle Type Variable: unsupported variable " + toHex(variable, 2) + " specified");
968 }
969 break;
971 if (!libsumo::Route::handleVariable(id, variable, this, &inputStorage)) {
972 throw libsumo::TraCIException("Get Route Variable: unsupported variable " + toHex(variable, 2) + " specified");
973 }
974 break;
976 if (!libsumo::POI::handleVariable(id, variable, this, &inputStorage)) {
977 throw libsumo::TraCIException("Get PoI Variable: unsupported variable " + toHex(variable, 2) + " specified");
978 }
979 break;
981 if (!libsumo::Polygon::handleVariable(id, variable, this, &inputStorage)) {
982 throw libsumo::TraCIException("Get Polygon Variable: unsupported variable " + toHex(variable, 2) + " specified");
983 }
984 break;
986 if (!libsumo::Junction::handleVariable(id, variable, this, &inputStorage)) {
987 throw libsumo::TraCIException("Get Junction Variable: unsupported variable " + toHex(variable, 2) + " specified");
988 }
989 break;
991 if (!libsumo::Edge::handleVariable(id, variable, this, &inputStorage)) {
992 throw libsumo::TraCIException("Get Edge Variable: unsupported variable " + toHex(variable, 2) + " specified");
993 }
994 break;
996 if (!TraCIServerAPI_Simulation::processGet(*this, inputStorage, id, variable)) {
997 throw libsumo::TraCIException("Get Simulation Variable: unsupported variable " + toHex(variable, 2) + " specified");
998 }
999 break;
1001 if (!libsumo::LaneArea::handleVariable(id, variable, this, &inputStorage)) {
1002 throw libsumo::TraCIException("Get Lane Area Detector Variable: unsupported variable " + toHex(variable, 2) + " specified");
1003 }
1004 break;
1006 if (!libsumo::Person::handleVariable(id, variable, this, &inputStorage)) {
1007 throw libsumo::TraCIException("Get Person Variable: unsupported variable " + toHex(variable, 2) + " specified");
1008 }
1009 break;
1011 if (!libsumo::BusStop::handleVariable(id, variable, this, &inputStorage)) {
1012 throw libsumo::TraCIException("Get BusStop Variable: unsupported variable " + toHex(variable, 2) + " specified");
1013 }
1014 break;
1016 if (!libsumo::ParkingArea::handleVariable(id, variable, this, &inputStorage)) {
1017 throw libsumo::TraCIException("Get ParkingArea Variable: unsupported variable " + toHex(variable, 2) + " specified");
1018 }
1019 break;
1021 if (!libsumo::ChargingStation::handleVariable(id, variable, this, &inputStorage)) {
1022 throw libsumo::TraCIException("Get ChargingStation Variable: unsupported variable " + toHex(variable, 2) + " specified");
1023 }
1024 break;
1026 if (!libsumo::RouteProbe::handleVariable(id, variable, this, &inputStorage)) {
1027 throw libsumo::TraCIException("Get RouteProbe Variable: unsupported variable " + toHex(variable, 2) + " specified");
1028 }
1029 break;
1031 if (!libsumo::Calibrator::handleVariable(id, variable, this, &inputStorage)) {
1032 throw libsumo::TraCIException("Get Calibrator Variable: unsupported variable " + toHex(variable, 2) + " specified");
1033 }
1034 break;
1036 if (!libsumo::Rerouter::handleVariable(id, variable, this, &inputStorage)) {
1037 throw libsumo::TraCIException("Get Rerouter Variable: unsupported variable " + toHex(variable, 2) + " specified");
1038 }
1039 break;
1041 if (!libsumo::VariableSpeedSign::handleVariable(id, variable, this, &inputStorage)) {
1042 throw libsumo::TraCIException("Get VariableSpeedSign Variable: unsupported variable " + toHex(variable, 2) + " specified");
1043 }
1044 break;
1046 if (!libsumo::MeanData::handleVariable(id, variable, this, &inputStorage)) {
1047 throw libsumo::TraCIException("Get MeanData Variable: unsupported variable " + toHex(variable, 2) + " specified");
1048 }
1049 break;
1051 if (!libsumo::OverheadWire::handleVariable(id, variable, this, &inputStorage)) {
1052 throw libsumo::TraCIException("Get OverheadWire Variable: unsupported variable " + toHex(variable, 2) + " specified");
1053 }
1054 break;
1055 default:
1056 return false;
1057 }
1058 } catch (libsumo::TraCIException& e) {
1059 return writeErrorStatusCmd(commandID, e.what(), outputStorage);
1060 }
1061 writeStatusCmd(commandID, libsumo::RTYPE_OK, "", outputStorage);
1063 return true;
1064}
1065
1066
1067void
1069 mySubscriptions.clear();
1070 myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
1072 myCurrentSocket->second->targetTime = myTargetTime;
1073 myCurrentSocket->second->executeMove = false;
1074 }
1078 for (auto& i : myVehicleStateChanges) {
1079 i.second.clear();
1080 }
1081 for (auto& i : myTransportableStateChanges) {
1082 i.second.clear();
1083 }
1084 myCurrentSocket = mySockets.begin();
1085}
1086
1087
1088std::map<int, TraCIServer::SocketInfo*>::iterator
1090#ifdef DEBUG_MULTI_CLIENTS
1091 std::cout << " Removing socket " << myCurrentSocket->second->socket
1092 << " (order " << myCurrentSocket->first << ")" << std::endl;
1093#endif
1094 delete myCurrentSocket->second;
1096 return myCurrentSocket;
1097}
1098
1099
1100int
1101TraCIServer::readCommandID(int& commandStart, int& commandLength) {
1102 commandStart = myInputStorage.position();
1103 commandLength = myInputStorage.readUnsignedByte();
1104 if (commandLength == 0) {
1105 commandLength = myInputStorage.readInt();
1106 }
1107#ifdef DEBUG_RAW_INPUT
1108 std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
1109 for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
1110 std::cout << (int)*it << " ";
1111 }
1112 std::cout << "\n";
1113#endif
1115}
1116
1117
1118int
1120 int commandStart, commandLength;
1121 int commandId = readCommandID(commandStart, commandLength);
1122#ifdef DEBUG_MULTI_CLIENTS
1123 std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
1124 << ", commandId = " << commandId << std::endl;
1125#endif
1126 bool success = false;
1127 // dispatch commands
1128 if (myExecutors.find(commandId) != myExecutors.end()) {
1129 success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
1130 } else if ((commandId >= libsumo::CMD_GET_INDUCTIONLOOP_VARIABLE && commandId <= libsumo::CMD_GET_BUSSTOP_VARIABLE)
1132 if (commandId == libsumo::CMD_GET_GUI_VARIABLE) {
1133 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1134 } else {
1135 success = processGet(commandId, myInputStorage, myOutputStorage);
1136 }
1137 } else {
1138 switch (commandId) {
1140 success = commandGetVersion();
1141 break;
1142 case libsumo::CMD_LOAD: {
1143 try {
1144 const std::vector<std::string> args = StoHelp::readTypedStringList(myInputStorage, "A load command needs a list of string arguments.");
1145#ifdef DEBUG_MULTI_CLIENTS
1146 std::cout << " commandId == libsumo::CMD_LOAD"
1147 << ", args = " << toString(args) << std::endl;
1148#endif
1149 myLoadArgs = args;
1150 success = true;
1152 // XXX: This only cares for the client that issued the load command.
1153 // Multiclient-load functionality is still to be implemented. Refs #3146.
1154 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1155 myCurrentSocket = mySockets.end();
1157 } catch (libsumo::TraCIException& e) {
1159 }
1160 break;
1161 }
1163 myCurrentSocket->second->executeMove = true;
1165 success = true;
1167 break;
1168 case libsumo::CMD_SIMSTEP: {
1169 const double nextT = myInputStorage.readDouble();
1170 if (nextT == 0.) {
1171 myCurrentSocket->second->targetTime += DELTA_T;
1172 } else {
1173 myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
1174 }
1175 myCurrentSocket->second->executeMove = false;
1176#ifdef DEBUG_MULTI_CLIENTS
1177 std::cout << " commandId == libsumo::CMD_SIMSTEP"
1178 << ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
1179#endif
1180 if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
1181 // This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
1182 // @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommands()
1184 }
1185 // Clear vehicleStateChanges and transportableStateChanges for this client
1186 // -> For subsequent TraCI stepping
1187 // that is performed within this SUMO step, no updates on vehicle states
1188 // belonging to the last SUMO simulation step will be received by this client.
1189 for (auto& item : myCurrentSocket->second->vehicleStateChanges) {
1190 item.second.clear();
1191 }
1192 for (auto& item : myCurrentSocket->second->transportableStateChanges) {
1193 item.second.clear();
1194 }
1196 return commandId;
1197 }
1198 case libsumo::CMD_CLOSE:
1200 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1202 if (mySockets.size() == 1) {
1203 // Last client has closed connection
1204 myDoCloseConnection = true;
1205 }
1206 // remove current socket and increment to next socket in ordering
1208 success = true;
1209 break;
1210 case libsumo::CMD_SETORDER: {
1211 const int order = myInputStorage.readInt();
1212#ifdef DEBUG_MULTI_CLIENTS
1213 std::cout << " commandId == libsumo::CMD_SETORDER"
1214 << ", order index is " << order << std::endl;
1215#endif
1216 if (order > libsumo::MAX_ORDER) {
1217 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
1218 }
1219 if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
1220 return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
1221 }
1222 // memorize reorder request (will only take effect in the next step)
1224 success = true;
1226 break;
1227 }
1252 success = addObjectVariableSubscription(commandId, false);
1253 break;
1278 success = addObjectVariableSubscription(commandId, true);
1279 break;
1281 success = addSubscriptionFilter();
1282 break;
1284 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1285 break;
1286 default:
1287 writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
1288 }
1289 }
1290 if (!success) {
1291 while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
1293 }
1294 }
1295 if ((int)myInputStorage.position() != commandStart + commandLength) {
1296 std::ostringstream msg;
1297 msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
1298 msg << " Expected command length was " << commandLength;
1299 msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
1300 writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
1301 myDoCloseConnection = true;
1302 }
1303 return commandId;
1304}
1305
1306
1307// ---------- Server-internal command handling
1308bool
1310 // Prepare response
1311 tcpip::Storage answerTmp;
1313 answerTmp.writeString("SUMO " VERSION_STRING);
1314 // When we get here, the response is stored in answerTmp -> put into myOutputStorage
1316 // command length
1317 myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
1318 // command type
1320 // and the parameter dependant part
1321 myOutputStorage.writeStorage(answerTmp);
1322 return true;
1323}
1324
1325
1326void
1329#ifdef DEBUG_MULTI_CLIENTS
1330 std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
1331#endif
1333 int noActive = 0;
1334 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1335 const libsumo::Subscription& s = *i;
1338
1340 if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
1341 i = mySubscriptions.erase(i);
1342 continue;
1343 }
1344 ++i;
1345 if (s.beginTime > t) {
1346 continue;
1347 }
1348 ++noActive;
1349 }
1351#ifdef DEBUG_SUBSCRIPTIONS
1352 std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
1353 << "\n Nr. of active subscriptions = " << noActive << std::endl;
1354#endif
1355 mySubscriptionCache.writeInt(noActive);
1356#ifdef DEBUG_SUBSCRIPTIONS
1357 std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
1358#endif
1359 for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1360 const libsumo::Subscription& s = *i;
1361 if (s.beginTime > t) {
1362 ++i;
1363 continue;
1364 }
1365 tcpip::Storage into;
1366 std::string errors;
1367 bool ok = processSingleSubscription(s, into, errors);
1368#ifdef DEBUG_SUBSCRIPTIONS
1369 std::cout << " Size of into-store for subscription " << s.id
1370 << ": " << into.size() << std::endl;
1371#endif
1373 if (ok) {
1374 ++i;
1375 } else {
1376 i = mySubscriptions.erase(i);
1377 }
1378 }
1380#ifdef DEBUG_SUBSCRIPTIONS
1381 std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1382#endif
1383}
1384
1385
1386void
1388#ifdef DEBUG_MULTI_CLIENTS
1389 std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1390 << " (-> intermediate TraCI step)."
1391 << "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1392 << std::endl;
1393#endif
1395
1396// NOTE: the commented code would send an empty response
1397// myOutputStorage.writeInt(0);
1398// myCurrentSocket->second->socket->sendExact(myOutputStorage);
1399// myOutputStorage.reset();
1401 // send results to active client
1402 myCurrentSocket->second->socket->sendExact(myOutputStorage);
1404}
1405
1406
1407void
1408TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1409 writeStatusCmd(commandId, status, description, myOutputStorage);
1410}
1411
1412
1413void
1414TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1415 if (status == libsumo::RTYPE_ERR) {
1416 WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1417 } else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1418 WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1419 }
1420 outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1421 outputStorage.writeUnsignedByte(commandId); // command type
1422 outputStorage.writeUnsignedByte(status); // status
1423 outputStorage.writeString(description); // description
1424}
1425
1426
1427bool
1428TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1429 writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1430 return false;
1431}
1432
1433
1434void
1436 tcpip::Storage writeInto;
1437 std::string errors;
1438 libsumo::Subscription* modifiedSubscription = nullptr;
1439 try {
1440 if (processSingleSubscription(s, writeInto, errors)) {
1442 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1443 } else {
1444 if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1445 // Add new subscription to subscription cache (note: seems a bit inefficient)
1447 // copy new subscription into cache
1448 int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1449 tcpip::Storage tmp;
1450 tmp.writeInt(noActive);
1451 while (mySubscriptionCache.valid_pos()) {
1453 }
1454 tmp.writeStorage(writeInto);
1457 }
1458 }
1460 }
1461 if (modifiedSubscription != nullptr && (
1462 modifiedSubscription->isVehicleToVehicleContextSubscription()
1463 || modifiedSubscription->isVehicleToPersonContextSubscription())) {
1464 // Set last modified vehicle context subscription active for filter modifications
1465 myLastContextSubscription = modifiedSubscription;
1466 } else {
1467 // adding other subscriptions deactivates the activation for filter addition
1468 myLastContextSubscription = nullptr;
1469 }
1470 } else {
1471 writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1472 }
1473 } catch (libsumo::TraCIException& e) {
1475 }
1476 myOutputStorage.writeStorage(writeInto);
1477}
1478
1479
1480void
1481TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1482 bool found = false;
1483 std::vector<libsumo::Subscription>::iterator j;
1484 for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1485 if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1486 j = mySubscriptions.erase(j);
1487 if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1488 // Remove also reference for filter additions
1489 myLastContextSubscription = nullptr;
1490 }
1491 found = true;
1492 continue;
1493 }
1494 ++j;
1495 }
1496 // try unsubscribe
1497 if (found) {
1498 writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1499 } else {
1500 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1501 }
1502}
1503
1504
1505bool
1507 std::string& errors) {
1508 bool ok = true;
1509 tcpip::Storage outputStorage;
1510 const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1511 std::set<std::string> objIDs;
1512 if (s.contextDomain > 0) {
1514 PositionVector shape;
1517 }
1519 } else {
1520 objIDs.insert(s.id);
1521 }
1522 const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1523 int skipped = 0;
1524 for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1525 if (s.contextDomain > 0) {
1526 //if (centralObject(s, *j)) {
1527 // skipped++;
1528 // continue;
1529 //}
1530 outputStorage.writeString(*j);
1531 }
1532 if (numVars > 0) {
1533 std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1534 for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1535 tcpip::Storage message;
1536 message.writeUnsignedByte(*i);
1537 message.writeString(*j);
1538 // TODO check why writeStorage fails here (probably some kind of invalid iterator)
1539 for (const auto& v :** k) {
1540 message.writeChar(v);
1541 }
1542 tcpip::Storage tmpOutput;
1543 try {
1544 if (myExecutors.find(getCommandId) != myExecutors.end()) {
1545 ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1546 } else if (!processGet(getCommandId, message, tmpOutput)) {
1547 if (getCommandId == libsumo::CMD_GET_GUI_VARIABLE) {
1548 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo", tmpOutput);
1549 }
1550 ok = false;
1551 }
1552 } catch (const std::invalid_argument&) {
1553 writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1554 ok = false;
1555 }
1556 // copy response part
1557 if (ok) {
1558 int length = tmpOutput.readUnsignedByte();
1559 while (--length > 0) {
1560 tmpOutput.readUnsignedByte();
1561 }
1562 int lengthLength = 1;
1563 length = tmpOutput.readUnsignedByte();
1564 if (length == 0) {
1565 lengthLength = 5;
1566 length = tmpOutput.readInt();
1567 }
1568 //read responseType
1569 tmpOutput.readUnsignedByte();
1570 int variable = tmpOutput.readUnsignedByte();
1571 std::string id = tmpOutput.readString();
1572 outputStorage.writeUnsignedByte(variable);
1573 outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1574 length -= (lengthLength + 1 + 4 + (int)id.length());
1575 while (--length > 0) {
1576 outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1577 }
1578 } else {
1579 //read length
1580 tmpOutput.readUnsignedByte();
1581 //read cmd
1582 tmpOutput.readUnsignedByte();
1583 //read status
1584 tmpOutput.readUnsignedByte();
1585 std::string msg = tmpOutput.readString();
1586 outputStorage.writeUnsignedByte(*i);
1589 outputStorage.writeString(msg);
1590 errors = errors + msg;
1591 }
1592 }
1593 }
1594 }
1595 int length = (1 + 4) + 1 + (4 + (int)s.id.length()) + 1 + (int)outputStorage.size();
1596 if (s.contextDomain > 0) {
1597 length += 1 + 4; // context domain and number of objects
1598 }
1599 // we always write extended command length here for backward compatibility
1600 writeInto.writeUnsignedByte(0); // command length -> extended
1601 writeInto.writeInt(length);
1602 writeInto.writeUnsignedByte(s.commandId + 0x10);
1603 writeInto.writeString(s.id);
1604 if (s.contextDomain > 0) {
1605 writeInto.writeUnsignedByte(s.contextDomain);
1606 }
1607 writeInto.writeUnsignedByte(numVars);
1608 if (s.contextDomain > 0) {
1609 writeInto.writeInt((int)objIDs.size() - skipped);
1610 }
1611 if (s.contextDomain == 0 || objIDs.size() != 0) {
1612 writeInto.writeStorage(outputStorage);
1613 }
1614 return ok;
1615}
1616
1617
1618bool
1619TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1620 const double beginTime = myInputStorage.readDouble();
1621 const double endTime = myInputStorage.readDouble();
1622 const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1623 const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1624 const std::string id = myInputStorage.readString();
1625 const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1626 double range = hasContext ? myInputStorage.readDouble() : 0.;
1627 if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
1628 range = std::numeric_limits<double>::max();
1629 }
1630 const int num = myInputStorage.readUnsignedByte();
1631 std::vector<int> variables;
1632 std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1633 for (int i = 0; i < num; ++i) {
1634 const int varID = myInputStorage.readUnsignedByte();
1635 variables.push_back(varID);
1636 parameters.push_back(std::make_shared<tcpip::Storage>());
1637 if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1638 if (!myInputStorage.valid_pos()) {
1639 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Missing parameter for subscription " + toHex(commandId, 2));
1640 return false;
1641 }
1642 int count = 1;
1643 while (count-- > 0) {
1644 const int parType = myInputStorage.readUnsignedByte();
1645 parameters.back()->writeUnsignedByte(parType);
1646 if (parType == libsumo::TYPE_DOUBLE) {
1647 parameters.back()->writeDouble(myInputStorage.readDouble());
1648 } else if (parType == libsumo::TYPE_INTEGER) {
1649 parameters.back()->writeInt(myInputStorage.readInt());
1650 } else if (parType == libsumo::TYPE_STRING) {
1651 parameters.back()->writeString(myInputStorage.readString());
1652 } else if (parType == libsumo::TYPE_BYTE) {
1653 parameters.back()->writeByte(myInputStorage.readByte());
1654 } else if (parType == libsumo::TYPE_UBYTE) {
1655 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1656 } else if (parType == libsumo::POSITION_2D) {
1657 parameters.back()->writeDouble(myInputStorage.readDouble());
1658 parameters.back()->writeDouble(myInputStorage.readDouble());
1659 if (varID == libsumo::DISTANCE_REQUEST) {
1660 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1661 break;
1662 }
1663 } else if (parType == libsumo::POSITION_3D) {
1664 parameters.back()->writeDouble(myInputStorage.readDouble());
1665 parameters.back()->writeDouble(myInputStorage.readDouble());
1666 parameters.back()->writeDouble(myInputStorage.readDouble());
1667 if (varID == libsumo::DISTANCE_REQUEST) {
1668 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1669 break;
1670 }
1671 } else if (parType == libsumo::POSITION_ROADMAP) {
1672 parameters.back()->writeString(myInputStorage.readString());
1673 parameters.back()->writeDouble(myInputStorage.readDouble());
1674 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1675 if (varID == libsumo::DISTANCE_REQUEST) {
1676 parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1677 break;
1678 }
1679 } else if (parType == libsumo::TYPE_COMPOUND) {
1680 count = myInputStorage.readInt();
1681 parameters.back()->writeInt(count);
1682 } else {
1683 writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Invalid parameter for subscription " + toHex(commandId, 2));
1684 return false;
1685 }
1686 }
1687 }
1688 }
1689 // check subscribe/unsubscribe
1690 if (variables.empty()) {
1691 removeSubscription(commandId, id, domain);
1692 return true;
1693 }
1694 // process subscription
1695 libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1697 return true;
1698}
1699
1700
1701
1702bool
1704 bool success = true;
1705 // Read filter type
1706 int filterType = myInputStorage.readUnsignedByte();
1707
1708 if (myLastContextSubscription == nullptr) {
1710 "No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1711 return false;
1712 }
1713
1714 // dispatch according to filter type
1715 switch (filterType) {
1717 // Remove all filters
1718 removeFilters();
1719 break;
1721 // Read relative lanes to consider for context filter
1722 int nrLanes = (int)myInputStorage.readByte();
1723 std::vector<int> lanes;
1724 for (int i = 0; i < nrLanes; ++i) {
1725 lanes.push_back((int) myInputStorage.readByte());
1726 }
1728 }
1729 break;
1731 // Add no-opposite filter
1733 break;
1735 myInputStorage.readByte(); // read type double
1736 double dist = myInputStorage.readDouble();
1738 }
1739 break;
1741 myInputStorage.readByte(); // read type double
1742 double dist = myInputStorage.readDouble();
1744 }
1745 break;
1747 // Read relative lanes to consider for context filter
1749 }
1750 break;
1752 myInputStorage.readByte(); // read type double
1753 double dist = myInputStorage.readDouble();
1755 }
1756 break;
1758 myInputStorage.readByte(); // read type stringlist
1761 }
1762 break;
1764 myInputStorage.readByte(); // read type stringlist
1765 std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1766 std::set<std::string> vTypesSet;
1767 vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1768 addSubscriptionFilterVType(vTypesSet);
1769 }
1770 break;
1772 myInputStorage.readByte(); // read type double
1773 double angle = myInputStorage.readDouble();
1775 }
1776 break;
1778 myInputStorage.readByte(); // read type double
1779 double dist = myInputStorage.readDouble();
1781 }
1782 break;
1783 default:
1785 "'" + toString(filterType) + "' is no valid filter type code.");
1786 success = false;
1787 }
1788
1789 if (success) {
1790 // acknowledge filter addition
1792 }
1793
1794 return success;
1795}
1796
1797
1798void
1800#ifdef DEBUG_SUBSCRIPTION_FILTERS
1801 std::cout << "Removing filters" << std::endl;
1802#endif
1804}
1805
1806void
1808#ifdef DEBUG_SUBSCRIPTION_FILTERS
1809 std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1810#endif
1813}
1814
1815void
1817#ifdef DEBUG_SUBSCRIPTION_FILTERS
1818 std::cout << "Adding no opposite filter" << std::endl;
1819#endif
1821}
1822
1823void
1825#ifdef DEBUG_SUBSCRIPTION_FILTERS
1826 std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1827#endif
1830}
1831
1832void
1834#ifdef DEBUG_SUBSCRIPTION_FILTERS
1835 std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1836#endif
1839}
1840
1841void
1843#ifdef DEBUG_SUBSCRIPTION_FILTERS
1844 std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1845#endif
1847}
1848
1849void
1851#ifdef DEBUG_SUBSCRIPTION_FILTERS
1852 std::cout << "Adding turn-maneuver filter" << std::endl;
1853#endif
1856}
1857
1858void
1860#ifdef DEBUG_SUBSCRIPTION_FILTERS
1861 std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1862#endif
1865}
1866
1867void
1868TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1869#ifdef DEBUG_SUBSCRIPTION_FILTERS
1870 std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1871#endif
1874}
1875
1876void
1878#ifdef DEBUG_SUBSCRIPTION_FILTERS
1879 std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1880#endif
1883}
1884
1885void
1887#ifdef DEBUG_SUBSCRIPTION_FILTERS
1888 std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1889#endif
1892}
1893
1894void
1896 if (tempMsg.size() < 254) {
1897 outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1898 } else {
1899 outputStorage.writeUnsignedByte(0); // command length -> extended
1900 outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1901 }
1902 outputStorage.writeStorage(tempMsg);
1903}
1904
1905
1906void
1908 myTargetTime = targetTime;
1909 for (auto& s : mySockets) {
1910 s.second->targetTime = targetTime;
1911 s.second->executeMove = false;
1912 for (auto& stateChange : s.second->vehicleStateChanges) {
1913 stateChange.second.clear();
1914 }
1915 for (auto& stateChange : s.second->transportableStateChanges) {
1916 stateChange.second.clear();
1917 }
1918 }
1919 mySubscriptions.clear();
1921}
1922
1923
1924bool
1925TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1926 return (s.id == objID && s.commandId + 32 == s.contextDomain);
1927}
1928
1929
1930/****************************************************************************/
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 processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change Calibrator State)
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 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 processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcd: Set AreaDetector Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc3: Change Lane State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc1: Set MeMeDetector 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 processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc6: Change ParkingArea State)
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 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 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, const std::string &objID, const int variable)
Processes a get value command (Command 0xab: Get Simulation Variable)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xcb: Set Simulation 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 processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc4: Change Vehicle State)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc5: Change Vehicle Type State)
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)
bool processGet(const int commandID, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command.
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 int readCompound(tcpip::Storage &ret, int expectedSize=-1, const std::string &error="")
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 std::string readTypedString(tcpip::Storage &ret, const std::string &error="")
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 TL_CONSTRAINT_SWAP
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