[wpiunits] Add Measure.divide(Measure<U2>) (#6611)

This commit is contained in:
Wispy
2024-05-15 08:22:38 -05:00
committed by GitHub
parent b0d3bf4ddf
commit 7fbbecb5b7
5 changed files with 75 additions and 11 deletions

View File

@@ -137,16 +137,29 @@ public interface Measure<U extends Unit<U>> extends Comparable<Measure<U>> {
}
/**
* Divides this measurement by some constant divisor and returns the result. This is equivalent to
* {@code divide(divisor.baseUnitMagnitude())}
* Divides this measurement by another measure and performs some dimensional analysis to reduce
* the units.
*
* @param divisor the dimensionless measure to divide by
* @param <U2> the type of the other measure to multiply by
* @param other the unit to multiply by
* @return the resulting measure
* @see #divide(double)
* @see #times(double)
*/
default Measure<U> divide(Measure<Dimensionless> divisor) {
return divide(divisor.baseUnitMagnitude());
default <U2 extends Unit<U2>> Measure<?> divide(Measure<U2> other) {
if (unit().getBaseUnit().equals(other.unit().getBaseUnit())) {
return Units.Value.ofBaseUnits(baseUnitMagnitude() / other.baseUnitMagnitude());
}
if (other.unit() instanceof Dimensionless) {
return divide(other.baseUnitMagnitude());
}
if (other.unit() instanceof Velocity<?> velocity
&& velocity.getUnit().getBaseUnit().equals(unit().getBaseUnit())) {
return times(velocity.reciprocal().ofBaseUnits(1 / other.baseUnitMagnitude()));
}
if (other.unit() instanceof Per<?, ?> per
&& per.numerator().getBaseUnit().equals(unit().getBaseUnit())) {
return times(per.reciprocal().ofBaseUnits(1 / other.baseUnitMagnitude()));
}
return unit().per(other.unit()).ofBaseUnits(baseUnitMagnitude() / other.baseUnitMagnitude());
}
/**

View File

@@ -109,6 +109,15 @@ public class Per<N extends Unit<N>, D extends Unit<D>> extends Unit<Per<N, D>> {
return m_denominator;
}
/**
* Returns the reciprocal of this Per.
*
* @return the reciprocal
*/
public Per<D, N> reciprocal() {
return m_denominator.per(m_numerator);
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -157,6 +157,15 @@ public class Velocity<D extends Unit<D>> extends Unit<Velocity<D>> {
return m_period;
}
/**
* Returns the reciprocal of this velocity.
*
* @return the reciprocal
*/
public Per<Time, D> reciprocal() {
return m_period.per(m_unit);
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -7,7 +7,6 @@ package edu.wpi.first.units;
import static edu.wpi.first.units.Units.Inches;
import static edu.wpi.first.units.Units.Revolutions;
import static edu.wpi.first.units.Units.Second;
import static edu.wpi.first.units.Units.Value;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
@@ -46,14 +45,14 @@ class EncoderTest {
@Test
void testAsDistance() {
var ticksPerRevolution = Value.of(2048);
double ticksPerRevolution = 2048;
var encoder = new Encoder<Distance>();
// distance per rotation = (wheel circumference / gear ratio)
// distance per tick = distance per rotation / ticks per rotation
var wheelDiameter = Inches.of(6);
var gearRatio = Value.of(10); // 10:1 ratio
double gearRatio = 10; // 10:1 ratio
Measure<Distance> distancePerPulse =
wheelDiameter.times(Math.PI).divide(gearRatio).divide(ticksPerRevolution);
encoder.setDistancePerPulse(distancePerPulse);
@@ -74,7 +73,7 @@ class EncoderTest {
@Test
void testAsRevolutions() {
var ticksPerRevolution = Value.of(2048);
double ticksPerRevolution = 2048;
var encoder = new Encoder<Angle>();

View File

@@ -162,6 +162,40 @@ class MeasureTest {
assertEquals(exampleUnit.of(42 * 17 / (12 * 25.4)), m3.times(m4));
}
@Test
void testDivideMeasure() {
// Dimensionless divide
var m1 = Units.Meters.of(6);
var m2 = Units.Value.of(3);
var result = m1.divide(m2);
assertEquals(m1.divide(m2).magnitude(), 2);
assertEquals(result.unit(), Units.Meters);
// Velocity divide
var m3 = Units.Meters.of(8);
var m4 = Units.Meters.per(Units.Second).of(4);
result = m3.divide(m4);
assertEquals(result.magnitude(), 2);
assertEquals(result.unit(), Units.Second);
// Per divide
var m5 = Units.Volts.of(6);
var m6 = Units.Volts.per(Units.Meter).of(2);
result = m5.divide(m6);
assertEquals(result.magnitude(), 3);
assertEquals(result.unit(), Units.Meter);
// Fallthrough divide
var m7 = Units.Seconds.of(10);
var m8 = Units.Amps.of(2);
result = m7.divide(m8);
assertEquals(result.magnitude(), 5);
assertEquals(result.unit(), Units.Seconds.per(Units.Amps));
// Same base unit divide
var m9 = Units.Meters.of(8);
var m10 = Units.Meters.of(4);
result = m9.divide(m10);
assertEquals(result.magnitude(), 2);
assertEquals(result.unit(), Units.Value);
}
@Test
void testToShortString() {
var measure = Units.Volts.of(343);