ABSTRACT - abo.fi

161
I ABSTRACT ÅBO AKADEMI UNIVERSITY Faculty of Mathematics and Natural Sciences Department of Computer Science Author: Leonidas Tsiopoulos Title: UML Modeling of Control Systems Master of Science Thesis, 65 pages Supervisor: Assistant Professor Marina Waldén March 2003 The Unified Modeling Language (UML) has become the de facto standard for modeling software and hardware systems. It is a graphical language for specifying, visualizing, developing and documenting complex systems. Moreover, UML has been used successfully by the industry in order to ease the development process of large systems. The aim of this thesis is to present how the Unified Modeling Language (UML) can be used for modeling industrial strength control systems, from initial specification to implementation through refinement steps. Use cases, component, class and statechart diagrams have been used to model the system, and the U2B (UML to B) tool, developed at Southampton University, is used to translate the class and statechart diagrams to B code in order to be able to verify them. As a case study, a part of a liquid handling workstation for health care clinicians and researchers has been developed. Moreover, because this workstation is a safety critical system, safety analysis is incorporated into the system in order to develop it.

Transcript of ABSTRACT - abo.fi

Page 1: ABSTRACT - abo.fi

I

ABSTRACT ÅBO AKADEMI UNIVERSITY Faculty of Mathematics and Natural Sciences Department of Computer Science Author: Leonidas Tsiopoulos Title: UML Modeling of Control Systems Master of Science Thesis, 65 pages Supervisor: Assistant Professor Marina Waldén March 2003 The Unified Modeling Language (UML) has become the de facto standard for modeling software and hardware systems. It is a graphical language for specifying, visualizing, developing and documenting complex systems. Moreover, UML has been used successfully by the industry in order to ease the development process of large systems. The aim of this thesis is to present how the Unified Modeling Language (UML) can be used for modeling industrial strength control systems, from initial specification to implementation through refinement steps. Use cases, component, class and statechart diagrams have been used to model the system, and the U2B (UML to B) tool, developed at Southampton University, is used to translate the class and statechart diagrams to B code in order to be able to verify them. As a case study, a part of a liquid handling workstation for health care clinicians and researchers has been developed. Moreover, because this workstation is a safety critical system, safety analysis is incorporated into the system in order to develop it.

Page 2: ABSTRACT - abo.fi

II

FOREWORD The work described in this Master of Science Thesis was done in cooperation with PerkinElmer Life Sciences in Turku, Finland. I would like to thank Lasse Laine, Peter Nylund and Nils Kullberg for their guidance and comments during this work. Also, I would like to thank Colin Snook from Southampton University for offering his UML to B Method translation tool to be used for this work. Special thanks to my thesis supervisor Assistant Professor Marina Waldén. Without her support and advices this thesis would not have been written. I would like also to thank the people working at the department of Computer Science and the Turku Centre for Computer Science (TUCS) for the excellent working conditions and inspiring atmosphere. I am thankful for the love and support from my family, relatives, friends and my Mervi.

Page 3: ABSTRACT - abo.fi

III

TABLE OF CONTENTS ABSTRACT........................................................................................................................I FOREWORD.................................................................................................................... I I TABLE OF CONTENTS...............................................................................................I I I TABLE OF FIGURES....................................................................................................VI Appendices......................................................................................................................VI I 1 Introduction.............................................................................................. 1 1.1 Background ............................................................................................................1

1.2 Structure of This Work .........................................................................................2 2 The Unified Modeling Language............................................................ 4 2.1 Use Cases.................................................................................................................4 2.1.1 Actors................................................................................................................5 2.1.2 Flow of Events...................................................................................................5 2.1.3 Scenarios...........................................................................................................5 2.2 Component Diagrams............................................................................................5 2.3 Class Diagrams.......................................................................................................6 2.4 Collaboration Diagrams........................................................................................7 2.5 Statechar t Diagrams..............................................................................................8 3 The Action Systems Formalism.............................................................. 9 3.1 Actions.....................................................................................................................9 3.2 Enabledness of actions...........................................................................................9 3.3 Action Systems.....................................................................................................10 4 The B Method......................................................................................... 11 4.1 Abstract Machine Specification..........................................................................11 4.2 Machine Refinement and Implementation ........................................................13 4.3 Structur ing Mechanisms in B .............................................................................15 5 B-action Systems.................................................................................... 17 5.1 Procedures in B-action systems..........................................................................18 5.2 Refinement of B-action Systems.........................................................................19 6 Tool suppor t ........................................................................................... 21 6.1 Rational Rose Enterpr ise Edition Tool ..............................................................21 6.2 U2B Tool .............................................................................................................. 22 6.3 Tools suppor ting the B Method ..........................................................................24

Page 4: ABSTRACT - abo.fi

IV

7 Modeling Control Systems.................................................................... 25 7.1 Determining the controller and the plant ..........................................................26 7.2 Determining sensors and actuators....................................................................26 8 Presentation of the Wallac case study.................................................. 28 8.1 The requirements of the case study...................................................................29 8.2 The integrated development process proposed for the case study .................30 8.3 Safety aspects of the development .....................................................................30 8.4 Presence of failures.............................................................................................32 9 UML-development incorporating safety aspects................................ 33 9.1 Use cases incorporating the possible failures...................................................34 9.2 Component-or iented development ....................................................................36 9.3 Class diagram of the specification.....................................................................37 9.4 Collaboration diagram of the Stackers.............................................................38 9.5 Statechar t Diagrams of the specification ..........................................................39

9.5.1 The Rotary Table ...........................................................................................39 9.5.2 The Stacker ....................................................................................................40 9.6 U2B translation to B-action systems and formal specification of the

system...................................................................................................................41 9.7 Formal specifications and safety analysis.........................................................43 10 Refining the system.............................................................................. 45 10.1 Class diagrams of the first refinement of the system.....................................45

10.1.1 The Rotary Table ........................................................................................45 10.1.2 The Stacker unit ..........................................................................................48 10.2 Statechar t Diagrams of the first refinement...................................................48

10.2.1 The Rotary Table ........................................................................................48 10.2.2 The Stacker unit ..........................................................................................50

10.3 U2B translation to B-action systems and first refinement of the system.....52 10.4 Safety issues for the first refinement ...............................................................54 10.5 Class diagram of the second refinement step of the Rotary Table...............55 10.6 Statechar t diagram of the second refinement for the Rotary Table............57 11 Control System development .............................................................. 58 11.1 Decomposition of the Rotary Table.................................................................58

11.1.1 Determining controller and plant ...............................................................58 11.1.2 Class diagram of the controller and plant specifications...........................58 11.1.3 Statechart diagram of the Rotary Table plant ............................................59 11.1.4 U2B translation to B-action systems...........................................................59

11.2 Determining sensors and actuators................................................................60 11.2.1 Class diagram of the final control system...................................................60 11.2.2 Statechart diagram of the plant & the B-action system of the final control

System .........................................................................................................61

Page 5: ABSTRACT - abo.fi

V

12 Conclusions........................................................................................... 62 References............................................................................................. 63

Page 6: ABSTRACT - abo.fi

VI

Table of Figures Figure 1. A use case diagram...............................................................................................4 Figure 2. A component diagram..........................................................................................6 Figure 3. Class Diagram ......................................................................................................7 Figure 4. Collaboration Diagram.........................................................................................7 Figure 5. Statechart diagram................................................................................................8 Figure 6. The structure of an abstract machine specification ............................................12 Figure 7. The structure of a machine refinement...............................................................14 Figure 8. M2 includes M1 [Schneider01] ..........................................................................15 Figure 9. M2 sees M1 [Schneider01] .................................................................................16 Figure 10. An action system A and its embedding to a B machine [WS98] ......................17 Figure 11. Declaration of a global variable z in B [WS98] ...............................................18 Figure 12. Procedures in B-action systems........................................................................18 Figure 13. The refined B-action system [WS98, PTWBEJ01] ..........................................19 Figure 14. Rational Rose Window.....................................................................................22 Figure 15. U2B Translation for the class STATION of Figure 14....................................23 Figure 16. Feedback Control [SG96] .................................................................................25 Figure 17. The structure of the control system specification.............................................25 Figure 18. General decomposition schema [Sekerinski99] ...............................................27 Figure 19. The Fillwell workstation [Fillwell02] ..............................................................28 Figure 20. Top view of the Rotary Table...........................................................................29 Figure 21. Safety analysis and stepwise system development [PTWBEJ01] ....................31 Figure 22. Use case diagram for the Stacker .....................................................................33 Figure 23. Use case diagram for the Rotary Table............................................................34 Figure 24. A component diagram for the Rotary Table and a Stacker ..............................37 Figure 25. Specification Class Diagram for Rotary Table and Stacker.............................38 Figure 26. Collaboration Diagram for the Stackers...........................................................38 Figure 27. Specification Statechart Diagram for the Rotary Table ...................................39 Figure 28. Specification Statechart Diagram of a Stacker for the stack service................40 Figure 29. Class Diagram of the Stacker ...........................................................................42 Figure 30. Position of plate holders after a two steps rotation...........................................46 Figure 31. A part of the 1st refinement statechart diagram for rotate service....................49 Figure 32. A part of the 1st refinement statechart diagram for stack service.....................51 Figure 33. Specification for “ role A” of the association end.............................................53 Figure 34. Proof Obligations generated by Atelier B for the first refinement of the Rotary Table......................................................................................................54 Figure 35. Proof Obligations generated by Atelier B for the first refinement of the Stacker unit .......................................................................................................54 Figure 36. Proof Obligations generated by Atelier B for the second refinement of the Rotary Table......................................................................................................57 Figure 37. Proof Obligations generated by Atelier B for the Rotary Table Control System..................................................................................................61

Page 7: ABSTRACT - abo.fi

VII

Appendices A Statechar t diagram of Stacker for the destack service 66 B The specification of the Rotary Table and the Stacker unit as B-action

Systems 67 B.1 The specification of the Rotary Table 67 B.2 The specification of the Stacker unit 70 B.3 The sets of commands for the Rotary Table and the Stacker unit 80 C The first refinement of the system - Diagrams 81 C.1 The class diagram 81 C.2 The statechart diagram of the 1st refinement for the rotate service of the

Rotary Table 82 C.3 The class diagram of the 1st refinement for the Stacker unit 83 C.4 The statechart diagram of the 1st refinement of a Stacker for the destack

Service 84 C.5 The statechart diagram of the 1st refinement of a Stacker for the stack

service 85 D The first refinement step of the Rotary Table and the Stacker unit 86 D.1 The refined Rotary Table 86 D.2 The procedure class machine PLATEHOLDER of the Rotary Table

refinement 90 D.3 The first refinement of the Stacker unit 94 D.4 The procedure class machine of the Stacker unit 108 D.5 The procedure machine of the XYZ driver for the Dispensing Head 109 D.6 The Z driver class of the Dispensing Head’s XYZ driver 110 D.7 The sets and constants of the Rotary Table & the Stacker unit 112 E The second refinement of the Rotary Table – Diagrams 114 E.1 The class diagram 114 E.2 The statechart diagram 115 F The second refinement step of the Rotary Table 116 F.1 The second refinement machine 116 F.2 The updated procedure class of the Rotary Table 120 F.3 The procedure class PLATE of the Rotary Table 125 F.4 The updated DEF2 class 126 G The control system decomposition of the Rotary Table – Diagrams 128 G.1 The class diagram of the plant & controller decomposition of the

Rotary Table 128 G.2 The statechart diagram of the plant of the Rotary Table 129 H The decomposition of the control system of the Rotary Table 130 H.1 The plant of the Rotary Table 130

Page 8: ABSTRACT - abo.fi

VIII

H.2 The controller of the Rotary Table 134 H.3 The updated DEF2 class 137 I The decomposition of the sensors & actuators of the Rotary Table – Diagrams 139 I.1 The class diagram of the sensor & actuator decomposition of the Rotary Table 139 J The decomposition of sensors & actuators 140 J.1 The Rotary Table plant refinement 140 J.2 The refined controller of the Rotary Table 143 J.3 The updated procedure class PLATEHOLDER2 of the Rotary Table 146 J.4 The sensor Z_SENSOR of the Dispensing Head driver 150 J.5 The actuator of the Rotary Table 151

Page 9: ABSTRACT - abo.fi

1

1 Introduction The purpose of this Master of Science thesis is to present how the Unified Modeling Language (UML) can be used for modeling industrial strength control systems, from initial specification to implementation through some refinement steps. Usually such a development method is not obvious, nor straightforward to obtain for a complex final system, given only the initial requirements. Using UML for the whole development process provides the developer(s) with good documentation, which is required in order to enable smoother evolution and reuse of the produced system. The work presented in this thesis has been done within the MATISSE1 project. 1.1 Background The Unified Modeling Language (UML) [BRJ99, UML1.4] is the accepted standard for the development of object – oriented software. It combines very important software engineering techniques, such as use cases, classes as well as statecharts. These techniques consist of a number of diagrams that help the programmer to specify, develop, maintain and reuse software. UML has been used successfully by the industry for the modeling of complex systems. A drawback of UML is that it does not have specific semantics, so the use of (UML specific) tools is inevitable, which are important in order to be able to verify the various kinds of UML diagrams. Such tools are Rational Rose [Rational03], which is used in this Thesis, and Rhapsody [Rhapsody03]. Another tool [SB03], which translates UML class diagrams to B Method code, is used so that these kinds of diagrams can be formally proved correct. The purpose of a control system is to maintain specified properties of the outputs of the process at given reference values called the set points [SG96]. Properties such as temperature, pressure, height and flow rates are monitored, and their values are used to control the process. Control systems consist of a number of entities embodying specific functions and properties that interact with each other to obtain the desired functionality and cooperation [BSS96].These entities are the sensors, the actuators, the controllers and the plants. Having these interactive entities, it is helpful to incorporate an object-oriented development process, which is offered by UML. A slightly different approach on decomposing a control system is presented in [Brooks85] where the decomposition is based on task achieving behaviour. In this approach the different behaviours of the control system’s controller are decided after analyzing the computational requirements of the system. Then the information from the sensors is passed to the controller to perform various computations and finally the processed data is passed to the actuators. The control system developed in the case study of this Thesis is part of a safety-critical healthcare system. When developing safety-critical systems, it is important to fulfill not only functional requirements specifying the services to be performed by the system, but also safety requirements specifying the characteristics the system should take into account in order to ensure safety. Moreover, reliability is an issue of such a system. Reliability means the correct functioning of the system under given operating conditions 1 MATISSE: Methodologies and Technologies for Industrial Strength Systems Engineering. www.matisse.qinetiq.com, IST-1999-11435

Page 10: ABSTRACT - abo.fi

2

and it should ensure an extremely high precision and quality of the experiments to be performed. By applying formal methods, enhancement of the safety and reliability of the system can be achieved. Formal methods mathematically prove the functional, as well as the safety and reliability requirements of the system in every development step. Furthermore, the application of formal methods allows early error discovery and correction, resulting in a faster development process. One way to develop complex control systems is by stepwise adding details to the system, starting from a high-level specification proceeding to a final control system via correctness preserving refinement steps. The B-action systems [WS98] used is a formalism which supports this kind of development of control systems. Each refinement step is accompanied by proofs. The B Method [Abrial96] and its associated tool provide a good mechanized support for refinement based development. Moreover, the B Method has been successfully used in industrial projects. Modeling the plant and the controller initially as a single B-action system allows the developer to abstract away from the communication mechanisms between them. Only in later refinement steps, an explicit mechanism for passing the values of sensors from the plant to the controller is introduced. 1.2 Structure of This Work This thesis approaches its topic with the classical top-down method starting from an abstract level describing the theory and the tools used, and gradually introducing the details. Chapter 2 describes the UML diagrams being used for the development of the control system. These are use case diagrams, component diagrams, class diagrams, collaboration diagrams, as well as statechart diagrams. Chapter 3 presents briefly the Action Systems formalism because it is the base, together with the B Method, for the B-action Systems formalism used in order to be able to verify the translated UML diagrams. What an action can be, when an action is enabled, as well as what an action system is, is explained. Chapter 4 gives a brief introduction to the B Method. What can be in an Abstract Machine Specification, as well as in a Machine Refinement and Implementation, is explained. Also, the structuring mechanisms of the B Method used in this Thesis are present. Chapter 5 describes the B-action Systems formalism. Specifically, procedure calls in B-action systems are described, as well as refinement of B-action Systems. Chapter 6 presents the tools used in the case study for the development process. The Atelier B support tool for the B Method is described, a brief presentation of the UML development tool, Rational Rose, is given, and a short description of the UML to B

Page 11: ABSTRACT - abo.fi

3

(U2B) tool, which translates class and statechart diagrams, if they are attached to a class, is given, too. Chapter 7 explains how a control system is modeled after all the details have been introduced to the system. The process of determining the plant and the controller, as well as the sensors and the actuators of the control system is explained. Chapter 8 presents the case study, the requirements of it and the integrated development process proposed for the case study. Moreover, in this chapter a description is given of how the safety aspects of the development are fulfilled. Chapter 9 tells how the UML development incorporates the safety aspects. The technical report [PTWBEJ01] was used as the basis to perform the safety analysis of the system in this case study, because it consists of the safety analysis and safety requirements of an other part of the same system being developed within the MATISSE project. Moreover, the component-oriented development is given, together with the class and statechart diagrams of the specification. An abstract collaboration diagram of part of the system is given, too. Furthermore, the translated B-action systems of the formal initial specification of the system are described, as well as what was required by U2B in order to translate the diagrams correctly. Chapter 10 presents the refinement steps of the development of the system. The system developed as a case study consists of two parts. One part was developed until the first refinement, while the other was developed completely. The safety issues concerning the refinements are presented, too, as well as the features required by U2B for the translation. Chapter 11 covers the control system development. The class and the statechart diagrams of the control system are described together with the translated B-action systems. This control system development consists of two steps. First, the controller and the plant are determined and then the sensors and the actuators of the system are also determined. Chapter 12 consists of concluding remarks.

Page 12: ABSTRACT - abo.fi

4

2 The Unified Modeling Language The Unified Modeling Language (UML) [BRJ99, UML1.4] has become the de facto standard notation for describing analysis and design models of software systems, as well as for documenting them. UML consists of a number of diagrams focusing on different aspects of the system independently. These diagrams can be separated into two groups depending on whether they are intended to describe structural or behavioural aspects. Major features of UML include use cases and scenarios, behavioral modeling with statecharts, packaging of various kinds of entities, object model, representation of tasking and task synchronization, models of physical topology, as well as support for object-oriented patterns. This thesis focuses on the UML diagrams that are most relevant for modeling control systems. In the case study an example of their use is shown. Comprehensive studying of UML can be obtained elsewhere [BRJ99, Douglass99, SP00]. 2.1 Use Cases Use cases specify desired behaviour of the system, without showing how that behaviour will be carried out and they let us focus on the issues of highest risk. A use case represents a functional requirement of the system as a whole. A use case is a set of actions, including variations, which a system performs to yield an observable result of value to an actor. A set of actions represents the interaction of its actors outside the system (its actors) with the system itself. These actions are in effect system level functions that are used to visualize, specify, construct and document the intended behaviour of the system during requirements capture and analysis. Furthermore, every use case must have a name that distinguishes it from other use cases. Figure 1 below illustrates a case with three use cases, service 1, service 2 and service 3, as well as an actor.

Actor

Service 1

Service 2

Service 3

Figure 1. A use case diagram.

Page 13: ABSTRACT - abo.fi

5

2.1.1 Actors A use case can have an actor, which might be a human, a hardware device, or even another system. An association relationship between an actor and a use case indicates that the actor and the use case communicate with one another. Figure 1 above consists of three use cases Service 1, Service 2, and Service 3, as well as an actor interacting with them. 2.1.2 Flow of Events The flow of events can specify the behaviour of a use case. In the description of the flow of events, the start and the end of the use case should be included, as well as the interactions between the actors and the use case. Moreover, which objects are exchanged, the basic flow and alternative flows of the behaviour should be included in that flow of events. 2.1.3 Scenarios In a complex system, like the one described in the case study of this thesis, it is often desirable to separate main versus exceptional flows of events. This is due to the fact that a use case describes a set of sequences and it would be impossible to express all the details of a complex use case in just one sequence. As an example of scenarios, two sequences of a loan system are shown below [SP00].

• Book borrower X borrows the library’s second copy of book z, when she has no other book on loan. The system is updated accordingly.

• Book borrower Y tries to borrow the library’s first copy of book w, but is refused because he already has 5 books out on loan, which is the maximum allowance.

From the above example, each book borrower can be related to the actor of the Figure 1 and each book loan service to the services of the same diagram. A sequence from the set of sequences represents one possible flow of events through all these variations. Each sequence is called a scenario.

2.2 Component Diagrams The use case diagrams show only the specified services and their relationships, while the component diagram distributes the services among a set of components that will implement them. The component diagram is deduced from the use case diagram and the component interactions are deduced from the use case relationships. Each use case can be mapped to a component service. A component is an abstraction over the space of services of a system, which are captured by the use case diagram. The components interact with each other via the provided services. Figure 2 below shows a simple component diagram where component Comp_A interacts with component Comp_B via the service Service 1 offered from Comp_A. The service Service 2 is local to the component Comp_A. A specification language will be used to specify the components in a precise manner.

Page 14: ABSTRACT - abo.fi

6

Comp_A

Comp_B

Figure 2. A component diagram. 2.3 Class Diagrams A class is a description of a set of objects that share the same attributes, operations, relationships, and semantics [BRJ99]. The class can be a description of only one object depending on the requirements of the system. Class diagrams are the most common diagrams for modeling object-oriented systems. These diagrams are used to model the static design view of a system and they are the foundation for component diagrams, because they consist of operations, which are actually the services of a component. A class diagram consists of classes and relationships such as dependency, generalization, association and realization relationships. In this Thesis we concentrate on association, dependency and realization relationships, because U2B requires them in order to translate correctly the diagrams to B code. An association relationship between two classes specifies that the objects of one class are connected to the objects of the other class and vice versa [BRJ99]. A dependency relation between two classes A and B means that class A depends on class B, if a change to class B may force a change to class A [SP00]. A realization relationship is a semantic relationship between two classes in which one class specifies a contract that the other class guarantees to carry out [SP00]. A class consists of a name, a set of attributes and a set of operations that may have parameters. Every class c may either define a set of objects called the instances of c, or a single object, depending on its multiplicity. A class diagram [SB02] with a class STATION and a class PLATFORM with an association relationship between them can be seen in Figure 3 below. A station can have several platforms. When a train arrives it is sent to any of the available platforms. If no platform is available it is queued until a platform is freed by a train departing. A platform is available when it has no trains and occupied when it has one train. If a second train arrives at a platform or if a train arrives at a closed platform, there is a crash. A platform can be closed if it has no trains at it and then opened again.

Service1

Service2

Page 15: ABSTRACT - abo.fi

7

PLATFORM t r a i n s : POW ( TRAI N ) = { }

a r r i v a l ( t t : TRAI N ) d e p a r t u r e ( ) c l o s e p l a t f o r m ( ) o p e n p l a t f o r m ( )

S TATI ON q u e u e : s e q ( TRAI N ) = < >

t r a i n _ a r r i v e s ( t t : TRAI N ) : o u t c o m e t r a i n _ d e p a r t s ( p p : PLATFORM) n e x t _ t r a i n ( ) a d d _ p l a t f o r m ( p p : PLATFORM)

0 . . n

+ p l a t f o r m s 0 . . n

Figure 3. Class Diagram. When crashed, opening the platform will clear any trains from that platform and make it available if it had two trains at it, or make it closed if it had more than two trains. 2.4 Collaboration Diagrams While a class is a description of a set of objects that share the same attributes, operations, relationships, and semantics, collaboration diagrams contain objects and links between them. A collaboration diagram corresponds to a class diagram if the objects are instances of the classes, the links can be mapped to the associations, and the multiplicity requirements of the class diagram are satisfied. These diagrams are useful to represent the cooperation between objects and the state of a system at a special moment of time. A collaboration diagram associated with the class diagram, given in Figure

s tation

p l atf o r m 1

p l atf o r m 2

tr ain a tr ain b

1:

3 :

4 :

2 :

Figure 4. Collaboration Diagram.

3, can be seen in Figure 4 [SB02]. In the diagram in Figure 4 there are five objects. The station, platform 1, platform 2, train a, and train b. The links and the messages sent between the objects can be seen, in conformance to the class diagram. The numbers in the diagram show in which sequence the messages are sent.

Page 16: ABSTRACT - abo.fi

8

2.5 Statechar t Diagrams

In class diagrams the static behaviour of a system is modeled. The dynamic behaviour of a system can be modeled with statechart diagrams. A statechart diagram shows a state machine, emphasizing the flow of control from state to state. Generally, they can be associated with classes in order to describe the dynamic behaviour of the objects of the classes. Moreover, they can be related to use cases to model a scenario. Statechart diagrams consist of simple states and composite states and transitions, including events and actions. A state is an object state, which reflects a situation in the life of an object during which this object satisfies some condition, performs some action, or waits for some event. The transitions specify state changes and more specifically, they are viewed in UML as relationships between two states indicating that an object in the first state will enter the second state and perform given actions when an event occurs, provided certain conditions, i.e. guards, are satisfied. A simple statechart diagram [SB02] associated with the class PLATFORM in Figure 3 is given below in Figure 5. The operations of the class PLATFORM are given as transitions in the statechart diagram. Furthermore, one operation may correspond to several transitions in the statechart diagram.

Initial

av ailab le c lo s e d

o c c u p ie d c r as h e d

o p e np latf o r m [ c ar d ( tr ains ) = 2 ] / tr ains : = { }

o p e np latf o r m [ c ar d ( tr ains ) > 2 ] / tr ains : = { }

ar r iv al

c lo s e p latf o r m

o p e np latf o r m

ar r iv al

d e p ar tu r e

ar r iv al

arrival Figure 5. Statechart diagram.

Let us consider the transition from state crashed to state available. In order for the transition openplatform to occur certain conditions have to hold, i.e., the number of trains to be equal to two, or bigger than two. Then the resulting state after the transition is either available or closed, respectively. In both cases the performed actions are the same, i.e. the value of the empty set is assigned to the variable trains.

Page 17: ABSTRACT - abo.fi

9

3 The Action Systems Formalism In order to understand the B-action systems formalism, which is used in this Thesis to verify the development steps of the case study, a basic understanding of the action systems formalism is required. This formalism together with the B Method, described later, is the base of the B-action systems formalism. The action systems formalism is based on an extended version of Dijkstra’s language of guarded commands [Dijkstra75]. This language consists of assignment, conditional choice, sequential composition, as well as iteration, and is defined using weakest precondition predicate transformers. A complete study on the action systems formalism can be found elsewhere [BaKu83, BS94]. 3.1 Actions An action A can be of the following form A :═ abort (abortion) | skip (empty statement) | v := e (deterministic assignment) | v :═ v′.( v′ ∈ R ) (nondeterministic assignment) | { P} (assert statement) | [P] (assumption) | A1 [] A2 (nondeterministic choice) | A1; A2 (sequential composition) where P and R are predicates and v is a variable or a list of variables [WS98, PS99]. A1 and A2 are actions. The weakest precondition for predicate transformers is applied in order to define the actions. The operators are defined below [WS98]. wp( abort, Q ) ═ false wp( skip, Q ) ═ Q wp( v :═ e, Q ) ═ Q[v :═ e] wp(v :═ v′.( v′ ∈ R ), Q) ═ (∃ v′∈ R) ∧ (∀ v′. v′ ∈ R. Q[v :═ v′]) wp( { P} , Q) ═ P ∧ Q wp( [P], Q) ═ P ⇒ Q wp((A1 [] A2), Q) ═ wp(A1, Q) ∧ wp(A2, Q) wp((A1; A2), Q) ═ wp(A1, wp(A2, Q)) Actions are considered to be atomic, which means that only their input-output behaviour is of interest. Furthermore, it means that whenever an action is selected for execution it will be completed without interference. 3.2 Enabledness of actions The guard gdA of an action A describes those states for which the action is enabled and is defined by [PS99]

Page 18: ABSTRACT - abo.fi

10

