Skip to content

Commit 856eb04

Browse files
committed
Current working version of MegaTag2 and MegaTag1
1 parent 2892ff8 commit 856eb04

File tree

5 files changed

+156
-11
lines changed

5 files changed

+156
-11
lines changed

src/main/java/com/team6962/lib/swerve/SwerveCore.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ public void addVisionMeasurement(
142142
poseEstimator.addVisionMeasurement(visionRobotPoseMeters, timestamp, visionMeasurementStdDevs);
143143
}
144144

145+
public void addVisionMeasurement(
146+
Pose2d visionRobotPoseMeters, Time timestamp) {
147+
poseEstimator.addVisionMeasurement(visionRobotPoseMeters, timestamp);
148+
}
149+
145150
public void addVisionHeading(Rotation2d visionHeading) {
146151
poseEstimator.addVisionHeading(visionHeading);
147152
}
@@ -166,6 +171,10 @@ public Angle getContinuousGyroscopeAngle() {
166171
return poseEstimator.getContinuousGyroscopeAngle();
167172
}
168173

174+
public PoseEstimator getPoseEstimator() {
175+
return poseEstimator;
176+
}
177+
169178
/** Should be called after CommandScheduler.run() to mimimize latency. */
170179
public void latePeriodic() {
171180
if (currentMovement == null) {

src/main/java/com/team6962/lib/swerve/SwerveDrive.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
import static edu.wpi.first.units.Units.Rotations;
88
import static edu.wpi.first.units.Units.Seconds;
99

10+
import java.util.List;
11+
import java.util.Set;
12+
import java.util.function.Supplier;
13+
1014
import com.pathplanner.lib.auto.AutoBuilder;
1115
import com.pathplanner.lib.commands.FollowPathCommand;
1216
import com.pathplanner.lib.config.PIDConstants;
@@ -24,6 +28,7 @@
2428
import com.team6962.lib.utils.CommandUtils;
2529
import com.team6962.lib.utils.KinematicsUtils;
2630
import com.team6962.lib.utils.MeasureMath;
31+
2732
import edu.wpi.first.math.MathUtil;
2833
import edu.wpi.first.math.controller.PIDController;
2934
import edu.wpi.first.math.geometry.Pose2d;
@@ -44,9 +49,6 @@
4449
import edu.wpi.first.wpilibj2.command.Command;
4550
import edu.wpi.first.wpilibj2.command.Commands;
4651
import edu.wpi.first.wpilibj2.command.SubsystemBase;
47-
import java.util.List;
48-
import java.util.Set;
49-
import java.util.function.Supplier;
5052

5153
/**
5254
* The main class for the swerve drive system. This class extends {@link SwerveCore} to provide the

src/main/java/com/team6962/lib/swerve/auto/PoseEstimator.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import static edu.wpi.first.units.Units.Seconds;
44

5+
import java.util.function.Supplier;
6+
57
import com.team6962.lib.telemetry.Logger;
68
import com.team6962.lib.utils.KinematicsUtils;
79
import com.team6962.lib.utils.RotationUtils;
10+
811
import edu.wpi.first.math.Matrix;
912
import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator;
1013
import edu.wpi.first.math.geometry.Pose2d;
@@ -20,10 +23,6 @@
2023
import edu.wpi.first.units.measure.Time;
2124
import edu.wpi.first.wpilibj.Timer;
2225
import edu.wpi.first.wpilibj2.command.SubsystemBase;
23-
import frc.robot.constants.Constants.LIMELIGHT;
24-
import frc.robot.vision.AprilTags;
25-
26-
import java.util.function.Supplier;
2726

2827
/**
2928
* {@code PoseEstimator} is a class that estimates the pose of a swerve drive robot using a
@@ -76,7 +75,7 @@ public void periodic() {
7675

7776
poseEstimator.updateWithTime(
7877
timestamp.in(Seconds), RotationUtils.fromAngle(gyroscope.getHeading()), modulePositions);
79-
AprilTags.injectVisionData(LIMELIGHT.APRILTAG_CAMERA_POSES, this);
78+
// AprilTags.injectVisionData(LIMELIGHT.APRILTAG_CAMERA_POSES, this);
8079
chassisVelocity =
8180
kinematics.toTwist2d(
8281
KinematicsUtils.toModulePositions(moduleStatesSupplier.get(), Seconds.of(1.0)));
@@ -86,6 +85,10 @@ public void periodic() {
8685
lastPositions = modulePositions;
8786
}
8887

88+
public SwerveGyroscope getGyroscope() {
89+
return gyroscope;
90+
}
91+
8992
public Angle getContinuousGyroscopeAngle() {
9093
return gyroscope.getHeading();
9194
}
@@ -96,6 +99,12 @@ public void addVisionMeasurement(
9699
visionRobotPoseMeters, timestamp.in(Seconds), visionMeasurementStdDevs);
97100
}
98101

102+
public void addVisionMeasurement(
103+
Pose2d visionRobotPoseMeters, Time timestamp) {
104+
poseEstimator.addVisionMeasurement(
105+
visionRobotPoseMeters, timestamp.in(Seconds));
106+
}
107+
99108
public void resetPoseEstimate(Pose2d expectedFieldPose) {
100109
poseEstimator.resetPosition(
101110
RotationUtils.fromAngle(gyroscope.getHeading()),

src/main/java/frc/robot/RobotContainer.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,22 @@
2525
import edu.wpi.first.wpilibj.Timer;
2626
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
2727
import edu.wpi.first.wpilibj2.command.Command;
28-
import frc.robot.constants.Constants.CAN;
29-
import frc.robot.constants.Constants.SWERVE;
3028
import frc.robot.auto.AutoAlign;
3129
import frc.robot.auto.Autonomous;
3230
import frc.robot.auto.Autonomous.Side;
3331
import frc.robot.commands.PieceCombos;
3432
import frc.robot.commands.SafeSubsystems;
33+
import frc.robot.constants.Constants.CAN;
34+
import frc.robot.constants.Constants.SWERVE;
3535
import frc.robot.subsystems.Controls;
36-
import frc.robot.subsystems.leds.LEDs;
3736
import frc.robot.subsystems.elevator.Elevator;
3837
import frc.robot.subsystems.hang.Hang;
38+
import frc.robot.subsystems.leds.LEDs;
3939
import frc.robot.subsystems.manipulator.Manipulator;
4040
import frc.robot.util.CachedRobotState;
4141
import frc.robot.util.RobotEvent;
4242
import frc.robot.vision.Algae;
43+
import frc.robot.vision.MegaTag2;
4344

4445
/**
4546
* This class is where the bulk of the robot should be declared. Since Command-based is a
@@ -71,6 +72,7 @@ public static RobotContainer getInstance() {
7172
public final PieceCombos pieceCombos;
7273
public final SafeSubsystems safeties;
7374
private final Command autonomousCommand;
75+
private final MegaTag2 megaTag2;
7476

7577
private static PowerDistribution PDH = new PowerDistribution(CAN.PDH, ModuleType.kRev);
7678

@@ -116,6 +118,7 @@ public RobotContainer() {
116118
autov3 = new Autonomous(swerveDrive, manipulator, elevator, pieceCombos);
117119
algaeDetector = new Algae();
118120
hang = Hang.create();
121+
megaTag2 = new MegaTag2(swerveDrive);
119122

120123
// // Configure the trigger bindings
121124
Controls.configureBindings(
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package frc.robot.vision;
2+
3+
import static edu.wpi.first.units.Units.Seconds;
4+
5+
import java.util.Set;
6+
7+
import com.team6962.lib.swerve.SwerveDrive;
8+
import com.team6962.lib.telemetry.Logger;
9+
import com.team6962.lib.utils.KinematicsUtils;
10+
11+
import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator;
12+
import edu.wpi.first.math.geometry.Pose2d;
13+
import edu.wpi.first.math.geometry.Rotation2d;
14+
import edu.wpi.first.wpilibj.Timer;
15+
import edu.wpi.first.wpilibj2.command.SubsystemBase;
16+
import frc.robot.constants.Constants.LIMELIGHT;
17+
import frc.robot.util.CachedRobotState;
18+
import io.limelightvision.LimelightHelpers;
19+
import io.limelightvision.LimelightHelpers.PoseEstimate;
20+
import io.limelightvision.LimelightHelpers.RawFiducial;
21+
22+
public class MegaTag2 extends SubsystemBase {
23+
private SwerveDrive swerveDrive;
24+
private SwerveDrivePoseEstimator megaTag1PoseEstimator;
25+
26+
public MegaTag2(SwerveDrive swerveDrive) {
27+
this.swerveDrive = swerveDrive;
28+
29+
megaTag1PoseEstimator = new SwerveDrivePoseEstimator(
30+
swerveDrive.getKinematics(),
31+
new Rotation2d(swerveDrive.getContinuousGyroscopeAngle()),
32+
KinematicsUtils.blankModulePositions(4),
33+
new Pose2d()
34+
);
35+
}
36+
37+
@Override
38+
public void periodic() {
39+
if (CachedRobotState.isDisabled()) seedGyroscopeAngle();
40+
41+
addVisionEstimates();
42+
}
43+
44+
// 1. Get pose estimates from MegaTag1
45+
// 2. Filter out bad pose estimates
46+
// 3. Add offset to gyroscope angle
47+
48+
public void seedGyroscopeAngle() {
49+
Set<String> cameraIds = LIMELIGHT.APRILTAG_CAMERA_POSES.keySet();
50+
51+
for (String cameraId : cameraIds) {
52+
PoseEstimate estimate = LimelightHelpers.getBotPoseEstimate_wpiBlue(cameraId);
53+
54+
for (RawFiducial fiducial : estimate.rawFiducials) {
55+
Logger.log("Fiducials/" + cameraId + "/" + fiducial.id + "/ambiguity", fiducial.ambiguity);
56+
Logger.log("Fiducials/" + cameraId + "/" + fiducial.id + "/distToCamera", fiducial.distToCamera);
57+
Logger.log("Fiducials/" + cameraId + "/" + fiducial.id + "/tagArea", fiducial.ta);
58+
}
59+
60+
if (!isEstimateGood(estimate)) continue;
61+
62+
Logger.getField().getObject("Estimate from " + cameraId).setPose(estimate.pose);
63+
64+
megaTag1PoseEstimator.addVisionMeasurement(
65+
estimate.pose,
66+
estimate.timestampSeconds
67+
);
68+
}
69+
70+
megaTag1PoseEstimator.updateWithTime(
71+
Timer.getFPGATimestamp(),
72+
new Rotation2d(swerveDrive.getContinuousGyroscopeAngle()),
73+
KinematicsUtils.blankModulePositions(4)
74+
);
75+
76+
Rotation2d fieldRelativeHeading = megaTag1PoseEstimator.getEstimatedPosition().getRotation();
77+
78+
Logger.getField().getObject("Field Relative Heading").setPose(megaTag1PoseEstimator.getEstimatedPosition());
79+
80+
for (String cameraId : cameraIds) {
81+
LimelightHelpers.SetRobotOrientation(
82+
cameraId,
83+
fieldRelativeHeading.getDegrees(),
84+
0,
85+
0,
86+
0,
87+
0,
88+
0
89+
);
90+
}
91+
}
92+
93+
public boolean isEstimateGood(PoseEstimate estimate) {
94+
for (RawFiducial fiducial : estimate.rawFiducials) {
95+
if (fiducial.ambiguity < 0.4) return true;
96+
}
97+
98+
return false;
99+
}
100+
101+
// 4. Get pose estimates from MegaTag2
102+
// 5. Filter out bad pose estimates
103+
// 6. Send MegaTag2 estimates to swerve
104+
105+
public void addVisionEstimates() {
106+
Set<String> cameraIds = LIMELIGHT.APRILTAG_CAMERA_POSES.keySet();
107+
108+
for (String cameraId : cameraIds) {
109+
PoseEstimate estimate = CachedRobotState.isBlue().orElse(false) ? LimelightHelpers.getBotPoseEstimate_wpiBlue_MegaTag2(cameraId) :
110+
LimelightHelpers.getBotPoseEstimate_wpiRed_MegaTag2(cameraId);
111+
112+
if (!isEstimateGood(estimate)) continue;
113+
114+
Logger.getField().getObject("MegaTag2 estimate from " + cameraId).setPose(estimate.pose);
115+
116+
swerveDrive.addVisionMeasurement(
117+
estimate.pose,
118+
Seconds.of(estimate.timestampSeconds)
119+
);
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)