@@ -77,12 +77,12 @@ is plotted in the Figure below.
77
77
22: // Vertical speed of the UAV detected by GPS sensor
78
78
23: float estimator_z_dot;
79
79
24:
80
- 25: /** PID funciton OUTPUTS */
80
+ 25: /** PID function OUTPUTS */
81
81
26: float desired_gaz;
82
82
27: float desired_pitch;
83
83
28:
84
- 29: /** Accumulated error in the control */
85
- 30: float climb_sum_err;
84
+ 29: /** The state variable: accumulated error in the control */
85
+ 30: float climb_sum_err=0 ;
86
86
31:
87
87
32: /** Computes desired_gaz and desired_pitch */
88
88
33: void climb_pid_run()
@@ -118,26 +118,35 @@ is plotted in the Figure below.
118
118
63: __CPROVER_assume(desired_climb>=-MAX_CLIMB && desired_climb<=MAX_CLIMB);
119
119
64: __CPROVER_assume(estimator_z_dot>=-MAX_CLIMB && estimator_z_dot<=MAX_CLIMB);
120
120
65:
121
- 66: climb_pid_run();
122
- 67:
123
- 68: }
124
- 69:
125
- 70: return 0;
126
- 72: }
121
+ 66: __CPROVER_input("desired_climb", desired_climb);
122
+ 67: __CPROVER_input("estimator_z_dot", estimator_z_dot);
123
+ 68:
124
+ 69: climb_pid_run();
125
+ 70:
126
+ 71: __CPROVER_output("desired_gaz", desired_gaz);
127
+ 72: __CPROVER_output("desired_pitch", desired_pitch);
128
+ 73:
129
+ 74: }
130
+ 75:
131
+ 76: return 0;
132
+ 77: }
127
133
</code></pre>
128
134
129
135
<p class="justified">
130
136
In order to test the PID controller, we construct a main control loop,
131
- which repeatedly invokes the function <code>climb_pid_run</code> (line 66).
132
- In the beginning of each loop iteration, the values of the desired speed <code>desired_climb</code>
133
- and the estimated speed <code>estimated_z_dot</code> are assigned non-deterministically.
137
+ which repeatedly invokes the function <code>climb_pid_run</code> (line 69).
138
+ This PID function has two input variables: the desired speed <code>desired_climb</code>
139
+ and the estimated speed <code>estimated_z_dot</code>.
140
+ In the beginning of each loop iteration, values of the inputs are assigned non-deterministically.
134
141
Subsequently, the <code>__CPROVER_assume</code> statement in lines 63 and 64 guarantees that
135
- their values are bounded within a valid range.
142
+ both values are bounded within a valid range.
143
+ The <code>__CPROVER_input</code> and <code>__CPROVER_output</code> will help clarify the inputs
144
+ and outputs of interest for generating test suites.
136
145
</p>
137
146
138
147
<p class="justified">
139
148
To demonstrate the automatic test suite generation in CBMC,
140
- we call the following command
149
+ we call the following command and we are going to explain the command line options one by one.
141
150
</p>
142
151
143
152
<pre><code>cbmc pid.c --cover mcdc --unwind 6 --trace --xml-ui
@@ -172,16 +181,37 @@ goals at the same time. Each trace corresponds to a test case.
172
181
</p>
173
182
174
183
<p class="justified">
175
- For the example above , the following test suites are generated.
184
+ In the end , the following test suites are automatically generated for testing the PID controller .
176
185
A test suite consists of a sequence of input parameters that are
177
186
passed to the PID function <code>climb_pid_run</code> at each loop iteration.
187
+ For example, Test 1 covers the MC/DC goal with id="climb_pid_run.coverage.1".
178
188
<pre><code>Test suite:
179
- T1: (desired_climb=-1.000000f, estimator_z_dot=-1.000000f)
180
- <em>goal id: climb_pid_run.coverage.1</em>
181
- T2: (desired_climb=-1.000000f, estimator_z_dot=-1.000000f); (desired_climb=1.000000f, estimator_z_dot=1.000000f)
182
- <em>goal id: climb_pid_run.coverage.2</em>
183
- T3: (desired_climb=0.000000f, estimator_z_dot=1.000000f)
184
- <em>goal id: climb_pid_run.coverage.3</em>
189
+ Test 1.
190
+ (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
191
+
192
+ Test 2.
193
+ (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
194
+ (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
195
+
196
+ Test 3.
197
+ (iteration 1) desired_climb=0.000000f, estimator_z_dot=-1.000000f
198
+ (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
199
+
200
+ Test 4.
201
+ (iteration 1) desired_climb=1.000000f, estimator_z_dot=-1.000000f
202
+ (iteration 2) desired_climb=1.000000f, estimator_z_dot=-1.000000f
203
+ (iteration 3) desired_climb=1.000000f, estimator_z_dot=-1.000000f
204
+ (iteration 4) desired_climb=1.000000f, estimator_z_dot=-1.000000f
205
+ (iteration 5) desired_climb=0.000000f, estimator_z_dot=-1.000000f
206
+ (iteration 6) desired_climb=1.000000f, estimator_z_dot=-1.000000f
207
+
208
+ Test 5.
209
+ (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
210
+ (iteration 2) desired_climb=-1.000000f, estimator_z_dot=1.000000f
211
+ (iteration 3) desired_climb=-1.000000f, estimator_z_dot=1.000000f
212
+ (iteration 4) desired_climb=-1.000000f, estimator_z_dot=1.000000f
213
+ (iteration 5) desired_climb=-1.000000f, estimator_z_dot=1.000000f
214
+ (iteration 6) desired_climb=-1.000000f, estimator_z_dot=1.000000f
185
215
</code></pre>
186
216
</p>
187
217
@@ -191,14 +221,7 @@ function body six times. In order to achieve the complete coverage on all the in
191
221
in the PID function <code>climb_pid_run</code>, the loop must be unwound sufficient enough times.
192
222
For example, <code>climb_pid_run</code> needs to be called at least six times for evaluating the
193
223
condition <code>climb_sum_err>MAX_CLIMB_SUM_ERR</code> in line 48 to <em>true</em>.
194
- This corresponds to the test suite below.
195
- <pre><code>(desired_climb=-1.000000f, estimator_z_dot=1.000000f);
196
- (desired_climb=-1.000000f, estimator_z_dot=0.000000f);
197
- (desired_climb=-1.000000f, estimator_z_dot=1.000000f);
198
- (desired_climb=-1.000000f, estimator_z_dot=1.000000f);
199
- (desired_climb=-1.000000f, estimator_z_dot=1.000000f);
200
- (desired_climb=-1.000000f, estimator_z_dot=1.000000f).
201
- </code></pre>
224
+ This corresponds to the Test 5.
202
225
An introduction to the use of loop unwinding can be found
203
226
in <a href="cbmc-loops.shtml">Understanding Loop Unwinding</a>.
204
227
</p>
0 commit comments