gdA = ¬wp(A, false). The action A is enabled in a state, where the guard is true. Actions are in general guarded commands, i.e., statements of the form A = g → S, where g is a boolean condition and S is a program statement. The guarded command g → S is defined as follows using assumption: g → S = [g];S Thus, the guard of A is g ∧ ¬wp(S, false). Hence, a guarded command g → S is only enabled when S is enabled and g holds. Furthermore, the nondeterministic choice A1 [] A2 is enabled when either A1 or A2 is enabled [WS98]: gd(A1 [] A2) = gd(A1) ∨ gd(A2) The body bd(A) of A is defined by bd(A) = gd(A) → A [] ¬gd(A) → abort 3.3 Action Systems An action system is a set of actions operating on local and global variables and has the form: A = |[ var z* , x; z, x := z0, x0; do A1 [] … [] An od ]|: u The action system A contains the local variables x, the exported global variables z, marked with * , and the imported global variables u. The local variables x are visible only within A, in contrast to the exported global variables z which are visible to other action systems as well. The imported global variables, u, are referenced in the actions A1,…, An, but they are not declared in A. The local and global variables are assumed to be distinct, meaning that no redeclaration of variables is permitted. The actions Ai are allowed to refer to all the state variables of the action system A. If the action system A does not have any global variables, it is said to be a closed action system, otherwise, it is open. Moreover, each action can have local variables of its own. Also, an action is called local to an action system, if it only refers to local variables of that action system.

Page 19: ABSTRACT - abo.fi

11

4 The B Method After the brief description of the action systems formalism, an overview of the B Method is given here. The B Method [Abrial96] is a formal approach to the specification and development of computer software systems. B takes into consideration advances in formal methods appeared during the last thirty years, including the Z notation, pre and post conditions, guarded commands [Dijkstra75], stepwise refinement, the refinement calculus [BaWright98], and data refinement [Schneider01]. A program development in the B Method consists of a specification, probably a number of refinements and an implementation. The specification is very abstract and involves a lot of non-determinism. The refinements transform stepwise the specification into an implementation. The implementation represents the final refinement and it is not allowed to contain any non-determinism. Within the B Method the specification, the refinements and the implementation have the form of abstract machines, which consist of global constraints and of operations on the state variables. The Abstract Machine Notation (AMN) is identical with the guarded command notation extended with precondition and unbounded choice. Every statement in AMN is a form of substitution [WS98]. It can be for example a skip-substitution, a simple substitution (x := e), a preconditioned substitution (PRE P THEN S END), or a guarded substitution (SELECT P THEN S END), where x is a variable, e is an expression, P is a predicate and S is a substitution. Every substitution S is defined as a predicate transformer, which transforms a postcondition Q into the weakest precondition for S to establish Q, wp(S, Q). The substitutions above are defined as follows: wp(skip, Q) = Q, wp(x:= e, Q) = Q[x := e], wp(PRE P THEN S END, Q) = P ∧ wp(S, Q), and wp(SELECT P THEN S END, Q) = P ⇒ wp(S, Q). At this point the similarity between the B Method and the Action Systems formalism, described above, can be seen, i.e. the weakest preconditions are the same . The structure of the specification, the refinement and the implementation are described below. 4.1 Abstract Machine Specification The basic building block of a specification is the abstract machine. A specification describes what the component can do. The abstract machine contains information that describes various aspects of the specification, listing them under appropriate headings. The operations of a specification describe the functions/services that can be carried out by the component. The collection of operations is the interface by which the machine interacts with its environment. Moreover, it is important to note that a machine is a description of an object in the object-oriented sense. It has a name, some internal state, and a set of operations. The MACHINE clause provides the name of the machine, which is useful in order for other machines to be able to reference that machine. It is necessary that all machines in a

Page 20: ABSTRACT - abo.fi

12

development have different names. A machine can have some parameters f for giving dimensional characteristics of the specification. These parameters are of type natural numbers or sets. The set of constraints F on the parameters f are given in the CONSTRAINTS clause. Moreover, constants c can be introduced in the CONSTANTS clause and the PROPERTIES clause gives the definition C of these constants c. An abstract machine has variables by which some local state information can be maintained. A variable may be of type NAT, which is the set of natural numbers, of type BOOL, as well as of type deferred set. All the variables are listed in the VARIABLES clause. Their types, as well as any other constraints, are given in the INVARIANT clause. The INVARIANT clause provides all the information about the variables of the machine. It has to give types of all the variables, and it can additionally give other restrictions on their possible values, and their relationships to each other. Furthermore, relationships among the variables and other parts of the system can be described in the invariant. The state of the variables can be changed by the machine, but the invariant describes properties of the variables, which must always hold. The INITIALISATION clause is used to describe the initial state of all the variables of the machine. All variables listed in the VARIABLES clause must be assigned some value. The possible initial states must be correct with respect to the invariant, in order for the INITIALISATION clause to be a consistent part of the specification.

Figure 6. The structure of an abstract machine specification. The OPERATIONS clause of the machine description consists of a list of operation definitions. A B description of an operation contains the information in a form which is

MACHINE Machine_name(f) CONSTRAINTS F CONSTANTS c PROPERTIES C VARIABLES x INVARIANT I INITIALISATION T OPERATIONS Operation_name = PRE P THEN S END; . . . END

Page 21: ABSTRACT - abo.fi

13

suited to structuring. The name, as well as input and output parameters of an operation are given by an operation header. outputs ← name(inputs) Where name is the name of the operation, outputs is a list of output parameters, and inputs is a list of input parameters. The variables are all formal parameters and they must be different. The structure of an abstract machine specification is shown in Figure 6 above. In order to prove that the machine Machine_name from the Figure 6 is consistent with its specification, a number of proof obligations are generated [WS98]: (C1) (∃ f. F) (C2) F ⇒ (∃ c. C) (C3) (F ∧ C) ⇒ (∃ x. I) (C4) (F ∧ C) ⇒ wp(T, I) (C5) (F ∧ C ∧ I ∧ P) ⇒ wp(S, I) The first three proof obligations are concerned with the consistency of the formal parameters, the constants and the variables. The obligation (C4) checks that the invariant is initially established and the condition (C5) checks that each operation preserves the invariant. 4.2 Machine Refinement and Implementation The B Method supports the notion of stepwise refinement, in which the design of the system implementation may be developed gradually. Specifically, a high level specification of a program may be transformed by a sequence of correctness preserving transformations into an executable program that satisfies the original specification [BS89]. A refinement in the B Method may either be a data refinement or an algorithmic refinement. The data refinement is achieved by changing the variables and the operations on them, while the algorithmic refinement permits the operations to change in order to make them more concrete without changing the state space. The structure of a machine refinement Refinement_name is shown in Figure 7 given below. It can be seen that a machine refinement and a machine specification have the same clauses, except that a machine refinement states in the REFINES clause which machine it refines. Also, the invariant R of the refinement gives the relation between the variables of the two machines in the data refinement. Hence, the invariant R in Figure 7 gives the relation between the abstract variables x in the machine specification Machine_name in Figure 6 and the concrete variables x′ in the machine refinement Refinement_name. Furthermore, the operations of the machine refinement refer only to the concrete variables x′. The operation signatures in the abstract machine Machine_name and its refinement Refinement_name have to be identical, which means that the corresponding operations in Machine_name and Refinement_name must have the same names. If the operations have

Page 22: ABSTRACT - abo.fi

14

parameters, these must be the same, too. Furthermore, all the operations that exist in the final refinement must exist in the specification with their body given as skip.

Figure 7. The structure of a machine refinement.

In order to prove that the machine refinement Refinement_name in Figure 7 is a refinement of the machine specification Machine_name in Figure 6, within the B Method, a number of proof obligations must be satisfied: (B1) (∃(x, x′ ). I ∧ R), (B2) wp(T′, ¬wp(T, ¬R)), (B3) (∀(x, x′ ). (I ∧ R ∧ P) ⇒ P′ ), and (B4) (∀(x, x′ ). (I ∧ R ∧ P) ⇒ wp(S′, ¬wp(S, ¬R))). The proof obligation (B1) states that the invariant R of the refinement does not contradict the invariant I of the specification. Moreover, the proof obligation (B2) checks that the new initialization T′ establishes a situation where the previous initialization T cannot fail to establish the invariant R. Furthermore, the last two proof obligations ensure the correctness of each operation. The precondition P of the substitution S implies the precondition P′ of the substitution S′ when the invariants hold, i.e., the precondition is weakened in the refinement, (B3). Finally, a substitution S′ in the refined operation establishes a situation where the substitution S in the abstract operation cannot fail to maintain R, (B4). An implementation machine is the final refinement in a development within the B Method. The most important feature of an implementation is that the operations must not contain any nondeterministic substitutions. The notion of refinement between the machine implementation and another machine is the same as of refinement between the machine refinement and another machine, i.e., the proof obligations (B1) – (B4).

REFINEMENT Refinement_name REFINES Machine_name VARIABLES x′ INVARIANT R INITIALISATION T′ OPERATIONS Operation_name = PRE P′ THEN S′ END; . . . END

Page 23: ABSTRACT - abo.fi

15

4.3 Structur ing Mechanisms in B It is valuable to structure large specifications in order to control complexity. The B Method provides structuring mechanisms [Schneider01], which enables machines to be expressed as combinations of simpler machines and allow distinct parts to be described and understood separately. Furthermore, the internal consistency conditions can be verified independently. Also, good structuring of a specification can reduce the proof effort by factoring the proof obligations into the appropriate components. Moreover, the machine state can be separated into different machines, which will be responsible for the operations on their own part of the state. The mechanisms that B provides are the INCLUDES, EXTENDS, USES, and SEES. The relationship between two machines, where M2 INCLUDES M1 is illustrated in Figure 8. read access promoted operation operation update access call access

Figure 8. M2 includes M1 [Schneider01]. The machine M1 is considered to be part of the description of M2 and its state is part of the M2 state. The sets, constants and variables of M1 are visible to M2, and the invariant of M1 is implicitly included in the M2 invariant. Additionally, M1’ s variables can be updated only via M1’ s operations; hence, M1 is responsible for preserving its own invariant. The M2 initialization initializes all its included machines and executes its own initialization. The machine M1 is not allowed to reference sets, constants, variables, and operations of M2, so it should be defined independently of the machine M2. The bodies of the M2 operations can contain calls to any operation of M1, and the syntax of an operation call is

MACHINE M2

SETS CONSTANTS VARIABLES

INVARIANT

MACHINE M1

SETS CONSTANTS

VARIABLES

INVARIANT

PROPERTIES

PROPERTIES

Page 24: ABSTRACT - abo.fi

16

x1, x2, …← op(e1, e2,…) where e1, e2, … are value expressions, and x1, x2, … are distinct variables standing for actual result parameters. A machine can call several operations of included machines in one step, as long as those operations are from different machines. Moreover, inclusion is transitive, but access to operations is not transitive. If all the operations of the included machine M1 are to be promoted to operations of M2, then M2 EXTENDS M1. Promoted operations change only the state of the included machine. The SEES and USES structuring mechanisms allow read-only access between machines. In this Thesis only the SEES mechanism of these two is used. A machine can be accessed by a number of other machines. In this case, it is useful when part of the state is expressed as a separate machine and other machines require knowledge of that part of the state. The SEES relationship of M2 sees M1 is illustrated in Figure 9. The machine M2 is provided read access to machine M1, which means that sets, constants, and variables of M1 are visible in M2. Furthermore, the invariant of M2 can refer to sets and constants of M1 but not to M1 variables. Because M1 is not under control of M2, M1 variables can be changed independently of M2. Only query operations can be called from M2, and this because query operations do not make any changes to the state of M1. The SEES relation, unlike INCLUDES, is not transitive. Moreover, if M2 sees M1, it also sees any machines that M1 includes. read access call access

Figure 9. M2 sees M1 [Schneider01].

MACHINE M2

SETSCONSTANTS

VARIABLES

INVARIANT PROPERTIES

MACHINE M1 query

SETS CONSTANTS VARIABLES

PROPERTIES INVARIANT

Page 25: ABSTRACT - abo.fi

17

5 B-action Systems In order to be able to reason about distributed systems within the B Method, the B-action systems formalism is used. The B-action systems formalism has been used in this Thesis in order to verify the UML diagrams in each development step. In this formalism, a state-based view of action systems has been considered. Comprehensive study of this formalism can be found elsewhere [WS98]. In Figure 10 an action system is written as an abstract machine specification. Parallel and distributed systems can be modeled with the B-action systems formalism, where the operations are selected for execution in a non-deterministic manner. The form of the operations is Oper = SELECT P THEN S END, where P is a predicate on the variables (guard) and S is a substitution statement. When P holds the operation Oper is enabled. Only enabled operations are considered for execution and when there are no enabled operations the system terminates. The translation of the local variables x in the action system A to a variable of the machine specification ActionSystem is straightforward as can be seen in Figure 10. Moreover, each action in A is translated to an operation in the machine specification ActionSystem. In the A = |[ var z* , x; z, x := z0, x0; do [] gA1 → sA1

[] gA2 → sA2

[] gA3 → sA3 od ]|: u

Figure 10. An action system A and its embedding to a B machine [WS98]. B Method two machines are not allowed to update the same variable while the global variables of an action system may be referenced from other action systems. In B-action systems, the global variables, z and u, of A, are included as separate machines, Global_z and Global_u, respectively, in the machine ActionSystem. In the machine Global_z, in Figure 11, the exported global variable z is declared and given some properties J(z). Moreover, since a variable can only be updated in one machine, the variable z is assigned via the operation assign_z(v) in Global_z, where the value v is given as a parameter. The assignments to z in an action Ai of the action system A, are then replaced by calls to assign_z in the corresponding operations in the machine specification ActionSystem. Thus, more than one abstract machine can assign the same global variables via the calls to the corresponding operations.

MACHINE ActionSystem INCLUDES Global_z, Global_u VARIABLES x INVARIANT I(x, z, u) INITIALISATION x:=x0 OPERATIONS A1 = SELECT gA1 THEN sA1 END; A2 = SELECT gA2 THEN sA2 END; A3 = SELECT gA3 THEN sA3 END; END

Page 26: ABSTRACT - abo.fi

18

Figure 11. Declaration of a global variable z in B [WS98]. 5.1 Procedures in B-action systems Procedures can be declared in a B-action system, too. These procedures can be local or exported [WS97]. The local procedures are declared and referenced within the same system, while the exported procedures may be referenced by other B-action system. An exported procedure of one system is an imported one of another system. Let us consider the exported procedure Exp_P declared in the machine B and called from the machine A shown below in Figure 12.

Figure 12. Procedures in B-action systems. The B Method requires the calling operation and the procedure to be in separate machines. When the operation A1 calls the procedure Exp_P, A1 is enabled only if the procedure Exp_P is also enabled, i.e., Q1 ∧ G holds. The procedure Exp_P and the operation A1 are executed as a single atomic entity. Detailed studying on the procedures can be found elsewhere [WS97].

MACHINE Global_z VARIABLES z INVARIANT J(z) INITIALISATION z:=z0 OPERATIONS assign_z(v) = PRE J(v) THEN z:=v END END

MACHINE A INCLUDES B VARIABLES x INVARIANT I(z) INITIALISATION x:=x0 OPERATIONS A1 = SELECT Q1 THEN T1 || Exp_P END; … END

MACHINE B VARIABLES y INVARIANT J(y) INITIALISATION y:=y0 OPERATIONS Exp_P = SELECT G THEN Z END; … END

Page 27: ABSTRACT - abo.fi

19

5.2 Refinement of B-action Systems The refined B-action system is shown in Figure 13. As it can be seen, the structure of the B-action system machine refinement is similar to the B Method refinement. The machine refinement RefActionSystem refines the machine specification ActionSystem.

Figure 13. The refined B-action system [WS98, PTWBEJ01]. The variables, the invariant and the actions of this B-action system form an abstract machine. The operations of the machine refinement refer only to the concrete variables x, as mentioned in section 4.2. Moreover, the operations B1 and B2 are given as B1 = BEGIN skip END and B2 = BEGIN skip END, respectively, in the machine specification ActionSystem. In order to prove that the machine refinement RefActionSystem in Figure 13 is a refinement of the machine specification ActionSystem in Figure 10, within the B-action systems, a number of proof obligations must be satisfied [PTWBEJ01]:

1. The initialization in RefActionSystem should be a refinement of the initialization in ActionSystem, and the initialization should establish the invariant R.

2. The operations A1, A2 and A3 in RefActionSystem should refine the corresponding operations in ActionSystem, and they should preserve the invariant R.

3. The new operations B1 and B2 in RefActionSystem should only take into account the new variable y, and preserve the invariant R.

REFINEMENT RefActionSystem REFINES ActionSystem INCLUDES Global_z, Global_u VARIABLES x, y INVARIANT R(x, y, z, u) INITIALISATION x, y:=x0, y0

OPERATIONS A1 = SELECT gA′1 THEN sA′1 END; A2 = SELECT gA′2 THEN sA′2 END; A3 = SELECT gA′3 THEN sA′3 END; B1 = SELECT gB1 THEN sB1 END; B2 = SELECT gB2 THEN sB2 END; END

Page 28: ABSTRACT - abo.fi

20

4. The new operations B1 and B2 in RefActionSystem should terminate, if they are executed in isolation.

5. Whenever an operation Ai (i=1,2,3) in ActionSystem is enabled, the corresponding operation in RefActionSystem is enabled or, otherwise, one of the new operations Bj (j=1,2) in RefActionSystem is enabled.

6. Whenever a fault-operation in ActionSystem is enabled, a fault-operation could also be enabled in RefActionSystem.

Fault-operations in (6.) are the ones leading to a suspension state. A general fault-operation in ActionSystem is partitioned in specific faults during the refinement process. Assuming that there are the abstract system ActionSystem with a global procedure Proc and a refined system RefActionSystem with the refined procedure Proc′. Then, in order for RefActionSystem to be a refinement of ActionSystem, two more proof obligations should hold:

7. The procedure Proc in ActionSystem should be refined by the corresponding

procedure Proc′ in RefActionSystem and Proc′ should also preserve the invariant. 8. If the procedure Proc is enabled, the procedure Proc′ should be enabled, too, or

then the operations in RefActionSystem should enable Proc′. The proof obligations (3.), (4.), (5.), (6.) and (8.) are additional to the proof obligations generated for a refinement in the B Method, described in section 4.2. These proof obligations are important in order to be able to reason about distributed systems within the B Method.

Page 29: ABSTRACT - abo.fi

21

6 Tool suppor t In order to have confidence in the correctness proof of stepwise refinement step, use of a mechanical tool is inevitable. In this section an overview of the refinement tools that have been considered for this task is given, as well as the U2B (UML to B Method) translation tool and the UML tool. The derivation of correct programs from specification involves generating proof obligations that need to be checked. These proof obligations were described earlier. A refinement tool assists the user by generating and proving these proof obligations mechanically, sometimes automatically and sometimes interactively. The automatic generation of proof obligations has been considered for the case study in this Thesis. 6.1 Rational Rose Enterpr ise Edition Tool The Rational Rose Enterprise Edition tool has been used to design the UML diagrams for the case study presented in this Thesis. Detailed presentation of its features can be found elsewhere [Rational03]. Here, only some major features of this tool are presented that were needed for producing “correct” B-action systems. The structure of a Rational Rose window can be seen in Figure 14, given below. The class diagram of a train station example, which was given in section 2.3, is shown in this window, as well as all the features that can be selected and added into this diagram. Moreover, the operation specification window of the operation train_arrives of the class STATION is shown. This window appears when right clicking an operation of the class specification window. Important features of Rational Rose for the case study development of this Thesis are:

� Buttons in the operation specification window, of a class diagram, allow the user to input preconditions, semantics, postconditions, as well as parameters for the operation.

� When the General button, of the operation specification window, is active, it

allows the programmer to write documentation for the operation, which is something very important when developing software systems.

� Return types and stereotypes can be input for each operation when the Detail

button is active.

� Statechart diagrams can be attached to classes to model the dynamic behaviour of them.

Page 30: ABSTRACT - abo.fi

22

Figure 14. Rational Rose Window.

6.2 U2B Tool The U2B tool [SB03] translates classes of class diagrams in UML to B machines. The important features for the U2B translation are:

� The class diagram defines the structure of B machines, the relationships to other classes, the attributes and the operations of each class.

� Further textual information in an adapted B form in the specifications of classes and operations defines the invariant, the initialization and operation semantics for the B machines.

Page 31: ABSTRACT - abo.fi

23

� The differences from normal B notation are that instance referencing can be used in an object-oriented style and reference to the current instance can be assumed implicit.

� The operations of the classes may be specified in statechart diagrams that are attached to these classes.

� The attributes and unidirectional associations are translated to variables with type defined as a function from the current instances to the attribute type or associated class. If the multiplicity of a class is set to 1..1 in the UML class specification, the attributes are translated to variables with the type given at declaration time.

Let us consider the class diagram given above in Figure 14. The translated B machine for the class STATION is given below in Figure 15. In order to translate the class diagram,

Figure 15. U2B Translation for the class STATION of Figure 14.

MACHINE STATION EXTENDS PLATFORM_CLASS SETS MSG={ in_station,waiting} VARIABLES queue, platforms INVARIANT queue : seq(TRAIN) & platforms : POW(PLATFORM) & ran(queue)/\UNION(pp).(pp:platforms|trains(pp)) = { } & size(queue)=card(ran(queue)) INITIALISATION queue := <> || platforms := { } OPERATIONS outcome <-- train_arrives (tt) = PRE tt:TRAIN & tt/: ran(queue) & tt/: UNION(pp).(pp:platforms|trains(pp)) THEN IF #(qq).(qq:platforms & platform_state(qq)=available) THEN ANY pp WHERE pp:platforms & platform_state(pp)=available THEN arrival(pp,tt) || outcome:=in_station END ELSE queue:=queue [tt] || outcome:=waiting END END . . END

Page 32: ABSTRACT - abo.fi

24

the user has to choose the option “Export Class Diagram to B” from the File menu of the Rational Rose environment. U2B uses mathematical categorizations of functions such as partial, total, injective, surjective, and range constraints to model the UML multiplicity constraints. The attribute types can be any valid B variable type. Definitions of type sets and constants for use in many machines can be included in “class utilities” which are classes that do not have any instances. Sets and constants can also be defined locally to a class’s specification window in the documentation box. Moreover, any valid B clause can be added in this documentation box. Specific features of U2B that are used in the case study of this Thesis will be explained later during the development process. 6.3 Tools suppor ting the B Method In this Thesis the Atelier B [AtelierB03] mechanical tool has been used to verify the development steps. This tool consists of a set of functionalities: a type checker and a syntax analyzer, as well as an automatic and an interactive prover. Facilities such as C-code generation and documentation are incorporated into this tool, too. During a program development the tool is supplied with the abstract machine specification and refinements of this specification. The tool first checks the syntax and the types of the machines. Then, it automatically generates the proof obligations needed for proving the consistency of the specification and the correctness of the refinement steps. The proof obligations can be automatically or interactively proved using the corresponding provers. The provers are based on a mathematical library consisting of a collection of mathematical laws for the underlying set theory. The automatic prover tries to prove these proof obligations using this library. If this library is not enough, the user may apply new rules and with the help of the interactive prover discharge the rest of the proof obligations.

Page 33: ABSTRACT - abo.fi

25

7 Modeling Control Systems The control system, which is developed as the case study of this thesis, is a kind of closed-loop control system [SG96]. It is so called, because the properties of the outputs of the process that have to be maintained by the control system are monitored. A closed-loop control system with feedback is given below in Figure 16. The controlled variable Input variables Controller ∆s to manipulated Controlled variable Set point variables

Figure 16. Feedback Control [SG96]

is the process variable whose value the system is intended to control. The input variables are the process variables that measure inputs to the process. A manipulated variable is a process variable whose value can be changed by the controller. The set points are given reference values. In this thesis, the structure of the control system is of the form given below in Figure 17. It consists of four entities. These entities are the controller, the sensors, the actuators and a plant [BSS96, LL95, PQS99, PRTWJ01]. They interact with each other in order for the control system to obtain the desired functionality. The plant in a control system describes the autonomous behaviour of the system. The task of the controller in a control system is to ensure that the plant operates within the predefined requirements. Hence, the controller reacts to changes in the plant. Plant Controller

Figure 17. The structure of the control system specification

Plant Variables

Plant operations Sensors

Actuators

Controller operations

Controller Variables

Process

Page 34: ABSTRACT - abo.fi

26

The feedback control system of Figure 16 corresponds to Figure 17 by mapping the Process to the Plant, the manipulated variables to the Actuators, the feedback to the controller from the controlled variable to the Sensors and the Controller of one system to the Controller of the other. 7.1 Determining the controller and the plant When all the details have been added to the system the development proceeds by decomposing the component specification into controller and plant specification pair, meaning that for a component both a controller and a plant specification is obtained. In B-action systems, the plant machine contains the transitions to the new states, but in order for the transition to take place, a controller procedure is called for handling the required decisions. The procedure is modeled as skip if the controller machine needs not to intervene. To obtain such decomposition, the operations of the machines have to be split and the variables are partitioned between the controller and the plant machines. Each operation of the form: Operation = SELECT state = act1 ∧ A THEN B; state := act2 END is replaced with the operation in the plant: Operation′ = SELECT state = act1 ∧ A THEN Act2 END, where the procedure Act2 of the controller is Act2 = PRE state = act1 ∧ A THEN B || state = act2 END. It can be seen that the effect of the new operation Operation′ is the same as the effect of the old operation Operation. Adding procedures while keeping the old functionality agrees with the refinement rules in B-action systems. 7.2 Determining sensors and actuators In the last development step, the sensors and the actuators for the component, from the controller and plant specification, are determined. The sensor variables are set by the plant and read by the controller. Because of this, the sensors are modeled as a separate machine, which is included by the plant and seen by the controller. Accordingly, the actuators are modeled as a separate machine, which is included by the controller and seen by the plant. The invariant of the plant relates the state variable of the whole control system to the plant and the controller state variable, as well as to the sensor and to the actuator variables. The general decomposition schema can be seen in the Figure 18. The plant and the controller are represented as B-action systems with local variables and actions, and local variables and procedures, respectively. The actuators and the sensors become global variables to the plant and controller, respectively, and are put in separate machines.

Page 35: ABSTRACT - abo.fi

27

Detailed studying of this decomposition process can be found elsewhere [Sekerinski99, PRTWJ01]. Figure 18 illustrates the decomposition process described above.

Figure 18. General decomposition schema [Sekerinski99].

REFINEMENT MachinePlant REFINES Machine INCLUDES MachineCtrl, MachineSensors VARIABLES plant state INVARIANT variable types ∧ refinement invariant for plant variables, controller variables, actuators, sensors INITIALISATION Plant state and sensors initialization OPERATIONS Operation_name = SELECT refined guard THEN Plant state and sensors change ; OperCtrl ( parameters ) END; … END

MACHINE MachineCtrl INCLUDES MachineActuators SEES MachineSensors VARIABLES controller state INVARIANT variable types INITIALISATION controller state and actuators initialization OPERATIONS OperCtrl ( parameters ) = PRE state THEN controller state and actuators change ; END; … END

MACHINE MachineSensors VARIABLES sensors INVARIANT variable types INITIALISATION sensors :∈ any value OPERATIONS SetSensor ( ss ) = sensor := ss ; … END

MACHINE MachineActuators VARIABLES actuators INVARIANT variable types INITIALISATION actuators :∈ any value OPERATIONS SetActuator ( aa ) = actuator := aa ; … END

Page 36: ABSTRACT - abo.fi

28

8 Presentation of the Wallac case study PerkinElmer Life Sciences designs, manufactures, develops, and markets analytical systems for use in drug discovery, research, mass population screening, and other bioresearch and clinical diagnostics areas. PerkinElmer Life Sciences [PerkinElmer03] was formed from the international Wallac group, and is today a worldwide organization with about one thousand employees. The company supplies complete analytical systems, which are used to provide researchers and clinicians with reliable processing of ‘difficult to measure’ substances found in blood or other biological sample materials. The manufactured analytical systems include reagents, sample handling and measuring instrumentation, as well as computer software.

Figure 19. The Fillwell workstation [Fillwell02]. The system being developed in this Thesis, is part of the Fillwell workstation that can be seen in Figure 19 above. The system belongs to the class of products for drug discovery and bioresearch. The Fillwell base unit consists of a Dispense Head, which dispenses liquid into microplates on an Operating Table, as well as on a Rotary Table being attached to the Operating Table as it is shown from the Figure 19 above. Moreover, there are four Stackers above the Rotary Table. The Fillwell workstation was the first liquid handling system designed for high density microplates. The Operating Table contains 3 plate positions. The Rotary Table consists of 6 plate positions. The gantry can move in XYZ-directions in order for the Dispensing Head to be able to reach all the positions on the Operating Table and the processing position on the Rotary Table. The gantry has a very high precision with an accuracy of 100 µm.

