11package org .steelhawks .subsystems .vision .objdetect ;
22
3- import edu .wpi .first .math .MathUtil ;
43import edu .wpi .first .math .geometry .*;
54import edu .wpi .first .wpilibj .Timer ;
65import edu .wpi .first .wpilibj .smartdashboard .FieldObject2d ;
@@ -50,23 +49,21 @@ private void addCoralObservationToPose(ObjectVisionIO.ObjectObservation observat
5049 if (Constants .loggedValue ("CoralObservation/WheelOdomEmpty" , oldWheelOdomPose .isEmpty ())) {
5150 return ;
5251 }
53-
54- // latency compensation via interpolation
5552 var estimatedPose = RobotContainer .s_Swerve .getPose ();
5653 var wheelOdometryPose = RobotContainer .s_Swerve .getWheelOdomPose ();
5754 Pose2d fieldToRobot =
5855 estimatedPose .transformBy (new Transform2d (wheelOdometryPose , oldWheelOdomPose .get ()));
5956 Transform3d robotToCamera =
6057 Objects .requireNonNull (VisionConstants .getObjDetectConfig ())[observation .camIndex ()].robotToCamera ();
6158
62- // Get bounding box corners in PIXEL coordinates
63- double [] txCorners = observation .info ().tx ();
64- double [] tyCorners = observation .info ().ty ();
59+ // in angle coordinates
60+ double [] txCorners = observation .info ().tx (); // degrees
61+ double [] tyCorners = observation .info ().ty (); // degrees
6562
66- Logger . recordOutput ("CoralObservation/TxCorners " , txCorners );
67- Logger . recordOutput ("CoralObservation/TyCorners " , tyCorners );
63+ Constants . loggedValue ("CoralObservation/TxCorners_degrees " , txCorners );
64+ Constants . loggedValue ("CoralObservation/TyCorners_degrees " , tyCorners );
6865
69- // Find bounding box center in pixels
66+ // bounding box center in deg
7067 double minX = Math .min (Math .min (txCorners [0 ], txCorners [1 ]),
7168 Math .min (txCorners [2 ], txCorners [3 ]));
7269 double maxX = Math .max (Math .max (txCorners [0 ], txCorners [1 ]),
@@ -76,95 +73,47 @@ private void addCoralObservationToPose(ObjectVisionIO.ObjectObservation observat
7673 double maxY = Math .max (Math .max (tyCorners [0 ], tyCorners [1 ]),
7774 Math .max (tyCorners [2 ], tyCorners [3 ]));
7875
79- double centerX_pixels = (minX + maxX ) / 2.0 ;
80- double centerY_pixels = (minY + maxY ) / 2.0 ;
81-
82- // Limelight resolution: 1280x800
83- double resolutionWidth = 1280.0 ;
84- double resolutionHeight = 800.0 ;
85-
86- // Convert pixels to normalized coordinates [-1, 1]
87- // Center of image is at (width/2, height/2)
88- double centerX = (centerX_pixels - resolutionWidth / 2.0 ) / (resolutionWidth / 2.0 );
89- double centerY = -(centerY_pixels - resolutionHeight / 2.0 ) / (resolutionHeight / 2.0 ); // negative because Y increases downward in pixels
90-
91- Logger .recordOutput ("CoralObservation/centerX_pixels" , centerX_pixels );
92- Logger .recordOutput ("CoralObservation/centerY_pixels" , centerY_pixels );
93- Logger .recordOutput ("CoralObservation/centerX_normalized" , centerX );
94- Logger .recordOutput ("CoralObservation/centerY_normalized" , centerY );
95-
96- // Convert normalized coordinates to angles
97- // limelight 4 H:82° V:56.2°
98- double horizontalFOV = 82 ; // degrees
99- double verticalFOV = 56.2 ; // degrees
76+ // in degrees
77+ double tx = (minX + maxX ) / 2.0 ;
78+ double ty = (minY + maxY ) / 2.0 ;
10079
101- double tx = centerX * ( horizontalFOV / 2.0 ); // angle in degrees
102- double ty = centerY * ( verticalFOV / 2.0 ); // angle in degrees
80+ Constants . loggedValue ( "CoralObservation/tx_degrees" , tx );
81+ Constants . loggedValue ( "CoralObservation/ty_degrees" , ty );
10382
83+ // trig
10484 double cameraHeight = robotToCamera .getZ ();
105- double cameraPitch = robotToCamera .getRotation ().getY (); // in radians
106-
107- // Debug logging
108- Logger .recordOutput ("CoralObservation/tx_degrees" , tx );
109- Logger .recordOutput ("CoralObservation/ty_degrees" , ty );
110- Logger .recordOutput ("CoralObservation/cameraPitch_radians" , cameraPitch );
111-
112- // Convert ty from degrees to radians
85+ double cameraPitch = robotToCamera .getRotation ().getY (); // radians
86+ Constants .loggedValue ("CoralObservation/cameraPitch_radians" , cameraPitch );
11387 double tyRadians = Math .toRadians (ty );
114-
115- // Calculate vertical angle from horizontal
116- // cameraPitch is camera tilt (positive = up), ty is offset from camera center
11788 double verticalAngleFromHorizontal = cameraPitch + tyRadians ;
118-
119- Logger .recordOutput ("CoralObservation/AngleFromHorizontal_radians" , verticalAngleFromHorizontal );
120- Logger .recordOutput ("CoralObservation/AngleFromHorizontal_degrees" , Math .toDegrees (verticalAngleFromHorizontal ));
121-
122- // Target must be below horizontal to be valid
89+ Constants .loggedValue ("CoralObservation/AngleFromHorizontal_radians" , verticalAngleFromHorizontal );
90+ Constants .loggedValue ("CoralObservation/AngleFromHorizontal_degrees" , Math .toDegrees (verticalAngleFromHorizontal ));
12391 if (Constants .loggedValue ("CoralObservation/VerticalAngleError" , verticalAngleFromHorizontal <= 0 )) {
12492 return ;
12593 }
126-
127- double targetHeight = 0.0 ; // coral is on the ground
94+ double targetHeight = 0.0 ;
12895 double forwardDistance = (cameraHeight - targetHeight ) / Math .tan (verticalAngleFromHorizontal );
129-
130- // Calculate the translation from camera to coral in CAMERA reference frame
13196 double txRadians = Math .toRadians (tx );
132-
133- // Create vector from camera to coral in camera's frame
134- // X-axis is forward, Y-axis is left
135- Translation2d cameraToCoralInCameraFrame = new Translation2d (
136- forwardDistance * Math .cos (txRadians ), // forward component
137- forwardDistance * Math .sin (txRadians ) // lateral component
138- );
139-
140- Logger .recordOutput ("CoralObservation/cameraToCoralInCameraFrame" ,
97+ Translation2d cameraToCoralInCameraFrame =
98+ new Translation2d (
99+ forwardDistance * Math .cos (txRadians ),
100+ forwardDistance * Math .sin (txRadians ));
101+ Constants .loggedValue ("CoralObservation/cameraToCoralInCameraFrame" ,
141102 new Pose2d (cameraToCoralInCameraFrame , new Rotation2d ()));
142103
143- // Transform camera pose to field coordinates
144104 Transform2d robotToCamera2d = new Transform2d (
145105 robotToCamera .getTranslation ().toTranslation2d (),
146106 robotToCamera .getRotation ().toRotation2d ());
147107 Pose2d fieldToCamera = fieldToRobot .transformBy (robotToCamera2d );
148108
149- // Debug logging
150- Logger .recordOutput ("CoralObservation/robotToCamera2d" , robotToCamera2d );
151- Logger .recordOutput ("CoralObservation/cameraYaw_degrees" ,
152- Math .toDegrees (robotToCamera .getRotation ().getZ ()));
153- Logger .recordOutput ("CoralObservation/fieldToRobot" , fieldToRobot );
154- Logger .recordOutput ("CoralObservation/fieldToCamera" , fieldToCamera );
155- Logger .recordOutput ("CoralObservation/forwardDistance" , forwardDistance );
156- Logger .recordOutput ("CoralObservation/txRadians" , txRadians );
157-
158- // Transform the camera-frame vector to field frame
159- Pose2d fieldToCoral = fieldToCamera .transformBy (
160- new Transform2d (cameraToCoralInCameraFrame , new Rotation2d ())
161- );
162-
163- Logger .recordOutput ("CoralObservation/fieldToCoral" , fieldToCoral );
109+ Constants .loggedValue ("CoralObservation/fieldToRobot" , fieldToRobot );
110+ Constants .loggedValue ("CoralObservation/fieldToCamera" , fieldToCamera );
111+ Constants .loggedValue ("CoralObservation/forwardDistance" , forwardDistance );
164112
113+ Pose2d fieldToCoral = fieldToCamera
114+ .transformBy (new Transform2d (cameraToCoralInCameraFrame , new Rotation2d ()));
115+ Constants .loggedValue ("CoralObservation/fieldToCoral" , fieldToCoral );
165116 CoralPose coralPose = new CoralPose (fieldToCoral .getTranslation (), observation .timestamp ());
166-
167- // Remove overlapping corals and old detections
168117 coralPoses .removeIf (
169118 c -> c .translation .getDistance (fieldToCoral .getTranslation ()) <= coralOverlap
170119 || now - c .timestamp > coralMaxAge );
@@ -183,8 +132,8 @@ public void periodic() {
183132 .sorted (Comparator .comparingDouble (ObjectVisionIO .ObjectObservation ::timestamp ))
184133 .forEach (this ::addCoralObservationToPose );
185134
186- coralPoses .stream ()
187- . forEach ( o -> Logger .recordOutput ("CoralDetections/Detection" , new Pose2d (o .translation , new Rotation2d ())));
135+ coralPoses .forEach ( o ->
136+ Logger .recordOutput ("CoralDetections/Detection" , new Pose2d (o .translation , new Rotation2d ())));
188137 coralObjects .setPoses (
189138 coralPoses .stream ()
190139 .map (coral -> new Pose2d (coral .translation , new Rotation2d ())) // zero rotation
0 commit comments