mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-03 03:01:44 +00:00
SCRIPT Move java files
This commit is contained in:
committed by
Peter Johnson
parent
7ca1be9bae
commit
c350c5f112
106
wpiunits/src/main/java/org/wpilib/units/AccelerationUnit.java
Normal file
106
wpiunits/src/main/java/org/wpilib/units/AccelerationUnit.java
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Acceleration;
|
||||
|
||||
/**
|
||||
* A generic unit of acceleration.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> This type is not compatible with unit-specific accelerations like
|
||||
* {@link edu.wpi.first.units.measure.LinearAcceleration}. Authors of APIs that need to interact
|
||||
* with all types should consider using a generic {@code Measure<? extends PerUnit<? extends
|
||||
* PerUnit<[dimension>], TimeUnit>, TimeUnit>}. Bounded wildcards are necessary in order to
|
||||
* interoperate with <i>any</i> subclass of the {@link edu.wpi.first.units.measure.Per} measurement
|
||||
* type.
|
||||
*
|
||||
* @param <D> the unit of the accelerating quantity
|
||||
*/
|
||||
public final class AccelerationUnit<D extends Unit> extends PerUnit<VelocityUnit<D>, TimeUnit> {
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static final CombinatoryUnitCache<VelocityUnit, TimeUnit, AccelerationUnit> cache =
|
||||
new CombinatoryUnitCache<>(AccelerationUnit::new);
|
||||
|
||||
AccelerationUnit(VelocityUnit<D> velocity, TimeUnit period) {
|
||||
super(
|
||||
velocity.isBaseUnit() && period.isBaseUnit()
|
||||
? null
|
||||
: combine(velocity.getBaseUnit(), period.getBaseUnit()),
|
||||
velocity,
|
||||
period);
|
||||
}
|
||||
|
||||
AccelerationUnit(
|
||||
AccelerationUnit<D> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Acceleration<D> of(double magnitude) {
|
||||
return new Acceleration<>(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Acceleration<D> ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Acceleration<>(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public Acceleration<D> zero() {
|
||||
return (Acceleration<D>) (Acceleration) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public Acceleration<D> one() {
|
||||
return (Acceleration<D>) (Acceleration) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<AccelerationUnit<D>> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<AccelerationUnit<D>, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another time unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other time unit
|
||||
* @param otherUnit the other time unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, AccelerationUnit<D> otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a generic velocity and time period into a unit of acceleration.
|
||||
*
|
||||
* @param velocity the unit of velocity
|
||||
* @param period the unit of the time period of acceleration
|
||||
* @param <D> the unit of the accelerating quantity
|
||||
* @return the combined acceleration unit
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <D extends Unit> AccelerationUnit<D> combine(
|
||||
VelocityUnit<D> velocity, TimeUnit period) {
|
||||
return cache.combine(velocity, period);
|
||||
}
|
||||
}
|
||||
87
wpiunits/src/main/java/org/wpilib/units/AngleUnit.java
Normal file
87
wpiunits/src/main/java/org/wpilib/units/AngleUnit.java
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Angle;
|
||||
|
||||
/**
|
||||
* Unit of angular dimension.
|
||||
*
|
||||
* <p>This is the base type for units of angular dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<AngleUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Degrees} and {@link Units#Radians}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
// technically, angles are unitless dimensions
|
||||
// eg MassUnit * DistanceUnit * VelocityUnit<AngleUnit> is equivalent to (MassUnit * DistanceUnit) /
|
||||
// TimeUnit - otherwise known
|
||||
// as PowerUnit - in other words, VelocityUnit<AngleUnit> is /actually/ Frequency
|
||||
public final class AngleUnit extends Unit {
|
||||
AngleUnit(AngleUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
AngleUnit(
|
||||
AngleUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngleUnit getBaseUnit() {
|
||||
return (AngleUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Angle of(double magnitude) {
|
||||
return Angle.ofRelativeUnits(magnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Angle ofBaseUnits(double baseUnitMagnitude) {
|
||||
return Angle.ofBaseUnits(baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocityUnit per(TimeUnit period) {
|
||||
return AngularVelocityUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<AngleUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another angle unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other angle unit
|
||||
* @param otherUnit the other angle unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, AngleUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Angle zero() {
|
||||
return (Angle) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Angle one() {
|
||||
return (Angle) super.one();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.AngularAcceleration;
|
||||
|
||||
/** A unit of angular acceleration, such as {@link Units#RadiansPerSecondPerSecond}. */
|
||||
public final class AngularAccelerationUnit extends PerUnit<AngularVelocityUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<AngularVelocityUnit, TimeUnit, AngularAccelerationUnit>
|
||||
cache = new CombinatoryUnitCache<>(AngularAccelerationUnit::new);
|
||||
|
||||
AngularAccelerationUnit(AngularVelocityUnit velocity, TimeUnit period) {
|
||||
super(
|
||||
velocity.isBaseUnit() && period.isBaseUnit()
|
||||
? null
|
||||
: combine(velocity.getBaseUnit(), period.getBaseUnit()),
|
||||
velocity,
|
||||
period);
|
||||
}
|
||||
|
||||
AngularAccelerationUnit(
|
||||
AngularAccelerationUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an angular velocity and time period unit into an angular acceleration.
|
||||
*
|
||||
* @param velocity the unit of velocity
|
||||
* @param period the unit of time
|
||||
* @return the combined angular acceleration unit
|
||||
*/
|
||||
public static AngularAccelerationUnit combine(AngularVelocityUnit velocity, TimeUnit period) {
|
||||
return cache.combine(velocity, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAccelerationUnit getBaseUnit() {
|
||||
return (AngularAccelerationUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAcceleration of(double magnitude) {
|
||||
return new AngularAcceleration(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAcceleration ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new AngularAcceleration(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAcceleration zero() {
|
||||
return (AngularAcceleration) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAcceleration one() {
|
||||
return (AngularAcceleration) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<AngularAccelerationUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<AngularAccelerationUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, AngularAccelerationUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
107
wpiunits/src/main/java/org/wpilib/units/AngularMomentumUnit.java
Normal file
107
wpiunits/src/main/java/org/wpilib/units/AngularMomentumUnit.java
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.AngularMomentum;
|
||||
|
||||
/**
|
||||
* A unit of angular momentum, modeled as linear momentum of an object rotating some distance away
|
||||
* from the axis of rotation.
|
||||
*/
|
||||
public final class AngularMomentumUnit extends MultUnit<LinearMomentumUnit, DistanceUnit> {
|
||||
private static final CombinatoryUnitCache<LinearMomentumUnit, DistanceUnit, AngularMomentumUnit>
|
||||
cache = new CombinatoryUnitCache<>(AngularMomentumUnit::new);
|
||||
|
||||
AngularMomentumUnit(LinearMomentumUnit momentumUnit, DistanceUnit distanceUnit) {
|
||||
super(
|
||||
momentumUnit.isBaseUnit() && distanceUnit.isBaseUnit()
|
||||
? null
|
||||
: combine(momentumUnit.getBaseUnit(), distanceUnit.getBaseUnit()),
|
||||
momentumUnit,
|
||||
distanceUnit);
|
||||
}
|
||||
|
||||
AngularMomentumUnit(
|
||||
AngularMomentumUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a linear momentum and distance to create a unit of angular momentum.
|
||||
*
|
||||
* @param linear the linear momentum unit
|
||||
* @param distance the unit of distance from the axis of rotation
|
||||
* @return the combined angular momentum unit
|
||||
*/
|
||||
public static AngularMomentumUnit combine(LinearMomentumUnit linear, DistanceUnit distance) {
|
||||
return cache.combine(linear, distance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularMomentumUnit getBaseUnit() {
|
||||
return (AngularMomentumUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularMomentum of(double magnitude) {
|
||||
return new AngularMomentum(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularMomentum ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new AngularMomentum(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularMomentum zero() {
|
||||
return (AngularMomentum) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularMomentum one() {
|
||||
return (AngularMomentum) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<AngularMomentumUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<AngularMomentumUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, AngularMomentumUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this angular momentum by an angular velocity to yield a unit of moment of inertia.
|
||||
*
|
||||
* @param omega the unit of angular velocity
|
||||
* @return the moment of inertia unit
|
||||
*/
|
||||
public MomentOfInertiaUnit mult(AngularVelocityUnit omega) {
|
||||
return MomentOfInertiaUnit.combine(this, omega);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.AngularVelocity;
|
||||
|
||||
/** A unit of angular velocity like {@link Units#RadiansPerSecond}. */
|
||||
public final class AngularVelocityUnit extends PerUnit<AngleUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<AngleUnit, TimeUnit, AngularVelocityUnit> cache =
|
||||
new CombinatoryUnitCache<>(AngularVelocityUnit::new);
|
||||
|
||||
AngularVelocityUnit(AngleUnit numerator, TimeUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
AngularVelocityUnit(
|
||||
AngularVelocityUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an angle unit and a period of time into a unit of angular velocity.
|
||||
*
|
||||
* @param angle the unit of the changing angle
|
||||
* @param time the period of the changing angle
|
||||
* @return the combined angular velocity unit
|
||||
*/
|
||||
public static AngularVelocityUnit combine(AngleUnit angle, TimeUnit time) {
|
||||
return cache.combine(angle, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocityUnit getBaseUnit() {
|
||||
return (AngularVelocityUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocity of(double magnitude) {
|
||||
return new AngularVelocity(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocity ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new AngularVelocity(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocity zero() {
|
||||
return (AngularVelocity) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularVelocity one() {
|
||||
return (AngularVelocity) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngularAccelerationUnit per(TimeUnit period) {
|
||||
return AngularAccelerationUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<AngularVelocityUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, AngularVelocityUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
40
wpiunits/src/main/java/org/wpilib/units/BaseUnits.java
Normal file
40
wpiunits/src/main/java/org/wpilib/units/BaseUnits.java
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
/** The base units of measure. */
|
||||
public final class BaseUnits {
|
||||
private BaseUnits() {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
/** The standard unit of distance, meters. */
|
||||
public static final DistanceUnit DistanceUnit = new DistanceUnit(null, 1, "Meter", "m");
|
||||
|
||||
/** The standard unit of time, seconds. */
|
||||
public static final TimeUnit TimeUnit = new TimeUnit(null, 1, "Second", "s");
|
||||
|
||||
/** The standard unit of mass, kilograms. */
|
||||
public static final MassUnit MassUnit = new MassUnit(null, 1, "Kilogram", "Kg");
|
||||
|
||||
/** The standard unit of angles, radians. */
|
||||
public static final AngleUnit AngleUnit = new AngleUnit(null, 1, "Radian", "rad");
|
||||
|
||||
/** The standard "unitless" unit. */
|
||||
public static final DimensionlessUnit Value = new DimensionlessUnit(null, 1, "<?>", "<?>");
|
||||
|
||||
/** The standard unit of voltage, volts. */
|
||||
public static final VoltageUnit VoltageUnit = new VoltageUnit(null, 1, "Volt", "V");
|
||||
|
||||
/** The standard unit of electric current, amperes. */
|
||||
public static final CurrentUnit CurrentUnit = new CurrentUnit(null, 1, "Amp", "A");
|
||||
|
||||
/** The standard unit of energy, joules. */
|
||||
public static final EnergyUnit EnergyUnit = new EnergyUnit(null, 1, "Joule", "J");
|
||||
|
||||
/** The standard unit of temperature, kelvin. */
|
||||
public static final TemperatureUnit TemperatureUnit =
|
||||
new TemperatureUnit(null, x -> x, x -> x, "Kelvin", "K");
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.collections.LongToObjectHashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* A helper class for creating and caching combined unit objects. This helps to reduce unnecessary
|
||||
* object allocation by reusing already-created units.
|
||||
*
|
||||
* @param <A> the type of the first unit to be combined
|
||||
* @param <B> the type of the second unit to be combined
|
||||
* @param <Out> the type of the combinatorial unit
|
||||
*/
|
||||
public final class CombinatoryUnitCache<A extends Unit, B extends Unit, Out extends Unit> {
|
||||
/**
|
||||
* Keep a cache of created instances so expressions like Volts.per(Meter) don't do any allocations
|
||||
* after the first.
|
||||
*/
|
||||
private final LongToObjectHashMap<Out> m_cache = new LongToObjectHashMap<>();
|
||||
|
||||
private final BiFunction<? super A, ? super B, ? extends Out> m_constructor;
|
||||
|
||||
/**
|
||||
* Creates a new combinatory unit cache. The cache is initially empty and is not shared across
|
||||
* instances.
|
||||
*
|
||||
* @param constructor the constructor function to use to create new combined units
|
||||
*/
|
||||
public CombinatoryUnitCache(BiFunction<? super A, ? super B, ? extends Out> constructor) {
|
||||
this.m_constructor =
|
||||
Objects.requireNonNull(constructor, "Cache unit constructor must be provided");
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines two units together and returns the result. The resulting units are cached and will be
|
||||
* returned on successive calls to avoid allocating many duplicate objects. The combination output
|
||||
* type is determined by the factory function passed into the cache's constructor.
|
||||
*
|
||||
* @param a the first unit
|
||||
* @param b the second unit
|
||||
* @return the combined unit
|
||||
*/
|
||||
public Out combine(A a, B b) {
|
||||
final long key = ((long) a.hashCode()) << 32L | (b.hashCode() & 0xFFFFFFFFL);
|
||||
|
||||
var existing = m_cache.get(key);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
var newUnit = m_constructor.apply(a, b);
|
||||
m_cache.put(key, newUnit);
|
||||
return newUnit;
|
||||
}
|
||||
}
|
||||
98
wpiunits/src/main/java/org/wpilib/units/CurrentUnit.java
Normal file
98
wpiunits/src/main/java/org/wpilib/units/CurrentUnit.java
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Current;
|
||||
|
||||
/**
|
||||
* Unit of electric current dimension.
|
||||
*
|
||||
* <p>This is the base type for units of current dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<CurrentUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Amps} and {@link Units#Milliamps}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class CurrentUnit extends Unit {
|
||||
CurrentUnit(CurrentUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
CurrentUnit(
|
||||
CurrentUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurrentUnit getBaseUnit() {
|
||||
return (CurrentUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a unit of power equivalent to this unit of electrical current multiplied by another
|
||||
* unit of voltage. For example, {@code Amps.times(Volts)} will return a unit of power equivalent
|
||||
* to one Watt; {@code Amps.times(Millivolts)} will return a unit of power equivalent to a
|
||||
* milliwatt, and so on.
|
||||
*
|
||||
* @param voltage the voltage unit to multiply by
|
||||
* @param name the name of the resulting unit of power
|
||||
* @param symbol the symbol used to represent the unit of power
|
||||
* @return the power unit
|
||||
*/
|
||||
public PowerUnit mult(VoltageUnit voltage, String name, String symbol) {
|
||||
return Units.derive(PowerUnit.combine(voltage, this)).named(name).symbol(symbol).make();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Current of(double magnitude) {
|
||||
return new Current(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Current ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Current(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Current zero() {
|
||||
return (Current) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Current one() {
|
||||
return (Current) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<CurrentUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<CurrentUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another current unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other current unit
|
||||
* @param otherUnit the other current unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, CurrentUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Dimensionless;
|
||||
|
||||
/**
|
||||
* A type of unit that corresponds to raw values and not any physical dimension, such as percentage.
|
||||
*/
|
||||
public final class DimensionlessUnit extends Unit {
|
||||
/**
|
||||
* Creates a new unit with the given name and multiplier to the base unit.
|
||||
*
|
||||
* @param baseUnitEquivalent the multiplier to convert this unit to the base unit of this type.
|
||||
* @param name the name of the unit
|
||||
* @param symbol the symbol of the unit
|
||||
*/
|
||||
DimensionlessUnit(
|
||||
DimensionlessUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
DimensionlessUnit(
|
||||
DimensionlessUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionlessUnit getBaseUnit() {
|
||||
return (DimensionlessUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimensionless of(double magnitude) {
|
||||
return new Dimensionless(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimensionless ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Dimensionless(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimensionless zero() {
|
||||
return (Dimensionless) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimensionless one() {
|
||||
return (Dimensionless) super.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another dimensionless unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other dimensionless unit
|
||||
* @param otherUnit the other dimensionless unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, DimensionlessUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a frequency unit as the ratio of this dimensionless unit to the period of time in which
|
||||
* a single cycle is made.
|
||||
*
|
||||
* @param period the cycle period
|
||||
* @return the combined frequency unit
|
||||
*/
|
||||
@Override
|
||||
public FrequencyUnit per(TimeUnit period) {
|
||||
return FrequencyUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<DimensionlessUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
}
|
||||
95
wpiunits/src/main/java/org/wpilib/units/DistanceUnit.java
Normal file
95
wpiunits/src/main/java/org/wpilib/units/DistanceUnit.java
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Distance;
|
||||
|
||||
/**
|
||||
* Unit of linear dimension.
|
||||
*
|
||||
* <p>This is the base type for units of linear dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<DistanceUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Meters} and {@link Units#Inches}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class DistanceUnit extends Unit {
|
||||
DistanceUnit(DistanceUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
DistanceUnit(
|
||||
DistanceUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistanceUnit getBaseUnit() {
|
||||
return (DistanceUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocityUnit per(TimeUnit period) {
|
||||
return LinearVelocityUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<DistanceUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another distance unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other distance unit
|
||||
* @param otherUnit the other distance unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, DistanceUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance of(double magnitude) {
|
||||
return new Distance(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Distance(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance zero() {
|
||||
return (Distance) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance one() {
|
||||
return (Distance) super.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this distance unit by a unit of force to create a unit of torque.
|
||||
*
|
||||
* @param force the unit of force
|
||||
* @return the combined torque unit
|
||||
*/
|
||||
public TorqueUnit multAsTorque(ForceUnit force) {
|
||||
return TorqueUnit.combine(this, force);
|
||||
}
|
||||
|
||||
// TODO: Add a multAsEnergy equivalent
|
||||
}
|
||||
89
wpiunits/src/main/java/org/wpilib/units/EnergyUnit.java
Normal file
89
wpiunits/src/main/java/org/wpilib/units/EnergyUnit.java
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Energy;
|
||||
|
||||
/**
|
||||
* Unit of energy dimension.
|
||||
*
|
||||
* <p>This is the base type for units of energy dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<EnergyUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Joules} and {@link Units#Kilojoules}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class EnergyUnit extends Unit {
|
||||
EnergyUnit(
|
||||
EnergyUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
EnergyUnit(EnergyUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnergyUnit getBaseUnit() {
|
||||
return (EnergyUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this unit of energy with a unit of time to create a unit of power.
|
||||
*
|
||||
* @param period the period of the change in energy
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
@Override
|
||||
public PowerUnit per(TimeUnit period) {
|
||||
return PowerUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<EnergyUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, EnergyUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Energy of(double magnitude) {
|
||||
return new Energy(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Energy ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Energy(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Energy zero() {
|
||||
return (Energy) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Energy one() {
|
||||
return (Energy) super.one();
|
||||
}
|
||||
}
|
||||
106
wpiunits/src/main/java/org/wpilib/units/ForceUnit.java
Normal file
106
wpiunits/src/main/java/org/wpilib/units/ForceUnit.java
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Force;
|
||||
|
||||
/** A unit of force like {@link Units#Newtons}. */
|
||||
public final class ForceUnit extends MultUnit<MassUnit, LinearAccelerationUnit> {
|
||||
private static final CombinatoryUnitCache<MassUnit, LinearAccelerationUnit, ForceUnit> cache =
|
||||
new CombinatoryUnitCache<>(ForceUnit::new);
|
||||
|
||||
ForceUnit(MassUnit mass, LinearAccelerationUnit acceleration) {
|
||||
super(
|
||||
mass.isBaseUnit() && acceleration.isBaseUnit()
|
||||
? null
|
||||
: combine(mass.getBaseUnit(), acceleration.getBaseUnit()),
|
||||
mass,
|
||||
acceleration);
|
||||
}
|
||||
|
||||
ForceUnit(
|
||||
ForceUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a mass and (linear) acceleration to form a unit of force.
|
||||
*
|
||||
* @param mass the unit of mass
|
||||
* @param acceleration the unit of acceleration
|
||||
* @return the combined unit of force
|
||||
*/
|
||||
public static ForceUnit combine(MassUnit mass, LinearAccelerationUnit acceleration) {
|
||||
return cache.combine(mass, acceleration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForceUnit getBaseUnit() {
|
||||
return (ForceUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this force unit by a unit of distance to create a unit of torque.
|
||||
*
|
||||
* @param distance the unit of distance
|
||||
* @return the combined torque unit
|
||||
*/
|
||||
public TorqueUnit multAsTorque(DistanceUnit distance) {
|
||||
return TorqueUnit.combine(distance, this);
|
||||
}
|
||||
|
||||
// TODO: Add a multAsEnergy equivalent
|
||||
|
||||
@Override
|
||||
public Force of(double magnitude) {
|
||||
return new Force(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Force ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Force(toBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Force zero() {
|
||||
return (Force) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Force one() {
|
||||
return (Force) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<ForceUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<ForceUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, ForceUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
107
wpiunits/src/main/java/org/wpilib/units/FrequencyUnit.java
Normal file
107
wpiunits/src/main/java/org/wpilib/units/FrequencyUnit.java
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import static edu.wpi.first.units.Units.Value;
|
||||
|
||||
import edu.wpi.first.units.measure.Frequency;
|
||||
|
||||
/** A unit of frequency like {@link edu.wpi.first.units.Units#Hertz}. */
|
||||
public final class FrequencyUnit extends PerUnit<DimensionlessUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<DimensionlessUnit, TimeUnit, FrequencyUnit> cache =
|
||||
new CombinatoryUnitCache<>(FrequencyUnit::new);
|
||||
|
||||
FrequencyUnit(DimensionlessUnit numerator, TimeUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
FrequencyUnit(
|
||||
FrequencyUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a dimensionless unit and a cycle period to create a frequency.
|
||||
*
|
||||
* @param dim the dimensionless unit
|
||||
* @param period the unit of time
|
||||
* @return the combined unit of frequency
|
||||
*/
|
||||
public static FrequencyUnit combine(DimensionlessUnit dim, TimeUnit period) {
|
||||
return cache.combine(dim, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrequencyUnit getBaseUnit() {
|
||||
return (FrequencyUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts a unit of time to get its corresponding frequency (as if the unit of time is the period
|
||||
* of the frequency).
|
||||
*
|
||||
* @param time period of the associated frequency
|
||||
* @return the frequency associated with the period
|
||||
*/
|
||||
public static FrequencyUnit inverse(TimeUnit time) {
|
||||
return combine(Value, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frequency of(double magnitude) {
|
||||
return new Frequency(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frequency ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Frequency(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frequency zero() {
|
||||
return (Frequency) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frequency one() {
|
||||
return (Frequency) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<FrequencyUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<FrequencyUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, FrequencyUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Dimensionless;
|
||||
|
||||
/**
|
||||
* A measure holds the magnitude and unit of some dimension, such as distance, time, or speed. An
|
||||
* immutable measure is <i>immutable</i> and <i>type safe</i>, making it easy to use in concurrent
|
||||
* situations and gives compile-time safety. Two measures with the same <i>unit</i> and
|
||||
* <i>magnitude</i> are effectively equivalent objects.
|
||||
*
|
||||
* @param magnitude the magnitude of the measure in terms of its unit
|
||||
* @param baseUnitMagnitude the magnitude of the measure in terms of its base unit
|
||||
* @param unit the unit of the measurement
|
||||
* @param <U> the unit type of the measure
|
||||
*/
|
||||
public record ImmutableMeasure<U extends Unit>(double magnitude, double baseUnitMagnitude, U unit)
|
||||
implements Measure<U> {
|
||||
/**
|
||||
* Creates a new measure in the given unit with a magnitude equal to the given one in base units.
|
||||
*
|
||||
* @param <U> the type of the units of measure
|
||||
* @param baseUnitMagnitude the magnitude of the measure, in terms of the base unit of measure
|
||||
* @param unit the unit of measure
|
||||
* @return a new measure
|
||||
*/
|
||||
public static <U extends Unit> ImmutableMeasure<U> ofBaseUnits(double baseUnitMagnitude, U unit) {
|
||||
return new ImmutableMeasure<>(unit.fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new measure in the given unit with a magnitude in terms of that unit.
|
||||
*
|
||||
* @param <U> the type of the units of measure
|
||||
* @param relativeMagnitude the magnitude of the measure
|
||||
* @param unit the unit of measure
|
||||
* @return a new measure
|
||||
*/
|
||||
public static <U extends Unit> ImmutableMeasure<U> ofRelativeUnits(
|
||||
double relativeMagnitude, U unit) {
|
||||
return new ImmutableMeasure<>(relativeMagnitude, unit.toBaseUnits(relativeMagnitude), unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> unaryMinus() {
|
||||
return ofBaseUnits(0 - baseUnitMagnitude, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> plus(Measure<? extends U> other) {
|
||||
return ofBaseUnits(baseUnitMagnitude + other.baseUnitMagnitude(), unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> minus(Measure<? extends U> other) {
|
||||
return ofBaseUnits(baseUnitMagnitude - other.baseUnitMagnitude(), unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> times(double multiplier) {
|
||||
return ofBaseUnits(baseUnitMagnitude * multiplier, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> times(Dimensionless multiplier) {
|
||||
return ofBaseUnits(baseUnitMagnitude * multiplier.baseUnitMagnitude(), unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> div(double divisor) {
|
||||
return ofBaseUnits(baseUnitMagnitude / divisor, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Measure<U> div(Dimensionless divisor) {
|
||||
return ofBaseUnits(baseUnitMagnitude / divisor.baseUnitMagnitude(), unit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.LinearAcceleration;
|
||||
|
||||
/**
|
||||
* A unit of linear acceleration like {@link edu.wpi.first.units.Units#MetersPerSecondPerSecond}.
|
||||
*/
|
||||
public final class LinearAccelerationUnit extends PerUnit<LinearVelocityUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<LinearVelocityUnit, TimeUnit, LinearAccelerationUnit>
|
||||
cache = new CombinatoryUnitCache<>(LinearAccelerationUnit::new);
|
||||
|
||||
LinearAccelerationUnit(LinearVelocityUnit numerator, TimeUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
LinearAccelerationUnit(
|
||||
LinearAccelerationUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a linear velocity and time unit to form a unit of linear acceleration.
|
||||
*
|
||||
* @param velocity the unit of linear velocity
|
||||
* @param period the unit of time
|
||||
* @return the combined unit of linear acceleration
|
||||
*/
|
||||
public static LinearAccelerationUnit combine(LinearVelocityUnit velocity, TimeUnit period) {
|
||||
return cache.combine(velocity, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearAccelerationUnit getBaseUnit() {
|
||||
return (LinearAccelerationUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearAcceleration of(double magnitude) {
|
||||
return new LinearAcceleration(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearAcceleration ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new LinearAcceleration(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearAcceleration zero() {
|
||||
return (LinearAcceleration) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearAcceleration one() {
|
||||
return (LinearAcceleration) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<LinearAccelerationUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<LinearAccelerationUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, LinearAccelerationUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unit of the changing velocity. This is equivalent to {@link #numerator()} and is left
|
||||
* for historical purposes.
|
||||
*
|
||||
* @return the unit of the changing velocity
|
||||
*/
|
||||
public LinearVelocityUnit getUnit() {
|
||||
return numerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unit of the acceleration period (how long it takes for a measured velocity to change
|
||||
* by one unit of velocity). This is equivalent to {@link #numerator()} and is left for historical
|
||||
* purposes.
|
||||
*
|
||||
* @return the unit of the acceleration period
|
||||
*/
|
||||
public TimeUnit getPeriod() {
|
||||
return denominator();
|
||||
}
|
||||
}
|
||||
104
wpiunits/src/main/java/org/wpilib/units/LinearMomentumUnit.java
Normal file
104
wpiunits/src/main/java/org/wpilib/units/LinearMomentumUnit.java
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.LinearMomentum;
|
||||
|
||||
/** A unit of linear momentum like {@link edu.wpi.first.units.Units#KilogramMetersPerSecond}. */
|
||||
public final class LinearMomentumUnit extends MultUnit<MassUnit, LinearVelocityUnit> {
|
||||
private static final CombinatoryUnitCache<MassUnit, LinearVelocityUnit, LinearMomentumUnit>
|
||||
cache = new CombinatoryUnitCache<>(LinearMomentumUnit::new);
|
||||
|
||||
LinearMomentumUnit(MassUnit unit, LinearVelocityUnit linearVelocityUnit) {
|
||||
super(
|
||||
unit.isBaseUnit() && linearVelocityUnit.isBaseUnit()
|
||||
? null
|
||||
: combine(unit.getBaseUnit(), linearVelocityUnit.getBaseUnit()),
|
||||
unit,
|
||||
linearVelocityUnit);
|
||||
}
|
||||
|
||||
LinearMomentumUnit(
|
||||
MultUnit<MassUnit, LinearVelocityUnit> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a mass and linear velocity unit to form a combined linear momentum unit.
|
||||
*
|
||||
* @param mass the unit of mass
|
||||
* @param velocity the unit of velocity
|
||||
* @return the combined unit of momentum
|
||||
*/
|
||||
public static LinearMomentumUnit combine(MassUnit mass, LinearVelocityUnit velocity) {
|
||||
return cache.combine(mass, velocity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearMomentumUnit getBaseUnit() {
|
||||
return (LinearMomentumUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearMomentum of(double magnitude) {
|
||||
return new LinearMomentum(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearMomentum ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new LinearMomentum(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearMomentum zero() {
|
||||
return (LinearMomentum) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearMomentum one() {
|
||||
return (LinearMomentum) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<LinearMomentumUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<LinearMomentumUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, LinearMomentumUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this unit by distance to form a unit of angular momentum.
|
||||
*
|
||||
* @param distance the unit of distance
|
||||
* @return the combined unit of angular momentum
|
||||
*/
|
||||
public AngularMomentumUnit mult(DistanceUnit distance) {
|
||||
return AngularMomentumUnit.combine(this, distance);
|
||||
}
|
||||
}
|
||||
100
wpiunits/src/main/java/org/wpilib/units/LinearVelocityUnit.java
Normal file
100
wpiunits/src/main/java/org/wpilib/units/LinearVelocityUnit.java
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.LinearVelocity;
|
||||
|
||||
/** A unit of linear velocity like {@link edu.wpi.first.units.Units#MetersPerSecond}. */
|
||||
public final class LinearVelocityUnit extends PerUnit<DistanceUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<DistanceUnit, TimeUnit, LinearVelocityUnit> cache =
|
||||
new CombinatoryUnitCache<>(LinearVelocityUnit::new);
|
||||
|
||||
LinearVelocityUnit(DistanceUnit unit, TimeUnit period) {
|
||||
super(
|
||||
unit.isBaseUnit() && period.isBaseUnit()
|
||||
? null
|
||||
: combine(unit.getBaseUnit(), period.getBaseUnit()),
|
||||
unit,
|
||||
period);
|
||||
}
|
||||
|
||||
LinearVelocityUnit(
|
||||
PerUnit<DistanceUnit, TimeUnit> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a distance and time unit for form a combined unit of velocity.
|
||||
*
|
||||
* @param distance the unit of distance
|
||||
* @param period the unit of time
|
||||
* @return the combined velocity unit
|
||||
*/
|
||||
public static LinearVelocityUnit combine(DistanceUnit distance, TimeUnit period) {
|
||||
return cache.combine(distance, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocityUnit getBaseUnit() {
|
||||
return (LinearVelocityUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocity of(double magnitude) {
|
||||
return new LinearVelocity(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocity ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new LinearVelocity(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocity zero() {
|
||||
return (LinearVelocity) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearVelocity one() {
|
||||
return (LinearVelocity) super.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this velocity with a time period of change to form a unit of acceleration.
|
||||
*
|
||||
* @param period the period of change in the velocity
|
||||
* @return the combined acceleration unit
|
||||
*/
|
||||
@Override
|
||||
public LinearAccelerationUnit per(TimeUnit period) {
|
||||
return LinearAccelerationUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<LinearVelocityUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, LinearVelocityUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
105
wpiunits/src/main/java/org/wpilib/units/MassUnit.java
Normal file
105
wpiunits/src/main/java/org/wpilib/units/MassUnit.java
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Mass;
|
||||
|
||||
/**
|
||||
* Unit of mass dimension.
|
||||
*
|
||||
* <p>This is the base type for units of mass dimension. It is also used to specify the dimension
|
||||
* for the mass-specific {@link Mass} measurement type.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Grams} and {@link Units#Pounds}) can be found in the {@link
|
||||
* Units} class.
|
||||
*/
|
||||
public final class MassUnit extends Unit {
|
||||
/** Creates a new unit with the given name and multiplier to the base unit. */
|
||||
MassUnit(MassUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
MassUnit(
|
||||
MassUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MassUnit getBaseUnit() {
|
||||
return (MassUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mass of(double magnitude) {
|
||||
return new Mass(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mass ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Mass(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mass zero() {
|
||||
return (Mass) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mass one() {
|
||||
return (Mass) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<MassUnit> per(TimeUnit period) {
|
||||
return VelocityUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<MassUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another mass unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other mass unit
|
||||
* @param otherUnit the other mass unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, MassUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this mass unit by a unit of linear velocity to form a combined unit of linear
|
||||
* momentum.
|
||||
*
|
||||
* @param velocity the unit of velocity
|
||||
* @return the combined unit of momentum
|
||||
*/
|
||||
public LinearMomentumUnit mult(LinearVelocityUnit velocity) {
|
||||
return LinearMomentumUnit.combine(this, velocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this mass unit by a unit of linear acceleration to form a combined unit of force.
|
||||
*
|
||||
* @param acceleration the unit of acceleration
|
||||
* @return the combined unit of force
|
||||
*/
|
||||
public ForceUnit mult(LinearAccelerationUnit acceleration) {
|
||||
return ForceUnit.combine(this, acceleration);
|
||||
}
|
||||
}
|
||||
1787
wpiunits/src/main/java/org/wpilib/units/Measure.java
Normal file
1787
wpiunits/src/main/java/org/wpilib/units/Measure.java
Normal file
File diff suppressed because it is too large
Load Diff
100
wpiunits/src/main/java/org/wpilib/units/MomentOfInertiaUnit.java
Normal file
100
wpiunits/src/main/java/org/wpilib/units/MomentOfInertiaUnit.java
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.MomentOfInertia;
|
||||
|
||||
/**
|
||||
* A unit of moment of inertia, like {@link edu.wpi.first.units.Units#KilogramSquareMeters}. Moments
|
||||
* of inertia describe how much an object resists being rotated, analogous to mass's resistance to
|
||||
* being accelerated along a line.
|
||||
*/
|
||||
public final class MomentOfInertiaUnit extends PerUnit<AngularMomentumUnit, AngularVelocityUnit> {
|
||||
private static final CombinatoryUnitCache<
|
||||
AngularMomentumUnit, AngularVelocityUnit, MomentOfInertiaUnit>
|
||||
cache = new CombinatoryUnitCache<>(MomentOfInertiaUnit::new);
|
||||
|
||||
MomentOfInertiaUnit(AngularMomentumUnit numerator, AngularVelocityUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
MomentOfInertiaUnit(
|
||||
MomentOfInertiaUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an angular momentum and angular velocity unit to form a moment of inertia unit.
|
||||
*
|
||||
* @param momentumUnit the unit of angular momentum
|
||||
* @param velocityUnit the unit of angular velocity
|
||||
* @return the combined moment of inertia unit
|
||||
*/
|
||||
public static MomentOfInertiaUnit combine(
|
||||
AngularMomentumUnit momentumUnit, AngularVelocityUnit velocityUnit) {
|
||||
return cache.combine(momentumUnit, velocityUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomentOfInertiaUnit getBaseUnit() {
|
||||
return (MomentOfInertiaUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomentOfInertia of(double magnitude) {
|
||||
return new MomentOfInertia(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomentOfInertia ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new MomentOfInertia(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomentOfInertia zero() {
|
||||
return (MomentOfInertia) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MomentOfInertia one() {
|
||||
return (MomentOfInertia) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<MomentOfInertiaUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<MomentOfInertiaUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, MomentOfInertiaUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
222
wpiunits/src/main/java/org/wpilib/units/MultUnit.java
Normal file
222
wpiunits/src/main/java/org/wpilib/units/MultUnit.java
Normal file
@@ -0,0 +1,222 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Mult;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A combinatory unit type that is equivalent to the product of two other others. Note that
|
||||
* algebraic reduction is not possible in Java's generic type system, so {@code MultUnit<A, B>} is
|
||||
* not type-compatible with {@code MultUnit<B, A>}!
|
||||
*
|
||||
* @param <A> the type of the first unit in the result
|
||||
* @param <B> the type of the second unit in the result
|
||||
*/
|
||||
public class MultUnit<A extends Unit, B extends Unit> extends Unit {
|
||||
private final A m_unitA;
|
||||
private final B m_unitB;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final CombinatoryUnitCache<Unit, Unit, MultUnit> cache =
|
||||
new CombinatoryUnitCache<>(MultUnit::new);
|
||||
|
||||
/**
|
||||
* Creates a new product unit. Consider using {@link #combine} instead of manually calling this
|
||||
* constructor.
|
||||
*
|
||||
* @param a the first unit of the product
|
||||
* @param b the second unit of the product
|
||||
*/
|
||||
private MultUnit(A a, B b) {
|
||||
super(
|
||||
a.isBaseUnit() && b.isBaseUnit() ? null : combine(a.getBaseUnit(), b.getBaseUnit()),
|
||||
a.toBaseUnits(1) * b.toBaseUnits(1),
|
||||
a.name() + "-" + b.name(),
|
||||
a.symbol() + "*" + b.symbol());
|
||||
m_unitA = a;
|
||||
m_unitB = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new product unit. Subclasses of {@code MultUnit} should use this constructor.
|
||||
*
|
||||
* @param baseUnit the base unit. Set this to null if the unit being constructed is its own base
|
||||
* unit
|
||||
* @param a the first unit of the product
|
||||
* @param b the second unit of the product
|
||||
*/
|
||||
protected MultUnit(MultUnit<A, B> baseUnit, A a, B b) {
|
||||
super(
|
||||
baseUnit,
|
||||
a.toBaseUnits(1) * b.toBaseUnits(1),
|
||||
a.name() + "-" + b.name(),
|
||||
a.symbol() + "*" + b.symbol());
|
||||
m_unitA = a;
|
||||
m_unitB = b;
|
||||
}
|
||||
|
||||
MultUnit(
|
||||
MultUnit<A, B> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
m_unitA = getBaseUnit().unitA();
|
||||
m_unitB = getBaseUnit().unitB();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MultUnit unit derived from two arbitrary units multiplied together.
|
||||
*
|
||||
* <pre>
|
||||
* MultUnit.combine(Volts, Meters) // Volt-Meters
|
||||
* </pre>
|
||||
*
|
||||
* @param <A> the type of the first unit
|
||||
* @param <B> the type of the second unit
|
||||
* @param a the first unit
|
||||
* @param b the second unit
|
||||
* @return the combined unit
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Unit, B extends Unit> MultUnit<A, B> combine(A a, B b) {
|
||||
return cache.combine(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Note: When called on an object of type {@code MultUnit} (and <i>not</i> a subclass!), this
|
||||
* method will always return a {@link edu.wpi.first.units.measure.Mult} instance. If you want to
|
||||
* avoid casting, use {@link #ofNativeBaseUnits(double)} that returns a {@code Per} instance
|
||||
* directly.
|
||||
*
|
||||
* @param magnitude the magnitude of the measure in terms of its base units.
|
||||
* @return the measurement object
|
||||
*/
|
||||
@Override
|
||||
public Measure<? extends MultUnit<A, B>> of(double magnitude) {
|
||||
return ofNative(magnitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Note: When called on an object of type {@code MultUnit} (and <i>not</i> a subclass!), this
|
||||
* method will always return a {@link edu.wpi.first.units.measure.Mult} instance. If you want to
|
||||
* avoid casting, use {@link #ofNativeBaseUnits(double)} that returns a {@code Per} instance
|
||||
* directly.
|
||||
*
|
||||
* @param baseUnitMagnitude the magnitude of the measure in terms of its base units.
|
||||
* @return the measurement object
|
||||
*/
|
||||
@Override
|
||||
public Measure<? extends MultUnit<A, B>> ofBaseUnits(double baseUnitMagnitude) {
|
||||
return ofNativeBaseUnits(baseUnitMagnitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of this unit. This will
|
||||
* always return a {@code Mult} object and cannot be overridden by subclasses.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement.
|
||||
* @return the measurement object
|
||||
* @see #of(double)
|
||||
*/
|
||||
public final Mult<A, B> ofNative(double magnitude) {
|
||||
return new Mult<>(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of the unit's base unit.
|
||||
* This will always return a {@code Mult} object and cannot be overridden by subclasses.
|
||||
*
|
||||
* @param baseUnitMagnitude the magnitude of the measure in terms of its base units.
|
||||
* @return the measurement object
|
||||
* @see #ofBaseUnits(double)
|
||||
*/
|
||||
public final Mult<A, B> ofNativeBaseUnits(double baseUnitMagnitude) {
|
||||
return new Mult<>(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Measure<? extends MultUnit<A, B>> zero() {
|
||||
return (Measure<? extends MultUnit<A, B>>) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Measure<? extends MultUnit<A, B>> one() {
|
||||
return (Measure<? extends MultUnit<A, B>>) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, MultUnit<A, B> otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MultUnit<A, B> getBaseUnit() {
|
||||
return (MultUnit<A, B>) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first unit of the product.
|
||||
*
|
||||
* @return the first unit
|
||||
*/
|
||||
public A unitA() {
|
||||
return m_unitA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the second unit of the product.
|
||||
*
|
||||
* @return the second unit
|
||||
*/
|
||||
public B unitB() {
|
||||
return m_unitB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + m_unitA.toString() + " * " + m_unitB.toString() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
MultUnit<?, ?> multUnit = (MultUnit<?, ?>) o;
|
||||
return Objects.equals(m_unitA, multUnit.m_unitA) && Objects.equals(m_unitB, multUnit.m_unitB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), m_unitA, m_unitB);
|
||||
}
|
||||
}
|
||||
259
wpiunits/src/main/java/org/wpilib/units/PerUnit.java
Normal file
259
wpiunits/src/main/java/org/wpilib/units/PerUnit.java
Normal file
@@ -0,0 +1,259 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Per;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Generic combinatory unit type that represents the proportion of one unit to another, such as
|
||||
* Meters per Second or Radians per Celsius.
|
||||
*
|
||||
* @param <N> the type of the numerator unit
|
||||
* @param <D> the type of the denominator unit
|
||||
*/
|
||||
public class PerUnit<N extends Unit, D extends Unit> extends Unit {
|
||||
private final N m_numerator;
|
||||
private final D m_denominator;
|
||||
|
||||
/**
|
||||
* Keep a cache of created instances so expressions like Volts.per(Meter) don't do any allocations
|
||||
* after the first.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final CombinatoryUnitCache<Unit, Unit, PerUnit> cache =
|
||||
new CombinatoryUnitCache<>(PerUnit::new);
|
||||
|
||||
/**
|
||||
* Creates a new proportional unit derived from the ratio of one unit to another. Consider using
|
||||
* {@link #combine} instead of manually calling this constructor.
|
||||
*
|
||||
* @param numerator the numerator unit
|
||||
* @param denominator the denominator unit
|
||||
*/
|
||||
private PerUnit(N numerator, D denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator.toBaseUnits(1) / denominator.toBaseUnits(1),
|
||||
numerator.name() + " per " + denominator.name(),
|
||||
numerator.symbol() + "/" + denominator.symbol());
|
||||
m_numerator = numerator;
|
||||
m_denominator = denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new proportional unit derived from the ratio of one unit to another. Subclasses of
|
||||
* {@code PerUnit} should use this constructor.
|
||||
*
|
||||
* @param baseUnit the base unit. Set this to null if the unit being constructed is its own base
|
||||
* unit
|
||||
* @param numerator the numerator unit
|
||||
* @param denominator the denominator unit
|
||||
*/
|
||||
protected PerUnit(PerUnit<N, D> baseUnit, N numerator, D denominator) {
|
||||
super(
|
||||
baseUnit,
|
||||
numerator.toBaseUnits(1) / denominator.toBaseUnits(1),
|
||||
numerator.name() + " per " + denominator.name(),
|
||||
numerator.symbol() + "/" + denominator.symbol());
|
||||
m_numerator = numerator;
|
||||
m_denominator = denominator;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
PerUnit(
|
||||
PerUnit<N, D> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
m_numerator = getBaseUnit().numerator();
|
||||
m_denominator = getBaseUnit().denominator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PerUnit unit derived from an arbitrary numerator and time denominator units.
|
||||
*
|
||||
* <pre>
|
||||
* PerUnit.combine(Volts, Meters) // possible PID constant
|
||||
* </pre>
|
||||
*
|
||||
* @param <N> the type of the numerator unit
|
||||
* @param <D> the type of the denominator unit
|
||||
* @param numerator the numerator unit
|
||||
* @param denominator the denominator for unit time
|
||||
* @return the combined unit
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <N extends Unit, D extends Unit> PerUnit<N, D> combine(N numerator, D denominator) {
|
||||
return cache.combine(numerator, denominator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public PerUnit<N, D> getBaseUnit() {
|
||||
return (PerUnit<N, D>) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the numerator unit. For a {@code PerUnit<A, B>}, this will return the {@code A} unit.
|
||||
*
|
||||
* @return the numerator unit
|
||||
*/
|
||||
public N numerator() {
|
||||
return m_numerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the denominator unit. For a {@code PerUnit<A, B>}, this will return the {@code B} unit.
|
||||
*
|
||||
* @return the denominator unit
|
||||
*/
|
||||
public D denominator() {
|
||||
return m_denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reciprocal of this PerUnit.
|
||||
*
|
||||
* @return the reciprocal
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PerUnit<D, N> reciprocal() {
|
||||
if (m_numerator instanceof TimeUnit t) {
|
||||
// Dividing by time, return a velocity
|
||||
return (PerUnit<D, N>) VelocityUnit.combine(m_denominator, t);
|
||||
} else {
|
||||
// Generic case
|
||||
return combine(m_denominator, m_numerator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this unit by a unit of its denominator.
|
||||
*
|
||||
* @param denom the denominator-typed unit to multiply by
|
||||
* @return the result
|
||||
*/
|
||||
public N mult(D denom) {
|
||||
if (denom.equivalent(denominator())) {
|
||||
return numerator();
|
||||
}
|
||||
|
||||
return Units.derive(numerator())
|
||||
.toBase(denom.getConverterToBase().div(denominator().getConverterToBase()))
|
||||
.fromBase(denom.getConverterFromBase().div(denominator().getConverterFromBase()))
|
||||
.named(name() + " " + denom.name())
|
||||
.symbol(symbol() + "-" + denom.symbol())
|
||||
.make();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Note: When called on an object of type {@code PerUnit} (and <i>not</i> a subclass!), this
|
||||
* method will always return a {@link edu.wpi.first.units.measure.Per} instance. If you want to
|
||||
* avoid casting, use {@link #ofNative(double)} that returns a {@code Per} instance directly.
|
||||
*
|
||||
* @param magnitude the magnitude of the measure
|
||||
* @return the ratio measure
|
||||
*/
|
||||
@Override
|
||||
public Measure<? extends PerUnit<N, D>> of(double magnitude) {
|
||||
return ofNative(magnitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Note: When called on an object of type {@code PerUnit} (and <i>not</i> a subclass!), this
|
||||
* method will always return a {@link edu.wpi.first.units.measure.Per} instance. If you want to
|
||||
* avoid casting, use {@link #ofNativeBaseUnits(double)} that returns a {@code Per} instance
|
||||
* directly.
|
||||
*
|
||||
* @param baseUnitMagnitude the magnitude of the measure in terms of its base units.
|
||||
* @return the ratio measure
|
||||
*/
|
||||
@Override
|
||||
public Measure<? extends PerUnit<N, D>> ofBaseUnits(double baseUnitMagnitude) {
|
||||
return ofNativeBaseUnits(baseUnitMagnitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of the ratio unit. This
|
||||
* will always return a {@code Per} object and cannot be overridden by subclasses.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement.
|
||||
* @return the measurement object
|
||||
* @see #of(double)
|
||||
*/
|
||||
public final Per<N, D> ofNative(double magnitude) {
|
||||
return new Per<>(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of the ratio unit's base
|
||||
* unit. This will always return a {@code Per} object and cannot be overridden by subclasses.
|
||||
*
|
||||
* @param baseUnitMagnitude the magnitude of the measure in terms of its base units.
|
||||
* @return the measurement object
|
||||
* @see #ofBaseUnits(double)
|
||||
*/
|
||||
public final Per<N, D> ofNativeBaseUnits(double baseUnitMagnitude) {
|
||||
return new Per<>(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Measure<? extends PerUnit<N, D>> zero() {
|
||||
return (Measure<? extends PerUnit<N, D>>) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Measure<? extends PerUnit<N, D>> one() {
|
||||
return (Measure<? extends PerUnit<N, D>>) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, PerUnit<? extends N, ? extends D> otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
PerUnit<?, ?> perUnit = (PerUnit<?, ?>) o;
|
||||
return Objects.equals(m_numerator, perUnit.m_numerator)
|
||||
&& Objects.equals(m_denominator, perUnit.m_denominator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), m_numerator, m_denominator);
|
||||
}
|
||||
}
|
||||
157
wpiunits/src/main/java/org/wpilib/units/PowerUnit.java
Normal file
157
wpiunits/src/main/java/org/wpilib/units/PowerUnit.java
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import static edu.wpi.first.units.Units.Joules;
|
||||
import static edu.wpi.first.units.Units.Seconds;
|
||||
|
||||
import edu.wpi.first.units.measure.Power;
|
||||
|
||||
/**
|
||||
* Unit of power dimension.
|
||||
*
|
||||
* <p>This is the base type for units of power dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<PowerUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Watts} and {@link Units#Horsepower}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class PowerUnit extends PerUnit<EnergyUnit, TimeUnit> {
|
||||
private static final CombinatoryUnitCache<EnergyUnit, TimeUnit, PowerUnit> cache =
|
||||
new CombinatoryUnitCache<>(PowerUnit::new);
|
||||
|
||||
PowerUnit(EnergyUnit energy, TimeUnit time) {
|
||||
super(
|
||||
energy.isBaseUnit() && time.isBaseUnit()
|
||||
? null
|
||||
: combine(energy.getBaseUnit(), time.getBaseUnit()),
|
||||
energy,
|
||||
time);
|
||||
}
|
||||
|
||||
PowerUnit(
|
||||
PowerUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an energy and a time unit to form a unit of power.
|
||||
*
|
||||
* @param energy the unit of energy
|
||||
* @param period the unit of time
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
public static PowerUnit combine(EnergyUnit energy, TimeUnit period) {
|
||||
return cache.combine(energy, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines voltage and current into power.
|
||||
*
|
||||
* @param voltage the unit of voltage
|
||||
* @param current the unit of current
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
public static PowerUnit combine(VoltageUnit voltage, CurrentUnit current) {
|
||||
return combine(
|
||||
new EnergyUnit(
|
||||
Joules,
|
||||
voltage.toBaseUnits(1) * current.toBaseUnits(1),
|
||||
voltage.name() + "-" + current.name(),
|
||||
voltage.symbol() + "*" + current.symbol()),
|
||||
Seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines voltage and current into power.
|
||||
*
|
||||
* @param current the unit of current
|
||||
* @param voltage the unit of voltage
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
public static PowerUnit combine(CurrentUnit current, VoltageUnit voltage) {
|
||||
return combine(voltage, current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
|
||||
*
|
||||
* @param angularVelocity the unit of angular velocity
|
||||
* @param torque the unit of torque
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
public static PowerUnit combine(AngularVelocityUnit angularVelocity, TorqueUnit torque) {
|
||||
return combine(
|
||||
new EnergyUnit(Joules, angularVelocity.toBaseUnits(1) * torque.toBaseUnits(1), "", ""),
|
||||
Seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines angular velocity and torque into power. Useful when dealing with motors and flywheels.
|
||||
*
|
||||
* @param torque the unit of torque
|
||||
* @param angularVelocity the unit of angular velocity
|
||||
* @return the combined unit of power
|
||||
*/
|
||||
public static PowerUnit combine(TorqueUnit torque, AngularVelocityUnit angularVelocity) {
|
||||
return combine(angularVelocity, torque);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PowerUnit getBaseUnit() {
|
||||
return (PowerUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Power of(double magnitude) {
|
||||
return new Power(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Power ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Power(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Power zero() {
|
||||
return (Power) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Power one() {
|
||||
return (Power) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<PowerUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<PowerUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another power unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other power unit
|
||||
* @param otherUnit the other power unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, PowerUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
97
wpiunits/src/main/java/org/wpilib/units/ResistanceUnit.java
Normal file
97
wpiunits/src/main/java/org/wpilib/units/ResistanceUnit.java
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Resistance;
|
||||
|
||||
/**
|
||||
* Unit of resistance dimension.
|
||||
*
|
||||
* <p>This is the base type for units of resistance dimension. It is also used to specify the
|
||||
* dimension for {@link Measure}: <code>Measure<ResistanceUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Ohms} and {@link Units#KiloOhms}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class ResistanceUnit extends PerUnit<VoltageUnit, CurrentUnit> {
|
||||
private static final CombinatoryUnitCache<VoltageUnit, CurrentUnit, ResistanceUnit> cache =
|
||||
new CombinatoryUnitCache<>(ResistanceUnit::new);
|
||||
|
||||
ResistanceUnit(VoltageUnit numerator, CurrentUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine(numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
ResistanceUnit(
|
||||
ResistanceUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an voltage and a current unit to form a unit of resistance.
|
||||
*
|
||||
* @param voltage the unit of voltage
|
||||
* @param current the unit of current
|
||||
* @return the combined unit of resistance
|
||||
*/
|
||||
public static ResistanceUnit combine(VoltageUnit voltage, CurrentUnit current) {
|
||||
return cache.combine(voltage, current);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResistanceUnit getBaseUnit() {
|
||||
return (ResistanceUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resistance of(double magnitude) {
|
||||
return new Resistance(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resistance ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Resistance(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resistance zero() {
|
||||
return (Resistance) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resistance one() {
|
||||
return (Resistance) super.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<ResistanceUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another power unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other power unit
|
||||
* @param otherUnit the other power unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, ResistanceUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
79
wpiunits/src/main/java/org/wpilib/units/TemperatureUnit.java
Normal file
79
wpiunits/src/main/java/org/wpilib/units/TemperatureUnit.java
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Temperature;
|
||||
|
||||
/**
|
||||
* Unit of temperature dimension.
|
||||
*
|
||||
* <p>This is the base type for units of temperature dimension. It is also used to specify the
|
||||
* dimension for {@link Measure}: <code>Measure<TemperatureUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Celsius} and {@link Units#Fahrenheit}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class TemperatureUnit extends Unit {
|
||||
TemperatureUnit(
|
||||
TemperatureUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemperatureUnit getBaseUnit() {
|
||||
return (TemperatureUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature of(double magnitude) {
|
||||
return new Temperature(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Temperature(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature zero() {
|
||||
return (Temperature) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature one() {
|
||||
return (Temperature) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<TemperatureUnit> per(TimeUnit period) {
|
||||
return VelocityUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<TemperatureUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another temperature unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other temperature unit
|
||||
* @param otherUnit the other temperature unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, TemperatureUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
95
wpiunits/src/main/java/org/wpilib/units/TimeUnit.java
Normal file
95
wpiunits/src/main/java/org/wpilib/units/TimeUnit.java
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Time;
|
||||
|
||||
/**
|
||||
* Unit of time dimension.
|
||||
*
|
||||
* <p>This is the base type for units of time dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<TimeUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Seconds} and {@link Units#Milliseconds}) can be found in
|
||||
* the {@link Units} class.
|
||||
*/
|
||||
public final class TimeUnit extends Unit {
|
||||
TimeUnit(TimeUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
TimeUnit(
|
||||
TimeUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeUnit getBaseUnit() {
|
||||
return (TimeUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dimensionless unit corresponding to the scale factor between this and another unit of
|
||||
* time.
|
||||
*
|
||||
* @param other the other unit of time
|
||||
* @return the result
|
||||
*/
|
||||
@Override
|
||||
public DimensionlessUnit per(TimeUnit other) {
|
||||
return Units.derive(Units.Value)
|
||||
.toBase(this.getConverterToBase().div(other.getConverterToBase()))
|
||||
.fromBase(other.getConverterFromBase().div(this.getConverterFromBase()))
|
||||
.named(this.name() + " per " + other.name())
|
||||
.symbol(this.symbol() + "/" + other.symbol())
|
||||
.make();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<TimeUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, TimeUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Time of(double magnitude) {
|
||||
return new Time(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Time ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Time(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Time zero() {
|
||||
return (Time) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Time one() {
|
||||
return (Time) super.one();
|
||||
}
|
||||
}
|
||||
94
wpiunits/src/main/java/org/wpilib/units/TorqueUnit.java
Normal file
94
wpiunits/src/main/java/org/wpilib/units/TorqueUnit.java
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Torque;
|
||||
|
||||
/** A unit of torque like {@link edu.wpi.first.units.Units#NewtonMeters}. */
|
||||
public final class TorqueUnit extends MultUnit<DistanceUnit, ForceUnit> {
|
||||
private static final CombinatoryUnitCache<DistanceUnit, ForceUnit, TorqueUnit> cache =
|
||||
new CombinatoryUnitCache<>(TorqueUnit::new);
|
||||
|
||||
TorqueUnit(DistanceUnit distanceUnit, ForceUnit forceUnit) {
|
||||
super(
|
||||
distanceUnit.isBaseUnit() && forceUnit.isBaseUnit()
|
||||
? null
|
||||
: combine(distanceUnit.getBaseUnit(), forceUnit.getBaseUnit()),
|
||||
distanceUnit,
|
||||
forceUnit);
|
||||
}
|
||||
|
||||
TorqueUnit(
|
||||
MultUnit<DistanceUnit, ForceUnit> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a unit of distance and force to create a unit of torque.
|
||||
*
|
||||
* @param distance the distance unit
|
||||
* @param force the force unit
|
||||
* @return the combined torque unit
|
||||
*/
|
||||
public static TorqueUnit combine(DistanceUnit distance, ForceUnit force) {
|
||||
return cache.combine(distance, force);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TorqueUnit getBaseUnit() {
|
||||
return (TorqueUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Torque of(double magnitude) {
|
||||
return new Torque(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Torque ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Torque(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Torque zero() {
|
||||
return (Torque) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Torque one() {
|
||||
return (Torque) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<TorqueUnit> per(TimeUnit time) {
|
||||
return VelocityUnit.combine(this, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<TorqueUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other unit
|
||||
* @param otherUnit the other unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, TorqueUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
125
wpiunits/src/main/java/org/wpilib/units/UnaryFunction.java
Normal file
125
wpiunits/src/main/java/org/wpilib/units/UnaryFunction.java
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A function that accepts a single {@code double} and returns a {@code double} result. This is used
|
||||
* to represent arbitrary mapping functions for converting units to and from a base unit
|
||||
* representation. Temperature units, in particular, typically have an offset from a value in Kelvin
|
||||
* and may have a multiplication factor added in, which means that units cannot always be
|
||||
* represented as simple ratios of their base units.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UnaryFunction {
|
||||
/** The identity function that simply returns the input value. */
|
||||
UnaryFunction IDENTITY = x -> x;
|
||||
|
||||
/**
|
||||
* Applies this function to the input value and returns the result.
|
||||
*
|
||||
* @param input the input value to the function
|
||||
* @return the result
|
||||
*/
|
||||
double apply(double input);
|
||||
|
||||
/**
|
||||
* Constructs a new function that first calls this function, then passes the result to another as
|
||||
* input.
|
||||
*
|
||||
* <pre>
|
||||
* f = x -> x + 1 // f(x) = x + 1
|
||||
* g = x -> 2 * x // g(x) = 2x
|
||||
*
|
||||
* h = f.pipeTo(g) // h(x) = g(f(x))
|
||||
* </pre>
|
||||
*
|
||||
* @param next the next operation to pipe to
|
||||
* @return the composite function g(f(x))
|
||||
*/
|
||||
default UnaryFunction pipeTo(UnaryFunction next) {
|
||||
Objects.requireNonNull(next, "The next operation in the chain must be provided");
|
||||
|
||||
return x -> next.apply(this.apply(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = f(x) * g(x).
|
||||
*
|
||||
* @param multiplier the function to multiply this one by
|
||||
* @return the composite function f(x) * g(x)
|
||||
*/
|
||||
default UnaryFunction mult(UnaryFunction multiplier) {
|
||||
Objects.requireNonNull(multiplier, "A multiplier function must be provided");
|
||||
|
||||
return x -> this.apply(x) * multiplier.apply(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = k * f(x).
|
||||
*
|
||||
* @param multiplier the constant value to multiply this function's results by
|
||||
* @return the composite function k * f(x)
|
||||
*/
|
||||
default UnaryFunction mult(double multiplier) {
|
||||
return x -> this.apply(x) * multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = f(x) / g(x).
|
||||
*
|
||||
* @param divisor the function to divide this one by
|
||||
* @return the composite function f(x) / g(x)
|
||||
*/
|
||||
default UnaryFunction div(UnaryFunction divisor) {
|
||||
Objects.requireNonNull(divisor, "A divisor function must be provided");
|
||||
|
||||
return x -> {
|
||||
double numerator = this.apply(x);
|
||||
|
||||
// fast-track to avoid another function call
|
||||
// avoids returning NaN if divisor is also zero
|
||||
if (numerator == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double div = divisor.apply(x);
|
||||
return numerator / div; // NOTE: returns +Infinity or -Infinity if div is zero
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = 1/k * f(x).
|
||||
*
|
||||
* @param divisor the constant value to divide this function's results by
|
||||
* @return the composite function 1/k * f(x)
|
||||
*/
|
||||
default UnaryFunction div(double divisor) {
|
||||
return x -> this.apply(x) / divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = f(x) ^ g(x).
|
||||
*
|
||||
* @param exponent the function to exponentiate this function's results by
|
||||
* @return the composite function f(x) ^ g(x)
|
||||
*/
|
||||
default UnaryFunction exp(UnaryFunction exponent) {
|
||||
Objects.requireNonNull(exponent, "An exponent function must be provided");
|
||||
|
||||
return x -> Math.pow(this.apply(x), exponent.apply(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite function h(x) such that h(x) = f(x) ^ k.
|
||||
*
|
||||
* @param exponent the constant value to exponentiate this function's results by
|
||||
* @return the composite function f(x) ^ k
|
||||
*/
|
||||
default UnaryFunction exp(double exponent) {
|
||||
return x -> Math.pow(this.apply(x), exponent);
|
||||
}
|
||||
}
|
||||
251
wpiunits/src/main/java/org/wpilib/units/Unit.java
Normal file
251
wpiunits/src/main/java/org/wpilib/units/Unit.java
Normal file
@@ -0,0 +1,251 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Unit of measurement that defines a quantity, such as grams, meters, or seconds.
|
||||
*
|
||||
* <p>This is the base class for units. Actual units (such as {@link Units#Grams} and {@link
|
||||
* Units#Meters}) can be found in the {@link Units} class.
|
||||
*/
|
||||
public abstract class Unit {
|
||||
private final UnaryFunction m_toBaseConverter;
|
||||
private final UnaryFunction m_fromBaseConverter;
|
||||
|
||||
private final Unit m_baseUnit;
|
||||
|
||||
private final String m_name;
|
||||
private final String m_symbol;
|
||||
|
||||
private final Measure<?> m_zero;
|
||||
private final Measure<?> m_one;
|
||||
|
||||
/**
|
||||
* Creates a new unit defined by its relationship to some base unit.
|
||||
*
|
||||
* @param baseUnit the base unit, e.g. Meters for distances. Set this to {@code null} if the unit
|
||||
* being constructed is its own base unit
|
||||
* @param toBaseConverter a function for converting units of this type to the base unit
|
||||
* @param fromBaseConverter a function for converting units of the base unit to this one
|
||||
* @param name the name of the unit. This should be a singular noun (so "Meter", not "Meters")
|
||||
* @param symbol the short symbol for the unit, such as "m" for meters or "lb." for pounds
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
protected Unit(
|
||||
Unit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
m_baseUnit = baseUnit == null ? this : baseUnit;
|
||||
m_toBaseConverter = Objects.requireNonNull(toBaseConverter);
|
||||
m_fromBaseConverter = Objects.requireNonNull(fromBaseConverter);
|
||||
m_name = Objects.requireNonNull(name);
|
||||
m_symbol = Objects.requireNonNull(symbol);
|
||||
|
||||
m_zero = of(0);
|
||||
m_one = of(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unit with the given name and multiplier to the base unit.
|
||||
*
|
||||
* @param baseUnit the base unit, e.g. Meters for distances
|
||||
* @param baseUnitEquivalent the multiplier to convert this unit to the base unit of this type.
|
||||
* For example, meters has a multiplier of 1, mm has a multiplier of 1e3, and km has
|
||||
* multiplier of 1e-3.
|
||||
* @param name the name of the unit. This should be a singular noun (so "Meter", not "Meters")
|
||||
* @param symbol the short symbol for the unit, such as "m" for meters or "lb." for pounds
|
||||
*/
|
||||
protected Unit(Unit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
this(baseUnit, x -> x * baseUnitEquivalent, x -> x / baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of this unit.
|
||||
* Implementations are <strong>strongly</strong> recommended to sharpen the return type to a
|
||||
* unit-specific measurement implementation.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement.
|
||||
* @return the measurement object
|
||||
*/
|
||||
public abstract Measure<?> of(double magnitude);
|
||||
|
||||
/**
|
||||
* Creates a new immutable measurement of the given magnitude in terms of this unit's base unit.
|
||||
* Implementations are <strong>strongly</strong> recommended to sharpen the return type to a
|
||||
* unit-specific measurement implementation.
|
||||
*
|
||||
* @param baseUnitMagnitude the magnitude in terms of the base unit
|
||||
* @return the measurement object
|
||||
*/
|
||||
public abstract Measure<?> ofBaseUnits(double baseUnitMagnitude);
|
||||
|
||||
/**
|
||||
* Gets a measure of zero magnitude in terms of this unit. The returned object is guaranteed to be
|
||||
* of the same type returned by {@link #of(double)}. Subclasses are encouraged to override this
|
||||
* method to sharpen the return type.
|
||||
*
|
||||
* @return a zero-magnitude measure of this unit
|
||||
*/
|
||||
public Measure<?> zero() {
|
||||
return m_zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a measure with a magnitude of 1.0 in terms of this unit. The returned object is guaranteed
|
||||
* to be of the same type returned by {@link #of(double)}. Subclasses are encouraged to override
|
||||
* this method to sharpen the return type.
|
||||
*
|
||||
* @return a measure of magnitude 1.0 in terms of this unit
|
||||
*/
|
||||
public Measure<?> one() {
|
||||
return m_one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this unit with a unit of time. This often - but not always - results in a velocity.
|
||||
* Subclasses should sharpen the return type to be unit-specific.
|
||||
*
|
||||
* @param time the unit of time
|
||||
* @return the combined unit
|
||||
*/
|
||||
public abstract Unit per(TimeUnit time);
|
||||
|
||||
/**
|
||||
* Gets the base unit of measurement that this unit is derived from. If the unit is the base unit,
|
||||
* the unit will be returned.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> Subclasses <strong>must</strong> override this method to provide the
|
||||
* correct return type. Failing to do say will make unit combinations that use it break at
|
||||
* runtime!
|
||||
*
|
||||
* <pre><code>
|
||||
* Unit baseUnit = new Unit(null, ...);
|
||||
* baseUnit.getBaseUnit(); // returns baseUnit
|
||||
*
|
||||
* Unit derivedUnit = new Unit(baseUnit, ...);
|
||||
* derivedUnit.getBaseUnit(); // returns baseUnit
|
||||
* </code></pre>
|
||||
*
|
||||
* @return the base unit
|
||||
*/
|
||||
public Unit getBaseUnit() {
|
||||
return m_baseUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this unit is the base unit for its own system of measurement.
|
||||
*
|
||||
* @return true if this is the base unit, false if not
|
||||
*/
|
||||
public boolean isBaseUnit() {
|
||||
return this.equals(m_baseUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value in terms of base units to a value in terms of this unit.
|
||||
*
|
||||
* @param valueInBaseUnits the value in base units to convert
|
||||
* @return the equivalent value in terms of this unit
|
||||
*/
|
||||
public double fromBaseUnits(double valueInBaseUnits) {
|
||||
return m_fromBaseConverter.apply(valueInBaseUnits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value in terms of this unit to a value in terms of the base unit.
|
||||
*
|
||||
* @param valueInNativeUnits the value in terms of this unit to convert
|
||||
* @return the equivalent value in terms of the base unit
|
||||
*/
|
||||
public double toBaseUnits(double valueInNativeUnits) {
|
||||
return m_toBaseConverter.apply(valueInNativeUnits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the conversion function used to convert values to base unit terms. This generally
|
||||
* shouldn't need to be used directly; prefer {@link #toBaseUnits(double)} instead.
|
||||
*
|
||||
* @return the conversion function
|
||||
*/
|
||||
public UnaryFunction getConverterToBase() {
|
||||
return m_toBaseConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the conversion function used to convert values to terms of this unit. This generally
|
||||
* shouldn't need to be used directly; prefer {@link #fromBaseUnits(double)} instead.
|
||||
*
|
||||
* @return the conversion function
|
||||
*/
|
||||
public UnaryFunction getConverterFromBase() {
|
||||
return m_fromBaseConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this unit is equivalent to another one. Equivalence is determined by both units
|
||||
* having the same base type and treat the same base unit magnitude as the same magnitude in their
|
||||
* own units, to within {@link Measure#EQUIVALENCE_THRESHOLD}.
|
||||
*
|
||||
* @param other the unit to compare to.
|
||||
* @return true if both units are equivalent, false if not
|
||||
*/
|
||||
public boolean equivalent(Unit other) {
|
||||
if (!getClass().equals(other.getClass())) {
|
||||
// different unit types, not compatible
|
||||
return false;
|
||||
}
|
||||
|
||||
double arbitrary = 16_777.214; // 2^24 / 1e3
|
||||
|
||||
return Math.abs(
|
||||
this.m_fromBaseConverter.apply(arbitrary)
|
||||
- other.m_fromBaseConverter.apply(arbitrary))
|
||||
<= Measure.EQUIVALENCE_THRESHOLD
|
||||
&& Math.abs(
|
||||
this.m_toBaseConverter.apply(arbitrary) - other.m_toBaseConverter.apply(arbitrary))
|
||||
<= Measure.EQUIVALENCE_THRESHOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o
|
||||
|| o instanceof Unit that
|
||||
&& m_name.equals(that.m_name)
|
||||
&& m_symbol.equals(that.m_symbol)
|
||||
&& this.equivalent(that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(m_toBaseConverter, m_fromBaseConverter, m_name, m_symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this unit.
|
||||
*
|
||||
* @return the unit's name
|
||||
*/
|
||||
public String name() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the symbol of this unit.
|
||||
*
|
||||
* @return the unit's symbol
|
||||
*/
|
||||
public String symbol() {
|
||||
return m_symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
293
wpiunits/src/main/java/org/wpilib/units/UnitBuilder.java
Normal file
293
wpiunits/src/main/java/org/wpilib/units/UnitBuilder.java
Normal file
@@ -0,0 +1,293 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Builder used for easily deriving new units from existing ones. When deriving a new unit, the base
|
||||
* unit class <strong>must</strong> redeclare the constructor {@link Unit#Unit(Unit, UnaryFunction,
|
||||
* UnaryFunction, String, String) (U, UnaryFunction, UnaryFunction, String, String)}. The unit
|
||||
* builder class will invoke this constructor automatically and build the new unit. Alternatively,
|
||||
* new units can be derived by passing an explicit constructor function to {@link
|
||||
* #make(UnitConstructorFunction)}.
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
*/
|
||||
public final class UnitBuilder<U extends Unit> {
|
||||
private final U m_base;
|
||||
private UnaryFunction m_fromBase = UnaryFunction.IDENTITY;
|
||||
private UnaryFunction m_toBase = UnaryFunction.IDENTITY;
|
||||
private String m_name;
|
||||
private String m_symbol;
|
||||
|
||||
/**
|
||||
* Creates a new unit builder object, building off of a base unit. The base unit does not have to
|
||||
* be <i>the</i> base unit of its unit system; furlongs work just as well here as meters.
|
||||
*
|
||||
* @param base the unit to base the new unit off of
|
||||
*/
|
||||
public UnitBuilder(U base) {
|
||||
this.m_base = Objects.requireNonNull(base, "Base unit cannot be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the unit conversions based on a simple offset. The new unit will have its values equal to
|
||||
* (base value - offset).
|
||||
*
|
||||
* @param offset the offset
|
||||
* @return this builder
|
||||
*/
|
||||
public UnitBuilder<U> offset(double offset) {
|
||||
m_toBase = derivedValue -> derivedValue + offset;
|
||||
m_fromBase = baseValue -> baseValue - offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a value {@code value} in the range {@code [inMin..inMax]} to an output in the range {@code
|
||||
* [outMin..outMax]}. Inputs outside the bounds will be mapped correspondingly to outputs outside
|
||||
* the output bounds. Inputs equal to {@code inMin} will be mapped to {@code outMin}, and inputs
|
||||
* equal to {@code inMax} will similarly be mapped to {@code outMax}.
|
||||
*
|
||||
* @param value the value to map
|
||||
* @param inMin the minimum input value (does not have to be absolute)
|
||||
* @param inMax the maximum input value (does not have to be absolute)
|
||||
* @param outMin the minimum output value (does not have to be absolute)
|
||||
* @param outMax the maximum output value (does not have to be absolute)
|
||||
* @return the mapped output
|
||||
*/
|
||||
// NOTE: This method lives here instead of in MappingBuilder because inner classes can't
|
||||
// define static methods prior to Java 16.
|
||||
private static double mapValue(
|
||||
double value, double inMin, double inMax, double outMin, double outMax) {
|
||||
return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
|
||||
}
|
||||
|
||||
/** Helper class used for safely chaining mapping builder calls. */
|
||||
public final class MappingBuilder {
|
||||
private final double m_minInput;
|
||||
private final double m_maxInput;
|
||||
|
||||
private MappingBuilder(double minInput, double maxInput) {
|
||||
this.m_minInput = minInput;
|
||||
this.m_maxInput = maxInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the mapping by defining the output range.
|
||||
*
|
||||
* @param minOutput the minimum output value (does not have to be absolute)
|
||||
* @param maxOutput the maximum output value (does not have to be absolute)
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> toOutputRange(double minOutput, double maxOutput) {
|
||||
UnitBuilder.this.m_fromBase = x -> mapValue(x, m_minInput, m_maxInput, minOutput, maxOutput);
|
||||
UnitBuilder.this.m_toBase = y -> mapValue(y, minOutput, maxOutput, m_minInput, m_maxInput);
|
||||
return UnitBuilder.this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a mapping for values within the given input range. This method call should be
|
||||
* immediately followed by {@code .toOutputRange}, eg {@code mappingInputRange(1,
|
||||
* 2).toOutputRange(3, 4)}, which will return the unit builder for continued chaining.
|
||||
*
|
||||
* @param minBase the minimum input value (does not have to be absolute)
|
||||
* @param maxBase the maximum output value (does not have to be absolute)
|
||||
* @return a builder object used to define the output range
|
||||
*/
|
||||
public MappingBuilder mappingInputRange(double minBase, double maxBase) {
|
||||
return new MappingBuilder(minBase, maxBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the conversion function to transform values in the base unit to values in the derived
|
||||
* unit.
|
||||
*
|
||||
* @param fromBase the conversion function
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> fromBase(UnaryFunction fromBase) {
|
||||
this.m_fromBase = Objects.requireNonNull(fromBase, "fromBase function cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the conversion function to transform values in the derived unit to values in the base
|
||||
* unit.
|
||||
*
|
||||
* @param toBase the conversion function
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> toBase(UnaryFunction toBase) {
|
||||
this.m_toBase = Objects.requireNonNull(toBase, "toBase function cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the new unit.
|
||||
*
|
||||
* @param name the new name
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> named(String name) {
|
||||
this.m_name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the symbol of the new unit.
|
||||
*
|
||||
* @param symbol the new symbol
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> symbol(String symbol) {
|
||||
this.m_symbol = symbol;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for defining units that are a scalar fraction of the base unit, such as centimeters
|
||||
* being 1/100th of the base unit (meters). The fraction value is specified as the denominator of
|
||||
* the fraction, so a centimeter definition would use {@code splitInto(100)} instead of {@code
|
||||
* splitInto(1/100.0)}.
|
||||
*
|
||||
* @param fraction the denominator portion of the fraction of the base unit that a value of 1 in
|
||||
* the derived unit corresponds to
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> splitInto(double fraction) {
|
||||
if (fraction == 0) {
|
||||
throw new IllegalArgumentException("Fraction must be nonzero");
|
||||
}
|
||||
|
||||
return toBase(x -> x / fraction).fromBase(b -> b * fraction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for defining units that are a scalar multiple of the base unit, such as kilometers being
|
||||
* 1000x of the base unit (meters).
|
||||
*
|
||||
* @param aggregation the magnitude required for a measure in the base unit to equal a magnitude
|
||||
* of 1 in the derived unit
|
||||
* @return the unit builder, for continued chaining
|
||||
*/
|
||||
public UnitBuilder<U> aggregate(double aggregation) {
|
||||
if (aggregation == 0) {
|
||||
throw new IllegalArgumentException("Aggregation amount must be nonzero");
|
||||
}
|
||||
|
||||
return toBase(x -> x * aggregation).fromBase(b -> b / aggregation);
|
||||
}
|
||||
|
||||
/**
|
||||
* A functional interface for constructing new units without relying on reflection.
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UnitConstructorFunction<U extends Unit> {
|
||||
/**
|
||||
* Creates a new unit instance based on its relation to the base unit of measure.
|
||||
*
|
||||
* @param baseUnit the base unit of the unit system
|
||||
* @param toBaseUnits a function that converts values of the new unit to equivalent values in
|
||||
* terms of the base unit
|
||||
* @param fromBaseUnits a function that converts values in the base unit to equivalent values in
|
||||
* terms of the new unit
|
||||
* @param name the name of the new unit
|
||||
* @param symbol the shorthand symbol of the new unit
|
||||
* @return a new unit
|
||||
*/
|
||||
U create(
|
||||
U baseUnit,
|
||||
UnaryFunction toBaseUnits,
|
||||
UnaryFunction fromBaseUnits,
|
||||
String name,
|
||||
String symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the new unit based off of the builder methods called prior, passing them to a provided
|
||||
* constructor function.
|
||||
*
|
||||
* @param constructor the function to use to create the new derived unit
|
||||
* @return the new derived unit
|
||||
* @throws NullPointerException if the unit conversions, unit name, or unit symbol were not set
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public U make(UnitConstructorFunction<U> constructor) {
|
||||
Objects.requireNonNull(m_fromBase, "fromBase function was not set");
|
||||
Objects.requireNonNull(m_toBase, "toBase function was not set");
|
||||
Objects.requireNonNull(m_name, "new unit name was not set");
|
||||
Objects.requireNonNull(m_symbol, "new unit symbol was not set");
|
||||
|
||||
return constructor.create(
|
||||
(U) m_base.getBaseUnit(),
|
||||
m_toBase.pipeTo(m_base.getConverterToBase()),
|
||||
m_base.getConverterFromBase().pipeTo(m_fromBase),
|
||||
m_name,
|
||||
m_symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the new unit based off of the builder methods called prior.
|
||||
*
|
||||
* @return the new derived unit
|
||||
* @throws NullPointerException if the unit conversions, unit name, or unit symbol were not set
|
||||
* @throws RuntimeException if the base unit does not define a constructor accepting the
|
||||
* conversion functions, unit name, and unit symbol - in that order
|
||||
*/
|
||||
public U make() {
|
||||
return make(
|
||||
(baseUnit, toBaseUnits, fromBaseUnits, name, symbol) -> {
|
||||
var baseClass = baseUnit.getClass();
|
||||
|
||||
try {
|
||||
var ctor = getConstructor(baseUnit);
|
||||
|
||||
return ctor.newInstance(baseUnit, toBaseUnits, fromBaseUnits, name, symbol);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException("Could not instantiate class " + baseClass.getName(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("Could not access constructor", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(
|
||||
"Constructing " + baseClass.getName() + " raised an exception", e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
"No compatible constructor "
|
||||
+ baseClass.getSimpleName()
|
||||
+ "("
|
||||
+ baseClass.getSimpleName()
|
||||
+ ", UnaryFunction, UnaryFunction, String, String)",
|
||||
e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "PMD.AvoidAccessibilityAlteration"})
|
||||
private static <U extends Unit> Constructor<? extends U> getConstructor(U baseUnit)
|
||||
throws NoSuchMethodException {
|
||||
var baseClass = baseUnit.getClass();
|
||||
|
||||
var ctor =
|
||||
baseClass.getDeclaredConstructor(
|
||||
baseClass, // baseUnit
|
||||
UnaryFunction.class, // toBaseUnits
|
||||
UnaryFunction.class, // fromBaseUnits
|
||||
String.class, // name
|
||||
String.class); // symbol
|
||||
|
||||
// need to flag the constructor as accessible so we can use private, package-private,
|
||||
// and protected constructors
|
||||
ctor.setAccessible(true);
|
||||
|
||||
return (Constructor<? extends U>) ctor;
|
||||
}
|
||||
}
|
||||
644
wpiunits/src/main/java/org/wpilib/units/Units.java
Normal file
644
wpiunits/src/main/java/org/wpilib/units/Units.java
Normal file
@@ -0,0 +1,644 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/** Contains a set of predefined units. */
|
||||
public final class Units {
|
||||
private Units() {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
// Pseudo-classes describing the more common units of measure.
|
||||
|
||||
// Unitless
|
||||
/** A dimensionless unit that performs no scaling whatsoever. */
|
||||
public static final DimensionlessUnit Value = BaseUnits.Value;
|
||||
|
||||
/**
|
||||
* A dimensionless unit equal to to 1/100th of a {@link #Value}. A measurement of {@code
|
||||
* Percent.of(42)} would be equivalent to {@code Value.of(0.42)}.
|
||||
*/
|
||||
public static final DimensionlessUnit Percent =
|
||||
derive(Value).splitInto(100).named("Percent").symbol("%").make();
|
||||
|
||||
// DistanceUnit
|
||||
/** The base unit of distance. */
|
||||
public static final DistanceUnit Meters = BaseUnits.DistanceUnit;
|
||||
|
||||
/** The base unit of distance. */
|
||||
public static final DistanceUnit Meter = Meters; // alias
|
||||
|
||||
/** 1/1000 of a {@link #Meter}. */
|
||||
public static final DistanceUnit Millimeters = Milli(Meters, "Millimeter", "mm");
|
||||
|
||||
/** 1/1000 of a {@link #Meter}. */
|
||||
public static final DistanceUnit Millimeter = Millimeters; // alias
|
||||
|
||||
/** 1/100 of a {@link #Meter}. */
|
||||
public static final DistanceUnit Centimeters =
|
||||
derive(Meters).splitInto(100).named("Centimeter").symbol("cm").make();
|
||||
|
||||
/** 1/100 of a {@link #Meter}. */
|
||||
public static final DistanceUnit Centimeter = Centimeters; // alias
|
||||
|
||||
/** 25.4/1000 of a {@link #Meter} and 1/12 of a {@link #Foot}. */
|
||||
public static final DistanceUnit Inches =
|
||||
derive(Millimeters).aggregate(25.4).named("Inch").symbol("in").make();
|
||||
|
||||
/** 25.4/1000 of a {@link #Meter} and 1/12 of a {@link #Foot}. */
|
||||
public static final DistanceUnit Inch = Inches; // alias
|
||||
|
||||
/** 304.8/1000 of a {@link #Meter}, or 12 {@link #Inches}. */
|
||||
public static final DistanceUnit Feet =
|
||||
derive(Inches).aggregate(12).named("Foot").symbol("ft").make();
|
||||
|
||||
/** 304.8/1000 of a {@link #Meter}, or 12 {@link #Inches}. */
|
||||
public static final DistanceUnit Foot = Feet; // alias
|
||||
|
||||
// TimeUnit
|
||||
/** The base unit of time. */
|
||||
public static final TimeUnit Seconds = BaseUnits.TimeUnit;
|
||||
|
||||
/** Alias for {@link #Seconds} to make combined unit definitions read more smoothly. */
|
||||
public static final TimeUnit Second = Seconds; // singularized alias
|
||||
|
||||
/** 1/1000 of a {@link #Seconds Second}. */
|
||||
public static final TimeUnit Milliseconds = Milli(Seconds);
|
||||
|
||||
/** Alias for {@link #Milliseconds} to make combined unit definitions read more smoothly. */
|
||||
public static final TimeUnit Millisecond = Milliseconds; // singularized alias
|
||||
|
||||
/** 1/1,000,000 of a {@link #Seconds Second}. */
|
||||
public static final TimeUnit Microseconds = Micro(Seconds);
|
||||
|
||||
/** Alias for {@link #Microseconds} to make combined unit definitions read more smoothly. */
|
||||
public static final TimeUnit Microsecond = Microseconds; // singularized alias
|
||||
|
||||
/** 60 {@link #Seconds}. */
|
||||
public static final TimeUnit Minutes =
|
||||
derive(Seconds).aggregate(60).named("Minute").symbol("min").make();
|
||||
|
||||
/** Alias for {@link #Minutes} to make combined unit definitions read more smoothly. */
|
||||
public static final TimeUnit Minute = Minutes; // singularized alias
|
||||
|
||||
// AngleUnit
|
||||
/**
|
||||
* The standard SI unit of angle, represented by the distance that the radius of a unit circle can
|
||||
* wrap around its circumference.
|
||||
*/
|
||||
public static final AngleUnit Radians = BaseUnits.AngleUnit;
|
||||
|
||||
/**
|
||||
* The standard SI unit of angle, represented by the distance that the radius of a unit circle can
|
||||
* wrap around its circumference.
|
||||
*/
|
||||
public static final AngleUnit Radian = Radians; // alias
|
||||
|
||||
/**
|
||||
* A single turn of an object around an external axis. Numerically equivalent to {@link
|
||||
* #Rotations}, but may be semantically more expressive in certain scenarios.
|
||||
*/
|
||||
public static final AngleUnit Revolutions =
|
||||
derive(Radians).aggregate(2 * Math.PI).named("Revolution").symbol("R").make();
|
||||
|
||||
/**
|
||||
* A single turn of an object around an external axis. Numerically equivalent to a {@link
|
||||
* #Rotation}, but may be semantically more expressive in certain scenarios.
|
||||
*/
|
||||
public static final AngleUnit Revolution = Revolutions; // alias
|
||||
|
||||
/**
|
||||
* A single turn of an object around an internal axis. Numerically equivalent to {@link
|
||||
* #Revolutions}, but may be semantically more expressive in certain scenarios.
|
||||
*/
|
||||
public static final AngleUnit Rotations =
|
||||
derive(Revolutions).named("Rotation").symbol("R").make();
|
||||
|
||||
/**
|
||||
* A single turn of an object around an internal axis. Numerically equivalent to a {@link
|
||||
* #Revolution}, but may be semantically more expressive in certain scenarios.
|
||||
*/
|
||||
public static final AngleUnit Rotation = Rotations; // alias
|
||||
|
||||
/** 1/360 of a turn around a circle, or 1/57.3 {@link #Radians}. */
|
||||
public static final AngleUnit Degrees =
|
||||
derive(Revolutions).splitInto(360).named("Degree").symbol("°").make();
|
||||
|
||||
/** 1/360 of a turn around a circle, or 1/57.3 {@link #Radians}. */
|
||||
public static final AngleUnit Degree = Degrees; // alias
|
||||
|
||||
// VelocityUnit
|
||||
/**
|
||||
* The standard SI unit of linear velocity, equivalent to travelling at a rate of one {@link
|
||||
* #Meters Meter} per {@link #Second}.
|
||||
*/
|
||||
public static final LinearVelocityUnit MetersPerSecond = Meters.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of linear velocity equivalent to travelling at a rate one {@link #Feet Foot} per {@link
|
||||
* #Second}.
|
||||
*/
|
||||
public static final LinearVelocityUnit FeetPerSecond = Feet.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of linear velocity equivalent to travelling at a rate of one {@link #Inches Inch} per
|
||||
* {@link #Second}.
|
||||
*/
|
||||
public static final LinearVelocityUnit InchesPerSecond = Inches.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular velocity equivalent to spinning at a rate of one {@link #Revolutions
|
||||
* Revolution} per {@link #Second}.
|
||||
*/
|
||||
public static final AngularVelocityUnit RevolutionsPerSecond = Revolutions.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular velocity equivalent to spinning at a rate of one {@link #Rotations Rotation}
|
||||
* per {@link #Second}.
|
||||
*/
|
||||
public static final AngularVelocityUnit RotationsPerSecond = Rotations.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular velocity equivalent to spinning at a rate of one {@link #Rotations Rotation}
|
||||
* per {@link #Minute}. Motor spec sheets often list maximum speeds in terms of RPM.
|
||||
*/
|
||||
public static final AngularVelocityUnit RPM = Rotations.per(Minute);
|
||||
|
||||
/**
|
||||
* The standard SI unit of angular velocity, equivalent to spinning at a rate of one {@link
|
||||
* #Radians Radian} per {@link #Second}.
|
||||
*/
|
||||
public static final AngularVelocityUnit RadiansPerSecond = Radians.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular velocity equivalent to spinning at a rate of one {@link #Degrees Degree} per
|
||||
* {@link #Second}.
|
||||
*/
|
||||
public static final AngularVelocityUnit DegreesPerSecond = Degrees.per(Second);
|
||||
|
||||
/**
|
||||
* The standard SI unit of frequency, equivalent to a periodic signal repeating once every {@link
|
||||
* #Second}.
|
||||
*/
|
||||
public static final FrequencyUnit Hertz =
|
||||
derive(Value.per(Second)).named("Hertz").symbol("hz").make();
|
||||
|
||||
/** 1/1000th of a {@link #Hertz}. */
|
||||
public static final FrequencyUnit Millihertz = Milli(Hertz);
|
||||
|
||||
// Acceleration
|
||||
/**
|
||||
* The standard SI unit of linear acceleration, equivalent to accelerating at a rate of one {@link
|
||||
* #Meters Meter} per {@link #Second} every second.
|
||||
*/
|
||||
public static final LinearAccelerationUnit MetersPerSecondPerSecond = MetersPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of linear acceleration equivalent to accelerating at a rate of one {@link #Foot Foot}
|
||||
* per {@link #Second} every second.
|
||||
*/
|
||||
public static final LinearAccelerationUnit FeetPerSecondPerSecond = FeetPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of linear acceleration equivalent to accelerating at a rate of one {@link #Inch Inch}
|
||||
* per {@link #Second} every second.
|
||||
*/
|
||||
public static final LinearAccelerationUnit InchesPerSecondPerSecond = InchesPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular acceleration equivalent to accelerating at a rate of one {@link #Rotations
|
||||
* Rotation} per {@link #Second} every second.
|
||||
*/
|
||||
public static final AngularAccelerationUnit RotationsPerSecondPerSecond =
|
||||
RotationsPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* The standard SI unit of angular acceleration, equivalent to accelerating at a rate of one
|
||||
* {@link #Radians Radian} per {@link #Second} every second.
|
||||
*/
|
||||
public static final AngularAccelerationUnit RadiansPerSecondPerSecond =
|
||||
RadiansPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of angular acceleration equivalent to accelerating at a rate of one {@link #Degrees
|
||||
* Degree} per {@link #Second} every second.
|
||||
*/
|
||||
public static final AngularAccelerationUnit DegreesPerSecondPerSecond =
|
||||
DegreesPerSecond.per(Second);
|
||||
|
||||
/**
|
||||
* A unit of acceleration equivalent to the pull of gravity on an object at sea level on Earth.
|
||||
*/
|
||||
public static final LinearAccelerationUnit Gs =
|
||||
derive(MetersPerSecondPerSecond).aggregate(9.80665).named("G").symbol("G").make();
|
||||
|
||||
// MassUnit
|
||||
/** The standard SI unit of mass. */
|
||||
public static final MassUnit Kilograms = BaseUnits.MassUnit;
|
||||
|
||||
/** The standard SI unit of mass. */
|
||||
public static final MassUnit Kilogram = Kilograms; // alias
|
||||
|
||||
/** 1/1000 of a {@link #Kilogram}. */
|
||||
public static final MassUnit Grams = Milli(Kilograms, "Gram", "g");
|
||||
|
||||
/** 1/1000 of a {@link #Kilogram}. */
|
||||
public static final MassUnit Gram = Grams; // alias
|
||||
|
||||
/**
|
||||
* A unit of mass equivalent to approximately 453 {@link #Grams}. This is <i>not</i> equivalent to
|
||||
* pounds-force, which is the amount of force required to accelerate an object with one pound of
|
||||
* mass at a rate of one {@link #Gs G}.
|
||||
*
|
||||
* @see #PoundsForce
|
||||
*/
|
||||
public static final MassUnit Pounds =
|
||||
derive(Grams).aggregate(453.592).named("Pound").symbol("lb.").make();
|
||||
|
||||
/**
|
||||
* A unit of mass equivalent to approximately 453 {@link #Grams}. This is <i>not</i> equivalent to
|
||||
* pounds-force, which is the amount of force required to accelerate an object with one pound of
|
||||
* mass at a rate of one {@link #Gs G}.
|
||||
*
|
||||
* @see #PoundForce
|
||||
*/
|
||||
public static final MassUnit Pound = Pounds; // alias
|
||||
|
||||
/** 1/16 of a {@link #Pound}. */
|
||||
public static final MassUnit Ounces =
|
||||
derive(Pounds).splitInto(16).named("Ounce").symbol("oz.").make();
|
||||
|
||||
/** 1/16 of a {@link #Pound}. */
|
||||
public static final MassUnit Ounce = Ounces; // alias
|
||||
|
||||
// Force
|
||||
|
||||
/**
|
||||
* The standard unit of force, equivalent to accelerating a mass of one {@link #Kilogram} at a
|
||||
* rate of one {@link #MetersPerSecondPerSecond meter per second per second}.
|
||||
*/
|
||||
public static final ForceUnit Newtons =
|
||||
derive(Kilograms.mult(MetersPerSecondPerSecond)).named("Newton").symbol("N").make();
|
||||
|
||||
/**
|
||||
* The standard unit of force, equivalent to the standard force of gravity applied to a one {@link
|
||||
* #Kilogram} mass.
|
||||
*/
|
||||
public static final ForceUnit Newton = Newtons;
|
||||
|
||||
/**
|
||||
* The standard Imperial unit of force, equivalent to the standard force of gravity applied to a
|
||||
* one {@link #Pound} mass.
|
||||
*/
|
||||
public static final ForceUnit PoundsForce =
|
||||
derive(Pounds.mult(Gs)).named("Pound-force").symbol("lbsf.").make();
|
||||
|
||||
/**
|
||||
* The standard Imperial unit of force, equivalent to the standard force of gravity applied to a
|
||||
* one {@link #Pound} mass.
|
||||
*/
|
||||
public static final ForceUnit PoundForce = PoundsForce;
|
||||
|
||||
/**
|
||||
* 1/16th of {@link #PoundsForce}, equivalent to the standard force of gravity applied to a one
|
||||
* {@link #Ounce} mass.
|
||||
*/
|
||||
public static final ForceUnit OuncesForce =
|
||||
derive(Ounces.mult(Gs)).named("Ounce-force").symbol("ozf").make();
|
||||
|
||||
/**
|
||||
* 1/16th of {@link #PoundsForce}, equivalent to the standard force of gravity applied to a one
|
||||
* {@link #Ounce} mass.
|
||||
*/
|
||||
public static final ForceUnit OunceForce = OuncesForce;
|
||||
|
||||
// Torque
|
||||
|
||||
/** The standard SI unit for torque. */
|
||||
public static final TorqueUnit NewtonMeters = Meters.multAsTorque(Newtons);
|
||||
|
||||
/** The standard SI unit for torque. */
|
||||
public static final TorqueUnit NewtonMeter = NewtonMeters;
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #PoundsForce pound of force} applied to an object one {@link
|
||||
* #Foot} away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit PoundFeet = Feet.multAsTorque(PoundsForce);
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #PoundsForce pound of force} applied to an object one {@link
|
||||
* #Foot} away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit PoundFoot = PoundFeet;
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #PoundsForce pound of force} applied to an object one {@link
|
||||
* #Inch} away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit PoundInches = Inches.multAsTorque(PoundsForce);
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #PoundsForce pound of force} applied to an object one {@link
|
||||
* #Inch} away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit PoundInch = PoundInches;
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #OunceForce ounce of force} applied to an object one {@link #Inch}
|
||||
* away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit OunceInches = Inches.multAsTorque(OuncesForce);
|
||||
|
||||
/**
|
||||
* The equivalent of one {@link #OunceForce ounce of force} applied to an object one {@link #Inch}
|
||||
* away from its center of rotation.
|
||||
*/
|
||||
public static final TorqueUnit OunceInch = OunceInches;
|
||||
|
||||
// Linear momentum
|
||||
|
||||
/**
|
||||
* The standard SI unit for linear momentum, equivalent to a one {@link #Kilogram} mass moving at
|
||||
* one {@link #MetersPerSecond}.
|
||||
*/
|
||||
public static final LinearMomentumUnit KilogramMetersPerSecond = Kilograms.mult(MetersPerSecond);
|
||||
|
||||
// Angular momentum
|
||||
|
||||
/** The standard SI unit for angular momentum. */
|
||||
public static final AngularMomentumUnit KilogramMetersSquaredPerSecond =
|
||||
KilogramMetersPerSecond.mult(Meters);
|
||||
|
||||
// Moment of Inertia
|
||||
|
||||
/** The standard SI unit for moment of inertia. */
|
||||
public static final MomentOfInertiaUnit KilogramSquareMeters =
|
||||
KilogramMetersSquaredPerSecond.mult(RadiansPerSecond);
|
||||
|
||||
// VoltageUnit
|
||||
/** The base unit of electric potential. */
|
||||
public static final VoltageUnit Volts = BaseUnits.VoltageUnit;
|
||||
|
||||
/** The base unit of electric potential. */
|
||||
public static final VoltageUnit Volt = Volts; // alias
|
||||
|
||||
/**
|
||||
* 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
|
||||
* or low-power circuits.
|
||||
*/
|
||||
public static final VoltageUnit Millivolts = Milli(Volts);
|
||||
|
||||
/**
|
||||
* 1/1000 of a {@link #Volt}. Useful when dealing with low-voltage applications like LED drivers
|
||||
* or low-power circuits.
|
||||
*/
|
||||
public static final VoltageUnit Millivolt = Millivolts; // alias
|
||||
|
||||
// CurrentUnit
|
||||
/** The base unit of electrical current. */
|
||||
public static final CurrentUnit Amps = BaseUnits.CurrentUnit;
|
||||
|
||||
/** The base unit of electrical current. */
|
||||
public static final CurrentUnit Amp = Amps; // alias
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
|
||||
* like LED drivers or low-power circuits.
|
||||
*/
|
||||
public static final CurrentUnit Milliamps = Milli(Amps);
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of an {@link #Amp}. Useful when dealing with low-current applications
|
||||
* like LED drivers or low-power circuits.
|
||||
*/
|
||||
public static final CurrentUnit Milliamp = Milliamps; // alias
|
||||
|
||||
// ResistanceUnit
|
||||
/** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
|
||||
public static final ResistanceUnit Ohms = derive(Volts.per(Amp)).named("Ohm").symbol("Ω").make();
|
||||
|
||||
/** The base unit of resistance. Equivalent to one {@link #Volt} per {@link #Amp}. */
|
||||
public static final ResistanceUnit Ohm = Ohms; // alias
|
||||
|
||||
/** A unit equal to 1,000 {@link #Ohms}. */
|
||||
public static final ResistanceUnit KiloOhms = Kilo(Ohms);
|
||||
|
||||
/** A unit equal to 1,000 {@link #Ohms}. */
|
||||
public static final ResistanceUnit KiloOhm = KiloOhms; // alias
|
||||
|
||||
/** A unit equal to 1/1000 of a {@link #Ohm}. */
|
||||
public static final ResistanceUnit MilliOhms = Milli(Ohms);
|
||||
|
||||
/** A unit equal to 1/1000 of a {@link #Ohm}. */
|
||||
public static final ResistanceUnit MilliOhm = MilliOhms; // alias
|
||||
|
||||
// EnergyUnit
|
||||
/** The base unit of energy. */
|
||||
public static final EnergyUnit Joules = BaseUnits.EnergyUnit;
|
||||
|
||||
/** The base unit of energy. */
|
||||
public static final EnergyUnit Joule = Joules; // alias
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of a {@link #Joule}. Useful when dealing with lower-power applications.
|
||||
*/
|
||||
public static final EnergyUnit Millijoules = Milli(Joules);
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of a {@link #Joule}. Useful when dealing with lower-power applications.
|
||||
*/
|
||||
public static final EnergyUnit Millijoule = Millijoules; // alias
|
||||
|
||||
/**
|
||||
* A unit equal to 1,000 {@link #Joules}. Useful when dealing with higher-level robot energy
|
||||
* usage.
|
||||
*/
|
||||
public static final EnergyUnit Kilojoules = Kilo(Joules);
|
||||
|
||||
/**
|
||||
* A unit equal to 1,000 {@link #Joules}. Useful when dealing with higher-level robot energy
|
||||
* usage.
|
||||
*/
|
||||
public static final EnergyUnit Kilojoule = Kilojoules; // alias
|
||||
|
||||
// PowerUnit
|
||||
/** The base unit of power. Equivalent to one {@link #Joule} per {@link #Second}. */
|
||||
public static final PowerUnit Watts = derive(Joules.per(Second)).named("Watt").symbol("W").make();
|
||||
|
||||
/** The base unit of power. Equivalent to one {@link #Joule} per {@link #Second}. */
|
||||
public static final PowerUnit Watt = Watts; // alias
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of a {@link #Watt}. Useful when dealing with lower-power applications.
|
||||
*/
|
||||
public static final PowerUnit Milliwatts = Milli(Watts);
|
||||
|
||||
/**
|
||||
* A unit equal to 1/1000 of a {@link #Watt}. Useful when dealing with lower-power applications.
|
||||
*/
|
||||
public static final PowerUnit Milliwatt = Milliwatts; // alias
|
||||
|
||||
/**
|
||||
* A unit equal to 745.7 {@link #Watts}. May be useful when dealing with high-power gearboxes and
|
||||
* motors.
|
||||
*/
|
||||
public static final PowerUnit Horsepower =
|
||||
derive(Watts).aggregate(745.7).named("Horsepower").symbol("HP").make();
|
||||
|
||||
// TemperatureUnit
|
||||
/**
|
||||
* The base unit of temperature, where a value of 0 corresponds with absolutely zero energy in the
|
||||
* measured system. Not particularly useful for robots unless you're cooling motors with liquid
|
||||
* helium.
|
||||
*/
|
||||
public static final TemperatureUnit Kelvin = BaseUnits.TemperatureUnit;
|
||||
|
||||
/**
|
||||
* The standard SI unit of temperature, where a value of 0 roughly corresponds to the freezing
|
||||
* point of water and a value of 100 corresponds to the boiling point. Electronics tend to exhibit
|
||||
* degraded performance or damage above 90 degrees Celsius.
|
||||
*/
|
||||
public static final TemperatureUnit Celsius =
|
||||
derive(Kelvin).offset(+273.15).named("Celsius").symbol("°C").make();
|
||||
|
||||
/**
|
||||
* The base imperial (American) unit of temperature, where a value of 32 roughly corresponds to
|
||||
* the freezing point of water and a value of 212 corresponds to the boiling point.
|
||||
*/
|
||||
public static final TemperatureUnit Fahrenheit =
|
||||
derive(Celsius)
|
||||
.mappingInputRange(0, 100)
|
||||
.toOutputRange(32, 212)
|
||||
.named("Fahrenheit")
|
||||
.symbol("°F")
|
||||
.make();
|
||||
|
||||
// Standard feedforward units for kV and kA.
|
||||
// kS and kG are just volts, which is already defined earlier
|
||||
/**
|
||||
* A standard unit for measuring linear mechanisms' feedforward voltages based on a model of the
|
||||
* system and a desired commanded linear velocity.
|
||||
*/
|
||||
public static final PerUnit<VoltageUnit, LinearVelocityUnit> VoltsPerMeterPerSecond =
|
||||
Volts.per(MetersPerSecond);
|
||||
|
||||
/**
|
||||
* A standard unit for measuring linear mechanisms' feedforward voltages based on a model of the
|
||||
* system and a desired commanded linear acceleration.
|
||||
*/
|
||||
public static final PerUnit<VoltageUnit, LinearAccelerationUnit> VoltsPerMeterPerSecondSquared =
|
||||
Volts.per(MetersPerSecondPerSecond);
|
||||
|
||||
/**
|
||||
* A standard unit for measuring angular mechanisms' feedforward voltages based on a model of the
|
||||
* system and a desired commanded angular velocity.
|
||||
*/
|
||||
public static final PerUnit<VoltageUnit, AngularVelocityUnit> VoltsPerRadianPerSecond =
|
||||
Volts.per(RadiansPerSecond);
|
||||
|
||||
/**
|
||||
* A standard unit for measuring angular mechanisms' feedforward voltages based on a model of the
|
||||
* system and a desired commanded angular acceleration.
|
||||
*/
|
||||
public static final PerUnit<VoltageUnit, AngularAccelerationUnit> VoltsPerRadianPerSecondSquared =
|
||||
Volts.per(RadiansPerSecond.per(Second));
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a thousandth of the base unit, eg Milliseconds = Milli(Units.Seconds).
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @param name the name of the new derived unit
|
||||
* @param symbol the symbol of the new derived unit
|
||||
* @return the milli-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Milli(U baseUnit, String name, String symbol) {
|
||||
return derive(baseUnit).splitInto(1000).named(name).symbol(symbol).make();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a thousandth of the base unit, eg Milliseconds = Milli(Units.Seconds).
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @return the milli-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Milli(U baseUnit) {
|
||||
return Milli(
|
||||
baseUnit, "Milli" + baseUnit.name().toLowerCase(Locale.ROOT), "m" + baseUnit.symbol());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a millionth of the base unit, eg {@code Microseconds =
|
||||
* Micro(Units.Seconds, "Microseconds", 'us")}.
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @param name the name of the new derived unit
|
||||
* @param symbol the symbol of the new derived unit
|
||||
* @return the micro-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Micro(U baseUnit, String name, String symbol) {
|
||||
return derive(baseUnit).splitInto(1_000_000).named(name).symbol(symbol).make();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a millionth of the base unit, eg Microseconds = Micro(Units.Seconds).
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @return the micro-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Micro(U baseUnit) {
|
||||
return Micro(
|
||||
baseUnit, "Micro" + baseUnit.name().toLowerCase(Locale.ROOT), "u" + baseUnit.symbol());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a thousand of the base unit, eg Kilograms = Kilo(Units.Grams).
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @param name the name of the new derived unit
|
||||
* @param symbol the symbol of the new derived unit
|
||||
* @return the kilo-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Kilo(U baseUnit, String name, String symbol) {
|
||||
return derive(baseUnit).aggregate(1000).named(name).symbol(symbol).make();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit equal to a thousand of the base unit, eg Kilograms = Kilo(Units.Grams).
|
||||
*
|
||||
* @param <U> the type of the unit
|
||||
* @param baseUnit the unit being derived from. This does not have to be the base unit of measure
|
||||
* @return the kilo-unit
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodname")
|
||||
public static <U extends Unit> U Kilo(U baseUnit) {
|
||||
return Kilo(
|
||||
baseUnit, "Kilo" + baseUnit.name().toLowerCase(Locale.ROOT), "K" + baseUnit.symbol());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unit builder object based on a given input unit. The builder can be used to
|
||||
* fluently describe a new unit in terms of its relation to the base unit.
|
||||
*
|
||||
* @param unit the base unit from which to derive a new unit
|
||||
* @param <U> the dimension of the unit to derive
|
||||
* @return a builder object
|
||||
*/
|
||||
public static <U extends Unit> UnitBuilder<U> derive(U unit) {
|
||||
return new UnitBuilder<>(unit);
|
||||
}
|
||||
}
|
||||
133
wpiunits/src/main/java/org/wpilib/units/VelocityUnit.java
Normal file
133
wpiunits/src/main/java/org/wpilib/units/VelocityUnit.java
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Velocity;
|
||||
|
||||
/**
|
||||
* Unit of velocity dimension that is a combination of a distance unit (numerator) and a time unit
|
||||
* (denominator).
|
||||
*
|
||||
* <p>This is a generic velocity type for units that do not have discrete velocity units (eg {@link
|
||||
* DistanceUnit} has {@link LinearVelocityUnit}, and so would not use this class).
|
||||
*
|
||||
* @param <D> the unit of the changing quantity, such as {@link VoltageUnit} or {@link
|
||||
* TemperatureUnit}
|
||||
*/
|
||||
public final class VelocityUnit<D extends Unit> extends PerUnit<D, TimeUnit> {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final CombinatoryUnitCache<Unit, TimeUnit, VelocityUnit> cache =
|
||||
new CombinatoryUnitCache<>(VelocityUnit::new);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
VelocityUnit(D numerator, TimeUnit denominator) {
|
||||
super(
|
||||
numerator.isBaseUnit() && denominator.isBaseUnit()
|
||||
? null
|
||||
: combine((D) numerator.getBaseUnit(), denominator.getBaseUnit()),
|
||||
numerator,
|
||||
denominator);
|
||||
}
|
||||
|
||||
VelocityUnit(
|
||||
VelocityUnit<D> baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a dimension unit and a unit of the period of change to create a unit of velocity.
|
||||
*
|
||||
* @param unit the unit of the changing dimension
|
||||
* @param period the unit of the period of change in the velocity
|
||||
* @param <D> the unit of the changing dimension
|
||||
* @return the combined velocity unit
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <D extends Unit> VelocityUnit<D> combine(D unit, TimeUnit period) {
|
||||
return cache.combine(unit, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<D> getBaseUnit() {
|
||||
return (VelocityUnit<D>) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the major unit being measured (eg Meters for Meters per Second).
|
||||
*
|
||||
* @return the major unit
|
||||
*/
|
||||
public D getUnit() {
|
||||
return numerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the period unit of the velocity, eg Seconds or Milliseconds.
|
||||
*
|
||||
* @return the period unit
|
||||
*/
|
||||
public TimeUnit getPeriod() {
|
||||
return denominator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Velocity<D> of(double magnitude) {
|
||||
return new Velocity<>(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Velocity<D> ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Velocity<>(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Velocity<D> zero() {
|
||||
return (Velocity<D>) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Velocity<D> one() {
|
||||
return (Velocity<D>) super.one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this velocity unit with a unit of a period of change to create an acceleration unit.
|
||||
*
|
||||
* @param period the unit of the period of change
|
||||
* @return the acceleration unit
|
||||
*/
|
||||
@Override
|
||||
public AccelerationUnit<D> per(TimeUnit period) {
|
||||
return AccelerationUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ratio unit between this unit and an arbitrary other unit.
|
||||
*
|
||||
* @param other the other unit
|
||||
* @param <U> the type of the other unit
|
||||
* @return the ratio unit
|
||||
*/
|
||||
public <U extends Unit> PerUnit<VelocityUnit<D>, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another velocity unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other velocity unit
|
||||
* @param otherUnit the other velocity unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, VelocityUnit<? extends D> otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
108
wpiunits/src/main/java/org/wpilib/units/VoltageUnit.java
Normal file
108
wpiunits/src/main/java/org/wpilib/units/VoltageUnit.java
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units;
|
||||
|
||||
import edu.wpi.first.units.measure.Voltage;
|
||||
|
||||
/**
|
||||
* Unit of electric voltage dimension.
|
||||
*
|
||||
* <p>This is the base type for units of voltage dimension. It is also used to specify the dimension
|
||||
* for {@link Measure}: <code>Measure<VoltageUnit></code>.
|
||||
*
|
||||
* <p>Actual units (such as {@link Units#Volts} and {@link Units#Millivolts}) can be found in the
|
||||
* {@link Units} class.
|
||||
*/
|
||||
public final class VoltageUnit extends Unit {
|
||||
VoltageUnit(VoltageUnit baseUnit, double baseUnitEquivalent, String name, String symbol) {
|
||||
super(baseUnit, baseUnitEquivalent, name, symbol);
|
||||
}
|
||||
|
||||
VoltageUnit(
|
||||
VoltageUnit baseUnit,
|
||||
UnaryFunction toBaseConverter,
|
||||
UnaryFunction fromBaseConverter,
|
||||
String name,
|
||||
String symbol) {
|
||||
super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoltageUnit getBaseUnit() {
|
||||
return (VoltageUnit) super.getBaseUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a unit of power equivalent to this unit of voltage multiplied by another unit of
|
||||
* electrical current. For example, {@code Volts.times(Amps)} will return a unit of power
|
||||
* equivalent to one Watt; {@code Volts.times(Milliamps)} will return a unit of power equivalent
|
||||
* to a milliwatt, and so on.
|
||||
*
|
||||
* @param current the current unit to multiply by
|
||||
* @param name the name of the resulting unit of power
|
||||
* @param symbol the symbol used to represent the unit of power
|
||||
* @return the power unit
|
||||
*/
|
||||
public PowerUnit mult(CurrentUnit current, String name, String symbol) {
|
||||
return Units.derive(PowerUnit.combine(this, current)).named(name).symbol(symbol).make();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Voltage of(double magnitude) {
|
||||
return new Voltage(magnitude, toBaseUnits(magnitude), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Voltage ofBaseUnits(double baseUnitMagnitude) {
|
||||
return new Voltage(fromBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Voltage zero() {
|
||||
return (Voltage) super.zero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Voltage one() {
|
||||
return (Voltage) super.one();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityUnit<VoltageUnit> per(TimeUnit period) {
|
||||
return VelocityUnit.combine(this, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this unit of voltage with a unit of current to form a unit of resistance.
|
||||
*
|
||||
* @param currentUnit the unit of current
|
||||
* @return the combined resistance unit
|
||||
*/
|
||||
public ResistanceUnit per(CurrentUnit currentUnit) {
|
||||
return ResistanceUnit.combine(this, currentUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a generic ratio unit of this voltage to a different unit type.
|
||||
*
|
||||
* @param other the other unit type
|
||||
* @param <U> the type of the other unit
|
||||
* @return the combined ratio type
|
||||
*/
|
||||
public <U extends Unit> PerUnit<VoltageUnit, U> per(U other) {
|
||||
return PerUnit.combine(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a measurement value in terms of another voltage unit to this unit.
|
||||
*
|
||||
* @param magnitude the magnitude of the measurement in terms of the other voltage unit
|
||||
* @param otherUnit the other voltage unit
|
||||
* @return the value of the measurement in terms of this unit
|
||||
*/
|
||||
public double convertFrom(double magnitude, VoltageUnit otherUnit) {
|
||||
return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units.collections;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A variant on {@code java.util.HashMap<K, V>} that uses primitive long ints for map keys instead
|
||||
* of autoboxed Long objects like would be used for a {@code Map<Long, V>}.
|
||||
*
|
||||
* @param <V> the type of the values stored in the map
|
||||
*/
|
||||
public class LongToObjectHashMap<V> {
|
||||
private static final int kInitialSize = 0;
|
||||
private static final int kInitialCapacity = 8; // NOTE: must be a power of two
|
||||
|
||||
/**
|
||||
* The default load factor of the hashmap. If the ratio of the number of entries to the map's
|
||||
* capacity exceeds this value, the map will be resized (doubled capacity) in order for more
|
||||
* values to be easily inserted.
|
||||
*/
|
||||
private static final double kLoadFactor = 75.00 / 100;
|
||||
|
||||
/** The current number of key-value pairs in the map. */
|
||||
private int m_size = kInitialSize;
|
||||
|
||||
/**
|
||||
* The current maximum capacity of the map. Note that it will be resized before m_size reaches
|
||||
* this value.
|
||||
*/
|
||||
private int m_capacity = kInitialCapacity;
|
||||
|
||||
/**
|
||||
* The keys in the map. This is a sparse array, and the location of a key may not be equal to the
|
||||
* result of calling {@link #bucket(long)} on that key. To handle hash collisions, if a bucket is
|
||||
* already in use when trying to insert a value, the bucket number is incremented (wrapping around
|
||||
* to 0 if it's equal to m_capacity) and <i>that</i> bucket is checked to see if it's available.
|
||||
* This process continues until an empty bucket is found (which is guaranteed because m_size is
|
||||
* always less than m_capacity).
|
||||
*/
|
||||
private long[] m_keys = new long[m_capacity];
|
||||
|
||||
/** Tracks which buckets are actually used (have a key-value mapping). */
|
||||
private boolean[] m_uses = new boolean[m_capacity];
|
||||
|
||||
/**
|
||||
* The values in the map. See the documentation for m_keys for how indexing into this array works.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private V[] m_values = (V[]) new Object[m_capacity];
|
||||
|
||||
/** Default constructor. */
|
||||
public LongToObjectHashMap() {}
|
||||
|
||||
/**
|
||||
* Puts a value {@code value} corresponding to key {@code key} in the map.
|
||||
*
|
||||
* @param key the associated key
|
||||
* @param value the value to insert
|
||||
* @return the previous value that was mapped to the key, or null if no such value existed
|
||||
*/
|
||||
public V put(long key, V value) {
|
||||
int bucket = bucket(key);
|
||||
|
||||
// Increment the bucket until we hit an open space (there's always going to be at least one)
|
||||
while (m_uses[bucket]) {
|
||||
if (m_keys[bucket] == key) {
|
||||
// replace the existing value
|
||||
var oldValue = m_values[bucket];
|
||||
m_values[bucket] = value;
|
||||
return oldValue;
|
||||
}
|
||||
bucket = safeIncrement(bucket);
|
||||
}
|
||||
|
||||
m_uses[bucket] = true;
|
||||
m_keys[bucket] = key;
|
||||
m_values[bucket] = value;
|
||||
m_size++;
|
||||
|
||||
if (m_size > maxSize()) {
|
||||
grow();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value associated with the given key.
|
||||
*
|
||||
* @param key the key to retrieve the value for
|
||||
* @return the value mapped to the key, or null if the key is not in the map
|
||||
*/
|
||||
public V get(long key) {
|
||||
int bucket = bucket(key);
|
||||
while (m_uses[bucket]) {
|
||||
if (m_keys[bucket] == key) {
|
||||
// found it
|
||||
return m_values[bucket];
|
||||
}
|
||||
bucket = safeIncrement(bucket);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the value associated with the given key and returns it.
|
||||
*
|
||||
* @param key the key to remove
|
||||
* @return the value corresponding to the key, or null if the key is not in the map
|
||||
*/
|
||||
public V remove(long key) {
|
||||
int bucket = bucket(key);
|
||||
while (m_uses[bucket]) {
|
||||
if (m_keys[bucket] == key) {
|
||||
// found it
|
||||
// TODO: Shrink the map when below a certain load factor
|
||||
// Current use cases don't remove elements from the map, so there's not much use
|
||||
// for shrinking at the moment.
|
||||
m_size--;
|
||||
m_keys[bucket] = 0L;
|
||||
m_uses[bucket] = false;
|
||||
|
||||
var oldValue = m_values[bucket];
|
||||
m_values[bucket] = null;
|
||||
return oldValue;
|
||||
}
|
||||
bucket = safeIncrement(bucket);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a key is contained in the map.
|
||||
*
|
||||
* @param key the key to check
|
||||
* @return true if the key has an associated value, false if not
|
||||
*/
|
||||
public boolean containsKey(long key) {
|
||||
int bucket = bucket(key);
|
||||
while (m_uses[bucket]) {
|
||||
if (m_keys[bucket] == key) {
|
||||
return true;
|
||||
}
|
||||
bucket = safeIncrement(bucket);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Clears and removes all entries from the map. */
|
||||
public void clear() {
|
||||
if (m_size == 0) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
m_size = 0;
|
||||
|
||||
Arrays.fill(m_uses, false);
|
||||
Arrays.fill(m_keys, 0L);
|
||||
Arrays.fill(m_values, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of key-value pairs currently contained in the map.
|
||||
*
|
||||
* @return the current size of the map
|
||||
*/
|
||||
public int size() {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
// package-private for tests
|
||||
int capacity() {
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the map contains any entries.
|
||||
*
|
||||
* @return true if at least one entry is present, false otherwise
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keys contained in the map. Ordering is not guaranteed. The returned set is read-only
|
||||
* and immutable. This uses a custom class for primitive long values to avoid unnecessary
|
||||
* autoboxing to {@code java.lang.Long}.
|
||||
*
|
||||
* @return a read-only set of keys
|
||||
*/
|
||||
public ReadOnlyPrimitiveLongSet keySet() {
|
||||
// copy the sparse key array into a compact array
|
||||
final long[] keys = new long[m_size];
|
||||
int i = 0;
|
||||
for (int bucket = 0; bucket < m_capacity; bucket++) {
|
||||
if (m_uses[bucket]) {
|
||||
keys[i] = m_keys[bucket];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return new ReadOnlyPrimitiveLongSet(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the values contained in the map. Ordering is not guaranteed. The returned collection is
|
||||
* read-only and immutable.
|
||||
*
|
||||
* @return a read-only collection of values
|
||||
*/
|
||||
public Collection<V> values() {
|
||||
Collection<V> values = new ArrayList<>();
|
||||
for (int bucket = 0; bucket < m_capacity; bucket++) {
|
||||
if (m_uses[bucket]) {
|
||||
values.add(m_values[bucket]);
|
||||
}
|
||||
}
|
||||
return List.copyOf(values); // return a readonly copy
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for map iterator function.
|
||||
*
|
||||
* @param <V> Value type.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IteratorFunction<V> {
|
||||
/**
|
||||
* Accepts a key-value pair from the map.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param value The value.
|
||||
*/
|
||||
void accept(long key, V value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over every key-value pair in the map and passes them to the given function.
|
||||
*
|
||||
* @param function the function to apply to every key-value pair.
|
||||
*/
|
||||
public void forEach(IteratorFunction<? super V> function) {
|
||||
for (int bucket = 0; bucket < m_capacity; bucket++) {
|
||||
if (m_uses[bucket]) {
|
||||
function.accept(m_keys[bucket], m_values[bucket]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
final int currentSize = m_size;
|
||||
final int oldCapacity = m_capacity;
|
||||
if (oldCapacity * kLoadFactor >= currentSize) {
|
||||
// We're below the maximum allowed size for the current capacity
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
final int newCapacity = oldCapacity * 2;
|
||||
final int newMask = newCapacity - 1;
|
||||
|
||||
final boolean[] oldUses = m_uses;
|
||||
final long[] oldKeys = m_keys;
|
||||
final V[] oldValues = m_values;
|
||||
|
||||
final boolean[] newUses = new boolean[newCapacity];
|
||||
final long[] newKeys = new long[newCapacity];
|
||||
@SuppressWarnings("unchecked")
|
||||
final V[] newValues = (V[]) new Object[newCapacity];
|
||||
|
||||
for (int oldBucket = 0; oldBucket < oldCapacity; oldBucket++) {
|
||||
if (!oldUses[oldBucket]) {
|
||||
// Bucket is empty, skip
|
||||
continue;
|
||||
}
|
||||
final long key = oldKeys[oldBucket];
|
||||
final V value = oldValues[oldBucket];
|
||||
|
||||
int newBucket = (int) (hash(key) & newMask);
|
||||
while (newUses[newBucket]) {
|
||||
newBucket = (newBucket + 1) & newMask;
|
||||
}
|
||||
|
||||
newUses[newBucket] = true;
|
||||
newKeys[newBucket] = key;
|
||||
newValues[newBucket] = value;
|
||||
}
|
||||
|
||||
m_capacity = newCapacity;
|
||||
m_uses = newUses;
|
||||
m_keys = newKeys;
|
||||
m_values = newValues;
|
||||
}
|
||||
|
||||
private int maxSize() {
|
||||
return (int) (m_capacity * kLoadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a hashcode for an input key. Does some bit shuffling to account for poor hash
|
||||
* functions.
|
||||
*
|
||||
* @param key the key to hash
|
||||
* @return a hashcode for the input key
|
||||
*/
|
||||
private long hash(long key) {
|
||||
return 31 + (key ^ (key >>> 15) ^ (key >>> 31) ^ (key << 31));
|
||||
}
|
||||
|
||||
/**
|
||||
* The mask to use when translating a hashcode to a bucket index. Relies on m_capacity being a
|
||||
* power of two.
|
||||
*/
|
||||
private int mask() {
|
||||
return m_capacity - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the desired bucket index for a particular key. Does nothing to handle the case where
|
||||
* the calculated index is already in use by another key.
|
||||
*
|
||||
* @param key the key to get the bucket for
|
||||
* @return the desired bucket index
|
||||
*/
|
||||
private int bucket(long key) {
|
||||
var hash = hash(key);
|
||||
return (int) (hash & mask());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a bucket index by 1, wrapping around to 0 if the index is already at the maximum.
|
||||
*
|
||||
* @param bucket the index to increment
|
||||
* @return the incremented bucket index
|
||||
*/
|
||||
private int safeIncrement(int bucket) {
|
||||
return (bucket + 1) & mask();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.units.collections;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
/** A read-only set of unique primitive {@code long} values. */
|
||||
public class ReadOnlyPrimitiveLongSet implements Iterable<Long> {
|
||||
private final long[] m_values;
|
||||
|
||||
/**
|
||||
* Creates a new set from the given values. These values do not have to be unique.
|
||||
*
|
||||
* @param values the values that belong to the set.
|
||||
*/
|
||||
@SuppressWarnings({"PMD.ForLoopCanBeForeach", "ForLoopReplaceableByForEach"})
|
||||
public ReadOnlyPrimitiveLongSet(long... values) {
|
||||
// initial size is the upper limit
|
||||
long[] uniqueValues = new long[values.length];
|
||||
int numUniqueValues = 0;
|
||||
boolean seenZero = false;
|
||||
|
||||
// copy the set of unique values to our array
|
||||
// using indexed for-loops to avoid allocations
|
||||
copyLoop:
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
long value = values[i];
|
||||
if (value == 0 && !seenZero) {
|
||||
// special case to support zero
|
||||
seenZero = true;
|
||||
} else {
|
||||
for (int j = 0; j < uniqueValues.length; j++) {
|
||||
long uniqueValue = uniqueValues[j];
|
||||
if (uniqueValue == value) {
|
||||
continue copyLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
uniqueValues[numUniqueValues] = value;
|
||||
numUniqueValues++;
|
||||
}
|
||||
|
||||
if (numUniqueValues == values.length) {
|
||||
// all input values were unique, no need to truncate
|
||||
m_values = uniqueValues;
|
||||
} else {
|
||||
// truncate the array to remove trailing empty space
|
||||
m_values = Arrays.copyOf(uniqueValues, numUniqueValues);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the set contains a particular value.
|
||||
*
|
||||
* @param value the value to check for
|
||||
* @return true if the value is in the set, false if not
|
||||
*/
|
||||
public boolean contains(long value) {
|
||||
for (long mValue : m_values) {
|
||||
if (mValue == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of elements in the set.
|
||||
*
|
||||
* @return the number of elements in the set
|
||||
*/
|
||||
public int size() {
|
||||
return m_values.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the set is empty, i.e. contains no values.
|
||||
*
|
||||
* @return true if there are no values in the set, false otherwise.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream of primitive long values for the set.
|
||||
*
|
||||
* @return a sequential Stream over the elements in this collection
|
||||
* @see Set#stream()
|
||||
*/
|
||||
public LongStream stream() {
|
||||
return Arrays.stream(m_values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array that contains all of the values in the set.
|
||||
*
|
||||
* @return an array containing all the values in the set
|
||||
*/
|
||||
public long[] toArray() {
|
||||
return Arrays.copyOf(m_values, m_values.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Long> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int m_index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return m_index < ReadOnlyPrimitiveLongSet.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return ReadOnlyPrimitiveLongSet.this.m_values[m_index++];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user