SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TraCIServerAPI_TLS.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // APIs for getting/setting traffic light values via TraCI
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
12 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #ifndef NO_TRACI
34 
35 #include "TraCIConstants.h"
37 #include <microsim/MSLane.h>
38 #include "TraCIServerAPI_TLS.h"
39 
40 #ifdef CHECK_MEMORY_LEAKS
41 #include <foreign/nvwa/debug_new.h>
42 #endif // CHECK_MEMORY_LEAKS
43 
44 
45 // ===========================================================================
46 // used namespaces
47 // ===========================================================================
48 using namespace traci;
49 
50 
51 // ===========================================================================
52 // method definitions
53 // ===========================================================================
54 bool
56  tcpip::Storage& outputStorage) {
57  // variable & id
58  int variable = inputStorage.readUnsignedByte();
59  std::string id = inputStorage.readString();
60  // check variable
61  if (variable != ID_LIST && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_DEFINITION_RYG
62  && variable != TL_CONTROLLED_LANES && variable != TL_CONTROLLED_LINKS
63  && variable != TL_CURRENT_PHASE && variable != TL_CURRENT_PROGRAM
64  && variable != TL_NEXT_SWITCH && variable != TL_PHASE_DURATION && variable != ID_COUNT) {
65  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Get TLS Variable: unsupported variable specified", outputStorage);
66  return false;
67  }
68  // begin response building
69  tcpip::Storage tempMsg;
70  // response-code, variableID, objectID
72  tempMsg.writeUnsignedByte(variable);
73  tempMsg.writeString(id);
74  if (variable == ID_LIST) {
75  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
77  tempMsg.writeStringList(ids);
78  } else if (variable == ID_COUNT) {
79  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
81  tempMsg.writeInt((int) ids.size());
82  } else {
83  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
84  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
85  return false;
86  }
88  switch (variable) {
89  case ID_LIST:
90  break;
93  std::string state = vars.getActive()->getCurrentPhaseDef().getState();
94  tempMsg.writeString(state);
95  }
96  break;
98  std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
100  tcpip::Storage tempContent;
101  unsigned int cnt = 0;
102  tempContent.writeUnsignedByte(TYPE_INTEGER);
103  tempContent.writeInt((int) logics.size());
104  ++cnt;
105  for (unsigned int i = 0; i < logics.size(); ++i) {
106  MSTrafficLightLogic* logic = logics[i];
107  tempContent.writeUnsignedByte(TYPE_STRING);
108  tempContent.writeString(logic->getProgramID());
109  ++cnt;
110  // type (always 0 by now)
111  tempContent.writeUnsignedByte(TYPE_INTEGER);
112  tempContent.writeInt(0);
113  ++cnt;
114  // subparameter (always 0 by now)
115  tempContent.writeUnsignedByte(TYPE_COMPOUND);
116  tempContent.writeInt(0);
117  ++cnt;
118  // (current) phase index
119  tempContent.writeUnsignedByte(TYPE_INTEGER);
120  tempContent.writeInt((int) logic->getCurrentPhaseIndex());
121  ++cnt;
122  // phase number
123  unsigned int phaseNo = logic->getPhaseNumber();
124  tempContent.writeUnsignedByte(TYPE_INTEGER);
125  tempContent.writeInt((int) phaseNo);
126  ++cnt;
127  for (unsigned int j = 0; j < phaseNo; ++j) {
128  MSPhaseDefinition phase = logic->getPhase(j);
129  tempContent.writeUnsignedByte(TYPE_INTEGER);
130  tempContent.writeInt(phase.duration);
131  ++cnt;
132  tempContent.writeUnsignedByte(TYPE_INTEGER);
133  tempContent.writeInt(phase.minDuration);
134  ++cnt; // not implemented
135  tempContent.writeUnsignedByte(TYPE_INTEGER);
136  tempContent.writeInt(phase.maxDuration);
137  ++cnt; // not implemented
138  const std::string& state = phase.getState();
139  //unsigned int linkNo = (unsigned int)(vars.getActive()->getLinks().size());
140  tempContent.writeUnsignedByte(TYPE_STRING);
141  tempContent.writeString(state);
142  ++cnt;
143  }
144  }
145  tempMsg.writeInt((int) cnt);
146  tempMsg.writeStorage(tempContent);
147  }
148  break;
149  case TL_CONTROLLED_LANES: {
152  std::vector<std::string> laneIDs;
153  for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
154  const MSTrafficLightLogic::LaneVector& llanes = (*i);
155  for (MSTrafficLightLogic::LaneVector::const_iterator j = llanes.begin(); j != llanes.end(); ++j) {
156  laneIDs.push_back((*j)->getID());
157  }
158  }
159  tempMsg.writeStringList(laneIDs);
160  }
161  break;
162  case TL_CONTROLLED_LINKS: {
165  //
167  tcpip::Storage tempContent;
168  unsigned int cnt = 0;
169  tempContent.writeUnsignedByte(TYPE_INTEGER);
170  unsigned int no = (unsigned int) lanes.size();
171  tempContent.writeInt((int) no);
172  for (unsigned int i = 0; i < no; ++i) {
173  const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
174  const MSTrafficLightLogic::LinkVector& llinks = links[i];
175  // number of links controlled by this signal (signal i)
176  tempContent.writeUnsignedByte(TYPE_INTEGER);
177  unsigned int no2 = (unsigned int) llanes.size();
178  tempContent.writeInt((int) no2);
179  ++cnt;
180  for (unsigned int j = 0; j < no2; ++j) {
181  MSLink* link = llinks[j];
182  std::vector<std::string> def;
183  // incoming lane
184  def.push_back(llanes[j]->getID());
185  // approached non-internal lane (if any)
186  def.push_back(link->getLane() != 0 ? link->getLane()->getID() : "");
187  // approached "via", internal lane (if any)
188 #ifdef HAVE_INTERNAL_LANES
189  def.push_back(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
190 #else
191  def.push_back("");
192 #endif
193  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
194  tempContent.writeStringList(def);
195  ++cnt;
196  }
197  }
198  tempMsg.writeInt((int) cnt);
199  tempMsg.writeStorage(tempContent);
200  }
201  break;
202  case TL_CURRENT_PHASE:
204  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseIndex());
205  break;
206  case TL_CURRENT_PROGRAM:
208  tempMsg.writeString(vars.getActive()->getProgramID());
209  break;
210  case TL_PHASE_DURATION:
212  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseDef().duration);
213  break;
214  case TL_NEXT_SWITCH:
216  tempMsg.writeInt((int) vars.getActive()->getNextSwitchTime());
217  break;
219  }
220  break;
221  default:
222  break;
223  }
224  }
225  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, "", outputStorage);
226  server.writeResponseWithLength(outputStorage, tempMsg);
227  return true;
228 }
229 
230 
231 bool
233  tcpip::Storage& outputStorage) {
234  std::string warning = ""; // additional description for response
235  // variable
236  int variable = inputStorage.readUnsignedByte();
237  if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM
238  && variable != TL_PHASE_DURATION && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG) {
239  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Change TLS State: unsupported variable specified", outputStorage);
240  return false;
241  }
242  std::string id = inputStorage.readString();
243  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
244  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
245  return false;
246  }
249  MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(id);
250  int valueDataType = inputStorage.readUnsignedByte();
251  switch (variable) {
252  case TL_PHASE_INDEX: {
253  if (valueDataType != TYPE_INTEGER) {
254  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index must be given as an integer.", outputStorage);
255  return false;
256  }
257  int index = inputStorage.readInt();
258  if (index < 0 || vars.getActive()->getPhaseNumber() <= (unsigned int)index) {
259  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index is not in the allowed range.", outputStorage);
260  return false;
261  }
262  int duration = vars.getActive()->getPhase(index).duration;
263  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
264  }
265  break;
266  case TL_PROGRAM: {
267  if (valueDataType != TYPE_STRING) {
268  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The program must be given as a string.", outputStorage);
269  return false;
270  }
271  std::string subID = inputStorage.readString();
272  try {
273  vars.switchTo(tlsControl, subID);
274  } catch (ProcessError& e) {
275  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, e.what(), outputStorage);
276  return false;
277  }
278  }
279  break;
280  case TL_PHASE_DURATION: {
281  if (valueDataType != TYPE_INTEGER) {
282  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase duration must be given as an integer.", outputStorage);
283  return false;
284  }
285  int duration = inputStorage.readInt();
286  int index = vars.getActive()->getCurrentPhaseIndex();
287  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
288  }
289  break;
291  if (valueDataType != TYPE_STRING) {
292  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase must be given as a string.", outputStorage);
293  return false;
294  }
295  // build only once...
296  std::string state = inputStorage.readString();
297  if (vars.getLogic("online") == 0) {
298  MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
299  std::vector<MSPhaseDefinition*> phases;
300  phases.push_back(phase);
301  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, "online", phases, 0, cTime + DELTA_T);
302  vars.addLogic("online", logic, true, true);
303  } else {
304  MSPhaseDefinition nphase(DELTA_T, state);
305  *(static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic("online"))->getPhases()[0]) = nphase;
306  }
307  // @note: this assumes logic "online" is still active
308  vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
309  vars.executeOnSwitchActions();
310  }
311  break;
313  if (valueDataType != TYPE_COMPOUND) {
314  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "A compound object is needed for setting a new program.", outputStorage);
315  return false;
316  }
317  //read itemNo
318  inputStorage.readInt();
319  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
320  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 1. parameter (subid) must be a string.", outputStorage);
321  return false;
322  }
323  std::string subid = inputStorage.readString();
324  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
325  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 2. parameter (type) must be an int.", outputStorage);
326  return false;
327  }
328  //read type
329  inputStorage.readInt();
330  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
331  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 3. parameter (subparams) must be a compound object.", outputStorage);
332  return false;
333  }
334  //read sublength
335  inputStorage.readInt();
336  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
337  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4. parameter (index) must be an int.", outputStorage);
338  return false;
339  }
340  int index = inputStorage.readInt();
341  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
342  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 5. parameter (phase number) must be an int.", outputStorage);
343  return false;
344  }
345  int phaseNo = inputStorage.readInt();
346  // make sure index and phaseNo are consistent
347  if (index >= phaseNo) {
348  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4/5. parameter (index) must be less than parameter (phase number).", outputStorage);
349  return false;
350  }
351 
352  std::vector<MSPhaseDefinition*> phases;
353  for (int j = 0; j < phaseNo; ++j) {
354  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
355  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.1. parameter (duration) must be an int.", outputStorage);
356  return false;
357  }
358  int duration = inputStorage.readInt();
359  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
360  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.2. parameter (min duration) must be an int.", outputStorage);
361  return false;
362  }
363  int minDuration = inputStorage.readInt();
364  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
365  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.3. parameter (max duration) must be an int.", outputStorage);
366  return false;
367  }
368  int maxDuration = inputStorage.readInt();
369  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
370  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.4. parameter (phase) must be a string.", outputStorage);
371  return false;
372  }
373  std::string state = inputStorage.readString();
374  MSPhaseDefinition* phase = new MSPhaseDefinition(duration, minDuration, maxDuration, state);
375  phases.push_back(phase);
376  }
377  if (vars.getLogic(subid) == 0) {
378  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, subid, phases, index, 0);
379  vars.addLogic(subid, logic, true, true);
380  } else {
381  static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(subid))->setPhases(phases, index);
382  }
383  vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
384  vars.executeOnSwitchActions();
385  }
386  break;
387  default:
388  break;
389  }
390  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
391  return true;
392 }
393 
394 #endif
395 
396 
397 /****************************************************************************/
398