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)); } }