This report documents the development of a model for an exploration robot, specified in RoboChart and analysed using FDR. First, we describe the requirements, and their formal CSP encoding suitable for verification with FDR, and then discuss the verification results for several iterations of the model, culminating in a version that satisfies all requirements.
This requirement is encoded in CSP as follows.
StopOp = StopCall -> StopRet -> SKIP
Timed(OneStep) {
R1 = CHAOS(Events) [| {|VCModule_cmd|} |> (StopOp ; TSTOP)
assert timed_priority(R1) [FD= System
}
Within a timed section, the process R1
encodes the requirement. Initially it behaves as CHAOS(Events)
, the process that nondeterministically can perform any event in the set Events
(of all events in scope). It can be interrupted by the event VCModule_cmd
to behave as StopOp ; TSTOP
, the sequential composition of StopOp
, the process that models the call to operation Stop
, and TSTOP
, the timed deadlock process. Observe that the call to operation Stop
needs to be completed without time passing.
The requirement is verified by stating that the System
process, that is the calculated timed semantics of the RoboChart model, is a refinement of R1
, where timed_priority
is a function that ensures R1
has the correct timed semantics of tock-CSP
as required for verification.
This requirement is encoded in CSP as follows.
Timed(OneStep) {
R2 = CHAOS(Events)
[| {|VCModule_found|} |>
(VCModule_flash.out -> StopOp; VCModule_cmd.in -> StopOp; STOP)
}
assert timed_priority(R2) [FD= System
We have, within a timed section, the process R2
defined using a pattern similar to R1
. Initially it behaves as CHAOS(Events)
and can be interrupted by VCModule_found
to behave as the process that offers VCModule_flash.out
, where out
indicates that this is an output form the software to the robotic platform, followed by a call to operation Stop
, and then also offers to accept a command, via the event VCModule_cmd.in
, where in
indicates that this is an input to the software.
Observe that VCModule_flash.out
and VCModule_cmd.in
have no timed constraints associated, and can therefore happen at any time. The calls to the operation Stop
, however, do not consume time, and thus are specified, just as before, outside the timed section.
This requirement is encoded in CSP as follows.
ReverseOp = ReverseCall -> ReverseRet -> SKIP
-- The following process models the 'ChangeDirection' operation, which can
-- call 'TurnRight' or 'TurnLeft'. The decision whether to call one or the
-- other is internal to the state machine.
ChangeDirectionOp = ChangeDirectionCall ->
(TurnRightCall -> TurnRightRet -> SKIP
|~|
TurnLeftCall -> TurnLeftRet -> SKIP)
; ChangeDirectionRet -> SKIP
Timed(OneStep) {
R3 = CHAOS(Events)
[| {|VCModule_obstacle.in.Loc_left, VCModule_obstacle.in.Loc_right|} |>
((ChangeDirectionOp |~| ReverseOp) ; R3)
R3System = timed_priority((System [| {|VCModule_cmd|} |] SKIP) \ {|VCModule_odometer|})
assert timed_priority(R3) [FD= R3System
}
Using a similar pattern to the previous processes, process R3
initially behaves nondeterministically. It can be interrupted by either
VCModule_obstacle.in.Loc_left
or VCModule_obstacle.in.Loc_right
, where, as before, in
indicates this is an input to the software, and Loc_left
and Loc_right
indicate that an obstacle is detected on either the left or right of the robot, specified using a data type in RoboChart. It can then behave as either ChangeDirectionOp
, that models the call to the RoboChart operation ChangeDirection
, or ReverseOp
, that models the call to Reverse
, followed by the recursion on R3
.
Observe that ChangeDirection
is a software operation, and as such, it interfaces with the platform by calling either TurnLeft
or TurnCall
, as specified in the CSP process ChangeDirectionOp
. Here we simply record that either operation can be called nondeterministically, since R3
does not specify a particular direction.
Both calls to ChangeDirection
and Reverse
do not consume time, and thus are specified outside the timed section.
As before, the requirement is stated using a refinement check, but in this case the System
process
is composed in parallel with SKIP
, synchronising on VCModule_cmd
, indicating that no command can
be issued, and VCModule_odometer
is hidden.
This requirement is encoded in CSP as follows.
Timed(OneStep) {
R4 = CHAOS(Events)
[| {|VCModule_obstacle.in.Loc_left, VCModule_obstacle.in.Loc_right|} |>
(Deadline(VCModule_odometer.in?x -> SKIP,0) ; R4)
R4System = (System [| {|VCModule_cmd|} |] SKIP)
assert timed_priority(R4) [FD= timed_priority(R4System)
}
Similar to the previous processes, R4
is specified using an interrupt on events VCModule_obstacle.in.Loc_left
and VCModule_obstacle.in.Loc_right
. Following such an event, the
The RoboChart model consists of a module named VCModule
, connecting the events of
platform VCRobot
to controller named VCController
. There are 5 input events:
odometer
of type natural that corresponds to an odometer reading; obstacle
of type Loc
, also defined in RoboChart, that identifies the location of an obstacle
relative to the robot left
, right
or no
obstacle; turn
that is used by the
platform to instruct the controller to turn
; found
to indicate whether the charging
station has been found; cmd
for the robot to be stopped. There is a single output
event flash
that is used for the controller to activate LEDs on the robot.
The robotic platform VCRobot
uses the input and output events, defined in an interface
Events
, and provides two interfaces: OperationSig
that contains operations implemented
by the platform, and OperationDef
containing a single operation ChangeDirection
that
is actually defined in RoboChart in terms of lower level operations in OperationSig
. All
operations in OperationSig
are specified as terminating.
The controller VCController
requires both interfaces OperationSig
and OperationDef
,
and uses the interface Events
. The input and output events are connected to a state
machine Movement
.
The structure of the controller and the robotic platform are the same throughout this
document. In what follows we focus our attention on the definition of the first version
of the state machine Movement
.
The state machine Movement
also requires the interfaces OperationSig
, OperationDef
and uses the interface Events
. In addition, it defines a number of constants: outPeriod
,
stuckDist
, turningPeriod
, batteryLife
and forwardPeriod
. It also defines 5 variables:
angle
, d0
, d1
, l
and l_new
. Finally, two clocks T1
and T2
are also defined.
It consists of two states, Searching
and Finish
.
To check that the refinements hold, the constants specified in RoboChart, as well as bounds for the data types need to be provided in order for model checking to be performed. Below we describe their values.
#### Parameters for model-checking.
For analysis the process System
is manually defined in the file ManualAssertions.csp
as:
System = timed::VCModule(1)
it is defined as the automatically calculated timed semantics of RoboChart as timed::VCModule(1)
,
where 1
is a natural that uniquely identifies the module. Observe that this is simply an artifact
of the semantics of RoboChart that provides support for specifying collections.
The data types and functions are instantiated as in the file
instantiations.csp
. Natural and real are instantiated as the set {0..2}
for verification. Of particular importance is the definition of the constants
outPeriod
, stuckDist
, batteryLife
, turningPeriod
and forwardPeriod
,
in addition to the definition of the function Length
, all reproduced below.
-- generate Movement_outPeriod not
Movement_outPeriod = 1
-- generate Movement_stuckDist not
Movement_stuckDist = 1
-- generate Movement_batteryLife not
Movement_batteryLife = 1
-- generate Length not
Length(i,j) = if i-j < 0 then Neg(i-j,real) else Minus(i,j,real)
-- generate Movement_turningPeriod not
Movement_turningPeriod = 1
-- generate Movement_forwardPeriod not
Movement_forwardPeriod = 1
The assertions file is called ManualAssertions.csp
within the folder src-gen/timed/
of a project (ie. its zip file).
Requirement | Result |
---|---|
R1 | pass |
R2 | pass |
R3 | fail |
R4 | fail |
Requirements R1
and R2
are satisfied, while R3
and R4
are not.
The counter-example for R3
, shown below,
timed_priority(tock)(R3) [FD= R3System:
Log:
Result: [31mFailed[m
Visited States: 6
Visited Transitions: 17
Visited Plys: 3
Estimated Total Storage: 134MB
Counterexample (Divergence Counterexample)
Specification Debug:
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left>
Implementation Debug:
R3System (Repeat Behaviour):
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left>
Repeats the trace: <τ>
indicates that following the trace <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_right>
there is a divergence. This is because there is an unreasonable
assumption that there can be an infinite number of odometer readings in a finite amount of
time. Therefore, we propose a new version of R3System
as R3System'
where the number of odometer readings
within a single time unit is bounded to at most 2
.
Bounded(S,N) = BoundedIni(S,N,N)
BoundedIni(S,N,I) = if N == 0 then tock -> Bounded(S,I)
else tock -> BoundedIni(S,I,I)
[]
([] x:S @ x -> BoundedIni(S,N-1,I))
Timed(OneStep) {
R3System' = timed_priority(((System [| {|VCModule_cmd|} |] SKIP)
[| {|VCModule_odometer,tock|} |]
Bounded({|VCModule_odometer|},2)) \{|VCModule_odometer|})
}
This is achieved by composing in parallel with (System [| {|VCModule_cmd|} |] SKIP)
a process
Bounded({|VCModule_odometer|},2)
, synchronising on the channel set VCModule_odometer
and the
event tock
, that only offers VCModule_odometer
at most twice before time elapses.
The new assertion is then
assert timed_priority(R3) [FD= R3System'
and as required it passes.
So the revised table of results is presented below.
Requirement | Result | Comments |
---|---|---|
R1 | pass | |
R2 | pass | |
R3 | pass | *with assumptions |
R4 | fail |
The verification of requirement R4
fails, as detailed below.
timed_priority(tock)(R4) [FD= R4System:
Log:
Result: [31mFailed[m
Visited States: 6
Visited Transitions: 15
Visited Plys: 3
Estimated Total Storage: 134MB
Counterexample (Trace Counterexample)
Specification Debug:
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left>
Available Events: {|VCModule_odometer.in|}
Implementation Debug:
R4System (Trace Behaviour):
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left>
Error Event: ChangeDirectionCall
In this case we have that after calling MoveForward
and noticing an
obstacle
the system can perform a call to ChangeDirection
, whereas
the requirement actually requires an odometer reading to take place
before a call to either ChangeDirection
or Reverse
. In this case,
and despite our earlier discussion earlier on the failure of R3
, it
is the model of state machine SMovement
that is at fault. So we
propose a new version in the following section.
To ensure that an odometer
reading follows an obstacle detection
we change states Avoiding
and AvoidingAgain
as follows.
As before, the parameters used in the instantiations.csp
file are
exactly the same.
Requirement | Result | Comments |
---|---|---|
R1 | pass | |
R2 | pass | |
R3 | pass | *irrespective of assumptions |
R4 | fail |
Note that, because of the change in the model, whereby odometer readings
are now performed only once in the entry action of states Avoiding
and
AvoidingAgain
, requirement R3
is successfully met irrespective of the
assumptions we considered for version 1 of the model. This is because
there is no longer the possibility for the state machine to keep reading
the odometer infinitely fast.
Similarly to the situation with version 1 of the model, all requirements
pass, except for R4
, as detailed below.
timed_priority(tock)(R4) [FD= R4System:
Log:
Result: [31mFailed[m
Visited States: 9
Visited Transitions: 19
Visited Plys: 4
Estimated Total Storage: 0B
Counterexample (Trace Counterexample)
Specification Debug:
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left>
Available Events: {|VCModule_odometer.in|}
Implementation Debug:
R3Spec (Trace Behaviour):
Trace: <MoveForwardCall, MoveForwardRet,
VCModule_obstacle.in.Loc_left, τ>
Error Event: tock
FDR provides a counter-example whereby after calling the operation
MoveForward
and detecting an obstacle
it is possible for time
to pass, whereas the specification R4
required the odometer reading
to be immediate. To rectify this problem, we impose a deadline of zero
time on this reading on the entry action of states Avoiding
and
AvoidingAgain
. Thus, we have a new version of the state machine
SMovement
, which we show in the following section.
To accommodate the deadline of requirement R4
, we update the entry
actions of states Avoiding
and AvoidingAgain
to require the odometer
reading to be completed immediately.
Following the modifications in the third version, it is possible to check that all requirements are satisfied.
The table of all results is shown below.
Requirement | Result | Comments |
---|---|---|
R1 | pass | |
R2 | pass | |
R3 | pass | *irrespective of assumptions |
R4 | pass |
The automatically generated code for simulation with ArGoS is available for download.
Department of Computer Science
Deramore Lane, University of York, Heslington, York, YO10 5GH, UK
Tel: 01904 325500
University of York legal statements