mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-24 01:31:44 +00:00
Add Photonlib (#231)
Merges Photonlib into Photonvision, along with the Photonlib code examples. Also creates a new PhotonTargeting library teams can depend on.
This commit is contained in:
98
photon-lib/src/test/java/org/photonvision/PacketTest.java
Normal file
98
photon-lib/src/test/java/org/photonvision/PacketTest.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.photonvision;
|
||||
|
||||
import edu.wpi.first.wpilibj.geometry.Rotation2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Transform2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Translation2d;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.photonvision.common.dataflow.structures.Packet;
|
||||
import org.photonvision.targeting.PhotonPipelineResult;
|
||||
import org.photonvision.targeting.PhotonTrackedTarget;
|
||||
|
||||
class PacketTest {
|
||||
@Test
|
||||
void testSimpleTrackedTarget() {
|
||||
var target =
|
||||
new PhotonTrackedTarget(
|
||||
3.0, 4.0, 9.0, -5.0, new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)));
|
||||
var p = new Packet(PhotonTrackedTarget.PACK_SIZE_BYTES);
|
||||
target.populatePacket(p);
|
||||
|
||||
var b = new PhotonTrackedTarget();
|
||||
b.createFromPacket(p);
|
||||
|
||||
Assertions.assertEquals(target, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimplePipelineResult() {
|
||||
var result = new PhotonPipelineResult(1, new ArrayList<>());
|
||||
var p = new Packet(result.getPacketSize());
|
||||
result.populatePacket(p);
|
||||
|
||||
var b = new PhotonPipelineResult();
|
||||
b.createFromPacket(p);
|
||||
|
||||
Assertions.assertEquals(result, b);
|
||||
|
||||
var result2 =
|
||||
new PhotonPipelineResult(
|
||||
2,
|
||||
List.of(
|
||||
new PhotonTrackedTarget(
|
||||
3.0,
|
||||
-4.0,
|
||||
9.0,
|
||||
4.0,
|
||||
new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5))),
|
||||
new PhotonTrackedTarget(
|
||||
3.0,
|
||||
-4.0,
|
||||
9.1,
|
||||
6.7,
|
||||
new Transform2d(new Translation2d(1, 5), new Rotation2d(1.5)))));
|
||||
var p2 = new Packet(result2.getPacketSize());
|
||||
result2.populatePacket(p2);
|
||||
|
||||
var b2 = new PhotonPipelineResult();
|
||||
b2.createFromPacket(p2);
|
||||
|
||||
Assertions.assertEquals(result2, b2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBytePackFromCpp() {
|
||||
byte[] bytePack = {
|
||||
64, 8, 0, 0, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0, 0, 0, 64, 34, 0, 0, 0, 0, 0, 0, -64, 20, 0, 0, 0,
|
||||
0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 85, 124, 101, 19, -54, -47,
|
||||
122
|
||||
};
|
||||
var t = new PhotonTrackedTarget();
|
||||
t.createFromPacket(new Packet(bytePack));
|
||||
|
||||
var target =
|
||||
new PhotonTrackedTarget(
|
||||
3.0, 4.0, 9.0, -5.0, new Transform2d(new Translation2d(1, 2), new Rotation2d(1.5)));
|
||||
|
||||
Assertions.assertEquals(t, target);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.photonvision;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.photonvision.common.dataflow.structures.Packet;
|
||||
import org.photonvision.targeting.PhotonPipelineResult;
|
||||
|
||||
class PhotonCameraTest {
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> {
|
||||
var packet = new Packet(1);
|
||||
var ret = new PhotonPipelineResult();
|
||||
packet.setData(new byte[0]);
|
||||
if (packet.getSize() < 1) {
|
||||
return;
|
||||
}
|
||||
ret.createFromPacket(packet);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.photonvision;
|
||||
|
||||
import edu.wpi.first.wpilibj.geometry.Pose2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Rotation2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Transform2d;
|
||||
import edu.wpi.first.wpilibj.util.Units;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PhotonUtilTest {
|
||||
@Test
|
||||
public void testDistance() {
|
||||
var camHeight = 1;
|
||||
var targetHeight = 3;
|
||||
var camPitch = Units.degreesToRadians(0);
|
||||
var targetPitch = Units.degreesToRadians(30);
|
||||
|
||||
var dist =
|
||||
PhotonUtils.calculateDistanceToTargetMeters(camHeight, targetHeight, camPitch, targetPitch);
|
||||
|
||||
Assertions.assertEquals(3.464, dist, 0.01);
|
||||
|
||||
camHeight = 1;
|
||||
targetHeight = 2;
|
||||
camPitch = Units.degreesToRadians(20);
|
||||
targetPitch = Units.degreesToRadians(-10);
|
||||
|
||||
dist =
|
||||
PhotonUtils.calculateDistanceToTargetMeters(camHeight, targetHeight, camPitch, targetPitch);
|
||||
Assertions.assertEquals(5.671, dist, 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransform() {
|
||||
|
||||
var camHeight = 1;
|
||||
var tgtHeight = 3;
|
||||
var camPitch = 0;
|
||||
var tgtPitch = Units.degreesToRadians(30);
|
||||
var tgtYaw = new Rotation2d();
|
||||
var gyroAngle = new Rotation2d();
|
||||
var fieldToTarget = new Pose2d();
|
||||
var cameraToRobot = new Transform2d();
|
||||
|
||||
var fieldToRobot =
|
||||
PhotonUtils.estimateFieldToRobot(
|
||||
PhotonUtils.estimateCameraToTarget(
|
||||
PhotonUtils.estimateCameraToTargetTranslation(
|
||||
PhotonUtils.calculateDistanceToTargetMeters(
|
||||
camHeight, tgtHeight, camPitch, tgtPitch),
|
||||
tgtYaw),
|
||||
fieldToTarget,
|
||||
gyroAngle),
|
||||
fieldToTarget,
|
||||
cameraToRobot);
|
||||
|
||||
Assertions.assertEquals(-3.464, fieldToRobot.getX(), 0.1);
|
||||
Assertions.assertEquals(0, fieldToRobot.getY(), 0.1);
|
||||
Assertions.assertEquals(0, fieldToRobot.getRotation().getDegrees(), 0.1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.photonvision;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import edu.wpi.first.wpilibj.geometry.Pose2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Rotation2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Transform2d;
|
||||
import edu.wpi.first.wpilibj.geometry.Translation2d;
|
||||
import edu.wpi.first.wpilibj.util.Units;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.photonvision.targeting.PhotonTrackedTarget;
|
||||
|
||||
class SimVisionSystemTest {
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> {
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 320, 240, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(new Pose2d(), 0.0, 1.0, 1.0));
|
||||
for (int loopIdx = 0; loopIdx < 100; loopIdx++) {
|
||||
sysUnderTest.processFrame(new Pose2d());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = {5, 10, 15, 20, 25, 30})
|
||||
public void testDistanceAligned(double dist) {
|
||||
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 320, 240, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 0.0, 1.0, 1.0));
|
||||
|
||||
final var robotPose = new Pose2d(new Translation2d(35 - dist, 0), new Rotation2d());
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
|
||||
var result = sysUnderTest.cam.getLatestResult();
|
||||
|
||||
assertTrue(result.hasTargets());
|
||||
assertEquals(result.getBestTarget().getCameraToTarget().getTranslation().getNorm(), dist);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVisibilityCupidShuffle() {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 640, 480, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 1.0, 3.0, 3.0));
|
||||
|
||||
// To the right, to the right
|
||||
var robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(-70));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// To the right, to the right
|
||||
robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(-95));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// To the left, to the left
|
||||
robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(90));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// To the left, to the left
|
||||
robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(65));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// now kick, now kick
|
||||
robotPose = new Pose2d(new Translation2d(2, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// now kick, now kick
|
||||
robotPose = new Pose2d(new Translation2d(2, 0), Rotation2d.fromDegrees(-5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// now walk it by yourself
|
||||
robotPose = new Pose2d(new Translation2d(2, 0), Rotation2d.fromDegrees(-179));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// now walk it by yourself
|
||||
sysUnderTest.moveCamera(
|
||||
new Transform2d(new Translation2d(), Rotation2d.fromDegrees(180)), 0, 1.0);
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotVisibleVert1() {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 640, 480, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 1.0, 3.0, 3.0));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
sysUnderTest.moveCamera(new Transform2d(), 5000, 1.0); // vooop selfie stick
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotVisibleVert2() {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 45.0, new Transform2d(), 1, 99999, 1234, 1234, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 3.0, 0.5, 0.5));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(32, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
// Pitched back camera should mean target goes out of view below the robot as distance increases
|
||||
robotPose = new Pose2d(new Translation2d(0, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotVisibleTgtSize() {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 640, 480, 20.0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 1.0, 0.25, 0.1));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(32, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
robotPose = new Pose2d(new Translation2d(0, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotVisibleTooFarForLEDs() {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 10, 640, 480, 1.0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 1.0, 0.25, 0.1));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(28, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertTrue(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
|
||||
robotPose = new Pose2d(new Translation2d(0, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
assertFalse(sysUnderTest.cam.getLatestResult().hasTargets());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = {-10, -5, -0, -1, -2, 5, 7, 10.23})
|
||||
public void testYawAngles(double testYaw) {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d(Math.PI / 4));
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 1, 99999, 640, 480, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 0.0, 0.5, 0.5));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(32, 0), Rotation2d.fromDegrees(testYaw));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
var res = sysUnderTest.cam.getLatestResult();
|
||||
assertTrue(res.hasTargets());
|
||||
var tgt = res.getBestTarget();
|
||||
assertEquals(tgt.getYaw(), testYaw, 0.0001);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = {-10, -5, -0, -1, -2, 5, 7, 10.23, 20.21, -19.999})
|
||||
public void testCameraPitch(double testPitch) {
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d(Math.PI / 4));
|
||||
final var robotPose = new Pose2d(new Translation2d(30, 0), new Rotation2d(0));
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 80.0, 0.0, new Transform2d(), 0.0, 99999, 640, 480, 0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, 0.0, 0.5, 0.5));
|
||||
|
||||
sysUnderTest.moveCamera(new Transform2d(), 0.0, testPitch);
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
var res = sysUnderTest.cam.getLatestResult();
|
||||
assertTrue(res.hasTargets());
|
||||
var tgt = res.getBestTarget();
|
||||
// If the camera is pitched down by 10 degrees, the target should appear
|
||||
// in the upper part of the image (ie, pitch positive). Therefor,
|
||||
// pass/fail involves -1.0.
|
||||
assertEquals(tgt.getPitch(), -1.0 * testPitch, 0.0001);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> distCalCParamProvider() {
|
||||
// Arbitrary and fairly random assortment of distances, camera pitches, and heights
|
||||
return Stream.of(
|
||||
Arguments.of(5, 35, 0),
|
||||
Arguments.of(6, 35, 1),
|
||||
Arguments.of(10, 35, 0),
|
||||
Arguments.of(15, 35, 2),
|
||||
Arguments.of(19.95, 35, 0),
|
||||
Arguments.of(20, 35, 0),
|
||||
Arguments.of(5, 42, 1),
|
||||
Arguments.of(6, 42, 0),
|
||||
Arguments.of(10, 42, 2),
|
||||
Arguments.of(15, 42, 0.5),
|
||||
Arguments.of(19.42, 35, 0),
|
||||
Arguments.of(20, 42, 0),
|
||||
Arguments.of(5, 55, 2),
|
||||
Arguments.of(6, 55, 0),
|
||||
Arguments.of(10, 54, 2.2),
|
||||
Arguments.of(15, 53, 0),
|
||||
Arguments.of(19.52, 35, 1.1),
|
||||
Arguments.of(20, 51, 2.87),
|
||||
Arguments.of(20, 55, 3));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("distCalCParamProvider")
|
||||
public void testDistanceCalc(double testDist, double testPitch, double testHeight) {
|
||||
// Assume dist along ground and tgt height the same. Iterate over other parameters.
|
||||
|
||||
final var targetPose = new Pose2d(new Translation2d(35, 0), new Rotation2d(Math.PI / 42));
|
||||
final var robotPose = new Pose2d(new Translation2d(35 - testDist, 0), new Rotation2d(0));
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem(
|
||||
"absurdlylongnamewhichshouldneveractuallyhappenbuteehwelltestitanywaysohowsyourdaygoingihopegoodhaveagreatrestofyourlife!",
|
||||
160.0,
|
||||
testPitch,
|
||||
new Transform2d(),
|
||||
testHeight,
|
||||
99999,
|
||||
640,
|
||||
480,
|
||||
0);
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPose, testDist, 0.5, 0.5));
|
||||
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
var res = sysUnderTest.cam.getLatestResult();
|
||||
assertTrue(res.hasTargets());
|
||||
var tgt = res.getBestTarget();
|
||||
assertEquals(tgt.getYaw(), 0.0, 0.0001);
|
||||
double distMeas =
|
||||
PhotonUtils.calculateDistanceToTargetMeters(
|
||||
testHeight,
|
||||
testDist,
|
||||
Units.degreesToRadians(testPitch),
|
||||
Units.degreesToRadians(tgt.getPitch()));
|
||||
assertEquals(distMeas, testDist, 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleTargets() {
|
||||
final var targetPoseL = new Pose2d(new Translation2d(35, 2), new Rotation2d());
|
||||
final var targetPoseC = new Pose2d(new Translation2d(35, 0), new Rotation2d());
|
||||
final var targetPoseR = new Pose2d(new Translation2d(35, -2), new Rotation2d());
|
||||
var sysUnderTest =
|
||||
new SimVisionSystem("Test", 160.0, 0.0, new Transform2d(), 5.0, 99999, 640, 480, 20.0);
|
||||
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseL, 0.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseC, 1.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseR, 2.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseL, 3.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseC, 4.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseR, 5.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseL, 6.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseC, 7.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseL, 8.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseR, 9.0, 0.25, 0.1));
|
||||
sysUnderTest.addSimVisionTarget(new SimVisionTarget(targetPoseL, 10.0, 0.25, 0.1));
|
||||
|
||||
var robotPose = new Pose2d(new Translation2d(30, 0), Rotation2d.fromDegrees(5));
|
||||
sysUnderTest.processFrame(robotPose);
|
||||
var res = sysUnderTest.cam.getLatestResult();
|
||||
assertTrue(res.hasTargets());
|
||||
List<PhotonTrackedTarget> tgtList;
|
||||
tgtList = res.getTargets();
|
||||
assertEquals(tgtList.size(), 11);
|
||||
}
|
||||
}
|
||||
91
photon-lib/src/test/native/cpp/PacketTest.cpp
Normal file
91
photon-lib/src/test/native/cpp/PacketTest.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <units/angle.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "photonlib/PhotonPipelineResult.h"
|
||||
#include "photonlib/PhotonTrackedTarget.h"
|
||||
|
||||
TEST(PacketTest, PhotonTrackedTarget) {
|
||||
photonlib::PhotonTrackedTarget target{
|
||||
3.0, 4.0, 9.0, -5.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)};
|
||||
photonlib::Packet p;
|
||||
p << target;
|
||||
|
||||
photonlib::PhotonTrackedTarget b;
|
||||
p >> b;
|
||||
|
||||
for (auto& c : p.GetData()) {
|
||||
std::cout << static_cast<int>(c) << ",";
|
||||
}
|
||||
|
||||
EXPECT_EQ(target, b);
|
||||
}
|
||||
|
||||
TEST(PacketTest, PhotonPipelineResult) {
|
||||
photonlib::PhotonPipelineResult result{1_s, {}};
|
||||
photonlib::Packet p;
|
||||
p << result;
|
||||
|
||||
photonlib::PhotonPipelineResult b;
|
||||
p >> b;
|
||||
|
||||
EXPECT_EQ(result, b);
|
||||
|
||||
wpi::SmallVector<photonlib::PhotonTrackedTarget, 2> targets{
|
||||
photonlib::PhotonTrackedTarget{
|
||||
3.0, -4.0, 9.0, 4.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)},
|
||||
photonlib::PhotonTrackedTarget{
|
||||
3.0, -4.0, 9.1, 6.7,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 5_m), 1.5_rad)}};
|
||||
|
||||
photonlib::PhotonPipelineResult result2{2_s, targets};
|
||||
photonlib::Packet p2;
|
||||
p2 << result2;
|
||||
|
||||
photonlib::PhotonPipelineResult b2;
|
||||
p2 >> b2;
|
||||
|
||||
EXPECT_EQ(result2, b2);
|
||||
}
|
||||
|
||||
TEST(PacketTest, BytePackFromJava) {
|
||||
std::vector<signed char> bytePack{
|
||||
64, 8, 0, 0, 0, 0, 0, 0, 64, 16, 0, 0, 0, 0,
|
||||
0, 0, 64, 34, 0, 0, 0, 0, 0, 0, -64, 20, 0, 0,
|
||||
0, 0, 0, 0, 63, -16, 0, 0, 0, 0, 0, 0, 64, 0,
|
||||
0, 0, 0, 0, 0, 0, 64, 85, 124, 101, 19, -54, -47, 122};
|
||||
|
||||
std::vector<char> bytes;
|
||||
for (auto a : bytePack) bytes.emplace_back(static_cast<char>(a));
|
||||
|
||||
photonlib::Packet packet{bytes};
|
||||
|
||||
photonlib::PhotonTrackedTarget res;
|
||||
packet >> res;
|
||||
|
||||
photonlib::PhotonTrackedTarget target{
|
||||
3.0, 4.0, 9.0, -5.0,
|
||||
frc::Transform2d(frc::Translation2d(1_m, 2_m), 1.5_rad)};
|
||||
|
||||
EXPECT_EQ(res, target);
|
||||
}
|
||||
21
photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp
Normal file
21
photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "photonlib/PhotonUtils.h"
|
||||
|
||||
TEST(PhotonUtilsTest, TestInclude) {}
|
||||
401
photon-lib/src/test/native/cpp/SimVisionSystemTest.cpp
Normal file
401
photon-lib/src/test/native/cpp/SimVisionSystemTest.cpp
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
|
||||
#include <units/angle.h>
|
||||
#include <units/length.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "photonlib/PhotonCamera.h"
|
||||
#include "photonlib/PhotonUtils.h"
|
||||
#include "photonlib/SimVisionSystem.h"
|
||||
|
||||
TEST(SimVisionSystemTest, testEmpty) {
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
320, 240, 0.0);
|
||||
|
||||
for (int loopIdx = 0; loopIdx < 100; loopIdx++) {
|
||||
sysUnderTest.ProcessFrame(frc::Pose2d());
|
||||
}
|
||||
}
|
||||
|
||||
class SimVisionSystemTestDistParam : public testing::TestWithParam<double> {};
|
||||
INSTANTIATE_TEST_SUITE_P(SimVisionSystemTestDistParamInst,
|
||||
SimVisionSystemTestDistParam,
|
||||
testing::Values(5, 10, 15, 20, 25, 30));
|
||||
|
||||
TEST_P(SimVisionSystemTestDistParam, testDistanceAligned) {
|
||||
double dist = GetParam();
|
||||
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
320, 240, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 0.0_m, 1.0_m, 1.0_m));
|
||||
|
||||
auto robotPose = frc::Pose2d(
|
||||
frc::Translation2d(units::meter_t(35.0 - dist), 0_m), frc::Rotation2d());
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
ASSERT_EQ(result.GetBestTarget()
|
||||
.GetCameraRelativePose()
|
||||
.Translation()
|
||||
.Norm()
|
||||
.to<double>(),
|
||||
dist);
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testVisibilityCupidShuffle) {
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
320, 240, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 0.0_m, 3.0_m, 3.0_m));
|
||||
|
||||
// To the right, to the right
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(5.0_m, 0.0_m), frc::Rotation2d(-70.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
|
||||
// To the right, to the right
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(5.0_m, 0.0_m), frc::Rotation2d(-95.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
|
||||
// To the left, to the left
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(5.0_m, 0.0_m), frc::Rotation2d(90.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
|
||||
// To the left, to the left
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(5.0_m, 0.0_m), frc::Rotation2d(65.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
|
||||
// now kick, now kick
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(2.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
|
||||
// now kick, now kick
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(2.0_m, 0.0_m), frc::Rotation2d(-5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
|
||||
// now walk it by yourself
|
||||
robotPose = frc::Pose2d(frc::Translation2d(2.0_m, 0.0_m),
|
||||
frc::Rotation2d(-179.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
|
||||
// now walk it by yourself
|
||||
sysUnderTest.MoveCamera(
|
||||
frc::Transform2d(frc::Translation2d(), frc::Rotation2d(180_deg)), 0.0_m,
|
||||
1.0_deg);
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testNotVisibleVert1) {
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
640, 480, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 1.0_m, 3.0_m, 2.0_m));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(5.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
|
||||
sysUnderTest.MoveCamera(
|
||||
frc::Transform2d(frc::Translation2d(), frc::Rotation2d(0_deg)), 5000.0_m,
|
||||
1.0_deg);
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testNotVisibleVert2) {
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 45.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
1234, 1234, 0.5);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 3.0_m, 0.5_m, 0.5_m));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(32.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(0.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testNotVisibleTgtSize) {
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
640, 480, 20.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 1.10_m, 0.25_m, 0.1_m));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(32.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(0.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testNotVisibleTooFarForLEDs) {
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 10.0_m,
|
||||
640, 480, 1.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 1.10_m, 0.25_m, 0.1_m));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(28.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_TRUE(result.HasTargets());
|
||||
|
||||
robotPose =
|
||||
frc::Pose2d(frc::Translation2d(0.0_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
result = sysUnderTest.cam.GetLatestResult();
|
||||
EXPECT_FALSE(result.HasTargets());
|
||||
}
|
||||
|
||||
class SimVisionSystemTestYawParam : public testing::TestWithParam<double> {};
|
||||
INSTANTIATE_TEST_SUITE_P(SimVisionSystemTestYawParamInst,
|
||||
SimVisionSystemTestYawParam,
|
||||
testing::Values(-10, -5, -0, -1, -2, 5, 7, 10.23));
|
||||
TEST_P(SimVisionSystemTestYawParam, testYawAngles) {
|
||||
double testYaw = GetParam(); // Nope, Chuck testYaw
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d(45_deg));
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
640, 480, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 0.0_m, 0.5_m, 0.5_m));
|
||||
|
||||
auto robotPose = frc::Pose2d(frc::Translation2d(32_m, 0.0_m),
|
||||
frc::Rotation2d(units::degree_t(testYaw)));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
auto tgt = result.GetBestTarget();
|
||||
EXPECT_DOUBLE_EQ(tgt.GetYaw(), testYaw);
|
||||
}
|
||||
|
||||
class SimVisionSystemTestCameraPitchParam
|
||||
: public testing::TestWithParam<double> {};
|
||||
INSTANTIATE_TEST_SUITE_P(SimVisionSystemTestCameraPitchParamInst,
|
||||
SimVisionSystemTestCameraPitchParam,
|
||||
testing::Values(-10, -5, -0, -1, -2, 5, 7, 10.23,
|
||||
20.21, -19.999));
|
||||
TEST_P(SimVisionSystemTestCameraPitchParam, testCameraPitch) {
|
||||
double testPitch = GetParam();
|
||||
auto targetPose =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d(45_deg));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(30_m, 0.0_m), frc::Rotation2d(0.0_deg));
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("Test", 80.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 1.0_m, 99999.0_m,
|
||||
640, 480, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPose, 0.0_m, 0.5_m, 0.5_m));
|
||||
|
||||
sysUnderTest.MoveCamera(
|
||||
frc::Transform2d(frc::Translation2d(), frc::Rotation2d()), 0.0_m,
|
||||
units::degree_t(testPitch));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
auto tgt = result.GetBestTarget();
|
||||
// If the camera is pitched down by 10 degrees, the target should appear
|
||||
// in the upper part of the image (ie, pitch positive). Therefor,
|
||||
// pass/fail involves -1.0.
|
||||
EXPECT_DOUBLE_EQ(tgt.GetPitch(), -1.0 * testPitch);
|
||||
}
|
||||
|
||||
class SimVisionSystemTestDistCalcParam
|
||||
: public testing::TestWithParam<std::tuple<double, double, double>> {};
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
SimVisionSystemTestDistCalcParamInst, SimVisionSystemTestDistCalcParam,
|
||||
testing::Values(std::tuple<double, double, double>(5, 35, 0),
|
||||
std::tuple<double, double, double>(6, 35, 1),
|
||||
std::tuple<double, double, double>(10, 35, 0),
|
||||
std::tuple<double, double, double>(15, 35, 2),
|
||||
std::tuple<double, double, double>(19.95, 35, 0),
|
||||
std::tuple<double, double, double>(20, 35, 0),
|
||||
std::tuple<double, double, double>(5, 42, 1),
|
||||
std::tuple<double, double, double>(6, 42, 0),
|
||||
std::tuple<double, double, double>(10, 42, 2),
|
||||
std::tuple<double, double, double>(15, 42, 0.5),
|
||||
std::tuple<double, double, double>(19.42, 35, 0),
|
||||
std::tuple<double, double, double>(20, 42, 0),
|
||||
std::tuple<double, double, double>(5, 55, 2),
|
||||
std::tuple<double, double, double>(6, 55, 0),
|
||||
std::tuple<double, double, double>(10, 54, 2.2),
|
||||
std::tuple<double, double, double>(15, 53, 0),
|
||||
std::tuple<double, double, double>(19.52, 35, 1.1),
|
||||
std::tuple<double, double, double>(20, 51, 2.87),
|
||||
std::tuple<double, double, double>(20, 55, 3)));
|
||||
TEST_P(SimVisionSystemTestDistCalcParam, testDistanceCalc) {
|
||||
std::tuple<double, double, double> testArgs = GetParam();
|
||||
double testDist = std::get<0>(testArgs);
|
||||
double testPitch = std::get<1>(testArgs);
|
||||
double testHeight = std::get<2>(testArgs);
|
||||
|
||||
auto targetPose = frc::Pose2d(frc::Translation2d(35_m, 0_m),
|
||||
frc::Rotation2d(units::radian_t(3.14159 / 42)));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(units::meter_t(35 - testDist), 0.0_m),
|
||||
frc::Rotation2d(0.0_deg));
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest(
|
||||
"absurdlylongnamewhichshouldneveractuallyhappenbuteehwelltestitanywaysoho"
|
||||
"wsyourdaygoingihopegoodhaveagreatrestofyourlife",
|
||||
160.0_deg, units::degree_t(testPitch), frc::Transform2d(),
|
||||
units::meter_t(testHeight), 99999.0_m, 640, 480, 0.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(photonlib::SimVisionTarget(
|
||||
targetPose, units::meter_t(testDist), 0.5_m, 0.5_m));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
auto tgt = result.GetBestTarget();
|
||||
EXPECT_DOUBLE_EQ(tgt.GetYaw(), 0.0);
|
||||
units::meter_t distMeas = photonlib::PhotonUtils::CalculateDistanceToTarget(
|
||||
units::meter_t(testHeight), units::meter_t(testDist),
|
||||
units::degree_t(testPitch), units::degree_t(tgt.GetPitch()));
|
||||
EXPECT_DOUBLE_EQ(distMeas.to<double>(), testDist);
|
||||
}
|
||||
|
||||
TEST(SimVisionSystemTest, testMultipleTargets) {
|
||||
auto targetPoseL =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 2_m), frc::Rotation2d());
|
||||
auto targetPoseC =
|
||||
frc::Pose2d(frc::Translation2d(35_m, 0_m), frc::Rotation2d());
|
||||
auto targetPoseR =
|
||||
frc::Pose2d(frc::Translation2d(35_m, -2_m), frc::Rotation2d());
|
||||
|
||||
photonlib::SimVisionSystem sysUnderTest("test", 160.0_deg, 0.0_deg,
|
||||
frc::Transform2d(), 5.0_m, 99999.0_m,
|
||||
640, 480, 20.0);
|
||||
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseL, 0.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseC, 1.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseR, 2.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseL, 3.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseC, 4.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseR, 5.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseL, 6.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseC, 7.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseL, 8.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseR, 9.0_m, 0.25_m, 0.1_m));
|
||||
sysUnderTest.AddSimVisionTarget(
|
||||
photonlib::SimVisionTarget(targetPoseL, 10.0_m, 0.25_m, 0.1_m));
|
||||
|
||||
auto robotPose =
|
||||
frc::Pose2d(frc::Translation2d(30_m, 0.0_m), frc::Rotation2d(5.0_deg));
|
||||
|
||||
sysUnderTest.ProcessFrame(robotPose);
|
||||
auto result = sysUnderTest.cam.GetLatestResult();
|
||||
ASSERT_TRUE(result.HasTargets());
|
||||
|
||||
auto tgtList = result.GetTargets();
|
||||
EXPECT_EQ(11ul, tgtList.size());
|
||||
}
|
||||
24
photon-lib/src/test/native/cpp/main.cpp
Normal file
24
photon-lib/src/test/native/cpp/main.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user