(
+ new JSONSync<>(
new ExampleJsonSyncClass(),
"filePath",
new JSONSync.JSONSyncConfigBuilder().build());
public final String testText = "";
+
public final Double testDouble = 0.0;
+
public Integer testInt = 0;
+
public final BasicMotorDataHolder motorData = null;
+ /** Nested class to represent motor-related data. */
public class BasicMotorDataHolder {
+
public final Double maxVoltage = 0.0;
+
public final Double minVoltage = 0.0;
+
public Double currentVoltage = 0.0;
+ @Override
public String toString() {
return "minVoltage: "
+ minVoltage
@@ -30,6 +59,7 @@ public String toString() {
}
}
+ @Override
public String toString() {
return "testText: "
+ testText
diff --git a/parameter_tools/src/test/java/JSONSyncTests.java b/parameter_tools/src/test/java/JSONSyncTests.java
index fb328a2..d69ccef 100644
--- a/parameter_tools/src/test/java/JSONSyncTests.java
+++ b/parameter_tools/src/test/java/JSONSyncTests.java
@@ -6,50 +6,77 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+/**
+ * Unit tests for the {@link JSONSync} class to validate its functionality, including data loading,
+ * file setting, and data saving.
+ *
+ * This test class uses JUnit 5 to ensure that {@link JSONSync} correctly serializes and
+ * deserializes objects to and from JSON files. It also verifies that {@link JSONSync} updates files
+ * when data changes.
+ */
public class JSONSyncTests {
+ /** Directory paths for storing and accessing test JSON files. */
public static final String DIRECTORY = new File("").getAbsolutePath();
+
public static final String BUILD_DIRECTORY = DIRECTORY + "/build";
public static final String RESOURCE_DIRECTORY = BUILD_DIRECTORY + "/resources/test";
+ /**
+ * Prepares a new {@link JSONSync} instance with a predefined configuration and file path before
+ * each test.
+ */
@BeforeEach
public void TestPrep() {
ExampleJsonSyncClass.synced =
- new JSONSync(
+ new JSONSync<>(
new ExampleJsonSyncClass(),
RESOURCE_DIRECTORY + "/ExampleJsonSyncClass.json",
new JSONSync.JSONSyncConfigBuilder().setPrettyPrinting(true).build());
}
+ /**
+ * Tests the {@link JSONSync#loadData} method to ensure data is correctly loaded from a JSON
+ * file.
+ */
@Test
public void JsonSyncLoadDataTest() {
ExampleJsonSyncClass.synced.loadData();
ExampleJsonSyncClass instance = ExampleJsonSyncClass.synced.getObject();
- Assertions.assertEquals(10.0, instance.testDouble);
- Assertions.assertEquals(2, instance.testInt);
- Assertions.assertNull(instance.motorData);
+ Assertions.assertEquals(10.0, instance.testDouble, "testDouble should be 10.0");
+ Assertions.assertEquals(2, instance.testInt, "testInt should be 2");
+ Assertions.assertNull(instance.motorData, "motorData should be null");
}
+ /**
+ * Tests the {@link JSONSync#setFile} method to verify it properly updates the file path and
+ * loads data from the newly specified file.
+ */
@Test
public void JsonSyncSetFileTest() {
ExampleJsonSyncClass.synced.setFile(RESOURCE_DIRECTORY + "/SetFileTest.json");
ExampleJsonSyncClass.synced.loadData();
ExampleJsonSyncClass instance = ExampleJsonSyncClass.synced.getObject();
- Assertions.assertEquals(10.0, instance.testDouble);
- Assertions.assertEquals(2, instance.testInt);
- Assertions.assertNotNull(instance.motorData);
- Assertions.assertEquals(-12.3, instance.motorData.minVoltage);
- Assertions.assertEquals(16.4, instance.motorData.maxVoltage);
- Assertions.assertEquals(0.0, instance.motorData.currentVoltage);
+ Assertions.assertEquals(10.0, instance.testDouble, "testDouble should be 10.0");
+ Assertions.assertEquals(2, instance.testInt, "testInt should be 2");
+ Assertions.assertNotNull(instance.motorData, "motorData should not be null");
+ Assertions.assertEquals(-12.3, instance.motorData.minVoltage, "minVoltage should be -12.3");
+ Assertions.assertEquals(16.4, instance.motorData.maxVoltage, "maxVoltage should be 16.4");
+ Assertions.assertEquals(
+ 0.0, instance.motorData.currentVoltage, "currentVoltage should be 0.0");
}
+ /**
+ * Tests the {@link JSONSync#saveData} method to ensure changes to an object are serialized and
+ * saved to a JSON file correctly.
+ */
@Test
public void JsonSyncSaveFileTest() {
ExampleJsonSyncClass.synced.loadData();
ExampleJsonSyncClass instance = ExampleJsonSyncClass.synced.getObject();
- instance.testInt = 10;
+ instance.testInt = 10; // Modify a value in the object
ExampleJsonSyncClass.synced.setFile(RESOURCE_DIRECTORY + "/SaveFileTest.json");
ExampleJsonSyncClass.synced.saveData();
}
diff --git a/vision/src/main/java/coppercore/vision/Camera.java b/vision/src/main/java/coppercore/vision/Camera.java
index 48c6597..ccd50c0 100644
--- a/vision/src/main/java/coppercore/vision/Camera.java
+++ b/vision/src/main/java/coppercore/vision/Camera.java
@@ -6,12 +6,25 @@
import edu.wpi.first.math.numbers.N3;
import org.littletonrobotics.junction.Logger;
+/**
+ * Represents a PhotonVision camera by wrapping a {@link CameraIO} interface. This class is
+ * responsible for managing the camera's IO, logging camera data, calculating standard deviations,
+ * assembling {@link CameraMeasurement} objects, and updating the camera's state.
+ */
public class Camera {
+ /** The name of the camera, typically defined in {@link CameraParams}. */
public final String name;
private final CameraIO io;
private final CameraIOInputsAutoLogged inputs;
+ /**
+ * Constructs a new {@code Camera} instance.
+ *
+ * @param params The parameters used to configure the camera, such as its name.
+ * @param io The {@link CameraIO} instance that provides the camera's input/output
+ * functionality.
+ */
public Camera(CameraParams params, CameraIO io) {
name = params.name();
@@ -19,24 +32,53 @@ public Camera(CameraParams params, CameraIO io) {
inputs = new CameraIOInputsAutoLogged();
}
+ /**
+ * Updates the camera's inputs by polling the {@link CameraIO} and processes the data for
+ * logging using the {@link Logger}.
+ */
public void update() {
io.updateInputs(inputs);
Logger.processInputs("Vision/" + name, inputs);
}
+ /**
+ * Checks if the camera has new measurements available.
+ *
+ * @return {@code true} if new measurements are available, as indicated by {@link
+ * coppercore.vision.CameraIO.CameraIOInputs#wasAccepted}.
+ */
public boolean hasNewMeasurement() {
return inputs.wasAccepted;
}
+ /**
+ * Checks if the camera is currently connected.
+ *
+ * @return {@code true} if the camera is connected, as indicated by {@link
+ * coppercore.vision.CameraIO.CameraIOInputs#connected}.
+ */
public boolean isConnected() {
return inputs.connected;
}
+ /**
+ * Retrieves the latest measurement from the camera, including the field-to-robot
+ * transformation, timestamp, and variance.
+ *
+ * @return A {@link CameraMeasurement} object containing the latest data.
+ */
public CameraMeasurement getLatestMeasurement() {
return new CameraMeasurement(
inputs.latestFieldToRobot, inputs.latestTimestampSeconds, getLatestVariance());
}
+ /**
+ * Calculates the variance of the latest measurement based on the distance to the target and the
+ * number of detected tags.
+ *
+ * @return A {@link Matrix} representing the variance of the latest measurement, with dimensions
+ * {@code N3 x N1}.
+ */
public Matrix getLatestVariance() {
Matrix stdDev = CoreVisionConstants.singleTagStdDev;
// TODO: Actually calculate variances!
@@ -52,7 +94,7 @@ public Matrix getLatestVariance() {
return CoreVisionConstants.rejectionStdDev;
}
- // distance based variance
+ // Distance-based variance
stdDev =
stdDev.times(
1
diff --git a/vision/src/main/java/coppercore/vision/CameraContainer.java b/vision/src/main/java/coppercore/vision/CameraContainer.java
index 40bbc78..e44f16b 100644
--- a/vision/src/main/java/coppercore/vision/CameraContainer.java
+++ b/vision/src/main/java/coppercore/vision/CameraContainer.java
@@ -2,10 +2,22 @@
import java.util.List;
-/** This is not an AdvantageKit IO interface, but a class to hold cameras and associated data */
+/**
+ * Represents a container for managing multiple {@link Camera} objects and their associated data.
+ * This interface provides methods to retrieve the cameras and update their state.
+ *
+ * Note: This is not an AdvantageKit IO interface but rather a utility for grouping and managing
+ * cameras.
+ */
public interface CameraContainer {
+ /**
+ * Retrieves the list of {@link Camera} objects managed by this container.
+ *
+ * @return A {@link List} of {@link Camera} objects.
+ */
public List getCameras();
+ /** Updates the state of all {@link Camera} objects in the container. */
public void update();
}
diff --git a/vision/src/main/java/coppercore/vision/CameraContainerReal.java b/vision/src/main/java/coppercore/vision/CameraContainerReal.java
index fcf6bc5..3f48221 100644
--- a/vision/src/main/java/coppercore/vision/CameraContainerReal.java
+++ b/vision/src/main/java/coppercore/vision/CameraContainerReal.java
@@ -4,20 +4,42 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * A implementation of {@link CameraContainer} that manages a list of {@link Camera} objects for
+ * real-life matches. This class initializes cameras based on a list of {@link CameraParams} and an
+ * {@link AprilTagFieldLayout}, and provides methods to retrieve and update them.
+ */
public class CameraContainerReal implements CameraContainer {
private List cameras = new ArrayList<>();
+ /**
+ * Constructs a {@code CameraContainerReal} with a list of camera parameters and an AprilTag
+ * field layout. Each {@link Camera} is initialized with the given parameters and a
+ * corresponding {@link CameraIOPhoton}.
+ *
+ * @param params the list of {@link CameraParams} used to configure the cameras
+ * @param layout the {@link AprilTagFieldLayout} associated with the cameras
+ */
public CameraContainerReal(List params, AprilTagFieldLayout layout) {
for (CameraParams param : params) {
cameras.add(new Camera(param, CameraIOPhoton.fromRealCameraParams(param, layout)));
}
}
+ /**
+ * Retrieves the list of cameras managed by this container.
+ *
+ * @return a {@link List} of {@link Camera} objects
+ */
public List getCameras() {
return cameras;
}
+ /**
+ * Updates all cameras in the container by invoking their {@link Camera#update()} method. This
+ * ensures the cameras are synchronized with the latest data.
+ */
public void update() {
for (Camera camera : cameras) {
camera.update();
diff --git a/vision/src/main/java/coppercore/vision/CameraContainerReplay.java b/vision/src/main/java/coppercore/vision/CameraContainerReplay.java
index 1d207df..ad0e9b8 100644
--- a/vision/src/main/java/coppercore/vision/CameraContainerReplay.java
+++ b/vision/src/main/java/coppercore/vision/CameraContainerReplay.java
@@ -3,19 +3,39 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * CameraContainerReplay simulates a container for cameras in a replay system. It does not interact
+ * with a real camera or simulation, and instead it updates the cameras based on replayed data.
+ */
public class CameraContainerReplay implements CameraContainer {
private List cameras = new ArrayList<>();
+ /**
+ * Initializes the CameraContainerReplay with the specified camera parameters.
+ *
+ * @param params A list of camera parameters for the replay.
+ */
public CameraContainerReplay(List params) {
for (CameraParams param : params) {
- cameras.add(new Camera(param, new CameraIO() {}));
+ cameras.add(new Camera(param, new CameraIO() {})); // Use a no-op CameraIO for replay
}
}
+ /**
+ * Gets the list of cameras in the replay system.
+ *
+ * @return A list of cameras.
+ */
+ @Override
public List getCameras() {
return cameras;
}
+ /**
+ * Updates the cameras by calling the update method on each camera. This does not interact with
+ * a real vision system but updates based on replayed data.
+ */
+ @Override
public void update() {
for (Camera camera : cameras) {
camera.update();
diff --git a/vision/src/main/java/coppercore/vision/CameraContainerSim.java b/vision/src/main/java/coppercore/vision/CameraContainerSim.java
index dc215fc..1244f27 100644
--- a/vision/src/main/java/coppercore/vision/CameraContainerSim.java
+++ b/vision/src/main/java/coppercore/vision/CameraContainerSim.java
@@ -2,7 +2,6 @@
import edu.wpi.first.apriltag.AprilTagFieldLayout;
import edu.wpi.first.math.geometry.Pose2d;
-import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Twist2d;
import edu.wpi.first.math.kinematics.SwerveDriveKinematics;
import edu.wpi.first.math.kinematics.SwerveModulePosition;
@@ -15,12 +14,14 @@
import org.littletonrobotics.junction.Logger;
import org.photonvision.simulation.VisionSystemSim;
+/**
+ * CameraContainerSim is used for handling cameras in a sim. It simulates the camera's interactions
+ * with the robot's state and the field's layout.
+ */
public class CameraContainerSim implements CameraContainer {
private VisionSystemSim visionSim = new VisionSystemSim("main");
-
private List cameras = new ArrayList<>();
-
private Supplier getModuleStates;
private Pose2d latestOdometryPose;
private SwerveModulePosition[] lastModulePositions =
@@ -31,9 +32,17 @@ public class CameraContainerSim implements CameraContainer {
new SwerveModulePosition()
};
private Timer dtTimer = new Timer();
-
- SwerveDriveKinematics kinematics;
-
+ private SwerveDriveKinematics kinematics;
+
+ /**
+ * Initializes a CameraContainerSim with camera parameters and field layout.
+ *
+ * @param params A list of camera parameters for the simulation.
+ * @param layout The layout of the AprilTags in the simulation.
+ * @param initialPose The initial pose of the robot.
+ * @param kinematics The kinematics for the robot's swerve drive.
+ * @param getModuleStates A supplier for the current swerve module states.
+ */
public CameraContainerSim(
List params,
AprilTagFieldLayout layout,
@@ -41,16 +50,10 @@ public CameraContainerSim(
SwerveDriveKinematics kinematics,
Supplier getModuleStates) {
this.getModuleStates = getModuleStates;
-
visionSim.addAprilTags(layout);
-
this.kinematics = kinematics;
-
latestOdometryPose =
- new Pose2d(
- initialPose.getX(),
- initialPose.getY(),
- Rotation2d.fromRadians(initialPose.getRotation().getRadians()));
+ new Pose2d(initialPose.getX(), initialPose.getY(), initialPose.getRotation());
for (CameraParams param : params) {
cameras.add(
@@ -60,10 +63,21 @@ public CameraContainerSim(
}
}
+ /**
+ * Gets the list of cameras in the simulation.
+ *
+ * @return A list of cameras.
+ */
+ @Override
public List getCameras() {
return cameras;
}
+ /**
+ * Updates the odometry and camera states for the simulation. Updates both the simulated robot
+ * pose and camera measurements.
+ */
+ @Override
public void update() {
updateOdometry();
visionSim.update(latestOdometryPose);
@@ -74,24 +88,20 @@ public void update() {
}
}
+ /** Updates the robot's odometry based on the latest swerve module states. */
private void updateOdometry() {
- SwerveModulePosition[] deltas = new SwerveModulePosition[4];
SwerveModuleState[] states = getModuleStates.get();
-
double dt = dtTimer.get();
dtTimer.reset();
dtTimer.start();
+ SwerveModulePosition[] deltas = new SwerveModulePosition[4];
for (int i = 0; i < states.length; i++) {
deltas[i] =
new SwerveModulePosition(
states[i].speedMetersPerSecond * dt
- lastModulePositions[i].distanceMeters,
- Rotation2d.fromRadians(
- states[i]
- .angle
- .minus(lastModulePositions[i].angle)
- .getRadians()));
+ states[i].angle.minus(lastModulePositions[i].angle));
}
Twist2d twist = kinematics.toTwist2d(deltas);
diff --git a/vision/src/main/java/coppercore/vision/CameraIO.java b/vision/src/main/java/coppercore/vision/CameraIO.java
index 5bb298d..41fef94 100644
--- a/vision/src/main/java/coppercore/vision/CameraIO.java
+++ b/vision/src/main/java/coppercore/vision/CameraIO.java
@@ -4,25 +4,52 @@
import edu.wpi.first.math.geometry.Rotation2d;
import org.littletonrobotics.junction.AutoLog;
+/**
+ * Interface representing the input/output (IO) functionality for a camera in the vision system.
+ * This interface provides a method to update camera inputs and includes an inner class for
+ * encapsulating camera-related data.
+ */
public interface CameraIO {
+ /**
+ * Class representing the inputs from a camera, including pose, tag information, and connection
+ * status.
+ */
@AutoLog
public static class CameraIOInputs {
+ /** The most recent pose of the robot relative to the field, as calculated by the camera. */
public Pose3d latestFieldToRobot = new Pose3d();
+
+ /** The average distance to detected tags in meters. */
public double averageTagDistanceM = 0.0;
+
+ /** The average yaw (rotation) of detected tags, represented as a {@link Rotation2d}. */
public Rotation2d averageTagYaw = new Rotation2d();
+
+ /** The number of tags currently detected by the camera. */
public int nTags = 0;
+ /** The timestamp of the latest measurement in seconds. */
public double latestTimestampSeconds = 0.0;
+
+ /** Whether the camera is currently connected. */
public boolean connected = false;
+
+ /** Indicates if a new measurement has been received from the camera. */
public boolean isNewMeasurement = false;
/**
- * Whether the new camera measurement was accepted by the initial filters. Always false if
- * `isNewMeasurement` is false.
+ * Indicates whether the new camera measurement was accepted by the initial filters. This is
+ * always {@code false} if {@code isNewMeasurement} is {@code false}.
*/
public boolean wasAccepted = false;
}
+ /**
+ * Updates the provided {@link CameraIOInputs} object with the latest camera data. This default
+ * implementation does nothing and should be overridden by implementing classes.
+ *
+ * @param inputs The {@link CameraIOInputs} object to update with the latest camera data.
+ */
public default void updateInputs(CameraIOInputs inputs) {}
}
diff --git a/vision/src/main/java/coppercore/vision/CameraIOPhoton.java b/vision/src/main/java/coppercore/vision/CameraIOPhoton.java
index a76c79f..84504e1 100644
--- a/vision/src/main/java/coppercore/vision/CameraIOPhoton.java
+++ b/vision/src/main/java/coppercore/vision/CameraIOPhoton.java
@@ -14,16 +14,42 @@
import org.photonvision.targeting.PhotonPipelineResult;
import org.photonvision.targeting.PhotonTrackedTarget;
+/**
+ * An implementation of {@link CameraIO} that integrates with PhotonVision cameras for real-time
+ * pose estimation using AprilTags. This class handles camera updates, data simulation, and
+ * field-to-robot transformations.
+ *
+ * This class supports both real-world and simulated cameras and provides utility methods for
+ * processing tag data such as distances and yaw angles.
+ */
public class CameraIOPhoton implements CameraIO {
+
private final PhotonCamera camera;
private final PhotonPoseEstimator poseEstimator;
-
private double latestTimestampSeconds = 0.0;
+ /**
+ * Creates a new {@code CameraIOPhoton} instance using a camera name, field layout, and the
+ * robot-to-camera transform.
+ *
+ * @param name The name of the camera.
+ * @param layout The {@link AprilTagFieldLayout} describing the field's AprilTag configuration.
+ * @param robotToCamera The {@link Transform3d} representing the transformation from the robot
+ * to the camera.
+ */
public CameraIOPhoton(String name, AprilTagFieldLayout layout, Transform3d robotToCamera) {
this(new PhotonCamera(name), layout, robotToCamera);
}
+ /**
+ * Creates a new {@code CameraIOPhoton} instance using an existing PhotonCamera object, field
+ * layout, and the robot-to-camera transform.
+ *
+ * @param camera The {@link PhotonCamera} instance to use.
+ * @param layout The {@link AprilTagFieldLayout} describing the field's AprilTag configuration.
+ * @param robotToCamera The {@link Transform3d} representing the transformation from the robot
+ * to the camera.
+ */
public CameraIOPhoton(
PhotonCamera camera, AprilTagFieldLayout layout, Transform3d robotToCamera) {
this.camera = camera;
@@ -34,11 +60,27 @@ public CameraIOPhoton(
poseEstimator.setMultiTagFallbackStrategy(PoseStrategy.LOWEST_AMBIGUITY);
}
+ /**
+ * Factory method for creating a {@code CameraIOPhoton} instance for real cameras.
+ *
+ * @param params The {@link CameraParams} object containing camera parameters.
+ * @param layout The {@link AprilTagFieldLayout} describing the field's AprilTag configuration.
+ * @return A {@code CameraIOPhoton} instance configured for real cameras.
+ */
public static CameraIOPhoton fromRealCameraParams(
CameraParams params, AprilTagFieldLayout layout) {
return new CameraIOPhoton(params.name(), layout, params.robotToCamera());
}
+ /**
+ * Factory method for creating a {@code CameraIOPhoton} instance for simulated cameras.
+ *
+ * @param params The {@link CameraParams} object containing camera parameters.
+ * @param layout The {@link AprilTagFieldLayout} describing the field's AprilTag configuration.
+ * @param sim The {@link VisionSystemSim} instance managing the simulation.
+ * @param stream Whether to enable raw and processed streams for the simulation.
+ * @return A {@code CameraIOPhoton} instance configured for simulated cameras.
+ */
public static CameraIOPhoton fromSimCameraParams(
CameraParams params, AprilTagFieldLayout layout, VisionSystemSim sim, boolean stream) {
PhotonCamera camera = new PhotonCamera(params.name());
@@ -57,6 +99,11 @@ public static CameraIOPhoton fromSimCameraParams(
return new CameraIOPhoton(camera, layout, params.robotToCamera());
}
+ /**
+ * Updates the {@link CameraIOInputs} object with the latest data from the PhotonVision camera.
+ *
+ * @param inputs The {@link CameraIOInputs} object to populate with the latest camera data.
+ */
@Override
public void updateInputs(CameraIOInputs inputs) {
inputs.connected = camera.isConnected();
@@ -86,17 +133,13 @@ public void updateInputs(CameraIOInputs inputs) {
});
}
- // NOTE: Can be used in 2025 code just not ready yet
- // private Optional getEstimatedPose () {
- // Optional visionEstimate = Optional.empty();
-
- // for (var change : camera.getAllUnreadResults()) {
- // visionEstimate = poseEstimator.update(change);
- // }
-
- // return visionEstimate;
- // }
-
+ /**
+ * Calculates the average distance from the robot to detected AprilTags.
+ *
+ * @param pose The {@link EstimatedRobotPose} containing the detected tags.
+ * @param inputs The {@link CameraIOInputs} object to populate with the calculated distance and
+ * tag count.
+ */
private void calculateAverageTagDistance(EstimatedRobotPose pose, CameraIOInputs inputs) {
double distance = 0.0;
int numTags = 0;
@@ -118,6 +161,12 @@ private void calculateAverageTagDistance(EstimatedRobotPose pose, CameraIOInputs
inputs.averageTagDistanceM = distance;
}
+ /**
+ * Calculates the average yaw of detected AprilTags.
+ *
+ * @param pose The {@link EstimatedRobotPose} containing the detected tags.
+ * @return The average yaw as a {@link Rotation2d}.
+ */
private static Rotation2d calculateAverageTagYaw(EstimatedRobotPose pose) {
double yawRad = 0.0;
for (PhotonTrackedTarget target : pose.targetsUsed) {
diff --git a/vision/src/main/java/coppercore/vision/CameraParams.java b/vision/src/main/java/coppercore/vision/CameraParams.java
index a92b1f5..3131465 100644
--- a/vision/src/main/java/coppercore/vision/CameraParams.java
+++ b/vision/src/main/java/coppercore/vision/CameraParams.java
@@ -3,6 +3,16 @@
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Transform3d;
+/**
+ * Represents the configuration parameters for a camera.
+ *
+ * @param name The camera name.
+ * @param xResolution Horizontal resolution in pixels.
+ * @param yResolution Vertical resolution in pixels.
+ * @param fps Frames per second.
+ * @param fov Field of view as a {@link Rotation2d}.
+ * @param robotToCamera Transform from the robot to the camera as a {@link Transform3d}.
+ */
public record CameraParams(
String name,
int xResolution,
diff --git a/vision/src/main/java/coppercore/vision/CoreVisionConstants.java b/vision/src/main/java/coppercore/vision/CoreVisionConstants.java
index 47f8390..8441051 100644
--- a/vision/src/main/java/coppercore/vision/CoreVisionConstants.java
+++ b/vision/src/main/java/coppercore/vision/CoreVisionConstants.java
@@ -11,7 +11,7 @@
* per-project.
*/
public final class CoreVisionConstants {
- // TODO: Tune this value
+ // TODO: Tune this value.
// This value mainly exists so that this file stays named CoreVisionConstants.
public static final double maxAcceptedDistanceMeters = 10.0;
public static final Matrix singleTagStdDev = VecBuilder.fill(1, 1, 1);
diff --git a/vision/src/main/java/coppercore/vision/LayoutUtil.java b/vision/src/main/java/coppercore/vision/LayoutUtil.java
index 368fc7e..fd14e89 100644
--- a/vision/src/main/java/coppercore/vision/LayoutUtil.java
+++ b/vision/src/main/java/coppercore/vision/LayoutUtil.java
@@ -6,11 +6,18 @@
import java.io.IOException;
import java.util.Collections;
+/** Utility class for loading an AprilTag field layout from a JSON file. */
public class LayoutUtil {
+ /**
+ * Initializes an AprilTag field layout from a JSON file located in the deploy directory. If the
+ * layout fails to load, an empty layout is returned and a warning is logged.
+ *
+ * @param name The name of the layout file (without the .json extension).
+ * @return The initialized {@link AprilTagFieldLayout}.
+ */
public static AprilTagFieldLayout initLayout(String name) {
AprilTagFieldLayout layout;
// AprilTagFieldLayout's constructor throws an IOException, so we must catch it
- // in order to initialize our layout as a static constant
try {
layout =
new AprilTagFieldLayout(
diff --git a/vision/src/main/java/coppercore/vision/VisionLocalizer.java b/vision/src/main/java/coppercore/vision/VisionLocalizer.java
index fb8b21e..d8731bd 100644
--- a/vision/src/main/java/coppercore/vision/VisionLocalizer.java
+++ b/vision/src/main/java/coppercore/vision/VisionLocalizer.java
@@ -7,17 +7,27 @@
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import java.util.function.Consumer;
+/**
+ * Localizes the robot using camera measurements. Periodically updates camera data and allows for
+ * custom handling of new measurements.
+ */
public class VisionLocalizer extends SubsystemBase {
private CameraContainer container;
- // avoid NullPointerExceptions by setting a default no-op
+ // Default no-op consumer to avoid NullPointerExceptions
private Consumer cameraConsumer = (c) -> {};
+ /**
+ * Constructs a VisionLocalizer with a given camera container.
+ *
+ * @param container The container holding cameras for localization.
+ */
public VisionLocalizer(CameraContainer container) {
this.container = container;
}
+ /** Periodically updates the camera data and processes new measurements. */
@Override
public void periodic() {
container.update();
@@ -28,18 +38,25 @@ public void periodic() {
}
}
+ /**
+ * Sets a custom consumer for handling camera measurements.
+ *
+ * @param cameraConsumer The consumer to handle new camera measurements.
+ */
public void setCameraConsumer(Consumer cameraConsumer) {
this.cameraConsumer = cameraConsumer;
}
+ /**
+ * Checks if the coprocessor is connected.
+ *
+ * @return True if the coprocessor is connected, otherwise false.
+ */
public boolean coprocessorConnected() {
return container.getCameras().get(0).isConnected();
}
- /**
- * This class exists solely because java has no functional interface for a function with 3
- * inputs
- */
+ /** Represents a camera measurement with a pose, timestamp, and variance. */
public static record CameraMeasurement(
Pose3d pose, double timestamp, Matrix variance) {}
}