mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[wpimath] Add ChassisAccelerations and drivetrain accelerations classes and add forward and inverse kinematics for accelerations to the interface (#8185)
ChassisAccelerations and the drivetrain acceleration types are added in both Java and C++. `ChassisAccelerations` is basically just `ChassisSpeeds` but for accelerations! `DifferentialDriveWheelAccelerations`, `MecanumDriveWheelAccelerations`, and `SwerveModuleAccelerations` are the acceleration equivalent of the drivetrain speeds types. In Java, the `Kinematics` interface now has an additional generic parameter `A` which represents the accelerations, and `toChassisAccelerations` and `toWheelAccelerations` methods, which are implemented the same way as `toChassisSpeeds` and `toWheelSpeeds`. Protobuf and struct classes were also added for all four classes in Java and C++. --------- Signed-off-by: Zach Harel <zach@zharel.me> Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com> Co-authored-by: Tyler Veness <calcmogul@gmail.com>
This commit is contained in:
@@ -66,7 +66,7 @@ public class PoseEstimator<T> {
|
||||
*/
|
||||
@SuppressWarnings("PMD.UnusedFormalParameter")
|
||||
public PoseEstimator(
|
||||
Kinematics<?, T> kinematics,
|
||||
Kinematics<T, ?, ?> kinematics,
|
||||
Odometry<T> odometry,
|
||||
Matrix<N3, N1> stateStdDevs,
|
||||
Matrix<N3, N1> visionMeasurementStdDevs) {
|
||||
|
||||
@@ -74,7 +74,7 @@ public class PoseEstimator3d<T> {
|
||||
*/
|
||||
@SuppressWarnings("PMD.UnusedFormalParameter")
|
||||
public PoseEstimator3d(
|
||||
Kinematics<?, T> kinematics,
|
||||
Kinematics<T, ?, ?> kinematics,
|
||||
Odometry3d<T> odometry,
|
||||
Matrix<N4, N1> stateStdDevs,
|
||||
Matrix<N4, N1> visionMeasurementStdDevs) {
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
// 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 org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecondPerSecond;
|
||||
import static org.wpilib.units.Units.RadiansPerSecondPerSecond;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.geometry.Translation2d;
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.ChassisAccelerationsProto;
|
||||
import org.wpilib.math.kinematics.struct.ChassisAccelerationsStruct;
|
||||
import org.wpilib.math.util.MathUtil;
|
||||
import org.wpilib.units.measure.AngularAcceleration;
|
||||
import org.wpilib.units.measure.LinearAcceleration;
|
||||
import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/**
|
||||
* Represents the acceleration of a robot chassis.
|
||||
*
|
||||
* <p>A strictly non-holonomic drivetrain, such as a differential drive, should never have an ay
|
||||
* component because it can never move sideways. Holonomic drivetrains such as swerve and mecanum
|
||||
* will often have all three components.
|
||||
*/
|
||||
public class ChassisAccelerations
|
||||
implements ProtobufSerializable, StructSerializable, Interpolatable<ChassisAccelerations> {
|
||||
/** Acceleration along the x-axis in meters per second squared. (Fwd is +) */
|
||||
public double ax;
|
||||
|
||||
/** Acceleration along the y-axis in meters per second squared. (Left is +) */
|
||||
public double ay;
|
||||
|
||||
/** Angular acceleration of the robot frame in radians per second squared. (CCW is +) */
|
||||
public double alpha;
|
||||
|
||||
/** ChassisAccelerations struct for serialization. */
|
||||
public static final ChassisAccelerationsStruct struct = new ChassisAccelerationsStruct();
|
||||
|
||||
/** ChassisAccelerations proto for serialization. */
|
||||
public static final ChassisAccelerationsProto proto = new ChassisAccelerationsProto();
|
||||
|
||||
/** Constructs a ChassisAccelerations with zeros for ax, ay, and omega. */
|
||||
public ChassisAccelerations() {}
|
||||
|
||||
/**
|
||||
* Constructs a ChassisAccelerations object.
|
||||
*
|
||||
* @param ax Forward acceleration in meters per second squared.
|
||||
* @param ay Sideways acceleration in meters per second squared.
|
||||
* @param alpha Angular acceleration in radians per second squared.
|
||||
*/
|
||||
public ChassisAccelerations(double ax, double ay, double alpha) {
|
||||
this.ax = ax;
|
||||
this.ay = ay;
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ChassisAccelerations object.
|
||||
*
|
||||
* @param ax Forward acceleration.
|
||||
* @param ay Sideways acceleration.
|
||||
* @param alpha Angular acceleration.
|
||||
*/
|
||||
public ChassisAccelerations(
|
||||
LinearAcceleration ax, LinearAcceleration ay, AngularAcceleration alpha) {
|
||||
this(
|
||||
ax.in(MetersPerSecondPerSecond),
|
||||
ay.in(MetersPerSecondPerSecond),
|
||||
alpha.in(RadiansPerSecondPerSecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this field-relative set of accelerations into a robot-relative ChassisAccelerations
|
||||
* object.
|
||||
*
|
||||
* @param robotAngle The angle of the robot as measured by a gyroscope. The robot's angle is
|
||||
* considered to be zero when it is facing directly away from your alliance station wall.
|
||||
* Remember that this should be CCW positive.
|
||||
* @return ChassisAccelerations object representing the accelerations in the robot's frame of
|
||||
* reference.
|
||||
*/
|
||||
public ChassisAccelerations toRobotRelative(Rotation2d robotAngle) {
|
||||
// CW rotation into chassis frame
|
||||
var rotated = new Translation2d(ax, ay).rotateBy(robotAngle.unaryMinus());
|
||||
return new ChassisAccelerations(rotated.getX(), rotated.getY(), alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this robot-relative set of accelerations into a field-relative ChassisAccelerations
|
||||
* object.
|
||||
*
|
||||
* @param robotAngle The angle of the robot as measured by a gyroscope. The robot's angle is
|
||||
* considered to be zero when it is facing directly away from your alliance station wall.
|
||||
* Remember that this should be CCW positive.
|
||||
* @return ChassisAccelerations object representing the accelerations in the field's frame of
|
||||
* reference.
|
||||
*/
|
||||
public ChassisAccelerations toFieldRelative(Rotation2d robotAngle) {
|
||||
// CCW rotation out of chassis frame
|
||||
var rotated = new Translation2d(ax, ay).rotateBy(robotAngle);
|
||||
return new ChassisAccelerations(rotated.getX(), rotated.getY(), alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two ChassisAccelerations and returns the sum.
|
||||
*
|
||||
* <p>For example, ChassisAccelerations{1.0, 0.5, 0.75} + ChassisAccelerations{2.0, 1.5, 0.25} =
|
||||
* ChassisAccelerations{3.0, 2.0, 1.0}
|
||||
*
|
||||
* @param other The ChassisAccelerations to add.
|
||||
* @return The sum of the ChassisAccelerations.
|
||||
*/
|
||||
public ChassisAccelerations plus(ChassisAccelerations other) {
|
||||
return new ChassisAccelerations(ax + other.ax, ay + other.ay, alpha + other.alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the other ChassisAccelerations from the current ChassisAccelerations and returns the
|
||||
* difference.
|
||||
*
|
||||
* <p>For example, ChassisAccelerations{5.0, 4.0, 2.0} - ChassisAccelerations{1.0, 2.0, 1.0} =
|
||||
* ChassisAccelerations{4.0, 2.0, 1.0}
|
||||
*
|
||||
* @param other The ChassisAccelerations to subtract.
|
||||
* @return The difference between the two ChassisAccelerations.
|
||||
*/
|
||||
public ChassisAccelerations minus(ChassisAccelerations other) {
|
||||
return new ChassisAccelerations(ax - other.ax, ay - other.ay, alpha - other.alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of the current ChassisAccelerations. This is equivalent to negating all
|
||||
* components of the ChassisAccelerations.
|
||||
*
|
||||
* @return The inverse of the current ChassisAccelerations.
|
||||
*/
|
||||
public ChassisAccelerations unaryMinus() {
|
||||
return new ChassisAccelerations(-ax, -ay, -alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the ChassisAccelerations by a scalar and returns the new ChassisAccelerations.
|
||||
*
|
||||
* <p>For example, ChassisAccelerations{2.0, 2.5, 1.0} * 2 = ChassisAccelerations{4.0, 5.0, 1.0}
|
||||
*
|
||||
* @param scalar The scalar to multiply by.
|
||||
* @return The scaled ChassisAccelerations.
|
||||
*/
|
||||
public ChassisAccelerations times(double scalar) {
|
||||
return new ChassisAccelerations(ax * scalar, ay * scalar, alpha * scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the ChassisAccelerations by a scalar and returns the new ChassisAccelerations.
|
||||
*
|
||||
* <p>For example, ChassisAccelerations{2.0, 2.5, 1.0} / 2 = ChassisAccelerations{1.0, 1.25, 0.5}
|
||||
*
|
||||
* @param scalar The scalar to divide by.
|
||||
* @return The scaled ChassisAccelerations.
|
||||
*/
|
||||
public ChassisAccelerations div(double scalar) {
|
||||
return new ChassisAccelerations(ax / scalar, ay / scalar, alpha / scalar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChassisAccelerations interpolate(ChassisAccelerations endValue, double t) {
|
||||
if (t <= 0) {
|
||||
return this;
|
||||
} else if (t >= 1) {
|
||||
return endValue;
|
||||
} else {
|
||||
return new ChassisAccelerations(
|
||||
MathUtil.lerp(this.ax, endValue.ax, t),
|
||||
MathUtil.lerp(this.ay, endValue.ay, t),
|
||||
MathUtil.lerp(this.alpha, endValue.alpha, t));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(ax, ay, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o == this
|
||||
|| o instanceof ChassisAccelerations c && ax == c.ax && ay == c.ay && alpha == c.alpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"ChassisAccelerations(Ax: %.2f m/s², Ay: %.2f m/s², Alpha: %.2f rad/s²)", ax, ay, alpha);
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,10 @@ import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.geometry.Transform2d;
|
||||
import org.wpilib.math.geometry.Translation2d;
|
||||
import org.wpilib.math.geometry.Twist2d;
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.ChassisSpeedsProto;
|
||||
import org.wpilib.math.kinematics.struct.ChassisSpeedsStruct;
|
||||
import org.wpilib.math.util.MathUtil;
|
||||
import org.wpilib.units.measure.AngularVelocity;
|
||||
import org.wpilib.units.measure.LinearVelocity;
|
||||
import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
@@ -28,7 +30,8 @@ import org.wpilib.util.struct.StructSerializable;
|
||||
* component because it can never move sideways. Holonomic drivetrains such as swerve and mecanum
|
||||
* will often have all three components.
|
||||
*/
|
||||
public class ChassisSpeeds implements ProtobufSerializable, StructSerializable {
|
||||
public class ChassisSpeeds
|
||||
implements ProtobufSerializable, StructSerializable, Interpolatable<ChassisSpeeds> {
|
||||
/** Velocity along the x-axis in meters per second. (Fwd is +) */
|
||||
public double vx;
|
||||
|
||||
@@ -199,6 +202,20 @@ public class ChassisSpeeds implements ProtobufSerializable, StructSerializable {
|
||||
return new ChassisSpeeds(vx / scalar, vy / scalar, omega / scalar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChassisSpeeds interpolate(ChassisSpeeds endValue, double t) {
|
||||
if (t <= 0) {
|
||||
return this;
|
||||
} else if (t >= 1) {
|
||||
return endValue;
|
||||
} else {
|
||||
return new ChassisSpeeds(
|
||||
MathUtil.lerp(this.vx, endValue.vx, t),
|
||||
MathUtil.lerp(this.vy, endValue.vy, t),
|
||||
MathUtil.lerp(this.omega, endValue.omega, t));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(vx, vy, omega);
|
||||
|
||||
@@ -23,7 +23,10 @@ import org.wpilib.util.struct.StructSerializable;
|
||||
* chassis speed.
|
||||
*/
|
||||
public class DifferentialDriveKinematics
|
||||
implements Kinematics<DifferentialDriveWheelSpeeds, DifferentialDriveWheelPositions>,
|
||||
implements Kinematics<
|
||||
DifferentialDriveWheelPositions,
|
||||
DifferentialDriveWheelSpeeds,
|
||||
DifferentialDriveWheelAccelerations>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Differential drive trackwidth in meters. */
|
||||
@@ -88,6 +91,23 @@ public class DifferentialDriveKinematics
|
||||
chassisSpeeds.vx + trackwidth / 2 * chassisSpeeds.omega);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChassisAccelerations toChassisAccelerations(
|
||||
DifferentialDriveWheelAccelerations wheelAccelerations) {
|
||||
return new ChassisAccelerations(
|
||||
(wheelAccelerations.left + wheelAccelerations.right) / 2,
|
||||
0.0,
|
||||
(wheelAccelerations.right - wheelAccelerations.left) / trackwidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DifferentialDriveWheelAccelerations toWheelAccelerations(
|
||||
ChassisAccelerations chassisAccelerations) {
|
||||
return new DifferentialDriveWheelAccelerations(
|
||||
chassisAccelerations.ax - trackwidth / 2 * chassisAccelerations.alpha,
|
||||
chassisAccelerations.ax + trackwidth / 2 * chassisAccelerations.alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Twist2d toTwist2d(
|
||||
DifferentialDriveWheelPositions start, DifferentialDriveWheelPositions end) {
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
// 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 org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecondPerSecond;
|
||||
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.DifferentialDriveWheelAccelerationsProto;
|
||||
import org.wpilib.math.kinematics.struct.DifferentialDriveWheelAccelerationsStruct;
|
||||
import org.wpilib.units.measure.LinearAcceleration;
|
||||
import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the wheel accelerations for a differential drive drivetrain. */
|
||||
public class DifferentialDriveWheelAccelerations
|
||||
implements Interpolatable<DifferentialDriveWheelAccelerations>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Acceleration of the left side of the robot in meters per second squared. */
|
||||
public double left;
|
||||
|
||||
/** Acceleration of the right side of the robot in meters per second squared. */
|
||||
public double right;
|
||||
|
||||
/** DifferentialDriveWheelAccelerations protobuf for serialization. */
|
||||
public static final DifferentialDriveWheelAccelerationsProto proto =
|
||||
new DifferentialDriveWheelAccelerationsProto();
|
||||
|
||||
/** DifferentialDriveWheelAccelerations struct for serialization. */
|
||||
public static final DifferentialDriveWheelAccelerationsStruct struct =
|
||||
new DifferentialDriveWheelAccelerationsStruct();
|
||||
|
||||
/**
|
||||
* Constructs a DifferentialDriveWheelAccelerations with zeros for left and right accelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations() {}
|
||||
|
||||
/**
|
||||
* Constructs a DifferentialDriveWheelAccelerations.
|
||||
*
|
||||
* @param left The left acceleration in meters per second squared.
|
||||
* @param right The right acceleration in meters per second squared.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations(double left, double right) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a DifferentialDriveWheelAccelerations.
|
||||
*
|
||||
* @param left The left acceleration in meters per second squared.
|
||||
* @param right The right acceleration in meters per second squared.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations(LinearAcceleration left, LinearAcceleration right) {
|
||||
this(left.in(MetersPerSecondPerSecond), right.in(MetersPerSecondPerSecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two DifferentialDriveWheelAccelerations and returns the sum.
|
||||
*
|
||||
* <p>For example, DifferentialDriveWheelAccelerations{1.0, 0.5} +
|
||||
* DifferentialDriveWheelAccelerations{2.0, 1.5} = DifferentialDriveWheelAccelerations{3.0, 2.0}
|
||||
*
|
||||
* @param other The DifferentialDriveWheelAccelerations to add.
|
||||
* @return The sum of the DifferentialDriveWheelAccelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations plus(DifferentialDriveWheelAccelerations other) {
|
||||
return new DifferentialDriveWheelAccelerations(left + other.left, right + other.right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the other DifferentialDriveWheelAccelerations from the current
|
||||
* DifferentialDriveWheelAccelerations and returns the difference.
|
||||
*
|
||||
* <p>For example, DifferentialDriveWheelAccelerations{5.0, 4.0} -
|
||||
* DifferentialDriveWheelAccelerations{1.0, 2.0} = DifferentialDriveWheelAccelerations{4.0, 2.0}
|
||||
*
|
||||
* @param other The DifferentialDriveWheelAccelerations to subtract.
|
||||
* @return The difference between the two DifferentialDriveWheelAccelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations minus(DifferentialDriveWheelAccelerations other) {
|
||||
return new DifferentialDriveWheelAccelerations(left - other.left, right - other.right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of the current DifferentialDriveWheelAccelerations. This is equivalent to
|
||||
* negating all components of the DifferentialDriveWheelAccelerations.
|
||||
*
|
||||
* @return The inverse of the current DifferentialDriveWheelAccelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations unaryMinus() {
|
||||
return new DifferentialDriveWheelAccelerations(-left, -right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the DifferentialDriveWheelAccelerations by a scalar and returns the new
|
||||
* DifferentialDriveWheelAccelerations.
|
||||
*
|
||||
* <p>For example, DifferentialDriveWheelAccelerations{2.0, 2.5} * 2 =
|
||||
* DifferentialDriveWheelAccelerations{4.0, 5.0}
|
||||
*
|
||||
* @param scalar The scalar to multiply by.
|
||||
* @return The scaled DifferentialDriveWheelAccelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations times(double scalar) {
|
||||
return new DifferentialDriveWheelAccelerations(left * scalar, right * scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the DifferentialDriveWheelAccelerations by a scalar and returns the new
|
||||
* DifferentialDriveWheelAccelerations.
|
||||
*
|
||||
* <p>For example, DifferentialDriveWheelAccelerations{2.0, 2.5} / 2 =
|
||||
* DifferentialDriveWheelAccelerations{1.0, 1.25}
|
||||
*
|
||||
* @param scalar The scalar to divide by.
|
||||
* @return The scaled DifferentialDriveWheelAccelerations.
|
||||
*/
|
||||
public DifferentialDriveWheelAccelerations div(double scalar) {
|
||||
return new DifferentialDriveWheelAccelerations(left / scalar, right / scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this DifferentialDriveWheelAccelerations and another.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public DifferentialDriveWheelAccelerations interpolate(
|
||||
DifferentialDriveWheelAccelerations endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
return new DifferentialDriveWheelAccelerations(
|
||||
left + t * (endValue.left - left), right + t * (endValue.right - right));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"DifferentialDriveWheelAccelerations(Left: %.2f m/s², Right: %.2f m/s²)", left, right);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecond;
|
||||
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.DifferentialDriveWheelSpeedsProto;
|
||||
import org.wpilib.math.kinematics.struct.DifferentialDriveWheelSpeedsStruct;
|
||||
import org.wpilib.units.measure.LinearVelocity;
|
||||
@@ -13,7 +14,10 @@ import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the wheel speeds for a differential drive drivetrain. */
|
||||
public class DifferentialDriveWheelSpeeds implements ProtobufSerializable, StructSerializable {
|
||||
public class DifferentialDriveWheelSpeeds
|
||||
implements Interpolatable<DifferentialDriveWheelSpeeds>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Speed of the left side of the robot in meters per second. */
|
||||
public double left;
|
||||
|
||||
@@ -150,6 +154,22 @@ public class DifferentialDriveWheelSpeeds implements ProtobufSerializable, Struc
|
||||
return new DifferentialDriveWheelSpeeds(left / scalar, right / scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this DifferentialDriveWheelSpeeds and another.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public DifferentialDriveWheelSpeeds interpolate(DifferentialDriveWheelSpeeds endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
return new DifferentialDriveWheelSpeeds(
|
||||
left + t * (endValue.left - left), right + t * (endValue.right - right));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -8,14 +8,15 @@ import org.wpilib.math.geometry.Twist2d;
|
||||
import org.wpilib.math.interpolation.Interpolator;
|
||||
|
||||
/**
|
||||
* Helper class that converts a chassis velocity (dx and dtheta components) into wheel speeds. Robot
|
||||
* code should not use this directly- Instead, use the particular type for your drivetrain (e.g.,
|
||||
* {@link DifferentialDriveKinematics}).
|
||||
* Helper class that converts a chassis velocity (dx and dtheta components) into wheel speeds and
|
||||
* chassis accelerations into wheel accelerations. Robot code should not use this directly- Instead,
|
||||
* use the particular type for your drivetrain (e.g., {@link DifferentialDriveKinematics}).
|
||||
*
|
||||
* @param <S> The type of the wheel speeds.
|
||||
* @param <P> The type of the wheel positions.
|
||||
* @param <S> The type of the wheel speeds.
|
||||
* @param <A> The type of the wheel accelerations.
|
||||
*/
|
||||
public interface Kinematics<S, P> extends Interpolator<P> {
|
||||
public interface Kinematics<P, S, A> extends Interpolator<P> {
|
||||
/**
|
||||
* Performs forward kinematics to return the resulting chassis speed from the wheel speeds. This
|
||||
* method is often used for odometry -- determining the robot's position on the field using data
|
||||
@@ -35,6 +36,27 @@ public interface Kinematics<S, P> extends Interpolator<P> {
|
||||
*/
|
||||
S toWheelSpeeds(ChassisSpeeds chassisSpeeds);
|
||||
|
||||
/**
|
||||
* Performs forward kinematics to return the resulting chassis accelerations from the wheel
|
||||
* accelerations. This method is often used for dynamics calculations -- determining the robot's
|
||||
* acceleration on the field using data from the real-world acceleration of each wheel on the
|
||||
* robot.
|
||||
*
|
||||
* @param wheelAccelerations The accelerations of the wheels.
|
||||
* @return The chassis accelerations.
|
||||
*/
|
||||
ChassisAccelerations toChassisAccelerations(A wheelAccelerations);
|
||||
|
||||
/**
|
||||
* Performs inverse kinematics to return the wheel accelerations from a desired chassis
|
||||
* acceleration. This method is often used for dynamics calculations -- converting desired robot
|
||||
* accelerations into individual wheel accelerations.
|
||||
*
|
||||
* @param chassisAccelerations The desired chassis accelerations.
|
||||
* @return The wheel accelerations.
|
||||
*/
|
||||
A toWheelAccelerations(ChassisAccelerations chassisAccelerations);
|
||||
|
||||
/**
|
||||
* Performs forward kinematics to return the resulting Twist2d from the given change in wheel
|
||||
* positions. This method is often used for odometry -- determining the robot's position on the
|
||||
|
||||
@@ -34,7 +34,8 @@ import org.wpilib.util.struct.StructSerializable;
|
||||
* field using encoders and a gyro.
|
||||
*/
|
||||
public class MecanumDriveKinematics
|
||||
implements Kinematics<MecanumDriveWheelSpeeds, MecanumDriveWheelPositions>,
|
||||
implements Kinematics<
|
||||
MecanumDriveWheelPositions, MecanumDriveWheelSpeeds, MecanumDriveWheelAccelerations>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
private final SimpleMatrix m_inverseKinematics;
|
||||
@@ -162,6 +163,88 @@ public class MecanumDriveKinematics
|
||||
chassisSpeedsVector.get(2, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs inverse kinematics to return the wheel accelerations from a desired chassis
|
||||
* acceleration. This method is often used for dynamics calculations -- converting desired robot
|
||||
* accelerations into individual wheel accelerations.
|
||||
*
|
||||
* <p>This function also supports variable centers of rotation. During normal operations, the
|
||||
* center of rotation is usually the same as the physical center of the robot; therefore, the
|
||||
* argument is defaulted to that use case. However, if you wish to change the center of rotation
|
||||
* for evasive maneuvers, vision alignment, or for any other use case, you can do so.
|
||||
*
|
||||
* @param chassisAccelerations The desired chassis accelerations.
|
||||
* @param centerOfRotation The center of rotation. For example, if you set the center of rotation
|
||||
* at one corner of the robot and provide a chassis acceleration that only has a dtheta
|
||||
* component, the robot will rotate around that corner.
|
||||
* @return The wheel accelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations toWheelAccelerations(
|
||||
ChassisAccelerations chassisAccelerations, Translation2d centerOfRotation) {
|
||||
// We have a new center of rotation. We need to compute the matrix again.
|
||||
if (!centerOfRotation.equals(m_prevCoR)) {
|
||||
var fl = m_frontLeftWheel.minus(centerOfRotation);
|
||||
var fr = m_frontRightWheel.minus(centerOfRotation);
|
||||
var rl = m_rearLeftWheel.minus(centerOfRotation);
|
||||
var rr = m_rearRightWheel.minus(centerOfRotation);
|
||||
|
||||
setInverseKinematics(fl, fr, rl, rr);
|
||||
m_prevCoR = centerOfRotation;
|
||||
}
|
||||
|
||||
var chassisAccelerationsVector = new SimpleMatrix(3, 1);
|
||||
chassisAccelerationsVector.setColumn(
|
||||
0, 0, chassisAccelerations.ax, chassisAccelerations.ay, chassisAccelerations.alpha);
|
||||
|
||||
var wheelsVector = m_inverseKinematics.mult(chassisAccelerationsVector);
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
wheelsVector.get(0, 0),
|
||||
wheelsVector.get(1, 0),
|
||||
wheelsVector.get(2, 0),
|
||||
wheelsVector.get(3, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs inverse kinematics. See {@link #toWheelAccelerations(ChassisAccelerations,
|
||||
* Translation2d)} for more information.
|
||||
*
|
||||
* @param chassisAccelerations The desired chassis accelerations.
|
||||
* @return The wheel accelerations.
|
||||
*/
|
||||
@Override
|
||||
public MecanumDriveWheelAccelerations toWheelAccelerations(
|
||||
ChassisAccelerations chassisAccelerations) {
|
||||
return toWheelAccelerations(chassisAccelerations, Translation2d.kZero);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs forward kinematics to return the resulting chassis accelerations from the given wheel
|
||||
* accelerations. This method is often used for dynamics calculations -- determining the robot's
|
||||
* acceleration on the field using data from the real-world acceleration of each wheel on the
|
||||
* robot.
|
||||
*
|
||||
* @param wheelAccelerations The current mecanum drive wheel accelerations.
|
||||
* @return The resulting chassis accelerations.
|
||||
*/
|
||||
@Override
|
||||
public ChassisAccelerations toChassisAccelerations(
|
||||
MecanumDriveWheelAccelerations wheelAccelerations) {
|
||||
var wheelAccelerationsVector = new SimpleMatrix(4, 1);
|
||||
wheelAccelerationsVector.setColumn(
|
||||
0,
|
||||
0,
|
||||
wheelAccelerations.frontLeft,
|
||||
wheelAccelerations.frontRight,
|
||||
wheelAccelerations.rearLeft,
|
||||
wheelAccelerations.rearRight);
|
||||
var chassisAccelerationsVector = m_forwardKinematics.mult(wheelAccelerationsVector);
|
||||
|
||||
return new ChassisAccelerations(
|
||||
chassisAccelerationsVector.get(0, 0),
|
||||
chassisAccelerationsVector.get(1, 0),
|
||||
chassisAccelerationsVector.get(2, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Twist2d toTwist2d(MecanumDriveWheelPositions start, MecanumDriveWheelPositions end) {
|
||||
var wheelDeltasVector = new SimpleMatrix(4, 1);
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// 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 org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecondPerSecond;
|
||||
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.MecanumDriveWheelAccelerationsProto;
|
||||
import org.wpilib.math.kinematics.struct.MecanumDriveWheelAccelerationsStruct;
|
||||
import org.wpilib.units.measure.LinearAcceleration;
|
||||
import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the wheel accelerations for a mecanum drive drivetrain. */
|
||||
public class MecanumDriveWheelAccelerations
|
||||
implements Interpolatable<MecanumDriveWheelAccelerations>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Acceleration of the front left wheel in meters per second squared. */
|
||||
public double frontLeft;
|
||||
|
||||
/** Acceleration of the front right wheel in meters per second squared. */
|
||||
public double frontRight;
|
||||
|
||||
/** Acceleration of the rear left wheel in meters per second squared. */
|
||||
public double rearLeft;
|
||||
|
||||
/** Acceleration of the rear right wheel in meters per second squared. */
|
||||
public double rearRight;
|
||||
|
||||
/** MecanumDriveWheelAccelerations protobuf for serialization. */
|
||||
public static final MecanumDriveWheelAccelerationsProto proto =
|
||||
new MecanumDriveWheelAccelerationsProto();
|
||||
|
||||
/** MecanumDriveWheelAccelerations struct for serialization. */
|
||||
public static final MecanumDriveWheelAccelerationsStruct struct =
|
||||
new MecanumDriveWheelAccelerationsStruct();
|
||||
|
||||
/** Constructs a MecanumDriveWheelAccelerations with zeros for all member fields. */
|
||||
public MecanumDriveWheelAccelerations() {}
|
||||
|
||||
/**
|
||||
* Constructs a MecanumDriveWheelAccelerations.
|
||||
*
|
||||
* @param frontLeft Acceleration of the front left wheel in meters per second squared.
|
||||
* @param frontRight Acceleration of the front right wheel in meters per second squared.
|
||||
* @param rearLeft Acceleration of the rear left wheel in meters per second squared.
|
||||
* @param rearRight Acceleration of the rear right wheel in meters per second squared.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations(
|
||||
double frontLeft, double frontRight, double rearLeft, double rearRight) {
|
||||
this.frontLeft = frontLeft;
|
||||
this.frontRight = frontRight;
|
||||
this.rearLeft = rearLeft;
|
||||
this.rearRight = rearRight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MecanumDriveWheelAccelerations.
|
||||
*
|
||||
* @param frontLeft Acceleration of the front left wheel in meters per second squared.
|
||||
* @param frontRight Acceleration of the front right wheel in meters per second squared.
|
||||
* @param rearLeft Acceleration of the rear left wheel in meters per second squared.
|
||||
* @param rearRight Acceleration of the rear right wheel in meters per second squared.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations(
|
||||
LinearAcceleration frontLeft,
|
||||
LinearAcceleration frontRight,
|
||||
LinearAcceleration rearLeft,
|
||||
LinearAcceleration rearRight) {
|
||||
this(
|
||||
frontLeft.in(MetersPerSecondPerSecond),
|
||||
frontRight.in(MetersPerSecondPerSecond),
|
||||
rearLeft.in(MetersPerSecondPerSecond),
|
||||
rearRight.in(MetersPerSecondPerSecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two MecanumDriveWheelAccelerations and returns the sum.
|
||||
*
|
||||
* <p>For example, MecanumDriveWheelAccelerations{1.0, 0.5, 2.0, 1.5} +
|
||||
* MecanumDriveWheelAccelerations{2.0, 1.5, 0.5, 1.0} = MecanumDriveWheelAccelerations{3.0, 2.0,
|
||||
* 2.5, 2.5}
|
||||
*
|
||||
* @param other The MecanumDriveWheelAccelerations to add.
|
||||
* @return The sum of the MecanumDriveWheelAccelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations plus(MecanumDriveWheelAccelerations other) {
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
frontLeft + other.frontLeft,
|
||||
frontRight + other.frontRight,
|
||||
rearLeft + other.rearLeft,
|
||||
rearRight + other.rearRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the other MecanumDriveWheelAccelerations from the current
|
||||
* MecanumDriveWheelAccelerations and returns the difference.
|
||||
*
|
||||
* <p>For example, MecanumDriveWheelAccelerations{5.0, 4.0, 6.0, 2.5} -
|
||||
* MecanumDriveWheelAccelerations{1.0, 2.0, 3.0, 0.5} = MecanumDriveWheelAccelerations{4.0, 2.0,
|
||||
* 3.0, 2.0}
|
||||
*
|
||||
* @param other The MecanumDriveWheelAccelerations to subtract.
|
||||
* @return The difference between the two MecanumDriveWheelAccelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations minus(MecanumDriveWheelAccelerations other) {
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
frontLeft - other.frontLeft,
|
||||
frontRight - other.frontRight,
|
||||
rearLeft - other.rearLeft,
|
||||
rearRight - other.rearRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of the current MecanumDriveWheelAccelerations. This is equivalent to
|
||||
* negating all components of the MecanumDriveWheelAccelerations.
|
||||
*
|
||||
* @return The inverse of the current MecanumDriveWheelAccelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations unaryMinus() {
|
||||
return new MecanumDriveWheelAccelerations(-frontLeft, -frontRight, -rearLeft, -rearRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the MecanumDriveWheelAccelerations by a scalar and returns the new
|
||||
* MecanumDriveWheelAccelerations.
|
||||
*
|
||||
* <p>For example, MecanumDriveWheelAccelerations{2.0, 2.5, 3.0, 3.5} * 2 =
|
||||
* MecanumDriveWheelAccelerations{4.0, 5.0, 6.0, 7.0}
|
||||
*
|
||||
* @param scalar The scalar to multiply by.
|
||||
* @return The scaled MecanumDriveWheelAccelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations times(double scalar) {
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
frontLeft * scalar, frontRight * scalar, rearLeft * scalar, rearRight * scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the MecanumDriveWheelAccelerations by a scalar and returns the new
|
||||
* MecanumDriveWheelAccelerations.
|
||||
*
|
||||
* <p>For example, MecanumDriveWheelAccelerations{2.0, 2.5, 1.5, 1.0} / 2 =
|
||||
* MecanumDriveWheelAccelerations{1.0, 1.25, 0.75, 0.5}
|
||||
*
|
||||
* @param scalar The scalar to divide by.
|
||||
* @return The scaled MecanumDriveWheelAccelerations.
|
||||
*/
|
||||
public MecanumDriveWheelAccelerations div(double scalar) {
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
frontLeft / scalar, frontRight / scalar, rearLeft / scalar, rearRight / scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this MecanumDriveWheelAccelerations and another.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public MecanumDriveWheelAccelerations interpolate(
|
||||
MecanumDriveWheelAccelerations endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
frontLeft + t * (endValue.frontLeft - frontLeft),
|
||||
frontRight + t * (endValue.frontRight - frontRight),
|
||||
rearLeft + t * (endValue.rearLeft - rearLeft),
|
||||
rearRight + t * (endValue.rearRight - rearRight));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"MecanumDriveWheelAccelerations(Front Left: %.2f m/s², Front Right: %.2f m/s², "
|
||||
+ "Rear Left: %.2f m/s², Rear Right: %.2f m/s²)",
|
||||
frontLeft, frontRight, rearLeft, rearRight);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecond;
|
||||
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.MecanumDriveWheelSpeedsProto;
|
||||
import org.wpilib.math.kinematics.struct.MecanumDriveWheelSpeedsStruct;
|
||||
import org.wpilib.units.measure.LinearVelocity;
|
||||
@@ -13,7 +14,8 @@ import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the wheel speeds for a mecanum drive drivetrain. */
|
||||
public class MecanumDriveWheelSpeeds implements ProtobufSerializable, StructSerializable {
|
||||
public class MecanumDriveWheelSpeeds
|
||||
implements Interpolatable<MecanumDriveWheelSpeeds>, ProtobufSerializable, StructSerializable {
|
||||
/** Speed of the front left wheel in meters per second. */
|
||||
public double frontLeft;
|
||||
|
||||
@@ -186,6 +188,25 @@ public class MecanumDriveWheelSpeeds implements ProtobufSerializable, StructSeri
|
||||
frontLeft / scalar, frontRight / scalar, rearLeft / scalar, rearRight / scalar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this MecanumDriveWheelSpeeds and another.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public MecanumDriveWheelSpeeds interpolate(MecanumDriveWheelSpeeds endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
return new MecanumDriveWheelSpeeds(
|
||||
frontLeft + t * (endValue.frontLeft - frontLeft),
|
||||
frontRight + t * (endValue.frontRight - frontRight),
|
||||
rearLeft + t * (endValue.rearLeft - rearLeft),
|
||||
rearRight + t * (endValue.rearRight - rearRight));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.wpilib.math.geometry.Translation2d;
|
||||
* @param <T> Wheel positions type.
|
||||
*/
|
||||
public class Odometry<T> {
|
||||
private final Kinematics<?, T> m_kinematics;
|
||||
private final Kinematics<T, ?, ?> m_kinematics;
|
||||
private Pose2d m_pose;
|
||||
|
||||
private Rotation2d m_gyroOffset;
|
||||
@@ -36,7 +36,7 @@ public class Odometry<T> {
|
||||
* @param initialPose The starting position of the robot on the field.
|
||||
*/
|
||||
public Odometry(
|
||||
Kinematics<?, T> kinematics, Rotation2d gyroAngle, T wheelPositions, Pose2d initialPose) {
|
||||
Kinematics<T, ?, ?> kinematics, Rotation2d gyroAngle, T wheelPositions, Pose2d initialPose) {
|
||||
m_kinematics = kinematics;
|
||||
m_pose = initialPose;
|
||||
m_gyroOffset = m_pose.getRotation().minus(gyroAngle);
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.wpilib.math.geometry.Twist3d;
|
||||
* @param <T> Wheel positions type.
|
||||
*/
|
||||
public class Odometry3d<T> {
|
||||
private final Kinematics<?, T> m_kinematics;
|
||||
private final Kinematics<T, ?, ?> m_kinematics;
|
||||
private Pose3d m_pose;
|
||||
|
||||
private Rotation3d m_gyroOffset;
|
||||
@@ -45,7 +45,7 @@ public class Odometry3d<T> {
|
||||
* @param initialPose The starting position of the robot on the field.
|
||||
*/
|
||||
public Odometry3d(
|
||||
Kinematics<?, T> kinematics, Rotation3d gyroAngle, T wheelPositions, Pose3d initialPose) {
|
||||
Kinematics<T, ?, ?> kinematics, Rotation3d gyroAngle, T wheelPositions, Pose3d initialPose) {
|
||||
m_kinematics = kinematics;
|
||||
m_pose = initialPose;
|
||||
m_gyroOffset = m_pose.getRotation().minus(gyroAngle);
|
||||
|
||||
@@ -43,11 +43,13 @@ import org.wpilib.util.struct.StructSerializable;
|
||||
*/
|
||||
@SuppressWarnings("overrides")
|
||||
public class SwerveDriveKinematics
|
||||
implements Kinematics<SwerveModuleState[], SwerveModulePosition[]>,
|
||||
implements Kinematics<SwerveModulePosition[], SwerveModuleState[], SwerveModuleAcceleration[]>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
private final SimpleMatrix m_inverseKinematics;
|
||||
private final SimpleMatrix m_forwardKinematics;
|
||||
private final SimpleMatrix m_firstOrderInverseKinematics;
|
||||
private final SimpleMatrix m_firstOrderForwardKinematics;
|
||||
private final SimpleMatrix m_secondOrderInverseKinematics;
|
||||
private final SimpleMatrix m_secondOrderForwardKinematics;
|
||||
|
||||
private final int m_numModules;
|
||||
private final Translation2d[] m_modules;
|
||||
@@ -72,13 +74,13 @@ public class SwerveDriveKinematics
|
||||
m_modules = Arrays.copyOf(moduleTranslations, m_numModules);
|
||||
m_moduleHeadings = new Rotation2d[m_numModules];
|
||||
Arrays.fill(m_moduleHeadings, Rotation2d.kZero);
|
||||
m_inverseKinematics = new SimpleMatrix(m_numModules * 2, 3);
|
||||
m_firstOrderInverseKinematics = new SimpleMatrix(m_numModules * 2, 3);
|
||||
m_secondOrderInverseKinematics = new SimpleMatrix(m_numModules * 2, 4);
|
||||
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
m_inverseKinematics.setRow(i * 2 + 0, 0, /* Start Data */ 1, 0, -m_modules[i].getY());
|
||||
m_inverseKinematics.setRow(i * 2 + 1, 0, /* Start Data */ 0, 1, +m_modules[i].getX());
|
||||
}
|
||||
m_forwardKinematics = m_inverseKinematics.pseudoInverse();
|
||||
setInverseKinematics(Translation2d.kZero);
|
||||
|
||||
m_firstOrderForwardKinematics = m_firstOrderInverseKinematics.pseudoInverse();
|
||||
m_secondOrderForwardKinematics = m_secondOrderInverseKinematics.pseudoInverse();
|
||||
|
||||
MathSharedStore.reportUsage("SwerveDriveKinematics", "");
|
||||
}
|
||||
@@ -132,19 +134,13 @@ public class SwerveDriveKinematics
|
||||
}
|
||||
|
||||
if (!centerOfRotation.equals(m_prevCoR)) {
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
m_inverseKinematics.setRow(
|
||||
i * 2 + 0, 0, /* Start Data */ 1, 0, -m_modules[i].getY() + centerOfRotation.getY());
|
||||
m_inverseKinematics.setRow(
|
||||
i * 2 + 1, 0, /* Start Data */ 0, 1, +m_modules[i].getX() - centerOfRotation.getX());
|
||||
}
|
||||
m_prevCoR = centerOfRotation;
|
||||
setInverseKinematics(centerOfRotation);
|
||||
}
|
||||
|
||||
var chassisSpeedsVector = new SimpleMatrix(3, 1);
|
||||
chassisSpeedsVector.setColumn(0, 0, chassisSpeeds.vx, chassisSpeeds.vy, chassisSpeeds.omega);
|
||||
|
||||
var moduleStatesMatrix = m_inverseKinematics.mult(chassisSpeedsVector);
|
||||
var moduleStatesMatrix = m_firstOrderInverseKinematics.mult(chassisSpeedsVector);
|
||||
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
double x = moduleStatesMatrix.get(i * 2, 0);
|
||||
@@ -201,7 +197,7 @@ public class SwerveDriveKinematics
|
||||
moduleStatesMatrix.set(i * 2 + 1, module.speed * module.angle.getSin());
|
||||
}
|
||||
|
||||
var chassisSpeedsVector = m_forwardKinematics.mult(moduleStatesMatrix);
|
||||
var chassisSpeedsVector = m_firstOrderForwardKinematics.mult(moduleStatesMatrix);
|
||||
return new ChassisSpeeds(
|
||||
chassisSpeedsVector.get(0, 0),
|
||||
chassisSpeedsVector.get(1, 0),
|
||||
@@ -229,10 +225,10 @@ public class SwerveDriveKinematics
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
var module = moduleDeltas[i];
|
||||
moduleDeltaMatrix.set(i * 2, 0, module.distance * module.angle.getCos());
|
||||
moduleDeltaMatrix.set(i * 2 + 1, module.distance * module.angle.getSin());
|
||||
moduleDeltaMatrix.set(i * 2 + 1, 0, module.distance * module.angle.getSin());
|
||||
}
|
||||
|
||||
var chassisDeltaVector = m_forwardKinematics.mult(moduleDeltaMatrix);
|
||||
var chassisDeltaVector = m_firstOrderForwardKinematics.mult(moduleDeltaMatrix);
|
||||
return new Twist2d(
|
||||
chassisDeltaVector.get(0, 0), chassisDeltaVector.get(1, 0), chassisDeltaVector.get(2, 0));
|
||||
}
|
||||
@@ -441,4 +437,155 @@ public class SwerveDriveKinematics
|
||||
public static final SwerveDriveKinematicsStruct getStruct(int numModules) {
|
||||
return new SwerveDriveKinematicsStruct(numModules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs inverse kinematics to return the module accelerations from a desired chassis
|
||||
* acceleration. This method is often used for dynamics calculations -- converting desired robot
|
||||
* accelerations into individual module accelerations.
|
||||
*
|
||||
* <p>This function also supports variable centers of rotation. During normal operations, the
|
||||
* center of rotation is usually the same as the physical center of the robot; therefore, the
|
||||
* argument is defaulted to that use case. However, if you wish to change the center of rotation
|
||||
* for evasive maneuvers, vision alignment, or for any other use case, you can do so.
|
||||
*
|
||||
* @param chassisAccelerations The desired chassis accelerations.
|
||||
* @param angularVelocity The desired robot angular velocity.
|
||||
* @param centerOfRotation The center of rotation. For example, if you set the center of rotation
|
||||
* at one corner of the robot and provide a chassis acceleration that only has a dtheta
|
||||
* component, the robot will rotate around that corner.
|
||||
* @return An array containing the module accelerations.
|
||||
*/
|
||||
public SwerveModuleAcceleration[] toSwerveModuleAccelerations(
|
||||
ChassisAccelerations chassisAccelerations,
|
||||
double angularVelocity,
|
||||
Translation2d centerOfRotation) {
|
||||
// Derivation for second-order kinematics from "Swerve Drive Second Order Kinematics"
|
||||
// by FRC Team 449 - The Blair Robot Project, Rafi Pedersen
|
||||
// https://www.chiefdelphi.com/uploads/short-url/qzj4k2LyBs7rLxAem0YajNIlStH.pdf
|
||||
|
||||
var moduleAccelerations = new SwerveModuleAcceleration[m_numModules];
|
||||
|
||||
if (chassisAccelerations.ax == 0.0
|
||||
&& chassisAccelerations.ay == 0.0
|
||||
&& chassisAccelerations.alpha == 0.0) {
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
moduleAccelerations[i] = new SwerveModuleAcceleration(0.0, Rotation2d.kZero);
|
||||
}
|
||||
return moduleAccelerations;
|
||||
}
|
||||
|
||||
if (!centerOfRotation.equals(m_prevCoR)) {
|
||||
setInverseKinematics(centerOfRotation);
|
||||
}
|
||||
|
||||
var chassisAccelerationsVector = new SimpleMatrix(4, 1);
|
||||
chassisAccelerationsVector.setColumn(
|
||||
0,
|
||||
0,
|
||||
chassisAccelerations.ax,
|
||||
chassisAccelerations.ay,
|
||||
angularVelocity * angularVelocity,
|
||||
chassisAccelerations.alpha);
|
||||
|
||||
var moduleAccelerationsMatrix = m_secondOrderInverseKinematics.mult(chassisAccelerationsVector);
|
||||
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
double x = moduleAccelerationsMatrix.get(i * 2, 0);
|
||||
double y = moduleAccelerationsMatrix.get(i * 2 + 1, 0);
|
||||
|
||||
// For swerve modules, we need to compute both linear acceleration and angular acceleration
|
||||
// The linear acceleration is the magnitude of the acceleration vector
|
||||
double linearAcceleration = Math.hypot(x, y);
|
||||
|
||||
if (linearAcceleration <= 1e-6) {
|
||||
moduleAccelerations[i] = new SwerveModuleAcceleration(linearAcceleration, Rotation2d.kZero);
|
||||
} else {
|
||||
moduleAccelerations[i] =
|
||||
new SwerveModuleAcceleration(linearAcceleration, new Rotation2d(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
return moduleAccelerations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs inverse kinematics. See {@link #toSwerveModuleAccelerations(ChassisAccelerations,
|
||||
* double, Translation2d)} toSwerveModuleAccelerations for more information.
|
||||
*
|
||||
* @param chassisAccelerations The desired chassis accelerations.
|
||||
* @param angularVelocity The desired robot angular velocity.
|
||||
* @return An array containing the module accelerations.
|
||||
*/
|
||||
public SwerveModuleAcceleration[] toSwerveModuleAccelerations(
|
||||
ChassisAccelerations chassisAccelerations, double angularVelocity) {
|
||||
return toSwerveModuleAccelerations(chassisAccelerations, angularVelocity, Translation2d.kZero);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwerveModuleAcceleration[] toWheelAccelerations(
|
||||
ChassisAccelerations chassisAccelerations) {
|
||||
return toSwerveModuleAccelerations(chassisAccelerations, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs forward kinematics to return the resulting chassis accelerations from the given module
|
||||
* accelerations. This method is often used for dynamics calculations -- determining the robot's
|
||||
* acceleration on the field using data from the real-world acceleration of each module on the
|
||||
* robot.
|
||||
*
|
||||
* @param moduleAccelerations The accelerations of the modules as measured from respective
|
||||
* encoders and gyros. The order of the swerve module accelerations should be same as passed
|
||||
* into the constructor of this class.
|
||||
* @return The resulting chassis accelerations.
|
||||
*/
|
||||
@Override
|
||||
public ChassisAccelerations toChassisAccelerations(
|
||||
SwerveModuleAcceleration... moduleAccelerations) {
|
||||
// Derivation for second-order kinematics from "Swerve Drive Second Order Kinematics"
|
||||
// by FRC Team 449 - The Blair Robot Project, Rafi Pedersen
|
||||
// https://www.chiefdelphi.com/uploads/short-url/qzj4k2LyBs7rLxAem0YajNIlStH.pdf
|
||||
|
||||
if (moduleAccelerations.length != m_numModules) {
|
||||
throw new IllegalArgumentException(
|
||||
"Number of modules is not consistent with number of module locations provided in "
|
||||
+ "constructor");
|
||||
}
|
||||
var moduleAccelerationsMatrix = new SimpleMatrix(m_numModules * 2, 1);
|
||||
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
var module = moduleAccelerations[i];
|
||||
|
||||
moduleAccelerationsMatrix.set(i * 2 + 0, 0, module.acceleration * module.angle.getCos());
|
||||
moduleAccelerationsMatrix.set(i * 2 + 1, 0, module.acceleration * module.angle.getSin());
|
||||
}
|
||||
|
||||
var chassisAccelerationsVector = m_secondOrderForwardKinematics.mult(moduleAccelerationsMatrix);
|
||||
|
||||
// the second order kinematics equation for swerve drive yields a state vector [aₓ, a_y, ω², α]
|
||||
return new ChassisAccelerations(
|
||||
chassisAccelerationsVector.get(0, 0),
|
||||
chassisAccelerationsVector.get(1, 0),
|
||||
chassisAccelerationsVector.get(3, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both inverse kinematics matrices based on the new center of rotation. This does not check
|
||||
* if the new center of rotation is different from the previous one, so a check should be included
|
||||
* before the call to this function.
|
||||
*
|
||||
* @param centerOfRotation new center of rotation
|
||||
*/
|
||||
private void setInverseKinematics(Translation2d centerOfRotation) {
|
||||
for (int i = 0; i < m_numModules; i++) {
|
||||
var rx = m_modules[i].getX() - centerOfRotation.getX();
|
||||
var ry = m_modules[i].getY() - centerOfRotation.getY();
|
||||
|
||||
m_firstOrderInverseKinematics.setRow(i * 2 + 0, 0, /* Start Data */ 1, 0, -ry);
|
||||
m_firstOrderInverseKinematics.setRow(i * 2 + 1, 0, /* Start Data */ 0, 1, rx);
|
||||
|
||||
m_secondOrderInverseKinematics.setRow(i * 2 + 0, 0, /* Start Data */ 1, 0, -rx, -ry);
|
||||
m_secondOrderInverseKinematics.setRow(i * 2 + 1, 0, /* Start Data */ 0, 1, -ry, +rx);
|
||||
}
|
||||
m_prevCoR = centerOfRotation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 org.wpilib.math.kinematics;
|
||||
|
||||
import static org.wpilib.units.Units.MetersPerSecondPerSecond;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.SwerveModuleAccelerationProto;
|
||||
import org.wpilib.math.kinematics.struct.SwerveModuleAccelerationStruct;
|
||||
import org.wpilib.units.measure.LinearAcceleration;
|
||||
import org.wpilib.util.protobuf.ProtobufSerializable;
|
||||
import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the accelerations of one swerve module. */
|
||||
public class SwerveModuleAcceleration
|
||||
implements Interpolatable<SwerveModuleAcceleration>,
|
||||
Comparable<SwerveModuleAcceleration>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Acceleration of the wheel of the module in meters per second squared. */
|
||||
public double acceleration;
|
||||
|
||||
/** Angle of the acceleration vector. */
|
||||
public Rotation2d angle = new Rotation2d();
|
||||
|
||||
/** SwerveModuleAccelerations protobuf for serialization. */
|
||||
public static final SwerveModuleAccelerationProto proto = new SwerveModuleAccelerationProto();
|
||||
|
||||
/** SwerveModuleAccelerations struct for serialization. */
|
||||
public static final SwerveModuleAccelerationStruct struct = new SwerveModuleAccelerationStruct();
|
||||
|
||||
/** Constructs a SwerveModuleAccelerations with zeros for acceleration and angle. */
|
||||
public SwerveModuleAcceleration() {}
|
||||
|
||||
/**
|
||||
* Constructs a SwerveModuleAccelerations.
|
||||
*
|
||||
* @param acceleration The acceleration of the wheel of the module in meters per second squared.
|
||||
* @param angle The angle of the acceleration vector.
|
||||
*/
|
||||
public SwerveModuleAcceleration(double acceleration, Rotation2d angle) {
|
||||
this.acceleration = acceleration;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SwerveModuleAccelerations.
|
||||
*
|
||||
* @param acceleration The acceleration of the wheel of the module.
|
||||
* @param angle The angle of the acceleration vector.
|
||||
*/
|
||||
public SwerveModuleAcceleration(LinearAcceleration acceleration, Rotation2d angle) {
|
||||
this(acceleration.in(MetersPerSecondPerSecond), angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this SwerveModuleAccelerations and another.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public SwerveModuleAcceleration interpolate(SwerveModuleAcceleration endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
return new SwerveModuleAcceleration(
|
||||
acceleration + t * (endValue.acceleration - acceleration),
|
||||
angle.interpolate(endValue.angle, t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof SwerveModuleAcceleration other
|
||||
&& Math.abs(other.acceleration - acceleration) < 1E-9
|
||||
&& angle.equals(other.angle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(acceleration, angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two swerve module accelerations. One swerve module is "greater" than the other if its
|
||||
* acceleration magnitude is higher than the other.
|
||||
*
|
||||
* @param other The other swerve module.
|
||||
* @return 1 if this is greater, 0 if both are equal, -1 if other is greater.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(SwerveModuleAcceleration other) {
|
||||
return Double.compare(this.acceleration, other.acceleration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"SwerveModuleAccelerations(Acceleration: %.2f m/s², Angle: %s)", acceleration, angle);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import static org.wpilib.units.Units.MetersPerSecond;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.interpolation.Interpolatable;
|
||||
import org.wpilib.math.kinematics.proto.SwerveModuleStateProto;
|
||||
import org.wpilib.math.kinematics.struct.SwerveModuleStateStruct;
|
||||
import org.wpilib.units.measure.LinearVelocity;
|
||||
@@ -16,7 +17,10 @@ import org.wpilib.util.struct.StructSerializable;
|
||||
|
||||
/** Represents the state of one swerve module. */
|
||||
public class SwerveModuleState
|
||||
implements Comparable<SwerveModuleState>, ProtobufSerializable, StructSerializable {
|
||||
implements Interpolatable<SwerveModuleState>,
|
||||
Comparable<SwerveModuleState>,
|
||||
ProtobufSerializable,
|
||||
StructSerializable {
|
||||
/** Speed of the wheel of the module in meters per second. */
|
||||
public double speed;
|
||||
|
||||
@@ -119,6 +123,28 @@ public class SwerveModuleState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linear interpolation of this SwerveModuleState and another. The angle is
|
||||
* interpolated using the shortest path between the two angles.
|
||||
*
|
||||
* @param endValue The end value for the interpolation.
|
||||
* @param t How far between the two values to interpolate. This is clamped to [0, 1].
|
||||
* @return The interpolated value.
|
||||
*/
|
||||
@Override
|
||||
public SwerveModuleState interpolate(SwerveModuleState endValue, double t) {
|
||||
// Clamp t to [0, 1]
|
||||
t = Math.max(0.0, Math.min(1.0, t));
|
||||
|
||||
// Interpolate speed linearly
|
||||
double interpolatedSpeed = speed + t * (endValue.speed - speed);
|
||||
|
||||
// Interpolate angle using the shortest path
|
||||
Rotation2d interpolatedAngle = angle.interpolate(endValue.angle, t);
|
||||
|
||||
return new SwerveModuleState(interpolatedSpeed, interpolatedAngle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales speed by cosine of angle error. This scales down movement perpendicular to the desired
|
||||
* direction of travel that can occur when modules change directions. This results in smoother
|
||||
|
||||
@@ -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 org.wpilib.math.kinematics.proto;
|
||||
|
||||
import org.wpilib.math.kinematics.ChassisAccelerations;
|
||||
import org.wpilib.math.proto.Kinematics.ProtobufChassisAccelerations;
|
||||
import org.wpilib.util.protobuf.Protobuf;
|
||||
import us.hebi.quickbuf.Descriptors.Descriptor;
|
||||
|
||||
public class ChassisAccelerationsProto
|
||||
implements Protobuf<ChassisAccelerations, ProtobufChassisAccelerations> {
|
||||
@Override
|
||||
public Class<ChassisAccelerations> getTypeClass() {
|
||||
return ChassisAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Descriptor getDescriptor() {
|
||||
return ProtobufChassisAccelerations.getDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufChassisAccelerations createMessage() {
|
||||
return ProtobufChassisAccelerations.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChassisAccelerations unpack(ProtobufChassisAccelerations msg) {
|
||||
return new ChassisAccelerations(msg.getAx(), msg.getAy(), msg.getAlpha());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ProtobufChassisAccelerations msg, ChassisAccelerations value) {
|
||||
msg.setAx(value.ax);
|
||||
msg.setAy(value.ay);
|
||||
msg.setAlpha(value.alpha);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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 org.wpilib.math.kinematics.proto;
|
||||
|
||||
import org.wpilib.math.kinematics.DifferentialDriveWheelAccelerations;
|
||||
import org.wpilib.math.proto.Kinematics.ProtobufDifferentialDriveWheelAccelerations;
|
||||
import org.wpilib.util.protobuf.Protobuf;
|
||||
import us.hebi.quickbuf.Descriptors.Descriptor;
|
||||
|
||||
public class DifferentialDriveWheelAccelerationsProto
|
||||
implements Protobuf<
|
||||
DifferentialDriveWheelAccelerations, ProtobufDifferentialDriveWheelAccelerations> {
|
||||
@Override
|
||||
public Class<DifferentialDriveWheelAccelerations> getTypeClass() {
|
||||
return DifferentialDriveWheelAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Descriptor getDescriptor() {
|
||||
return ProtobufDifferentialDriveWheelAccelerations.getDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufDifferentialDriveWheelAccelerations createMessage() {
|
||||
return ProtobufDifferentialDriveWheelAccelerations.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DifferentialDriveWheelAccelerations unpack(
|
||||
ProtobufDifferentialDriveWheelAccelerations msg) {
|
||||
return new DifferentialDriveWheelAccelerations(msg.getLeft(), msg.getRight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(
|
||||
ProtobufDifferentialDriveWheelAccelerations msg, DifferentialDriveWheelAccelerations value) {
|
||||
msg.setLeft(value.left);
|
||||
msg.setRight(value.right);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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 org.wpilib.math.kinematics.proto;
|
||||
|
||||
import org.wpilib.math.kinematics.MecanumDriveWheelAccelerations;
|
||||
import org.wpilib.math.proto.Kinematics.ProtobufMecanumDriveWheelAccelerations;
|
||||
import org.wpilib.util.protobuf.Protobuf;
|
||||
import us.hebi.quickbuf.Descriptors.Descriptor;
|
||||
|
||||
public class MecanumDriveWheelAccelerationsProto
|
||||
implements Protobuf<MecanumDriveWheelAccelerations, ProtobufMecanumDriveWheelAccelerations> {
|
||||
@Override
|
||||
public Class<MecanumDriveWheelAccelerations> getTypeClass() {
|
||||
return MecanumDriveWheelAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Descriptor getDescriptor() {
|
||||
return ProtobufMecanumDriveWheelAccelerations.getDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufMecanumDriveWheelAccelerations createMessage() {
|
||||
return ProtobufMecanumDriveWheelAccelerations.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MecanumDriveWheelAccelerations unpack(ProtobufMecanumDriveWheelAccelerations msg) {
|
||||
return new MecanumDriveWheelAccelerations(
|
||||
msg.getFrontLeft(), msg.getFrontRight(), msg.getRearLeft(), msg.getRearRight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(
|
||||
ProtobufMecanumDriveWheelAccelerations msg, MecanumDriveWheelAccelerations value) {
|
||||
msg.setFrontLeft(value.frontLeft);
|
||||
msg.setFrontRight(value.frontRight);
|
||||
msg.setRearLeft(value.rearLeft);
|
||||
msg.setRearRight(value.rearRight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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 org.wpilib.math.kinematics.proto;
|
||||
|
||||
import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.kinematics.SwerveModuleAcceleration;
|
||||
import org.wpilib.math.proto.Kinematics.ProtobufSwerveModuleAcceleration;
|
||||
import org.wpilib.util.protobuf.Protobuf;
|
||||
import us.hebi.quickbuf.Descriptors.Descriptor;
|
||||
|
||||
public class SwerveModuleAccelerationProto
|
||||
implements Protobuf<SwerveModuleAcceleration, ProtobufSwerveModuleAcceleration> {
|
||||
@Override
|
||||
public Class<SwerveModuleAcceleration> getTypeClass() {
|
||||
return SwerveModuleAcceleration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Descriptor getDescriptor() {
|
||||
return ProtobufSwerveModuleAcceleration.getDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtobufSwerveModuleAcceleration createMessage() {
|
||||
return ProtobufSwerveModuleAcceleration.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwerveModuleAcceleration unpack(ProtobufSwerveModuleAcceleration msg) {
|
||||
return new SwerveModuleAcceleration(
|
||||
msg.getAcceleration(), Rotation2d.proto.unpack(msg.getAngle()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ProtobufSwerveModuleAcceleration msg, SwerveModuleAcceleration value) {
|
||||
msg.setAcceleration(value.acceleration);
|
||||
Rotation2d.proto.pack(msg.getMutableAngle(), value.angle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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 org.wpilib.math.kinematics.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.wpilib.math.kinematics.ChassisAccelerations;
|
||||
import org.wpilib.util.struct.Struct;
|
||||
|
||||
public class ChassisAccelerationsStruct implements Struct<ChassisAccelerations> {
|
||||
@Override
|
||||
public Class<ChassisAccelerations> getTypeClass() {
|
||||
return ChassisAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "ChassisAccelerations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return kSizeDouble * 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "double ax;double ay;double alpha";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChassisAccelerations unpack(ByteBuffer bb) {
|
||||
double ax = bb.getDouble();
|
||||
double ay = bb.getDouble();
|
||||
double alpha = bb.getDouble();
|
||||
return new ChassisAccelerations(ax, ay, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, ChassisAccelerations value) {
|
||||
bb.putDouble(value.ax);
|
||||
bb.putDouble(value.ay);
|
||||
bb.putDouble(value.alpha);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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 org.wpilib.math.kinematics.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.wpilib.math.kinematics.DifferentialDriveWheelAccelerations;
|
||||
import org.wpilib.util.struct.Struct;
|
||||
|
||||
public class DifferentialDriveWheelAccelerationsStruct
|
||||
implements Struct<DifferentialDriveWheelAccelerations> {
|
||||
@Override
|
||||
public Class<DifferentialDriveWheelAccelerations> getTypeClass() {
|
||||
return DifferentialDriveWheelAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "DifferentialDriveWheelAccelerations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return kSizeDouble * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "double left;double right";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DifferentialDriveWheelAccelerations unpack(ByteBuffer bb) {
|
||||
double left = bb.getDouble();
|
||||
double right = bb.getDouble();
|
||||
return new DifferentialDriveWheelAccelerations(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, DifferentialDriveWheelAccelerations value) {
|
||||
bb.putDouble(value.left);
|
||||
bb.putDouble(value.right);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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 org.wpilib.math.kinematics.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.wpilib.math.kinematics.MecanumDriveWheelAccelerations;
|
||||
import org.wpilib.util.struct.Struct;
|
||||
|
||||
public class MecanumDriveWheelAccelerationsStruct
|
||||
implements Struct<MecanumDriveWheelAccelerations> {
|
||||
@Override
|
||||
public Class<MecanumDriveWheelAccelerations> getTypeClass() {
|
||||
return MecanumDriveWheelAccelerations.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "MecanumDriveWheelAccelerations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return kSizeDouble * 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "double front_left;double front_right;double rear_left;double rear_right";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MecanumDriveWheelAccelerations unpack(ByteBuffer bb) {
|
||||
double frontLeft = bb.getDouble();
|
||||
double frontRight = bb.getDouble();
|
||||
double rearLeft = bb.getDouble();
|
||||
double rearRight = bb.getDouble();
|
||||
return new MecanumDriveWheelAccelerations(frontLeft, frontRight, rearLeft, rearRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, MecanumDriveWheelAccelerations value) {
|
||||
bb.putDouble(value.frontLeft);
|
||||
bb.putDouble(value.frontRight);
|
||||
bb.putDouble(value.rearLeft);
|
||||
bb.putDouble(value.rearRight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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 org.wpilib.math.kinematics.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.wpilib.math.geometry.Rotation2d;
|
||||
import org.wpilib.math.kinematics.SwerveModuleAcceleration;
|
||||
import org.wpilib.util.struct.Struct;
|
||||
|
||||
public class SwerveModuleAccelerationStruct implements Struct<SwerveModuleAcceleration> {
|
||||
@Override
|
||||
public Class<SwerveModuleAcceleration> getTypeClass() {
|
||||
return SwerveModuleAcceleration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "SwerveModuleAccelerations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return kSizeDouble + Rotation2d.struct.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "double acceleration;Rotation2d angle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Struct<?>[] getNested() {
|
||||
return new Struct<?>[] {Rotation2d.struct};
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwerveModuleAcceleration unpack(ByteBuffer bb) {
|
||||
double acceleration = bb.getDouble();
|
||||
Rotation2d angle = Rotation2d.struct.unpack(bb);
|
||||
return new SwerveModuleAcceleration(acceleration, angle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, SwerveModuleAcceleration value) {
|
||||
bb.putDouble(value.acceleration);
|
||||
Rotation2d.struct.pack(bb, value.angle);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user