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.Joules;
008import static edu.wpi.first.units.Units.Seconds;
009
010import edu.wpi.first.units.measure.Power;
011
012/**
013 * Unit of power dimension.
014 *
015 * <p>This is the base type for units of power dimension. It is also used to specify the dimension
016 * for {@link Measure}: <code>Measure&lt;PowerUnit&gt;</code>.
017 *
018 * <p>Actual units (such as {@link Units#Watts} and {@link Units#Horsepower}) can be found in the
019 * {@link Units} class.
020 */
021public final class PowerUnit extends PerUnit<EnergyUnit, TimeUnit> {
022  private static final CombinatoryUnitCache<EnergyUnit, TimeUnit, PowerUnit> cache =
023      new CombinatoryUnitCache<>(PowerUnit::new);
024
025  PowerUnit(EnergyUnit energy, TimeUnit time) {
026    super(
027        energy.isBaseUnit() && time.isBaseUnit()
028            ? null
029            : combine(energy.getBaseUnit(), time.getBaseUnit()),
030        energy,
031        time);
032  }
033
034  PowerUnit(
035      PowerUnit baseUnit,
036      UnaryFunction toBaseConverter,
037      UnaryFunction fromBaseConverter,
038      String name,
039      String symbol) {
040    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
041  }
042
043  /**
044   * Combines an energy and a time unit to form a unit of power.
045   *
046   * @param energy the unit of energy
047   * @param period the unit of time
048   * @return the combined unit of power
049   */
050  public static PowerUnit combine(EnergyUnit energy, TimeUnit period) {
051    return cache.combine(energy, period);
052  }
053
054  /**
055   * Combines voltage and current into power.
056   *
057   * @param voltage the unit of voltage
058   * @param current the unit of current
059   * @return the combined unit of power
060   */
061  public static PowerUnit combine(VoltageUnit voltage, CurrentUnit current) {
062    return combine(
063        new EnergyUnit(
064            Joules,
065            voltage.toBaseUnits(1) * current.toBaseUnits(1),
066            voltage.name() + "-" + current.name(),
067            voltage.symbol() + "*" + current.symbol()),
068        Seconds);
069  }
070
071  /**
072   * Combines voltage and current into power.
073   *
074   * @param current the unit of current
075   * @param voltage the unit of voltage
076   * @return the combined unit of power
077   */
078  public static PowerUnit combine(CurrentUnit current, VoltageUnit voltage) {
079    return combine(voltage, current);
080  }
081
082  /**
083   * Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
084   *
085   * @param angularVelocity the unit of angular velocity
086   * @param torque the unit of torque
087   * @return the combined unit of power
088   */
089  public static PowerUnit combine(AngularVelocityUnit angularVelocity, TorqueUnit torque) {
090    return combine(
091        new EnergyUnit(Joules, angularVelocity.toBaseUnits(1) * torque.toBaseUnits(1), "", ""),
092        Seconds);
093  }
094
095  /**
096   * Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
097   *
098   * @param torque the unit of torque
099   * @param angularVelocity the unit of angular velocity
100   * @return the combined unit of power
101   */
102  public static PowerUnit combine(TorqueUnit torque, AngularVelocityUnit angularVelocity) {
103    return combine(angularVelocity, torque);
104  }
105
106  @Override
107  public PowerUnit getBaseUnit() {
108    return (PowerUnit) super.getBaseUnit();
109  }
110
111  @Override
112  public Power of(double magnitude) {
113    return new Power(magnitude, toBaseUnits(magnitude), this);
114  }
115
116  @Override
117  public Power ofBaseUnits(double baseUnitMagnitude) {
118    return new Power(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
119  }
120
121  @Override
122  public Power zero() {
123    return (Power) super.zero();
124  }
125
126  @Override
127  public Power one() {
128    return (Power) super.one();
129  }
130
131  @Override
132  public VelocityUnit<PowerUnit> per(TimeUnit time) {
133    return VelocityUnit.combine(this, time);
134  }
135
136  /**
137   * Creates a ratio unit between this unit and an arbitrary other unit.
138   *
139   * @param other the other unit
140   * @param <U> the type of the other unit
141   * @return the ratio unit
142   */
143  public <U extends Unit> PerUnit<PowerUnit, U> per(U other) {
144    return PerUnit.combine(this, other);
145  }
146
147  /**
148   * Converts a measurement value in terms of another power unit to this unit.
149   *
150   * @param magnitude the magnitude of the measurement in terms of the other power unit
151   * @param otherUnit the other power unit
152   * @return the value of the measurement in terms of this unit
153   */
154  public double convertFrom(double magnitude, PowerUnit otherUnit) {
155    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
156  }
157}