Options
The unfortunate part about programming for the FTC robot is that to test code, you must build, download, then run; for large codebases this is often a slow process. Sometimes, there will be numbers which are not necessarily fixed, and rebuilding just before every competition and match is infeasible.
This collection of classes gives you a dynamic solution to this problem:
ftc.evlib.opmodes.AbstractOptionsOp
ftc.evlib.util.FileUtil
ftc.electronvolts.util.OptionsFile
ftc.electronvolts.util.OptionEntry
These classes allow you to set variables by running an AbstractOptionsOp
, then access them later in an unrelated Opmode.
NOTE: Option setting is an opt-in feature. An opmode for setting options does not show up by default.
Interface
You'll probably want to orient your driver hub to be landscape to use the interface
TODO: Add picture of driver hub
The table on the right shows a list of option names and their current values.
- To select an option, press dpad-up or dpad-down (navigate up or down) until you reach it (the arrows are on either side of the option).
- For discrete variables (e.g. integers), press the left/right bumpers to modify their values (this change will be reflected on the telemetry log).
- For approximate continuous variables (e.g. floating-points), press the left/right triggers.
- The depth of the trigger press will be reflected in the rate at which the option is modified (the heavier the touch, the more the variable goes up).
- To save the options, press the start button
- The options will not save the opmode finishes but the start button is not pressed
- To clear changes to the last save, press the reset button
- This will irrevocably remove all changes that were not saved
Defining Variables
You'll first want to set up two classes: An OpMode extending AbstractOptionsOp
and an enum class implementing OptionEntry
. Here is an example:
// ExampleOptions.java
import ftc.electronvolts.util.OptionEntry;
public enum ExampleOptions implements OptionEntry {
TypeData<?> data;
@Override
public TypeData<?> getData {
return data;
}
ExampleOptions(TypeDataBuilder<?> t) {
data = t.build();
}
}
// ExampleOptionsOp.java
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import ftc.evlib.opmodes.AbstractOptionsOp;
@TeleOp(name = "Example Options Op")
public class ExampleOptionsOp extends AbstractOptionsOp {
@Override
protected void setImplementationSpecificDetails() {
filename = "example_options.json";
options = ExampleOptions.class;
}
}
These classes would run fine by themselves, but if you try running "Example Options Op" you would see nothing. To create options, you would have to define an entry in ExampleOptions
. Let's define one that is heavily suited for this task: The alliance color. It's one you'll only know on the field, and will not necessarily have the time to set.
Let's say that you represent your alliance color like so:
// AllianceColor.java
public enum AllianceColor {
RED,
BLUE,
}
We'll define an option with these properties:
- It is called
ALLIANCE_COLOR
- It stores the
AllianceColor
enum - We somehow tipped off the judge, so we're expecting it to mostly be red
Here is the full definition:
ALLIANCE_COLOR(TypeDataBuilder
.enumType(AllianceColor.class)
.withFallback(AllianceColor.RED)
)
Here it is inserted into ExampleOptions
:
public enum ExampleOptions implements OptionEntry {
ALLIANCE_COLOR(TypeDataBuilder
.enumType(AllianceColor.class)
.withFallback(AllianceColor.RED)
)
TypeData<?> data;
@Override
public TypeData<?> getData {
return data;
}
ExampleOptions(TypeDataBuilder<?> t) {
data = t.build();
}
}
Now if you run "Example Options Op" again, it will show this one option, which you can now change using the bumpers on your controller. Adding more options is as easy as adding more enum variants.
TODO: add an image
Fetching Options
After you have set these options, you can programatically access them using the OptionsFile
class. Admittedly this is not an easy thing to do, and will be the next thing to improve about the option framework.
To get the object containing the options, use:
OptionsFile file = new OptionsFile(FileUtil.getOptionsFile("example_options.json"));
The string "example_options.json"
comes from the ExampleOptionsOp
defined before.
To get out the AllianceColor
, access the object like so:
AllianceColor color = (AllianceColor) file.load(ExampleOptions.ALLIANCE_COLOR);
The cast is necessary, without it you will have a compile error.