Page 37: ABSTRACT - abo.fi

29

8.1 The requirements of the case study The Fillwell workstation consists of several interacting parts. The parts considered for this case study are the Rotary Table and the four Stackers. The task of every stacker is to destack, which means to place a plate to be analysed on the Rotary Table, and to stack, which means to remove/take off an analysed plate from the Rotary Table. Every stacker has a maximum capacity of twenty plates. The stackers have, also, arms in order to be able to hold and stack or destack the plates. The Rotary Table has six positions. In every position there is always a plate holder. The processing position of the Rotary Table is the position 1 and above the positions 2, 3, 5, and 6 there are the Stackers. The interfacing of the Rotary Table with the Stackers and the Dispensing Head can be seen in Figure 19 above. The top view of the Rotary Table itself is given below in Figure 20. Plateholder

Figure 20. Top view of the Rotary Table. Initially there is not any plate on the Rotary Table and some stackers can be full while others can be empty. Due to the fact that the Rotary Table, the Stackers and the Dispensing Head may collide the following safety requirements are defined:

• When a Stacker is ready to destack a plate to the Rotary Table, the arms, holding a plate, may extend only if there is not a plate in the corresponding position of the Rotary Table.

• When a Stacker is ready to stack a plate from the Rotary Table, the arms may extend only if there is a plate in the corresponding position of the Rotary Table.

• The Rotary Table may rotate only when the arms of all the Stackers are retracted, and the Dispensing Head is not processing at position 1 of the Rotary Table.

During a typical course of events the following sequence of actions occurs with a plate. The possible failures have not considered here.

1. A Stacker destacks a plate to the Rotary Table (destack).

pos 4

pos 3 pos 5

pos 2 pos 6 pos 1

Page 38: ABSTRACT - abo.fi

30

2. The Rotary Table rotates the plate to the processing position 1 (rotate(steps)). 3. The Dispensing Head processes the plate. 4. The Rotary Table rotates the processed plate under a stacker (rotate(steps)). 5. A Stacker stacks the processed plate (stack).

It can be mentioned that other courses of events are possible depending on how many stackers are working and in which order the commands rotate, destack and stack are given. 8.2 The integrated development process proposed for the case study The main idea of the whole development process is based on applying both safety analysis and B reasoning for correctness to an already constructed UML specification of the eventual control system. Usually such a specification is not obvious, nor straightforward to obtain for a complex final system, given only the initial requirements. A scalable approach is required for producing the first specification of the system. This first specification is very important to the whole development of a system, because introduced errors at this step may propagate along to the next more concrete steps of the development. The initial specification should ensure safety and its consistency must be proved. Details are added to the initial specification by introducing functionality details in a stepwise manner. The correctness of the refined UML diagrams, of the initial specification, into a specification taking into account these details is proved using the B-action systems. In every refinement step, the safety properties of the system are conserved. The goal for the operator and user of the whole system in this case study is careful functional and safety analysis for producing the eventual software. A combination of UML, formal methods and safety analysis for checking the quality of the eventual software and for producing this software is applied. As a result, this process consists of three main phases. First, a system specification is developed from the initial informal requirements. Second, when the consistency of this specification has been proved with these requirements, the specification is stepwise refined into a concrete, more detailed system. Third, when all the details have been introduced, the system is decomposed to a control system consisting of a plant, a controller, sensors and actuators. Safety and reliability considerations are taken into account for the entire process. 8.3 Safety aspects of the development The system being developed in this Thesis is safety critical. Thus, the development process should ensure safety and reliability of the system by incorporating safety analysis. Moreover, it should be ensured that the controlling software reacts in time on hazardous situations by trying to force the system back to a safe state. This can be achieved only if the information provided by the safety analysis is taken into account in the whole software development process.

Page 39: ABSTRACT - abo.fi

31

In [PTWBEJ01] an approach for conducting software development in parallel with safety analysis was developed. This approach is presented in Figure 19. It was observed that both safety analysis and the stepwise program development conduct reasoning from an abstract to a concrete level. Hazards that are potentially dangerous are identified by safety analysis and then detailed descriptions of them are produced, together with finding the means to cope with these hazards. The development process starts by producing an abstract specification describing in general the services of the system without incorporating any details. In every refinement step more implementation details are added to the abstract specification, so that a program has been constructed at the end. As a result, the information that becomes available at every stage of the safety process, by performing corresponding refinements of the initial specification, can be incorporated to the development process. Therefore, during the system development the safety analysis will be composed into the UML development as will be seen in the following sections. …

Figure 21. Safety analysis and stepwise system development [PTWBEJ01].

Functional requirements

Safety analysis

Safety requirements

Abstract specification

Refined specification

Elaborated safety analysis

Elaborated safety requirements

Safety analysis of implementation

Elaborated safety requiremen

Implementation

Page 40: ABSTRACT - abo.fi

32

8.4 Presence of failures A control system consisting of a controller managing a plant is usually a safety-critical system. In order to build a controller able to handle components’ failures the following actions are required [PTWBEJ01]:

• to understand the nature of faults and their impact on the system, • to decide on the detection procedures, repair procedures, functioning of the

system when a failure occurs, • to introduce effective maintenance procedure.

In order to incorporate the results of safety analysis in the refinement process the following methodological aspects should be addressed [PTWBEJ01]:

� Modeling fault occurrence and detection � Modeling system behaviour and synchronization when faults occur � Modeling different operating modes and transition between them

including the system failure � Design and specification of a maintenance procedure � Specification of the execution log.

These actions of handling failures are taken into account in the UML and B-action systems development described in the following sections.

Page 41: ABSTRACT - abo.fi

33

9 UML-development incorporating safety aspects

The starting point of a system development is an informal specification describing the services required from the final product. Hints about the software and hardware parts may be considered in later steps. In this thesis, that is considered the most general starting point for the development process of a control system. The functional requirements of the case study are depicted in use case diagrams. Each use case is a service that the system will eventually provide to a user. The simplified operations form the protocol of the devices. There are three devices interacting with each other in this case study, but only two of them, the stacker unit and the Rotary Table, are developed within this case study. A typical protocol of a Stacker from the stacker unit can be as follows:

1. Destack a plate to the Rotary Table 2. Stack a plate from the Rotary Table

A typical protocol for the rotary table can be:

1. Rotate clockwise or counterclockwise Thus the functional requirements of the Stackers are to destack and stack plates, while the functional requirement of the Rotary Table is only to rotate clockwise or counterclockwise. A use case diagram of a Stacker is given in Figure 22.

Destack plate

Actor

Stack plate

Figure 22. Use case diagram for the Stacker.

A use case diagram for the Rotary Table is given in Figure 23.

Page 42: ABSTRACT - abo.fi

34

Actor

Rotate

Figure 23. Use case diagram for the Rotary Table. The Rotary Table and the Stackers interact by the Stackers stacking a plate from the Rotary Table or destacking a plate to the Rotary Table. The Stackers are the active partners while the Rotary Table is the passive partner during the interaction. In addition to the functional services, the reliability and safety issues related to these functional services are captured at a reasonable level of detail. These issues are captured in the specification of the use cases, expressed as structured English text. The basic functions for the eventual software of this case study are, to capture the protocol information when entered, to communicate the protocol information with the mechanical parts and to inform about failures and the failure points. 9.1 Use cases incorporating the possible failures Two use cases, stack and destack, have been identified for the Stackers, and one use case, rotate, has been identified for the Rotary Table as shown in Figures 22 and 23, respectively. These use cases are considered as subroutines, because it is more convenient with subroutines for the purpose of safety and reliability analysis [PTWBEJ01]. Subroutine Stack captures a Stacker stacking a plate from the Rotary Table. Typical course of events:

1. Stacker receives command stack a plate from plateholder at position ph_pos from protocol.

2. System checks if ph_pos is a valid plateholder position, i.e. 2, 3, 5, or 6 position on Rotary Table; if not, then SF1.

3. System checks if there is plate on the plateholder at ph_pos; if not, then SF2. 4. System checks if the Stacker is full; if yes, then SF3. 5. Stacker stacks the plate from the plateholder at position ph_pos. 6. System checks if the plate has been stacked into the Stacker, i.e. there is no plate

on the plateholder at ph_pos; if the plate is still on the plateholder, then SF4. 7. Signal stack_ok.

Failure reports: SF1. ph_pos is outside the valid plateholder position range. Remedy: User changes ph_pos, identifies the cause and resumes or aborts calling protocol execution. SF2. There is no plate on the plateholder to be stacked.

Page 43: ABSTRACT - abo.fi

35

Remedy: Wait a while for the plate to become available. User places a plate manually on the plateholder and resumes or aborts calling protocol execution. SF3. Stacker is full. Remedy: User unloads the stacker and resumes or aborts calling protocol execution. SF4. Stacker has not stacked the plate. Remedy: User identifies the cause and resumes or aborts calling protocol execution. Subroutine Destack captures a Stacker destacking a plate onto the Rotary Table. Typical course of events:

1. Stacker receives command destack a plate onto plateholder at position ph_pos from protocol.

2. System checks if ph_pos is a valid plateholder position, i.e. 2, 3, 5, or 6 position on Rotary Table; if not, then DF1.

3. System checks if there is not a plate on the plateholder at ph_pos; if there is plate on the plateholder, then DF2.

4. System checks if the stacker is empty; if yes, then DF3. 5. Stacker destacks a plate onto the plateholder at position ph_pos. 6. System checks if there is plate on the plateholder at ph_pos; if not, then DF4. 7. Signal destack_ok.

Failure reports: DF1. ph_pos is outside the valid plateholder position range. Remedy: User changes ph_pos, identifies the cause and resumes or aborts calling protocol execution. DF2. There is plate on the plateholder. Remedy: User takes the plate manually from the plateholder and resumes or aborts calling protocol execution. DF3. Stacker is empty. Remedy: User loads the Stacker and resumes or aborts calling protocol execution. DF4. Stacker has not destacked the plate. Remedy: User identifies the cause and resumes or aborts calling protocol execution. Subroutine Rotate captures the clockwise or counterclockwise rotation of the Rotary Table. Typical course of events:

1. Rotary Table receives command rotate p_steps steps from protocol. 2. System checks if p_steps is inside the valid range, i.e. from –5 to +5 steps; if not,

then RoF1. 3. System checks if it is safe to rotate; if not, then RoF2. 4. Rotary Table rotates p_steps.

Page 44: ABSTRACT - abo.fi

36

5. System checks if the rotation was successful; if not, then RoF3. 6. Signal rotate_ok.

Failure reports: RoF1. Input parameter p_steps is outside the valid range (-5..5)

Remedy: User changes parameter p_steps, identifies the cause and resumes or aborts calling protocol execution.

RoF2. Dispensing Head or Stackers are not safe. Remedy: Wait a while for the Dispensing Head or Stackers to become safe. User resumes or aborts calling protocol execution.

RoF3. Rotary Table has not rotated p_steps steps. Remedy: Calibrate and resume or abort calling protocol execution. Failures: From the alternative courses of events defined above, the following failures can be derived for the system:

a) Stacker stack failure b) Stacker destack failure c) No plate present d) Plate already present e) Stacker empty f) Stacker full g) Rotary Table rotate failure h) Not safe

Having specified in a detailed manner the use cases given above, the next step is to determine the logically related use cases, and group them together. Each group of related use cases defines a component of a control system. 9.2 Component-or iented development The component oriented development is very useful when developing control systems, because it consists of reusing existing components, developing new ones and constructing new systems from them. The computation can already be distributed in this early development stage, supporting well reuse and scalability. From the use case diagrams in Figures 22 and 23 an associated component diagram can be constructed, which is given below in Figure 24. The Stackers interact with the Rotary Table by their provided services, which are stacking or destacking a plate, while the provided service of the Rotary Table is to rotate.

Page 45: ABSTRACT - abo.fi

37

Stacker

Destack plate

Stack plate

Rotary table

Rotate

Figure 24. A component diagram for the Rotary Table and a Stacker. 9.3 Class diagram of the specification At this level, each conceptual component can be shown as an active class in a class diagram. The class diagram of the system’s specification model is given below in Figure 25. This diagram specifies the static view of the system. Statechart diagrams, which are attached to the classes of this diagram, specify the autonomous behaviour of the classes. For the specification model only the command variables, rcmd and scmd, of the Rotary Table and the Stacker, respectively, as well as the state variables are of interest. The state variables are not declared in the classes because U2B generates them automatically by checking the attached statechart diagrams. The arrows, in Figure 25, are pointing to the main operations/services of the classes, which capture the functional requirements of the system. Furthermore, the multiplicity of the ROTARY_TABLE class is set to one, because there is only one Rotary Table, and the multiplicity of the STACKER class is set to four, because there are four instances of a Stacker. The rest of the operations capture the correct commands given to the system and the safety requirements in an abstract way.

Page 46: ABSTRACT - abo.fi

38

ROTARY_TABLE rcmd : TCOMMAND

RotateCommand(p_steps : INT) Rotate() RotateFail() RotateCommandRemedy() PreRotateNoRemedy() RotateOk() RotateNotOk() RotateRemedy() RotateNoRemedy() ServiceNotReady() Remedy() NoRemedy()

STACKER scmd : SCOMMAND

DestackCommand() Destack() DestackFail() DestackCommandRemedy() PrepDestackNoRemedy() DestackOk() DestackNotOk() DestackRemedy() DestackNoRemedy() StackCommand() Stack() StackFail() StackCommandRemedy() PrepStackNoRemedy() StackOk() StackNotOk() StackRemedy() StackNoRemedy() ServiceNotReady() Remedy() NoRemedy()

Figure 25. Specification Class Diagram for Rotary Table and Stacker

9.4 Collaboration diagram of the Stackers and the Rotary Table A collaboration diagram of the Stacker unit and the Rotary Table is given below in Figure 26. This diagram shows the four Stacker objects and the cooperation between them and the Rotary Table object. Moreover, the links between them can be seen, as well as the messages sent from one object to another. It can be seen as Stacker4 sends a message to Rotary Table informing that it is destacking a plate and the Rotary Table sends a message to Stacker1 to stack a plate from it. The third message in the sequence is from Stacker4 to Stacker3 saying to wait and then Stacker3 sends a message (4) to Rotary Table in order to inform Stacker2 (message 5) that it has to wait for a plate.

Stacker1 Stacker 2

Stacker 3 Stacker 4

R o tar y T ab le

4:

1 :

3 :

2 :

5 :

Figure 26. Collaboration Diagram for the Stackers and the Rotary Table

Page 47: ABSTRACT - abo.fi

39

This diagram corresponds to the class diagram of Figure 25 because it satisfies the multiplicities of the classes. Moreover, it is useful to the developer because it helps to understand better the cooperation between the objects of the system at a specific time. This kind of diagram is not further developed in this Thesis because they are not taken into account from U2B for the refinement steps. 9.5 Statechar t Diagrams of the specification The classes of the system consist of attributes and methods and the autonomous behaviour is specified using statechart diagrams. For each service of the system a statechart diagram is developed. 9.5.1 The Rotary Table The first abstract statechart diagram for the Rotary Table is shown in Figure 27.

stop

start

idle get_ready

rotate

suspended

pre_rot_suspended

rot_suspended

abort

stop

RotateCommand / rcmd:=rot_cmd

ServiceNotReady

RotateOk[ rcmd=rot_cmd ]

RotateNotOk[ rcmd = rot_cmd ]

RotateRemedy[ rcmd=rot_cmd ]

RotateNoRemedy

Remedy

NoRemedy

Rotate[ rcmd=rot_cmd ]

RotateFail[ rcmd=rot_cmd ]

RotateCommandRemedy[ rcmd=rot_cmd ] PreRotateNoRemedy

Figure 27. Specification Statechart Diagram for the Rotary Table.

The service in this statechart diagram is derived from the service in the use case diagram. The service providing state rotate, together with the states idle, get_ready, pre_rot_suspended, suspended and abort, form the states in this abstract statechart diagram. The component evolves from a state idle to a state get_ready, and at the same time the corresponding rotate command, rot_cmd, is being assigned to the attribute rcmd which models the command of the Rotary Table. If an exception occurs, such as, the

Page 48: ABSTRACT - abo.fi

40

service is not ready, the component evolves from the state idle to the state suspended, wherefrom, if a remedy is found, the component resumes to state idle. From the state get_ready, the component evolves to the state rotate performing the required service, provided certain conditions are satisfied. The certain condition at this stage is only that the attribute rcmd must be equal to rotate command rot_cmd. On the presence of an exception, the behaviour of the component is suspended and it evolves to the state pre_rot_suspended. If a remedy of this exception is found, the component can resume and go back to the state get_ready, where it can continue until the required service has been performed. Otherwise, the exception is a failure and the component aborts its execution. If the rotate service is successfully performed the component returns to its state idle. An exception of this service suspends the behaviour of the component, which evolves to the state rot_suspended. If a remedy occurs, the component can resume its service providing state. Otherwise, the component aborts its execution. The only reason that more than one suspended state are in the diagram, is to guarantee that the evolving of the component’s behaviour continues from the state prior to suspension. 9.5.2 The Stacker The first abstract statechart diagram of a Stacker for the stack service is shown in Figure 28. For each of the two services of a Stacker, a statechart diagram is derived. This serves for simplicity reasons. The service providing state stack, together with the states idle, prepare, prep_sk_suspended, suspended and abort, form the states in this abstract statechart diagram, in a similar way as in the abstract statechart diagram of the Rotary Table. An instance of the Stacker component evolves from a state idle to a state prepare,

stack st_suspended

prep_sk_susp ended idle

suspended

prepare abort

stop start

ServiceNotReady StackCommand / scmd:=sk_cmd

StackRemedy[ scmd=sk_cmd ] StackNoRemedy

Remedy

NoRemedy

Stack[ scmd=sk_cmd ] StackFail[ scmd=sk_cmd ]

StackCommandRemedy[ scmd=sk_cmd ]

PrepStackNoRemedy

StackNotOk[ scmd=sk_cmd ]

StackOk[ scmd=sk_cmd ]

Figure 28. Specification Statechart Diagram of a Stacker for the stack service.

Page 49: ABSTRACT - abo.fi

41

and at the same time the corresponding stack command, sk_cmd, is being assigned to the attribute scmd modeling the command of a Stacker. In relevance to the Rotary Table, if an exception occurs, such as, the service is not ready, the Stacker evolves from the state idle to the state suspended, wherefrom, if a remedy is found, the component resumes to state idle. Otherwise, if there is no remedy, the Stacker aborts its execution. From the state prepare, the Stacker evolves to the state stack performing the required service, provided certain conditions are satisfied. The certain condition is only that the attribute scmd must be equal to the stack command sk_cmd. On the presence of an exception, the behaviour of the Stacker is suspended and it evolves to the state prep_sk_suspended. If a remedy of this exception is found, the component can resume and go back to the state prepare, where it can continue until the required service has been performed. Otherwise, the exception is a failure and the Stacker aborts its execution. If the stack service is completed successfully, the component returns to its state idle. An exception of this service suspends the behaviour of the component, which evolves to the state st_suspended. If a remedy occurs, the object can resume its service providing state. If not, the exception is a failure and the Stacker aborts. The corresponding abstract statechart diagram of a Stacker modeling the destack service can be found in Appendix A. 9.6 U2B translation to B-action systems and formal specification of the system At this point, the specification class and statechart diagrams can be translated to B-action systems, using the U2B tool, in order to be able to verify them with the Atelier B tool. U2B checks the multiplicities of the ROTARY_TABLE and the STACKER classes, in order to create instances of the classes if it is required. The ROTARY_TABLE class multiplicity is set to one, because there is only one instance of the Rotary Table. The multiplicity of the STACKER class is set to four, because there are four instances of the Stacker unit. U2B checks the multiplicity of the STACKER class, as mentioned above, and generates a constant STACKER, putting it in the STACKER_CLASS machine, with properties 1..4 meaning that there are four Stacker instances. Furthermore, U2B checks the attached statechart diagrams of the classes and translates automatically the set of states and the state variable, for which the name is the name of the state machine in UML. Moreover, the sets of possible commands of the Rotary Table and the Stacker are given in the machine def.mch in Appendix B.3. The translated specification machines for the Rotary Table and the Stacker unit can be found in Appendices B.1 and B.2, respectively. In Figure 29, below, the Rational Rose window of the Stacker class diagram is given. The SEES and INVARIANT B clauses can be seen in the documentation box of the class specification window. U2B adds in the invariant of the machine the attributes and their types. For the case of the STACKER class, U2B translates its attributes as functions in the B Method, with source set the STACKER constant, and target set the type of the variable given in the class. For example, the command attribute scmd, which can be assigned some value from the set SCOMMAND, consisting of the stack command, sk_cmd, and the destack command, dsk_cmd, is of type: scmd : STACKER � SCOMMAND

Page 50: ABSTRACT - abo.fi

42

in the abstract machine specification. This means that every instance of the Stacker has a command variable, scmd, which can be assigned the value stack command, sk_cmd, or destack command, dsk_cmd.

Figure 29. Class Diagram of the Stacker.

Page 51: ABSTRACT - abo.fi

43

The state variable is automatically initialized by U2B, which checks the starting point in the statechart diagrams. The start point in these diagrams is the black circle and the stop point is the black circle inside a white circle. The rest of the variables are initialized in the class diagram. U2B initializes automatically in a non-deterministic way variables that are not assigned any initial value. The event triggering state transitions correspond to operation names in the classes, as it can be seen from the class and statechart diagrams given above. If an event triggering state transition does not correspond to an operation name of the class, the body of this class’ operation is given as skip. The event transitions and the operation names in the classes correspond to operation names in the abstract machine specification. Lets consider the event transition StackCommand from Figure 28. The translated abstract machine operation is:

StackCommand(thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER) = idle THEN s_state(thisSTACKER) := prepare || scmd(thisSTACKER) := sk_cmd END

END U2B parameterizes the operation with a parameter thisSTACKER of type STACKER. The initial state of the transition for thisSTACKER instance is given as SELECT guard, and the state as well as command variables are assigned the values prepare and sk_cmd, respectively. At implementation time the specific instance of the Stacker can be supplied to the machine operations, i.e. Stacker 1, 2, 3, or 4. 9.7 Formal specifications and safety analysis The initial specification of the system is abstract, because it just models transitions between states. Nevertheless, already in the initial specification a possibility of fault occurrence and system failure is preserved [PTWBEJ01]. Actions such as RotateFail model failure of execution of command. Erroneous commands are taken care in the protocol runner which its development is not part of this Thesis. RotateFail = SELECT rcmd = rot_cmd ∧ r_state = idle THEN r_state := pre_rot_suspended END The action ServiceNotReady models possible spontaneous fault occurrence even when a service is not requested. A spontaneous fault could be a primary hardware fault. ServiceNotReady = SELECT r_state = idle THEN r_state := suspended END

Page 52: ABSTRACT - abo.fi

44

From the suspension states the system tries to perform recovery procedures and continue functioning as specified from the relevant remedy actions, i.e. Remedy = SELECT r_state = suspended THEN r_state := idle END When the fault tolerance limit has been reached, a failure of the system occurs and it enters the state abort. This is modeled with actions such as RotateNoRemedy: RotateNoRemedy = SELECT r_state = rot_suspended THEN r_state := abort END This kind of actions represents the transition of the system into a fail-safe state.

Page 53: ABSTRACT - abo.fi

45

10 Refining the system It is useful to stepwise introduce details about the system when dealing with complex control systems. This way, the implementation details of the system do not have to be handled at once. After translating the basic class and statechart diagrams into a B-action system, the system is gradually refined. The requirements of the system are a good source of information when introducing variables in the refinement. Compared to the abstract machine specifications the refinement machines consist of more variables and have more detailed, as well as, newly introduced operations which change the variables. The guards consist of more precise conditions, too. 10.1 Class diagrams of the first refinement of the system 10.1.1 The Rotary Table The class diagram of the first refinement of the Rotary Table and the Stacker unit can be found in Appendix C.1 and C.3, respectively. In this refinement step the introduced details for the Rotary Table are on: • rotating the Rotary Table clockwise or counterclockwise, • the status of the six plate holders on the Rotary Table, • the presence of liquid in a plate holder, • the position of a Stacker’s arms, • how deep in the plate the Dispensing Head is allowed to go when it is processing in

position 1 of the Rotary Table, • the minimum height that the Dispensing Head can be above the position 1 of the

Rotary Table in order the Rotary Table to be able to rotate, and • the position of the Dispensing Head above the Operating Table In order to be able to reason on the introduced details the following variables are added to the system. A variable temp_ph_pos1 is added in order to store the plate holder id being at the dispensing position DispPos before the rotation. Then, this variable is used to check the correctness of the rotation after the Rotary Table has rotated. Additionally, a variable ph_pos is introduced which models the position of the six plate holders on the Rotary Table. Furthermore, a variable pholder is added, which stores the height of a plate holder and senses whether a plate is present (TRUE) on a plate holder, or not (FALSE). This variable is a function from the plate holder id to a structure containing the variable height and the Boolean variable plate_present. Moreover, a variable liq_present is added to check if there is liquid present (TRUE) on a plate holder, or not (FALSE). In order to understand the rotation of the plate holders on the Rotary Table, Figure 30, which shows the changing of the plate holders’ position after a clockwise rotation of two steps, is given below. For example, the variable ph_pos(1) at

Page 54: ABSTRACT - abo.fi

46

position 1 has the value 1 before the rotation and after the rotation it has the value 5 indicating that plate holder 5 is now at position 1.

Figure 30. Position of plate holders after a two steps rotation. Also, a variable zminAllowed is added in order to model the minimum height of a plate holder. The Dispensing Head needs to check this variable for safety reasons, i.e., not to try to go lower. Furthermore, a variable zmid is added in order to model the lowest z position possible when the Dispensing Head is moving in xy-direction. The variables temp_ph_pos1, ph_pos, pholder, liq_present, zmid and zminAllowed, as well as the procedures that change their values, are given in the procedure class PLATEHOLDER. A variable ZCoord exists in the class ZDRIVER and is compared against the variable zmid in order to allow the Rotary Table to rotate. The ZDRIVER class belongs to the class diagram of the XYZ Driver of the Dispensing Head and is imported in the Rotary Table class diagram in order for the ROTARY_TABLE_R1 class to be able to see it. The development of the Dispensing Head is done elsewhere [BJW03] within the MATISSE project. Furthermore, a variable extpos is defined and updated in the procedure class XYZD_PROC of the XYZ Driver. This procedure class is imported in the class diagram of the first refinement of the Rotary Table, for the same reason as mentioned above. If extpos is smaller than or equal to three, it means that the Dispensing Head is not above the dispensing position one of the Rotary Table, but in one of the three positions of the Operating Table, thus the Rotary Table is allowed to rotate. The Rotary Table is an extension of the Operating Table as mentioned earlier. Moreover, a variable steps is added in this refinement step modeling how many steps and in which direction the Rotary Table to rotate. The minus sign indicates counterclockwise rotation, while the plus sign indicates clockwise rotation. The rotation could go on forever, so the steps variable is restricted and can be assigned values from –5

pos 4

pos 3 pos 5

pos 2 pos 6 pos 1

pos 4

pos 3 pos 5

pos 2 pos 6 pos 1

ph 1

ph 2

ph3

ph 4

ph 5

ph 6

ph 5

ph 6

ph 1

ph 2

ph 3

ph4

Page 55: ABSTRACT - abo.fi

47

