- FRC Game Manual
- FRC Game Q&A

# The C++ Units Library

WPILib is coupled with a Units library for C++ teams. This library leverages the C++ type system to enforce proper dimensionality for method parameters, automatically perform unit conversions, and even allow users to define arbitrary defined unit types. Since the C++ type system is enforced at compile-time, the library has essentially no runtime cost.

## Using the Units Library

The units library is a header-only library. You must include the relevant header in your source files for the units you want to use. Here’s a list of available units.

    #include <units/acceleration.h>
    #include <units/angle.h>
    #include <units/angular_acceleration.h>
    #include <units/angular_velocity.h>
    #include <units/area.h>
    #include <units/capacitance.h>
    #include <units/charge.h>
    #include <units/concentration.h>
    #include <units/conductance.h>
    #include <units/current.h>
    #include <units/curvature.h>
    #include <units/data.h>
    #include <units/data_transfer_rate.h>
    #include <units/density.h>
    #include <units/dimensionless.h>
    #include <units/energy.h>
    #include <units/force.h>
    #include <units/frequency.h>
    #include <units/illuminance.h>
    #include <units/impedance.h>
    #include <units/inductance.h>
    #include <units/length.h>
    #include <units/luminous_flux.h>
    #include <units/luminous_intensity.h>
    #include <units/magnetic_field_strength.h>
    #include <units/magnetic_flux.h>
    #include <units/mass.h>
    #include <units/moment_of_inertia.h>
    #include <units/power.h>
    #include <units/pressure.h>
    #include <units/radiation.h>
    #include <units/solid_angle.h>
    #include <units/substance.h>
    #include <units/temperature.h>
    #include <units/time.h>
    #include <units/torque.h>
    #include <units/velocity.h>
    #include <units/voltage.h>
    #include <units/volume.h>

The `units/math.h` header provides unit-aware functions like `units::math::abs()`.

### Unit Types and Container Types

The C++ units library is based around two sorts of type definitions: unit types and container types.

#### Unit Types

Unit types correspond to the abstract concept of a unit, without any actual stored value. Unit types are the fundamental “building block” of the units library - all unit types are defined constructively (using the `compound_unit` template) from a small number of “basic” unit types (such as `meters`, `seconds`, etc).

While unit types cannot contain numerical values, their use in building other unit types means that when a type or method uses a template parameter to specify its dimensionality, that parameter will be a unit type.

#### Container Types

Container types correspond to an actual quantity dimensioned according to some unit - that is, they are what actually hold the numerical value. Container types are constructed from unit types with the `unit_t` template. Most unit types have a corresponding container type that has the same name suffixed by `_t` - for example, the unit type `units::meter` corresponds to the container type `units::meter_t`.

Whenever a specific quantity of a unit is used (as a variable or a method parameter), it will be an instance of the container type. By default, container types will store the actual value as a `double` - advanced users may change this by calling the `unit_t` template manually.

A full list of unit and container types can be found in the documentation.

### Creating Instances of Units

To create an instance of a specific unit, we create an instance of its container type:

    // The variable speed has a value of 5 meters per second.
    units::meters_per_second_t speed{5.0};

Alternatively, the units library has type literals defined for some of the more common container types. These can be used in conjunction with type inference via `auto` to define a unit more succinctly:

    // The variable speed has a value of 5 meters per second.
    auto speed = 5_mps;

Units can also be initialized using a value of an another container type, as long as the types can be converted between one another. For example, a `meter_t` value can be created from a `foot_t` value.

    auto feet = 6_ft;
    units::meter_t meters{feet};

In fact, all container types representing convertible unit types are implicitly convertible. Thus, the following is perfectly legal:

    units::meter_t distance = 6_ft;

In short, we can use any unit of length in place of any other unit of length, anywhere in our code; the units library will automatically perform the correct conversion for us.

### Performing Arithmetic with Units

Container types support all of the ordinary arithmetic operations of their underlying data type, with the added condition that the operation must be dimensionally sound. Thus, addition must always be performed on two compatible container types:

    // Add two meter_t values together
    auto sum = 5_m + 7_m; // sum is 12_m
    // Adds meters to feet; both are length, so this is fine
    auto sum = 5_m + 7_ft;
    // Tries to add a meter_t to a second_t, will throw a compile-time error
    auto sum = 5_m + 7_s;

Multiplication may be performed on any pair of container types, and yields the container type of a compound unit:

Note

When a calculation yields a compound unit type, this type will only be checked for validity at the point of operation if the result type is specified explicitly. If `auto` is used, this check will not occur. For example, when we divide distance by time, we may want to ensure the result is, indeed, a velocity (i.e. `units::meters_per_second_t`). If the return type is declared as `auto`, this check will not be made.

    // Multiply two meter_t values, result is square_meter_t
    auto product = 5_m * 7_m; // product is 35_sq_m

    // Divide a meter_t value by a second_t, result is a meter_per_second_t
    units::meters_per_second_t speed = 6_m / 0.5_s; // speed is 12_mps

### `<cmath>` Functions

Some `std` functions (such as `clamp`) are templated to accept any type on which the arithmetic operations can be performed. Quantities stored as container types will work with these functions without issue.

However, other `std` functions work only on ordinary numerical types (e.g. `double`). The units library’s `units::math` namespace contains wrappers for several of these functions that accept units. Examples of such functions include `sqrt`, `pow`, etc.

    auto area = 36_sq_m;
    units::meter_t sideLength = units::math::sqrt(area);

### Removing the Unit Wrapper

To convert a container type to its underlying value, use the `value()` method. This serves as an escape hatch from the units type system, which should be used only when necessary.

    units::meter_t distance = 6.5_m;
    double distanceMeters = distance.value();

## Example of the Units Library in WPILib Code

Several arguments for methods in new features of WPILib (ex. kinematics) use the units library. Here is an example of sampling a trajectory.

    // Sample the trajectory at 1.2 seconds. This represents where the robot
    // should be after 1.2 seconds of traversal.
    Trajectory::State point = trajectory.Sample(1.2_s);
    // Since units of time are implicitly convertible, this is exactly equivalent to the above code
    Trajectory::State point = trajectory.Sample(1200_ms);

Some WPILib classes represent objects that could naturally work with multiple choices of unit types - for example, a motion profile might operate on either linear distance (e.g. meters) or angular distance (e.g. radians). For such classes, the unit type is required as a template parameter:

    // Creates a new set of trapezoidal motion profile constraints
    // Max velocity of 10 meters per second
    // Max acceleration of 20 meters per second squared
    frc::TrapezoidProfile<units::meters>::Constraints{10_mps, 20_mps_sq};
    // Creates a new set of trapezoidal motion profile constraints
    // Max velocity of 10 radians per second
    // Max acceleration of 20 radians per second squared
    frc::TrapezoidProfile<units::radians>::Constraints{10_rad_per_s, 20__rad_per_s / 1_s};

For more detailed documentation, please visit the official GitHub page for the units library.