/** * implements vision_behaviors.h */ #include "vision_behaviors.hh" #define MIN(a,b) (ab?a:b) #define NO_HUE -1 #define THRESH 6 //#define LOOKUP_RANGE={164,108,85,71,62,56,51,47,44,41,39,37,35,33,32,31,30,29,28}; namespace Soccer03 { /** * Function to map image co-ordinates (x,y) to polar co-ordinates * (R, theta). Polar co-ordinates are relative to the centre of the * kicker mechanism of the robot. * * Inputs: x,y INT * Outputs: R,theta *INT * * Initial Implementation: * Equations to map to polar have been derived from experiments * which yeilded relationships between image co-ords and * polar co-ords. * * @author: Jarrod Bassan * @date: 11/04/03 * */ FindBall::FindBall() { ball.r = 0; ball.phi = 0; ball_found = 0; findball_bt *fd = (findball_bt*) HDTFindEntry(B_FINDBALL,0); if(fd==NULL) OSPanic("Cannot find\n findball data\n"); hue = fd->hue; threshold = fd->threshold; intensity_lo = fd->intensity_lo; intensity_hi = fd->intensity_hi; K = fd->K_far; intensity_thresh = fd->intensity_thresh; req_matches = fd->req_matches; } int FindBall::image_to_polar(int x, int y) { ball.phi = ((20.0*x)/(1<<5)) - 26.0; ball.r = (float)( (y<20) ? lookup_range[y] : div(512,y) ); ball.phi = -1 * ball.phi * M_PI / 180.0; ball.visible = true; return 0; } /** * return hue value for RGB color */ int FindBall::RGBtoHue(BYTE r, BYTE g, BYTE b) { int hue, delta, max, min, intensity; max = MAX(r, MAX(g,b)); min = MIN(r, MIN(g,b)); delta = max - min; hue = 0; /* init hue*/ if (K*delta <= (max*10) ) { hue = NO_HUE; /* gray, no color */ } else { if (r==max) hue = 42 + 42*(g-b)/delta; /* 1*42 */ else if (g==max) hue = 126 +42*(b-r)/delta; /* 3*42 */ else if (b==max) hue = 210 +42*(r-g)/delta; /* 5*42 */ } return (BYTE) hue; /* now: hue is in range [0..252] */ } int FindBall::CheckHue(BYTE r, BYTE g, BYTE b) { int h, intensity, distance; h = RGBtoHue(r,g,b); intensity=r+g+b; if ((h != NO_HUE)&&(intensity < intensity_hi)&&(intensity > intensity_lo)) { distance = ((int)h-hue); /* hue distance */ if (distance < 0) distance = -distance; if (distance > 126) distance = 253 - distance; if (distance < threshold) return 1; } return 0; } int FindBall::CheckIntensity(BYTE r, BYTE g, BYTE b) { if ((r+g+b)Image()); rows_to_scan = 2; ball.visible = false; /* Scan image */ //K_param = K_close; //Check bottom row of image... for (i=imagerows-2;i>rows_to_scan;(i>30) ? (i-=2) : (i-=1)) { k=i*3*imagecolumns + 3*imagecolumns/2; m=-1; //if (i>55) K_param = K_far; for (j=0; j<3*(imagecolumns-4); (i>40) ? (j+=6) : (j+=3)) { m*=-1; k+=m*j; if (CheckHue(I[k+RED],I[k+GREEN],I[k+BLUE]) == 1) { // Now check the 4 neighbouring pixels // north = NORTH(k); south = SOUTH(k); east = EAST(k); west = WEST(k); num_matches = CheckHue(I[east+RED],I[east+GREEN],I[east+BLUE]) + 1; num_matches += CheckHue(I[west+RED],I[west+GREEN],I[west+BLUE]); num_matches += CheckHue(I[north+RED],I[north+GREEN],I[north+BLUE]); num_matches += CheckHue(I[south+RED],I[south+GREEN],I[south+BLUE]); if (num_matches >= req_matches) { ball_y = i; ball_x = (int)(j/3.0); image_to_polar(ball_x, ball_y); return EXCITE_IDLE; } } } } // Check bottom row of image k = (imagerows-2)*imagecolumns*3; int current_pix=0; int end_pix=0; int best_run=0; int best_end=0; int run=0; int x = 0; for (j=k+3;j<(k+(3*(imagecolumns-1)));j+=3) { current_pix = x++; if (CheckIntensity(I[j+RED],I[j+GREEN],I[j+BLUE]) == 1) { end_pix = current_pix; run++; if (run > best_run) { best_run = run; best_end = end_pix; } } } if (best_run > req_matches) { ball.visible = true; ball.r = 3.0; ball.phi = 0.0; //((20.0* (best_end - (best_run/2)) )/(1<<5)) - 26.0; return EXCITE_IDLE; } return EXCITE_IDLE; } void FindBall::Feed(SignalLink &l) { if (!l.Generic()) reinterpret_cast(l).Ball(ball); Behavior::Feed(l); } }; // namespace Soccer03