Class Hood

java.lang.Object
com.crossbotics.ftchelper.robot.Module<Hood>
com.crossbotics.ftchelper.robot.Hood
All Implemented Interfaces:
Subsystem

public final class Hood extends Module<Hood>
A launcher's hood: the part that tilts to make the shot leave steeper or flatter. Given to a Launcher, the hood angle comes from the shot table's third column (blended between rows, like the speed), and the launcher waits for the hood to arrive before it feeds. It works for any hood design: a standard servo or a motor with an encoder, a straight gear or a linkage, any range, either direction.

 launcher = add(Launcher.flywheel("launcher", "gobilda-5203-6000").feeder(Indexer.servo("indexer"))
         .hood(Hood.servo("hood"))                          // or Hood.motor("hood", "gobilda-5203-117")
         .speedFromDistance(camera));

 public static class Hood {                                 // Tunables.java
     public static double posA = 0.20, posB = 0.65;         // servo positions at the two hard stops (Hood Finder)
     public static double angleA = 0, angleB = 25;          // optional: the hood's angle there (degrees)
     public static double travelSec = 0.5;                  // stop to stop, seconds (a servo cannot say where it is)
 }
 public static class Launcher {
     public static double[][] speedByDistance = {{24, 2200, 4}, {48, 2550, 12}, {72, 2900, 18}};  // in, rpm, hood
 }
 

Calibration. posA and posB are where the hood touches (a hair off) its two hard stops: servo positions 0 to 1, or encoder ticks for Hood.motor. They are the HARD LIMITS: every angle (a table row, a trim, a stick) is kept between them, so it never pushes on a stop. Both are needed (a safety number never comes from a library default); the Hood Finder finds them.

  • With angleA, angleB: you work in the hood's angle (any scale, either way round), on a straight line between the two stops.
  • Without them: the "angle" IS the servo position (or tick count). The shot table's hood column then holds positions ({48, 2550, 0.42}). Fine if you never measure angles.
  • A linkage or cam is not a straight line: calibration = {{0.20, 0}, {0.35, 8}, {0.50, 17}, {0.65, 25}} ({position, angle} rows, from the Hood Finder) is blended between rows instead. Its first and last rows are then the hard limits (posA/posB are not used).

Ready. A motor hood is ready when its encoder says it is within tolerance. A servo cannot say where it is, so a servo hood's "arrived" is a time estimate: travelSec for the whole range, less for a shorter move (time a stop-to-stop move to measure it).

