|
| 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