Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / scout / libscout / src / behaviors / line_follow.cpp @ 60b98383

History | View | Annotate | Download (5.57 KB)

1
/**
2
 * @file line_follow.cpp
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 line_follow(speed) command.  However, direct use
7
 * of this class is discouraged as its behavior is used by lineDrive.cpp, 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 "line_follow.h"
15

    
16
//! Anything lower than this value is white
17
int GREY_THRESHOLD = 300;
18
//! Anything higher than this value is black
19
int BLACK_THRESHOLD = 750;
20

    
21
int countHi = 0;
22
int countLo = 0;
23
int maxAvg, avg;
24

    
25
int duration[2] = {0};
26
int lastColor[2] = {0};
27
char isReset[2] = {1};
28
int lastReadings[2][ NUM_READINGS ] = {{0}};
29
int lastReadingsPtr[2] = {0};
30
int numLast[2][4] = { {0, 0, 0, NUM_READINGS}, {0, 0, 0, NUM_READINGS} };
31
int bitColor[2] = {0};
32

    
33
int turnDistance=0;
34
//! Counts the number of full line readings before we determine an intersection
35
int intersectionFilter=0;
36

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

    
41
int min(int x, int y){return x>y ? y : x;}
42
int max(int x, int y){return x<y ? y : x;}
43

    
44

    
45
void line_follow::init()
46
{
47
  int i, j, curReading;
48
  int lowGrey = 1000, highGrey = 0, lowBlack = 1000,
49
      highBlack = 0;
50

    
51
  analog_init(0);
52
  encoders_init();
53
  lost = 0;
54
  intersectionFilter=0;
55

    
56
  for(i=0; i<2; i++)
57
  {
58
    for(j=0; j<NUM_READINGS; j++)
59
    {
60
      lastReadings[i][j] = BAD_READING;
61
    }
62
    isReset[i] = 1;
63
  }
64

    
65
  // Calibrate thresholds
66
  orb_set_color(YELLOW);
67
  delay_ms(2000);
68

    
69
  orb_set_color(BLUE);
70

    
71
  for(i=0; i<100; i++)
72
  {
73
    curReading = read_line(LEFT_SENSOR + 6);
74
    if(curReading < lowGrey)
75
      lowGrey = curReading;
76
    if(curReading > highGrey)
77
      highGrey = curReading;
78

    
79
    delay_ms(20);
80
  }
81

    
82
  orb_set_color(YELLOW);
83
  delay_ms(2000);
84

    
85
  orb_set_color(GREEN);
86

    
87
  for(i=0; i<100; i++)
88
  {
89
    curReading = read_line(LEFT_SENSOR + 6);
90
    if(curReading < lowBlack)
91
      lowBlack = curReading;
92
    if(curReading > highBlack)
93
      highBlack = curReading;
94

    
95
    delay_ms(20);
96
  }
97

    
98
  orbs_set(0,0,0,0,0,0);
99

    
100
  GREY_THRESHOLD = lowGrey / 2;
101
  BLACK_THRESHOLD = (highGrey + lowBlack) / 2;
102

    
103
  usb_puts("Grey: ");
104
  usb_puti(lowGrey);
105
  usb_puts(", ");
106
  usb_puti(highGrey);
107
  usb_puts("\nBlack: ");
108
  usb_puti(lowBlack);
109
  usb_puts(", ");
110
  usb_puti(highBlack);
111
  usb_puts("\nThresholds: ");
112
  usb_puti(GREY_THRESHOLD);
113
  usb_puts(", ");
114
  usb_puti(BLACK_THRESHOLD);
115
  usb_puts("\n\n");
116

    
117
  delay_ms(1500);
118
}
119

    
120

    
121
/** 
122
 * Follows a line at the given speed.
123
 * @param speed The speed with which to follow the line.
124
 */
