From b7a0fad54c0bfd7d65d4438a1e9da4cf4834c3d0 Mon Sep 17 00:00:00 2001 From: Sam Freund Date: Wed, 21 Jan 2026 18:44:49 -0600 Subject: [PATCH] Set max target limit to 50 (#2320) ## Description closes #2318 closes #2319 For the 2027 game, teams might want to detect more than 10 results. Therefore, we're increasing the limit. We also ran into an issue with our sim, where a user can create too many objects and cause an overflow. We implement that same limit of 50 targets here. ## Meta Merge checklist: - [x] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes - [x] The description documents the _what_ and _why_ - [ ] If this PR changes behavior or adds a feature, user documentation is updated - [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly - [ ] If this PR touches configuration, this is backwards compatible with settings back to v2025.3.2 - [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated - [ ] If this PR addresses a bug, a regression test for it is added --- .../vision/pipeline/CVPipeline.java | 2 +- .../photonlibpy/simulation/photonCameraSim.py | 3 ++ photon-lib/py/test/visionSystemSim_test.py | 29 +++++++++++++++++++ .../simulation/PhotonCameraSim.java | 4 +++ .../cpp/photon/simulation/PhotonCameraSim.cpp | 4 +++ .../org/photonvision/VisionSystemSimTest.java | 22 ++++++++++++++ .../test/native/cpp/VisionSystemSimTest.cpp | 23 +++++++++++++++ 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java index 91dc44a58..60e033cf9 100644 --- a/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java +++ b/photon-core/src/main/java/org/photonvision/vision/pipeline/CVPipeline.java @@ -26,7 +26,7 @@ import org.photonvision.vision.pipeline.result.CVPipelineResult; public abstract class CVPipeline implements Releasable { - static final int MAX_MULTI_TARGET_RESULTS = 10; + static final int MAX_MULTI_TARGET_RESULTS = 50; protected S settings; protected FrameStaticProperties frameStaticProperties; diff --git a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py index 8f3472732..a1ee052a1 100644 --- a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py +++ b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py @@ -271,6 +271,9 @@ class PhotonCameraSim: camRt = RotTrlTransform3d.makeRelativeTo(cameraPose) for tgt in targets: + if len(detectableTgts) >= 50: + break + # pose isn't visible, skip to next if not self.canSeeTargetPose(cameraPose, tgt): continue diff --git a/photon-lib/py/test/visionSystemSim_test.py b/photon-lib/py/test/visionSystemSim_test.py index df5dba4c1..9b1280569 100644 --- a/photon-lib/py/test/visionSystemSim_test.py +++ b/photon-lib/py/test/visionSystemSim_test.py @@ -78,6 +78,35 @@ def test_VisibilityCupidShuffle() -> None: assert camera.getLatestResult().hasTargets() +def test_bunchaTargets() -> None: + visionSysSim = VisionSystemSim("Test") + camera = PhotonCamera("camera") + cameraSim = PhotonCameraSim(camera) + visionSysSim.addCamera(cameraSim, Transform3d()) + + cameraSim.prop.setCalibrationFromFOV(640, 480, fovDiag=Rotation2d.fromDegrees(80.0)) + + for i in range(100): + targetPose = Pose3d( + Translation3d(15.98 + i * 0.1, 0.0, 2.0), Rotation3d(0, 0, math.pi) + ) + visionSysSim.addVisionTargets( + [ + VisionTargetSim( + targetPose, + TargetModel.createPlanar(width=1.0, height=1.0), + 4774 + i, + ) + ] + ) + + robotPose = Pose2d(Translation2d(2.0, 0.0), Rotation2d.fromDegrees(5.0)) + + visionSysSim.update(robotPose) + + assert len(camera.getLatestResult().getTargets()) == 50 + + def test_NotVisibleVert1() -> None: targetPose = Pose3d(Translation3d(15.98, 0.0, 2.0), Rotation3d(0, 0, math.pi)) diff --git a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java index d20af6958..c4331ba8c 100644 --- a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java +++ b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java @@ -442,6 +442,10 @@ public class PhotonCameraSim implements AutoCloseable { Mat.zeros(videoFrameSize, CvType.CV_8UC1).assignTo(videoSimFrameRaw); for (var tgt : targets) { + if (detectableTgts.size() >= 50) { + break; + } + // pose isn't visible, skip to next if (!canSeeTargetPose(cameraPose, tgt)) continue; diff --git a/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp b/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp index ed6d2bd35..4914436ec 100644 --- a/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp +++ b/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp @@ -131,6 +131,10 @@ PhotonPipelineResult PhotonCameraSim::Process( blankFrame.assignTo(videoSimFrameRaw); for (const auto& tgt : targets) { + if (detectableTgts.size() >= 50) { + break; + } + if (!CanSeeTargetPose(cameraPose, tgt)) { continue; } diff --git a/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java b/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java index 3d85c4825..917d1d5ad 100644 --- a/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java +++ b/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java @@ -179,6 +179,28 @@ class VisionSystemSimTest { assertTrue(result.hasTargets()); } + @Test + public void testBunchaTargets() { + var visionSysSim = new VisionSystemSim("Test"); + var camera = new PhotonCamera(inst, "camera"); + var cameraSim = new PhotonCameraSim(camera); + visionSysSim.addCamera(cameraSim, new Transform3d()); + cameraSim.prop.setCalibration(640, 480, Rotation2d.fromDegrees(80)); + + for (int i = 0; i < 100; i++) { + final var targetPose = + new Pose3d(new Translation3d(15.98 + i * 0.1, 0, 1), new Rotation3d(0, 0, Math.PI)); + visionSysSim.addVisionTargets(new VisionTargetSim(targetPose, new TargetModel(0.5, 0.5), i)); + } + + var robotPose = new Pose2d(new Translation2d(5, 0), Rotation2d.fromDegrees(5)); + visionSysSim.update(robotPose); + + var res = waitForSequenceNumber(camera, 1); + + assertEquals(50, res.getTargets().size()); + } + @Test public void testNotVisibleVert1() { final var targetPose = diff --git a/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp b/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp index 501baa9c5..621a660b4 100644 --- a/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp +++ b/photon-lib/src/test/native/cpp/VisionSystemSimTest.cpp @@ -117,6 +117,29 @@ TEST_F(VisionSystemSimTest, TestVisibilityCupidShuffle) { ASSERT_TRUE(camera.GetLatestResult().HasTargets()); } +TEST_F(VisionSystemSimTest, TestBunchaTargets) { + photon::VisionSystemSim visionSysSim{"Test"}; + photon::PhotonCamera camera{"camera"}; + photon::PhotonCameraSim cameraSim{&camera}; + visionSysSim.AddCamera(&cameraSim, frc::Transform3d{}); + cameraSim.prop.SetCalibration(640, 480, frc::Rotation2d{80_deg}); + + std::vector targets; + for (int i = 0; i < 100; i++) { + targets.emplace_back( + frc::Pose3d{ + frc::Translation3d{15.98_m + i * 0.1_m, 0_m, 1_m}, + frc::Rotation3d{0_rad, 0_rad, units::radian_t{std::numbers::pi}}}, + photon::TargetModel{0.5_m, 0.5_m}, i); + } + visionSysSim.AddVisionTargets(targets); + + frc::Pose2d robotPose{frc::Translation2d{5_m, 0_m}, frc::Rotation2d{5_deg}}; + visionSysSim.Update(robotPose); + + ASSERT_EQ(camera.GetLatestResult().targets.size(), 50u); +} + TEST_F(VisionSystemSimTest, TestNotVisibleVert1) { frc::Pose3d targetPose{ frc::Translation3d{15.98_m, 0_m, 1_m},