Class Tunable

java.lang.Object
com.crossbotics.ftchelper.tuning.Tunable

public final class Tunable extends Object
A number you can change while the robot runs, from the gamepad (TuningMenu), without rebuilding. Saved values stay on the Control Hub until you reset them.

 // Make it once (a static field is easiest):
 static final Tunable LIFT_KP = Tunable.number("Lift/kP", 0.004, 0.0005);

 // Read it every loop, so a change takes effect at once:
 pid.setGains(LIFT_KP.get(), 0, 0, 0);
 

The part before "/" is the group shown in the menu ("Lift"). When you are happy with a value, copy it into the code as the new default, then reset the saved value: the code is the record, the saved file is only for tuning.

Saved values are kept in the robot's SettingsFile, under names that start with "tunable.". Tutorial 15 (docs/tutorials/15-telemetry-profiles-tuning.md) walks through it. Docs: docs/guides/tuning.md

  • Method Summary

    Modifier and Type
    Method
    Description
    static List<Tunable>
    all()
    Every tunable made so far, in the order they were made.
    static List<String>
    The values that differ from the code, as lines to copy into it: "Lift: kP = 0.0050" means kP = 0.0050 in Tunables.java, class Lift.
    static int
    How many tunables use a saved value that is different from the code.
    void
    One step down.
    double
    The value written in the code.
    The value as short text, e.g.
    static void
    For JUnit tests only: forgets every tunable in memory (they are shared by the whole app, so one test's robot would otherwise see another's numbers).
    static Tunable
    fromCode(String name, double defaultValue, double step)
    Like number(java.lang.String, double, double), for a number written in the team's code (the robot in five files uses it for every Tunables.java field).
    double
    get()
    The current value.
    The group: the part of the name before the first "/" ("" if none).
    static List<String>
    The groups hidden now (parts not on the robot), in order, e.g.
    static void
    hideGroup(String group, boolean hidden)
    Hides (or shows again) every tunable of one group, e.g.
    void
    One step up.
    boolean
    True if the value is not the code value.
    boolean
    True while it is hidden from the menu (its part is not on the robot).
    The full name, e.g.
    static Tunable
    number(String name, double defaultValue, double step)
    Makes a tunable number, or returns the existing one with this name.
    static List<String>
    INIT notes for code values outside their allowed range, e.g.
    range(double min, double max)
    Limits the value to a range (the menu will not go past it).
    void
    Back to the code value.
    static boolean
    Puts every tunable back to its code value and deletes the saved values.
    static void
    resetAll(), with the file written on a background thread.
    static boolean
    Saves every tunable's value on the Control Hub.
    static void
    Saves every tunable's value on a background thread; returns at once.
    void
    set(double newValue)
    Sets the value (inside the range).
    static List<Tunable>
    The tunables the tuning menu shows: every one but those of parts that are not on the robot (see hideGroup(java.lang.String, boolean)).
    Where the code value came from (see source(String)), "" when it was written as a number.
    source(String words)
    Says where the code value came from, shown next to it in the tuning menu while it is not changed: Tunables.java wrote DEFAULT_FROM_CATALOG, so the library worked it out ("from the catalog (gobilda-5203-435)", "general starting value (no part in Robot.java)").
    double
    How much one D-pad press changes the value.

    Methods inherited from class java.lang.Object

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

    • fromCode

      public static Tunable fromCode(String name, double defaultValue, double step)
      Like number(java.lang.String, double, double), for a number written in the team's code (the robot in five files uses it for every Tunables.java field). If a tunable with this name already exists, was not changed (not tuned, nothing saved) and has another code value, it takes this code value: the code is the record. Example: two robots in one app with Tunables.Auto.leaveInches 24 and 12; each robot drives its own distance. The step of an existing one is kept.
      Parameters:
      name - "Group/Name", e.g. "Auto/leaveInches"
      defaultValue - the value in the code
      step - how much one D-pad press changes it, used only when the tunable is new
      Returns:
      the tunable
    • number

      public static Tunable number(String name, double defaultValue, double step)
      Makes a tunable number, or returns the existing one with this name. (If one with this name already exists, the default and step given here are not used.)
      Parameters:
      name - "Group/Name", e.g. "Lift/kP"
      defaultValue - the value in the code
      step - how much one D-pad press changes it
      Returns:
      the tunable
    • all

      public static List<Tunable> all()
      Every tunable made so far, in the order they were made.
    • shown

      public static List<Tunable> shown()
      The tunables the tuning menu shows: every one but those of parts that are not on the robot (see hideGroup(java.lang.String, boolean)).
    • hideGroup

      public static void hideGroup(String group, boolean hidden)
      Hides (or shows again) every tunable of one group, e.g. "IntakeDeploy" for "IntakeDeploy/deployed". The robot in five files hides the numbers of a part that is not on the robot (marked optional(), its device not in the configuration): changing them would do nothing. Their saved values are kept, for the day the part is there. Set again at every INIT.
      Parameters:
      group - the group (a part's Tunables section)
      hidden - true = left out of the menu
    • hiddenGroups

      public static List<String> hiddenGroups()
      The groups hidden now (parts not on the robot), in order, e.g. ["IntakeDeploy"].
    • isHidden

      public boolean isHidden()
      True while it is hidden from the menu (its part is not on the robot).
    • countChanged

      public static int countChanged()
      How many tunables use a saved value that is different from the code. Show it in INIT.
    • changedAsCode

      public static List<String> changedAsCode()
      The values that differ from the code, as lines to copy into it: "Lift: kP = 0.0050" means kP = 0.0050 in Tunables.java, class Lift. Empty if none differ. The code is the record: a value saved only on the hub is lost with a new Control Hub.
    • saveAll

      public static boolean saveAll()
      Saves every tunable's value on the Control Hub. WAITS for the storage: in a running OpMode use saveAllInBackground(java.util.function.Consumer<java.lang.Boolean>) (the tuning menu does).
      Returns:
      true if it worked
    • saveAllInBackground

      public static void saveAllInBackground(Consumer<Boolean> whenDone)
      Saves every tunable's value on a background thread; returns at once.
      Parameters:
      whenDone - gets true if it worked (runs on the background thread); may be null
    • resetAll

      public static boolean resetAll()
      Puts every tunable back to its code value and deletes the saved values. WAITS for the storage: in a running OpMode use resetAllInBackground(java.util.function.Consumer<java.lang.Boolean>).
      Returns:
      true if the file was saved
    • resetAllInBackground

      public static void resetAllInBackground(Consumer<Boolean> whenDone)
      resetAll(), with the file written on a background thread. The values change at once.
    • forgetAllForTests

      public static void forgetAllForTests()
      For JUnit tests only: forgets every tunable in memory (they are shared by the whole app, so one test's robot would otherwise see another's numbers). new PretendDevices() calls it. Never in robot code: the tuning menu would lose its numbers.
    • range

      public Tunable range(double min, double max)
      Limits the value to a range (the menu will not go past it). Use it so tuning can never reach a dangerous number, for example a negative gain.
      Parameters:
      min - the smallest allowed value
      max - the largest allowed value
      Returns:
      this tunable, so you can write Tunable.number(...).range(0, 1)
    • outsideRangeNotes

      public static List<String> outsideRangeNotes(Collection<String> groups)
      INIT notes for code values outside their allowed range, e.g. "Tunables.Claw.open = 1.2 is outside its allowed range 0 to 1: 1 is used. Fix it in Tunables.java". Only for these groups (a robot's Tunables sections); empty when all are fine.
      Parameters:
      groups - the sections to look at, e.g. ["Claw", "Lift"]
    • get

      public double get()
      The current value. Read it every loop.
    • set

      public void set(double newValue)
      Sets the value (inside the range). Not saved until saveAll().
      Parameters:
      newValue - the new value; outside the range it is pulled back to the nearest end
    • increase

      public void increase()
      One step up.
    • decrease

      public void decrease()
      One step down.
    • reset

      public void reset()
      Back to the code value.
    • isChanged

      public boolean isChanged()
      True if the value is not the code value.
    • name

      public String name()
      The full name, e.g. "Lift/kP".
    • defaultValue

      public double defaultValue()
      The value written in the code.
    • step

      public double step()
      How much one D-pad press changes the value.
    • group

      public String group()
      The group: the part of the name before the first "/" ("" if none).
    • source

      public Tunable source(String words)
      Says where the code value came from, shown next to it in the tuning menu while it is not changed: Tunables.java wrote DEFAULT_FROM_CATALOG, so the library worked it out ("from the catalog (gobilda-5203-435)", "general starting value (no part in Robot.java)"). The "copy into Tunables.java" lines stay real numbers.
      Parameters:
      words - the words, "" for none
      Returns:
      this tunable
    • source

      public String source()
      Where the code value came from (see source(String)), "" when it was written as a number.
    • display

      public String display()
      The value as short text, e.g. "0.0040".