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 edu.wpi.first.units.measure.ImmutableTorque;
008import edu.wpi.first.units.measure.MutTorque;
009import edu.wpi.first.units.measure.Torque;
010
011/** A unit of torque like {@link edu.wpi.first.units.Units#NewtonMeters}. */
012public final class TorqueUnit extends MultUnit<DistanceUnit, ForceUnit> {
013  private static final CombinatoryUnitCache<DistanceUnit, ForceUnit, TorqueUnit> cache =
014      new CombinatoryUnitCache<>(TorqueUnit::new);
015
016  TorqueUnit(DistanceUnit distanceUnit, ForceUnit forceUnit) {
017    super(
018        distanceUnit.isBaseUnit() && forceUnit.isBaseUnit()
019            ? null
020            : combine(distanceUnit.getBaseUnit(), forceUnit.getBaseUnit()),
021        distanceUnit,
022        forceUnit);
023  }
024
025  TorqueUnit(
026      MultUnit<DistanceUnit, ForceUnit> baseUnit,
027      UnaryFunction toBaseConverter,
028      UnaryFunction fromBaseConverter,
029      String name,
030      String symbol) {
031    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
032  }
033
034  /**
035   * Combines a unit of distance and force to create a unit of torque.
036   *
037   * @param distance the distance unit
038   * @param force the force unit
039   * @return the combined torque unit
040   */
041  public static TorqueUnit combine(DistanceUnit distance, ForceUnit force) {
042    return cache.combine(distance, force);
043  }
044
045  @Override
046  public TorqueUnit getBaseUnit() {
047    return (TorqueUnit) super.getBaseUnit();
048  }
049
050  @Override
051  public Torque of(double magnitude) {
052    return new ImmutableTorque(magnitude, toBaseUnits(magnitude), this);
053  }
054
055  @Override
056  public Torque ofBaseUnits(double baseUnitMagnitude) {
057    return new ImmutableTorque(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
058  }
059
060  @Override
061  public Torque zero() {
062    return (Torque) super.zero();
063  }
064
065  @Override
066  public Torque one() {
067    return (Torque) super.one();
068  }
069
070  @Override
071  public MutTorque mutable(double initialMagnitude) {
072    return new MutTorque(initialMagnitude, toBaseUnits(initialMagnitude), this);
073  }
074
075  @Override
076  public VelocityUnit<TorqueUnit> per(TimeUnit time) {
077    return VelocityUnit.combine(this, time);
078  }
079
080  /**
081   * Creates a ratio unit between this unit and an arbitrary other unit.
082   *
083   * @param other the other unit
084   * @param <U> the type of the other unit
085   * @return the ratio unit
086   */
087  public <U extends Unit> PerUnit<TorqueUnit, U> per(U other) {
088    return PerUnit.combine(this, other);
089  }
090
091  /**
092   * Converts a measurement value in terms of another unit to this unit.
093   *
094   * @param magnitude the magnitude of the measurement in terms of the other unit
095   * @param otherUnit the other unit
096   * @return the value of the measurement in terms of this unit
097   */
098  public double convertFrom(double magnitude, TorqueUnit otherUnit) {
099    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
100  }
101}