From dc106be35f689e2d130a9575a29a65f8b86a5a1f Mon Sep 17 00:00:00 2001 From: samfreund Date: Wed, 5 Aug 2026 13:49:51 -0700 Subject: [PATCH] did stuff Signed-off-by: samfreund --- build.gradle | 2 +- photon-lib/build.gradle | 2 +- .../src/test/native/cpp/PhotonCameraTest.cpp | 46 ++-- .../native/cpp/PhotonPoseEstimatorTest.cpp | 232 ++++++++++------- .../src/test/native/cpp/PhotonUtilsTest.cpp | 4 +- .../src/test/native/cpp/VersionTest.cpp | 4 +- .../test/native/cpp/VisionSystemSimTest.cpp | 241 +++++++++--------- photon-lib/src/test/native/cpp/main.cpp | 30 ++- photon-serde-tests/build.gradle | 5 +- photon-serde/templates/ThingTests.cpp.jinja | 11 +- photon-targeting/build.gradle | 2 +- .../src/test/native/cpp/CasadiWrapperTest.cpp | 6 +- .../src/test/native/cpp/PacketTest.cpp | 12 +- photon-targeting/src/test/native/cpp/main.cpp | 30 ++- .../src/test/native/cpp/net/TimeSyncTest.cpp | 44 ++-- shared/config.gradle | 1 + 16 files changed, 378 insertions(+), 294 deletions(-) diff --git a/build.gradle b/build.gradle index 4c5a30115a..0d2a1d4131 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id "cpp" id "com.diffplug.spotless" version "8.1.0" id "org.wpilib.WPILibRepositoriesPlugin" version "2027.0.0" - id 'org.wpilib.NativeUtils' version '2027.7.1' apply false + id 'org.wpilib.NativeUtils' version '2027.69.0' apply false id 'org.wpilib.DeployUtils' version '2027.1.0' apply false id 'org.photonvision.tools.WpilibTools' version 'v5.0.1' id 'com.google.protobuf' version '0.9.5' apply false diff --git a/photon-lib/build.gradle b/photon-lib/build.gradle index 2e4a4e93e4..c670259581 100644 --- a/photon-lib/build.gradle +++ b/photon-lib/build.gradle @@ -92,7 +92,7 @@ model { nativeUtils.useRequiredLibrary(it, "cscore_shared") nativeUtils.useRequiredLibrary(it, "cameraserver_shared") nativeUtils.useRequiredLibrary(it, "wpilib_shared") - nativeUtils.useRequiredLibrary(it, "googletest_static") + nativeUtils.useRequiredLibrary(it, "catch2_static") nativeUtils.useRequiredLibrary(it, "apriltag_shared") nativeUtils.useRequiredLibrary(it, "opencv_shared") } diff --git a/photon-lib/src/test/native/cpp/PhotonCameraTest.cpp b/photon-lib/src/test/native/cpp/PhotonCameraTest.cpp index b704a3abc4..af5843bbb9 100644 --- a/photon-lib/src/test/native/cpp/PhotonCameraTest.cpp +++ b/photon-lib/src/test/native/cpp/PhotonCameraTest.cpp @@ -25,8 +25,8 @@ #include #include +#include #include -#include #include #include #include @@ -36,7 +36,7 @@ #include #include -TEST(TimeSyncProtocolTest, Smoketest) { +TEST_CASE("TimeSyncProtocolTest Smoketest", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -52,15 +52,15 @@ TEST(TimeSyncProtocolTest, Smoketest) { // give us time to warm up if (i > 5) { - EXPECT_TRUE(m.rtt2 > 0); - EXPECT_TRUE(m.pongsReceived > 0); + CHECK(m.rtt2 > 0); + CHECK(m.pongsReceived > 0); } } client.Stop(); } -TEST(PhotonCameraTest, Alerts) { +TEST_CASE("PhotonCameraTest Alerts", "[photonlib]") { // GIVEN a local-only NT instance auto inst = wpi::nt::NetworkTableInstance::GetDefault(); inst.StopClient(); @@ -73,7 +73,7 @@ TEST(PhotonCameraTest, Alerts) { // AND a PhotonCamera that is disconnected photon::PhotonCamera camera(inst, cameraName); - EXPECT_FALSE(camera.IsConnected()); + CHECK_FALSE(camera.IsConnected()); std::string disconnectedCameraString = "PhotonCamera '" + cameraName + "' is disconnected."; @@ -95,11 +95,11 @@ TEST(PhotonCameraTest, Alerts) { // The alert state will be set (hard-coded here) auto alerts = getActiveAlerts(); - EXPECT_TRUE(std::any_of(alerts.begin(), alerts.end(), - [&disconnectedCameraString]( - const wpi::sim::AlertSim::AlertInfo& alert) { - return alert.text == disconnectedCameraString; - })); + CHECK(std::any_of(alerts.begin(), alerts.end(), + [&disconnectedCameraString]( + const wpi::sim::AlertSim::AlertInfo& alert) { + return alert.text == disconnectedCameraString; + })); std::this_thread::sleep_for(std::chrono::milliseconds(20)); } @@ -120,20 +120,20 @@ TEST(PhotonCameraTest, Alerts) { // THEN the camera isn't disconnected auto alerts = getActiveAlerts(); - EXPECT_TRUE(std::none_of(alerts.begin(), alerts.end(), - [&disconnectedCameraString]( - const wpi::sim::AlertSim::AlertInfo& alert) { - return alert.text == disconnectedCameraString; - })); + CHECK(std::none_of(alerts.begin(), alerts.end(), + [&disconnectedCameraString]( + const wpi::sim::AlertSim::AlertInfo& alert) { + return alert.text == disconnectedCameraString; + })); // AND the alert string looks like a timesync warning - EXPECT_EQ(1, std::count_if( - alerts.begin(), alerts.end(), - [](const wpi::sim::AlertSim::AlertInfo& alert) { - return alert.text.find( - "is not connected to the TimeSyncServer") != - std::string::npos; - })); + CHECK(1 == std::count_if( + alerts.begin(), alerts.end(), + [](const wpi::sim::AlertSim::AlertInfo& alert) { + return alert.text.find( + "is not connected to the TimeSyncServer") != + std::string::npos; + })); std::this_thread::sleep_for(std::chrono::milliseconds(20)); } diff --git a/photon-lib/src/test/native/cpp/PhotonPoseEstimatorTest.cpp b/photon-lib/src/test/native/cpp/PhotonPoseEstimatorTest.cpp index 1cf1ae714a..f4dff3eb9b 100644 --- a/photon-lib/src/test/native/cpp/PhotonPoseEstimatorTest.cpp +++ b/photon-lib/src/test/native/cpp/PhotonPoseEstimatorTest.cpp @@ -27,7 +27,8 @@ #include #include -#include +#include +#include #include #include #include @@ -61,7 +62,7 @@ static std::vector detectedCorners{ photon::TargetCorner{1., 2.}, photon::TargetCorner{3., 4.}, photon::TargetCorner{5., 6.}, photon::TargetCorner{7., 8.}}; -TEST(PhotonPoseEstimatorTest, LowestAmbiguityStrategy) { +TEST_CASE("PhotonPoseEstimatorTest LowestAmbiguityStrategy", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{ @@ -98,20 +99,25 @@ TEST(PhotonPoseEstimatorTest, LowestAmbiguityStrategy) { for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateLowestAmbiguityPose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR( - 11, wpi::units::unit_cast(estimatedPose.value().timestamp), .02); - EXPECT_NEAR(1, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(3, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(2, wpi::units::unit_cast(pose.Z()), .01); + CHECK(11 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.02)); + CHECK(1 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(3 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(2 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // Only the chosen (lowest-ambiguity) target should be reported as used. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); - EXPECT_EQ(1, estimatedPose.value().targetsUsed[0].GetFiducialId()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); + CHECK(1 == estimatedPose.value().targetsUsed[0].GetFiducialId()); } -TEST(PhotonPoseEstimatorTest, LowestAmbiguityIgnoresNonFiducialTargets) { +TEST_CASE("PhotonPoseEstimatorTest LowestAmbiguityIgnoresNonFiducialTargets", + "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); // A non-fiducial target reports poseAmbiguity = -1. Without the guard the @@ -141,16 +147,20 @@ TEST(PhotonPoseEstimatorTest, LowestAmbiguityIgnoresNonFiducialTargets) { for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateLowestAmbiguityPose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); // Tag 1 is at (5,5,5), bestCameraToTarget = (4,2,3), so the estimated // robot pose lands at (1,3,2) in the field frame. wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(1, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(3, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(2, wpi::units::unit_cast(pose.Z()), .01); + CHECK(1 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(3 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(2 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); } -TEST(PhotonPoseEstimatorTest, ClosestToCameraHeightStrategy) { +TEST_CASE("PhotonPoseEstimatorTest ClosestToCameraHeightStrategy", + "[poseest]") { std::vector tags = { {0, wpi::math::Pose3d(wpi::units::meter_t(3), wpi::units::meter_t(3), wpi::units::meter_t(3), wpi::math::Rotation3d())}, @@ -200,21 +210,26 @@ TEST(PhotonPoseEstimatorTest, ClosestToCameraHeightStrategy) { for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateClosestToCameraHeightPose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR( - 17, wpi::units::unit_cast(estimatedPose.value().timestamp), .02); - EXPECT_NEAR(4, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(4, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(0, wpi::units::unit_cast(pose.Z()), .01); + CHECK(17 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.02)); + CHECK(4 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(4 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(0 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // Only the chosen target should be reported as used. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); - EXPECT_EQ(1, estimatedPose.value().targetsUsed[0].GetFiducialId()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); + CHECK(1 == estimatedPose.value().targetsUsed[0].GetFiducialId()); } -TEST(PhotonPoseEstimatorTest, ClosestToReferencePoseStrategy) { +TEST_CASE("PhotonPoseEstimatorTest ClosestToReferencePoseStrategy", + "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{ @@ -254,20 +269,24 @@ TEST(PhotonPoseEstimatorTest, ClosestToReferencePoseStrategy) { wpi::math::Rotation3d(0_rad, 0_rad, 0_rad))); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR( - 17, wpi::units::unit_cast(estimatedPose.value().timestamp), .01); - EXPECT_NEAR(1, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(1.1, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(.9, wpi::units::unit_cast(pose.Z()), .01); + CHECK(17 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.01)); + CHECK(1 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(1.1 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(.9 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // Only the chosen target should be reported as used. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); - EXPECT_EQ(0, estimatedPose.value().targetsUsed[0].GetFiducialId()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); + CHECK(0 == estimatedPose.value().targetsUsed[0].GetFiducialId()); } -TEST(PhotonPoseEstimatorTest, ClosestToLastPose) { +TEST_CASE("PhotonPoseEstimatorTest ClosestToLastPose", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{ @@ -307,7 +326,7 @@ TEST(PhotonPoseEstimatorTest, ClosestToLastPose) { wpi::math::Rotation3d(0_rad, 0_rad, 0_rad))); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; std::vector targetsThree{ @@ -342,21 +361,24 @@ TEST(PhotonPoseEstimatorTest, ClosestToLastPose) { estimatedPose = estimator.EstimateClosestToReferencePose(result, pose); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(21.0, - wpi::units::unit_cast(estimatedPose.value().timestamp), - .01); - EXPECT_NEAR(.9, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(1.1, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(1, wpi::units::unit_cast(pose.Z()), .01); + CHECK(21.0 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.01)); + CHECK(.9 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(1.1 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(1 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // Only the chosen target should be reported as used. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); - EXPECT_EQ(0, estimatedPose.value().targetsUsed[0].GetFiducialId()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); + CHECK(0 == estimatedPose.value().targetsUsed[0].GetFiducialId()); } -TEST(PhotonPoseEstimatorTest, PnpDistanceTrigSolve) { +TEST_CASE("PhotonPoseEstimatorTest PnpDistanceTrigSolve", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); cameraOne.test = true; @@ -392,17 +414,17 @@ TEST(PhotonPoseEstimatorTest, PnpDistanceTrigSolve) { estimatedPose = estimator.EstimatePnpDistanceTrigSolvePose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(wpi::units::unit_cast(realPose.X()), - wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(wpi::units::unit_cast(realPose.Y()), - wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(wpi::units::unit_cast(realPose.Z()), - wpi::units::unit_cast(pose.Z()), .01); + CHECK(wpi::units::unit_cast(realPose.X()) == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(wpi::units::unit_cast(realPose.Y()) == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(wpi::units::unit_cast(realPose.Z()) == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // PNP_DISTANCE_TRIG_SOLVE uses only the best target. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); /* Straight on */ wpi::math::Transform3d straightOnTestTransform = wpi::math::Transform3d( @@ -424,20 +446,20 @@ TEST(PhotonPoseEstimatorTest, PnpDistanceTrigSolve) { estimatedPose = estimator.EstimatePnpDistanceTrigSolvePose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(wpi::units::unit_cast(realPose.X()), - wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(wpi::units::unit_cast(realPose.Y()), - wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(wpi::units::unit_cast(realPose.Z()), - wpi::units::unit_cast(pose.Z()), .01); + CHECK(wpi::units::unit_cast(realPose.X()) == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(wpi::units::unit_cast(realPose.Y()) == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(wpi::units::unit_cast(realPose.Z()) == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // PNP_DISTANCE_TRIG_SOLVE uses only the best target. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); } -TEST(PhotonPoseEstimatorTest, AverageBestPoses) { +TEST_CASE("PhotonPoseEstimatorTest AverageBestPoses", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{ @@ -481,25 +503,30 @@ TEST(PhotonPoseEstimatorTest, AverageBestPoses) { estimatedPose = estimator.EstimateAverageBestTargetsPose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(15.0, - wpi::units::unit_cast(estimatedPose.value().timestamp), - .01); - EXPECT_NEAR(2.15, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(2.15, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(2.15, wpi::units::unit_cast(pose.Z()), .01); + CHECK(15.0 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.01)); + CHECK(2.15 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(2.15 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(2.15 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // Only the three fiducial targets contributed; the non-fiducial fourth target // is excluded. - EXPECT_EQ(static_cast(3), estimatedPose.value().targetsUsed.size()); + CHECK(static_cast(3) == estimatedPose.value().targetsUsed.size()); for (const auto& t : estimatedPose.value().targetsUsed) { - EXPECT_NE(-1, t.GetFiducialId()); + CHECK(-1 != t.GetFiducialId()); } } -TEST(PhotonPoseEstimatorTest, - ClosestToCameraHeightReturnsEmptyForNoFiducialTargets) { +TEST_CASE( + "PhotonPoseEstimatorTest " + "ClosestToCameraHeightReturnsEmptyForNoFiducialTargets", + "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); // A single non-fiducial target (fid = -1) should yield no estimate. @@ -518,11 +545,13 @@ TEST(PhotonPoseEstimatorTest, for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateClosestToCameraHeightPose(result); } - EXPECT_FALSE(estimatedPose); + CHECK_FALSE(estimatedPose); } -TEST(PhotonPoseEstimatorTest, - ClosestToReferencePoseReturnsEmptyForNoFiducialTargets) { +TEST_CASE( + "PhotonPoseEstimatorTest " + "ClosestToReferencePoseReturnsEmptyForNoFiducialTargets", + "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{photon::PhotonTrackedTarget{ @@ -541,10 +570,10 @@ TEST(PhotonPoseEstimatorTest, estimatedPose = estimator.EstimateClosestToReferencePose( result, wpi::math::Pose3d(1_m, 1_m, 1_m, wpi::math::Rotation3d())); } - EXPECT_FALSE(estimatedPose); + CHECK_FALSE(estimatedPose); } -TEST(PhotonPoseEstimatorTest, MultiTagOnCoprocFallback) { +TEST_CASE("PhotonPoseEstimatorTest MultiTagOnCoprocFallback", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); std::vector targets{ @@ -574,25 +603,29 @@ TEST(PhotonPoseEstimatorTest, MultiTagOnCoprocFallback) { for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateCoprocMultiTagPose(result); } - ASSERT_FALSE(estimatedPose); + REQUIRE_FALSE(estimatedPose); for (const auto& result : cameraOne.GetAllUnreadResults()) { estimatedPose = estimator.EstimateLowestAmbiguityPose(result); } - ASSERT_TRUE(estimatedPose); + REQUIRE(estimatedPose); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; // Make sure values match what we'd expect for the LOWEST_AMBIGUITY strategy - EXPECT_NEAR( - 11, wpi::units::unit_cast(estimatedPose.value().timestamp), .02); - EXPECT_NEAR(1, wpi::units::unit_cast(pose.X()), .01); - EXPECT_NEAR(3, wpi::units::unit_cast(pose.Y()), .01); - EXPECT_NEAR(2, wpi::units::unit_cast(pose.Z()), .01); + CHECK(11 == Catch::Approx(wpi::units::unit_cast( + estimatedPose.value().timestamp)) + .margin(.02)); + CHECK(1 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(.01)); + CHECK(3 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(.01)); + CHECK(2 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(.01)); // LOWEST_AMBIGUITY fallback should report only the single chosen target. - EXPECT_EQ(static_cast(1), estimatedPose.value().targetsUsed.size()); - EXPECT_EQ(1, estimatedPose.value().targetsUsed[0].GetFiducialId()); + CHECK(static_cast(1) == estimatedPose.value().targetsUsed.size()); + CHECK(1 == estimatedPose.value().targetsUsed[0].GetFiducialId()); } -TEST(PhotonPoseEstimatorTest, CopyResult) { +TEST_CASE("PhotonPoseEstimatorTest CopyResult", "[poseest]") { std::vector targets{}; auto testResult = photon::PhotonPipelineResult{ @@ -601,11 +634,11 @@ TEST(PhotonPoseEstimatorTest, CopyResult) { auto test2 = testResult; - EXPECT_NEAR(testResult.GetTimestamp().to(), - test2.GetTimestamp().to(), 0.001); + CHECK(testResult.GetTimestamp().to() == + Catch::Approx(test2.GetTimestamp().to()).margin(0.001)); } -TEST(PhotonPoseEstimatorTest, ConstrainedPnpEmptyCase) { +TEST_CASE("PhotonPoseEstimatorTest ConstrainedPnpEmptyCase", "[poseest]") { photon::PhotonPoseEstimator estimator( wpi::apriltag::AprilTagFieldLayout::LoadField( wpi::apriltag::AprilTagField::k2024Crescendo), @@ -618,10 +651,10 @@ TEST(PhotonPoseEstimatorTest, ConstrainedPnpEmptyCase) { {0, 0, 1}}; auto estimate = estimator.EstimateConstrainedSolvepnpPose( result, cameraMat, distortion, wpi::math::Pose3d(), true, 0.0); - EXPECT_FALSE(estimate.has_value()); + CHECK_FALSE(estimate.has_value()); } -TEST(PhotonPoseEstimatorTest, ConstrainedPnpOneTag) { +TEST_CASE("PhotonPoseEstimatorTest ConstrainedPnpOneTag", "[poseest]") { photon::PhotonCamera cameraOne = photon::PhotonCamera("test"); auto distortion = Eigen::VectorXd::Zero(8); auto cameraMat = Eigen::Matrix3d{{399.37500000000006, 0, 319.5}, @@ -678,13 +711,16 @@ TEST(PhotonPoseEstimatorTest, ConstrainedPnpOneTag) { cameraOne.testResult[0], cameraMat, distortion, estimatedMultiTagPose->estimatedPose, true, 0); - ASSERT_TRUE(estimatedPose.has_value()); + REQUIRE(estimatedPose.has_value()); wpi::math::Pose3d pose = estimatedPose.value().estimatedPose; - EXPECT_NEAR(3.58, wpi::units::unit_cast(pose.X()), 0.01); - EXPECT_NEAR(4.13, wpi::units::unit_cast(pose.Y()), 0.01); - EXPECT_NEAR(0.0, wpi::units::unit_cast(pose.Z()), 0.01); + CHECK(3.58 == + Catch::Approx(wpi::units::unit_cast(pose.X())).margin(0.01)); + CHECK(4.13 == + Catch::Approx(wpi::units::unit_cast(pose.Y())).margin(0.01)); + CHECK(0.0 == + Catch::Approx(wpi::units::unit_cast(pose.Z())).margin(0.01)); - EXPECT_EQ(photon::CONSTRAINED_SOLVEPNP, estimatedPose.value().strategy); + CHECK(photon::CONSTRAINED_SOLVEPNP == estimatedPose.value().strategy); } diff --git a/photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp b/photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp index f9a493cba5..1cad0a490f 100644 --- a/photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp +++ b/photon-lib/src/test/native/cpp/PhotonUtilsTest.cpp @@ -24,6 +24,6 @@ #include "photon/PhotonUtils.h" -#include +#include -TEST(PhotonUtilsTest, Include) {} +TEST_CASE("PhotonUtilsTest Include", "[photonlib]") {} diff --git a/photon-lib/src/test/native/cpp/VersionTest.cpp b/photon-lib/src/test/native/cpp/VersionTest.cpp index 442f14adb2..183e553a99 100644 --- a/photon-lib/src/test/native/cpp/VersionTest.cpp +++ b/photon-lib/src/test/native/cpp/VersionTest.cpp @@ -22,11 +22,11 @@ * SOFTWARE. */ -#include +#include #include #include "PhotonVersion.h" -TEST(VersionTest, PrintVersion) { +TEST_CASE("VersionTest PrintVersion", "[photonlib]") { wpi::util::println("{}", photon::PhotonVersion::versionString); } diff --git a/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp b/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp index 651e6f1d8b..da409956e6 100644 --- a/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp +++ b/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp @@ -27,7 +27,9 @@ #include #include -#include +#include +#include +#include #include #include "photon/PhotonUtils.h" @@ -36,24 +38,19 @@ // Ignore GetLatestResult warnings WPI_IGNORE_DEPRECATED -class VisionSystemSimTest : public ::testing::Test { - void SetUp() override { +class VisionSystemSimTest { + public: + VisionSystemSimTest() { wpi::nt::NetworkTableInstance::GetDefault().StartServer(); photon::PhotonCamera::SetVersionCheckEnabled(false); } - - void TearDown() override {} }; -class VisionSystemSimTestWithParamsTest - : public VisionSystemSimTest, - public testing::WithParamInterface {}; -class VisionSystemSimTestDistanceParamsTest - : public VisionSystemSimTest, - public testing::WithParamInterface> {}; +class VisionSystemSimTestWithParamsTest : public VisionSystemSimTest {}; +class VisionSystemSimTestDistanceParamsTest : public VisionSystemSimTest {}; -TEST_F(VisionSystemSimTest, TestVisibilityCupidShuffle) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestVisibilityCupidShuffle", + "[photonlib]") { wpi::math::Pose3d targetPose{ wpi::math::Translation3d{15.98_m, 0_m, 2_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -71,43 +68,43 @@ TEST_F(VisionSystemSimTest, TestVisibilityCupidShuffle) { wpi::math::Pose2d robotPose{wpi::math::Translation2d{5_m, 0_m}, wpi::math::Rotation2d{-70_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); // To the right, to the right robotPose = wpi::math::Pose2d{wpi::math::Translation2d{5_m, 0_m}, wpi::math::Rotation2d{-95_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); // To the left, to the left robotPose = wpi::math::Pose2d{wpi::math::Translation2d{5_m, 0_m}, wpi::math::Rotation2d{90_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); // To the left, to the left robotPose = wpi::math::Pose2d{wpi::math::Translation2d{5_m, 0_m}, wpi::math::Rotation2d{65_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); // Now kick, now kick robotPose = wpi::math::Pose2d{wpi::math::Translation2d{2_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); // Now kick, now kick robotPose = wpi::math::Pose2d{wpi::math::Translation2d{2_m, 0_m}, wpi::math::Rotation2d{-5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); // Now walk it by yourself robotPose = wpi::math::Pose2d{wpi::math::Translation2d{2_m, 0_m}, wpi::math::Rotation2d{-179_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); // Now walk it by yourself visionSysSim.AdjustCamera( @@ -117,10 +114,10 @@ TEST_F(VisionSystemSimTest, TestVisibilityCupidShuffle) { wpi::math::Rotation3d{0_deg, 0_deg, wpi::units::radian_t{std::numbers::pi}}}); visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); } -TEST_F(VisionSystemSimTest, TestBunchaTargets) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestBunchaTargets", "[photonlib]") { photon::VisionSystemSim visionSysSim{"Test"}; photon::PhotonCamera camera{"camera"}; photon::PhotonCameraSim cameraSim{&camera}; @@ -142,10 +139,10 @@ TEST_F(VisionSystemSimTest, TestBunchaTargets) { wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_EQ(camera.GetLatestResult().targets.size(), 50u); + REQUIRE(camera.GetLatestResult().targets.size() == 50u); } -TEST_F(VisionSystemSimTest, TestNotVisibleVert1) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestNotVisibleVert1", "[photonlib]") { wpi::math::Pose3d targetPose{ wpi::math::Translation3d{15.98_m, 0_m, 1_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -162,7 +159,7 @@ TEST_F(VisionSystemSimTest, TestNotVisibleVert1) { wpi::math::Pose2d robotPose{wpi::math::Translation2d{5_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); visionSysSim.AdjustCamera( &cameraSim, @@ -171,10 +168,10 @@ TEST_F(VisionSystemSimTest, TestNotVisibleVert1) { wpi::math::Rotation3d{0_deg, 0_deg, wpi::units::radian_t{std::numbers::pi}}}); visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); } -TEST_F(VisionSystemSimTest, TestNotVisibleVert2) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestNotVisibleVert2", "[photonlib]") { wpi::math::Pose3d targetPose{ wpi::math::Translation3d{15.98_m, 0_m, 2_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -196,15 +193,16 @@ TEST_F(VisionSystemSimTest, TestNotVisibleVert2) { wpi::math::Pose2d robotPose{wpi::math::Translation2d{13.98_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); robotPose = wpi::math::Pose2d{wpi::math::Translation2d{0_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); } -TEST_F(VisionSystemSimTest, TestNotVisibleTargetSize) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestNotVisibleTargetSize", + "[photonlib]") { wpi::math::Pose3d targetPose{ wpi::math::Translation3d{15.98_m, 0_m, 1_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -222,15 +220,16 @@ TEST_F(VisionSystemSimTest, TestNotVisibleTargetSize) { wpi::math::Pose2d robotPose{wpi::math::Translation2d{12_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); robotPose = wpi::math::Pose2d{wpi::math::Translation2d{0_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); } -TEST_F(VisionSystemSimTest, TestNotVisibleTooFarLeds) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestNotVisibleTooFarLeds", + "[photonlib]") { wpi::math::Pose3d targetPose{ wpi::math::Translation3d{15.98_m, 0_m, 1_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -249,19 +248,23 @@ TEST_F(VisionSystemSimTest, TestNotVisibleTooFarLeds) { wpi::math::Pose2d robotPose{wpi::math::Translation2d{10_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_TRUE(camera.GetLatestResult().HasTargets()); + REQUIRE(camera.GetLatestResult().HasTargets()); robotPose = wpi::math::Pose2d{wpi::math::Translation2d{0_m, 0_m}, wpi::math::Rotation2d{5_deg}}; visionSysSim.Update(robotPose); - ASSERT_FALSE(camera.GetLatestResult().HasTargets()); + REQUIRE_FALSE(camera.GetLatestResult().HasTargets()); } -TEST_P(VisionSystemSimTestWithParamsTest, YawAngles) { +TEST_CASE_METHOD(VisionSystemSimTestWithParamsTest, "YawAngles", + "[photonlib]") { const wpi::math::Pose3d targetPose{ {15.98_m, 0_m, 0_m}, wpi::math::Rotation3d{0_deg, 0_deg, wpi::units::radian_t{3 * std::numbers::pi / 4}}}; + auto param = GENERATE(-10_deg, -5_deg, -0_deg, -1_deg, -2_deg, 5_deg, 7_deg, + 10.23_deg); + photon::VisionSystemSim visionSysSim{"Test"}; photon::PhotonCamera camera{"camera"}; photon::PhotonCameraSim cameraSim{&camera}; @@ -273,21 +276,25 @@ TEST_P(VisionSystemSimTestWithParamsTest, YawAngles) { // If the robot is rotated x deg (CCW+), the target yaw should be x deg (CW+) wpi::math::Pose2d robotPose{wpi::math::Translation2d{10_m, 0_m}, - wpi::math::Rotation2d{GetParam()}}; + wpi::math::Rotation2d{param}}; visionSysSim.Update(robotPose); const auto result = camera.GetLatestResult(); - ASSERT_TRUE(result.HasTargets()); - ASSERT_NEAR(GetParam().to(), result.GetBestTarget().GetYaw(), 0.25); + REQUIRE(result.HasTargets()); + REQUIRE(param.to() == + Catch::Approx(result.GetBestTarget().GetYaw()).margin(0.25)); } -TEST_P(VisionSystemSimTestWithParamsTest, PitchAngles) { +TEST_CASE_METHOD(VisionSystemSimTestWithParamsTest, "PitchAngles", + "[photonlib]") { const wpi::math::Pose3d targetPose{ {15.98_m, 0_m, 0_m}, wpi::math::Rotation3d{0_deg, 0_deg, wpi::units::radian_t{3 * std::numbers::pi / 4}}}; - wpi::math::Pose2d robotPose{{10_m, 0_m}, - wpi::math::Rotation2d{GetParam() * -1.0}}; + auto param = GENERATE(-10_deg, -5_deg, -0_deg, -1_deg, -2_deg, 5_deg, 7_deg, + 10.23_deg); + + wpi::math::Pose2d robotPose{{10_m, 0_m}, wpi::math::Rotation2d{param * -1.0}}; photon::VisionSystemSim visionSysSim{"Test"}; photon::PhotonCamera camera{"camera"}; photon::PhotonCameraSim cameraSim{&camera}; @@ -298,28 +305,40 @@ TEST_P(VisionSystemSimTestWithParamsTest, PitchAngles) { targetPose, photon::TargetModel{0.5_m, 0.5_m}, 3}}); robotPose = wpi::math::Pose2d{wpi::math::Translation2d{10_m, 0_m}, - wpi::math::Rotation2d{-1 * GetParam()}}; + wpi::math::Rotation2d{-1 * param}}; visionSysSim.AdjustCamera( - &cameraSim, wpi::math::Transform3d{ - wpi::math::Translation3d{}, - wpi::math::Rotation3d{ - 0_rad, wpi::units::degree_t{GetParam()}, 0_rad}}); + &cameraSim, + wpi::math::Transform3d{ + wpi::math::Translation3d{}, + wpi::math::Rotation3d{0_rad, wpi::units::degree_t{param}, 0_rad}}); visionSysSim.Update(robotPose); const auto result = camera.GetLatestResult(); - ASSERT_TRUE(result.HasTargets()); - ASSERT_NEAR(GetParam().to(), result.GetBestTarget().GetPitch(), 0.25); + REQUIRE(result.HasTargets()); + REQUIRE(param.to() == + Catch::Approx(result.GetBestTarget().GetPitch()).margin(0.25)); } -INSTANTIATE_TEST_SUITE_P(AnglesTests, VisionSystemSimTestWithParamsTest, - testing::Values(-10_deg, -5_deg, -0_deg, -1_deg, - -2_deg, 5_deg, 7_deg, 10.23_deg)); - -TEST_P(VisionSystemSimTestDistanceParamsTest, DistanceCalc) { - wpi::units::foot_t distParam; - wpi::units::degree_t pitchParam; - wpi::units::foot_t heightParam; - std::tie(distParam, pitchParam, heightParam) = GetParam(); +TEST_CASE_METHOD(VisionSystemSimTestDistanceParamsTest, "DistanceCalc", + "[photonlib]") { + auto [distParam, pitchParam, heightParam] = + GENERATE(std::make_tuple(5_ft, -15.98_deg, 0_ft), + std::make_tuple(6_ft, -15.98_deg, 1_ft), + std::make_tuple(10_ft, -15.98_deg, 0_ft), + std::make_tuple(15_ft, -15.98_deg, 2_ft), + std::make_tuple(19.95_ft, -15.98_deg, 0_ft), + std::make_tuple(20_ft, -15.98_deg, 0_ft), + std::make_tuple(5_ft, -42_deg, 1_ft), + std::make_tuple(6_ft, -42_deg, 0_ft), + std::make_tuple(10_ft, -42_deg, 2_ft), + std::make_tuple(15_ft, -42_deg, 0.5_ft), + std::make_tuple(19.42_ft, -15.98_deg, 0_ft), + std::make_tuple(20_ft, -42_deg, 0_ft), + std::make_tuple(5_ft, -55_deg, 2_ft), + std::make_tuple(6_ft, -55_deg, 0_ft), + std::make_tuple(10_ft, -54_deg, 2.2_ft), + std::make_tuple(15_ft, -53_deg, 0_ft), + std::make_tuple(19.52_ft, -15.98_deg, 1.1_ft)); const wpi::math::Pose3d targetPose{ {15.98_m, 0_m, 1_m}, @@ -344,39 +363,20 @@ TEST_P(VisionSystemSimTestDistanceParamsTest, DistanceCalc) { visionSysSim.Update(robotPose); photon::PhotonPipelineResult res = camera.GetLatestResult(); - ASSERT_TRUE(res.HasTargets()); + REQUIRE(res.HasTargets()); photon::PhotonTrackedTarget target = res.GetBestTarget(); - ASSERT_NEAR(0.0, target.GetYaw(), 0.5); + REQUIRE(0.0 == Catch::Approx(target.GetYaw()).margin(0.5)); wpi::units::meter_t dist = photon::PhotonUtils::CalculateDistanceToTarget( robotToCamera.Z(), targetPose.Z(), -pitchParam, wpi::units::degree_t{target.GetPitch()}); - ASSERT_NEAR(dist.to(), - distParam.convert().to(), 0.25); + REQUIRE(dist.to() == + Catch::Approx(distParam.convert().to()) + .margin(0.25)); } -INSTANTIATE_TEST_SUITE_P( - DistanceParamsTests, VisionSystemSimTestDistanceParamsTest, - testing::Values(std::make_tuple(5_ft, -15.98_deg, 0_ft), - std::make_tuple(6_ft, -15.98_deg, 1_ft), - std::make_tuple(10_ft, -15.98_deg, 0_ft), - std::make_tuple(15_ft, -15.98_deg, 2_ft), - std::make_tuple(19.95_ft, -15.98_deg, 0_ft), - std::make_tuple(20_ft, -15.98_deg, 0_ft), - std::make_tuple(5_ft, -42_deg, 1_ft), - std::make_tuple(6_ft, -42_deg, 0_ft), - std::make_tuple(10_ft, -42_deg, 2_ft), - std::make_tuple(15_ft, -42_deg, 0.5_ft), - std::make_tuple(19.42_ft, -15.98_deg, 0_ft), - std::make_tuple(20_ft, -42_deg, 0_ft), - std::make_tuple(5_ft, -55_deg, 2_ft), - std::make_tuple(6_ft, -55_deg, 0_ft), - std::make_tuple(10_ft, -54_deg, 2.2_ft), - std::make_tuple(15_ft, -53_deg, 0_ft), - std::make_tuple(19.52_ft, -15.98_deg, 1.1_ft))); - -TEST_F(VisionSystemSimTest, TestMultipleTargets) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestMultipleTargets", "[photonlib]") { wpi::math::Pose3d targetPoseL{ wpi::math::Translation3d{15.98_m, 2_m, 0_m}, wpi::math::Rotation3d{0_rad, 0_rad, @@ -446,12 +446,12 @@ TEST_F(VisionSystemSimTest, TestMultipleTargets) { wpi::math::Rotation2d{.25_deg}}; visionSysSim.Update(robotPose); photon::PhotonPipelineResult res = camera.GetLatestResult(); - ASSERT_TRUE(res.HasTargets()); + REQUIRE(res.HasTargets()); std::span tgtList = res.GetTargets(); - ASSERT_EQ(static_cast(11), tgtList.size()); + REQUIRE(static_cast(11) == tgtList.size()); } -TEST_F(VisionSystemSimTest, TestPoseEstimation) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestPoseEstimation", "[photonlib]") { photon::VisionSystemSim visionSysSim{"Test"}; photon::PhotonCamera camera{"camera"}; photon::PhotonCameraSim cameraSim{&camera}; @@ -495,14 +495,13 @@ TEST_F(VisionSystemSimTest, TestPoseEstimation) { } auto results = photon::VisionEstimation::EstimateCamPosePNP( camEigen, distEigen, targets, layout, photon::kAprilTag16h5); - ASSERT_TRUE(results); + REQUIRE(results); wpi::math::Pose3d pose = wpi::math::Pose3d{} + results->best; - ASSERT_NEAR(5, pose.X().to(), 0.01); - ASSERT_NEAR(1, pose.Y().to(), 0.01); - ASSERT_NEAR(0, pose.Z().to(), 0.01); - ASSERT_NEAR( - wpi::units::degree_t{5}.convert().to(), - pose.Rotation().Z().to(), 0.01); + REQUIRE(5 == Catch::Approx(pose.X().to()).margin(0.01)); + REQUIRE(1 == Catch::Approx(pose.Y().to()).margin(0.01)); + REQUIRE(0 == Catch::Approx(pose.Z().to()).margin(0.01)); + REQUIRE(wpi::units::degree_t{5}.convert().to() == + Catch::Approx(pose.Rotation().Z().to()).margin(0.01)); visionSysSim.AddVisionTargets( {photon::VisionTargetSim{tagList[1].pose, photon::kAprilTag16h5, 1}}); @@ -518,17 +517,19 @@ TEST_F(VisionSystemSimTest, TestPoseEstimation) { } auto results2 = photon::VisionEstimation::EstimateCamPosePNP( camEigen, distEigen, targets2, layout, photon::kAprilTag16h5); - ASSERT_TRUE(results2); + REQUIRE(results2); wpi::math::Pose3d pose2 = wpi::math::Pose3d{} + results2->best; - ASSERT_NEAR(robotPose.X().to(), pose2.X().to(), 0.01); - ASSERT_NEAR(robotPose.Y().to(), pose2.Y().to(), 0.01); - ASSERT_NEAR(0, pose2.Z().to(), 0.01); - ASSERT_NEAR( - wpi::units::degree_t{5}.convert().to(), - pose2.Rotation().Z().to(), 0.01); + REQUIRE(robotPose.X().to() == + Catch::Approx(pose2.X().to()).margin(0.01)); + REQUIRE(robotPose.Y().to() == + Catch::Approx(pose2.Y().to()).margin(0.01)); + REQUIRE(0 == Catch::Approx(pose2.Z().to()).margin(0.01)); + REQUIRE(wpi::units::degree_t{5}.convert().to() == + Catch::Approx(pose2.Rotation().Z().to()).margin(0.01)); } -TEST_F(VisionSystemSimTest, TestPoseEstimationRotated) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestPoseEstimationRotated", + "[photonlib]") { wpi::math::Transform3d robotToCamera{ wpi::math::Translation3d{6_in, 6_in, 6_in}, wpi::math::Rotation3d{0_deg, -30_deg, 25.5_deg}}; @@ -572,7 +573,7 @@ TEST_F(VisionSystemSimTest, TestPoseEstimationRotated) { auto targetSpan = camResults.GetTargets(); // We need to see at least one target - ASSERT_GT(targetSpan.size(), static_cast(0)); + REQUIRE(targetSpan.size() > static_cast(0)); std::vector targets; for (photon::PhotonTrackedTarget tar : targetSpan) { @@ -580,15 +581,15 @@ TEST_F(VisionSystemSimTest, TestPoseEstimationRotated) { } auto results = photon::VisionEstimation::EstimateCamPosePNP( camEigen, distEigen, targets, layout, photon::kAprilTag36h11); - ASSERT_TRUE(results); + REQUIRE(results); wpi::math::Pose3d pose = wpi::math::Pose3d{} + results->best; pose = pose.TransformBy(robotToCamera.Inverse()); - ASSERT_NEAR(5, pose.X().to(), 0.01); - ASSERT_NEAR(1, pose.Y().to(), 0.01); - ASSERT_NEAR(0, pose.Z().to(), 0.01); - ASSERT_NEAR( - wpi::units::degree_t{-5}.convert().to(), - pose.Rotation().Z().to(), 0.01); + REQUIRE(5 == Catch::Approx(pose.X().to()).margin(0.01)); + REQUIRE(1 == Catch::Approx(pose.Y().to()).margin(0.01)); + REQUIRE(0 == Catch::Approx(pose.Z().to()).margin(0.01)); + REQUIRE( + wpi::units::degree_t{-5}.convert().to() == + Catch::Approx(pose.Rotation().Z().to()).margin(0.01)); visionSysSim.AddVisionTargets( {photon::VisionTargetSim{tagList[1].pose, photon::kAprilTag36h11, 1}}); @@ -604,18 +605,20 @@ TEST_F(VisionSystemSimTest, TestPoseEstimationRotated) { } auto results2 = photon::VisionEstimation::EstimateCamPosePNP( camEigen, distEigen, targets2, layout, photon::kAprilTag36h11); - ASSERT_TRUE(results2); + REQUIRE(results2); wpi::math::Pose3d pose2 = wpi::math::Pose3d{} + results2->best; pose2 = pose2.TransformBy(robotToCamera.Inverse()); - ASSERT_NEAR(robotPose.X().to(), pose2.X().to(), 0.01); - ASSERT_NEAR(robotPose.Y().to(), pose2.Y().to(), 0.01); - ASSERT_NEAR(0, pose2.Z().to(), 0.01); - ASSERT_NEAR( - wpi::units::degree_t{-5}.convert().to(), - pose2.Rotation().Z().to(), 0.01); + REQUIRE(robotPose.X().to() == + Catch::Approx(pose2.X().to()).margin(0.01)); + REQUIRE(robotPose.Y().to() == + Catch::Approx(pose2.Y().to()).margin(0.01)); + REQUIRE(0 == Catch::Approx(pose2.Z().to()).margin(0.01)); + REQUIRE( + wpi::units::degree_t{-5}.convert().to() == + Catch::Approx(pose2.Rotation().Z().to()).margin(0.01)); } -TEST_F(VisionSystemSimTest, TestTagAmbiguity) { +TEST_CASE_METHOD(VisionSystemSimTest, "TestTagAmbiguity", "[photonlib]") { photon::VisionSystemSim visionSysSim{"Test"}; photon::PhotonCamera camera{"camera"}; photon::PhotonCameraSim cameraSim{&camera}; @@ -635,11 +638,11 @@ TEST_F(VisionSystemSimTest, TestTagAmbiguity) { visionSysSim.Update(robotPose); double ambiguity = camera.GetLatestResult().GetBestTarget().GetPoseAmbiguity(); - ASSERT_TRUE(ambiguity > 0.5); + REQUIRE(ambiguity > 0.5); robotPose = wpi::math::Pose2d{wpi::math::Translation2d{-2_m, -2_m}, wpi::math::Rotation2d{30_deg}}; visionSysSim.Update(robotPose); ambiguity = camera.GetLatestResult().GetBestTarget().GetPoseAmbiguity(); - ASSERT_TRUE(0 < ambiguity && ambiguity < 0.2); + REQUIRE((0 < ambiguity && ambiguity < 0.2)); } diff --git a/photon-lib/src/test/native/cpp/main.cpp b/photon-lib/src/test/native/cpp/main.cpp index 6b8949b2f2..988f3bb0a7 100644 --- a/photon-lib/src/test/native/cpp/main.cpp +++ b/photon-lib/src/test/native/cpp/main.cpp @@ -22,14 +22,34 @@ * SOFTWARE. */ +#include + +#include +#include #include -#include "gtest/gtest.h" +namespace { + +bool IsCatchListCommand(int argc, char** argv) { + for (int i = 1; i < argc; ++i) { + std::string_view arg{argv[i]}; + if (arg == "--list-tests" || arg == "--list-tags" || + arg == "--list-reporters" || arg == "--list-listeners") { + return true; + } + } + return false; +} + +} // namespace int main(int argc, char** argv) { - HAL_Initialize(500, 0); - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - HAL_Shutdown(); + if (!IsCatchListCommand(argc, argv)) { + HAL_Initialize(500, 0); + } + int ret = Catch::Session().run(argc, argv); + if (!IsCatchListCommand(argc, argv)) { + HAL_Shutdown(); + } return ret; } diff --git a/photon-serde-tests/build.gradle b/photon-serde-tests/build.gradle index 0eff89fe07..cfaa4541f8 100644 --- a/photon-serde-tests/build.gradle +++ b/photon-serde-tests/build.gradle @@ -87,8 +87,11 @@ model { } nativeUtils.useRequiredLibrary(it, "wpilib_shared") - nativeUtils.useRequiredLibrary(it, "googletest_static") + nativeUtils.useRequiredLibrary(it, "catch2_static") nativeUtils.useRequiredLibrary(it, "datalog_shared") + nativeUtils.useRequiredLibrary(it, "apriltag_shared") + nativeUtils.useRequiredLibrary(it, "cscore_shared") + nativeUtils.useRequiredLibrary(it, "opencv_shared") } } diff --git a/photon-serde/templates/ThingTests.cpp.jinja b/photon-serde/templates/ThingTests.cpp.jinja index ea9216762d..0a678fc86e 100644 --- a/photon-serde/templates/ThingTests.cpp.jinja +++ b/photon-serde/templates/ThingTests.cpp.jinja @@ -21,10 +21,10 @@ #include #include +#include +#include #include -#include "gtest/gtest.h" - {% for include in cpp_includes -%} #include {{ include }} {% endfor %} @@ -35,8 +35,7 @@ // Hack int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + return Catch::Session().run(argc, argv); } using namespace photon; @@ -51,14 +50,14 @@ inline bool test_serde(const T& data) { } {% for test in tests %} -TEST(AutoSerdeTest, {{ test.name }}) { +TEST_CASE("AutoSerdeTest {{ test.name }}", "[serde]") { std::cout << "Running {{ test.name }}\n"; {% for test_case in test.cases %} {{ test.type }} {{ test_case.name }}{}; {% for field in test_case.fields -%} {{ test_case.name }}.{{ field.name }} = {{ field.cpp_value }}; {% endfor -%} - ASSERT_TRUE(test_serde({{ test_case.name }})); + REQUIRE(test_serde({{ test_case.name }})); {% endfor %} } {% endfor %} \ No newline at end of file diff --git a/photon-targeting/build.gradle b/photon-targeting/build.gradle index 563afbc5fa..897eb2ac8e 100644 --- a/photon-targeting/build.gradle +++ b/photon-targeting/build.gradle @@ -118,7 +118,7 @@ model { } nativeUtils.useRequiredLibrary(it, "wpilib_shared") - nativeUtils.useRequiredLibrary(it, "googletest_static") + nativeUtils.useRequiredLibrary(it, "catch2_static") nativeUtils.useRequiredLibrary(it, "datalog_shared") nativeUtils.useRequiredLibrary(it, "apriltag_shared") nativeUtils.useRequiredLibrary(it, "cscore_shared") diff --git a/photon-targeting/src/test/native/cpp/CasadiWrapperTest.cpp b/photon-targeting/src/test/native/cpp/CasadiWrapperTest.cpp index a8fe9d8d1d..e7abedcdf1 100644 --- a/photon-targeting/src/test/native/cpp/CasadiWrapperTest.cpp +++ b/photon-targeting/src/test/native/cpp/CasadiWrapperTest.cpp @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -#include +#include #include #include #include @@ -180,4 +180,6 @@ void print_cost(casadi_real robot_x, casadi_real robot_y, } } -TEST(CasadiWrapperTest, smoketest) { print_cost(0.1, 0.1, 0.0); } +TEST_CASE("CasadiWrapperTest smoketest", "[casadi]") { + print_cost(0.1, 0.1, 0.0); +} diff --git a/photon-targeting/src/test/native/cpp/PacketTest.cpp b/photon-targeting/src/test/native/cpp/PacketTest.cpp index 923d19713c..de5e3ff8e9 100644 --- a/photon-targeting/src/test/native/cpp/PacketTest.cpp +++ b/photon-targeting/src/test/native/cpp/PacketTest.cpp @@ -20,10 +20,10 @@ #include #include +#include #include #include -#include "gtest/gtest.h" #include "photon/targeting/MultiTargetPNPResult.h" #include "photon/targeting/PhotonPipelineResult.h" #include "photon/targeting/PhotonTrackedTarget.h" @@ -31,7 +31,7 @@ using namespace photon; -TEST(PacketTest, PnpResult) { +TEST_CASE("PacketTest PnpResult", "[packet]") { PnpResult result{}; result.best = {1_m, 2_m, 3_m, wpi::math::Rotation3d{6_deg, 7_deg, 12_deg}}; @@ -46,7 +46,7 @@ TEST(PacketTest, PnpResult) { PnpResult b = p.Unpack(); - EXPECT_EQ(result, b); + CHECK(result == b); } // TEST(PacketTest, MultiTargetPNPResult) { @@ -86,14 +86,14 @@ TEST(PacketTest, PnpResult) { // EXPECT_EQ(target, b); // } -TEST(PacketTest, PhotonPipelineResult) { +TEST_CASE("PacketTest PhotonPipelineResult", "[packet]") { PhotonPipelineResult result(PhotonPipelineMetadata(0, 0, 1, 2), std::vector{}, std::nullopt); Packet p; p.Pack(result); auto b = p.Unpack(); - EXPECT_EQ(result, b); + CHECK(result == b); std::vector targets{ PhotonTrackedTarget{ @@ -141,7 +141,7 @@ TEST(PacketTest, PhotonPipelineResult) { auto t2 = std::chrono::steady_clock::now(); auto b2 = p2.Unpack(); auto t3 = std::chrono::steady_clock::now(); - EXPECT_EQ(result2, b2); + CHECK(result2 == b2); wpi::util::println( "Pack {} unpack {} packet length {}", diff --git a/photon-targeting/src/test/native/cpp/main.cpp b/photon-targeting/src/test/native/cpp/main.cpp index 89d0cd5c16..b100ecf603 100644 --- a/photon-targeting/src/test/native/cpp/main.cpp +++ b/photon-targeting/src/test/native/cpp/main.cpp @@ -15,14 +15,34 @@ * along with this program. If not, see . */ +#include + +#include +#include #include -#include "gtest/gtest.h" +namespace { + +bool IsCatchListCommand(int argc, char** argv) { + for (int i = 1; i < argc; ++i) { + std::string_view arg{argv[i]}; + if (arg == "--list-tests" || arg == "--list-tags" || + arg == "--list-reporters" || arg == "--list-listeners") { + return true; + } + } + return false; +} + +} // namespace int main(int argc, char** argv) { - HAL_Initialize(500, 0); - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - HAL_Shutdown(); + if (!IsCatchListCommand(argc, argv)) { + HAL_Initialize(500, 0); + } + int ret = Catch::Session().run(argc, argv); + if (!IsCatchListCommand(argc, argv)) { + HAL_Shutdown(); + } return ret; } diff --git a/photon-targeting/src/test/native/cpp/net/TimeSyncTest.cpp b/photon-targeting/src/test/native/cpp/net/TimeSyncTest.cpp index 4d550607b8..e7f3842db4 100644 --- a/photon-targeting/src/test/native/cpp/net/TimeSyncTest.cpp +++ b/photon-targeting/src/test/native/cpp/net/TimeSyncTest.cpp @@ -15,13 +15,13 @@ * along with this program. If not, see . */ -#include +#include #include #include #include #include -TEST(TimeSyncProtocolTest, Smoketest) { +TEST_CASE("TimeSyncProtocolTest Smoketest", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -40,7 +40,7 @@ TEST(TimeSyncProtocolTest, Smoketest) { server.Stop(); } -TEST(TimeSyncClientTest, CalculateZero) { +TEST_CASE("TimeSyncClientTest CalculateZero", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -61,13 +61,13 @@ TEST(TimeSyncClientTest, CalculateZero) { client.UpdateStatistics(pong_client_time, ping, pong); // THEN the statistics will reflect no delay - EXPECT_EQ(0, client.GetMetadata().offset); - EXPECT_EQ(0, client.GetMetadata().rtt2); - EXPECT_EQ(1u, client.GetMetadata().pongsReceived); - EXPECT_EQ(pong_client_time, client.GetMetadata().lastPongTime); + CHECK(0 == client.GetMetadata().offset); + CHECK(0 == client.GetMetadata().rtt2); + CHECK(1u == client.GetMetadata().pongsReceived); + CHECK(pong_client_time == client.GetMetadata().lastPongTime); } -TEST(TimeSyncClientTest, CalculateZeroOffset) { +TEST_CASE("TimeSyncClientTest CalculateZeroOffset", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -89,13 +89,13 @@ TEST(TimeSyncClientTest, CalculateZeroOffset) { // THEN the statistics will reflect no offset, and the expected rtt2 // (client-to-client) latency - EXPECT_EQ(0, client.GetMetadata().offset); - EXPECT_EQ(20, client.GetMetadata().rtt2); - EXPECT_EQ(1u, client.GetMetadata().pongsReceived); - EXPECT_EQ(pong_client_time, client.GetMetadata().lastPongTime); + CHECK(0 == client.GetMetadata().offset); + CHECK(20 == client.GetMetadata().rtt2); + CHECK(1u == client.GetMetadata().pongsReceived); + CHECK(pong_client_time == client.GetMetadata().lastPongTime); } -TEST(TimeSyncClientTest, CalculateZeroRtt) { +TEST_CASE("TimeSyncClientTest CalculateZeroRtt", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -116,13 +116,13 @@ TEST(TimeSyncClientTest, CalculateZeroRtt) { client.UpdateStatistics(pong_client_time, ping, pong); // THEN the statistics will reflect the expected 23ms offset - EXPECT_EQ(23, client.GetMetadata().offset); - EXPECT_EQ(0, client.GetMetadata().rtt2); - EXPECT_EQ(1u, client.GetMetadata().pongsReceived); - EXPECT_EQ(pong_client_time, client.GetMetadata().lastPongTime); + CHECK(23 == client.GetMetadata().offset); + CHECK(0 == client.GetMetadata().rtt2); + CHECK(1u == client.GetMetadata().pongsReceived); + CHECK(pong_client_time == client.GetMetadata().lastPongTime); } -TEST(TimeSyncClientTest, CalculateBoth) { +TEST_CASE("TimeSyncClientTest CalculateBoth", "[timesync]") { using namespace wpi::tsp; using namespace std::chrono_literals; @@ -146,8 +146,8 @@ TEST(TimeSyncClientTest, CalculateBoth) { client.UpdateStatistics(pong_client_time, ping, pong); // THEN the statistics will reflect the expected latency and RTT - EXPECT_EQ(offset, client.GetMetadata().offset); - EXPECT_EQ(network_latency * 2, client.GetMetadata().rtt2); - EXPECT_EQ(1u, client.GetMetadata().pongsReceived); - EXPECT_EQ(pong_client_time, client.GetMetadata().lastPongTime); + CHECK(offset == client.GetMetadata().offset); + CHECK(network_latency * 2 == client.GetMetadata().rtt2); + CHECK(1u == client.GetMetadata().pongsReceived); + CHECK(pong_client_time == client.GetMetadata().lastPongTime); } diff --git a/shared/config.gradle b/shared/config.gradle index 977252691f..7e0e227353 100644 --- a/shared/config.gradle +++ b/shared/config.gradle @@ -7,6 +7,7 @@ nativeUtils.withCrossSystemCore() nativeUtils.wpi.configureDependencies { wpiVersion = wpilibVersion opencvVersion = openCVversion + mrcLibVersion = "2027.1.0-alpha-1-93-g7293eb0" } // Configure warnings and errors