22
33import static edu .wpi .first .units .Units .Seconds ;
44
5- import java .util .Set ;
5+ import java .util .HashMap ;
6+ import java .util .Map ;
67
78import com .team6962 .lib .swerve .SwerveDrive ;
89import com .team6962 .lib .telemetry .Logger ;
1920import io .limelightvision .LimelightHelpers .PoseEstimate ;
2021import io .limelightvision .LimelightHelpers .RawFiducial ;
2122
23+ /**
24+ * The MegaTag2 class is responsible for pose estimation using a combination
25+ * of MegaTag1 and MegaTag2.
26+ */
2227public class MegaTag2 extends SubsystemBase {
2328 private SwerveDrive swerveDrive ;
29+
30+ /**
31+ * Pose estimator used to find field-relative headings with MegaTag1.
32+ */
2433 private SwerveDrivePoseEstimator megaTag1PoseEstimator ;
2534
35+ /**
36+ * Map from limelight ids to most recent MegaTag2-generated pose estimates,
37+ * used for logging.
38+ */
39+ private Map <String , Pose2d > megaTag2PoseEstimates = new HashMap <>(LIMELIGHT .APRILTAG_CAMERA_IDS .size ());
40+
2641 public MegaTag2 (SwerveDrive swerveDrive ) {
2742 this .swerveDrive = swerveDrive ;
2843
@@ -32,6 +47,8 @@ public MegaTag2(SwerveDrive swerveDrive) {
3247 KinematicsUtils .blankModulePositions (4 ),
3348 new Pose2d ()
3449 );
50+
51+ Logger .addUpdate ("poseEstimationData" , this ::logPoseEstimationData );
3552 }
3653
3754 @ Override
@@ -41,25 +58,33 @@ public void periodic() {
4158 addVisionEstimates ();
4259 }
4360
44- // 1. Get pose estimates from MegaTag1
45- // 2. Filter out bad pose estimates
46- // 3. Add offset to gyroscope angle
61+ private void logPoseEstimationData () {
62+ for ( String cameraId : LIMELIGHT . APRILTAG_CAMERA_IDS ) {
63+ PoseEstimate estimate = LimelightHelpers . getBotPoseEstimate_wpiBlue ( cameraId );
4764
48- public void seedGyroscopeAngle () {
49- Set <String > cameraIds = LIMELIGHT .APRILTAG_CAMERA_POSES .keySet ();
65+ Logger .log ("PoseEstimation/" + cameraId + "/pose" , estimate .pose );
66+ Logger .log ("PoseEstimation/" + cameraId + "/latency" , estimate .latency );
67+ Logger .log ("PoseEstimation/" + cameraId + "/tagCount" , estimate .tagCount );
68+ Logger .log ("PoseEstimation/" + cameraId + "/timestampSeconds" , estimate .timestampSeconds );
5069
51- for (String cameraId : cameraIds ) {
52- PoseEstimate estimate = LimelightHelpers .getBotPoseEstimate_wpiBlue (cameraId );
53-
5470 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 );
71+ Logger .log ("PoseEstimation /" + cameraId + "/tags /" + fiducial .id + "/ambiguity" , fiducial .ambiguity );
72+ Logger .log ("PoseEstimation /" + cameraId + "/tags /" + fiducial .id + "/distToCamera" , fiducial .distToCamera );
73+ Logger .log ("PoseEstimation /" + cameraId + "/tags /" + fiducial .id + "/tagArea" , fiducial .ta );
5874 }
5975
60- if (!isEstimateGood (estimate )) continue ;
76+ Logger .log ("PoseEstimation/" + cameraId + "/accurate" , isEstimateAccurate (estimate ));
77+ }
78+ }
6179
62- Logger .getField ().getObject ("Estimate from " + cameraId ).setPose (estimate .pose );
80+ /**
81+ * Gives MegaTag2 field-relative gyroscope angles detected by MegaTag1.
82+ */
83+ public void seedGyroscopeAngle () {
84+ for (String cameraId : LIMELIGHT .APRILTAG_CAMERA_IDS ) {
85+ PoseEstimate estimate = LimelightHelpers .getBotPoseEstimate_wpiBlue (cameraId );
86+
87+ if (!isEstimateAccurate (estimate )) continue ;
6388
6489 megaTag1PoseEstimator .addVisionMeasurement (
6590 estimate .pose ,
@@ -75,9 +100,7 @@ public void seedGyroscopeAngle() {
75100
76101 Rotation2d fieldRelativeHeading = megaTag1PoseEstimator .getEstimatedPosition ().getRotation ();
77102
78- Logger .getField ().getObject ("Field Relative Heading" ).setPose (megaTag1PoseEstimator .getEstimatedPosition ());
79-
80- for (String cameraId : cameraIds ) {
103+ for (String cameraId : LIMELIGHT .APRILTAG_CAMERA_IDS ) {
81104 LimelightHelpers .SetRobotOrientation (
82105 cameraId ,
83106 fieldRelativeHeading .getDegrees (),
@@ -90,28 +113,31 @@ public void seedGyroscopeAngle() {
90113 }
91114 }
92115
93- public boolean isEstimateGood (PoseEstimate estimate ) {
116+ /**
117+ * Checks if a pose estimate is roughly accurate.
118+ * @param estimate The pose estimate to check the accuracy of.
119+ * @return True if it's somewhat accurate.
120+ */
121+ public boolean isEstimateAccurate (PoseEstimate estimate ) {
94122 for (RawFiducial fiducial : estimate .rawFiducials ) {
95123 if (fiducial .ambiguity < 0.4 ) return true ;
96124 }
97125
98126 return false ;
99127 }
100128
101- // 4. Get pose estimates from MegaTag2
102- // 5. Filter out bad pose estimates
103- // 6. Send MegaTag2 estimates to swerve
104-
129+ /**
130+ * Adds vision measurements from MegaTag2 to the swerve drive pose
131+ * estimator.
132+ */
105133 public void addVisionEstimates () {
106- Set <String > cameraIds = LIMELIGHT .APRILTAG_CAMERA_POSES .keySet ();
107-
108- for (String cameraId : cameraIds ) {
134+ for (String cameraId : LIMELIGHT .APRILTAG_CAMERA_IDS ) {
109135 PoseEstimate estimate = CachedRobotState .isBlue ().orElse (false ) ? LimelightHelpers .getBotPoseEstimate_wpiBlue_MegaTag2 (cameraId ) :
110136 LimelightHelpers .getBotPoseEstimate_wpiRed_MegaTag2 (cameraId );
111137
112- if (!isEstimateGood (estimate )) continue ;
138+ if (!isEstimateAccurate (estimate )) continue ;
113139
114- Logger . getField (). getObject ( "MegaTag2 estimate from " + cameraId ). setPose ( estimate .pose );
140+ megaTag2PoseEstimates . put ( cameraId , estimate .pose );
115141
116142 swerveDrive .addVisionMeasurement (
117143 estimate .pose ,
0 commit comments