Caddy
A 2005 Roborodentia entry with vision and path planning capability
 All Data Structures Files Functions Variables Typedefs Macros Pages
ball_tracking.c
Go to the documentation of this file.
1 /*
2  * This file is part of Caddy.
3  *
4  * Caddy is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Caddy is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Caddy. If not, see <http://www.gnu.org/licenses/>.
16  */
18 #include "ball_tracking.h"
19 #include "line_tracking.h"
20 #include "camera.h"
21 #include "servos.h"
22 #include "robot_control.h"
23 #include "motor_control.h"
24 #include "tweak_data.h"
25 #include "utility.h"
26 
27 // AVRLIB
28 #include "rprintf.h"
29 
30 // avr-libc
31 #include <stdint.h>
32 #include <stdbool.h>
33 
34 // Track the RED ball on black/white background
35 #define BALL_RMIN 150
36 #define BALL_RMAX 240
37 #define BALL_GMIN 16
38 #define BALL_GMAX 60
39 #define BALL_BMIN 16
40 #define BALL_BMAX 50
41 
42 // Global variables
43 volatile bool colorStatsProcessed;
44 bool inSeekPosition;
45 
46 static uint8_t distToPix( uint8_t distance );
47 
48 void trackColorInit(int8_t dir)
49 {
50  if (!inSeekPosition)
51  {
52  brake(BOTH_MOTORS);
53  msDelay(200);
54  moveStraight(-1 * 0xb, 255);
55  inSeekPosition = true;
56  }
57 
58  // Set pan (center) and tilt
59  switch (dir)
60  {
61  case LOOK_LEFT:
62  setServo(PAN, PAN_CENTER + panOffset + PAN_SEEK_OFFSET);
63  setServo(TILT, TILT_VERT + tiltOffset);
64  break;
65  case LOOK_RIGHT:
66  setServo(PAN, PAN_CENTER + panOffset - PAN_SEEK_OFFSET);
67  setServo(TILT, TILT_VERT + tiltOffset);
68  break;
69  case LOOK_UP:
70  setServo(PAN, PAN_CENTER + panOffset);
71  setServo(TILT, TILT_LOOKUP);
72  break;
73  default:
74  break;
75  }
76  msDelay(500);
77 
79  rprintf("DS 1 1\r");
80  rprintf("LM 0 0\r");
81 
82  // Change to poll mode so only one packet is sent
83  rprintf("PM 1\r");
84 }
85 
86 /*
87  * Returns Y1 (top of ball) if camera sees a ball, zero otherwise
88  */
89 uint8_t getBallY( void )
90 {
91  rprintf("lm 0 0\r");
92 
93  // Mask everything but the 'My' value
94  //rprintf("OM 0 2\r"); //<- NO MASKING?
95 
96  // Change to poll mode so only one packet is sent
97  rprintf("PM 1\r");
98 
99  // Track red
100  rprintf("TC %d %d %d %d %d %d\r",
101  BALL_RMIN, BALL_RMAX, BALL_GMIN, BALL_GMAX, BALL_BMIN, BALL_BMAX);
102 
103  colorStatsProcessed = true;
104  while (colorStatsProcessed) ;
105 
106  return (lineStats[0][Y1_NDX]);
107 }
108 
109 
110 bool seeBall( void )
111 {
112  // Track red
113  rprintf("TC %d %d %d %d %d %d\r",
114  BALL_RMIN, BALL_RMAX, BALL_GMIN, BALL_GMAX, BALL_BMIN, BALL_BMAX);
115  colorStatsProcessed = true;
116  while (colorStatsProcessed) ;
117 
118  return lineStats[0][Y1_NDX] > 0;
119 }
120 
121 
122 /*
123  * Just does left seeks
124  * PRE - the longest check is the last element of the uncheckedBalls array
125  *
126  * uncheckedBalls - ball node numbers and ground distances away from bot
127  */
128 bool cameraSeekLeft( uint8_t uncheckedBalls[][2], uint8_t numUncheckedBalls )
129 {
130  bool foundBall = false; // Return value
131  uint8_t scanHeight = 4;
132  uint8_t x = 174;
133  //uint8_t ballDist[3];
134  //uint8_t ballCount = 0;
135  uint8_t scanLimit = distToPix(
136  uncheckedBalls[numUncheckedBalls - 1][BALL_DIST] + 1);
137 
138  // get pixel ranges for unchecked balls passed in
139  uint8_t i = 0;
140  uint8_t maxBallX[3];
141  while (i + 1 < numUncheckedBalls)
142  {
143  maxBallX[i] = (distToPix(uncheckedBalls[i][BALL_DIST]) +
144  distToPix(uncheckedBalls[i + 1][BALL_DIST])) / 2;
145  i++;
146  }
147  maxBallX[i] = scanLimit;
148 
149  // scan from small ground distance to large ground distance
150  while (x - scanHeight > scanLimit)
151  {
152  x -= scanHeight;
153  setVirtualWindow(x - scanHeight, 1, x, 254);
154  if (seeBall())
155  {
156  foundBall = true;
157  //ballDist[ballCount++] = xToDist(x);
158 
159  // find ball number of ball at this x
160  i = 0;
161  while (maxBallX[i] > x)
162  {
163  i++;
164  }
165  addToGoalList(uncheckedBalls[i][BALL_NODE_NUM]);
166 
167  while (seeBall())
168  {
169  x -= scanHeight;
170  setVirtualWindow(x - scanHeight, 1, x, 254);
171  }
172  }
173  }
174 
175  return foundBall;
176 }
177 
178 // returns pixel equivalent of 'distance'
179 static uint8_t distToPix( uint8_t distance )
180 {
181  switch (distance)
182  {
183  case 0:
184  case 1:
185  return 174;
186  case 2:
187  return 0x8d;
188  case 3:
189  return 0x61;
190  case 4:
191  return 0x48;
192  case 5:
193  return 0x36;
194  case 6:
195  return 0x2b;
196  case 7:
197  return 0x22;
198  case 8:
199  return 0x1d;
200  case 9:
201  return 0x18;
202  case 10:
203  return 0x14;
204  case 11:
205  return 0x11;
206  case 12:
207  return 0x0e;
208  default:
209  return 0x0;
210  }
211 }
212 
213 /*
214  * Just does right seeks
215  * PRE - the longest check is the last element of the uncheckedBalls array
216  *
217  * uncheckedBalls - ball node numbers and ground distances away from bot
218  */
219 bool cameraSeekRight(uint8_t uncheckedBalls[][2], uint8_t numUncheckedBalls)
220 {
221  bool foundBall = false; // Return value
222  uint8_t scanHeight = 4;
223  uint8_t x = 0;
224  uint8_t scanLimit = 174 - distToPix(
225  uncheckedBalls[numUncheckedBalls - 1][BALL_DIST] + 1);
226 
227  // get pixel ranges for unchecked balls passed in
228  uint8_t i = 0;
229  uint8_t maxBallX[3];
230  while (i + 1 < numUncheckedBalls)
231  {
232  maxBallX[i] = ((174 - distToPix(uncheckedBalls[i][BALL_DIST])) +
233  (174 - distToPix(uncheckedBalls[i + 1][BALL_DIST])))
234  / 2;
235  i++;
236  }
237  maxBallX[i] = scanLimit;
238 
239  // scan from small ground distance to large ground distance
240  while (x + scanHeight < scanLimit)
241  {
242  x += scanHeight;
243  setVirtualWindow(x, 1, x + scanHeight, 254);
244  if (seeBall())
245  {
246  foundBall = true;
247  //ballDist[ballCount++] = xToDist(x);
248 
249  // find ball number of ball at this x
250  i = 0;
251  while (maxBallX[i] < x)
252  {
253  i++;
254  }
255  addToGoalList(uncheckedBalls[i][BALL_NODE_NUM]);
256 
257  while (seeBall())
258  {
259  x += scanHeight;
260  setVirtualWindow(x, 1, x + scanHeight, 254);
261  }
262  }
263  }
264 
265  return foundBall;
266 }
267