photonlibpy 2025.0.0b2__py3-none-any.whl → 2025.0.0b3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- photonlibpy/estimation/openCVHelp.py +12 -7
 - photonlibpy/estimation/rotTrlTransform3d.py +24 -1
 - photonlibpy/estimation/targetModel.py +63 -80
 - photonlibpy/estimation/visionEstimation.py +4 -4
 - photonlibpy/generated/MultiTargetPNPResultSerde.py +7 -1
 - photonlibpy/generated/PhotonPipelineMetadataSerde.py +6 -1
 - photonlibpy/generated/PhotonPipelineResultSerde.py +9 -1
 - photonlibpy/generated/PhotonTrackedTargetSerde.py +7 -1
 - photonlibpy/generated/PnpResultSerde.py +6 -1
 - photonlibpy/generated/TargetCornerSerde.py +6 -1
 - photonlibpy/networktables/NTTopicSet.py +4 -2
 - photonlibpy/photonCamera.py +1 -1
 - photonlibpy/simulation/photonCameraSim.py +18 -48
 - photonlibpy/simulation/simCameraProperties.py +44 -62
 - photonlibpy/simulation/visionSystemSim.py +12 -7
 - photonlibpy/targeting/TargetCorner.py +2 -2
 - photonlibpy/targeting/multiTargetPNPResult.py +4 -15
 - photonlibpy/targeting/photonPipelineResult.py +4 -3
 - photonlibpy/targeting/photonTrackedTarget.py +2 -2
 - photonlibpy/version.py +2 -2
 - {photonlibpy-2025.0.0b2.dist-info → photonlibpy-2025.0.0b3.dist-info}/METADATA +8 -8
 - photonlibpy-2025.0.0b3.dist-info/RECORD +36 -0
 - photonlibpy-2025.0.0b2.dist-info/RECORD +0 -36
 - {photonlibpy-2025.0.0b2.dist-info → photonlibpy-2025.0.0b3.dist-info}/WHEEL +0 -0
 - {photonlibpy-2025.0.0b2.dist-info → photonlibpy-2025.0.0b3.dist-info}/top_level.txt +0 -0
 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            import math
         
     | 
| 
       2 
     | 
    
         
            -
            from typing import Any 
     | 
| 
      
 2 
     | 
    
         
            +
            from typing import Any
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            import cv2 as cv
         
     | 
| 
       5 
5 
     | 
    
         
             
            import numpy as np
         
     | 
| 
         @@ -48,13 +48,13 @@ class OpenCVHelp: 
     | 
|
| 
       48 
48 
     | 
    
         
             
                    )
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
                @staticmethod
         
     | 
