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-sim.org/
13 // Copyright (C) 2001-2013 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),
73  myDetectorBuilder(db),
74  myOffset(0),
75  myJunctions(0),
76  myNetIsLoaded(false) {
79 }
80 
81 
83  delete myLogicControl;
84  delete myJunctions;
85 }
86 
87 
88 void
90  const std::string& key,
91  const SumoXMLNodeType type,
92  SUMOReal x, SUMOReal y,
93  const PositionVector& shape,
94  const std::vector<MSLane*>& incomingLanes,
95  const std::vector<MSLane*>& internalLanes) {
96 #ifdef HAVE_INTERNAL_LANES
97  myActiveInternalLanes = internalLanes;
98 #else
99  UNUSED_PARAMETER(internalLanes);
100 #endif
101  myActiveIncomingLanes = incomingLanes;
102  myActiveID = id;
103  myActiveKey = key;
104  myType = type;
105  myPosition.set(x, y);
106  myShape = shape;
107 }
108 
109 
110 void
112  if (myJunctions == 0) {
113  throw ProcessError("Information about the number of nodes was missing.");
114  }
115  MSJunction* junction = 0;
116  switch (myType) {
117  case NODETYPE_NOJUNCTION:
118  case NODETYPE_DEAD_END:
120  case NODETYPE_DISTRICT:
122  junction = buildNoLogicJunction();
123  break;
126  case NODETYPE_PRIORITY:
129  junction = buildLogicJunction();
130  break;
131  case NODETYPE_INTERNAL:
132 #ifdef HAVE_INTERNAL_LANES
134  junction = buildInternalJunction();
135  }
136 #endif
137  break;
138  default:
139  throw InvalidArgument("False junction logic type.");
140  }
141  if (junction != 0) {
142  if (!myJunctions->add(myActiveID, junction)) {
143  throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
144  }
145  }
146 }
147 
148 
152  myJunctions = 0;
153  return js;
154 }
155 
156 
157 MSJunction*
160 #ifdef HAVE_INTERNAL_LANES
161  , myActiveInternalLanes
162 #endif
163  );
164 }
165 
166 
167 MSJunction*
170  // build the junction
172 #ifdef HAVE_INTERNAL_LANES
173  myActiveInternalLanes,
174 #endif
175  jtype);
176 }
177 
178 
179 #ifdef HAVE_INTERNAL_LANES
180 MSJunction*
181 NLJunctionControlBuilder::buildInternalJunction() {
182  // build the junction
184  myActiveInternalLanes);
185 }
186 #endif
187 
188 
191  // get and check the junction logic
192  if (myLogics.find(myActiveID) == myLogics.end()) {
193  throw InvalidArgument("Missing junction logic '" + myActiveID + "'.");
194  }
195  return myLogics[myActiveID];
196 }
197 
198 
200 NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
201  return getTLLogicControlToUse().get(id);
202 }
203 
204 
205 void
207  if (myActiveProgram == "off") {
208  if (myAbsDuration > 0) {
209  throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
210  }
213  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
214  }
215  return;
216  }
217  if (myAbsDuration == 0) {
218  throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
219  }
220  // compute the initial step and first switch time of the tls-logic
221  // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
222  // @note The implementation of % for negative values is implementation defined in ISO1998
223  SUMOTime offset; // the time to run the traffic light in advance
224  if (myOffset >= 0) {
226  } else {
228  }
229  unsigned int step = 0;
230  SUMOTime firstEventOffset = 0;
231  MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
232  while (offset >= (*i)->duration) {
233  step++;
234  offset -= (*i)->duration;
235  ++i;
236  }
237  firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
238 
239  //
240  if (myActiveProgram == "") {
241  myActiveProgram = "default";
242  }
243  MSTrafficLightLogic* tlLogic = 0;
244  // build the tls-logic in dependance to its type
245  switch (myLogicType) {
246  case TLTYPE_ACTUATED:
249  myActivePhases, step, firstEventOffset,
251  break;
252  case TLTYPE_AGENT:
255  myActivePhases, step, firstEventOffset,
257  break;
258  case TLTYPE_STATIC:
259  tlLogic =
262  myActivePhases, step, firstEventOffset,
264  break;
265  }
266  myActivePhases.clear();
267  if (tlLogic != 0) {
268  if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
269  if (myNetIsLoaded) {
270  tlLogic->init(myDetectorBuilder);
271  } else {
272  myLogics2PostLoadInit.push_back(tlLogic);
273  }
274  } else {
275  WRITE_ERROR("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
276  delete tlLogic;
277  }
278  }
279 }
280 
281 
282 void
284  myActiveKey = id;
285  myActiveProgram = "";
286  myActiveLogic.clear();
287  myActiveFoes.clear();
288  myActiveConts.reset();
289  myRequestSize = NO_REQUEST_SIZE; // seems not to be used
291  myCurrentHasError = false;
292 }
293 
294 
295 void
297  const std::string& response,
298  const std::string& foes,
299  bool cont) {
300  if (myCurrentHasError) {
301  // had an error
302  return;
303  }
304  if (request > 63) {
305  // bad request
306  myCurrentHasError = true;
307  throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
308  }
310  // initialize
311  myRequestSize = (int)response.size();
312  }
313  if (static_cast<int>(response.size()) != myRequestSize) {
314  myCurrentHasError = true;
315  throw InvalidArgument("Invalid response size " + toString(response.size()) +
316  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
317  }
318  if (static_cast<int>(foes.size()) != myRequestSize) {
319  myCurrentHasError = true;
320  throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
321  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
322  }
323  // assert that the logicitems come ordered by their request index
324  assert(myActiveLogic.size() == (size_t) request);
325  assert(myActiveFoes.size() == (size_t) request);
326  // add the read response for the given request index
327  myActiveLogic.push_back(std::bitset<64>(response));
328  // add the read junction-internal foes for the given request index
329  myActiveFoes.push_back(std::bitset<64>(foes));
330  // add whether the vehicle may drive a little bit further
331  myActiveConts.set(request, cont);
332  // increse number of set information
334 }
335 
336 
337 void
338 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
339  TrafficLightType type, SUMOTime offset) {
340  myActiveKey = id;
341  myActiveProgram = programID;
342  myActivePhases.clear();
343  myAbsDuration = 0;
345  myLogicType = type;
346  myOffset = offset;
347  myAdditionalParameter.clear();
348 }
349 
350 
351 void
352 NLJunctionControlBuilder::addPhase(SUMOTime duration, const std::string& state,
353  int minDuration, int maxDuration) {
354  // build and add the phase definition to the list
355  myActivePhases.push_back(new MSPhaseDefinition(duration, minDuration, maxDuration, state));
356  // add phase duration to the absolute duration
357  myAbsDuration += duration;
358 }
359 
360 
361 void
364  // We have a legacy network. junction element did not contain logicitems; read the logic later
365  return;
366  }
367  if (myCurrentHasError) {
368  // had an error before...
369  return;
370  }
372  throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
373  }
374  if (myLogics.count(myActiveKey) > 0) {
375  throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice.");
376  }
380  myActiveConts);
381  myLogics[myActiveKey] = logic;
382 }
383 
384 
388  throw ProcessError("Traffic lights could not be built.");
389  }
391  myLogicControl = 0;
392  return ret;
393 }
394 
395 
396 void
397 NLJunctionControlBuilder::addParam(const std::string& key,
398  const std::string& value) {
399  myAdditionalParameter[key] = value;
400 }
401 
402 
405  if (myLogicControl != 0) {
406  return *myLogicControl;
407  }
408  return myNet.getTLSControl();
409 }
410 
411 
412 const std::string&
414  return myActiveKey;
415 }
416 
417 
418 const std::string&
420  return myActiveProgram;
421 }
422 
423 
424 void
426  for (std::vector<MSTrafficLightLogic*>::const_iterator it = myLogics2PostLoadInit.begin();
427  it != myLogics2PostLoadInit.end(); ++it) {
428  (*it)->init(myDetectorBuilder);
429  }
430  myNetIsLoaded = true;
431 }
432 
433 /****************************************************************************/