Use unicode characters in docs equations (#3487)

javac and javadoc needed the encoding set to UTF-8.
This commit is contained in:
Tyler Veness
2021-07-29 22:42:43 -07:00
committed by GitHub
parent 85748f2e6f
commit 3838cc4ec4
42 changed files with 216 additions and 170 deletions

View File

@@ -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.
*/

View File

@@ -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.

View File

@@ -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));

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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)))));
}
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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()));
}
}

View File

@@ -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.
*

View File

@@ -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);

View File

@@ -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).