39 #define LINE_STAT_MASK 0Xf // Sends the mean, min, max, and pixel count
46 #define LINE_Y_MAX_NDX (LINE_STATS_ROWS - SCAN_WIDTH - 1)
47 #define JUNC_Y_MAX_NDX (LINE_STATS_ROWS - JUNC_SCAN_WIDTH - 1)
48 #define BALL_Y_MAX_NDX (LINE_STATS_ROWS - BALL_SCAN_WIDTH - 1)
52 #define JUNC_SCAN_WIDTH 1
53 #define BALL_SCAN_WIDTH 7
56 volatile uint8_t lineStats[LINE_STATS_ROWS][LINE_STATS_COLS];
57 volatile bool lineStatsProcessed;
60 static int16_t correction;
61 static int8_t possibleBallY;
64 void adjustPWM(
void )
66 PWM_LEFT(MIN(MAX(l_base - correction, BASE_MIN), BASE_MAX));
67 PWM_RIGHT(MIN(MAX(r_base + correction, BASE_MIN), BASE_MAX));
72 lcdPrintHex(MIN(MAX(l_base - correction, BASE_MIN), BASE_MAX), 1, 11);
73 lcdPrintHex(MIN(MAX(r_base + correction, BASE_MIN), BASE_MAX), 1, 14);
78 void trackLineInit(
void)
84 lcdWriteStr(
" ", 0, 0);
85 lcdWriteStr(
" ", 1, 0);
93 lineStatsProcessed =
true;
96 forward(BOTH_MOTORS, 0);
103 rprintf(
"DS %d %d\r", DS_X_LINE, DS_Y_LINE);
105 rprintf(
"VW %d %d %d %d\r", VW_X1_LINE, VW_Y1_LINE, VW_X2_LINE, VW_Y2_LINE);
111 rprintf(
"OM 5 %d\r", LINE_STAT_MASK);
117 rprintf(
"TC %d %d %d %d %d %d\r",
118 LINE_RMIN, LINE_RMAX, LINE_GMIN,
119 LINE_GMAX, LINE_BMIN, LINE_GMAX);
123 void restartLineMode(
void )
127 rprintf(
"tc %d %d %d %d %d %d\r",
128 LINE_RMIN, LINE_RMAX, LINE_GMIN,
129 LINE_GMAX, LINE_BMIN, LINE_GMAX);
133 bool isGoodScan(uint8_t y)
137 for (i = y; i < y + SCAN_WIDTH; i++)
139 if (lineStats[i][X_MEAN] == 0 ||
140 lineStats[i][X_MIN] < VW_X1_LINE+5 ||
141 lineStats[i][X_MAX] > VW_X2_LINE-5 ||
142 lineStats[i][LINE_COUNT] > 9)
150 bool isJunctionScan(uint8_t y)
154 for (i = y; i < y + JUNC_SCAN_WIDTH; i++)
156 if (lineStats[i][X_MEAN] == 0
158 (lineStats[i][X_MIN] > VW_X1_LINE + 10 &&
159 lineStats[i][X_MAX] < VW_X2_LINE - 10)
161 lineStats[i][LINE_COUNT] < 9)
169 bool mayBeBall(uint8_t y)
173 for (i = y; i < y + BALL_SCAN_WIDTH; i++)
175 if (lineStats[i][X_MEAN] != 0)
183 void analyzeLineStats(
void)
196 static int16_t lineSlope = 0;
197 static int16_t lastSlope = 0;
203 while (y < LINE_Y_MAX_NDX && !isGoodScan(y))
208 for (i = y; i < y + SCAN_WIDTH; i++)
210 sum += lineStats[i][X_MEAN];
212 lineX1 = sum / SCAN_WIDTH;
217 while (y > lineY1 && !isGoodScan(y))
222 for (i = y; i < y + SCAN_WIDTH; i++)
224 sum += lineStats[i][X_MEAN];
226 lineX2 = sum / SCAN_WIDTH;
230 while (y <= JUNC_Y_MAX_NDX && !isJunctionScan(y))
234 if (y > JUNC_Y_MAX_NDX)
236 junctionY = -VW_Y1_LINE;
245 while (y <= BALL_Y_MAX_NDX && !mayBeBall(y))
249 if (y > BALL_Y_MAX_NDX)
251 possibleBallY = -VW_Y1_LINE;
259 lineY1 += VW_Y1_LINE;
260 lineY2 += VW_Y1_LINE;
261 junctionY += VW_Y1_LINE;
262 possibleBallY += VW_Y1_LINE;
265 m = (double) (lineX2 - lineX1) / (double) (lineY2 - lineY1);
266 lastSlope = lineSlope;
267 lineSlope = (int16_t) (slopeCoef * m);
268 damping = lineSlope - lastSlope;
269 lineOffset = lineCenter - (m * (LINE_Y3 - lineY1) + lineX1);
270 correction = slopeCoef * m +
271 offCoef * lineOffset +
277 lcdPrintHex(lineY1, 0, 0);
278 lcdPrintHex(lineX1, 0, 3);
279 lcdPrintHex(lineY2, 1, 0);
280 lcdPrintHex(lineX2, 1, 3);
281 lcdPrintHex(damping, 0, 6);
282 lcdPrintHex(lineSlope>>8, 0, 9);
283 lcdPrintHex(lineSlope, 0, 11);
284 lcdPrintHex(lineOffset, 0, 14);
286 lcdPrintHex(junctionY, 1, 6);
290 lineStatsProcessed =
true;