-
Notifications
You must be signed in to change notification settings - Fork 2
Usage
This page goes into more detail on how to use BadgerLog
- Basic Usage
- Types of Entries
- Publisher
- Subscriber
- Sendable
- Entry Configuration
@Key@StructType@UnitConversion@AutoGenerateStruct
-
DashboardmethodsputValuegetValueputSendablecreateSelectorFromEnumcreateNetworkTablesButtonremoveNetworkTablesEntry
- Wrappers
- Value
- Struct Value
- Subtable
- Sendable
- Common Issues
BadgerLog is designed to use annotations to generate custom NetworkTables wrappers that support some additional functionality. Annotations are the preferred method of using BadgerLog.
Some Notes before starting.
- Fields need to be initialized after the constructor
- Fields can not be final
- Fields can have any access modifier (public, private, protected)
- Fields may be either instance, or static fields
-
Dashboard.updatemust be called in a periodic method. (usuallyRobot.robotPeriodic) -
Dashboard.configuremay be called on startup. (UsuallyRobot.robotInit)
Given this, it is relatively easy to start creating entries.
The base annotation needed to mark a field to have an entry created is the @Entry annotation
Example base usage
@Entry(EntryType.PUBLISHER)
public int basicInteger = 1;Without specifying the key using the @Key annotation, the default is Enclosing Class/Field Name.
In this example, if the class the field was defined in was named ArmSubsystem then the final NetworkTables key would
be ArmSubsystem/basicInteger
The / in the key for NetworkTables specifies that it should use the table within the BadgerLog table named
ArmSubsystem and the entry named basicInteger.
There are 3 options to generate entries for NetworkTables. Publishers, Subscribers, and Sendables. They all have different specifications and do different things.
Publisher entries take the value on the field and put it to NetworkTables. Changing the field's value in code, changes
it on NetworkTables.
This can be used with any type of field except those with the value of Sendable
Subscriber entries take the value from NetworkTables and set the field's value to it. Changing the value on NetworkTables changes the field's value.
This can be used with any type of field except those with the value of Sendable and additionally, unlike publishers,
cannot be used with the STRUCT StructType option.
Sendable entries use the defined Sendable.init method to create associated entries and tables. Natively supports using
both publisher and subscriber options.
This can be used with only the Sendable (or subclasses of it) field type.
BadgerLog allows for a high level of customization of each entry. This is done also through annotations, but are always optional and have a global default if missing.
The @Key annotation allows for customization of the key used on NetworkTables.
Parameters: String - the key to use on NetworkTables instead of the generated one
Changes: Key on NetworkTables
Usage Example
@Entry(EntryType.SUBSCRIBER)
@Key("Auto/AutoWaitTime")
public double waitTime = 0;This creates a double entry under the Auto table named AutoWaitTime.
Using @Key removes the standard generation of the key from the field name and enclosing class
The @Key annotation additionally allows for instance specific keys in any portion of the key, referencing an instance
variable.
It is in the format of {Field Name}.
Usage Example
@Entry(EntryType.SUBSCRIBER)
@Key("Modules/{descriptor}/Module P")
public double moduleP = 0;
private String descriptor;
public SwerveModule(/*Other parameters */, String descriptor) {
// Other initialization code
this.descriptor = descriptor;
}This would create a new entry for every instance of the SwerveModule class. The entry would be under both the
Modules
table and the table with the name of descriptor.
The {Field Name} must match the field name exactly as defined in the class.
The @StructType annotation allows for customization of how a Struct type entry is created.
See Wrappers for an explanation of each type.
Parameters: StructType - the type of struct entry to use
Changes: How a struct entry is created
Usage Example
@Entry(EntryType.PUBLISHER)
@Struct(StructType.STRUCT)
public Rotation2d rotation2d = Rotation2d.fromDegrees(1306);This would publish the struct as a value-struct, using the default NetworkTables implementation of the StructEntry.
This could be changed to StructOptions.SUB_TABLE for subtable publishing or StructOptions.MAPPING for mapping
publishing.
The @UnitConversion annotation allows units to be converted to a different form of the same unit.
Parameters:
-
String- the unit to convert to -
String converterId- (Optional) the id of the converter to use with a mapping. Defaults empty
Usage Example
@Entry(EntryType.PUBLISHER)
@UnitConversion("meters")
public Distance height = Inches.of(10);This publishes a double entry of the height converted to meters. Subscribing works the same way but in reverse. The unit
String can be any form of the unit, case-insensitive.
// These all work
@UnitConversion("m")
@UnitConversion("meter")
@UnitConversion("METERS")
@UnitConversion("M")The @UnitConversion annotation also allows for itself to be placed multiple times on a field to specify the converters
to use for a more complicated mapping. Examples include Pose2d, Pose3d, Twist2d, and Twist3d.
The converterId is always translation for distance types and rotation for rotation types. It is only ever used
when there are more than one unit to convert at a time.
Usage Example
@Entry(EntryType.SUBSCRIBER)
@UnitConversion(value = "in", converterId = "translation")
@UnitConversion(value = "radian", converterId = "rotation")
public Pose2d robotPose = Pose2d.kZero;This converts any distance to inches and any rotation to radians in the Pose2d
The @AutoGenerateStruct annotation allows a struct to be generated from a record or enum class.
It is used as a marker for BadgerLog to use the generated struct instead of a mapping.
Parameters: boolean (Optional) whether to generate the struct or not. Defaults true
Changes: Marks the field to have a struct auto generated for it
Usage Example
@Entry(EntryType.SUBSCRIBER)
@AutoGenerateStruct
public CustomRecord record = new CustomRecord("value", 3);
public record CustomRecord(String value, int count) {
}This will automatically generate a struct for this, allowing it to be used with BadgerLog's struct publishing options.
BadgerLog provides a bunch of utility methods to allow for some unique interactions with NetworkTables.
The putValue method acts similarly to the EntryType.PUBLISHER for annotations. The only difference is that it
doesn't automatically generate the configuration from annotations. Useful for one time logging of specific fields,
but not recommended.
Usage Example
public void execute() {
Dashboard.putValue("MoveArmCommand/Current Draw", /* the current draw */);
Dashboard.putValue("MoveArmCommand/Arm Angle", /* the current angle */,
new Configuration().withConverter("", UnitConversion.createConverter("degrees")));
}The getValue method acts similarly to the EntryType.SUBSCRIBER for annotations. The only difference is that it
doesn't automatically generate the configuration from annotations. Useful for one time retrieving of specific keys,
but not recommended.
Usage Example
public void periodic() {
int kG = Dashboard.getValue("Arm/kG", /* the initial value */);
int targetRotation = Dashboard.getValue("Arm/Target Rotation", /* initial rotation */,
new Configuration().withStructType(StructType.SUBTABLE));
}The putSendable method acts similarly to the EntryType.SENDABLE for annotations. There is almost no difference in
its use, except that it allows for publishing a Sendable within a method. putSendable may be called as many times as
desired with the same key. It will close and override the previous entry.
Usage Example
public void updateOdometry() {
Field2d field2d = new Field2d();
field2d.setRobotPose(/* pose data */);
Dashboard.putSendable("Field2d", field2d);
}The createSelectorFromEnum method allows an enum's constants to be published as a SendableChooser. It takes the name
of each constant, and publishes it as a string.
By default, it will use the first constant defined in the Enum class, but can be specified with the method
overload.
public Robot() {
Dashboard.createSelectorFromEnum("Robot/RobotModeSelector", RobotMode.class, RobotMode.AUTOMATIC,
(value) -> /* on changed */
);
}
public enum RobotMode {
MANUAL,
AUTOMATIC,
DISABLED
}The createNetworkTablesButton method allows a Trigger to be bound to a boolean on NetworkTables. The
createAutoResettingButton is similar, but resets back to false after being true for 0.25 seconds.
A special requirement of both methods: it cannot be called more than once with the same key
public Autos() {
Dashboard.createNetworkTablesButton("Auto/IgnoreWaitTime", CommandScheduler.getInstance().getDefaultButtonLoop())
.onTrue(/* some command */);
Dashboard.createAutoResettingButton("Auto/ResetOdometry", CommandScheduler.getInstance().getDefaultButtonLoop())
.onTrue(/* some command */);
}The removeNetworkTablesEntry method allows for the unpublishing of an entry. It removes the entry completely from
updating and NetworkTables.
BadgerLog contains wrappers around NetworkTables entries to enable more customization and features.
Defined by ValueEntry. Enables the use of the mapping system, allows the conversion of any type into a valid
NetworkTables type.
Defined by StructValueEntry. Publishes the struct as is, using the NetworkTables struct implementation.
Does not work with Elastic (Support for structs doesn't exist).
Defined by SubtableEntry. Generates every entry needed to create a struct-like view. Creates relative tables for each
field defined in the struct.
Defined by SendableEntry. Registers the Sendable with the SendableRegistry and updates it.
-
Entries not appearing on NetworkTables:
-
Invalidated
-
Key specified wrong
-
Final field
-
Null field
-
Struct generated wrong
-
Invalid schema
-
Enum has invalid schema when autogenerated and using subtable publishing
-
Converter has default id when specified and multiple of them
-
Converter has invalid unit type
-
Converter has wrong id
-
Record references itself
-
Mapping doesn't exist for a type
-
Struct value doesn't let subscribing
Javadoc can be found on Jitpack