From cba14f5107224802a73c088310119744b6f52925 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 13:07:16 -0500 Subject: [PATCH 01/19] start upgrading to alpha 5 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1e31781372..1d27c8a8e2 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ ext.allOutputsFolder = file("$project.buildDir/outputs") apply from: "versioningHelper.gradle" ext { - wpilibVersion = "2027.0.0-alpha-4" + wpilibVersion = "2027.0.0-alpha-4-109-gf89cf297e" wpimathVersion = wpilibVersion openCVYear = "2025" openCVversion = "4.10.0-3" From a64b7297cd26be974846f39e89f74c56ff6d6ba3 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 13:09:57 -0500 Subject: [PATCH 02/19] thanks tyler --- .../cpp/photon/constrained_solvepnp/wrap/casadi_wrapper.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/wrap/casadi_wrapper.cpp b/photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/wrap/casadi_wrapper.cpp index e92d524427..e6b698c89a 100644 --- a/photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/wrap/casadi_wrapper.cpp +++ b/photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/wrap/casadi_wrapper.cpp @@ -169,8 +169,7 @@ constrained_solvepnp::do_optimization( point_observations.cols() != (nTags * 4)) { if constexpr (VERBOSE) fmt::println("Got unexpected num cols!"); // TODO find a new error code - return wpi::util::unexpected{ - slp::ExitStatus::NONFINITE_INITIAL_COST_OR_CONSTRAINTS}; + return wpi::util::unexpected{slp::ExitStatus::NONFINITE_INITIAL_GUESS}; } // rescale observations to homogenous pixel coordinates @@ -199,8 +198,7 @@ constrained_solvepnp::do_optimization( auto problemOpt = createProblem(nTags, heading_free); if (!problemOpt) { - return wpi::util::unexpected{ - slp::ExitStatus::NONFINITE_INITIAL_COST_OR_CONSTRAINTS}; + return wpi::util::unexpected{slp::ExitStatus::NONFINITE_INITIAL_GUESS}; } ProblemState<3> pState{robot2camera, field2points, point_observations, From 7728fd92e1ede9c4ada5c651b57783f01d92117b Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 13:24:47 -0500 Subject: [PATCH 03/19] fpgatimestamp --> monotonic --- .../design-descriptions/e2e-latency.md | 4 ++-- .../vision/pipe/impl/CalculateFPSPipe.java | 4 ++-- photon-lib/py/photonlibpy/photonCamera.py | 8 ++++---- .../py/photonlibpy/simulation/photonCameraSim.py | 8 ++++---- .../py/photonlibpy/simulation/visionSystemSim.py | 16 ++++++++-------- .../py/photonlibpy/timesync/timeSyncServer.py | 2 +- .../main/java/org/photonvision/PhotonCamera.java | 10 +++++----- .../photonvision/simulation/VisionSystemSim.java | 16 ++++++++-------- .../src/main/native/cpp/photon/PhotonCamera.cpp | 10 +++++----- .../include/photon/simulation/VisionSystemSim.h | 16 ++++++++-------- .../java/org/photonvision/PhotonCameraTest.java | 2 +- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/source/docs/contributing/design-descriptions/e2e-latency.md b/docs/source/docs/contributing/design-descriptions/e2e-latency.md index 7d81b59b44..83870eb0fb 100644 --- a/docs/source/docs/contributing/design-descriptions/e2e-latency.md +++ b/docs/source/docs/contributing/design-descriptions/e2e-latency.md @@ -79,9 +79,9 @@ public class Robot extends TimedRobot { camera.getAllUnreadResults(); } - var t1 = Timer.getFPGATimestamp(); + var t1 = Timer.getMonotonicTimestamp(); light.set(true); - var t2 = Timer.getFPGATimestamp(); + var t2 = Timer.getMonotonicTimestamp(); for (int i = 0; i < 100; i++) { diff --git a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/CalculateFPSPipe.java b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/CalculateFPSPipe.java index 0c2af2c786..b46cb519c4 100644 --- a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/CalculateFPSPipe.java +++ b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/CalculateFPSPipe.java @@ -31,10 +31,10 @@ public class CalculateFPSPipe @Override protected Integer process(Void in) { if (lastTime < 0) { - lastTime = Timer.getFPGATimestamp(); + lastTime = Timer.getMonotonicTimestamp(); } - var now = Timer.getFPGATimestamp(); + var now = Timer.getMonotonicTimestamp(); var dtSeconds = now - lastTime; lastTime = now; diff --git a/photon-lib/py/photonlibpy/photonCamera.py b/photon-lib/py/photonlibpy/photonCamera.py index 653afafa76..25bd573d5f 100644 --- a/photon-lib/py/photonlibpy/photonCamera.py +++ b/photon-lib/py/photonlibpy/photonCamera.py @@ -112,7 +112,7 @@ def __init__(self, cameraName: str): ) self._prevHeartbeat = 0 - self._prevHeartbeatChangeTime = Timer.getFPGATimestamp() + self._prevHeartbeatChangeTime = Timer.getMonotonicTimestamp() # Start the time sync server inst.start() @@ -274,7 +274,7 @@ def isConnected(self) -> bool: """ curHeartbeat = self._heartbeatEntry.get() - now = Timer.getFPGATimestamp() + now = Timer.getMonotonicTimestamp() if curHeartbeat != self._prevHeartbeat: self._prevHeartbeat = curHeartbeat @@ -288,10 +288,10 @@ def _versionCheck(self) -> None: if not _VERSION_CHECK_ENABLED: return - if (Timer.getFPGATimestamp() - _lastVersionTimeCheck) < 5.0: + if (Timer.getMonotonicTimestamp() - _lastVersionTimeCheck) < 5.0: return - _lastVersionTimeCheck = Timer.getFPGATimestamp() + _lastVersionTimeCheck = Timer.getMonotonicTimestamp() # Heartbeat entry is assumed to always be present. If it's not present, we # assume that a camera with that name was never connected in the first place. diff --git a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py index b804d3e0fa..37130a437a 100644 --- a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py +++ b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py @@ -66,7 +66,7 @@ def __init__( # TODO switch this back to default True when the functionality is enabled self.videoSimProcEnabled: bool = False self.heartbeatCounter: int = 0 - self.nextNtEntryTime = wpilib.Timer.getFPGATimestamp() + self.nextNtEntryTime = wpilib.Timer.getMonotonicTimestamp() self.tagLayout = tagLayout self.cam = camera @@ -182,7 +182,7 @@ def consumeNextEntryTime(self) -> float | None: ready """ # check if this camera is ready for another frame update - now = wpilib.Timer.getFPGATimestamp() + now = wpilib.Timer.getMonotonicTimestamp() timestamp = 0.0 iter = 0 # prepare next latest update @@ -434,7 +434,7 @@ def distance(target: VisionTargetSim): # put this simulated data to NT self.heartbeatCounter += 1 - publishTimestampMicros = wpilib.Timer.getFPGATimestamp() * 1e6 + publishTimestampMicros = wpilib.Timer.getMonotonicTimestamp() * 1e6 return PhotonPipelineResult( ntReceiveTimestampMicros=int(publishTimestampMicros + 10), metadata=PhotonPipelineMetadata( @@ -461,7 +461,7 @@ def submitProcessedFrame( :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) """ if receiveTimestamp_us is None: - receiveTimestamp_us = wpilib.Timer.getFPGATimestamp() * 1e6 + receiveTimestamp_us = wpilib.Timer.getMonotonicTimestamp() * 1e6 receiveTimestamp_us = int(receiveTimestamp_us) self.ts.latencyMillisEntry.set(result.getLatencyMillis(), receiveTimestamp_us) diff --git a/photon-lib/py/photonlibpy/simulation/visionSystemSim.py b/photon-lib/py/photonlibpy/simulation/visionSystemSim.py index 7abd3c2045..9b849277a2 100644 --- a/photon-lib/py/photonlibpy/simulation/visionSystemSim.py +++ b/photon-lib/py/photonlibpy/simulation/visionSystemSim.py @@ -69,7 +69,7 @@ def addCamera(self, cameraSim: PhotonCameraSim, robotToCamera: Transform3d) -> N self.bufferLength ) self.camTrfMap[cameraSim].addSample( - wpilib.Timer.getFPGATimestamp(), Pose3d() + robotToCamera + wpilib.Timer.getMonotonicTimestamp(), Pose3d() + robotToCamera ) def clearCameras(self) -> None: @@ -92,7 +92,7 @@ def removeCamera(self, cameraSim: PhotonCameraSim) -> bool: def getRobotToCamera( self, cameraSim: PhotonCameraSim, - time: seconds = wpilib.Timer.getFPGATimestamp(), + time: seconds = wpilib.Timer.getMonotonicTimestamp(), ) -> Transform3d | None: """Get a simulated camera's position relative to the robot. If the requested camera is invalid, an empty optional is returned. @@ -115,7 +115,7 @@ def getRobotToCamera( def getCameraPose( self, cameraSim: PhotonCameraSim, - time: seconds = wpilib.Timer.getFPGATimestamp(), + time: seconds = wpilib.Timer.getMonotonicTimestamp(), ) -> Pose3d | None: """Get a simulated camera's position on the field. If the requested camera is invalid, an empty optional is returned. @@ -147,7 +147,7 @@ def adjustCamera( """ if cameraSim in self.camTrfMap: self.camTrfMap[cameraSim].addSample( - wpilib.Timer.getFPGATimestamp(), Pose3d() + robotToCamera + wpilib.Timer.getMonotonicTimestamp(), Pose3d() + robotToCamera ) return True else: @@ -155,7 +155,7 @@ def adjustCamera( def resetCameraTransforms(self, cameraSim: PhotonCameraSim | None = None) -> None: """Reset the transform history for this camera to just the current transform.""" - now = wpilib.Timer.getFPGATimestamp() + now = wpilib.Timer.getMonotonicTimestamp() def resetSingleCamera(self, cameraSim: PhotonCameraSim) -> bool: if cameraSim in self.camTrfMap: @@ -241,7 +241,7 @@ def removeVisionTargets( return removedList def getRobotPose( - self, timestamp: seconds = wpilib.Timer.getFPGATimestamp() + self, timestamp: seconds = wpilib.Timer.getMonotonicTimestamp() ) -> Pose3d | None: """Get the robot pose in meters saved by the vision system at this timestamp. @@ -257,7 +257,7 @@ def resetRobotPose(self, robotPose: Pose2d | Pose3d) -> None: assert type(robotPose) is Pose3d self.robotPoseBuffer.clear() - self.robotPoseBuffer.addSample(wpilib.Timer.getFPGATimestamp(), robotPose) + self.robotPoseBuffer.addSample(wpilib.Timer.getMonotonicTimestamp(), robotPose) def getDebugField(self) -> Field2d: return self.dbgField @@ -280,7 +280,7 @@ def update(self, robotPose: Pose2d | Pose3d) -> None: self.dbgField.getObject(targetType).setPoses(posesToAdd) # save "real" robot poses over time - now = wpilib.Timer.getFPGATimestamp() + now = wpilib.Timer.getMonotonicTimestamp() self.robotPoseBuffer.addSample(now, robotPose) self.dbgField.setRobotPose(robotPose.toPose2d()) diff --git a/photon-lib/py/photonlibpy/timesync/timeSyncServer.py b/photon-lib/py/photonlibpy/timesync/timeSyncServer.py index f7a860dd97..69fc838b8b 100644 --- a/photon-lib/py/photonlibpy/timesync/timeSyncServer.py +++ b/photon-lib/py/photonlibpy/timesync/timeSyncServer.py @@ -53,7 +53,7 @@ class TimeSyncServer: PORT = 5810 def __init__(self, time_provider: Optional[Callable[[], int]] = None): - self.time_provider = time_provider or Timer.getFPGATimestamp + self.time_provider = time_provider or Timer.getMonotonicTimestamp self._process: Optional[threading.Thread] = None self.logger = logging.getLogger("PhotonVision-TimeSyncServer") diff --git a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java index c16fa36f45..b90d5e1b0f 100644 --- a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java +++ b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java @@ -310,8 +310,8 @@ private void checkTimeSyncOrWarn(PhotonPipelineResult result) { timesyncAlert.setText(warningText); timesyncAlert.set(true); - if (Timer.getFPGATimestamp() > (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { - prevTimeSyncWarnTime = Timer.getFPGATimestamp(); + if (Timer.getMonotonicTimestamp() > (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { + prevTimeSyncWarnTime = Timer.getMonotonicTimestamp(); DriverStation.reportWarning( warningText @@ -441,7 +441,7 @@ public String getName() { */ public boolean isConnected() { var curHeartbeat = heartbeatSubscriber.get(); - var now = Timer.getFPGATimestamp(); + var now = Timer.getMonotonicTimestamp(); if (curHeartbeat < 0) { // we have never heard from the camera @@ -494,8 +494,8 @@ public final NetworkTable getCameraTable() { void verifyVersion() { if (!VERSION_CHECK_ENABLED) return; - if ((Timer.getFPGATimestamp() - lastVersionCheckTime) < VERSION_CHECK_INTERVAL) return; - lastVersionCheckTime = Timer.getFPGATimestamp(); + if ((Timer.getMonotonicTimestamp() - lastVersionCheckTime) < VERSION_CHECK_INTERVAL) return; + lastVersionCheckTime = Timer.getMonotonicTimestamp(); // Heartbeat entry is assumed to always be present. If it's not present, we // assume that a camera with that name was never connected in the first place. diff --git a/photon-lib/src/main/java/org/photonvision/simulation/VisionSystemSim.java b/photon-lib/src/main/java/org/photonvision/simulation/VisionSystemSim.java index a2dca15cfd..46491defed 100644 --- a/photon-lib/src/main/java/org/photonvision/simulation/VisionSystemSim.java +++ b/photon-lib/src/main/java/org/photonvision/simulation/VisionSystemSim.java @@ -106,7 +106,7 @@ public void addCamera(PhotonCameraSim cameraSim, Transform3d robotToCamera) { camTrfMap.put(cameraSim, TimeInterpolatableBuffer.createBuffer(kBufferLengthSeconds)); camTrfMap .get(cameraSim) - .addSample(Timer.getFPGATimestamp(), new Pose3d().plus(robotToCamera)); + .addSample(Timer.getMonotonicTimestamp(), new Pose3d().plus(robotToCamera)); } } @@ -137,7 +137,7 @@ public boolean removeCamera(PhotonCameraSim cameraSim) { * @return The transform of this camera, or an empty optional if it is invalid */ public Optional getRobotToCamera(PhotonCameraSim cameraSim) { - return getRobotToCamera(cameraSim, Timer.getFPGATimestamp()); + return getRobotToCamera(cameraSim, Timer.getMonotonicTimestamp()); } /** @@ -164,7 +164,7 @@ public Optional getRobotToCamera(PhotonCameraSim cameraSim, double * @return The pose of this camera, or an empty optional if it is invalid */ public Optional getCameraPose(PhotonCameraSim cameraSim) { - return getCameraPose(cameraSim, Timer.getFPGATimestamp()); + return getCameraPose(cameraSim, Timer.getMonotonicTimestamp()); } /** @@ -191,7 +191,7 @@ public Optional getCameraPose(PhotonCameraSim cameraSim, double timeSeco public boolean adjustCamera(PhotonCameraSim cameraSim, Transform3d robotToCamera) { var trfBuffer = camTrfMap.get(cameraSim); if (trfBuffer == null) return false; - trfBuffer.addSample(Timer.getFPGATimestamp(), new Pose3d().plus(robotToCamera)); + trfBuffer.addSample(Timer.getMonotonicTimestamp(), new Pose3d().plus(robotToCamera)); return true; } @@ -207,7 +207,7 @@ public void resetCameraTransforms() { * @return If the cameraSim was valid and transforms were reset */ public boolean resetCameraTransforms(PhotonCameraSim cameraSim) { - double now = Timer.getFPGATimestamp(); + double now = Timer.getMonotonicTimestamp(); var trfBuffer = camTrfMap.get(cameraSim); if (trfBuffer == null) return false; var lastTrf = new Transform3d(new Pose3d(), trfBuffer.getSample(now).orElse(new Pose3d())); @@ -339,7 +339,7 @@ public Set removeVisionTargets(VisionTargetSim... targets) { * @return The latest robot pose */ public Pose3d getRobotPose() { - return getRobotPose(Timer.getFPGATimestamp()); + return getRobotPose(Timer.getMonotonicTimestamp()); } /** @@ -368,7 +368,7 @@ public void resetRobotPose(Pose2d robotPose) { */ public void resetRobotPose(Pose3d robotPose) { robotPoseBuffer.clear(); - robotPoseBuffer.addSample(Timer.getFPGATimestamp(), robotPose); + robotPoseBuffer.addSample(Timer.getMonotonicTimestamp(), robotPose); } public Field2d getDebugField() { @@ -403,7 +403,7 @@ public void update(Pose3d robotPoseMeters) { if (robotPoseMeters == null) return; // save "real" robot poses over time - double now = Timer.getFPGATimestamp(); + double now = Timer.getMonotonicTimestamp(); robotPoseBuffer.addSample(now, robotPoseMeters); dbgField.setRobotPose(robotPoseMeters.toPose2d()); diff --git a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp index cd69705185..f1e5d461d8 100644 --- a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp +++ b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp @@ -263,9 +263,9 @@ void PhotonCamera::CheckTimeSyncOrWarn(photon::PhotonPipelineResult& result) { timesyncAlert.SetText(warningText); timesyncAlert.Set(true); - if (wpi::Timer::GetFPGATimestamp() < + if (wpi::Timer::getMonotonicTimestamp() < (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { - prevTimeSyncWarnTime = wpi::Timer::GetFPGATimestamp(); + prevTimeSyncWarnTime = wpi::Timer::getMonotonicTimestamp(); WPILIB_ReportWarning( warningText + @@ -319,7 +319,7 @@ const std::string_view PhotonCamera::GetCameraName() const { bool PhotonCamera::IsConnected() { auto currentHeartbeat = heartbeatSubscriber.Get(); - auto now = wpi::Timer::GetFPGATimestamp(); + auto now = wpi::Timer::getMonotonicTimestamp(); if (currentHeartbeat < 0) { // we have never heard from the camera @@ -367,10 +367,10 @@ void PhotonCamera::VerifyVersion() { return; } - if ((wpi::Timer::GetFPGATimestamp() - lastVersionCheckTime) < + if ((wpi::Timer::getMonotonicTimestamp() - lastVersionCheckTime) < VERSION_CHECK_INTERVAL) return; - this->lastVersionCheckTime = wpi::Timer::GetFPGATimestamp(); + this->lastVersionCheckTime = wpi::Timer::getMonotonicTimestamp(); const std::string& versionString = versionEntry.Get(""); if (versionString.empty()) { diff --git a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h index 95a76326f5..b0e8708fe4 100644 --- a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h +++ b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h @@ -101,7 +101,7 @@ class VisionSystemSim { std::make_pair(std::move(cameraSim), wpi::math::TimeInterpolatableBuffer{ bufferLength})); - camTrfMap.at(cameraSim).AddSample(wpi::Timer::GetFPGATimestamp(), + camTrfMap.at(cameraSim).AddSample(wpi::Timer::getMonotonicTimestamp(), wpi::math::Pose3d{} + robotToCamera); } } @@ -138,7 +138,7 @@ class VisionSystemSim { */ std::optional GetRobotToCamera( PhotonCameraSim* cameraSim) { - return GetRobotToCamera(cameraSim, wpi::Timer::GetFPGATimestamp()); + return GetRobotToCamera(cameraSim, wpi::Timer::getMonotonicTimestamp()); } /** @@ -175,7 +175,7 @@ class VisionSystemSim { * @return The pose of this camera, or an empty optional if it is invalid */ std::optional GetCameraPose(PhotonCameraSim* cameraSim) { - return GetCameraPose(cameraSim, wpi::Timer::GetFPGATimestamp()); + return GetCameraPose(cameraSim, wpi::Timer::getMonotonicTimestamp()); } /** @@ -207,7 +207,7 @@ class VisionSystemSim { bool AdjustCamera(PhotonCameraSim* cameraSim, const wpi::math::Transform3d& robotToCamera) { if (camTrfMap.find(cameraSim) != camTrfMap.end()) { - camTrfMap.at(cameraSim).AddSample(wpi::Timer::GetFPGATimestamp(), + camTrfMap.at(cameraSim).AddSample(wpi::Timer::getMonotonicTimestamp(), wpi::math::Pose3d{} + robotToCamera); return true; } else { @@ -230,7 +230,7 @@ class VisionSystemSim { * @return If the cameraSim was valid and transforms were reset */ bool ResetCameraTransforms(PhotonCameraSim* cameraSim) { - wpi::units::second_t now = wpi::Timer::GetFPGATimestamp(); + wpi::units::second_t now = wpi::Timer::getMonotonicTimestamp(); if (camTrfMap.find(cameraSim) != camTrfMap.end()) { auto trfBuffer = camTrfMap.at(cameraSim); wpi::math::Transform3d lastTrf{ @@ -369,7 +369,7 @@ class VisionSystemSim { * @return The latest robot pose */ wpi::math::Pose3d GetRobotPose() { - return GetRobotPose(wpi::Timer::GetFPGATimestamp()); + return GetRobotPose(wpi::Timer::getMonotonicTimestamp()); } /** @@ -398,7 +398,7 @@ class VisionSystemSim { */ void ResetRobotPose(const wpi::math::Pose3d& robotPose) { robotPoseBuffer.Clear(); - robotPoseBuffer.AddSample(wpi::Timer::GetFPGATimestamp(), robotPose); + robotPoseBuffer.AddSample(wpi::Timer::getMonotonicTimestamp(), robotPose); } wpi::Field2d& GetDebugField() { return dbgField; } @@ -427,7 +427,7 @@ class VisionSystemSim { dbgField.GetObject(set.first)->SetPoses(posesToAdd); } - wpi::units::second_t now = wpi::Timer::GetFPGATimestamp(); + wpi::units::second_t now = wpi::Timer::getMonotonicTimestamp(); robotPoseBuffer.AddSample(now, robotPose); dbgField.SetRobotPose(robotPose.ToPose2d()); diff --git a/photon-lib/src/test/java/org/photonvision/PhotonCameraTest.java b/photon-lib/src/test/java/org/photonvision/PhotonCameraTest.java index 04cb0364de..2edbed5a33 100644 --- a/photon-lib/src/test/java/org/photonvision/PhotonCameraTest.java +++ b/photon-lib/src/test/java/org/photonvision/PhotonCameraTest.java @@ -125,7 +125,7 @@ public void testTimeSyncServerWithPhotonCamera() throws InterruptedException, IO var res = camera.getLatestResult(); var captureTime = res.getTimestampSeconds(); - var now = Timer.getFPGATimestamp(); + var now = Timer.getMonotonicTimestamp(); // expectTrue(captureTime < now); From 7c4e87521aa7b0c0ae489047ae51bd8a39bda534 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 13:31:12 -0500 Subject: [PATCH 04/19] update pixel format --- .../vision/camera/FileVisionSource.java | 2 +- .../USBCameras/GenericUSBCameraSettables.java | 4 +-- .../camera/csi/LibcameraGpuSettables.java | 30 +++++++++---------- .../frame/consumer/MJPGFrameConsumer.java | 2 +- .../frame/provider/USBFrameProvider.java | 2 +- .../photonlibpy/simulation/photonCameraSim.py | 4 +-- .../simulation/PhotonCameraSim.java | 2 +- .../src/test/java/jni/CscoreExtrasTest.java | 4 +-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java b/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java index 59e15ca59f..5e56f9b152 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/FileVisionSource.java @@ -108,7 +108,7 @@ public static class FileSourceSettables extends VisionSourceSettables { this.frameStaticProperties = frameStaticProperties; videoMode = new VideoMode( - PixelFormat.kMJPEG, + PixelFormat.MJPEG, frameStaticProperties.imageWidth, frameStaticProperties.imageHeight, 30); diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/GenericUSBCameraSettables.java b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/GenericUSBCameraSettables.java index 24c97a41d6..b50a71175a 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/GenericUSBCameraSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/USBCameras/GenericUSBCameraSettables.java @@ -291,8 +291,8 @@ private void cacheVideoModes() { try { for (VideoMode videoMode : camera.enumerateVideoModes()) { // Filter grey modes - if (videoMode.pixelFormat == PixelFormat.kGray - || videoMode.pixelFormat == PixelFormat.kUnknown) { + if (videoMode.pixelFormat == PixelFormat.GRAY + || videoMode.pixelFormat == PixelFormat.UNKNOWN) { continue; } diff --git a/photon-core/src/main/java/org/photonvision/vision/camera/csi/LibcameraGpuSettables.java b/photon-core/src/main/java/org/photonvision/vision/camera/csi/LibcameraGpuSettables.java index 3abbe04988..7ffce73e95 100644 --- a/photon-core/src/main/java/org/photonvision/vision/camera/csi/LibcameraGpuSettables.java +++ b/photon-core/src/main/java/org/photonvision/vision/camera/csi/LibcameraGpuSettables.java @@ -67,18 +67,18 @@ public LibcameraGpuSettables(CameraConfiguration configuration) { if (sensorModel == LibCameraJNI.SensorModel.IMX219) { // Settings for the IMX219 sensor, which is used on the Pi Camera Module v2 - videoModes.put(0, new FPSRatedVideoMode(PixelFormat.kUnknown, 320, 240, 120, 120, .39)); - videoModes.put(1, new FPSRatedVideoMode(PixelFormat.kUnknown, 320, 240, 30, 30, .39)); - videoModes.put(2, new FPSRatedVideoMode(PixelFormat.kUnknown, 640, 480, 65, 90, .39)); - videoModes.put(3, new FPSRatedVideoMode(PixelFormat.kUnknown, 640, 480, 30, 30, .39)); + videoModes.put(0, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 320, 240, 120, 120, .39)); + videoModes.put(1, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 320, 240, 30, 30, .39)); + videoModes.put(2, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 640, 480, 65, 90, .39)); + videoModes.put(3, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 640, 480, 30, 30, .39)); // TODO: fix 1280x720 in the native code and re-add it - videoModes.put(4, new FPSRatedVideoMode(PixelFormat.kUnknown, 1920, 1080, 15, 20, .53)); - videoModes.put(5, new FPSRatedVideoMode(PixelFormat.kUnknown, 3280 / 2, 2464 / 2, 15, 20, 1)); - videoModes.put(6, new FPSRatedVideoMode(PixelFormat.kUnknown, 3280 / 4, 2464 / 4, 15, 20, 1)); + videoModes.put(4, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 1920, 1080, 15, 20, .53)); + videoModes.put(5, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 3280 / 2, 2464 / 2, 15, 20, 1)); + videoModes.put(6, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 3280 / 4, 2464 / 4, 15, 20, 1)); } else if (sensorModel == LibCameraJNI.SensorModel.OV9281) { // Taken from https://www.ovt.com/wp-content/uploads/2022/01/OV9281-OV9282-PB-v1.3-WEB.pdf - videoModes.put(0, new FPSRatedVideoMode(PixelFormat.kUnknown, 640, 400, 120, 240, 1)); - videoModes.put(1, new FPSRatedVideoMode(PixelFormat.kUnknown, 1280, 800, 120, 120, 1)); + videoModes.put(0, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 640, 400, 120, 240, 1)); + videoModes.put(1, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 1280, 800, 120, 120, 1)); } else { if (sensorModel == LibCameraJNI.SensorModel.IMX477) { @@ -93,13 +93,13 @@ public LibcameraGpuSettables(CameraConfiguration configuration) { } // Settings for the OV5647 sensor, which is used by the Pi Camera Module v1 - videoModes.put(0, new FPSRatedVideoMode(PixelFormat.kUnknown, 320, 240, 90, 90, 1)); - videoModes.put(1, new FPSRatedVideoMode(PixelFormat.kUnknown, 640, 480, 85, 90, 1)); - videoModes.put(2, new FPSRatedVideoMode(PixelFormat.kUnknown, 960, 720, 45, 49, 0.74)); + videoModes.put(0, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 320, 240, 90, 90, 1)); + videoModes.put(1, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 640, 480, 85, 90, 1)); + videoModes.put(2, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 960, 720, 45, 49, 0.74)); // Half the size of the active areas on the OV5647 - videoModes.put(3, new FPSRatedVideoMode(PixelFormat.kUnknown, 2592 / 2, 1944 / 2, 20, 20, 1)); - videoModes.put(4, new FPSRatedVideoMode(PixelFormat.kUnknown, 1280, 720, 30, 45, 0.91)); - videoModes.put(5, new FPSRatedVideoMode(PixelFormat.kUnknown, 1920, 1080, 15, 20, 0.72)); + videoModes.put(3, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 2592 / 2, 1944 / 2, 20, 20, 1)); + videoModes.put(4, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 1280, 720, 30, 45, 0.91)); + videoModes.put(5, new FPSRatedVideoMode(PixelFormat.UNKNOWN, 1920, 1080, 15, 20, 0.72)); } // TODO need to add more video modes for new sensors here diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/MJPGFrameConsumer.java b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/MJPGFrameConsumer.java index 167634eec1..6c39692488 100644 --- a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/MJPGFrameConsumer.java +++ b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/MJPGFrameConsumer.java @@ -33,7 +33,7 @@ public class MJPGFrameConsumer implements AutoCloseable { private MjpegServer mjpegServer; public MJPGFrameConsumer(String sourceName, int width, int height, int port) { - this.cvSource = new CvSource(sourceName, PixelFormat.kMJPEG, width, height, 30); + this.cvSource = new CvSource(sourceName, PixelFormat.MJPEG, width, height, 30); this.mjpegServer = new MjpegServer("serve_" + cvSource.getName(), port); mjpegServer.setSource(cvSource); diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java b/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java index fff866e689..742d41e2f8 100644 --- a/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java +++ b/photon-core/src/main/java/org/photonvision/vision/frame/provider/USBFrameProvider.java @@ -103,7 +103,7 @@ public CapturedFrame getInputMat() { cameraMode.height, // hard-coded 3 channel cameraMode.width * 3, - PixelFormat.kBGR); + PixelFormat.BGR); // This is from wpi::nt::Now, or WPIUtilJNI.now(). The epoch from grabFrame is uS since // Hal::initialize was called diff --git a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py index 37130a437a..e27ecd0307 100644 --- a/photon-lib/py/photonlibpy/simulation/photonCameraSim.py +++ b/photon-lib/py/photonlibpy/simulation/photonCameraSim.py @@ -76,7 +76,7 @@ def __init__( # TODO Check fps is right self.videoSimRaw = cs.CvSource( self.cam.getName() + "-raw", - cs.VideoMode.PixelFormat.kGray, + cs.VideoMode.PixelFormat.GRAY, self.prop.getResWidth(), self.prop.getResHeight(), 1, @@ -88,7 +88,7 @@ def __init__( # TODO Check fps is right self.videoSimProcessed = cs.CvSource( self.cam.getName() + "-processed", - cs.VideoMode.PixelFormat.kGray, + cs.VideoMode.PixelFormat.GRAY, self.prop.getResWidth(), self.prop.getResHeight(), 1, diff --git a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java index 1b7eba56f3..b3a2331651 100644 --- a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java +++ b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java @@ -153,7 +153,7 @@ public PhotonCameraSim( videoSimRaw = CameraServer.putVideo(camera.getName() + "-raw", prop.getResWidth(), prop.getResHeight()); - videoSimRaw.setPixelFormat(PixelFormat.kGray); + videoSimRaw.setPixelFormat(PixelFormat.GRAY); videoSimProcessed = CameraServer.putVideo( camera.getName() + "-processed", prop.getResWidth(), prop.getResHeight()); diff --git a/photon-targeting/src/test/java/jni/CscoreExtrasTest.java b/photon-targeting/src/test/java/jni/CscoreExtrasTest.java index 9816a5e6e7..2cefdd3c01 100644 --- a/photon-targeting/src/test/java/jni/CscoreExtrasTest.java +++ b/photon-targeting/src/test/java/jni/CscoreExtrasTest.java @@ -59,7 +59,7 @@ public void testCaptureImage() { UsbCamera camera = CameraServer.startAutomaticCapture(2); - camera.setVideoMode(PixelFormat.kMJPEG, 1280, 720, 30); + camera.setVideoMode(PixelFormat.MJPEG, 1280, 720, 30); var cameraMode = camera.getVideoMode(); CvSink cvSink = CameraServer.getVideo(camera); @@ -74,7 +74,7 @@ public void testCaptureImage() { cameraMode.height, // hard-coded 3 channel cameraMode.width * 3, - PixelFormat.kBGR); + PixelFormat.BGR); final double CSCORE_DEFAULT_FRAME_TIMEOUT = 1.0 / 4.0; long time = CscoreExtras.grabRawSinkFrameTimeoutLastTime( From 03d1998c40b40e4c610d454b5a8c0b1b40fe0ce9 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 13:41:14 -0500 Subject: [PATCH 05/19] whee it works --- .../networktables/NTDataChangeListener.java | 2 +- .../dataflow/networktables/NTDriverStation.java | 4 ++-- .../networktables/NetworkTablesManager.java | 16 ++++++++-------- .../frame/consumer/FileSaveFrameConsumer.java | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDataChangeListener.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDataChangeListener.java index 2d3ae4df78..c66fbb5ec2 100644 --- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDataChangeListener.java +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDataChangeListener.java @@ -36,7 +36,7 @@ public NTDataChangeListener( this.instance = instance; listenerID = this.instance.addListener( - watchedEntry, EnumSet.of(NetworkTableEvent.Kind.kValueAll), dataChangeConsumer); + watchedEntry, EnumSet.of(NetworkTableEvent.Kind.VALUE_ALL), dataChangeConsumer); } public void remove() { diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDriverStation.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDriverStation.java index 5001972395..28fec29b7b 100644 --- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDriverStation.java +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NTDriverStation.java @@ -68,9 +68,9 @@ public NTDriverStation(NetworkTableInstance inst) { fmsTable.addListener( "FMSControlData", - EnumSet.of(Kind.kValueAll), + EnumSet.of(Kind.VALUE_ALL), (table, key, event) -> { - if (event.is(Kind.kValueAll) && event.valueData.value.isInteger()) { + if (event.is(Kind.VALUE_ALL) && event.valueData.value.isInteger()) { // Logger totally isnt thread safe but whatevs var word = NTDriverStation.getControlWord(event.valueData.value.getInteger()); diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java index 5f0e37ba73..ed305cd5c2 100644 --- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java @@ -85,11 +85,11 @@ public class NetworkTablesManager { private NetworkTablesManager() { ntInstance.addLogger( - LogMessage.kInfo, LogMessage.kCritical, this::logNtMessage); // to hide error messages + LogMessage.INFO, LogMessage.CRITICAL, this::logNtMessage); // to hide error messages ntInstance.addConnectionListener(true, this::checkNtConnectState); // to hide error messages ntInstance.addListener( - m_fieldLayoutSubscriber, EnumSet.of(Kind.kValueAll), this::onFieldLayoutChanged); + m_fieldLayoutSubscriber, EnumSet.of(Kind.VALUE_ALL), this::onFieldLayoutChanged); ntDriverStation = new NTDriverStation(this.getNTInst()); @@ -126,16 +126,16 @@ public void setMismatchAlert(boolean on, String message) { private void logNtMessage(NetworkTableEvent event) { String levelmsg = "DEBUG"; LogLevel pvlevel = LogLevel.DEBUG; - if (event.logMessage.level >= LogMessage.kCritical) { + if (event.logMessage.level >= LogMessage.CRITICAL) { pvlevel = LogLevel.ERROR; levelmsg = "CRITICAL"; - } else if (event.logMessage.level >= LogMessage.kError) { + } else if (event.logMessage.level >= LogMessage.ERROR) { pvlevel = LogLevel.ERROR; levelmsg = "ERROR"; - } else if (event.logMessage.level >= LogMessage.kWarning) { + } else if (event.logMessage.level >= LogMessage.WARNING) { pvlevel = LogLevel.WARN; levelmsg = "WARNING"; - } else if (event.logMessage.level >= LogMessage.kInfo) { + } else if (event.logMessage.level >= LogMessage.INFO) { pvlevel = LogLevel.INFO; levelmsg = "INFO"; } @@ -156,8 +156,8 @@ private void logNtMessage(NetworkTableEvent event) { } public void checkNtConnectState(NetworkTableEvent event) { - var isConnEvent = event.is(Kind.kConnected); - var isDisconnEvent = event.is(Kind.kDisconnected); + var isConnEvent = event.is(Kind.DISCONNECTED); + var isDisconnEvent = event.is(Kind.DISCONNECTED); if (isDisconnEvent) { var msg = diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java index 56d1ab7f20..9bb3d48bfb 100644 --- a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java +++ b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java @@ -165,7 +165,7 @@ private String getMatchData() { logger.warn("Did not receive event name, defaulting to 'UNKNOWN'"); } - MatchType wpiMatchType = MatchType.None; // Default is to be unknown + MatchType wpiMatchType = MatchType.NONE; // Default is to be unknown if (matchType.value < 0 || matchType.value >= MatchType.values().length) { logger.error("Invalid match type from FMS: " + matchType.value); } else { From f25e900250dc7313a96709b6d147a71020d1c016 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 14:56:48 -0500 Subject: [PATCH 06/19] fix a bit --- .../main/java/org/photonvision/simulation/PhotonCameraSim.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java index b3a2331651..ebbe59cb2d 100644 --- a/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java +++ b/photon-lib/src/main/java/org/photonvision/simulation/PhotonCameraSim.java @@ -649,7 +649,7 @@ public PhotonPipelineResult process( } // put this simulated data to NT - var now = RobotController.getFPGATime(); + var now = RobotController.getMonotonicTime(); var ret = new PhotonPipelineResult( heartbeatCounter, From 2c7c3b86dcaf8dc2668c66a3304b3218ece64ee8 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 16:03:58 -0500 Subject: [PATCH 07/19] oops, missed that --- .../src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp b/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp index d3f18b1c64..8be6e0bec1 100644 --- a/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp +++ b/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp @@ -51,7 +51,7 @@ PhotonCameraSim::PhotonCameraSim( videoSimRaw = wpi::CameraServer::PutVideo(std::string{camera->GetCameraName()} + "-raw", prop.GetResWidth(), prop.GetResHeight()); - videoSimRaw.SetPixelFormat(wpi::util::PixelFormat::kGray); + videoSimRaw.SetPixelFormat(wpi::util::PixelFormat::GRAY); videoSimProcessed = wpi::CameraServer::PutVideo( std::string{camera->GetCameraName()} + "-processed", prop.GetResWidth(), prop.GetResHeight()); From 0fc5720fabd8fb0ed1521c4c8b8f0a9944197609 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 16:07:42 -0500 Subject: [PATCH 08/19] caps --- photon-lib/py/photonlibpy/photonCamera.py | 2 +- .../src/main/native/cpp/photon/PhotonCamera.cpp | 13 ++++++------- .../include/photon/simulation/VisionSystemSim.h | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/photon-lib/py/photonlibpy/photonCamera.py b/photon-lib/py/photonlibpy/photonCamera.py index 25bd573d5f..a7782d4c2c 100644 --- a/photon-lib/py/photonlibpy/photonCamera.py +++ b/photon-lib/py/photonlibpy/photonCamera.py @@ -163,7 +163,7 @@ def getLatestResult(self) -> PhotonPipelineResult: self._versionCheck() - now = RobotController.getFPGATime() + now = RobotController.getMonotonicTime() packetWithTimestamp = self._rawBytesEntry.getAtomic() byteList = packetWithTimestamp.value packetWithTimestamp.time diff --git a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp index f1e5d461d8..fa050d8158 100644 --- a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp +++ b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp @@ -193,7 +193,7 @@ PhotonPipelineResult PhotonCamera::GetLatestResult() { // Fill the packet with latest data and populate result. wpi::units::microsecond_t now = - wpi::units::microsecond_t(wpi::RobotController::GetFPGATime()); + wpi::units::microsecond_t(wpi::RobotController::GetMonotonicTime()); const auto value = rawBytesEntry.Get(); if (!value.size()) return PhotonPipelineResult{}; @@ -263,9 +263,9 @@ void PhotonCamera::CheckTimeSyncOrWarn(photon::PhotonPipelineResult& result) { timesyncAlert.SetText(warningText); timesyncAlert.Set(true); - if (wpi::Timer::getMonotonicTimestamp() < + if (wpi::Timer::GetMonotonicTimestamp() < (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { - prevTimeSyncWarnTime = wpi::Timer::getMonotonicTimestamp(); + prevTimeSyncWarnTime = wpi::Timer::GetMonotonicTimestamp(); WPILIB_ReportWarning( warningText + @@ -319,7 +319,7 @@ const std::string_view PhotonCamera::GetCameraName() const { bool PhotonCamera::IsConnected() { auto currentHeartbeat = heartbeatSubscriber.Get(); - auto now = wpi::Timer::getMonotonicTimestamp(); + auto now = wpi::Timer::GetMonotonicTimestamp(); if (currentHeartbeat < 0) { // we have never heard from the camera @@ -367,10 +367,9 @@ void PhotonCamera::VerifyVersion() { return; } - if ((wpi::Timer::getMonotonicTimestamp() - lastVersionCheckTime) < - VERSION_CHECK_INTERVAL) + if ((wpi::Timer::GetMonotonicTimestamp() - lastVersionCheckTime) < VERSION_CHECK_INTERVAL) return; - this->lastVersionCheckTime = wpi::Timer::getMonotonicTimestamp(); + this->lastVersionCheckTime = wpi::Timer::GetMonotonicTimestamp(); const std::string& versionString = versionEntry.Get(""); if (versionString.empty()) { diff --git a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h index b0e8708fe4..55b76d0f4f 100644 --- a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h +++ b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h @@ -101,7 +101,7 @@ class VisionSystemSim { std::make_pair(std::move(cameraSim), wpi::math::TimeInterpolatableBuffer{ bufferLength})); - camTrfMap.at(cameraSim).AddSample(wpi::Timer::getMonotonicTimestamp(), + camTrfMap.at(cameraSim).AddSample(wpi::Timer::GetMonotonicTimestamp(), wpi::math::Pose3d{} + robotToCamera); } } @@ -138,7 +138,7 @@ class VisionSystemSim { */ std::optional GetRobotToCamera( PhotonCameraSim* cameraSim) { - return GetRobotToCamera(cameraSim, wpi::Timer::getMonotonicTimestamp()); + return GetRobotToCamera(cameraSim, wpi::Timer::GetMonotonicTimestamp()); } /** From c2f6228b1f2bb5f2cc86e010863443613466531e Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 16:20:26 -0500 Subject: [PATCH 09/19] lint --- photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp index fa050d8158..48f5d1c3b8 100644 --- a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp +++ b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp @@ -367,7 +367,8 @@ void PhotonCamera::VerifyVersion() { return; } - if ((wpi::Timer::GetMonotonicTimestamp() - lastVersionCheckTime) < VERSION_CHECK_INTERVAL) + if ((wpi::Timer::GetMonotonicTimestamp() - lastVersionCheckTime) < + VERSION_CHECK_INTERVAL) return; this->lastVersionCheckTime = wpi::Timer::GetMonotonicTimestamp(); From 9481160b1a8191cad7e6810bb2d76e6354c3fe31 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 16:31:42 -0500 Subject: [PATCH 10/19] gah --- .../include/photon/simulation/VisionSystemSim.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h index 55b76d0f4f..f0338af82f 100644 --- a/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h +++ b/photon-lib/src/main/native/include/photon/simulation/VisionSystemSim.h @@ -175,7 +175,7 @@ class VisionSystemSim { * @return The pose of this camera, or an empty optional if it is invalid */ std::optional GetCameraPose(PhotonCameraSim* cameraSim) { - return GetCameraPose(cameraSim, wpi::Timer::getMonotonicTimestamp()); + return GetCameraPose(cameraSim, wpi::Timer::GetMonotonicTimestamp()); } /** @@ -207,7 +207,7 @@ class VisionSystemSim { bool AdjustCamera(PhotonCameraSim* cameraSim, const wpi::math::Transform3d& robotToCamera) { if (camTrfMap.find(cameraSim) != camTrfMap.end()) { - camTrfMap.at(cameraSim).AddSample(wpi::Timer::getMonotonicTimestamp(), + camTrfMap.at(cameraSim).AddSample(wpi::Timer::GetMonotonicTimestamp(), wpi::math::Pose3d{} + robotToCamera); return true; } else { @@ -230,7 +230,7 @@ class VisionSystemSim { * @return If the cameraSim was valid and transforms were reset */ bool ResetCameraTransforms(PhotonCameraSim* cameraSim) { - wpi::units::second_t now = wpi::Timer::getMonotonicTimestamp(); + wpi::units::second_t now = wpi::Timer::GetMonotonicTimestamp(); if (camTrfMap.find(cameraSim) != camTrfMap.end()) { auto trfBuffer = camTrfMap.at(cameraSim); wpi::math::Transform3d lastTrf{ @@ -369,7 +369,7 @@ class VisionSystemSim { * @return The latest robot pose */ wpi::math::Pose3d GetRobotPose() { - return GetRobotPose(wpi::Timer::getMonotonicTimestamp()); + return GetRobotPose(wpi::Timer::GetMonotonicTimestamp()); } /** @@ -398,7 +398,7 @@ class VisionSystemSim { */ void ResetRobotPose(const wpi::math::Pose3d& robotPose) { robotPoseBuffer.Clear(); - robotPoseBuffer.AddSample(wpi::Timer::getMonotonicTimestamp(), robotPose); + robotPoseBuffer.AddSample(wpi::Timer::GetMonotonicTimestamp(), robotPose); } wpi::Field2d& GetDebugField() { return dbgField; } @@ -427,7 +427,7 @@ class VisionSystemSim { dbgField.GetObject(set.first)->SetPoses(posesToAdd); } - wpi::units::second_t now = wpi::Timer::getMonotonicTimestamp(); + wpi::units::second_t now = wpi::Timer::GetMonotonicTimestamp(); robotPoseBuffer.AddSample(now, robotPose); dbgField.SetRobotPose(robotPose.ToPose2d()); From 441906a33f94cdb938c237f0a2cfa15a0b894495 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 17:15:10 -0500 Subject: [PATCH 11/19] alpha 5 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1d27c8a8e2..c7e5c01ab6 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ ext { libcameraDriverVersion = "v2026.0.0" rknnVersion = "dev-v2026.0.1-1-g89b2888" rubikVersion = "dev-v2026.0.1-4-g13d6279" - frcYear = "2027_alpha4" + frcYear = "2027_alpha5" mrcalVersion = "v2027.0.1"; pubVersion = versionString From 6fbac6618d602cd2d09e594e93917d67c770af8b Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 13 Apr 2026 18:18:40 -0500 Subject: [PATCH 12/19] avaje json --- build.gradle | 3 ++- shared/common.gradle | 1 + shared/javacommon.gradle | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c7e5c01ab6..dc71038651 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id "cpp" id "com.diffplug.spotless" version "8.1.0" id "org.wpilib.WPILibRepositoriesPlugin" version "2027.0.0" - id 'org.wpilib.NativeUtils' version '2027.4.1' apply false + id 'org.wpilib.NativeUtils' version '2027.5.1' apply false id 'org.wpilib.DeployUtils' version '2027.1.0' apply false id 'org.photonvision.tools.WpilibTools' version '3.0.0-photon' id 'com.google.protobuf' version '0.9.5' apply false @@ -40,6 +40,7 @@ ext { openCVversion = "4.10.0-3" ejmlVersion = "0.43.1"; jacksonVersion = "2.15.2"; + avajeJsonbVersion = "3.11"; quickbufVersion = "1.3.3"; jacocoVersion = "0.8.14"; diff --git a/shared/common.gradle b/shared/common.gradle index 587a1b2d23..d0b130305b 100644 --- a/shared/common.gradle +++ b/shared/common.gradle @@ -37,6 +37,7 @@ dependencies { implementation group: "com.fasterxml.jackson.core", name: "jackson-annotations", version: jacksonVersion implementation group: "com.fasterxml.jackson.core", name: "jackson-core", version: jacksonVersion implementation group: "com.fasterxml.jackson.core", name: "jackson-databind", version: jacksonVersion + implementation "io.avaje:avaje-jsonb:$avajeJsonbVersion" implementation group: "org.ejml", name: "ejml-simple", version: ejmlVersion implementation group: "us.hebi.quickbuf", name: "quickbuf-runtime", version: quickbufVersion; diff --git a/shared/javacommon.gradle b/shared/javacommon.gradle index 56867192f8..7208eeeb21 100644 --- a/shared/javacommon.gradle +++ b/shared/javacommon.gradle @@ -152,6 +152,7 @@ dependencies { implementation group: "com.fasterxml.jackson.core", name: "jackson-annotations", version: jacksonVersion implementation group: "com.fasterxml.jackson.core", name: "jackson-core", version: jacksonVersion implementation group: "com.fasterxml.jackson.core", name: "jackson-databind", version: jacksonVersion + implementation "io.avaje:avaje-jsonb:$avajeJsonbVersion" implementation group: "org.ejml", name: "ejml-simple", version: ejmlVersion implementation group: "us.hebi.quickbuf", name: "quickbuf-runtime", version: quickbufVersion; From 5dc95562ef41ddcc813f6cc6009d593226cba4f7 Mon Sep 17 00:00:00 2001 From: samfreund Date: Tue, 14 Apr 2026 16:50:29 -0500 Subject: [PATCH 13/19] fix migration --- .../common/dataflow/networktables/NetworkTablesManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java index ed305cd5c2..76dce256ad 100644 --- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java +++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java @@ -156,7 +156,7 @@ private void logNtMessage(NetworkTableEvent event) { } public void checkNtConnectState(NetworkTableEvent event) { - var isConnEvent = event.is(Kind.DISCONNECTED); + var isConnEvent = event.is(Kind.CONNECTED); var isDisconnEvent = event.is(Kind.DISCONNECTED); if (isDisconnEvent) { From c94643acdb0a071109fad3fdd5df6309892d01a3 Mon Sep 17 00:00:00 2001 From: samfreund Date: Wed, 22 Apr 2026 22:45:57 -0500 Subject: [PATCH 14/19] bigger is better right? --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dc71038651..0a118917ea 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ ext.allOutputsFolder = file("$project.buildDir/outputs") apply from: "versioningHelper.gradle" ext { - wpilibVersion = "2027.0.0-alpha-4-109-gf89cf297e" + wpilibVersion = "2027.0.0-alpha-4-124-g44b9545f3" wpimathVersion = wpilibVersion openCVYear = "2025" openCVversion = "4.10.0-3" From f987272689ece74b8691f0da15d9d3e43af12e10 Mon Sep 17 00:00:00 2001 From: samfreund Date: Wed, 22 Apr 2026 23:18:16 -0500 Subject: [PATCH 15/19] fix driverstation flatten --- .../frame/consumer/FileSaveFrameConsumer.java | 2 +- .../consumer/FileSaveFrameConsumerTest.java | 6 ++--- .../java/org/photonvision/PhotonCamera.java | 22 +++++++++---------- .../org/photonvision/PhotonPoseEstimator.java | 6 ++--- .../simulation/SimCameraProperties.java | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java index 9bb3d48bfb..19344b3f81 100644 --- a/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java +++ b/photon-core/src/main/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumer.java @@ -29,7 +29,7 @@ import org.photonvision.common.logging.Logger; import org.photonvision.vision.frame.StaticFrames; import org.photonvision.vision.opencv.CVMat; -import org.wpilib.driverstation.DriverStation.MatchType; +import org.wpilib.driverstation.MatchType; import org.wpilib.networktables.IntegerEntry; import org.wpilib.networktables.IntegerSubscriber; import org.wpilib.networktables.NetworkTable; diff --git a/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java b/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java index 5c2f596033..906fc87342 100644 --- a/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java @@ -36,8 +36,8 @@ import org.photonvision.common.util.TestUtils; import org.photonvision.jni.LibraryLoader; import org.photonvision.vision.frame.provider.FileFrameProvider; -import org.wpilib.driverstation.DriverStation; -import org.wpilib.driverstation.DriverStation.MatchType; +import org.wpilib.driverstation.internal.DriverStationBackend; +import org.wpilib.driverstation.MatchType; import org.wpilib.hardware.hal.HAL; import org.wpilib.networktables.NetworkTableInstance; import org.wpilib.simulation.DriverStationSim; @@ -103,7 +103,7 @@ public void testNoMatch( DriverStationSim.setMatchType(matchType); DriverStationSim.setMatchNumber(matchNumber); DriverStationSim.setEventName(eventName); - DriverStation.refreshData(); + DriverStationBackend.refreshData(); // WHEN we save the image var currentTime = new Date(); diff --git a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java index b90d5e1b0f..d8a6711fac 100644 --- a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java +++ b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java @@ -34,7 +34,7 @@ import org.photonvision.targeting.PhotonPipelineResult; import org.photonvision.timesync.TimeSyncSingleton; import org.wpilib.driverstation.Alert; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.hal.HAL; import org.wpilib.math.linalg.MatBuilder; import org.wpilib.math.linalg.Matrix; @@ -226,8 +226,8 @@ static void verifyDependencies() { """; // spotless:on - DriverStation.reportWarning(bfw, false); - DriverStation.reportError(bfw, false); + DriverStationErrors.reportWarning(bfw, false); + DriverStationErrors.reportError(bfw, false); throw new UnsupportedOperationException(bfw); } } @@ -313,7 +313,7 @@ private void checkTimeSyncOrWarn(PhotonPipelineResult result) { if (Timer.getMonotonicTimestamp() > (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { prevTimeSyncWarnTime = Timer.getMonotonicTimestamp(); - DriverStation.reportWarning( + DriverStationErrors.reportWarning( warningText + "\n\nCheck /photonvision/.timesync/{COPROCESSOR_HOSTNAME} for more information.", false); @@ -502,11 +502,11 @@ void verifyVersion() { if (!heartbeatSubscriber.exists()) { var cameraNames = getTablesThatLookLikePhotonCameras(); if (cameraNames.isEmpty()) { - DriverStation.reportError( + DriverStationErrors.reportError( "Could not find **any** PhotonVision coprocessors on NetworkTables. Double check that PhotonVision is running, and that your camera is connected!", false); } else { - DriverStation.reportError( + DriverStationErrors.reportError( "PhotonVision coprocessor at path " + path + " not found on NetworkTables. Double check that your camera names match!", @@ -519,7 +519,7 @@ void verifyVersion() { cameraNameStr.append("\n"); } - DriverStation.reportError( + DriverStationErrors.reportError( "Found the following PhotonVision cameras on NetworkTables:\n" + cameraNameStr.toString(), false); @@ -527,7 +527,7 @@ void verifyVersion() { } // Check for connection status. Warn if disconnected. else if (!isConnected()) { - DriverStation.reportWarning( + DriverStationErrors.reportWarning( "PhotonVision coprocessor at path " + path + " is not sending new data.", false); } @@ -539,7 +539,7 @@ else if (!isConnected()) { if (remote_uuid == null || remote_uuid.isEmpty()) { // not connected yet? - DriverStation.reportWarning( + DriverStationErrors.reportWarning( "PhotonVision coprocessor at path " + path + " has not reported a message interface UUID - is your coprocessor's camera started?", @@ -573,7 +573,7 @@ else if (!isConnected()) { """; // spotless:on - DriverStation.reportWarning(bfw, false); + DriverStationErrors.reportWarning(bfw, false); String versionMismatchMessage = "Photon version " + PhotonVersion.versionString @@ -586,7 +586,7 @@ else if (!isConnected()) { + remote_uuid + ")" + "!"; - DriverStation.reportError(versionMismatchMessage, false); + DriverStationErrors.reportError(versionMismatchMessage, false); throw new UnsupportedOperationException(versionMismatchMessage); } } diff --git a/photon-lib/src/main/java/org/photonvision/PhotonPoseEstimator.java b/photon-lib/src/main/java/org/photonvision/PhotonPoseEstimator.java index ea29a83cdb..e87578e216 100644 --- a/photon-lib/src/main/java/org/photonvision/PhotonPoseEstimator.java +++ b/photon-lib/src/main/java/org/photonvision/PhotonPoseEstimator.java @@ -29,7 +29,7 @@ import org.photonvision.estimation.VisionEstimation; import org.photonvision.targeting.PhotonPipelineResult; import org.photonvision.targeting.PhotonTrackedTarget; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.hardware.hal.HAL; import org.wpilib.math.geometry.Pose2d; import org.wpilib.math.geometry.Pose3d; @@ -607,7 +607,7 @@ public Optional estimateClosestToReferencePose( return Optional.empty(); } if (referencePose == null) { - DriverStation.reportError( + DriverStationErrors.reportError( "[PhotonPoseEstimator] Tried to use reference pose strategy without setting the reference!", false); return Optional.empty(); @@ -758,7 +758,7 @@ private double calculateDifference(Pose3d x, Pose3d y) { private void reportFiducialPoseError(int fiducialId) { if (!reportedErrors.contains(fiducialId)) { - DriverStation.reportError( + DriverStationErrors.reportError( "[PhotonPoseEstimator] Tried to get pose of unknown AprilTag: " + fiducialId, false); reportedErrors.add(fiducialId); } diff --git a/photon-lib/src/main/java/org/photonvision/simulation/SimCameraProperties.java b/photon-lib/src/main/java/org/photonvision/simulation/SimCameraProperties.java index 7f602f6f5b..921742b4b9 100644 --- a/photon-lib/src/main/java/org/photonvision/simulation/SimCameraProperties.java +++ b/photon-lib/src/main/java/org/photonvision/simulation/SimCameraProperties.java @@ -38,7 +38,7 @@ import org.opencv.imgproc.Imgproc; import org.photonvision.estimation.OpenCVHelp; import org.photonvision.estimation.RotTrlTransform3d; -import org.wpilib.driverstation.DriverStation; +import org.wpilib.driverstation.DriverStationErrors; import org.wpilib.math.geometry.Pose3d; import org.wpilib.math.geometry.Rotation2d; import org.wpilib.math.geometry.Rotation3d; @@ -167,7 +167,7 @@ public SimCameraProperties setRandomSeed(long seed) { public SimCameraProperties setCalibration(int resWidth, int resHeight, Rotation2d fovDiag) { if (fovDiag.getDegrees() < 1 || fovDiag.getDegrees() > 179) { fovDiag = Rotation2d.fromDegrees(Math.clamp(fovDiag.getDegrees(), 1, 179)); - DriverStation.reportError( + DriverStationErrors.reportError( "Requested invalid FOV! Clamping between (1, 179) degrees...", false); } double resDiag = Math.hypot(resWidth, resHeight); From cdbdbde34927dd030737f8d866760a6f30e1edeb Mon Sep 17 00:00:00 2001 From: Sam Freund Date: Wed, 22 Apr 2026 23:21:35 -0500 Subject: [PATCH 16/19] Oopsies, flipped a size check Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../vision/frame/consumer/FileSaveFrameConsumerTest.java | 2 +- photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java b/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java index 906fc87342..fed3a6e328 100644 --- a/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java +++ b/photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java @@ -36,8 +36,8 @@ import org.photonvision.common.util.TestUtils; import org.photonvision.jni.LibraryLoader; import org.photonvision.vision.frame.provider.FileFrameProvider; -import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.driverstation.MatchType; +import org.wpilib.driverstation.internal.DriverStationBackend; import org.wpilib.hardware.hal.HAL; import org.wpilib.networktables.NetworkTableInstance; import org.wpilib.simulation.DriverStationSim; diff --git a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp index 48f5d1c3b8..7c584f65dd 100644 --- a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp +++ b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp @@ -263,7 +263,7 @@ void PhotonCamera::CheckTimeSyncOrWarn(photon::PhotonPipelineResult& result) { timesyncAlert.SetText(warningText); timesyncAlert.Set(true); - if (wpi::Timer::GetMonotonicTimestamp() < + if (wpi::Timer::GetMonotonicTimestamp() > (prevTimeSyncWarnTime + WARN_DEBOUNCE_SEC)) { prevTimeSyncWarnTime = wpi::Timer::GetMonotonicTimestamp(); From 7e6ff6c35a21f961ee0a228aaa393f9a7cba9650 Mon Sep 17 00:00:00 2001 From: samfreund Date: Thu, 23 Apr 2026 00:17:16 -0500 Subject: [PATCH 17/19] uncomment --- .github/workflows/build.yml | 542 +++++++++++++++++------------------ .github/workflows/python.yml | 262 ++++++++--------- 2 files changed, 402 insertions(+), 402 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a401ff5426..e048cb0abb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,75 +21,75 @@ jobs: - uses: actions/checkout@v6 - uses: gradle/actions/wrapper-validation@v5 - # build-examples: - - # strategy: - # fail-fast: false - # matrix: - # include: - # - os: windows-2022 - # artifact-name: Win64 - # - os: macos-14 - # artifact-name: macOS - # - os: ubuntu-24.04 - # artifact-name: Linux - - # name: "Photonlib - Build Examples - ${{ matrix.os }}" - # runs-on: ${{ matrix.os }} - # needs: [build-photonlib-host, build-photonlib-docker] - - # steps: - # - name: Checkout code - # uses: actions/checkout@v6 - # with: - # fetch-depth: 0 - # - name: Fetch tags - # run: git fetch --tags --force - # - uses: actions/setup-java@v5 - # with: - # java-version: 25 - # distribution: temurin - # - name: Install SystemCore Toolchain - # run: ./gradlew installSystemCoreToolchain - # - name: Delete duplicate toolchains - # run: | - # find ~/.gradle/cache/ -name *bookworm* -exec rm -rf {} + - # du -h . | sort -h - # if: matrix.os == 'ubuntu-24.04' - # # Download prebuilt photonlib artifacts - # - uses: actions/download-artifact@v7 - # with: - # name: maven-${{ matrix.artifact-name }} - # - uses: actions/download-artifact@v7 - # with: - # name: maven-Athena - # - name: Move to maven local - # run: | - # mkdir -p ~/.m2/repository/ - # mv maven/org ~/.m2/repository/ - # - name: Copy vendordeps - # shell: bash - # run: | - # for vendordep_folder in photonlib-*-examples/*/; do - # # Remove trailing slash for cross-platform compatibility - # vendordep_folder="${vendordep_folder%/}" - - # # Filter for projects only - # if [ -e "$vendordep_folder/build.gradle" ]; then - # mkdir -p "$vendordep_folder/vendordeps/" - # cp vendordeps/photonlib-json-1.0.json "$vendordep_folder/vendordeps/" - # fi - # done - # - name: Build Java examples - # working-directory: photonlib-java-examples - # run: | - # ./gradlew build - # ./gradlew clean - # - name: Build C++ examples - # working-directory: photonlib-cpp-examples - # run: | - # ./gradlew build - # ./gradlew clean + build-examples: + + strategy: + fail-fast: false + matrix: + include: + - os: windows-2022 + artifact-name: Win64 + - os: macos-14 + artifact-name: macOS + - os: ubuntu-24.04 + artifact-name: Linux + + name: "Photonlib - Build Examples - ${{ matrix.os }}" + runs-on: ${{ matrix.os }} + needs: [build-photonlib-host, build-photonlib-docker] + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Fetch tags + run: git fetch --tags --force + - uses: actions/setup-java@v5 + with: + java-version: 25 + distribution: temurin + - name: Install SystemCore Toolchain + run: ./gradlew installSystemCoreToolchain + - name: Delete duplicate toolchains + run: | + find ~/.gradle/cache/ -name *bookworm* -exec rm -rf {} + + du -h . | sort -h + if: matrix.os == 'ubuntu-24.04' + # Download prebuilt photonlib artifacts + - uses: actions/download-artifact@v7 + with: + name: maven-${{ matrix.artifact-name }} + - uses: actions/download-artifact@v7 + with: + name: maven-Athena + - name: Move to maven local + run: | + mkdir -p ~/.m2/repository/ + mv maven/org ~/.m2/repository/ + - name: Copy vendordeps + shell: bash + run: | + for vendordep_folder in photonlib-*-examples/*/; do + # Remove trailing slash for cross-platform compatibility + vendordep_folder="${vendordep_folder%/}" + + # Filter for projects only + if [ -e "$vendordep_folder/build.gradle" ]; then + mkdir -p "$vendordep_folder/vendordeps/" + cp vendordeps/photonlib-json-1.0.json "$vendordep_folder/vendordeps/" + fi + done + - name: Build Java examples + working-directory: photonlib-java-examples + run: | + ./gradlew build + ./gradlew clean + - name: Build C++ examples + working-directory: photonlib-cpp-examples + run: | + ./gradlew build + ./gradlew clean playwright-tests: name: "Playwright E2E tests" @@ -222,8 +222,8 @@ jobs: fail-fast: false matrix: include: -# - os: windows-2022 -# artifact-name: Win64 + - os: windows-2022 + artifact-name: Win64 - os: macos-26 artifact-name: macOS - os: ubuntu-24.04 @@ -467,203 +467,203 @@ jobs: ls *.jar | %{ Write-Host "Running $($_.Name)"; Start-Process "java" -ArgumentList "-jar `"$($_.FullName)`" --smoketest" -NoNewWindow -Wait; break } if: ${{ (matrix.os) == 'windows-latest' }} -# build-image: -# needs: [build-package-linux] -# -# strategy: -# fail-fast: false -# matrix: -# include: -# - os: ubuntu-24.04-arm -# image_suffix: RaspberryPi -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_raspi.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: limelight2 -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: limelight3 -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: limelight3G -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3g.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: limelight4 -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight4.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: luma_p1 -# plat_override: LINUX_RASPBIAN64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_luma_p1.img.xz -# minimum_free_mb: 100 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi5 -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi5b -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5b.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi5plus -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5plus.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi5pro -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5pro.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi5max -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5max.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: rock5c -# plat_override: LINUX_RK3588_64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rock5c.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: orangepi6plus -# plat_override: LINUX_AARCH64 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi6plus.img.xz -# minimum_free_mb: 1024 -# - os: ubuntu-24.04-arm -# image_suffix: rubikpi3 -# plat_override: LINUX_QCS6490 -# image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rubikpi3.tar.xz -# minimum_free_mb: 1024 -# root_location: 'offset=569376768' -# shrink_image: 'no' -# -# runs-on: ${{ matrix.os }} -# name: "Build image - ${{ matrix.image_suffix }}" -# -# steps: -# - name: Checkout code -# uses: actions/checkout@v6 -# with: -# fetch-depth: 0 -# - uses: actions/download-artifact@v8 -# with: -# pattern: photonvision-*-linuxarm64.jar -# - uses: photonvision/photon-image-runner@HEAD -# name: Generate image -# id: generate_image -# with: -# image_url: ${{ matrix.image_url }} -# minimum_free_mb: ${{ matrix.minimum_free_mb }} -# root_location: ${{ matrix.root_location || 'partition=2' }} -# shrink_image: ${{ matrix.shrink_image || 'yes' }} -# commands: ./scripts/armrunner.sh -# -# - name: Compress image -# # Compress the standard images -# if: ${{ ! startsWith(matrix.image_suffix, 'rubik') }} -# run: | -# set -ex -# new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) -# new_image_name=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") -# sudo mv ${{ steps.generate_image.outputs.image }} $new_image_name -# sudo xz -T 0 -kv $new_image_name -# echo "smoketest_image_loc=${new_image_name}" >> $GITHUB_ENV -# -# - name: Tar built image (Rubik) -# # Build the RubikPi3-specific tar file -# if: ${{ startsWith(matrix.image_suffix, 'rubik') }} -# run: | -# set -ex -# new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) -# tardir=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") -# imagedir=$(dirname ${{ steps.generate_image.outputs.image }}) -# sudo mkdir --parents ${tardir} -# sudo cp ${imagedir}/* ${tardir}/ -# sudo tar -I 'xz -T0' -cf ${tardir}.tar.xz ${tardir} --checkpoint=10000 --checkpoint-action=echo='%T' -# # Point smoketest to the old image -# echo "smoketest_image_loc=${{ steps.generate_image.outputs.image }}" >> $GITHUB_ENV -# -# - uses: actions/upload-artifact@v7 -# with: -# archive: false -# path: photonvision*.xz -# -# # This is done after uploading the image to avoid contaminating the image with logs, caches, etc. -# - uses: photonvision/photon-image-runner@HEAD -# name: Smoketest Image -# with: -# image_url: file://${{ env.smoketest_image_loc }} -# minimum_free_mb: ${{ matrix.minimum_free_mb }} -# root_location: ${{ matrix.root_location || 'partition=2' }} -# shrink_image: ${{ matrix.shrink_image || 'yes' }} -# commands: java -jar *.jar --smoketest --platform=${{ matrix.plat_override }} -# -# matrix-checker: -# # This job always runs last to set the overall result based on the matrix jobs. If any matrix job failed, this job will fail. -# # This makes it so that we don't need to add each matrix job individually to CI checks. -# runs-on: ubuntu-latest -# needs: [build-image] -# if: always() -# steps: -# - run: ${{!contains(needs.*.result, 'failure')}} - -# release: -# # Require smoketest-native so that if those fail, we don't release broken artifacts -# needs: [build-photonlib-vendorjson, build-image, combine, build-package-linux, build-package-macos, build-package-windows, run-smoketest-native] -# if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.repository == 'PhotonVision/photonvision' -# runs-on: ubuntu-24.04 -# steps: -# # Download all fat JARs -# - uses: actions/download-artifact@v8 -# with: -# merge-multiple: true -# pattern: photonvision-*.jar -# # Download offline photonlib -# - uses: actions/download-artifact@v8 -# with: -# merge-multiple: true -# pattern: photonlib-offline -# # Download vendor json -# - uses: actions/download-artifact@v8 -# with: -# pattern: photonlib-*.json -# # Download all images -# - uses: actions/download-artifact@v8 -# with: -# merge-multiple: true -# pattern: photonvision-*.xz -# -# - run: find -# # Push to dev release -# - uses: pyTooling/Actions/releaser@r6 -# with: -# token: ${{ secrets.GITHUB_TOKEN }} -# tag: 'Dev' -# rm: true -# snapshots: false -# files: | -# **/*.xz -# **/*linux*.jar -# **/*win*.jar -# **/photonlib*.json -# **/photonlib*.zip -# if: github.event_name == 'push' -# - name: Create Vendor JSON Repo PR -# uses: wpilibsuite/vendor-json-repo/.github/actions/add_vendordep@HEAD -# with: -# repo: PhotonVision/vendor-json-repo -# token: ${{ secrets.VENDOR_JSON_REPO_PUSH_TOKEN }} -# vendordep_file: ${{ github.workspace }}/photonlib-${{ github.ref_name }}.json -# pr_title: Update photonlib to ${{ github.ref_name }} -# pr_branch: photonlib-${{ github.ref_name }} -# if: github.repository == 'PhotonVision/photonvision' && startsWith(github.ref, 'refs/tags/v') + build-image: + needs: [build-package-linux] + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04-arm + image_suffix: RaspberryPi + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_raspi.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: limelight2 + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: limelight3 + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: limelight3G + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3g.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: limelight4 + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight4.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: luma_p1 + plat_override: LINUX_RASPBIAN64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_luma_p1.img.xz + minimum_free_mb: 100 + - os: ubuntu-24.04-arm + image_suffix: orangepi5 + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: orangepi5b + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5b.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: orangepi5plus + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5plus.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: orangepi5pro + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5pro.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: orangepi5max + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5max.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: rock5c + plat_override: LINUX_RK3588_64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rock5c.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: orangepi6plus + plat_override: LINUX_AARCH64 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi6plus.img.xz + minimum_free_mb: 1024 + - os: ubuntu-24.04-arm + image_suffix: rubikpi3 + plat_override: LINUX_QCS6490 + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rubikpi3.tar.xz + minimum_free_mb: 1024 + root_location: 'offset=569376768' + shrink_image: 'no' + + runs-on: ${{ matrix.os }} + name: "Build image - ${{ matrix.image_suffix }}" + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - uses: actions/download-artifact@v8 + with: + pattern: photonvision-*-linuxarm64.jar + - uses: photonvision/photon-image-runner@HEAD + name: Generate image + id: generate_image + with: + image_url: ${{ matrix.image_url }} + minimum_free_mb: ${{ matrix.minimum_free_mb }} + root_location: ${{ matrix.root_location || 'partition=2' }} + shrink_image: ${{ matrix.shrink_image || 'yes' }} + commands: ./scripts/armrunner.sh + + - name: Compress image + # Compress the standard images + if: ${{ ! startsWith(matrix.image_suffix, 'rubik') }} + run: | + set -ex + new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) + new_image_name=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") + sudo mv ${{ steps.generate_image.outputs.image }} $new_image_name + sudo xz -T 0 -kv $new_image_name + echo "smoketest_image_loc=${new_image_name}" >> $GITHUB_ENV + + - name: Tar built image (Rubik) + # Build the RubikPi3-specific tar file + if: ${{ startsWith(matrix.image_suffix, 'rubik') }} + run: | + set -ex + new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) + tardir=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") + imagedir=$(dirname ${{ steps.generate_image.outputs.image }}) + sudo mkdir --parents ${tardir} + sudo cp ${imagedir}/* ${tardir}/ + sudo tar -I 'xz -T0' -cf ${tardir}.tar.xz ${tardir} --checkpoint=10000 --checkpoint-action=echo='%T' + # Point smoketest to the old image + echo "smoketest_image_loc=${{ steps.generate_image.outputs.image }}" >> $GITHUB_ENV + + - uses: actions/upload-artifact@v7 + with: + archive: false + path: photonvision*.xz + + # This is done after uploading the image to avoid contaminating the image with logs, caches, etc. + - uses: photonvision/photon-image-runner@HEAD + name: Smoketest Image + with: + image_url: file://${{ env.smoketest_image_loc }} + minimum_free_mb: ${{ matrix.minimum_free_mb }} + root_location: ${{ matrix.root_location || 'partition=2' }} + shrink_image: ${{ matrix.shrink_image || 'yes' }} + commands: java -jar *.jar --smoketest --platform=${{ matrix.plat_override }} + + matrix-checker: + # This job always runs last to set the overall result based on the matrix jobs. If any matrix job failed, this job will fail. + # This makes it so that we don't need to add each matrix job individually to CI checks. + runs-on: ubuntu-latest + needs: [build-image] + if: always() + steps: + - run: ${{!contains(needs.*.result, 'failure')}} + + release: + # Require smoketest-native so that if those fail, we don't release broken artifacts + needs: [build-photonlib-vendorjson, build-image, combine, build-package-linux, build-package-macos, build-package-windows, run-smoketest-native] + if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.repository == 'PhotonVision/photonvision' + runs-on: ubuntu-24.04 + steps: + # Download all fat JARs + - uses: actions/download-artifact@v8 + with: + merge-multiple: true + pattern: photonvision-*.jar + # Download offline photonlib + - uses: actions/download-artifact@v8 + with: + merge-multiple: true + pattern: photonlib-offline + # Download vendor json + - uses: actions/download-artifact@v8 + with: + pattern: photonlib-*.json + # Download all images + - uses: actions/download-artifact@v8 + with: + merge-multiple: true + pattern: photonvision-*.xz + + - run: find + # Push to dev release + - uses: pyTooling/Actions/releaser@r6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: 'Dev' + rm: true + snapshots: false + files: | + **/*.xz + **/*linux*.jar + **/*win*.jar + **/photonlib*.json + **/photonlib*.zip + if: github.event_name == 'push' + - name: Create Vendor JSON Repo PR + uses: wpilibsuite/vendor-json-repo/.github/actions/add_vendordep@HEAD + with: + repo: PhotonVision/vendor-json-repo + token: ${{ secrets.VENDOR_JSON_REPO_PUSH_TOKEN }} + vendordep_file: ${{ github.workspace }}/photonlib-${{ github.ref_name }}.json + pr_title: Update photonlib to ${{ github.ref_name }} + pr_branch: photonlib-${{ github.ref_name }} + if: github.repository == 'PhotonVision/photonvision' && startsWith(github.ref, 'refs/tags/v') diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 40df068009..4aa136791f 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,134 +12,134 @@ concurrency: cancel-in-progress: true jobs: -# build-py: -# runs-on: ubuntu-24.04 -# -# steps: -# - name: Checkout code -# uses: actions/checkout@v6 -# with: -# fetch-depth: 0 -# -# - name: Set up Python -# uses: actions/setup-python@v6 -# with: -# python-version: 3.14 -# -# - name: Install dependencies -# run: | -# python -m pip install --upgrade pip -# pip install setuptools wheel -# -# - name: Build wheel -# working-directory: ./photon-lib/py -# run: python setup.py sdist bdist_wheel -# -# - name: Upload artifacts -# uses: actions/upload-artifact@v7 -# with: -# name: dist -# path: ./photon-lib/py/dist/ -# -# test-py: -# needs: build-py -# runs-on: ubuntu-24.04 -# -# steps: -# - name: Checkout code -# uses: actions/checkout@v6 -# with: -# fetch-depth: 0 -# -# - name: Set up Python -# uses: actions/setup-python@v6 -# with: -# python-version: 3.14 -# -# - name: Install dependencies -# run: | -# python -m pip install --upgrade pip -# pip install pytest mypy -# -# - name: Download artifacts -# uses: actions/download-artifact@v8 -# with: -# name: dist -# path: dist/ -# -# - name: Install package -# shell: bash -# run: pip install --no-cache-dir dist/*.whl -# -# - name: Run Unit Tests -# shell: bash -# run: pytest --import-mode=importlib photon-lib/py/test/ -# -# - name: Run mypy type checking -# run: mypy --show-column-numbers --config-file photon-lib/py/pyproject.toml photon-lib -# -# build-python-examples: -# needs: build-py -# strategy: -# matrix: -# os: [ubuntu-24.04, windows-2022, macos-14] -# runs-on: ${{ matrix.os }} -# -# steps: -# -# - name: Checkout code -# uses: actions/checkout@v6 -# with: -# fetch-depth: 0 -# -# - name: Set up Python -# uses: actions/setup-python@v6 -# with: -# python-version: 3.14 -# -# - name: Install dependencies -# run: | -# python -m pip install --upgrade pip -# -# - name: Download artifacts -# uses: actions/download-artifact@v8 -# with: -# name: dist -# path: ./photon-lib/py/dist/ -# -# - name: Install PhotonLibPy package -# working-directory: ./photon-lib/py -# shell: bash -# run: | -# pip install --no-cache-dir dist/*.whl -# -# - name: Build Python examples -# working-directory: photonlib-python-examples -# shell: bash -# run: | -# for folder in */; -# do -# echo $folder -# ./run.sh $folder -# done -# -# deploy: -# needs: [test-py, build-python-examples] -# runs-on: ubuntu-24.04 -# # Only upload on tags -# if: startsWith(github.ref, 'refs/tags/v') -# -# steps: -# - name: Download artifacts -# uses: actions/download-artifact@v8 -# with: -# name: dist -# path: dist/ -# -# - name: Publish package distributions to PyPI -# uses: pypa/gh-action-pypi-publish@release/v1 -# with: -# packages-dir: ./dist/ -# -# permissions: -# id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + build-py: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: 3.14 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel + + - name: Build wheel + working-directory: ./photon-lib/py + run: python setup.py sdist bdist_wheel + + - name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: dist + path: ./photon-lib/py/dist/ + + test-py: + needs: build-py + runs-on: ubuntu-24.04 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: 3.14 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest mypy + + - name: Download artifacts + uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + + - name: Install package + shell: bash + run: pip install --no-cache-dir dist/*.whl + + - name: Run Unit Tests + shell: bash + run: pytest --import-mode=importlib photon-lib/py/test/ + + - name: Run mypy type checking + run: mypy --show-column-numbers --config-file photon-lib/py/pyproject.toml photon-lib + + build-python-examples: + needs: build-py + strategy: + matrix: + os: [ubuntu-24.04, windows-2022, macos-14] + runs-on: ${{ matrix.os }} + + steps: + + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: 3.14 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + + - name: Download artifacts + uses: actions/download-artifact@v8 + with: + name: dist + path: ./photon-lib/py/dist/ + + - name: Install PhotonLibPy package + working-directory: ./photon-lib/py + shell: bash + run: | + pip install --no-cache-dir dist/*.whl + + - name: Build Python examples + working-directory: photonlib-python-examples + shell: bash + run: | + for folder in */; + do + echo $folder + ./run.sh $folder + done + + deploy: + needs: [test-py, build-python-examples] + runs-on: ubuntu-24.04 + # Only upload on tags + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Download artifacts + uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./dist/ + + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing From e39345ea0df7b4287229eeac3c5e900c181ad0a1 Mon Sep 17 00:00:00 2001 From: samfreund Date: Mon, 27 Apr 2026 12:54:22 -0500 Subject: [PATCH 18/19] alpha 5 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0a118917ea..04b51aa069 100644 --- a/build.gradle +++ b/build.gradle @@ -34,7 +34,7 @@ ext.allOutputsFolder = file("$project.buildDir/outputs") apply from: "versioningHelper.gradle" ext { - wpilibVersion = "2027.0.0-alpha-4-124-g44b9545f3" + wpilibVersion = "2027.0.0-alpha-5" wpimathVersion = wpilibVersion openCVYear = "2025" openCVversion = "4.10.0-3" From 15196ff86ba3eb7e8946fa4c5f391c71b8cf07e0 Mon Sep 17 00:00:00 2001 From: samfreund Date: Tue, 28 Apr 2026 10:18:17 -0500 Subject: [PATCH 19/19] rerun cause wpilib be sliding