libFAUDES

Sections

Types

Elevator Example - Details

This page gathers detailed models, specifications and supervisors related to the elevator example from the iodevice plug-in. Corresponding files are located in libfaudes/plugin/iodevice/tutorial/data.

Signals and Events

The LRT laboratory set-up uses a simple analog circuit to simulate the behaviour of the elevator plant. Relevant digital signals (over continuous time) are given in the below table. The bit address in the first column refers to the wiring of the laboratory set-up.

Input Signals Output Signals
Name Comments (active) Addr.
U_CM_UP cabin motor on, upwards #0
U_CM_DN cabin motor on, downwards #2
U_DM_OP door motor on, open #4
U_DM_CL door motor on, close #6
U_OL_UP button led, upper level, on#8
U_OL_LW button led, lower level, on#10
 
Name Comments (active) Addr.
Y_CS_UP cabin sensor, upper position#6
Y_CS_LW cabin sensor, lower position#4
Y_DS_OP door sensor, open #10
Y_DS_CL door sensor, closed #8
Y_OB_UP upper button pressed #12
Y_OB_LW lower button pressed #14
Y_DS_LB light bracket occupied #16

Relevant discrete events by definition correspond to edges on the above signals. An event that is triggered by the plant is called a sensor event. An event that must be triggered externally (e.g. by the supervisor) is called an actuator event. The below tables specify the correspondence between edges of signals and actuator- and sensor events.

Cabin

Event TypeTrigger/Action Comments
c_up actuator clear U_CM_DN, set U_CM_UP activate cabin motor, upwards
c_down actuator clear U_CM_UP, set U_CM_UP activate cabin motor, downwards
c_stp actuator clear U_CM_DN, clear U_CM_UP stop cabin motor
c_arup sensor pos. edge on Y_CS_UP cabin arrives at upper sensor
c_lvup sensor neg. edge on Y_CS_UP cabin leaves upper sensor
c_arlw sensor pos. edge on Y_CS_LW cabin arrives at lower sensor
c_lvlw sensor neg. edge on Y_CS_LW cabin leaves lower sensor

Door

Event TypeTrigger/Action Comments
d_open actuator clear U_DM_OP, set U_DM_CL activate door motor to open
d_close actuator clear U_DM_CL, set U_DM_OP activate door motor to close
d_stp actuator clear U_DM_OP, clear U_DM_CL stop door motor
d_arop sensor pos. edge on Y_DS_OP door arrives at sensor open
d_lvop sensor neg. edge on Y_DS_OP door leaves sensor open
d_arcl sensor pos. edge on Y_DS_CL door arrives at sensor closed
d_lvcl sensor neg. edge on Y_DS_CL door leaves sensor closed
d_lbbl sensor pos. edge on Y_DS_LB light bracket blocked
d_lbrl sensor neg. edge on Y_DS_LB light bracket released

Operator

Event TypeTrigger/Action Comments
o_upb sensor pos. edge on Y_OB_UP upper button pressed
o_lwb sensor pos. edge on Y_OB_LW lower button pressed
o_uplon actuator set Y_OL_UP illuminate upper button
o_uploff actuator clear Y_OL_UP turn off upper button light
o_lwlon actuator set Y_OL_LW illuminate lower button
o_lwlnoff actuator clear Y_OL_LW turn off lower button light

Device Configuration

The LRT laboratory set-up uses two Advantech PCI boards for digital IO, one of them providing 64 inputs, the other 64 outputs. Signals are accessed through the comedi framework, where we use the system device files /dev/comedi0 and /dev/comedi1. The below iodevice configuration introduces events to libFAUDES according to the above definition. Signals referenced by a bits address, where each board uses a range from 0 to 63.

<DeviceContainer>
"LrtElevatorIO"      % overall device name
10                   % ms/ftu (overwrites per device def)


<Devices>

<ComediDevice>   
"LrtElevatorInput"    % device name
10                    % ms/ftu
64                    % max bitaddress   
100                   % background sample period in nsec
"/dev/comedi0"        % system device file

<EventConfiguration>

%%% Cabin sensor: arrive oat upper position 
"c_arup"      
<Sensor> <Triggers> 6 +PosEdge+ </Triggers> </Sensor>
%%% Cabin sensor: leave upper position 
"c_lvup"         
<Sensor> <Triggers> 6 +NegEdge+ </Triggers> </Sensor>
%%% Cabin sensor: arrive at lower position 
"c_arlw"         
<Sensor> <Triggers> 4 +PosEdge+ </Triggers> </Sensor>
%%% Cabin sensor: leave lower position 
"c_lvlw"
<Sensor> <Triggers> 4 +NegEdge+ </Triggers> </Sensor>

