Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
626bfd6
refactor(hardware/gyro): separate IMUs and single axis gyros
Baconing Oct 2, 2024
a699ec7
feat(hardware/gyro/imu): implement ADIS16448IMU and ADIS16470IMU
Baconing Oct 2, 2024
f2445de
refactor(hardware/gyro/imu): remove NotNull annotations from abstract…
Baconing Oct 3, 2024
1b9402f
refactor(hardware/gyro/imu): use Translation3d instead of Rotation3d …
Baconing Oct 3, 2024
045bb2c
refactor(hardware/gyro/imu): use radians instead of degrees
Baconing Oct 3, 2024
d180bee
feat/refactor(hardware/gyro/imu/adis16*): finish implementations
Baconing Oct 3, 2024
4f91bc7
style(hardware/gyro/imu/adis16470): remove unused import
Baconing Oct 3, 2024
a49c171
chore(build.gradle): add wpiunits dependency
Baconing Oct 3, 2024
2e5b57d
refactor(hardware/gyro/imu/adis16470): use unqualified name instead o…
Baconing Oct 3, 2024
3881104
refactor(hardware/gyro/imu): put unit in method name for IMU.getRotat…
Baconing Oct 3, 2024
e26558e
feat(hardware/gyro/imu): add getAngleRadians(SingleAxisGyroscope.Axis…
Baconing Oct 3, 2024
2b1123a
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
a95c639
refactor(hardware/imu/adis16448): use unqualified name instead of FQD…
Baconing Oct 3, 2024
a39601e
Merge remote-tracking branch 'origin/v2025-1-0-0/gyros' into v2025-1-…
Baconing Oct 3, 2024
77d2f72
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
fe3c8b6
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
6556a2a
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
8dd30a7
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
935a74f
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
426ea9c
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
d4743f9
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
0837d8d
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
73d6fd0
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
f48f6c7
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 3, 2024
648adab
feat/fix(hardware/gyro/imu/adis16*): implement getAngleRadians(Single…
Baconing Oct 4, 2024
28dfa6c
feat(hardware/gyro/imu): finish implementation of IMU and it's subcla…
Baconing Oct 7, 2024
5722c6b
refactor(hardware/gyro/imu): move yaw pitch roll axis assignment to a…
Baconing Oct 7, 2024
213fecf
refactor(hardware/gyro): remove SingleAxisGyroscope, just use IMU.
Baconing Oct 7, 2024
898776e
feat(hardware/gyro): implement KauaiLabs NavX
Baconing Oct 7, 2024
64eb036
docs(hardware/gyro/adis16*): update documentation to reflect changes
Baconing Oct 7, 2024
9ba4834
style(hardware/gyro/imu): remove unnecessary qualifiers in IMU.Cartes…
Baconing Oct 7, 2024
7108bbc
refactor(hardware/gyro): clean up some of the long methods
Baconing Oct 7, 2024
336dd89
Merge branch 'master' into v2025-1-0-0/gyros
Baconing Oct 10, 2024
fa12c52
refactor(hardware/gyro/imu): only use Rotation3d where absolutely nec…
Baconing Oct 10, 2024
9669e48
test(hardware/gyro): implement tests for ADIS16448, ADIS16470, and de…
Baconing Oct 14, 2024
ed1a44c
fix(hardware/gyro): implement getRate() function
Baconing Oct 14, 2024
4e72ffa
fix(hardware/gyro): (re)implement angle rate logic
Baconing Oct 14, 2024
7ae15eb
test(hardware/gyro): finish implementing unit tests for all implement…
Baconing Oct 14, 2024
e6b51db
fix(hardware/gyro/navx): use Gs not m/ss
Baconing Oct 14, 2024
2de1188
docs(hardware/gyro): annotate deprecated members
Baconing Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not just remove single axis gyroscopes. They can be useful for tracking rotating parts like arms or grabbers. In addition, you could "get" a single axis gyroscope from IMUs to allow more adaptability.

This file was deleted.

122 changes: 122 additions & 0 deletions src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16448IMU.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package net.frc5183.librobot.hardware.gyro.imu;

import edu.wpi.first.math.geometry.Rotation3d;
import edu.wpi.first.wpilibj.ADIS16448_IMU;
import edu.wpi.first.wpilibj.SPI;
import org.jetbrains.annotations.NotNull;

import java.util.Optional;

Check warning on line 8 in src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16448IMU.java

View workflow job for this annotation

GitHub Actions / pmd

Unused import 'java.util.Optional'

Reports import statements that can be removed. They are either unused, duplicated, or the members they import are already implicitly in scope, because they're in java.lang, or the current package. If some imports cannot be resolved, for instance because you run PMD with an incomplete auxiliary classpath, some imports may be conservatively marked as used even if they're not to avoid false positives. UnnecessaryImport (Priority: 4, Ruleset: Code Style) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_codestyle.html#unnecessaryimport

/**
* Represents an ADIS16448 {@link IMU}.
*/
public class ADIS16448IMU extends IMU {
/**
* The ADIS16448 IMU.
*/
@NotNull
private final ADIS16448_IMU imu;

/**
* The YAW axis.
*/
private final IMUAxis yaw;

Check warning on line 23 in src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16448IMU.java

View workflow job for this annotation

GitHub Actions / pmd

Avoid unused private fields such as 'yaw'.

Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. UnusedPrivateField (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_bestpractices.html#unusedprivatefield

/**
* The PITCH axis.
*/
private final IMUAxis pitch;

Check warning on line 28 in src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16448IMU.java

View workflow job for this annotation

GitHub Actions / pmd

Avoid unused private fields such as 'pitch'.

Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. UnusedPrivateField (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_bestpractices.html#unusedprivatefield

/**
* The ROLL axis.
*/
private final IMUAxis roll;

Check warning on line 33 in src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16448IMU.java

View workflow job for this annotation

GitHub Actions / pmd

Avoid unused private fields such as 'roll'.

Detects when a private field is declared and/or assigned a value, but not used. Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework. UnusedPrivateField (Priority: 3, Ruleset: Best Practices) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_bestpractices.html#unusedprivatefield

/**
* Creates a new {@link ADIS16448IMU} using the RIO's Onboard MXP port, 500ms calibration time, and Z axis as yaw.
* @see ADIS16448_IMU#ADIS16448_IMU()
*/
public ADIS16448IMU() {
yaw = IMUAxis.Z;
imu = new ADIS16448_IMU();
}

/**
* Creates a new {@link ADIS16448IMU} from an existing ADIS16448 IMU instance.
* @param imu the ADIS16448 IMU to use.
*/
public ADIS16448IMU(@NotNull ADIS16448_IMU imu) {
this.imu = imu;
}

/**
* Creates a new {@link ADIS16448IMU} with a specified yaw axis.
* Uses default RIO's Onboard MXP port and 512ms calibration time.
* @param yaw the YAW axis.
*/
public ADIS16448IMU(IMUAxis yaw) {
this.yaw = yaw;
imu = new ADIS16448_IMU(fromIMUAxis(yaw), SPI.Port.kMXP, ADIS16448_IMU.CalibrationTime._512ms);
}

/**
* Creates a new {@link ADIS16448IMU} with a specified yaw axis and SPI port.
* Uses default 512ms calibration time.
* @param yaw the YAW axis.
* @param port the SPI port.
*/
public ADIS16448IMU(IMUAxis yaw, SPI.Port port) {
this.yaw = yaw;
imu = new ADIS16448_IMU(fromIMUAxis(yaw), port, ADIS16448_IMU.CalibrationTime._512ms);
}

/**
* Creates a new {@link ADIS16448IMU} with a specified yaw axis, SPI port, and calibration time.
* @param yaw the YAW axis.
* @param port the SPI port.
* @param calibrationTime the calibration time.
*/
public ADIS16448IMU(IMUAxis yaw, SPI.Port port, ADIS16448_IMU.CalibrationTime calibrationTime) {
this.yaw = yaw;
imu = new ADIS16448_IMU(fromIMUAxis(yaw), port, calibrationTime);
}

@Override
public @NotNull Rotation3d getRawRotation3dDegrees() {
return new Rotation3d(imu.getGyroAngleX(), imu.getGyroAngleY(), imu.getGyroAngleZ());
}

@Override
public @NotNull Rotation3d getAccelerationMetersPerSecondSquared() {
return new Rotation3d(imu.getAccelX(), imu.getAccelY(), imu.getAccelZ());
}

@Override
public void calibrate() {
imu.calibrate();
}

@Override
public void reset() {
imu.reset();
}

@Override
public @NotNull ADIS16448_IMU getRawIMU() {
return imu;
}

/**
* Returns a new {@link ADIS16448_IMU.IMUAxis} from an {@link IMUAxis}.
* @param axis the {@link IMUAxis} to convert
* @return the converted {@link ADIS16448_IMU.IMUAxis}
*/
@NotNull
public static ADIS16448_IMU.IMUAxis fromIMUAxis(@NotNull IMUAxis axis) {
return switch (axis) {
case X -> ADIS16448_IMU.IMUAxis.kX;
case Y -> ADIS16448_IMU.IMUAxis.kY;
case Z -> ADIS16448_IMU.IMUAxis.kZ;
};
}
}
111 changes: 111 additions & 0 deletions src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16470IMU.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package net.frc5183.librobot.hardware.gyro.imu;

import edu.wpi.first.math.geometry.Rotation3d;
import edu.wpi.first.wpilibj.ADIS16448_IMU;

Check warning on line 4 in src/main/java/net/frc5183/librobot/hardware/gyro/imu/ADIS16470IMU.java

View workflow job for this annotation

GitHub Actions / pmd

Unused import 'edu.wpi.first.wpilibj.ADIS16448_IMU'

Reports import statements that can be removed. They are either unused, duplicated, or the members they import are already implicitly in scope, because they're in java.lang, or the current package. If some imports cannot be resolved, for instance because you run PMD with an incomplete auxiliary classpath, some imports may be conservatively marked as used even if they're not to avoid false positives. UnnecessaryImport (Priority: 4, Ruleset: Code Style) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_codestyle.html#unnecessaryimport
import edu.wpi.first.wpilibj.ADIS16470_IMU;
import edu.wpi.first.wpilibj.SPI;
import org.jetbrains.annotations.NotNull;

/**
* Represents an ADIS16470 {@link IMU}.
*/
public class ADIS16470IMU extends IMU {
/**
* The ADIS16470 IMU.
*/
@NotNull
private final ADIS16470_IMU imu;

/**
* Creates a new {@link ADIS16470IMU} using the RIO's Onboard MXP port and 500ms calibration time, and yaw pitch roll as ZXY respectively.
* @see ADIS16470_IMU#ADIS16470_IMU()
*/
public ADIS16470IMU() {
imu = new ADIS16470_IMU();
}

/**
* Creates a new {@link ADIS16470IMU} from an existing ADIS16470 IMU instance.
* @param imu the ADIS16470 IMU to use.
*/
public ADIS16470IMU(@NotNull ADIS16470_IMU imu) {
this.imu = imu;
}

/**
* Creates a new {@link ADIS16470IMU} with a specified yaw, pitch, and roll axis.
* Uses default RIO's Onboard MXP port and 500ms calibration time.
* @param yaw the YAW axis.
* @param pitch the PITCH axis.
* @param roll the ROLL axis.
*/
public ADIS16470IMU(IMUAxis yaw, IMUAxis pitch, IMUAxis roll) {
imu = new ADIS16470_IMU(fromIMUAxis(yaw), fromIMUAxis(pitch), fromIMUAxis(roll));
}

/**
* Creates a new {@link ADIS16470IMU} with a specified yaw, pitch, roll axis, and SPI port.
* Uses default 4s calibration time.
* @param yaw the YAW axis.
* @param pitch the PITCH axis.
* @param roll the ROLL axis.
* @param port the SPI port.
*/
public ADIS16470IMU(IMUAxis yaw, IMUAxis pitch, IMUAxis roll, SPI.Port port) {
imu = new ADIS16470_IMU(fromIMUAxis(yaw), fromIMUAxis(pitch), fromIMUAxis(roll), port, ADIS16470_IMU.CalibrationTime._4s);
}

/**
* Creates a new {@link ADIS16470IMU} with a specified yaw, pitch, roll axis, SPI port, and calibration time.
* @param yaw the YAW axis.
* @param pitch the PITCH axis.
* @param roll the ROLL axis.
* @param port the SPI port.
* @param calibrationTime the calibration time.
*/
public ADIS16470IMU(IMUAxis yaw, IMUAxis pitch, IMUAxis roll, SPI.Port port, ADIS16470_IMU.CalibrationTime calibrationTime) {
imu = new ADIS16470_IMU(fromIMUAxis(yaw), fromIMUAxis(pitch), fromIMUAxis(roll), port, calibrationTime);
}

@Override
public @NotNull Rotation3d getRawRotation3dDegrees() {
return new Rotation3d(
imu.getAngle(fromIMUAxis(IMUAxis.X)),
imu.getAngle(fromIMUAxis(IMUAxis.Y)),
imu.getAngle(fromIMUAxis(IMUAxis.Z))
);
}

@Override
public @NotNull Rotation3d getAccelerationMetersPerSecondSquared() {
return new Rotation3d(imu.getAccelX(), imu.getAccelY(), imu.getAccelZ());
}

@Override
public void calibrate() {
imu.calibrate();
}

@Override
public void reset() {
imu.reset();
}

@Override
public @NotNull ADIS16470_IMU getRawIMU() {
return imu;
}

/**
* Returns a new {@link ADIS16470_IMU.IMUAxis} from an {@link IMUAxis}.
* @param axis the {@link IMUAxis} to convert
* @return the converted {@link ADIS16470_IMU.IMUAxis}
*/
public static ADIS16470_IMU.IMUAxis fromIMUAxis(IMUAxis axis) {
return switch (axis) {
case X -> ADIS16470_IMU.IMUAxis.kX;
case Y -> ADIS16470_IMU.IMUAxis.kY;
case Z -> ADIS16470_IMU.IMUAxis.kZ;
};
}
}
82 changes: 82 additions & 0 deletions src/main/java/net/frc5183/librobot/hardware/gyro/imu/IMU.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package net.frc5183.librobot.hardware.gyro.imu;

import edu.wpi.first.math.geometry.Rotation3d;
import org.jetbrains.annotations.NotNull;

/**
* Represents an IMU (Inertial Measurement Unit).
*/
public abstract class IMU {
/**
* The offset to be added to the gyroscope.
*/
private Rotation3d offset = new Rotation3d(0, 0, 0);

/**
* Gets the rotation of the gyroscope (with offset) in degrees.
* @return {@link Rotation3d} of the rotation of the gyroscope (with offset) in degrees.
*/
@NotNull
public Rotation3d getRotation3dDegrees() {
return getRawRotation3dDegrees().plus(getOffset());
}

/**
* Gets the rotation of the gyroscope (without offset) in degrees.
* @return {@link Rotation3d} of the rotation of the gyroscope (without offset) in degrees.
*/
@NotNull
public abstract Rotation3d getRawRotation3dDegrees();

/**
* Gets the acceleration from the IMU in meters per second squared.
* @return {@link Rotation3d} of the acceleration from the IMU in meters per second squared.
*/
@NotNull
public abstract Rotation3d getAccelerationMetersPerSecondSquared();

/**
* Sets the offset of the gyroscope.
* @param offset the offset of the gyroscope.
*/
public void setOffset(@NotNull Rotation3d offset) {
this.offset = offset;
}

/**
* Gets the offset of the gyroscope.
* @return {@link Rotation3d} the offset of the gyroscope.
*/
@NotNull
public Rotation3d getOffset() {
return offset;
}

/**
* Calibrates the gyroscope.
*/
public abstract void calibrate();

/**
* Resets the gyroscope.
*/
public abstract void reset();

/**
* Returns the raw gyroscope object.
* Should only be used when you know the subclass of the gyroscope.
* <br><br>
* Implementations should override the return type to the type of the gyroscope used in the vendor's API.
* (e.g the {@link ADIS16448IMU} would return {@link edu.wpi.first.wpilibj.ADIS16448_IMU})
* @return the raw gyroscope object.
*/
@NotNull
public abstract Object getRawIMU();

/**
* Represents the three axes of a gyroscope.
*/
public enum IMUAxis {
X, Y, Z
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.frc5183.librobot.hardware.gyro.single;

import edu.wpi.first.math.geometry.Rotation2d;

Check warning on line 3 in src/main/java/net/frc5183/librobot/hardware/gyro/single/SingleAxisGyroscope.java

View workflow job for this annotation

GitHub Actions / pmd

Unused import 'edu.wpi.first.math.geometry.Rotation2d'

Reports import statements that can be removed. They are either unused, duplicated, or the members they import are already implicitly in scope, because they're in java.lang, or the current package. If some imports cannot be resolved, for instance because you run PMD with an incomplete auxiliary classpath, some imports may be conservatively marked as used even if they're not to avoid false positives. UnnecessaryImport (Priority: 4, Ruleset: Code Style) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_codestyle.html#unnecessaryimport

public abstract class SingleAxisGyroscope {

Check failure on line 5 in src/main/java/net/frc5183/librobot/hardware/gyro/single/SingleAxisGyroscope.java

View workflow job for this annotation

GitHub Actions / pmd

No abstract method which means that the keyword is most likely used to prevent instantiation. Use a private or protected constructor instead.

If an abstract class does not provide any methods, it may be acting as a simple data container that is not meant to be instantiated. In this case, it is probably better to use a private or protected constructor in order to prevent instantiation than make the class misleadingly abstract. AbstractClassWithoutAnyMethod (Priority: 1, Ruleset: Design) https://docs.pmd-code.org/pmd-doc-7.6.0/pmd_rules_java_design.html#abstractclasswithoutanymethod
// todo
public enum Axis {
YAW, PITCH, ROLL
}
}
Loading