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