photonlibpy 2025.0.0b5__tar.gz → 2025.0.0b7__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/PKG-INFO +2 -2
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/networktables/NTTopicSet.py +5 -4
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/photonCameraSim.py +38 -36
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/simCameraProperties.py +6 -7
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/visionSystemSim.py +3 -2
- photonlibpy-2025.0.0b7/photonlibpy/version.py +2 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy.egg-info/PKG-INFO +2 -2
- photonlibpy-2025.0.0b5/photonlibpy/version.py +0 -2
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimatedRobotPose.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/cameraTargetRelation.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/openCVHelp.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/rotTrlTransform3d.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/targetModel.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/visionEstimation.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/MultiTargetPNPResultSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PhotonPipelineMetadataSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PhotonPipelineResultSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PhotonTrackedTargetSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PnpResultSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/TargetCornerSerde.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/networktables/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/packet.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/photonCamera.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/photonPoseEstimator.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/py.typed +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/videoSimUtil.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/visionTargetSim.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/TargetCorner.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/__init__.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/multiTargetPNPResult.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/photonPipelineResult.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/photonTrackedTarget.py +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy.egg-info/SOURCES.txt +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy.egg-info/dependency_links.txt +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy.egg-info/requires.txt +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy.egg-info/top_level.txt +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/pyproject.toml +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/setup.cfg +0 -0
- {photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/setup.py +0 -0
@@ -1,7 +1,7 @@
|
|
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.0b7
|
4
|
+
Summary: Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors. Implemented with PhotonVision version v2025.0.0-beta-7 .
|
5
5
|
Home-page: https://photonvision.org
|
6
6
|
Author: Photonvision Development Team
|
7
7
|
Description-Content-Type: text/markdown
|
@@ -17,10 +17,11 @@ class NTTopicSet:
|
|
17
17
|
different for sim vs. real camera
|
18
18
|
"""
|
19
19
|
|
20
|
-
def __init__(
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
ntSubTable: nt.NetworkTable,
|
23
|
+
) -> None:
|
24
|
+
self.subTable = ntSubTable
|
24
25
|
|
25
26
|
def updateEntries(self) -> None:
|
26
27
|
options = nt.PubSubOptions()
|
@@ -60,11 +60,10 @@ class PhotonCameraSim:
|
|
60
60
|
self.videoSimRawEnabled: bool = False
|
61
61
|
self.videoSimWireframeEnabled: bool = False
|
62
62
|
self.videoSimWireframeResolution: float = 0.1
|
63
|
-
|
64
|
-
|
65
|
-
)
|
63
|
+
# TODO switch this back to default True when the functionality is enabled
|
64
|
+
self.videoSimProcEnabled: bool = False
|
66
65
|
self.heartbeatCounter: int = 0
|
67
|
-
self.nextNtEntryTime =
|
66
|
+
self.nextNtEntryTime = wpilib.Timer.getFPGATimestamp()
|
68
67
|
self.tagLayout = AprilTagFieldLayout.loadField(AprilTagField.k2024Crescendo)
|
69
68
|
|
70
69
|
self.cam = camera
|
@@ -95,7 +94,7 @@ class PhotonCameraSim:
|
|
95
94
|
(self.prop.getResWidth(), self.prop.getResHeight())
|
96
95
|
)
|
97
96
|
|
98
|
-
self.ts = NTTopicSet(
|
97
|
+
self.ts = NTTopicSet(self.cam._cameraTable)
|
99
98
|
self.ts.updateEntries()
|
100
99
|
|
101
100
|
# Handle this last explicitly for this function signature because the other constructor is called in the initialiser list
|
@@ -173,20 +172,20 @@ class PhotonCameraSim:
|
|
173
172
|
def consumeNextEntryTime(self) -> float | None:
|
174
173
|
"""Determine if this camera should process a new frame based on performance metrics and the time
|
175
174
|
since the last update. This returns an Optional which is either empty if no update should occur
|
176
|
-
or a
|
175
|
+
or a float of the timestamp in seconds of when the frame which should be received by NT. If
|
177
176
|
a timestamp is returned, the last frame update time becomes that timestamp.
|
178
177
|
|
179
|
-
:returns: Optional
|
178
|
+
:returns: Optional float which is empty while blocked or the NT entry timestamp in seconds if
|
180
179
|
ready
|
181
180
|
"""
|
182
181
|
# check if this camera is ready for another frame update
|
183
|
-
now =
|
184
|
-
timestamp = 0
|
182
|
+
now = wpilib.Timer.getFPGATimestamp()
|
183
|
+
timestamp = 0.0
|
185
184
|
iter = 0
|
186
185
|
# prepare next latest update
|
187
186
|
while now >= self.nextNtEntryTime:
|
188
|
-
timestamp =
|
189
|
-
frameTime =
|
187
|
+
timestamp = self.nextNtEntryTime
|
188
|
+
frameTime = self.prop.estSecUntilNextFrame()
|
190
189
|
self.nextNtEntryTime += frameTime
|
191
190
|
|
192
191
|
# if frame time is very small, avoid blocking
|
@@ -432,7 +431,9 @@ class PhotonCameraSim:
|
|
432
431
|
)
|
433
432
|
|
434
433
|
def submitProcessedFrame(
|
435
|
-
self,
|
434
|
+
self,
|
435
|
+
result: PhotonPipelineResult,
|
436
|
+
receiveTimestamp_us: float | None = None,
|
436
437
|
):
|
437
438
|
"""Simulate one processed frame of vision data, putting one result to NT. Image capture timestamp
|
438
439
|
overrides :meth:`.PhotonPipelineResult.getTimestampSeconds` for more
|
@@ -441,44 +442,45 @@ class PhotonCameraSim:
|
|
441
442
|
:param result: The pipeline result to submit
|
442
443
|
:param receiveTimestamp: The (sim) timestamp when this result was read by NT in microseconds. If not passed image capture time is assumed be (current time - latency)
|
443
444
|
"""
|
444
|
-
if
|
445
|
-
|
446
|
-
|
445
|
+
if receiveTimestamp_us is None:
|
446
|
+
receiveTimestamp_us = wpilib.Timer.getFPGATimestamp() * 1e6
|
447
|
+
receiveTimestamp_us = int(receiveTimestamp_us)
|
447
448
|
|
448
|
-
self.ts.latencyMillisEntry.set(result.getLatencyMillis(),
|
449
|
+
self.ts.latencyMillisEntry.set(result.getLatencyMillis(), receiveTimestamp_us)
|
449
450
|
|
450
451
|
newPacket = PhotonPipelineResult.photonStruct.pack(result)
|
451
|
-
self.ts.rawBytesEntry.set(newPacket.getData(),
|
452
|
+
self.ts.rawBytesEntry.set(newPacket.getData(), receiveTimestamp_us)
|
452
453
|
|
453
454
|
hasTargets = result.hasTargets()
|
454
|
-
self.ts.hasTargetEntry.set(hasTargets,
|
455
|
+
self.ts.hasTargetEntry.set(hasTargets, receiveTimestamp_us)
|
455
456
|
if not hasTargets:
|
456
|
-
self.ts.targetPitchEntry.set(0.0,
|
457
|
-
self.ts.targetYawEntry.set(0.0,
|
458
|
-
self.ts.targetAreaEntry.set(0.0,
|
459
|
-
self.ts.targetPoseEntry.set(Transform3d(),
|
460
|
-
self.ts.targetSkewEntry.set(0.0,
|
457
|
+
self.ts.targetPitchEntry.set(0.0, receiveTimestamp_us)
|
458
|
+
self.ts.targetYawEntry.set(0.0, receiveTimestamp_us)
|
459
|
+
self.ts.targetAreaEntry.set(0.0, receiveTimestamp_us)
|
460
|
+
self.ts.targetPoseEntry.set(Transform3d(), receiveTimestamp_us)
|
461
|
+
self.ts.targetSkewEntry.set(0.0, receiveTimestamp_us)
|
461
462
|
else:
|
462
463
|
bestTarget = result.getBestTarget()
|
463
464
|
assert bestTarget
|
464
465
|
|
465
|
-
self.ts.targetPitchEntry.set(bestTarget.getPitch(),
|
466
|
-
self.ts.targetYawEntry.set(bestTarget.getYaw(),
|
467
|
-
self.ts.targetAreaEntry.set(bestTarget.getArea(),
|
468
|
-
self.ts.targetSkewEntry.set(bestTarget.getSkew(),
|
466
|
+
self.ts.targetPitchEntry.set(bestTarget.getPitch(), receiveTimestamp_us)
|
467
|
+
self.ts.targetYawEntry.set(bestTarget.getYaw(), receiveTimestamp_us)
|
468
|
+
self.ts.targetAreaEntry.set(bestTarget.getArea(), receiveTimestamp_us)
|
469
|
+
self.ts.targetSkewEntry.set(bestTarget.getSkew(), receiveTimestamp_us)
|
469
470
|
|
470
471
|
self.ts.targetPoseEntry.set(
|
471
|
-
bestTarget.getBestCameraToTarget(),
|
472
|
+
bestTarget.getBestCameraToTarget(), receiveTimestamp_us
|
472
473
|
)
|
473
474
|
|
474
|
-
|
475
|
-
|
476
|
-
|
475
|
+
intrinsics = self.prop.getIntrinsics()
|
476
|
+
intrinsicsView = intrinsics.flatten().tolist()
|
477
|
+
self.ts.cameraIntrinsicsPublisher.set(intrinsicsView, receiveTimestamp_us)
|
477
478
|
|
478
|
-
|
479
|
-
|
480
|
-
|
479
|
+
distortion = self.prop.getDistCoeffs()
|
480
|
+
distortionView = distortion.flatten().tolist()
|
481
|
+
self.ts.cameraDistortionPublisher.set(distortionView, receiveTimestamp_us)
|
481
482
|
|
482
|
-
|
483
|
+
self.ts.heartbeatPublisher.set(self.heartbeatCounter, receiveTimestamp_us)
|
484
|
+
self.heartbeatCounter += 1
|
483
485
|
|
484
|
-
|
486
|
+
self.ts.subTable.getInstance().flush()
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/simulation/simCameraProperties.py
RENAMED
@@ -4,6 +4,7 @@ import typing
|
|
4
4
|
|
5
5
|
import cv2 as cv
|
6
6
|
import numpy as np
|
7
|
+
import numpy.typing as npt
|
7
8
|
from wpimath.geometry import Rotation2d, Rotation3d, Translation3d
|
8
9
|
from wpimath.units import hertz, seconds
|
9
10
|
|
@@ -31,8 +32,8 @@ class SimCameraProperties:
|
|
31
32
|
"""Default constructor which is the same as {@link #PERFECT_90DEG}"""
|
32
33
|
self.resWidth: int = -1
|
33
34
|
self.resHeight: int = -1
|
34
|
-
self.camIntrinsics: np.
|
35
|
-
self.distCoeffs: np.
|
35
|
+
self.camIntrinsics: npt.NDArray[np.floating] = np.zeros((3, 3)) # [3,3]
|
36
|
+
self.distCoeffs: npt.NDArray[np.floating] = np.zeros((8, 1)) # [8,1]
|
36
37
|
self.avgErrorPx: float = 0.0
|
37
38
|
self.errorStdDevPx: float = 0.0
|
38
39
|
self.frameSpeed: seconds = 0.0
|
@@ -80,7 +81,6 @@ class SimCameraProperties:
|
|
80
81
|
newCamIntrinsics: np.ndarray,
|
81
82
|
newDistCoeffs: np.ndarray,
|
82
83
|
) -> None:
|
83
|
-
|
84
84
|
self.resWidth = width
|
85
85
|
self.resHeight = height
|
86
86
|
self.camIntrinsics = newCamIntrinsics
|
@@ -173,10 +173,10 @@ class SimCameraProperties:
|
|
173
173
|
def getAspectRatio(self) -> float:
|
174
174
|
return 1.0 * self.resWidth / self.resHeight
|
175
175
|
|
176
|
-
def getIntrinsics(self) -> np.
|
176
|
+
def getIntrinsics(self) -> npt.NDArray[np.floating]:
|
177
177
|
return self.camIntrinsics
|
178
178
|
|
179
|
-
def getDistCoeffs(self) -> np.
|
179
|
+
def getDistCoeffs(self) -> npt.NDArray[np.floating]:
|
180
180
|
return self.distCoeffs
|
181
181
|
|
182
182
|
def getFPS(self) -> hertz:
|
@@ -355,7 +355,6 @@ class SimCameraProperties:
|
|
355
355
|
|
356
356
|
# find intersections
|
357
357
|
for i, normal in enumerate(self.viewplanes):
|
358
|
-
|
359
358
|
# // we want to know the value of t when the line intercepts this plane
|
360
359
|
# // parametrized: v = t * ab + a, where v lies on the plane
|
361
360
|
# // we can find the projection of a onto the plane normal
|
@@ -467,7 +466,7 @@ class SimCameraProperties:
|
|
467
466
|
|
468
467
|
def estSecUntilNextFrame(self) -> seconds:
|
469
468
|
"""
|
470
|
-
:returns: Estimate how long until the next frame should be processed in
|
469
|
+
:returns: Estimate how long until the next frame should be processed in seconds
|
471
470
|
"""
|
472
471
|
# // exceptional processing latency blocks the next frame
|
473
472
|
return self.frameSpeed + max(0.0, self.estLatency() - self.frameSpeed)
|
@@ -305,7 +305,7 @@ class VisionSystemSim:
|
|
305
305
|
timestampNt = optTimestamp
|
306
306
|
latency = camSim.prop.estLatency()
|
307
307
|
# the image capture timestamp in seconds of this result
|
308
|
-
timestampCapture = timestampNt
|
308
|
+
timestampCapture = timestampNt - latency
|
309
309
|
|
310
310
|
# use camera pose from the image capture timestamp
|
311
311
|
lateRobotPose = self.getRobotPose(timestampCapture)
|
@@ -318,7 +318,8 @@ class VisionSystemSim:
|
|
318
318
|
# process a PhotonPipelineResult with visible targets
|
319
319
|
camResult = camSim.process(latency, lateCameraPose, allTargets)
|
320
320
|
# publish this info to NT at estimated timestamp of receive
|
321
|
-
|
321
|
+
# needs a timestamp in microseconds
|
322
|
+
camSim.submitProcessedFrame(camResult, timestampNt * 1.0e6)
|
322
323
|
# display debug results
|
323
324
|
for tgt in camResult.getTargets():
|
324
325
|
trf = tgt.getBestCameraToTarget()
|
@@ -1,7 +1,7 @@
|
|
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.0b7
|
4
|
+
Summary: Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors. Implemented with PhotonVision version v2025.0.0-beta-7 .
|
5
5
|
Home-page: https://photonvision.org
|
6
6
|
Author: Photonvision Development Team
|
7
7
|
Description-Content-Type: text/markdown
|
File without changes
|
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/cameraTargetRelation.py
RENAMED
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/rotTrlTransform3d.py
RENAMED
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/estimation/visionEstimation.py
RENAMED
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/MultiTargetPNPResultSerde.py
RENAMED
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PhotonPipelineResultSerde.py
RENAMED
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/PhotonTrackedTargetSerde.py
RENAMED
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/generated/TargetCornerSerde.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/multiTargetPNPResult.py
RENAMED
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/photonPipelineResult.py
RENAMED
File without changes
|
{photonlibpy-2025.0.0b5 → photonlibpy-2025.0.0b7}/photonlibpy/targeting/photonTrackedTarget.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|