Skip to content

Commit

Permalink
Merge pull request #18 from chopshop-166/vision-lib
Browse files Browse the repository at this point in the history
Vision lib
  • Loading branch information
msoucy authored Jan 30, 2025
2 parents 2b308f6 + 088c29b commit 79fc652
Show file tree
Hide file tree
Showing 8 changed files with 444 additions and 149 deletions.
41 changes: 41 additions & 0 deletions src/main/java/com/chopshop166/chopshoplib/maps/CameraSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.chopshop166.chopshoplib.maps;

import org.photonvision.PhotonCamera;
import org.photonvision.PhotonPoseEstimator;
import org.photonvision.PhotonPoseEstimator.PoseStrategy;
import edu.wpi.first.apriltag.AprilTagFieldLayout;
import edu.wpi.first.apriltag.AprilTagFields;
import edu.wpi.first.math.geometry.Transform3d;

/** Simplified wrapper around a camera with a pose estimator. */
public class CameraSource {
/** The default field, loaded for convenience. */
public static final AprilTagFieldLayout DEFAULT_FIELD = AprilTagFieldLayout.loadField(AprilTagFields.kDefaultField);
/** The camera object. */
public final PhotonCamera camera;
/** The pose estimator. */
public final PhotonPoseEstimator estimator;

/**
* Constructor.
*
* @param cameraName The camera's name in Photon Vision.
* @param robotToCam The offset of the camera from the center of the robot.
*/
public CameraSource(final String cameraName, final Transform3d robotToCam) {
this(new PhotonCamera(cameraName), robotToCam);
}

/**
* Constructor.
*
* @param cameraName The camera object.
* @param robotToCam The offset of the camera from the center of the robot.
*/
public CameraSource(final PhotonCamera camera, final Transform3d robotToCam) {
this.camera = camera;
this.estimator = new PhotonPoseEstimator(DEFAULT_FIELD,
PoseStrategy.MULTI_TAG_PNP_ON_COPROCESSOR, robotToCam);
this.estimator.setMultiTagFallbackStrategy(PoseStrategy.LOWEST_AMBIGUITY);
}
}
54 changes: 54 additions & 0 deletions src/main/java/com/chopshop166/chopshoplib/maps/VisionMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.chopshop166.chopshoplib.maps;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import edu.wpi.first.math.estimator.PoseEstimator;

public class VisionMap {

/** Camera-based position estimators. */
public final List<CameraSource> visionSources;

/** Default constructor. */
public VisionMap() {
this(new ArrayList<>());
}

/**
* Constructor.
*
* @param visionSources Any number of vision sources.
*/
public VisionMap(final CameraSource... visionSources) {
this(Arrays.asList(visionSources));
}

/**
* Constructor.
*
* @param visionSources A list of vision sources.
*/
public VisionMap(final List<CameraSource> visionSources) {
this.visionSources = visionSources;
}

/**
* Update the data in a pose estimator with the poses from all cameras.
*
* @param <T> Estimator wheel type.
* @param estimator The WPIlib estimator object.
*/
public <T> void updateData(final PoseEstimator<T> estimator) {
for (var source : this.visionSources) {
var results = source.camera.getAllUnreadResults();
if (!results.isEmpty()) {
var estimate = source.estimator.update(results.get(results.size() - 1));
estimate.ifPresent(est -> {
estimator.addVisionMeasurement(est.estimatedPose.toPose2d(),
est.timestampSeconds);
});
}
}
}
}
170 changes: 170 additions & 0 deletions src/main/java/frc/robot/FieldConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package frc.robot;

// Copyright (c) 2025 FRC 6328
// http://github.com/Mechanical-Advantage
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file at
// the root directory of this project.

