How to pause GRIP data input?

We are using GRIP for our image processing and we need to grab the information of a single contour. Currently it is not possible for us to eliminate all other contours, so instead we are using the largest contour to determine what the goal is.

We are currently finding the position of the largest contour in the array and finding that number value in another array (like center x, or height). This doesn’t work because the smaller contours fluctuate a lot and the position of the goal/largest contour changes from the first time we get the data (area) to the second time we get the data (centerX, or height).

Is there any way to pause the input from the Network Tables? Or can we take a picture using the webcam and just analyze the picture?

Thanks

This feature hasn’t been documented yet, but yes, you can pause GRIP using NetworkTables if you’re using the very latest release candidate (v1.3-rc1).

NetworkTable table = NetworkTable.getTable("GRIP");

table.putBoolean("run", false); // Stop GRIP without killing the process

doSomeStuffThatDoesntNeedVision();

table.putBoolean("run", true); // Start GRIP again

This should work if you just want to process a “snapshot” of the input, but keep in mind that there’s always a little latency with NetworkTables updates, so you can’t precisely control when GRIP starts and stops.

This doesn’t work because the smaller contours fluctuate a lot and the position of the goal/largest contour changes from the first time we get the data (area) to the second time we get the data (centerX, or height).

The latest NetworkTables protocol supports RPC “transactions”, which should help fix this, but currently there’s still work to be done in bringing support for this feature to the Java bindings.

This doesn’t work because the smaller contours fluctuate a lot and the position of the goal/largest contour changes from the first time we get the data (area) to the second time we get the data (centerX, or height).
You could just flash the data immediately… something like how I do ours


        self.rotateError = 0
        try:
            beta = self._getArray("area")
            x = self._getArray("centerX")
            y = self._getArray("centerY") 
            self.largestArea = 0
            self.largestIndex = -1
            for index in range(len(beta)):
                if beta[index] > self.largestArea:
                    self.largestIndex = index
                    self.largestArea = beta[index]
            if self.largestIndex != -1:
                wpilib.SmartDashboard.putNumber("Largest Area", beta[self.largestIndex])
                wpilib.SmartDashboard.putNumber("Largest x", x[self.largestIndex])
                wpilib.SmartDashboard.putNumber("Largest y", y[self.largestIndex])
                wpilib.SmartDashboard.putNumber("X Error", self.center_x - x[self.largestIndex])
                wpilib.SmartDashboard.putNumber("Rotate Error", self.degrees_per_x_error * (self.center_x - x[self.largestIndex]))
                wpilib.SmartDashboard.putNumber("Y Error", self.center_y - y[self.largestIndex])
                
                self.rotateError = self.degrees_per_x_error * (self.center_x - x[self.largestIndex])
                self.y = y[self.largestIndex]
            return
        except KeyError:
            return
        except IndexError:
            return

In our testing of the system, we have seen the noise coming fast enough that successive calls to getArray() return different sized arrays (meaning the table updated asynchronously in the two cycles between the getArray() calls)

For now, I have solved this by checking the array size for all the elements, and if there is a mismatch I just punt that dataset. Even that isn’t perfect because the array could have updated but be different sizes… but it’s as close as I can get without an atomic operation.