def compute(self, now, x, y, angle):
        """
            Call this when vision processing should be enabled
        
            :param now:   The value passed to ``update_sim``
            :param x:     Returned from physics_controller.get_position
            :param y:     Returned from physics_controller.get_position
            :param angle: Returned from physics_controller.get_position
            
            :returns: None or list of tuples of (found=0 or 1, capture_time, offset_degrees, distance).
                      The tuples are ordered by absolute offset from the
                      target. If a list is returned, it is guaranteed to have at
                      least one element in it.
                      
                      Note: If your vision targeting doesn't have the ability
                      to focus on multiple targets, then you should ignore
                      the other elements.
        """

        # Normalize angle to [-180,180]
        output = []
        angle = ((angle + math.pi) % (math.pi * 2)) - math.pi

        for target in self.targets:
            proposed = target.compute(now, x, y, angle)
            if proposed:
                output.append(proposed)

        if not output:
            output.append((0, now, inf, 0))
            self.distance = None
        else:
            # order by absolute offset
            output.sort(key=lambda i: abs(i[2]))
            self.distance = output[-1][3]

        # Only store stuff every once in awhile
        if now - self.last_compute_time > self.update_period:

            self.last_compute_time = now
            self.send_queue.appendleft(output)

        # simulate latency by delaying camera output
        if self.send_queue:
            output = self.send_queue[-1]
            if now - output[0][1] > self.data_lag:
                return self.send_queue.pop()
Call this when vision processing should be enabled
        
            :param now:   The value passed to ``update_sim``
            :param x:     Returned from physics_controller.get_position
            :param y:     Returned from physics_controller.get_position
            :param angle: Returned from physics_controller.get_position
            
            :returns: None or list of tuples of (found=0 or 1, capture_time, offset_degrees, distance).
                      The tuples are ordered by absolute offset from the
                      target. If a list is returned, it is guaranteed to have at
                      least one element in it.
                      
                      Note: If your vision targeting doesn't have the ability
                      to focus on multiple targets, then you should ignore
                      the other elements.