// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. package edu.wpi.first.units; import static edu.wpi.first.units.Units.Value; import edu.wpi.first.units.measure.Acceleration; import edu.wpi.first.units.measure.Angle; import edu.wpi.first.units.measure.AngularAcceleration; import edu.wpi.first.units.measure.AngularMomentum; import edu.wpi.first.units.measure.AngularVelocity; import edu.wpi.first.units.measure.Current; import edu.wpi.first.units.measure.Dimensionless; import edu.wpi.first.units.measure.Distance; import edu.wpi.first.units.measure.Energy; import edu.wpi.first.units.measure.Force; import edu.wpi.first.units.measure.Frequency; import edu.wpi.first.units.measure.LinearAcceleration; import edu.wpi.first.units.measure.LinearMomentum; import edu.wpi.first.units.measure.LinearVelocity; import edu.wpi.first.units.measure.Mass; import edu.wpi.first.units.measure.MomentOfInertia; import edu.wpi.first.units.measure.Mult; import edu.wpi.first.units.measure.Per; import edu.wpi.first.units.measure.Power; import edu.wpi.first.units.measure.Resistance; import edu.wpi.first.units.measure.Temperature; import edu.wpi.first.units.measure.Time; import edu.wpi.first.units.measure.Torque; import edu.wpi.first.units.measure.Velocity; import edu.wpi.first.units.measure.Voltage; /** * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. Two * measures with the same unit and magnitude are effectively equivalent objects. * * @param the unit type of the measure */ public interface Measure extends Comparable> { /** * The threshold for two measures to be considered equivalent if converted to the same unit. This * is only needed due to floating-point error. */ double EQUIVALENCE_THRESHOLD = 1e-12; /** * Gets the unitless magnitude of this measure. * * @return the magnitude in terms of {@link #unit() the unit}. */ double magnitude(); /** * Gets the magnitude of this measure in terms of the base unit. If the unit is the base unit for * its system of measure, then the value will be equivalent to {@link #magnitude()}. * * @return the magnitude in terms of the base unit */ double baseUnitMagnitude(); /** * Gets the units of this measure. * * @return the unit */ U unit(); /** * Converts this measure to a measure with a different unit of the same type, eg minutes to * seconds. Converting to the same unit is equivalent to calling {@link #magnitude()}. * *
   *   Meters.of(12).in(Feet) // 39.3701
   *   Seconds.of(15).in(Minutes) // 0.25
   * 
* * @param unit the unit to convert this measure to * @return the value of this measure in the given unit */ default double in(U unit) { if (this.unit().equals(unit)) { return magnitude(); } else { return unit.fromBaseUnits(baseUnitMagnitude()); } } /** * A convenience method to get the base unit of the measurement. Equivalent to {@code * unit().getBaseUnit()}. * * @return the base unit of measure. */ @SuppressWarnings("unchecked") default U baseUnit() { return (U) unit().getBaseUnit(); } /** * Absolute value of measure. * * @param unit unit to use * @return the absolute value of this measure in the given unit */ default double abs(U unit) { return Math.abs(this.in(unit)); } /** * Take the sign of another measure. * * @param other measure from which to take sign * @param unit unit to use * @return the value of the measure in the given unit with the sign of the provided measure */ default double copySign(Measure other, U unit) { return Math.copySign(this.in(unit), other.in(unit)); } /** * Returns an immutable copy of this measure. The copy can be used freely and is guaranteed never * to change. * * @return the copied measure */ Measure copy(); /** * Returns a mutable copy of this measure. It will be initialized to the current state of this * measure, but can be changed over time without needing to allocate new measurement objects. * * @return the copied measure */ MutableMeasure mutableCopy(); /** * Returns a measure equivalent to this one equal to zero minus its current value. For non-linear * unit types like temperature, the zero point is treated as the zero value of the base unit (eg * Kelvin). In effect, this means code like {@code Celsius.of(10).unaryMinus()} returns a value * equivalent to -10 Kelvin, and not -10° Celsius. * * @return a measure equal to zero minus this measure */ Measure unaryMinus(); /** * Returns a measure equivalent to this one equal to zero minus its current value. For non-linear * unit types like temperature, the zero point is treated as the zero value of the base unit (eg * Kelvin). In effect, this means code like {@code Celsius.of(10).negate()} returns a value * equivalent to -10 Kelvin, and not -10° Celsius. * * @return a measure equal to zero minus this measure * @deprecated use unaryMinus() instead. This was renamed for consistancy with other WPILib * classes like Rotation2d */ @Deprecated(since = "2025", forRemoval = true) default Measure negate() { return unaryMinus(); } /** * Adds another measure of the same unit type to this one. * * @param other the measurement to add * @return a measure of the sum of both measures */ Measure plus(Measure other); /** * Subtracts another measure of the same unit type from this one. * * @param other the measurement to subtract * @return a measure of the difference between the measures */ Measure minus(Measure other); /** * Multiplies this measure by a scalar unitless multiplier. * * @param multiplier the scalar multiplication factor * @return the scaled result */ Measure times(double multiplier); /** * Multiplies this measure by a scalar dimensionless multiplier. * * @param multiplier the scalar multiplication factor * @return the scaled result */ Measure times(Dimensionless multiplier); /** * Generates a new measure that is equal to this measure multiplied by another. Some dimensional * analysis is performed to reduce the units down somewhat; for example, multiplying a {@code * Measure