to +5, only, which means the Rotary Table can rotate maximum five positions counterclockwise, or clockwise. This additional variable can be found in the class ROTARY_TABLE_R1. In the procedure class of the Rotary Table, PLATEHOLDER, a local procedure, NewPlateholderPos, of the Rotary Table is given, which calculates the new plate holder position on the Rotary Table after the rotation has taken place. The operations of the Rotary Table are updated to reflect to the changes of the new variables. The subroutine Rotate is described in detail in Section 10.2.1, below. For this subroutine all possible failures are taken into consideration and a remedy is given for each failure if it is possible. As it can be seen in the ROTARY_TABLE_R1 class, two new operations, RotateArmsFail and RotateZCoordFail, have been added in order to model the subroutine’s failures because of the Stacker’s arms being down low on the Rotary Table and of the position of the Dispensing Head, respectively. These two operations correspond to the new transitions in the statechart diagram described below. The invariant of the Rotary Table classes The invariant written in the class documentation box of the ROTARY_TABLE_R1 class shows the relation between the state and the command of the Rotary Table and the variables steps, extpos, ZCoord, zmid and arms. Specifically, when the variable extpos has a value bigger than three and the Rotary Table is in the state rotate, the variable ZCoord, which is the z position of the Dispensing Head, has to be equal or bigger than the variable zmid, which models the lowest z position possible when the Dispensing Head is moving in xy-direction. Moreover, when the extpos variable has a value greater than three, meaning that the Dispensing Head is above the position 1 of the Rotary Table, the ZCoord variable has to have a value greater than or equal to the value of the zminAllowed variable, which is the minimum height of a plate holder. Finally, when the Rotary Table is in the states rotate, the command, rcmd, has to be equal to the rotate command, rot_cmd. This invariant can be seen below. (extpos > 3 & r_state = rotate => ZCoord >= zmid) & (extpos > 3 => ZCoord >=zminAllowed) & (r_state = rotate => rcmd = rot_cmd) The invariant written in class documentation box of the procedure class PLATEHOLDER shows the relation between the variables ph_pos, pholder, liq_present, zmid and zminAllowed. The plate holder ids of the plate holder variable, pholder, have to be the same with the plate holder ids of the plate holder position variable, ph_pos. Moreover, if there is liquid present, liq_present, on the Rotary Table, there is plate holder with a plate present on the Rotary Table. This invariant can be seen below. ran(ph_pos) = dom(pholder) & dom(pholder) = dom(liq_present) & !xx.(xx:PH_ID & (pholder(xx))'plate_present = FALSE =>

liq_present(xx) = FALSE)

Page 56: ABSTRACT - abo.fi

48

The deferred set PH_ID, which contains the ids of the plate holders, is given in the class machine def2, together with the constants zmin, zmax and ROTARY_POS, and their properties. The six fixed positions of the Rotary Table are the properties of the ROTARY_POS constant. 10.1.2 The Stacker unit In this refinement step the introduced details for the Stacker unit are on: • the position of a Stacker’s arms, • the position of the Stackers above the Rotary Table and, • the capacity of each Stacker. A variable arms is added in order to model the position of the arms of each Stacker. At this stage two arms positions are taken into account, up and down. Moreover, a variable s_pos is added to model the position of every stacker above the Rotary Table. The stackers can be above the positions 2, 3, 5, and 6 of the Rotary Table. The variables arms and s_pos, as well as the procedure that changes the status of the variable arms, are given in the procedure class STACKER_PROC. Furthermore, a variable full is added modeling a Stacker sensing whether it is full (TRUE) or not (FALSE). If a Stacker is full, it cannot stack any more plates from the Rotary Table. A variable empty is added, too, modeling a Stacker sensing whether it is empty (TRUE) or not (FALSE). If a Stacker is empty, it cannot destack any plate to the Rotary Table. The variables full and empty are given in the class STACKER_R1. The invariant of the Stacker unit classes The invariant of the refinement class STACKER_R1 shows the relation between the variable state of this class and the variable state of the class STACKER, which refines. In this refinement step, the state variable required renaming because four more states are added to the set of states of a Stacker, two for the stack service and two for the destack service. Moreover, the relation between the state variable and the variable arms, as well as the commands of the Stackers is shown. When a Stacker is in the state ready_to_destack1, the arms of that Stacker have to be down. Also, when a Stacker is in the state stack1 or destack1, the command, scmd, has to be equal to the stack command, sk_cmd, or the destack command, dsk_cmd, respectively. The part of the invariant for the arms and the command is shown below.

s_state1(thisSTACKER) = ready_to_destack1 => arms(Stacker_proc(thisSTACKER)) = down &

s_state1(thisSTACKER) = ready_to_stack1 => arms(Stacker_proc(thisSTACKER)) = down &

s_state1(thisSTACKER) = stack1 => scmd(thisSTACKER) = sk_cmd & s_state1(thisSTACKER) = destack1 => scmd(thisSTACKER) = dsk_cmd The set ARM_POS is given in the class machine def2, in the Appendix D.7 and contains the two possible arm positions, up and down.

Page 57: ABSTRACT - abo.fi

49

10.2 Statechar t Diagrams of the first refinement 10.2.1 The Rotary Table The statechart diagram of the first refinement for the Rotary Table can be found in Appendix C.2. As it can be seen, there are not any new states compared to the initial specification diagram. A description of the refined, only, transitions is following. The component evolves from a state idle to a state get_ready, and at the same time the rotate command, rot_cmd, is being assigned to the variable rcmd. Additionally, a parameter p_steps is given to this event triggering transition, which is assigned to the variable steps. Moreover, as one of the actions of this transition, the SetOldPos local procedure of the Rotary Table is called from the PLATEHOLDER class. This procedure assigns to the variable temp_ph_pos1 the id of the plate holder being at the dispensing position one of the Rotary Table prior to the rotation, so that the correctness of the rotation can be checked afterwards. From the state get_ready the component evolves to the state rotate performing its service, provided certain conditions are satisfied. These certain conditions are now precisely specified. The command variable, rcmd, must be equal to the rotate command, rot_cmd, as in the specification statechart diagram. Then, the arms of all the Stackers must be up. Moreover, the Zcoord variable must be bigger than or equal to the zmid variable, meaning that the Dispensing Head must be at a certain height above the dispensing position one of the Rotary Table, or the Dispensing Head to be in one of the three positions of the Operating Table. The later is checked with the variable extpos. As it can be seen from the diagram decision pseudo states have been added in order to reduce guard complexity. Furthermore, as one of the actions of the Rotate transition, the NewPlateholderPos local procedure of the Rotary Table is called from the PLATEHOLDER class, in order to calculate the new plate holder position after the rotation and to update the zminAllowed variable as well. A part of the statechart diagram is given below in Figure 31.

rotate

Rotate[ZCoord >= zmid or extpos<=3]/ NewPlateholderPos(steps)

RotateZCoordFail[ZCoord<=zmid & extpos > 3] [!ss.(ss:STACKERS_PROC =>arms(ss) = up)]

