Skip to content

Tunable values

DogLog's tunable values feature leverages NetworkTables to stream strings, numbers, and booleans to your robot code, making it easy to tweak robot behavior without needing to redeploy code.

Creating a tunable value

You can create a tunable value by calling DogLog.tunable() and providing a key for the value in NetworkTables, and a default value.

// Create a tunable double with a key of "Intake/Voltage" and a default value of 4.5
private final DoubleSubscriber voltage = DogLog.tunable("Intake/Voltage", 4.5);

Creating a tunable value will return a NetworkTables Subscriber used for accessing the tunable value.

Once a tunable value is created, DogLog will continuously log its value to the Robot/Tunable/ table in the robot DataLog.

Reading a tunable value

Once you've created a tunable value, you can read the value from the NetworkTables entry like so:

tunable.get();

At competitions

Tunable values are great for speeding up development at home, but at competitions it's best to avoid relying on NetworkTables for core robot functionality. By default, DogLog will ignore tunable values from NetworkTables when connected to the FMS on a competition field.

You can customize this behavior with the ntTunables option in DogLogOptions.

When ntTunables is disabled, reading the value of a tunable will return the default value.

On change callbacks

In addition to periodically polling the latest value of a tunable, you can also register a consumer function to be called whenever the value changes.

private final DoubleSubscriber voltage = DogLog.tunable("Intake/Voltage", 4, newVoltage -> {
motor.setVoltage(newVoltage);
});

One callback can be registered per tunable value. When the value is changed, the provided function will be called with the updated value of the tunable.

Changing a tunable value

Once a tunable value is created in code, you can change the value via NetworkTables.

Tunable values are published under the "Tunable/" table in NetworkTables. So, a tunable value with a key of Intake/Voltage would be published under the Tunable/Intake/Voltage key.

Here are some examples of how to change a tunable value using various popular FRC dashboards:

Full example

Here's a full example of how you can use tunable values to configure PID for a TalonFX without needing to redeploy code:

src/main/java/frc/robot/TunablePid.java
package frc.robot;
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.hardware.TalonFX;
import dev.doglog.DogLog;
public class TunablePid {
public static void create(String key, TalonFX motor, TalonFXConfiguration defaultConfig) {
DogLog.tunable(key + "/kP", defaultConfig.Slot0.kP, newP ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKP(newP))
);
DogLog.tunable(key + "/kI", defaultConfig.Slot0.kI, newI ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKI(newI))
);
DogLog.tunable(key + "/kD", defaultConfig.Slot0.kD, newD ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKD(newD))
);
DogLog.tunable(key + "/kS", defaultConfig.Slot0.kS, newS ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKS(newS))
);
DogLog.tunable(key + "/kV", defaultConfig.Slot0.kV, newV ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKV(newV))
);
DogLog.tunable(key + "/kA", defaultConfig.Slot0.kA, newA ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKA(newA))
);
DogLog.tunable(key + "/kG", defaultConfig.Slot0.kG, newG ->
motor.getConfigurator().apply(defaultConfig.Slot0.withKG(newG))
);
}
private TunablePid() {}
}

You can use this TunablePid class like so:

TunablePid.create("Elevator", elevatorMotor, new TalonFXConfiguration());