diff --git a/wpiunits/generate_units.py b/wpiunits/generate_units.py
index 3f35152b61b..0e558316db6 100755
--- a/wpiunits/generate_units.py
+++ b/wpiunits/generate_units.py
@@ -77,7 +77,11 @@ def output(output_dir, outfn: str, contents: str):
},
"AngularVelocity": {
"base_unit": "RadiansPerSecond",
- "multiply": {"Time": "Angle", "Frequency": "AngularAcceleration"},
+ "multiply": {
+ "Time": "Angle",
+ "Frequency": "AngularAcceleration",
+ "Torque": "Power",
+ },
"divide": {"Time": "AngularAcceleration"},
"extra": inspect.cleandoc(
"""
@@ -222,7 +226,13 @@ def output(output_dir, outfn: str, contents: str):
"multiply": {
"Time": "Energy",
},
- "divide": {"Voltage": "Current", "Current": "Voltage", "Energy": "Frequency"},
+ "divide": {
+ "Voltage": "Current",
+ "Current": "Voltage",
+ "Energy": "Frequency",
+ "Torque": "AngularVelocity",
+ "AngularVelocity": "Torque",
+ },
},
"Resistance": {
"base_unit": "Ohms",
@@ -258,7 +268,7 @@ def output(output_dir, outfn: str, contents: str):
},
"Torque": {
"base_unit": "NewtonMeters",
- "multiply": {},
+ "multiply": {"AngularVelocity : Power"},
"divide": {"Distance": "Force", "Force": "Distance"},
},
"Velocity": {
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/AngularVelocityUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/AngularVelocityUnit.java
index 5a2f81b7610..a17d11c9f19 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/AngularVelocityUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/AngularVelocityUnit.java
@@ -4,6 +4,8 @@
package edu.wpi.first.units;
+import static edu.wpi.first.units.Units.Watts;
+
import edu.wpi.first.units.measure.AngularVelocity;
import edu.wpi.first.units.measure.ImmutableAngularVelocity;
import edu.wpi.first.units.measure.MutAngularVelocity;
@@ -72,6 +74,24 @@ public MutAngularVelocity mutable(double initialMagnitude) {
return new MutAngularVelocity(initialMagnitude, toBaseUnits(initialMagnitude), this);
}
+ /**
+ * Constructs a unit of power equivalent to this unit of angular velocity multiplied by another
+ * unit of torque. For example, {@code NewtonMeters.times(RadiansPerSecond)} will return a unit of
+ * power equivalent to one Watt.
+ *
+ * @param torque the unit of torque
+ * @param name the name of the resulting unit of power
+ * @param symbol the symbol used to represent the unit of power
+ * @return the power unit
+ */
+ public PowerUnit mult(TorqueUnit torque, String name, String symbol) {
+ double baseUnitEquivalent = torque.toBaseUnits(1) / this.toBaseUnits(1);
+ UnaryFunction toBaseConverter = x -> x * baseUnitEquivalent;
+ UnaryFunction fromBaseConverter = x -> x / baseUnitEquivalent;
+ PowerUnit powerUnit = new PowerUnit(Watts, toBaseConverter, fromBaseConverter, name, symbol);
+ return Units.derive(powerUnit).named(name).symbol(symbol).make();
+ }
+
@Override
public AngularAccelerationUnit per(TimeUnit period) {
return AngularAccelerationUnit.combine(this, period);
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/BaseUnits.java b/wpiunits/src/main/java/edu/wpi/first/units/BaseUnits.java
index 9794087d076..46098a376a8 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/BaseUnits.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/BaseUnits.java
@@ -25,15 +25,9 @@ private BaseUnits() {
/** The standard "unitless" unit. */
public static final DimensionlessUnit Value = new DimensionlessUnit(null, 1, ">", ">");
- /** The standard unit of voltage, volts. */
- public static final VoltageUnit VoltageUnit = new VoltageUnit(null, 1, "Volt", "V");
-
/** The standard unit of electric current, amperes. */
public static final CurrentUnit CurrentUnit = new CurrentUnit(null, 1, "Amp", "A");
- /** The standard unit of energy, joules. */
- public static final EnergyUnit EnergyUnit = new EnergyUnit(null, 1, "Joule", "J");
-
/** The standard unit of temperature, kelvin. */
public static final TemperatureUnit TemperatureUnit =
new TemperatureUnit(null, x -> x, x -> x, "Kelvin", "K");
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/CurrentUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/CurrentUnit.java
index e22ab54525f..339510707b6 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/CurrentUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/CurrentUnit.java
@@ -4,6 +4,8 @@
package edu.wpi.first.units;
+import static edu.wpi.first.units.Units.Watts;
+
import edu.wpi.first.units.measure.Current;
import edu.wpi.first.units.measure.ImmutableCurrent;
import edu.wpi.first.units.measure.MutCurrent;
@@ -43,12 +45,20 @@ public CurrentUnit getBaseUnit() {
* milliwatt, and so on.
*
* @param voltage the voltage unit to multiply by
- * @param name the name of the resulting unit of power
- * @param symbol the symbol used to represent the unit of power
* @return the power unit
*/
- public PowerUnit mult(VoltageUnit voltage, String name, String symbol) {
- return Units.derive(PowerUnit.combine(voltage, this)).named(name).symbol(symbol).make();
+ public PowerUnit mult(VoltageUnit voltage) {
+ double baseUnitEquivalent = voltage.toBaseUnits(1) * this.toBaseUnits(1);
+ UnaryFunction toBaseConverter = x -> x * baseUnitEquivalent;
+ UnaryFunction fromBaseConverter = x -> x / baseUnitEquivalent;
+ PowerUnit powerUnit =
+ new PowerUnit(
+ Watts,
+ toBaseConverter,
+ fromBaseConverter,
+ this.name() + "-" + voltage.name(),
+ this.symbol() + "*" + voltage.symbol());
+ return powerUnit;
}
@Override
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/DistanceUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/DistanceUnit.java
index df4c1ffee47..eb4866b1a16 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/DistanceUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/DistanceUnit.java
@@ -98,5 +98,13 @@ public TorqueUnit multAsTorque(ForceUnit force) {
return TorqueUnit.combine(this, force);
}
- // TODO: Add a multAsEnergy equivalent
+ /**
+ * Multiplies this distance unit by a unit of force to create a unit of energy.
+ *
+ * @param force the unit of force
+ * @return the combined energy unit
+ */
+ public EnergyUnit multAsEnergy(ForceUnit force) {
+ return EnergyUnit.combine(force, this);
+ }
}
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/EnergyUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/EnergyUnit.java
index 90a0be81efe..c3f234e1c03 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/EnergyUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/EnergyUnit.java
@@ -17,7 +17,19 @@
*
Actual units (such as {@link Units#Joules} and {@link Units#Kilojoules}) can be found in the
* {@link Units} class.
*/
-public final class EnergyUnit extends Unit {
+public final class EnergyUnit extends MultUnit {
+ private static final CombinatoryUnitCache cache =
+ new CombinatoryUnitCache<>(EnergyUnit::new);
+
+ EnergyUnit(ForceUnit force, DistanceUnit distance) {
+ super(
+ force.isBaseUnit() && distance.isBaseUnit()
+ ? null
+ : combine(force.getBaseUnit(), distance.getBaseUnit()),
+ force,
+ distance);
+ }
+
EnergyUnit(
EnergyUnit baseUnit,
UnaryFunction toBaseConverter,
@@ -27,46 +39,20 @@ public final class EnergyUnit extends Unit {
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
}
- EnergyUnit(EnergyUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
- super(baseUnit, baseUnitEquivalent, name, symbol);
- }
-
- @Override
- public EnergyUnit getBaseUnit() {
- return (EnergyUnit) super.getBaseUnit();
- }
-
- /**
- * Combines this unit of energy with a unit of time to create a unit of power.
- *
- * @param period the period of the change in energy
- * @return the combined unit of power
- */
- @Override
- public PowerUnit per(TimeUnit period) {
- return PowerUnit.combine(this, period);
- }
-
/**
- * Creates a ratio unit between this unit and an arbitrary other unit.
+ * Combines a force and distance to form a unit of energy.
*
- * @param other the other unit
- * @param the type of the other unit
- * @return the ratio unit
+ * @param force the unit of force
+ * @param distance the unit of distance
+ * @return the combined unit of energy
*/
- public PerUnit per(U other) {
- return PerUnit.combine(this, other);
+ public static EnergyUnit combine(ForceUnit force, DistanceUnit distance) {
+ return cache.combine(force, distance);
}
- /**
- * Converts a measurement value in terms of another unit to this unit.
- *
- * @param magnitude the magnitude of the measurement in terms of the other unit
- * @param otherUnit the other unit
- * @return the value of the measurement in terms of this unit
- */
- public double convertFrom(double magnitude, EnergyUnit otherUnit) {
- return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
+ @Override
+ public EnergyUnit getBaseUnit() {
+ return (EnergyUnit) super.getBaseUnit();
}
@Override
@@ -89,8 +75,41 @@ public Energy one() {
return (Energy) super.one();
}
+ /**
+ * Converts a measurement value in terms of another unit to this unit.
+ *
+ * @param magnitude the magnitude of the measurement in terms of the other unit
+ * @param otherUnit the other unit
+ * @return the value of the measurement in terms of this unit
+ */
+ public double convertFrom(double magnitude, EnergyUnit otherUnit) {
+ return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
+ }
+
@Override
public MutEnergy mutable(double initialMagnitude) {
return new MutEnergy(initialMagnitude, toBaseUnits(initialMagnitude), this);
}
+
+ /**
+ * Combines this unit of energy with a unit of time to create a unit of power.
+ *
+ * @param period the period of the change in energy
+ * @return the combined unit of power
+ */
+ @Override
+ public PowerUnit per(TimeUnit period) {
+ return PowerUnit.combine(this, period);
+ }
+
+ /**
+ * Creates a ratio unit between this unit and an arbitrary other unit.
+ *
+ * @param other the other unit
+ * @param the type of the other unit
+ * @return the ratio unit
+ */
+ public PerUnit per(U other) {
+ return PerUnit.combine(this, other);
+ }
}
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/ForceUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/ForceUnit.java
index 9fead01b377..9bf1f9f5c74 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/ForceUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/ForceUnit.java
@@ -57,7 +57,15 @@ public TorqueUnit multAsTorque(DistanceUnit distance) {
return TorqueUnit.combine(distance, this);
}
- // TODO: Add a multAsEnergy equivalent
+ /**
+ * Multiplies this force unit by a unit of distance to create a unit of energy.
+ *
+ * @param distance the unit of distance
+ * @return the combined energy unit
+ */
+ public EnergyUnit multAsEnergy(DistanceUnit distance) {
+ return EnergyUnit.combine(this, distance);
+ }
@Override
public Force of(double magnitude) {
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/PowerUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/PowerUnit.java
index 4129b22177d..a02f8041b29 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/PowerUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/PowerUnit.java
@@ -4,8 +4,7 @@
package edu.wpi.first.units;
-import static edu.wpi.first.units.Units.Joules;
-import static edu.wpi.first.units.Units.Seconds;
+import static edu.wpi.first.units.Units.Amps;
import edu.wpi.first.units.measure.ImmutablePower;
import edu.wpi.first.units.measure.MutPower;
@@ -53,58 +52,6 @@ public static PowerUnit combine(EnergyUnit energy, TimeUnit period) {
return cache.combine(energy, period);
}
- /**
- * Combines voltage and current into power.
- *
- * @param voltage the unit of voltage
- * @param current the unit of current
- * @return the combined unit of power
- */
- public static PowerUnit combine(VoltageUnit voltage, CurrentUnit current) {
- return combine(
- new EnergyUnit(
- Joules,
- voltage.toBaseUnits(1) * current.toBaseUnits(1),
- voltage.name() + "-" + current.name(),
- voltage.symbol() + "*" + current.symbol()),
- Seconds);
- }
-
- /**
- * Combines voltage and current into power.
- *
- * @param current the unit of current
- * @param voltage the unit of voltage
- * @return the combined unit of power
- */
- public static PowerUnit combine(CurrentUnit current, VoltageUnit voltage) {
- return combine(voltage, current);
- }
-
- /**
- * Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
- *
- * @param angularVelocity the unit of angular velocity
- * @param torque the unit of torque
- * @return the combined unit of power
- */
- public static PowerUnit combine(AngularVelocityUnit angularVelocity, TorqueUnit torque) {
- return combine(
- new EnergyUnit(Joules, angularVelocity.toBaseUnits(1) * torque.toBaseUnits(1), "", ""),
- Seconds);
- }
-
- /**
- * Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
- *
- * @param torque the unit of torque
- * @param angularVelocity the unit of angular velocity
- * @return the combined unit of power
- */
- public static PowerUnit combine(TorqueUnit torque, AngularVelocityUnit angularVelocity) {
- return combine(angularVelocity, torque);
- }
-
@Override
public PowerUnit getBaseUnit() {
return (PowerUnit) super.getBaseUnit();
@@ -135,6 +82,40 @@ public MutPower mutable(double initialMagnitude) {
return new MutPower(initialMagnitude, toBaseUnits(initialMagnitude), this);
}
+ /**
+ * Constructs a unit of voltage equivalent to this unit of power divided by another unit of
+ * current. For example, {@code Watts.per(Amps)} will return a unit of power equivalent to one
+ * Volt.
+ *
+ * @param current the current unit to multiply by
+ * @return the power unit
+ */
+ public VoltageUnit per(CurrentUnit current) {
+ return VoltageUnit.combine(this, current);
+ }
+
+ /**
+ * Constructs a unit of current equivalent to this unit of power divided by another unit of
+ * voltage. For example, {@code Watts.per(Volts)} will return a unit of power equivalent to one
+ * Amp.
+ *
+ * @param voltage the voltage unit to multiply by
+ * @return the power unit
+ */
+ public CurrentUnit per(VoltageUnit voltage) {
+ double baseUnitEquivalent = this.toBaseUnits(1) / voltage.toBaseUnits(1);
+ UnaryFunction toBaseConverter = x -> x * baseUnitEquivalent;
+ UnaryFunction fromBaseConverter = x -> x / baseUnitEquivalent;
+ CurrentUnit currentUnit =
+ new CurrentUnit(
+ Amps,
+ toBaseConverter,
+ fromBaseConverter,
+ this.name() + " per " + voltage.name(),
+ this.symbol() + "/" + voltage.symbol());
+ return Units.derive(currentUnit).make();
+ }
+
@Override
public VelocityUnit per(TimeUnit time) {
return VelocityUnit.combine(this, time);
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/TorqueUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/TorqueUnit.java
index 3aeef3b55d2..b6624a1873a 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/TorqueUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/TorqueUnit.java
@@ -4,6 +4,8 @@
package edu.wpi.first.units;
+import static edu.wpi.first.units.Units.Watts;
+
import edu.wpi.first.units.measure.ImmutableTorque;
import edu.wpi.first.units.measure.MutTorque;
import edu.wpi.first.units.measure.Torque;
@@ -72,6 +74,24 @@ public MutTorque mutable(double initialMagnitude) {
return new MutTorque(initialMagnitude, toBaseUnits(initialMagnitude), this);
}
+ /**
+ * Constructs a unit of power equivalent to this unit of torque multiplied by another unit of
+ * angular velocity. For example, {@code NewtonMeters.times(RadiansPerSecond)} will return a unit
+ * of power equivalent to one Watt.
+ *
+ * @param angularVelocity the unit of angular velocity
+ * @param name the name of the resulting unit of power
+ * @param symbol the symbol used to represent the unit of power
+ * @return the power unit
+ */
+ public PowerUnit mult(AngularVelocityUnit angularVelocity, String name, String symbol) {
+ double baseUnitEquivalent = this.toBaseUnits(1) / angularVelocity.toBaseUnits(1);
+ UnaryFunction toBaseConverter = x -> x * baseUnitEquivalent;
+ UnaryFunction fromBaseConverter = x -> x / baseUnitEquivalent;
+ PowerUnit powerUnit = new PowerUnit(Watts, toBaseConverter, fromBaseConverter, name, symbol);
+ return Units.derive(powerUnit).named(name).symbol(symbol).make();
+ }
+
@Override
public VelocityUnit per(TimeUnit time) {
return VelocityUnit.combine(this, time);
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/Units.java b/wpiunits/src/main/java/edu/wpi/first/units/Units.java
index d75eebc303c..6dc7381e169 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/Units.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/Units.java
@@ -374,66 +374,9 @@ private Units() {
public static final MomentOfInertiaUnit KilogramSquareMeters =
KilogramMetersSquaredPerSecond.mult(RadiansPerSecond);
- // VoltageUnit
- /** The base unit of electric potential. */
- public static final VoltageUnit Volts = BaseUnits.VoltageUnit;
-
- /** The base unit of electric potential. */
- public static final VoltageUnit Volt = Volts; // alias
-
- /**
- * 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
- * or low-power circuits.
- */
- public static final VoltageUnit Millivolts = Milli(Volts);
-
- /**
- * 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
- * or low-power circuits.
- */
- public static final VoltageUnit Millivolt = Millivolts; // alias
-
- // CurrentUnit
- /** The base unit of electrical current. */
- public static final CurrentUnit Amps = BaseUnits.CurrentUnit;
-
- /** The base unit of electrical current. */
- public static final CurrentUnit Amp = Amps; // alias
-
- /**
- * A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
- * like LED drivers or low-power circuits.
- */
- public static final CurrentUnit Milliamps = Milli(Amps);
-
- /**
- * A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
- * like LED drivers or low-power circuits.
- */
- public static final CurrentUnit Milliamp = Milliamps; // alias
-
- // ResistanceUnit
- /** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
- public static final ResistanceUnit Ohms = derive(Volts.per(Amp)).named("Ohm").symbol("Ω").make();
-
- /** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
- public static final ResistanceUnit Ohm = Ohms; // alias
-
- /** A unit equal to 1,000 {@link #Ohms}. */
- public static final ResistanceUnit KiloOhms = Kilo(Ohms);
-
- /** A unit equal to 1,000 {@link #Ohms}. */
- public static final ResistanceUnit KiloOhm = KiloOhms; // alias
-
- /** A unit equal to 1/1000 of a {@link #Ohm}. */
- public static final ResistanceUnit MilliOhms = Milli(Ohms);
-
- /** A unit equal to 1/1000 of a {@link #Ohm}. */
- public static final ResistanceUnit MilliOhm = MilliOhms; // alias
-
// EnergyUnit
/** The base unit of energy. */
- public static final EnergyUnit Joules = BaseUnits.EnergyUnit;
+ public static final EnergyUnit Joules = Newton.multAsEnergy(Meters);
/** The base unit of energy. */
public static final EnergyUnit Joule = Joules; // alias
@@ -484,6 +427,63 @@ private Units() {
public static final PowerUnit Horsepower =
derive(Watts).aggregate(745.7).named("Horsepower").symbol("HP").make();
+ // CurrentUnit
+ /** The base unit of electrical current. */
+ public static final CurrentUnit Amps = BaseUnits.CurrentUnit;
+
+ /** The base unit of electrical current. */
+ public static final CurrentUnit Amp = Amps; // alias
+
+ /**
+ * A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
+ * like LED drivers or low-power circuits.
+ */
+ public static final CurrentUnit Milliamps = Milli(Amps);
+
+ /**
+ * A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
+ * like LED drivers or low-power circuits.
+ */
+ public static final CurrentUnit Milliamp = Milliamps; // alias
+
+ // VoltageUnit
+ /** The base unit of electric potential. */
+ public static final VoltageUnit Volts = derive(Watts.per(Amp)).named("Volt").symbol("V").make();
+
+ /** The base unit of electric potential. */
+ public static final VoltageUnit Volt = Volts; // alias
+
+ /**
+ * 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
+ * or low-power circuits.
+ */
+ public static final VoltageUnit Millivolts = Milli(Volts);
+
+ /**
+ * 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
+ * or low-power circuits.
+ */
+ public static final VoltageUnit Millivolt = Millivolts; // alias
+
+ // ResistanceUnit
+ /** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
+ public static final ResistanceUnit Ohms = derive(Volts.per(Amp)).named("Ohm").symbol("Ω").make();
+
+ /** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
+ public static final ResistanceUnit Ohm = Ohms; // alias
+
+ /** A unit equal to 1,000 {@link #Ohms}. */
+ public static final ResistanceUnit KiloOhms = Kilo(Ohms);
+
+ /** A unit equal to 1,000 {@link #Ohms}. */
+ public static final ResistanceUnit KiloOhm = KiloOhms; // alias
+
+ /** A unit equal to 1/1000 of a {@link #Ohm}. */
+ public static final ResistanceUnit MilliOhms = Milli(Ohms);
+
+ /** A unit equal to 1/1000 of a {@link #Ohm}. */
+ public static final ResistanceUnit MilliOhm = MilliOhms; // alias
+
// TemperatureUnit
/**
* The base unit of temperature, where a value of 0 corresponds with absolutely zero energy in the
diff --git a/wpiunits/src/main/java/edu/wpi/first/units/VoltageUnit.java b/wpiunits/src/main/java/edu/wpi/first/units/VoltageUnit.java
index 75069351707..45f8a36bff3 100644
--- a/wpiunits/src/main/java/edu/wpi/first/units/VoltageUnit.java
+++ b/wpiunits/src/main/java/edu/wpi/first/units/VoltageUnit.java
@@ -4,6 +4,8 @@
package edu.wpi.first.units;
+import static edu.wpi.first.units.Units.Watts;
+
import edu.wpi.first.units.measure.ImmutableVoltage;
import edu.wpi.first.units.measure.MutVoltage;
import edu.wpi.first.units.measure.Voltage;
@@ -17,9 +19,17 @@
* Actual units (such as {@link Units#Volts} and {@link Units#Millivolts}) can be found in the
* {@link Units} class.
*/
-public final class VoltageUnit extends Unit {
- VoltageUnit(VoltageUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
- super(baseUnit, baseUnitEquivalent, name, symbol);
+public final class VoltageUnit extends PerUnit {
+ private static final CombinatoryUnitCache cache =
+ new CombinatoryUnitCache<>(VoltageUnit::new);
+
+ VoltageUnit(PowerUnit power, CurrentUnit current) {
+ super(
+ power.isBaseUnit() && current.isBaseUnit()
+ ? null
+ : combine(power.getBaseUnit(), current.getBaseUnit()),
+ power,
+ current);
}
VoltageUnit(
@@ -31,24 +41,20 @@ public final class VoltageUnit extends Unit {
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
}
- @Override
- public VoltageUnit getBaseUnit() {
- return (VoltageUnit) super.getBaseUnit();
- }
-
/**
- * Constructs a unit of power equivalent to this unit of voltage multiplied by another unit of
- * electrical current. For example, {@code Volts.times(Amps)} will return a unit of power
- * equivalent to one Watt; {@code Volts.times(Milliamps)} will return a unit of power equivalent
- * to a milliwatt, and so on.
+ * Combines a power and a current unit to form a unit of voltage.
*
- * @param current the current unit to multiply by
- * @param name the name of the resulting unit of power
- * @param symbol the symbol used to represent the unit of power
- * @return the power unit
+ * @param power the unit of energy
+ * @param current the unit of time
+ * @return the combined unit of power
*/
- public PowerUnit mult(CurrentUnit current, String name, String symbol) {
- return Units.derive(PowerUnit.combine(this, current)).named(name).symbol(symbol).make();
+ public static VoltageUnit combine(PowerUnit power, CurrentUnit current) {
+ return cache.combine(power, current);
+ }
+
+ @Override
+ public VoltageUnit getBaseUnit() {
+ return (VoltageUnit) super.getBaseUnit();
}
@Override
@@ -76,6 +82,30 @@ public MutVoltage mutable(double magnitude) {
return new MutVoltage(magnitude, toBaseUnits(magnitude), this);
}
+ /**
+ * Constructs a unit of power equivalent to this unit of voltage multiplied by another unit of
+ * electrical current. For example, {@code Volts.times(Amps)} will return a unit of power
+ * equivalent to one Watt; {@code Volts.times(Milliamps)} will return a unit of power equivalent
+ * to a milliwatt, and so on.
+ *
+ * @param current the current unit to multiply by
+ * @return the power unit
+ */
+ @Override
+ public PowerUnit mult(CurrentUnit current) {
+ double baseUnitEquivalent = this.toBaseUnits(1) * current.toBaseUnits(1);
+ UnaryFunction toBaseConverter = x -> x * baseUnitEquivalent;
+ UnaryFunction fromBaseConverter = x -> x / baseUnitEquivalent;
+ PowerUnit powerUnit =
+ new PowerUnit(
+ Watts,
+ toBaseConverter,
+ fromBaseConverter,
+ this.name() + "-" + current.name(),
+ this.symbol() + "*" + current.symbol());
+ return powerUnit;
+ }
+
@Override
public VelocityUnit per(TimeUnit period) {
return VelocityUnit.combine(this, period);
diff --git a/wpiunits/src/test/java/edu/wpi/first/units/CurrentUnitTest.java b/wpiunits/src/test/java/edu/wpi/first/units/CurrentUnitTest.java
index 5c215f7bf35..1a5dcc5c527 100644
--- a/wpiunits/src/test/java/edu/wpi/first/units/CurrentUnitTest.java
+++ b/wpiunits/src/test/java/edu/wpi/first/units/CurrentUnitTest.java
@@ -12,15 +12,13 @@
class CurrentUnitTest {
@Test
void testAmpsTimesVolts() {
- PowerUnit combined = Units.Amps.mult(Units.Volts, "Watt", "w");
-
- assertTrue(combined.equivalent(Units.Watts));
+ assertTrue(Units.Amps.mult(Units.Volts).equivalent(Units.Watts));
}
@Test
void testMilliAmpsTimesMilliVolts() {
// results in microwatts
- PowerUnit times = Units.Milliamps.mult(Units.Millivolts, "Microwatt", "uW");
+ PowerUnit times = Units.Milliamps.mult(Units.Millivolts);
PowerUnit millimilli = Units.Milli(Units.Milliwatts);
assertEquals(1, times.convertFrom(1e-6, Units.Watts));
diff --git a/wpiunits/src/test/java/edu/wpi/first/units/VoltageUnitTest.java b/wpiunits/src/test/java/edu/wpi/first/units/VoltageUnitTest.java
index 3696b06cda4..388f5e3349c 100644
--- a/wpiunits/src/test/java/edu/wpi/first/units/VoltageUnitTest.java
+++ b/wpiunits/src/test/java/edu/wpi/first/units/VoltageUnitTest.java
@@ -4,6 +4,7 @@
package edu.wpi.first.units;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
@@ -11,12 +12,17 @@
class VoltageUnitTest {
@Test
void testVoltsTimesAmps() {
- assertTrue(Units.Volts.mult(Units.Amps, "", "").equivalent(Units.Watts));
+ assertTrue(Units.Volts.mult(Units.Amps).equivalent(Units.Watts));
}
@Test
void testMilliVoltsTimesMilliAmps() {
// results in microwatts
- assertTrue(Units.Millivolts.mult(Units.Milliamps, "", "").equivalent(Units.Micro(Units.Watts)));
+ PowerUnit times = Units.Millivolts.mult(Units.Milliamps);
+ PowerUnit millimilli = Units.Milli(Units.Milliwatts);
+
+ assertEquals(1, times.convertFrom(1e-6, Units.Watts));
+ assertEquals(1, millimilli.convertFrom(1e-6, Units.Watts));
+ assertTrue(times.equivalent(millimilli));
}
}