001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.units; 006 007import static edu.wpi.first.units.Units.Seconds; 008 009/** 010 * A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. Two 011 * measures with the same <i>unit</i> and <i>magnitude</i> are effectively equivalent objects. 012 * 013 * @param <U> the unit type of the measure 014 */ 015public interface Measure<U extends Unit<U>> extends Comparable<Measure<U>> { 016 /** 017 * The threshold for two measures to be considered equivalent if converted to the same unit. This 018 * is only needed due to floating-point error. 019 */ 020 double EQUIVALENCE_THRESHOLD = 1e-12; 021 022 /** 023 * Gets the unitless magnitude of this measure. 024 * 025 * @return the magnitude in terms of {@link #unit() the unit}. 026 */ 027 double magnitude(); 028 029 /** 030 * Gets the magnitude of this measure in terms of the base unit. If the unit is the base unit for 031 * its system of measure, then the value will be equivalent to {@link #magnitude()}. 032 * 033 * @return the magnitude in terms of the base unit 034 */ 035 double baseUnitMagnitude(); 036 037 /** 038 * Gets the units of this measure. 039 * 040 * @return the unit 041 */ 042 U unit(); 043 044 /** 045 * Converts this measure to a measure with a different unit of the same type, eg minutes to 046 * seconds. Converting to the same unit is equivalent to calling {@link #magnitude()}. 047 * 048 * <pre> 049 * Meters.of(12).in(Feet) // 39.3701 050 * Seconds.of(15).in(Minutes) // 0.25 051 * </pre> 052 * 053 * @param unit the unit to convert this measure to 054 * @return the value of this measure in the given unit 055 */ 056 default double in(Unit<U> unit) { 057 if (this.unit().equals(unit)) { 058 return magnitude(); 059 } else { 060 return unit.fromBaseUnits(baseUnitMagnitude()); 061 } 062 } 063 064 /** 065 * Multiplies this measurement by some constant multiplier and returns the result. The magnitude 066 * of the result will be the <i>base</i> magnitude multiplied by the scalar value. If the measure 067 * uses a unit with a non-linear relation to its base unit (such as Fahrenheit for temperature), 068 * then the result will only be a multiple <i>in terms of the base unit</i>. 069 * 070 * @param multiplier the constant to multiply by 071 * @return the resulting measure 072 */ 073 default Measure<U> times(double multiplier) { 074 return ImmutableMeasure.ofBaseUnits(baseUnitMagnitude() * multiplier, unit()); 075 } 076 077 /** 078 * Generates a new measure that is equal to this measure multiplied by another. Some dimensional 079 * analysis is performed to reduce the units down somewhat; for example, multiplying a {@code 080 * Measure<Time>} by a {@code Measure<Velocity<Distance>>} will return just a {@code 081 * Measure<Distance>} instead of the naive {@code Measure<Mult<Time, Velocity<Distance>>}. This is 082 * not guaranteed to perform perfect dimensional analysis. 083 * 084 * @param <U2> the type of the other measure to multiply by 085 * @param other the unit to multiply by 086 * @return the multiplicative unit 087 */ 088 @SuppressWarnings("unchecked") 089 default <U2 extends Unit<U2>> Measure<?> times(Measure<U2> other) { 090 if (other.unit() instanceof Dimensionless) { 091 // scalar multiplication 092 return times(other.baseUnitMagnitude()); 093 } 094 095 if (unit() instanceof Per 096 && other.unit().getBaseUnit().equals(((Per<?, ?>) unit()).denominator().getBaseUnit())) { 097 // denominator of the Per cancels out, return with just the units of the numerator 098 Unit<?> numerator = ((Per<?, ?>) unit()).numerator(); 099 return numerator.ofBaseUnits(baseUnitMagnitude() * other.baseUnitMagnitude()); 100 } else if (unit() instanceof Velocity && other.unit().getBaseUnit().equals(Seconds)) { 101 // Multiplying a velocity by a time, return the scalar unit (eg Distance) 102 Unit<?> numerator = ((Velocity<?>) unit()).getUnit(); 103 return numerator.ofBaseUnits(baseUnitMagnitude() * other.baseUnitMagnitude()); 104 } else if (other.unit() instanceof Per 105 && unit().getBaseUnit().equals(((Per<?, ?>) other.unit()).denominator().getBaseUnit())) { 106 Unit<?> numerator = ((Per<?, ?>) other.unit()).numerator(); 107 return numerator.ofBaseUnits(baseUnitMagnitude() * other.baseUnitMagnitude()); 108 } else if (unit() instanceof Per 109 && other.unit() instanceof Per 110 && ((Per<?, ?>) unit()) 111 .denominator() 112 .getBaseUnit() 113 .equals(((Per<?, U>) other.unit()).numerator().getBaseUnit()) 114 && ((Per<?, ?>) unit()) 115 .numerator() 116 .getBaseUnit() 117 .equals(((Per<?, ?>) other.unit()).denominator().getBaseUnit())) { 118 // multiplying eg meters per second * milliseconds per foot 119 // return a scalar 120 return Units.Value.of(baseUnitMagnitude() * other.baseUnitMagnitude()); 121 } 122 123 // Dimensional analysis fallthrough, do a basic unit multiplication 124 return unit().mult(other.unit()).ofBaseUnits(baseUnitMagnitude() * other.baseUnitMagnitude()); 125 } 126 127 /** 128 * Divides this measurement by some constant divisor and returns the result. This is equivalent to 129 * {@code times(1 / divisor)} 130 * 131 * @param divisor the constant to divide by 132 * @return the resulting measure 133 * @see #times(double) 134 */ 135 default Measure<U> divide(double divisor) { 136 return times(1 / divisor); 137 } 138 139 /** 140 * Divides this measurement by another measure and performs some dimensional analysis to reduce 141 * the units. 142 * 143 * @param <U2> the type of the other measure to multiply by 144 * @param other the unit to multiply by 145 * @return the resulting measure 146 */ 147 default <U2 extends Unit<U2>> Measure<?> divide(Measure<U2> other) { 148 if (unit().getBaseUnit().equals(other.unit().getBaseUnit())) { 149 return Units.Value.ofBaseUnits(baseUnitMagnitude() / other.baseUnitMagnitude()); 150 } 151 if (other.unit() instanceof Dimensionless) { 152 return divide(other.baseUnitMagnitude()); 153 } 154 if (other.unit() instanceof Velocity<?> velocity 155 && velocity.getUnit().getBaseUnit().equals(unit().getBaseUnit())) { 156 return times(velocity.reciprocal().ofBaseUnits(1 / other.baseUnitMagnitude())); 157 } 158 if (other.unit() instanceof Per<?, ?> per 159 && per.numerator().getBaseUnit().equals(unit().getBaseUnit())) { 160 return times(per.reciprocal().ofBaseUnits(1 / other.baseUnitMagnitude())); 161 } 162 return unit().per(other.unit()).ofBaseUnits(baseUnitMagnitude() / other.baseUnitMagnitude()); 163 } 164 165 /** 166 * Creates a velocity measure by dividing this one by a time period measure. 167 * 168 * <pre> 169 * Meters.of(1).per(Second) // Measure<Velocity<Distance>> 170 * </pre> 171 * 172 * @param period the time period to divide by. 173 * @return the velocity result 174 */ 175 default Measure<Velocity<U>> per(Measure<Time> period) { 176 var newUnit = unit().per(period.unit()); 177 return ImmutableMeasure.ofBaseUnits(baseUnitMagnitude() / period.baseUnitMagnitude(), newUnit); 178 } 179 180 /** 181 * Creates a relational measure equivalent to this one per some other unit. 182 * 183 * <pre> 184 * Volts.of(1.05).per(Meter) // V/m, potential PID constant 185 * </pre> 186 * 187 * @param <U2> the type of the denominator unit 188 * @param denominator the denominator unit being divided by 189 * @return the relational measure 190 */ 191 default <U2 extends Unit<U2>> Measure<Per<U, U2>> per(U2 denominator) { 192 var newUnit = unit().per(denominator); 193 return newUnit.of(magnitude()); 194 } 195 196 /** 197 * Creates a velocity measure equivalent to this one per a unit of time. 198 * 199 * <pre> 200 * Radians.of(3.14).per(Second) // Velocity<Angle> equivalent to RadiansPerSecond.of(3.14) 201 * </pre> 202 * 203 * @param time the unit of time 204 * @return the velocity measure 205 */ 206 default Measure<Velocity<U>> per(Time time) { 207 var newUnit = unit().per(time); 208 return newUnit.of(magnitude()); 209 } 210 211 /** 212 * Adds another measure to this one. The resulting measure has the same unit as this one. 213 * 214 * @param other the measure to add to this one 215 * @return a new measure containing the result 216 */ 217 default Measure<U> plus(Measure<U> other) { 218 return unit().ofBaseUnits(baseUnitMagnitude() + other.baseUnitMagnitude()); 219 } 220 221 /** 222 * Subtracts another measure from this one. The resulting measure has the same unit as this one. 223 * 224 * @param other the measure to subtract from this one 225 * @return a new measure containing the result 226 */ 227 default Measure<U> minus(Measure<U> other) { 228 return unit().ofBaseUnits(baseUnitMagnitude() - other.baseUnitMagnitude()); 229 } 230 231 /** 232 * Negates this measure and returns the result. 233 * 234 * @return the resulting measure 235 */ 236 default Measure<U> negate() { 237 return times(-1); 238 } 239 240 /** 241 * Returns an immutable copy of this measure. The copy can be used freely and is guaranteed never 242 * to change. 243 * 244 * @return the copied measure 245 */ 246 Measure<U> copy(); 247 248 /** 249 * Creates a new mutable copy of this measure. 250 * 251 * @return a mutable measure initialized to be identical to this measure 252 */ 253 default MutableMeasure<U> mutableCopy() { 254 return MutableMeasure.mutable(this); 255 } 256 257 /** 258 * Checks if this measure is near another measure of the same unit. Provide a variance threshold 259 * for use for a +/- scalar, such as 0.05 for +/- 5%. 260 * 261 * <pre> 262 * Inches.of(11).isNear(Inches.of(10), 0.1) // true 263 * Inches.of(12).isNear(Inches.of(10), 0.1) // false 264 * </pre> 265 * 266 * @param other the other measurement to compare against 267 * @param varianceThreshold the acceptable variance threshold, in terms of an acceptable +/- error 268 * range multiplier. Checking if a value is within 10% means a value of 0.1 should be passed; 269 * checking if a value is within 1% means a value of 0.01 should be passed, and so on. 270 * @return true if this unit is near the other measure, otherwise false 271 */ 272 default boolean isNear(Measure<?> other, double varianceThreshold) { 273 if (!this.unit().getBaseUnit().equivalent(other.unit().getBaseUnit())) { 274 return false; // Disjoint units, not compatible 275 } 276 277 // abs so negative inputs are calculated correctly 278 var tolerance = Math.abs(other.baseUnitMagnitude() * varianceThreshold); 279 280 return Math.abs(this.baseUnitMagnitude() - other.baseUnitMagnitude()) <= tolerance; 281 } 282 283 /** 284 * Checks if this measure is near another measure of the same unit, with a specified tolerance of 285 * the same unit. 286 * 287 * <pre> 288 * Meters.of(1).isNear(Meters.of(1.2), Millimeters.of(300)) // true 289 * Degrees.of(90).isNear(Rotations.of(0.5), Degrees.of(45)) // false 290 * </pre> 291 * 292 * @param other the other measure to compare against. 293 * @param tolerance the tolerance allowed in which the two measures are defined as near each 294 * other. 295 * @return true if this unit is near the other measure, otherwise false. 296 */ 297 default boolean isNear(Measure<U> other, Measure<U> tolerance) { 298 return Math.abs(this.baseUnitMagnitude() - other.baseUnitMagnitude()) 299 <= Math.abs(tolerance.baseUnitMagnitude()); 300 } 301 302 /** 303 * Checks if this measure is equivalent to another measure of the same unit. 304 * 305 * @param other the measure to compare to 306 * @return true if this measure is equivalent, false otherwise 307 */ 308 default boolean isEquivalent(Measure<?> other) { 309 if (!this.unit().getBaseUnit().equals(other.unit().getBaseUnit())) { 310 return false; // Disjoint units, not compatible 311 } 312 313 return Math.abs(baseUnitMagnitude() - other.baseUnitMagnitude()) <= EQUIVALENCE_THRESHOLD; 314 } 315 316 /** {@inheritDoc} */ 317 @Override 318 default int compareTo(Measure<U> o) { 319 return Double.compare(this.baseUnitMagnitude(), o.baseUnitMagnitude()); 320 } 321 322 /** 323 * Checks if this measure is greater than another measure of the same unit. 324 * 325 * @param o the other measure to compare to 326 * @return true if this measure has a greater equivalent magnitude, false otherwise 327 */ 328 default boolean gt(Measure<U> o) { 329 return compareTo(o) > 0; 330 } 331 332 /** 333 * Checks if this measure is greater than or equivalent to another measure of the same unit. 334 * 335 * @param o the other measure to compare to 336 * @return true if this measure has an equal or greater equivalent magnitude, false otherwise 337 */ 338 default boolean gte(Measure<U> o) { 339 return compareTo(o) > 0 || isEquivalent(o); 340 } 341 342 /** 343 * Checks if this measure is less than another measure of the same unit. 344 * 345 * @param o the other measure to compare to 346 * @return true if this measure has a lesser equivalent magnitude, false otherwise 347 */ 348 default boolean lt(Measure<U> o) { 349 return compareTo(o) < 0; 350 } 351 352 /** 353 * Checks if this measure is less than or equivalent to another measure of the same unit. 354 * 355 * @param o the other measure to compare to 356 * @return true if this measure has an equal or lesser equivalent magnitude, false otherwise 357 */ 358 default boolean lte(Measure<U> o) { 359 return compareTo(o) < 0 || isEquivalent(o); 360 } 361 362 /** 363 * Returns the measure with the absolute value closest to positive infinity. 364 * 365 * @param <U> the type of the units of the measures 366 * @param measures the set of measures to compare 367 * @return the measure with the greatest positive magnitude, or null if no measures were provided 368 */ 369 @SafeVarargs 370 static <U extends Unit<U>> Measure<U> max(Measure<U>... measures) { 371 if (measures.length == 0) { 372 return null; // nothing to compare 373 } 374 375 Measure<U> max = null; 376 for (Measure<U> measure : measures) { 377 if (max == null || measure.gt(max)) { 378 max = measure; 379 } 380 } 381 382 return max; 383 } 384 385 /** 386 * Returns the measure with the absolute value closest to negative infinity. 387 * 388 * @param <U> the type of the units of the measures 389 * @param measures the set of measures to compare 390 * @return the measure with the greatest negative magnitude 391 */ 392 @SafeVarargs 393 static <U extends Unit<U>> Measure<U> min(Measure<U>... measures) { 394 if (measures.length == 0) { 395 return null; // nothing to compare 396 } 397 398 Measure<U> max = null; 399 for (Measure<U> measure : measures) { 400 if (max == null || measure.lt(max)) { 401 max = measure; 402 } 403 } 404 405 return max; 406 } 407 408 /** 409 * Returns a string representation of this measurement in a shorthand form. The symbol of the 410 * backing unit is used, rather than the full name, and the magnitude is represented in scientific 411 * notation. 412 * 413 * @return the short form representation of this measurement 414 */ 415 default String toShortString() { 416 // eg 1.234e+04 V/m (1234 Volt per Meter in long form) 417 return String.format("%.3e %s", magnitude(), unit().symbol()); 418 } 419 420 /** 421 * Returns a string representation of this measurement in a longhand form. The name of the backing 422 * unit is used, rather than its symbol, and the magnitude is represented in a full string, not 423 * scientific notation. (Very large values may be represented in scientific notation, however) 424 * 425 * @return the long form representation of this measurement 426 */ 427 default String toLongString() { 428 // eg 1234 Volt per Meter (1.234e+04 V/m in short form) 429 return String.format("%s %s", magnitude(), unit().name()); 430 } 431}