Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / linefollowing / lineFollow.c @ 1942

History | View | Annotate | Download (7.91 KB)

1
/**
2
 * @file lineFollow.c
3
 * @defgroup lineFollwing Line Following
4
 *
5
 * Takes care of following a line. Running this program is done by calling the
6
 * init() function and then the lineFollow(speed) command.  However, direct use
7
 * of this class is discouraged as its behavior is used by lineDrive.c, which
8
 * extends this class to provide behavior functionality.
9
 *
10
 * @author Dan Jacobs and the Colony Project
11
 * @date 11-1-2010
12
 */
13

    
14
#include "lineFollow.h"
15

    
16
//! The number of bits expected in a barcode
17
#define CODESIZE 5 
18

    
19
int countHi = 0;
20
int countLo = 0;
21
int maxAvg, avg;
22
int barCode[ CODESIZE ];
23
int barCodePosition=0;
24

    
25
int duration = 0;
26
int lastColor = 0;
27
char isReset = 0;
28

    
29
int turnDistance=0;
30
//! Counts the number of full line readings before we determine an intersection
31
int intersectionFilter=0;
32
int disableBarCode=0;
33

    
34
//! Keeps track of where the encoder of one motor started, for use in turns.
35
int encoderStart = -1;
36
int encoderReset = 0;   // 0 if encoderStart has no value set
37

    
38

    
39
void lineFollow_init()
40
{
41
        analog_init(0);
42
        lost = 0;
43
        intersectionFilter=0;
44
        disableBarCode=0;
45
}
46

    
47

    
48
/** 
49
 * Follows a line at the given speed.
50
 * @param speed The speed with which to follow the line.
51
 */
52
int lineFollow(int speed)
53
{
54
        int colors[5];
55
        int position;
56
        
57

    
58
        updateLine(colors);
59
        position = lineLocate(colors);         
60
        
61
        //not on line
62
        if(position == NOLINE)
63
        {
64
                if(lost++ > 20)
65
                {
66
                        orb2_set_color(GREEN);
67
                        motors_off();
68
                        return LINELOST;
69
                }
70
        }
71
        else if(position == FULL_LINE)
72
        {
73
                if(intersectionFilter++ > 4)
74
                {
75
                        orb2_set_color(RED);
76
                        barCodePosition=0;
77
                        disableBarCode=50;
78
                }
79
        }
80
        //on line
81
        else
82
        {
83
                position*=30;
84
                orb2_set_color(ORB_OFF);
85
                motorLeft(min(speed+position, 255));
86
                motorRight(min(speed-position, 255));
87
                lost=0;
88
                intersectionFilter=0;
89
        }
90

    
91
    // If we're running over a line, stop reading barcodes for a sec
92
        if(disableBarCode-- > 0)
93
        {
94
        // Return intersection once we cross the line
95
                if(disableBarCode) return NOBARCODE;
96
                return INTERSECTION;
97
        }
98
        updateBarCode();
99
        return getBarCode();
100
}
101

    
102

    
103
/**
104
 * Implements the left merge, assuming a line exists to the left.  Works by
105
 * turning off the line at an increasing angle and waiting to hit another line
106
 * on the left.
107
 */
108
int mergeLeft()
109
{
110
        motor_l_set(FORWARD, 200);
111
        if(turnDistance!=21)motor_r_set(FORWARD, 230);
112
        else motor_r_set(FORWARD, 210);
113
        int colors[5];
114
        updateLine(colors);
115
        int position = lineLocate(colors);
116
        if(position>3 || position<-3)turnDistance++;
117

    
118
        if(turnDistance>20)
119
        {
120
        turnDistance=21;
121
        
122
                if(position<3 && position>-3)
123
                {
124
                        turnDistance = 0;
125
                        return 0;
126
                }        
127
        }
128
        return 1;
129
}
130

    
131

    
132
/**
133
 * Implements the right merge, assuming a line exists to the right.  Works by
134
 * turning off the line at an increasing angle and waiting to hit another line
135
 * on the right.
136
 */
137
int mergeRight()
138
{
139
        motor_r_set(FORWARD, 200);
140
        if(turnDistance!=21)motor_l_set(FORWARD, 230);
141
        else motor_l_set(FORWARD, 210);
142
        int colors[5];
143
        updateLine(colors);
144
        int position = lineLocate(colors);
145
        if(position>3 || position<-3)turnDistance++;
146

    
147
        if(turnDistance>20)
148
        {
149
        turnDistance=21;
150

    
151
                if(position<3 && position>-3)
152
                {
153
                        turnDistance = 0;
154
                        return 0;
155
                } 
156
        }
157
        return 1;
158
}
159

    
160

    
161

    
162
/**
163
 * Turns left at a cross of two lines.  Assumes that we are at lines in a cross
164
 * pattern, and turns until it sets straight on the new line.
165
 * @return 0 if turn finishes otherwise return 1
166
 */