| 
       51 
     | 
    
         
            -
                def avgPoint(points:  
     | 
| 
      
 51 
     | 
    
         
            +
                def avgPoint(points: np.ndarray) -> np.ndarray:
         
     | 
| 
       52 
52 
     | 
    
         
             
                    x = 0.0
         
     | 
| 
       53 
53 
     | 
    
         
             
                    y = 0.0
         
     | 
| 
       54 
54 
     | 
    
         
             
                    for p in points:
         
     | 
| 
       55 
     | 
    
         
            -
                        x += p[0]
         
     | 
| 
       56 
     | 
    
         
            -
                        y += p[1]
         
     | 
| 
       57 
     | 
    
         
            -
                    return (x / len(points), y / len(points))
         
     | 
| 
      
 55 
     | 
    
         
            +
                        x += p[0, 0]
         
     | 
| 
      
 56 
     | 
    
         
            +
                        y += p[0, 1]
         
     | 
| 
      
 57 
     | 
    
         
            +
                    return np.array([[x / len(points), y / len(points)]])
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
                @staticmethod
         
     | 
| 
       60 
60 
     | 
    
         
             
                def pointsToTargetCorners(points: np.ndarray) -> list[TargetCorner]:
         
     | 
| 
         @@ -126,6 +126,9 @@ class OpenCVHelp: 
     | 
|
| 
       126 
126 
     | 
    
         
             
                    objectMat = np.array(OpenCVHelp.translationToTVec(modelTrls))
         
     | 
| 
       127 
127 
     | 
    
         | 
| 
       128 
128 
     | 
    
         
             
                    alt: Transform3d | None = None
         
     | 
| 
      
 129 
     | 
    
         
            +
                    reprojectionError: cv.typing.MatLike | None = None
         
     | 
| 
      
 130 
     | 
    
         
            +
                    best: Transform3d = Transform3d()
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
       129 
132 
     | 
    
         
             
                    for tries in range(2):
         
     | 
| 
       130 
133 
     | 
    
         
             
                        retval, rvecs, tvecs, reprojectionError = cv.solvePnPGeneric(
         
     | 
| 
       131 
134 
     | 
    
         
             
                            objectMat,
         
     | 
| 
         @@ -145,7 +148,9 @@ class OpenCVHelp: 
     | 
|
| 
       145 
148 
     | 
    
         
             
                                OpenCVHelp.rVecToRotation(rvecs[1]),
         
     | 
| 
       146 
149 
     | 
    
         
             
                            )
         
     | 
| 
       147 
150 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
                        if not math.isnan( 
     | 
| 
      
 151 
     | 
    
         
            +
                        if reprojectionError is not None and not math.isnan(
         
     | 
| 
      
 152 
     | 
    
         
            +
                            reprojectionError[0, 0]
         
     | 
| 
      
 153 
     | 
    
         
            +
                        ):
         
     | 
| 
       149 
154 
     | 
    
         
             
                            break
         
     | 
| 
       150 
155 
     | 
    
         
             
                        else:
         
     | 
| 
       151 
156 
     | 
    
         
             
                            pt = imagePoints[0]
         
     | 
| 
         @@ -153,7 +158,7 @@ class OpenCVHelp: 
     | 
|
| 
       153 
158 
     | 
    
         
             
                            pt[0, 1] -= 0.001
         
     | 
| 
       154 
159 
     | 
    
         
             
                            imagePoints[0] = pt
         
     | 
| 
       155 
160 
     | 
    
         | 
| 
       156 
     | 
    
         
            -
                    if math.isnan(reprojectionError[0, 0]):
         
     | 
| 
      
 161 
     | 
    
         
            +
                    if reprojectionError is None or math.isnan(reprojectionError[0, 0]):
         
     | 
| 
       157 
162 
     | 
    
         
             
                        print("SolvePNP_Square failed!")
         
     | 
| 
       158 
163 
     | 
    
         
             
                        return None
         
     | 
| 
       159 
164 
     | 
    
         | 
| 
         @@ -24,9 +24,32 @@ class RotTrlTransform3d: 
     | 
|
| 
       24 
24 
     | 
    
         
             
                def getRotation(self) -> Rotation3d:
         
     | 
| 
       25 
25 
     | 
    
         
             
                    return self.rot
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                def  
     | 
| 
      
 27 
     | 
    
         
            +
                def applyTranslation(self, trlToApply: Translation3d) -> Translation3d:
         
     | 
| 
       28 
28 
     | 
    
         
             
                    return trlToApply.rotateBy(self.rot) + self.trl
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                def applyRotation(self, rotToApply: Rotation3d) -> Rotation3d:
         
     | 
| 
      
 31 
     | 
    
         
            +
                    return rotToApply + self.rot
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def applyPose(self, poseToApply: Pose3d) -> Pose3d:
         
     | 
| 
      
 34 
     | 
    
         
            +
                    return Pose3d(
         
     | 
| 
      
 35 
     | 
    
         
            +
                        self.applyTranslation(poseToApply.translation()),
         
     | 
| 
      
 36 
     | 
    
         
            +
                        self.applyRotation(poseToApply.rotation()),
         
     | 
| 
      
 37 
     | 
    
         
            +
                    )
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def applyTrls(self, rots: list[Rotation3d]) -> list[Rotation3d]:
         
     | 
| 
      
 40 
     | 
    
         
            +
                    retVal: list[Rotation3d] = []
         
     | 
| 
      
 41 
     | 
    
         
            +
                    for rot in rots:
         
     | 
| 
      
 42 
     | 
    
         
            +
                        retVal.append(self.applyRotation(rot))
         
     | 
| 
      
 43 
     | 
    
         
            +
                    return retVal
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       30 
45 
     | 
    
         
             
                @classmethod
         
     | 
| 
       31 
46 
     | 
    
         
             
                def makeRelativeTo(cls, pose: Pose3d) -> Self:
         
     | 
| 
       32 
47 
     | 
    
         
             
                    return cls(pose.rotation(), pose.translation()).inverse()
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 50 
     | 
    
         
            +
                def makeBetweenPoses(cls, initial: Pose3d, last: Pose3d) -> Self:
         
     | 
| 
      
 51 
     | 
    
         
            +
                    return cls(
         
     | 
| 
      
 52 
     | 
    
         
            +
                        last.rotation() - initial.rotation(),
         
     | 
| 
      
 53 
     | 
    
         
            +
                        last.translation()
         
     | 
| 
      
 54 
     | 
    
         
            +
                        - initial.translation().rotateBy(last.rotation() - initial.rotation()),
         
     | 
| 
      
 55 
     | 
    
         
            +
                    )
         
     | 
| 
         @@ -8,87 +8,70 @@ from . import RotTrlTransform3d 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            class TargetModel:
         
     | 
| 
       11 
     | 
    
         
            -
                def __init__(
         
     | 
| 
       12 
     | 
    
         
            -
                    self,
         
     | 
| 
       13 
     | 
    
         
            -
                    *,
         
     | 
| 
       14 
     | 
    
         
            -
                    width: meters | None = None,
         
     | 
| 
       15 
     | 
    
         
            -
                    height: meters | None = None,
         
     | 
| 
       16 
     | 
    
         
            -
                    length: meters | None = None,
         
     | 
| 
       17 
     | 
    
         
            -
                    diameter: meters | None = None,
         
     | 
| 
       18 
     | 
    
         
            -
                    verts: List[Translation3d] | None = None
         
     | 
| 
       19 
     | 
    
         
            -
                ):
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    if (
         
     | 
| 
       22 
     | 
    
         
            -
                        width is not None
         
     | 
| 
       23 
     | 
    
         
            -
                        and height is not None
         
     | 
| 
       24 
     | 
    
         
            -
                        and length is None
         
     | 
| 
       25 
     | 
    
         
            -
                        and diameter is None
         
     | 
| 
       26 
     | 
    
         
            -
                        and verts is None
         
     | 
| 
       27 
     | 
    
         
            -
                    ):
         
     | 
| 
       28 
     | 
    
         
            -
                        self.isPlanar = True
         
     | 
| 
       29 
     | 
    
         
            -
                        self.isSpherical = False
         
     | 
| 
       30 
     | 
    
         
            -
                        self.vertices = [
         
     | 
| 
       31 
     | 
    
         
            -
                            Translation3d(0.0, -width / 2.0, -height / 2.0),
         
     | 
| 
       32 
     | 
    
         
            -
                            Translation3d(0.0, width / 2.0, -height / 2.0),
         
     | 
| 
       33 
     | 
    
         
            -
                            Translation3d(0.0, width / 2.0, height / 2.0),
         
     | 
| 
       34 
     | 
    
         
            -
                            Translation3d(0.0, -width / 2.0, height / 2.0),
         
     | 
| 
       35 
     | 
    
         
            -
                        ]
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                        return
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                    elif (
         
     | 
| 
       40 
     | 
    
         
            -
                        length is not None
         
     | 
| 
       41 
     | 
    
         
            -
                        and width is not None
         
     | 
| 
       42 
     | 
    
         
            -
                        and height is not None
         
     | 
| 
       43 
     | 
    
         
            -
                        and diameter is None
         
     | 
| 
       44 
     | 
    
         
            -
                        and verts is None
         
     | 
| 
       45 
     | 
    
         
            -
                    ):
         
     | 
| 
       46 
     | 
    
         
            -
                        verts = [
         
     | 
| 
       47 
     | 
    
         
            -
                            Translation3d(length / 2.0, -width / 2.0, -height / 2.0),
         
     | 
| 
       48 
     | 
    
         
            -
                            Translation3d(length / 2.0, width / 2.0, -height / 2.0),
         
     | 
| 
       49 
     | 
    
         
            -
                            Translation3d(length / 2.0, width / 2.0, height / 2.0),
         
     | 
| 
       50 
     | 
    
         
            -
                            Translation3d(length / 2.0, -width / 2.0, height / 2.0),
         
     | 
| 
       51 
     | 
    
         
            -
                            Translation3d(-length / 2.0, -width / 2.0, height / 2.0),
         
     | 
| 
       52 
     | 
    
         
            -
                            Translation3d(-length / 2.0, width / 2.0, height / 2.0),
         
     | 
| 
       53 
     | 
    
         
            -
                            Translation3d(-length / 2.0, width / 2.0, -height / 2.0),
         
     | 
| 
       54 
     | 
    
         
            -
                            Translation3d(-length / 2.0, -width / 2.0, -height / 2.0),
         
     | 
| 
       55 
     | 
    
         
            -
                        ]
         
     | 
| 
       56 
     | 
    
         
            -
                        # Handle the rest of this in the "default" case
         
     | 
| 
       57 
     | 
    
         
            -
                    elif (
         
     | 
| 
       58 
     | 
    
         
            -
                        diameter is not None
         
     | 
| 
       59 
     | 
    
         
            -
                        and width is None
         
     | 
| 
       60 
     | 
    
         
            -
                        and height is None
         
     | 
| 
       61 
     | 
    
         
            -
                        and length is None
         
     | 
| 
       62 
     | 
    
         
            -
                        and verts is None
         
     | 
| 
       63 
     | 
    
         
            -
                    ):
         
     | 
| 
       64 
     | 
    
         
            -
                        self.isPlanar = False
         
     | 
| 
       65 
     | 
    
         
            -
                        self.isSpherical = True
         
     | 
| 
       66 
     | 
    
         
            -
                        self.vertices = [
         
     | 
| 
       67 
     | 
    
         
            -
                            Translation3d(0.0, -diameter / 2.0, 0.0),
         
     | 
| 
       68 
     | 
    
         
            -
                            Translation3d(0.0, 0.0, -diameter / 2.0),
         
     | 
| 
       69 
     | 
    
         
            -
                            Translation3d(0.0, diameter / 2.0, 0.0),
         
     | 
| 
       70 
     | 
    
         
            -
                            Translation3d(0.0, 0.0, diameter / 2.0),
         
     | 
| 
       71 
     | 
    
         
            -
                        ]
         
     | 
| 
       72 
     | 
    
         
            -
                        return
         
     | 
| 
       73 
     | 
    
         
            -
                    elif (
         
     | 
| 
       74 
     | 
    
         
            -
                        verts is not None
         
     | 
| 
       75 
     | 
    
         
            -
                        and width is None
         
     | 
| 
       76 
     | 
    
         
            -
                        and height is None
         
     | 
| 
       77 
     | 
    
         
            -
                        and length is None
         
     | 
| 
       78 
     | 
    
         
            -
                        and diameter is None
         
     | 
| 
       79 
     | 
    
         
            -
                    ):
         
     | 
| 
       80 
     | 
    
         
            -
                        # Handle this in the "default" case
         
     | 
| 
       81 
     | 
    
         
            -
                        pass
         
     | 
| 
       82 
     | 
    
         
            -
                    else:
         
     | 
| 
       83 
     | 
    
         
            -
                        raise Exception("Not a valid overload")
         
     | 
| 
       84 
11 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                     
     | 
| 
       87 
     | 
    
         
            -
                     
     | 
| 
      
 12 
     | 
    
         
            +
                def __init__(self):
         
     | 
| 
      
 13 
     | 
    
         
            +
                    self.vertices: List[Translation3d] = []
         
     | 
| 
      
 14 
     | 
    
         
            +
                    self.isPlanar = False
         
     | 
| 
      
 15 
     | 
    
         
            +
                    self.isSpherical = False
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 18 
     | 
    
         
            +
                def createPlanar(cls, width: meters, height: meters) -> Self:
         
     | 
| 
      
 19 
     | 
    
         
            +
                    tm = cls()
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    tm.isPlanar = True
         
     | 
| 
      
 22 
     | 
    
         
            +
                    tm.isSpherical = False
         
     | 
| 
      
 23 
     | 
    
         
            +
                    tm.vertices = [
         
     | 
| 
      
 24 
     | 
    
         
            +
                        Translation3d(0.0, -width / 2.0, -height / 2.0),
         
     | 
| 
      
 25 
     | 
    
         
            +
                        Translation3d(0.0, width / 2.0, -height / 2.0),
         
     | 
| 
      
 26 
     | 
    
         
            +
                        Translation3d(0.0, width / 2.0, height / 2.0),
         
     | 
| 
      
 27 
     | 
    
         
            +
                        Translation3d(0.0, -width / 2.0, height / 2.0),
         
     | 
| 
      
 28 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    return tm
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 32 
     | 
    
         
            +
                def createCuboid(cls, length: meters, width: meters, height: meters) -> Self:
         
     | 
| 
      
 33 
     | 
    
         
            +
                    tm = cls()
         
     | 
| 
      
 34 
     | 
    
         
            +
                    verts = [
         
     | 
| 
      
 35 
     | 
    
         
            +
                        Translation3d(length / 2.0, -width / 2.0, -height / 2.0),
         
     | 
| 
      
 36 
     | 
    
         
            +
                        Translation3d(length / 2.0, width / 2.0, -height / 2.0),
         
     | 
| 
      
 37 
     | 
    
         
            +
                        Translation3d(length / 2.0, width / 2.0, height / 2.0),
         
     | 
| 
      
 38 
     | 
    
         
            +
                        Translation3d(length / 2.0, -width / 2.0, height / 2.0),
         
     | 
| 
      
 39 
     | 
    
         
            +
                        Translation3d(-length / 2.0, -width / 2.0, height / 2.0),
         
     | 
| 
      
 40 
     | 
    
         
            +
                        Translation3d(-length / 2.0, width / 2.0, height / 2.0),
         
     | 
| 
      
 41 
     | 
    
         
            +
                        Translation3d(-length / 2.0, width / 2.0, -height / 2.0),
         
     | 
| 
      
 42 
     | 
    
         
            +
                        Translation3d(-length / 2.0, -width / 2.0, -height / 2.0),
         
     | 
| 
      
 43 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    tm._common_construction(verts)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    return tm
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 50 
     | 
    
         
            +
                def createSpheroid(cls, diameter: meters) -> Self:
         
     | 
| 
      
 51 
     | 
    
         
            +
                    tm = cls()
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    tm.isPlanar = False
         
     | 
| 
      
 54 
     | 
    
         
            +
                    tm.isSpherical = True
         
     | 
| 
      
 55 
     | 
    
         
            +
                    tm.vertices = [
         
     | 
| 
      
 56 
     | 
    
         
            +
                        Translation3d(0.0, -diameter / 2.0, 0.0),
         
     | 
| 
      
 57 
     | 
    
         
            +
                        Translation3d(0.0, 0.0, -diameter / 2.0),
         
     | 
| 
      
 58 
     | 
    
         
            +
                        Translation3d(0.0, diameter / 2.0, 0.0),
         
     | 
| 
      
 59 
     | 
    
         
            +
                        Translation3d(0.0, 0.0, diameter / 2.0),
         
     | 
| 
      
 60 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    return tm
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 65 
     | 
    
         
            +
                def createArbitrary(cls, verts: List[Translation3d]) -> Self:
         
     | 
| 
      
 66 
     | 
    
         
            +
                    tm = cls()
         
     | 
| 
      
 67 
     | 
    
         
            +
                    tm._common_construction(verts)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    return tm
         
     | 
| 
       88 
70 
     | 
    
         | 
| 
      
 71 
     | 
    
         
            +
                def _common_construction(self, verts: List[Translation3d]) -> None:
         
     | 
| 
       89 
72 
     | 
    
         
             
                    self.isSpherical = False
         
     | 
| 
       90 
73 
     | 
    
         
             
                    if len(verts) <= 2:
         
     | 
| 
       91 
     | 
    
         
            -
                        self.vertices 
     | 
| 
      
 74 
     | 
    
         
            +
                        self.vertices = []
         
     | 
| 
       92 
75 
     | 
    
         
             
                        self.isPlanar = False
         
     | 
| 
       93 
76 
     | 
    
         
             
                    else:
         
     | 
| 
       94 
77 
     | 
    
         
             
                        cornersPlaner = True
         
     | 
| 
         @@ -105,7 +88,7 @@ class TargetModel: 
     | 
|
| 
       105 
88 
     | 
    
         
             
                    retVal = []
         
     | 
| 
       106 
89 
     | 
    
         | 
| 
       107 
90 
     | 
    
         
             
                    for vert in self.vertices:
         
     | 
| 
       108 
     | 
    
         
            -
                        retVal.append(basisChange. 
     | 
| 
      
 91 
     | 
    
         
            +
                        retVal.append(basisChange.applyTranslation(vert))
         
     | 
| 
       109 
92 
     | 
    
         | 
| 
       110 
93 
     | 
    
         
             
                    return retVal
         
     | 
| 
       111 
94 
     | 
    
         | 
| 
         @@ -130,8 +113,8 @@ class TargetModel: 
     | 
|
| 
       130 
113 
     | 
    
         | 
| 
       131 
114 
     | 
    
         
             
                @classmethod
         
     | 
| 
       132 
115 
     | 
    
         
             
                def AprilTag36h11(cls) -> Self:
         
     | 
| 
       133 
     | 
    
         
            -
                    return cls(width=6.5 * 0.0254, height=6.5 * 0.0254)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    return cls.createPlanar(width=6.5 * 0.0254, height=6.5 * 0.0254)
         
     | 
| 
       134 
117 
     | 
    
         | 
| 
       135 
118 
     | 
    
         
             
                @classmethod
         
     | 
| 
       136 
119 
     | 
    
         
             
                def AprilTag16h5(cls) -> Self:
         
     | 
| 
       137 
     | 
    
         
            -
                    return cls(width=6.0 * 0.0254, height=6.0 * 0.0254)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    return cls.createPlanar(width=6.0 * 0.0254, height=6.0 * 0.0254)
         
     | 
| 
         @@ -16,10 +16,10 @@ class VisionEstimation: 
     | 
|
| 
       16 
16 
     | 
    
         
             
                        id = tag.getFiducialId()
         
     | 
| 
       17 
17 
     | 
    
         
             
                        maybePose = layout.getTagPose(id)
         
     | 
| 
       18 
18 
     | 
    
         
             
                        if maybePose:
         
     | 
| 
       19 
     | 
    
         
            -
                             
     | 
| 
       20 
     | 
    
         
            -
                             
     | 
| 
       21 
     | 
    
         
            -
                             
     | 
| 
       22 
     | 
    
         
            -
                            retVal.append( 
     | 
| 
      
 19 
     | 
    
         
            +
                            aprilTag = AprilTag()
         
     | 
| 
      
 20 
     | 
    
         
            +
                            aprilTag.ID = id
         
     | 
| 
      
 21 
     | 
    
         
            +
                            aprilTag.pose = maybePose
         
     | 
| 
      
 22 
     | 
    
         
            +
                            retVal.append(aprilTag)
         
     | 
| 
       23 
23 
     | 
    
         
             
                    return retVal
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                @staticmethod
         
     | 
| 
         @@ -20,8 +20,14 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import MultiTargetPNPResult  # noqa
         
     | 
| 
      
 30 
     | 
    
         
            +
                from ..targeting import PnpResult  # noqa
         
     | 
| 
       25 
31 
     | 
    
         | 
| 
       26 
32 
     | 
    
         | 
| 
       27 
33 
     | 
    
         
             
            class MultiTargetPNPResultSerde:
         
     | 
| 
         @@ -20,8 +20,13 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import PhotonPipelineMetadata  # noqa
         
     | 
| 
       25 
30 
     | 
    
         | 
| 
       26 
31 
     | 
    
         | 
| 
       27 
32 
     | 
    
         
             
            class PhotonPipelineMetadataSerde:
         
     | 
| 
         @@ -20,8 +20,16 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import MultiTargetPNPResult  # noqa
         
     | 
| 
      
 30 
     | 
    
         
            +
                from ..targeting import PhotonPipelineMetadata  # noqa
         
     | 
| 
      
 31 
     | 
    
         
            +
                from ..targeting import PhotonPipelineResult  # noqa
         
     | 
| 
      
 32 
     | 
    
         
            +
                from ..targeting import PhotonTrackedTarget  # noqa
         
     | 
| 
       25 
33 
     | 
    
         | 
| 
       26 
34 
     | 
    
         | 
| 
       27 
35 
     | 
    
         
             
            class PhotonPipelineResultSerde:
         
     | 
| 
         @@ -20,8 +20,14 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import PhotonTrackedTarget  # noqa
         
     | 
| 
      
 30 
     | 
    
         
            +
                from ..targeting import TargetCorner  # noqa
         
     | 
| 
       25 
31 
     | 
    
         | 
| 
       26 
32 
     | 
    
         | 
| 
       27 
33 
     | 
    
         
             
            class PhotonTrackedTargetSerde:
         
     | 
| 
         @@ -20,8 +20,13 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import PnpResult  # noqa
         
     | 
| 
       25 
30 
     | 
    
         | 
| 
       26 
31 
     | 
    
         | 
| 
       27 
32 
     | 
    
         
             
            class PnpResultSerde:
         
     | 
| 
         @@ -20,8 +20,13 @@ 
     | 
|
| 
       20 
20 
     | 
    
         
             
            ##                        --> DO NOT MODIFY <--
         
     | 
| 
       21 
21 
     | 
    
         
             
            ###############################################################################
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            from typing import TYPE_CHECKING
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       23 
25 
     | 
    
         
             
            from ..packet import Packet
         
     | 
| 
       24 
     | 
    
         
            -
            from ..targeting import *
         
     | 
| 
      
 26 
     | 
    
         
            +
            from ..targeting import *  # noqa
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            if TYPE_CHECKING:
         
     | 
| 
      
 29 
     | 
    
         
            +
                from ..targeting import TargetCorner  # noqa
         
     | 
| 
       25 
30 
     | 
    
         | 
| 
       26 
31 
     | 
    
         | 
| 
       27 
32 
     | 
    
         
             
            class TargetCornerSerde:
         
     | 
| 
         @@ -10,8 +10,10 @@ PhotonPipelineResult_TYPE_STRING = ( 
     | 
|
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            class NTTopicSet:
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                def __init__(self) -> None:
         
     | 
| 
       14 
     | 
    
         
            -
                     
     | 
| 
      
 13 
     | 
    
         
            +
                def __init__(self, tableName: str, cameraName: str) -> None:
         
     | 
| 
      
 14 
     | 
    
         
            +
                    instance = nt.NetworkTableInstance.getDefault()
         
     | 
| 
      
 15 
     | 
    
         
            +
                    photonvision_root_table = instance.getTable(tableName)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.subTable = photonvision_root_table.getSubTable(cameraName)
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
       16 
18 
     | 
    
         
             
                def updateEntries(self) -> None:
         
     | 
| 
       17 
19 
     | 
    
         
             
                    options = nt.PubSubOptions()
         
     | 
    
        photonlibpy/photonCamera.py
    CHANGED
    
    | 
         @@ -231,7 +231,7 @@ class PhotonCamera: 
     | 
|
| 
       231 
231 
     | 
    
         
             
                    versionString = self.versionEntry.get(defaultValue="")
         
     | 
| 
       232 
232 
     | 
    
         
             
                    localUUID = PhotonPipelineResult.photonStruct.MESSAGE_VERSION
         
     | 
| 
       233 
233 
     | 
    
         | 
| 
       234 
     | 
    
         
            -
                    remoteUUID = self._rawBytesEntry.getTopic().getProperty("message_uuid")
         
     | 
| 
      
 234 
     | 
    
         
            +
                    remoteUUID = str(self._rawBytesEntry.getTopic().getProperty("message_uuid"))
         
     | 
| 
       235 
235 
     | 
    
         | 
| 
       236 
236 
     | 
    
         
             
                    if not remoteUUID:
         
     | 
| 
       237 
237 
     | 
    
         
             
                        wpilib.reportWarning(
         
     | 
| 
         @@ -4,8 +4,8 @@ import typing 
     | 
|
| 
       4 
4 
     | 
    
         
             
            import cscore as cs
         
     | 
| 
       5 
5 
     | 
    
         
             
            import cv2 as cv
         
     | 
| 
       6 
6 
     | 
    
         
             
            import numpy as np
         
     | 
| 
       7 
     | 
    
         
            -
            import robotpy_apriltag
         
     | 
| 
       8 
7 
     | 
    
         
             
            import wpilib
         
     | 
| 
      
 8 
     | 
    
         
            +
            from robotpy_apriltag import AprilTagField, AprilTagFieldLayout
         
     | 
| 
       9 
9 
     | 
    
         
             
            from wpimath.geometry import Pose3d, Transform3d
         
     | 
| 
       10 
10 
     | 
    
         
             
            from wpimath.units import meters, seconds
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -31,7 +31,7 @@ class PhotonCameraSim: 
     | 
|
| 
       31 
31 
     | 
    
         
             
                def __init__(
         
     | 
| 
       32 
32 
     | 
    
         
             
                    self,
         
     | 
| 
       33 
33 
     | 
    
         
             
                    camera: PhotonCamera,
         
     | 
| 
       34 
     | 
    
         
            -
                    props: SimCameraProperties  
     | 
| 
      
 34 
     | 
    
         
            +
                    props: SimCameraProperties = SimCameraProperties.PERFECT_90DEG(),
         
     | 
| 
       35 
35 
     | 
    
         
             
                    minTargetAreaPercent: float | None = None,
         
     | 
| 
       36 
36 
     | 
    
         
             
                    maxSightRange: meters | None = None,
         
     | 
| 
       37 
37 
     | 
    
         
             
                ):
         
     | 
| 
         @@ -41,37 +41,12 @@ class PhotonCameraSim: 
     | 
|
| 
       41 
41 
     | 
    
         
             
                    self.videoSimRawEnabled: bool = False
         
     | 
| 
       42 
42 
     | 
    
         
             
                    self.videoSimWireframeEnabled: bool = False
         
     | 
| 
       43 
43 
     | 
    
         
             
                    self.videoSimWireframeResolution: float = 0.1
         
     | 
| 
       44 
     | 
    
         
            -
                    self.videoSimProcEnabled: bool =  
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                    self.videoSimProcEnabled: bool = (
         
     | 
| 
      
 45 
     | 
    
         
            +
                        False  # TODO switch this back to default True when the functionality is enabled
         
     | 
| 
      
 46 
     | 
    
         
            +
                    )
         
     | 
| 
       46 
47 
     | 
    
         
             
                    self.heartbeatCounter: int = 0
         
     | 
| 
       47 
48 
     | 
    
         
             
                    self.nextNtEntryTime = int(wpilib.Timer.getFPGATimestamp() * 1e6)
         
     | 
| 
       48 
     | 
    
         
            -
                    self.tagLayout =  
     | 
| 
       49 
     | 
    
         
            -
                        robotpy_apriltag.AprilTagField.k2024Crescendo
         
     | 
| 
       50 
     | 
    
         
            -
                    )
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                    if (
         
     | 
| 
       53 
     | 
    
         
            -
                        camera is not None
         
     | 
| 
       54 
     | 
    
         
            -
                        and props is None
         
     | 
| 
       55 
     | 
    
         
            -
                        and minTargetAreaPercent is None
         
     | 
| 
       56 
     | 
    
         
            -
                        and maxSightRange is None
         
     | 
| 
       57 
     | 
    
         
            -
                    ):
         
     | 
| 
       58 
     | 
    
         
            -
                        props = SimCameraProperties.PERFECT_90DEG()
         
     | 
| 
       59 
     | 
    
         
            -
                    elif (
         
     | 
| 
       60 
     | 
    
         
            -
                        camera is not None
         
     | 
| 
       61 
     | 
    
         
            -
                        and props is not None
         
     | 
| 
       62 
     | 
    
         
            -
                        and minTargetAreaPercent is not None
         
     | 
| 
       63 
     | 
    
         
            -
                        and maxSightRange is not None
         
     | 
| 
       64 
     | 
    
         
            -
                    ):
         
     | 
| 
       65 
     | 
    
         
            -
                        pass
         
     | 
| 
       66 
     | 
    
         
            -
                    elif (
         
     | 
| 
       67 
     | 
    
         
            -
                        camera is not None
         
     | 
| 
       68 
     | 
    
         
            -
                        and props is not None
         
     | 
| 
       69 
     | 
    
         
            -
                        and minTargetAreaPercent is None
         
     | 
| 
       70 
     | 
    
         
            -
                        and maxSightRange is None
         
     | 
| 
       71 
     | 
    
         
            -
                    ):
         
     | 
| 
       72 
     | 
    
         
            -
                        pass
         
     | 
| 
       73 
     | 
    
         
            -
                    else:
         
     | 
| 
       74 
     | 
    
         
            -
                        raise Exception("Invalid Constructor Called")
         
     | 
| 
      
 49 
     | 
    
         
            +
                    self.tagLayout = AprilTagFieldLayout.loadField(AprilTagField.k2024Crescendo)
         
     | 
| 
       75 
50 
     | 
    
         | 
| 
       76 
51 
     | 
    
         
             
                    self.cam = camera
         
     | 
| 
       77 
52 
     | 
    
         
             
                    self.prop = props
         
     | 
| 
         @@ -101,16 +76,11 @@ class PhotonCameraSim: 
     | 
|
| 
       101 
76 
     | 
    
         
             
                        (self.prop.getResWidth(), self.prop.getResHeight())
         
     | 
| 
       102 
77 
     | 
    
         
             
                    )
         
     | 
| 
       103 
78 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
                    self.ts 
     | 
| 
      
 79 
     | 
    
         
            +
                    self.ts = NTTopicSet("photonvision", self.cam.getName())
         
     | 
| 
       105 
80 
     | 
    
         
             
                    self.ts.updateEntries()
         
     | 
| 
       106 
81 
     | 
    
         | 
| 
       107 
82 
     | 
    
         
             
                    # Handle this last explicitly for this function signature because the other constructor is called in the initialiser list
         
     | 
| 
       108 
     | 
    
         
            -
                    if  
     | 
| 
       109 
     | 
    
         
            -
                        camera is not None
         
     | 
| 
       110 
     | 
    
         
            -
                        and props is not None
         
     | 
| 
       111 
     | 
    
         
            -
                        and minTargetAreaPercent is not None
         
     | 
| 
       112 
     | 
    
         
            -
                        and maxSightRange is not None
         
     | 
| 
       113 
     | 
    
         
            -
                    ):
         
     | 
| 
      
 83 
     | 
    
         
            +
                    if minTargetAreaPercent is not None and maxSightRange is not None:
         
     | 
| 
       114 
84 
     | 
    
         
             
                        self.minTargetAreaPercent = minTargetAreaPercent
         
     | 
| 
       115 
85 
     | 
    
         
             
                        self.maxSightRange = maxSightRange
         
     | 
| 
       116 
86 
     | 
    
         | 
| 
         @@ -194,19 +164,19 @@ class PhotonCameraSim: 
     | 
|
| 
       194 
164 
     | 
    
         
             
                    self.maxSightRange = range
         
     | 
| 
       195 
165 
     | 
    
         | 
| 
       196 
166 
     | 
    
         
             
                def enableRawStream(self, enabled: bool) -> None:
         
     | 
| 
      
 167 
     | 
    
         
            +
                    self.videoSimRawEnabled = enabled
         
     | 
| 
       197 
168 
     | 
    
         
             
                    raise Exception("Raw stream not implemented")
         
     | 
| 
       198 
     | 
    
         
            -
                    # self.videoSimRawEnabled = enabled
         
     | 
| 
       199 
169 
     | 
    
         | 
| 
       200 
170 
     | 
    
         
             
                def enableDrawWireframe(self, enabled: bool) -> None:
         
     | 
| 
      
 171 
     | 
    
         
            +
                    self.videoSimWireframeEnabled = enabled
         
     | 
| 
       201 
172 
     | 
    
         
             
                    raise Exception("Wireframe not implemented")
         
     | 
| 
       202 
     | 
    
         
            -
                    # self.videoSimWireframeEnabled = enabled
         
     | 
| 
       203 
173 
     | 
    
         | 
| 
       204 
174 
     | 
    
         
             
                def setWireframeResolution(self, resolution: float) -> None:
         
     | 
| 
       205 
175 
     | 
    
         
             
                    self.videoSimWireframeResolution = resolution
         
     | 
| 
       206 
176 
     | 
    
         | 
| 
       207 
177 
     | 
    
         
             
                def enableProcessedStream(self, enabled: bool) -> None:
         
     | 
| 
      
 178 
     | 
    
         
            +
                    self.videoSimProcEnabled = enabled
         
     | 
| 
       208 
179 
     | 
    
         
             
                    raise Exception("Processed stream not implemented")
         
     | 
| 
       209 
     | 
    
         
            -
                    # self.videoSimProcEnabled = enabled
         
     | 
| 
       210 
180 
     | 
    
         | 
| 
       211 
181 
     | 
    
         
             
                def process(
         
     | 
| 
       212 
182 
     | 
    
         
             
                    self, latency: seconds, cameraPose: Pose3d, targets: list[VisionTargetSim]
         
     | 
| 
         @@ -217,9 +187,7 @@ class PhotonCameraSim: 
     | 
|
| 
       217 
187 
     | 
    
         | 
| 
       218 
188 
     | 
    
         
             
                    targets.sort(key=distance, reverse=True)
         
     | 
| 
       219 
189 
     | 
    
         | 
| 
       220 
     | 
    
         
            -
                    visibleTgts: list[
         
     | 
| 
       221 
     | 
    
         
            -
                        typing.Tuple[VisionTargetSim, list[typing.Tuple[float, float]]]
         
     | 
| 
       222 
     | 
    
         
            -
                    ] = []
         
     | 
| 
      
 190 
     | 
    
         
            +
                    visibleTgts: list[typing.Tuple[VisionTargetSim, np.ndarray]] = []
         
     | 
| 
       223 
191 
     | 
    
         
             
                    detectableTgts: list[PhotonTrackedTarget] = []
         
     | 
| 
       224 
192 
     | 
    
         | 
| 
       225 
193 
     | 
    
         
             
                    camRt = RotTrlTransform3d.makeRelativeTo(cameraPose)
         
     | 
| 
         @@ -258,6 +226,7 @@ class PhotonCameraSim: 
     | 
|
| 
       258 
226 
     | 
    
         
             
                            ] * 4
         
     | 
| 
       259 
227 
     | 
    
         
             
                            t = (l + 1) % 4
         
     | 
| 
       260 
228 
     | 
    
         
             
                            b = (l + 1) % 4
         
     | 
| 
      
 229 
     | 
    
         
            +
                            r = 0
         
     | 
| 
       261 
230 
     | 
    
         
             
                            for i in range(4):
         
     | 
| 
       262 
231 
     | 
    
         
             
                                if i == l:
         
     | 
| 
       263 
232 
     | 
    
         
             
                                    continue
         
     | 
| 
         @@ -271,14 +240,14 @@ class PhotonCameraSim: 
     | 
|
| 
       271 
240 
     | 
    
         
             
                                if i != t and i != l and i != b:
         
     | 
| 
       272 
241 
     | 
    
         
             
                                    r = i
         
     | 
| 
       273 
242 
     | 
    
         
             
                            rect = cv.RotatedRect(
         
     | 
| 
       274 
     | 
    
         
            -
                                center,
         
     | 
| 
      
 243 
     | 
    
         
            +
                                (center[0, 0], center[0, 1]),
         
     | 
| 
       275 
244 
     | 
    
         
             
                                (
         
     | 
| 
       276 
245 
     | 
    
         
             
                                    imagePoints[r, 0, 0] - lc[0, 0],
         
     | 
| 
       277 
246 
     | 
    
         
             
                                    imagePoints[b, 0, 1] - imagePoints[t, 0, 1],
         
     | 
| 
       278 
247 
     | 
    
         
             
                                ),
         
     | 
| 
       279 
248 
     | 
    
         
             
                                -angles[r],
         
     | 
| 
       280 
249 
     | 
    
         
             
                            )
         
     | 
| 
       281 
     | 
    
         
            -
                            imagePoints = rect.points()
         
     | 
| 
      
 250 
     | 
    
         
            +
                            imagePoints = np.array([[p[0], p[1], p[2]] for p in rect.points()])
         
     | 
| 
       282 
251 
     | 
    
         | 
| 
       283 
252 
     | 
    
         
             
                        visibleTgts.append((tgt, imagePoints))
         
     | 
| 
       284 
253 
     | 
    
         
             
                        noisyTargetCorners = self.prop.estPixelNoise(imagePoints)
         
     | 
| 
         @@ -325,13 +294,13 @@ class PhotonCameraSim: 
     | 
|
| 
       325 
294 
     | 
    
         
             
                        )
         
     | 
| 
       326 
295 
     | 
    
         | 
| 
       327 
296 
     | 
    
         
             
                    # Video streams disabled for now
         
     | 
| 
       328 
     | 
    
         
            -
                    if self. 
     | 
| 
      
 297 
     | 
    
         
            +
                    if self.videoSimRawEnabled:
         
     | 
| 
       329 
298 
     | 
    
         
             
                        # VideoSimUtil::UpdateVideoProp(videoSimRaw, prop);
         
     | 
| 
       330 
299 
     | 
    
         
             
                        # cv::Size videoFrameSize{prop.GetResWidth(), prop.GetResHeight()};
         
     | 
| 
       331 
300 
     | 
    
         
             
                        # cv::Mat blankFrame = cv::Mat::zeros(videoFrameSize, CV_8UC1);
         
     | 
| 
       332 
301 
     | 
    
         
             
                        # blankFrame.assignTo(videoSimFrameRaw);
         
     | 
| 
       333 
302 
     | 
    
         
             
                        pass
         
     | 
| 
       334 
     | 
    
         
            -
                    if self. 
     | 
| 
      
 303 
     | 
    
         
            +
                    if self.videoSimProcEnabled:
         
     | 
| 
       335 
304 
     | 
    
         
             
                        # VideoSimUtil::UpdateVideoProp(videoSimProcessed, prop);
         
     | 
| 
       336 
305 
     | 
    
         
             
                        pass
         
     | 
| 
       337 
306 
     | 
    
         | 
| 
         @@ -385,6 +354,7 @@ class PhotonCameraSim: 
     | 
|
| 
       385 
354 
     | 
    
         
             
                        self.ts.targetSkewEntry.set(0.0, receiveTimestamp)
         
     | 
| 
       386 
355 
     | 
    
         
             
                    else:
         
     | 
| 
       387 
356 
     | 
    
         
             
                        bestTarget = result.getBestTarget()
         
     | 
| 
      
 357 
     | 
    
         
            +
                        assert bestTarget
         
     | 
| 
       388 
358 
     | 
    
         | 
| 
       389 
359 
     | 
    
         
             
                        self.ts.targetPitchEntry.set(bestTarget.getPitch(), receiveTimestamp)
         
     | 
| 
       390 
360 
     | 
    
         
             
                        self.ts.targetYawEntry.set(bestTarget.getYaw(), receiveTimestamp)
         
     | 
| 
         @@ -11,7 +11,7 @@ from ..estimation import RotTrlTransform3d 
     | 
|
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            class SimCameraProperties:
         
     | 
| 
       14 
     | 
    
         
            -
                def __init__(self 
     | 
| 
      
 14 
     | 
    
         
            +
                def __init__(self):
         
     | 
| 
       15 
15 
     | 
    
         
             
                    self.resWidth: int = -1
         
     | 
| 
       16 
16 
     | 
    
         
             
                    self.resHeight: int = -1
         
     | 
| 
       17 
17 
     | 
    
         
             
                    self.camIntrinsics: np.ndarray = np.zeros((3, 3))  # [3,3]
         
     | 
| 
         @@ -24,57 +24,41 @@ class SimCameraProperties: 
     | 
|
| 
       24 
24 
     | 
    
         
             
                    self.latencyStdDev: seconds = 0.0
         
     | 
| 
       25 
25 
     | 
    
         
             
                    self.viewplanes: list[np.ndarray] = []  # [3,1]
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                     
     | 
| 
       28 
     | 
    
         
            -
                        self.setCalibration(960, 720, fovDiag=Rotation2d(math.radians(90.0)))
         
     | 
| 
       29 
     | 
    
         
            -
                    else:
         
     | 
| 
       30 
     | 
    
         
            -
                        raise Exception("not yet implemented")
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                def setCalibration(
         
     | 
| 
       33 
     | 
    
         
            -
                    self,
         
     | 
| 
       34 
     | 
    
         
            -
                    width: int,
         
     | 
| 
       35 
     | 
    
         
            -
                    height: int,
         
     | 
| 
       36 
     | 
    
         
            -
                    *,
         
     | 
| 
       37 
     | 
    
         
            -
                    fovDiag: Rotation2d | None = None,
         
     | 
| 
       38 
     | 
    
         
            -
                    newCamIntrinsics: np.ndarray | None = None,
         
     | 
| 
       39 
     | 
    
         
            -
                    newDistCoeffs: np.ndarray | None = None,
         
     | 
| 
       40 
     | 
    
         
            -
                ):
         
     | 
| 
       41 
     | 
    
         
            -
                    # Should be an inverted XOR on the args to differentiate between the signatures
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                    has_fov_args = fovDiag is not None
         
     | 
| 
       44 
     | 
    
         
            -
                    has_matrix_args = newCamIntrinsics is not None and newDistCoeffs is not None
         
     | 
| 
      
 27 
     | 
    
         
            +
                    self.setCalibrationFromFOV(960, 720, fovDiag=Rotation2d(math.radians(90.0)))
         
     | 
| 
       45 
28 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
                def setCalibrationFromFOV(
         
     | 
| 
      
 30 
     | 
    
         
            +
                    self, width: int, height: int, fovDiag: Rotation2d
         
     | 
| 
      
 31 
     | 
    
         
            +
                ) -> None:
         
     | 
| 
      
 32 
     | 
    
         
            +
                    if fovDiag.degrees() < 1.0 or fovDiag.degrees() > 179.0:
         
     | 
| 
      
 33 
     | 
    
         
            +
                        fovDiag = Rotation2d.fromDegrees(max(min(fovDiag.degrees(), 179.0), 1.0))
         
     | 
| 
      
 34 
     | 
    
         
            +
                        logging.error("Requested invalid FOV! Clamping between (1, 179) degrees...")
         
     | 
| 
       50 
35 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                     
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                            )
         
     | 
| 
       56 
     | 
    
         
            -
                            logging.error(
         
     | 
| 
       57 
     | 
    
         
            -
                                "Requested invalid FOV! Clamping between (1, 179) degrees..."
         
     | 
| 
       58 
     | 
    
         
            -
                            )
         
     | 
| 
      
 36 
     | 
    
         
            +
                    resDiag = math.sqrt(width * width + height * height)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    diagRatio = math.tan(fovDiag.radians() / 2.0)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    fovWidth = Rotation2d(math.atan((diagRatio * (width / resDiag)) * 2))
         
     | 
| 
      
 39 
     | 
    
         
            +
                    fovHeight = Rotation2d(math.atan(diagRatio * (height / resDiag)) * 2)
         
     | 
| 
       59 
40 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                        diagRatio = math.tan(fovDiag.radians() / 2.0)
         
     | 
| 
       62 
     | 
    
         
            -
                        fovWidth = Rotation2d(math.atan((diagRatio * (width / resDiag)) * 2))
         
     | 
| 
       63 
     | 
    
         
            -
                        fovHeight = Rotation2d(math.atan(diagRatio * (height / resDiag)) * 2)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    newDistCoeffs = np.zeros((8, 1))
         
     | 
| 
       64 
42 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
                    cx = width / 2.0 - 0.5
         
     | 
| 
      
 44 
     | 
    
         
            +
                    cy = height / 2.0 - 0.5
         
     | 
| 
       66 
45 
     | 
    
         | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
      
 46 
     | 
    
         
            +
                    fx = cx / math.tan(fovWidth.radians() / 2.0)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    fy = cy / math.tan(fovHeight.radians() / 2.0)
         
     | 
| 
       69 
48 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                        fy = cy / math.tan(fovHeight.radians() / 2.0)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    newCamIntrinsics = np.array([[fx, 0.0, cx], [0.0, fy, cy], [0.0, 0.0, 1.0]])
         
     | 
| 
       72 
50 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
      
 51 
     | 
    
         
            +
                    self.setCalibrationFromIntrinsics(
         
     | 
| 
      
 52 
     | 
    
         
            +
                        width, height, newCamIntrinsics, newDistCoeffs
         
     | 
| 
      
 53 
     | 
    
         
            +
                    )
         
     | 
| 
       74 
54 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                     
     | 
| 
       77 
     | 
    
         
            -
                     
     | 
| 
      
 55 
     | 
    
         
            +
                def setCalibrationFromIntrinsics(
         
     | 
| 
      
 56 
     | 
    
         
            +
                    self,
         
     | 
| 
      
 57 
     | 
    
         
            +
                    width: int,
         
     | 
| 
      
 58 
     | 
    
         
            +
                    height: int,
         
     | 
| 
      
 59 
     | 
    
         
            +
                    newCamIntrinsics: np.ndarray,
         
     | 
| 
      
 60 
     | 
    
         
            +
                    newDistCoeffs: np.ndarray,
         
     | 
| 
      
 61 
     | 
    
         
            +
                ) -> None:
         
     | 
| 
       78 
62 
     | 
    
         | 
| 
       79 
63 
     | 
    
         
             
                    self.resWidth = width
         
     | 
| 
       80 
64 
     | 
    
         
             
                    self.resHeight = height
         
     | 
| 
         @@ -171,10 +155,8 @@ class SimCameraProperties: 
     | 
|
| 
       171 
155 
     | 
    
         
             
                def getLatencyStdDev(self) -> seconds:
         
     | 
| 
       172 
156 
     | 
    
         
             
                    return self.latencyStdDev
         
     | 
| 
       173 
157 
     | 
    
         | 
| 
       174 
     | 
    
         
            -
                def getContourAreaPercent(self, points:  
     | 
| 
       175 
     | 
    
         
            -
                    return (
         
     | 
| 
       176 
     | 
    
         
            -
                        cv.contourArea(cv.convexHull(np.array(points))) / self.getResArea() * 100.0
         
     | 
| 
       177 
     | 
    
         
            -
                    )
         
     | 
| 
      
 158 
     | 
    
         
            +
                def getContourAreaPercent(self, points: np.ndarray) -> float:
         
     | 
| 
      
 159 
     | 
    
         
            +
                    return cv.contourArea(cv.convexHull(points)) / self.getResArea() * 100.0
         
     | 
| 
       178 
160 
     | 
    
         | 
| 
       179 
161 
     | 
    
         
             
                def getPixelYaw(self, pixelX: float) -> Rotation2d:
         
     | 
| 
       180 
162 
     | 
    
         
             
                    fx = self.camIntrinsics[0, 0]
         
     | 
| 
         @@ -188,14 +170,14 @@ class SimCameraProperties: 
     | 
|
| 
       188 
170 
     | 
    
         
             
                    yOffset = cy - pixelY
         
     | 
| 
       189 
171 
     | 
    
         
             
                    return Rotation2d(fy, -yOffset)
         
     | 
| 
       190 
172 
     | 
    
         | 
| 
       191 
     | 
    
         
            -
                def getPixelRot(self, point: typing. 
     | 
| 
      
 173 
     | 
    
         
            +
                def getPixelRot(self, point: cv.typing.Point2f) -> Rotation3d:
         
     | 
| 
       192 
174 
     | 
    
         
             
                    return Rotation3d(
         
     | 
| 
       193 
175 
     | 
    
         
             
                        0.0,
         
     | 
| 
       194 
176 
     | 
    
         
             
                        self.getPixelPitch(point[1]).radians(),
         
     | 
| 
       195 
177 
     | 
    
         
             
                        self.getPixelYaw(point[0]).radians(),
         
     | 
| 
       196 
178 
     | 
    
         
             
                    )
         
     | 
| 
       197 
179 
     | 
    
         | 
| 
       198 
     | 
    
         
            -
                def getCorrectedPixelRot(self, point: typing. 
     | 
| 
      
 180 
     | 
    
         
            +
                def getCorrectedPixelRot(self, point: cv.typing.Point2f) -> Rotation3d:
         
     | 
| 
       199 
181 
     | 
    
         
             
                    fx = self.camIntrinsics[0, 0]
         
     | 
| 
       200 
182 
     | 
    
         
             
                    cx = self.camIntrinsics[0, 2]
         
     | 
| 
       201 
183 
     | 
    
         
             
                    xOffset = cx - point[0]
         
     | 
| 
         @@ -226,8 +208,8 @@ class SimCameraProperties: 
     | 
|
| 
       226 
208 
     | 
    
         
             
                def getVisibleLine(
         
     | 
| 
       227 
209 
     | 
    
         
             
                    self, camRt: RotTrlTransform3d, a: Translation3d, b: Translation3d
         
     | 
| 
       228 
210 
     | 
    
         
             
                ) -> typing.Tuple[float | None, float | None]:
         
     | 
| 
       229 
     | 
    
         
            -
                    relA = camRt. 
     | 
| 
       230 
     | 
    
         
            -
                    relB = camRt. 
     | 
| 
      
 211 
     | 
    
         
            +
                    relA = camRt.applyTranslation(a)
         
     | 
| 
      
 212 
     | 
    
         
            +
                    relB = camRt.applyTranslation(b)
         
     | 
| 
       231 
213 
     | 
    
         | 
| 
       232 
214 
     | 
    
         
             
                    if relA.X() <= 0.0 and relB.X() <= 0.0:
         
     | 
| 
       233 
215 
     | 
    
         
             
                        return (None, None)
         
     | 
| 
         @@ -279,7 +261,7 @@ class SimCameraProperties: 
     | 
|
| 
       279 
261 
     | 
    
         
             
                                ipts[i] = None
         
     | 
| 
       280 
262 
     | 
    
         
             
                                break
         
     | 
| 
       281 
263 
     | 
    
         | 
| 
       282 
     | 
    
         
            -
                        if  
     | 
| 
      
 264 
     | 
    
         
            +
                        if ipts[i] is None:
         
     | 
| 
       283 
265 
     | 
    
         
             
                            continue
         
     | 
| 
       284 
266 
     | 
    
         | 
| 
       285 
267 
     | 
    
         
             
                        for j in range(i - 1, 0 - 1):
         
     | 
| 
         @@ -357,7 +339,7 @@ class SimCameraProperties: 
     | 
|
| 
       357 
339 
     | 
    
         
             
                @classmethod
         
     | 
| 
       358 
340 
     | 
    
         
             
                def PI4_LIFECAM_320_240(cls) -> typing.Self:
         
     | 
| 
       359 
341 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       360 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 342 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       361 
343 
     | 
    
         
             
                        320,
         
     | 
| 
       362 
344 
     | 
    
         
             
                        240,
         
     | 
| 
       363 
345 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -391,7 +373,7 @@ class SimCameraProperties: 
     | 
|
| 
       391 
373 
     | 
    
         
             
                @classmethod
         
     | 
| 
       392 
374 
     | 
    
         
             
                def PI4_LIFECAM_640_480(cls) -> typing.Self:
         
     | 
| 
       393 
375 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       394 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 376 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       395 
377 
     | 
    
         
             
                        640,
         
     | 
| 
       396 
378 
     | 
    
         
             
                        480,
         
     | 
| 
       397 
379 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -425,7 +407,7 @@ class SimCameraProperties: 
     | 
|
| 
       425 
407 
     | 
    
         
             
                @classmethod
         
     | 
| 
       426 
408 
     | 
    
         
             
                def LL2_640_480(cls) -> typing.Self:
         
     | 
| 
       427 
409 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       428 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 410 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       429 
411 
     | 
    
         
             
                        640,
         
     | 
| 
       430 
412 
     | 
    
         
             
                        480,
         
     | 
| 
       431 
413 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -459,7 +441,7 @@ class SimCameraProperties: 
     | 
|
| 
       459 
441 
     | 
    
         
             
                @classmethod
         
     | 
| 
       460 
442 
     | 
    
         
             
                def LL2_960_720(cls) -> typing.Self:
         
     | 
| 
       461 
443 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       462 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 444 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       463 
445 
     | 
    
         
             
                        960,
         
     | 
| 
       464 
446 
     | 
    
         
             
                        720,
         
     | 
| 
       465 
447 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -493,7 +475,7 @@ class SimCameraProperties: 
     | 
|
| 
       493 
475 
     | 
    
         
             
                @classmethod
         
     | 
| 
       494 
476 
     | 
    
         
             
                def LL2_1280_720(cls) -> typing.Self:
         
     | 
| 
       495 
477 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       496 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 478 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       497 
479 
     | 
    
         
             
                        1280,
         
     | 
| 
       498 
480 
     | 
    
         
             
                        720,
         
     | 
| 
       499 
481 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -527,7 +509,7 @@ class SimCameraProperties: 
     | 
|
| 
       527 
509 
     | 
    
         
             
                @classmethod
         
     | 
| 
       528 
510 
     | 
    
         
             
                def OV9281_640_480(cls) -> typing.Self:
         
     | 
| 
       529 
511 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       530 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 512 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       531 
513 
     | 
    
         
             
                        640,
         
     | 
| 
       532 
514 
     | 
    
         
             
                        480,
         
     | 
| 
       533 
515 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -561,7 +543,7 @@ class SimCameraProperties: 
     | 
|
| 
       561 
543 
     | 
    
         
             
                @classmethod
         
     | 
| 
       562 
544 
     | 
    
         
             
                def OV9281_800_600(cls) -> typing.Self:
         
     | 
| 
       563 
545 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       564 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 546 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       565 
547 
     | 
    
         
             
                        800,
         
     | 
| 
       566 
548 
     | 
    
         
             
                        600,
         
     | 
| 
       567 
549 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -595,7 +577,7 @@ class SimCameraProperties: 
     | 
|
| 
       595 
577 
     | 
    
         
             
                @classmethod
         
     | 
| 
       596 
578 
     | 
    
         
             
                def OV9281_1280_720(cls) -> typing.Self:
         
     | 
| 
       597 
579 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       598 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 580 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       599 
581 
     | 
    
         
             
                        1280,
         
     | 
| 
       600 
582 
     | 
    
         
             
                        720,
         
     | 
| 
       601 
583 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -629,7 +611,7 @@ class SimCameraProperties: 
     | 
|
| 
       629 
611 
     | 
    
         
             
                @classmethod
         
     | 
| 
       630 
612 
     | 
    
         
             
                def OV9281_1920_1080(cls) -> typing.Self:
         
     | 
| 
       631 
613 
     | 
    
         
             
                    prop = cls()
         
     | 
| 
       632 
     | 
    
         
            -
                    prop. 
     | 
| 
      
 614 
     | 
    
         
            +
                    prop.setCalibrationFromIntrinsics(
         
     | 
| 
       633 
615 
     | 
    
         
             
                        1920,
         
     | 
| 
       634 
616 
     | 
    
         
             
                        1080,
         
     | 
| 
       635 
617 
     | 
    
         
             
                        newCamIntrinsics=np.array(
         
     | 
| 
         @@ -84,7 +84,11 @@ class VisionSystemSim: 
     | 
|
| 
       84 
84 
     | 
    
         
             
                    if robotToCamera is None:
         
     | 
| 
       85 
85 
     | 
    
         
             
                        return None
         
     | 
| 
       86 
86 
     | 
    
         
             
                    else:
         
     | 
| 
       87 
     | 
    
         
            -
                         
     | 
| 
      
 87 
     | 
    
         
            +
                        pose = self.getRobotPose(time)
         
     | 
| 
      
 88 
     | 
    
         
            +
                        if pose:
         
     | 
| 
      
 89 
     | 
    
         
            +
                            return pose + robotToCamera
         
     | 
| 
      
 90 
     | 
    
         
            +
                        else:
         
     | 
| 
      
 91 
     | 
    
         
            +
                            return None
         
     | 
| 
       88 
92 
     | 
    
         | 
| 
       89 
93 
     | 
    
         
             
                def adjustCamera(
         
     | 
| 
       90 
94 
     | 
    
         
             
                    self, cameraSim: PhotonCameraSim, robotToCamera: Transform3d
         
     | 
| 
         @@ -167,7 +171,7 @@ class VisionSystemSim: 
     | 
|
| 
       167 
171 
     | 
    
         | 
| 
       168 
172 
     | 
    
         
             
                def getRobotPose(
         
     | 
| 
       169 
173 
     | 
    
         
             
                    self, timestamp: seconds = wpilib.Timer.getFPGATimestamp()
         
     | 
| 
       170 
     | 
    
         
            -
                ) -> Pose3d:
         
     | 
| 
      
 174 
     | 
    
         
            +
                ) -> Pose3d | None:
         
     | 
| 
       171 
175 
     | 
    
         
             
                    return self.robotPoseBuffer.sample(timestamp)
         
     | 
| 
       172 
176 
     | 
    
         | 
| 
       173 
177 
     | 
    
         
             
                def resetRobotPose(self, robotPose: Pose2d | Pose3d) -> None:
         
     | 
| 
         @@ -216,15 +220,16 @@ class VisionSystemSim: 
     | 
|
| 
       216 
220 
     | 
    
         
             
                        timestampCapture = timestampNt * 1.0e-6 - latency
         
     | 
| 
       217 
221 
     | 
    
         | 
| 
       218 
222 
     | 
    
         
             
                        lateRobotPose = self.getRobotPose(timestampCapture)
         
     | 
| 
       219 
     | 
    
         
            -
                         
     | 
| 
       220 
     | 
    
         
            -
             
     | 
| 
       221 
     | 
    
         
            -
             
     | 
| 
      
 223 
     | 
    
         
            +
                        robotToCamera = self.getRobotToCamera(camSim, timestampCapture)
         
     | 
| 
      
 224 
     | 
    
         
            +
                        if lateRobotPose is None or robotToCamera is None:
         
     | 
| 
      
 225 
     | 
    
         
            +
                            return None
         
     | 
| 
      
 226 
     | 
    
         
            +
                        lateCameraPose = lateRobotPose + robotToCamera
         
     | 
| 
       222 
227 
     | 
    
         
             
                        cameraPoses2d.append(lateCameraPose.toPose2d())
         
     | 
| 
       223 
228 
     | 
    
         | 
| 
       224 
229 
     | 
    
         
             
                        camResult = camSim.process(latency, lateCameraPose, allTargets)
         
     | 
| 
       225 
230 
     | 
    
         
             
                        camSim.submitProcessedFrame(camResult, timestampNt)
         
     | 
| 
       226 
     | 
    
         
            -
                        for  
     | 
| 
       227 
     | 
    
         
            -
                            trf =  
     | 
| 
      
 231 
     | 
    
         
            +
                        for tgt in camResult.getTargets():
         
     | 
| 
      
 232 
     | 
    
         
            +
                            trf = tgt.getBestCameraToTarget()
         
     | 
| 
       228 
233 
     | 
    
         
             
                            if trf == Transform3d():
         
     | 
| 
       229 
234 
     | 
    
         
             
                                continue
         
     | 
| 
       230 
235 
     | 
    
         | 
| 
         @@ -2,7 +2,7 @@ from dataclasses import dataclass 
     | 
|
| 
       2 
2 
     | 
    
         
             
            from typing import TYPE_CHECKING, ClassVar
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       5 
     | 
    
         
            -
                from .. import  
     | 
| 
      
 5 
     | 
    
         
            +
                from ..generated.TargetCornerSerde import TargetCornerSerde
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -10,4 +10,4 @@ class TargetCorner: 
     | 
|
| 
       10 
10 
     | 
    
         
             
                x: float = 0
         
     | 
| 
       11 
11 
     | 
    
         
             
                y: float = 9
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                photonStruct: ClassVar[" 
     | 
| 
      
 13 
     | 
    
         
            +
                photonStruct: ClassVar["TargetCornerSerde"]
         
     | 
| 
         @@ -3,10 +3,9 @@ from typing import TYPE_CHECKING, ClassVar 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            from wpimath.geometry import Transform3d
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
            from ..packet import Packet
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
6 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       9 
     | 
    
         
            -
                from .. import  
     | 
| 
      
 7 
     | 
    
         
            +
                from ..generated.MultiTargetPNPResultSerde import MultiTargetPNPResultSerde
         
     | 
| 
      
 8 
     | 
    
         
            +
                from ..generated.PnpResultSerde import PnpResultSerde
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
11 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -17,7 +16,7 @@ class PnpResult: 
     | 
|
| 
       17 
16 
     | 
    
         
             
                bestReprojErr: float = 0.0
         
     | 
| 
       18 
17 
     | 
    
         
             
                altReprojErr: float = 0.0
         
     | 
| 
       19 
18 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                photonStruct: ClassVar[" 
     | 
| 
      
 19 
     | 
    
         
            +
                photonStruct: ClassVar["PnpResultSerde"]
         
     | 
| 
       21 
20 
     | 
    
         | 
| 
       22 
21 
     | 
    
         | 
| 
       23 
22 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -27,14 +26,4 @@ class MultiTargetPNPResult: 
     | 
|
| 
       27 
26 
     | 
    
         
             
                estimatedPose: PnpResult = field(default_factory=PnpResult)
         
     | 
| 
       28 
27 
     | 
    
         
             
                fiducialIDsUsed: list[int] = field(default_factory=list)
         
     | 
| 
       29 
28 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
       31 
     | 
    
         
            -
                    self.estimatedPose = PnpResult()
         
     | 
| 
       32 
     | 
    
         
            -
                    self.estimatedPose.createFromPacket(packet)
         
     | 
| 
       33 
     | 
    
         
            -
                    self.fiducialIDsUsed = []
         
     | 
| 
       34 
     | 
    
         
            -
                    for _ in range(MultiTargetPNPResult._MAX_IDS):
         
     | 
| 
       35 
     | 
    
         
            -
                        fidId = packet.decode16()
         
     | 
| 
       36 
     | 
    
         
            -
                        if fidId >= 0:
         
     | 
| 
       37 
     | 
    
         
            -
                            self.fiducialIDsUsed.append(fidId)
         
     | 
| 
       38 
     | 
    
         
            -
                    return packet
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                photonStruct: ClassVar["generated.MultiTargetPNPResultSerde"]
         
     | 
| 
      
 29 
     | 
    
         
            +
                photonStruct: ClassVar["MultiTargetPNPResultSerde"]
         
     | 
| 
         @@ -5,7 +5,8 @@ from .multiTargetPNPResult import MultiTargetPNPResult 
     | 
|
| 
       5 
5 
     | 
    
         
             
            from .photonTrackedTarget import PhotonTrackedTarget
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       8 
     | 
    
         
            -
                from .. import  
     | 
| 
      
 8 
     | 
    
         
            +
                from ..generated.PhotonPipelineMetadataSerde import PhotonPipelineMetadataSerde
         
     | 
| 
      
 9 
     | 
    
         
            +
                from ..generated.PhotonPipelineResultSerde import PhotonPipelineResultSerde
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -20,7 +21,7 @@ class PhotonPipelineMetadata: 
     | 
|
| 
       20 
21 
     | 
    
         | 
| 
       21 
22 
     | 
    
         
             
                timeSinceLastPong: int = -1
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                photonStruct: ClassVar[" 
     | 
| 
      
 24 
     | 
    
         
            +
                photonStruct: ClassVar["PhotonPipelineMetadataSerde"]
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
27 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -69,4 +70,4 @@ class PhotonPipelineResult: 
     | 
|
| 
       69 
70 
     | 
    
         
             
                        return None
         
     | 
| 
       70 
71 
     | 
    
         
             
                    return self.getTargets()[0]
         
     | 
| 
       71 
72 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                photonStruct: ClassVar[" 
     | 
| 
      
 73 
     | 
    
         
            +
                photonStruct: ClassVar["PhotonPipelineResultSerde"]
         
     | 
| 
         @@ -7,7 +7,7 @@ from ..packet import Packet 
     | 
|
| 
       7 
7 
     | 
    
         
             
            from .TargetCorner import TargetCorner
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
       10 
     | 
    
         
            -
                from .. import  
     | 
| 
      
 10 
     | 
    
         
            +
                from ..generated.PhotonTrackedTargetSerde import PhotonTrackedTargetSerde
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            @dataclass
         
     | 
| 
         @@ -63,4 +63,4 @@ class PhotonTrackedTarget: 
     | 
|
| 
       63 
63 
     | 
    
         
             
                        retList.append(TargetCorner(cx, cy))
         
     | 
| 
       64 
64 
     | 
    
         
             
                    return retList
         
     | 
| 
       65 
65 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                photonStruct: ClassVar[" 
     | 
| 
      
 66 
     | 
    
         
            +
                photonStruct: ClassVar["PhotonTrackedTargetSerde"]
         
     | 
    
        photonlibpy/version.py
    CHANGED
    
    | 
         @@ -1,2 +1,2 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            PHOTONLIB_VERSION="v2025.0.0.beta. 
     | 
| 
       2 
     | 
    
         
            -
            PHOTONVISION_VERSION="v2025.0.0-beta- 
     | 
| 
      
 1 
     | 
    
         
            +
            PHOTONLIB_VERSION="v2025.0.0.beta.3"
         
     | 
| 
      
 2 
     | 
    
         
            +
            PHOTONVISION_VERSION="v2025.0.0-beta-3"
         
     | 
| 
         @@ -1,16 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Metadata-Version: 2.1
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: photonlibpy
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 2025.0. 
     | 
| 
       4 
     | 
    
         
            -
            Summary: Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors. Implemented with PhotonVision version v2025.0.0-beta- 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 2025.0.0b3
         
     | 
| 
      
 4 
     | 
    
         
            +
            Summary: Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors. Implemented with PhotonVision version v2025.0.0-beta-3 .
         
     | 
| 
       5 
5 
     | 
    
         
             
            Home-page: https://photonvision.org
         
     | 
| 
       6 
6 
     | 
    
         
             
            Author: Photonvision Development Team
         
     | 
| 
       7 
7 
     | 
    
         
             
            Description-Content-Type: text/markdown
         
     | 
| 
       8 
     | 
    
         
            -
            Requires-Dist: numpy~=1 
     | 
| 
       9 
     | 
    
         
            -
            Requires-Dist: wpilib<2025 
     | 
| 
       10 
     | 
    
         
            -
            Requires-Dist: robotpy-wpimath<2025 
     | 
| 
       11 
     | 
    
         
            -
            Requires-Dist: robotpy-apriltag<2025 
     | 
| 
       12 
     | 
    
         
            -
            Requires-Dist: robotpy-cscore<2025 
     | 
| 
       13 
     | 
    
         
            -
            Requires-Dist: pyntcore<2025 
     | 
| 
      
 8 
     | 
    
         
            +
            Requires-Dist: numpy~=2.1
         
     | 
| 
      
 9 
     | 
    
         
            +
            Requires-Dist: wpilib<2026,>=2025.0.0b1
         
     | 
| 
      
 10 
     | 
    
         
            +
            Requires-Dist: robotpy-wpimath<2026,>=2025.0.0b1
         
     | 
| 
      
 11 
     | 
    
         
            +
            Requires-Dist: robotpy-apriltag<2026,>=2025.0.0b1
         
     | 
| 
      
 12 
     | 
    
         
            +
            Requires-Dist: robotpy-cscore<2026,>=2025.0.0b1
         
     | 
| 
      
 13 
     | 
    
         
            +
            Requires-Dist: pyntcore<2026,>=2025.0.0b1
         
     | 
| 
       14 
14 
     | 
    
         
             
            Requires-Dist: opencv-python; platform_machine != "roborio"
         
     | 
| 
       15 
15 
     | 
    
         
             
            Requires-Dist: robotpy-opencv; platform_machine == "roborio"
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            photonlibpy/__init__.py,sha256=WW1OGrrcNXwwxaHSZlkxmhH2GYiQIHHxSxGVTJZhZbY,1136
         
     | 
| 
      
 2 
     | 
    
         
            +
            photonlibpy/estimatedRobotPose.py,sha256=X7wF9xdPXGKSVy0MY0qrWZJOEbuZPd721lYp0KXKlP0,1603
         
     | 
| 
      
 3 
     | 
    
         
            +
            photonlibpy/packet.py,sha256=5YomViVFwOljL2FGOetWM9FbPc_yCQ15ylzkYlgLIs8,9724
         
     | 
| 
      
 4 
     | 
    
         
            +
            photonlibpy/photonCamera.py,sha256=061meWm5G36_9vByAUBFCor0fR4G24baw306xt_cWB8,10181
         
     | 
| 
      
 5 
     | 
    
         
            +
            photonlibpy/photonPoseEstimator.py,sha256=2iMqxPFsQHTsq95yv-WCSv1a6wXNcHPqOyMc4Bu6IG0,12584
         
     | 
| 
      
 6 
     | 
    
         
            +
            photonlibpy/version.py,sha256=A48GfU-qwEM5vulc7mQd7EH8j_mm-7dL2tuMzcswSqg,77
         
     | 
| 
      
 7 
     | 
    
         
            +
            photonlibpy/estimation/__init__.py,sha256=pZ-d6fN1DJvT-lRl4FfIos5HAvlzmetIOrGIinrdv7k,223
         
     | 
| 
      
 8 
     | 
    
         
            +
            photonlibpy/estimation/cameraTargetRelation.py,sha256=i7DPBXtkZve4ToXQscEIe-5F1oGQ1Qmf5QBaE__EeMQ,1158
         
     | 
| 
      
 9 
     | 
    
         
            +
            photonlibpy/estimation/openCVHelp.py,sha256=6ynO0WbccVxbUCeDu4QgISgipqiqs-erLd14rnSSH-c,6726
         
     | 
| 
      
 10 
     | 
    
         
            +
            photonlibpy/estimation/rotTrlTransform3d.py,sha256=_5q3oMdbYRVBhzxQt5UwyRE7AXkhT3Fth5Ljrj3gANY,1728
         
     | 
| 
      
 11 
     | 
    
         
            +
            photonlibpy/estimation/targetModel.py,sha256=ZfuiB0ZDNM8gMum5nuq6KWyEeFts49jYgMo7-oojjY0,3726
         
     | 
| 
      
 12 
     | 
    
         
            +
            photonlibpy/estimation/visionEstimation.py,sha256=v4WkVtEQd5Q9OWxrcJAseIjP-trMHj_MDzMj4fcfjtw,3019
         
     | 
| 
      
 13 
     | 
    
         
            +
            photonlibpy/generated/MultiTargetPNPResultSerde.py,sha256=CzsCosHUnzxAoSC_sSAqpsXsDp54KW-BClnIXdzfMPc,2506
         
     | 
| 
      
 14 
     | 
    
         
            +
            photonlibpy/generated/PhotonPipelineMetadataSerde.py,sha256=9pq5XUEDEoRowCd7sRnuGV7xtugu5HZCRrnwqZG2xXc,2887
         
     | 
| 
      
 15 
     | 
    
         
            +
            photonlibpy/generated/PhotonPipelineResultSerde.py,sha256=jTf1obU2jPNDsxvt-tl9Ty_qzJws9Wqron3C1QiHkP8,3137
         
     | 
| 
      
 16 
     | 
    
         
            +
            photonlibpy/generated/PhotonTrackedTargetSerde.py,sha256=-6vKir_ABDVBGbg8ktM48IKm_nBMFBbiyuZLiO_fP9U,4437
         
     | 
| 
      
 17 
     | 
    
         
            +
            photonlibpy/generated/PnpResultSerde.py,sha256=YoTKdQ51oSdxC-7Poy6hunL0-zkMKvP5uedqaHWPudY,2693
         
     | 
| 
      
 18 
     | 
    
         
            +
            photonlibpy/generated/TargetCornerSerde.py,sha256=kziD_rQIwyhzPfgOaDgn-3d87tvtXiAYbBjzu76biYU,2190
         
     | 
| 
      
 19 
     | 
    
         
            +
            photonlibpy/generated/__init__.py,sha256=mElM8M88---wxTWO-SRqIJ4EfxN0fdIUwZBZ-UIGuRw,428
         
     | 
| 
      
 20 
     | 
    
         
            +
            photonlibpy/networktables/NTTopicSet.py,sha256=NduTI3c3fG4MuVcY2cuLIoV1i1PSxxYzqBOt24ngS9k,2708
         
     | 
| 
      
 21 
     | 
    
         
            +
            photonlibpy/networktables/__init__.py,sha256=o_LxTdyIylAszMy_zhUtTkXHyu6jqxccccj78d44OrI,35
         
     | 
| 
      
 22 
     | 
    
         
            +
            photonlibpy/simulation/__init__.py,sha256=HKJV02of5d8bOnuI7syLzSYtOYge7XUrHSaLvawh99M,227
         
     | 
| 
      
 23 
     | 
    
         
            +
            photonlibpy/simulation/photonCameraSim.py,sha256=BJ870459FdaO1HLkAMfA23W2S8S9axn3rZUPyxQfH40,14078
         
     | 
| 
      
 24 
     | 
    
         
            +
            photonlibpy/simulation/simCameraProperties.py,sha256=gcRfMOH5zQhv8mBElSo8GT7yOC9dA0EsQoJz-1WsCCw,19960
         
     | 
| 
      
 25 
     | 
    
         
            +
            photonlibpy/simulation/videoSimUtil.py,sha256=xMuTvJ2Jx9IoQqmAJi_zUm06MdEwhVpIz9OyzYQp0k4,29
         
     | 
| 
      
 26 
     | 
    
         
            +
            photonlibpy/simulation/visionSystemSim.py,sha256=WZKYdu89IVchcCsXR04AXVQv78F_KgZIQRZ00ocusWE,8814
         
     | 
| 
      
 27 
     | 
    
         
            +
            photonlibpy/simulation/visionTargetSim.py,sha256=AN7jXW3guQfNUu2EiQl23Jj8Mkgn4gYmRphGXL0-Dqk,1734
         
     | 
| 
      
 28 
     | 
    
         
            +
            photonlibpy/targeting/TargetCorner.py,sha256=ouKj3E5uD76OZSNHHuSDzKOY65a8HqtcOsuejH-MVsU,276
         
     | 
| 
      
 29 
     | 
    
         
            +
            photonlibpy/targeting/__init__.py,sha256=YzINSpq6A0cjr-yAQcFqHoiYdLGKPFXThlVYlMjY11w,295
         
     | 
| 
      
 30 
     | 
    
         
            +
            photonlibpy/targeting/multiTargetPNPResult.py,sha256=Y9rweHtMzoCZ6mv6F8CutQi2Thq5pHN0ydBWvTCsOwY,806
         
     | 
| 
      
 31 
     | 
    
         
            +
            photonlibpy/targeting/photonPipelineResult.py,sha256=MbaSyHZTJpoKTtLOZztpSGSt9xWWFqhzgwj8medObVA,2732
         
     | 
| 
      
 32 
     | 
    
         
            +
            photonlibpy/targeting/photonTrackedTarget.py,sha256=zCoFp32hX-3GmBYEmsYBQieBoMzXtP2F_55_q0zPOXA,1956
         
     | 
| 
      
 33 
     | 
    
         
            +
            photonlibpy-2025.0.0b3.dist-info/METADATA,sha256=C6jySUa1aCRwXFf3ZKZS8l8C_MV4pnnfBS6Ueho98WM,750
         
     | 
| 
      
 34 
     | 
    
         
            +
            photonlibpy-2025.0.0b3.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
         
     | 
| 
      
 35 
     | 
    
         
            +
            photonlibpy-2025.0.0b3.dist-info/top_level.txt,sha256=T8Xc6U6he2VjKUAca6zawSkHdUZuLanxYIc4nxw2ctc,12
         
     | 
| 
      
 36 
     | 
    
         
            +
            photonlibpy-2025.0.0b3.dist-info/RECORD,,
         
     | 
| 
         @@ -1,36 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            photonlibpy/__init__.py,sha256=WW1OGrrcNXwwxaHSZlkxmhH2GYiQIHHxSxGVTJZhZbY,1136
         
     | 
| 
       2 
     | 
    
         
            -
            photonlibpy/estimatedRobotPose.py,sha256=X7wF9xdPXGKSVy0MY0qrWZJOEbuZPd721lYp0KXKlP0,1603
         
     | 
| 
       3 
     | 
    
         
            -
            photonlibpy/packet.py,sha256=5YomViVFwOljL2FGOetWM9FbPc_yCQ15ylzkYlgLIs8,9724
         
     | 
| 
       4 
     | 
    
         
            -
            photonlibpy/photonCamera.py,sha256=wz55_9XoKzGX6UQ-2Oa3kjrz9KM6R7-wExiaUPkUeto,10176
         
     | 
| 
       5 
     | 
    
         
            -
            photonlibpy/photonPoseEstimator.py,sha256=2iMqxPFsQHTsq95yv-WCSv1a6wXNcHPqOyMc4Bu6IG0,12584
         
     | 
| 
       6 
     | 
    
         
            -
            photonlibpy/version.py,sha256=gk9q-HkZ3pUpfERPbTZbPNGvNy0gR9d01A_Db5oMkZ4,77
         
     | 
| 
       7 
     | 
    
         
            -
            photonlibpy/estimation/__init__.py,sha256=pZ-d6fN1DJvT-lRl4FfIos5HAvlzmetIOrGIinrdv7k,223
         
     | 
| 
       8 
     | 
    
         
            -
            photonlibpy/estimation/cameraTargetRelation.py,sha256=i7DPBXtkZve4ToXQscEIe-5F1oGQ1Qmf5QBaE__EeMQ,1158
         
     | 
| 
       9 
     | 
    
         
            -
            photonlibpy/estimation/openCVHelp.py,sha256=ThJDVuJ_QFteuuSeo7wQHoE4YzPQOx60_bmFRnILS1Y,6544
         
     | 
| 
       10 
     | 
    
         
            -
            photonlibpy/estimation/rotTrlTransform3d.py,sha256=nX60k9rgei7bkLRR3Ykl2lhnjpsiSNuImk6fERFcy2w,915
         
     | 
| 
       11 
     | 
    
         
            -
            photonlibpy/estimation/targetModel.py,sha256=e5IaDKFdNtek6pJLrzw2poit5wxvraIRtHPDmN-rqUk,4416
         
     | 
| 
       12 
     | 
    
         
            -
            photonlibpy/estimation/visionEstimation.py,sha256=jCOBHHOjhzjNOD-_kn-jpTOXqlGxek24oKL51GiRSKU,2999
         
     | 
| 
       13 
     | 
    
         
            -
            photonlibpy/generated/MultiTargetPNPResultSerde.py,sha256=WoCdln8kkciBltG-YdFn5OjdLGMD3VwwHymfe95QF4s,2342
         
     | 
| 
       14 
     | 
    
         
            -
            photonlibpy/generated/PhotonPipelineMetadataSerde.py,sha256=0beAVUFeQ1Shq5ku4q5IgE-sYkMzk3XoemRnC5Vx8Hg,2767
         
     | 
| 
       15 
     | 
    
         
            -
            photonlibpy/generated/PhotonPipelineResultSerde.py,sha256=q2w8ei-8X1ZJgHnYsTfX7NHTybUboP-DqQkdGY5bj1M,2847
         
     | 
| 
       16 
     | 
    
         
            -
            photonlibpy/generated/PhotonTrackedTargetSerde.py,sha256=TT18q7jb2WzcPDOf26NOo1l23W9gY80CyrNYUBXbHYs,4271
         
     | 
| 
       17 
     | 
    
         
            -
            photonlibpy/generated/PnpResultSerde.py,sha256=FVvv34GzQ856uGobpRSUO8TbV-h7IVipkTqgqfRa35Y,2586
         
     | 
| 
       18 
     | 
    
         
            -
            photonlibpy/generated/TargetCornerSerde.py,sha256=rUJUBfs02gTWgkHvSjuaGLQdSzZcfpRRcSLDlFo8-_E,2080
         
     | 
| 
       19 
     | 
    
         
            -
            photonlibpy/generated/__init__.py,sha256=mElM8M88---wxTWO-SRqIJ4EfxN0fdIUwZBZ-UIGuRw,428
         
     | 
| 
       20 
     | 
    
         
            -
            photonlibpy/networktables/NTTopicSet.py,sha256=9jagxRAxO6nN7LvHZti86qA9V_d9_FStoDz5C3siM7Y,2545
         
     | 
| 
       21 
     | 
    
         
            -
            photonlibpy/networktables/__init__.py,sha256=o_LxTdyIylAszMy_zhUtTkXHyu6jqxccccj78d44OrI,35
         
     | 
| 
       22 
     | 
    
         
            -
            photonlibpy/simulation/__init__.py,sha256=HKJV02of5d8bOnuI7syLzSYtOYge7XUrHSaLvawh99M,227
         
     | 
| 
       23 
     | 
    
         
            -
            photonlibpy/simulation/photonCameraSim.py,sha256=xul2eXUe1XgJ-RWALG6cgU4zDPcDOvHHvjFjAASS188,14706
         
     | 
| 
       24 
     | 
    
         
            -
            photonlibpy/simulation/simCameraProperties.py,sha256=LAmxwm9FSyx-CTsVO-TRhfn4Pz5oanJV0Jh7KUnCNgM,20557
         
     | 
| 
       25 
     | 
    
         
            -
            photonlibpy/simulation/videoSimUtil.py,sha256=xMuTvJ2Jx9IoQqmAJi_zUm06MdEwhVpIz9OyzYQp0k4,29
         
     | 
| 
       26 
     | 
    
         
            -
            photonlibpy/simulation/visionSystemSim.py,sha256=q4ifF4q_XkCJ9jIkHBX6lYY6INc-uvFBi4c2OLQR3WA,8615
         
     | 
| 
       27 
     | 
    
         
            -
            photonlibpy/simulation/visionTargetSim.py,sha256=AN7jXW3guQfNUu2EiQl23Jj8Mkgn4gYmRphGXL0-Dqk,1734
         
     | 
| 
       28 
     | 
    
         
            -
            photonlibpy/targeting/TargetCorner.py,sha256=5a7RdK_WLCgui7BVE3KnHmb3jHbXeM5_SfFSDbnmd0M,251
         
     | 
| 
       29 
     | 
    
         
            -
            photonlibpy/targeting/__init__.py,sha256=YzINSpq6A0cjr-yAQcFqHoiYdLGKPFXThlVYlMjY11w,295
         
     | 
| 
       30 
     | 
    
         
            -
            photonlibpy/targeting/multiTargetPNPResult.py,sha256=zcUF1rIAgovURXu9saiLHIjuspSpRn3r7-J6tB_YlU4,1125
         
     | 
| 
       31 
     | 
    
         
            -
            photonlibpy/targeting/photonPipelineResult.py,sha256=Sy_KBvI0ps1pQOJ80XYHTrz50aqUDBcuvIC_b1ku3G4,2617
         
     | 
| 
       32 
     | 
    
         
            -
            photonlibpy/targeting/photonTrackedTarget.py,sha256=m6y-dBqP8iVt5J0WcGDxYpmgctVy6SNL358ZY1YgjCc,1917
         
     | 
| 
       33 
     | 
    
         
            -
            photonlibpy-2025.0.0b2.dist-info/METADATA,sha256=EdH_l3RSbxbU8Z2s7SIBpIwca7DCOPRaOwVuniX1fro,752
         
     | 
| 
       34 
     | 
    
         
            -
            photonlibpy-2025.0.0b2.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
         
     | 
| 
       35 
     | 
    
         
            -
            photonlibpy-2025.0.0b2.dist-info/top_level.txt,sha256=T8Xc6U6he2VjKUAca6zawSkHdUZuLanxYIc4nxw2ctc,12
         
     | 
| 
       36 
     | 
    
         
            -
            photonlibpy-2025.0.0b2.dist-info/RECORD,,
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     |