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.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   * Creates a ratio unit between this unit and an arbitrary other unit.
078   *
079   * @param other the other unit
080   * @param <U> the type of the other unit
081   * @return the ratio unit
082   */
083  public <U extends Unit> PerUnit<AngularMomentumUnit, U> per(U other) {
084    return PerUnit.combine(this, other);
085  }
086
087  /**
088   * Converts a measurement value in terms of another unit to this unit.
089   *
090   * @param magnitude the magnitude of the measurement in terms of the other unit
091   * @param otherUnit the other unit
092   * @return the value of the measurement in terms of this unit
093   */
094  public double convertFrom(double magnitude, AngularMomentumUnit otherUnit) {
095    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
096  }
097
098  /**
099   * Multiplies this angular momentum by an angular velocity to yield a unit of moment of inertia.
100   *
101   * @param omega the unit of angular velocity
102   * @return the moment of inertia unit
103   */
104  public MomentOfInertiaUnit mult(AngularVelocityUnit omega) {
105    return MomentOfInertiaUnit.combine(this, omega);
106  }
107}