167
int turnLeft()
168
{
169
        /*motor_l_set(BACKWARD, 200);
170
        motor_r_set(FORWARD, 200);
171
        int colors[5];
172
        updateLine(colors);
173
        int position = lineLocate(colors);
174
        if(position>2 || position<-2)turnDistance++;
175
        if(turnDistance>1)
176
        {
177
                if(position<3 && position>-3)
178
                {
179
                        turnDistance = 0;
180
                         return 0;
181
                }
182
        }
183
        return 1;*/
184

    
185
        motor_l_set(BACKWARD,200);
186
        motor_r_set(FORWARD,200);
187
        if(!encoderReset)
188
        {
189
            encoderStart = encoder_get_x(RIGHT);
190
            encoderReset = 1;
191
        }
192

    
193
        if(encoder_get_x(RIGHT) < encoderStart)
194
        {
195
            encoderStart = 0;
196
            // Temporary: display an "error message" in case of overflow.
197
            // Using this for debugging, take it out soon!
198
            motor_l_set(FORWARD,0);
199
            motor_r_set(FORWARD,0);
200
            orb_set_color(WHITE);
201
            delay_ms(2000);
202
        }
203

    
204
        if(encoder_get_x(RIGHT) - encoderStart > 300)
205
        {
206
            encoderReset = 0;
207
            return 0;
208
        }
209
        return 1;
210
}
211

    
212

    
213

    
214
/**
215
 * Turns right at a cross of two lines.  Assumes that we are at lines in a cross
216
 * pattern, and turns until it sets straight on the new line.
217
 * @return 0 if the turn finishes otherwise return 1
218
 */
219
int turnRight()
220
{
221
        motor_r_set(BACKWARD, 200);
222
        motor_l_set(FORWARD, 200);
223
        int colors[5];
224
        updateLine(colors);
225
        int position = lineLocate(colors);
226
        if(position>2 || position<-2)turnDistance++;
227
        if(turnDistance>1) 
228
        {
229
                if(position<3 && position>-3)
230
                {
231
                        turnDistance = 0;
232
                         return 0;
233
                }
234
        }
235
        return 1;
236
}
237

    
238

    
239

    
240
int getBarCode()
241
{
242
        if(barCodePosition != CODESIZE)
243
        return NOBARCODE ;
244
    else
245
    {
246
        int temp = 0;
247
        for(int i=0; i<CODESIZE; i++)
248
            temp += (barCode[i] << i);
249
        barCodePosition = 0;
250
        return temp;
251
    }
252
}
253

    
254

    
255

    
256
void updateLine(int* values)
257
{        
258
        for(int i = 0; i<5; i++)
259
                values[i] = (read_line(4-i) < 150 ? LWHITE : LBLACK);
260
}
261

    
262

    
263

    
264
int lineLocate(int* colors)
265
{
266
        int i;
267
        int wsum = 0;
268
        int count=0;
269

    
270
        for(i = 0; i<5; i++)
271
        {
272
                count += colors[i]/2;
273
                wsum += (i)*colors[i];
274
        }
275
        if(count==0)
276
                return NOLINE;        
277
        if(count==5)
278
                return FULL_LINE;
279
        return (wsum/count)-4; // Subtract 4 to center the index around the center.
280
}
281

    
282

    
283
// new version by Alex
284
/*void updateBarCode()
285
{
286
    // Average the readings of the last 2 sensors
287
    int curReading = (read_line(6) + read_line(7)) / 2;
288
    int curColor = (curReading > 500) ? LBLACK : LWHITE;
289

290
    // USING THESE GLOBAL VARIABLES
291
    // global int duration = 0;
292
    // global int lastColor = 0;
293
    // global int barCodePosition = 0;
294
    // global char isReset = 0;
295

296
    // Just an error check
297
    if(barCodePosition > CODESIZE)
298
    {
299
        barCodePosition = 0;
300
    }
301

302
    if(curColor == lastColor)
303
    {
304
        duration++;
305
    }
306
    else
307
    {
308
        duration = 0;
309
        lastColor = curColor;
310
    }
311

312
    if(duration > MAX_DURATION)
313
    {
314
        // Now we assume our reading is significant - a bit, or a white space
315

316
        // Only read a value if we have read 0 first (isReset == 1)
317
        if(isReset && (curColor == LBLACK || curColor == LGREY) )
318
        {
319
            isReset = 0;
320

321
            barCode[barCodePosition++] = (curColor == LBLACK) ? 1 : 0;
322
        }
323
        else if(curColor == LWHITE)
324
        {
325
            isReset = 1;
326
        }
327
    }
328
}*/
329

    
330

    
331
void updateBarCode()
332
{
333
        //! Note: currently only uses one of the barcode sensors.
334

    
335
        //maps the sensors to the analog input ports
336
        int ports[2] = {8,1};
337
        int current[2];
338
//        current[0] = analog_get10(ports[0]);
339
        //current[1] = analog_get10(ports[1]);
340
    current[1] = read_line(6);
341

    
342
        if(current[1] > 150)
343
        {
344
                if(countHi++ == 0) 
345
                {
346
                        avg = 500;
347
                        maxAvg = 500;
348
                }
349
                else
350
                {
351
                        avg = 3*avg + current[1];
352
                        avg/=4;
353
                        maxAvg = max(maxAvg, avg);
354
                }
355
        }
356
        else if(countHi > 5)
357
        {
358
                if(countLo++ > 15)
359
                {
360
                        countHi = countLo = 0;
361
                        if(maxAvg > 825)
362
                orb1_set_color(RED);
363
                        else orb1_set_color(BLUE);
364
                        barCode[barCodePosition++] = maxAvg > 825 ? 1:0;
365
                }
366
        }
367
        else countHi/=2;
368
        if(countHi==0)countLo=0; 
369
}
370

    
371

    
372
int min(int x, int y){return x>y ? y : x;}
373
int max(int x, int y){return x<y ? y : x;}
374

    
375
void motorLeft(int speed){
376
        ((speed-=127)>=0)?motor_l_set(FORWARD, 160+speed*95/128):motor_l_set(BACKWARD, 160-speed*95/127);
377
}
378

    
379
void motorRight(int speed){
380
        ((speed-=127)>=0)?motor_r_set(FORWARD, 160+speed*95/128):motor_r_set(BACKWARD, 160-speed*95/127);
381
}