import edu.wpi.first.math.geometry.*;
import edu.wpi.first.math.util.Units;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Contains various field dimensions and useful reference points. All units are
* in meters and poses
* have a blue alliance origin.
*/
public class FieldConstants {
public static final double fieldLength = Units.inchesToMeters(690.876);
public static final double fieldWidth = Units.inchesToMeters(317);
public static final double startingLineX = Units.inchesToMeters(299.438); // Measured from the inside of starting
// line

public static class Processor {
public static final Pose2d centerFace = new Pose2d(Units.inchesToMeters(235.726), 0,
Rotation2d.fromDegrees(90));
}

public static class Barge {
public static final Translation2d farCage = new Translation2d(Units.inchesToMeters(345.428),
Units.inchesToMeters(286.779));
public static final Translation2d middleCage = new Translation2d(Units.inchesToMeters(345.428),
Units.inchesToMeters(242.855));
public static final Translation2d closeCage = new Translation2d(Units.inchesToMeters(345.428),
Units.inchesToMeters(199.947));

// Measured from floor to bottom of cage
public static final double deepHeight = Units.inchesToMeters(3.125);
public static final double shallowHeight = Units.inchesToMeters(30.125);
}

public static class CoralStation {
public static final Pose2d leftCenterFace = new Pose2d(
Units.inchesToMeters(33.526),
Units.inchesToMeters(291.176),
Rotation2d.fromDegrees(90 - 144.011));
public static final Pose2d rightCenterFace = new Pose2d(
Units.inchesToMeters(33.526),
Units.inchesToMeters(25.824),
Rotation2d.fromDegrees(144.011 - 90));
}

public static class Reef {
public static final Translation2d center = new Translation2d(Units.inchesToMeters(176.746),
Units.inchesToMeters(158.501));
public static final double faceToZoneLine = Units.inchesToMeters(12); // Side of the reef to the inside of the
// reef zone line

public static final Pose2d[] centerFaces = new Pose2d[6]; // Starting facing the driver station in clockwise
// order
public static final List<Map<ReefHeight, Pose3d>> branchPositions = new ArrayList<>(); // Starting at the right
// branch facing the
// driver station in
// clockwise

static {
// Initialize faces
centerFaces[0] = new Pose2d(
Units.inchesToMeters(144.003),
Units.inchesToMeters(158.500),
Rotation2d.fromDegrees(180));
centerFaces[1] = new Pose2d(
Units.inchesToMeters(160.373),
Units.inchesToMeters(186.857),
Rotation2d.fromDegrees(120));
centerFaces[2] = new Pose2d(
Units.inchesToMeters(193.116),
Units.inchesToMeters(186.858),
Rotation2d.fromDegrees(60));
centerFaces[3] = new Pose2d(
Units.inchesToMeters(209.489),
Units.inchesToMeters(158.502),
Rotation2d.fromDegrees(0));
centerFaces[4] = new Pose2d(
Units.inchesToMeters(193.118),
Units.inchesToMeters(130.145),
Rotation2d.fromDegrees(-60));
centerFaces[5] = new Pose2d(
Units.inchesToMeters(160.375),
Units.inchesToMeters(130.144),
Rotation2d.fromDegrees(-120));

// Initialize branch positions
for (int face = 0; face < 6; face++) {
Map<ReefHeight, Pose3d> fillRight = new HashMap<>();
Map<ReefHeight, Pose3d> fillLeft = new HashMap<>();
for (var level : ReefHeight.values()) {
Pose2d poseDirection = new Pose2d(center, Rotation2d.fromDegrees(180 - (60 * face)));
double adjustX = Units.inchesToMeters(30.738);
double adjustY = Units.inchesToMeters(6.469);

fillRight.put(
level,
new Pose3d(
new Translation3d(
poseDirection
.transformBy(new Transform2d(adjustX, adjustY, new Rotation2d()))
.getX(),
poseDirection
.transformBy(new Transform2d(adjustX, adjustY, new Rotation2d()))
.getY(),
level.height),
new Rotation3d(
0,
Units.degreesToRadians(level.pitch),
poseDirection.getRotation().getRadians())));
fillLeft.put(
level,
new Pose3d(
new Translation3d(
poseDirection
.transformBy(new Transform2d(adjustX, -adjustY, new Rotation2d()))
.getX(),
poseDirection
.transformBy(new Transform2d(adjustX, -adjustY, new Rotation2d()))
.getY(),
level.height),
new Rotation3d(
0,
Units.degreesToRadians(level.pitch),
poseDirection.getRotation().getRadians())));
}
branchPositions.add((face * 2) + 1, fillRight);
branchPositions.add((face * 2) + 2, fillLeft);
}
}
}

public static class StagingPositions {
// Measured from the center of the ice cream (coral marks)
public static final Pose2d leftIceCream = new Pose2d(Units.inchesToMeters(48), Units.inchesToMeters(230.5),
new Rotation2d());
public static final Pose2d middleIceCream = new Pose2d(Units.inchesToMeters(48), Units.inchesToMeters(158.5),
new Rotation2d());
public static final Pose2d rightIceCream = new Pose2d(Units.inchesToMeters(48), Units.inchesToMeters(86.5),
new Rotation2d());
}

public enum ReefHeight {
L4(Units.inchesToMeters(72), -90),
L3(Units.inchesToMeters(47.625), -35),
L2(Units.inchesToMeters(31.875), -35),
L1(Units.inchesToMeters(18), 0);

ReefHeight(double height, double pitch) {
this.height = height;
this.pitch = pitch; // in degrees
}

public final double height;
public final double pitch;
}

public static final double aprilTagWidth = Units.inchesToMeters(6.50);
public static final int aprilTagCount = 22;
}
4 changes: 3 additions & 1 deletion src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public final class Robot extends CommandRobot {
return driveScaler.applyAsDouble(-driveController.getLeftY());
}, () -> {
return driveScaler.applyAsDouble(-driveController.getRightX());
});
}, map.getVisionMap());
private Led led = new Led(map.getLedMap());
private AlgaeDestage algaeDestage = new AlgaeDestage(map.getAlgaeDestageMap());
private Outtake outtake = new Outtake(map.getOuttakeMap());
Expand Down Expand Up @@ -127,6 +127,8 @@ public void configureButtonBindings() {
driveController.x().whileTrue(outtake.scoreL1());
driveController.y().whileTrue(algaeDestage.destageAlgae());

driveController.rightBumper().whileTrue(drive.aimAtReefCenter());

}

