mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-22 01:11:42 +00:00
Use unicode characters in docs equations (#3487)
javac and javadoc needed the encoding set to UTF-8.
This commit is contained in:
@@ -290,7 +290,7 @@ public class Matrix<R extends Num, C extends Num> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the transpose, M^T of this matrix.
|
||||
* Calculates the transpose, Mᵀ of this matrix.
|
||||
*
|
||||
* @return The transpose matrix.
|
||||
*/
|
||||
|
||||
@@ -88,8 +88,8 @@ public final class StateSpaceUtil {
|
||||
* Returns true if (A, B) is a stabilizable pair.
|
||||
*
|
||||
* <p>(A,B) is stabilizable if and only if the uncontrollable eigenvalues of A, if any, have
|
||||
* absolute values less than one, where an eigenvalue is uncontrollable if rank(lambda * I - A, B)
|
||||
* %3C n where n is number of states.
|
||||
* absolute values less than one, where an eigenvalue is uncontrollable if rank(λI - A, B) %3C n
|
||||
* where n is number of states.
|
||||
*
|
||||
* @param <States> Num representing the size of A.
|
||||
* @param <Inputs> Num representing the columns of B.
|
||||
|
||||
@@ -103,8 +103,8 @@ public class LinearQuadraticRegulator<States extends Num, Inputs extends Num, Ou
|
||||
|
||||
var S = Drake.discreteAlgebraicRiccatiEquation(discA, discB, Q, R);
|
||||
|
||||
// K = (BᵀSB + R)⁻¹BᵀSA
|
||||
var temp = discB.transpose().times(S).times(discB).plus(R);
|
||||
|
||||
m_K = temp.solve(discB.transpose().times(S).times(discA));
|
||||
|
||||
m_r = new Matrix<>(new SimpleMatrix(B.getNumRows(), 1));
|
||||
@@ -137,8 +137,8 @@ public class LinearQuadraticRegulator<States extends Num, Inputs extends Num, Ou
|
||||
|
||||
var S = Drake.discreteAlgebraicRiccatiEquation(discA, discB, Q, R, N);
|
||||
|
||||
// K = (BᵀSB + R)⁻¹(BᵀSA + Nᵀ)
|
||||
var temp = discB.transpose().times(S).times(discB).plus(R);
|
||||
|
||||
m_K = temp.solve(discB.transpose().times(S).times(discA).plus(N.transpose()));
|
||||
|
||||
m_r = new Matrix<>(new SimpleMatrix(B.getNumRows(), 1));
|
||||
|
||||
@@ -36,15 +36,15 @@ import java.util.function.BiConsumer;
|
||||
*
|
||||
* <p>Our state-space system is:
|
||||
*
|
||||
* <p><strong> x = [[x, y, theta, dist_l, dist_r]]^T </strong> in the field coordinate system
|
||||
* (dist_* are wheel distances.)
|
||||
* <p><strong> x = [[x, y, theta, dist_l, dist_r]]ᵀ </strong> in the field coordinate system (dist_*
|
||||
* are wheel distances.)
|
||||
*
|
||||
* <p><strong> u = [[vx, vy, omega]]^T </strong> (robot-relative velocities) -- NB: using velocities
|
||||
* <p><strong> u = [[vx, vy, omega]]ᵀ </strong> (robot-relative velocities) -- NB: using velocities
|
||||
* make things considerably easier, because it means that teams don't have to worry about getting an
|
||||
* accurate model. Basically, we suspect that it's easier for teams to get good encoder data than it
|
||||
* is for them to perform system identification well enough to get a good model.
|
||||
*
|
||||
* <p><strong>y = [[x, y, theta]]^T </strong> from vision, or <strong>y = [[dist_l, dist_r, theta]]
|
||||
* <p><strong>y = [[x, y, theta]]ᵀ </strong> from vision, or <strong>y = [[dist_l, dist_r, theta]]
|
||||
* </strong> from encoders and gyro.
|
||||
*/
|
||||
public class DifferentialDrivePoseEstimator {
|
||||
@@ -66,14 +66,14 @@ public class DifferentialDrivePoseEstimator {
|
||||
* @param gyroAngle The current gyro angle.
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta, dist_l, dist_r]^T,
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta, dist_l, dist_r]ᵀ,
|
||||
* with units in meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [dist_l, dist_r, theta]^T, with units in meters and radians.
|
||||
* is in the form [dist_l, dist_r, theta]ᵀ, with units in meters and radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public DifferentialDrivePoseEstimator(
|
||||
Rotation2d gyroAngle,
|
||||
@@ -96,14 +96,14 @@ public class DifferentialDrivePoseEstimator {
|
||||
* @param gyroAngle The current gyro angle.
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta, dist_l, dist_r]^T,
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta, dist_l, dist_r]ᵀ,
|
||||
* with units in meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [dist_l, dist_r, theta]^T, with units in meters and radians.
|
||||
* is in the form [dist_l, dist_r, theta]ᵀ, with units in meters and radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
* @param nominalDtSeconds The time in seconds between each robot loop.
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
@@ -160,7 +160,7 @@ public class DifferentialDrivePoseEstimator {
|
||||
*
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void setVisionMeasurementStdDevs(Matrix<N3, N1> visionMeasurementStdDevs) {
|
||||
m_visionContR = StateSpaceUtil.makeCovarianceMatrix(Nat.N3(), visionMeasurementStdDevs);
|
||||
@@ -279,7 +279,7 @@ public class DifferentialDrivePoseEstimator {
|
||||
* source in this case.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void addVisionMeasurement(
|
||||
Pose2d visionRobotPoseMeters,
|
||||
|
||||
@@ -141,7 +141,7 @@ public class ExtendedKalmanFilter<States extends Num, Inputs extends Num, Output
|
||||
|
||||
final var discR = Discretization.discretizeR(m_contR, dtSeconds);
|
||||
|
||||
// IsStabilizable(A^T, C^T) will tell us if the system is observable.
|
||||
// IsStabilizable(Aᵀ, Cᵀ) will tell us if the system is observable.
|
||||
boolean isObservable = StateSpaceUtil.isStabilizable(discA.transpose(), C.transpose());
|
||||
if (isObservable && outputs.getNum() <= states.getNum()) {
|
||||
m_initP =
|
||||
@@ -267,7 +267,10 @@ public class ExtendedKalmanFilter<States extends Num, Inputs extends Num, Output
|
||||
final var discQ = discPair.getSecond();
|
||||
|
||||
m_xHat = NumericalIntegration.rk4(f, m_xHat, u, dtSeconds);
|
||||
|
||||
// Pₖ₊₁⁻ = APₖ⁻Aᵀ + Q
|
||||
m_P = discA.times(m_P).times(discA.transpose()).plus(discQ);
|
||||
|
||||
m_dtSeconds = dtSeconds;
|
||||
}
|
||||
|
||||
@@ -338,23 +341,24 @@ public class ExtendedKalmanFilter<States extends Num, Inputs extends Num, Output
|
||||
|
||||
final var S = C.times(m_P).times(C.transpose()).plus(discR);
|
||||
|
||||
// We want to put K = PC^T S^-1 into Ax = b form so we can solve it more
|
||||
// We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more
|
||||
// efficiently.
|
||||
//
|
||||
// K = PC^T S^-1
|
||||
// KS = PC^T
|
||||
// (KS)^T = (PC^T)^T
|
||||
// S^T K^T = CP^T
|
||||
// K = PCᵀS⁻¹
|
||||
// KS = PCᵀ
|
||||
// (KS)ᵀ = (PCᵀ)ᵀ
|
||||
// SᵀKᵀ = CPᵀ
|
||||
//
|
||||
// The solution of Ax = b can be found via x = A.solve(b).
|
||||
//
|
||||
// K^T = S^T.solve(CP^T)
|
||||
// K = (S^T.solve(CP^T))^T
|
||||
//
|
||||
// Now we have the Kalman gain
|
||||
// Kᵀ = Sᵀ.solve(CPᵀ)
|
||||
// K = (Sᵀ.solve(CPᵀ))ᵀ
|
||||
final Matrix<States, Rows> K = S.transpose().solve(C.times(m_P.transpose())).transpose();
|
||||
|
||||
// x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − h(x̂ₖ₊₁⁻, uₖ₊₁))
|
||||
m_xHat = addFuncX.apply(m_xHat, K.times(residualFuncY.apply(y, h.apply(m_xHat, u))));
|
||||
|
||||
// Pₖ₊₁⁺ = (I − KC)Pₖ₊₁⁻
|
||||
m_P = Matrix.eye(m_states).minus(K.times(C)).times(m_P);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class KalmanFilter<States extends Num, Inputs extends Num, Outputs extend
|
||||
|
||||
var C = plant.getC();
|
||||
|
||||
// isStabilizable(A^T, C^T) will tell us if the system is observable.
|
||||
// isStabilizable(Aᵀ, Cᵀ) will tell us if the system is observable.
|
||||
var isObservable = StateSpaceUtil.isStabilizable(discA.transpose(), C.transpose());
|
||||
if (!isObservable) {
|
||||
MathSharedStore.reportError(
|
||||
@@ -90,20 +90,21 @@ public class KalmanFilter<States extends Num, Inputs extends Num, Outputs extend
|
||||
new Matrix<>(
|
||||
Drake.discreteAlgebraicRiccatiEquation(discA.transpose(), C.transpose(), discQ, discR));
|
||||
|
||||
// S = CPCᵀ + R
|
||||
var S = C.times(P).times(C.transpose()).plus(discR);
|
||||
|
||||
// We want to put K = PC^T S^-1 into Ax = b form so we can solve it more
|
||||
// We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more
|
||||
// efficiently.
|
||||
//
|
||||
// K = PC^T S^-1
|
||||
// KS = PC^T
|
||||
// (KS)^T = (PC^T)^T
|
||||
// S^T K^T = CP^T
|
||||
// K = PCᵀS⁻¹
|
||||
// KS = PCᵀ
|
||||
// (KS)ᵀ = (PCᵀ)ᵀ
|
||||
// SᵀKᵀ = CPᵀ
|
||||
//
|
||||
// The solution of Ax = b can be found via x = A.solve(b).
|
||||
//
|
||||
// K^T = S^T.solve(CP^T)
|
||||
// K = (S^T.solve(CP^T))^T
|
||||
// Kᵀ = Sᵀ.solve(CPᵀ)
|
||||
// K = (Sᵀ.solve(CPᵀ))ᵀ
|
||||
m_K =
|
||||
new Matrix<>(
|
||||
S.transpose().getStorage().solve((C.times(P.transpose())).getStorage()).transpose());
|
||||
@@ -194,6 +195,7 @@ public class KalmanFilter<States extends Num, Inputs extends Num, Outputs extend
|
||||
public void correct(Matrix<Inputs, N1> u, Matrix<Outputs, N1> y) {
|
||||
final var C = m_plant.getC();
|
||||
final var D = m_plant.getD();
|
||||
// x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁))
|
||||
m_xHat = m_xHat.plus(m_K.times(y.minus(C.times(m_xHat).plus(D.times(u)))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ import java.util.function.BiConsumer;
|
||||
*
|
||||
* <p>Our state-space system is:
|
||||
*
|
||||
* <p><strong> x = [[x, y, theta]]^T </strong> in the field-coordinate system.
|
||||
* <p><strong> x = [[x, y, theta]]ᵀ </strong> in the field-coordinate system.
|
||||
*
|
||||
* <p><strong> u = [[vx, vy, theta]]^T </strong> in the field-coordinate system.
|
||||
* <p><strong> u = [[vx, vy, theta]]ᵀ </strong> in the field-coordinate system.
|
||||
*
|
||||
* <p><strong> y = [[x, y, theta]]^T </strong> in field coords from vision, or <strong> y =
|
||||
* [[theta]]^T </strong> from the gyro.
|
||||
* <p><strong> y = [[x, y, theta]]ᵀ </strong> in field coords from vision, or <strong> y =
|
||||
* [[theta]]ᵀ </strong> from the gyro.
|
||||
*/
|
||||
public class MecanumDrivePoseEstimator {
|
||||
private final UnscentedKalmanFilter<N3, N3, N1> m_observer;
|
||||
@@ -62,14 +62,14 @@ public class MecanumDrivePoseEstimator {
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param kinematics A correctly-configured kinematics object for your drivetrain.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]^T, with units in
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]ᵀ, with units in
|
||||
* meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [theta], with units in radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public MecanumDrivePoseEstimator(
|
||||
Rotation2d gyroAngle,
|
||||
@@ -95,14 +95,14 @@ public class MecanumDrivePoseEstimator {
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param kinematics A correctly-configured kinematics object for your drivetrain.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]^T, with units in
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]ᵀ, with units in
|
||||
* meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [theta], with units in radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
* @param nominalDtSeconds The time in seconds between each robot loop.
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
@@ -161,7 +161,7 @@ public class MecanumDrivePoseEstimator {
|
||||
*
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void setVisionMeasurementStdDevs(Matrix<N3, N1> visionMeasurementStdDevs) {
|
||||
m_visionContR = StateSpaceUtil.makeCovarianceMatrix(Nat.N3(), visionMeasurementStdDevs);
|
||||
@@ -242,7 +242,7 @@ public class MecanumDrivePoseEstimator {
|
||||
* Timer.getFPGATimestamp as your time source in this case.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void addVisionMeasurement(
|
||||
Pose2d visionRobotPoseMeters,
|
||||
|
||||
@@ -34,12 +34,12 @@ import java.util.function.BiConsumer;
|
||||
*
|
||||
* <p>Our state-space system is:
|
||||
*
|
||||
* <p><strong> x = [[x, y, theta]]^T </strong> in the field-coordinate system.
|
||||
* <p><strong> x = [[x, y, theta]]ᵀ </strong> in the field-coordinate system.
|
||||
*
|
||||
* <p><strong> u = [[vx, vy, omega]]^T </strong> in the field-coordinate system.
|
||||
* <p><strong> u = [[vx, vy, omega]]ᵀ </strong> in the field-coordinate system.
|
||||
*
|
||||
* <p><strong> y = [[x, y, theta]]^T </strong> in field coords from vision, or <strong> y =
|
||||
* [[theta]]^T </strong> from the gyro.
|
||||
* <p><strong> y = [[x, y, theta]]ᵀ </strong> in field coords from vision, or <strong> y =
|
||||
* [[theta]]ᵀ </strong> from the gyro.
|
||||
*/
|
||||
public class SwerveDrivePoseEstimator {
|
||||
private final UnscentedKalmanFilter<N3, N3, N1> m_observer;
|
||||
@@ -62,14 +62,14 @@ public class SwerveDrivePoseEstimator {
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param kinematics A correctly-configured kinematics object for your drivetrain.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]^T, with units in
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]ᵀ, with units in
|
||||
* meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [theta], with units in radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public SwerveDrivePoseEstimator(
|
||||
Rotation2d gyroAngle,
|
||||
@@ -95,14 +95,14 @@ public class SwerveDrivePoseEstimator {
|
||||
* @param initialPoseMeters The starting pose estimate.
|
||||
* @param kinematics A correctly-configured kinematics object for your drivetrain.
|
||||
* @param stateStdDevs Standard deviations of model states. Increase these numbers to trust your
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]^T, with units in
|
||||
* model's state estimates less. This matrix is in the form [x, y, theta]ᵀ, with units in
|
||||
* meters and radians.
|
||||
* @param localMeasurementStdDevs Standard deviations of the encoder and gyro measurements.
|
||||
* Increase these numbers to trust sensor readings from encoders and gyros less. This matrix
|
||||
* is in the form [theta], with units in radians.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
* @param nominalDtSeconds The time in seconds between each robot loop.
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
@@ -161,7 +161,7 @@ public class SwerveDrivePoseEstimator {
|
||||
*
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void setVisionMeasurementStdDevs(Matrix<N3, N1> visionMeasurementStdDevs) {
|
||||
m_visionContR = StateSpaceUtil.makeCovarianceMatrix(Nat.N3(), visionMeasurementStdDevs);
|
||||
@@ -242,7 +242,7 @@ public class SwerveDrivePoseEstimator {
|
||||
* Timer.getFPGATimestamp as your time source in this case.
|
||||
* @param visionMeasurementStdDevs Standard deviations of the vision measurements. Increase these
|
||||
* numbers to trust global measurements from vision less. This matrix is in the form [x, y,
|
||||
* theta]^T, with units in meters and radians.
|
||||
* theta]ᵀ, with units in meters and radians.
|
||||
*/
|
||||
public void addVisionMeasurement(
|
||||
Pose2d visionRobotPoseMeters,
|
||||
|
||||
@@ -171,7 +171,9 @@ public class UnscentedKalmanFilter<States extends Num, Inputs extends Num, Outpu
|
||||
}
|
||||
|
||||
// New mean is usually just the sum of the sigmas * weight:
|
||||
// dot = \Sigma^n_1 (W[k]*Xi[k])
|
||||
// n
|
||||
// dot = Σ W[k] Xᵢ[k]
|
||||
// k=1
|
||||
Matrix<C, N1> x = meanFunc.apply(sigmas, Wm);
|
||||
|
||||
// New covariance is the sum of the outer product of the residuals times the
|
||||
@@ -403,22 +405,24 @@ public class UnscentedKalmanFilter<States extends Num, Inputs extends Num, Outpu
|
||||
// Compute cross covariance of the state and the measurements
|
||||
Matrix<States, R> Pxy = new Matrix<>(m_states, rows);
|
||||
for (int i = 0; i < m_pts.getNumSigmas(); i++) {
|
||||
// Pxy += (sigmas_f[:, i] - xHat) * (sigmas_h[:, i] - yHat)^T * W_c[i]
|
||||
// Pxy += (sigmas_f[:, i] - x̂)(sigmas_h[:, i] - ŷ)ᵀ W_c[i]
|
||||
var dx = residualFuncX.apply(m_sigmasF.extractColumnVector(i), m_xHat);
|
||||
var dy = residualFuncY.apply(sigmasH.extractColumnVector(i), yHat).transpose();
|
||||
|
||||
Pxy = Pxy.plus(dx.times(dy).times(m_pts.getWc(i)));
|
||||
}
|
||||
|
||||
// K = P_{xy} Py^-1
|
||||
// K^T = P_y^T^-1 P_{xy}^T
|
||||
// P_y^T K^T = P_{xy}^T
|
||||
// K^T = P_y^T.solve(P_{xy}^T)
|
||||
// K = (P_y^T.solve(P_{xy}^T)^T
|
||||
// K = P_{xy} P_y⁻¹
|
||||
// Kᵀ = P_yᵀ⁻¹ P_{xy}ᵀ
|
||||
// P_yᵀKᵀ = P_{xy}ᵀ
|
||||
// Kᵀ = P_yᵀ.solve(P_{xy}ᵀ)
|
||||
// K = (P_yᵀ.solve(P_{xy}ᵀ)ᵀ
|
||||
Matrix<States, R> K = new Matrix<>(Py.transpose().solve(Pxy.transpose()).transpose());
|
||||
|
||||
// xHat + K * (y - yHat)
|
||||
// x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − ŷ)
|
||||
m_xHat = addFuncX.apply(m_xHat, K.times(residualFuncY.apply(y, yHat)));
|
||||
|
||||
// Pₖ₊₁⁺ = Pₖ₊₁⁻ − KP_yKᵀ
|
||||
m_P = m_P.minus(K.times(Py).times(K.transpose()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import java.util.Arrays;
|
||||
* This class implements a linear, digital filter. All types of FIR and IIR filters are supported.
|
||||
* Static factory methods are provided to create commonly used types of filters.
|
||||
*
|
||||
* <p>Filters are of the form: y[n] = (b0*x[n] + b1*x[n-1] + ... + bP*x[n-P]) - (a0*y[n-1] +
|
||||
* a2*y[n-2] + ... + aQ*y[n-Q])
|
||||
* <p>Filters are of the form: y[n] = (b0 x[n] + b1 x[n-1] + ... + bP x[n-P]) - (a0 y[n-1] + a2
|
||||
* y[n-2] + ... + aQ y[n-Q])
|
||||
*
|
||||
* <p>Where: y[n] is the output at time "n" x[n] is the input at time "n" y[n-1] is the output from
|
||||
* the LAST time step ("n-1") x[n-1] is the input from the LAST time step ("n-1") b0...bP are the
|
||||
@@ -71,8 +71,8 @@ public class LinearFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a one-pole IIR low-pass filter of the form: y[n] = (1-gain)*x[n] + gain*y[n-1] where
|
||||
* gain = e^(-dt / T), T is the time constant in seconds.
|
||||
* Creates a one-pole IIR low-pass filter of the form: y[n] = (1-gain) x[n] + gain y[n-1] where
|
||||
* gain = e<sup>-dt / T</sup>, T is the time constant in seconds.
|
||||
*
|
||||
* <p>Note: T = 1 / (2 pi f) where f is the cutoff frequency in Hz, the frequency above which the
|
||||
* input starts to attenuate.
|
||||
@@ -92,8 +92,8 @@ public class LinearFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a first-order high-pass filter of the form: y[n] = gain*x[n] + (-gain)*x[n-1] +
|
||||
* gain*y[n-1] where gain = e^(-dt / T), T is the time constant in seconds.
|
||||
* Creates a first-order high-pass filter of the form: y[n] = gain x[n] + (-gain) x[n-1] + gain
|
||||
* y[n-1] where gain = e<sup>-dt / T</sup>, T is the time constant in seconds.
|
||||
*
|
||||
* <p>Note: T = 1 / (2 pi f) where f is the cutoff frequency in Hz, the frequency below which the
|
||||
* input starts to attenuate.
|
||||
@@ -113,8 +113,7 @@ public class LinearFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a K-tap FIR moving average filter of the form: y[n] = 1/k * (x[k] + x[k-1] + ... +
|
||||
* x[0]).
|
||||
* Creates a K-tap FIR moving average filter of the form: y[n] = 1/k (x[k] + x[k-1] + ... + x[0]).
|
||||
*
|
||||
* <p>This filter is always stable.
|
||||
*
|
||||
|
||||
@@ -64,6 +64,7 @@ public final class Discretization {
|
||||
/**
|
||||
* Discretizes the given continuous A and Q matrices.
|
||||
*
|
||||
* @param <States> Nat representing the number of states.
|
||||
* @param contA Continuous system matrix.
|
||||
* @param contQ Continuous process noise covariance matrix.
|
||||
* @param dtSeconds Discretization timestep.
|
||||
@@ -128,11 +129,11 @@ public final class Discretization {
|
||||
Matrix<States, States> lastTerm = Q.copy();
|
||||
double lastCoeff = dtSeconds;
|
||||
|
||||
// A^T^n
|
||||
// Aᵀⁿ
|
||||
Matrix<States, States> Atn = contA.transpose();
|
||||
Matrix<States, States> phi12 = lastTerm.times(lastCoeff);
|
||||
|
||||
// i = 6 i.e. 6th order should be enough precision
|
||||
// i = 6 i.e. 5th order should be enough precision
|
||||
for (int i = 2; i < 6; ++i) {
|
||||
lastTerm = contA.times(-1).times(lastTerm).plus(Q.times(Atn));
|
||||
lastCoeff *= dtSeconds / ((double) i);
|
||||
|
||||
@@ -18,7 +18,7 @@ public final class LinearSystemId {
|
||||
|
||||
/**
|
||||
* Create a state-space model of an elevator system. The states of the system are [position,
|
||||
* velocity]^T, inputs are [voltage], and outputs are [position].
|
||||
* velocity]ᵀ, inputs are [voltage], and outputs are [position].
|
||||
*
|
||||
* @param motor The motor (or gearbox) attached to the arm.
|
||||
* @param massKg The mass of the elevator carriage, in kilograms.
|
||||
@@ -72,7 +72,7 @@ public final class LinearSystemId {
|
||||
|
||||
/**
|
||||
* Create a state-space model of a differential drive drivetrain. In this model, the states are
|
||||
* [v_left, v_right]^T, inputs are [V_left, V_right]^T and outputs are [v_left, v_right]^T.
|
||||
* [v_left, v_right]ᵀ, inputs are [V_left, V_right]ᵀ and outputs are [v_left, v_right]ᵀ.
|
||||
*
|
||||
* @param motor the gearbox representing the motors driving the drivetrain.
|
||||
* @param massKg the mass of the robot.
|
||||
@@ -157,7 +157,7 @@ public final class LinearSystemId {
|
||||
/**
|
||||
* Identify a position system from it's kV (volts/(unit/sec)) and kA (volts/(unit/sec^2). These
|
||||
* constants cam be found using frc-characterization. The states of the system are [position,
|
||||
* velocity]^T, inputs are [voltage], and outputs are [position].
|
||||
* velocity]ᵀ, inputs are [voltage], and outputs are [position].
|
||||
*
|
||||
* <p>The distance unit you choose MUST be an SI unit (i.e. meters or radians). You can use the
|
||||
* {@link edu.wpi.first.math.util.Units} class for converting between unit types.
|
||||
@@ -181,8 +181,8 @@ public final class LinearSystemId {
|
||||
* Identify a standard differential drive drivetrain, given the drivetrain's kV and kA in both
|
||||
* linear (volts/(meter/sec) and volts/(meter/sec^2)) and angular (volts/(meter/sec) and
|
||||
* volts/(meter/sec^2)) cases. This can be found using frc-characterization. The states of the
|
||||
* system are [left velocity, right velocity]^T, inputs are [left voltage, right voltage]^T, and
|
||||
* outputs are [left velocity, right velocity]^T.
|
||||
* system are [left velocity, right velocity]ᵀ, inputs are [left voltage, right voltage]ᵀ, and
|
||||
* outputs are [left velocity, right velocity]ᵀ.
|
||||
*
|
||||
* @param kVLinear The linear velocity gain, volts per (meter per second).
|
||||
* @param kALinear The linear acceleration gain, volts per (meter per second squared).
|
||||
@@ -211,8 +211,8 @@ public final class LinearSystemId {
|
||||
* Identify a standard differential drive drivetrain, given the drivetrain's kV and kA in both
|
||||
* linear (volts/(meter/sec) and volts/(meter/sec^2)) and angular (volts/(radian/sec) and
|
||||
* volts/(radian/sec^2)) cases. This can be found using frc-characterization. The states of the
|
||||
* system are [left velocity, right velocity]^T, inputs are [left voltage, right voltage]^T, and
|
||||
* outputs are [left velocity, right velocity]^T.
|
||||
* system are [left velocity, right velocity]ᵀ, inputs are [left voltage, right voltage]ᵀ, and
|
||||
* outputs are [left velocity, right velocity]ᵀ.
|
||||
*
|
||||
* @param kVLinear The linear velocity gain, volts per (meter per second).
|
||||
* @param kALinear The linear acceleration gain, volts per (meter per second squared).
|
||||
|
||||
Reference in New Issue
Block a user