mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-19 00:41:41 +00:00
Fix version verification with non-default networktable (#407)
Adds version verification to c++ too
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -143,3 +143,4 @@ build/*
|
||||
build
|
||||
photon-lib/src/main/java/org/photonvision/PhotonVersion.java
|
||||
/photonlib-java-examples/bin/
|
||||
photon-lib/src/generate/native/include/PhotonVersion.h
|
||||
|
||||
@@ -25,7 +25,8 @@ dependencies {
|
||||
}
|
||||
|
||||
task writeCurrentVersionJava {
|
||||
writePhotonVersionFile(Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
|
||||
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
|
||||
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
|
||||
versionString)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ model {
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs "src/main/native/include"
|
||||
srcDirs "src/generate/native/include"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,11 +106,15 @@ task generateVendorJson() {
|
||||
build.dependsOn generateVendorJson
|
||||
|
||||
|
||||
task writeCurrentVersionJava {
|
||||
writePhotonVersionFile(Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
|
||||
task writeCurrentVersion {
|
||||
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
|
||||
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
|
||||
versionString)
|
||||
versionFileIn = file("${rootDir}/shared/PhotonVersion.h.in")
|
||||
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "generate", "native", "include", "PhotonVersion.h"),
|
||||
versionString)
|
||||
}
|
||||
|
||||
build.dependsOn writeCurrentVersionJava
|
||||
build.dependsOn writeCurrentVersion
|
||||
|
||||
apply from: "publish.gradle"
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.photonvision.targeting.PhotonPipelineResult;
|
||||
|
||||
/** Represents a camera that is connected to PhotonVision. */
|
||||
public class PhotonCamera {
|
||||
protected final NetworkTable rootTable;
|
||||
final NetworkTableEntry rawBytesEntry;
|
||||
final NetworkTableEntry driverModeEntry;
|
||||
final NetworkTableEntry inputSaveImgEntry;
|
||||
@@ -42,7 +43,6 @@ public class PhotonCamera {
|
||||
final NetworkTableEntry ledModeEntry;
|
||||
final NetworkTableEntry versionEntry;
|
||||
|
||||
final NetworkTable mainTable = NetworkTableInstance.getDefault().getTable("photonvision");
|
||||
private final String path;
|
||||
|
||||
Packet packet = new Packet(1);
|
||||
@@ -50,9 +50,14 @@ public class PhotonCamera {
|
||||
/**
|
||||
* Constructs a PhotonCamera from a root table.
|
||||
*
|
||||
* @param rootTable The root table that the camera is broadcasting information over.
|
||||
* @param instance The NetworkTableInstance to pull data from. This can be a custom instance in
|
||||
* simulation, but should *usually* be the default NTInstance from
|
||||
* NetworkTableInstance::getDefault
|
||||
* @param cameraName The name of the camera, as seen in the UI.
|
||||
*/
|
||||
public PhotonCamera(NetworkTable rootTable) {
|
||||
public PhotonCamera(NetworkTableInstance instance, String cameraName) {
|
||||
var mainTable = instance.getTable("photonvision");
|
||||
this.rootTable = mainTable.getSubTable(cameraName);
|
||||
path = rootTable.getPath();
|
||||
rawBytesEntry = rootTable.getEntry("rawBytes");
|
||||
driverModeEntry = rootTable.getEntry("driverMode");
|
||||
@@ -69,7 +74,7 @@ public class PhotonCamera {
|
||||
* @param cameraName The nickname of the camera (found in the PhotonVision UI).
|
||||
*/
|
||||
public PhotonCamera(String cameraName) {
|
||||
this(NetworkTableInstance.getDefault().getTable("photonvision").getSubTable(cameraName));
|
||||
this(NetworkTableInstance.getDefault(), cameraName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
package org.photonvision;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import java.util.Arrays;
|
||||
@@ -46,10 +45,13 @@ public class SimPhotonCamera extends PhotonCamera {
|
||||
/**
|
||||
* Constructs a Simulated PhotonCamera from a root table.
|
||||
*
|
||||
* @param rootTable The root table that the camera is broadcasting information over.
|
||||
* @param instance The NetworkTableInstance to pull data from. This can be a custom instance in
|
||||
* simulation, but should *usually* be the default NTInstance from
|
||||
* NetworkTableInstance::getDefault
|
||||
* @param cameraName The name of the camera, as seen in the UI.
|
||||
*/
|
||||
public SimPhotonCamera(NetworkTable rootTable) {
|
||||
super(rootTable);
|
||||
public SimPhotonCamera(NetworkTableInstance instance, String cameraName) {
|
||||
super(instance, cameraName);
|
||||
|
||||
latencyMillisEntry = rootTable.getEntry("latencyMillis");
|
||||
hasTargetEntry = rootTable.getEntry("hasTargetEntry");
|
||||
@@ -66,7 +68,7 @@ public class SimPhotonCamera extends PhotonCamera {
|
||||
* @param cameraName The nickname of the camera (found in the PhotonVision UI).
|
||||
*/
|
||||
public SimPhotonCamera(String cameraName) {
|
||||
this(NetworkTableInstance.getDefault().getTable("photonvision").getSubTable(cameraName));
|
||||
this(NetworkTableInstance.getDefault(), cameraName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,23 +24,34 @@
|
||||
|
||||
#include "photonlib/PhotonCamera.h"
|
||||
|
||||
#include <frc/Errors.h>
|
||||
|
||||
#include "PhotonVersion.h"
|
||||
#include "photonlib/Packet.h"
|
||||
|
||||
namespace photonlib {
|
||||
PhotonCamera::PhotonCamera(std::shared_ptr<nt::NetworkTable> rootTable)
|
||||
: rawBytesEntry(rootTable->GetEntry("rawBytes")),
|
||||
PhotonCamera::PhotonCamera(std::shared_ptr<nt::NetworkTableInstance> instance,
|
||||
const std::string& cameraName)
|
||||
: mainTable(instance->GetTable("photonvision")),
|
||||
rootTable(mainTable->GetSubTable(cameraName)),
|
||||
rawBytesEntry(rootTable->GetEntry("rawBytes")),
|
||||
driverModeEntry(rootTable->GetEntry("driverMode")),
|
||||
inputSaveImgEntry(rootTable->GetEntry("inputSaveImgCmd")),
|
||||
outputSaveImgEntry(rootTable->GetEntry("outputSaveImgCmd")),
|
||||
pipelineIndexEntry(rootTable->GetEntry("pipelineIndex")),
|
||||
ledModeEntry(mainTable->GetEntry("ledMode")) {}
|
||||
ledModeEntry(mainTable->GetEntry("ledMode")),
|
||||
versionEntry(mainTable->GetEntry("version")),
|
||||
path(rootTable->GetPath()) {}
|
||||
|
||||
PhotonCamera::PhotonCamera(const std::string& cameraName)
|
||||
: PhotonCamera(nt::NetworkTableInstance::GetDefault()
|
||||
.GetTable("photonvision")
|
||||
->GetSubTable(cameraName)) {}
|
||||
: PhotonCamera(std::make_shared<nt::NetworkTableInstance>(
|
||||
nt::NetworkTableInstance::GetDefault()),
|
||||
cameraName) {}
|
||||
|
||||
PhotonPipelineResult PhotonCamera::GetLatestResult() const {
|
||||
// Prints warning if not connected
|
||||
VerifyVersion();
|
||||
|
||||
// Clear the current packet.
|
||||
packet.Clear();
|
||||
|
||||
@@ -87,4 +98,20 @@ LEDMode PhotonCamera::GetLEDMode() const {
|
||||
void PhotonCamera::SetLEDMode(LEDMode mode) {
|
||||
ledModeEntry.SetDouble(static_cast<double>(static_cast<int>(mode)));
|
||||
}
|
||||
|
||||
void PhotonCamera::VerifyVersion() const {
|
||||
const std::string& versionString = versionEntry.GetString("");
|
||||
if (versionString.empty()) {
|
||||
std::string path_ = path;
|
||||
FRC_ReportError(
|
||||
frc::warn::Warning,
|
||||
"PhotonVision coprocessor at path {} not found on NetworkTables!",
|
||||
path_);
|
||||
} else if (!VersionMatches(versionString)) {
|
||||
FRC_ReportError(frc::warn::Warning,
|
||||
"Photon version {} does not match coprocessor version {}!",
|
||||
PhotonVersion::versionString, versionString);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace photonlib
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
|
||||
namespace photonlib {
|
||||
|
||||
SimPhotonCamera::SimPhotonCamera(std::shared_ptr<nt::NetworkTable> rootTable)
|
||||
: PhotonCamera(rootTable) {}
|
||||
SimPhotonCamera::SimPhotonCamera(
|
||||
std::shared_ptr<nt::NetworkTableInstance> instance,
|
||||
const std::string& cameraName)
|
||||
: PhotonCamera(instance, cameraName) {}
|
||||
|
||||
SimPhotonCamera::SimPhotonCamera(const std::string& cameraName)
|
||||
: PhotonCamera(cameraName) {}
|
||||
|
||||
@@ -45,10 +45,15 @@ class PhotonCamera {
|
||||
public:
|
||||
/**
|
||||
* Constructs a PhotonCamera from a root table.
|
||||
* @param rootTable The root table that the camera is broadcasting information
|
||||
*
|
||||
* @param instance The NetworkTableInstance to pull data from. This can be a
|
||||
* custom instance in simulation, but should *usually* be the default
|
||||
* NTInstance from {@link NetworkTableInstance::getDefault}
|
||||
* @param cameraName The name of the camera, as seen in the UI.
|
||||
* over.
|
||||
*/
|
||||
explicit PhotonCamera(std::shared_ptr<nt::NetworkTable> rootTable);
|
||||
explicit PhotonCamera(std::shared_ptr<nt::NetworkTableInstance> instance,
|
||||
const std::string& cameraName);
|
||||
|
||||
/**
|
||||
* Constructs a PhotonCamera from the name of the camera.
|
||||
@@ -133,19 +138,23 @@ class PhotonCamera {
|
||||
"This method should be replaced with PhotonPipelineResult::HasTargets()")
|
||||
bool HasTargets() const { return GetLatestResult().HasTargets(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<nt::NetworkTable> mainTable =
|
||||
nt::NetworkTableInstance::GetDefault().GetTable("photonvision");
|
||||
|
||||
protected:
|
||||
std::shared_ptr<nt::NetworkTable> mainTable;
|
||||
std::shared_ptr<nt::NetworkTable> rootTable;
|
||||
nt::NetworkTableEntry rawBytesEntry;
|
||||
nt::NetworkTableEntry driverModeEntry;
|
||||
nt::NetworkTableEntry inputSaveImgEntry;
|
||||
nt::NetworkTableEntry outputSaveImgEntry;
|
||||
nt::NetworkTableEntry pipelineIndexEntry;
|
||||
nt::NetworkTableEntry ledModeEntry;
|
||||
nt::NetworkTableEntry versionEntry;
|
||||
|
||||
std::string path;
|
||||
|
||||
mutable Packet packet;
|
||||
|
||||
private:
|
||||
void VerifyVersion() const;
|
||||
};
|
||||
|
||||
} // namespace photonlib
|
||||
|
||||
@@ -44,10 +44,13 @@ class SimPhotonCamera : public PhotonCamera {
|
||||
/**
|
||||
* Constructs a Simulated PhotonCamera from a root table.
|
||||
*
|
||||
* @param rootTable The root table that the camera is broadcasting information
|
||||
* over.
|
||||
* @param instance The NetworkTableInstance to pull data from. This can be a
|
||||
* custom instance in simulation, but should *usually* be the default
|
||||
* NTInstance from {@link NetworkTableInstance::getDefault}
|
||||
* @param cameraName The name of the camera, as seen in the UI.
|
||||
*/
|
||||
explicit SimPhotonCamera(std::shared_ptr<nt::NetworkTable> rootTable);
|
||||
explicit SimPhotonCamera(std::shared_ptr<nt::NetworkTableInstance> instance,
|
||||
const std::string& cameraName);
|
||||
|
||||
/**
|
||||
* Constructs a Simulated PhotonCamera from the name of the camera.
|
||||
|
||||
45
shared/PhotonVersion.h.in
Normal file
45
shared/PhotonVersion.h.in
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) Photon Vision.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <regex>
|
||||
|
||||
/*
|
||||
* Autogenerated file! Do not manually edit this file. This version is
|
||||
* regenerated any time the publish task is run, or when this file is deleted.
|
||||
*/
|
||||
|
||||
namespace photonlib {
|
||||
namespace PhotonVersion {
|
||||
const std::string versionString = "dev-v2022.1.4-2-ga22f8af0";
|
||||
const std::string buildDate = "2022-1-20 10:10:04";
|
||||
const bool isRelease = !(versionString.rfind("dev", 0) == 0);
|
||||
}
|
||||
|
||||
bool VersionMatches(const std::string& other) {
|
||||
std::smatch match;
|
||||
std::regex versionPattern{"v[0-9]+.[0-9]+.[0-9]+"};
|
||||
// Check that both versions are in the right format
|
||||
if (std::regex_search(PhotonVersion::versionString, match, versionPattern) &&
|
||||
std::regex_search(other, match, versionPattern)) {
|
||||
// If they are, check string equality
|
||||
return (PhotonVersion::versionString == other);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,14 @@ gradle.allprojects {
|
||||
ext.versionString = getCurrentVersion()
|
||||
}
|
||||
|
||||
ext.writePhotonVersionFile = { Path path, String version ->
|
||||
ext.writePhotonVersionFile = {File versionFileIn, Path path, String version ->
|
||||
println("Writing " + version + " to " + path.toAbsolutePath().toString())
|
||||
String date = DateTimeFormatter.ofPattern("yyyy-M-d hh:mm:ss").format(LocalDateTime.now())
|
||||
File versionFileOut = new File(path.toAbsolutePath().toString())
|
||||
versionFileOut.delete()
|
||||
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
|
||||
def read = versionFileIn.text.replace('${version}', version).replace('${date}', date)
|
||||
if (!versionFileOut.parentFile.exists()) versionFileOut.parentFile.mkdirs()
|
||||
if (!versionFileOut.exists()) versionFileOut.createNewFile()
|
||||
versionFileOut.write(read)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user