Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
BytingBulldogs3539 authored Dec 1, 2023
2 parents 6969c2b + 469bc0e commit bbb6fe6
Show file tree
Hide file tree
Showing 98 changed files with 2,119 additions and 1,359 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Steps to reproduce the behavior:
4. See error

**Screenshots / Videos**
If applicable, add screenshots to help explain your problem. Additionally, provide journalctl logs and settings zip export.
If applicable, add screenshots to help explain your problem. Additionally, provide journalctl logs and settings zip export. If your issue is regarding the web dashboard, please provide screenshots and the output of the browser console.

**Platform:**
- Hardware Platform (ex. Raspberry Pi 4, Windows x64):
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ jobs:
path: build/html
build-photonlib-host:
env:
MACOSX_DEPLOYMENT_TARGET: 11
MACOSX_DEPLOYMENT_TARGET: 12
strategy:
fail-fast: false
matrix:
Expand Down
14 changes: 5 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id "com.diffplug.spotless" version "6.22.0"
id "edu.wpi.first.NativeUtils" version "2024.2.0" apply false
id "edu.wpi.first.NativeUtils" version "2024.3.2" apply false
id "edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin" version "2020.2"
id "edu.wpi.first.GradleRIO" version "2024.1.1-beta-3"
id 'edu.wpi.first.WpilibTools' version '1.3.0'
Expand All @@ -21,6 +21,7 @@ apply from: "versioningHelper.gradle"

