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 org.wpilib.units;
006
007import org.wpilib.units.measure.AngularMomentum;
008
009/**
010 * A unit of angular momentum, modeled as linear momentum of an object rotating some distance away
011 * from the axis of rotation.
012 */
013public final class AngularMomentumUnit extends MultUnit<LinearMomentumUnit, DistanceUnit> {
014  private static final CombinatoryUnitCache<LinearMomentumUnit, DistanceUnit, AngularMomentumUnit>
015      cache = new CombinatoryUnitCache<>(AngularMomentumUnit::new);
016
017  AngularMomentumUnit(LinearMomentumUnit momentumUnit, DistanceUnit distanceUnit) {
018    super(
019        momentumUnit.isBaseUnit() && distanceUnit.isBaseUnit()
020            ? null
021            : combine(momentumUnit.getBaseUnit(), distanceUnit.getBaseUnit()),
022        momentumUnit,
023        distanceUnit);
024  }
025
026  AngularMomentumUnit(
027      AngularMomentumUnit baseUnit,
028      UnaryFunction toBaseConverter,
029      UnaryFunction fromBaseConverter,
030      String name,
031      String symbol) {
032    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
033  }
034
035  /**
036   * Combines a linear momentum and distance to create a unit of angular momentum.
037   *
038   * @param linear the linear momentum unit
039   * @param distance the unit of distance from the axis of rotation
040   * @return the combined angular momentum unit
041   */
042  public static AngularMomentumUnit combine(LinearMomentumUnit linear, DistanceUnit distance) {
043    return cache.combine(linear, distance);
044  }
045
046  @Override
047  public AngularMomentumUnit getBaseUnit() {
048    return (AngularMomentumUnit) super.getBaseUnit();
049  }
050
051  @Override
052  public AngularMomentum of(double magnitude) {
053    return new AngularMomentum(magnitude, toBaseUnits(magnitude), this);
054  }
055
056  @Override
057  public AngularMomentum ofBaseUnits(double baseUnitMagnitude) {
058    return new AngularMomentum(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
059  }
060
061  @Override
062  public AngularMomentum zero() {
063    return (AngularMomentum) super.zero();
064  }
065
066  @Override
067  public AngularMomentum one() {
068    return (AngularMomentum) super.one();
069  }
070
071  @Override
072  public VelocityUnit<AngularMomentumUnit> per(TimeUnit time) {
073    return VelocityUnit.combine(this, time);
074  }
075
076  /**
077   * Combines this angular momentum by an angular velocity to yield a unit of moment of inertia.
078   *
079   * @param omega the unit of angular velocity
080   * @return the moment of inertia unit
081   */
082  public MomentOfInertiaUnit per(AngularVelocityUnit omega) {
083    return MomentOfInertiaUnit.combine(this, omega);
084  }
085
086  /**
087   * Creates a ratio unit between this unit and an arbitrary other unit.
088   *
089   * @param other the other unit
090   * @param <U> the type of the other unit
091   * @return the ratio unit
092   */
093  public <U extends Unit> PerUnit<AngularMomentumUnit, U> per(U other) {
094    return PerUnit.combine(this, other);
095  }
096
097  /**
098   * Converts a measurement value in terms of another unit to this unit.
099   *
100   * @param magnitude the magnitude of the measurement in terms of the other unit
101   * @param otherUnit the other unit
102   * @return the value of the measurement in terms of this unit
103   */
104  public double convertFrom(double magnitude, AngularMomentumUnit otherUnit) {
105    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
106  }
107}