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-2016 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 #ifdef CHECK_MEMORY_LEAKS
44 #include <foreign/nvwa/debug_new.h>
45 #endif // CHECK_MEMORY_LEAKS
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
51 bool
53  tcpip::Storage& outputStorage) {
54  // variable & id
55  int variable = inputStorage.readUnsignedByte();
56  std::string id = inputStorage.readString();
57  // check variable
58  if (variable != ID_LIST && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_DEFINITION_RYG
59  && variable != TL_CONTROLLED_LANES && variable != TL_CONTROLLED_LINKS
60  && variable != TL_CURRENT_PHASE && variable != TL_CURRENT_PROGRAM
61  && variable != TL_NEXT_SWITCH && variable != TL_PHASE_DURATION && variable != ID_COUNT
62  && variable != VAR_PARAMETER && variable != TL_EXTERNAL_STATE) {
63  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
64  }
65  // begin response building
66  tcpip::Storage tempMsg;
67  // response-code, variableID, objectID
69  tempMsg.writeUnsignedByte(variable);
70  tempMsg.writeString(id);
71  if (variable == ID_LIST) {
72  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
74  tempMsg.writeStringList(ids);
75  } else if (variable == ID_COUNT) {
76  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
78  tempMsg.writeInt((int) ids.size());
79  } else {
80  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
81  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Traffic light '" + id + "' is not known", outputStorage);
82  }
84  switch (variable) {
85  case ID_LIST:
86  break;
89  std::string state = vars.getActive()->getCurrentPhaseDef().getState();
90  tempMsg.writeString(state);
91  }
92  break;
94  std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
96  tcpip::Storage tempContent;
97  unsigned int cnt = 0;
98  tempContent.writeUnsignedByte(TYPE_INTEGER);
99  tempContent.writeInt((int) logics.size());
100  ++cnt;
101  for (unsigned int i = 0; i < logics.size(); ++i) {
102  MSTrafficLightLogic* logic = logics[i];
103  tempContent.writeUnsignedByte(TYPE_STRING);
104  tempContent.writeString(logic->getProgramID());
105  ++cnt;
106  // type (always 0 by now)
107  tempContent.writeUnsignedByte(TYPE_INTEGER);
108  tempContent.writeInt(0);
109  ++cnt;
110  // subparameter (always 0 by now)
111  tempContent.writeUnsignedByte(TYPE_COMPOUND);
112  tempContent.writeInt(0);
113  ++cnt;
114  // (current) phase index
115  tempContent.writeUnsignedByte(TYPE_INTEGER);
116  tempContent.writeInt(logic->getCurrentPhaseIndex());
117  ++cnt;
118  // phase number
119  int phaseNo = logic->getPhaseNumber();
120  tempContent.writeUnsignedByte(TYPE_INTEGER);
121  tempContent.writeInt(phaseNo);
122  ++cnt;
123  for (int j = 0; j < phaseNo; ++j) {
124  MSPhaseDefinition phase = logic->getPhase(j);
125  tempContent.writeUnsignedByte(TYPE_INTEGER);
126  tempContent.writeInt((int)phase.duration);
127  ++cnt;
128  tempContent.writeUnsignedByte(TYPE_INTEGER);
129  tempContent.writeInt((int)phase.minDuration);
130  ++cnt; // not implemented
131  tempContent.writeUnsignedByte(TYPE_INTEGER);
132  tempContent.writeInt((int)phase.maxDuration);
133  ++cnt; // not implemented
134  const std::string& state = phase.getState();
135  //unsigned int linkNo = (unsigned int)(vars.getActive()->getLinks().size());
136  tempContent.writeUnsignedByte(TYPE_STRING);
137  tempContent.writeString(state);
138  ++cnt;
139  }
140  }
141  tempMsg.writeInt((int) cnt);
142  tempMsg.writeStorage(tempContent);
143  }
144  break;
145  case TL_CONTROLLED_LANES: {
148  std::vector<std::string> laneIDs;
149  for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
150  const MSTrafficLightLogic::LaneVector& llanes = (*i);
151  for (MSTrafficLightLogic::LaneVector::const_iterator j = llanes.begin(); j != llanes.end(); ++j) {
152  laneIDs.push_back((*j)->getID());
153  }
154  }
155  tempMsg.writeStringList(laneIDs);
156  }
157  break;
158  case TL_CONTROLLED_LINKS: {
161  //
163  tcpip::Storage tempContent;
164  unsigned int cnt = 0;
165  tempContent.writeUnsignedByte(TYPE_INTEGER);
166  unsigned int no = (unsigned int) lanes.size();
167  tempContent.writeInt((int) no);
168  for (unsigned int i = 0; i < no; ++i) {
169  const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
170  const MSTrafficLightLogic::LinkVector& llinks = links[i];
171  // number of links controlled by this signal (signal i)
172  tempContent.writeUnsignedByte(TYPE_INTEGER);
173  unsigned int no2 = (unsigned int) llanes.size();
174  tempContent.writeInt((int) no2);
175  ++cnt;
176  for (unsigned int j = 0; j < no2; ++j) {
177  MSLink* link = llinks[j];
178  std::vector<std::string> def;
179  // incoming lane
180  def.push_back(llanes[j]->getID());
181  // approached non-internal lane (if any)
182  def.push_back(link->getLane() != 0 ? link->getLane()->getID() : "");
183  // approached "via", internal lane (if any)
184 #ifdef HAVE_INTERNAL_LANES
185  def.push_back(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
186 #else
187  def.push_back("");
188 #endif
189  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
190  tempContent.writeStringList(def);
191  ++cnt;
192  }
193  }
194  tempMsg.writeInt((int) cnt);
195  tempMsg.writeStorage(tempContent);
196  }
197  break;
198  case TL_CURRENT_PHASE:
200  tempMsg.writeInt(vars.getActive()->getCurrentPhaseIndex());
201  break;
202  case TL_CURRENT_PROGRAM:
204  tempMsg.writeString(vars.getActive()->getProgramID());
205  break;
206  case TL_PHASE_DURATION:
208  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseDef().duration);
209  break;
210  case TL_NEXT_SWITCH:
212  tempMsg.writeInt((int) vars.getActive()->getNextSwitchTime());
213  break;
214  case VAR_PARAMETER: {
215  std::string paramName = "";
216  if (!server.readTypeCheckingString(inputStorage, paramName)) {
217  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Retrieval of a parameter requires its name.", outputStorage);
218  }
220  tempMsg.writeString(vars.getActive()->getParameter(paramName, ""));
221  }
222  break;
224  }
225  break;
226  case TL_EXTERNAL_STATE: {
227  MSTrafficLightLogic* tls = vars.getActive();
228  const std::string& state = tls->getCurrentPhaseDef().getState();
229  const std::map<std::string, std::string>& params = tls->getMap();
230  unsigned int num = 0;
231  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
232  if ("connection:" == (*i).first.substr(0, 11)) {
233  ++num;
234  }
235  }
236 
239  tempMsg.writeInt(num * 2);
240  for (std::map<std::string, std::string>::const_iterator i = params.begin(); i != params.end(); ++i) {
241  if ("connection:" != (*i).first.substr(0, 11)) {
242  continue;
243  }
245  tempMsg.writeString((*i).second); // foreign id
246  std::string connection = (*i).first.substr(11);
247  std::string from, to;
248  size_t b = connection.find("->");
249  if (b == std::string::npos) {
250  from = connection;
251  } else {
252  from = connection.substr(0, b);
253  to = connection.substr(b + 2);
254  }
255  bool denotesEdge = from.find("_") == std::string::npos;
256  MSLane* fromLane = 0;
258  MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin();
259  for (; j != lanes.end() && fromLane == 0;) {
260  for (MSTrafficLightLogic::LaneVector::const_iterator k = (*j).begin(); k != (*j).end() && fromLane == 0;) {
261  if (denotesEdge && (*k)->getEdge().getID() == from) {
262  fromLane = *k;
263  } else if (!denotesEdge && (*k)->getID() == from) {
264  fromLane = *k;
265  }
266  if (fromLane == 0) {
267  ++k;
268  }
269  }
270  if (fromLane == 0) {
271  ++j;
272  }
273  }
274  if (fromLane == 0) {
275  return server.writeErrorStatusCmd(CMD_GET_TL_VARIABLE, "Could not find edge or lane '" + from + "' in traffic light '" + id + "'.", outputStorage);
276  }
277  int pos = (int)std::distance(lanes.begin(), j);
278  tempMsg.writeUnsignedByte(TYPE_UBYTE);
279  tempMsg.writeUnsignedByte(state[pos]); // state
280  }
281  }
282  break;
283  default:
284  break;
285  }
286  }
287  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, "", outputStorage);
288  server.writeResponseWithLength(outputStorage, tempMsg);
289  return true;
290 }
291 
292 
293 bool
295  tcpip::Storage& outputStorage) {
296  std::string warning = ""; // additional description for response
297  // variable
298  int variable = inputStorage.readUnsignedByte();
299  if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM && variable != TL_PHASE_DURATION
300  && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG
301  && variable != VAR_PARAMETER) {
302  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "Change TLS State: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
303  }
304  std::string id = inputStorage.readString();
305  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
306  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "Traffic light '" + id + "' is not known", outputStorage);
307  }
310  MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(id);
311  switch (variable) {
312  case TL_PHASE_INDEX: {
313  int index = 0;
314  if (!server.readTypeCheckingInt(inputStorage, index)) {
315  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase index must be given as an integer.", outputStorage);
316  }
317  if (index < 0 || vars.getActive()->getPhaseNumber() <= index) {
318  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase index " + toString(index) + " is not in the allowed range [0,"
319  + toString(vars.getActive()->getPhaseNumber() - 1) + "].", outputStorage);
320  }
321  const SUMOTime duration = vars.getActive()->getPhase(index).duration;
322  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
323  }
324  break;
325  case TL_PROGRAM: {
326  std::string subID;
327  if (!server.readTypeCheckingString(inputStorage, subID)) {
328  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The program must be given as a string.", outputStorage);
329  }
330  try {
331  vars.switchTo(tlsControl, subID);
332  } catch (ProcessError& e) {
333  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, e.what(), outputStorage);
334  }
335  }
336  break;
337  case TL_PHASE_DURATION: {
338  int duration = 0;
339  if (!server.readTypeCheckingInt(inputStorage, duration)) {
340  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase duration must be given as an integer.", outputStorage);
341  }
342  int index = vars.getActive()->getCurrentPhaseIndex();
343  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
344  }
345  break;
347  std::string state;
348  if (!server.readTypeCheckingString(inputStorage, state)) {
349  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The phase must be given as a string.", outputStorage);
350  }
351  vars.setStateInstantiatingOnline(tlsControl, state);
352  }
353  break;
355  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
356  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a new program.", outputStorage);
357  }
358  int type = 0, index = 0, phaseNo = 0;
359  //read itemNo
360  inputStorage.readInt();
361  std::string subid;
362  if (!server.readTypeCheckingString(inputStorage, subid)) {
363  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 1. parameter (subid) must be a string.", outputStorage);
364  }
365  if (!server.readTypeCheckingInt(inputStorage, type)) {
366  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 2. parameter (type) must be an int.", outputStorage);
367  }
368  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
369  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 3. parameter (subparams) must be a compound object.", outputStorage);
370  }
371  inputStorage.readInt();
372  if (!server.readTypeCheckingInt(inputStorage, index)) {
373  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4. parameter (index) must be an int.", outputStorage);
374  }
375  if (!server.readTypeCheckingInt(inputStorage, phaseNo)) {
376  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 5. parameter (phase number) must be an int.", outputStorage);
377  }
378  // make sure index and phaseNo are consistent
379  if (index >= phaseNo) {
380  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 4/5. parameter (index) must be less than parameter (phase number).", outputStorage);
381  }
382 
383  std::vector<MSPhaseDefinition*> phases;
384  for (int j = 0; j < phaseNo; ++j) {
385  int duration = 0, minDuration = 0, maxDuration = 0;
386  if (!server.readTypeCheckingInt(inputStorage, duration)) {
387  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.1. parameter (duration) must be an int.", outputStorage);
388  }
389  if (!server.readTypeCheckingInt(inputStorage, minDuration)) {
390  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.2. parameter (min duration) must be an int.", outputStorage);
391  }
392  if (!server.readTypeCheckingInt(inputStorage, maxDuration)) {
393  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.3. parameter (max duration) must be an int.", outputStorage);
394  }
395  std::string state;
396  if (!server.readTypeCheckingString(inputStorage, state)) {
397  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "set program: 6.4. parameter (phase) must be a string.", outputStorage);
398  }
399  MSPhaseDefinition* phase = new MSPhaseDefinition(duration, minDuration, maxDuration, state);
400  phases.push_back(phase);
401  }
402  if (vars.getLogic(subid) == 0) {
403  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, subid, phases, index, 0, std::map<std::string, std::string>());
404  vars.addLogic(subid, logic, true, true);
405  } else {
406  static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(subid))->setPhases(phases, index);
407  }
408  }
409  break;
410  case VAR_PARAMETER: {
411  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
412  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "A compound object is needed for setting a parameter.", outputStorage);
413  }
414  //readt itemNo
415  inputStorage.readInt();
416  std::string name;
417  if (!server.readTypeCheckingString(inputStorage, name)) {
418  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The name of the parameter must be given as a string.", outputStorage);
419  }
420  std::string value;
421  if (!server.readTypeCheckingString(inputStorage, value)) {
422  return server.writeErrorStatusCmd(CMD_SET_TL_VARIABLE, "The value of the parameter must be given as a string.", outputStorage);
423  }
424  vars.getActive()->addParameter(name, value);
425  }
426  break;
427  default:
428  break;
429  }
430  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
431  return true;
432 }
433 
434 #endif
435 
436 
437 /****************************************************************************/
438 
virtual const MSPhaseDefinition & getCurrentPhaseDef() const =0
Returns the definition of the current phase.
#define TL_NEXT_SWITCH
long long int SUMOTime
Definition: SUMOTime.h:43
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
#define TYPE_UBYTE
#define RTYPE_OK
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:160
bool readTypeCheckingString(tcpip::Storage &inputStorage, std::string &into)
Reads the value type and a string, verifying the type.
#define TYPE_STRINGLIST
std::vector< std::string > getAllTLIds() const
#define RESPONSE_GET_TL_VARIABLE
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
const std::map< std::string, std::string > & getMap() const
Returns the inner key/value map.
virtual void writeUnsignedByte(int)
#define TL_CONTROLLED_JUNCTIONS
const std::string & getParameter(const std::string &key, const std::string &defaultValue) const
Returns the value for a given key.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
#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.
MSTrafficLightLogic * getLogic(const std::string &programID) const
virtual void writeInt(int)
A fixed traffic light logic.
#define TYPE_STRING
virtual int readUnsignedByte()
#define TL_PHASE_DURATION
#define TL_CURRENT_PROGRAM
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, unsigned int step, SUMOTime stepDuration)=0
Changes the current phase and her duration.
SUMOTime getNextSwitchTime() const
Returns the assumed next switch time.
#define CMD_SET_TL_VARIABLE
A class that stores and controls tls and switching of their programs.
std::vector< MSTrafficLightLogic * > getAllLogics() const
const std::string & getID() const
Returns the id.
Definition: Named.h:65
SUMOTime duration
The duration of the phase.
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.
virtual int getPhaseNumber() const =0
Returns the number of phases.
MSTrafficLightLogic * getActive() const
virtual int readInt()
#define TL_COMPLETE_PROGRAM_RYG
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:369
#define TL_COMPLETE_DEFINITION_RYG
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
virtual void writeStringList(const std::vector< std::string > &s)
#define TL_EXTERNAL_STATE
virtual std::string readString()
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
TraCI server used to control sumo by a remote TraCI client.
Definition: TraCIServer.h:73
void setStateInstantiatingOnline(MSTLLogicControl &tlc, const std::string &state)
bool knows(const std::string &id) const
Returns the information whether the named tls is stored.
virtual void writeStorage(tcpip::Storage &store)
#define TL_CONTROLLED_LINKS
void writeResponseWithLength(tcpip::Storage &outputStorage, tcpip::Storage &tempMsg)
const LaneVectorVector & getLaneVectors() const
Returns the list of lists of all lanes controlled by this tls.
#define TL_RED_YELLOW_GREEN_STATE
std::vector< MSLink * > LinkVector
Definition of the list of links that participate in this tl-light.
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
void switchTo(MSTLLogicControl &tlc, const std::string &programID)
std::vector< MSLane * > LaneVector
Definition of the list of links that participate in this tl-light.
std::vector< LaneVector > LaneVectorVector
Definition of a list that holds lists of links 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:64
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
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)
const std::string & getProgramID() const
Returns this tl-logic&#39;s id.
void writeStatusCmd(int commandId, int status, const std::string &description, tcpip::Storage &outputStorage)
Writes a status command to the given storage.
#define TL_CONTROLLED_LANES
#define VAR_PARAMETER
#define ID_COUNT
#define TYPE_INTEGER
#define ID_LIST
#define TL_PHASE_INDEX
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
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)