Units¶
TelemetryKit supports unit metadata for AdvantageScope's unit-aware graphing and seamless integration with WPILib's units library.
Overview¶
Unit metadata allows AdvantageScope to:
- Display values with their proper units (e.g., "3.5 m/s")
- Convert between compatible units when graphing
- Provide better context for logged values
TelemetryKit provides two approaches for unit metadata:
- Manual unit strings - Specify unit abbreviations as strings
- WPILib units integration - Automatic unit extraction from
units::unit_ttypes
Manual Unit Strings¶
Specify unit metadata as a third parameter when logging:
#include <telemetrykit/core/Logger.h>
// Global convenience function
tkit::RecordOutput("/Speed", 3.5, "m/s");
tkit::RecordOutput("/Angle", 1.57, "radians");
tkit::RecordOutput("/Current", 42.0, "amps");
// Or via Logger instance
auto& logger = tkit::Logger::GetInstance();
logger.RecordOutput("/Distance", 5.0, "meters");
LogTable with Units¶
Units work with LogTable as well:
tkit::LogTable table;
table.Put("/Speed", 3.5, "m/s");
table.Put("/Angle", 1.57, "radians");
// Retrieve unit metadata
std::string unit = table.GetUnit("/Speed"); // Returns "m/s"
// Get all units in the table
auto allUnits = table.GetAllUnits();
// Returns: {"/Speed" -> "m/s", "/Angle" -> "radians"}
Subtables with Units¶
Units are preserved through subtables:
tkit::LogTable rootTable;
auto gyroTable = rootTable.GetSubtable("/Gyro");
gyroTable.Put("Yaw", 45.0, "degrees");
gyroTable.Put("Pitch", 10.0, "degrees");
// Units accessible from root table
rootTable.GetUnit("/Gyro/Yaw"); // Returns "degrees"
WPILib Units Integration¶
For automatic unit extraction from WPILib unit types, include the Units header:
#include <telemetrykit/core/Units.h>
// WPILib units headers
#include <units/length.h>
#include <units/velocity.h>
#include <units/angle.h>
RecordOutput with Unit Types¶
The tkit::RecordOutput function is overloaded for WPILib unit types:
#include <telemetrykit/core/Units.h>
#include <units/length.h>
#include <units/velocity.h>
#include <units/angle.h>
#include <units/voltage.h>
// Automatic unit extraction
tkit::RecordOutput("/Distance", units::meter_t{3.5});
// Logs 3.5 with unit "m"
tkit::RecordOutput("/Angle", units::degree_t{90.0});
// Logs 90.0 with unit "deg"
tkit::RecordOutput("/Speed", units::meters_per_second_t{2.5});
// Logs 2.5 with unit "mps"
tkit::RecordOutput("/Voltage", units::volt_t{12.6});
// Logs 12.6 with unit "V"
Put with Unit Types¶
Use tkit::Put helper for LogTable operations:
#include <telemetrykit/core/Units.h>
tkit::LogTable table;
// Automatic unit extraction
tkit::Put(table, "/Distance", units::meter_t{5.0});
tkit::Put(table, "/Angle", units::degree_t{45.0});
tkit::Put(table, "/Speed", units::meters_per_second_t{3.5});
// Verify units were set
table.GetUnit("/Distance"); // Returns "m"
table.GetUnit("/Angle"); // Returns "deg"
table.GetUnit("/Speed"); // Returns "mps"
Subtables with Unit Types¶
tkit::LogTable rootTable;
auto driveTable = rootTable.GetSubtable("/Drive");
tkit::Put(driveTable, "LeftVelocity", units::meters_per_second_t{2.0});
tkit::Put(driveTable, "RightVelocity", units::meters_per_second_t{2.1});
// Units accessible from root table
rootTable.GetUnit("/Drive/LeftVelocity"); // Returns "mps"
Supported Unit Types¶
TelemetryKit works with any WPILib unit type. See the WPILib Units Documentation for the full list of available types.
WPILib Abbreviations
Unit abbreviations come from WPILib's units::abbreviation() function. Some may differ from common notation (e.g., "mps" instead of "m/s", "rad_per_s" instead of "rad/s").
How It Works¶
TelemetryKit uses a C++20 concept to detect WPILib unit types at compile time:
template<typename T>
concept UnitType = requires(T t) {
{ t.value() } -> std::convertible_to<double>;
typename T::unit_type;
};
When a unit type is detected:
value.value()extracts the numeric valueunits::abbreviation(T{})gets the unit string- Both are passed to the standard logging functions
template<UnitType T>
inline void RecordOutput(std::string_view key, const T& value) {
std::string unit = detail::GetUnitAbbreviation<T>();
Logger::GetInstance().RecordOutput(key, value.value(), unit);
}
Real-World Example¶
#include <telemetrykit/core/Units.h>
#include <telemetrykit/core/Logger.h>
#include <units/length.h>
#include <units/velocity.h>
#include <units/angle.h>
#include <units/voltage.h>
#include <units/current.h>
class DriveSubsystem {
public:
void Periodic() {
// Get sensor readings as unit types
auto leftVelocity = m_leftEncoder.GetVelocity(); // units::meters_per_second_t
auto rightVelocity = m_rightEncoder.GetVelocity(); // units::meters_per_second_t
auto gyroAngle = m_gyro.GetYaw(); // units::degree_t
// Log with automatic unit extraction
tkit::RecordOutput("/Drive/LeftVelocity", leftVelocity);
tkit::RecordOutput("/Drive/RightVelocity", rightVelocity);
tkit::RecordOutput("/Drive/GyroAngle", gyroAngle);
// Motor diagnostics
tkit::RecordOutput("/Drive/LeftMotor/Voltage", m_leftMotor.GetVoltage());
tkit::RecordOutput("/Drive/LeftMotor/Current", m_leftMotor.GetCurrent());
}
};
In AdvantageScope, these values will display with their proper units and support unit-aware graphing features.
Unit Metadata in WPILOG¶
Unit metadata is stored in the WPILOG file's entry metadata as JSON:
This allows AdvantageScope to read and use the unit information when loading log files.
Next Steps¶
- Learn about LogValue for all supported types
- See Struct Logging for WPILib geometry types
- Check out Examples for practical usage patterns