Commit | Line | Data |
---|---|---|
7e447ed5 KZ |
1 | package org.usfirst.frc.team3501.robot.subsystems; |
2 | ||
3 | import com.ni.vision.NIVision.PointDouble; | |
4 | ||
5 | import edu.wpi.first.wpilibj.image.BinaryImage; | |
6 | import edu.wpi.first.wpilibj.image.HSLImage; | |
7 | import edu.wpi.first.wpilibj.image.NIVisionException; | |
8 | import edu.wpi.first.wpilibj.image.ParticleAnalysisReport; | |
9 | import edu.wpi.first.wpilibj.networktables.NetworkTable; | |
10 | import edu.wpi.first.wpilibj.vision.AxisCamera; | |
11 | ||
12 | /** | |
13 | * | |
14 | */ | |
15 | ||
16 | /** | |
17 | * | |
18 | * @author Elijah Kaufman | |
19 | * @version 1.0 | |
20 | * @description Uses opencv and network table 3.0 to detect the vision targets | |
21 | * | |
22 | */ | |
23 | public class TowerTracker2 { | |
24 | ||
25 | /** | |
26 | * static method to load opencv and networkTables | |
27 | */ | |
28 | static { | |
29 | System.out.println(System.getProperty("java.library.path")); | |
30 | System.loadLibrary("libopencv_java310.so"); | |
31 | NetworkTable.setClientMode(); | |
32 | NetworkTable.setIPAddress("roborio-3502.local"); | |
33 | } | |
34 | // constants for the color rbg values | |
35 | // these are the threshold values in order | |
36 | // LOWER_BOUNDS = new Scalar(58, 0, 109), | |
37 | // UPPER_BOUNDS = new Scalar(93, 255, 240); | |
38 | ||
39 | // the size for resing the image | |
40 | // public static final Size resize = new Size(320, 240); | |
41 | ||
42 | public static HSLImage originalImage; | |
43 | public static AxisCamera camera; | |
44 | public static BinaryImage filteredImage; | |
45 | ||
46 | // Constants for known variables | |
47 | // the height to the top of the target in first stronghold is 97 inches | |
48 | public static final int TOP_TARGET_HEIGHT = 97; | |
49 | // the physical height of the camera lens | |
50 | public static final int TOP_CAMERA_HEIGHT = 32; | |
51 | ||
52 | // camera details, can usually be found on the datasheets of the camera | |
53 | public static final double VERTICAL_FOV = 51; | |
54 | public static final double HORIZONTAL_FOV = 67; | |
55 | public static final double CAMERA_ANGLE = 10; | |
56 | ||
57 | public static boolean shouldRun = true; | |
58 | ||
59 | /** | |
60 | * | |
61 | * @param args | |
62 | * command line arguments | |
63 | * just the main loop for the program and the entry points | |
64 | */ | |
65 | public static void main(String[] args) { | |
66 | // TODO Auto-generated method stub | |
67 | NetworkTable table = NetworkTable.getTable("SmartDashboard"); | |
68 | // main loop of the program | |
69 | while (shouldRun) { | |
70 | try { | |
71 | // opens up the camera stream and tries to load it | |
72 | // videoCapture = new VideoCapture(); | |
73 | // videoCapture.open("http://10.35.01.11/mjpg/video.mjpg"); | |
74 | // wait until it is opened | |
75 | // while (!videoCapture.isOpened()) {} | |
76 | // time to actually process the acquired images | |
77 | processImage(); | |
78 | } catch (Exception e) { | |
79 | e.printStackTrace(); | |
80 | break; | |
81 | } | |
82 | } | |
83 | // make sure the java process quits when the loop finishes | |
84 | // videoCapture.release(); | |
85 | System.exit(0); | |
86 | } | |
87 | ||
88 | /** | |
89 | * | |
90 | * reads an image from a live image capture and outputs information to the | |
91 | * SmartDashboard or a file | |
92 | * | |
93 | * @throws NIVisionException | |
94 | */ | |
95 | public static void processImage() throws NIVisionException { | |
96 | // ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>(); | |
97 | double x, y, targetX, targetY, distance, azimuth; | |
98 | // frame counter | |
99 | int FrameCount = 0; | |
100 | long before = System.currentTimeMillis(); | |
101 | // only run for the specified time | |
102 | while (FrameCount < 100) { | |
103 | originalImage = camera.getImage(); | |
104 | filteredImage = originalImage.thresholdHSL(328, 360, 100, 255, 43, 255); | |
105 | ParticleAnalysisReport[] reports = filteredImage | |
106 | .getOrderedParticleAnalysisReports(); | |
107 | // make sure the contours that are detected are at least 20x20 | |
108 | // pixels with an area of 400 and an aspect ration greater then 1 | |
109 | // Commented by HB to go past syntax errors | |
110 | for (ParticleAnalysisReport report : reports) { | |
111 | if (report.boundingRectHeight > 25 && report.boundingRectWidth > 25 | |
112 | && report.boundingRectWidth > report.boundingRectHeight) { | |
113 | y = reports[0].boundingRectTop - reports[0].boundingRectHeight / 2; | |
114 | y = -((2 * (y / originalImage.getHeight())) - 1); | |
115 | distance = (TOP_TARGET_HEIGHT - TOP_CAMERA_HEIGHT) / | |
116 | Math.tan((y * VERTICAL_FOV / 2.0 + CAMERA_ANGLE) * Math.PI / 180); | |
117 | // angle to target...would not rely on this | |
118 | targetX = reports[0].boundingRectLeft + reports[0].boundingRectWidth | |
119 | / 2; | |
120 | targetX = (2 * (targetX / originalImage.getWidth())) - 1; | |
121 | azimuth = normalize360(targetX * HORIZONTAL_FOV / 2.0 + 0); | |
122 | // drawing info on target | |
123 | x = reports[0].boundingRectLeft + originalImage.getWidth() / 2; | |
124 | y = reports[0].boundingRectTop - originalImage.getHeight() / 2; | |
125 | PointDouble center = new PointDouble(x, y); | |
126 | System.out.println(distance + "m, " + azimuth + " degrees " | |
127 | + center.x + ", " + center.y); | |
128 | } | |
129 | } | |
130 | // Commented by HB to go past syntax errors | |
131 | for (ParticleAnalysisReport report : reports) { | |
132 | // Imgproc.rectangle(matOriginal, rec.br(), rec.tl(), BLACK); | |
133 | // draw a rectangle on image matOriginal using bottom right vertex and | |
134 | // top left vertex as input | |
135 | } | |
136 | // if there is only 1 target, then we have found the target we want | |
137 | // output an image for debugging | |
138 | // Imgcodecs.imwrite("output.png", matOriginal); | |
139 | FrameCount++; | |
140 | } | |
141 | shouldRun = false; | |
142 | } | |
143 | ||
144 | /** | |
145 | * @param angle | |
146 | * a nonnormalized angle | |
147 | */ | |
148 | public static double normalize360(double angle) { | |
149 | while (angle >= 360.0) | |
150 | { | |
151 | angle -= 360.0; | |
152 | } | |
153 | while (angle < 0.0) | |
154 | { | |
155 | angle += 360.0; | |
156 | } | |
157 | return angle; | |
158 | } | |
159 | } |