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