%%% Door sensor: door reached closed position
"d_closed"
<Sensor> <Triggers> 8 +PosEdge+ </Triggers> </Sensor>
%%% Door sensor: door leaving closed position
"d_lvClosed"
<Sensor> <Triggers> 8 +NegEdge+ </Triggers> </Sensor>
%%% Door sensor: door reached open position
"d_opened"
<Sensor> <Triggers> 10 +PosEdge+ </Triggers> </Sensor>
%%% Door sensor: door leaving open position
"d_lvOpened"
<Sensor> <Triggers> 10 +NegEdge+ </Triggers> </Sensor>
%%% Door sensor: light break occupied
"lb_occupied"
<Sensor> <Triggers> 16 +PosEdge+ </Triggers> </Sensor>
%%% Door sensor: light break released
"lb_released"
<Sensor> <Triggers> 16 +NegEdge+ </Triggers> </Sensor>

%%% Opertor sensor: upper button pressed
"upb_pressed"
<Sensor> <Triggers> 12 +NegEdge+ </Triggers> </Sensor>
%%% Opertor sensor: lower button pressed
"lwb_pressed"
<Sensor> <Triggers> 14 +NegEdge+ </Triggers> </Sensor>

</EventConfiguration>

</ComediDevice>

<ComediDevice>
"LrtElevatorOuput"              % device name
10                              % ms/ftu
64                              % max bitaddress
100                             % background sample period in nsec
"/dev/comedi1"                  % system device file

<EventConfiguration>

%%% Cabin actuator: stop motor 
"c_stp"  
<Actuator> <Actions> 0 +Clr+ 2 +Clr+ </Actions> </Actuator>
%%% Cabin actuator: start motor upwards 
"c_mvup" 
<Actuator> <Actions> 2 +Clr+ 0 +Set+ </Actions> </Actuator>
%%% Cabin actuator: start motor downwards 
"c_mvdw" 
<Actuator> <Actions> 0 +Clr+ 2 +Set+ </Actions> </Actuator>

%%% Door actuator: stop motor
"d_stp"
<Actuator> <Actions> 4 +Clr+ 6 +Clr+ </Actions> </Actuator>
%%% Door actuator: start motor to open door
"d_open"
<Actuator> <Actions> 6 +Clr+ 4 +Set+ </Actions> </Actuator>
%%% Door actuator: start motor to close door
"d_close"
<Actuator> <Actions> 4 +Clr+ 6 +Set+ </Actions> </Actuator>

%%% Operator actuator: illuminate button upstairs
"upLED_on"
<Actuator> <Actions> 8 +Set+  </Actions> </Actuator>
%%% Operator actuator: turn off light for button upstairs
"upLED_off"
<Actuator> <Actions> 8 +Clr+  </Actions> </Actuator>
%%% Operator actuator: illuminate button downstairs
"dwLED_on" <Actuator> <Actions> 10 +Set+ </Actions> </Actuator>
%%% Operator actuator: turn off light for button downstairs
"dwLED_off"
<Actuator> <Actions> 10 +Clr+  </Actions> </Actuator>

</EventConfiguration>
</ComediDevice>
</Devices>
</DeviceContainer>

Plant Model

Our plant model is organized in four components, namely Gcabin, Gdoor, and Glbracket, and G_operator, each referring to the respective alphabet.

Cabin Gcabin
Door Gdoor
Light bracket Glbracket

Operator events are the push buttons incl. illumination. The operator model G_operator realises the corresponding full language.

Specification

Eopcmds: We sense the operator button to enable cabin activity. The internal events a_* are introduced to simplify synchronisation with further specification components.

Ecabmot: Cabin movement must not be interupted until the upper or lower position is reached. Note that this specification also introduces that a_done can only occur after the cabin did perform some shuttle operation.

Edrmot1: Similar to the cabin motion as specified by Ecabmot, the door motion specification requires the door to either open or close and to stop once the goal is accomplished. However, the we allow the closing operation to fail to accomodate for the light bracket. The internal events a_close and a_open to indicate the outcome of a door operation.

Escheds: The top level schedule enables cabin movement once the door has been closed. After cabin movement, the door is to be opened.

Edrsaf1: The first safety requirement to the door is that it must not be open when the cabin moves.

Edrsaf2: The second safety requirement to the door is that it must re-open when the light bracket becomes blocked during closing.

