Eclipse SUMO - Simulation of Urban MObility
TraCIServerAPI_TrafficLight.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2009-2020 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 /****************************************************************************/
21 // APIs for getting/setting traffic light values via TraCI
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <microsim/MSLane.h>
26 #include <microsim/MSEdge.h>
29 #include <libsumo/TraCIConstants.h>
30 #include <libsumo/TrafficLight.h>
32 
33 
34 // ===========================================================================
35 // method definitions
36 // ===========================================================================
37 bool
39  tcpip::Storage& outputStorage) {
40  const int variable = inputStorage.readUnsignedByte();
41  const std::string id = inputStorage.readString();
42  server.initWrapper(libsumo::RESPONSE_GET_TL_VARIABLE, variable, id);
43  try {
44  if (!libsumo::TrafficLight::handleVariable(id, variable, &server)) {
45  switch (variable) {
47  std::vector<libsumo::TraCILogic> logics = libsumo::TrafficLight::getCompleteRedYellowGreenDefinition(id);
48  tcpip::Storage& storage = server.getWrapperStorage();
50  storage.writeInt((int)logics.size());
51  for (const libsumo::TraCILogic& logic : logics) {
53  storage.writeInt(5);
55  storage.writeString(logic.programID);
56  // type
58  storage.writeInt(logic.type);
59  // (current) phase index
61  storage.writeInt(logic.currentPhaseIndex);
62  // phase number
64  storage.writeInt((int)logic.phases.size());
65  for (const libsumo::TraCIPhase* phase : logic.phases) {
67  storage.writeInt(6);
69  storage.writeDouble(phase->duration);
71  storage.writeString(phase->state);
73  storage.writeDouble(phase->minDur);
75  storage.writeDouble(phase->maxDur);
77  storage.writeInt((int)phase->next.size());
78  for (int n : phase->next) {
80  storage.writeInt(n);
81  }
83  storage.writeString(phase->name);
84  }
85  // subparameter
87  storage.writeInt((int)logic.subParameter.size());
88  for (const auto& item : logic.subParameter) {
90  storage.writeInt(2);
91  storage.writeString(item.first);
92  storage.writeString(item.second);
93  }
94  }
95  break;
96  }
98  const std::vector<std::vector<libsumo::TraCILink> > links = libsumo::TrafficLight::getControlledLinks(id);
100  tcpip::Storage tempContent;
101  int cnt = 0;
103  tempContent.writeInt((int)links.size());
104  for (const std::vector<libsumo::TraCILink>& sublinks : links) {
106  tempContent.writeInt((int)sublinks.size());
107  ++cnt;
108  for (const libsumo::TraCILink& link : sublinks) {
110  tempContent.writeStringList(std::vector<std::string>({ link.fromLane, link.toLane, link.viaLane }));
111  ++cnt;
112  }
113  }
114  server.getWrapperStorage().writeInt(cnt);
115  server.getWrapperStorage().writeStorage(tempContent);
116  break;
117  }
119  int index = 0;
120  if (!server.readTypeCheckingInt(inputStorage, index)) {
121  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The phase index must be given as an integer.", outputStorage);
122  }
124  server.getWrapperStorage().writeInt(libsumo::TrafficLight::getServedPersonCount(id, index));
125  break;
126  }
128  int index = 0;
129  if (!server.readTypeCheckingInt(inputStorage, index)) {
130  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The link index must be given as an integer.", outputStorage);
131  }
133  server.getWrapperStorage().writeStringList(libsumo::TrafficLight::getBlockingVehicles(id, index));
134  break;
135  }
137  int index = 0;
138  if (!server.readTypeCheckingInt(inputStorage, index)) {
139  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The link index must be given as an integer.", outputStorage);
140  }
142  server.getWrapperStorage().writeStringList(libsumo::TrafficLight::getRivalVehicles(id, index));
143  break;
144  }
146  int index = 0;
147  if (!server.readTypeCheckingInt(inputStorage, index)) {
148  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The link index must be given as an integer.", outputStorage);
149  }
151  server.getWrapperStorage().writeStringList(libsumo::TrafficLight::getPriorityVehicles(id, index));
152  break;
153  }
154  case libsumo::VAR_PARAMETER: {
155  std::string paramName = "";
156  if (!server.readTypeCheckingString(inputStorage, paramName)) {
157  return server.writeErrorStatusCmd(libsumo::CMD_GET_TL_VARIABLE, "Retrieval of a parameter requires its name.", outputStorage);
158  }
160  server.getWrapperStorage().writeString(libsumo::TrafficLight::getParameter(id, paramName));
161  break;
162  }
164  std::string paramName = "";
165  if (!server.readTypeCheckingString(inputStorage, paramName)) {
166  return server.writeErrorStatusCmd(libsumo::CMD_GET_TL_VARIABLE, "Retrieval of a parameter requires its name.", outputStorage);
167  }
169  server.getWrapperStorage().writeInt(2);
171  server.getWrapperStorage().writeString(paramName);
173  server.getWrapperStorage().writeString(libsumo::TrafficLight::getParameter(id, paramName));
174  break;
175  }
177  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
178  throw libsumo::TraCIException("Traffic light '" + id + "' is not known");
179  }
181  const std::string& state = tls->getCurrentPhaseDef().getState();
182  const std::map<std::string, std::string>& params = tls->getParametersMap();
183  int num = 0;
184  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
185  if ("connection:" == (*i).first.substr(0, 11)) {
186  ++num;
187  }
188  }
189 
192  server.getWrapperStorage().writeInt(num * 2);
193  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
194  if ("connection:" != (*i).first.substr(0, 11)) {
195  continue;
196  }
198  server.getWrapperStorage().writeString((*i).second); // foreign id
199  std::string connection = (*i).first.substr(11);
200  std::string from, to;
201  const std::string::size_type b = connection.find("->");
202  if (b == std::string::npos) {
203  from = connection;
204  } else {
205  from = connection.substr(0, b);
206  to = connection.substr(b + 2);
207  }
208  bool denotesEdge = from.find("_") == std::string::npos;
209  MSLane* fromLane = nullptr;
211  MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin();
212  for (; j != lanes.end() && fromLane == nullptr;) {
213  for (MSTrafficLightLogic::LaneVector::const_iterator k = (*j).begin(); k != (*j).end() && fromLane == nullptr;) {
214  if (denotesEdge && (*k)->getEdge().getID() == from) {
215  fromLane = *k;
216  } else if (!denotesEdge && (*k)->getID() == from) {
217  fromLane = *k;
218  }
219  if (fromLane == nullptr) {
220  ++k;
221  }
222  }
223  if (fromLane == nullptr) {
224  ++j;
225  }
226  }
227  if (fromLane == nullptr) {
228  return server.writeErrorStatusCmd(libsumo::CMD_GET_TL_VARIABLE, "Could not find edge or lane '" + from + "' in traffic light '" + id + "'.", outputStorage);
229  }
230  int pos = (int)std::distance(lanes.begin(), j);
232  server.getWrapperStorage().writeUnsignedByte(state[pos]); // state
233  }
234  break;
235  }
236  default:
237  return server.writeErrorStatusCmd(libsumo::CMD_GET_TL_VARIABLE, "Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
238  }
239  }
240  } catch (libsumo::TraCIException& e) {
241  return server.writeErrorStatusCmd(libsumo::CMD_GET_TL_VARIABLE, e.what(), outputStorage);
242  }
244  server.writeResponseWithLength(outputStorage, server.getWrapperStorage());
245  return true;
246 }
247 
248 
249 bool
251  tcpip::Storage& outputStorage) {
252  std::string warning = ""; // additional description for response
253  // variable
254  const int variable = inputStorage.readUnsignedByte();
255  if (variable != libsumo::TL_PHASE_INDEX && variable != libsumo::TL_PROGRAM && variable != libsumo::TL_PHASE_DURATION
257  && variable != libsumo::VAR_NAME
258  && variable != libsumo::VAR_PARAMETER) {
259  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "Change TLS State: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
260  }
261  const std::string id = inputStorage.readString();
262  try {
263  switch (variable) {
265  int index = 0;
266  if (!server.readTypeCheckingInt(inputStorage, index)) {
267  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The phase index must be given as an integer.", outputStorage);
268  }
269  libsumo::TrafficLight::setPhase(id, index);
270  }
271  break;
272  case libsumo::VAR_NAME: {
273  std::string name;
274  if (!server.readTypeCheckingString(inputStorage, name)) {
275  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The phase name must be given as a string.", outputStorage);
276  }
277  libsumo::TrafficLight::setPhaseName(id, name);
278  }
279  break;
280  case libsumo::TL_PROGRAM: {
281  std::string subID;
282  if (!server.readTypeCheckingString(inputStorage, subID)) {
283  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The program must be given as a string.", outputStorage);
284  }
285  libsumo::TrafficLight::setProgram(id, subID);
286  }
287  break;
289  double duration = 0.;
290  if (!server.readTypeCheckingDouble(inputStorage, duration)) {
291  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The phase duration must be given as a double.", outputStorage);
292  }
293  libsumo::TrafficLight::setPhaseDuration(id, duration);
294  }
295  break;
297  std::string state;
298  if (!server.readTypeCheckingString(inputStorage, state)) {
299  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The phase must be given as a string.", outputStorage);
300  }
301  libsumo::TrafficLight::setRedYellowGreenState(id, state);
302  }
303  break;
305  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
306  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "A compound object is needed for setting a new program.", outputStorage);
307  }
308  //read itemNo
309  inputStorage.readInt();
310  libsumo::TraCILogic logic;
311  if (!server.readTypeCheckingString(inputStorage, logic.programID)) {
312  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 1. parameter (programID) must be a string.", outputStorage);
313  }
314  if (!server.readTypeCheckingInt(inputStorage, logic.type)) {
315  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 2. parameter (type) must be an int.", outputStorage);
316  }
317  if (!server.readTypeCheckingInt(inputStorage, logic.currentPhaseIndex)) {
318  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 3. parameter (index) must be an int.", outputStorage);
319  }
320  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
321  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "A compound object is needed for the phases.", outputStorage);
322  }
323  const int numPhases = inputStorage.readInt();
324  for (int j = 0; j < numPhases; ++j) {
325  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
326  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "A compound object is needed for every phase.", outputStorage);
327  }
328  const int items = inputStorage.readInt();
329  if (items != 6 && items != 5) {
330  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "A phase compound object requires 5 or 6 items.", outputStorage);
331  }
332  double duration = 0., minDuration = 0., maxDuration = 0.;
333  std::vector<int> next;
334  std::string name;
335  if (!server.readTypeCheckingDouble(inputStorage, duration)) {
336  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.1. parameter (duration) must be a double.", outputStorage);
337  }
338  std::string state;
339  if (!server.readTypeCheckingString(inputStorage, state)) {
340  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.2. parameter (phase) must be a string.", outputStorage);
341  }
342  if (!server.readTypeCheckingDouble(inputStorage, minDuration)) {
343  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.3. parameter (min duration) must be a double.", outputStorage);
344  }
345  if (!server.readTypeCheckingDouble(inputStorage, maxDuration)) {
346  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.4. parameter (max duration) must be a double.", outputStorage);
347  }
348  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
349  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program 4.5 parameter (next) must be a compound (list of ints).", outputStorage);
350  }
351  const int numNext = inputStorage.readInt();
352  for (int k = 0; k < numNext; k++) {
353  int nextEntry;
354  if (!server.readTypeCheckingInt(inputStorage, nextEntry)) {
355  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.5. parameter (next) must be a list of int.", outputStorage);
356  }
357  next.push_back(nextEntry);
358  }
359  if (items == 6) {
360  if (!server.readTypeCheckingString(inputStorage, name)) {
361  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 4.6. parameter (name) must be a string.", outputStorage);
362  }
363  }
364  logic.phases.emplace_back(new libsumo::TraCIPhase(duration, state, minDuration, maxDuration, next, name));
365  }
366  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
367  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "set program: 5. parameter (subparams) must be a compound object.", outputStorage);
368  }
369  const int numParams = inputStorage.readInt();
370  for (int j = 0; j < numParams; j++) {
371  std::vector<std::string> par;
372  server.readTypeCheckingStringList(inputStorage, par);
373  logic.subParameter[par[0]] = par[1];
374  }
375  libsumo::TrafficLight::setCompleteRedYellowGreenDefinition(id, logic);
376  }
377  break;
378  case libsumo::VAR_PARAMETER: {
379  if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
380  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "A compound object is needed for setting a parameter.", outputStorage);
381  }
382  //read itemNo
383  inputStorage.readInt();
384  std::string name;
385  if (!server.readTypeCheckingString(inputStorage, name)) {
386  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The name of the parameter must be given as a string.", outputStorage);
387  }
388  std::string value;
389  if (!server.readTypeCheckingString(inputStorage, value)) {
390  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, "The value of the parameter must be given as a string.", outputStorage);
391  }
392  libsumo::TrafficLight::setParameter(id, name, value);
393  }
394  break;
395  default:
396  break;
397  }
398  } catch (libsumo::TraCIException& e) {
399  return server.writeErrorStatusCmd(libsumo::CMD_SET_TL_VARIABLE, e.what(), outputStorage);
400  }
401  server.writeStatusCmd(libsumo::CMD_SET_TL_VARIABLE, libsumo::RTYPE_OK, warning, outputStorage);
402  return true;
403 }
404 
405 
406 /****************************************************************************/
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:54
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:171
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:444
const std::string & getState() const
Returns the state within this phase.
MSTrafficLightLogic * getActive() const
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
The parent class for traffic light logics.
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
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)
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:59
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
tcpip::Storage & getWrapperStorage()
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 readTypeCheckingInt(tcpip::Storage &inputStorage, int &into)
Reads the value type and an int, verifying the type.
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
std::map< std::string, std::string > subParameter
Definition: TraCIDefs.h:291
std::string programID
Definition: TraCIDefs.h:287
std::vector< TraCIPhase * > phases
Definition: TraCIDefs.h:290
std::vector< int > next
Definition: TraCIDefs.h:267
std::string state
Definition: TraCIDefs.h:265
std::string name
Definition: TraCIDefs.h:268
virtual std::string readString()
Definition: storage.cpp:175
virtual void writeString(const std::string &s)
Definition: storage.cpp:192
virtual void writeInt(int)
Definition: storage.cpp:316
virtual void writeDouble(double)
Definition: storage.cpp:349
virtual int readUnsignedByte()
Definition: storage.cpp:150
virtual void writeStringList(const std::vector< std::string > &s)
Definition: storage.cpp:242
virtual void writeUnsignedByte(int)
Definition: storage.cpp:160
virtual void writeStorage(tcpip::Storage &store)
Definition: storage.cpp:383
virtual int readInt()
Definition: storage.cpp:306
TRACI_CONST int VAR_NAME
TRACI_CONST int CMD_GET_TL_VARIABLE
TRACI_CONST int TL_BLOCKING_VEHICLES
TRACI_CONST int TL_PRIORITY_VEHICLES
TRACI_CONST int TYPE_COMPOUND
TRACI_CONST int TL_COMPLETE_DEFINITION_RYG
TRACI_CONST int TYPE_UBYTE
TRACI_CONST int VAR_PERSON_NUMBER
TRACI_CONST int TL_EXTERNAL_STATE
TRACI_CONST int TYPE_STRINGLIST
TRACI_CONST int TL_CONTROLLED_LINKS
TRACI_CONST int TYPE_INTEGER
TRACI_CONST int VAR_PARAMETER
TRACI_CONST int VAR_PARAMETER_WITH_KEY
TRACI_CONST int TL_PROGRAM
TRACI_CONST int RESPONSE_GET_TL_VARIABLE
TRACI_CONST int TL_PHASE_DURATION
TRACI_CONST int TL_PHASE_INDEX
TRACI_CONST int TYPE_DOUBLE
TRACI_CONST int TL_COMPLETE_PROGRAM_RYG
TRACI_CONST int CMD_SET_TL_VARIABLE
TRACI_CONST int TL_RED_YELLOW_GREEN_STATE
TRACI_CONST int RTYPE_OK
TRACI_CONST int TYPE_STRING
TRACI_CONST int TL_RIVAL_VEHICLES