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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // APIs for getting/setting traffic light values via TraCI
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <microsim/MSLane.h>
28 #include <microsim/MSEdge.h>
31 #include <libsumo/TrafficLight.h>
32 #include "TraCIConstants.h"
34 
35 
36 // ===========================================================================
37 // method definitions
38 // ===========================================================================
39 bool
41  tcpip::Storage& outputStorage) {
42  const int variable = inputStorage.readUnsignedByte();
43  const std::string id = inputStorage.readString();
44  server.initWrapper(RESPONSE_GET_TL_VARIABLE, variable, id);
45  try {
46  if (!libsumo::TrafficLight::handleVariable(id, variable, &server)) {
47  switch (variable) {
49  std::vector<libsumo::TraCILogic> logics = libsumo::TrafficLight::getCompleteRedYellowGreenDefinition(id);
50  tcpip::Storage& storage = server.getWrapperStorage();
52  storage.writeInt((int)logics.size());
53  for (const libsumo::TraCILogic& logic : logics) {
55  storage.writeInt(5);
57  storage.writeString(logic.programID);
58  // type
60  storage.writeInt(logic.type);
61  // (current) phase index
63  storage.writeInt(logic.currentPhaseIndex);
64  // phase number
66  storage.writeInt((int)logic.phases.size());
67  for (const libsumo::TraCIPhase& phase : logic.phases) {
69  storage.writeInt(5);
71  storage.writeDouble(phase.duration);
73  storage.writeString(phase.state);
75  storage.writeDouble(phase.minDur);
77  storage.writeDouble(phase.maxDur);
79  storage.writeInt(phase.next);
80  }
81  // subparameter
83  storage.writeInt((int)logic.subParameter.size());
84  for (const auto& item : logic.subParameter) {
86  storage.writeInt(2);
87  storage.writeString(item.first);
88  storage.writeString(item.second);
89  }
90  }
91  break;
92  }
93  case TL_CONTROLLED_LINKS: {
94  const std::vector<std::vector<libsumo::TraCILink> > links = libsumo::TrafficLight::getControlledLinks(id);
96  tcpip::Storage tempContent;
97  int cnt = 0;
98  tempContent.writeUnsignedByte(TYPE_INTEGER);
99  tempContent.writeInt((int)links.size());
100  for (const std::vector<libsumo::TraCILink>& sublinks : links) {
101  tempContent.writeUnsignedByte(TYPE_INTEGER);
102  tempContent.writeInt((int)sublinks.size());
103  ++cnt;
104  for (const libsumo::TraCILink& link : sublinks) {
105  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
106  tempContent.writeStringList(std::vector<std::string>({ link.fromLane, link.toLane, link.viaLane }));
107  ++cnt;
108  }
109  }
110  server.getWrapperStorage().writeInt(cnt);
111  server.getWrapperStorage().writeStorage(tempContent);
112  break;
113  }
114  case VAR_PARAMETER: {
115  std::string paramName = "";
116  if (!server.readTypeCheckingString(inputStorage, paramName)) {
117  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Retrieval of a parameter requires its name.", outputStorage);
118  }
121  break;
122  }
123  case TL_EXTERNAL_STATE: {
124  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
125  throw libsumo::TraCIException("Traffic light '" + id + "' is not known");
126  }
128  const std::string& state = tls->getCurrentPhaseDef().getState();
129  const std::map<std::string, std::string>& params = tls->getParametersMap();
130  int num = 0;
131  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
132  if ("connection:" == (*i).first.substr(0, 11)) {
133  ++num;
134  }
135  }
136 
139  server.getWrapperStorage().writeInt(num * 2);
140  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
141  if ("connection:" != (*i).first.substr(0, 11)) {
142  continue;
143  }
145  server.getWrapperStorage().writeString((*i).second); // foreign id
146  std::string connection = (*i).first.substr(11);
147  std::string from, to;
148  const std::string::size_type b = connection.find("->");
149  if (b == std::string::npos) {
150  from = connection;
151  } else {
152  from = connection.substr(0, b);
153  to = connection.substr(b + 2);
154  }
155  bool denotesEdge = from.find("_") == std::string::npos;
156  MSLane* fromLane = nullptr;
158  MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin();
159  for (; j != lanes.end() && fromLane == nullptr;) {
160  for (MSTrafficLightLogic::LaneVector::const_iterator k = (*j).begin(); k != (*j).end() && fromLane == nullptr;) {
161  if (denotesEdge && (*k)->getEdge().getID() == from) {
162  fromLane = *k;
163  } else if (!denotesEdge && (*k)->getID() == from) {
164  fromLane = *k;
165  }
166  if (fromLane == nullptr) {
167  ++k;
168  }
169  }
170  if (fromLane == nullptr) {
171  ++j;
172  }
173  }
174  if (fromLane == nullptr) {
175  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Could not find edge or lane '" + from + "' in traffic light '" + id + "'.", outputStorage);
176  }
177  int pos = (int)std::distance(lanes.begin(), j);
179  server.getWrapperStorage().writeUnsignedByte(state[pos]); // state
180  }
181  break;
182  }
183  default:
184  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
185  }
186  }
187  } catch (libsumo::TraCIException& e) {
188  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, e.what(), outputStorage);
189  }
190  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, "", outputStorage);
191  server.writeResponseWithLength(outputStorage, server.getWrapperStorage());
192  return true;
193 }
194 
195 
196 bool
198  tcpip::Storage& outputStorage) {
199  std::string warning = ""; // additional description for response
200  // variable
201  const int variable = inputStorage.readUnsignedByte();
202  if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM && variable != TL_PHASE_DURATION
203  && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG
204  && variable != VAR_PARAMETER) {
205  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "Change TLS State: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
206  }
207  const std::string id = inputStorage.readString();
208  try {
209  switch (variable) {
210  case TL_PHASE_INDEX: {
211  int index = 0;
212  if (!server.readTypeCheckingInt(inputStorage, index)) {
213  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase index must be given as an integer.", outputStorage);
214  }
216  }
217  break;
218  case TL_PROGRAM: {
219  std::string subID;
220  if (!server.readTypeCheckingString(inputStorage, subID)) {
221  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The program must be given as a string.", outputStorage);
222  }
224  }
225  break;
226  case TL_PHASE_DURATION: {
227  double duration = 0.;
228  if (!server.readTypeCheckingDouble(inputStorage, duration)) {
229  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase duration must be given as a double.", outputStorage);
230  }
232  }
233  break;
235  std::string state;
236  if (!server.readTypeCheckingString(inputStorage, state)) {
237  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase must be given as a string.", outputStorage);
238  }
240  }
241  break;
243  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
244  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a new program.", outputStorage);
245  }
246  //read itemNo
247  inputStorage.readInt();
248  libsumo::TraCILogic logic;
249  if (!server.readTypeCheckingString(inputStorage, logic.programID)) {
250  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 1. parameter (programID) must be a string.", outputStorage);
251  }
252  if (!server.readTypeCheckingInt(inputStorage, logic.type)) {
253  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 2. parameter (type) must be an int.", outputStorage);
254  }
255  if (!server.readTypeCheckingInt(inputStorage, logic.currentPhaseIndex)) {
256  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 3. parameter (index) must be an int.", outputStorage);
257  }
258  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
259  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for the phases.", outputStorage);
260  }
261  const int numPhases = inputStorage.readInt();
262  for (int j = 0; j < numPhases; ++j) {
263  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
264  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for every phase.", outputStorage);
265  }
266  inputStorage.readInt();
267  double duration = 0., minDuration = 0., maxDuration = 0.;
268  int next = -1;
269  if (!server.readTypeCheckingDouble(inputStorage, duration)) {
270  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4.1. parameter (duration) must be a double.", outputStorage);
271  }
272  std::string state;
273  if (!server.readTypeCheckingString(inputStorage, state)) {
274  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4.2. parameter (phase) must be a string.", outputStorage);
275  }
276  if (!server.readTypeCheckingDouble(inputStorage, minDuration)) {
277  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4.3. parameter (min duration) must be a double.", outputStorage);
278  }
279  if (!server.readTypeCheckingDouble(inputStorage, maxDuration)) {
280  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4.4. parameter (max duration) must be a double.", outputStorage);
281  }
282  if (!server.readTypeCheckingInt(inputStorage, next)) {
283  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4.5. parameter (next) must be an int.", outputStorage);
284  }
285  logic.phases.emplace_back(libsumo::TraCIPhase(duration, state, minDuration, maxDuration, next));
286  }
287  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
288  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 5. parameter (subparams) must be a compound object.", outputStorage);
289  }
290  const int numParams = inputStorage.readInt();
291  for (int j = 0; j < numParams; j++) {
292  std::vector<std::string> par;
293  server.readTypeCheckingStringList(inputStorage, par);
294  logic.subParameter[par[0]] = par[1];
295  }
297  }
298  break;
299  case VAR_PARAMETER: {
300  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
301  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a parameter.", outputStorage);
302  }
303  //read itemNo
304  inputStorage.readInt();
305  std::string name;
306  if (!server.readTypeCheckingString(inputStorage, name)) {
307  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The name of the parameter must be given as a string.", outputStorage);
308  }
309  std::string value;
310  if (!server.readTypeCheckingString(inputStorage, value)) {
311  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The value of the parameter must be given as a string.", outputStorage);
312  }
313  libsumo::TrafficLight::setParameter(id, name, value);
314  }
315  break;
316  default:
317  break;
318  }
319  } catch (libsumo::TraCIException& e) {
320  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, e.what(), outputStorage);
321  }
322  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
323  return true;
324 }
325 
326 
327 /****************************************************************************/
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
const std::string & getState() const
Returns the state within this phase.
#define CMD_GET_TL_VARIABLE
#define TYPE_COMPOUND
static void setPhaseDuration(const std::string &tlsID, const double phaseDuration)
#define TYPE_UBYTE
#define RTYPE_OK
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
static void setParameter(const std::string &tlsID, const std::string &paramName, const std::string &value)
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc2: Change Traffic Lights State)
bool readTypeCheckingInt(tcpip::Storage &inputStorage, int &into)
Reads the value type and an int, verifying the type.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:165
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
#define TYPE_STRINGLIST
bool readTypeCheckingDouble(tcpip::Storage &inputStorage, double &into)
Reads the value type and a double, verifying the type.
std::map< std::string, std::string > subParameter
Definition: TraCIDefs.h:235
#define RESPONSE_GET_TL_VARIABLE
static bool handleVariable(const std::string &objID, const int variable, VariableWrapper *wrapper)
virtual void writeUnsignedByte(int)
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
std::vector< TraCIPhase > phases
Definition: TraCIDefs.h:234
virtual void writeInt(int)
#define TYPE_STRING
virtual int readUnsignedByte()
#define TL_PHASE_DURATION
static void setRedYellowGreenState(const std::string &tlsID, const std::string &state)
#define CMD_SET_TL_VARIABLE
virtual int readInt()
#define TL_COMPLETE_PROGRAM_RYG
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:389
#define TL_COMPLETE_DEFINITION_RYG
bool readTypeCheckingStringList(tcpip::Storage &inputStorage, std::vector< std::string > &into)
Reads the value type and a string list, verifying the type.
virtual void writeStringList(const std::vector< std::string > &s)
#define TL_EXTERNAL_STATE
tcpip::Storage & getWrapperStorage()
virtual std::string readString()
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:62
virtual void writeStorage(tcpip::Storage &store)
#define TL_CONTROLLED_LINKS
static std::vector< TraCILogic > getCompleteRedYellowGreenDefinition(const std::string &tlsID)
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
#define TL_RED_YELLOW_GREEN_STATE
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa2: Get Traffic Lights Variable)
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of lanes that do have the same attribute.
virtual void writeString(const std::string &s)
#define TL_PROGRAM
#define TYPE_DOUBLE
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:59
std::string programID
Definition: TraCIDefs.h:231
static void setPhase(const std::string &tlsID, const int index)
virtual void writeDouble(double)
static void setCompleteRedYellowGreenDefinition(const std::string &tlsID, const TraCILogic &logic)
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
The parent class for traffic light logics.
static void setProgram(const std::string &tlsID, const std::string &programID)
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
void initWrapper(const int domainID, const int variable, const std::string &objID)
#define VAR_PARAMETER
MSTrafficLightLogic * getActive() const
static std::string getParameter(const std::string &tlsID, const std::string &paramName)
#define TYPE_INTEGER
std::string state
Definition: TraCIDefs.h:211
#define TL_PHASE_INDEX
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
static std::vector< std::vector< TraCILink > > getControlledLinks(const std::string &tlsID)