RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
MathUtil.java
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5package org.wpilib.math.util;
6
7import org.wpilib.math.geometry.Translation2d;
8import org.wpilib.math.geometry.Translation3d;
9import org.wpilib.math.linalg.Vector;
10
12public final class MathUtil {
13 private MathUtil() {
14 throw new AssertionError("utility class");
15 }
16
26 public static double lerp(double a, double b, double t) {
27 return a + (b - a) * t;
28 }
29
39 public static double inverseLerp(double a, double b, double q) {
40 // q = a + (b − a)t
41 // (b − a)t = q − a
42 // t = (q − a)/(b − a)
43 if (Math.abs(a - b) < 1e-9) {
44 return 0.0;
45 } else {
46 return (q - a) / (b - a);
47 }
48 }
49
59 public static double applyDeadband(double value, double deadband, double maxMagnitude) {
60 if (Math.abs(value) < deadband) {
61 return 0;
62 }
63 if (value > 0.0) {
64 // Map deadband to 0 and map max to max with a linear relationship.
65 //
66 // y - y₁ = m(x - x₁)
67 // y - y₁ = (y₂ - y₁)/(x₂ - x₁) (x - x₁)
68 // y = (y₂ - y₁)/(x₂ - x₁) (x - x₁) + y₁
69 //
70 // (x₁, y₁) = (deadband, 0) and (x₂, y₂) = (max, max).
71 //
72 // x₁ = deadband
73 // y₁ = 0
74 // x₂ = max
75 // y₂ = max
76 // y = (max - 0)/(max - deadband) (x - deadband) + 0
77 // y = max/(max - deadband) (x - deadband)
78 //
79 // To handle high values of max, rewrite so that max only appears on the denominator.
80 //
81 // y = ((max - deadband) + deadband)/(max - deadband) (x - deadband)
82 // y = (1 + deadband/(max - deadband)) (x - deadband)
83 return (1 + deadband / (maxMagnitude - deadband)) * (value - deadband);
84 } else {
85 // Map -deadband to 0 and map -max to -max with a linear relationship.
86 //
87 // y - y₁ = m(x - x₁)
88 // y - y₁ = (y₂ - y₁)/(x₂ - x₁) (x - x₁)
89 // y = (y₂ - y₁)/(x₂ - x₁) (x - x₁) + y₁
90 //
91 // (x₁, y₁) = (-deadband, 0) and (x₂, y₂) = (-max, -max).
92 //
93 // x₁ = -deadband
94 // y₁ = 0
95 // x₂ = -max
96 // y₂ = -max
97 // y = (-max - 0)/(-max + deadband) (x + deadband) + 0
98 // y = max/(max - deadband) (x + deadband)
99 //
100 // To handle high values of max, rewrite so that max only appears on the denominator.
101 //
102 // y = ((max - deadband) + deadband)/(max - deadband) (x + deadband)
103 // y = (1 + deadband/(max - deadband)) (x + deadband)
104 return (1 + deadband / (maxMagnitude - deadband)) * (value + deadband);
105 }
106 }
107
116 public static double applyDeadband(double value, double deadband) {
117 return applyDeadband(value, deadband, 1);
118 }
119
131 public static <R extends Num> Vector<R> applyDeadband(
132 Vector<R> value, double deadband, double maxMagnitude) {
133 if (value.norm() < 1e-9) {
134 return value.times(0);
135 }
136 return value.unit().times(applyDeadband(value.norm(), deadband, maxMagnitude));
137 }
138
149 public static <R extends Num> Vector<R> applyDeadband(Vector<R> value, double deadband) {
150 return applyDeadband(value, deadband, 1);
151 }
152
170 public static double copyDirectionPow(double value, double exponent, double maxMagnitude) {
171 return Math.copySign(Math.pow(Math.abs(value) / maxMagnitude, exponent), value) * maxMagnitude;
172 }
173
185 public static double copyDirectionPow(double value, double exponent) {
186 return copyDirectionPow(value, exponent, 1);
187 }
188
204 public static <R extends Num> Vector<R> copyDirectionPow(
205 Vector<R> value, double exponent, double maxMagnitude) {
206 if (value.norm() < 1e-9) {
207 return value.times(0);
208 }
209 return value.unit().times(copyDirectionPow(value.norm(), exponent, maxMagnitude));
210 }
211
221 public static <R extends Num> Vector<R> copyDirectionPow(Vector<R> value, double exponent) {
222 return copyDirectionPow(value, exponent, 1);
223 }
224
233 public static double inputModulus(double input, double minimumInput, double maximumInput) {
234 double modulus = maximumInput - minimumInput;
235
236 // Wrap input if it's above the maximum input
237 int numMax = (int) ((input - minimumInput) / modulus);
238 input -= numMax * modulus;
239
240 // Wrap input if it's below the minimum input
241 int numMin = (int) ((input - maximumInput) / modulus);
242 input -= numMin * modulus;
243
244 return input;
245 }
246
253 public static double angleModulus(double angleRadians) {
254 return inputModulus(angleRadians, -Math.PI, Math.PI);
255 }
256
265 public static boolean isNear(double expected, double actual, double tolerance) {
266 if (tolerance < 0) {
267 throw new IllegalArgumentException("Tolerance must be a non-negative number!");
268 }
269 return Math.abs(expected - actual) < tolerance;
270 }
271
289 public static boolean isNear(
290 double expected, double actual, double tolerance, double min, double max) {
291 if (tolerance < 0) {
292 throw new IllegalArgumentException("Tolerance must be a non-negative number!");
293 }
294 // Max error is exactly halfway between the min and max
295 double errorBound = (max - min) / 2.0;
296 double error = MathUtil.inputModulus(expected - actual, -errorBound, errorBound);
297 return Math.abs(error) < tolerance;
298 }
299
310 Translation2d current, Translation2d next, double dt, double maxVelocity) {
311 if (maxVelocity < 0) {
312 Exception e = new IllegalArgumentException();
314 "maxVelocity must be a non-negative number, got " + maxVelocity, e.getStackTrace());
315 return next;
316 }
317 Translation2d diff = next.minus(current);
318 double dist = diff.getNorm();
319 if (dist < 1e-9) {
320 return next;
321 }
322 if (dist > maxVelocity * dt) {
323 // Move maximum allowed amount in direction of the difference
324 return current.plus(diff.times(maxVelocity * dt / dist));
325 }
326 return next;
327 }
328
339 Translation3d current, Translation3d next, double dt, double maxVelocity) {
340 if (maxVelocity < 0) {
341 Exception e = new IllegalArgumentException();
343 "maxVelocity must be a non-negative number, got " + maxVelocity, e.getStackTrace());
344 return next;
345 }
346 Translation3d diff = next.minus(current);
347 double dist = diff.getNorm();
348 if (dist < 1e-9) {
349 return next;
350 }
351 if (dist > maxVelocity * dt) {
352 // Move maximum allowed amount in direction of the difference
353 return current.plus(diff.times(maxVelocity * dt / dist));
354 }
355 return next;
356 }
357}
Translation2d minus(Translation2d other)
Translation2d plus(Translation2d other)
Translation2d times(double scalar)
Translation3d plus(Translation3d other)
Translation3d times(double scalar)
Translation3d minus(Translation3d other)
static void reportError(String error, StackTraceElement[] stackTrace)
static Translation3d slewRateLimit(Translation3d current, Translation3d next, double dt, double maxVelocity)
static double copyDirectionPow(double value, double exponent)
static boolean isNear(double expected, double actual, double tolerance, double min, double max)
static double angleModulus(double angleRadians)
static double inverseLerp(double a, double b, double q)
Definition MathUtil.java:39
static double lerp(double a, double b, double t)
Definition MathUtil.java:26
static< R extends Num > Vector< R > copyDirectionPow(Vector< R > value, double exponent, double maxMagnitude)
static< R extends Num > Vector< R > applyDeadband(Vector< R > value, double deadband)
static< R extends Num > Vector< R > applyDeadband(Vector< R > value, double deadband, double maxMagnitude)
static Translation2d slewRateLimit(Translation2d current, Translation2d next, double dt, double maxVelocity)
static boolean isNear(double expected, double actual, double tolerance)
static double applyDeadband(double value, double deadband)
static double copyDirectionPow(double value, double exponent, double maxMagnitude)
static< R extends Num > Vector< R > copyDirectionPow(Vector< R > value, double exponent)
static double applyDeadband(double value, double deadband, double maxMagnitude)
Definition MathUtil.java:59
static double inputModulus(double input, double minimumInput, double maximumInput)