RotateArmsFail[#ss.(ss:STACKERS_PROC & arms(ss) = down)]

get_ready

RotateFail[rcmd=rot_cmd] pre_rot_suspended

RotateCommandRemedy[rcmd=rot_cmd & !ss.(ss:STACKERS_PROC=>arms(ss)=up) & (ZCoord>=zmid or extpos <= 3)]

Figure 31. A part of the 1st refinement statechart diagram for rotate service.

Page 58: ABSTRACT - abo.fi

50

On the presence of an exception, the component evolves from the state get_ready to the state pre_rot_suspended. In addition to the transition RotateFail, which models failure of execution of command, two new transitions have been added. The transition RotateArmsFail suspends the behaviour of the component to the state pre_rot_suspended, if there exists some stacker having the arms down. The transition RotateZCoordFail suspends the behaviour of the Rotary Table, if the Dispensing Head is not at the specified height above the position one of the Rotary Table in order the rotation to be allowed. If remedies of these exceptions are found, the component can resume and continue from the state get_ready until the required service has been performed. Otherwise, the component aborts its execution. If the service is successfully performed the component returns to the state idle. In the guard of this transition, RotateOk, is checked that the plate holder, with some id, which was at position one, has been rotated to a new position according to the number of steps given for the rotation. An exception of this service suspends the behaviour of the component to the state rot_suspended. If a remedy occurs, the component resumes its service providing state as in the specification diagram. In a different situation, the component aborts its execution. 10.2.2 The Stacker unit The statechart diagram of the first refinement for the stack service of a Stacker can be found in Appendix C.5. The corresponding statechart diagram for the destack service of a Stacker can be found in Appendix C.4. As it can be seen from these diagrams, some new states have been added. Thus, the state variable and the states required renaming and the relationship between the state variable of the specification and the state variable of the refinement is given in the invariant of the STACKER_R1 class. A detailed description of the refined and the new transitions of the statechart diagram for the stack1 service is following. The evolvement of a Stacker from the state idle1 to the state prepare is the same as in the specification diagram. From the state prepare1 the component evolves to the newly added state ready_to_stack1 provided specific conditions are satisfied. The conditions are that the command variable, scmd, must be equal to the stack command, sk_cmd, the Stacker is not full, and the plate holder under this stacker’s position has a plate present. As an action of this transition, this Stacker calls the local procedure ChangeStArms from its procedure class STACKER_PROC. This procedure changes the position of the Stacker’s arms to position down, in order for the Stacker to be able to hold (get) the plate. Decision pseudo states have been added in this diagram as well to reduce guard complexity. If an exception occurs on the conditions mentioned above, the component evolves from the state prepare1 to the state prep_sk_suspended1. Additionally to the transition StackFail, taking care of failure of execution of command, two new transitions have been added. The transition StackFullStackerFail suspends the behaviour of the component to the state prep_sk_suspended1 if the component is full. The transition StackPlateFail suspends the behaviour of the component to the state prep_sk_suspended1 if there is not a plate present on the plate holder under this Stacker. On the presence of a remedy of these exceptions, the component can resume and continue from the state prepare1. From the state ready_to_stack1 the component evolves to the state stack to perform its intended

Page 59: ABSTRACT - abo.fi

51

service provided that the command variable, scmd, is equal to the stack command, sk_cmd, and the arms are down ready to take up the plate. If the arms are not down but up, the new transition StackArmsFail suspends the behaviour of the component to the state prestack_suspended1. If there is remedy for this exception, the component resumes and can continue from the state ready_to_stack1. Otherwise, the component aborts its execution. As actions of the Stack transition, the local procedure ChangeStArms is called to change the position of the arms to position up, and the exported procedure of the Rotary Table, PlateholderPlateRemove, is called from the PLATEHOLDER class to remove a plate from the plate holder being under this Stacker. Moreover, the component evolves back to the state idle1 from the service providing state stack1, provided that the command is satisfied, the arms of this Stacker are up and there is not a plate present under this Stacker. If the arms are down the behaviour of the component is suspended to the state st_suspended1 with the transition AfterSkArmsFail. If there is a plate present on the plate holder under this Stacker, the behaviour of the component is suspended with the transition AfterSkPlateFail to the state st_suspended1, too. From this state the component resumes to the service providing state stack1 if there is a remedy, or aborts its execution if there is not a remedy. A part of the statechart diagram for the stack service is given below in Figure 32. As it can be seen from the statechart diagram for the destack service of a Stacker in Appendix C.4, the transitions occur in a similar way as in the statechart diagram for the stack service. A description of the differences between these two diagrams is following.

ready_to_stack1

PrepareStack[(pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = TRUE]/ ChangeStArms(Stacker_proc, down)

StackPlateFail[(pholder(ph_pos(s_pos(Stacker_proc))))´plate_present=FALSE] [full = FALSE]

StackFullStackerFail[full = TRUE]

[scmd = sk_cmd] StackFail[scmd=sk_cmd]

prepare1

prep_sk_suspended1

StackCommandRemedy[scmd=sk_cmd & full=FALSE & pholder(ph_pos(s_pos(Stacker_proc)))´plate_present = TRUE

Figure 32. A part of the 1st refinement statechart diagram for stack service.

Page 60: ABSTRACT - abo.fi

52

In order for the component to evolve from the state prepare1 to the state ready_to_destack1, the command variable, scmd, must be equal to the destack command, dsk_cmd, the Stacker must not be empty, and there must not be a plate present on the plate holder under this Stacker. If the Stacker is empty, the transition DestackEmptyStackerFail suspends the Stacker’s behaviour to the state prep_dsk_suspended1. Moreover, if there is a plate present under this Stacker, the transition DestackPlateFail suspends the Stacker’s behaviour to the state prep_dsk_suspended1. On the presence of a remedy the component evolves to the state prepare1, wherefrom it can continue until the required service has been performed. From the state ready_to_destack1 the component evolves to the service providing state destack1, provided that the arms of the Stacker are down, as in the corresponding stack service statechart diagram. Furthermore, as one of this transition’s actions, the Rotary Table’s exported procedure, PlateholderPlateAdd is called, which adds a plate to the plate holder being under this Stacker. From the state destack1, the component can return to the state idle1 provided that the arms of the Stacker are up and there is a plate present on the plate holder being under this Stacker. If there are exceptions on these conditions the component evolves to the state des_suspended1 from the state destack1, with the transitions AfterDskPlateFail and AfterDskArmsFail, having as guards that there is not a plate on the Rotary Table under the Stacker, and that the arms are down, respectively. From the state des_suspended1 the component resumes to the state destack1 if there is a remedy, otherwise it aborts. 10.3 U2B translation to B-action systems and first refinement of the system At this point the class and statechart diagrams of the first refinement of the system can be translated to B-action systems, using the U2B tool. Then the Atelier B tool can be used in order to verify that these diagrams refine the corresponding abstract ones. It can be seen from the Rotary Table’s first refinement class diagram that dependency relationships are used between the classes, with a stereotype bind. U2B detects this kind of relationship with that stereotype and adds an INCLUDES clause with the names of the included machines in the ROTARY_TABLE_R1 refinement machine. An INCLUDES clause can be written manually in the documentation box of the classes as well. Furthermore, a realize relationship indicates that the ROTARY_TABLE_R1 class refines the ROTARY_TABLE class. As it can be seen, the specification class contains the same number of operations as the refinement class. This occurs in the UML diagram because the B-action systems formalism requires it. The operations that are new in the refinement and specified there, they are given as skip operations in the specification diagram. The PLATEHOLDER class does not have any statechart diagram attached. All the procedures are specified within this class. For every operation there is a specification window so that all the parameters, preconditions, and semantics can be written there. The SELECT guards are an important feature to B-action systems, so by giving the stereotype action system or event system to the logical view of the UML model, allows the U2B tool to translate all the conditions given in the precondition box of an operation, as SELECT

Page 61: ABSTRACT - abo.fi

53

guards. The translated machines of the first refinement class diagram for the Rotary Table is given in Appendix D. One extra feature in the Stacker’s first refinement class diagram compared to the Rotary Table’s ones, is the association UML relationship between the STACKER_R1 class and the STACKER_PROC procedure class of the Stacker. The procedure class has the same multiplicity, four, as the STACKER_R1 class, and the four objects specified from each of these classes must be connected. Setting the cardinality of the association relationship to 0..1 at the STACKER_R1 class end, and to 1..1 at the STACKER_PROC class end, as it can be seen in Figure 33 below, is equivalent to a total injection in the B Method. Then

Figure 33. Specification for “ role A” of the association end. the Stacker_proc role name of the association is translated as a total injection function in the STACKER_R1 refinement, which relates the instances of the two classes. Stacker_proc : STACKER >-> STACKER_PROC Thus, wherever a procedure is called from the STACKER_PROC class, the Stacker_proc variable is used as a “parameter” in order U2B to automatically generate the instance parameter thisSTACKER. The variable Stacker_proc could be placed automatically in the statechart diagrams. The placement of this variable, Stacker_proc, into the statechart

Page 62: ABSTRACT - abo.fi

54

diagrams was done manually. Moreover, the Stacker_proc variable is used in the same way in the guards of the Stacker’s operations if they contain the variable arms or the variable s_pos, both defined in the procedure class, in order for the instance parameter, thisSTACKER, to be generated. This can be seen in the translated refinement machine STACKER_R1.ref given in Appendix D.3. Proof Obligations for the first refinement The tool Atelier B can now be used to generate the proof obligations for the refinement and try to prove them automatically. Figure 34, below, shows the number of proof obligations generated for the Rotary Table and how many of them were automatically

Figure 34. Proof Obligations generated by Atelier B for the first refinement of the Rotary Table

proved. Only two of the proof obligations require interactive proving. Figure 35, below, shows the number of the proof obligations generated for the Stacker unit and how many of them were automatically proved. It can be seen that more proof obligations of the Stacker unit require the interactive prover in order to be proved, compared to the Rotary Table.

Figure 35. Proof Obligations generated by Atelier B for the first refinement of the Stacker unit

This is due to the instance referencing mainly.

Rotary Table Specification Model � Proof Obligations Generated: 13

Proved: 13 Unproved: 0 Rotary Table 1st Refinement Model

� Proof Obligations Generated: 53 Proved: 51 Unproved: 2

Stacker Specification Model � Proof Obligations Generated: 114

Proved: 78 Unproved: 36 Stacker 1st Refinement Model

� Proof Obligations Generated: 175 Proved: 130 Unproved: 45

Page 63: ABSTRACT - abo.fi

55

10.4 Safety issues for the first refinement For the first refinement of the system more detailed information about faults and conditions of failure presence has been obtained. This refinement step introduces distinction between failures. The operation, for example, StackArmsFail models fault occurrence during the execution of the action Stack: StackArmsFail (thisSTACKER) =

PRE thisSTACKER : STACKER THEN

SELECT arms(Stacker_proc(thisSTACKER)) = up THEN s_state1(thisSTACKER):=prestack_suspended1 || SELECT s_state1(thisSTACKER)=ready_to_stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END

END These kinds of faults are caused by the physical failures of the system components taking part in the execution. Actions such as PreStackNoRemedy model system shut down: PreStackNoRemedy (thisSTACKER) =

PRE thisSTACKER : STACKER

THEN SELECT s_state1(thisSTACKER)=prestack_suspended1 THEN s_state1(thisSTACKER):=abort1 END

END Such actions are enabled when attempts to fix the occurred faults fail. Safety analysis has been evolved by identifying different failure modes of the system. 10.5 Class diagram of the second refinement step of the Rotary Table The class diagram of the second refinement of the Rotary Table can be found in Appendix E.1. In this refinement step the introduced details for the Rotary Table are on the status of a plate on a plate holder and on the plate holder itself. The class PLATEHOLDER of the first refinement is renamed to PLATEHOLDER1 because some new variables have been added, the variables zmid and zminAllowed have been renamed and the variable liq_present has been removed because it is not applicable in this refinement step, after the added details for a plate being on a plate holder.

Page 64: ABSTRACT - abo.fi

56

As mentioned above, the variable zmid is renamed xymoveOk. It is easier to understand now that this variable models the lowest z position possible when the Dispensing Head is moving in xy-direction. Also, the variable zminAllowed is renamed Acc_minHeight, because of the more precise positioning of the Dispensing Head onto the plates. Moreover, a variable plate_id is added in the PLATEHOLDER class in order to keep track of the plate’s id being on a plate holder, because every plate in the system has an id. Furthermore, a variable Acc_Height is added, which models the height of the plate holder with or without a plate on it. The variables pholder, temp_ph_pos1, and ph_pos have not changed. The variable liq_present is not needed in this refinement step because of the new class PLATE, which contains a variable Plate keeping track of a plate, with some id, having a certain height, height, a liquid amount, liquid_amt, a minimum height, minheight, a maximum volume, maxVol, and a number of wells, noOfW. The PLATEHOLDER1 class includes the procedure class PLATE. This class PLATE contains the procedures that update these variables and these procedures are called from the corresponding procedures of the PLATEHOLDER1 class. The procedures in the PLATEHOLDER1 class are updated in order to take into account the newly introduced variables. Moreover, in the procedure NewPlateholderPos of this class, the Acc_minHeight variable is updated in a deterministic way by referring to the specific heights of the plate holder and the plate, in contrast to the non-determinism used in the first refinement, to update the zminAllowed variable after every time a rotation occurred. The same variables, extpos and ZCoord, from the XYZD_PROC and ZDRIVER1 classes, respectively, are checked from the ROTARY_TABLE_R2 class as in the previous refinement step. The invariant of the classes The invariant of the PLATEHOLDER1 machine is updated to relate the variables of the PLATEHOLDER1 to the variables of PLATEHOLDER as follows. When there is a plate holder on the Rotary Table, the variable Acc_minHeight has a value greater than or equal to the plate holder’s height, pholder( )´height. Moreover, when there is a plate present on the plate holder, the id of the plate is a valid id from the set PID, and if there is a plate on the plate holder at the dispensing position, the value of the variable Acc_minHeight is equal to the height of the plate holder plus the minimum height of the plate plus the zmin value. If there is not a plate at the dispensing position, the value of the variable Acc_minHeight is equal to the height of the plate holder plus the zmin value. Furthermore, the variable xymoveOk has to have a value greater than the plate holder’s height plus the zmin height. (!xx.(xx:dom(pholder) => Acc_minHeight >= (pholder(xx))'height)) & (!xx.(xx:dom(pholder) & (pholder(xx))'plate_present = TRUE =>

plate_id(xx):dom(Plate))) & ((pholder(ph_pos(DispPos)))'plate_present=TRUE => Acc_minHeight =

(pholder(ph_pos(DispPos)))'height + (Plate(plate_id(ph_pos(DispPos))))'minheight + zmin) & ((pholder(ph_pos(DispPos)))'plate_present=FALSE => Acc_minHeight =

(pholder(ph_pos(DispPos)))'height + zmin) & (!xx.(xx:dom(pholder) => (pholder(xx))'height + zmin < xymoveOk))

Page 65: ABSTRACT - abo.fi

57

The invariant of the PLATE machine states that the plate’s minimum height, minheight, is less than the plate’s height and that the liquid amount, liquid_amt, of the plate is always less than the plate’s maximum volume, maxVol. (!xx:(xx:PID => (Plate(xx))'minheight <= (Plate(xx))'height)) & (!xx.(xx:PID => (Plate(xx))'liquid_amt <= (Plate(xx))'maxVol)) Furthermore, the invariant of the ROTARY_TABLE_R2 refinement class states the refinement relation of the zmid and zminAllowed variables to the xymoveOk and Acc_minHeight variables, respectively. The zmid and xymoveOk variables are equal and the Acc_minHeight variable is more concrete but the set of its values has the same limits than the zminAllowed variable. Also, the refinement relation is stated, in that invariant, between the liq_present variable of the PLATEHOLDER class and the liquid_amt variable of the PLATE class. If there is liquid present in the plate holder, then the liquid amount of the plate is greater than zero, and if there is not liquid present in the plate holder then the liquid amount of the plate is zero. xymoveOk = zmid & Acc_minHeight = zminAllowed & (!xx.(xx:PH_ID => liq_present(xx) = TRUE => !yy.(yy:PID => (Plate(yy))'liquid_amt > 0))) & (!xx.(xx:PH_ID => liq_present(xx) = FALSE => !yy.(yy:PID => (Plate(yy))'liquid_amt = 0))) 10.6 Statechar t diagram of the second refinement for the Rotary Table The statechart diagram of the Rotary Table can be found in Appendix E.2. As it can be seen this diagram is identical to the statechart diagram of the first refinement, except that the guards of some transitions have changed to reflect the changes of the variables. The variable zmid in the guards of the transitions RotateZCoordFail, Rotate, RotateCommandRemedy, and RotateRemedy has been substituted from the variable xymoveOk. Everything else has remained the same in this statechart diagram as before. The translated machines of the class diagram can be found in Appendix F. Proof Obligations Generated for the second refinement Figure 36, below, shows the number of proof obligations generated for the Rotary Table and how many of them were automatically proved.

Figure 36. Proof Obligations generated by Atelier B for the second refinement of the Rotary Table

Rotary Table 2nd Refinement Model � Proof Obligations Generated: 117

Proved: 70 Unproved: 47

Page 66: ABSTRACT - abo.fi

58

11 Control System development A control system is usually a complex system consisting of several components interacting with each other, like the Rotary Table, the Stackers and the Dispensing Head in this case study. The final step of the Rotary Table development is the control system development. This component will be decomposed to control system modules. 11.1 Decomposition of the Rotary Table A stepwise development method is described here for developing the Rotary Table control system. During this development, safety and reliability measures have to be incorporated into the system. This means increasing complexity in the control logic, because it has to cope with malfunctioning sensors and actuators [PTWBEJ01]. In this stepwise development method, first an initial specification is created where the Rotary Table component is decomposed to a plant and a controller specification and, finally, sensors and actuators specifications are introduced to the system. 11.1.1 Determining controller and plant After all the details have been introduced for the Rotary Table component in the second refinement step, this component is decomposed to a controller specification and a plant specification. The obtained plant specification describes autonomous behaviour of the component, while the controller specification describes algorithms that guide the plant behaviour. Thus, the controller reacts to changes in the plant. 11.1.2 Class diagram of the controller and plant specifications The class diagram of the Rotary Table’s controller and plant specifications can be found in Appendix G.1. The plant class, ROTARY_TABLE_PLANT, is refining the class ROTARY_TABLE_R2. It contains the operations of the system, so it has the active role of the system. The plant class includes the controller class for calling its procedures. The controller class, ROTARY_TABLE_CONTROLLER, contains all the controlling procedures, one for each operation of the plant, as well as the calls to the procedures of the PLATEHOLDER1 class. Moreover, the controller class includes the STACKER_PROC, XYZD_PROC, and ZDRIVER1 classes. Because of the includes structuring mechanism’s transitivity, the plant can read the variables of these classes. Furthermore, these classes have not changed since the second refinement step. Whenever the plant wants to notify the controller of an event, it calls the corresponding control procedure. Every state change in the plant and the controller constitutes a single atomic operation, thus a controller state variable, ctrl_r_state, is defined and the invariant of the plant states that the plant’s state variable is equal to the controller’s state variable. The role of the ctrl_r_state variable is to coordinate the plant and the controller classes. The set of the controller states, CTRL_R_STATE, is defined in the class DEF2. As it can be seen from the diagram, the attributes, or variables, except the state variable of the ROTARY_TABLE_R2 second refinement class are declared in the controller

Page 67: ABSTRACT - abo.fi

59

class. The plant contains only the state variable, which is the same as the state variable of the ROTARY_TABLE_R2 class. Thus, whenever the plant needs to change the state the relevant control procedure is called. It is necessary that the controller’s procedures contain no SELECT guards. Only PRE guards are allowed in these procedures. Thus, the procedures of the controller class are completely defined in the class diagram by using the operation specification window for each procedure. 11.1.3 Statechart diagram of the Rotary Table plant The statechart diagram of the plant can be found in Appendix G.2. As it can be seen, the states are the same as the states from the previous refinement step, as well as the transitions names and the guards of these transitions. The calls to the procedures of the PLATEHOLDER1 class are moved into the controller’s procedures and for every transition of the plant the corresponding controller procedure is called. 11.1.4 U2B translation to B-action systems The same features in the class and statechart diagram are checked by U2B as in the previous development steps, except that now the action system stereotype has been removed from the logical view of the UML model. This prevents U2B from translating whatever is written in the precondition box of every operation as SELECT guard. The preconditions of the controller’s procedures are now translated as PRE preconditions and the preconditions of the plant’s operations are given as SELECT guards. As an example, let us consider the operation RotateFail from the plant. The U2B translation is given below. RotateFail =

BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended || RrotateFail END

END U2B checks the initial state and puts it in the SELECT guard, as well as the rotate command, rot_cmd, which is written in the guard box of the transition’s specification window. Then the RrotateFail procedure from the controller is called, as one of the actions of the transition. The precondition PRE in RrotateFail is the same as the guard SELECT in RotateFail. The translation of this procedure is given below. RrotateFail =

PRE ctrl_r_state=ctrl_get_ready & rcmd=rot_cmd

THEN ctrl_r_state:=ctrl_pre_rot_suspended

END

Page 68: ABSTRACT - abo.fi

60

The translated plant and controller machines together with the machines they include and see, are given in Appendix H. The parallel decomposition of a B-action system into more B-action systems that have the same effect as the initial B-action system is a structuring technique. Thus, this control system development step is correct. 11.2 Determining sensors and actuators In the last development step, the sensors and actuators are determined for the component from the controller and plant specifications. Usually, some of the variables of the plant and the controller are used for communication. The sensors and actuators are found from these variables and they are used to synchronize the plant and the controller. In the Rotary Table the position of the plate holder on the table, ph_pos, the id of a plate being on a plate holder, plate_id, the variable with the status of the plate holder, pholder, as well as the height of a plate holder with or without a plate on it, Acc_Height, are changed by the controller. Hence, these variables model actuators. The ZDRIVER1 class of the Dispensing Head has been checked until now from the Rotary Table because the actual z position, ZCoord, variable is of interest to it. This variable models a sensor, which is included by the plant. 11.2.1 Class diagram of the final control system The class diagram of the final control system is given in Appendix I.1. As it can be seen from the diagram, the operations of the refined class, ROTARY_TABLE_PLANT1, have remained the same as in the first plant specification. The same applies to the refined controller class, ROTARY_TABLE_CONTROLLER1. This controller class includes the PLATEHOLDER2 class, which in turn includes the class having the actuators of the Rotary Table, RT_CONTROLLER_ACTUATOR. As in the previous step, the PLATEHOLDER2 class includes the PLATE class, which is unchanged. The PLATEHOLDER2 class is renamed, from PLATEHOLDER1, because of the moving of the actuators to the actuator class RT_CONTROLLER_ACTUATOR, and because of the updating of its operations to reflect the changes. The decomposition of the sensor and actuator machines, in the section 7.2, differs from the one presented in this section, here, in the way that the actuator machine, RT_CONTROLLER_ACTUATOR, is one level lower. It is not at the same level as the PLATEHOLDER2 machine, because this machine includes the actuator machine. Putting the actuator machine at the same level, it would require a lot of restructuring of the class diagram. This is still ongoing research. Moreover, whenever a procedure, which previously updated the variables being in this step actuators, is called from the PLATEHOLDER2 class, the corresponding procedure from the RT_CONTROLLER_ACTUATOR is called, in order to update the actuator values.

Page 69: ABSTRACT - abo.fi

61

The sensor of the system, ZCoord, requires renaming to ZCoord1 because it is defined in two different classes. This is important because it allows the proving to be done for the whole system development in Atelier B. The invariant of the plant states that these two variables are the same. This sensor value is in the class Z_SENSOR, which is included by the class of the plant. 11.2.2 Statechart diagram of the plant & the B-action system of the final control system The statechart diagram of the plant of the final control system can be found in Appendix I.2. Because of the renaming of the sensor, ZCoord1, the guards of the transitions, in which the ZCoord variable occurred, need to be updated. This is the only difference between this diagram and the statechart diagram of the previous development step. By using the U2B tool to translate the class diagram, the B-action system of the final control system is given in Appendix J. This step required mainly rewriting and restructuring. Hence, with the tool Atelier B can be proved that the final control system is a refinement of the previous system without sensors and actuators. Proof Obligations Generated for the Control System decomposition Figure 37 below shows the number of generated proof obligations for the first and second step of the control system decomposition for the Rotary Table. Figure 37. Proof Obligations generated by Atelier B for the Rotary Table Control System

Rotary Table Control System (1st step) � Proof Obligations Generated: 258

Proved: 209 Unproved: 49 Rotary Table Control System (final)

� Proof Obligations Generated: 101 Proved: 42 Unproved: 59

Page 70: ABSTRACT - abo.fi

62

12 Conclusions The purpose of this Master of Science thesis was to present how the Unified Modeling Language (UML) can be used for modeling industrial strength control systems, from initial specification to implementation through some refinement steps. This development method is not obvious, nor straightforward to obtain for a complex final system, given only the initial requirements. This thesis has shown that the UML can be used successfully for such a development method, if there is good support of tools, such the ones used for this work. The use of the interactive prover of AtelierB was out of the scope of this work. Even though this limited the formality of the development method, the results by using only the automatic prover were good for the specification and the first refinement steps. One other advantage of using UML for the complete development of a control system is that generally diagrams are easier to understand and follow than pure program code. This was proved valuable during the meetings with the project team of Wallac company. No one of that team had experience with the B Method resulting in a slight “disappointment” when our team tried to show some B code, but when the UML diagrams were on the table for discussion they seemed pleased. Moreover, this kind of development provides the users/programmers with good documentation, something very important when developing large and complex systems. Furthermore, the U2B tool could be improved in some aspects. For example, the handling of the states could be more automatic. Also, U2B generated double initialization for some of the variables because it did not detect the ANY…WHERE…THEN statement in the INITIALISATION clause. Moreover, U2B could take into account more UML diagrams than the statechart and class diagrams. In complex systems, such as the one developed in this thesis, where many objects interact with each other, collaboration, sequence and activity diagrams are of interest. Collaboration diagrams emphasize the structural organization of the objects, sequence diagrams emphasize the time ordering of messages sent between the objects and this is very useful at testing time of a system, and activity diagrams model the function of a system, because they emphasize the flow of control among objects.

Page 71: ABSTRACT - abo.fi

63

References [Abrial96] J. –R. Abrial. The B-Book: Assigning Programs to Meanings. Cambridge

University Press, 1996. [AtelierB03] Atelier B. http://www.atelierb.societe.com/index_uk.html [BaKu83] R.J.R. Back and R. Kurki-Suonio, Decentralization of process nets with centralized control. In Proc. of the 2nd ACM SIGAST-SIGOPS Symp. on Principles of Distributed Computing, pages 131-142, 1983. [BS94] R.J.R. Back and K. Sere. From Actions Systems to Modular Systems. In

Proc. of FME’94: Industrial Benefit of Formal Methods. LNCS 873, pp.1-25, Barcelona, Spain, October 1994. Springer-Verlag. [BaWright98] R.J.R. Back and J. von Wright. Refinement Calculus – A Systematic

Introduction. Springer – Verlag, 1998. [BRJ99] G. Booch, J. Rumbaugh and I. Jacobson. The Unified Modeling Language

User Guide. Addison Wesley, 1999. [BJW03] P. Bostroem, M. Jansson and M. Walden. A Healthcare Case Study: Fillwell. TUCS Technical Reports, Turku

Centre for Computer Science, Finland. To appear Spring 2003. [Brooks85] Rodney A. Brooks. A Robust Layered Control System For a Mobile Robot. Massachusetts Institute of Technology, Artificial Intelligence Laboratory.

September 1985.

[BSS96] M. Butler, E. Sekerinski, and K.Sere. An Action System Approach to the Steam Boiler Problem. In Jean-Raymond Abrial, Egon Borger and Hans Langmaack, editors, Formal Methods for Industrial Applications: Specifying and Programming the Steam Boiler Control. Lecture Notes in Computer Science Vol. 1165. Springer-Verlag, 1996.

[Dijkstra75] Edsger W. Dijkstra. Guarded Commands, Nondeterminacy and Formal

Derivation of Programs. Communications of ACM. Volume 18, Number 8, August 1975.

[Douglass99] B. P. Douglass. Doing Hard Time. Developing Real-Time Systems with

UML, Objects, Frameworks, and Patterns. Addison Wesley, 1999. [Fillwell02] The Fillwell workstation. http://www.abo.fi/~mwalden/Fillwell.pdf [IST-1999-11435] MATISSE: Methodologies and Technologies for Industrial

Strength Systems Engineering. www.matisse.qinetiq.com

Page 72: ABSTRACT - abo.fi

64

[LL95] C. Lewerentz and Th. Linder (eds). Formal Development of Reactive Systems – Case Study Production Cell. Lecture Notes in Computer Science 891, Springer – Verlag 1995.

[PerkinElmer03] PerkinElmer Life Sciences. http://www.perkinelmer.com/lifesciences

[PQS99] L. Petre, M. Qvist and K. Sere. Distributed Object-Based Control Systems.

TUCS Technical Reports, No 241, Turku Centre for Computer Science, Finland, February 1999.

[PRTWJ01] L. Petre, M. Rönkkö, E. Troubitsyna, M.Waldén and M. Jansson. A methodology for co-design based on a healthcare case study. TUCS Technical Reports, No 437, Turku Centre for Computer Science, Finland, December 2001.

[PTWBEJ01] L. Petre, E. Troubitsyna, M.Waldén, P. Boström, N. Engblom and M.

Jansson, A methodology for integration of formal methods in a healthcare case study. TUCS Technical Reports, No 436, Turku Centre for Computer Science, Finland, December 2001.

[PS99] J. Plosila and T. Seceleanu. Synchronization of Action Systems. TUCS

Technical Reports, No 271, Turku Centre for Computer Science, Finland, May 1999.

[Rational03] Rational Rose Enterprise edition. http://www.rational.com/products/rose/rsds/renterprise_generic.jsp

[Rhapsody03] The Rhapsody tool. http://www.ilogix.com/products/rhapsody/index.cfm

[Schneider01] S. Schneider. The b-method. An Introduction. Palgrave, 2001. [Sekerinski99] E. Sekerinski. Production Cell. Chapter 6 in Program Development by

Refinement. Case Studies Using the B Method. Springer – Verlag, 1999. [SB02] C. Snook and M. Butler. Tool-Supported Use of UML for Constructing B

Specifications. Technical Report DSSE – TR-2002-1, University of Southampton, United Kingdom, April 2002.

[SB03] C. Snook and M. Butler. UML to B downloads.

http://www.ecs.soton.ac.uk/~cfs/U2Bdwonloads/U2Bdownloads.htm [SP00] P. Stevens and R. Pooley. Using UML. Software Engineering with Objects

and Components. Addison Wesley, 2000.

Page 73: ABSTRACT - abo.fi

65

[SG96] M. Swaw and D. Garlan. Software Architecture. Perspectives on an Emerging Discipline. Prentice Hall, 1996.

[UML1.4] Unified Modeling Language (UML) 1.4 specification.

http://cgi.omg.org/cgi-bin/doc?formal/01-09-67 [WS97] M. Waldén and K. Sere, Data Refinement of Remote Procedures. In Proc.

of Computer Software (TACS97), edited by M. Abadi and T. Ito, LNCS 1281, pp. 267 – 294, Sendai, Japan, September 1997. Springer – Verlag.

[WS98] M. Waldén and K. Sere, Reasoning about Action Systems using the

B Method. In Formal Methods in System Design, Vol.13, No. 1, May1998, pp. 5 - 35. Kluwer Academic Publishers.

Page 74: ABSTRACT - abo.fi

66

Appendix A: Statechar t diagram of Stacker for the destack service.

idle

suspended

prepare

destack des_suspe nded

abort

start

stop

prep_dsk_ suspended

ServiceNotReady

DestackCommand / scmd:=dsk_cmd

DestackCommandRemedy[ scmd=dsk_cmd ]

PrepDestackNoRemedy

Remedy

NoRemedy

Destack[ scmd=dsk_cmd ]

DestackFail[ scmd=dsk_cmd ]

DestackOk[ scmd=dsk_cmd ]

DestackNotOk[ scmd=dsk_cmd ]

DestackRemedy[ scmd=dsk_cmd ]

DestackNoRemedy

Page 75: ABSTRACT - abo.fi

67

Appendix B: The specification of the Rotary Table and the Stacker unit as B-action systems B.1 The specification of the Rotary Table MACHINE ROTARY_TABLE SEES def SETS /* Rotary Table states * / R_STATE={ rotate,pre_rot_suspended,suspended,abort,get_ready,idle,rot_suspended} VARIABLES r_state, /* State variable * / rcmd /* Command variable * / INVARIANT r_state : R_STATE & rcmd : TCOMMAND & /* When Rotary Table is in states "get_ready", "rotate" and "rot_suspended" the command variable has to be equal to rotate command "rot_cmd" * / (r_state = get_ready => rcmd = rot_cmd) & (r_state = rotate => rcmd = rot_cmd) & (r_state = rot_suspended => rcmd = rot_cmd) INITIALISATION r_state := idle || /* The initial state is "idle" * / rcmd :: TCOMMAND OPERATIONS /* Operation for supplying the rotate command, "rot_cmd", to the command variable "rcmd".* / RotateCommand (p_steps) = PRE p_steps:INT THEN SELECT r_state=idle THEN r_state:=get_ready || rcmd:=rot_cmd END END ; /* Operation to Rotate. * / Rotate = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd

Page 76: ABSTRACT - abo.fi

68

THEN r_state:=rotate END END ; /* Failure when starting the rotation. Suspend rotation. * / RotateFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended END END ; /* Remedy for failure starting a rotation * / RotateCommandRemedy = BEGIN SELECT r_state=pre_rot_suspended & rcmd=rot_cmd THEN r_state:=get_ready END END ; /* Abort if there is no remedy when starting a rotation * / PreRotateNoRemedy = BEGIN SELECT r_state=pre_rot_suspended THEN r_state:=abort END END ; /* Rotation completed successfully * / RotateOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd THEN r_state:=idle END END ; /* Rotation did not completed successfully * / RotateNotOk = BEGIN SELECT r_state=rotate & rcmd = rot_cmd THEN r_state:=rot_suspended END

Page 77: ABSTRACT - abo.fi

69

END ; /* Remedy for failures occurred during rotation * / RotateRemedy = BEGIN SELECT r_state=rot_suspended & rcmd=rot_cmd THEN r_state:=rotate END END ; /* No remedy for failures occurred during rotation. Abort execution * / RotateNoRemedy = BEGIN SELECT r_state=rot_suspended THEN r_state:=abort END END ; /* General failure * / ServiceNotReady = BEGIN SELECT r_state=idle THEN r_state:=suspended END END ; /* Remedy for general failure * / Remedy = BEGIN SELECT r_state=suspended THEN r_state:=idle END END ; /* No remedy for general failure. Abort * / NoRemedy = BEGIN SELECT r_state=suspended THEN r_state:=abort END END ; /* Operations specified in the first refinement step. Required here from Atelier B * / RotateArmsFail = BEGIN

Page 78: ABSTRACT - abo.fi

70

SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended END END ; RotateZCoordFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended END END END B.2 The specification of the Stacker unit MACHINE STACKER_CLASS_STACKER_R1 SEES def SETS /* Stacker states * / S_STATE={ idle,suspended,prepare,destack,des_suspended,abort,prep_dsk_suspended,stack,st_suspended,prep_sk_suspended} CONSTANTS STACKER PROPERTIES STACKER = 1..4 /* There are four Stackers * / VARIABLES s_state, /* State variable * / scmd /* Command variable * / INVARIANT s_state : STACKER --> S_STATE & scmd : STACKER --> SCOMMAND & !(thisSTACKER).(thisSTACKER:STACKER => (

s_state(thisSTACKER) = prepare => scmd(thisSTACKER) = dsk_cmd or s_state(thisSTACKER) = prepare => scmd(thisSTACKER) = sk_cmd &

s_state(thisSTACKER) = destack => scmd(thisSTACKER) = dsk_cmd & s_state(thisSTACKER) = des_suspended => scmd(thisSTACKER) = dsk_cmd & s_state(thisSTACKER) = stack => scmd(thisSTACKER) = sk_cmd & s_state(thisSTACKER) = st_suspended => scmd(thisSTACKER) = sk_cmd)) INITIALISATION s_state:= %xx.(xx:STACKER | idle) || ANY yy WHERE yy:SCOMMAND THEN scmd:= %xx.(xx:STACKER | yy) END

Page 79: ABSTRACT - abo.fi

71

OPERATIONS /* Operation for supplying the destack command, "dsk_cmd", to the command variable "scmd".* / DestackCommand (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=idle THEN s_state(thisSTACKER):=prepare || scmd(thisSTACKER):=dsk_cmd END END ; /* Required here from Atelier B * / PrepareDestack (thisSTACKER) = PRE thisSTACKER : STACKER THEN skip END ; /* Failure – suspend service * / DestackFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=prep_dsk_suspended END END ; /* fix the problem * / DestackCommandRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prep_dsk_suspended & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=prepare END END

Page 80: ABSTRACT - abo.fi

72

; /* Abort – The problem cannot be fixed * / PrepDestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prep_dsk_suspended THEN s_state(thisSTACKER):=abort END END ; /* Destack plate * / Destack (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=destack END END ; /* The stacker has destacked plate * / DestackOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=destack & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=idle END END ; /* Failure – The Stacker has not destacked a plate * / DestackNotOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=destack & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=des_suspended END END

Page 81: ABSTRACT - abo.fi

73

; /* Abort – The problem cannot be fixed * / DestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=des_suspended THEN s_state(thisSTACKER):=abort END END ; /* Fix the problem * / DestackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=des_suspended & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=destack END END ; /* Operation for supplying the stack command, "dsk_cmd", to the command variable "scmd".* / StackCommand (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=idle THEN s_state(thisSTACKER):=prepare || scmd(thisSTACKER):=sk_cmd END END ; /* Required here from Atelier B. Specified later * / PrepareStack (thisSTACKER) = PRE thisSTACKER : STACKER THEN skip END ;

Page 82: ABSTRACT - abo.fi

74

/* Failure – suspend service * / StackFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=prep_sk_suspended END END ; /* Fix the problem * / StackCommandRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prep_sk_suspended & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=prepare END END ; /* The problem cannot be fixed * / PrepStackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prep_sk_suspended THEN s_state(thisSTACKER):=abort END END ; /* Stack a plate * / Stack (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=stack END END

Page 83: ABSTRACT - abo.fi

75

; /* The Stacker has stacked a plate * / StackOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=stack & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=idle END END ; /* Failure – The Stacker has not stacked a plate * / StackNotOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=stack & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=st_suspended END END ; /* Abort – The problem cannot be fixed * / StackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=st_suspended THEN s_state(thisSTACKER):=abort END END ; /* Fix the problem * / StackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=st_suspended & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=stack

Page 84: ABSTRACT - abo.fi

76

END END ; /* General “not ready” failure * / ServiceNotReady (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=idle THEN s_state(thisSTACKER):=suspended END END ; /* Fix the problem * / Remedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=suspended THEN s_state(thisSTACKER):=idle END END ; /* No remedy – Abort * / NoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=suspended THEN s_state(thisSTACKER):=abort END END ; /* ******************************************************************* / /* Operations required here from Atelier B * / StackPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=prep_sk_suspended

Page 85: ABSTRACT - abo.fi

77

END END ; AfterDskArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=destack & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=des_suspended END END ; /* Required here from Atelier B. Specified later * / StackFullStackerFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=prep_sk_suspended END END ; AfterSkArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=stack & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=st_suspended END END ; DestackEmptyStackerFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare &

Page 86: ABSTRACT - abo.fi

78

scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=prep_dsk_suspended END END ; DestackArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=prep_dsk_suspended END END ; StackArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prepare & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=prep_sk_suspended END END ; AfterDskPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=destack & scmd(thisSTACKER)=dsk_cmd THEN s_state(thisSTACKER):=des_suspended END END ; PreStackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER

Page 87: ABSTRACT - abo.fi

79

THEN SELECT s_state(thisSTACKER)=prep_sk_suspended THEN s_state(thisSTACKER):=abort END ; PreDestackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)= prep_dsk_suspended THEN s_state(thisSTACKER):=prepare END ; AfterSkPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=stack & scmd(thisSTACKER)=sk_cmd THEN s_state(thisSTACKER):=st_suspended END END ; PreStackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)= prep_sk_suspended THEN s_state(thisSTACKER):=prepare END ; PreDestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state(thisSTACKER)=prep_dsk_suspended THEN s_state(thisSTACKER):=abort END END

Page 88: ABSTRACT - abo.fi

80

B.3 The sets of commands for the Rotary Table and the Stacker unit In DEF machine the sets of commands are defined which are used in the Rotary Table and the Stacker unit MACHINE DEF SETS TCOMMAND={ rot_cmd} ; /* Rotary Table command set * / SCOMMAND={ dsk_cmd, sk_cmd} ; /* Stacker command set * / END

Page 89: ABSTRACT - abo.fi

81

Appendix C: The 1st refinement of the system Appendix C.1: The class diagram of the 1st refinement for the Rotary Table.

ROTARY_TABLE rcmd : TCOMMAND

RotateCommand(p_steps : INT) Rotate() RotateFail() RotateCommandRemedy() PreRotateNoRemedy() RotateOk() RotateNotOk() RotateRemedy() RotateNoRemedy() ServiceNotReady() Remedy() NoRemedy() RotateArmsFail() RotateZCoordFail()

ROTARY_TABLE_R1 rcmd : TCOMMAND steps : INT = ::-5..5

RotateCommand() Rotate() RotateFail() RotateCommandRemedy() PreRotateNoRemedy() RotateOk() RotateNotOk() RotateRemedy() RotateNoRemedy() RotateArmsFail() RotateZCoordFail() ServiceNotReady() Remedy() NoRemedy()

PLATEHOLDER ph_pos : ROTARY_POS --> PH_ID temp_ph_pos1 : PH_ID pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT) liq_present : PH_ID +-> BOOL zmid : NAT zminAllowed : zmin..zmid

PlateholderChange(ph_id : PH_ID, p_height : NAT, pos : ROTARY_POS) PlateholderPlateAdd(ph_id : PH_ID, pl_liq : BOOL) PlateholderPlateRemove(ph_id : PH_ID) PlateholderLiquidPresent(ph_id : PH_ID) AddLiquid(ph_id : PH_ID) RemoveLiquid(ph_id : PH_ID) NewPlateholderPos(rr : INT) HeightOk(zpos : NAT) HeightNotOk(zpos : NAT) SetOldPos(p_phid : PH_ID)

STACKER_PROC arms : ARM_POS = up s_pos : {2, 3, 5, 6}

ChangeStArms(dir : ARM_POS)

DEF2

XYZDRIVER_PROC extpos : 1..max_extpos = home_ext old_extpos : 1..max_extpos = home_ext z_refpoint : REFERENCE_POINTS = acc_maxheight old_z_refpoint : REFERENCE_POINTS = acc_maxheight

SetExtPos(p_extpos : NAT) SetOldExtPos() SetZRefpoint(p_zrefpoint : REFERENCE_POINTS) SetOldZRefpoint()

ZDRIVER1 ZDest_Coord : zmin..zmax = zcoord(home_z)

ZMove(pos : zmin..zmax) ZMoveFail() ZMoveNotOk() ZServiceNotReady() ZRemedy() ZFailure() ZMoveRemedy() ZMoveOk() ZGeneralRemedy()

<<bind>>

<<bind>>

<<bind>>

<<bind>>

Page 90: ABSTRACT - abo.fi

82

Appendix C.2: The statechart diagram of the 1st refinement for the rotate service of the Rotary Table.

abort

get _readyidle

stop

start

pre_rot_suspended

rot_suspended

rotate

suspended

[ !ss.(ss:STACKER_PROC =>arms(ss) = up) ]

RotateArmsFai l [ #ss.(ss:STACKER_PROC & arms(ss) = down) ]

RotateZC oordFai l [ ZCoord<=zmid & extpos > 3 ]

Rotate[ ZCoord >= zmid or extpos<=3 ] / NewPlateholderPos(steps)

Remedy

NoRemedy

RotateFai l[ rcmd=ro t_cmd ][ rcmd = rot_cmd ]

RotateCommand( p_steps ) / steps:=p_steps;SetOldPos(ph_pos(DispPos));rcmd:=rot_cmd

ServiceNotReady

RotateNotOk[ rcmd = rot_cmd & ph_pos~(temp_ph_pos1) /= ((6+DispPos+steps-1)mod 6)+1 ]

RotateOk[ rcmd = rot_cmd & ph_pos~(temp_ph_pos1) = ((6+DispPos+steps-1)mod 6)+1 ]

RotateNoRemedy

RotateRemedy[ rcmd = rot_cmd & (extpos <= 3 or ZCoord >= zmid) & !ss.(ss:STACKER_PROC =>arms(ss) = up) ]

RotateCommandR emedy[ rcmd = ro t_cmd & !ss.(ss:STACK ER_PROC =>arms(ss) = up) & (ZC oor d>=zmi d o r ex tpo s <= 3) ]

PreRotateNoRemedy

Page 91: ABSTRACT - abo.fi

83

Appendix C.3: The class diagram of the 1st refinement for the Stacker unit.

DEF2STACKER

scmd : SCOMMAND

DestackCommand()DestackFai l ()DestackCommandRemedy()PrepDestackNoRemedy()Destack()DestackOk()DestackNotOk()DestackRemedy()DestackNoRemedy()StackCommand()Stack()StackFai l ()StackCommandRemedy()PrepStackNoRemedy()StackOk()StackNotOk()StackRemedy()StackNoRemedy()ServiceNotReady()Remedy()NoRemedy()StackFul lStacker()StackPlateFai l ()AfterDskArmsFai l ()AfterSkArmsFai l ()DestackEmptyStackerFai l ()DestackPlateFai l ()DestackArmsFai l ()StackArmsFai l ()AfterDskPlateFai l ()PreStackNoRemedy()PreDestackRemedy()AfterSkPlateFai l ()PreStackRemedy()PreDestackNoRemedy()

PLATEHOLDER

ph_pos : ROTARY_POS --> PH_IDtemp_ph_pos1 : PH_IDpholder : PH_ID +-> struct(plate_present:BOOL,height:NAT)l iq_present : PH_ID +-> BOOLzmid : NATzminAl lowed : zm in..zmid

PlateholderChange(ph_id : PH_ID, p_height : NAT , pos : ROTARY_POS)PlateholderPlateAdd(ph_id : PH_ID, pl_l iq : BOOL)PlateholderPlateRemove(ph_id : PH_ID)PlateholderLiquidPresent(ph_id : PH_ID)AddLiquid(ph_id : PH_ID)RemoveLiquid(ph_id : PH_ID)NewPlateholderPos(rr : INT )HeightOk(zpos : NAT)HeightNotOk(zpos : NAT)SetOldPos(p_phid : PH_ID)

STACKER_PROC

arms : ARM_POS = ups_p os : {2, 3, 5, 6}

Chang eStArms(d ir : ARM_POS)

STACKER_R1

scmd : SCOMMANDemp ty : BOOLful l : BOOL

De st ackCommand()De st ackFai l ()De st ackPla te Fai l()De st ackEm pt ySt ackerFai l()De st ackCommandRem edy ()PrepDestackNoRe me dy()Prepa reDestac k()De st ackArmsFai l ()PreDe st ackRemedy()PreDe st ackNoRemed y()De st ack()De st ackOk()De st ackNot Ok()Aft erDskA rmsFai l()Aft erDskP lateFai l ()De st ackRemedy()De st ackNoReme dy()Stac kComman d()Stac kFai l ()Stac kFul lSta ckerFai l ()Stac kPlat eFai l ()Stac kComman dRemedy()PrepS tackNo Remedy ()Prepa reS tack()Stac kArm sFa il ()PreStackRemed y()PreStackNoRe medy()Stac k()Stac kOk()Stac kNotOk()Aft erS kArm sFa il ()Aft erS kPlat eFai l ()Stac kRemed y()Stac kNoRe medy()Se rv ic eNot Read y()Re me dy()No Remedy ()

<<bind>>

1..1

0..1

+Stacker_proc

1..1

0..1

refine

includes

Page 92: ABSTRACT - abo.fi

84

Appendix C.4: The statechart diagram of the 1st refinement of a Stacker for the destack service.

idle1 start

stop

suspended1

prepare1

destack1

des_suspended1

abort1

ready_to_destack1 [ scmd = dsk_cmd ]

prep_dsk_suspended1 DestackFail[ scmd=dsk_cmd ]

[ scmd=dsk_cmd ] DestackEmptyStackerFail[ empty = TRUE ]

[ empty = FALSE ]

predestack_suspended1 PreDestackRemedy[ scmd=dsk_cmd & arms(Stacker_proc) = down ]

PreDestackNoRemedy

PrepareDestack[ (pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = FALSE ] / ChangeStArms(Stacker_proc, down)

DestackPlateFail[ (pholder(ph_pos(s_pos(Stacker_proc)))´plate_present = TRUE ] DestackNoRemedy

DestackRemedy[ scmd=dsk_cmd & (pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = TRUE & arms(Stacker_proc) = up ]

ServiceNotReady

DestackCommand / scmd:=dsk_cmd

DestackCommandRemedy[ scmd=dsk_cmd & empty = FALSE & (pholder_id(ph_pos(s_pos(Stacker_proc))))´plate_present = FALSE ] PrepDestackNoRemedy

Remedy

NoRemedy

DestackOk[ (pholder(ph_pos(s_pos(Stacker_proc))´plate_present = TRUE ]

AfterDskPlateFail[ (pholder(ph_pos(s_pos(Stacker_proc)))´plate_present = FALSE ] AfterDskArmsFail[ arms(Stacker_proc) = down ]

[ arms(Stacker_proc) = up ]

DestackNotOk[ scmd=dsk_cmd ] [ scmd = dsk_cmd ]

Destack[ arms(Stacker_proc) = down ] / ChangeStArms(Stacker_proc, up) || PlateholderPlateAdd(ph_pos(s_pos(Stacker_proc))) DestackArmsFail[ arms(Stacker_proc) = up ]

Page 93: ABSTRACT - abo.fi

85

Appendix C.5: The statechart diagram of the 1st refinement of a Stacker for the stack service. stack1

st_suspended1

abort1 prepare1

idle1

suspended1

start

stop

ready_to_stack1 [ scmd = sk_cmd ]

prep_sk_suspended1 StackFail[ scmd=sk_cmd ]

[ scmd = sk_cmd ]

prestack_suspended1

StackCommandRemedy[ scmd=sk_cmd & full = FALSE & (pholder(ph_pos(s_pos(Stacker_proc)))´plate_present = TRUE ]

PrepStackNoRemedy

ServiceNotReady

StackCommand / scmd:=sk_cmd StackFullStackerFail[ full = TRUE ]

[ full = FALSE ]

StackPlateFail[ (pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = FALSE ]

PrepareStack[ (pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = TRUE ] / ChangeStArms(Stacker_proc, down)

PreStackRemedy[ scmd = sk_cmd & arms(Stacker_proc) = down ]

PreStackNoRemedy

Stack[ arms(Stacker_proc) = down ] / ChangeStArms(Stacker_proc, up) || PlateholderPlateRemove(ph_pos(s_pos(Stacker_proc))) StackArmsFail[ arms(Stacker_proc) = up ]

StackNotOk[ scmd = sk_cmd ] [ scmd = sk_cmd ]

Remedy

NoRemedy

StackNoRemedy

StackRemedy[ scmd=sk_cmd & arms(Stacker_proc) = down & (pholder(ph_pos(s_pos(Stacker_proc))))´plate_present = FALSE ]

StackOk[ (pholder(ph_pos(s_pos(Stacker_proc)))´plate_present = FALSE ]

AfterSkPlateFail[ (pholder(s_pos(Stacker_proc)))´plate_present = TRUE ]

AfterSkArmsFail[ arms(Stacker_proc) = down ]

[ arms(Stacker_proc) = up ]

Page 94: ABSTRACT - abo.fi

86

Appendix D: The first refinement step of the Rotary Table and the Stacker unit D.1 The refined Rotary Table REFINEMENT ROTARY_TABLE_R1 REFINES ROTARY_TABLE SEES def2, def /* INCLUDES XYZD_PROC, /* The Dispensing Head’s position above the Operating and Rotary Table is defined there, with the extpos variable * / ZDRIVER1, /* The z-position of the Dispensing Head is defined there * / STACKER_PROC_CLASS, /* The arms’ position of the Stackers is changed there * / PLATEHOLDER SETS /* Rotary Table states * / R_STATE={ rotate,rot_suspended,suspended,abort,get_ready,idle,pre_rot_suspended} VARIABLES r_state, /* State variable * / rcmd, /* Command variable * / steps /* Variable to store the number of rotation steps * / INVARIANT r_state : R_STATE & rcmd : TCOMMAND & steps : INT & /* When Rotary Table is in state "rotate" and the Dispensing Head is above the Dispensing Position 1, the Dispensing Head has to be at a certain height * / (extpos > 3 & r_state = rotate => ZCoord >= zmid) & /* When the Dispensing Head is above the Dispensing Position 1 of the Rotary Table, it has to be at the same height or higher than the minimum Z coordinate allowed. * / (extpos > 3 => ZCoord >=zminAllowed) & /* When Rotary Table is in state "rotate" the arms of all the Stackers have to be up * / (r_state = rotate => !ss.(ss:STACKERS_PROC =>arms(ss) = up)) & /* When Rotary Table is in state “ rotate” , “get_ready” and “ rot_suspended” the command variable "rcmd" has to be equal to rotate command "rot_cmd" * / (r_state = rotate => rcmd = rot_cmd) &

Page 95: ABSTRACT - abo.fi

87

(r_state = get_ready => rcmd = rot_cmd) & (r_state = rot_suspended => rcmd = rot_cmd) INITIALISATION r_state := idle || /* The initial state is "idle" * / rcmd :: TCOMMAND || steps :: -5..5 OPERATIONS

/* Operation for supplying the rotate command, "rot_cmd", to the command variable, “ rcmd” , giving the number of steps the table to rotate and calling the procedure SetOldPos from PLATEHOLDER class to store the id of the plateholder being at position 1 of the table before the rotation * /

RotateCommand (p_steps) = BEGIN SELECT r_state=idle THEN r_state:=get_ready || steps:=p_steps;SetOldPos(ph_pos(DispPos));rcmd:=rot_cmd END END ; /* Failure when starting the rotation. Suspend rotation. * / RotateFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended END END /* Suspend service – The arms of the Stackers are down * / RotateArmsFail = BEGIN SELECT #ss.(ss:STACKER_PROC & arms(ss) = down) THEN r_state:=pre_rot_suspended || SELECT r_state=get_ready & rcmd = rot_cmd THEN skip END END END ; /* Suspend service – The Dispensing head is not safe * /

Page 96: ABSTRACT - abo.fi

88

RotateZCoordFail = BEGIN SELECT ZCoord<=zmid & extpos > 3 THEN r_state:=pre_rot_suspended || SELECT !ss.(ss:STACKER_PROC =>arms(ss) = up) THEN SELECT r_state=get_ready & rcmd = rot_cmd THEN skip END END END END ; /* Remedy for failure when starting a rotation * / RotateCommandRemedy = BEGIN SELECT r_state=pre_rot_suspended & rcmd = rot_cmd & !ss.(ss:STACKER_PROC =>arms(ss) = up) & (ZCoord>=zmid or extpos <= 3) THEN r_state:=get_ready END END ; /* Abort if there is no remedy when starting a rotation * / PreRotateNoRemedy = BEGIN SELECT r_state=pre_rot_suspended THEN r_state:=abort END END /* Operation to Rotate. * / Rotate = BEGIN SELECT ZCoord >= zmid or extpos<=3 THEN r_state:=rotate || /* Call this operation from class PLATEHOLDER to calculate the new plate

holders’ positions * / NewPlateholderPos(steps) || SELECT !ss.(ss:STACKER_PROC =>arms(ss) = up) THEN

Page 97: ABSTRACT - abo.fi

89

SELECT r_state=get_ready & rcmd = rot_cmd THEN skip END END END END ; /* Rotation completed successfully * / RotateOk = BEGIN SELECT r_state=rotate & rcmd = rot_cmd & ph_pos~(temp_ph_pos1) = ((6+DispPos+steps-1)mod 6)+1 THEN r_state:=idle END END ; END ; /* Failure - Rotation did not completed successfully * / RotateNotOk = BEGIN SELECT r_state=rotate & rcmd = rot_cmd & ph_pos~(temp_ph_pos1) /= ((6+DispPos+steps-1)mod 6)+1 THEN r_state:=rot_suspended END END ; /* Fix the problem * / RotateRemedy = BEGIN SELECT r_state=rot_suspended & rcmd = rot_cmd & (extpos <= 3 or ZCoord >= zmid) & !ss.(ss:STACKER_PROC =>arms(ss) = up) THEN r_state:=rotate END END ; /* No remedy – Abort * /

Page 98: ABSTRACT - abo.fi

90

RotateNoRemedy = BEGIN SELECT r_state=rot_suspended THEN r_state:=abort END END ; /* General “not ready” failure * / ServiceNotReady = BEGIN SELECT r_state=idle THEN r_state:=suspended END END ; /* Fix the problem * / Remedy = BEGIN SELECT r_state=suspended THEN r_state:=idle END END ; /* No remedy – Abort * / NoRemedy = BEGIN SELECT r_state=suspended THEN r_state:=abort END END END D.2 The procedure class machine PLATEHOLDER of the Rotary Table refinement MACHINE PLATEHOLDER SEES def2, /* Consists of the sets and constants for the Rotary Table & Stacker Unit * / def /* Consists of the sets and constants for the Dispensing Head * / VARIABLES ph_pos, temp_ph_pos1, pholder, liq_present,

Page 99: ABSTRACT - abo.fi

91

zmid, zminAllowed INVARIANT

ph_pos : ROTARY_POS --> PH_ID & /* The position of a plateholder on the Rotary Table * /

temp_ph_pos1 : PH_ID & /* Temporary position of a plateholder at position 1 of the Rotary Table * / pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT) & /* plate_present -TRUE if there is a plate on the plateholder * height -the height of the plateholder * / liq_present : PH_ID +-> BOOL & /* True if there is liquid present on the plateholder * / zmid : NAT & /* Lowest z pos when Dispensing Head moves in xy-direction * / zminAllowed : zmin..zmid & /* Lowest possible z pos of Dispensing Head * / zmid <= zmax & zmid >= zmin & ran(ph_pos) = dom(pholder) & dom(pholder) = dom(liq_present) & !xx.(xx:PH_ID & (pholder(xx))'plate_present = FALSE => liq_present(xx) = FALSE) INITIALISATION temp_ph_pos1 :: PH_ID || zmid :: NAT || zminAllowed :: zmin..zmid || ANY phs, p_height WHERE phs<: PH_ID & card(phs) = card(ROTARY_POS) & p_height:NAT THEN pholder := phs*{ rec(plate_present : FALSE, height : p_height)} || ph_pos := ROTARY_POS*phs || liq_present := phs*{ FALSE} END OPERATIONS /* Local procedure * / /* Change plate holder with new plate holder having id, ph_id, a height, p_height and position, pos, on the Rotary Table * / PlateholderChange (ph_id, p_height, pos) = PRE ph_id:PH_ID & p_height:NAT & pos:ROTARY_POS & ph_id/:ran(ph_pos) & (pholder(ph_id))'plate_present = FALSE THEN

Page 100: ABSTRACT - abo.fi

92

ph_pos := ph_pos<+{ pos|->ph_id} || pholder:={ ph_pos(pos)} <<|pholder<+{ ph_id|->rec(FALSE,p_height)} || liq_present:={ ph_pos(pos)} <<|(liq_present<+{ ph_id|->FALSE} ) END ; /* Global procedures * / /* Add plate to plate holder with id, ph_id. Plate might contain liquid * / PlateholderPlateAdd (ph_id,pl_liq) = PRE ph_id:PH_ID & pl_liq:BOOL & ph_id : dom(pholder) & (pholder(ph_id))'plate_present = FALSE THEN pholder:=pholder<+{ ph_id|->rec(TRUE,(pholder(ph_id))´height)} || liq_present := liq_present<+{ ph_id|->pl_liq} END ; /* Remove plate from plateholder with id, ph_id * / PlateholderPlateRemove (ph_id) = PRE ph_id:PH_ID & ph_id:dom(pholder) & (pholder(ph_id))´plate_present=TRUE THEN pholder:=pholder<+{ ph_id|->rec(FALSE,(pholder(ph_id))´height)} || liq_present := liq_present<+{ ph_id|->FALSE} END ; /* Global procedure for Dispensing Head * / PlateholderLiquidPresent (ph_id) = PRE ph_id:PH_ID & ph_id:dom(liq_present) & liq_present(ph_id) = TRUE THEN skip END ;

/* Global procedure for Dispensing Head * / AddLiquid (ph_id) = PRE ph_id:PH_ID & ph_id:dom(pholder)

Page 101: ABSTRACT - abo.fi

93

THEN liq_present:=liq_present<+{ ph_id|->TRUE} END ;

/* Global procedure for Dispensing Head * / RemoveLiquid (ph_id) = PRE ph_id:PH_ID & ph_id:dom(pholder) & liq_present(ph_id) = TRUE THEN ANY bb WHERE bb:BOOL THEN liq_present:=liq_present<+{ ph_id|->bb} END END ; /* Local procedure * / /* Procedure to calculate the new plateholder position and the new zminAllowed after * every rotation * / NewPlateholderPos (rr ) = PRE rr :INT & rr:-5..5 THEN SELECT rr > 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((xx+rr-1)mod 6)+1)=ph_pos$0(xx))) || ANY zz WHERE zz:zmin..zmid THEN zminAllowed := zz END WHEN rr < 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((6+xx+rr-1)mod 6)+1)=ph_pos$0(xx))) || ANY zz WHERE zz:zmin..zmid THEN zminAllowed := zz END WHEN rr = 0 THEN skip END

Page 102: ABSTRACT - abo.fi

94

END ; /* Global procedure for the Dispensing Head to check the height * / HeightOk (zpos) = PRE zpos:NAT & zpos > zmid & zpos <= zmax THEN skip END ; /* Global procedure for Dispensing Head * / HeightNotOk (zpos) = PRE zpos:NAT & zpos >= zmid THEN skip END ; /* Local procedure * / /* Store plateholder id at position 1 in order to check the correctness of the rotation afterwards * / SetOldPos (p_phid) = PRE p_phid:PH_ID THEN temp_ph_pos1:=p_phid END END D.3 The first refinement of the Stacker unit REFINEMENT STACKER_R1_CLASS REFINES STACKER_CLASS_STACKER_R1 SEES def2 INCLUDES PLATEHOLDER EXTENDS

Page 103: ABSTRACT - abo.fi

95

STACKER_PROC_CLASS SETS S_STATE1={ idle1,destack1,stack1,des_suspended1,st_suspended1,suspended1,abort1,prepare1,ready_to_destack1,ready_to_stack1,prep_sk_suspended1,prestack_suspended1,prep_dsk_suspended1,predestack_suspended1} VARIABLES s_state1, scmd, empty, full, Stacker_proc INVARIANT s_state1 : STACKER --> S_STATE1 & scmd : STACKER --> SCOMMAND & empty : STACKER --> BOOL & full : STACKER --> BOOL & Stacker_proc : STACKER >-> STACKER_PROC & /* Refinement relation * / !(thisSTACKER).(thisSTACKER:STACKER => ( s_state(thisSTACKER) = idle => s_state1(thisSTACKER) = idle1 & s_state1(thisSTACKER) = idle1 => s_state(thisSTACKER) = idle & s_state(thisSTACKER) = prepare => s_state1(thisSTACKER) = prepare1 or

s_state1(thisSTACKER) = ready_to_destack1 or s_state1(thisSTACKER) = ready_to_stack1 &

s_state1(thisSTACKER) = prepare1 or s_state1(thisSTACKER) = ready_to_destack1 or s_state1(thisSTACKER) = ready_to_stack1 => s_state(thisSTACKER) = prepare & s_state(thisSTACKER) = destack => s_state1(thisSTACKER) = destack1 & s_state1(thisSTACKER) = destack1 => s_state(thisSTACKER) = destack & s_state(thisSTACKER) = des_suspended => s_state1(thisSTACKER) =

des_suspended1 & s_state1(thisSTACKER) = des_suspended1 => s_state(thisSTACKER) = des_suspended &

s_state(thisSTACKER) = prep_dsk_suspended => s_state1(thisSTACKER) = prep_dsk_suspended1 or s_state1(thisSTACKER) = predestack_suspended1 & s_state1(thisSTACKER) = prep_dsk_suspended1 or s_state1(thisSTACKER) = predestack_suspended1 => s_state(thisSTACKER) = prep_dsk_suspended & s_state(thisSTACKER) = prep_sk_suspended => s_state1(thisSTACKER) = prep_sk_suspended1 or s_state1(thisSTACKER) = prestack_suspended1 & s_state1(thisSTACKER) = prep_sk_suspended1 or s_state1(thisSTACKER) = prestack_suspended1 => s_state(thisSTACKER) = prep_sk_suspended &

Page 104: ABSTRACT - abo.fi

96

s_state(thisSTACKER) = st_suspended => s_state1(thisSTACKER) = st_suspended1 & s_state1(thisSTACKER) = st_suspended1 => s_state(thisSTACKER) = st_suspended &

s_state(thisSTACKER) = stack => s_state1(thisSTACKER) = stack1 & s_state1(thisSTACKER) = stack1 => s_state(thisSTACKER) = stack &

/* When Stacker is in states ready_to_destack1 and ready_to_stack1, the arms have to be down * /

s_state1(thisSTACKER) = ready_to_destack1 => arms(Stacker_proc(thisSTACKER)) = down & s_state1(thisSTACKER) = ready_to_stack1 => arms(Stacker_proc(thisSTACKER)) = down & /* When the Stacker is in states stack1, destack1 and prepare1 the command has to be equal to stack corresponding command, sk_cmd or dsk_cmd * / s_state1(thisSTACKER) = stack1 => scmd(thisSTACKER) = sk_cmd & s_state1(thisSTACKER) = destack1 => scmd(thisSTACKER) = dsk_cmd &

s_state1(thisSTACKER) = prepare1 => scmd(thisSTACKER) = sk_cmd or s_state1(thisSTACKER) = prepare1 => scmd(thisSTACKER) = dsk_cmd))

INITIALISATION s_state1:= %xx.(xx:STACKER | idle) || ANY yy WHERE yy:SCOMMAND THEN scmd:= %xx.(xx:STACKER | yy) END || ANY yy WHERE yy:BOOL THEN empty:= %xx.(xx:STACKER | yy) END || ANY yy WHERE yy:BOOL THEN full:= %xx.(xx:STACKER | yy) END || ANY yy WHERE STACKER_PROC THEN Stacker_proc:= %xx.(xx:STACKER | yy) OPERATIONS /* Operation for supplying the destack command, "dsk_cmd", to the command variable "scmd".* / DestackCommand (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=idle1 THEN s_state1(thisSTACKER):=prepare1 || scmd(thisSTACKER):=dsk_cmd END END ; /* General Failure – Suspend service * /

Page 105: ABSTRACT - abo.fi

97

DestackFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER)=dsk_cmd THEN s_state1(thisSTACKER):=prep_dsk_suspended1 END END ; /* Failure – There is already plate present under the Stacker – Suspend service * / DestackPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER))))´plate_present = TRUE THEN s_state1(thisSTACKER):=prep_dsk_suspended1 || SELECT empty(thisSTACKER) = FALSE THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER)=dsk_cmd THEN skip END END END END ; /* Failure – The Stacker is empty. Suspend service * / DestackEmptyStackerFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT empty(thisSTACKER) = TRUE THEN s_state1(thisSTACKER):=prep_dsk_suspended1 || SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER)=dsk_cmd THEN skip END END END ; /* Fix the problem * / DestackCommandRemedy (thisSTACKER) =

Page 106: ABSTRACT - abo.fi

98

PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prep_dsk_suspended1 & scmd(thisSTACKER)=dsk_cmd & empty(thisSTACKER) = FALSE & (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = FALSE THEN s_state1(thisSTACKER):=prepare1 END END ; /* Abort – No remedy * / PrepDestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prep_dsk_suspended1 THEN s_state1(thisSTACKER):=abort1 END END ; /* Operation for reaching the state ready_to_destack1. The arms have to be down when in that state, the Stacker is not empty and there is not plate present under the Stacker * / PrepareDestack (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = FALSE THEN s_state1(thisSTACKER):=ready_to_destack1 || /* Call procedure from STACKER_PROC class to change the position of the arms down*/ ChangeStArms(Stacker_proc(thisSTACKER), down) || SELECT empty(thisSTACKER) = FALSE THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER)=dsk_cmd THEN skip END END END END ; /* Failure – The arms are up. Suspend service * / DestackArmsFail (thisSTACKER) = PRE

Page 107: ABSTRACT - abo.fi

99

thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = up THEN s_state1(thisSTACKER):=predestack_suspended1 || SELECT s_state1(thisSTACKER)=ready_to_destack1 & scmd(thisSTACKER) = dsk_cmd THEN skip END END END ; /* Fix the problem * / PreDestackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=predestack_suspended1 & scmd(thisSTACKER)=dsk_cmd & arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=ready_to_destack1 END END ; /* Abort – The problem cannot be fixed * / PreDestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=predestack_suspended1 THEN s_state1(thisSTACKER):=abort1 END END /* Destack plate * / Destack (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=destack1 || /* Call procedure from STACKER_PROC class to change the position of the arms up* / ChangeStArms(Stacker_proc(thisSTACKER), up) || /* Call procedure from PLATEHOLDER machine to add a plate on the Rotary Table * / PlateholderPlateAdd(ph_pos(s_pos(Stacker_proc(thisSTACKER)))) || SELECT s_state1(thisSTACKER)=ready_to_destack1 &

Page 108: ABSTRACT - abo.fi

100

scmd(thisSTACKER) = dsk_cmd THEN skip END END END ; /* The Stacker has destacked the plate * / DestackOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))´plate_present = TRUE THEN s_state1(thisSTACKER):=idle || SELECT arms(Stacker_proc(thisSTACKER)) = up THEN SELECT s_state1(thisSTACKER)=destack1 & scmd(thisSTACKER) = dsk_cmd THEN skip END END END END ; /* Failure – The Stacker has not destacked the plate. Suspend service * / DestackNotOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=destack1 & scmd(thisSTACKER)=dsk_cmd THEN s_state1(thisSTACKER):=des_suspended1 END END ; /* Failure – After destack the arms are down * / AfterDskArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=des_suspended1 ||

Page 109: ABSTRACT - abo.fi

101

SELECT s_state1(thisSTACKER)=destack1 & scmd(thisSTACKER) = dsk_cmd THEN skip END END END ; /* Failure – After destack there is no plate under the Stacker * / AfterDskPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER))))´plate_present = FALSE THEN s_state1(thisSTACKER):=des_suspended1 || SELECT arms(Stacker_proc(thisSTACKER)) = up THEN SELECT s_state1(thisSTACKER)=destack1 & scmd(thisSTACKER) = dsk_cmd THEN skip END END END END ; /* Fix the problem * / DestackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=des_suspended1 & scmd(thisSTACKER)=dsk_cmd & (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = TRUE & arms(Stacker_proc(thisSTACKER)) = up THEN s_state1(thisSTACKER):=destack1 END END ; /* Abort – The problem cannot be fixed * / DestackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=des_suspended1

Page 110: ABSTRACT - abo.fi

102

THEN s_state1(thisSTACKER):=abort1 END END ; /* Operation for supplying the stack command, "sk_cmd", to the command variable "scmd".* / StackCommand (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=idle1 THEN s_state1(thisSTACKER):=prepare1 || scmd(thisSTACKER):=sk_cmd END END ; /* General failure – Suspend service * / StackFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER)=sk_cmd THEN s_state1(thisSTACKER):=prep_sk_suspended1 END END ; /* Suspend service – The Stacker is full * / StackFullStackerFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT full(thisSTACKER) = TRUE THEN s_state1(thisSTACKER):=prep_sk_suspended1 || SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END ; /* Suspend service – There is no plate under the Stacker * / StackPlateFail (thisSTACKER) = PRE

Page 111: ABSTRACT - abo.fi

103

thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = FALSE THEN s_state1(thisSTACKER):=prep_sk_suspended1 || SELECT full(thisSTACKER) = FALSE THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END END ; /* Fix the problem * / StackCommandRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prep_sk_suspended1 & scmd(thisSTACKER)=sk_cmd & full(thisSTACKER) = FALSE & (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER))))´plate_present = TRUE THEN s_state1(thisSTACKER):=prepare1 END END ; /* Abort – The problem cannot be fixed * / PrepStackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prep_sk_suspended1 THEN s_state1(thisSTACKER):=abort1 END END ; /* Operation for reaching the state ready_to_stack1. The arms have to be down when in that state, the Stacker is not full and there is plate present under the Stacker * / PrepareStack (thisSTACKER) = PRE thisSTACKER : STACKER THEN

Page 112: ABSTRACT - abo.fi

104

SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = TRUE THEN s_state1(thisSTACKER):=ready_to_stack1 || /* Call procedure from STACKER_PROC class to change the position of the arms down * / ChangeStArms(Stacker_proc(thisSTACKER), down) || SELECT full(thisSTACKER) = FALSE THEN SELECT s_state1(thisSTACKER)=prepare1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END END ; /* Suspend service – The arms are still up * / StackArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = up THEN s_state1(thisSTACKER):=prestack_suspended1|| SELECT s_state1(thisSTACKER)=ready_to_stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END ; /* Fix the problem * / PreStackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prestack_suspended1 & scmd(thisSTACKER) = sk_cmd & arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=ready_to_stack1 END END ; /* Abort – The problem cannot be fixed * / PreStackNoRemedy (thisSTACKER) = PRE

Page 113: ABSTRACT - abo.fi

105

thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=prestack_suspended1 THEN s_state1(thisSTACKER):=abort1 END END ; /* Stack plate * / Stack (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=stack1 || /* Call procedure from STACKER_PROC class to change the position of the arms up * / ChangeStArms(Stacker_proc(thisSTACKER), up) || /* Call procedure from the PLATEHOLDER class to remove the plate under this Stacker * / PlateholderPlateRemove(ph_pos(s_pos(Stacker_proc(thisSTACKER)))) || SELECT s_state1(thisSTACKER)=ready_to_stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END ; /* The Stacker has stacked the plate * / StackOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER))))´plate_present = FALSE THEN s_state1(thisSTACKER):=idle1 || SELECT arms(Stacker_proc(thisSTACKER)) = up THEN SELECT s_state1(thisSTACKER)=stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END END ;

Page 114: ABSTRACT - abo.fi

106

/* Failure – The Stacker has not stacked the plate * / StackNotOk (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=stack1 & scmd(thisSTACKER) = sk_cmd THEN s_state1(thisSTACKER):=st_suspended1 END END ; /* Failure - After stack the arms are down * / AfterSkArmsFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT arms(Stacker_proc(thisSTACKER)) = down THEN s_state1(thisSTACKER):=st_suspended1 || SELECT s_state1(thisSTACKER)=stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END ; /* Failure – There is still plate under the Stacker * / AfterSkPlateFail (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT (pholder(s_pos(Stacker_proc(thisSTACKER))))´plate_present = TRUE THEN s_state1(thisSTACKER):=st_suspended1 || SELECT arms(Stacker_proc(thisSTACKER)) = up THEN SELECT s_state1(thisSTACKER)=stack1 & scmd(thisSTACKER) = sk_cmd THEN skip END END END END /* Fix the problem * / StackRemedy (thisSTACKER) = PRE thisSTACKER : STACKER

Page 115: ABSTRACT - abo.fi

107

THEN SELECT s_state1(thisSTACKER)=st_suspended1 & scmd(thisSTACKER)=sk_cmd & arms(Stacker_proc(thisSTACKER)) = down & (pholder(ph_pos(s_pos(Stacker_proc(thisSTACKER)))))´plate_present = FALSE THEN s_state1(thisSTACKER):=stack1 END END ; /* Abort – The problem cannot be fixed * / StackNoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=st_suspended1 THEN s_state1(thisSTACKER):=abort1 END END ; /* General ‘not ready’ failure – Suspend service * / ServiceNotReady (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=idle1 THEN s_state1(thisSTACKER):=suspended1 END END ; /* Fix the problem * / Remedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=suspended1 THEN s_state1(thisSTACKER):=idle1 END END ; /* Abort – The problem cannot be fixed * / NoRemedy (thisSTACKER) = PRE thisSTACKER : STACKER THEN SELECT s_state1(thisSTACKER)=suspended1 THEN s_state1(thisSTACKER):=abort1

Page 116: ABSTRACT - abo.fi

108

END END END D.4 The procedure class machine of the Stacker unit MACHINE STACKER_PROC_CLASS SEES def2 CONSTANTS STACKER_PROC PROPERTIES STACKER_PROC = 1..4 VARIABLES arms, s_pos INVARIANT arms : STACKER_PROC --> ARM_POS & s_pos : STACKER_PROC --> { 2, 3, 5, 6} /* Stacker position on the table * / INITIALISATION arms:= %xx.(xx:STACKER_PROC | up) || /* The arms of all the Stackers have to be up in the beginning * / s_pos := { 1|->2, 2|->3, 3|->5, 4|->6} /* This initialisation assigns stackers 1, 2, 3, and 4 to the Rotary Table positions

2, 3, 5, 6 respectively * / OPERATIONS /* Local procedure * / /* Change the position of the Stacker’s arms * / ChangeStArms (thisSTACKER_PROC,dir) = PRE thisSTACKER_PROC : STACKER_PROC & dir:ARM_POS THEN arms(thisSTACKER_PROC) := dir END END D.5 The procedure machine of the XYZ driver for the Dispensing Head. The extpos variable has to be checked from the Rotary Table. MACHINE XYZDRIVER_PROC SEES

Page 117: ABSTRACT - abo.fi

109

def VARIABLES extpos, old_extpos, z_refpoint, old_z_refpoint INVARIANT extpos : 1..max_extpos & old_extpos : 1..max_extpos & z_refpoint : REFERENCE_POINTS & old_z_refpoint : REFERENCE_POINTS INITIALISATION extpos := home_ext || old_extpos := home_ext || z_refpoint := acc_maxheight || old_z_refpoint := acc_maxheight OPERATIONS SetExtPos (p_extpos) = PRE p_extpos:NAT THEN extpos:=p_extpos END ; SetOldExtPos = BEGIN old_extpos:=extpos END ; SetZRefpoint (p_zrefpoint) = PRE p_zrefpoint:REFERENCE_POINTS THEN z_refpoint:=p_zrefpoint END ; SetOldZRefpoint = BEGIN old_z_refpoint:=z_refpoint END ; ResetExtpos = BEGIN extpos:=old_extpos

Page 118: ABSTRACT - abo.fi

110

END END D.6 The Z driver class of the Dispensing Head XYZ driver. Rotary Table needs to check the Z coordinate of the Dispensing Head. MACHINE ZDRIVER1 SEES def, YELLOW_LAMP INCLUDES ZD_PROC VARIABLES z_state, ZDest_Coord, ZCoord /* This is the variable of interest * / INVARIANT z_state : Z_STATE & ZDest_Coord : zmin..zmax & ZCoord : zmin..zmax & (z_state=zidle =>z_state1=zidle1) & (z_state1=zidle1 => z_state=zidle) & (z_state=zmove => z_state1=zmove1) & (z_state1=zmove1 => z_state=zmove) & (z_state=zsuspended => z_state1:{ zsuspended1, z_msuspended1} ) & (z_state1:{ zsuspended1, z_msuspended1} =>z_state=zsuspended) & (z_state=zabort => z_state1=zabort1) & (z_state1=zabort1 => z_state=zabort) INITIALISATION z_state := zidle1 || ZDest_Coord := zcoord(home_z) || ZCoord := zcoord(home_z) OPERATIONS ZMove (pos) = PRE pos:zmin..zmax THEN SELECT z_state=zidle1 & yellow_lamp=on THEN z_state:=zmove1 || ZCoord:=pos || ZDest_Coord:=pos END

Page 119: ABSTRACT - abo.fi

111

END ; ZMoveFail = BEGIN SELECT z_state=zidle1 & yellow_lamp=off THEN z_state:=zsuspended1 END END ; ZMoveNotOk = BEGIN SELECT z_state=zmove1 & ZCoord/=ZDest_Coord THEN z_state:=z_msuspended1 END END ; ZServiceNotReady = BEGIN SELECT z_state=zidle1 THEN z_state:=zsuspended1 END END ; ZRemedy = BEGIN SELECT z_state=zsuspended1 & yellow_lamp = on THEN z_state:=zidle1 END END ; ZFailure = BEGIN SELECT z_state=zsuspended1 THEN z_state:=zabort1 WHEN z_state=z_msuspended1 THEN z_state:=zabort1 END END ; ZMoveRemedy = BEGIN SELECT z_state=z_msuspended1 & yellow_lamp=on

Page 120: ABSTRACT - abo.fi

112

THEN z_state:=zmove1 END END ; ZMoveOk = BEGIN SELECT z_state=zmove1 & ZCoord=ZDest_Coord THEN z_state:=zidle1 END END ; ZGeneralRemedy = BEGIN SELECT z_state=zsuspended1 THEN z_state:=zidle1 END END ; ZEmergency = PRE not(z_state1 = z_abort1) THEN z_state1:=z_abort1 END ; ZGeneralMoveNotOk = BEGIN SELECT z_state=zmove1 THEN z_state:=z_msuspended1 END END END D.7 The sets and constants of the Rotary Table & the Stacker unit. MACHINE DEF2 SETS TCOMMAND={ rot_cmd} ; SCOMMAND={ dsk_cmd, sk_cmd} ; PH_ID; /* The set of plateholder ids * / ARM_POS={ up, down} /* The possible positions of the arms of a Stacker * / CONSTANTS zmin, zmax, ROTARY_POS, /* The set of the six Rotary Table positions * /

Page 121: ABSTRACT - abo.fi

113

DispPos /* The Dispensing Position 1 of the Rotary Table * / PROPERTIES zmin : NAT & zmax : NAT & zmin + 1<zmax & ROTARY_POS = { 1, 2, 3, 4, 5, 6} & DispPos = 1 END

Page 122: ABSTRACT - abo.fi

114

Appendix E: The 2nd refinement of the Rotary Table Appendix E.1: The class diagram of the 2nd refinement of the Rotary Table. The classes STACKER_PROC, ZDRIVER1 and XYZDRIVER_PROC are the same as previously, in Appendix

PLATE HOLDER1

p h_pos : ROTARY_ POS --> PH_I Dtemp_p h_po s1 : PH_ IDAcc_minHeigh t : zm in. .zmaxp hol der : PH_I D + -> struct(pl ate _prese nt :BOOL,he igh t:NAT)p late_id : PH_ ID +-> PID = {}Acc_He ig ht : PH_ID +-> NATxymove Ok : zm in. .zmax

Plateho lde rCh ange (ph _i d : PH_I D, p_ hei ght : NAT, po s : ROTARY_ PO S)Plateho lde rPlateAdd (p h_i d : PH_ID, pid : PID, ph ei ght : NAT , l iq_ amt : NA T , pmi nheight : NAT, p ma xVol : NAT , p noOf W : NAT1)Plateho lde rPlateRemo ve(ph_id : PH_ ID, pid : PID)Ad dLi quid(ph_id : PH_ ID, intpos : NAT, p id : PID, a mt : NAT)Re moveL iqu id (ph _id : PH_I D, pid : PI D, i ntp os : NA T , amt : NAT)Ne wPla te hol derPos(rr : I NT )He ig htOk(zpos : NAT)He ig htNo tOk(z pos : NAT)Se tOldPos(p_ph id : PH_ ID)

PLATE

Plate : PID +-> struct(height:NAT , l iquid_amt:NAT , minheight:NAT , maxVol:NAT, noOfW:NAT1) = {}

PlateAdd(pid : PID, pheight : NAT , l iq_amt : NAT , pminheight : NAT , pmaxVol : NAT , pnoOfW : NAT1)PlateRemove(pid : PID)Plate_LiquidAdd(pid : PID, intpos : NAT , amt : NAT)Plate_LiquidRemove(pid : PID, intpos : NAT , amt : NAT)

<<bind>>

ROTARY_TABLE_R2

rcmd : TCOMMANDsteps : INT = ::-5..5

RotateCommand(p_steps : INT )Rotate()RotateFai l ()RotateCommandRemedy()RotateArmsFai l ()RotateZCoordFai l ()RotateNotOk()RotateRemedy()RotateNoRemedy()RotateOk()PreRotateNoRemedy()ServiceNotReady()Remedy()NoRemedy()

DEF2ZDRIVER1 XYZDRIVER_PROC STACKER_PROC

<<bind>>

<<bind>>

<<bind>>

<<bind>>

Page 123: ABSTRACT - abo.fi

115

Appendix E.2: The statechart diagram of the 2nd refinement of the Rotary Table.

idle

suspended

rotate

get_ready pre_rot_suspended

abort

rot_suspended

RotateFail[ rcmd=rot_cmd ]

RotateRemedy[ rcmd=rot_cmd & (extpos <= 3 or ZCoord >= xymoveOk) & !ss.(ss:STACKER_PROC=>arms(ss)=up) ]

RotateNoRemedy [ rcmd=rot_cmd ]

RotateArmsFail[ #ss.(ss:STACKER_PROC & arms(ss)=down) ]

[ !ss.(ss:STACKER_PROC=>arms(ss) = up) ]

start

stop

ServiceNotReady

RotateCommand( p_steps )[ p_steps:-5..5 ] / steps:=p_steps;SetOldPos(ph_pos(DispPos));rcmd:=rot_cmd

Remedy

NoRemedy

RotateCommandRemedy[ rcmd=rot_cmd & !ss.(ss:STACKER_PROC=>arms(ss)=up) & (ZCoord>=xymoveOk or extpos<=3) ] PreRotateNoRemedy

RotateZCoordFail[ ZCoord < xymoveOk & extpos > 3 ]

Rotate[ ZCoord>=xymoveOk or extpos<=3 ] / NewPlateholderPos(steps)

RotateOk[ rcmd=rot_cmd & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1)mod 6)+1 ]

RotateNotOk[ rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1)mod 6)+1 ]

Page 124: ABSTRACT - abo.fi

116

Appendix F: The 2nd refinement step of the Rotary Table. Appendix F.1: The refinement machine ROTARY_TABLE_R2. REFINEMENT ROTARY_TABLE_R2 REFINES ROTARY_TABLE_R1 SEES def2, def INCLUDES XYZD_PROC, ZDRIVER1, STACKER_PROC_CLASS, PLATEHOLDER1 SETS R_STATE={ idle,suspended,rotate,get_ready,pre_rot_suspended,abort,rot_suspended} VARIABLES r_state, rcmd, steps INVARIANT r_state : R_STATE & rcmd : TCOMMAND & steps : INT & steps:-5..5 & /* When Rotary Table is in state "rotate" and the Dispensing Head is above the Dispensing Position 1, the Dispensing Head has to be at a certain height * /

(extpos > 3 & r_state = rotate => ZCoord >= xymoveOk) & /* When Rotary Table is in state "rotate" the arms of all the Stackers

have to be up * / (r_state = rotate => !ss.(ss:STACKER_PROC =>arms(ss) = up)) & r_state = rotate => temp_ph_pos1:ran(ph_pos) & /* REFINEMENT RELATIONSHIP * / xymoveOk = zmid & Acc_minHeight = zminAllowed & /* When liq_present is TRUE, the liquid amount of a plate has to be greater than

zero * / (!xx.(xx:PH_ID => liq_present(xx) = TRUE => !yy.(yy:PID => (Plate(yy))'liquid_amt > 0))) &

Page 125: ABSTRACT - abo.fi

117

/* When liq_present is TRUE, the liquid amount of a plate has to be equal to zero * / (!xx.(xx:PH_ID => liq_present(xx) = FALSE => !yy.(yy:PID => (Plate(yy))'liquid_amt = 0))) INITIALISATION r_state := idle || rcmd :: TCOMMAND || steps :: -5..5 OPERATIONS /* Operation for supplying the rotate command, "rot_cmd", to the command variable, “ rcmd” , giving the number of steps the table to rotate and calling the procedure SetOldPos from PLATEHOLDER class to store the id of the plateholder being at position 1 of the table before the rotation * / RotateCommand (p_steps) = BEGIN SELECT r_state=idle & p_steps:-5..5 THEN r_state:=get_ready || steps:=p_steps;SetOldPos(ph_pos(DispPos));rcmd:=rot_cmd END END ; /* General failure – Suspend service * / RotateFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended END END ; /* Failure – Suspend service. Some Stacker is not safe – Its arms are down * / RotateArmsFail = BEGIN SELECT #ss.(ss:STACKER_PROC & arms(ss)=down) THEN r_state:=pre_rot_suspended || SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END ;

Page 126: ABSTRACT - abo.fi

118

/* Failure – Suspend service. The Dispensing Head is not safe. RotateZCoordFail = BEGIN SELECT ZCoord < xymoveOk & extpos > 3 THEN r_state:=pre_rot_suspended || SELECT !ss.(ss:STACKER_PROC=>arms(ss) = up) THEN SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END END ;

/* Fix the problem * / RotateCommandRemedy = BEGIN SELECT r_state=pre_rot_suspended & rcmd=rot_cmd & !ss.(ss:STACKER_PROC=>arms(ss)=up) & (ZCoord>=xymoveOk or extpos<=3) THEN r_state:=get_ready END END ; /* Abort execution. Problem cannot be fixed * / PreRotateNoRemedy = BEGIN SELECT r_state=pre_rot_suspended THEN r_state:=abort END END ; /* Operation to Rotate. * / Rotate = BEGIN SELECT ZCoord>=xymoveOk or extpos<=3 THEN r_state:=rotate || /* Call this operation from class PLATEHOLDER to calculate the new plate

holders’ positions * / NewPlateholderPos(steps) || SELECT !ss.(ss:STACKER_PROC=>arms(ss) = up) THEN SELECT r_state=get_ready &

Page 127: ABSTRACT - abo.fi

119

rcmd=rot_cmd THEN skip END END END END ;

/* Failure - Rotation did not completed successfully * / RotateNotOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1)mod 6)+1 THEN r_state:=rot_suspended END END ; /* Fix the problem * / RotateRemedy = BEGIN SELECT r_state=rot_suspended & rcmd=rot_cmd & (extpos <= 3 or ZCoord >= xymoveOk) & !ss.(ss:STACKER_PROC=>arms(ss)=up) THEN r_state:=rotate END END ; /* Abort – The problem cannot be fixed * / RotateNoRemedy = BEGIN SELECT r_state=rot_suspended THEN r_state:=abort END END ; /* Rotation completed successfully * / RotateOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1)mod 6)+1 THEN r_state:=idle END END ; /* General ‘not ready’ failure * / ServiceNotReady = BEGIN

Page 128: ABSTRACT - abo.fi

120

SELECT r_state=idle THEN r_state:=suspended END END ; /* Fix the problem * / Remedy = BEGIN SELECT r_state=suspended THEN r_state:=idle END END ; /* Abort – The problem cannot be fixed * / NoRemedy = BEGIN SELECT r_state=suspended THEN r_state:=abort END END END F.2: The updated procedure class PLATEHOLDER1. MACHINE PLATEHOLDER1 SEES def2, def INCLUDES PLATE VARIABLES ph_pos, temp_ph_pos1, Acc_minHeight, pholder, plate_id, Acc_Height, xymoveOk INVARIANT ph_pos : ROTARY_POS --> PH_ID & temp_ph_pos1 : PH_ID & Acc_minHeight : zmin..zmax & pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT) & plate_id : PH_ID +-> PID & Acc_Height : PH_ID +-> NAT & xymoveOk : zmin..zmax &

Page 129: ABSTRACT - abo.fi

121

xymoveOk=max(ran(Acc_Height)) & dom(pholder) = dom(Acc_Height) & (!xx.(xx:dom(pholder) => Acc_minHeight >= (pholder(xx))'height)) & (!xx.(xx:dom(pholder) & (pholder(xx))'plate_present = TRUE => plate_id(xx):dom(Plate))) & ((pholder(ph_pos(DispPos)))'plate_present=TRUE => Acc_minHeight = (pholder(ph_pos(DispPos)))'height + (Plate(plate_id(ph_pos(DispPos))))'minheight + zmin) & ((pholder(ph_pos(DispPos)))'plate_present=FALSE => Acc_minHeight = (pholder(ph_pos(DispPos)))'height + zmin) & (!xx.(xx:dom(pholder) => (pholder(xx))'height + zmin < xymoveOk)) & ran(plate_id) = dom(Plate) INITIALISATION temp_ph_pos1 :: PH_ID || plate_id := { } || ANY phs, p_height WHERE phs<: PH_ID & card(phs) = card(ROTARY_POS) & p_height:NAT THEN pholder := phs*{ rec(plate_present : FALSE, height : p_height)} || ph_pos := ROTARY_POS*phs || Acc_Height := phs*{ p_height} || Acc_minHeight := p_height || xymoveOk := p_height END OPERATIONS /* Change plateholder and at the same time update the variables ph_pos, pholder, Acc_Height, Acc_minHeight and xymoveOk * / PlateholderChange (ph_id,p_height,pos) = PRE ph_id:PH_ID & p_height:NAT & pos:ROTARY_POS & ph_id/:ran(ph_pos) & pholder(ph_id))'plate_present = FALSE THEN ph_pos := ph_pos<+{ pos|->ph_id} || pholder:={ ph_pos(pos)} <<|pholder<+{ ph_id|->rec(FALSE,p_height)} || Acc_Height(ph_id):=p_height + zmin || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ p_height+zmin} ) || IF pos=DispPos THEN Acc_minHeight := (pholder(ph_pos(DispPos)))'height + zmin ELSE skip END

Page 130: ABSTRACT - abo.fi

122

END ; /* Global procedures * / /* Add a plate on the plateholder * / PlateholderPlateAdd (ph_id,pid,pheight,liq_amt,pminheight,pmaxVol,pnoOfW) = PRE ph_id:PH_ID & /* Plateholder id * / pid:PID & /* Plate id * / pheight:NAT & /* plate height * / liq_amt:NAT & /* liquid amount of the plate * / pminheight:NAT & /* plate minimum height * / pmaxVol:NAT & /* plate maximum volume * / pnoOfW:NAT1 & /* plate number of wells * / (pholder(ph_id))´plate_present=FALSE & Acc_Height(ph_id)+pheight<=zmax THEN pholder:=pholder<+{ ph_id|->rec(TRUE,(pholder(ph_id))´height)} || plate_id(ph_id):=pid || Acc_Height(ph_id):=Acc_Height(ph_id)+pheight || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ Acc_Height(ph_id)+pheight} ) || /* Call this procedure from the PLATE machine * / PlateAdd(pid, pheight, liq_amt, pminheight, pmaxVol, pnoOfW) || IF ((ph_pos~(ph_id))=DispPos) THEN Acc_minHeight := (pholder(ph_pos(DispPos)))'height + pminheight + zmin ELSE skip END END ; /* Remove a plate from a plateholder * / PlateholderPlateRemove (ph_id, pid) = PRE ph_id:PH_ID & pid:PID & ph_id:dom(pholder) & (pholder(ph_id))´plate_present=TRUE & liq_present(ph_id) = FALSE & pid:ran(plate_id) THEN pholder:=pholder<+{ ph_id|->rec(FALSE,(pholder(ph_id))´height)} || plate_id:=plate_id|>>{ pid} || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ (pholder(ph_id))'height+zmin} ) || Acc_Height(ph_id):=(pholder(ph_id))'height+zmin || PlateRemove(pid) || IF ((ph_pos~(ph_id)) = DispPos) THEN

Page 131: ABSTRACT - abo.fi

123

Acc_minHeight := (pholder(ph_pos(DispPos)))'height + zmin ELSE skip END END ; /* Add liquid to a plate * / AddLiquid (ph_id,intpos,pid,amt) = PRE ph_id:PH_ID & intpos:NAT & pid:PID & amt:NAT & ph_id:dom(pholder) THEN /* Call this operation from the PLATE machine * / Plate_LiquidAdd(pid, intpos, amt) END ; /* Remove liquid from a plate * / RemoveLiquid (ph_id,pid,intpos,amt) = PRE ph_id:PH_ID & pid:PID & intpos:NAT & amt:NAT & ph_id:dom(pholder) & liq_present(ph_id) = TRUE THEN /* Call this operation from the PLATE machine * / Plate_LiquidRemove(pid, intpos, amt) END ; /* Local procedure * / /* Procedure to calculate the new plateholder position and the new minimum height of an accessory after every rotation * / NewPlateholderPos (rr ) = PRE rr :INT & rr:-5..5 THEN SELECT rr > 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((xx+rr-1)mod 6)+1)=ph_pos$0(xx))) || ANY yy WHERE yy:ROTARY_POS & (((yy+rr-1)mod 6)+1) = 1 THEN IF (pholder(ph_pos(yy)))'plate_present = TRUE THEN

Page 132: ABSTRACT - abo.fi

124

Acc_minHeight := (pholder(ph_pos((yy)))'height + (Plate(plate_id(ph_pos(yy))))'minheight + zmin ELSE Acc_minHeight := (pholder(ph_pos(yy)))'height + zmin END END WHEN rr < 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((6+xx+rr-1)mod 6)+1)=ph_pos$0(xx))) || ANY yy WHERE yy:ROTARY_POS & (((6+yy+rr-1)mod 6)+1) = 1 THEN IF (pholder(ph_pos(yy)))'plate_present = TRUE THEN Acc_minHeight := (pholder(ph_pos((yy)))'height + (Plate(plate_id(ph_pos(yy))))'minheight + zmin ELSE Acc_minHeight := (pholder(ph_pos(yy)))'height + zmin END END WHEN rr = 0 THEN skip END END ; /* Global procedures for the Dispensing Head to check the height* / HeightOk (zpos) = PRE zpos:NAT & zpos > xymoveOk & zpos <= zmax THEN skip END ; HeightNotOk (zpos) = PRE zpos:NAT & zpos <= xymoveOk THEN skip END ; /* Local procedure * /

Page 133: ABSTRACT - abo.fi

125

/* Store the current plateholder id before every rotation. To be used later to check the correctness of the rotation SetOldPos (p_phid) = PRE p_phid:PH_ID THEN temp_ph_pos1:=p_phid END END F.3: The procedure class PLATE of the Rotary Table. MACHINE PLATE SEES def, def2 VARIABLES Plate INVARIANT Plate : PID +-> struct(height:NAT, liquid_amt:NAT, minheight:NAT, maxVol:NAT, noOfW:NAT1) & /* height – The height of the plate * / /* liquid_amt – The liquid amount of the plate * / /* minheight – The minimum height of the plate * / /* maxVol – The maximum volume of the plate * / /* noOfW – The number of wells of the plate * / /* The minimum height of the plate is always smaller or equal to the height of it * / (!xx:(xx:PID => (Plate(xx))'minheight <= (Plate(xx))'height)) & /* The liquid amount of the plate is always smaller or equal to the plate’s maximum volume * / (!xx.(xx:PID => (Plate(xx))'liquid_amt <= (Plate(xx))'maxVol)) INITIALISATION Plate := { } /* Initially there is no plate on the Rotary Table * / OPERATIONS /* Add a plate * / PlateAdd (pid,pheight,liq_amt,pminheight,pmaxVol,pnoOfW) = PRE pid:PID & pheight:NAT & liq_amt:NAT & pminheight:NAT & pmaxVol:NAT &

Page 134: ABSTRACT - abo.fi

126

pnoOfW:NAT1 & pid/:dom(Plate) & liq_amt <= pmaxVol & pminheight <= pheight THEN Plate:=Plate<+{ pid|->rec(pheight,liq_amt,pminheight,pmaxVol,pnoOfW)} END ; /* Remove a plate * / PlateRemove (pid) = PRE pid:PID & pid:dom(Plate) THEN Plate:={ pid} <<|Plate END ; /* Add liquid to plate * / Plate_LiquidAdd (pid,intpos,amt) = PRE pid:PID & intpos:NAT & amt:NAT & pid:dom(Plate) & ((Plate(pid))'liquid_amt+amt <= (Plate(pid))'maxVol) & amt>0 THEN Plate := Plate <+{ pid|->rec((Plate(pid))'height, (Plate(pid))'liquid_amt + amt, (Plate(pid))'minheight, (Plate(pid))'maxVol, (Plate(pid))'noOfW)} END ; /* Remove liquid from plate * / Plate_LiquidRemove (pid,intpos,amt) = PRE pid:PID & intpos:NAT & amt:NAT & amt <= (Plate(pid))'liquid_amt & pid:dom(Plate) & amt > 0 THEN Plate := Plate<+{ pid|->rec((Plate(pid))'height, (Plate(pid))'liquid_amt - amt, (Plate(pid))'minheight, (Plate(pid))'maxVol, (Plate(pid))'noOfW)} END END F.4: The updated DEF2 class. MACHINE DEF2 SETS TCOMMAND={ rot_cmd} ; SCOMMAND={ dsk_cmd, sk_cmd} ;

Page 135: ABSTRACT - abo.fi

127

PH_ID; PID; ARM_POS={ up, down} ; CONSTANTS zmin, zmax, ROTARY_POS, DispPos PROPERTIES zmin : NAT & zmax : NAT & zmin + 1<zmax & ROTARY_POS = { 1, 2, 3, 4, 5, 6} & DispPos = 1 END

Page 136: ABSTRACT - abo.fi

128

Appendix G: The control system decomposition of the Rotary Table. Appendix G.1: The class diagram of the plant and controller decomposition of the Rotary Table. Assume the classes ZDRIVER1, XYZDRIVER_PROC & PLATE the same as previously.

ROTARY_TABLE_PLANT

RotateCommand(p_steps : INT) Rotate() RotateFail() RotateCommandRemedy() RotateArmsFail() RotateZCoordFail() RotateNotOk() RotateRemedy() RotateNoRemedy() RotateOk() PreRotateNoRemedy() ServiceNotReady() Remedy() NoRemedy()

ROTARY_TABLE_CONTROLLER rcmd : TCOMMAND steps : INT = ::-5..5 ctrl_r_state : CTRL_R_STATE = ctrl_idle

RrotateCommand(p_steps : INT) Rrotate() RrotateFail() RrotateCommandRemedy() RrotateArmsFail() RrotateZCoordFail() RrotateNotOk() RrotateRemedy() RrotateNoRemedy() RrotateOk() RpreRotateNoRemedy() RServiceNotReady() Rremedy() RnoRemedy()

STACKER_PROC arms : ARM_POS = up s_pos : {2, 3, 5, 6}

ChangeStArms(dir : ARM_POS)

PLATEHOLDER1 ph_pos : ROTARY_POS --> PH_ID temp_ph_pos1 : PH_ID Acc_minHeight : zmin..zmax pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT) plate_id : PH_ID +-> PID = {} Acc_Height : PH_ID +-> NAT xymoveOk : zmin..zmax

PlateholderChange(ph_id : PH_ID, p_height : NAT, pos : ROTARY_POS) PlateholderPlateAdd(ph_id : PH_ID, pid : PID, pheight : NAT, liq_amt : NAT, pminheight : NAT, pmaxVol : NAT, pnoOfW : NAT1) PlateholderPlateRemove(ph_id : PH_ID, pid : PID) AddLiquid(ph_id : PH_ID, intpos : NAT, pid : PID, amt : NAT) RemoveLiquid(ph_id : PH_ID, pid : PID, intpos : NAT, amt : NAT) NewPlateholderPos(rr : INT) HeightOk(zpos : NAT) HeightNotOk(zpos : NAT) SetOldPos(p_phid : PH_ID)

DEF2

ZDRIVER1

XYZDRIVER_PROC <<bind>>

<<bind>>

<<bind>>

<<bind>>

<<bind>>

PLATE <<bind>>

Page 137: ABSTRACT - abo.fi

129

Appendix G.2: The statechart diagram of the plant of the Rotary Table.

idle get_ready

suspended

rotate

pre_rot_suspended

rot_suspended

abort stop

stop

[ rcmd=rot_cmd ] RotateFail[ rcmd=rot_cmd ] / RrotateFail

RotateNotOk[ rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1) mod 6)+1 ] / RrotateNotOk

RotateOk[ rcmd=rot_cmd & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1) mod 6)+1 ] / RrotateOk

[ !ss.(ss:STACKER_PROC => arms(ss) = up) ]

RotateArmsFail[ #ss.(ss:STACKER_PROC & arms(ss)=down) ] / RrotateArmsFail

Rotate[ (ZCoord>=xymoveOk or extpos<=3) ] / Rrotate

RotateZCoordFail[ ZCoord<xymoveOk & extpos > 3 ] / RrotateZCoordFail

Remedy / Rremedy

NoRemedy / RnoRemedy

RotateCommandRemedy[ rcmd=rot_cmd & !ss.(ss:STACKERS_PROC => arms(ss) = up) & (ZCoord>=xymoveOk or extpos<=3) ] / RrotateCommandRemedy

PreRotateNoRemedy / RpreRotateNoRemedy

RotateRemedy[ rcmd=rot_cmd & (ZCoord>=xymoveOk or extpos <=3) & !ss.(ss:STACKER_PROC => arms(ss) = up) ] / RrotateRemedy

RotateNoRemedy / RrotateNoRemedy

RotateCommand( p_steps )[ p_steps:-5..5 ] / RrotateCommand(p_steps)

ServiceNotReady / RServiceNotReady

Page 138: ABSTRACT - abo.fi

130

Appendix H: The decomposition of the control system of the Rotary Table. The procedures classes ZDRIVER1, XYZDRIVER_PROC, PLATEHOLDER1, and PLATE are the same as before. Appendix H.1: The plant of the Rotary Table. For every operation of the plant, a corresponding operation from the controller is called. REFINEMENT ROTARY_TABLE_PLANT REFINES ROTARY_TABLE_R2 SEES def2, def INCLUDES XYZDRIVER_PROC, ZDRIVER1, ROTARY_TABLE_CONTROLLER SETS R_STATE={ idle,get_ready,suspended,rotate,pre_rot_suspended,rot_suspended,abort} VARIABLES r_state INVARIANT r_state : R_STATE & steps:-5..5 &

/* Relation of plant and controller state. The plant state is equal to the controller state * /

(extpos > 3 & r_state = rotate => ZCoord >= xymoveOk) & (r_state = rotate => !ss.(ss:STACKERS_PROC =>arms(ss) = up)) & r_state = rotate => temp_ph_pos1:ran(ph_pos) & (r_state = rotate => ctrl_r_state = ctrl_rotate) & (ctrl_r_state = ctrl_rotate => r_state = rotate) & (r_state = rot_suspended => ctrl_r_state = ctrl_rot_suspended) & (ctrl_r_state = ctrl_rot_suspended => r_state = rot_suspended) & (r_state = pre_rot_suspended => ctrl_r_state = ctrl_pre_rot_suspended) & (ctrl_r_state = ctrl_pre_rot_suspended => r_state = pre_rot_suspended) & (r_state = suspended => ctrl_r_state = ctrl_suspended) & (ctrl_r_state = ctrl_suspended => r_state = suspended) & (r_state = abort => ctrl_r_state = ctrl_abort) & (ctrl_r_state = ctrl_abort => r_state = abort) & (r_state = get_ready => ctrl_r_state = ctrl_get_ready) & (ctrl_r_state = ctrl_get_ready => r_state = get_ready) & (r_state = idle => ctrl_r_state = ctrl_idle) & (ctrl_r_state = ctrl_idle => r_state = idle) INITIALISATION

Page 139: ABSTRACT - abo.fi

131

r_state := idle OPERATIONS /* Operation for supplying the rotate command, "rot_cmd", to the command

variable, “ rcmd” , and calling the corresponding controller operation * / RotateCommand (p_steps) = BEGIN SELECT r_state=idle & p_steps:-5..5 THEN r_state:=get_ready || RrotateCommand(p_steps) END END ; /* General failure – Call the corresponding controller operation * / RotateFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended || RrotateFail END END ;

/* Suspend service – The arms of the Stackers are down. Call the corresponding controller operation * /

RotateArmsFail = BEGIN SELECT #ss.(ss:STACKER_PROC & arms(ss)=down) THEN r_state:=pre_rot_suspended || RrotateArmsFail || SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END ;

/* Suspend service – The Dispensing head is not safe. Call the corresponding controller operation * /

RotateZCoordFail = BEGIN SELECT ZCoord<xymoveOk & extpos > 3 THEN r_state:=pre_rot_suspended || RrotateZCoordFail ||

Page 140: ABSTRACT - abo.fi

132

SELECT !ss.(ss:STACKER_PROC => arms(ss) = up) THEN SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END END ;

/* Remedy for failure when starting a rotation. Call the corresponding controller operation * /

RotateCommandRemedy = BEGIN SELECT r_state=pre_rot_suspended & rcmd=rot_cmd & !ss.(ss:STACKER_PROC => arms(ss) = up) & (ZCoord>=xymoveOk or extpos<=3) THEN r_state:=get_ready || RrotateCommandRemedy END END ;

/* Abort – Problem cannot be fixed. Call the corresponding controller operation * /

PreRotateNoRemedy = BEGIN SELECT r_state=pre_rot_suspended THEN r_state:=abort || RpreRotateNoRemedy END END ;

/* Operation to rotate. Call the corresponding controller operation * / Rotate = BEGIN SELECT (ZCoord>=xymoveOk or extpos<=3) THEN r_state:=rotate || Rrotate || SELECT !ss.(ss:STACKER_PROC => arms(ss) = up) THEN SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END

Page 141: ABSTRACT - abo.fi

133

END ;

/* Failure - Rotation did not completed successfully. Call the corresponding controller operation * /

RotateNotOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1) mod 6)+1 THEN r_state:=rot_suspended || RrotateNotOk END END ; /* Fix the problem. Call the corresponding controller operation * / RotateRemedy = BEGIN SELECT r_state=rot_suspended & rcmd=rot_cmd & (ZCoord>=xymoveOk or extpos <=3) & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN r_state:=rotate || RrotateRemedy END END ; /*Abort – Problem cannot be fixed. Call the corresponding controller operation * / RotateNoRemedy = BEGIN SELECT r_state=rot_suspended THEN r_state:=abort || RrotateNoRemedy END END ; /* Rotation completed successfully. Call the corresponding controller operation * / RotateOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1) mod 6)+1 THEN r_state:=idle || RrotateOk END END ; /* General ‘not ready’ failure. Call the corresponding controller operation * / ServiceNotReady = BEGIN

Page 142: ABSTRACT - abo.fi

134

SELECT r_state=idle THEN r_state:=suspended || RServiceNotReady END END ; /* Fix the problem. Call the corresponding controller operation * / Remedy = BEGIN SELECT r_state=suspended THEN r_state:=idle || Rremedy END END ; /* Abort – Problem cannot be fixed. Call the corresponding controller operation * / NoRemedy = BEGIN SELECT r_state=suspended THEN r_state:=abort || RnoRemedy END END END Appendix H.2: The controller of the Rotary Table. PRE preconditions have substituted the SELECT guards. The procedure calling is the same as in the refinement ROTARY_TABLE_R2. MACHINE ROTARY_TABLE_CONTROLLER SEES def2, def, XYZDRIVER_PROC, ZDRIVER1 INCLUDES PLATEHOLDER1, STACKER_PROC VARIABLES rcmd, steps, ctrl_r_state INVARIANT rcmd : TCOMMAND & steps : INT & ctrl_r_state : CTRL_R_STATE &

Page 143: ABSTRACT - abo.fi

135

steps : -5..5 INITIALISATION rcmd :: TCOMMAND || steps :: -5..5 || ctrl_r_state := ctrl_idle OPERATIONS RrotateCommand (p_steps) = PRE p_steps:INT & ctrl_r_state=ctrl_idle & p_steps:-5..5 THEN ctrl_r_state:=ctrl_get_ready || SetOldPos(ph_pos(DispPos)) || rcmd:= rot_cmd || steps:=p_steps END ; RrotateFail = PRE ctrl_r_state=ctrl_get_ready & rcmd=rot_cmd THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateArmsFail = PRE #ss.(ss:STACKER_PROC & arms(ss) = down) & rcmd = rot_cmd & ctrl_r_state = ctrl_get_ready THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateZCoordFail = PRE ZCoord < xymoveOk & extpos >3 & rcmd=rot_cmd & ctrl_r_state = ctrl_get_ready & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateCommandRemedy = PRE ctrl_r_state=ctrl_pre_rot_suspended & rcmd = rot_cmd & !ss.(ss:STACKER_PROC => arms(ss) = up) & (ZCoord>=xymoveOk or extpos<= 3) THEN ctrl_r_state:=ctrl_get_ready END

Page 144: ABSTRACT - abo.fi

136

; RpreRotateNoRemedy = PRE ctrl_r_state=ctrl_pre_rot_suspended THEN ctrl_r_state:=ctrl_abort END ; Rrotate = PRE (ZCoord >= xymoveOk or extpos <= 3) & ctrl_r_state = ctrl_get_ready & rcmd=rot_cmd & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_rotate || NewPlateholderPos(steps) END ; RrotateNotOk = PRE ctrl_r_state=ctrl_rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1) mod 6)+1 THEN ctrl_r_state:=ctrl_rot_suspended END ; RrotateRemedy = PRE ctrl_r_state=ctrl_rot_suspended & rcmd=rot_cmd & (ZCoord>=xymoveOk or extpos <= 3) & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_rotate END ; RrotateNoRemedy = PRE ctrl_r_state=ctrl_rot_suspended THEN ctrl_r_state:=ctrl_abort END ; RrotateOk = PRE ctrl_r_state=ctrl_rotate & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1) mod 6)+1

Page 145: ABSTRACT - abo.fi

137

THEN ctrl_r_state:=ctrl_idle END ; RServiceNotReady = PRE ctrl_r_state=ctrl_idle THEN ctrl_r_state:=ctrl_suspended END ; Rremedy = PRE ctrl_r_state=ctrl_suspended THEN ctrl_r_state:=ctrl_idle END ; RnoRemedy = PRE ctrl_r_state=ctrl_suspended THEN ctrl_r_state:=ctrl_abort END END Appendix H.3: The updated DEF2 class. The set of states for the controller is included. MACHINE DEF2 SETS TCOMMAND={ rot_cmd} ; SCOMMAND={ dsk_cmd, sk_cmd} ; PH_ID; PID; ARM_POS={ up, down} ; CTRL_R_STATE={ ctrl_rotate,ctrl_rot_suspended, ctrl_pre_rot_suspended, ctrl_suspended, ctrl_abort, ctrl_get_ready, ctrl_idle} CONSTANTS zmin, zmax, ROTARY_POS, DispPos PROPERTIES zmin : NAT &

Page 146: ABSTRACT - abo.fi

138

zmax : NAT & zmin + 1<zmax &

ROTARY_POS = { 1, 2, 3, 4, 5, 6} & DispPos = 1 END

Page 147: ABSTRACT - abo.fi

139

Appendix I : The decomposition of the sensors & actuators of the Rotary Table. Appendix I.1: The class diagram of the sensor and controller decomposition of the Rotary Table. Assume the classes PLATE and STACKER_PROC the same as previously.

RT_CONTROLLER_ACTUATOR

ph_pos : ROTARY_POS --> PH_IDplate_id : PH_ID +-> PID = {}pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT)Acc_Height : PH_ID +-> NAT

PlateholderChangeAct()PlateholderPlateAddAct()PlateholderPlateRemoveAct()NewPhPosClockwiseAct()NewPhPosCounterClkwiseAct()

PLATEHOLDER2

temp_ph_pos1 : PH_IDAcc_minHeight : zmin..zmaxxymoveOk : zmin..zmax

PlateholderChange(ph_id : PH_ID, p_height : NAT, pos : ROTARY_POS)PlateholderPlateAdd(ph_id : PH_ID, pid : PID, pheight : NAT, l iq_amt : NAT, pminheight : NAT, pmaxVol : NAT, pnoOfW : NAT1)PlateholderPlateRemove(ph_id : PH_ID, pid : PID)AddLiquid(ph_id : PH_ID, intpos : NAT, pid : PID, amt : NAT)RemoveLiquid(ph_id : PH_ID, pid : PID, intpos : NAT, amt : NAT)NewPlateholderPos(rr : INT)HeightOk(zpos : NAT)HeightNotOk(zpos : NAT)SetOldPos(p_phid : PH_ID)

ROTARY_TABLE_CONTROLLER1

rcmd : TCOMMANDsteps : INT = ::-5..5ctrl _r_stat e : CTRL _R_STA TE = c trl_ id le

Rro ta teComma nd(p_ste ps : INT)Rro ta te()Rro ta teFai l()Rro ta teComma ndRe me dy()Rro ta teA rmsFai l()Rro ta teZCoordFa i l()Rro ta teNotOk()Rro ta teRemedy()Rro ta teNoRemedy()Rro ta teOk()RpreRot ateNoRe medy()RServiceNotRe ady()Rre medy()RnoRe medy()

ROTARY_TABLE_PLANT1

RotateCommand(p_steps : INT)Rotate()RotateFai l()RotateCommandRemedy()RotateArmsFai l()RotateZCoordFai l()RotateNotOk()RotateRemedy()RotateNoRemedy()RotateOk()PreRotateNoRemedy()ServiceNotReady()Remedy()NoRemedy()

<<bind>>

Z_SENSOR

ZCoord1 : zmin..zmax = zcoord(home_z)

SetZSensor(p_z : zmin..zmax)zz <-- GetZSensorValue()

<<bind>>

<<bind>>

STACKER_PROC

PLATE <<bind>>

<<bind>><<bind>>

DEF2

Page 148: ABSTRACT - abo.fi

140

Appendix J: The decomposition of sensors & actuators. The classes STACKER_PROC and PLATE are the same as in the previous step. Appendix J.1: The Rotary Table plant refinement. REFINEMENT ROTARY_TABLE_PLANT 1 REFINES ROTARY_TABLE_PLANT SEES def2, def INCLUDES XYZDRIVER_PROC, ZSENSOR, ROTARY_TABLE_CONTROLLER1 SETS R_STATE={ idle,get_ready,suspended,rotate,pre_rot_suspended,rot_suspended,abort} VARIABLES r_state INVARIANT r_state : R_STATE & steps:-5..5 & /* Relation of plant and controller state. The plant state is equal to the controller state * / (extpos > 3 & r_state = rotate => ZCoord >= xymoveOk) & (r_state = rotate => !ss.(ss:STACKER_PROC =>arms(ss) = up)) & r_state = rotate => temp_ph_pos1:ran(ph_pos) & (r_state = rotate => ctrl_r_state = ctrl_rotate) & (ctrl_r_state = ctrl_rotate => r_state = rotate) & (r_state = rot_suspended => ctrl_r_state = ctrl_rot_suspended) & (ctrl_r_state = ctrl_rot_suspended => r_state = rot_suspended) & (r_state = pre_rot_suspended => ctrl_r_state = ctrl_pre_rot_suspended) & (ctrl_r_state = ctrl_pre_rot_suspended => r_state = pre_rot_suspended) & (r_state = suspended => ctrl_r_state = ctrl_suspended) & (ctrl_r_state = ctrl_suspended => r_state = suspended) & (r_state = abort => ctrl_r_state = ctrl_abort) & (ctrl_r_state = ctrl_abort => r_state = abort) & (r_state = get_ready => ctrl_r_state = ctrl_get_ready) & (ctrl_r_state = ctrl_get_ready => r_state = get_ready) & (r_state = idle => ctrl_r_state = ctrl_idle) & (ctrl_r_state = ctrl_idle => r_state = idle) & ZCoord = ZCoord1 INITIALISATION r_state := idle OPERATIONS

Page 149: ABSTRACT - abo.fi

141

/* Operation for supplying the rotate command, "rot_cmd", to the command variable, "rcmd", and calling the corresponding controller operation * / RotateCommand (p_steps) = BEGIN SELECT r_state=idle & p_steps:-5..5 THEN r_state:=get_ready || RrotateCommand(p_steps) END END ; /* General failure - Call the corresponding controller operation * / RotateFail = BEGIN SELECT r_state=get_ready & rcmd=rot_cmd THEN r_state:=pre_rot_suspended || RrotateFail END END ; /* Suspend service - The arms of the Stackers are down. Call the corresponding controller operation * / RotateArmsFail = BEGIN SELECT #ss.(ss:STACKER_PROC & arms(ss)=down) THEN r_state:=pre_rot_suspended || RrotateArmsFail || SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END ; /* Suspend service - The Dispensing head is not safe. Call the corresponding controller operation * / RotateZCoordFail = BEGIN SELECT ZCoord1<xymoveOk & extpos > 3 THEN r_state:=pre_rot_suspended || RrotateZCoordFail || SELECT !ss.(ss:STACKER_PROC => arms(ss) = up) THEN SELECT r_state=get_ready &

Page 150: ABSTRACT - abo.fi

142

rcmd=rot_cmd THEN skip END END END END ; /* Remedy for failure when starting a rotation. Call the corresponding controller operation * / RotateCommandRemedy = BEGIN SELECT r_state=pre_rot_suspended & rcmd=rot_cmd & !ss.(ss:STACKER_PROC => arms(ss) = up) & (ZCoord1>=xymoveOk or extpos<=3) THEN r_state:=get_ready || RrotateCommandRemedy END END ; /* Abort - Problem cannot be fixed. Call the corresponding controller operation * / PreRotateNoRemedy = BEGIN SELECT r_state=pre_rot_suspended THEN r_state:=abort || RpreRotateNoRemedy END END ; /* Operation to rotate. Call the corresponding controller operation * / Rotate = BEGIN SELECT (ZCoord1>=xymoveOk or extpos<=3) THEN r_state:=rotate || Rrotate || SELECT !ss.(ss:STACKER_PROC => arms(ss) = up) THEN SELECT r_state=get_ready & rcmd=rot_cmd THEN skip END END END END ; /* Failure - Rotation did not completed successfully. Call the corresponding controller operation * /

Page 151: ABSTRACT - abo.fi

143

RotateNotOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1) mod 6)+1 THEN r_state:=rot_suspended || RrotateNotOk END END ; /* Fix the problem. Call the corresponding controller operation * / RotateRemedy = BEGIN SELECT r_state=rot_suspended & rcmd=rot_cmd & (ZCoord1>=xymoveOk or extpos <=3) & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN r_state:=rotate || RrotateRemedy END END ; /*Abort - Problem cannot be fixed. Call the corresponding controller operation * / RotateNoRemedy = BEGIN SELECT r_state=rot_suspended THEN r_state:=abort || RrotateNoRemedy END END ; /* Rotation completed successfully. Call the corresponding controller operation * / RotateOk = BEGIN SELECT r_state=rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1) mod 6)+1 THEN r_state:=idle || RrotateOk END END ; /* General 'not ready' failure. Call the corresponding controller operation * / ServiceNotReady = BEGIN SELECT r_state=idle THEN r_state:=suspended || RServiceNotReady END

Page 152: ABSTRACT - abo.fi

144

END ; /* Fix the problem. Call the corresponding controller operation * / Remedy = BEGIN SELECT r_state=suspended THEN r_state:=idle || Rremedy END END ; /* Abort - Problem cannot be fixed. Call the corresponding controller operation * / NoRemedy = BEGIN SELECT r_state=suspended THEN r_state:=abort || RnoRemedy END END END Appendix J.2: The refined controller of the Rotary Table. MACHINE ROTARY_TABLE_CONTROLLER1 SEES def2, def, XYZDRIVER_PROC, ZDRIVER1 INCLUDES PLATEHOLDER2, STACKER_PROC VARIABLES rcmd, steps, ctrl_r_state INVARIANT rcmd : TCOMMAND & steps : INT & ctrl_r_state : CTRL_R_STATE & steps : -5..5 INITIALISATION rcmd :: TCOMMAND || steps :: -5..5 || ctrl_r_state := ctrl_idle

Page 153: ABSTRACT - abo.fi

145

OPERATIONS RrotateCommand (p_steps) = PRE p_steps:INT & ctrl_r_state=ctrl_idle & p_steps:-5..5 THEN ctrl_r_state:=ctrl_get_ready || SetOldPos(ph_pos(DispPos)) || rcmd:= rot_cmd || steps:=p_steps END ; RrotateFail = PRE ctrl_r_state=ctrl_get_ready & rcmd=rot_cmd THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateArmsFail = PRE #ss.(ss:STACKER_PROC & arms(ss) = down) & rcmd = rot_cmd & ctrl_r_state = ctrl_get_ready THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateZCoordFail = PRE ZCoord1 < xymoveOk & extpos >3 & rcmd=rot_cmd & ctrl_r_state = ctrl_get_ready & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_pre_rot_suspended END ; RrotateCommandRemedy = PRE ctrl_r_state=ctrl_pre_rot_suspended & rcmd = rot_cmd & !ss.(ss:STACKERS_PROC => arms(ss) = up) & (ZCoord1>=xymoveOk or extpos<= 3) THEN ctrl_r_state:=ctrl_get_ready END ; RpreRotateNoRemedy = PRE ctrl_r_state=ctrl_pre_rot_suspended THEN ctrl_r_state:=ctrl_abort

Page 154: ABSTRACT - abo.fi

146

END ; Rrotate = PRE (ZCoord1 >= xymoveOk or extpos <= 3) & ctrl_r_state = ctrl_get_ready & rcmd=rot_cmd & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_rotate || NewPlateholderPos(steps) END ; RrotateNotOk = PRE ctrl_r_state=ctrl_rotate & rcmd=rot_cmd & ph_pos~(temp_ph_pos1)/=((6+DispPos+steps-1) mod 6)+1 THEN ctrl_r_state:=ctrl_rot_suspended END ; RrotateRemedy = PRE ctrl_r_state=ctrl_rot_suspended & rcmd=rot_cmd & (ZCoord1>=xymoveOk or extpos <= 3) & !ss.(ss:STACKER_PROC => arms(ss) = up) THEN ctrl_r_state:=ctrl_rotate END ; RrotateNoRemedy = PRE ctrl_r_state=ctrl_rot_suspended THEN ctrl_r_state:=ctrl_abort END ; RrotateOk = PRE ctrl_r_state=ctrl_rotate & ph_pos~(temp_ph_pos1)=((6+DispPos+steps-1) mod 6)+1 THEN ctrl_r_state:=ctrl_idle END ; RServiceNotReady = PRE

Page 155: ABSTRACT - abo.fi

147

ctrl_r_state=ctrl_idle THEN ctrl_r_state:=ctrl_suspended END ; Rremedy = PRE ctrl_r_state=ctrl_suspended THEN ctrl_r_state:=ctrl_idle END ; RnoRemedy = PRE ctrl_r_state=ctrl_suspended THEN ctrl_r_state:=ctrl_abort END END Appendix J.3: The updated procedure class PLATEHOLDER2 of the Rotary Table. MACHINE PLATEHOLDER2 SEES def2, def INCLUDES PLATE, RT_CONTROLLER_ACTUATOR VARIABLES temp_ph_pos1, Acc_minHeight, xymoveOk INVARIANT temp_ph_pos1 : PH_ID & Acc_minHeight : zmin..zmax & xymoveOk : zmin..zmax & xymoveOk=max(ran(Acc_Height)) & dom(pholder) = dom(Acc_Height) & (!xx.(xx:dom(pholder) => Acc_minHeight >= (pholder(xx))'height)) & (!xx.(xx:dom(pholder) & (pholder(xx))'plate_present = TRUE =>

plate_id(xx):dom(Plate))) & /* If plate_present is TRUE then there is plate in that plateholder * / ((pholder(ph_pos(DispPos)))'plate_present=TRUE => Acc_minHeight =

Page 156: ABSTRACT - abo.fi

148

(pholder(ph_pos(DispPos)))'height + (Plate(plate_id(ph_pos(DispPos))))'minheight + zmin) & ((pholder(ph_pos(DispPos)))'plate_present=FALSE => Acc_minHeight = (pholder(ph_pos(DispPos)))'height + zmin) & (!xx.(xx:dom(pholder) => (pholder(xx))'height + zmin < xymoveOk)) & ran(plate_id) = dom(Plate) INITIALISATION temp_ph_pos1 :: PH_ID || ANY p_height WHERE p_height:NAT THEN Acc_minHeight := p_height || xymoveOk := p_height END OPERATIONS PlateholderChange (ph_id,p_height,pos) = PRE ph_id:PH_ID & p_height:NAT & pos:ROTARY_POS & ph_id/:ran(ph_pos) & (pholder(ph_id)´plate_present = FALSE THEN /* Call this operation from the Actuator class * / PlateholderChangeAct(ph_id, pos, p_height) || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ p_height+zmin} ) || IF pos=DispPos THEN Acc_minHeight := (pholder(ph_pos(DispPos))´height + zmin ELSE skip END END ; PlateholderPlateAdd (ph_id,pid,pheight,liq_amt,pminheight,pmaxVol,pnoOfW) = PRE ph_id:PH_ID & pid:PID & pheight:NAT & liq_amt:NAT & pminheight:NAT & pmaxVol:NAT & pnoOfW:NAT1 & (pholder(ph_id))´plate_present=FALSE & Acc_Height(ph_id)+pheight<=zmax THEN /* Call this operation from the actuator class * /

Page 157: ABSTRACT - abo.fi

149

PlateholderPlateAddAct(ph_id, pid, pheight) || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ Acc_Height(ph_id)+pheight} ) || /*Call this operation from the PLATE class * / PlateAdd(pid, pheight, liq_amt, pminheight, pmaxVol, pnoOfW) || IF ((ph_pos~(ph_id))=DispPos) THEN Acc_minHeight := (pholder(ph_pos(DispPos)))'height + pminheight + zmin ELSE skip END END ; PlateholderPlateRemove (ph_id,pid) = PRE ph_id:PH_ID & pid:PID & ph_id:dom(pholder) & (pholder(ph_id))´plate_present=TRUE & pid:ran(plate_id) THEN /* Call this operation from the actuator class * / PlateholderPlateRemoveAct(ph_id, pid) || xymoveOk:=max(ran({ ph_id} <<|Acc_Height)\/{ (pholder(ph_id))'height+zmin} ) || /*Call this operation from the PLATE class * / PlateRemove(pid) || IF ((ph_pos~(ph_id)) = DispPos) THEN Acc_minHeight := (pholder(ph_pos(DispPos)))'height + zmin ELSE skip END END ; AddLiquid (ph_id,intpos,pid,amt) = PRE ph_id:PH_ID & intpos:NAT & pid:PID & amt:NAT & ph_id:dom(pholder) THEN Plate_LiquidAdd(pid, intpos, amt) END ; RemoveLiquid (ph_id,pid,intpos,amt) = PRE ph_id:PH_ID &

Page 158: ABSTRACT - abo.fi

150

pid:PID & intpos:NAT & amt:NAT & ph_id:dom(pholder) THEN Plate_LiquidRemove(pid, intpos, amt) END ; NewPlateholderPos (rr ) = PRE rr :INT & rr:-5..5 THEN SELECT rr > 0 THEN /* Call this operation from actuator class for clockwise rotation * / NewPhPosClockwiseAct(rr) || ANY yy WHERE yy:ROTARY_POS & (((yy+rr-1)mod 6)+1) = 1 THEN IF (pholder(ph_pos(yy)))'plate_present = TRUE THEN Acc_minHeight := (pholder(ph_pos((yy)))'height + (Plate(plate_id(ph_pos(yy))))'minheight + zmin ELSE Acc_minHeight := (pholder(ph_pos(yy)))'height + zmin END END WHEN rr < 0 THEN /* Call this operation from actuator class for counterclockwise rotation * / NewPhPosCounterClkwiseAct || ANY yy WHERE yy:ROTARY_POS & (((6+yy+rr-1)mod 6)+1) = 1 THEN IF (pholder(ph_pos(yy)))'plate_present = TRUE THEN Acc_minHeight := (pholder(ph_pos((yy)))'height + (Plate(plate_id(ph_pos(yy))))'minheight + zmin ELSE Acc_minHeight := (pholder(ph_pos(yy)))'height + zmin END END WHEN rr = 0 THEN skip END

Page 159: ABSTRACT - abo.fi

151

END ; HeightOk (zpos) = PRE zpos:NAT & zpos > xymoveOk & zpos <= zmax THEN skip END ; HeightNotOk (zpos) = PRE zpos:NAT & zpos <= xymoveOk THEN skip END ; SetOldPos (p_phid) = PRE p_phid:PH_ID THEN temp_ph_pos1:=p_phid END END Appendix J.4 The sensor Z_SENSOR. MACHINE Z_SENSOR SEES def, def2 VARIABLES ZCoord1 INVARIANT ZCoord1 : zmin..zmax INITIALISATION ZCoord1 := zcoord(home_z) OPERATIONS SetZSensor (p_z) = PRE p_z:zmin..zmax THEN ZCoord1:=p_z

Page 160: ABSTRACT - abo.fi

152

END ; zz <-- GetZSensorValue = BEGIN zz:=ZCoord1 END END Appendix J.5. The actuator RT_CONTROLLER_ACTUATOR. MACHINE RT_CONTROLLER_ACTUATOR VARIABLES ph_pos, plate_id, pholder, Acc_Height INVARIANT ph_pos : ROTARY_POS --> PH_ID & plate_id : PH_ID +-> PID & pholder : PH_ID +-> struct(plate_present:BOOL,height:NAT) & Acc_Height : PH_ID +-> NAT INITIALISATION plate_id := { } || ANY phs, p_height WHERE phs<: PH_ID & card(phs) = card(ROTARY_POS) & p_height:NAT THEN pholder := phs*{ rec(plate_present:FALSE, height:p_height} || ph_pos := ROTARY_POS*phs || Acc_Height := phs*{ p_height} END OPERATIONS /* Change plateholder and update variables * / PlateholderChangeAct (ph_id,pos,p_height) = PRE ph_id:PH_ID & pos:ROTARY_POS & p_height:NAT & ph_id/:ran(ph_pos) & (pholder(ph_id))'plate_present = FALSE THEN ph_pos := ph_pos<+{ pos|->ph_id} || pholder := { ph_pos(pos)} <<|(pholder<+{ ph_id|->rec(FALSE,p_height)} || Acc_Height(ph_id):=p_height + zmin END ; /* Add plate and update heights * / PlateholderPlateAddAct (ph_id,pid,pheight) =

Page 161: ABSTRACT - abo.fi

153

PRE ph_id:PH_ID & pid:PID & pheight:NAT & (pholder(ph_id))´plate_present=FALSE & Acc_Height(ph_id)+pheight<=zmax THEN pholder:=pholder<+{ ph_id|->rec(TRUE,(pholder(ph_id))´height)} || plate_id(ph_id):=pid || Acc_Height(ph_id):=Acc_Height(ph_id)+pheight END ; /* Remove plate and update heights * / PlateholderPlateRemoveAct (ph_id,pid) = PRE ph_id:PH_ID & pid:PID & ph_id:dom(pholder) & (pholder(ph_id))´plate_present=TRUE & pid:ran(plate_id) THEN pholder:=pholder<+{ ph_id|->rec(FALSE,(pholder(ph_id))´height)} || plate_id:=plate_id|>>{ pid} || Acc_Height(ph_id):=(pholder(ph_id))'height+zmin END ; /* Calculate new plateholder positions for clockwise rotation * / NewPhPosClockwiseAct (rr) = PRE rr:INT & rr > 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((xx+rr-1)mod 6)+1)=ph_pos$0(xx))) END ; /* Calculate new plateholder positions for counterclockwise rotation * / NewPhPosCounterClkwiseAct (rr) = PRE rr:INT & rr < 0 THEN ph_pos:(!xx.(xx:ROTARY_POS=>ph_pos(((6+xx+rr-1)mod 6)+1)=ph_pos$0(xx))) END END