Set max target limit to 50 (#2320)

## Description

<!-- What changed? Why? (the code + comments should speak for itself on
the "how") -->

<!-- Fun screenshots or a cool video or something are super helpful as
well. If this touches platform-specific behavior, this is where test
evidence should be collected. -->

<!-- Any issues this pull request closes or pull requests this
supersedes should be linked with `Closes #issuenumber`. -->

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
This commit is contained in:
Sam Freund
2026-01-21 18:44:49 -06:00
committed by GitHub
parent e73420d62a
commit b7a0fad54c
7 changed files with 86 additions and 1 deletions

View File

@@ -26,7 +26,7 @@ import org.photonvision.vision.pipeline.result.CVPipelineResult;
public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelineSettings>
implements Releasable {
static final int MAX_MULTI_TARGET_RESULTS = 10;
static final int MAX_MULTI_TARGET_RESULTS = 50;
protected S settings;
protected FrameStaticProperties frameStaticProperties;

View File

@@ -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

View File

@@ -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))

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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 =

View File

@@ -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<photon::VisionTargetSim> 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},