-- CSC1208 Assignment 2a. -- Robert Bernecky 1999-11-12 -- reachable states: 186 (2^7.53916) out of 98304 (2^16.585) -- Hopefully fancier version of traffic signal model with turn arrows -- This model encodes the changing of a signal and the turn arrows -- as instances of a module. The goal of this is to localize the code -- required to support each of these functions, and to facilitate -- changes in intersection configuration, e.g., adding another signal. -- Design Comments: -- 1999-11-06 -- This design places signals into one or more equivalence classes. -- Within a given class, all signals are Green concurrently. -- A given signal may appear in more than one class. -- I gave up on trying to arrange things so that signals that are -- Green in two consecutive phases (e.g., N is phases 1 and 2) don't -- go Red during the transition. If I was a driver, I would not be happy -- with this state of affairs... -- I have (sigh) reintroduced the sensor latches, in hopes of making -- this thing work. -- Signals and arrows are both modeled using the "signal" module. -- This gives us a simpler design, and also ensures that arrows -- undergo a transition period to permit traffic in the intersection -- to clear it before turning Green. -- I have not included extra states to enforce not-unit durations for -- signals, but that's not particularly difficult, just ugly. -- Signal/arrow module definition MODULE signal(Sensor_Me,Class_Me,Color_Them,Phase) -- module inputs: -- Sensor_Me: This is the value of this signal's traffic sensor. -- It is used in conjunction with equivalence class -- phase to control this signal's turning to Green. -- Phase: Signal phase now. -- module outputs: -- Light values, as specified in assignment VAR Color : {Green,Yellow,JustRed,Red}; -- color of signal -- JustRed holds for one tick; we use it to propagate rightofway GV : boolean; -- A vehicle has appeared at our Sensor (perhaps transiently) -- We latch this in order to ensure that this signal changes -- even if the vehicle has run the signal before we have rightofway. -- This makes things slightly less efficient in Boston, but otherwise -- simplifies control logic. DEFINE -- If ROW (right of way) is set, we can change to Green if -- opposing signals are Red. ROW := Phase in Class_Me; ASSIGN next(Color) := case -- The next line controls the length of time a signal stays Green. -- It could include a counter to keep signals Green for more than -- one cycle. Red duration could be treated in the same way. (Color = Green) & ! ROW : Yellow; (Color = Yellow) : JustRed; (Color = JustRed) : Red; (Color = Red) & ROW & Color_Them : Green; 1 : Color; esac; init(GV) := 0; next(GV) := case Color = Green : 0; (Sensor_Me | GV) : 1; 1 : 0; esac; MODULE main IVAR -- Specified inputs Sensor_E : boolean; Sensor_N : boolean; Sensor_S : boolean; Sensor_NW : boolean; Sensor_ES : boolean; VAR -- Phase is a ring counter that grants right-of-way for -- each equivalence class. -- It is driven from state to state by traffic sensors for -- the other states. -- The signals belonging to the active phase will wait until -- other signals all go Red, then they will turn Green and -- pass on the right-of-way. -- The signals not belonging to the active phase will turn Red -- when they detect the phase change. -- Phase 1: N, S are Green -- Phase 2: N, NW, ES are Green -- Phase 3: E, ES are Green Phase : {Phase_1,Phase_2,Phase_3}; -- Define the signals Signal_E: signal(Sensor_E, {Phase_3}, N_RED & S_RED & NW_RED, Phase); Arrow_ES: signal(Sensor_ES, {Phase_2,Phase_3}, S_RED, Phase); Signal_S: signal(Sensor_S, {Phase_1}, E_RED & ES_RED & NW_RED, Phase); Signal_N: signal(Sensor_N, {Phase_1,Phase_2}, E_RED, Phase); Arrow_NW: signal(Sensor_NW, Phase_2, S_RED & E_RED, Phase); DEFINE -- Outputs for signals E_GREEN := Signal_E.Color = Green; E_YELLOW := Signal_E.Color = Yellow; -- From the standpoint of safety, the following Red expression is safer -- than one based on assertion of Red |JustRed. E_RED := !(E_GREEN | E_YELLOW); N_GREEN := Signal_N.Color = Green; N_YELLOW := Signal_N.Color = Yellow; N_RED := !(N_GREEN | N_YELLOW); S_GREEN := Signal_S.Color = Green; S_YELLOW := Signal_S.Color = Yellow; S_RED := !(S_GREEN | S_YELLOW); -- Outputs for arrows NW_ARROW := Arrow_NW.Color = Green; NW_YELLOW := Arrow_NW.Color = Yellow; NW_JUSTRED:= Arrow_NW.Color = JustRed; ES_ARROW := Arrow_ES.Color = Green; ES_YELLOW := Arrow_ES.Color = Yellow; ES_JUSTRED:= Arrow_ES.Color = JustRed; NW_RED := Arrow_NW.Color = Red; ES_RED := Arrow_ES.Color = Red; -- My phase sensors. If there is a vehicle here, we hang onto our -- ROW until we go Green, then pass it on to next signal. Sensor_1 := Signal_N.GV | Signal_S.GV; Sensor_2 := Signal_N.GV | Arrow_NW.GV | Arrow_ES.GV; Sensor_3 := Signal_E.GV | Arrow_ES.GV; -- My Green sensors. When our signals are all Green, we pass on -- the right-of-way to next phase. Phase_1_Green := N_GREEN & S_GREEN; Phase_2_Green := N_GREEN & NW_ARROW & ES_ARROW; Phase_3_Green := E_GREEN & ES_ARROW; ASSIGN -- First signal is Green. All others initialize to Red. init(Signal_N.Color) := Green; init(Signal_E.Color) := Red; init(Signal_S.Color) := Green; -- Color Red for arrows is OFF. init(Arrow_NW.Color) := Red; init(Arrow_ES.Color) := Red; -- Phase ring counter init(Phase) := Phase_1; next(Phase) := case (Phase = Phase_1) & (Sensor_2 | Sensor_3) & Phase_1_Green : Phase_2; (Phase = Phase_2) & (Sensor_1 | Sensor_3) & Phase_2_Green : Phase_3; (Phase = Phase_3) & (Sensor_1 | Sensor_2) & Phase_3_Green : Phase_1; 1 : Phase; esac ;