@@ -21,16 +21,15 @@ public class localizationSubsystem extends SubsystemBase {
2121 private static final double TARGET_DISTANCE_FEET = 2.0 ;
2222 private static final double ANGLE_TOLERANCE_DEGREES = 2.0 ;
2323 private static final double DISTANCE_TOLERANCE_FEET = 0.3 ;
24-
24+
2525 private static final double CAMERA_MOUNT_ANGLE_X_DEGREES = 40.0 ;
2626 private static final double CAMERA_MOUNT_ANGLE_Y_DEGREES = 99.846552 ;
2727 private static final double CAMERA_HEIGHT_INCHES = 9.5 ;
28- private static final double TAG_HEIGHT_INCHES = 1.0 ;
2928 private static final double CAMERA_OFFSET_X_INCHES = 8.41 ;
3029 private static final double CAMERA_OFFSET_Y_INCHES = 11.6 ;
3130
3231 private AprilTagFieldLayout aprilTagFieldLayout ;
33-
32+
3433 private double lastUpdate = 0.0 ;
3534
3635 private double tx = 0.0 ;
@@ -41,7 +40,7 @@ public class localizationSubsystem extends SubsystemBase {
4140
4241 public localizationSubsystem () {
4342 try {
44- aprilTagFieldLayout = AprilTagFieldLayout .loadFromResource (AprilTagFields .k2024Crescendo .m_resourceFile );
43+ aprilTagFieldLayout = AprilTagFieldLayout .loadFromResource (AprilTagFields .k2025ReefscapeAndyMark .m_resourceFile );
4544 } catch (Exception e ) {
4645 Logger .recordOutput ("Localization/AprilTagLayoutError" , e .getMessage ());
4746 }
@@ -159,104 +158,104 @@ private void calculateDiagonalsAndMidpoint() {
159158 private void calculateOptimalMovement () {
160159 double realTimeTA = calculateTagArea ();
161160 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
162-
161+
163162 double cameraOffsetDistance = Math .sqrt (
164- Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
165- Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
166-
163+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
164+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 )
165+ );
166+
167167 double horizontalAngleError = tx ;
168- double verticalAngleError = ty ;
169-
170- double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
171-
172- double adjustedCameraDistance = Math .sqrt (
173- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
174-
168+
169+ double adjustedCameraDistance = cameraDistanceToTag / Math .cos (Math .toRadians (CAMERA_MOUNT_ANGLE_Y_DEGREES ));
170+
175171 double robotCenterDistanceToTag = Math .sqrt (
176- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
177- 2 * adjustedCameraDistance * cameraOffsetDistance *
178- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES )));
179-
172+ Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
173+ 2 * adjustedCameraDistance * cameraOffsetDistance *
174+ Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
175+ );
176+
180177 double currentDistance = robotCenterDistanceToTag + 1.0 ;
181-
178+
182179 Logger .recordOutput ("Movement/CameraDistance_Feet" , cameraDistanceToTag );
183180 Logger .recordOutput ("Movement/RobotCenterDistance_Feet" , robotCenterDistanceToTag );
184181 Logger .recordOutput ("Movement/CurrentDistance_Feet" , currentDistance );
185182 Logger .recordOutput ("Movement/TargetDistance_Feet" , TARGET_DISTANCE_FEET );
186183 Logger .recordOutput ("Movement/CameraOffset_Feet" , cameraOffsetDistance );
187- Logger .recordOutput ("Movement/HeightDifference_Feet" , heightDifference );
188-
184+
189185 Logger .recordOutput ("Movement/HorizontalAngleError_Degrees" , horizontalAngleError );
190- Logger .recordOutput ("Movement/VerticalAngleError_Degrees" , verticalAngleError );
191-
186+
192187 double forwardMovement = currentDistance - TARGET_DISTANCE_FEET ;
193188 Logger .recordOutput ("Movement/RequiredForward_Feet" , forwardMovement );
194-
189+
195190 double strafeMovement = currentDistance * Math .tan (Math .toRadians (horizontalAngleError ));
196191 Logger .recordOutput ("Movement/RequiredStrafe_Feet" , strafeMovement );
197-
192+
198193 double rotationRequired = horizontalAngleError ;
199194 Logger .recordOutput ("Movement/RequiredRotation_Degrees" , rotationRequired );
200-
195+
201196 String movementCommand = generateMovementCommand (forwardMovement , strafeMovement , rotationRequired );
202197 Logger .recordOutput ("Movement/Command" , movementCommand );
203-
198+
204199 boolean isAligned = checkAlignment (forwardMovement , rotationRequired );
205200 Logger .recordOutput ("Movement/IsAligned" , isAligned );
206-
201+
207202 logMovementBreakdown (forwardMovement , strafeMovement , rotationRequired );
208203 }
209204
210205 private void calculateAndLogPoseEstimation () {
211- if (aprilTagFieldLayout == null || tagId == -1 ) {
212- Logger .recordOutput ("PoseEstimation/Status" , "AprilTag layout not loaded or invalid tag ID" );
206+ if (aprilTagFieldLayout == null ) {
207+ Logger .recordOutput ("PoseEstimation/Status" , "AprilTag layout not loaded" );
208+ return ;
209+ }
210+
211+ if (tagId == -1 ) {
212+ Logger .recordOutput ("PoseEstimation/Status" , "No valid tag detected" );
213213 return ;
214214 }
215215
216216 Optional <edu .wpi .first .math .geometry .Pose3d > tagPoseOptional = aprilTagFieldLayout .getTagPose (tagId );
217217 if (!tagPoseOptional .isPresent ()) {
218- Logger .recordOutput ("PoseEstimation/Status" , "Tag ID " + tagId + " not found in field layout" );
218+ Logger .recordOutput ("PoseEstimation/Status" , "Tag ID " + tagId + " not in field layout" );
219+ Logger .recordOutput ("PoseEstimation/TagID" , tagId );
219220 return ;
220221 }
221222
222223 edu .wpi .first .math .geometry .Pose3d tagPose3d = tagPoseOptional .get ();
223224 Pose2d tagPose = tagPose3d .toPose2d ();
224-
225+
225226 double realTimeTA = calculateTagArea ();
226227 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
227-
228+
228229 double cameraOffsetDistance = Math .sqrt (
229- Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
230- Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
231-
230+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
231+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 )
232+ );
233+
232234 double horizontalAngleError = tx ;
233- double verticalAngleError = ty ;
234-
235- double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
236-
237- double adjustedCameraDistance = Math .sqrt (
238- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
239-
235+
236+ double adjustedCameraDistance = cameraDistanceToTag / Math .cos (Math .toRadians (CAMERA_MOUNT_ANGLE_Y_DEGREES ));
237+
240238 double robotCenterDistanceToTag = Math .sqrt (
241- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
242- 2 * adjustedCameraDistance * cameraOffsetDistance *
243- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES )));
244-
239+ Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
240+ 2 * adjustedCameraDistance * cameraOffsetDistance *
241+ Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
242+ );
243+
245244 double currentDistance = robotCenterDistanceToTag + 1.0 ;
246245 double distanceMeters = currentDistance * 0.3048 ;
247-
246+
248247 double robotAngleToTag = tagPose .getRotation ().getDegrees () + 180 - horizontalAngleError ;
249248 Rotation2d robotRotation = Rotation2d .fromDegrees (robotAngleToTag );
250-
249+
251250 double angleRad = Math .toRadians (robotAngleToTag );
252251 double robotX = tagPose .getX () - distanceMeters * Math .cos (angleRad );
253252 double robotY = tagPose .getY () - distanceMeters * Math .sin (angleRad );
254-
253+
255254 Translation2d robotTranslation = new Translation2d (robotX , robotY );
256255 Pose2d estimatedPose = new Pose2d (robotTranslation , robotRotation );
257-
256+
258257 double timestamp = Timer .getFPGATimestamp ();
259-
258+
260259 Logger .recordOutput ("PoseEstimation/TagID" , tagId );
261260 Logger .recordOutput ("PoseEstimation/TagPoseX" , tagPose .getX ());
262261 Logger .recordOutput ("PoseEstimation/TagPoseY" , tagPose .getY ());
@@ -267,58 +266,58 @@ private void calculateAndLogPoseEstimation() {
267266 Logger .recordOutput ("PoseEstimation/DistanceToTag_Meters" , distanceMeters );
268267 Logger .recordOutput ("PoseEstimation/Timestamp" , timestamp );
269268 Logger .recordOutput ("PoseEstimation/EstimatedPose2d" , estimatedPose );
270- Logger .recordOutput ("PoseEstimation/Status" , "Valid pose estimation " );
269+ Logger .recordOutput ("PoseEstimation/Status" , "Valid" );
271270 }
272271
273272 private String generateMovementCommand (double forward , double strafe , double rotation ) {
274273 StringBuilder command = new StringBuilder ();
275-
276- if (Math .abs (forward ) < DISTANCE_TOLERANCE_FEET &&
277- Math .abs (rotation ) < ANGLE_TOLERANCE_DEGREES ) {
274+
275+ if (Math .abs (forward ) < DISTANCE_TOLERANCE_FEET &&
276+ Math .abs (rotation ) < ANGLE_TOLERANCE_DEGREES ) {
278277 return "ALIGNED - Hold position" ;
279278 }
280-
279+
281280 if (Math .abs (rotation ) > ANGLE_TOLERANCE_DEGREES ) {
282- command .append (String .format ("ROTATE %.1f° %s" ,
283- Math .abs (rotation ),
284- rotation > 0 ? "RIGHT" : "LEFT" ));
281+ command .append (String .format ("ROTATE %.1f° %s" ,
282+ Math .abs (rotation ),
283+ rotation > 0 ? "RIGHT" : "LEFT" ));
285284 command .append (" → THEN → " );
286285 }
287-
286+
288287 if (Math .abs (forward ) > DISTANCE_TOLERANCE_FEET ) {
289- command .append (String .format ("DRIVE %.2f ft %s" ,
290- Math .abs (forward ),
291- forward > 0 ? "BACKWARD" : "FORWARD" ));
288+ command .append (String .format ("DRIVE %.2f ft %s" ,
289+ Math .abs (forward ),
290+ forward > 0 ? "BACKWARD" : "FORWARD" ));
292291 } else {
293292 command .append ("HOLD DISTANCE" );
294293 }
295-
294+
296295 if (Math .abs (strafe ) > 0.1 ) {
297- command .append (String .format (" + STRAFE %.2f ft %s" ,
298- Math .abs (strafe ),
299- strafe > 0 ? "RIGHT" : "LEFT" ));
296+ command .append (String .format (" + STRAFE %.2f ft %s" ,
297+ Math .abs (strafe ),
298+ strafe > 0 ? "RIGHT" : "LEFT" ));
300299 }
301-
300+
302301 return command .toString ();
303302 }
304303
305304 private boolean checkAlignment (double forwardError , double rotationError ) {
306- return Math .abs (forwardError ) < DISTANCE_TOLERANCE_FEET &&
307- Math .abs (rotationError ) < ANGLE_TOLERANCE_DEGREES ;
305+ return Math .abs (forwardError ) < DISTANCE_TOLERANCE_FEET &&
306+ Math .abs (rotationError ) < ANGLE_TOLERANCE_DEGREES ;
308307 }
309308
310309 private void logMovementBreakdown (double forward , double strafe , double rotation ) {
311310 Logger .recordOutput ("Movement/Phase1_RotationNeeded" , Math .abs (rotation ) > ANGLE_TOLERANCE_DEGREES );
312311 Logger .recordOutput ("Movement/Phase2_ForwardNeeded" , Math .abs (forward ) > DISTANCE_TOLERANCE_FEET );
313312 Logger .recordOutput ("Movement/Phase3_StrafeNeeded" , Math .abs (strafe ) > 0.1 );
314-
313+
315314 Logger .recordOutput ("Movement/Direction_Forward" , forward < 0 );
316315 Logger .recordOutput ("Movement/Direction_Backward" , forward > 0 );
317316 Logger .recordOutput ("Movement/Direction_StrafeLeft" , strafe < 0 );
318317 Logger .recordOutput ("Movement/Direction_StrafeRight" , strafe > 0 );
319318 Logger .recordOutput ("Movement/Direction_RotateLeft" , rotation < 0 );
320319 Logger .recordOutput ("Movement/Direction_RotateRight" , rotation > 0 );
321-
320+
322321 Logger .recordOutput ("Movement/ForwardError_Inches" , forward * 12 );
323322 Logger .recordOutput ("Movement/StrafeError_Inches" , strafe * 12 );
324323 Logger .recordOutput ("Movement/RotationError_Degrees" , rotation );
@@ -343,26 +342,25 @@ public double getTa() {
343342 public double [] getTcornxy () {
344343 return tcornxy ;
345344 }
346-
345+
347346 public int getTagId () {
348347 return tagId ;
349348 }
350-
349+
351350 public double getCurrentDistance () {
352351 if (isCornersValid ()) {
353352 return calculateDistanceFromArea (calculateTagArea ());
354353 }
355354 return -1.0 ;
356355 }
357-
356+
358357 public boolean isAligned () {
359- if (!isCornersValid ())
360- return false ;
361-
358+ if (!isCornersValid ()) return false ;
359+
362360 double currentDistance = getCurrentDistance ();
363361 double forwardError = currentDistance - TARGET_DISTANCE_FEET ;
364362 double rotationError = tx ;
365-
363+
366364 return checkAlignment (forwardError , rotationError );
367365 }
368366
@@ -378,41 +376,39 @@ public Pose2d getEstimatedPose() {
378376
379377 edu .wpi .first .math .geometry .Pose3d tagPose3d = tagPoseOptional .get ();
380378 Pose2d tagPose = tagPose3d .toPose2d ();
381-
379+
382380 double realTimeTA = calculateTagArea ();
383381 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
384-
382+
385383 double cameraOffsetDistance = Math .sqrt (
386- Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
387- Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
388-
384+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
385+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 )
386+ );
387+
389388 double horizontalAngleError = tx ;
390- double verticalAngleError = ty ;
391-
392- double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
393-
394- double adjustedCameraDistance = Math .sqrt (
395- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
396-
389+
390+ double adjustedCameraDistance = cameraDistanceToTag / Math .cos (Math .toRadians (CAMERA_MOUNT_ANGLE_Y_DEGREES ));
391+
397392 double robotCenterDistanceToTag = Math .sqrt (
398- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
399- 2 * adjustedCameraDistance * cameraOffsetDistance *
400- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES )));
401-
393+ Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
394+ 2 * adjustedCameraDistance * cameraOffsetDistance *
395+ Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
396+ );
397+
402398 double currentDistance = robotCenterDistanceToTag + 1.0 ;
403399 double distanceMeters = currentDistance * 0.3048 ;
404-
400+
405401 double robotAngleToTag = tagPose .getRotation ().getDegrees () + 180 - horizontalAngleError ;
406402 Rotation2d robotRotation = Rotation2d .fromDegrees (robotAngleToTag );
407-
403+
408404 double angleRad = Math .toRadians (robotAngleToTag );
409405 double robotX = tagPose .getX () - distanceMeters * Math .cos (angleRad );
410406 double robotY = tagPose .getY () - distanceMeters * Math .sin (angleRad );
411-
407+
412408 Translation2d robotTranslation = new Translation2d (robotX , robotY );
413409 return new Pose2d (robotTranslation , robotRotation );
414410 }
415-
411+
416412 public double getTimestamp () {
417413 return Timer .getFPGATimestamp ();
418414 }
0 commit comments