SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NLJunctionControlBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Builder of microsim-junctions and tls
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 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 #include <map>
35 #include <string>
36 #include <vector>
37 #include <list>
38 #include <algorithm>
47 #include <microsim/MSGlobals.h>
53 #include <utils/common/ToString.h>
54 #include <netbuild/NBNode.h>
55 #include "NLBuilder.h"
57 
58 #ifdef CHECK_MEMORY_LEAKS
59 #include <foreign/nvwa/debug_new.h>
60 #endif // CHECK_MEMORY_LEAKS
61 
62 
63 // ===========================================================================
64 // static members
65 // ===========================================================================
67 
68 // ===========================================================================
69 // method definitions
70 // ===========================================================================
72  : myNet(net), myDetectorBuilder(db), myOffset(0), myJunctions(0) {
75 }
76 
77 
79  delete myLogicControl;
80  delete myJunctions;
81 }
82 
83 
84 void
86  const std::string& key,
87  const SumoXMLNodeType type,
88  SUMOReal x, SUMOReal y,
89  const PositionVector& shape,
90  const std::vector<MSLane*>& incomingLanes,
91  const std::vector<MSLane*>& internalLanes) throw(InvalidArgument) {
92 #ifdef HAVE_INTERNAL_LANES
93  myActiveInternalLanes = internalLanes;
94 #else
95  UNUSED_PARAMETER(internalLanes);
96 #endif
97  myActiveIncomingLanes = incomingLanes;
98  myActiveID = id;
99  myActiveKey = key;
100  myType = type;
101  myPosition.set(x, y);
102  myShape = shape;
103 }
104 
105 
106 void
108  if (myJunctions == 0) {
109  throw ProcessError("Information about the number of nodes was missing.");
110  }
111  MSJunction* junction = 0;
112  switch (myType) {
113  case NODETYPE_NOJUNCTION:
114  case NODETYPE_DEAD_END:
116  case NODETYPE_DISTRICT:
117  junction = buildNoLogicJunction();
118  break;
122  junction = buildLogicJunction();
123  break;
124  case NODETYPE_INTERNAL:
125 #ifdef HAVE_INTERNAL_LANES
127  junction = buildInternalJunction();
128  }
129 #endif
130  break;
131  default:
132  throw InvalidArgument("False junction logic type.");
133  }
134  if (junction != 0) {
135  if (!myJunctions->add(myActiveID, junction)) {
136  throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
137  }
138  }
139 }
140 
141 
145  myJunctions = 0;
146  return js;
147 }
148 
149 
150 MSJunction*
153 #ifdef HAVE_INTERNAL_LANES
154  , myActiveInternalLanes
155 #endif
156  );
157 }
158 
159 
160 MSJunction*
163  // build the junction
165 #ifdef HAVE_INTERNAL_LANES
166  myActiveInternalLanes,
167 #endif
168  jtype);
169 }
170 
171 
172 #ifdef HAVE_INTERNAL_LANES
173 MSJunction*
174 NLJunctionControlBuilder::buildInternalJunction() {
175  // build the junction
177  myActiveInternalLanes);
178 }
179 #endif
180 
181 
184  // get and check the junction logic
185  if (myLogics.find(myActiveID) == myLogics.end()) {
186  throw InvalidArgument("Missing junction logic '" + myActiveID + "'.");
187  }
188  return myLogics[myActiveID];
189 }
190 
191 
193 NLJunctionControlBuilder::getTLLogic(const std::string& id) const throw(InvalidArgument) {
194  return getTLLogicControlToUse().get(id);
195 }
196 
197 
198 void
200  if (myActiveProgram == "off") {
201  if (myAbsDuration > 0) {
202  throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
203  }
206  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
207  }
208  return;
209  }
210  if (myAbsDuration == 0) {
211  throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
212  }
213  // compute the initial step and first switch time of the tls-logic
214  // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
215  // @note The implementation of % for negative values is implementation defined in ISO1998
216  SUMOTime offset; // the time to run the traffic light in advance
217  if (myOffset >= 0) {
219  } else {
221  }
222  unsigned int step = 0;
223  SUMOTime firstEventOffset = 0;
224  MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
225  while (offset >= (*i)->duration) {
226  step++;
227  offset -= (*i)->duration;
228  ++i;
229  }
230  firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
231 
232  //
233  if (myActiveProgram == "") {
234  myActiveProgram = "default";
235  }
236  MSTrafficLightLogic* tlLogic = 0;
237  // build the tls-logic in dependance to its type
238  switch (myLogicType) {
239  case TLTYPE_ACTUATED:
242  myActivePhases, step, firstEventOffset, myAdditionalParameter);
243  break;
244  case TLTYPE_AGENT:
247  myActivePhases, step, firstEventOffset, myAdditionalParameter);
248  break;
249  case TLTYPE_STATIC:
250  tlLogic =
253  myActivePhases, step, firstEventOffset);
255  }
256  TLInitInfo ii;
257  ii.logic = tlLogic;
259  myJunctions2PostLoadInit.push_back(ii);
260  myActivePhases.clear();
261  if (tlLogic != 0) {
262  try {
263  if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
264  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
265  }
267  tlLogic->init(myDetectorBuilder);
268  } catch (InvalidArgument&) {
269  delete tlLogic;
270  throw;
271  }
272  }
273 }
274 
275 
276 void
278  myActiveKey = id;
279  myActiveProgram = "";
280  myActiveLogic.clear();
281  myActiveFoes.clear();
282  myActiveConts.reset();
283  myRequestSize = NO_REQUEST_SIZE; // seems not to be used
285  myCurrentHasError = false;
286 }
287 
288 
289 void
291  const std::string& response,
292  const std::string& foes,
293  bool cont) throw(InvalidArgument) {
294  if (myCurrentHasError) {
295  // had an error
296  return;
297  }
298  if (request > 63) {
299  // bad request
300  myCurrentHasError = true;
301  throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
302  }
303  if (myRequestSize == NO_REQUEST_SIZE) {
304  // initialize
305  myRequestSize = (int)response.size();
306  }
307  if (static_cast<int>(response.size()) != myRequestSize) {
308  myCurrentHasError = true;
309  throw InvalidArgument("Invalid response size " + toString(response.size()) +
310  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
311  }
312  if (static_cast<int>(foes.size()) != myRequestSize) {
313  myCurrentHasError = true;
314  throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
315  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
316  }
317  // assert that the logicitems come ordered by their request index
318  assert(myActiveLogic.size() == (size_t) request);
319  assert(myActiveFoes.size() == (size_t) request);
320  // add the read response for the given request index
321  myActiveLogic.push_back(std::bitset<64>(response));
322  // add the read junction-internal foes for the given request index
323  myActiveFoes.push_back(std::bitset<64>(foes));
324  // add whether the vehicle may drive a little bit further
325  myActiveConts.set(request, cont);
326  // increse number of set information
327  myRequestItemNumber++;
328 }
329 
330 
331 void
332 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
333  TrafficLightType type, SUMOTime offset) {
334  myActiveKey = id;
335  myActiveProgram = programID;
336  myActivePhases.clear();
337  myAbsDuration = 0;
339  myLogicType = type;
340  myOffset = offset;
341  myAdditionalParameter.clear();
342 }
343 
344 
345 void
346 NLJunctionControlBuilder::addPhase(SUMOTime duration, const std::string& state,
347  int minDuration, int maxDuration) {
348  // build and add the phase definition to the list
349  myActivePhases.push_back(new MSPhaseDefinition(duration, minDuration, maxDuration, state));
350  // add phase duration to the absolute duration
351  myAbsDuration += duration;
352 }
353 
354 
355 void
358  // We have a legacy network. junction element did not contain logicitems; read the logic later
359  return;
360  }
361  if (myCurrentHasError) {
362  // had an error before...
363  return;
364  }
366  throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
367  }
368  if (myLogics.count(myActiveKey) > 0) {
369  throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice.");
370  }
374  myActiveConts);
375  myLogics[myActiveKey] = logic;
376 }
377 
378 
382  throw ProcessError("Traffic lights could not be built.");
383  }
385  myLogicControl = 0;
386  return ret;
387 }
388 
389 
390 void
391 NLJunctionControlBuilder::addParam(const std::string& key,
392  const std::string& value) {
393  myAdditionalParameter[key] = value;
394 }
395 
396 
399  if (myLogicControl != 0) {
400  return *myLogicControl;
401  }
402  return myNet.getTLSControl();
403 }
404 
405 
406 const std::string&
408  return myActiveKey;
409 }
410 
411 
412 const std::string&
414  return myActiveProgram;
415 }
416 
417 
418 /****************************************************************************/