Add NT controlled framerate limiter (#2257)

Adds a method to lower the speed of a pipeline over NT, primarily to
reduce power consumption.
This commit is contained in:
Sam Freund
2025-12-29 23:01:10 -06:00
committed by GitHub
parent fddff5dbca
commit 80d3efe00e
16 changed files with 234 additions and 15 deletions

View File

@@ -47,6 +47,13 @@ class NTTopicSet:
self.driverModeSubscriber.getTopic().publish().setDefault(False)
self.fpsLimitPublisher = self.subTable.getIntegerTopic("fpsLimit").publish()
self.fpsLimitSubscriber = self.subTable.getIntegerTopic(
"fpsLimitRequest"
).subscribe(-1)
self.fpsLimitSubscriber.getTopic().publish().setDefault(-1)
self.latencyMillisEntry = self.subTable.getDoubleTopic(
"latencyMillis"
).publish()

View File

@@ -74,6 +74,12 @@ class PhotonCamera:
self._driverModeSubscriber = self._cameraTable.getBooleanTopic(
"driverMode"
).subscribe(False)
self._fpsLimitPublisher = self._cameraTable.getIntegerTopic(
"fpsLimitRequest"
).publish()
self._fpsLimitSubscriber = self._cameraTable.getIntegerTopic(
"fpsLimit"
).subscribe(-1)
self._inputSaveImgEntry = self._cameraTable.getIntegerTopic(
"inputSaveImgCmd"
).getEntry(0)
@@ -190,6 +196,22 @@ class PhotonCamera:
self._driverModePublisher.set(driverMode)
def getFPSLimit(self) -> int:
"""Returns the current FPS limit set on the camera.
:returns: The current FPS limit.
"""
return self._fpsLimitSubscriber.get()
def setFPSLimit(self, fpsLimit: int) -> None:
"""Sets the FPS limit on the camera.
:param fpsLimit: The FPS limit to set. Set to -1 for unlimited FPS.
"""
self._fpsLimitPublisher.set(fpsLimit)
def takeInputSnapshot(self) -> None:
"""Request the camera to save a new image file from the input camera stream with overlays. Images
take up space in the filesystem of the PhotonCamera. Calling it frequently will fill up disk

View File

@@ -66,6 +66,8 @@ public class PhotonCamera implements AutoCloseable {
PacketSubscriber<PhotonPipelineResult> resultSubscriber;
BooleanPublisher driverModePublisher;
BooleanSubscriber driverModeSubscriber;
IntegerPublisher fpsLimitPublisher;
IntegerSubscriber fpsLimitSubscriber;
StringSubscriber versionEntry;
IntegerEntry inputSaveImgEntry, outputSaveImgEntry;
IntegerPublisher pipelineIndexRequest, ledModeRequest;
@@ -81,6 +83,8 @@ public class PhotonCamera implements AutoCloseable {
resultSubscriber.close();
driverModePublisher.close();
driverModeSubscriber.close();
fpsLimitPublisher.close();
fpsLimitSubscriber.close();
versionEntry.close();
inputSaveImgEntry.close();
outputSaveImgEntry.close();
@@ -144,6 +148,8 @@ public class PhotonCamera implements AutoCloseable {
resultSubscriber = new PacketSubscriber<>(rawBytesEntry, PhotonPipelineResult.photonStruct);
driverModePublisher = cameraTable.getBooleanTopic("driverModeRequest").publish();
driverModeSubscriber = cameraTable.getBooleanTopic("driverMode").subscribe(false);
fpsLimitPublisher = cameraTable.getIntegerTopic("fpsLimitRequest").publish();
fpsLimitSubscriber = cameraTable.getIntegerTopic("fpsLimit").subscribe(-1);
inputSaveImgEntry = cameraTable.getIntegerTopic("inputSaveImgCmd").getEntry(0);
outputSaveImgEntry = cameraTable.getIntegerTopic("outputSaveImgCmd").getEntry(0);
pipelineIndexRequest = cameraTable.getIntegerTopic("pipelineIndexRequest").publish();
@@ -373,6 +379,24 @@ public class PhotonCamera implements AutoCloseable {
driverModePublisher.set(driverMode);
}
/**
* Gets the FPS limit set on the camera.
*
* @return The current FPS limit.
*/
public int getFPSLimit() {
return (int) fpsLimitSubscriber.get();
}
/**
* Sets the FPS limit on the camera.
*
* @param fps The FPS limit to set. Set to -1 for unlimited FPS.
*/
public void setFPSLimit(int fps) {
fpsLimitPublisher.set(fps);
}
/**
* Request the camera to save a new image file from the input camera stream with overlays. Images
* take up space in the filesystem of the PhotonCamera. Calling it frequently will fill up disk

View File

@@ -196,6 +196,9 @@ PhotonCamera::PhotonCamera(nt::NetworkTableInstance instance,
rootTable->GetBooleanTopic("driverMode").Subscribe(false)),
driverModePublisher(
rootTable->GetBooleanTopic("driverModeRequest").Publish()),
fpsLimitSubscriber(rootTable->GetIntegerTopic("fpsLimit").Subscribe(-1)),
fpsLimitPublisher(
rootTable->GetIntegerTopic("fpsLimitRequest").Publish()),
heartbeatSubscriber(
rootTable->GetIntegerTopic("heartbeat").Subscribe(-1)),
topicNameSubscriber(instance, PHOTON_PREFIX, {.topicsOnly = true}),
@@ -322,6 +325,14 @@ void PhotonCamera::SetDriverMode(bool driverMode) {
driverModePublisher.Set(driverMode);
}
bool PhotonCamera::GetDriverMode() const { return driverModeSubscriber.Get(); }
int PhotonCamera::GetFPSLimit() const { return fpsLimitSubscriber.Get(); }
void PhotonCamera::SetFPSLimit(int fpsLimit) {
fpsLimitPublisher.Set(fpsLimit);
}
void PhotonCamera::TakeInputSnapshot() {
inputSaveImgEntry.Set(inputSaveImgSubscriber.Get() + 1);
}
@@ -330,8 +341,6 @@ void PhotonCamera::TakeOutputSnapshot() {
outputSaveImgEntry.Set(outputSaveImgSubscriber.Get() + 1);
}
bool PhotonCamera::GetDriverMode() const { return driverModeSubscriber.Get(); }
void PhotonCamera::SetPipelineIndex(int index) { pipelineIndexPub.Set(index); }
int PhotonCamera::GetPipelineIndex() const {

View File

@@ -103,6 +103,16 @@ class PhotonCamera {
*/
bool GetDriverMode() const;
/**
* @param fpsLimit The FPS limit to set. Use -1 for unlimited FPS.
*/
void SetFPSLimit(int fpsLimit);
/**
* @return The FPS limit set on the camera, or -1 if no limit is set.
*/
int GetFPSLimit() const;
/**
* Request the camera to save a new image file from the input
* camera stream with overlays.
@@ -210,6 +220,9 @@ class PhotonCamera {
nt::BooleanSubscriber driverModeSubscriber;
nt::BooleanPublisher driverModePublisher;
nt::IntegerSubscriber fpsLimitSubscriber;
nt::IntegerPublisher fpsLimitPublisher;
nt::IntegerSubscriber ledModeSubscriber;
nt::IntegerSubscriber heartbeatSubscriber;