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-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:
121  junction = buildNoLogicJunction();
122  break;
126  junction = buildLogicJunction();
127  break;
128  case NODETYPE_INTERNAL:
129 #ifdef HAVE_INTERNAL_LANES
131  junction = buildInternalJunction();
132  }
133 #endif
134  break;
135  default:
136  throw InvalidArgument("False junction logic type.");
137  }
138  if (junction != 0) {
139  if (!myJunctions->add(myActiveID, junction)) {
140  throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
141  }
142  }
143 }
144 
145 
149  myJunctions = 0;
150  return js;
151 }
152 
153 
154 MSJunction*
157 #ifdef HAVE_INTERNAL_LANES
158  , myActiveInternalLanes
159 #endif
160  );
161 }
162 
163 
164 MSJunction*
167  // build the junction
169 #ifdef HAVE_INTERNAL_LANES
170  myActiveInternalLanes,
171 #endif
172  jtype);
173 }
174 
175 
176 #ifdef HAVE_INTERNAL_LANES
177 MSJunction*
178 NLJunctionControlBuilder::buildInternalJunction() {
179  // build the junction
181  myActiveInternalLanes);
182 }
183 #endif
184 
185 
188  // get and check the junction logic
189  if (myLogics.find(myActiveID) == myLogics.end()) {
190  throw InvalidArgument("Missing junction logic '" + myActiveID + "'.");
191  }
192  return myLogics[myActiveID];
193 }
194 
195 
197 NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
198  return getTLLogicControlToUse().get(id);
199 }
200 
201 
202 void
204  if (myActiveProgram == "off") {
205  if (myAbsDuration > 0) {
206  throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
207  }
210  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
211  }
212  return;
213  }
214  if (myAbsDuration == 0) {
215  throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
216  }
217  // compute the initial step and first switch time of the tls-logic
218  // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
219  // @note The implementation of % for negative values is implementation defined in ISO1998
220  SUMOTime offset; // the time to run the traffic light in advance
221  if (myOffset >= 0) {
223  } else {
225  }
226  unsigned int step = 0;
227  SUMOTime firstEventOffset = 0;
228  MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
229  while (offset >= (*i)->duration) {
230  step++;
231  offset -= (*i)->duration;
232  ++i;
233  }
234  firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
235 
236  //
237  if (myActiveProgram == "") {
238  myActiveProgram = "default";
239  }
240  MSTrafficLightLogic* tlLogic = 0;
241  // build the tls-logic in dependance to its type
242  switch (myLogicType) {
243  case TLTYPE_ACTUATED:
246  myActivePhases, step, firstEventOffset,
248  break;
249  case TLTYPE_AGENT:
252  myActivePhases, step, firstEventOffset,
254  break;
255  case TLTYPE_STATIC:
256  tlLogic =
259  myActivePhases, step, firstEventOffset,
261  break;
262  }
263  myActivePhases.clear();
264  if (tlLogic != 0) {
265  if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
266  if (myNetIsLoaded) {
267  tlLogic->init(myDetectorBuilder);
268  } else {
269  myLogics2PostLoadInit.push_back(tlLogic);
270  }
271  } else {
272  WRITE_ERROR("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists.");
273  delete tlLogic;
274  }
275  }
276 }
277 
278 
279 void
281  myActiveKey = id;
282  myActiveProgram = "";
283  myActiveLogic.clear();
284  myActiveFoes.clear();
285  myActiveConts.reset();
286  myRequestSize = NO_REQUEST_SIZE; // seems not to be used
288  myCurrentHasError = false;
289 }
290 
291 
292 void
294  const std::string& response,
295  const std::string& foes,
296  bool cont) {
297  if (myCurrentHasError) {
298  // had an error
299  return;
300  }
301  if (request > 63) {
302  // bad request
303  myCurrentHasError = true;
304  throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
305  }
307  // initialize
308  myRequestSize = (int)response.size();
309  }
310  if (static_cast<int>(response.size()) != myRequestSize) {
311  myCurrentHasError = true;
312  throw InvalidArgument("Invalid response size " + toString(response.size()) +
313  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
314  }
315  if (static_cast<int>(foes.size()) != myRequestSize) {
316  myCurrentHasError = true;
317  throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
318  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
319  }
320  // assert that the logicitems come ordered by their request index
321  assert(myActiveLogic.size() == (size_t) request);
322  assert(myActiveFoes.size() == (size_t) request);
323  // add the read response for the given request index
324  myActiveLogic.push_back(std::bitset<64>(response));
325  // add the read junction-internal foes for the given request index
326  myActiveFoes.push_back(std::bitset<64>(foes));
327  // add whether the vehicle may drive a little bit further
328  myActiveConts.set(request, cont);
329  // increse number of set information
331 }
332 
333 
334 void
335 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
336  TrafficLightType type, SUMOTime offset) {
337  myActiveKey = id;
338  myActiveProgram = programID;
339  myActivePhases.clear();
340  myAbsDuration = 0;
342  myLogicType = type;
343  myOffset = offset;
344  myAdditionalParameter.clear();
345 }
346 
347 
348 void
349 NLJunctionControlBuilder::addPhase(SUMOTime duration, const std::string& state,
350  int minDuration, int maxDuration) {
351  // build and add the phase definition to the list
352  myActivePhases.push_back(new MSPhaseDefinition(duration, minDuration, maxDuration, state));
353  // add phase duration to the absolute duration
354  myAbsDuration += duration;
355 }
356 
357 
358 void
361  // We have a legacy network. junction element did not contain logicitems; read the logic later
362  return;
363  }
364  if (myCurrentHasError) {
365  // had an error before...
366  return;
367  }
369  throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
370  }
371  if (myLogics.count(myActiveKey) > 0) {
372  throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice.");
373  }
377  myActiveConts);
378  myLogics[myActiveKey] = logic;
379 }
380 
381 
385  throw ProcessError("Traffic lights could not be built.");
386  }
388  myLogicControl = 0;
389  return ret;
390 }
391 
392 
393 void
394 NLJunctionControlBuilder::addParam(const std::string& key,
395  const std::string& value) {
396  myAdditionalParameter[key] = value;
397 }
398 
399 
402  if (myLogicControl != 0) {
403  return *myLogicControl;
404  }
405  return myNet.getTLSControl();
406 }
407 
408 
409 const std::string&
411  return myActiveKey;
412 }
413 
414 
415 const std::string&
417  return myActiveProgram;
418 }
419 
420 
421 void
423  for (std::vector<MSTrafficLightLogic*>::const_iterator it = myLogics2PostLoadInit.begin();
424  it != myLogics2PostLoadInit.end(); ++it) {
425  (*it)->init(myDetectorBuilder);
426  }
427  myNetIsLoaded = true;
428 }
429 
430 /****************************************************************************/