Implementation¶
Usage¶
Battleaid offers LoadableConfig
to make defining and loading configuration files simple. LoadableConfig
will automatically initialize class fields when an instance of the configuration is created. This encourages reuse and supports scalability.
I. Defining Configurations¶
To define a configuration, you must create a class that meets these requirements:
The class shall extend
LoadableConfig
.All fields in the class shall be declared
public
and uninitialized.Fields shall be typed as one of the following:
Java primitive
String
A class that extends
LoadableConfig
(nested configs)
The class shall contain a
public
constructor with a single parameterString filename
that callssuper.load(this, filename)
.Nested config definitions shall have an empty,
public
constructor and no other constructors.Nested config definitions shall be outside the scope of the encompassing config definition.
For example:
1// ExampleConfig.java
2public class ExampleConfig extends LoadableConfig {
3 public double d;
4 public byte b;
5 public int i;
6 public float f;
7 public boolean flag;
8 public char c;
9 public short s;
10 public long l;
11 public String str;
12 public NestedConfig nstd1;
13 public NestedConfig nstd2;
14
15 public ExampleConfig(String filename) {
16 super.load(this, filename);
17 }
18}
1// NestedConfig.java
2public class NestedConfig extends LoadableConfig {
3 public int that;
4 public float is;
5 public boolean cool;
6
7 public NestedConfig(){};
8}
Note
Optionally, one can call LoadableConfig.print(this)
to debug the class contents.
Warning
LoadableConfig
does not yet support arrays!
II. Creating Configuration Files¶
LoadableConfig
uses TOML
for configuration files. To make a configuration file, you must create a file that meets these requirements:
The file shall be located under
src/main/deploy/configuration
and have the extension.toml
.The file shall contain all fields defined in the class to be initialized.
The identifier shall be identical to the identifier of the class field.
Table identifiers shall be identical to identifiers of class fields that are nested configs.
Tables shall contain all fields defined in the nested config.
Using the ExampleConfig
from above, a configuration file might be the following:
1# example-config.toml
2str = "Hello, world!"
3flag = true
4
5# order doesn't matter!
6f = 3.14
7d = 1.6181
8
9# read the toml standard for details
10b = 0b1010_0101
11s = 0xFE
12i = 1_000
13l = 999_999_999
14
15[nstd1]
16that = 99
17is = 2.71828
18cool = true
19
20[nstd2]
21that = 1
22is = 0.0
23cool = false
III. Utilizing the Config¶
Time to use our config!
1// RobotContainer.java
2public class RobotContainer {
3 public RobotContainer(){
4 ExampleConfig cfg = new ExampleConfig("example-config.toml");
5
6 // this subsystem needs that config!
7 SomeSubsystem ss = new SomeSubsystem(cfg);
8 }
9}
Making Changes¶
Steps¶
Make a change in your
*.toml
.Run
./gradlew deployStandalonefrcStaticFileDeployroborio
in your terminal.Restart robot code:
Notes¶
I.¶
An effective strategy is to combine a subsystem with a configuration. You can nest the config class in a subsystem class by adding the static
modifier:
1// ExampleSubsystem.java
2public class ExampleSubsystem {
3 private ExampleSubsystem.Config cnfg;
4
5 public static class Config {
6 public int some_data;
7
8 public Config(String filename){
9 super.load(this, filename);
10 }
11 }
12
13 public ExampleSubsystem(ExampleSubsystem.Config cnfg)
14 {
15 this.cnfg = cnfg;
16 }
17}
1// RobotContainer.java
2public class RobotContainer {
3 public RobotContainer(){
4 // now the semantic meaning of the config is embedded
5 // into the namespacing of our program
6 ExampleSubsystem.Config cnfg = new ExampleSubsystem.Config("config.toml");
7 ExampleSubsystem ss = new ExampleSubsystem(cnfg);
8 }
9}