Eclipse SUMO - Simulation of Urban MObility
NLJunctionControlBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // Builder of microsim-junctions and tls
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <map>
26 #include <string>
27 #include <vector>
28 #include <list>
29 #include <algorithm>
32 #include <utils/common/ToString.h>
33 #include <microsim/MSGlobals.h>
34 #include <microsim/MSNet.h>
56 #include "NLBuilder.h"
59 
60 
61 // ===========================================================================
62 // static members
63 // ===========================================================================
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
70  myNet(net),
71  myDetectorBuilder(db),
72  myOffset(0),
73  myJunctions(nullptr),
74  myNetIsLoaded(false) {
77 }
78 
79 
81  delete myLogicControl;
82  delete myJunctions;
83 }
84 
85 
86 void
88  const std::string& key,
89  const SumoXMLNodeType type,
90  const Position pos,
91  const PositionVector& shape,
92  const std::vector<MSLane*>& incomingLanes,
93  const std::vector<MSLane*>& internalLanes,
94  const std::string& name) {
95  myActiveInternalLanes = internalLanes;
96  myActiveIncomingLanes = incomingLanes;
97  myActiveID = id;
98  myActiveKey = key;
99  myType = type;
100  myPosition.set(pos);
101  myShape = shape;
102  myActiveName = name;
103  myAdditionalParameter.clear();
104 }
105 
106 
107 void
108 NLJunctionControlBuilder::closeJunction(const std::string& basePath) {
109  if (myJunctions == nullptr) {
110  throw ProcessError("Information about the number of nodes was missing.");
111  }
112  MSJunction* junction = nullptr;
113  switch (myType) {
119  junction = buildNoLogicJunction();
120  break;
128  junction = buildLogicJunction();
129  break;
132  junction = buildInternalJunction();
133  }
134  break;
137  myOffset = 0;
139  myActiveProgram = "0";
141  closeTrafficLightLogic(basePath);
142  junction = buildLogicJunction();
143  break;
144  default:
145  throw InvalidArgument("False junction logic type.");
146  }
147  if (junction != nullptr) {
148  if (!myJunctions->add(myActiveID, junction)) {
149  throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists.");
150  }
151  }
153 }
154 
155 
159  myJunctions = nullptr;
160  return js;
161 }
162 
163 
164 MSJunction*
168 }
169 
170 
171 MSJunction*
174  // build the junction
178  jtype);
179 }
180 
181 
182 MSJunction*
184  // build the junction
187 }
188 
189 
192  // get and check the junction logic
193  if (myLogics.find(myActiveID) == myLogics.end()) {
194  throw InvalidArgument("Missing junction logic '" + myActiveID + "'.");
195  }
196  return myLogics[myActiveID];
197 }
198 
199 
201 NLJunctionControlBuilder::getTLLogic(const std::string& id) const {
202  return getTLLogicControlToUse().get(id);
203 }
204 
205 
206 void
208  if (myActiveProgram == "off") {
209  if (myAbsDuration > 0) {
210  throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases.");
211  }
214  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
215  }
216  return;
217  }
218  SUMOTime firstEventOffset = 0;
219  int step = 0;
220  MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin();
222  if (existing != nullptr && (existing->getLogicType() == TrafficLightType::RAIL_SIGNAL || existing->getLogicType() == TrafficLightType::RAIL_CROSSING)) {
224  return;
225  } else {
227  if (myAbsDuration == 0) {
228  if (existing == nullptr) {
229  throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0.");
230  } else {
231  // only modify the offset of an existing logic
232  myAbsDuration = existing->getDefaultCycleTime();
233  i = existing->getPhases().begin();
234  }
235  } else if (existing != nullptr) {
236  throw InvalidArgument("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
237  }
238  // compute the initial step and first switch time of the tls-logic
239  // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds
240  // @note The implementation of % for negative values is implementation defined in ISO1998
241  SUMOTime offset; // the time to run the traffic light in advance
242  if (myOffset >= 0) {
244  } else {
246  }
247  while (offset >= (*i)->duration) {
248  step++;
249  offset -= (*i)->duration;
250  ++i;
251  }
252  firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep();
253  if (existing != nullptr) {
255  myNet.getCurrentTimeStep(), step, (*i)->duration - offset);
256  // parameters that are used when initializing a logic will not take
257  // effect but parameters that are checked at runtime can be used
258  // here (i.e. device.glosa.range)
260  return;
261  }
262  }
263  }
264 
265  if (myActiveProgram == "") {
266  myActiveProgram = "default";
267  }
268  MSTrafficLightLogic* tlLogic = nullptr;
269  // build the tls-logic in dependance to its type
270  switch (myLogicType) {
272  firstEventOffset = DELTA_T; //this is needed because swarm needs to update the pheromone on the lanes at every step
274  break;
277  break;
280  break;
283  break;
286  break;
289  break;
292  break;
294  // @note it is unclear how to apply the given offset in the context
295  // of variable-length phases
298  myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
300  break;
302  tlLogic = new NEMALogic(getTLLogicControlToUse(),
304  myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
305  myAdditionalParameter, basePath);
306  break;
310  myActivePhases, step, (*i)->minDuration + myNet.getCurrentTimeStep(),
311  myAdditionalParameter, basePath);
312  break;
317  myActivePhases, step, firstEventOffset,
319  break;
321  tlLogic = new MSRailSignal(getTLLogicControlToUse(),
324  break;
326  tlLogic = new MSRailCrossing(getTLLogicControlToUse(),
329  break;
332  break;
334  throw ProcessError("Invalid traffic light type '" + toString(myLogicType) + "'");
335  }
336  myActivePhases.clear();
337  if (tlLogic != nullptr) {
338  if (getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) {
339  if (myNetIsLoaded) {
340  tlLogic->init(myDetectorBuilder);
341  } else {
342  myLogics2PostLoadInit.push_back(tlLogic);
343  }
344  } else {
345  WRITE_ERROR("Another logic with id '" + myActiveKey + "' and programID '" + myActiveProgram + "' exists.");
346  delete tlLogic;
347  }
348  }
349 }
350 
351 
352 void
354  myActiveKey = id;
355  myActiveProgram = "";
356  myActiveLogic.clear();
357  myActiveFoes.clear();
358  myActiveConts.reset();
359  myRequestSize = NO_REQUEST_SIZE; // seems not to be used
361  myCurrentHasError = false;
362 }
363 
364 
365 void
367  const std::string& response,
368  const std::string& foes,
369  bool cont) {
370  if (myCurrentHasError) {
371  // had an error
372  return;
373  }
374  if (request >= SUMO_MAX_CONNECTIONS) {
375  // bad request
376  myCurrentHasError = true;
377  throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network.");
378  }
380  // initialize
381  myRequestSize = (int)response.size();
382  }
383  if (static_cast<int>(response.size()) != myRequestSize) {
384  myCurrentHasError = true;
385  throw InvalidArgument("Invalid response size " + toString(response.size()) +
386  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
387  }
388  if (static_cast<int>(foes.size()) != myRequestSize) {
389  myCurrentHasError = true;
390  throw InvalidArgument("Invalid foes size " + toString(foes.size()) +
391  " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")");
392  }
393  // assert that the logicitems come ordered by their request index
394  assert((int)myActiveLogic.size() == request);
395  assert((int)myActiveFoes.size() == request);
396  // add the read response for the given request index
397  myActiveLogic.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(response));
398  // add the read junction-internal foes for the given request index
399  myActiveFoes.push_back(std::bitset<SUMO_MAX_CONNECTIONS>(foes));
400  // add whether the vehicle may drive a little bit further
401  myActiveConts.set(request, cont);
402  // increse number of set information
404 }
405 
406 
407 void
408 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID,
409  TrafficLightType type, SUMOTime offset) {
410  myActiveKey = id;
411  myActiveProgram = programID;
412  myActivePhases.clear();
413  myActiveConditions.clear();
414  myAbsDuration = 0;
416  myLogicType = type;
417  myOffset = offset;
418  myAdditionalParameter.clear();
419 }
420 
421 
422 void
424  // build and add the phase definition to the list
425  myActivePhases.push_back(phase);
426  // add phase duration to the absolute duration
427  myAbsDuration += phase->duration;
428 }
429 
430 
431 bool
432 NLJunctionControlBuilder::addCondition(const std::string& id, const std::string& value) {
433  if (myActiveConditions.count(id) == 0) {
434  myActiveConditions[id] = value;
435  return true;
436  } else {
437  return false;
438  }
439 }
440 
441 void
444  // We have a legacy network. junction element did not contain logicitems; read the logic later
445  return;
446  }
447  if (myCurrentHasError) {
448  // had an error before...
449  return;
450  }
452  throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious.");
453  }
454  if (myLogics.count(myActiveKey) > 0) {
455  throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice.");
456  }
460  myActiveConts);
461  myLogics[myActiveKey] = logic;
462 }
463 
464 
467  postLoadInitialization(); // must happen after edgeBuilder is finished
469  throw ProcessError("Traffic lights could not be built.");
470  }
472  myLogicControl = nullptr;
473  return ret;
474 }
475 
476 
477 void
478 NLJunctionControlBuilder::addParam(const std::string& key,
479  const std::string& value) {
480  myAdditionalParameter[key] = value;
481 }
482 
483 
486  if (myLogicControl != nullptr) {
487  return *myLogicControl;
488  }
489  return myNet.getTLSControl();
490 }
491 
492 
493 const std::string&
495  return myActiveKey;
496 }
497 
498 
499 const std::string&
501  return myActiveProgram;
502 }
503 
504 
505 void
507  for (MSTrafficLightLogic* const logic : myLogics2PostLoadInit) {
508  logic->init(myDetectorBuilder);
509  }
510  myNetIsLoaded = true;
511 }
512 
513 
514 MSJunction*
515 NLJunctionControlBuilder::retrieve(const std::string id) {
516  if (myJunctions != nullptr) {
517  return myJunctions->get(id);
518  } else {
519  return nullptr;
520  }
521 }
522 
523 
524 /****************************************************************************/
MSBitSetLogic< SUMO_MAX_CONNECTIONS > MSBitsetLogic
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
long long int SUMOTime
Definition: SUMOTime.h:32
TrafficLightType
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
Definition: StdDefs.h:41
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
An actuated (adaptive) traffic light logic.
std::vector< std::bitset< N > > Foes
Container holding the information which internal lanes prohibt which links Build the same way as Logi...
Definition: MSBitSetLogic.h:53
std::vector< std::bitset< N > > Logic
Container that holds the right of way bitsets. Each link has it's own bitset. The bits in the bitsets...
Definition: MSBitSetLogic.h:49
An actuated traffic light logic based on time delay of approaching vehicles.
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:72
Container for junctions; performs operations on all stored junctions.
The base class for an intersection.
Definition: MSJunction.h:58
The simulated network and simulation perfomer.
Definition: MSNet.h:88
MSTLLogicControl & getTLSControl()
Returns the tls logics control.
Definition: MSNet.h:449
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
A traffic lights logic which represents a tls in an off-mode.
The definition of a single phase of a tls logic.
SUMOTime duration
The duration of the phase.
A signal for rails.
A signal for rails.
Definition: MSRailSignal.h:46
A junction with right-of-way - rules.
Class for low-level marching policy.
Class for low-level phase policy.
Class for low-level platoon policy.
A self-organizing traffic light logic based on a particular policy.
Class for low-level request policy.
A fixed traffic light logic.
Storage for all programs of a single tls.
A class that stores and controls tls and switching of their programs.
bool closeNetworkReading()
Lets MSTLLogicControl know that the network has been loaded.
TLSLogicVariants & get(const std::string &id) const
Returns the variants of a named tls.
The parent class for traffic light logics.
virtual void changeStepAndDuration(MSTLLogicControl &tlcontrol, SUMOTime simStep, int step, SUMOTime stepDuration)=0
Changes the current phase and her duration.
TrafficLightType getLogicType() const
Returns the type of the logic.
SUMOTime getDefaultCycleTime() const
Returns the cycle time (in ms)
virtual const Phases & getPhases() const =0
Returns the phases of this tls program.
virtual void init(NLDetectorBuilder &nb)
Initialises the tls with information about incoming lanes.
A NEMA (adaptive) traffic light logic based on E2Detector.
Builds detectors for microsim.
PositionVector myShape
The shape of the current junction.
NLJunctionControlBuilder(MSNet &net, NLDetectorBuilder &db)
Constructor.
void closeJunctionLogic()
Ends the building of a junction logic (row-logic)
int myRequestItemNumber
Counter for the inserted items.
SumoXMLNodeType myType
The type of the currently chosen junction.
MSTLLogicControl::TLSLogicVariants & getTLLogic(const std::string &id) const
Returns a previously build tls logic.
std::string myActiveName
the name of the current junction
virtual ~NLJunctionControlBuilder()
Destructor.
MSJunction * retrieve(const std::string id)
try to retrieve junction by id
MSBitsetLogic::Foes myActiveFoes
The description about which lanes disallow other passing the junction simultaneously.
std::string myActiveID
The id of the currently chosen junction.
SUMOTime myOffset
The switch offset within the tls.
MSTLLogicControl * myLogicControl
The tls control to use (0 if net's tls control shall be used)
std::string myActiveKey
The key of the currently chosen junction.
TrafficLightType myLogicType
The current logic type.
bool myCurrentHasError
Information whether the current logic had an error.
MSTLLogicControl * buildTLLogics()
Returns the built tls-logic control.
MSJunctionControl * build() const
Builds the MSJunctionControl which holds all of the simulations junctions.
int myRequestSize
The size of the request.
void addPhase(MSPhaseDefinition *phase)
Adds a phase to the currently built traffic lights logic.
MSTLLogicControl & getTLLogicControlToUse() const
Returns the used tls control.
LaneVector myActiveIncomingLanes
The list of the incoming lanes of the currently chosen junction.
std::map< std::string, MSJunctionLogic * > myLogics
Map of loaded junction logics.
const std::string & getActiveSubKey() const
Returns the active sub key.
bool addCondition(const std::string &id, const std::string &value)
Adds a condition to the currently built traffic lights logic.
StringParameterMap myAdditionalParameter
Parameter map (key->value)
void openJunction(const std::string &id, const std::string &key, const SumoXMLNodeType type, const Position pos, const PositionVector &shape, const std::vector< MSLane * > &incomingLanes, const std::vector< MSLane * > &internalLanes, const std::string &name)
Begins the processing of the named junction.
void addParam(const std::string &key, const std::string &value)
Adds a parameter.
LaneVector myActiveInternalLanes
The list of the internal lanes of the currently chosen junction.
void initJunctionLogic(const std::string &id)
Initialises a junction logic.
void initTrafficLightLogic(const std::string &id, const std::string &programID, TrafficLightType type, SUMOTime offset)
Begins the reading of a traffic lights logic.
virtual MSJunction * buildLogicJunction()
Builds a junction with a logic.
NLDetectorBuilder & myDetectorBuilder
The detector builder to use.
virtual MSJunction * buildNoLogicJunction()
Builds a junction that does not use a logic.
virtual MSJunction * buildInternalJunction()
Builds an internal junction.
MSJunctionControl * myJunctions
The junctions controls.
const std::string & getActiveKey() const
Returns the active key.
Position myPosition
The position of the junction.
MSJunctionLogic * getJunctionLogicSecure()
Returns the current junction logic.
void postLoadInitialization()
initialize junctions after all connections have been loaded
std::map< std::string, std::string > myActiveConditions
The current switching conditions for an actuated traffic light.
void addLogicItem(int request, const std::string &response, const std::string &foes, bool cont)
Adds a logic item.
std::vector< MSTrafficLightLogic * > myLogics2PostLoadInit
The container for information which junctions shall be initialised using which values.
MSBitsetLogic::Logic myActiveLogic
The right-of-way-logic of the currently chosen bitset-logic.
SUMOTime myAbsDuration
The absolute duration of a tls-control loop.
void closeJunction(const std::string &basePath)
Closes (ends) the processing of the current junction.
MSSimpleTrafficLightLogic::Phases myActivePhases
The current phase definitions for a simple traffic light.
bool myNetIsLoaded
whether the network has been loaded
virtual void closeTrafficLightLogic(const std::string &basePath)
Ends the building of a traffic lights logic.
std::bitset< SUMO_MAX_CONNECTIONS > myActiveConts
The description about which lanes have an internal follower.
T get(const std::string &id) const
Retrieves an item.
bool add(const std::string &id, T item)
Adds an item.
void updateParameters(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
void set(double x, double y)
set positions x and y
Definition: Position.h:85
A list of positions.