@Override
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/frc/robot/maps/Alpha.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package frc.robot.maps;

import java.util.ArrayList;

import org.littletonrobotics.junction.Logger;
import org.littletonrobotics.junction.networktables.NT4Publisher;
import org.littletonrobotics.junction.wpilog.WPILOGWriter;

import com.chopshop166.chopshoplib.digital.CSDigitalInput;
import com.chopshop166.chopshoplib.drive.SDSSwerveModule;
import com.chopshop166.chopshoplib.drive.SDSSwerveModule.Configuration;
import com.chopshop166.chopshoplib.maps.CameraSource;
import com.chopshop166.chopshoplib.maps.RobotMapFor;
import com.chopshop166.chopshoplib.maps.SwerveDriveMap;
import com.chopshop166.chopshoplib.maps.VisionMap;
import com.chopshop166.chopshoplib.motors.CSSparkMax;
import com.chopshop166.chopshoplib.sensors.CtreEncoder;
import com.chopshop166.chopshoplib.sensors.gyro.PigeonGyro2;
Expand All @@ -21,6 +25,9 @@
import com.pathplanner.lib.controllers.PPHolonomicDriveController;

import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.geometry.Translation3d;
import edu.wpi.first.math.geometry.Transform3d;
import edu.wpi.first.math.geometry.Rotation3d;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj.PowerDistribution;
Expand Down Expand Up @@ -114,6 +121,16 @@ public SwerveDriveMap getDriveMap() {

}

@Override
public VisionMap getVisionMap() {
Transform3d kRobotToCam = new Transform3d(
new Translation3d(Units.inchesToMeters(-6.9965), Units.inchesToMeters(-3.029),
Units.inchesToMeters(12.445)),
new Rotation3d(0, Units.degreesToRadians(-16.875), Units.degreesToRadians(-6.5 + 180)));
return new VisionMap(new CameraSource("Camera", kRobotToCam));

}

@Override
public AlgaeDestageMap getAlgaeDestageMap() {
// CSSparkMax motor = new CSSparkMax(9);
Expand All @@ -136,7 +153,8 @@ public OuttakeMap getOuttakeMap() {

@Override
public void setupLogging() {
Logger.addDataReceiver(new WPILOGWriter("/media/sda1/")); // Log to a USB stick
// Logger.addDataReceiver(new WPILOGWriter("/media/sda1/")); // Log to a USB
// stick
Logger.addDataReceiver(new NT4Publisher()); // Publish data to NetworkTables
Logger.recordMetadata("RobotMap", this.getClass().getSimpleName());
new PowerDistribution(1, ModuleType.kRev); // Enables power distribution logging
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/frc/robot/maps/RobotMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.chopshop166.chopshoplib.maps.LedMapBase;
import com.chopshop166.chopshoplib.maps.MockLedMap;
import com.chopshop166.chopshoplib.maps.SwerveDriveMap;
import com.chopshop166.chopshoplib.maps.VisionMap;

import frc.robot.maps.subsystems.AlgaeDestageMap;
import frc.robot.maps.subsystems.CoralManipMap;
Expand All @@ -21,6 +22,10 @@ public SwerveDriveMap getDriveMap() {
return new SwerveDriveMap();
}

public VisionMap getVisionMap() {
return new VisionMap();
}

public LedMapBase getLedMap() {
return new MockLedMap();
}
Expand Down
Loading

0 comments on commit 79fc652

Please sign in to comment.