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