Skip to content

Commit

Permalink
Add support for enum logging as inputs and outputs
Browse files Browse the repository at this point in the history
Closes #54
  • Loading branch information
jwbonner committed Dec 10, 2023
1 parent 904794f commit d8c6c44
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/DATA-FLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ AdvantageKit also supports logging the state of a `Mechanism2d` object as an out

WPILib includes a [units library](https://docs.wpilib.org/en/latest/docs/software/basic-programming/java-units.html) that can be used to simplify unit conversions. `Measure` objects can be logged and replayed by AdvantageKit. These values will be stored in the log as doubles using the [base unit](https://github.com/wpilibsuite/allwpilib/blob/main/wpiunits/src/main/java/edu/wpi/first/units/BaseUnits.java) for the measurement type (e.g. distances will always be logged in meters).

### Enums

[Enum](https://www.w3schools.com/java/java_enums.asp) values can be logged and replayed by AdvantageKit. These values will be stored in the log as string values (using the [`name()`](https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#name--) method).

## Deterministic Timestamps

### The Problem
Expand Down
5 changes: 4 additions & 1 deletion docs/RECORDING-INPUTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public RobotContainer() {
## `AutoLog` Annotation & Data Types

By adding the `@AutoLog` annotation to your inputs class, AdvantageKit will automatically generate implementations of `toLog` and `fromLog` for your inputs. All simple data types (including single values and arrays) are supported. [Structured data types](DATA-FLOW.md#structured-data-types) are also supported, so geometry objects like `Rotation2d` and `Pose3d` can be directly used as inputs.
By adding the `@AutoLog` annotation to your inputs class, AdvantageKit will automatically generate implementations of `toLog` and `fromLog` for your inputs. All simple data types (including single values and arrays) are supported. [Structured data types](DATA-FLOW.md#structured-data-types) and enum values are also supported, so geometry objects like `Rotation2d` and `Pose3d` can be directly used as inputs.

For example:

Expand All @@ -61,6 +61,7 @@ For example:
public class MyInputs {
public double myNumber = 0.0;
public Pose2d myPose = new Pose2d();
public MyEnum myEnum = MyEnum.VALUE;
}
```

Expand All @@ -71,11 +72,13 @@ class MyInputsAutoLogged extends MyInputs implements LoggableInputs {
public void toLog(LogTable table) {
table.put("MyNumber", myField);
table.put("MyPose", myPose);
table.put("MyEnum", myEnum);
}

public void fromLog(LogTable table) {
myNumber = table.get("MyNumber", myNumber);
myPose = table.get("MyPose", myPose);
myEnum = table.get("MyEnum", myEnum);
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions docs/RECORDING-OUTPUTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ The logging framework supports recording this output data on the real robot and

```java
Logger.recordOutput("Flywheel/Setpoint", setpointSpeed);
Logger.recordOutput("FeederState", "IDLE");
Logger.recordOutput("Drive/CalculatedLeftVolts", leftVolts);
Logger.recordOutput("Drive/Pose", odometryPose);
Logger.recordOutput("FeederState", FeederState.RUNNING);
```

> Note: This data is automatically saved to the `RealOutputs` or `ReplayOutputs` table, and it can be divided further into subtables using slashes (as seen above).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,14 @@ private static void registerField(String key, Class<?> type, Supplier<?> supplie
if (value != null)
Logger.recordOutput(key, (String) value);
});
} else if (type.isEnum()) {
callbacks.add(
() -> {
Object value = supplier.get();
if (value != null)
// Cannot cast to enum subclass, log the name directly
Logger.recordOutput(key, ((Enum<?>) value).name());
});
} else if (type.equals(Measure.class)) {
callbacks.add(
() -> {
Expand Down
18 changes: 18 additions & 0 deletions junction/core/src/org/littletonrobotics/junction/LogTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ public void put(String key, String value) {
put(key, new LogValue(value, null));
}

/**
* Writes a new enum value to the table. Skipped if the key already exists as
* a different type.
*/
public <E extends Enum<E>> void put(String key, E value) {
put(key, new LogValue(value.name(), null));
}

/**
* Writes a new Measure value to the table. Skipped if the key already exists as
* a different type.
Expand Down Expand Up @@ -532,6 +540,16 @@ public String get(String key, String defaultValue) {
}
}

/** Reads an enum value from the table. */
public <E extends Enum<E>> E get(String key, E defaultValue) {
if (data.containsKey(prefix + key)) {
String name = get(key).getString(defaultValue.name());
return (E) Enum.valueOf(defaultValue.getClass(), name);
} else {
return defaultValue;
}
}

/** Reads a Measure value from the table. */
public <U extends Unit<U>> Measure<U> get(String key, Measure<U> defaultValue) {
if (data.containsKey(prefix + key)) {
Expand Down
14 changes: 14 additions & 0 deletions junction/core/src/org/littletonrobotics/junction/Logger.java
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,20 @@ public static void recordOutput(String key, String value) {
}
}

/**
* Records a single output field for easy access when viewing the log. On the
* simulator, use this method to record extra data based on the original inputs.
*
* @param key The name of the field to record. It will be stored under
* "/RealOutputs" or "/ReplayOutputs"
* @param value The value of the field.
*/
public static <E extends Enum<E>> void recordOutput(String key, E value) {
if (running) {
outputTable.put(key, value);
}
}

/**
* Records a single output field for easy access when viewing the log. On the
* simulator, use this method to record extra data based on the original inputs.
Expand Down

0 comments on commit d8c6c44

Please sign in to comment.