125
int line_follow::follow_line(int speed)
126
{
127
        int colors[5];
128
        int position;
129
        
130

    
131
        updateLine(colors);
132
        position = lineLocate(colors);         
133
        
134
        //not on line
135
        if(position == NOLINE)
136
        {
137
                if(lost++ > 20)
138
                {
139
                        orb2_set_color(GREEN);
140
                        motors_off();
141
                        return LINELOST;
142
                }
143
        }
144
        else if(position == FULL_LINE)
145
        {
146
                if(intersectionFilter++ > 4)
147
                {
148
                        orb2_set_color(RED);
149
                        barCodePosition[0]=0;
150
            barCodePosition[1]=0;
151
                        disableBarCode=50;
152
                }
153
        }
154
        //on line
155
        else
156
        {
157
                position*=30;
158
                orb2_set_color(ORB_OFF);
159
                motorLeft(min(speed+position, 255));
160
                motorRight(min(speed-position, 255));
161
                lost=0;
162
                intersectionFilter=0;
163
        }
164
}
165

    
166

    
167
/**
168
 * Turns left at a cross of two lines.  Assumes that we are at lines in a cross
169
 * pattern, and turns until it sets straight on the new line.
170
 * @return 0 if turn finishes otherwise return 1
171
 */
172
int line_follow::turnLeft()
173
{
174
        motors->set_sides(-20, 20, MOTOR_ABSOLUTE);
175
                
176
        if(!encoderReset)
177
        {
178
            encoderStart = encoder_get_x(RIGHT);
179
            encoderReset = 1;
180
        }
181

    
182
        if(encoder_get_x(RIGHT) < encoderStart)
183
        {
184
            encoderStart = 0;
185
            motors->set_sides(0, 0, MOTOR_ABSOLUTE);
186
            delay_ms(2000);
187
        }
188

    
189
        if(encoder_get_x(RIGHT) - encoderStart > 300)
190
        {
191
            encoderReset = 0;
192
            return 0;
193
        }
194
        return 1;
195
}
196

    
197

    
198

    
199
/**
200
 * Turns right at a cross of two lines.  Assumes that we are at lines in a cross
201
 * pattern, and turns until it sets straight on the new line.
202
 * @return 0 if the turn finishes otherwise return 1
203
 */
204
int line_follow::turnRight()
205
{
206
  /// Set motors using new motors functions
207
  motors->set_sides(20, -20, MOTOR_ABSOLUTE);
208

    
209
  int colors[5];
210
  updateLine(colors);
211
  int position = lineLocate(colors);
212
  if(position>2 || position<-2)
213
    turnDistance++;
214

    
215
  if(turnDistance>1) 
216
  {
217
    if(position<3 && position>-3)
218
    {
219
      turnDistance = 0;
220
      return 0;
221
    }
222
  }
223
  return 1;
224
}
225

    
226

    
227
void line_follow::updateLine(int* values)
228
{        
229
        for(int i = 0; i<5; i++)
230
                values[i] = (read_line(4-i) < LINE_COLOR ? LWHITE : LBLACK);
231
}
232

    
233

    
234
int line_follow::lineLocate(int* colors)
235
{
236
        int i;
237
        int wsum = 0;
238
        int count=0;
239

    
240
        for(i = 0; i<5; i++)
241
        {
242
                count += colors[i]/2;
243
                wsum += (i)*colors[i];
244
        }
245
        if(count==0)
246
                return NOLINE;        
247
        if(count==5)
248
                return FULL_LINE;
249
        return (wsum/count)-4; /// Subtract 4 to center the index around the center.
250
}
251

    
252
void line_follow::motorLeft(int speed)
253
{
254
        int tempspeed = 0;
255
        if ((speed-=127)>=0)
256
        {        
257
                tempspeed = 160+speed*95/128;
258
                motors->set(MOTOR_LEFT, tempspeed, MOTOR_ABSOLUTE);
259
        }
260
        else
261
        {
262
                tempspeed = 160+speed*95/128;
263
                motors->set(MOTOR_LEFT, -tempspeed, MOTOR_ABSOLUTE);
264
        }
265
}
266

    
267
void line_follow::motorRight(int speed)
268
{
269
        int tempspeed = 0;
270
        if ((speed-=127)>=0)
271
        {        
272
                tempspeed = 160+speed*95/128;
273
                motors->set(MOTOR_RIGHT, tempspeed, MOTOR_ABSOLUTE);
274
        }
275
        else
276
        {
277
                tempspeed = 160+speed*95/128;
278
                motors->set(MOTOR_RIGHT, -tempspeed, MOTOR_ABSOLUTE);
279
        }
280
}
281