Controller Synthesis

Controller synthesis for the entire elevator setup is performed by the luafaudes script elevator_synthesis.lua from the iodevice plug-in tutorial.

-------------------------------------------------------------------------------
-- read files
-------------------------------------------------------------------------------

-- report
print("elevator: reading plant and specification data")

-- load plant components from file
plant_cabin    = faudes.Generator("data/elevator_plant_cabin.gen")
plant_door     = faudes.Generator("data/elevator_plant_door.gen")
plant_lbracket = faudes.Generator("data/elevator_plant_lbracket.gen")
plant_buttons  = faudes.Generator("data/elevator_plant_buttons.gen")
plant_leds     = faudes.Generator("data/elevator_plant_leds.gen")

-- load specification components from file
spec_opcmd   = faudes.Generator("data/elevator_spec_opcmd.gen")
spec_opcmds  = faudes.Generator("data/elevator_spec_opcmds.gen")
spec_opled   = faudes.Generator("data/elevator_spec_opled.gen")
spec_cabmot  = faudes.Generator("data/elevator_spec_cabmot.gen")
spec_cabmots = faudes.Generator("data/elevator_spec_cabmots.gen")
spec_drmot1  = faudes.Generator("data/elevator_spec_drmot1.gen")
spec_drsaf1  = faudes.Generator("data/elevator_spec_drsaf1.gen")
spec_drsaf2  = faudes.Generator("data/elevator_spec_drsaf2.gen")
spec_scheds  = faudes.Generator("data/elevator_spec_scheds.gen")

-- dont name states
faudes.StateNamesOff();

-------------------------------------------------------------------------------
-- build plant model
-------------------------------------------------------------------------------

-- report
print("elevator: build pant model")

-- prepare plant model
plant_full = faudes.Generator() 
plant_full_min = faudes.Generator()

-- build full model consisting of cabin, door and operator
faudes.Parallel(plant_full,plant_cabin,plant_full)
faudes.Parallel(plant_full,plant_door,plant_full)
faudes.Parallel(plant_full,plant_lbracket,plant_full)
faudes.Parallel(plant_full,plant_buttons,plant_full)
faudes.Parallel(plant_full,plant_leds,plant_full)

-- have a sensible name
plant_full:Name("elevator full plant (cabin plus buttons)")

-- get eventset of plant model
plant_full_alphabet = faudes.EventSet(plant_full:Alphabet())

-- reduce state space 
faudes.StateMin(plant_full,plant_full_min)

-- write to file
plant_full_min:Write("tmp_elevator_plant_full.gen")

-------------------------------------------------------------------------------
-- build specification
-------------------------------------------------------------------------------

-- report
print("elevator: build specification")

-- prepare overall specification
spec_full = faudes.Generator()
spec_full_min = faudes.Generator()

-- compose overall specification
faudes.Parallel(spec_full,spec_opcmds,spec_full)
faudes.Parallel(spec_full,spec_scheds,spec_full)
faudes.Parallel(spec_full,spec_opled,spec_full)
faudes.Parallel(spec_full,spec_cabmots,spec_full)
faudes.Parallel(spec_full,spec_drmot1,spec_full)
faudes.Parallel(spec_full,spec_drsaf1,spec_full)
faudes.Parallel(spec_full,spec_drsaf2,spec_full)
faudes.StateMin(spec_full,spec_full_min)

-- write to file
spec_full_min:Write("tmp_elevator_spec_full.gen")


-------------------------------------------------------------------------------
-- build synthesis
-------------------------------------------------------------------------------

-- report
print("elevator: synthesis")

-- match plant and spec alphabets
alphabet_full = faudes.EventSet();
alphabet_plant_extra = faudes.EventSet();
faudes.AlphabetUnion(plant_full:Alphabet(),spec_full:Alphabet(),alphabet_full);
faudes.AlphabetDifference(alphabet_full,plant_full:Alphabet(),alphabet_plant_extra);
faudes.InvProject(spec_full_min,alphabet_full);
faudes.InvProject(plant_full_min,alphabet_full);

-- extra events in the specification are controllable
plant_full_min:SetControllable(alphabet_plant_extra);

-- compute supervisor for full elevator setup
super_full = faudes.Generator();
super_full_min = faudes.Generator();
faudes.SupConNB(plant_full_min,spec_full_min,super_full)
super_full:Name("elevator supervisor (full)")
faudes.StateMin(super_full,super_full_min)

-- write to file
super_full_min:Write("tmp_elevator_super_full.gen")

