Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@

import edu.wpi.first.math.geometry.Transform3d;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEvent;
import edu.wpi.first.networktables.NetworkTablesJNI;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.dataflow.CVPipelineResultConsumer;
import org.photonvision.common.logging.LogGroup;
Expand All @@ -43,111 +39,17 @@ public class NTDataPublisher implements CVPipelineResultConsumer {

private final NTTopicSet ts = new NTTopicSet();

NTDataChangeListener pipelineIndexListener;
private final Supplier<Integer> pipelineIndexSupplier;
private final Consumer<Integer> pipelineIndexConsumer;

NTDataChangeListener driverModeListener;
private final BooleanSupplier driverModeSupplier;
private final Consumer<Boolean> driverModeConsumer;

NTDataChangeListener fpsLimitListener;
private final Consumer<Integer> fpsLimitConsumer;
private final Supplier<Integer> fpsLimitSupplier;

public NTDataPublisher(
String cameraNickname,
Supplier<Integer> pipelineIndexSupplier,
Consumer<Integer> pipelineIndexConsumer,
BooleanSupplier driverModeSupplier,
Consumer<Boolean> driverModeConsumer,
Supplier<Integer> fpsLimitSupplier,
Consumer<Integer> fpsLimitConsumer) {
this.pipelineIndexSupplier = pipelineIndexSupplier;
this.pipelineIndexConsumer = pipelineIndexConsumer;
this.driverModeSupplier = driverModeSupplier;
this.driverModeConsumer = driverModeConsumer;
this.fpsLimitSupplier = fpsLimitSupplier;
this.fpsLimitConsumer = fpsLimitConsumer;

public NTDataPublisher(String cameraNickname) {
updateCameraNickname(cameraNickname);
updateEntries();
}

private void onPipelineIndexChange(NetworkTableEvent entryNotification) {
var newIndex = (int) entryNotification.valueData.value.getInteger();
var originalIndex = pipelineIndexSupplier.get();

// ignore indexes below 0
if (newIndex < 0) {
ts.pipelineIndexPublisher.set(originalIndex);
return;
}

if (newIndex == originalIndex) {
logger.debug("Pipeline index is already " + newIndex);
return;
}

pipelineIndexConsumer.accept(newIndex);
var setIndex = pipelineIndexSupplier.get();
if (newIndex != setIndex) { // set failed
ts.pipelineIndexPublisher.set(setIndex);
// TODO: Log
}
logger.debug("Set pipeline index to " + newIndex);
}

private void onDriverModeChange(NetworkTableEvent entryNotification) {
var newDriverMode = entryNotification.valueData.value.getBoolean();
var originalDriverMode = driverModeSupplier.getAsBoolean();

if (newDriverMode == originalDriverMode) {
logger.debug("Driver mode is already " + newDriverMode);
return;
}

driverModeConsumer.accept(newDriverMode);
logger.debug("Set driver mode to " + newDriverMode);
}

private void onFPSLimitChange(NetworkTableEvent entryNotification) {
var newFPSLimit = (int) entryNotification.valueData.value.getInteger();
var originalFPSLimit = fpsLimitSupplier.get();

if (newFPSLimit == originalFPSLimit) {
logger.debug("FPS limit is already " + newFPSLimit);
return;
}

fpsLimitConsumer.accept(newFPSLimit);
logger.debug("Set FPS limit to " + newFPSLimit);
ts.updateEntries();
}

private void removeEntries() {
if (pipelineIndexListener != null) pipelineIndexListener.remove();
if (driverModeListener != null) driverModeListener.remove();
ts.removeEntries();
}

private void updateEntries() {
if (pipelineIndexListener != null) pipelineIndexListener.remove();
if (driverModeListener != null) driverModeListener.remove();
if (fpsLimitListener != null) fpsLimitListener.remove();

ts.updateEntries();

pipelineIndexListener =
new NTDataChangeListener(
ts.subTable.getInstance(), ts.pipelineIndexRequestSub, this::onPipelineIndexChange);

driverModeListener =
new NTDataChangeListener(
ts.subTable.getInstance(), ts.driverModeSubscriber, this::onDriverModeChange);

fpsLimitListener =
new NTDataChangeListener(
ts.subTable.getInstance(), ts.fpsLimitSubscriber, this::onFPSLimitChange);
}

public void updateCameraNickname(String newCameraNickname) {
Expand Down Expand Up @@ -194,9 +96,6 @@ public void accept(CVPipelineResult result) {
ts.protoResultPublisher.set(simplified);
}

ts.pipelineIndexPublisher.set(pipelineIndexSupplier.get());
ts.driverModePublisher.set(driverModeSupplier.getAsBoolean());
ts.fpsLimitPublisher.set(fpsLimitSupplier.get());
ts.latencyMillisEntry.set(acceptedResult.getLatencyMillis());
ts.fpsEntry.set(acceptedResult.fps);
ts.hasTargetEntry.set(acceptedResult.hasTargets());
Expand Down Expand Up @@ -225,18 +124,6 @@ public void accept(CVPipelineResult result) {
ts.bestTargetPosY.set(0);
}

// Something in the result can sometimes be null -- so check probably too many things
if (acceptedResult.inputAndOutputFrame != null
&& acceptedResult.inputAndOutputFrame.frameStaticProperties != null
&& acceptedResult.inputAndOutputFrame.frameStaticProperties.cameraCalibration != null) {
var fsp = acceptedResult.inputAndOutputFrame.frameStaticProperties;
ts.cameraIntrinsicsPublisher.accept(fsp.cameraCalibration.getIntrinsicsArr());
ts.cameraDistortionPublisher.accept(fsp.cameraCalibration.getDistCoeffsArr());
} else {
ts.cameraIntrinsicsPublisher.accept(new double[0]);
ts.cameraDistortionPublisher.accept(new double[0]);
}

ts.heartbeatPublisher.set(acceptedResult.sequenceID);

// TODO...nt4... is this needed?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,17 @@

package org.photonvision.common.dataflow.networktables;

import edu.wpi.first.apriltag.AprilTagFieldLayout;
import edu.wpi.first.cscore.CameraServerJNI;
import edu.wpi.first.networktables.LogMessage;
import edu.wpi.first.networktables.MultiSubscriber;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEvent;
import edu.wpi.first.networktables.NetworkTableEvent.Kind;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.networktables.StringSubscriber;
import edu.wpi.first.wpilibj.Alert;
import edu.wpi.first.wpilibj.Alert.AlertType;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import java.io.IOException;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import org.photonvision.PhotonVersion;
import org.photonvision.common.configuration.CameraConfiguration;
Expand All @@ -46,7 +42,6 @@
import org.photonvision.common.logging.Logger;
import org.photonvision.common.networking.NetworkUtils;
import org.photonvision.common.util.TimedTaskManager;
import org.photonvision.common.util.file.JacksonUtils;

public class NetworkTablesManager {
private static final Logger logger =
Expand All @@ -56,7 +51,6 @@ public class NetworkTablesManager {
private final String kRootTableName = "/photonvision";
// The coprocessors table should only be used for operations/data related to MAC address
public final String kCoprocTableName = "coprocessors";
private final String kFieldLayoutName = "apriltag_field_layout";
public final NetworkTable kRootTable = ntInstance.getTable(kRootTableName);
public final NetworkTable kCoprocTable = kRootTable.getSubTable(kCoprocTableName);

Expand All @@ -76,9 +70,6 @@ public class NetworkTablesManager {

private boolean m_isRetryingConnection = false;

private StringSubscriber m_fieldLayoutSubscriber =
kRootTable.getStringTopic(kFieldLayoutName).subscribe("");

private final TimeSyncManager m_timeSync = new TimeSyncManager(kRootTable);

NTDriverStation ntDriverStation;
Expand All @@ -88,9 +79,6 @@ private NetworkTablesManager() {
LogMessage.kInfo, LogMessage.kCritical, 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);

ntDriverStation = new NTDriverStation(this.getNTInst());

// This should start as false, since we don't know if there's a conflict yet
Expand Down Expand Up @@ -195,24 +183,6 @@ public NetworkTableInstance getNTInst() {
return ntInstance;
}

private void onFieldLayoutChanged(NetworkTableEvent event) {
var atfl_json = event.valueData.value.getString();
try {
System.out.println("Got new field layout!");
var atfl = JacksonUtils.deserialize(atfl_json, AprilTagFieldLayout.class);
ConfigManager.getInstance().getConfig().setApriltagFieldLayout(atfl);
ConfigManager.getInstance().requestSave();
DataChangeService.getInstance()
.publishEvent(
new OutgoingUIEvent<>(
"fullsettings",
UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig())));
} catch (IOException e) {
logger.error("Error deserializing atfl!");
logger.error(atfl_json);
}
}

public void broadcastConnectedStatus() {
TimedTaskManager.getInstance().addOneShotTask(this::broadcastConnectedStatusImpl, 1000L);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,7 @@ public VisionModule(PipelineManager pipelineManager, VisionSource visionSource)

ntConsumer =
new NTDataPublisher(
visionSource.getSettables().getConfiguration().nickname,
pipelineManager::getRequestedIndex,
this::setPipeline,
pipelineManager::getDriverMode,
this::setDriverMode,
this::getFPSLimit,
this::setFPSLimit);
visionSource.getSettables().getConfiguration().nickname);
uiDataConsumer = new UIDataPublisher(visionSource.getSettables().getConfiguration().uniqueName);
statusLEDsConsumer =
new StatusLEDConsumer(visionSource.getSettables().getConfiguration().uniqueName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import edu.wpi.first.math.Pair;
import edu.wpi.first.math.geometry.Pose3d;
import edu.wpi.first.math.geometry.Transform3d;
import edu.wpi.first.networktables.DoubleArrayPublisher;
import edu.wpi.first.util.PixelFormat;
import edu.wpi.first.util.WPIUtilJNI;
import edu.wpi.first.wpilibj.RobotController;
Expand Down Expand Up @@ -72,6 +73,9 @@ public class PhotonCameraSim implements AutoCloseable {
@SuppressWarnings("doclint")
protected NTTopicSet ts = new NTTopicSet();

private DoubleArrayPublisher cameraIntrinsicsPublisher;
private DoubleArrayPublisher cameraDistortionPublisher;

private long heartbeatCounter = 1;

/** This simulated camera's {@link SimCameraProperties} */
Expand Down Expand Up @@ -106,6 +110,8 @@ public void close() {
videoSimFrameRaw.release();
videoSimProcessed.close();
videoSimFrameProcessed.release();
if (cameraIntrinsicsPublisher != null) cameraIntrinsicsPublisher.close();
if (cameraDistortionPublisher != null) cameraDistortionPublisher.close();
}

/**
Expand Down Expand Up @@ -162,6 +168,13 @@ public PhotonCameraSim(
ts.removeEntries();
ts.subTable = camera.getCameraTable();
ts.updateEntries();

if (cameraIntrinsicsPublisher != null) cameraIntrinsicsPublisher.close();
if (cameraDistortionPublisher != null) cameraDistortionPublisher.close();
cameraIntrinsicsPublisher =
ts.subTable.getDoubleArrayTopic("cameraIntrinsics").publish();
cameraDistortionPublisher =
ts.subTable.getDoubleArrayTopic("cameraDistortion").publish();
}

/**
Expand Down Expand Up @@ -697,8 +710,8 @@ public void submitProcessedFrame(PhotonPipelineResult result, long receiveTimest
ts.targetPoseEntry.set(transform, receiveTimestamp);
}

ts.cameraIntrinsicsPublisher.set(prop.getIntrinsics().getData(), receiveTimestamp);
ts.cameraDistortionPublisher.set(prop.getDistCoeffs().getData(), receiveTimestamp);
cameraIntrinsicsPublisher.set(prop.getIntrinsics().getData(), receiveTimestamp);
cameraDistortionPublisher.set(prop.getDistCoeffs().getData(), receiveTimestamp);

ts.heartbeatPublisher.set(heartbeatCounter, receiveTimestamp);
heartbeatCounter += 1;
Expand Down
7 changes: 0 additions & 7 deletions photon-server/src/main/java/org/photonvision/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,6 @@ public static void main(String[] args) {
logger.error("Failed to parse command-line options!", e);
}

// We don't want to trigger an exit in test mode or smoke test. This is
// specifically for MacOS.
if (!(Platform.isSupported() || isSmoketest || isTestMode)) {
logger.error("This platform is unsupported!");
System.exit(1);
}

try {
boolean success = LoadJNI.loadLibraries();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public enum Platform {

// Completely unsupported
WINDOWS_32("Windows x86", Platform::getUnknownModel, false, OSType.WINDOWS, false),
MACOS("Mac OS", Platform::getUnknownModel, false, OSType.MACOS, false),
MACOS("Mac OS", Platform::getUnknownModel, false, OSType.MACOS, true),
LINUX_ARM32(
"Linux ARM32", Platform::getUnknownModel, false, OSType.LINUX, false), // ODROID XU4, C1+
UNKNOWN("Unsupported Platform", Platform::getUnknownModel, false, OSType.UNKNOWN, false);
Expand Down
Loading
Loading