diff --git a/photon-lib/py/photonlibpy/photonCamera.py b/photon-lib/py/photonlibpy/photonCamera.py index b5bb659e8..e8102f699 100644 --- a/photon-lib/py/photonlibpy/photonCamera.py +++ b/photon-lib/py/photonlibpy/photonCamera.py @@ -53,7 +53,9 @@ class PhotonCamera: self._cameraTable = photonvision_root_table.getSubTable(cameraName) self._path = self._cameraTable.getPath() self._rawBytesEntry = self._cameraTable.getRawTopic("rawBytes").subscribe( - "rawBytes", bytes([]), ntcore.PubSubOptions(periodic=0.01, sendAll=True) + f"photonstruct:PhotonPipelineResult:{PhotonPipelineResult.photonStruct.MESSAGE_VERSION}", + bytes([]), + ntcore.PubSubOptions(periodic=0.01, sendAll=True), ) self._driverModePublisher = self._cameraTable.getBooleanTopic( @@ -226,6 +228,7 @@ class PhotonCamera: versionString = self.versionEntry.get(defaultValue="") localUUID = PhotonPipelineResult.photonStruct.MESSAGE_VERSION + remoteUUID = self._rawBytesEntry.getTopic().getProperty("message_uuid") if remoteUUID is None or len(remoteUUID) == 0: @@ -233,7 +236,11 @@ class PhotonCamera: f"PhotonVision coprocessor at path {self._path} has not reported a message interface UUID - is your coprocessor's camera started?", True, ) - elif localUUID != remoteUUID: + + # ntcore hands us a JSON string with leading/trailing quotes - remove those + remoteUUID = remoteUUID.replace('"', "") + + if localUUID != remoteUUID: # Verified version mismatch bfw = """ diff --git a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java index 633cf5fcb..8a6035d52 100644 --- a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java +++ b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java @@ -137,7 +137,7 @@ public class PhotonCamera implements AutoCloseable { cameraTable .getRawTopic("rawBytes") .subscribe( - "rawBytes", + PhotonPipelineResult.photonStruct.getTypeString(), new byte[] {}, PubSubOption.periodic(0.01), PubSubOption.sendAll(true), @@ -185,6 +185,8 @@ public class PhotonCamera implements AutoCloseable { * make sure to call this frequently enough to avoid old results being discarded, too! */ public List getAllUnreadResults() { + verifyVersion(); + List ret = new ArrayList<>(); var changes = resultSubscriber.getAllChanges(); diff --git a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp index 34905a382..91a1d9514 100644 --- a/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp +++ b/photon-lib/src/main/native/cpp/photon/PhotonCamera.cpp @@ -69,6 +69,10 @@ void PhotonCamera::SetVersionCheckEnabled(bool enabled) { VERSION_CHECK_ENABLED = enabled; } +static const std::string TYPE_STRING = + std::string{"photonstruct:PhotonPipelineResult:"} + + std::string{SerdeType::GetSchemaHash()}; + PhotonCamera::PhotonCamera(nt::NetworkTableInstance instance, const std::string_view cameraName) : mainTable(instance.GetTable("photonvision")), @@ -76,7 +80,7 @@ PhotonCamera::PhotonCamera(nt::NetworkTableInstance instance, rawBytesEntry( rootTable->GetRawTopic("rawBytes") .Subscribe( - "rawBytes", {}, + TYPE_STRING, {}, {.pollStorage = 20, .periodic = 0.01, .sendAll = true})), inputSaveImgEntry( rootTable->GetIntegerTopic("inputSaveImgCmd").Publish()), @@ -262,17 +266,25 @@ void PhotonCamera::VerifyVersion() { std::string cameraNameOutString; for (unsigned int i = 0; i < cameraNames.size(); i++) { - cameraNameOutString += "\n" + cameraNames[i]; + cameraNameOutString += ("\n" + cameraNames[i]); } FRC_ReportError( frc::warn::Warning, - "Found the following PhotonVision cameras on NetworkTables:{}", + "Found the following PhotonVision cameras on NetworkTables:\n{}", cameraNameOutString); } } else { std::string local_uuid{SerdeType::GetSchemaHash()}; - std::string remote_uuid = + + // implicit conversion here might throw an exception, so be careful of that + wpi::json remote_uuid_json = rawBytesEntry.GetTopic().GetProperty("message_uuid"); + if (!remote_uuid_json.is_string()) { + FRC_ReportError(frc::warn::Warning, + "Cannot find property message_uuid for PhotonCamera {}", + path); + } + std::string remote_uuid{remote_uuid_json}; if (local_uuid != remote_uuid) { FRC_ReportError(frc::warn::Warning, bfw); 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 94c31f0f4..c8da8306b 100644 --- a/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp +++ b/photon-lib/src/main/native/cpp/photon/simulation/PhotonCameraSim.cpp @@ -353,8 +353,7 @@ void PhotonCameraSim::SubmitProcessedFrame(const PhotonPipelineResult& result, ts.targetPitchEntry.Set(0.0, ReceiveTimestamp); ts.targetYawEntry.Set(0.0, ReceiveTimestamp); ts.targetAreaEntry.Set(0.0, ReceiveTimestamp); - std::array poseData{0.0, 0.0, 0.0}; - ts.targetPoseEntry.Set(poseData, ReceiveTimestamp); + ts.targetPoseEntry.Set(frc::Transform3d{}, ReceiveTimestamp); ts.targetSkewEntry.Set(0.0, ReceiveTimestamp); } else { PhotonTrackedTarget bestTarget = result.GetBestTarget(); @@ -364,11 +363,8 @@ void PhotonCameraSim::SubmitProcessedFrame(const PhotonPipelineResult& result, ts.targetAreaEntry.Set(bestTarget.GetArea(), ReceiveTimestamp); ts.targetSkewEntry.Set(bestTarget.GetSkew(), ReceiveTimestamp); - frc::Transform3d transform = bestTarget.GetBestCameraToTarget(); - std::array poseData{ - transform.X().to(), transform.Y().to(), - transform.Rotation().ToRotation2d().Degrees().to()}; - ts.targetPoseEntry.Set(poseData, ReceiveTimestamp); + ts.targetPoseEntry.Set(bestTarget.GetBestCameraToTarget(), + ReceiveTimestamp); } Eigen::Matrix intrinsics = diff --git a/photon-targeting/src/main/java/org/photonvision/common/networktables/PacketSubscriber.java b/photon-targeting/src/main/java/org/photonvision/common/networktables/PacketSubscriber.java index aca8c4d92..9a045d5b7 100644 --- a/photon-targeting/src/main/java/org/photonvision/common/networktables/PacketSubscriber.java +++ b/photon-targeting/src/main/java/org/photonvision/common/networktables/PacketSubscriber.java @@ -88,7 +88,9 @@ public class PacketSubscriber implements AutoCloseable { // TODO - i can see an argument for moving this logic all here instead of keeping in photoncamera public String getInterfaceUUID() { - return subscriber.getTopic().getProperty("message_uuid"); + // ntcore hands us a JSON string with leading/trailing quotes - remove those + var uuidStr = subscriber.getTopic().getProperty("message_uuid"); + return uuidStr.replace("\"", ""); } public List> getAllChanges() { diff --git a/photon-targeting/src/main/native/include/photon/networktables/NTTopicSet.h b/photon-targeting/src/main/native/include/photon/networktables/NTTopicSet.h index ff647cd7c..e3f79a91e 100644 --- a/photon-targeting/src/main/native/include/photon/networktables/NTTopicSet.h +++ b/photon-targeting/src/main/native/include/photon/networktables/NTTopicSet.h @@ -18,15 +18,22 @@ #pragma once #include +#include +#include #include #include #include #include #include #include +#include namespace photon { +const std::string PhotonPipelineResult_TYPE_STRING = + std::string{"photonstruct:PhotonPipelineResult:"} + + std::string{SerdeType::GetSchemaHash()}; + class NTTopicSet { public: std::shared_ptr subTable; @@ -44,7 +51,7 @@ class NTTopicSet { nt::DoublePublisher targetPitchEntry; nt::DoublePublisher targetYawEntry; nt::DoublePublisher targetAreaEntry; - nt::DoubleArrayPublisher targetPoseEntry; + nt::StructPublisher targetPoseEntry; nt::DoublePublisher targetSkewEntry; nt::DoublePublisher bestTargetPosX; @@ -60,8 +67,8 @@ class NTTopicSet { nt::PubSubOptions options; options.periodic = 0.01; options.sendAll = true; - rawBytesEntry = - subTable->GetRawTopic("rawBytes").Publish("rawBytes", options); + rawBytesEntry = subTable->GetRawTopic("rawBytes") + .Publish(PhotonPipelineResult_TYPE_STRING, options); pipelineIndexPublisher = subTable->GetIntegerTopic("pipelineIndexState").Publish(); @@ -80,7 +87,8 @@ class NTTopicSet { targetPitchEntry = subTable->GetDoubleTopic("targetPitch").Publish(); targetAreaEntry = subTable->GetDoubleTopic("targetArea").Publish(); targetYawEntry = subTable->GetDoubleTopic("targetYaw").Publish(); - targetPoseEntry = subTable->GetDoubleArrayTopic("targetPose").Publish(); + targetPoseEntry = + subTable->GetStructTopic("targetPose").Publish(); targetSkewEntry = subTable->GetDoubleTopic("targetSkew").Publish(); bestTargetPosX = subTable->GetDoubleTopic("targetPixelsX").Publish(); diff --git a/photonlib-java-examples/aimandrange/build.gradle b/photonlib-java-examples/aimandrange/build.gradle index 28dc34bca..9a885f3e8 100644 --- a/photonlib-java-examples/aimandrange/build.gradle +++ b/photonlib-java-examples/aimandrange/build.gradle @@ -10,6 +10,10 @@ apply from: "${rootDir}/../shared/examples_common.gradle" def ROBOT_MAIN_CLASS = "frc.robot.Main" +repositories { + mavenLocal(); +} + wpi.maven.useDevelopment = true wpi.versions.wpilibVersion = "2024.3.2" wpi.versions.wpimathVersion = "2024.3.2"