Class AimController

java.lang.Object
com.crossbotics.ftchelper.vision.AimController

public class AimController extends Object
Turns a camera target into a turn power, safely: no target, an old picture, or no bearing all give 0 (the robot never turns toward a target it cannot see now). (Last season's TagAimController.)

It is a small "PD" controller. P (proportional): the farther off the target is, the harder it turns. D (derivative): if the error is shrinking fast, it eases off so the robot does not swing past the target. Tutorial 07 (docs/tutorials/07-pid-lift.md) explains P, I and D step by step, and Tutorial 18 (docs/tutorials/18-vision-aim.md) uses this class.


 AimController aim = new AimController(0.02, 0.003)   // P and D on the bearing (degrees)
         .deadband(1.5)                               // close enough
         .maxPower(0.5)
         .maxAgeMs(150);                              // ignore pictures older than this
 // every loop, while the driver holds the aim button:
 drive.drive(forward, strafe, aim.turnPower(camera.target("RED SCORING")));   // ready for the drive's turn
 
For a turret, use turret.aimAtTarget(target, cameraOnTurret) instead. Docs: docs/modules/vision.md
  • Constructor Summary

    Constructors
    Constructor
    Description
    AimController(double kP, double kD)
    Makes an aim controller.
    AimController(double kP, double kD, LongSupplier clockNanos)
    For tests: the same, with a clock you control (nanoseconds).
  • Method Summary

    Modifier and Type
    Method
    Description
    double
    The same power, COUNTERCLOCKWISE positive (the IMU's sign), e.g.
    deadband(double deg)
    Errors smaller than this (degrees) give 0 power and count as aimed.
    boolean
    True if the last fresh target was inside the deadband.
    maxAgeMs(double ms)
    Pictures older than this are ignored (milliseconds).
    maxPower(double p)
    The most turn power the aim may use, 0 to 1.
    offset(double deg)
    Where the target should sit in the camera's view when the LAUNCHER points straight at it, in degrees (positive = the target appears left of the camera's center).
    void
    Forgets the past (call when the driver lets go of the aim button).
    double
    The turn power toward the target, CLOCKWISE positive: the same sign as every drive's turn (drive.drive(f, s, aim.turnPower(t)), tank.arcade(f, aim.turnPower(t))).

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • AimController

      public AimController(double kP, double kD)
      Makes an aim controller.
      Parameters:
      kP - turn power per degree of error (e.g. 0.02: 10 degrees off gives 0.2 power)
      kD - turn power per (degree per second) of change in the error; 0 turns the D part off
    • AimController

      public AimController(double kP, double kD, LongSupplier clockNanos)
      For tests: the same, with a clock you control (nanoseconds).
  • Method Details

    • deadband

      public AimController deadband(double deg)
      Errors smaller than this (degrees) give 0 power and count as aimed. Default 1.5. Without it the robot would twitch back and forth around the target forever. Returns this controller, so you can chain settings: .deadband(1.5).maxPower(0.5).
    • maxPower

      public AimController maxPower(double p)
      The most turn power the aim may use, 0 to 1. Default 0.6. Lower = gentler, slower aiming.
    • maxAgeMs

      public AimController maxAgeMs(double ms)
      Pictures older than this are ignored (milliseconds). Default 150.
    • offset

      public AimController offset(double deg)
      Where the target should sit in the camera's view when the LAUNCHER points straight at it, in degrees (positive = the target appears left of the camera's center). Use it when the camera is not centered on the launcher. Example: a camera mounted left of the launcher sees the target a little to its right when the launcher is aimed, so the offset is negative. Find it with the aim tuner (docs/modules/finders.md). Default 0.
    • turnPower

      public double turnPower(TargetObservation target)
      The turn power toward the target, CLOCKWISE positive: the same sign as every drive's turn (drive.drive(f, s, aim.turnPower(t)), tank.arcade(f, aim.turnPower(t))). 0 when there is no fresh target. Call it every loop while aiming.
      Parameters:
      target - the target from the camera, e.g. camera.target("RED SCORING"); null is fine (gives 0)
    • ccwPower

      public double ccwPower(TargetObservation target)
      The same power, COUNTERCLOCKWISE positive (the IMU's sign), e.g. for your own heading math. The D part only changes on a NEW picture, so a repeated picture never fakes motion.
    • isAimed

      public boolean isAimed()
      True if the last fresh target was inside the deadband.
    • reset

      public void reset()
      Forgets the past (call when the driver lets go of the aim button). Without this, the D part would compare the next picture with one from long ago and give a wrong kick.