Skip to content

Commit 1b13461

Browse files
updated pose math
1 parent 22243bd commit 1b13461

File tree

1 file changed

+97
-101
lines changed

1 file changed

+97
-101
lines changed

src/main/java/frc/robot/subsystems/localization/localizationSubsystem.java

Lines changed: 97 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)