Class Interlock

java.lang.Object
com.crossbotics.ftchelper.robot.Interlock

public final class Interlock extends Object
An interlock rule: two parts that must never be in the same space at the same time. "While the lift is up, the turret stays out of the back" is written once in Robot.java, and the library keeps to it every loop, in TeleOp and autonomous, whoever moves the part (a button, a stick, an action, a following turret, a step).

 // Robot.java, in define(), after the parts:
 keepApart("TurretLift", turret.zone(), lift.zoneAbove());

 // Tunables.java: the rule's numbers, in each part's own units
 public static class TurretLift {
     public static double turretFrom = 154, turretTo = 218;   // degrees: the turret's zone
     public static double liftAbove = 620;                    // counts: the lift's zone
     public static double turretMargin = 4, liftMargin = 60;  // optional: extra safety distances
     public static double turretStopSec = 0.2;                // optional: seconds to stop (default 0.15)
 }
 

The rule: the two parts are never both in their zones. Whoever is in its zone first keeps it; the other part waits outside its own zone until the first one leaves.

  • A part that wants to go into its zone (a target inside it, or a stick pushing toward it) goes, if the other part is out of its zone. The other part is then held out of its zone.
  • A held part stops at a safe distance from its zone (two margins) and waits there. Its target is kept: it goes on by itself when the other part leaves. The Driver Station says so: "Turret held at 150 deg: Lift is above 620 counts".
  • A turret whose target is on the other side of its zone goes the other way round if its range allows (e.g. a range of -190 to 190, or a slip ring); else it waits at the edge.
  • Both want in at the same moment: the first part named in the rule goes first.
  • Both already in their zones (at START, or after one was pushed by hand): neither may go deeper. Each may only move OUT. As soon as one is out, the other keeps its zone. The Driver Station says "both in their zones: move one out".
  • A part whose position is not known (a turret not homed yet; a servo before its first command, or while it is still moving) counts as "maybe anywhere it could be": in its zone, if the zone is in reach. So the other part waits.
  • And the other way round: a part whose position is not known does not move at all (no homing, no stick, no first servo move) while the other part is in its zone, since it could sweep through it. The Driver Station says "Turret waits (not homed yet): Lift is above 620 counts; move Lift out of its zone first". It goes as soon as the other part is out.

Stop distance (motor parts: a turret, lift or arm): a moving motor does not stop at once. It goes on until the next loop (which may be slow: a camera, a busy hub; and its position is from the last loop, so count that one too), then it coasts while it brakes. So every loop the rule measures the part's speed (from its encoder) and works out how far it would still go if told to stop now: speed x (2 x the slowest of the last 25 loops + half its <part>StopSec, default 0.15 s). A part that is kept out may only use the power that lets it stop in time: it slows down near its waiting point and brakes as soon as that distance would take it past it. A part that could not stop before its zone counts as already in it (the other part waits). A servo needs none: it is never sent past the fence.

Margins (<part>Margin, in its units; defaults: 3 degrees or twice the turret's tolerance, twice a lift's or arm's tolerance (at least 1/50 of its range), 0.02 for a servo, 1/50 of a hood's range): a part counts as in its zone within one margin of it, and a held part waits two margins away. The stop distance already covers coasting: the margin is extra safety (an encoder that slips, a part that bends).

Measured, not guessed: motors use their encoders every loop. A servo cannot say where it is, so it counts as anywhere between where it was and where it was sent, until its travelSec (Tunables) says it has arrived.

Checked at INIT (the OpMode stops with the reason): the rule's Tunables section and every number it needs; a zone that is empty (from is not below to), outside the part's range, or covering its whole range (the part could never be out of it); a negative margin; a part that is not on the robot, or one with no position (an intake roller: use Zone.when(java.lang.String, java.util.function.BooleanSupplier)); a stop time outside 0 to 2 s.

Not changeable live. The numbers are read once at INIT and are not in the tuning menu: a zone that moves while the parts move could suddenly put both in their zones. Change them in Tunables.java, then INIT again.

Software only: it does not replace hard stops, and a part pushed by hand (or by another robot) can still end up in its zone. The rule then only lets it move out. Docs: docs/modules/robot.md (section "Interlock"), docs/guides/interlocks.md

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final double
    The default <part>StopSec: a motor part in BRAKE stops in about this long (seconds).
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    True while the rule is holding a part back (it wants to go further but must wait).
    boolean
    True if the rule is off because one of its parts is not on the robot (Module.optional()).
    The rule's name: its section in Tunables.java.
    What it is doing, for the Driver Station ("" when nothing is held).
    The rule in words: "Turret between 154 and 218 deg / Lift above 620 counts".

    Methods inherited from class java.lang.Object

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

    • DEFAULT_STOP_SEC

      public static final double DEFAULT_STOP_SEC
      The default <part>StopSec: a motor part in BRAKE stops in about this long (seconds).
      See Also:
  • Method Details

    • name

      public String name()
      The rule's name: its section in Tunables.java.
    • isHolding

      public boolean isHolding()
      True while the rule is holding a part back (it wants to go further but must wait).
    • status

      public String status()
      What it is doing, for the Driver Station ("" when nothing is held).
    • words

      public String words()
      The rule in words: "Turret between 154 and 218 deg / Lift above 620 counts".
    • isOff

      public boolean isOff()
      True if the rule is off because one of its parts is not on the robot (Module.optional()).