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  std::string warning = ""; // additional description for response
58  // variable & id
59  int variable = inputStorage.readUnsignedByte();
60  std::string id = inputStorage.readString();
61  // check variable
62  if (variable != ID_LIST && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_DEFINITION_RYG
63  && variable != TL_CONTROLLED_LANES && variable != TL_CONTROLLED_LINKS
64  && variable != TL_CURRENT_PHASE && variable != TL_CURRENT_PROGRAM
65  && variable != TL_NEXT_SWITCH && variable != TL_PHASE_DURATION && variable != ID_COUNT) {
66  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Get TLS Variable: unsupported variable specified", outputStorage);
67  return false;
68  }
69  // begin response building
70  tcpip::Storage tempMsg;
71  // response-code, variableID, objectID
73  tempMsg.writeUnsignedByte(variable);
74  tempMsg.writeString(id);
75  if (variable == ID_LIST) {
76  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
78  tempMsg.writeStringList(ids);
79  } else if (variable == ID_COUNT) {
80  std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
82  tempMsg.writeInt((int) ids.size());
83  } else {
84  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
85  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
86  return false;
87  }
89  switch (variable) {
90  case ID_LIST:
91  break;
94  std::string state = vars.getActive()->getCurrentPhaseDef().getState();
95  tempMsg.writeString(state);
96  }
97  break;
99  std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
101  tcpip::Storage tempContent;
102  unsigned int cnt = 0;
103  tempContent.writeUnsignedByte(TYPE_INTEGER);
104  tempContent.writeInt((int) logics.size());
105  ++cnt;
106  for (unsigned int i = 0; i < logics.size(); ++i) {
107  MSTrafficLightLogic* logic = logics[i];
108  tempContent.writeUnsignedByte(TYPE_STRING);
109  tempContent.writeString(logic->getProgramID());
110  ++cnt;
111  // type (always 0 by now)
112  tempContent.writeUnsignedByte(TYPE_INTEGER);
113  tempContent.writeInt(0);
114  ++cnt;
115  // subparameter (always 0 by now)
116  tempContent.writeUnsignedByte(TYPE_COMPOUND);
117  tempContent.writeInt(0);
118  ++cnt;
119  // (current) phase index
120  tempContent.writeUnsignedByte(TYPE_INTEGER);
121  tempContent.writeInt((int) logic->getCurrentPhaseIndex());
122  ++cnt;
123  // phase number
124  unsigned int phaseNo = logic->getPhaseNumber();
125  tempContent.writeUnsignedByte(TYPE_INTEGER);
126  tempContent.writeInt((int) phaseNo);
127  ++cnt;
128  for (unsigned int j = 0; j < phaseNo; ++j) {
129  MSPhaseDefinition phase = logic->getPhase(j);
130  tempContent.writeUnsignedByte(TYPE_INTEGER);
131  tempContent.writeInt(phase.duration);
132  ++cnt;
133  tempContent.writeUnsignedByte(TYPE_INTEGER);
134  tempContent.writeInt(phase.minDuration);
135  ++cnt; // not implemented
136  tempContent.writeUnsignedByte(TYPE_INTEGER);
137  tempContent.writeInt(phase.maxDuration);
138  ++cnt; // not implemented
139  const std::string& state = phase.getState();
140  //unsigned int linkNo = (unsigned int)(vars.getActive()->getLinks().size());
141  tempContent.writeUnsignedByte(TYPE_STRING);
142  tempContent.writeString(state);
143  ++cnt;
144  }
145  }
146  tempMsg.writeInt((int) cnt);
147  tempMsg.writeStorage(tempContent);
148  }
149  break;
150  case TL_CONTROLLED_LANES: {
153  std::vector<std::string> laneIDs;
154  for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
155  const MSTrafficLightLogic::LaneVector& llanes = (*i);
156  for (MSTrafficLightLogic::LaneVector::const_iterator j = llanes.begin(); j != llanes.end(); ++j) {
157  laneIDs.push_back((*j)->getID());
158  }
159  }
160  tempMsg.writeStringList(laneIDs);
161  }
162  break;
163  case TL_CONTROLLED_LINKS: {
166  //
168  tcpip::Storage tempContent;
169  unsigned int cnt = 0;
170  tempContent.writeUnsignedByte(TYPE_INTEGER);
171  unsigned int no = (unsigned int) lanes.size();
172  tempContent.writeInt((int) no);
173  for (unsigned int i = 0; i < no; ++i) {
174  const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
175  const MSTrafficLightLogic::LinkVector& llinks = links[i];
176  // number of links controlled by this signal (signal i)
177  tempContent.writeUnsignedByte(TYPE_INTEGER);
178  unsigned int no2 = (unsigned int) llanes.size();
179  tempContent.writeInt((int) no2);
180  ++cnt;
181  for (unsigned int j = 0; j < no2; ++j) {
182  MSLink* link = llinks[j];
183  std::vector<std::string> def;
184  // incoming lane
185  def.push_back(llanes[j]->getID());
186  // approached non-internal lane (if any)
187  def.push_back(link->getLane() != 0 ? link->getLane()->getID() : "");
188  // approached "via", internal lane (if any)
189 #ifdef HAVE_INTERNAL_LANES
190  def.push_back(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
191 #else
192  def.push_back("");
193 #endif
194  tempContent.writeUnsignedByte(TYPE_STRINGLIST);
195  tempContent.writeStringList(def);
196  ++cnt;
197  }
198  }
199  tempMsg.writeInt((int) cnt);
200  tempMsg.writeStorage(tempContent);
201  }
202  break;
203  case TL_CURRENT_PHASE:
205  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseIndex());
206  break;
207  case TL_CURRENT_PROGRAM:
209  tempMsg.writeString(vars.getActive()->getProgramID());
210  break;
211  case TL_PHASE_DURATION:
213  tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseDef().duration);
214  break;
215  case TL_NEXT_SWITCH:
217  tempMsg.writeInt((int) vars.getActive()->getNextSwitchTime());
218  break;
220  }
221  break;
222  default:
223  break;
224  }
225  }
226  server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
227  server.writeResponseWithLength(outputStorage, tempMsg);
228  return true;
229 }
230 
231 
232 bool
234  tcpip::Storage& outputStorage) {
235  std::string warning = ""; // additional description for response
236  // variable
237  int variable = inputStorage.readUnsignedByte();
238  if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM
239  && variable != TL_PHASE_DURATION && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG) {
240  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Change TLS State: unsupported variable specified", outputStorage);
241  return false;
242  }
243  std::string id = inputStorage.readString();
244  if (!MSNet::getInstance()->getTLSControl().knows(id)) {
245  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
246  return false;
247  }
250  MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(id);
251  int valueDataType = inputStorage.readUnsignedByte();
252  switch (variable) {
253  case TL_PHASE_INDEX: {
254  if (valueDataType != TYPE_INTEGER) {
255  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index must be given as an integer.", outputStorage);
256  return false;
257  }
258  int index = inputStorage.readInt();
259  if (index < 0 || vars.getActive()->getPhaseNumber() <= (unsigned int)index) {
260  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index is not in the allowed range.", outputStorage);
261  return false;
262  }
263  int duration = vars.getActive()->getPhase(index).duration;
264  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
265  }
266  break;
267  case TL_PROGRAM: {
268  if (valueDataType != TYPE_STRING) {
269  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The program must be given as a string.", outputStorage);
270  return false;
271  }
272  std::string subID = inputStorage.readString();
273  try {
274  vars.switchTo(tlsControl, subID);
275  } catch (ProcessError& e) {
276  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, e.what(), outputStorage);
277  return false;
278  }
279  }
280  break;
281  case TL_PHASE_DURATION: {
282  if (valueDataType != TYPE_INTEGER) {
283  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase duration must be given as an integer.", outputStorage);
284  return false;
285  }
286  int duration = inputStorage.readInt();
287  int index = vars.getActive()->getCurrentPhaseIndex();
288  vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
289  }
290  break;
292  if (valueDataType != TYPE_STRING) {
293  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase must be given as a string.", outputStorage);
294  return false;
295  }
296  // build only once...
297  std::string state = inputStorage.readString();
298  if (vars.getLogic("online") == 0) {
299  MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
300  std::vector<MSPhaseDefinition*> phases;
301  phases.push_back(phase);
302  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, "online", phases, 0, cTime + DELTA_T);
303  vars.addLogic("online", logic, true, true);
304  } else {
305  MSPhaseDefinition nphase(DELTA_T, state);
306  *(static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic("online"))->getPhases()[0]) = nphase;
307  }
308  // @note: this assumes logic "online" is still active
309  vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
310  vars.executeOnSwitchActions();
311  }
312  break;
314  if (valueDataType != TYPE_COMPOUND) {
315  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "A compound object is needed for setting a new program.", outputStorage);
316  return false;
317  }
318  //read itemNo
319  inputStorage.readInt();
320  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
321  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 1. parameter (subid) must be a string.", outputStorage);
322  return false;
323  }
324  std::string subid = inputStorage.readString();
325  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
326  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 2. parameter (type) must be an int.", outputStorage);
327  return false;
328  }
329  //read type
330  inputStorage.readInt();
331  if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
332  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 3. parameter (subparams) must be a compound object.", outputStorage);
333  return false;
334  }
335  //read sublength
336  inputStorage.readInt();
337  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
338  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4. parameter (index) must be an int.", outputStorage);
339  return false;
340  }
341  int index = inputStorage.readInt();
342  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
343  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 5. parameter (phase number) must be an int.", outputStorage);
344  return false;
345  }
346  int phaseNo = inputStorage.readInt();
347  // make sure index and phaseNo are consistent
348  if (index >= phaseNo) {
349  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4/5. parameter (index) must be less than parameter (phase number).", outputStorage);
350  return false;
351  }
352 
353  std::vector<MSPhaseDefinition*> phases;
354  for (int j = 0; j < phaseNo; ++j) {
355  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
356  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.1. parameter (duration) must be an int.", outputStorage);
357  return false;
358  }
359  int duration = inputStorage.readInt();
360  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
361  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.2. parameter (min duration) must be an int.", outputStorage);
362  return false;
363  }
364  int minDuration = inputStorage.readInt();
365  if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
366  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.3. parameter (max duration) must be an int.", outputStorage);
367  return false;
368  }
369  int maxDuration = inputStorage.readInt();
370  if (inputStorage.readUnsignedByte() != TYPE_STRING) {
371  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.4. parameter (phase) must be a string.", outputStorage);
372  return false;
373  }
374  std::string state = inputStorage.readString();
375  MSPhaseDefinition* phase = new MSPhaseDefinition(duration, minDuration, maxDuration, state);
376  phases.push_back(phase);
377  }
378  if (vars.getLogic(subid) == 0) {
379  MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, subid, phases, index, 0);
380  vars.addLogic(subid, logic, true, true);
381  } else {
382  static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(subid))->setPhases(phases, index);
383  }
384  vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
385  vars.executeOnSwitchActions();
386  }
387  break;
388  default:
389  break;
390  }
391  server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
392  return true;
393 }
394 
395 #endif
396 
397 
398 /****************************************************************************/
399