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.Acceleration;
008import edu.wpi.first.units.measure.ImmutableAcceleration;
009import edu.wpi.first.units.measure.MutAcceleration;
010
011/**
012 * A generic unit of acceleration.
013 *
014 * <p><strong>NOTE:</strong> This type is not compatible with unit-specific accelerations like
015 * {@link edu.wpi.first.units.measure.LinearAcceleration}. Authors of APIs that need to interact
016 * with all types should consider using a generic {@code Measure<? extends PerUnit<? extends
017 * PerUnit<[dimension>], TimeUnit>, TimeUnit>}. Bounded wildcards are necessary in order to
018 * interoperate with <i>any</i> subclass of the {@link edu.wpi.first.units.measure.Per} measurement
019 * type.
020 *
021 * @param <D> the unit of the accelerating quantity
022 */
023public final class AccelerationUnit<D extends Unit> extends PerUnit<VelocityUnit<D>, TimeUnit> {
024  @SuppressWarnings({"rawtypes", "unchecked"})
025  private static final CombinatoryUnitCache<VelocityUnit, TimeUnit, AccelerationUnit> cache =
026      new CombinatoryUnitCache<>(AccelerationUnit::new);
027
028  AccelerationUnit(VelocityUnit<D> velocity, TimeUnit period) {
029    super(
030        velocity.isBaseUnit() && period.isBaseUnit()
031            ? null
032            : combine(velocity.getBaseUnit(), period.getBaseUnit()),
033        velocity,
034        period);
035  }
036
037  AccelerationUnit(
038      AccelerationUnit<D> baseUnit,
039      UnaryFunction toBaseConverter,
040      UnaryFunction fromBaseConverter,
041      String name,
042      String symbol) {
043    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
044  }
045
046  @Override
047  public Acceleration<D> of(double magnitude) {
048    return new ImmutableAcceleration<>(magnitude, toBaseUnits(magnitude), this);
049  }
050
051  @Override
052  public Acceleration<D> ofBaseUnits(double baseUnitMagnitude) {
053    return new ImmutableAcceleration<>(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
054  }
055
056  @Override
057  @SuppressWarnings({"unchecked", "rawtypes"})
058  public Acceleration<D> zero() {
059    return (Acceleration<D>) (Acceleration) super.zero();
060  }
061
062  @Override
063  @SuppressWarnings({"unchecked", "rawtypes"})
064  public Acceleration<D> one() {
065    return (Acceleration<D>) (Acceleration) super.one();
066  }
067
068  @Override
069  public MutAcceleration<D> mutable(double initialMagnitude) {
070    return new MutAcceleration<>(initialMagnitude, toBaseUnits(initialMagnitude), this);
071  }
072
073  @Override
074  public VelocityUnit<AccelerationUnit<D>> per(TimeUnit time) {
075    return VelocityUnit.combine(this, time);
076  }
077
078  /**
079   * Creates a ratio unit between this unit and an arbitrary other unit.
080   *
081   * @param other the other unit
082   * @param <U> the type of the other unit
083   * @return the ratio unit
084   */
085  public <U extends Unit> PerUnit<AccelerationUnit<D>, U> per(U other) {
086    return PerUnit.combine(this, other);
087  }
088
089  /**
090   * Converts a measurement value in terms of another time unit to this unit.
091   *
092   * @param magnitude the magnitude of the measurement in terms of the other time unit
093   * @param otherUnit the other time unit
094   * @return the value of the measurement in terms of this unit
095   */
096  public double convertFrom(double magnitude, AccelerationUnit<D> otherUnit) {
097    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
098  }
099
100  /**
101   * Combines a generic velocity and time period into a unit of acceleration.
102   *
103   * @param velocity the unit of velocity
104   * @param period the unit of the time period of acceleration
105   * @param <D> the unit of the accelerating quantity
106   * @return the combined acceleration unit
107   */
108  @SuppressWarnings("unchecked")
109  public static <D extends Unit> AccelerationUnit<D> combine(
110      VelocityUnit<D> velocity, TimeUnit period) {
111    return cache.combine(velocity, period);
112  }
113}