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