mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-29 02:21:41 +00:00
Add photonlibpy (#1040)
* Added a pure-python implementation of photonlib, named photonlibpy and hosted on pypi --------- Co-authored-by: Matt <matthew.morley.ca@gmail.com>
This commit is contained in:
62
.github/workflows/python.yml
vendored
Normal file
62
.github/workflows/python.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Build and Distribute PhotonLibPy
|
||||
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
buildAndDeploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
sparse-checkout-cone-mode: false
|
||||
fetch-tags: true
|
||||
fetch-depth: 99999
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools wheel pytest
|
||||
|
||||
- name: Build wheel
|
||||
working-directory: ./photon-lib/py
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
- name: Run Unit Tests
|
||||
working-directory: ./photon-lib/py
|
||||
run: |
|
||||
pip install --no-cache-dir dist/*.whl
|
||||
pytest
|
||||
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: dist
|
||||
path: ./photon-lib/py/dist/
|
||||
|
||||
- name: Publish package distributions to TestPyPI
|
||||
# Only upload on tags
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages_dir: ./photon-lib/py/dist/
|
||||
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
||||
5
photon-lib/py/.gitignore
vendored
Normal file
5
photon-lib/py/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
photonlibpy.egg-info/
|
||||
dist/
|
||||
build/
|
||||
.eggs/
|
||||
photonlibpy/version.py
|
||||
14
photon-lib/py/buildAndTest.bat
Normal file
14
photon-lib/py/buildAndTest.bat
Normal file
@@ -0,0 +1,14 @@
|
||||
:: Uninstall if it already was installed
|
||||
pip uninstall -y photonlibpy
|
||||
|
||||
:: Build wheel
|
||||
python setup.py bdist_wheel
|
||||
|
||||
:: Install whatever wheel was made
|
||||
for %%f in (dist/*.whl) do (
|
||||
echo installing dist/%%f
|
||||
pip install --no-cache-dir dist/%%f
|
||||
)
|
||||
|
||||
:: Run the test suite
|
||||
pytest
|
||||
1
photon-lib/py/photonlibpy/__init__.py
Normal file
1
photon-lib/py/photonlibpy/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# No one here but us chickens
|
||||
45
photon-lib/py/photonlibpy/multiTargetPNPResult.py
Normal file
45
photon-lib/py/photonlibpy/multiTargetPNPResult.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from dataclasses import dataclass, field
|
||||
from wpimath.geometry import Transform3d
|
||||
from photonlibpy.packet import Packet
|
||||
|
||||
|
||||
@dataclass
|
||||
class PNPResult:
|
||||
_NUM_BYTES_IN_FLOAT = 8
|
||||
PACK_SIZE_BYTES = 1 + (_NUM_BYTES_IN_FLOAT * 7 * 2) + (_NUM_BYTES_IN_FLOAT * 3)
|
||||
|
||||
isPresent: bool = False
|
||||
best: Transform3d = field(default_factory=Transform3d)
|
||||
alt: Transform3d = field(default_factory=Transform3d)
|
||||
ambiguity: float = 0.0
|
||||
bestReprojError: float = 0.0
|
||||
altReprojError: float = 0.0
|
||||
|
||||
def createFromPacket(self, packet: Packet) -> Packet:
|
||||
self.isPresent = packet.decodeBoolean()
|
||||
self.best = packet.decodeTransform()
|
||||
self.alt = packet.decodeTransform()
|
||||
self.bestReprojError = packet.decodeDouble()
|
||||
self.altReprojError = packet.decodeDouble()
|
||||
self.ambiguity = packet.decodeDouble()
|
||||
return packet
|
||||
|
||||
|
||||
@dataclass
|
||||
class MultiTargetPNPResult:
|
||||
_MAX_IDS = 32
|
||||
# pnpresult + MAX_IDS possible targets (arbitrary upper limit that should never be hit, ideally)
|
||||
_PACK_SIZE_BYTES = PNPResult.PACK_SIZE_BYTES + (1 * _MAX_IDS)
|
||||
|
||||
estimatedPose: PNPResult = field(default_factory=PNPResult)
|
||||
fiducialIDsUsed: list[int] = field(default_factory=list)
|
||||
|
||||
def createFromPacket(self, packet: Packet) -> Packet:
|
||||
self.estimatedPose = PNPResult()
|
||||
self.estimatedPose.createFromPacket(packet)
|
||||
self.fiducialIDsUsed = []
|
||||
for _ in range(MultiTargetPNPResult._MAX_IDS):
|
||||
fidId = packet.decode16()
|
||||
if fidId >= 0:
|
||||
self.fiducialIDsUsed.append(fidId)
|
||||
return packet
|
||||
143
photon-lib/py/photonlibpy/packet.py
Normal file
143
photon-lib/py/photonlibpy/packet.py
Normal file
@@ -0,0 +1,143 @@
|
||||
import struct
|
||||
from wpimath.geometry import Transform3d, Translation3d, Rotation3d, Quaternion
|
||||
import wpilib
|
||||
|
||||
|
||||
class Packet:
|
||||
def __init__(self, data: list[int]):
|
||||
"""
|
||||
* Constructs an empty packet.
|
||||
*
|
||||
* @param self.size The self.size of the packet buffer.
|
||||
"""
|
||||
self.packetData = data
|
||||
self.size = len(data)
|
||||
self.readPos = 0
|
||||
self.outOfBytes = False
|
||||
|
||||
def clear(self):
|
||||
"""Clears the packet and resets the read and write positions."""
|
||||
self.packetData = [0] * self.size
|
||||
self.readPos = 0
|
||||
self.outOfBytes = False
|
||||
|
||||
def getSize(self):
|
||||
return self.size
|
||||
|
||||
_NO_MORE_BYTES_MESSAGE = """
|
||||
Photonlib - Ran out of bytes while decoding.
|
||||
Make sure the version of photonvision on the coprocessor
|
||||
matches the version of photonlib running in the robot code.
|
||||
"""
|
||||
|
||||
def _getNextByte(self) -> int:
|
||||
retVal = 0x00
|
||||
|
||||
if not self.outOfBytes:
|
||||
try:
|
||||
retVal = 0x00FF & self.packetData[self.readPos]
|
||||
self.readPos += 1
|
||||
except IndexError:
|
||||
wpilib.reportError(Packet._NO_MORE_BYTES_MESSAGE, True)
|
||||
self.outOfBytes = True
|
||||
|
||||
return retVal
|
||||
|
||||
def getData(self) -> list[int]:
|
||||
"""
|
||||
* Returns the packet data.
|
||||
*
|
||||
* @return The packet data.
|
||||
"""
|
||||
return self.packetData
|
||||
|
||||
def setData(self, data: list[int]):
|
||||
"""
|
||||
* Sets the packet data.
|
||||
*
|
||||
* @param data The packet data.
|
||||
"""
|
||||
self.clear()
|
||||
self.packetData = data
|
||||
self.size = len(self.packetData)
|
||||
|
||||
def _decodeGeneric(self, unpackFormat, numBytes):
|
||||
# Read ints in from the data buffer
|
||||
intList = []
|
||||
for _ in range(numBytes):
|
||||
intList.append(self._getNextByte())
|
||||
|
||||
# Interpret the bytes as a floating point number
|
||||
value = struct.unpack(unpackFormat, bytes(intList))[0]
|
||||
|
||||
return value
|
||||
|
||||
def decode8(self) -> int:
|
||||
"""
|
||||
* Returns a single decoded byte from the packet.
|
||||
*
|
||||
* @return A decoded byte from the packet.
|
||||
"""
|
||||
return self._decodeGeneric(">b", 1)
|
||||
|
||||
def decode16(self) -> int:
|
||||
"""
|
||||
* Returns a single decoded byte from the packet.
|
||||
*
|
||||
* @return A decoded byte from the packet.
|
||||
"""
|
||||
return self._decodeGeneric(">h", 2)
|
||||
|
||||
def decode32(self) -> int:
|
||||
"""
|
||||
* Returns a decoded int (32 bytes) from the packet.
|
||||
*
|
||||
* @return A decoded int from the packet.
|
||||
"""
|
||||
return self._decodeGeneric(">l", 4)
|
||||
|
||||
def decodeDouble(self) -> float:
|
||||
"""
|
||||
* Returns a decoded double from the packet.
|
||||
*
|
||||
* @return A decoded double from the packet.
|
||||
"""
|
||||
return self._decodeGeneric(">d", 8)
|
||||
|
||||
def decodeBoolean(self) -> bool:
|
||||
"""
|
||||
* Returns a decoded boolean from the packet.
|
||||
*
|
||||
* @return A decoded boolean from the packet.
|
||||
"""
|
||||
return self.decode8() == 1
|
||||
|
||||
def decodeDoubleArray(self, length: int) -> list[float]:
|
||||
"""
|
||||
* Returns a decoded array of floats from the packet.
|
||||
*
|
||||
* @return A decoded array of floats from the packet.
|
||||
"""
|
||||
ret = []
|
||||
for _ in range(length):
|
||||
ret.append(self.decodeDouble())
|
||||
return ret
|
||||
|
||||
def decodeTransform(self) -> Transform3d:
|
||||
"""
|
||||
* Returns a decoded Transform3d
|
||||
*
|
||||
* @return A decoded Tansform3d from the packet.
|
||||
"""
|
||||
x = self.decodeDouble()
|
||||
y = self.decodeDouble()
|
||||
z = self.decodeDouble()
|
||||
translation = Translation3d(x, y, z)
|
||||
|
||||
w = self.decodeDouble()
|
||||
x = self.decodeDouble()
|
||||
y = self.decodeDouble()
|
||||
z = self.decodeDouble()
|
||||
rotation = Rotation3d(Quaternion(w, x, y, z))
|
||||
|
||||
return Transform3d(translation, rotation)
|
||||
170
photon-lib/py/photonlibpy/photonCamera.py
Normal file
170
photon-lib/py/photonlibpy/photonCamera.py
Normal file
@@ -0,0 +1,170 @@
|
||||
from enum import Enum
|
||||
import ntcore
|
||||
from wpilib import Timer
|
||||
import wpilib
|
||||
from photonlibpy.packet import Packet
|
||||
from photonlibpy.photonPipelineResult import PhotonPipelineResult
|
||||
from photonlibpy.version import PHOTONVISION_VERSION, PHOTONLIB_VERSION
|
||||
|
||||
|
||||
class VisionLEDMode(Enum):
|
||||
kDefault = -1
|
||||
kOff = 0
|
||||
kOn = 1
|
||||
kBlink = 2
|
||||
|
||||
|
||||
lastVersionTimeCheck = 0.0
|
||||
_VERSION_CHECK_ENABLED = True
|
||||
|
||||
|
||||
def setVersionCheckEnabled(enabled: bool):
|
||||
_VERSION_CHECK_ENABLED = enabled
|
||||
|
||||
|
||||
class PhotonCamera:
|
||||
def __init__(self, cameraName: str):
|
||||
instance = ntcore.NetworkTableInstance.getDefault()
|
||||
self.name = cameraName
|
||||
self._tableName = "photonvision"
|
||||
photonvision_root_table = instance.getTable(self._tableName)
|
||||
self.cameraTable = photonvision_root_table.getSubTable(cameraName)
|
||||
self.path = self.cameraTable.getPath()
|
||||
self.rawBytesEntry = self.cameraTable.getRawTopic("rawBytes").subscribe(
|
||||
"rawBytes", bytes([]), ntcore.PubSubOptions(periodic=0.01, sendAll=True)
|
||||
)
|
||||
|
||||
self.driverModePublisher = self.cameraTable.getBooleanTopic(
|
||||
"driverModeRequest"
|
||||
).publish()
|
||||
self.driverModeSubscriber = self.cameraTable.getBooleanTopic(
|
||||
"driverMode"
|
||||
).subscribe(False)
|
||||
self.inputSaveImgEntry = self.cameraTable.getIntegerTopic(
|
||||
"inputSaveImgCmd"
|
||||
).getEntry(0)
|
||||
self.outputSaveImgEntry = self.cameraTable.getIntegerTopic(
|
||||
"outputSaveImgCmd"
|
||||
).getEntry(0)
|
||||
self.pipelineIndexRequest = self.cameraTable.getIntegerTopic(
|
||||
"pipelineIndexRequest"
|
||||
).publish()
|
||||
self.pipelineIndexState = self.cameraTable.getIntegerTopic(
|
||||
"pipelineIndexState"
|
||||
).subscribe(0)
|
||||
self.heartbeatEntry = self.cameraTable.getIntegerTopic("heartbeat").subscribe(
|
||||
-1
|
||||
)
|
||||
|
||||
self.ledModeRequest = photonvision_root_table.getIntegerTopic(
|
||||
"ledModeRequest"
|
||||
).publish()
|
||||
self.ledModeState = photonvision_root_table.getIntegerTopic(
|
||||
"ledModeState"
|
||||
).subscribe(-1)
|
||||
self.versionEntry = photonvision_root_table.getStringTopic("version").subscribe(
|
||||
""
|
||||
)
|
||||
|
||||
# Existing is enough to make this multisubscriber do its thing
|
||||
self.topicNameSubscriber = ntcore.MultiSubscriber(
|
||||
instance, ["/photonvision/"], ntcore.PubSubOptions(topicsOnly=True)
|
||||
)
|
||||
|
||||
self.prevHeartbeat = 0
|
||||
self.prevHeartbeatChangeTime = Timer.getFPGATimestamp()
|
||||
|
||||
def getLatestResult(self) -> PhotonPipelineResult:
|
||||
self._versionCheck()
|
||||
|
||||
retVal = PhotonPipelineResult()
|
||||
packetWithTimestamp = self.rawBytesEntry.getAtomic()
|
||||
byteList = packetWithTimestamp.value
|
||||
timestamp = packetWithTimestamp.time
|
||||
|
||||
if len(byteList) < 1:
|
||||
return retVal
|
||||
else:
|
||||
retVal.populateFromPacket(Packet(byteList))
|
||||
# NT4 allows us to correct the timestamp based on when the message was sent
|
||||
retVal.setTimestampSeconds(
|
||||
timestamp / 1e-6 - retVal.getLatencyMillis() / 1e-3
|
||||
)
|
||||
return retVal
|
||||
|
||||
def getDriverMode(self) -> bool:
|
||||
return self.driverModeSubscriber.get()
|
||||
|
||||
def setDriverMode(self, driverMode: bool) -> None:
|
||||
self.driverModePublisher.set(driverMode)
|
||||
|
||||
def takeInputSnapshot(self) -> None:
|
||||
self.inputSaveImgEntry.set(self.inputSaveImgEntry.get() + 1)
|
||||
|
||||
def takeOutputSnapshot(self) -> None:
|
||||
self.outputSaveImgEntry.set(self.outputSaveImgEntry.get() + 1)
|
||||
|
||||
def getPipelineIndex(self) -> int:
|
||||
return self.pipelineIndexState.get(0)
|
||||
|
||||
def setPipelineIndex(self, index: int) -> None:
|
||||
self.pipelineIndexRequest.set(index)
|
||||
|
||||
def getLEDMode(self) -> VisionLEDMode:
|
||||
mode = self.ledModeState.get()
|
||||
return VisionLEDMode(mode)
|
||||
|
||||
def setLEDMode(self, led: VisionLEDMode) -> None:
|
||||
self.ledModeRequest.set(led.value)
|
||||
|
||||
def getName(self) -> str:
|
||||
return self.name
|
||||
|
||||
def isConnected(self) -> bool:
|
||||
curHeartbeat = self.heartbeatEntry.get()
|
||||
now = Timer.getFPGATimestamp()
|
||||
|
||||
if curHeartbeat != self.prevHeartbeat:
|
||||
self.prevHeartbeat = curHeartbeat
|
||||
self.prevHeartbeatChangeTime = now
|
||||
|
||||
return (now - self.prevHeartbeatChangeTime) < 0.5
|
||||
|
||||
def _versionCheck(self) -> None:
|
||||
if not _VERSION_CHECK_ENABLED:
|
||||
return
|
||||
|
||||
if (Timer.getFPGATimestamp() - lastVersionTimeCheck) < 5.0:
|
||||
return
|
||||
|
||||
if not self.heartbeatEntry.exists():
|
||||
cameraNames = (
|
||||
self.cameraTable.getInstance().getTable(self._tableName).getSubTables()
|
||||
)
|
||||
if len(cameraNames) == 0:
|
||||
wpilib.reportError(
|
||||
"Could not find any PhotonVision coprocessors on NetworkTables. Double check that PhotonVision is running, and that your camera is connected!",
|
||||
False,
|
||||
)
|
||||
else:
|
||||
wpilib.reportError(
|
||||
f"PhotonVision coprocessor at path {self.path} not found in Network Tables. Double check that your camera names match! Only the following camera names were found: { ''.join(cameraNames)}",
|
||||
True,
|
||||
)
|
||||
|
||||
elif not self.isConnected():
|
||||
wpilib.reportWarning(
|
||||
f"PhotonVision coprocessor at path {self.path} is not sending new data.",
|
||||
True,
|
||||
)
|
||||
|
||||
versionString = self.versionEntry.get(defaultValue="")
|
||||
if len(versionString) > 0 and versionString != PHOTONVISION_VERSION:
|
||||
wpilib.reportWarning(
|
||||
"Photon version "
|
||||
+ PHOTONVISION_VERSION
|
||||
+ " does not match coprocessor version "
|
||||
+ versionString
|
||||
+ f"! Please install photonlibpy version {PHOTONLIB_VERSION}",
|
||||
True,
|
||||
)
|
||||
38
photon-lib/py/photonlibpy/photonPipelineResult.py
Normal file
38
photon-lib/py/photonlibpy/photonPipelineResult.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from photonlibpy.multiTargetPNPResult import MultiTargetPNPResult
|
||||
from photonlibpy.packet import Packet
|
||||
from photonlibpy.photonTrackedTarget import PhotonTrackedTarget
|
||||
|
||||
|
||||
@dataclass
|
||||
class PhotonPipelineResult:
|
||||
latencyMillis: float = -1.0
|
||||
timestampSec: float = -1.0
|
||||
targets: list[PhotonTrackedTarget] = field(default_factory=list)
|
||||
multiTagResult: MultiTargetPNPResult = field(default_factory=MultiTargetPNPResult)
|
||||
|
||||
def populateFromPacket(self, packet: Packet) -> Packet:
|
||||
self.targets = []
|
||||
self.latencyMillis = packet.decodeDouble()
|
||||
self.multiTagResult = MultiTargetPNPResult()
|
||||
self.multiTagResult.createFromPacket(packet)
|
||||
targetCount = packet.decode8()
|
||||
for _ in range(targetCount):
|
||||
target = PhotonTrackedTarget()
|
||||
target.createFromPacket(packet)
|
||||
self.targets.append(target)
|
||||
|
||||
return packet
|
||||
|
||||
def setTimestampSeconds(self, timestampSec: float) -> None:
|
||||
self.timestampSec = timestampSec
|
||||
|
||||
def getLatencyMillis(self) -> float:
|
||||
return self.latencyMillis
|
||||
|
||||
def getTimestamp(self) -> float:
|
||||
return self.timestampSec
|
||||
|
||||
def getTargets(self) -> list[PhotonTrackedTarget]:
|
||||
return self.targets
|
||||
82
photon-lib/py/photonlibpy/photonTrackedTarget.py
Normal file
82
photon-lib/py/photonlibpy/photonTrackedTarget.py
Normal file
@@ -0,0 +1,82 @@
|
||||
from dataclasses import dataclass, field
|
||||
from wpimath.geometry import Transform3d
|
||||
from photonlibpy.packet import Packet
|
||||
|
||||
|
||||
@dataclass
|
||||
class TargetCorner:
|
||||
x: float
|
||||
y: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class PhotonTrackedTarget:
|
||||
_MAX_CORNERS = 8
|
||||
_NUM_BYTES_IN_FLOAT = 8
|
||||
_PACK_SIZE_BYTES = _NUM_BYTES_IN_FLOAT * (5 + 7 + 2 * 4 + 1 + 7 + 2 * _MAX_CORNERS)
|
||||
|
||||
yaw: float = 0.0
|
||||
pitch: float = 0.0
|
||||
area: float = 0.0
|
||||
skew: float = 0.0
|
||||
fiducialId: int = -1
|
||||
bestCameraToTarget: Transform3d = field(default_factory=Transform3d)
|
||||
altCameraToTarget: Transform3d = field(default_factory=Transform3d)
|
||||
minAreaRectCorners: list[TargetCorner] | None = None
|
||||
detectedCorners: list[TargetCorner] | None = None
|
||||
poseAmbiguity: float = 0.0
|
||||
|
||||
def getYaw(self) -> float:
|
||||
return self.yaw
|
||||
|
||||
def getPitch(self) -> float:
|
||||
return self.pitch
|
||||
|
||||
def getArea(self) -> float:
|
||||
return self.area
|
||||
|
||||
def getSkew(self) -> float:
|
||||
return self.skew
|
||||
|
||||
def getFiducialId(self) -> int:
|
||||
return self.fiducialId
|
||||
|
||||
def getPoseAmbiguity(self) -> float:
|
||||
return self.poseAmbiguity
|
||||
|
||||
def getMinAreaRectCorners(self) -> list[TargetCorner] | None:
|
||||
return self.minAreaRectCorners
|
||||
|
||||
def getDetectedCorners(self) -> list[TargetCorner] | None:
|
||||
return self.detectedCorners
|
||||
|
||||
def getBestCameraToTarget(self) -> Transform3d:
|
||||
return self.bestCameraToTarget
|
||||
|
||||
def getAlternateCameraToTarget(self) -> Transform3d:
|
||||
return self.altCameraToTarget
|
||||
|
||||
def _decodeTargetList(self, packet: Packet, numTargets: int) -> list[TargetCorner]:
|
||||
retList = []
|
||||
for _ in range(numTargets):
|
||||
cx = packet.decodeDouble()
|
||||
cy = packet.decodeDouble()
|
||||
retList.append(TargetCorner(cx, cy))
|
||||
return retList
|
||||
|
||||
def createFromPacket(self, packet: Packet) -> Packet:
|
||||
self.yaw = packet.decodeDouble()
|
||||
self.pitch = packet.decodeDouble()
|
||||
self.area = packet.decodeDouble()
|
||||
self.skew = packet.decodeDouble()
|
||||
self.fiducialId = packet.decode32()
|
||||
|
||||
self.bestCameraToTarget = packet.decodeTransform()
|
||||
self.altCameraToTarget = packet.decodeTransform()
|
||||
|
||||
self.poseAmbiguity = packet.decodeDouble()
|
||||
|
||||
self.minAreaRectCorners = self._decodeTargetList(packet, 4) # always four
|
||||
numCorners = packet.decode8()
|
||||
self.detectedCorners = self._decodeTargetList(packet, numCorners)
|
||||
return packet
|
||||
54
photon-lib/py/setup.py
Normal file
54
photon-lib/py/setup.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from setuptools import setup, find_packages
|
||||
import subprocess, re
|
||||
|
||||
gitDescribeResult = (
|
||||
subprocess.check_output(["git", "describe", "--tags", "--match=v*", "--always"])
|
||||
.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
|
||||
m = re.search(
|
||||
r"(v[0-9]{4}\.[0-9]{1}\.[0-9]{1})-?((?:beta)?(?:alpha)?)-?([0-9\.]*)",
|
||||
gitDescribeResult,
|
||||
)
|
||||
|
||||
# Extract the first portion of the git describe result
|
||||
# which should be PEP440 compliant
|
||||
if m:
|
||||
versionString = m.group(0)
|
||||
prefix = m.group(1)
|
||||
maturity = m.group(2)
|
||||
suffix = m.group(3).replace(".", "")
|
||||
versionString = f"{prefix}.{maturity}.{suffix}"
|
||||
|
||||
|
||||
else:
|
||||
print("Warning, no valid version found")
|
||||
versionString = gitDescribeResult
|
||||
|
||||
print(f"Building version {versionString}")
|
||||
|
||||
# Put the version info into a python file for runtime access
|
||||
with open("photonlibpy/version.py", "w", encoding="utf-8") as fp:
|
||||
fp.write(f'PHOTONLIB_VERSION="{versionString}"\n')
|
||||
fp.write(f'PHOTONVISION_VERSION="{gitDescribeResult}"\n')
|
||||
|
||||
|
||||
descriptionStr = f"""
|
||||
Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors.
|
||||
Implemented with PhotonVision version {gitDescribeResult} .
|
||||
"""
|
||||
|
||||
setup(
|
||||
name="photonlibpy",
|
||||
packages=find_packages(),
|
||||
version=versionString,
|
||||
install_requires=[
|
||||
"wpilib<2025,>=2024.0.0b2",
|
||||
"robotpy-wpimath<2025,>=2024.0.0b2",
|
||||
"pyntcore<2025,>=2024.0.0b2",
|
||||
],
|
||||
description=descriptionStr,
|
||||
url="https://photonvision.org",
|
||||
author="Photonvision Development Team",
|
||||
)
|
||||
239
photon-lib/py/test/data.py
Normal file
239
photon-lib/py/test/data.py
Normal file
@@ -0,0 +1,239 @@
|
||||
# fmt: off
|
||||
rawBytes1 = [
|
||||
64, 166, 117, 41, 225, 243, 165, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0
|
||||
]
|
||||
rawBytes2 = [
|
||||
64, 114, 72, 58, 227, 96, 141, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 0
|
||||
]
|
||||
rawBytes3 = [
|
||||
64, 55, 65, 189, 215, 102, 131, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0
|
||||
]
|
||||
rawBytes4 = [
|
||||
64, 115, 23, 245, 248, 9, 145, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 1, 64, 41, 32, 212, 70, 53, 253, 38, 64, 19, 140,
|
||||
198, 187, 206, 56, 251, 64, 38, 63, 170, 170, 170, 170, 170, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 17, 63, 226, 15, 19, 123, 229, 152, 236, 191, 191, 225,
|
||||
27, 96, 1, 219, 30, 63, 168, 175, 103, 65, 172, 24, 8, 63, 115, 51, 123,
|
||||
216, 202, 14, 128, 191, 155, 163, 119, 215, 217, 209, 224, 63, 212, 76, 79,
|
||||
227, 166, 197, 80, 63, 238, 85, 211, 252, 64, 132, 136, 63, 226, 13, 126,
|
||||
170, 219, 202, 209, 191, 190, 134, 80, 94, 25, 179, 17, 63, 168, 92, 53,
|
||||
102, 36, 28, 64, 63, 204, 203, 52, 12, 186, 226, 51, 63, 148, 67, 104, 89,
|
||||
131, 114, 208, 63, 211, 104, 18, 25, 149, 138, 78, 63, 237, 159, 242, 53,
|
||||
211, 204, 51, 63, 217, 254, 169, 82, 190, 36, 22, 64, 123, 96, 0, 6, 100,
|
||||
53, 178, 64, 112, 207, 255, 241, 198, 25, 18, 64, 132, 215, 255, 254, 189,
|
||||
61, 109, 64, 86, 191, 255, 217, 164, 214, 161, 64, 138, 55, 94, 60, 205,
|
||||
229, 39, 64, 115, 130, 222, 78, 57, 230, 238, 64, 131, 15, 94, 65, 66, 194,
|
||||
147, 64, 126, 162, 222, 73, 150, 202, 88, 4, 64, 130, 248, 64, 192, 0, 0, 0,
|
||||
64, 126, 15, 133, 64, 0, 0, 0, 64, 137, 206, 237, 128, 0, 0, 0, 64, 116, 48,
|
||||
240, 32, 0, 0, 0, 64, 132, 218, 43, 96, 0, 0, 0, 64, 86, 210, 155, 128, 0,
|
||||
0, 0, 64, 123, 102, 127, 192, 0, 0, 0, 64, 112, 211, 233, 96, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
rawBytes5 = [
|
||||
64, 102, 149, 235, 181, 90, 192, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 1, 64, 21, 210, 112, 148, 86, 4, 131, 64, 3, 87,
|
||||
196, 18, 174, 105, 145, 64, 47, 80, 237, 9, 123, 66, 95, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 240, 0, 0,
|
||||
0, 0, 0, 0, 64, 116, 192, 0, 0, 0, 0, 0, 64, 127, 128, 0, 0, 0, 0, 0, 64,
|
||||
116, 192, 0, 0, 0, 0, 0, 64, 100, 96, 0, 0, 0, 0, 0, 64, 133, 72, 0, 0, 0,
|
||||
0, 0, 64, 100, 96, 0, 0, 0, 0, 0, 64, 133, 72, 0, 0, 0, 0, 0, 64, 127, 128,
|
||||
0, 0, 0, 0, 0, 4, 64, 133, 78, 45, 224, 0, 0, 0, 64, 127, 129, 184, 160, 0,
|
||||
0, 0, 64, 133, 78, 1, 192, 0, 0, 0, 64, 100, 100, 194, 224, 0, 0, 0, 64,
|
||||
118, 181, 224, 64, 0, 0, 0, 64, 102, 98, 136, 0, 0, 0, 0, 64, 116, 207, 155,
|
||||
64, 0, 0, 0, 64, 126, 121, 100, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
rawBytes6 = [
|
||||
64, 78, 129, 235, 32, 116, 234, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 8, 64, 43, 213, 73, 8, 241, 221, 240, 192, 2, 146,
|
||||
71, 190, 201, 205, 25, 64, 37, 96, 141, 183, 156, 102, 0, 192, 9, 112, 76,
|
||||
0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191,
|
||||
240, 0, 0, 0, 0, 0, 0, 64, 101, 10, 36, 92, 234, 132, 108, 64, 89, 45, 24,
|
||||
60, 197, 216, 218, 64, 114, 7, 35, 134, 17, 204, 20, 64, 87, 129, 247, 219,
|
||||
201, 12, 226, 64, 114, 67, 177, 81, 138, 189, 202, 64, 100, 68, 236, 33,
|
||||
157, 19, 147, 64, 101, 131, 63, 243, 220, 103, 216, 64, 101, 26, 124, 82,
|
||||
27, 121, 143, 0, 192, 32, 131, 181, 181, 155, 145, 13, 192, 37, 92, 235, 61,
|
||||
221, 83, 253, 63, 173, 176, 233, 61, 133, 212, 255, 192, 73, 171, 139, 128,
|
||||
0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191,
|
||||
240, 0, 0, 0, 0, 0, 0, 64, 92, 42, 37, 190, 203, 146, 101, 64, 102, 61, 168,
|
||||
153, 137, 73, 186, 64, 94, 48, 100, 45, 88, 178, 51, 64, 100, 249, 193, 146,
|
||||
50, 77, 24, 64, 94, 220, 25, 65, 52, 109, 155, 64, 101, 62, 112, 102, 118,
|
||||
182, 70, 64, 92, 213, 218, 210, 167, 77, 205, 64, 102, 130, 87, 109, 205,
|
||||
178, 232, 0, 192, 19, 156, 59, 67, 88, 173, 35, 192, 37, 85, 193, 76, 240,
|
||||
22, 41, 63, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255,
|
||||
255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 240, 0, 0, 0, 0, 0, 0, 64,
|
||||
96, 128, 0, 0, 0, 0, 0, 64, 101, 128, 0, 0, 0, 0, 0, 64, 97, 64, 0, 0, 0, 0,
|
||||
0, 64, 101, 128, 0, 0, 0, 0, 0, 64, 97, 64, 0, 0, 0, 0, 0, 64, 101, 224, 0,
|
||||
0, 0, 0, 0, 64, 96, 128, 0, 0, 0, 0, 0, 64, 101, 224, 0, 0, 0, 0, 0, 0, 64,
|
||||
48, 164, 171, 25, 83, 4, 154, 192, 34, 178, 85, 3, 174, 51, 62, 63, 147,
|
||||
255, 255, 245, 245, 4, 85, 192, 28, 128, 4, 0, 0, 0, 0, 255, 255, 255, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63,
|
||||
240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 240, 0, 0, 0, 0, 0, 0, 64, 110,
|
||||
24, 157, 164, 237, 183, 149, 64, 101, 4, 236, 103, 73, 0, 224, 64, 111, 24,
|
||||
157, 165, 1, 191, 69, 64, 100, 228, 236, 103, 153, 126, 38, 64, 111, 32, 0,
|
||||
27, 18, 72, 107, 64, 101, 32, 0, 24, 182, 255, 32, 64, 110, 32, 0, 26, 254,
|
||||
64, 187, 64, 101, 64, 0, 24, 102, 129, 218, 0, 63, 247, 149, 178, 38, 100,
|
||||
246, 86, 192, 9, 184, 134, 230, 194, 222, 110, 63, 150, 102, 102, 85, 138,
|
||||
188, 43, 64, 81, 228, 41, 192, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 240, 0, 0, 0, 0, 0, 0, 64, 100, 147, 51, 63,
|
||||
205, 146, 189, 64, 96, 153, 153, 160, 125, 112, 225, 64, 100, 224, 0, 12,
|
||||
123, 135, 101, 64, 96, 128, 0, 6, 164, 45, 139, 64, 101, 35, 51, 64, 50,
|
||||
109, 67, 64, 97, 73, 153, 159, 130, 143, 31, 64, 100, 214, 102, 115, 132,
|
||||
120, 155, 64, 97, 99, 51, 57, 91, 210, 117, 0, 192, 33, 131, 192, 140, 90,
|
||||
220, 117, 192, 54, 53, 227, 123, 209, 81, 175, 63, 136, 0, 0, 0, 0, 0, 0,
|
||||
64, 86, 128, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 191, 240, 0, 0, 0, 0, 0, 0, 64, 92, 128, 0, 0, 0, 0, 0, 64,
|
||||
109, 128, 0, 0, 0, 0, 0, 64, 93, 64, 0, 0, 0, 0, 0, 64, 109, 128, 0, 0, 0,
|
||||
0, 0, 64, 93, 64, 0, 0, 0, 0, 0, 64, 109, 224, 0, 0, 0, 0, 0, 64, 92, 128,
|
||||
0, 0, 0, 0, 0, 64, 109, 224, 0, 0, 0, 0, 0, 0, 192, 25, 145, 202, 146, 13,
|
||||
244, 248, 192, 36, 180, 8, 18, 34, 149, 42, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 191, 240, 0, 0, 0, 0, 0, 0, 64, 95, 128, 0, 0, 0, 0, 0, 64, 101, 96, 0,
|
||||
0, 0, 0, 0, 64, 96, 32, 0, 0, 0, 0, 0, 64, 101, 96, 0, 0, 0, 0, 0, 64, 96,
|
||||
32, 0, 0, 0, 0, 0, 64, 101, 160, 0, 0, 0, 0, 0, 64, 95, 128, 0, 0, 0, 0, 0,
|
||||
64, 101, 160, 0, 0, 0, 0, 0, 0, 192, 35, 144, 241, 16, 205, 7, 236, 192, 0,
|
||||
254, 21, 96, 184, 112, 69, 63, 135, 255, 255, 219, 151, 33, 85, 192, 70,
|
||||
128, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 191, 240, 0, 0, 0, 0, 0, 0, 64, 91, 0, 0, 64, 109, 58, 156, 64, 96,
|
||||
96, 0, 31, 237, 203, 144, 64, 91, 192, 0, 63, 219, 151, 34, 64, 96, 0, 0,
|
||||
32, 54, 157, 78, 64, 92, 32, 0, 63, 146, 197, 100, 64, 96, 48, 0, 32, 18,
|
||||
52, 112, 64, 91, 96, 0, 64, 36, 104, 222, 64, 96, 144, 0, 31, 201, 98, 178,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
46
photon-lib/py/test/photonlibpy_test.py
Normal file
46
photon-lib/py/test/photonlibpy_test.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from photonlibpy.packet import Packet
|
||||
from photonlibpy.photonPipelineResult import PhotonPipelineResult
|
||||
from data import rawBytes1
|
||||
from data import rawBytes2
|
||||
from data import rawBytes3
|
||||
from data import rawBytes4
|
||||
from data import rawBytes5
|
||||
from data import rawBytes6
|
||||
|
||||
|
||||
def setupCommon(bytesIn):
|
||||
res = PhotonPipelineResult()
|
||||
packet = Packet(bytesIn)
|
||||
res.populateFromPacket(packet)
|
||||
assert packet.outOfBytes is False
|
||||
return res
|
||||
|
||||
|
||||
def test_byteParse1():
|
||||
res = setupCommon(rawBytes1)
|
||||
assert len(res.getTargets()) == 0
|
||||
|
||||
|
||||
def test_byteParse2():
|
||||
res = setupCommon(rawBytes2)
|
||||
assert len(res.getTargets()) == 0
|
||||
|
||||
|
||||
def test_byteParse3():
|
||||
res = setupCommon(rawBytes3)
|
||||
assert len(res.getTargets()) == 0
|
||||
|
||||
|
||||
def test_byteParse4():
|
||||
res = setupCommon(rawBytes4)
|
||||
assert len(res.getTargets()) == 1
|
||||
|
||||
|
||||
def test_byteParse5():
|
||||
res = setupCommon(rawBytes5)
|
||||
assert len(res.getTargets()) == 1
|
||||
|
||||
|
||||
def test_byteParse6():
|
||||
res = setupCommon(rawBytes6)
|
||||
assert len(res.getTargets()) > 6
|
||||
Reference in New Issue
Block a user