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