Enum interface to Preferences

Over winter break I was reprogramming an old robot and was getting annoyed by how many files I had to change when adding a variable to the list of variables controlled by the Preferences class. (That is the class that stores things in the Roborio’s flash memory and lets you alter them via Shuffleboard so you don’t have to recompile and redownload code when tuning variables.) I came up with a scheme using an enum called TuningVariables that I think makes this more convenient. To add a tuning variable and its default value add
varName(defaultValue)
to the comma-separated list at the top of the enum. To get its value from flash memory use
TuningVariables.varName.get()
In the hopes that others may find it useful, here is the code:

// Author: Bill Dunlap [email protected], FRC 4173 (Team IMVERT), January 2023.
// This software is free to use by anyone with no restrictions.

package frc.robot;

import edu.wpi.first.wpilibj.Preferences;

/** These things are like the variables in Constants,

  • but can be set via the Preferences class (e.g.,

  • via Shuffleboard) and so will be stored in [persistent]

  • flash memory on the roborio. The TuningVariables class

  • also stores default values in Java (nonpersistent)

  • memory.

  • To add a new variable, say newVar, with default value newVarDefault,

  • to this scheme, add newVar(newVarDefault) to the comma-separated

  • list at the start of the enum below.

  • To get a tuning variable’s value use the syntax

  • TuningVariables.variableName.get()

  • A current limitation is that the turning variables

  • must be doubles.
    */
    public enum TuningVariables {
    // To add a new value, just enter its name and default value to the following list
    defaultSpinRate_DegreesPerSecond (40.0),
    defaultTravelRate_FeetPerSecond (2.0);

    private double m_defaultValue;
    /** Users cannot call an enum constructor directly;

    • Java will call it for each variable listed above.
    • Note the constructor will not change pre-existing
    • values in flash memory. Use setToDefaultValue or
    • setAllToDefaultValues for that.
      /
      private TuningVariables(double defaultValue){
      m_defaultValue = defaultValue;
      if (!Preferences.containsKey(name())) {
      Preferences.setDouble(name(), m_defaultValue);
      }
      }
      /
      * From flash memory, get the value of this variable /
      public double get() {
      return Preferences.getDouble(name(), m_defaultValue);
      }
      /
      * In flash memory, set this variable to a value /
      void set(double value) {
      Preferences.setDouble(name(), value);
      }
      /
      * In flash memory, set this variable to its default value /
      void setToDefaultValue() {
      set(m_defaultValue);
      }
      /
      * In flash memory, set all variables to their default values /
      static void setAllToDefaultValues() {
      for(TuningVariables tv: TuningVariables.values()) {
      tv.setToDefaultValue();
      }
      }
      /
      * Remove this variable from flash memory /
      void remove(){
      Preferences.remove(name());
      }
      /
      * Remove all variables from flash memory */
      static void removeAllKnown() {
      for(TuningVariables tv : TuningVariables.values()) {
      tv.remove();
      }
      }
      }

I did something similar in our code. The main goal was to take that boilerplate check on the preference and squirrel it away in common code. I tried an enum variation and a generic type variation. What I like about the enum implementation is that the enum becomes the string that the Preferences uses to lookup the value. However, I didn’t necessarily like the need to put everything in the enum class. So the generic version has a standardized implementation based off of a static string. FRCLibrary/FRC5010Example/src/main/java/frc/robot/FRC5010/constants at main · FRC5010/FRCLibrary · GitHub

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.