-- report
print("elevator: full supervisor statistics")
super_full_min:WriteStatistics()

Resulting Supervisor Sfull

Simulation

A shell script elevator_simulation.sh and a configuration file elevator_supervisor.sim are prepared to run a simulation on the supervisor. The simulation also includes the plant components Gcabin and Gdoor to monitor the plant state. The below log shows the elevator moving from the the lower level to the upper level incl. door operations.

$ cd ./libfaudes/plugins/iodevice/tutorial
$ ./elevator_simulation.sh -v
% simfaudes: ========================================== found generator #1: cabin
% simfaudes: ========================================== found generator #2: door
% simfaudes: ========================================== found generator #3: supervisor (full)
...
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleOp"      1              </DiscreteState> 
% simfaudes: ========================================== enabled events:
<EnabledEvents> "d_lbbl"      "o_upb"       "o_lwb"        </EnabledEvents> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command:

The simulator starts in its initial state, where the first two components refer to the cabin and the door respectively. The third component is the supervisor state. All enabled events are sensor events and cofigured to have a negative priority. Hence, the simulation will not propose to execute either of them automatically. We decide to manually issue a o_upb event, i.e. the operator presses the upper button. The simulator proposes to execute the synchronisation event a_start and to turn on the button lights. We accept the proposal by hitting the return key.

% simfaudes: ========================================== enter command: o_upb
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleOp"      34             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "a_start" </ProposedEvent>
% simfaudes: ========================================== enter command: a_start
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleOp"      69             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "o_uplon" </ProposedEvent>
% simfaudes: ========================================== enter command: o_uplon
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleOp"      30             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "o_lwlon" </ProposedEvent>
% simfaudes: ========================================== enter command: o_lwlon
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleOp"      64             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "d_close" </ProposedEvent>
% simfaudes: ========================================== enter command:

In the remaining log, the simulator closes the door, drives the cabin upstairs and opens the door again. As above, sensor events must be chosen manually, actuator events are proposed by the simulator. The simulation ends with door opened and the cabin upstairs, while waiting for sensor events (e.g. an operator button).

% simfaudes: ========================================== execute event: d_close
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "CloseOp"     16             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: d_lvop
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "CloseMd"     55             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: d_arcl
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "CloseCl"     26             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "d_stp" </ProposedEvent>
% simfaudes: ========================================== enter command: d_stp
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleCl"      27             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "a_close" </ProposedEvent>
% simfaudes: ========================================== enter command: a_close
% simfaudes: ========================================== current state:
<DiscreteState> "IdleLw"      "IdleCl"      2              </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "c_up" </ProposedEvent>
% simfaudes: ========================================== enter command: c_up
% simfaudes: ========================================== current state:
<DiscreteState> "UpLw"        "IdleCl"      8              </DiscreteState> 
% simfaudes: ========================================== proposed action: 
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: c_lvlw
% simfaudes: ========================================== current state:
<DiscreteState> "UpMd"        "IdleCl"      81             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: c_arup
% simfaudes: ========================================== current state:
<DiscreteState> "UpUp"        "IdleCl"      100            </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "c_stp" </ProposedEvent>
% simfaudes: ========================================== enter command: c_stp
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleCl"      25             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "d_open" </ProposedEvent>
% simfaudes: ========================================== enter command: d_open
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "OpenCl"      98             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: d_lvcl
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "OpenMd"      57             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command: d_arop
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "OpenOp"      90             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "d_stp" </ProposedEvent>
% simfaudes: ========================================== enter command: d_stp
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleOp"      40             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "a_open" </ProposedEvent>
% simfaudes: ========================================== enter command: a_open
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleOp"      82             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "a_done" </ProposedEvent>
% simfaudes: ========================================== enter command: a_done
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleOp"      49             </DiscreteState> 
% simfaudes: ========================================== proposed action: 
<ProposedEvent> "o_uploff" </ProposedEvent>
% simfaudes: ========================================== enter command: o_uploff
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleOp"      76             </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedEvent> "o_lwloff" </ProposedEvent>
% simfaudes: ========================================== enter command: o_lwloff
% simfaudes: ========================================== current state:
<DiscreteState> "IdleUp"      "IdleOp"      3              </DiscreteState> 
% simfaudes: ========================================== proposed action:
<ProposedTime> inf </ProposedTime>
% simfaudes: ========================================== enter command:

libFAUDES 2.16b --- 2010-9-8 --- plugins "example synthesis observer diagnosis hiosys multitasking timed simulator iodevice luabindings"