ext {
wpilibVersion = "2024.1.1-beta-3"
wpimathVersion = wpilibVersion
openCVversion = "4.8.0-2"
joglVersion = "2.4.0-rc-20200307"
javalinVersion = "5.6.2"
Expand All @@ -36,16 +37,11 @@ ext {
if (nativeName == "macx64") nativeName = "osxx86-64";
if (nativeName == "macarm64") nativeName = "osxarm64";
jniPlatform = nativeName
println("Building for platform " + jniPlatform)
println("Building for platform: " + jniPlatform)
println("Using Wpilib: " + wpilibVersion)
println("Using OpenCV: " + openCVversion)
}

wpilibTools.deps.wpilibVersion = wpilibVersion

// Tell gradlerio what version of things to use (that we care about)
// See: https://github.com/wpilibsuite/GradleRIO/blob/main/src/main/java/edu/wpi/first/gradlerio/wpi/WPIVersionsExtension.java
wpi.getVersions().getOpencvVersion().convention(openCVversion);
wpi.getVersions().getWpilibVersion().convention(wpilibVersion);

spotless {
java {
target fileTree('.') {
Expand Down
39 changes: 23 additions & 16 deletions photon-client/src/components/app/photon-camera-stream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PvIcon from "@/components/common/pv-icon.vue";
const props = defineProps<{
streamType: "Raw" | "Processed";
id?: string;
id: string;
}>();
const streamSrc = computed<string>(() => {
Expand All @@ -25,8 +25,6 @@ const streamDesc = computed<string>(() => `${props.streamType} Stream View`);
const streamStyle = computed<StyleValue>(() => {
if (useStateStore().colorPickingMode) {
return { width: "100%", cursor: "crosshair" };
} else if (streamSrc.value !== loadingImage) {
return { width: "100%", cursor: "pointer" };
}
return { width: "100%" };
Expand All @@ -40,37 +38,45 @@ const overlayStyle = computed<StyleValue>(() => {
}
});
const handleStreamClick = () => {
if (!useStateStore().colorPickingMode && streamSrc.value !== loadingImage) {
window.open(streamSrc.value);
}
};
const handleCaptureClick = () => {
if (props.streamType === "Raw") {
useCameraSettingsStore().saveInputSnapshot();
} else {
useCameraSettingsStore().saveOutputSnapshot();
}
};
const handlePopoutClick = () => {
window.open(streamSrc.value);
};
const handleFullscreenRequest = () => {
const stream = document.getElementById(props.id);
if (!stream) return;
stream.requestFullscreen();
};
</script>

<template>
<div class="stream-container">
<img
:id="id"
crossorigin="anonymous"
:src="streamSrc"
:alt="streamDesc"
:style="streamStyle"
@click="handleStreamClick"
/>
<img :id="id" crossorigin="anonymous" :src="streamSrc" :alt="streamDesc" :style="streamStyle" />
<div class="stream-overlay" :style="overlayStyle">
<pv-icon
icon-name="mdi-camera-image"
tooltip="Capture and save a frame of this stream"
class="ma-1 mr-2"
@click="handleCaptureClick"
/>
<pv-icon
icon-name="mdi-fullscreen"
tooltip="Open this stream in fullscreen"
class="ma-1 mr-2"
@click="handleFullscreenRequest"
/>
<pv-icon
icon-name="mdi-open-in-new"
tooltip="Open this stream in a new window"
class="ma-1 mr-2"
@click="handlePopoutClick"
/>
</div>
</div>
</template>
Expand All @@ -81,6 +87,7 @@ const handleCaptureClick = () => {
}
.stream-overlay {
display: flex;
opacity: 0;
transition: 0.1s ease;
position: absolute;
Expand Down
14 changes: 12 additions & 2 deletions photon-client/src/components/cameras/CamerasView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,20 @@ const fpsTooLow = computed<boolean>(() => {
</v-card-title>
<div class="stream-container pb-4">
<div class="stream">
<photon-camera-stream v-show="value.includes(0)" stream-type="Raw" style="max-width: 100%" />
<photon-camera-stream
v-show="value.includes(0)"
id="input-camera-stream"
stream-type="Raw"
style="max-width: 100%"
/>
</div>
<div class="stream">
<photon-camera-stream v-show="value.includes(1)" stream-type="Processed" style="max-width: 100%" />
<photon-camera-stream
v-show="value.includes(1)"
id="output-camera-stream"
stream-type="Processed"
style="max-width: 100%"
/>
</div>
</div>
<v-divider />
Expand Down
13 changes: 10 additions & 3 deletions photon-client/src/components/dashboard/tabs/TargetsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings
useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled
"
>
<th class="text-center">Ambiguity %</th>
<th class="text-center">Ambiguity Ratio</th>
</template>
</tr>
</thead>
Expand Down Expand Up @@ -73,7 +73,7 @@ const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings
useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled
"
>
<td>{{ target.ambiguity >= 0 ? target.ambiguity?.toFixed(2) + "%" : "(In Multi-Target)" }}</td>
<td>{{ target.ambiguity >= 0 ? target.ambiguity.toFixed(2) : "(In Multi-Target)" }}</td>
</template>
</tr>
</tbody>
Expand Down Expand Up @@ -102,7 +102,14 @@ const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings
<tbody v-show="useStateStore().currentPipelineResults?.multitagResult">
<td>{{ useStateStore().currentPipelineResults?.multitagResult?.bestTransform.x.toFixed(2) }}&nbsp;m</td>
<td>{{ useStateStore().currentPipelineResults?.multitagResult?.bestTransform.y.toFixed(2) }}&nbsp;m</td>
<td>{{ useStateStore().currentPipelineResults?.multitagResult?.bestTransform.angle_z.toFixed(2) }}&deg;</td>
<td>
{{
(
useStateStore().currentPipelineResults?.multitagResult?.bestTransform.angle_z *
(180.0 / Math.PI)
).toFixed(2)
}}&deg;
</td>
<td>{{ useStateStore().currentPipelineResults?.multitagResult?.fiducialIDsUsed }}</td>
</tbody>
</v-simple-table>
Expand Down
18 changes: 2 additions & 16 deletions photon-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
plugins {
id 'edu.wpi.first.WpilibTools' version '1.3.0'
}

import java.nio.file.Path

apply from: "${rootDir}/shared/common.gradle"

dependencies {
implementation project(':photon-targeting')

implementation "io.javalin:javalin:$javalinVersion"

implementation 'org.msgpack:msgpack-core:0.9.0'
implementation 'org.msgpack:jackson-dataformat-msgpack:0.9.0'

// JOGL stuff (currently we only distribute for aarch64, which is Pi 4)
implementation "org.jogamp.gluegen:gluegen-rt:$joglVersion"
implementation "org.jogamp.jogl:jogl-all:$joglVersion"

implementation "org.jogamp.gluegen:gluegen-rt:$joglVersion:natives-linux-aarch64"
implementation "org.jogamp.jogl:jogl-all:$joglVersion:natives-linux-aarch64"

// Zip
implementation 'org.zeroturnaround:zt-zip:1.14'

implementation wpilibTools.deps.wpilibJava("apriltag")

implementation "org.xerial:sqlite-jdbc:3.41.0.0"
}

task writeCurrentVersionJava {
task writeCurrentVersion {
def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
writePhotonVersionFile(versionFileIn, Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
versionString)
}

build.dependsOn writeCurrentVersionJava
build.dependsOn writeCurrentVersion
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.photonvision.vision.camera;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -108,8 +110,20 @@ public static QuirkyCamera getQuirkyCamera(int usbVid, int usbPid, String baseNa
for (var qc : quirkyCameras) {
boolean hasBaseName = !qc.baseName.isEmpty();
boolean matchesBaseName = qc.baseName.equals(baseName) || !hasBaseName;
// If we have a quirkycamera we need to copy the quirks from our predefined object and create
// a quirkycamera object with the baseName.
if (qc.usbVid == usbVid && qc.usbPid == usbPid && matchesBaseName) {
return qc;
List<CameraQuirk> quirks = new ArrayList<CameraQuirk>();
for (var q : CameraQuirk.values()) {
if (qc.hasQuirk(q)) quirks.add(q);
}
QuirkyCamera c =
new QuirkyCamera(
usbVid,
usbPid,
baseName,
Arrays.copyOf(quirks.toArray(), quirks.size(), CameraQuirk[].class));
return c;
}
}
return new QuirkyCamera(usbVid, usbPid, baseName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
import org.photonvision.common.util.TestUtils;
import org.photonvision.vision.frame.FrameProvider;
import org.photonvision.vision.frame.provider.FileFrameProvider;
import org.photonvision.vision.frame.provider.USBFrameProvider;
import org.photonvision.vision.processes.VisionSource;
import org.photonvision.vision.processes.VisionSourceSettables;
Expand All @@ -37,10 +39,10 @@ public class USBCameraSource extends VisionSource {
private final Logger logger;
private final UsbCamera camera;
private final USBCameraSettables usbCameraSettables;
private final USBFrameProvider usbFrameProvider;
private FrameProvider usbFrameProvider;
private final CvSink cvSink;

public final QuirkyCamera cameraQuirks;
private QuirkyCamera cameraQuirks;

public USBCameraSource(CameraConfiguration config) {
super(config);
Expand Down Expand Up @@ -77,6 +79,22 @@ public USBCameraSource(CameraConfiguration config) {
}
}

/**
* Mostly just used for unit tests to better simulate a usb camera without a camera being present.
*/
public USBCameraSource(CameraConfiguration config, int pid, int vid, boolean unitTest) {
this(config);

cameraQuirks = QuirkyCamera.getQuirkyCamera(pid, vid, config.baseName);

if (unitTest)
usbFrameProvider =
new FileFrameProvider(
TestUtils.getWPIImagePath(
TestUtils.WPI2019Image.kCargoStraightDark72in_HighRes, false),
TestUtils.WPI2019Image.FOV);
}

void disableAutoFocus() {
if (cameraQuirks.hasQuirk(CameraQuirk.AdjustableFocus)) {
try {
Expand All @@ -88,6 +106,10 @@ void disableAutoFocus() {
}
}

public QuirkyCamera getCameraQuirks() {
return this.cameraQuirks;
}

@Override
public FrameProvider getFrameProvider() {
return usbFrameProvider;
Expand All @@ -103,7 +125,7 @@ protected USBCameraSettables(CameraConfiguration configuration) {
super(configuration);
getAllVideoModes();
if (!cameraQuirks.hasQuirk(CameraQuirk.StickyFPS))
setVideoMode(videoModes.get(0)); // fixes double FPS set
if (!videoModes.isEmpty()) setVideoMode(videoModes.get(0)); // fixes double FPS set
}

public void setAutoExposure(boolean cameraAutoExposure) {
Expand Down Expand Up @@ -343,11 +365,27 @@ public boolean isVendorCamera() {
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
USBCameraSource that = (USBCameraSource) o;
return cameraQuirks.equals(that.cameraQuirks);
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
USBCameraSource other = (USBCameraSource) obj;
if (camera == null) {
if (other.camera != null) return false;
} else if (!camera.equals(other.camera)) return false;
if (usbCameraSettables == null) {
if (other.usbCameraSettables != null) return false;
} else if (!usbCameraSettables.equals(other.usbCameraSettables)) return false;
if (usbFrameProvider == null) {
if (other.usbFrameProvider != null) return false;
} else if (!usbFrameProvider.equals(other.usbFrameProvider)) return false;
if (cvSink == null) {
if (other.cvSink != null) return false;
} else if (!cvSink.equals(other.cvSink)) return false;
if (cameraQuirks == null) {
if (other.cameraQuirks != null) return false;
} else if (!cameraQuirks.equals(other.cameraQuirks)) return false;
return true;
}

@Override
Expand Down
Loading

0 comments on commit bbb6fe6

Please sign in to comment.