SUMO - Simulation of Urban MObility
TraCIServerAPI_TLS.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // APIs for getting/setting traffic light values via TraCI
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2009-2017 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #ifndef NO_TRACI
35 
36 #include "TraCIConstants.h"
37 #include <microsim/MSLane.h>
38 #include <microsim/MSEdge.h>
41 #include "TraCIServerAPI_TLS.h"
42 
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 bool
49  tcpip::Storage& outputStorage) {
50  // variable & id
51  int variable = inputStorage.readUnsignedByte();
52  std::string id = inputStorage.readString();
53  // check variable
54  if (variable != ID_LIST && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_DEFINITION_RYG
55  && variable != TL_CONTROLLED_LANES && variable != TL_CONTROLLED_LINKS
56  && variable != TL_CURRENT_PHASE && variable != TL_CURRENT_PROGRAM
57  && variable != TL_NEXT_SWITCH && variable != TL_PHASE_DURATION && variable != ID_COUNT
58  && variable != VAR_PARAMETER && variable != TL_EXTERNAL_STATE) {
59  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
60  }
61  // begin response building
62  tcpip::Storage tempMsg;
63  // response-code, variableID, objectID
65  tempMsg.writeUnsignedByte(variable);
66  tempMsg.writeString(id);
67  if (variable == ID_LIST) {
68  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
70  tempMsg.writeStringList(ids);
71  } else if (variable == ID_COUNT) {
72  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
74  tempMsg.writeInt((int) ids.size());
75  } else {
76  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
77  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Traffic light '" + id + "' is not known", outputStorage);
78  }
80  switch (variable) {
81  case ID_LIST:
82  break;
85  std::string state = vars.getActive()->getCurrentPhaseDef().getState();
86  tempMsg.writeString(state);
87  }
88  break;
90  std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
92  tcpip::Storage tempContent;
93  int cnt = 0;
94  tempContent.writeUnsignedByte(TYPE_INTEGER);
95  tempContent.writeInt((int) logics.size());
96  ++cnt;
97  for (int i = 0; i < (int)logics.size(); ++i) {
98  MSTrafficLightLogic* logic = logics[i];
99  tempContent.writeUnsignedByte(TYPE_STRING);
100  tempContent.writeString(logic->getProgramID());
101  ++cnt;
102  // type (always 0 by now)
103  tempContent.writeUnsignedByte(TYPE_INTEGER);
104  tempContent.writeInt(0);
105  ++cnt;
106  // subparameter (always 0 by now)
107  tempContent.writeUnsignedByte(TYPE_COMPOUND);
108  tempContent.writeInt(0);
109  ++cnt;
110  // (current) phase index
111  tempContent.writeUnsignedByte(TYPE_INTEGER);
112  tempContent.writeInt(logic->getCurrentPhaseIndex());
113  ++cnt;
114  // phase number
115  int phaseNo = logic->getPhaseNumber();
116  tempContent.writeUnsignedByte(TYPE_INTEGER);
117  tempContent.writeInt(phaseNo);
118  ++cnt;
119  for (int j = 0; j < phaseNo; ++j) {
120  MSPhaseDefinition phase = logic->getPhase(j);
121  tempContent.writeUnsignedByte(TYPE_INTEGER);
122  tempContent.writeInt((int)phase.duration);
123  ++cnt;
124  tempContent.writeUnsignedByte(TYPE_INTEGER);
125  tempContent.writeInt((int)phase.minDuration);
126  ++cnt; // not implemented
127  tempContent.writeUnsignedByte(TYPE_INTEGER);
128  tempContent.writeInt((int)phase.maxDuration);
129  ++cnt; // not implemented
130  const std::string& state = phase.getState();
131  //int linkNo = (int)(vars.getActive()->getLinks().size());
132  tempContent.writeUnsignedByte(TYPE_STRING);
133  tempContent.writeString(state);
134  ++cnt;
135  }
136  }
137  tempMsg.writeInt((int) cnt);
138  tempMsg.writeStorage(tempContent);
139  }
140  break;
141  case TL_CONTROLLED_LANES: {
144  std::vector<std::string> laneIDs;
145  for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
146  const MSTrafficLightLogic::LaneVector& llanes = (*i);
147  for (MSTrafficLightLogic::LaneVector::const_iterator j = llanes.begin(); j != llanes.end(); ++j) {
148  laneIDs.push_back((*j)->getID());
149  }
150  }
151  tempMsg.writeStringList(laneIDs);
152  }
153  break;
154  case TL_CONTROLLED_LINKS: {
157  //
159  tcpip::Storage tempContent;
160  int cnt = 0;
161  tempContent.writeUnsignedByte(TYPE_INTEGER);
162  int no = (int) lanes.size();
163  tempContent.writeInt((int) no);
164  for (int i = 0; i < no; ++i) {
165  const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
166  const MSTrafficLightLogic::LinkVector& llinks = links[i];
167  // number of links controlled by this signal (signal i)
168  tempContent.writeUnsignedByte(TYPE_INTEGER);
169  int no2 = (int) llanes.size();
170  tempContent.writeInt((int) no2);
171  ++cnt;
172  for (int j = 0; j < no2; ++j) {
173  MSLink* link = llinks[j];
174  std::vector<std::string> def;
175  // incoming lane
176  def.push_back(llanes[j]->getID());
177  // approached non-internal lane (if any)
178  def.push_back(link->getLane() != 0 ? link->getLane()->getID() : "");
179  // approached "via", internal lane (if any)
180  def.push_back(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
181  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
182  tempContent.writeStringList(def);
183  ++cnt;
184  }
185  }
186  tempMsg.writeInt((int) cnt);
187  tempMsg.writeStorage(tempContent);
188  }
189  break;
190  case TL_CURRENT_PHASE:
192  tempMsg.writeInt(vars.getActive()->getCurrentPhaseIndex());
193  break;
194  case TL_CURRENT_PROGRAM:
196  tempMsg.writeString(vars.getActive()->getProgramID());
197  break;
198  case TL_PHASE_DURATION:
200  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseDef().duration);
201  break;
202  case TL_NEXT_SWITCH:
204  tempMsg.writeInt((int) vars.getActive()->getNextSwitchTime());
205  break;
206  case VAR_PARAMETER: {
207  std::string paramName = "";
208  if (!server.readTypeCheckingString(inputStorage, paramName)) {
209  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Retrieval of a parameter requires its name.", outputStorage);
210  }
212  tempMsg.writeString(vars.getActive()->getParameter(paramName, ""));
213  }
214  break;
216  }
217  break;
218  case TL_EXTERNAL_STATE: {
219  MSTrafficLightLogic* tls = vars.getActive();
220  const std::string& state = tls->getCurrentPhaseDef().getState();
221  const std::map<std::string, std::string>& params = tls->getMap();
222  int num = 0;
223  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
224  if ("connection:" == (*i).first.substr(0, 11)) {
225  ++num;
226  }
227  }
228 
231  tempMsg.writeInt(num * 2);
232  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
233  if ("connection:" != (*i).first.substr(0, 11)) {
234  continue;
235  }
237  tempMsg.writeString((*i).second); // foreign id
238  std::string connection = (*i).first.substr(11);
239  std::string from, to;
240  const std::string::size_type b = connection.find("->");
241  if (b == std::string::npos) {
242  from = connection;
243  } else {
244  from = connection.substr(0, b);
245  to = connection.substr(b + 2);
246  }
247  bool denotesEdge = from.find("_") == std::string::npos;
248  MSLane* fromLane = 0;
250  MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin();
251  for (; j != lanes.end() && fromLane == 0;) {
252  for (MSTrafficLightLogic::LaneVector::const_iterator k = (*j).begin(); k != (*j).end() && fromLane == 0;) {
253  if (denotesEdge && (*k)->getEdge().getID() == from) {
254  fromLane = *k;
255  } else if (!denotesEdge && (*k)->getID() == from) {
256  fromLane = *k;
257  }
258  if (fromLane == 0) {
259  ++k;
260  }
261  }
262  if (fromLane == 0) {
263  ++j;
264  }
265  }
266  if (fromLane == 0) {
267  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Could not find edge or lane '" + from + "' in traffic light '" + id + "'.", outputStorage);
268  }
269  int pos = (int)std::distance(lanes.begin(), j);
270  tempMsg.writeUnsignedByte(TYPE_UBYTE);
271  tempMsg.writeUnsignedByte(state[pos]); // state
272  }
273  }
274  break;
275  default:
276  break;
277  }
278  }
279  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, "", outputStorage);
280  server.writeResponseWithLength(outputStorage, tempMsg);
281  return true;
282 }
283 
284 
285 bool
287  tcpip::Storage& outputStorage) {
288  std::string warning = ""; // additional description for response
289  // variable
290  int variable = inputStorage.readUnsignedByte();
291  if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM && variable != TL_PHASE_DURATION
292  && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG
293  && variable != VAR_PARAMETER) {
294  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "Change TLS State: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
295  }
296  std::string id = inputStorage.readString();
297  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
298  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "Traffic light '" + id + "' is not known", outputStorage);
299  }
302  MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(id);
303  switch (variable) {
304  case TL_PHASE_INDEX: {
305  int index = 0;
306  if (!server.readTypeCheckingInt(inputStorage, index)) {
307  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase index must be given as an integer.", outputStorage);
308  }
309  if (index < 0 || vars.getActive()->getPhaseNumber() <= index) {
310  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase index " + toString(index) + " is not in the allowed range [0,"
311  + toString(vars.getActive()->getPhaseNumber() - 1) + "].", outputStorage);
312  }
313  const SUMOTime duration = vars.getActive()->getPhase(index).duration;
314  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
315  }
316  break;
317  case TL_PROGRAM: {
318  std::string subID;
319  if (!server.readTypeCheckingString(inputStorage, subID)) {
320  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The program must be given as a string.", outputStorage);
321  }
322  try {
323  vars.switchTo(tlsControl, subID);
324  } catch (ProcessError& e) {
325  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, e.what(), outputStorage);
326  }
327  }
328  break;
329  case TL_PHASE_DURATION: {
330  int duration = 0;
331  if (!server.readTypeCheckingInt(inputStorage, duration)) {
332  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase duration must be given as an integer.", outputStorage);
333  }
334  int index = vars.getActive()->getCurrentPhaseIndex();
335  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
336  }
337  break;
339  std::string state;
340  if (!server.readTypeCheckingString(inputStorage, state)) {
341  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase must be given as a string.", outputStorage);
342  }
343  vars.setStateInstantiatingOnline(tlsControl, state);
344  }
345  break;
347  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
348  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a new program.", outputStorage);
349  }
350  int type = 0, index = 0, phaseNo = 0;
351  //read itemNo
352  inputStorage.readInt();
353  std::string subid;
354  if (!server.readTypeCheckingString(inputStorage, subid)) {
355  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 1. parameter (subid) must be a string.", outputStorage);
356  }
357  if (!server.readTypeCheckingInt(inputStorage, type)) {
358  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 2. parameter (type) must be an int.", outputStorage);
359  }
360  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
361  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 3. parameter (subparams) must be a compound object.", outputStorage);
362  }
363  inputStorage.readInt();
364  if (!server.readTypeCheckingInt(inputStorage, index)) {
365  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4. parameter (index) must be an int.", outputStorage);
366  }
367  if (!server.readTypeCheckingInt(inputStorage, phaseNo)) {
368  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 5. parameter (phase number) must be an int.", outputStorage);
369  }
370  // make sure index and phaseNo are consistent
371  if (index >= phaseNo) {
372  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4/5. parameter (index) must be less than parameter (phase number).", outputStorage);
373  }
374 
375  std::vector<MSPhaseDefinition*> phases;
376  for (int j = 0; j < phaseNo; ++j) {
377  int duration = 0, minDuration = 0, maxDuration = 0;
378  if (!server.readTypeCheckingInt(inputStorage, duration)) {
379  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.1. parameter (duration) must be an int.", outputStorage);
380  }
381  if (!server.readTypeCheckingInt(inputStorage, minDuration)) {
382  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.2. parameter (min duration) must be an int.", outputStorage);
383  }
384  if (!server.readTypeCheckingInt(inputStorage, maxDuration)) {
385  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.3. parameter (max duration) must be an int.", outputStorage);
386  }
387  std::string state;
388  if (!server.readTypeCheckingString(inputStorage, state)) {
389  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.4. parameter (phase) must be a string.", outputStorage);
390  }
391  MSPhaseDefinition* phase = new MSPhaseDefinition(duration, minDuration, maxDuration, state);
392  phases.push_back(phase);
393  }
394  if (vars.getLogic(subid) == 0) {
395  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, subid, phases, index, 0, std::map<std::string, std::string>());
396  vars.addLogic(subid, logic, true, true);
397  } else {
398  static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(subid))->setPhases(phases, index);
399  }
400  }
401  break;
402  case VAR_PARAMETER: {
403  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
404  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a parameter.", outputStorage);
405  }
406  //readt itemNo
407  inputStorage.readInt();
408  std::string name;
409  if (!server.readTypeCheckingString(inputStorage, name)) {
410  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The name of the parameter must be given as a string.", outputStorage);
411  }
412  std::string value;
413  if (!server.readTypeCheckingString(inputStorage, value)) {
414  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The value of the parameter must be given as a string.", outputStorage);
415  }
416  vars.getActive()->addParameter(name, value);
417  }
418  break;
419  default:
420  break;
421  }
422  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
423  return true;
424 }
425 
426 #endif
427 
428 
429 /****************************************************************************/
430 
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
#define TL_NEXT_SWITCH
const std::string & getState() const
Returns the state within this phase.
#define CMD_GET_TL_VARIABLE
Storage for all programs of a single tls.
#define TYPE_COMPOUND
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration)=0
Changes the current phase and her duration.
#define TYPE_UBYTE
#define RTYPE_OK
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
virtual const MSPhaseDefinition & getPhase(int givenstep) const =0
Returns the definition of the phase from the given position within the plan.
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:158
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
#define TYPE_STRINGLIST
#define RESPONSE_GET_TL_VARIABLE
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
virtual void writeUnsignedByte(int)
#define TL_CONTROLLED_JUNCTIONS
#define TL_CURRENT_PHASE
bool writeErrorStatusCmd(int commandId, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage with status = RTYPE_ERR.
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
virtual void writeInt(int)
A fixed traffic light logic.
#define TYPE_STRING
virtual int readUnsignedByte()
#define TL_PHASE_DURATION
#define TL_CURRENT_PROGRAM
#define CMD_SET_TL_VARIABLE
A class that stores and controls tls and switching of their programs.
SUMOTime duration
The duration of the phase.
std::vector< MSTrafficLightLogic * > getAllLogics() const
bool addLogic(const std::string &programID, MSTrafficLightLogic *logic, bool netWasLoaded, bool isNewDefault=true)
Adds a logic (program)
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
virtual int getPhaseNumber() const =0
Returns the number of phases.
virtual int readInt()
#define TL_COMPLETE_PROGRAM_RYG
const std::string & getProgramID() const
Returns this tl-logic&#39;s id.
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:383
#define TL_COMPLETE_DEFINITION_RYG
virtual void writeStringList(const std::vector< std::string > &s)
#define TL_EXTERNAL_STATE
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:257
virtual std::string readString()
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:74
void setStateInstantiatingOnline(MSTLLogicControl &tlc, const std::string &state)
virtual void writeStorage(tcpip::Storage &store)
#define TL_CONTROLLED_LINKS
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
bool knows(const std::string &id) const
Returns the information whether the named tls is stored.
#define TL_RED_YELLOW_GREEN_STATE
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
const std::string & getParameter(const std::string &key, const std::string &defaultValue) const
Returns the value for a given key.
void switchTo(MSTLLogicControl &tlc, const std::string &programID)
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
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)
SUMOTime maxDuration
The maximum duration of the phase.
#define TL_PROGRAM
std::string toHex(const T i, std::streamsize numDigits=0)
Definition: ToString.h:66
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
const std::map< std::string, std::string > & getMap() const
Returns the inner key/value map.
SUMOTime minDuration
The minimum duration of the phase.
The parent class for traffic light logics.
static bool processSet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a set value command (Command 0xc2: Change Traffic Lights State)
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
long long int SUMOTime
Definition: TraCIDefs.h:52
#define TL_CONTROLLED_LANES
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
#define VAR_PARAMETER
#define ID_COUNT
MSTrafficLightLogic * getActive() const
std::vector< std::string > getAllTLIds() const
MSTrafficLightLogic * getLogic(const std::string &programID) const
#define TYPE_INTEGER
#define ID_LIST
#define TL_PHASE_INDEX
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
The definition of a single phase of a tls logic.
static bool processGet(TraCIServer &server, tcpip::Storage &inputStorage, tcpip::Storage &outputStorage)
Processes a get value command (Command 0xa2: Get Traffic Lights Variable)