Skip to content

Commit 8349c5e

Browse files
committed
Add the code for the second part of the first assignment/to do: loop invariants and variants
1 parent c542df9 commit 8349c5e

File tree

1 file changed

+382
-0
lines changed

1 file changed

+382
-0
lines changed

Diff for: tabs_loop.c

+382
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
//Array index mnemonics for negative big, medium, and small, zero, and positive small, medium and big.
2+
#define NB 0
3+
#define NM 1
4+
#define NS 2
5+
#define ZE 3
6+
#define PS 4
7+
#define PM 5
8+
#define PB 6
9+
10+
/*
11+
* Optimum wheel slip under braking: S_ref = 0.15. Multiplied by 1000.
12+
*/
13+
#define S_ref 150
14+
15+
/*
16+
* The control signal to hydraulic modulator is calculated periodically once
17+
* every 20 ms. Multiplied by 1000.
18+
*/
19+
#define delta_t 20
20+
21+
/*
22+
* The radius of the wheels is 0.25 m. Multiplied by 1000.
23+
*/
24+
#define R 250
25+
26+
/*
27+
* The table u used to compute the control signal. First index is for error
28+
* (variable e in the function compute_control_signal) and second index for
29+
* error prime (variable ep in the function compute_control_signal). Each
30+
* entry has been multiplied by 1000 and rounded to nearest integer.
31+
*/
32+
// NB NM NS ZE PS PM PB
33+
const int u[7][7] = /*NB*/ {{1000, 1000, 1000, 1000, 667, 333, 0},
34+
/*NM*/ {1000, 1000, 1000, 667, 667, 0, -333},
35+
/*NS*/ {1000, 667, 667, 333, 0, -333, -667},
36+
/*ZE*/ {1000, 667, 333, 0, -333, -667, -1000},
37+
/*PS*/ {667, 333, 0, -333, -667, -667, -1000},
38+
/*PM*/ {333, 0, -667, -667, -1000, -1000, -1000},
39+
/*PB*/ {0, -333, -667, -1000, -1000, -1000, -1000}};
40+
41+
/*
42+
* Dummy variable representing the wheel velocity sensor in radians/s.
43+
*/
44+
int wt_sensor;
45+
46+
/*
47+
* Dummy variable representing the vehicle acceleration sensor in m/s².
48+
*/
49+
int at_sensor;
50+
51+
/*
52+
* Dummy variable representing the sensor of whether the brake pedal is pushed
53+
* or not. Nonzero value is true and zero is false.
54+
*/
55+
int bp_sensor;
56+
57+
/*
58+
* Stores the wheel slip value computed from the last computation of the
59+
* control signal. That is, the last computed wheel slip value.
60+
*/
61+
int S_previous;
62+
63+
/*
64+
* Stores the velocity of the vehicle just before braking. Written each time
65+
* the top-level function hydraulic_modulator_driver is invoked and the brake
66+
* pedal is not pushed. Used to compute the current velocity of the vehicle
67+
* during braking.
68+
*/
69+
int velocity_before_braking;
70+
71+
/*
72+
* Stores the sum of the acceleration samples of the vehicle read during
73+
* braking. Written by hydraulic_modulator_driver. If the brake pedal is not
74+
* pushed, then acceleration_sum is set to the current acceleration of the
75+
* vehicle. If the brake pedal is pushed, then acceleration_sum is added with
76+
* the current acceleration of the vehicle. Hence, acceleration_sum = Σa_i.
77+
* acceleration_sum is used to compute the current velocity of the vehicle.
78+
*/
79+
int acceleration_sum;
80+
81+
/*
82+
* Dummy variable representing the hydraulic modulator. This variable holds
83+
* the value currently being sent to the hydraulic modulator.
84+
*/
85+
int signal_to_hydraulic_modulator;
86+
87+
/******************************************************************************
88+
* The Membership functions µₘ*************************************************
89+
******************************************************************************/
90+
91+
/*
92+
*µNB(x) ≔ 1 if x ≤ -1
93+
*µNB(x) ≔ -2x - 1 if -1 < x < -0.5
94+
*µNB(x) ≔ 0 if -0.5 ≤ x
95+
*/
96+
int mNB(int x) {
97+
if (x <= -1000)
98+
return 1000;
99+
else if (-1000 < x && x <-500)
100+
return -2*x - 1000;
101+
else
102+
return 0;
103+
}
104+
105+
/*
106+
*µNM(x) ≔ 0 if x ≤ -1
107+
*µNM(x) ≔ 2x + 2 if -1 < x ≤ -0.5
108+
*µNM(x) ≔ -4x - 1 if -0.5 < x < -0.25
109+
*µNM(x) ≔ 0 if -0.25 ≤ x
110+
*/
111+
int mNM(int x) {
112+
if (x <= -1000)
113+
return 0;
114+
else if (-1000 < x && x <= -500)
115+
return 2*x + 2000;
116+
else if (-500 < x && x < -250)
117+
return -4*x - 1000;
118+
else
119+
return 0;
120+
}
121+
122+
/*
123+
*µNS(x) ≔ 0 if x ≤ -0.5
124+
*µNS(x) ≔ 4x + 2 if -0.5 < x ≤ -0.25
125+
*µNS(x) ≔ -4x if -0.25 < x < 0
126+
*µNS(x) ≔ 0 if 0 ≤ x
127+
*/
128+
int mNS(int x) {
129+
if (x <= -500)
130+
return 0;
131+
else if (-500 < x && x <= -250)
132+
return 4*x + 2000;
133+
else if (-250 < x && x < 0)
134+
return -4*x;
135+
else
136+
return 0;
137+
}
138+
139+
/*
140+
*µZE(x) ≔ 0 if x ≤ -0.25
141+
*µZE(x) ≔ 4x + 1 if -0.25 < x ≤ 0
142+
*µZE(x) ≔ -4x + 1 if 0 < x < 0.25
143+
*µZE(x) ≔ 0 if 0.25 ≤ x
144+
*/
145+
int mZE(int x) {
146+
if (x <= -250)
147+
return 0;
148+
else if (-250 < x && x <= 0)
149+
return 4*x + 1000;
150+
else if (0 < x && x < 250)
151+
return -4*x + 1000;
152+
else
153+
return 0;
154+
}
155+
156+
/*
157+
*µPS(x) ≔ 0 if x ≤ 0
158+
*µPS(x) ≔ 4x if 0 < x ≤ 0.25
159+
*µPS(x) ≔ -4x + 2 if 0.25 < x < 0.5
160+
*µPS(x) ≔ 0 if 0.5 ≤ x
161+
*/
162+
int mPS(int x) {
163+
if (x <= 0)
164+
return 0;
165+
else if (0 < x && x <= 250)
166+
return 4*x;
167+
else if (250 < x && x < 500)
168+
return -4*x + 2000;
169+
else
170+
return 0;
171+
}
172+
173+
/*
174+
*µPM(x) ≔ 0 if x ≤ 0.25
175+
*µPM(x) ≔ 4x - 1 if 0.25 < x ≤ 0.5
176+
*µPM(x) ≔ -2x + 2 if 0.5 < x < 1
177+
*µPM(x) ≔ 0 if 1 ≤ x
178+
*/
179+
int mPM(int x) {
180+
if (x <= 250)
181+
return 0;
182+
else if (250 < x && x <= 500)
183+
return 4*x - 1000;
184+
else if (500 < x && x < 1000)
185+
return -2*x + 2000;
186+
else
187+
return 0;
188+
}
189+
190+
/*
191+
*µPB(x) ≔ 0 if x ≤ 0.5
192+
*µPB(x) ≔ 2x - 1 if 0.5 < x < 1
193+
*µPB(x) ≔ 1 if 1 ≤ x
194+
*/
195+
int mPB(int x) {
196+
if (x <= 500)
197+
return 0;
198+
else if (500 < x && x < 1000)
199+
return 2*x - 1000;
200+
else
201+
return 1000;
202+
}
203+
204+
/*
205+
* Computes the membership degree.
206+
* index ∈ {NB, NM, NS, ZE, PS, PM, PB}.
207+
* x is e or ep.
208+
*/
209+
int md(int index, int x) {
210+
if (index == NB)
211+
return mNB(x);
212+
else if (index == NM)
213+
return mNM(x);
214+
else if (index == NS)
215+
return mNS(x);
216+
else if (index == ZE)
217+
return mZE(x);
218+
else if (index == PS)
219+
return mPS(x);
220+
else if (index == PM)
221+
return mPM(x);
222+
else
223+
return mPB(x);
224+
}
225+
226+
/******************************************************************************
227+
* End of Membership functions ************************************************
228+
******************************************************************************/
229+
230+
231+
232+
/******************************************************************************
233+
* Dummy functions used to perform input/output *******************************
234+
******************************************************************************/
235+
236+
/*
237+
* Returns the current angular wheel velocity.
238+
*/
239+
int read_wheel_angular_velocity(void) {
240+
return wt_sensor;
241+
}
242+
243+
/*
244+
* Returns the current acceleration of the vehicle.
245+
*/
246+
int read_acceleration_of_vehicle(void) {
247+
return at_sensor;
248+
}
249+
250+
/*
251+
* Returns non-zero if the brake pedal is pushed, and zero if the brake pedal
252+
* is not pushed.
253+
*/
254+
int read_brake_pedal(void) {
255+
return bp_sensor;
256+
}
257+
258+
/*
259+
* Writes uc to the hydraulic modulator.
260+
*/
261+
void write_control_signal_to_hydraulic_modulator(int uc) {
262+
signal_to_hydraulic_modulator = uc;
263+
}
264+
265+
/******************************************************************************
266+
* End of dummy functions used to perform input/output ************************
267+
******************************************************************************/
268+
269+
270+
/*
271+
* Output: Velocity of vehicle = Σa*dt + v0 = v0 + dt⋅Σa.
272+
* First term is divided by 1000 to keep the quantities in terms of 1000,
273+
* since both acceleration_sum and delta_t are already multiplied by 1000.
274+
*/
275+
int compute_velocity_of_vehicle(void) {
276+
return acceleration_sum*delta_t/1000 + velocity_before_braking;
277+
}
278+
279+
/*
280+
* v: Vehicle velocity m/s.
281+
* wt: Angular wheel velocity radians/s.
282+
*
283+
* Output: New wheel slip S.
284+
*/
285+
int compute_wheel_slip(int v, int wt) {
286+
return (v - wt*R/1000)/v;
287+
}
288+
289+
/*
290+
* Computes the control signal to the hydraulic modulator.
291+
*/
292+
int compute_control_signal(void) {
293+
int wt = read_wheel_angular_velocity();
294+
295+
int v = compute_velocity_of_vehicle();
296+
297+
int S = compute_wheel_slip(v, wt);
298+
299+
int e = S - S_ref; //error.
300+
301+
int ep = (S - S_previous)/delta_t; //error prime.
302+
303+
S_previous = S; //Updates old value of wheel slip.
304+
305+
//Computes the control signal for each of the error and error derivative combinations.
306+
//The code below this for loop is equivalent to this for loop, hopefully. Except for scaling.
307+
// for (error_index = 0; error_index < 7; error_index = error_index + 1)
308+
// for (error_prime_index = 0; error_prime_index < 7; error_prime_index = error_prime_index + 1) {
309+
// int m = md(error_index, error)*md(error_prime_index, error_prime);
310+
// numerator += m*u_table[error_index][error_prime_index];
311+
// denominator += m;
312+
// }
313+
314+
int numerator = 0, denominator = 0;
315+
316+
int ep_sum = 0;
317+
318+
for (int i = 0; i < 7; i++) //i ∈ {NB, NM, NS, ZE, PS, PM, PB}
319+
ep_sum += md(i, ep);
320+
321+
//error is NB. Go through all of {NB, NM, NS, ZE, PS, PM, PB} for error prime.
322+
for (int ep_index = 0; ep_index < 7; ep_index++)
323+
numerator += md(NB, e)*md(ep_index, ep)*u[NB][ep_index]/1000;
324+
325+
//error is NM. Go through all of {NB, NM, NS, ZE, PS, PM, PB} for error prime.
326+
for (int ep_index = 0; ep_index < 7; ep_index++)
327+
numerator += md(NM, e)*md(ep_index, ep)*u[NM][ep_index]/1000;
328+
329+
//error is NS. Go through all of {NB, NM, NS, ZE, PS, PM, PB} for error prime.
330+
for (int ep_index = 0; ep_index < 7; ep_index++)
331+
numerator += md(NS, e)*md(ep_index, ep)*u[NS][ep_index]/1000;
332+
333+
//error ∈ {ZE, PS, PM, PB}.
334+
for (int e_index = 3; e_index < 7; e_index++)
335+
for (int ep_index = 0; ep_index < 7; ep_index++) //ep_index ∈ {NB, NM, NS, ZE, PS, PM, PB}
336+
numerator += md(e_index, e)*md(ep_index, ep)*u[e_index][ep_index]/1000;
337+
338+
for (int i = 0; i < 7; i++) //i ∈ {NB, NM, NS, ZE, PS, PM, PB}
339+
denominator += md(i, e)*ep_sum/1000;
340+
341+
//Returns uc.
342+
return numerator/denominator;
343+
}
344+
345+
/*
346+
* It is assumed that the interrupt service routine calls this main function
347+
* each time a timer interrupt occurs (once every 0.02 seconds).
348+
*/
349+
void hydraulic_modulator_driver(void) {
350+
//The brake pedal is not pushed.
351+
if (read_brake_pedal() == 0) {
352+
//Reads the current angular velocity of the wheel to compute the
353+
//current velocity of vehicle.
354+
int wt = read_wheel_angular_velocity();
355+
velocity_before_braking = wt*R;
356+
//Stores the current acceleration of the vehicle. The first time
357+
//hydraulic_modulator_driver is invoked when the brake pedal is pushed,
358+
//acceleration_sum is equal to the acceleration of the vehicle just
359+
//before braking. This means that the integration of the acceleration
360+
//over time is done over the time interval that starts when braking
361+
//starts.
362+
acceleration_sum = read_acceleration_of_vehicle();
363+
//No wheel slip since the brakes are not applied and therefore the
364+
//wheels are rolling freely.
365+
S_previous = 0;
366+
//Instructs the hydraulic modulator to not cause any brake pressure.
367+
write_control_signal_to_hydraulic_modulator(-1000);
368+
} else {
369+
//The brake pedal is pushed.
370+
//Adds the current acceleration of the vehicle.
371+
acceleration_sum += read_acceleration_of_vehicle();
372+
//Computes the control signal.
373+
int uc = compute_control_signal();
374+
//Sends the control signal to the hydraulic modulator.
375+
write_control_signal_to_hydraulic_modulator(uc);
376+
}
377+
}
378+
379+
//Dummy function. GCC requires a main function.
380+
int main(void) {
381+
return 0;
382+
}

0 commit comments

Comments
 (0)