Desperate for help in camera tracking

My team and I had only managed to make the camera track in the pan direction. We are having a serious problem tracking in the tilt direction. We are programing in EasyC pro, and since there isn’t any prepared code for the camera search and tracking, we made it ourselves. Here’s what our tracking function mainly does: after it finds the light (with the search function we maid witch works pretty fine), it has to find the value of the center of the light. If there is only 1 light then the value to rotate to is the centroid_x. If there are 2 lights the value to rotate to is: if the centroid_x is closer to the right, then it is about 3 pixels to the left from the upright_x, and if it’s more closer to the left then it is about 3 pixels right from the bottomleft_x. After that I put the pan_move function. This function gets the value that it has to move for. The rotation is 255-value because the value and the rotation’s x axle are upside down (correct me if I’m wrong). All this works pretty fine, (it moves a bit too little, but I think it’s correct). Now, the big problem is the tilt direction. I set the rotation of the tilt direction to be the 255-centroid_y value (that means it has to rotate to the PWM value). But the problem is: it just goes up and down and running crazy. Our team doesn’t have any idea what’s the problem:confused:
Our code goes something like this:


Search_Light(); //when found it stops the movement of  the servos
while(1) //infinite loop
{
     Get_Target(); //Stores the x and y values to rotate to into global variables
     Pan_Move(); //Moves the pan servo using PWM from the global variable
     Tilt_Move(); //Moves the tilt servo using PWM from the global variable
}               

The code is supposed to keep tracking the green light.
Please help us, we are sitting with this irritating problem for over 3 weeks now. We are desperate for help!:frowning:
I would be very happy if someone gave us some direction to go to.

The problem is that the servos are absolute, unlike motors. If you have a servo connected to pwm01, a

SetPWM(1, 127)

will send the servo to approximately its center point. Instead of measuring how far off you are and adding a small number to that PWM until you have the target centered, you are using 255-centroid y. That is not a magic formula:

Say your camera is happily centered on the target, with (for simplicity’s sake) the X and Y servos both at 127 (which will most likely never, ever happen). The camera’s FOV (field of view) is 159 pixels wide by 239 pixels tall; therefore the center of it is at about (80, 120). With your formula, the camera would report that the centroid is at (80, 120), and your code would send the Y servo off to 255-120=135 just on the first cycle.

What you really need to do is say (in Jacob-ese pseudo-code):

if ((centroid_y - 120) > 3) {
move the camera up/down--depends on how it's mounted
}
else if ((centroid_y - 120) < 3) {
Do the opposite of ^ that ^
}
else {
your camera is lined up.
}

Tweak these values if needed. The “< 3” part can be tweaked if you want your camera to be more accurate, but if this number is too small, the camera could end up bouncing back and forth as it overshoots one direction and then the other in rapid succession…

If you need some real code made up, post back and I’ll see what I can do; I just think it’s better for you to program it. You learn a lot more doing it yourself.

Good luck,
JBot

Thanks for the information about the centroid range…
The camera probably bounced up and down because it never realy got to the right centroid_y. I didn’t understand the code, what does 3 stand for? And 120 is supposed to represent the center of the tilt, right? Now I’ll repair this in the pan direction too. So lets say I call the value of the x direction as target_x (like in the demo code) then every pixel of the centroid_x range is: target_x/159?
And another question: our camera is mounted with the ON/OFF switch on top, so where is the 0 of the centroid_x and the 159 of it? Same thing about the tilt.
Oh, and about the code, I will be glad if you could give me some pseodo code to learn from… I am a rookie as you see, and I’m getting very nevous about this camera because I can’t get almost nothing from it:(
Thanks in advance.

:::EDIT:::
I thought about it, and isn’t it easier to calculate the exact tilt location according to the centroid_y (after the conversion to rotation, 239 centroid_y pixels are 255 rotation ticks–> 255/239=1.066… rotation ticks for each pixel. So if the centroid_y is let’s say at 150, then the rotation has to be:


rotation=(int)centroid_y*(255/239); // or rotation=(int)255-centroid_y*(255/239);  Depends on the centroid_y direction.
SetPWM(Port_2,rotation)

Same thing about the pan servo (but not necessarily with centroid_x).
Correct me if I’m wrong please.

I’m glad you got it. I’m a horrible teacher; I was just about out of ways to help you.

Yes, it seems that you’ve got the solution. Just make sure it indeed does work–test it thoroughly.

Good luck and feel free to keep asking questions. That’s how you learn.

JBot

Ok, we have managed to make the camera track to the tilt direction. There is a little problem: the tilt bounces a bit, not something very significal. Here is our Tilt_Move code:


if(centroid_y<120-8) //there is a "-8" for making the range larger, avoids bounces
{
    Tilt_Rotation=Tilt_Rotation+1; //sets to rotate by 1
    SetPWM(Tilt_Servo_Port,Tilt_Rotation); //rotates
    wait(10); //gives time for the servo to spin
}

else if(centroid_y>120+8)
{
    Tilt_Rotation=Tilt_Rotation-1;
    SetPWM(Tilt_Servo_Port,Tilt_Rotation);
    wait(10);
}



What do you think about it?:smiley:

which PWM port are you using to drive the tilt servo?

That’s just about exactly what I was hoping you’d do! Good job!

Is it slow at all? It seems like moving it by 1/255 of the servo’s range would be somewhat slow. Maybe not. Don’t listen to me if it’s working…:smiley:

Let me know if you need more help.

JBot

Well, it was slow so I put the speed to be faster and now it’s fine:rolleyes:
Now the main little problem is that there is a dead zone. The dead zone has to be different according to the distance of the light from the camera, but I think that the camera will be in the worst case 2 meters from the light, so the dead zone is pretty fine (I tested it from a distance of about 3.5 meters and it worked fine). So do you think it is necessary to make the dead zone dynamic?
Oh, and I realized there is no reason for the wait time, it works fine without it.
BTW, you’re really helping:) Thanks a lot! Added to you reputation.

Do you mean: if the tilt is higher, make the dead zone smaller, otherwise, make it bigger? You could do that, but do you really need a super-accurate fix on the light from a distance? I think it would be better to make the dead zone as small as you can without making the camera bounce, and leave it at that.

Glad to hear I’m helping. I’d rather have an opponent with an autonomous mode that’s better (or at least as good as…:smiley: ) mine, instead of my team winning because nobody else had an autonomous mode.

JBot

Lol, you’re right:)

About the dead zone: the dead zone is the range of centroids that the camera will not rotate to. I mean, it is the range that the camera won’t bother to rotate because the change of the centroid is very small. In this example the range is between 112-128 in centroid_y. That means if the camera is looking at 112 but the centroid is at 124 then it won’t bother to move, and this avoids bouncing. The problem witch I thought about is when the camera is very close to the light, then the dead zone has to be a lot bigger. But I think it’s fine without the sophisticated dynamic dead zone:o