@@ -21,16 +21,16 @@ 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-
25- private static final double CAMERA_MOUNT_ANGLE_X_DEGREES = 0 .0 ;
26- private static final double CAMERA_MOUNT_ANGLE_Y_DEGREES = 0.0 ;
27- private static final double CAMERA_HEIGHT_INCHES = 24.0 ;
28- private static final double TAG_HEIGHT_INCHES = 6 .0 ;
29- private static final double CAMERA_OFFSET_X_INCHES = 0.0 ;
30- private static final double CAMERA_OFFSET_Y_INCHES = 0.0 ;
24+
25+ private static final double CAMERA_MOUNT_ANGLE_X_DEGREES = 40 .0 ;
26+ private static final double CAMERA_MOUNT_ANGLE_Y_DEGREES = 99.846552 ;
27+ private static final double CAMERA_HEIGHT_INCHES = 9.5 ;
28+ private static final double TAG_HEIGHT_INCHES = 1 .0 ;
29+ private static final double CAMERA_OFFSET_X_INCHES = 8.41 ;
30+ private static final double CAMERA_OFFSET_Y_INCHES = 11.6 ;
3131
3232 private AprilTagFieldLayout aprilTagFieldLayout ;
33-
33+
3434 private double lastUpdate = 0.0 ;
3535
3636 private double tx = 0.0 ;
@@ -159,54 +159,51 @@ private void calculateDiagonalsAndMidpoint() {
159159 private void calculateOptimalMovement () {
160160 double realTimeTA = calculateTagArea ();
161161 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
162-
162+
163163 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- );
167-
164+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
165+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
166+
168167 double horizontalAngleError = tx ;
169168 double verticalAngleError = ty ;
170-
169+
171170 double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
172-
171+
173172 double adjustedCameraDistance = Math .sqrt (
174- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 )
175- );
176-
173+ Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
174+
177175 double robotCenterDistanceToTag = Math .sqrt (
178- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
179- 2 * adjustedCameraDistance * cameraOffsetDistance *
180- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
181- );
182-
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+
183180 double currentDistance = robotCenterDistanceToTag + 1.0 ;
184-
181+
185182 Logger .recordOutput ("Movement/CameraDistance_Feet" , cameraDistanceToTag );
186183 Logger .recordOutput ("Movement/RobotCenterDistance_Feet" , robotCenterDistanceToTag );
187184 Logger .recordOutput ("Movement/CurrentDistance_Feet" , currentDistance );
188185 Logger .recordOutput ("Movement/TargetDistance_Feet" , TARGET_DISTANCE_FEET );
189186 Logger .recordOutput ("Movement/CameraOffset_Feet" , cameraOffsetDistance );
190187 Logger .recordOutput ("Movement/HeightDifference_Feet" , heightDifference );
191-
188+
192189 Logger .recordOutput ("Movement/HorizontalAngleError_Degrees" , horizontalAngleError );
193190 Logger .recordOutput ("Movement/VerticalAngleError_Degrees" , verticalAngleError );
194-
191+
195192 double forwardMovement = currentDistance - TARGET_DISTANCE_FEET ;
196193 Logger .recordOutput ("Movement/RequiredForward_Feet" , forwardMovement );
197-
194+
198195 double strafeMovement = currentDistance * Math .tan (Math .toRadians (horizontalAngleError ));
199196 Logger .recordOutput ("Movement/RequiredStrafe_Feet" , strafeMovement );
200-
197+
201198 double rotationRequired = horizontalAngleError ;
202199 Logger .recordOutput ("Movement/RequiredRotation_Degrees" , rotationRequired );
203-
200+
204201 String movementCommand = generateMovementCommand (forwardMovement , strafeMovement , rotationRequired );
205202 Logger .recordOutput ("Movement/Command" , movementCommand );
206-
203+
207204 boolean isAligned = checkAlignment (forwardMovement , rotationRequired );
208205 Logger .recordOutput ("Movement/IsAligned" , isAligned );
209-
206+
210207 logMovementBreakdown (forwardMovement , strafeMovement , rotationRequired );
211208 }
212209
@@ -224,45 +221,42 @@ private void calculateAndLogPoseEstimation() {
224221
225222 edu .wpi .first .math .geometry .Pose3d tagPose3d = tagPoseOptional .get ();
226223 Pose2d tagPose = tagPose3d .toPose2d ();
227-
224+
228225 double realTimeTA = calculateTagArea ();
229226 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
230-
227+
231228 double cameraOffsetDistance = Math .sqrt (
232- Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
233- Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 )
234- );
235-
229+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
230+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
231+
236232 double horizontalAngleError = tx ;
237233 double verticalAngleError = ty ;
238-
234+
239235 double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
240-
236+
241237 double adjustedCameraDistance = Math .sqrt (
242- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 )
243- );
244-
238+ Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
239+
245240 double robotCenterDistanceToTag = Math .sqrt (
246- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
247- 2 * adjustedCameraDistance * cameraOffsetDistance *
248- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
249- );
250-
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+
251245 double currentDistance = robotCenterDistanceToTag + 1.0 ;
252246 double distanceMeters = currentDistance * 0.3048 ;
253-
247+
254248 double robotAngleToTag = tagPose .getRotation ().getDegrees () + 180 - horizontalAngleError ;
255249 Rotation2d robotRotation = Rotation2d .fromDegrees (robotAngleToTag );
256-
250+
257251 double angleRad = Math .toRadians (robotAngleToTag );
258252 double robotX = tagPose .getX () - distanceMeters * Math .cos (angleRad );
259253 double robotY = tagPose .getY () - distanceMeters * Math .sin (angleRad );
260-
254+
261255 Translation2d robotTranslation = new Translation2d (robotX , robotY );
262256 Pose2d estimatedPose = new Pose2d (robotTranslation , robotRotation );
263-
257+
264258 double timestamp = Timer .getFPGATimestamp ();
265-
259+
266260 Logger .recordOutput ("PoseEstimation/TagID" , tagId );
267261 Logger .recordOutput ("PoseEstimation/TagPoseX" , tagPose .getX ());
268262 Logger .recordOutput ("PoseEstimation/TagPoseY" , tagPose .getY ());
@@ -278,53 +272,53 @@ private void calculateAndLogPoseEstimation() {
278272
279273 private String generateMovementCommand (double forward , double strafe , double rotation ) {
280274 StringBuilder command = new StringBuilder ();
281-
282- if (Math .abs (forward ) < DISTANCE_TOLERANCE_FEET &&
283- Math .abs (rotation ) < ANGLE_TOLERANCE_DEGREES ) {
275+
276+ if (Math .abs (forward ) < DISTANCE_TOLERANCE_FEET &&
277+ Math .abs (rotation ) < ANGLE_TOLERANCE_DEGREES ) {
284278 return "ALIGNED - Hold position" ;
285279 }
286-
280+
287281 if (Math .abs (rotation ) > ANGLE_TOLERANCE_DEGREES ) {
288- command .append (String .format ("ROTATE %.1f° %s" ,
289- Math .abs (rotation ),
290- rotation > 0 ? "RIGHT" : "LEFT" ));
282+ command .append (String .format ("ROTATE %.1f° %s" ,
283+ Math .abs (rotation ),
284+ rotation > 0 ? "RIGHT" : "LEFT" ));
291285 command .append (" → THEN → " );
292286 }
293-
287+
294288 if (Math .abs (forward ) > DISTANCE_TOLERANCE_FEET ) {
295- command .append (String .format ("DRIVE %.2f ft %s" ,
296- Math .abs (forward ),
297- forward > 0 ? "BACKWARD" : "FORWARD" ));
289+ command .append (String .format ("DRIVE %.2f ft %s" ,
290+ Math .abs (forward ),
291+ forward > 0 ? "BACKWARD" : "FORWARD" ));
298292 } else {
299293 command .append ("HOLD DISTANCE" );
300294 }
301-
295+
302296 if (Math .abs (strafe ) > 0.1 ) {
303- command .append (String .format (" + STRAFE %.2f ft %s" ,
304- Math .abs (strafe ),
305- strafe > 0 ? "RIGHT" : "LEFT" ));
297+ command .append (String .format (" + STRAFE %.2f ft %s" ,
298+ Math .abs (strafe ),
299+ strafe > 0 ? "RIGHT" : "LEFT" ));
306300 }
307-
301+
308302 return command .toString ();
309303 }
310304
311305 private boolean checkAlignment (double forwardError , double rotationError ) {
312- return Math .abs (forwardError ) < DISTANCE_TOLERANCE_FEET &&
313- Math .abs (rotationError ) < ANGLE_TOLERANCE_DEGREES ;
306+ return Math .abs (forwardError ) < DISTANCE_TOLERANCE_FEET &&
307+ Math .abs (rotationError ) < ANGLE_TOLERANCE_DEGREES ;
314308 }
315309
316310 private void logMovementBreakdown (double forward , double strafe , double rotation ) {
317311 Logger .recordOutput ("Movement/Phase1_RotationNeeded" , Math .abs (rotation ) > ANGLE_TOLERANCE_DEGREES );
318312 Logger .recordOutput ("Movement/Phase2_ForwardNeeded" , Math .abs (forward ) > DISTANCE_TOLERANCE_FEET );
319313 Logger .recordOutput ("Movement/Phase3_StrafeNeeded" , Math .abs (strafe ) > 0.1 );
320-
314+
321315 Logger .recordOutput ("Movement/Direction_Forward" , forward < 0 );
322316 Logger .recordOutput ("Movement/Direction_Backward" , forward > 0 );
323317 Logger .recordOutput ("Movement/Direction_StrafeLeft" , strafe < 0 );
324318 Logger .recordOutput ("Movement/Direction_StrafeRight" , strafe > 0 );
325319 Logger .recordOutput ("Movement/Direction_RotateLeft" , rotation < 0 );
326320 Logger .recordOutput ("Movement/Direction_RotateRight" , rotation > 0 );
327-
321+
328322 Logger .recordOutput ("Movement/ForwardError_Inches" , forward * 12 );
329323 Logger .recordOutput ("Movement/StrafeError_Inches" , strafe * 12 );
330324 Logger .recordOutput ("Movement/RotationError_Degrees" , rotation );
@@ -349,25 +343,26 @@ public double getTa() {
349343 public double [] getTcornxy () {
350344 return tcornxy ;
351345 }
352-
346+
353347 public int getTagId () {
354348 return tagId ;
355349 }
356-
350+
357351 public double getCurrentDistance () {
358352 if (isCornersValid ()) {
359353 return calculateDistanceFromArea (calculateTagArea ());
360354 }
361355 return -1.0 ;
362356 }
363-
357+
364358 public boolean isAligned () {
365- if (!isCornersValid ()) return false ;
366-
359+ if (!isCornersValid ())
360+ return false ;
361+
367362 double currentDistance = getCurrentDistance ();
368363 double forwardError = currentDistance - TARGET_DISTANCE_FEET ;
369364 double rotationError = tx ;
370-
365+
371366 return checkAlignment (forwardError , rotationError );
372367 }
373368
@@ -383,44 +378,41 @@ public Pose2d getEstimatedPose() {
383378
384379 edu .wpi .first .math .geometry .Pose3d tagPose3d = tagPoseOptional .get ();
385380 Pose2d tagPose = tagPose3d .toPose2d ();
386-
381+
387382 double realTimeTA = calculateTagArea ();
388383 double cameraDistanceToTag = calculateDistanceFromArea (realTimeTA );
389-
384+
390385 double cameraOffsetDistance = Math .sqrt (
391- Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
392- Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 )
393- );
394-
386+ Math .pow (CAMERA_OFFSET_X_INCHES / 12.0 , 2 ) +
387+ Math .pow (CAMERA_OFFSET_Y_INCHES / 12.0 , 2 ));
388+
395389 double horizontalAngleError = tx ;
396390 double verticalAngleError = ty ;
397-
391+
398392 double heightDifference = (CAMERA_HEIGHT_INCHES - TAG_HEIGHT_INCHES ) / 12.0 ;
399-
393+
400394 double adjustedCameraDistance = Math .sqrt (
401- Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 )
402- );
403-
395+ Math .pow (cameraDistanceToTag , 2 ) - Math .pow (heightDifference , 2 ));
396+
404397 double robotCenterDistanceToTag = Math .sqrt (
405- Math .pow (adjustedCameraDistance , 2 ) + Math .pow (cameraOffsetDistance , 2 ) -
406- 2 * adjustedCameraDistance * cameraOffsetDistance *
407- Math .cos (Math .toRadians (horizontalAngleError + CAMERA_MOUNT_ANGLE_X_DEGREES ))
408- );
409-
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+
410402 double currentDistance = robotCenterDistanceToTag + 1.0 ;
411403 double distanceMeters = currentDistance * 0.3048 ;
412-
404+
413405 double robotAngleToTag = tagPose .getRotation ().getDegrees () + 180 - horizontalAngleError ;
414406 Rotation2d robotRotation = Rotation2d .fromDegrees (robotAngleToTag );
415-
407+
416408 double angleRad = Math .toRadians (robotAngleToTag );
417409 double robotX = tagPose .getX () - distanceMeters * Math .cos (angleRad );
418410 double robotY = tagPose .getY () - distanceMeters * Math .sin (angleRad );
419-
411+
420412 Translation2d robotTranslation = new Translation2d (robotX , robotY );
421413 return new Pose2d (robotTranslation , robotRotation );
422414 }
423-
415+
424416 public double getTimestamp () {
425417 return Timer .getFPGATimestamp ();
426418 }
0 commit comments