Revision 1b3adcdd devices/DiWheelDrive/userthread.cpp
devices/DiWheelDrive/userthread.cpp | ||
---|---|---|
42 | 42 |
// BLACK is the line itselfe |
43 | 43 |
// GREY is the boarder between the line and the surface |
44 | 44 |
// WHITE is the common surface |
45 |
enum colorMember : uint8_t { |
|
46 |
BLACK=0, |
|
47 |
GREY=1, |
|
48 |
WHITE=2 |
|
49 |
}; |
|
45 |
// enum colorMember : uint8_t {
|
|
46 |
// BLACK=0,
|
|
47 |
// GREY=1,
|
|
48 |
// WHITE=2
|
|
49 |
// };
|
|
50 | 50 |
|
51 | 51 |
// a buffer for the z-value of the accelerometer |
52 | 52 |
int16_t accel_z; |
... | ... | |
57 | 57 |
int policyCounter = 0; // Do not change this, it points to the beginning of the policy |
58 | 58 |
|
59 | 59 |
// Different speed settings (all values in "rounds per minute") |
60 |
const int rpmTurnLeft[2] = {-10, 10}; |
|
61 |
const int rpmTurnRight[2] = {rpmTurnLeft[1],rpmTurnLeft[0]}; |
|
62 |
const int rpmHalt[2] = {0, 0}; |
|
60 |
// const int rpmTurnLeft[2] = {-10, 10};
|
|
61 |
// const int rpmTurnRight[2] = {rpmTurnLeft[1],rpmTurnLeft[0]};
|
|
62 |
// const int rpmHalt[2] = {0, 0};
|
|
63 | 63 |
|
64 | 64 |
// Definition of the fuzzyfication function |
65 | 65 |
// | Membership |
... | ... | |
71 | 71 |
// All values are "raw sensor values" |
72 | 72 |
/* Use these values for white ground surface (e.g. paper) */ |
73 | 73 |
|
74 |
const int blackStartFalling = 0x1000; // Where the black curve starts falling |
|
75 |
const int blackOff = 0x1800; // Where no more black is detected |
|
76 |
const int whiteStartRising = 0x2800; // Where the white curve starts rising |
|
77 |
const int whiteOn = 0x6000; // Where the white curve has reached the maximum value |
|
78 |
const int greyMax = (whiteOn + blackStartFalling) / 2; // Where grey has its maximum |
|
79 |
const int greyStartRising = blackStartFalling; // Where grey starts rising |
|
80 |
const int greyOff = whiteOn; // Where grey is completely off again |
|
74 |
// const int blackStartFalling = 0x1000; // Where the black curve starts falling
|
|
75 |
// const int blackOff = 0x1800; // Where no more black is detected
|
|
76 |
// const int whiteStartRising = 0x2800; // Where the white curve starts rising
|
|
77 |
// const int whiteOn = 0x6000; // Where the white curve has reached the maximum value
|
|
78 |
// const int greyMax = (whiteOn + blackStartFalling) / 2; // Where grey has its maximum
|
|
79 |
// const int greyStartRising = blackStartFalling; // Where grey starts rising
|
|
80 |
// const int greyOff = whiteOn; // Where grey is completely off again
|
|
81 | 81 |
|
82 | 82 |
/* Use these values for gray ground surfaces */ |
83 | 83 |
/* |
... | ... | |
111 | 111 |
// chprintf((BaseSequentialStream*) &SD1, "Speed left: %d, Speed right: %d\r\n", target[0], target[1]); |
112 | 112 |
} |
113 | 113 |
|
114 |
// Fuzzyfication of the sensor values |
|
115 |
void fuzzyfication(int sensorValue, float (&fuzziedValue)[3]) { |
|
116 |
if (sensorValue < blackStartFalling ) { |
|
117 |
// Only black value |
|
118 |
fuzziedValue[BLACK] = 1.0f; |
|
119 |
fuzziedValue[GREY] = 0.0f; |
|
120 |
fuzziedValue[WHITE] = 0.0f; |
|
121 |
} else if (sensorValue > whiteOn ) { |
|
122 |
// Only white value |
|
123 |
fuzziedValue[BLACK] = 0.0f; |
|
124 |
fuzziedValue[GREY] = 0.0f; |
|
125 |
fuzziedValue[WHITE] = 1.0f; |
|
126 |
} else if ( sensorValue < greyMax) { |
|
127 |
// Some greyisch value between black and grey |
|
128 |
|
|
129 |
// Black is going down |
|
130 |
if ( sensorValue > blackOff) { |
|
131 |
fuzziedValue[BLACK] = 0.0f; |
|
132 |
} else { |
|
133 |
fuzziedValue[BLACK] = static_cast<float>(sensorValue-blackOff) / (blackStartFalling-blackOff); |
|
134 |
} |
|
135 |
|
|
136 |
// Grey is going up |
|
137 |
if ( sensorValue < greyStartRising) { |
|
138 |
fuzziedValue[GREY] = 0.0f; |
|
139 |
} else { |
|
140 |
fuzziedValue[GREY] = static_cast<float>(sensorValue-greyStartRising) / (greyMax-greyStartRising); |
|
141 |
} |
|
142 |
|
|
143 |
// White is absent |
|
144 |
fuzziedValue[WHITE] = 0.0f; |
|
145 |
|
|
146 |
} else if ( sensorValue >= greyMax) { |
|
147 |
// Some greyisch value between grey white |
|
148 |
|
|
149 |
// Black is absent |
|
150 |
fuzziedValue[BLACK] = 0.0f; |
|
151 |
|
|
152 |
// Grey is going down |
|
153 |
if ( sensorValue < greyOff) { |
|
154 |
fuzziedValue[GREY] = static_cast<float>(sensorValue-greyOff) / (greyMax-greyOff); |
|
155 |
} else { |
|
156 |
fuzziedValue[GREY] = 0.0f; |
|
157 |
} |
|
158 |
|
|
159 |
// White is going up |
|
160 |
if ( sensorValue < whiteStartRising) { |
|
161 |
fuzziedValue[WHITE] = 0.0f; |
|
162 |
} else { |
|
163 |
fuzziedValue[WHITE] = static_cast<float>(sensorValue-whiteStartRising) / (whiteOn-whiteStartRising); |
|
164 |
} |
|
165 |
} |
|
166 |
} |
|
167 |
|
|
168 |
// Return the color, which has the highest fuzzy value |
|
169 |
colorMember getMember(float (&fuzzyValue)[3]) { |
|
170 |
colorMember member; |
|
171 |
|
|
172 |
if (fuzzyValue[BLACK] > fuzzyValue[GREY]) |
|
173 |
if (fuzzyValue[BLACK] > fuzzyValue[WHITE]) |
|
174 |
member = BLACK; |
|
175 |
else |
|
176 |
member = WHITE; |
|
177 |
else |
|
178 |
if (fuzzyValue[GREY] > fuzzyValue[WHITE]) |
|
179 |
member = GREY; |
|
180 |
else |
|
181 |
member = WHITE; |
|
182 |
|
|
183 |
return member; |
|
184 |
} |
|
185 |
|
|
186 |
// Get a crisp output for the steering commands |
|
187 |
void defuzzyfication(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]) { |
|
188 |
|
|
189 |
// all sensors are equal |
|
190 |
if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_LEFT] && |
|
191 |
member[constants::DiWheelDrive::PROX_FRONT_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_RIGHT] && |
|
192 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == member[constants::DiWheelDrive::PROX_WHEEL_RIGHT]) { |
|
193 |
// something is wrong -> stop |
|
194 |
copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
195 |
// both front sensor detect a line |
|
196 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK && |
|
197 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK) { |
|
198 |
// straight |
|
199 |
copyRpmSpeed(global.rpmForward, rpmFuzzyCtrl); |
|
200 |
// exact one front sensor detects a line |
|
201 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK || |
|
202 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK) { |
|
203 |
// soft correction |
|
204 |
if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY) { |
|
205 |
// soft right |
|
206 |
copyRpmSpeed(global.rpmSoftRight, rpmFuzzyCtrl); |
|
207 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == WHITE) { |
|
208 |
// hard right |
|
209 |
copyRpmSpeed(global.rpmHardRight, rpmFuzzyCtrl); |
|
210 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) { |
|
211 |
// soft left |
|
212 |
copyRpmSpeed(global.rpmSoftLeft, rpmFuzzyCtrl); |
|
213 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == WHITE) { |
|
214 |
// hard left |
|
215 |
copyRpmSpeed(global.rpmHardLeft, rpmFuzzyCtrl); |
|
216 |
} |
|
217 |
// both wheel sensors detect a line |
|
218 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK && |
|
219 |
member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) { |
|
220 |
// something is wrong -> stop |
|
221 |
copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
222 |
// exactly one wheel sensor detects a line |
|
223 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK || |
|
224 |
member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) { |
|
225 |
if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == BLACK) { |
|
226 |
// turn left |
|
227 |
copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl); |
|
228 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == BLACK) { |
|
229 |
// turn right |
|
230 |
copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl); |
|
231 |
} |
|
232 |
// both front sensors may detect a line |
|
233 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY && |
|
234 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) { |
|
235 |
if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY) { |
|
236 |
// turn left |
|
237 |
copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl); |
|
238 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) { |
|
239 |
// turn right |
|
240 |
copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl); |
|
241 |
} |
|
242 |
// exactly one front sensor may detect a line |
|
243 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY || |
|
244 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) { |
|
245 |
if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY) { |
|
246 |
// turn left |
|
247 |
copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl); |
|
248 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY) { |
|
249 |
// turn right |
|
250 |
copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl); |
|
251 |
} |
|
252 |
// both wheel sensors may detect a line |
|
253 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY && |
|
254 |
member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) { |
|
255 |
// something is wrong -> stop |
|
256 |
copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
257 |
// exactly one wheel sensor may detect a line |
|
258 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY || |
|
259 |
member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) { |
|
260 |
if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == GREY) { |
|
261 |
// turn left |
|
262 |
copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl); |
|
263 |
} else if (member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] == GREY) { |
|
264 |
// turn right |
|
265 |
copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl); |
|
266 |
} |
|
267 |
// no sensor detects anything |
|
268 |
} else { |
|
269 |
// line is lost -> stop |
|
270 |
copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
271 |
} |
|
272 |
|
|
273 |
return; |
|
274 |
} |
|
275 |
|
|
276 |
Color memberToLed(colorMember member) { |
|
277 |
switch (member) { |
|
278 |
case BLACK: |
|
279 |
return Color(Color::GREEN); |
|
280 |
case GREY: |
|
281 |
return Color(Color::YELLOW); |
|
282 |
case WHITE: |
|
283 |
return Color(Color::RED); |
|
284 |
default: |
|
285 |
return Color(Color::WHITE); |
|
286 |
} |
|
287 |
} |
|
288 |
|
|
289 |
//void lineFollowing_new(xyz) {} |
|
290 |
|
|
291 |
void defuzz(colorMember (&member)[4], int (&rpmFuzzyCtrl)[2]){ |
|
292 |
// all sensors are equal |
|
293 |
// if (member[constants::DiWheelDrive::PROX_WHEEL_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_LEFT] && |
|
294 |
// member[constants::DiWheelDrive::PROX_FRONT_LEFT] == member[constants::DiWheelDrive::PROX_FRONT_RIGHT] && |
|
295 |
// member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == member[constants::DiWheelDrive::PROX_WHEEL_RIGHT]) { |
|
296 |
// // something is wrong -> stop |
|
297 |
// copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
298 |
// // both front sensor detect a line |
|
299 |
if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK && |
|
300 |
(member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == GREY)) { |
|
301 |
// straight |
|
302 |
copyRpmSpeed(global.rpmForward, rpmFuzzyCtrl); |
|
303 |
// Deviation to right |
|
304 |
} else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK |
|
305 |
&& member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == WHITE){ |
|
306 |
copyRpmSpeed(global.rpmSoftLeft, rpmFuzzyCtrl); |
|
307 |
// Deviation to left |
|
308 |
}else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == BLACK |
|
309 |
&& member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK){ |
|
310 |
copyRpmSpeed(global.rpmSoftRight, rpmFuzzyCtrl); |
|
311 |
// Hard deviatio to right |
|
312 |
}else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY |
|
313 |
&& member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == WHITE){ |
|
314 |
copyRpmSpeed(rpmTurnLeft, rpmFuzzyCtrl); |
|
315 |
// Hard deviation to left |
|
316 |
}else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == GREY |
|
317 |
&& member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == BLACK){ |
|
318 |
copyRpmSpeed(rpmTurnRight, rpmFuzzyCtrl); |
|
319 |
// stop if white |
|
320 |
}else if (member[constants::DiWheelDrive::PROX_FRONT_LEFT] == WHITE |
|
321 |
&& member[constants::DiWheelDrive::PROX_FRONT_RIGHT] == WHITE ){ |
|
322 |
copyRpmSpeed(rpmHalt, rpmFuzzyCtrl); |
|
323 |
} |
|
324 |
} |
|
325 |
|
|
326 |
// Line following by a fuzzy controler |
|
327 |
void lineFollowing(int (&proximity)[4], int (&rpmFuzzyCtrl)[2]) { |
|
328 |
// FUZZYFICATION |
|
329 |
// First we need to get the fuzzy value for our 3 values {BLACK, GREY, WHITE} |
|
330 |
float leftWheelFuzzyMemberValues[3], leftFrontFuzzyMemberValues[3], rightFrontFuzzyMemberValues[3], rightWheelFuzzyMemberValues[3]; |
|
331 |
fuzzyfication(proximity[constants::DiWheelDrive::PROX_WHEEL_LEFT], leftWheelFuzzyMemberValues); |
|
332 |
fuzzyfication(proximity[constants::DiWheelDrive::PROX_FRONT_LEFT], leftFrontFuzzyMemberValues); |
|
333 |
fuzzyfication(proximity[constants::DiWheelDrive::PROX_FRONT_RIGHT], rightFrontFuzzyMemberValues); |
|
334 |
fuzzyfication(proximity[constants::DiWheelDrive::PROX_WHEEL_RIGHT], rightWheelFuzzyMemberValues); |
|
335 |
|
|
336 |
// INFERENCE RULE DEFINITION |
|
337 |
// Get the member for each sensor |
|
338 |
colorMember member[4]; |
|
339 |
member[constants::DiWheelDrive::PROX_WHEEL_LEFT] = getMember(leftWheelFuzzyMemberValues); |
|
340 |
member[constants::DiWheelDrive::PROX_FRONT_LEFT] = getMember(leftFrontFuzzyMemberValues); |
|
341 |
member[constants::DiWheelDrive::PROX_FRONT_RIGHT] = getMember(rightFrontFuzzyMemberValues); |
|
342 |
member[constants::DiWheelDrive::PROX_WHEEL_RIGHT] = getMember(rightWheelFuzzyMemberValues); |
|
343 |
|
|
344 |
// visualize sensors via LEDs |
|
345 |
global.robot.setLightColor(constants::LightRing::LED_WNW, memberToLed(member[constants::DiWheelDrive::PROX_WHEEL_LEFT])); |
|
346 |
global.robot.setLightColor(constants::LightRing::LED_NNW, memberToLed(member[constants::DiWheelDrive::PROX_FRONT_LEFT])); |
|
347 |
global.robot.setLightColor(constants::LightRing::LED_NNE, memberToLed(member[constants::DiWheelDrive::PROX_FRONT_RIGHT])); |
|
348 |
global.robot.setLightColor(constants::LightRing::LED_ENE, memberToLed(member[constants::DiWheelDrive::PROX_WHEEL_RIGHT])); |
|
349 |
|
|
350 |
// chprintf((BaseSequentialStream*) &SD1, "Left: BLACK: %f, GREY: %f, WHITE: %f\r\n", leftWheelFuzzyMemberValues[BLACK], leftWheelFuzzyMemberValues[GREY], leftWheelFuzzyMemberValues[WHITE]); |
|
351 |
// chprintf((BaseSequentialStream*) &SD1, "Right: BLACK: %f, GREY: %f, WHITE: %f\r\n", rightFuzzyMemberValues[BLACK], rightFuzzyMemberValues[GREY], rightFuzzyMemberValues[WHITE]); |
|
352 |
|
|
353 |
// DEFUZZYFICATION |
|
354 |
// defuzzyfication(member, rpmFuzzyCtrl); |
|
355 |
defuzz(member, rpmFuzzyCtrl); |
|
356 |
} |
|
357 |
|
|
358 |
|
|
359 |
|
|
360 | 114 |
|
361 | 115 |
// Set the speed by the array |
362 | 116 |
void setRpmSpeed(const int (&rpmSpeed)[2]) { |
... | ... | |
452 | 206 |
vcnl4020AmbientLight[i] = global.vcnl4020[i].getAmbientLight(); |
453 | 207 |
vcnl4020Proximity[i] = global.vcnl4020[i].getProximityScaledWoOffset(); |
454 | 208 |
} |
455 |
lf.stableFollow(vcnl4020Proximity, rpmFuzzyCtrl, &global); |
|
209 |
// lf.stableFollow(vcnl4020Proximity, rpmFuzzyCtrl, &global);
|
|
456 | 210 |
// chprintf((BaseSequentialStream*) &SD1, "0x%04X 0x%04X 0x%04X 0x%04X\n", |
457 | 211 |
// vcnl4020Proximity[constants::DiWheelDrive::PROX_WHEEL_LEFT], |
458 | 212 |
// vcnl4020Proximity[constants::DiWheelDrive::PROX_FRONT_LEFT], |
Also available in: Unified diff