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