Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NEMAController.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 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/****************************************************************************/
19// An actuated NEMA-phase-compliant traffic light logic
20/****************************************************************************/
21#pragma once
22#include <config.h>
23
24#include <utility>
25#include <vector>
26#include <bitset>
27#include <map>
28#include <set>
33#include "MSPhaseDefinition.h"
34
35
36// ===========================================================================
37// class declarations
38// ===========================================================================
40class MSE2Collector;
41class NEMAPhase;
43
44// ===========================================================================
45// Enumeration
46// ===========================================================================
47enum class LightState {
48 RedXfer,
49 Red,
50 Yellow,
51 Green,
54};
55
56
57// ===========================================================================
58// class definitions
59// ===========================================================================
65public:
66
68
69 typedef std::map<MSLane*, MSE2Collector*> LaneDetectorMap;
70
71 typedef std::map<MSE2Collector*, MSLane*, ComparatorIdLess> DetectorLaneMap;
72
73 // Small structure for storing two ring transitions and the average distance
79
84
86 const std::string lightHeadPriority = "GgyuOs";
87
88 typedef std::vector<transitionInfo> TransitionPairs;
89
99 NEMALogic(MSTLLogicControl& tlcontrol,
100 const std::string& id, const std::string& programID,
101 const SUMOTime offset,
103 int step, SUMOTime delay,
104 const std::map<std::string, std::string>& parameter,
105 const std::string& basePath);
106
107
112 void init(NLDetectorBuilder& nb) override;
113
115 ~NEMALogic();
116
118 SUMOTime trySwitch() override;
119
122
126 const MSPhaseDefinition& getCurrentPhaseDef() const override;
128
129 void resetLastSwitch(SUMOTime t);
130
131 void activateProgram() override;
132 void deactivateProgram() override;
133
134 bool showDetectors() const {
135 return myShowDetectors;
136 }
137
138 void setShowDetectors(bool show);
139
141 std::map<std::string, double> getDetectorStates() const override;
142
148 void getNextPhases(TransitionPairs& transitions);
149
159
160
168 void getLaneInfoFromNEMAState(std::string state, StringVector& laneIDs, IntVector& stateIndex);
169
175 void setNewMaxGreens(std::vector<double> newMaxGreens);
176
182 void setNewSplits(std::vector<double> newSplits);
183
189 void setNewCycleLength(double newCycleLength);
190
196 void setNewOffset(double newOffset);
197
206
208 void setParameter(const std::string& key, const std::string& value) override;
209
211 const std::string getParameter(const std::string& key, const std::string defaultValue = "") const override;
212
214 inline SUMOTime getCurrentTime(void) const {
215 return simTime;
216 }
217
218 // /// @brief Wrapper Function to Simplify Accessing Offset Cycle Time
219 // inline SUMOTime getCurrentOffsetTime(void) const {return simTime - cycleRefPoint - offset; };
220
222 inline SUMOTime getTimeInCycle() const {
224 }
225
226
228 void setActivePhase(PhasePtr phase);
229
236 inline PhasePtr getActivePhase(int ringNum) {
237 return myActivePhaseObjs[ringNum];
238 }
239
246 std::vector<PhasePtr> getPhasesByRing(int ringNum);
247
256 PhasePtr getPhaseObj(int phaseNum, int ringNum = -1);
257
263 inline std::vector<PhasePtr> getPhaseObjs(void) {
264 return myPhaseObjs;
265 }
266
275 int measureRingDistance(int p1, int p2, int ringNum);
276
283 inline bool isType170(void) const {
284 return myControllerType == Type170;
285 }
286
294
297
302 void implementTraciChanges(void);
303
307
308protected:
309
312
317
322
325
328
331
333 inline void setCurrentTime(void) {
335 }
336
338 PhasePtr myActivePhaseObjs[2] = { nullptr, nullptr };
339
341 std::vector<PhasePtr > myPhaseObjs;
342
345
354 void constructTimingAndPhaseDefs(std::string& barriers, std::string& coordinates,
355 std::string& ring1, std::string& ring2);
356
360 std::string composeLightString();
361
367 bool vectorContainsPhase(std::vector<int> v, int phaseNum);
368
369 // create a small datatype for mapping detector to phase index
370 // This is the one copied from MSActuatedTrafficLightLogic
371 // not used in our controller, but it is here for meeting the SUMO default traffic logic light check
372 // this one and related could be removed with extra efforts
374 DetectorInfo(MSE2Collector* _det, int numPhases) :
375 det(_det),
376 servedPhase(numPhases, false)
377 {}
380 std::vector<bool> servedPhase;
381 };
382 typedef std::vector<std::vector<DetectorInfo*>> detectorMap;
385 std::vector<DetectorInfo> myDetectorInfoVector;
386
387
389 bool hasMajor(const std::string& state, const LaneVector& lanes) const;
390
398 std::vector<int> readParaFromString(std::string s);
399
407 bool isLeftTurnLane(const MSLane* const lane) const;
408
410 int string2int(std::string s);
411
414
416 std::map<std::string, int> myLanePhaseMap;
417
420
423
426
429
431 std::string myFile;
432
435
437 std::string myVehicleTypes;
438
439 /*
440 {
441 {3,4,1,2},
442 {7,8,5,6}
443 }
444 */
445 std::vector<std::vector<int>> rings;
446
447 /*
448 {
449 {1 : PhaseDetectorInfo{
450 detectors: {det1, det2, ...},
451 crossPhaseDetector: 6
452 },
453 },
454 {2 : ...
455 }
456 */
457 // std::map<int, PhaseDetectorInfo> phase2DetectorMap;
458 std::map<int, std::vector<std::string>> phase2ControllerLanesMap;
459
461 SUMOTime cycleRefPoint;// missing update
464
473
474 // Store the cabinet type
476
483 controllerType parseControllerType(std::string inputType);
484
487
494 void error_handle_not_set(std::string param_variable, std::string param_name);
495
501 void validate_timing();
502
514
517 switch (myControllerType) {
518 case Type170:
519 return calculateForceOffs170();
520 case TS2:
521 return calculateForceOffsTS2();
522 default:
523 return calculateForceOffs170();
524 }
525 }
526
527
534 switch (myControllerType) {
535 case Type170:
537 case TS2:
539 default:
540 // Default to Type170
542 }
543 }
544};
545
546
556public:
559
587
588 // create a PhaseDetectorInfo type
590
607 bool isBarrier,
608 bool isGreenRest,
609 bool isCoordinated,
610 bool minRecall,
611 bool maxRecall,
612 bool fixForceOff,
613 int barrierNum,
614 int ringNum,
615 IntVector phaseStringInds,
616 MSPhaseDefinition* phase);
617
619 ~NEMAPhase();
620
623 return myLightState;
624 }
626 inline std::vector<MSE2Collector*> getDetectors() const {
628 }
629
630
632 inline void setDetectors(std::vector<MSE2Collector*> detectors) {
633 myDetectorInfo.detectors = detectors;
634 }
635
637 inline bool isTransitionActive() const {
639 }
640
641 // Build a Map of Valid Transitions and store the detector-based information
650 void init(NEMALogic* controller, int crossPhaseTarget, int crossPhaseSource, bool latching);
651
657 void update(NEMALogic* controller);
658
665 void exit(NEMALogic* controller, PhaseTransitionLogic* nextPhases[2]);
666
673 void handleGreenRestOrTransfer(NEMALogic* controller, PhaseTransitionLogic* nextPhases[2]);
674
680 void enterYellow(NEMALogic* controller);
681
687 void handleRedXferOrNextPhase(NEMALogic* controller, PhaseTransitionLogic* nextPhases[2]);
688
690 inline bool hasRecall(void) {
691 return minRecall || maxRecall;
692 }
693
695 inline bool callActive(void) {
697 }
698
700 inline bool detectActive(void) {
702 }
703
705 void checkMyDetectors(void);
706
708 void clearMyDetectors(void);
709
710 // Need-to-know Phase Settings
720
723
729
732
740
748 return yellow + red;
749 }
750
754 }
755
757 inline void setSequentialPriorPhase(PhasePtr priorPhase) {
758 sequentialPriorPhase = priorPhase;
759 }
760
767 std::vector<PhaseTransitionLogic*> trySwitch(NEMALogic* controller);
768
776
778 char getNEMAChar(int i);
779
781 void recalculateTiming(void);
782
784 inline void forceEnter(NEMALogic* controller) {
785 enter(controller, sequentialPriorPhase);
786 }
787
789 inline bool controlledIndex(int i) {
790 return std::count(myPhaseStringInds.begin(), myPhaseStringInds.end(), i) > 0;
791 }
792
802
804 inline void cleanupExit(void) {
805 transitionActive = false;
806 readyToSwitch = false;
808 }
809
811 inline bool okay2ForceSwitch(NEMALogic* controller) {
812 return readyToSwitch && !transitionActive && (getTransitionTime(controller) <= TIME2STEPS(0));
813 }
814
815private:
818
825
826 // Phase Knowledge Space
829
837
841 std::string myGreenString;
842 std::string myYellowString;
843 std::string myRedString;
845
853
855 std::vector<PhaseTransitionLogic*> myTransitions;
856
864 void enter(NEMALogic* controller, PhasePtr lastPhase);
865
870 void setMyNEMAStates(void);
871
874
877
878};
879
880
890public:
893
903 );
904
913 bool okay(NEMALogic* controller);
914
921 int getDistance(PhaseTransitionLogic* otherTrans);
923 inline void setDistance(int d) {
924 distance = d;
925 }
927
930
932 inline PhasePtr getToPhase(void) const {
933 return toPhase;
934 }
935
937 inline PhasePtr getFromPhase(void) const {
938 return fromPhase;
939 }
940
941private:
944
946 void buildLogic(void);
947
956 bool fromBarrier(NEMALogic* controller);
957
966 bool fromCoord(NEMALogic* controller);
967
976 bool freeBase(NEMALogic* controller);
977
986 bool coordBase(NEMALogic* controller);
987};
long long int SUMOTime
Definition GUI.h:36
LightState
std::vector< std::string > StringVector
Definition of a vector of strings.
Definition Option.h:42
std::vector< int > IntVector
Definition of a vector of ints.
Definition Option.h:37
#define TIME2STEPS(x)
Definition SUMOTime.h:60
An areal detector corresponding to a sequence of consecutive lanes.
Representation of a lane in the micro simulation.
Definition MSLane.h:84
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
The definition of a single phase of a tls logic.
A fixed traffic light logic.
A class that stores and controls tls and switching of their programs.
std::vector< MSLane * > LaneVector
Definition of the list of arrival lanes subjected to this tls.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
A NEMA (adaptive) traffic light logic based on E2Detector.
SUMOTime cycleRefPoint
std::vector< std::vector< DetectorInfo * > > detectorMap
std::map< std::string, double > getDetectorStates() const override
retrieve all detectors used by this program
int measureRingDistance(int p1, int p2, int ringNum)
return the ring distance between two phases
SUMOTime getTimeInCycle() const
override Function to Simplify Accessing Offset Cycle Time
void getLaneInfoFromNEMAState(std::string state, StringVector &laneIDs, IntVector &stateIndex)
returns the IDs of the phase's controlled lanes. Found by looking for the "G" in the light state stri...
void getNextPhases(TransitionPairs &transitions)
extends the transitions vector with valid Transitions given the current traffic light state
void setNewMaxGreens(std::vector< double > newMaxGreens)
Set the max green of all phases.
void calculateForceOffs170()
calculate the forceOffs for a Type 170 style offset From https://ops.fhwa.dot.gov/publications/fhwaho...
void calculateInitialPhases()
directs the controller to the correct calculate phases function
void resetLastSwitch(SUMOTime t)
const std::string lightHeadPriority
constant for storing the priority order for light heads. Iterates left to right and stops when finds ...
const std::string getParameter(const std::string &key, const std::string defaultValue="") const override
try to get the value of the given parameter. Parameters prefixed with 'NEMA.' control functionality
std::vector< DetectorInfo > myDetectorInfoVector
storing the detector info in a vector
SUMOTime myNextCycleLength
the next cycle length (set by traci)
void init(NLDetectorBuilder &nb) override
Initialises the tls with information about incoming lanes.
void calculateInitialPhasesTS2()
calculate the initial phases for the TS2 style controller to start in
std::string myVehicleTypes
Whether detector output separates by vType.
std::string myFile
The output file for generated detectors.
PhasePtr getActivePhase(int ringNum)
Get the Active Phase object for a specified ring.
double myDetectorLength
store the generated detector length
SUMOTime getCurrentCycleLength()
Get the current cycle length.
bool showDetectors() const
std::vector< std::vector< int > > rings
SUMOTime myFreq
The frequency for aggregating detector output.
DetectorLaneMap myDetectorLaneMap
A map from detectors to lanes.
SUMOTime trySwitch() override
overrides the MSSimpleTrafficLightLogic trySwitch method
bool isType170(void) const
checks if the controller is of type170
void validate_timing()
validates the NEMA timing. Writes warnings if ignoreError set to true else throws ProcessError
bool queuedTraciChanges
flag to keep track of whether a timing change has been requested via traci
SUMOTime simTime
stores the simulation time to make it easily accessible
void activateProgram() override
called when switching programs
void setShowDetectors(bool show)
bool whetherOutputState
void constructTimingAndPhaseDefs(std::string &barriers, std::string &coordinates, std::string &ring1, std::string &ring2)
constructs phase using the configuration file
int myPhaseStrLen
stores the length of phase string for the controller "GGrrrrs" = 6. Must be the same length for all p...
NEMAPhase * PhasePtr
int myNumberRings
stores controllers # of rings
PhasePtr defaultBarrierPhases[2][2]
an array to store the phases located at a barrier for each ring
SUMOTime getCurrentTime(void) const
Wrapper Function to Simplify Accessing Time.
std::vector< PhasePtr > myPhaseObjs
a vector that stores a pointer to the instantiated NEMAPhase objects
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter. Parameters prefixed with 'NEMA.' control functionality
void error_handle_not_set(std::string param_variable, std::string param_name)
throw an InvalidArgument error if the param_name is not set
void implementTraciChanges(void)
implement any pending traci changes This function is called once per cycle
PhasePtr getPhaseObj(int phaseNum, int ringNum=-1)
get the phase object matching the phaseNum If ringNum is passed, it will only search for the phase in...
void setNewOffset(double newOffset)
Set the new offset for the controller.
std::vector< PhasePtr > getPhasesByRing(int ringNum)
get all phases for a given ring
std::map< MSLane *, MSE2Collector * > LaneDetectorMap
controllerType parseControllerType(std::string inputType)
parse the controllerType from the tllogic description
SUMOTime myCycleLength
the coordinated cycle length
SUMOTime offset
the controller's offset
void calculateInitialPhases170()
calculate the initial phases for Type 170
SUMOTime myNextOffset
the next offset to implement
SUMOTime ModeCycle(SUMOTime a, SUMOTime b)
Calculates the modulus a / b, normally used to calculate the cycle time between two times....
void calculateForceOffs()
directs the code to the correct force off function accorifing to its cabinet type
std::vector< int > readParaFromString(std::string s)
converts a comma separated string into a integer vector "1,2,3,4" -> {1,2,3,4}
std::map< MSE2Collector *, MSLane *, ComparatorIdLess > DetectorLaneMap
std::vector< PhasePtr > getPhaseObjs(void)
get a vector of all phase objects
bool myShowDetectors
Whether the detectors shall be shown in the GUI.
detectorMap myDetectorForPhase
int string2int(std::string s)
convert a string to an integer
bool hasMajor(const std::string &state, const LaneVector &lanes) const
return whether there is a major link from the given lane in the given phase
bool coordinateMode
whether the controller is in coordinated mode or not
PhasePtr myActivePhaseObjs[2]
variable to store the active phases
void deactivateProgram() override
void setCurrentTime(void)
Set the simTime.
~NEMALogic()
Destructor.
MSPhaseDefinition myPhase
virtual phase that holds the current state
PhaseTransitionLogic * getDefaultTransition(PhaseTransitionLogic *t, PhaseTransitionLogic *ot)
return the default transition for t give its and the ot's state
bool vectorContainsPhase(std::vector< int > v, int phaseNum)
check if a vector contains an element
void calculateForceOffsTS2()
calculate the forceOffs for a TS2 style offset From https://ops.fhwa.dot.gov/publications/fhwahop0802...
PhasePtr getOtherPhase(PhasePtr p)
Get the opposite active phase.
double myDetectorLengthLeftTurnLane
store the left turn lane detestor length
controllerType myControllerType
bool isLeftTurnLane(const MSLane *const lane) const
decide whether the detector is for left turn lane if it is, use the detector length for left turn lan...
LaneDetectorMap myLaneDetectorMap
A map from lanes to detectors.
PhasePtr coordinatePhaseObjs[2]
a store of the coordinated phase objects. Only used meaningfully when the controller is in coordinate...
std::map< std::string, int > myLanePhaseMap
A map from lanes names to phases.
std::string composeLightString()
iterates over the two active phases (myActivePhaseObjs) and merges the two active phases
void setNewCycleLength(double newCycleLength)
set the new cycle length for the controller
void setActivePhase(PhasePtr phase)
set the active phase
std::vector< transitionInfo > TransitionPairs
const MSPhaseDefinition & getCurrentPhaseDef() const override
Returns myPhase, which doesn't correspond to a NEMA phase, but rather the composite light string.
std::map< int, std::vector< std::string > > phase2ControllerLanesMap
void setNewSplits(std::vector< double > newSplits)
Set the new splits of all phases.
One phase in the NEMAController.
bool lastDetectActive
store the last detect check for traci purposes
std::string myYellowString
NEMAPhase * PhasePtr
Typedef for commonly used phase pointer.
void setDetectors(std::vector< MSE2Collector * > detectors)
sets the detectors for the phase
SUMOTime myLastEnd
SUMOTime vehExt
SUMOTime nextMaxDuration
void cleanupExit(void)
public method to set whether phase is active or not
MSPhaseDefinition * myCorePhase
A reference to the core phase of which NEMAPhase wraps.
LightState myLightState
std::string myGreenString
LightState getCurrentState() const
gets the current light state
SUMOTime myExpectedDuration
void setMyNEMAStates(void)
this function replaces getNEMAStates calculation at every call It sets my myGreenString,...
~NEMAPhase()
Destructor.
PhasePtr getSequentialPriorPhase(void)
get the prior phase
bool controlledIndex(int i)
Return whether or not the phase index is controlled by me.
bool coordinatePhase
SUMOTime greenRestTimer
a count down timer to track green rest transition time
void clearMyDetectors(void)
Clear My Detectors. Called on all phases at every step.
void checkMyDetectors(void)
Check Detectors. Called on all phases at every step.
SUMOTime yellow
SUMOTime minDuration
PhaseDetectorInfo myDetectorInfo
PhasePtr sequentialPriorPhase
void setSequentialPriorPhase(PhasePtr priorPhase)
set the prior phase
SUMOTime greatestStartTime
PhaseDetectorInfo PhaseDetectorInfo
std::vector< PhaseTransitionLogic * > trySwitch(NEMALogic *controller)
calculate a vector of potention next phases
std::vector< MSE2Collector * > getDetectors() const
returns a vector of the phases detectors
char getNEMAChar(int i)
Return the ryg light string for the phase.
SUMOTime forceOffTime
stores the force off time in coordinated mode
SUMOTime red
void recalculateTiming(void)
accessory function to recalculate timing
void handleRedXferOrNextPhase(NEMALogic *controller, PhaseTransitionLogic *nextPhases[2])
handles the transition into a red xfer state, which is roughly the same as green rest
SUMOTime getTransitionTimeStateless(void)
Get the Transition time given.
SUMOTime calcVehicleExtension(SUMOTime duration)
}
bool okay2ForceSwitch(NEMALogic *controller)
simple internal check to see if done okay to transition
void init(NEMALogic *controller, int crossPhaseTarget, int crossPhaseSource, bool latching)
initializes the object
PhasePtr myInstance
bool isTransitionActive() const
check if a transition is active
void enterYellow(NEMALogic *controller)
handles the transition into yellow
PhaseTransitionLogic * getTransition(int toPhase)
return the PhaseTransitionLogic matching the toPhase
SUMOTime maxDuration
void handleGreenRestOrTransfer(NEMALogic *controller, PhaseTransitionLogic *nextPhases[2])
handles the transition into a green rest state
bool readyToSwitch
flag to for the supervisory controller to denote whether phase is ready to switch or not.
bool transitionActive
variable to store whether a transition is active or not
std::vector< PhaseTransitionLogic * > myTransitions
stores a sorted list of potential transitions
SUMOTime myStartTime
void forceEnter(NEMALogic *controller)
Force Enter. This Should only be called at initialization time.
PhasePtr myLastPhaseInstance
bool callActive(void)
simple method to check if there is either a recall or an active detector
std::string myRedString
SUMOTime getTransitionTime(NEMALogic *controller)
Get the Transition Time.
PhaseTransitionLogic * lastTransitionDecision
pointer to save the last transition
void enter(NEMALogic *controller, PhasePtr lastPhase)
handles entry to the phase during simulation Sets the color to green and determines maximum duration
SUMOTime maxGreenDynamic
bool hasRecall(void)
simple method to check if there is a recall on the phase.
IntVector myPhaseStringInds
void exit(NEMALogic *controller, PhaseTransitionLogic *nextPhases[2])
handles the transition out of a phase into the next (puts the phase through (G -> Y -> R) transition
bool detectActive(void)
simple method to check if a detector is active
Builds detectors for microsim.
This class handles the transition logic between two phases.
void setDistance(int d)
set the transition distance
int getDistance(PhaseTransitionLogic *otherTrans)
return the ring distance that this transition represents
bool okay(NEMALogic *controller)
This function is the main PhaseTransitionLogic function It is called by the fromPhase to check if a t...
bool freeBase(NEMALogic *controller)
this represents the bare minimum logic, that the toPhase has an active detector and that the fromPhas...
bool coordBase(NEMALogic *controller)
represents the bare minimum coordinate mode logic. Requires that the toPhase can fit its minimum gree...
bool fromBarrier(NEMALogic *controller)
If the fromPhase is at a barrier, then this function will be called to check whether the transition i...
bool fromCoord(NEMALogic *controller)
if the fromPhase is a coordinated phase, then this logic will be checked
PhasePtr getFromPhase(void) const
get the from phase
~PhaseTransitionLogic()
deconstructor
PhasePtr getToPhase(void) const
get the to phase
void buildLogic(void)
build the transition logic based on the from and to phase
NEMAPhase * PhasePtr
Typedef for commonly used phase pointer.
DetectorInfo(MSE2Collector *_det, int numPhases)
std::vector< bool > servedPhase
PhaseTransitionLogic * p2
PhaseTransitionLogic * p1
stores information about the phase's detector(s)
bool detectActive
where any of my detectors are active or not
std::vector< MSE2Collector * > detectors
a vector of pointers to the phase's detectors
PhaseDetectorInfo(bool latching, PhasePtr cpdSource, PhasePtr cpdTarget)
PhasePtr cpdSource
the cross-phase switching source for myself (1 if 6 should check 1 if 6 is green and I am phase 6)
PhasePtr cpdTarget
the cross-phase switching target for myself (6 if 6 should check 1 if 6 is green and I am phase 1)
bool latching
whether the detectors are latching or not