-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBasicHomographySample.java
More file actions
158 lines (129 loc) · 4.93 KB
/
BasicHomographySample.java
File metadata and controls
158 lines (129 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package org.firstinspires.ftc.teamcode;
import java.util.ArrayList;
import java.util.List;
import com.qualcomm.hardware.limelightvision.LLResult;
import com.qualcomm.hardware.limelightvision.LLResultTypes;
import com.qualcomm.hardware.limelightvision.Limelight3A;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import org.opencv.core.Point;
/**
* BasicHomographySample demonstrates using a homography transformation
* with a Limelight camera to convert camera coordinates to robot-relative coordinates.
*/
@TeleOp(name = "BasicHomographySample", group = "Linear OpMode")
public class BasicHomographySample extends LinearOpMode {
// Offset constants in inches
public static double HORIZONTAL_OFFSET = 0;
public static double VERTICAL_OFFSET = 24;
// Camera resolution constants
public static double CAMERA_WIDTH = 640.0;
public static double CAMERA_HEIGHT = 480.0;
// Camera field of view constants in degrees
public static double HORIZONTAL_FOV = 54.5;
public static double VERTICAL_FOV = 42.0;
// Homography transformation matrix
private final double[][] H = {
{4.158013, 5.076947, -1146.668632},
{-1.674058, 8.920382, -450.058258},
{-0.000171, 0.003455, 1.000000}
};
// Pixels Per Inch on calibration image
private final double PPI = 96.0;
private Limelight3A limelight;
@Override
public void runOpMode() {
initializeLimelight();
waitForStart();
if (opModeIsActive()) {
while (opModeIsActive()) {
ArrayList<Item> results = processLimelightResults();
displayResults(results);
}
}
}
/**
* Configures and starts the Limelight camera.
*/
private void initializeLimelight() {
limelight = hardwareMap.get(Limelight3A.class, "limelight");
limelight.pipelineSwitch(0);
limelight.start();
}
/**
* Processes the latest results from the Limelight camera.
*
* @return ArrayList of detected items with robot-relative coordinates
*/
private ArrayList<Item> processLimelightResults() {
LLResult results = limelight.getLatestResult();
ArrayList<Item> items = new ArrayList<>();
if (results != null && results.isValid()) {
List<LLResultTypes.DetectorResult> detectorResults = results.getDetectorResults();
for (LLResultTypes.DetectorResult result : detectorResults) {
Point robotCoordinates = calculateRobotCoordinates(result);
int id = result.getClassId();
items.add(new Item(id, robotCoordinates));
}
}
return items;
}
/**
* Displays the detected items in telemetry.
*
* @param results List of detected items to display
*/
private void displayResults(ArrayList<Item> results) {
StringBuilder output = new StringBuilder();
for (Item item : results) {
output.append(item.toString()).append("\n");
}
telemetry.addData("Results", output.toString());
telemetry.update();
}
/**
* Transforms detector result using homography matrix to get robot-relative coordinates.
*
* @param result The detector result to transform
* @return Robot-relative coordinates of the detected object
*/
private Point calculateRobotCoordinates(LLResultTypes.DetectorResult result) {
// Get angular coordinates
double x_degrees = result.getTargetXDegrees();
double y_degrees = result.getTargetYDegrees();
// Convert to pixel coordinates using configurable resolution and FOV
double x = (x_degrees / HORIZONTAL_FOV) * CAMERA_WIDTH + (CAMERA_WIDTH / 2.0);
double y = (y_degrees / VERTICAL_FOV) * CAMERA_HEIGHT + (CAMERA_HEIGHT / 2.0);
// Apply homography transformation
double X_prime = H[0][0] * x + H[0][1] * y + H[0][2];
double Y_prime = H[1][0] * x + H[1][1] * y + H[1][2];
double W = H[2][0] * x + H[2][1] * y + H[2][2];
// Convert to robot coordinates with offsets
double x_robot = X_prime / W / PPI + HORIZONTAL_OFFSET;
double y_robot = Y_prime / W / PPI + VERTICAL_OFFSET;
return new Point(x_robot, y_robot);
}
}
/**
* Helper class to store results after transformation.
*/
class Item {
// Detected Class ID
private final int id;
// Robot-relative position
private final Point position;
/**
* Creates a new Item with ID and position.
*
* @param id The class ID of the detected object
* @param position The position in robot-relative coordinates
*/
public Item(int id, Point position) {
this.id = id;
this.position = position;
}
@Override
public String toString() {
return "Detected Item " + id + " at " + position.toString();
}
}