Changable RPM based on distance from target using vision camera

Originally, I wanted to use the slider on the joystick in order to change RPM mid match so we can shoot from anywhere, however I was thinking I could just automate all that with the vision camera, however I need a way to turn the vision camera into a rangefinder so I can run the distance through a set of conditions to find what RPM to run the shooter motors at. I have found people using the camera to drive to a set distance, but I haven’t been able to find anything on how to get the current distance saved to a variable so I can run it through some IF statements. If you have any good resources for such stuff or know a method, any help is greatly appreciated.

Assuming you have the bounding box of the target and the ideal width of the target in real units, you can use this equation to estimate the distance between the camera and target:

d = (h2-h1) / tan(a1+a2)

where h1 is the height of the camera above the floor, a1 is its mounting angle,
h2 is the height of the hub, and a2 is the y-angle to the target (which can be calculated using your camera’s FOV):

then, you should be able to use d to control the flywheel RPM


Here is a tutorial on estimating distance to the goal: Case Study: Estimating Distance — Limelight 1.0 documentation

Once you have an estimate, create a lookup table of RPMs based on distance.

For example:

| distance | RPM  |
| 4 ft     | 1000 |
| 8 ft     | 2000 |
| 12 ft    | 4000 |

Then you can use linear interpolation to choose a value. For example, if you are at 10 ft you would choose 3000 RPM. Note that distance and RPM are not linearly related in my example, so you may want to try different fits. Adding more points to the table will also help minimize error due to interpolation.


If you are just interpolating you don’t even need to know the actual distance, just the vertical angle off of the camera. Interpolate between the close angle, the middle angle, and the far angle.

1 Like

Thank you. One thing that I’m not sure how to adjust for is if we need to quickly shoot a shot by just going up against the bottom hub and launching up, at the angle I doubt the camera will be able to get a reading on the reflecting tape. Is there a way to account for this or will I just need to make an override button to set a RPM for that? Also for the equation, I don’t know how to get a2 and how would one implement this into a Java program?

I’m guessing unless you want to try and make moveable limelight, you would need an override button (you could also get fancy with it and do it with odometry).

As for the implementation, here’s what we did:

(the cotan function should probably be in math utils if you have one though)

Actually, it’s A1 that you need to know, A2 comes from the camera.
The way to calculate A1 is to put the camera at a known distance and run the math ‘backwards’ to solve for A1, presuming you can determine H1 accurately.

Or, you can measure it.

Well that just takes the fun out of it :wink:


Okay thanks. So, would the limelightconstants be a file you made similar to robotmap or constants? and if so, can i use my current constants file to hold all of those values? Also the get degree to vertical function would equal a2. BlueEpiphone mentioned that the a2 comes from the camera, so what does the function work?

Are you using a Limelight or other type of Raspberry Pi based vision processing already? A couple of people have posted using LL docs as a reference, but you didn’t say that was your setup, specifically. If so, the LL docs and this example page here are a good place to start. Or else consult the

If you’re just using a regular camera, though, then just processing images from it from scratch is a much bigger exercise, so thought I’d check that.

Else, A2 is just the Y value that the LL or other processor will report over NetworkTables.

Sorry, forgot to mention I am in fact using a limelight for our vision camera. Anyway, thank you for all of the information and resources. Looks like I got my work cut out for me this week.

Yep, the limelight constants can be stored in whatever file you want.

Here is the open-source limelight library we use for all the measurements: Library (
Example usage: Robot example

a2 is the value returned by getdegVerticalToTarget()
a1 is cameraAngleDegrees
h1 is camerHeightMeters
h2 is goalHeightMeters

I would recommend a separate button for shooting against the fender. You could check if the limelight had a valid target during distance calculation and use a minimum, fender-distance shot if not, but this would mean anytime you fail to acquire the target you will default to a straight-up fender shot.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.