trajectory/ballistics/calculators: Docs + reorganization
- BCResult: Define a static no solution record
- Refactor evalSingleCandidate into BallisticCalculator
- getCandidatePenalty() made private
This commit is contained in:
parent
138dfc5d7f
commit
93aa5b7430
|
|
@ -7,6 +7,8 @@ import org.fairportrobotics.frc.robolib.trajectory.ballistics.constraints.BCEval
|
||||||
*/
|
*/
|
||||||
public record BCResult(Double penalty, BCEvalParams evalParams) {
|
public record BCResult(Double penalty, BCEvalParams evalParams) {
|
||||||
|
|
||||||
|
public static final BCResult kNoSolution = new BCResult(null, null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the result is valid (i.e. checks if penalty != null)
|
* Checks if the result is valid (i.e. checks if penalty != null)
|
||||||
* @return True if the evalParams evaluates as valid, false otherwise
|
* @return True if the evalParams evaluates as valid, false otherwise
|
||||||
|
|
|
||||||
|
|
@ -10,24 +10,43 @@ import org.fairportrobotics.frc.robolib.trajectory.ballistics.models.BallisticMo
|
||||||
|
|
||||||
import edu.wpi.first.units.measure.Angle;
|
import edu.wpi.first.units.measure.Angle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base cass for ballistics calculators
|
||||||
|
*/
|
||||||
public abstract class BallisticCalculator {
|
public abstract class BallisticCalculator {
|
||||||
|
/** The list of constraints used to evaluate solutions */
|
||||||
private ArrayList<BallisticConstraint> constraints;
|
private ArrayList<BallisticConstraint> constraints;
|
||||||
|
/** The weight to assign to difference in velocity while evaluating */
|
||||||
private double velocityDiffWeight;
|
private double velocityDiffWeight;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup code
|
// Setup code
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default constructor. Sets velocity diff weight to 1.0
|
||||||
|
*/
|
||||||
public BallisticCalculator() {
|
public BallisticCalculator() {
|
||||||
constraints = new ArrayList<>();
|
constraints = new ArrayList<>();
|
||||||
this.velocityDiffWeight = 1.0;
|
this.velocityDiffWeight = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a constraint to the calculator
|
||||||
|
* @param constraint The constraint to add to the calculator
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
public BallisticCalculator addConstraint(BallisticConstraint constraint) {
|
public BallisticCalculator addConstraint(BallisticConstraint constraint) {
|
||||||
constraints.add(constraint);
|
constraints.add(constraint);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the weight for the difference in velocity
|
||||||
|
* @param weight The weight to assign to difference in velocity
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
public BallisticCalculator setVelocityDiffWeight(double weight) {
|
public BallisticCalculator setVelocityDiffWeight(double weight) {
|
||||||
this.velocityDiffWeight = weight;
|
this.velocityDiffWeight = weight;
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -62,7 +81,9 @@ public abstract class BallisticCalculator {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the best solution for given initial conditions
|
* Compute the best solution for given initial conditions.
|
||||||
|
*
|
||||||
|
* NOTE: May reset seen candidates
|
||||||
*
|
*
|
||||||
* @param <M> The type of model to compute against
|
* @param <M> The type of model to compute against
|
||||||
* @param <P> The candidate parameter type of the model
|
* @param <P> The candidate parameter type of the model
|
||||||
|
|
@ -81,6 +102,30 @@ public abstract class BallisticCalculator {
|
||||||
Velocity3d shooterVelocity
|
Velocity3d shooterVelocity
|
||||||
) throws BallisticException;
|
) throws BallisticException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate and evaluate a solution for a given model, param, and robot state
|
||||||
|
*
|
||||||
|
* @param <M> The type of model to evaluate for
|
||||||
|
* @param <P> The type of param to model M
|
||||||
|
* @param model The model to evaluate for
|
||||||
|
* @param modelParam The parameter to evaluate for
|
||||||
|
* @param robotVelocity The robot's current velocity
|
||||||
|
* @param robotAngle The robot's current angle
|
||||||
|
* @param shooterVelocity The current velocity provided by the shooter
|
||||||
|
* @return The BCResult instance for the given params
|
||||||
|
* @throws BallisticException If thrown by registered constraints
|
||||||
|
*/
|
||||||
|
protected <M extends BallisticModel<P>, P> BCResult evaluateCandidate(
|
||||||
|
M model,
|
||||||
|
P modelParam,
|
||||||
|
Velocity3d robotVelocity,
|
||||||
|
Angle robotAngle,
|
||||||
|
Velocity3d shooterVelocity
|
||||||
|
) throws BallisticException {
|
||||||
|
Velocity3d candidateVelocity = model.getCandidateVelocity(modelParam);
|
||||||
|
BCEvalParams evalParams = new BCEvalParams(robotVelocity, robotAngle, shooterVelocity, candidateVelocity);
|
||||||
|
return new BCResult(this.getCandidatePenalty(model, evalParams), evalParams);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the average penalty for a given set of params
|
* Get the average penalty for a given set of params
|
||||||
|
|
@ -91,8 +136,9 @@ public abstract class BallisticCalculator {
|
||||||
* @param evalParams The eval function param block
|
* @param evalParams The eval function param block
|
||||||
* @return The weighted average of penalties from velocity diferences and
|
* @return The weighted average of penalties from velocity diferences and
|
||||||
* constraints (null if evalParams fail any constraints)
|
* constraints (null if evalParams fail any constraints)
|
||||||
|
* @throws BallisicsException If thrown by registered constraints
|
||||||
*/
|
*/
|
||||||
protected <M extends BallisticModel<P>, P> Double evaluateCandidate(
|
private <M extends BallisticModel<P>, P> Double getCandidatePenalty(
|
||||||
M model, BCEvalParams evalParams
|
M model, BCEvalParams evalParams
|
||||||
) throws BallisticException {
|
) throws BallisticException {
|
||||||
// Get the weight component for velocity difference
|
// Get the weight component for velocity difference
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,23 @@ import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.Velocity3d;
|
import org.fairportrobotics.frc.robolib.trajectory.Velocity3d;
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.constraints.BCEvalParams;
|
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.exceptions.BallisticException;
|
import org.fairportrobotics.frc.robolib.trajectory.ballistics.exceptions.BallisticException;
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.models.BallisticModel;
|
import org.fairportrobotics.frc.robolib.trajectory.ballistics.models.BallisticModel;
|
||||||
|
|
||||||
import edu.wpi.first.units.measure.Angle;
|
import edu.wpi.first.units.measure.Angle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple greedy calculator (i.e. returns the first valid result)
|
||||||
|
*/
|
||||||
public class GreedyBallisticCalculator extends BallisticCalculator {
|
public class GreedyBallisticCalculator extends BallisticCalculator {
|
||||||
|
/**
|
||||||
|
* Default constructor for the calculator
|
||||||
|
*/
|
||||||
public GreedyBallisticCalculator() {
|
public GreedyBallisticCalculator() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public <M extends BallisticModel<P>, P> BCResult computeSolution(
|
public <M extends BallisticModel<P>, P> BCResult computeSolution(
|
||||||
M model,
|
M model,
|
||||||
P initParam,
|
P initParam,
|
||||||
|
|
@ -33,18 +38,16 @@ public class GreedyBallisticCalculator extends BallisticCalculator {
|
||||||
P param = candidate_params.removeFirst();
|
P param = candidate_params.removeFirst();
|
||||||
if(model.paramComputed(param)) continue;
|
if(model.paramComputed(param)) continue;
|
||||||
|
|
||||||
Velocity3d candidate = model.getCandidateVelocity(param);
|
BCResult candidate = this.evaluateCandidate(
|
||||||
if(candidate != null) {
|
model, param, robotVelocity, robotAngle, shooterVelocity
|
||||||
BCEvalParams evalParams = new BCEvalParams(robotVelocity, robotAngle, shooterVelocity, candidate);
|
);
|
||||||
Double penalty = this.evaluateCandidate(model, evalParams);
|
if(candidate.isValid()) {
|
||||||
if(penalty != null) {
|
return candidate;
|
||||||
return new BCResult(penalty, evalParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the candidate list
|
// Update the candidate list
|
||||||
candidate_params.addAll(Arrays.asList(model.getNeighborParams(param)));
|
candidate_params.addAll(Arrays.asList(model.getNeighborParams(param)));
|
||||||
}
|
}
|
||||||
return new BCResult(null, null);
|
return BCResult.kNoSolution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,25 @@
|
||||||
package org.fairportrobotics.frc.robolib.trajectory.ballistics.calculators;
|
package org.fairportrobotics.frc.robolib.trajectory.ballistics.calculators;
|
||||||
|
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.Velocity3d;
|
import org.fairportrobotics.frc.robolib.trajectory.Velocity3d;
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.constraints.BCEvalParams;
|
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.exceptions.BallisticException;
|
import org.fairportrobotics.frc.robolib.trajectory.ballistics.exceptions.BallisticException;
|
||||||
import org.fairportrobotics.frc.robolib.trajectory.ballistics.models.BallisticModel;
|
import org.fairportrobotics.frc.robolib.trajectory.ballistics.models.BallisticModel;
|
||||||
|
|
||||||
import edu.wpi.first.units.measure.Angle;
|
import edu.wpi.first.units.measure.Angle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solution calculator implementing a gradient descent algorithm to find a
|
||||||
|
* solution with a local minimum penalty (not guaranteed to find a global
|
||||||
|
* minimum penalty)
|
||||||
|
*/
|
||||||
public class HillDescentBallisticCalculator extends BallisticCalculator {
|
public class HillDescentBallisticCalculator extends BallisticCalculator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default consttructor for the calculator
|
||||||
|
*/
|
||||||
public HillDescentBallisticCalculator() {
|
public HillDescentBallisticCalculator() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private <M extends BallisticModel<P>, P> BCResult evalSingleCandidate(
|
|
||||||
M model,
|
|
||||||
P modelParam,
|
|
||||||
Velocity3d robotVelocity,
|
|
||||||
Angle robotAngle,
|
|
||||||
Velocity3d shooterVelocity
|
|
||||||
) throws BallisticException {
|
|
||||||
Velocity3d candidateVelocity = model.getCandidateVelocity(modelParam);
|
|
||||||
BCEvalParams evalParams = new BCEvalParams(robotVelocity, robotAngle, shooterVelocity, candidateVelocity);
|
|
||||||
return new BCResult(this.evaluateCandidate(model, evalParams), evalParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <M extends BallisticModel<P>, P> BCResult computeSolution(
|
public <M extends BallisticModel<P>, P> BCResult computeSolution(
|
||||||
M model,
|
M model,
|
||||||
P initParam,
|
P initParam,
|
||||||
|
|
@ -35,7 +30,7 @@ public class HillDescentBallisticCalculator extends BallisticCalculator {
|
||||||
model.paramComputedReset();
|
model.paramComputedReset();
|
||||||
|
|
||||||
P bestParam = initParam;
|
P bestParam = initParam;
|
||||||
BCResult bestResult = this.evalSingleCandidate(model, initParam, robotVelocity, robotAngle, shooterVelocity);
|
BCResult bestResult = this.evaluateCandidate(model, initParam, robotVelocity, robotAngle, shooterVelocity);
|
||||||
boolean foundImprovement = true;
|
boolean foundImprovement = true;
|
||||||
|
|
||||||
while(bestResult.isValid() && foundImprovement) {
|
while(bestResult.isValid() && foundImprovement) {
|
||||||
|
|
@ -44,7 +39,7 @@ public class HillDescentBallisticCalculator extends BallisticCalculator {
|
||||||
for (P param : model.getNeighborParams(bestParam)) {
|
for (P param : model.getNeighborParams(bestParam)) {
|
||||||
if(model.paramComputed(param)) continue;
|
if(model.paramComputed(param)) continue;
|
||||||
|
|
||||||
BCResult result = this.evalSingleCandidate(model, param, robotVelocity, robotAngle, shooterVelocity);
|
BCResult result = this.evaluateCandidate(model, param, robotVelocity, robotAngle, shooterVelocity);
|
||||||
if(result.isValid() && result.penalty() < bestResult.penalty()) {
|
if(result.isValid() && result.penalty() < bestResult.penalty()) {
|
||||||
bestParam = param;
|
bestParam = param;
|
||||||
bestResult = result;
|
bestResult = result;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue