14
14
import edu .wpi .first .math .util .Units ;
15
15
import frc .lib .UnitTestingUtil ;
16
16
import frc .robot .utils .VisionPoseEstimator ;
17
+ import frc .robot .utils .VisionPoseEstimator .VisionPoseEstimate ;
17
18
import frc .robot .utils .VisionPoseEstimator .VisionPoseEstimatorConstants ;
18
19
import java .util .ArrayList ;
19
20
import java .util .List ;
@@ -41,8 +42,22 @@ public static void setupField() {
41
42
List <AprilTag > tags = new ArrayList <>();
42
43
43
44
// // add all tags to the field layout
44
- tags .add (new AprilTag (1 , new Pose3d (1 , 0 , 1 , new Rotation3d (0 , 0 , -Math .PI ))));
45
- tags .add (new AprilTag (2 , new Pose3d (2 , 0.5 , 0.5 , new Rotation3d (0 , -0.3 , -Math .PI ))));
45
+ tags .add (
46
+ new AprilTag (1 , new Pose3d (1 , 0 , 1.2 , new Rotation3d (0 , 0 , -Math .PI )))); // close tag #1
47
+ tags .add (
48
+ new AprilTag (
49
+ 2 ,
50
+ new Pose3d (
51
+ 2 , 0.5 , 0.5 , new Rotation3d (0 , -0.3 , -Math .PI )))); // close tag #2 (for multi-tag)
52
+ tags .add (
53
+ new AprilTag (
54
+ 3 ,
55
+ new Pose3d (
56
+ 5 , 0.5 , 0.5 , new Rotation3d (0 , -1 , -Math .PI )))); // far tag #1 (for distance test)
57
+ tags .add (
58
+ new AprilTag (
59
+ 4 ,
60
+ new Pose3d (1.5 , 0 , 1 , new Rotation3d (0 , 0 , -Math .PI )))); // close tag #3 (for ambiguity)
46
61
47
62
_fieldLayout = new AprilTagFieldLayout (tags , Units .feetToMeters (54 ), Units .feetToMeters (27 ));
48
63
}
@@ -79,18 +94,19 @@ public void noResults() {
79
94
_testCam .update (this ::dummyGyroHeading );
80
95
81
96
// no targets, no new estimates
82
- assertEquals (_testCam .getNewEstimates ().size (), 0 );
97
+ assertEquals (0 , _testCam .getNewEstimates ().size ());
83
98
}
84
99
85
100
@ Test
86
101
public void singleTagResult () {
87
102
_visionSystemSim .addVisionTargets (
88
103
new VisionTargetSim (_fieldLayout .getTagPose (1 ).get (), TargetModel .kAprilTag36h11 , 1 ));
104
+
89
105
_visionSystemSim .update (Pose2d .kZero ); // should see the single target
90
106
91
107
_testCam .update (this ::dummyGyroHeading );
92
108
93
- assertEquals (_testCam .getNewEstimates ().size (), 1 );
109
+ assertEquals (1 , _testCam .getNewEstimates ().size ());
94
110
}
95
111
96
112
@ Test
@@ -103,54 +119,55 @@ public void singleTagResults() {
103
119
104
120
_testCam .update (this ::dummyGyroHeading );
105
121
106
- assertEquals (_testCam .getNewEstimates ().size (), 2 );
122
+ assertEquals (2 , _testCam .getNewEstimates ().size ());
107
123
}
108
124
109
125
@ Test
110
126
public void singleTagEstimate () {
111
127
_visionSystemSim .addVisionTargets (
112
128
new VisionTargetSim (_fieldLayout .getTagPose (1 ).get (), TargetModel .kAprilTag36h11 , 1 ));
129
+
113
130
_visionSystemSim .update (Pose2d .kZero );
114
131
115
132
_testCam .update (this ::dummyGyroHeading );
116
133
117
134
var estimates = _testCam .getNewEstimates (); // 1 estimate
118
- assertEquals (estimates .size (), 1 );
135
+ assertEquals (1 , estimates .size ());
119
136
120
137
var estimate = estimates .get (0 );
121
138
122
139
assert estimate .isValid ();
123
140
124
141
// pose validity
125
- assertEquals (estimate .pose ().getX (), 0 , 1e-4 );
126
- assertEquals (estimate .pose ().getY (), 0 , 1e-4 );
127
- assertEquals (estimate .pose ().getZ (), 0 , 1e-4 );
128
- assertEquals (estimate .pose ().getRotation ().getX (), 0 , 1e-4 );
129
- assertEquals (estimate .pose ().getRotation ().getY (), 0 , 1e-4 );
130
- assertEquals (estimate .pose ().getRotation ().getZ (), 0 , 1e-4 );
142
+ assertEquals (0 , estimate .pose ().getX (), 1e-4 );
143
+ assertEquals (0 , estimate .pose ().getY (), 1e-4 );
144
+ assertEquals (0 , estimate .pose ().getZ (), 1e-4 );
145
+ assertEquals (0 , estimate .pose ().getRotation ().getX (), 1e-4 );
146
+ assertEquals (0 , estimate .pose ().getRotation ().getY (), 1e-4 );
147
+ assertEquals (0 , estimate .pose ().getRotation ().getZ (), 1e-4 );
131
148
132
149
// should see only ID 1
133
- assertArrayEquals (estimate . detectedTags (), new int [] {1 });
150
+ assertArrayEquals (new int [] {1 }, estimate . detectedTags () );
134
151
135
152
// distance validity
136
153
assertEquals (
137
- estimate .avgTagDistance (),
138
154
_fieldLayout
139
155
.getTagPose (1 )
140
156
.get ()
141
157
.getTranslation ()
142
158
.getDistance (Pose3d .kZero .getTranslation ()),
159
+ estimate .avgTagDistance (),
143
160
1e-4 );
144
161
145
162
// std devs validity
146
- assertNotEquals (estimate .stdDevs (), new int [] {0 , 0 , 0 });
163
+ assertNotEquals (new int [] {-1 , -1 , -1 }, estimate .stdDevs ());
164
+ assertNotEquals (new int [] {0 , 0 , 0 }, estimate .stdDevs ());
147
165
}
148
166
149
167
// multi-tag does not work due to this issue:
150
168
// https://github.com/PhotonVision/photonvision/issues/1630
151
- // the field-relative corner coordinates are used in the multi-tag solvepnp:
169
+ // and the field-relative corner coordinates are used in the multi-tag solvepnp:
152
170
// https://github.com/PhotonVision/photonvision/blob/e8efef476b3b4681c8899a8720774d6dbd5ccf56/photon-targeting/src/main/java/org/photonvision/estimation/OpenCVHelp.java#L573
153
-
154
171
// @Test
155
172
public void multiTagEstimate () {
156
173
_visionSystemSim .addAprilTags (_fieldLayout );
@@ -159,7 +176,7 @@ public void multiTagEstimate() {
159
176
_testCam .update (this ::dummyGyroHeading );
160
177
161
178
var estimates = _testCam .getNewEstimates (); // 1 estimate
162
- assertEquals (estimates .size (), 1 );
179
+ assertEquals (1 , estimates .size ());
163
180
164
181
var estimate = estimates .get (0 );
165
182
@@ -168,19 +185,20 @@ public void multiTagEstimate() {
168
185
assert estimate .isValid ();
169
186
170
187
// pose validity
171
- assertEquals (estimate .pose ().getX (), 0 , 1e-4 );
172
- assertEquals (estimate .pose ().getY (), 0 , 1e-4 );
173
- assertEquals (estimate .pose ().getZ (), 0 , 1e-4 );
174
- assertEquals (estimate .pose ().getRotation ().getX (), 0 , 1e-4 );
175
- assertEquals (estimate .pose ().getRotation ().getY (), 0 , 1e-4 );
176
- assertEquals (estimate .pose ().getRotation ().getZ (), 0 , 1e-4 );
188
+ assertEquals (0 , estimate .pose ().getX (), 1e-4 );
189
+ assertEquals (0 , estimate .pose ().getY (), 1e-4 );
190
+ assertEquals (0 , estimate .pose ().getZ (), 1e-4 );
191
+ assertEquals (0 , estimate .pose ().getRotation ().getX (), 1e-4 );
192
+ assertEquals (0 , estimate .pose ().getRotation ().getY (), 1e-4 );
193
+ assertEquals (0 , estimate .pose ().getRotation ().getZ (), 1e-4 );
177
194
178
195
// should see only ID 1 and 2
179
- assertArrayEquals (estimate .detectedTags (), new int [] {1 , 2 });
196
+ assertArrayEquals (new int [] {1 , 2 }, estimate .detectedTags ());
197
+
198
+ assertEquals (-1 , estimate .ambiguity ()); // -1 ambiguity, it's not present during multi-tag
180
199
181
200
// distance validity
182
201
assertEquals (
183
- estimate .avgTagDistance (),
184
202
(_fieldLayout
185
203
.getTagPose (1 )
186
204
.get ()
@@ -192,10 +210,12 @@ public void multiTagEstimate() {
192
210
.getTranslation ()
193
211
.getDistance (Pose3d .kZero .getTranslation ()))
194
212
/ 2 ,
213
+ estimate .avgTagDistance (),
195
214
1e-4 );
196
215
197
216
// std devs validity
198
- assertNotEquals (estimate .stdDevs (), new int [] {0 , 0 , 0 });
217
+ assertNotEquals (new int [] {-1 , -1 , -1 }, estimate .stdDevs ());
218
+ assertNotEquals (new int [] {0 , 0 , 0 }, estimate .stdDevs ());
199
219
}
200
220
201
221
@ Test
@@ -209,51 +229,132 @@ public void boundsFilter() {
209
229
_testCam .update (this ::dummyGyroHeading );
210
230
211
231
var estimates = _testCam .getNewEstimates (); // 1 estimate
212
- assertEquals (estimates .size (), 1 );
232
+ assertEquals (1 , estimates .size ());
213
233
214
234
var estimate = estimates .get (0 );
215
235
216
236
assertFalse (estimate .isValid ());
217
237
218
238
// pose validity
219
- assertEquals (estimate .pose ().getX (), 0 , 1e-4 );
220
- assertEquals (estimate .pose ().getY (), 0 , 1e-4 );
221
- assertNotEquals (estimate .pose ().getZ (), 0 , 1e-4 );
222
- assertEquals (estimate .pose ().getRotation ().getX (), 0 , 1e-4 );
223
- assertEquals (estimate .pose ().getRotation ().getY (), 0 , 1e-4 );
224
- assertEquals (estimate .pose ().getRotation ().getZ (), 0 , 1e-4 );
239
+ assertEquals (0 , estimate .pose ().getX (), 1e-4 );
240
+ assertEquals (0 , estimate .pose ().getY (), 1e-4 );
241
+ assertNotEquals (0 , estimate .pose ().getZ (), 1e-4 );
242
+ assertEquals (0 , estimate .pose ().getRotation ().getX (), 1e-4 );
243
+ assertEquals (0 , estimate .pose ().getRotation ().getY (), 1e-4 );
244
+ assertEquals (0 , estimate .pose ().getRotation ().getZ (), 1e-4 );
225
245
226
246
// should see only ID 1
227
- assertArrayEquals (estimate . detectedTags (), new int [] {1 });
247
+ assertArrayEquals (new int [] {1 }, estimate . detectedTags () );
228
248
229
249
// distance validity
230
250
assertNotEquals (
231
- estimate .avgTagDistance (),
232
251
_fieldLayout
233
252
.getTagPose (1 )
234
253
.get ()
235
254
.getTranslation ()
236
255
.getDistance (Pose3d .kZero .getTranslation ()),
256
+ estimate .avgTagDistance (),
237
257
1e-4 );
238
258
239
259
// std devs validity
240
- assertArrayEquals (estimate . stdDevs (), new double [] {-1 , -1 , -1 });
260
+ assertArrayEquals (new double [] {-1 , -1 , -1 }, estimate . stdDevs () );
241
261
}
242
262
243
- // ⬇ TODO ⬇
263
+ // beta ambiguity issue:
264
+ // https://github.com/PhotonVision/photonvision/issues/1623
265
+ // so this isn't gonna work
266
+ // @Test
267
+ public void ambiguityFilter () {
268
+ // TODO
269
+ }
244
270
245
271
@ Test
246
- public void ambiguityFilter () {}
272
+ public void singleTagDistanceFilter () {
273
+ _visionSystemSim .addVisionTargets (
274
+ new VisionTargetSim (_fieldLayout .getTagPose (3 ).get (), TargetModel .kAprilTag36h11 , 3 ));
247
275
248
- @ Test
249
- public void singleTagDistanceFilter () {}
276
+ _visionSystemSim .update (Pose2d .kZero );
250
277
251
- @ Test
252
- public void multiTagDistanceFilter () {}
278
+ _testCam .update (this ::dummyGyroHeading );
253
279
254
- @ Test
255
- public void estimateSort () {}
280
+ var estimates = _testCam .getNewEstimates (); // 1 estimate
281
+ assertEquals (1 , estimates .size ());
282
+
283
+ var estimate = estimates .get (0 );
284
+
285
+ assertFalse (estimate .isValid ());
286
+
287
+ // pose validity
288
+ assertEquals (0 , estimate .pose ().getX (), 1e-4 );
289
+ assertEquals (0 , estimate .pose ().getY (), 1e-4 );
290
+ assertEquals (0 , estimate .pose ().getZ (), 1e-4 );
291
+ assertEquals (0 , estimate .pose ().getRotation ().getX (), 1e-4 );
292
+ assertEquals (0 , estimate .pose ().getRotation ().getY (), 1e-4 );
293
+ assertEquals (0 , estimate .pose ().getRotation ().getZ (), 1e-4 );
294
+
295
+ // should see only ID 3
296
+ assertArrayEquals (new int [] {3 }, estimate .detectedTags ());
297
+
298
+ // distance validity
299
+ assertEquals (
300
+ _fieldLayout
301
+ .getTagPose (3 )
302
+ .get ()
303
+ .getTranslation ()
304
+ .getDistance (Pose3d .kZero .getTranslation ()),
305
+ estimate .avgTagDistance (),
306
+ 1e-4 );
307
+
308
+ // std devs validity
309
+ assertArrayEquals (new double [] {-1 , -1 , -1 }, estimate .stdDevs ());
310
+ }
311
+
312
+ // multi-tag doesn't work, see other comment about multi-tag above
313
+ // @Test
314
+ public void multiTagDistanceFilter () {
315
+ // TODO
316
+ }
256
317
257
318
@ Test
258
- public void disambiguation () {}
319
+ public void estimateSort () {
320
+ List <VisionPoseEstimate > newEstimates = new ArrayList <>();
321
+
322
+ for (int i = 3 ; i > 0 ; i --) {
323
+ newEstimates .add (
324
+ new VisionPoseEstimate (
325
+ Pose3d .kZero , i , 0.03 , new int [] {1 }, 1.2 , new double [] {0.3 , 0.1 , 0.2 }, true ));
326
+ }
327
+
328
+ newEstimates .add (
329
+ new VisionPoseEstimate (
330
+ Pose3d .kZero ,
331
+ 2 , // same timestamp case
332
+ 0.03 ,
333
+ new int [] {1 },
334
+ 1.2 ,
335
+ new double [] {
336
+ 4 , 3 , 5
337
+ }, // these are worse std devs, so it should come before the better estimate @ timestamp
338
+ // = 2s
339
+ true ));
340
+
341
+ newEstimates .sort (VisionPoseEstimate .sorter );
342
+
343
+ // should be sorted from least timestamp to greatest
344
+ assertEquals (1 , newEstimates .get (0 ).timestamp ());
345
+ assertEquals (2 , newEstimates .get (1 ).timestamp ());
346
+ assertEquals (2 , newEstimates .get (2 ).timestamp ());
347
+ assertEquals (3 , newEstimates .get (3 ).timestamp ());
348
+
349
+ assertArrayEquals (new double [] {4 , 3 , 5 }, newEstimates .get (1 ).stdDevs ());
350
+ assertArrayEquals (new double [] {0.3 , 0.1 , 0.2 }, newEstimates .get (2 ).stdDevs ());
351
+ }
352
+
353
+ // beta ambiguity issue:
354
+ // https://github.com/PhotonVision/photonvision/issues/1623
355
+ // so this isn't gonna work
356
+ // @Test
357
+ public void disambiguation () {
358
+ // TODO
359
+ }
259
360
}
0 commit comments