java.lang.Object
diff --git a/docs/swervelib/parser/json/package-summary.html b/docs/swervelib/parser/json/package-summary.html
index 4b244489..f4cc8f4f 100644
--- a/docs/swervelib/parser/json/package-summary.html
+++ b/docs/swervelib/parser/json/package-summary.html
@@ -1,11 +1,11 @@
-
+
swervelib.parser.json
-
+
diff --git a/docs/swervelib/parser/json/package-tree.html b/docs/swervelib/parser/json/package-tree.html
index b06ae663..a1f8d9af 100644
--- a/docs/swervelib/parser/json/package-tree.html
+++ b/docs/swervelib/parser/json/package-tree.html
@@ -1,11 +1,11 @@
-
+
swervelib.parser.json Class Hierarchy
-
+
diff --git a/docs/swervelib/parser/package-summary.html b/docs/swervelib/parser/package-summary.html
index 86422422..ecaa7886 100644
--- a/docs/swervelib/parser/package-summary.html
+++ b/docs/swervelib/parser/package-summary.html
@@ -1,11 +1,11 @@
-
+
swervelib.parser
-
+
diff --git a/docs/swervelib/parser/package-tree.html b/docs/swervelib/parser/package-tree.html
index 11b40238..4631dd9b 100644
--- a/docs/swervelib/parser/package-tree.html
+++ b/docs/swervelib/parser/package-tree.html
@@ -1,11 +1,11 @@
-
+
swervelib.parser Class Hierarchy
-
+
diff --git a/docs/swervelib/simulation/SwerveIMUSimulation.html b/docs/swervelib/simulation/SwerveIMUSimulation.html
index 12c38650..e50b7351 100644
--- a/docs/swervelib/simulation/SwerveIMUSimulation.html
+++ b/docs/swervelib/simulation/SwerveIMUSimulation.html
@@ -1,11 +1,11 @@
-
+
SwerveIMUSimulation
-
+
diff --git a/docs/swervelib/simulation/SwerveModuleSimulation.html b/docs/swervelib/simulation/SwerveModuleSimulation.html
index ab9d63d5..60966fdb 100644
--- a/docs/swervelib/simulation/SwerveModuleSimulation.html
+++ b/docs/swervelib/simulation/SwerveModuleSimulation.html
@@ -1,11 +1,11 @@
-
+
SwerveModuleSimulation
-
+
diff --git a/docs/swervelib/simulation/package-summary.html b/docs/swervelib/simulation/package-summary.html
index 7b30b4c7..88fe3094 100644
--- a/docs/swervelib/simulation/package-summary.html
+++ b/docs/swervelib/simulation/package-summary.html
@@ -1,11 +1,11 @@
-
+
swervelib.simulation
-
+
diff --git a/docs/swervelib/simulation/package-tree.html b/docs/swervelib/simulation/package-tree.html
index 84356a9c..d522275c 100644
--- a/docs/swervelib/simulation/package-tree.html
+++ b/docs/swervelib/simulation/package-tree.html
@@ -1,11 +1,11 @@
-
+
swervelib.simulation Class Hierarchy
-
+
diff --git a/docs/swervelib/telemetry/Alert.AlertType.html b/docs/swervelib/telemetry/Alert.AlertType.html
index 4cb3c987..330b4fa5 100644
--- a/docs/swervelib/telemetry/Alert.AlertType.html
+++ b/docs/swervelib/telemetry/Alert.AlertType.html
@@ -1,11 +1,11 @@
-
+
Alert.AlertType
-
+
diff --git a/docs/swervelib/telemetry/Alert.SendableAlerts.html b/docs/swervelib/telemetry/Alert.SendableAlerts.html
index bf0b2dd3..47081689 100644
--- a/docs/swervelib/telemetry/Alert.SendableAlerts.html
+++ b/docs/swervelib/telemetry/Alert.SendableAlerts.html
@@ -1,11 +1,11 @@
-
+
Alert.SendableAlerts
-
+
diff --git a/docs/swervelib/telemetry/Alert.html b/docs/swervelib/telemetry/Alert.html
index 40fea98d..aa9d6ad3 100644
--- a/docs/swervelib/telemetry/Alert.html
+++ b/docs/swervelib/telemetry/Alert.html
@@ -1,11 +1,11 @@
-
+
Alert
-
+
diff --git a/docs/swervelib/telemetry/SwerveDriveTelemetry.TelemetryVerbosity.html b/docs/swervelib/telemetry/SwerveDriveTelemetry.TelemetryVerbosity.html
index ecb4da07..49c01fe5 100644
--- a/docs/swervelib/telemetry/SwerveDriveTelemetry.TelemetryVerbosity.html
+++ b/docs/swervelib/telemetry/SwerveDriveTelemetry.TelemetryVerbosity.html
@@ -1,11 +1,11 @@
-
+
SwerveDriveTelemetry.TelemetryVerbosity
-
+
diff --git a/docs/swervelib/telemetry/SwerveDriveTelemetry.html b/docs/swervelib/telemetry/SwerveDriveTelemetry.html
index 97570755..540de87d 100644
--- a/docs/swervelib/telemetry/SwerveDriveTelemetry.html
+++ b/docs/swervelib/telemetry/SwerveDriveTelemetry.html
@@ -1,11 +1,11 @@
-
+
SwerveDriveTelemetry
-
+
diff --git a/docs/swervelib/telemetry/package-summary.html b/docs/swervelib/telemetry/package-summary.html
index aa5ac437..adfcf9d9 100644
--- a/docs/swervelib/telemetry/package-summary.html
+++ b/docs/swervelib/telemetry/package-summary.html
@@ -1,11 +1,11 @@
-
+
swervelib.telemetry
-
+
diff --git a/docs/swervelib/telemetry/package-tree.html b/docs/swervelib/telemetry/package-tree.html
index 5c487e76..a1e4b0a0 100644
--- a/docs/swervelib/telemetry/package-tree.html
+++ b/docs/swervelib/telemetry/package-tree.html
@@ -1,11 +1,11 @@
-
+
swervelib.telemetry Class Hierarchy
-
+
diff --git a/docs/type-search-index.js b/docs/type-search-index.js
index d6cf158e..380ad0d6 100644
--- a/docs/type-search-index.js
+++ b/docs/type-search-index.js
@@ -1 +1 @@
-typeSearchIndex = [{"p":"swervelib.imu","l":"ADIS16448Swerve"},{"p":"swervelib.imu","l":"ADIS16470Swerve"},{"p":"swervelib.imu","l":"ADXRS450Swerve"},{"p":"swervelib.telemetry","l":"Alert"},{"p":"swervelib.telemetry","l":"Alert.AlertType"},{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"swervelib.encoders","l":"AnalogAbsoluteEncoderSwerve"},{"p":"swervelib.imu","l":"AnalogGyroSwerve"},{"p":"swervelib.parser.json.modules","l":"BoolMotorJson"},{"p":"swervelib.parser","l":"Cache"},{"p":"swervelib.encoders","l":"CanAndCoderSwerve"},{"p":"swervelib.encoders","l":"CANCoderSwerve"},{"p":"swervelib.parser.json","l":"ControllerPropertiesJson"},{"p":"swervelib.parser.json","l":"DeviceJson"},{"p":"swervelib.parser.json.modules","l":"LocationJson"},{"p":"swervelib.math","l":"Matter"},{"p":"swervelib.parser.json","l":"ModuleJson"},{"p":"swervelib.parser.json","l":"MotorConfigDouble"},{"p":"swervelib.parser.json","l":"MotorConfigInt"},{"p":"swervelib.imu","l":"NavXSwerve"},{"p":"swervelib.parser.json","l":"PhysicalPropertiesJson"},{"p":"swervelib.parser","l":"PIDFConfig"},{"p":"swervelib.parser.json","l":"PIDFPropertiesJson"},{"p":"swervelib.parser.deserializer","l":"PIDFRange"},{"p":"swervelib.imu","l":"Pigeon2Swerve"},{"p":"swervelib.imu","l":"PigeonSwerve"},{"p":"swervelib.encoders","l":"PWMDutyCycleEncoderSwerve"},{"p":"swervelib.telemetry","l":"Alert.SendableAlerts"},{"p":"swervelib.motors","l":"SparkFlexSwerve"},{"p":"swervelib.motors","l":"SparkFlexSwerve.SparkMAX_slotIdx"},{"p":"swervelib.motors","l":"SparkMaxSwerve.SparkMAX_slotIdx"},{"p":"swervelib.encoders","l":"SparkMaxAnalogEncoderSwerve"},{"p":"swervelib.motors","l":"SparkMaxBrushedMotorSwerve"},{"p":"swervelib.encoders","l":"SparkMaxEncoderSwerve"},{"p":"swervelib.motors","l":"SparkMaxSwerve"},{"p":"swervelib.encoders","l":"SwerveAbsoluteEncoder"},{"p":"swervelib","l":"SwerveController"},{"p":"swervelib.parser","l":"SwerveControllerConfiguration"},{"p":"swervelib","l":"SwerveDrive"},{"p":"swervelib.parser","l":"SwerveDriveConfiguration"},{"p":"swervelib.parser.json","l":"SwerveDriveJson"},{"p":"swervelib.telemetry","l":"SwerveDriveTelemetry"},{"p":"swervelib","l":"SwerveDriveTest"},{"p":"swervelib.imu","l":"SwerveIMU"},{"p":"swervelib.simulation","l":"SwerveIMUSimulation"},{"p":"swervelib.math","l":"SwerveMath"},{"p":"swervelib","l":"SwerveModule"},{"p":"swervelib.parser","l":"SwerveModuleConfiguration"},{"p":"swervelib.parser","l":"SwerveModulePhysicalCharacteristics"},{"p":"swervelib.simulation","l":"SwerveModuleSimulation"},{"p":"swervelib.motors","l":"SwerveMotor"},{"p":"swervelib.parser","l":"SwerveParser"},{"p":"swervelib.motors","l":"TalonFXSwerve"},{"p":"swervelib.motors","l":"TalonSRXSwerve"},{"p":"swervelib.telemetry","l":"SwerveDriveTelemetry.TelemetryVerbosity"}];updateSearchResults();
\ No newline at end of file
+typeSearchIndex = [{"p":"swervelib.imu","l":"ADIS16448Swerve"},{"p":"swervelib.imu","l":"ADIS16470Swerve"},{"p":"swervelib.imu","l":"ADXRS450Swerve"},{"p":"swervelib.telemetry","l":"Alert"},{"p":"swervelib.telemetry","l":"Alert.AlertType"},{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"swervelib.encoders","l":"AnalogAbsoluteEncoderSwerve"},{"p":"swervelib.imu","l":"AnalogGyroSwerve"},{"p":"swervelib.parser.json.modules","l":"AngleConversionFactorsJson"},{"p":"swervelib.parser.json.modules","l":"BoolMotorJson"},{"p":"swervelib.parser","l":"Cache"},{"p":"swervelib.encoders","l":"CanAndCoderSwerve"},{"p":"swervelib.encoders","l":"CANCoderSwerve"},{"p":"swervelib.parser.json","l":"ControllerPropertiesJson"},{"p":"swervelib.parser.json.modules","l":"ConversionFactorsJson"},{"p":"swervelib.parser.json","l":"DeviceJson"},{"p":"swervelib.parser.json.modules","l":"DriveConversionFactorsJson"},{"p":"swervelib.parser.json.modules","l":"LocationJson"},{"p":"swervelib.math","l":"Matter"},{"p":"swervelib.parser.json","l":"ModuleJson"},{"p":"swervelib.parser.json","l":"MotorConfigDouble"},{"p":"swervelib.parser.json","l":"MotorConfigInt"},{"p":"swervelib.imu","l":"NavXSwerve"},{"p":"swervelib.parser.json","l":"PhysicalPropertiesJson"},{"p":"swervelib.parser","l":"PIDFConfig"},{"p":"swervelib.parser.json","l":"PIDFPropertiesJson"},{"p":"swervelib.parser.deserializer","l":"PIDFRange"},{"p":"swervelib.imu","l":"Pigeon2Swerve"},{"p":"swervelib.imu","l":"PigeonSwerve"},{"p":"swervelib.encoders","l":"PWMDutyCycleEncoderSwerve"},{"p":"swervelib.telemetry","l":"Alert.SendableAlerts"},{"p":"swervelib.motors","l":"SparkFlexSwerve"},{"p":"swervelib.motors","l":"SparkFlexSwerve.SparkMAX_slotIdx"},{"p":"swervelib.motors","l":"SparkMaxSwerve.SparkMAX_slotIdx"},{"p":"swervelib.encoders","l":"SparkMaxAnalogEncoderSwerve"},{"p":"swervelib.motors","l":"SparkMaxBrushedMotorSwerve"},{"p":"swervelib.encoders","l":"SparkMaxEncoderSwerve"},{"p":"swervelib.motors","l":"SparkMaxSwerve"},{"p":"swervelib.encoders","l":"SwerveAbsoluteEncoder"},{"p":"swervelib","l":"SwerveController"},{"p":"swervelib.parser","l":"SwerveControllerConfiguration"},{"p":"swervelib","l":"SwerveDrive"},{"p":"swervelib.parser","l":"SwerveDriveConfiguration"},{"p":"swervelib.parser.json","l":"SwerveDriveJson"},{"p":"swervelib.telemetry","l":"SwerveDriveTelemetry"},{"p":"swervelib","l":"SwerveDriveTest"},{"p":"swervelib.imu","l":"SwerveIMU"},{"p":"swervelib.simulation","l":"SwerveIMUSimulation"},{"p":"swervelib.math","l":"SwerveMath"},{"p":"swervelib","l":"SwerveModule"},{"p":"swervelib.parser","l":"SwerveModuleConfiguration"},{"p":"swervelib.parser","l":"SwerveModulePhysicalCharacteristics"},{"p":"swervelib.simulation","l":"SwerveModuleSimulation"},{"p":"swervelib.motors","l":"SwerveMotor"},{"p":"swervelib.parser","l":"SwerveParser"},{"p":"swervelib.motors","l":"TalonFXSwerve"},{"p":"swervelib.motors","l":"TalonSRXSwerve"},{"p":"swervelib.telemetry","l":"SwerveDriveTelemetry.TelemetryVerbosity"}];updateSearchResults();
\ No newline at end of file
diff --git a/swervelib/SwerveDrive.java b/swervelib/SwerveDrive.java
index 9f45b916..dfbb82c2 100644
--- a/swervelib/SwerveDrive.java
+++ b/swervelib/SwerveDrive.java
@@ -1159,6 +1159,21 @@ public void restoreInternalOffset()
}
}
+ /**
+ * Enable auto-centering module wheels. This has a side effect of causing some jitter to the robot when a PID is not
+ * tuned perfectly. This function is a wrapper for {@link SwerveModule#setAntiJitter(boolean)} to perform
+ * auto-centering.
+ *
+ * @param enabled Enable auto-centering (disable antiJitter)
+ */
+ public void setAutoCenteringModules(boolean enabled)
+ {
+ for (SwerveModule module : swerveModules)
+ {
+ module.setAntiJitter(!enabled);
+ }
+ }
+
/**
* Enable or disable the {@link swervelib.parser.SwerveModuleConfiguration#useCosineCompensator} for all
* {@link SwerveModule}'s in the swerve drive. The cosine compensator will slow down or speed up modules that are
diff --git a/swervelib/math/SwerveMath.java b/swervelib/math/SwerveMath.java
index eb7de873..d78e5871 100644
--- a/swervelib/math/SwerveMath.java
+++ b/swervelib/math/SwerveMath.java
@@ -359,6 +359,9 @@ public static SwerveModuleConfiguration getSwerveModule(
/**
* Put an angle within the 360 deg scope of a reference. For example, given a scope reference of 756 degrees, assumes
* the full scope is (720-1080), and places an angle of 22 degrees into it, returning 742 deg.
+ *
+ * A more formal definition: returns the closest angle {@code n} to {@code scopeReference} such that {@code n} is
+ * congruent to {@code newAngle}.
*
* @param scopeReference Current Angle (deg)
* @param newAngle Target Angle (deg)
@@ -366,34 +369,11 @@ public static SwerveModuleConfiguration getSwerveModule(
*/
public static double placeInAppropriate0To360Scope(double scopeReference, double newAngle)
{
- double lowerBound;
- double upperBound;
- double lowerOffset = scopeReference % 360;
- if (lowerOffset >= 0)
- {
- lowerBound = scopeReference - lowerOffset;
- upperBound = scopeReference + (360 - lowerOffset);
- } else
- {
- upperBound = scopeReference - lowerOffset;
- lowerBound = scopeReference - (360 + lowerOffset);
- }
- while (newAngle < lowerBound)
- {
- newAngle += 360;
- }
- while (newAngle > upperBound)
- {
- newAngle -= 360;
- }
- if (newAngle - scopeReference > 180)
- {
- newAngle -= 360;
- } else if (newAngle - scopeReference < -180)
- {
- newAngle += 360;
- }
- return newAngle;
+ // Figure out how many revolutions from the angle to the reference
+ double diffRevs = Math.round((scopeReference - newAngle) / 360) * 360;
+
+ // Add that many revolutions
+ return diffRevs + newAngle;
}
/**
diff --git a/swervelib/parser/json/ModuleJson.java b/swervelib/parser/json/ModuleJson.java
index b9f24043..5eb34713 100644
--- a/swervelib/parser/json/ModuleJson.java
+++ b/swervelib/parser/json/ModuleJson.java
@@ -9,6 +9,7 @@
import swervelib.parser.SwerveModuleConfiguration;
import swervelib.parser.SwerveModulePhysicalCharacteristics;
import swervelib.parser.json.modules.BoolMotorJson;
+import swervelib.parser.json.modules.ConversionFactorsJson;
import swervelib.parser.json.modules.LocationJson;
/**
@@ -20,11 +21,11 @@ public class ModuleJson
/**
* Drive motor device configuration.
*/
- public DeviceJson drive;
+ public DeviceJson drive;
/**
* Angle motor device configuration.
*/
- public DeviceJson angle;
+ public DeviceJson angle;
/**
* Conversion factor for the module, if different from the one in swervedrive.json
*
@@ -32,31 +33,35 @@ public class ModuleJson
* {@link swervelib.math.SwerveMath#calculateDegreesPerSteeringRotation(double, double)} for angle motors or
* {@link swervelib.math.SwerveMath#calculateMetersPerRotation(double, double, double)} for drive motors.
*/
- public MotorConfigDouble conversionFactor = new MotorConfigDouble(0, 0);
+ public MotorConfigDouble conversionFactor = new MotorConfigDouble(0, 0);
+ /**
+ * Conversion Factors composition. Auto-calculates the conversion factors.
+ */
+ public ConversionFactorsJson conversionFactors = new ConversionFactorsJson();
/**
* Absolute encoder device configuration.
*/
- public DeviceJson encoder;
+ public DeviceJson encoder;
/**
* Defines which motors are inverted.
*/
- public BoolMotorJson inverted;
+ public BoolMotorJson inverted;
/**
* Absolute encoder offset from 0 in degrees.
*/
- public double absoluteEncoderOffset;
+ public double absoluteEncoderOffset;
/**
* Absolute encoder inversion state.
*/
- public boolean absoluteEncoderInverted = false;
+ public boolean absoluteEncoderInverted = false;
/**
* The location of the swerve module from the center of the robot in inches.
*/
- public LocationJson location;
+ public LocationJson location;
/**
* Should do cosine compensation when not pointing correct direction;.
*/
- public boolean useCosineCompensator = true;
+ public boolean useCosineCompensator = true;
/**
* Create the swerve module configuration based off of parsed data.
@@ -85,6 +90,27 @@ public SwerveModuleConfiguration createModuleConfiguration(
}
}
+ // Setup deprecation notice.
+// if (this.conversionFactor.drive != 0 && this.conversionFactor.angle != 0)
+// {
+// new Alert("Configuration",
+// "\n'conversionFactor': {'drive': " + conversionFactor.drive + ", 'angle': " + conversionFactor.angle +
+// "} \nis deprecated, please use\n" +
+// "'conversionFactors': {'drive': {'factor': " + conversionFactor.drive + "}, 'angle': {'factor': " +
+// conversionFactor.angle + "} }",
+// AlertType.WARNING).set(true);
+// }
+
+ // Override with composite conversion factor.
+ if (!conversionFactors.isAngleEmpty())
+ {
+ conversionFactor.angle = conversionFactors.angle.calculate();
+ }
+ if (!conversionFactors.isDriveEmpty())
+ {
+ conversionFactor.drive = conversionFactors.drive.calculate();
+ }
+
// Set the conversion factors to null if they are both 0.
if (this.conversionFactor != null)
{
diff --git a/swervelib/parser/json/PhysicalPropertiesJson.java b/swervelib/parser/json/PhysicalPropertiesJson.java
index 4ede4025..7715d9d9 100644
--- a/swervelib/parser/json/PhysicalPropertiesJson.java
+++ b/swervelib/parser/json/PhysicalPropertiesJson.java
@@ -1,6 +1,9 @@
package swervelib.parser.json;
import swervelib.parser.SwerveModulePhysicalCharacteristics;
+import swervelib.parser.json.modules.ConversionFactorsJson;
+import swervelib.telemetry.Alert;
+import swervelib.telemetry.Alert.AlertType;
/**
* {@link swervelib.parser.SwerveModulePhysicalCharacteristics} parsed data. Used to configure the SwerveModule.
@@ -14,23 +17,27 @@ public class PhysicalPropertiesJson
* {@link swervelib.math.SwerveMath#calculateDegreesPerSteeringRotation(double, double)} for angle motors or
* {@link swervelib.math.SwerveMath#calculateMetersPerRotation(double, double, double)} for drive motors.
*/
- public MotorConfigDouble conversionFactor = new MotorConfigDouble(0, 0);
+ public MotorConfigDouble conversionFactor = new MotorConfigDouble(0, 0);
+ /**
+ * Conversion Factors composition. Auto-calculates the conversion factors.
+ */
+ public ConversionFactorsJson conversionFactors = new ConversionFactorsJson();
/**
* The current limit in AMPs to apply to the motors.
*/
- public MotorConfigInt currentLimit = new MotorConfigInt(40, 20);
+ public MotorConfigInt currentLimit = new MotorConfigInt(40, 20);
/**
* The minimum number of seconds to take for the motor to go from 0 to full throttle.
*/
- public MotorConfigDouble rampRate = new MotorConfigDouble(0.25, 0.25);
+ public MotorConfigDouble rampRate = new MotorConfigDouble(0.25, 0.25);
/**
* The grip tape coefficient of friction on carpet. Used to calculate the practical maximum acceleration.
*/
- public double wheelGripCoefficientOfFriction = 1.19;
+ public double wheelGripCoefficientOfFriction = 1.19;
/**
* The voltage to use for the smart motor voltage compensation, default is 12.
*/
- public double optimalVoltage = 12;
+ public double optimalVoltage = 12;
/**
* Create the physical characteristics based off the parsed data.
@@ -39,6 +46,28 @@ public class PhysicalPropertiesJson
*/
public SwerveModulePhysicalCharacteristics createPhysicalProperties()
{
+ // Setup deprecation notice.
+// if (conversionFactor.drive != 0 && conversionFactor.angle != 0 && conversionFactors.isDriveEmpty() &&
+// conversionFactors.isAngleEmpty())
+// {
+// new Alert("Configuration",
+// "\n'conversionFactor': {'drive': " + conversionFactor.drive + ", 'angle': " + conversionFactor.angle +
+// "} \nis deprecated, please use\n" +
+// "'conversionFactors': {'drive': {'factor': " + conversionFactor.drive + "}, 'angle': {'factor': " +
+// conversionFactor.angle + "} }",
+// AlertType.ERROR_TRACE).set(true);
+// }
+
+ if (!conversionFactors.isAngleEmpty())
+ {
+ conversionFactor.angle = conversionFactors.angle.calculate();
+ }
+
+ if (!conversionFactors.isDriveEmpty())
+ {
+ conversionFactor.drive = conversionFactors.drive.calculate();
+ }
+
return new SwerveModulePhysicalCharacteristics(
conversionFactor,
wheelGripCoefficientOfFriction,
diff --git a/swervelib/parser/json/modules/AngleConversionFactorsJson.java b/swervelib/parser/json/modules/AngleConversionFactorsJson.java
new file mode 100644
index 00000000..a7c8613a
--- /dev/null
+++ b/swervelib/parser/json/modules/AngleConversionFactorsJson.java
@@ -0,0 +1,41 @@
+package swervelib.parser.json.modules;
+
+import swervelib.math.SwerveMath;
+import swervelib.telemetry.Alert;
+import swervelib.telemetry.Alert.AlertType;
+
+/**
+ * Angle motor conversion factors composite JSON parse class.
+ */
+public class AngleConversionFactorsJson
+{
+
+ /**
+ * Gear ratio for the angle/steering/azimuth motor on the Swerve Module. Motor rotations to 1 wheel rotation.
+ */
+ public double gearRatio = 0;
+ /**
+ * Calculated or given conversion factor.
+ */
+ public double factor = 0;
+
+ /**
+ * Calculate the drive conversion factor.
+ *
+ * @return Drive conversion factor, if factor isn't set.
+ */
+ public double calculate()
+ {
+ if (factor != 0 && gearRatio != 0)
+ {
+ new Alert("Configuration",
+ "The given angle conversion factor takes precedence over the composite conversion factor, please remove 'factor' if you want to use the composite factor instead.",
+ AlertType.WARNING).set(true);
+ }
+ if (factor == 0)
+ {
+ factor = SwerveMath.calculateDegreesPerSteeringRotation(gearRatio);
+ }
+ return factor;
+ }
+}
diff --git a/swervelib/parser/json/modules/ConversionFactorsJson.java b/swervelib/parser/json/modules/ConversionFactorsJson.java
new file mode 100644
index 00000000..85ff25f2
--- /dev/null
+++ b/swervelib/parser/json/modules/ConversionFactorsJson.java
@@ -0,0 +1,37 @@
+package swervelib.parser.json.modules;
+
+/**
+ * Conversion Factors parsed JSON class
+ */
+public class ConversionFactorsJson
+{
+
+ /**
+ * Drive motor conversion factors composition.
+ */
+ public DriveConversionFactorsJson drive = new DriveConversionFactorsJson();
+ /**
+ * Angle motor conversion factors composition.
+ */
+ public AngleConversionFactorsJson angle = new AngleConversionFactorsJson();
+
+ /**
+ * Check if the conversion factors are set for the drive motor.
+ *
+ * @return Empty
+ */
+ public boolean isDriveEmpty()
+ {
+ return drive.factor == 0 && drive.diameter == 0 && drive.gearRatio == 0;
+ }
+
+ /**
+ * Check if the conversion factors are set for the angle motor.
+ *
+ * @return Empty
+ */
+ public boolean isAngleEmpty()
+ {
+ return angle.factor == 0 && angle.gearRatio == 0;
+ }
+}
diff --git a/swervelib/parser/json/modules/DriveConversionFactorsJson.java b/swervelib/parser/json/modules/DriveConversionFactorsJson.java
new file mode 100644
index 00000000..d792d36d
--- /dev/null
+++ b/swervelib/parser/json/modules/DriveConversionFactorsJson.java
@@ -0,0 +1,46 @@
+package swervelib.parser.json.modules;
+
+import edu.wpi.first.math.util.Units;
+import swervelib.math.SwerveMath;
+import swervelib.telemetry.Alert;
+import swervelib.telemetry.Alert.AlertType;
+
+/**
+ * Drive motor composite JSON parse class.
+ */
+public class DriveConversionFactorsJson
+{
+
+ /**
+ * Gear ratio for the drive motor rotations to turn the wheel 1 complete rotation.
+ */
+ public double gearRatio = 0;
+ /**
+ * Diameter of the wheel in inches.
+ */
+ public double diameter = 0;
+ /**
+ * Calculated conversion factor.
+ */
+ public double factor = 0;
+
+ /**
+ * Calculate the drive conversion factor.
+ *
+ * @return Drive conversion factor, if factor isn't set.
+ */
+ public double calculate()
+ {
+ if (factor != 0 && (diameter != 0 || gearRatio != 0))
+ {
+ new Alert("Configuration",
+ "The given drive conversion factor takes precedence over the composite conversion factor, please remove 'factor' if you want to use the composite factor instead.",
+ AlertType.WARNING).set(true);
+ }
+ if (factor == 0)
+ {
+ factor = SwerveMath.calculateMetersPerRotation(Units.inchesToMeters(this.diameter), this.gearRatio);
+ }
+ return factor;
+ }
+}