By hand. Suggested operator stick: left stick Y (up = a bigger angle). While the shot table sets the angle it is a hood TRIM (added to the table, at most +/- trimMax; back to 0 with the launcher's double-tap D-pad down); otherwise it moves the hood. Your own buttons: step(int), setAngle(double), goToStart().

Optional Tunables (defaults scale with the range, so they suit degrees, positions and ticks): startAngle (where it goes at START; default angleA), stepAngle (1/25 of the range), byHandPerSec (the range in 2.5 s), trimMax (1/5 of the range). A motor hood: kP (0.005 power per tick), maxPower (0.5), tolerance (1/50 of the range). Its encoder counts from where it is at INIT: start the robot with the hood at the stop you call 0 ticks. Nothing moves in INIT: the hood goes to startAngle at START. Docs: docs/modules/robot.md (section "Hood"), lesson 9 (docs/tutorials/start/09-shooter-and-camera.md)

  • Method Summary

    Modifier and Type
    Method
    Description
    void
    The part's telemetry line; each module adds its own.
    double
    Where the hood is now: measured (a motor) or estimated from the time (a servo), like Turret.angle().
    void
    byHand(double amount)
    By hand from a stick, every loop: -1 to 1 (up = a bigger angle), byHandPerSec at full push.
    boolean
    True while the angle comes from the shot table (the launcher's distance), false when it is set by hand.
    A servo hood uses its servo's whole turn: positions 0 to 1 send the servo's full pulse range (the part's, else 500-2500 us) instead of the FTC SDK's normal 600-2400 us.
    void
    Back to startAngle (Tunables): where it went at START.
    boolean
    True when the hood is (a motor) or should be (a servo, by time) at its target angle.
    boolean
    True for Hood.motor, false for Hood.servo.
    boolean
    True when Robot.java says reversed().
    double
    The biggest angle it may go to (a hard limit).
    double
    The smallest angle it may go to (a hard limit).
    static Hood
    motor(String motor, String motorId)
    A hood on a motor with an encoder: it knows where the hood really is.
    The hood as an AngleDevice (what the launcher drives), for anything this module does not offer.
    double[]
    The pulse range (microseconds, {low, high}) its servo gets at INIT with fullRange(), or null for the SDK's normal range.
    void
    The hood trim back to 0 (the launcher's double-tap D-pad down does this too).
    It turns the other way.
    static Hood
    servo(String servo)
    A hood on a standard (positional) servo.
    void
    setAngle(double angle)
    Sends the hood to this angle (kept inside its hard limits).
    void
    setTrim(double amount)
    Sets the hood trim (0 = none), kept to +/- trimMax.
    shotAngles(double atA, double atB)
    For the simulator only: the launcher's shot angle (as in Launcher.shotAngle: degrees up from the wheel shape's forward) with the hood at angleA and at angleB.
    double
    Tunables startAngle: where it goes at START (default angleA).
    void
    step(int steps)
    One step per count (stepAngle): +1 = a bigger angle, -1 = smaller.
    void
    Stops all motion.
    double
    The angle the hood is going to (or is at); NaN before its first move (START).
    double
    The hood trim now (0 = none), in the hood's scale.
    void
    trimBy(double amount)
    Adds to the hood trim (added to the shot table's angle), kept to +/- trimMax.
    void
    Called once every loop.
    boolean
    True with angleA/angleB or a calibration table (real angles); false when the angle is the position.

    Methods inherited from class com.crossbotics.ftchelper.robot.Module

    deviceName, isOptional, isPresent, looks, name, optional, part, tunables, zone, zoneAbove, zoneBelow

    Methods inherited from class java.lang.Object

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

    • servo

      public static Hood servo(String servo)
      A hood on a standard (positional) servo. Its Tunables section is the name in CamelCase ("hood" -> Hood).
      Parameters:
      servo - the servo's configuration name
    • motor

      public static Hood motor(String motor, String motorId)
      A hood on a motor with an encoder: it knows where the hood really is. posA, posB (and calibration rows) are then encoder ticks, counted from where the hood is at INIT.
      Parameters:
      motor - the motor's configuration name
      motorId - the motor's parts-catalog id (see Motors), e.g. "gobilda-5203-117"
    • fullRange

      public Hood fullRange()
      A servo hood uses its servo's whole turn: positions 0 to 1 send the servo's full pulse range (the part's, else 500-2500 us) instead of the FTC SDK's normal 600-2400 us. A goBILDA 2000 servo then turns 300 degrees instead of 270. Turn it on BEFORE the Hood Finder (it uses the same range), or find posA and posB again: the same position points somewhere else after the change.
      Returns:
      this hood
      Throws:
      IllegalStateException - on a motor hood (it has no servo)
    • pulseRangeUs

      public double[] pulseRangeUs()
      The pulse range (microseconds, {low, high}) its servo gets at INIT with fullRange(), or null for the SDK's normal range. The Hood Finder uses the same one.
    • reversed

      public Hood reversed()
      It turns the other way. The Hood Finder's numbers are for the hood as set up here.
    • shotAngles

      public Hood shotAngles(double atA, double atB)
      For the simulator only: the launcher's shot angle (as in Launcher.shotAngle: degrees up from the wheel shape's forward) with the hood at angleA and at angleB. The simulated shot then leaves steeper or flatter as the hood moves (on a straight line between the two).
      Parameters:
      atA - the shot angle with the hood at angleA (posA), e.g. 80
      atB - the shot angle with the hood at angleB (posB), e.g. 55
    • setAngle

      public void setAngle(double angle)
      Sends the hood to this angle (kept inside its hard limits). While the shot table sets the angle, the table sets it again at the next loop: use trimBy(double) then.
      Parameters:
      angle - the hood angle, in your scale (degrees, or the position without angleA/angleB)
    • goToStart

      public void goToStart()
      Back to startAngle (Tunables): where it went at START.
    • step

      public void step(int steps)
      One step per count (stepAngle): +1 = a bigger angle, -1 = smaller. While the shot table sets the angle it changes the hood trim; else it moves the hood. For your own buttons: g2.y.press(() -> robot.launcher.hood().step(+1)).
      Parameters:
      steps - e.g. +1 or -1
    • byHand

      public void byHand(double amount)
      By hand from a stick, every loop: -1 to 1 (up = a bigger angle), byHandPerSec at full push. While the shot table sets the angle it moves the hood trim; else the hood. 0 does nothing.
      Parameters:
      amount - the stick, -1 to 1
    • trimBy

      public void trimBy(double amount)
      Adds to the hood trim (added to the shot table's angle), kept to +/- trimMax. Starts at 0 at every INIT. Only used while the angle comes from the shot table.
      Parameters:
      amount - e.g. +1 (degree) or -0.5
    • setTrim

      public void setTrim(double amount)
      Sets the hood trim (0 = none), kept to +/- trimMax.
    • resetTrim

      public void resetTrim()
      The hood trim back to 0 (the launcher's double-tap D-pad down does this too).
    • trim

      public double trim()
      The hood trim now (0 = none), in the hood's scale.
    • angle

      public double angle()
      Where the hood is now: measured (a motor) or estimated from the time (a servo), like Turret.angle(). NaN before its first move (START).
    • targetAngle

      public double targetAngle()
      The angle the hood is going to (or is at); NaN before its first move (START).
    • isAtTarget

      public boolean isAtTarget()
      True when the hood is (a motor) or should be (a servo, by time) at its target angle.
    • followsTable

      public boolean followsTable()
      True while the angle comes from the shot table (the launcher's distance), false when it is set by hand.
    • minAngle

      public double minAngle()
      The smallest angle it may go to (a hard limit). NaN before INIT.
    • maxAngle

      public double maxAngle()
      The biggest angle it may go to (a hard limit). NaN before INIT.
    • startAngle

      public double startAngle()
      Tunables startAngle: where it goes at START (default angleA). NaN before INIT.
    • usesAngles

      public boolean usesAngles()
      True with angleA/angleB or a calibration table (real angles); false when the angle is the position.
    • isMotor

      public boolean isMotor()
      True for Hood.motor, false for Hood.servo.
    • isReversed

      public boolean isReversed()
      True when Robot.java says reversed().
    • part

      public AngleDevice part()
      The hood as an AngleDevice (what the launcher drives), for anything this module does not offer.
    • update

      public void update()
      Description copied from interface: Subsystem
      Called once every loop. Do the hardware work here. Must be quick: no sleep, no waiting. While update() waits, the whole robot is frozen (no driving, no limits, no STOP).
    • stop

      public void stop()
      Description copied from interface: Subsystem
      Stops all motion. Called at the end of every OpMode.
    • addTelemetry

      public void addTelemetry(RobotTelemetry t)
      Description copied from class: Module
      The part's telemetry line; each module adds its own.
      Specified by:
      addTelemetry in interface Subsystem
      Overrides:
      addTelemetry in class Module<Hood>