2018 FRC Control System

Using Generated Code in a Robot Program

GRIP generates a class that can be added to an FRC program that runs on a roboRIO and without a lot of additional code, drive the robot based on the output.

Included here is a complete sample program that uses a GRIP pipeline that drives a robot towards a piece of retroreflective material.

This program is designed to illustrate how the vision code works and does not necessarily represent the best technique for writing your robot program. When writing your own program be aware of the following considerations:

Using the camera output for steering the robot could be problematic. The camera code in this example that captures and processes images runs at a much slower rate that is desirable for a control loop for steering the robot. A better, and only slightly more complex solution, is to get headings from the camera and it's processing rate, then have a much faster control loop steering to those headings using a gyro sensor.

Keep the vision code in the class that wraps the pipeline. A better way of writing object oriented code is to subclass or instantiate the generated pipeline class and process the OpenCV results there rather than in the robot program. In this example, the robot code extracts the direction to drive by manipulating the resultant OpenCV contours. By having the OpenCV code exposed throughout the robot program it makes it difficult to change the vision algorithm should you have a better one.

The robotInit() method is called once when the program starts up. It creates a CameraServer instance that begins capturing images at the requested resolution (IMG_WIDTH by IMG_HEIGHT).

Next an instance of the class VisionThread is created. VisionThread begins capturing images from the camera asynchronously in a separate thread. After processing each image, the pipeline computed bounding box around the target is retrieved and it's center X value is computed. This centerX value will be the x pixel value of the center of the rectangle in the image.

The VisionThread also takes a VisionPipeline instance (here, we have a subclass MyVisionPipeline generated by GRIP) as well as a callback that we use to handle the output of the pipeline. In this example, the pipeline outputs a list of contours (outlines of areas in an image) that mark goals or targets of some kind. The callback finds the bounding box of the first contour in order to find its center, then saves that value in the variable centerX. Note the synchronized block around the assignment: this makes sure the main robot thread will always have the most up-to-date value of the variable, as long as it also uses synchronized blocks to read the variable.

This, the final part of the program, is called repeatedly during the autonomous period of the match. It gets the centerX pixel value of the target and subtracts half the image width to change it to a value that is zero when the rectangle is centered in the image and positive or negative when the target center is on the left or right side of the frame. That value is used to steer the robot towards the target.

Note the synchronized block at the beginning. This takes a snapshot of the most recent centerX value found by the VisionThread.

0
Report Errors

Use this form to report any errors with the documentation. For help with WPILib, please use the FIRST Forums at http://forums.usfirst.org For reporting WPILib bugs, please submit an issue on GitHub at https://github.com/wpilibsuite/allwpilib/issues/new