Skip to content

Commit

Permalink
Merge branch 'master' into multiag-pnp
Browse files Browse the repository at this point in the history
  • Loading branch information
srimanachanta authored Oct 17, 2023
2 parents f44aa75 + ededc4f commit 77c0502
Show file tree
Hide file tree
Showing 13 changed files with 368 additions and 308 deletions.
299 changes: 76 additions & 223 deletions .github/workflows/main.yml → .github/workflows/build.yml

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions .github/workflows/lint-format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Lint and Format

on:
push:
branches: [ master ]
tags:
- 'v*'
pull_request:
branches: [ master ]

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true

jobs:
wpiformat:
name: "wpiformat"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install wpiformat
run: pip3 install wpiformat
- name: Run
run: wpiformat
- name: Check output
run: git --no-pager diff --exit-code HEAD
- name: Generate diff
run: git diff HEAD > wpiformat-fixes.patch
if: ${{ failure() }}
- uses: actions/upload-artifact@v3
with:
name: wpiformat fixes
path: wpiformat-fixes.patch
if: ${{ failure() }}
javaformat:
name: "Java Formatting"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- run: |
chmod +x gradlew
./gradlew spotlessCheck
client-lint-format:
name: "PhotonClient Lint and Formatting"
defaults:
run:
working-directory: photon-client
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Dependencies
run: npm ci
- name: Check Linting
run: npm run lint-ci
- name: Check Formatting
run: npm run format-ci
server-index:
name: "Check server index.html not changed"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Check index.html not changed
run: git --no-pager diff --exit-code origin/master photon-server/src/main/resources/web/index.html
74 changes: 62 additions & 12 deletions photon-client/src/components/app/photon-camera-stream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
import { useStateStore } from "@/stores/StateStore";
import loadingImage from "@/assets/images/loading.svg";
import type { StyleValue } from "vue/types/jsx";
import CvIcon from "@/components/common/cv-icon.vue";
const props = defineProps<{
streamType: "Raw" | "Processed";
id?: string;
}>();
const src = computed<string>(() => {
const streamSrc = computed<string>(() => {
const port =
useCameraSettingsStore().currentCameraSettings.stream[props.streamType === "Raw" ? "inputPort" : "outputPort"];
Expand All @@ -20,25 +21,74 @@ const src = computed<string>(() => {
return `http://${inject("backendHostname")}:${port}/stream.mjpg`;
});
const alt = computed<string>(() => `${props.streamType} Stream View`);
const style = computed<StyleValue>(() => {
const streamDesc = computed<string>(() => `${props.streamType} Stream View`);
const streamStyle = computed<StyleValue>(() => {
if (useStateStore().colorPickingMode) {
return { cursor: "crosshair" };
} else if (src.value !== loadingImage) {
return { cursor: "pointer" };
return { width: "100%", cursor: "crosshair" };
} else if (streamSrc.value !== loadingImage) {
return { width: "100%", cursor: "pointer" };
}
return {};
return { width: "100%" };
});
const handleClick = () => {
if (!useStateStore().colorPickingMode && src.value !== loadingImage) {
window.open(src.value);
const overlayStyle = computed<StyleValue>(() => {
if (useStateStore().colorPickingMode || streamSrc.value == loadingImage) {
return { display: "none" };
} else {
return {};
}
});
const handleStreamClick = () => {
if (!useStateStore().colorPickingMode && streamSrc.value !== loadingImage) {
window.open(streamSrc.value);
}
};
const handleCaptureClick = () => {
if (props.streamType === "Raw") {
useCameraSettingsStore().saveInputSnapshot();
} else {
useCameraSettingsStore().saveOutputSnapshot();
}
};
</script>

<template>
<img :id="id" crossorigin="anonymous" :src="src" :alt="alt" :style="style" @click="handleClick" />
<div class="stream-container">
<img
:id="id"
crossorigin="anonymous"
:src="streamSrc"
:alt="streamDesc"
:style="streamStyle"
@click="handleStreamClick"
/>
<div class="stream-overlay" :style="overlayStyle">
<cv-icon
icon-name="mdi-camera-image"
tooltip="Capture and save a frame of this stream"
class="ma-1 mr-2"
@click="handleCaptureClick"
/>
</div>
</div>
</template>

<style scoped>
.stream-container {
position: relative;
}
.stream-overlay {
opacity: 0;
transition: 0.1s ease;
position: absolute;
top: 0;
right: 0;
}
.stream-container:hover .stream-overlay {
opacity: 1;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ const endCalibration = () => {
color="secondary"
style="width: 100%"
:disabled="!settingsValid"
@click="isCalibrating ? useCameraSettingsStore().takeCalibrationSnapshot(true) : startCalibration()"
@click="isCalibrating ? useCameraSettingsStore().takeCalibrationSnapshot() : startCalibration()"
>
{{ isCalibrating ? "Take Snapshot" : "Start Calibration" }}
</v-btn>
Expand Down
6 changes: 3 additions & 3 deletions photon-client/src/components/cameras/CamerasView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const fpsTooLow = computed<boolean>(() => {
</script>

<template>
<v-card class="mb-3 pr-6 pb-3 pa-4" color="primary" dark>
<v-card class="mb-3 pb-3 pa-4" color="primary" dark>
<v-card-title
class="pb-0 mb-2 pl-4 pt-1"
style="min-height: 50px; justify-content: space-between; align-content: center"
Expand Down Expand Up @@ -133,16 +133,16 @@ th {
.stream {
display: flex;
justify-content: center;
width: 100%;
}

@media only screen and (min-width: 512px) and (max-width: 960px) {
.stream-container {
flex-wrap: nowrap;
justify-content: center;
}

.stream {
width: 50%;
max-width: 50%;
}
}
</style>
22 changes: 12 additions & 10 deletions photon-client/src/components/dashboard/ConfigOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,19 @@ const tabGroups = computed<ConfigOption[][]>(() => {
const isAprilTag = useCameraSettingsStore().currentWebsocketPipelineType === WebsocketPipelineType.AprilTag;
const isAruco = useCameraSettingsStore().currentWebsocketPipelineType === WebsocketPipelineType.Aruco;
return getTabGroups().map((tabGroup) =>
tabGroup.filter(
(tabConfig) =>
!(!allow3d && tabConfig.tabName === "3D") && //Filter out 3D tab any time 3D isn't calibrated
!((!allow3d || isAprilTag || isAruco) && tabConfig.tabName === "PnP") && //Filter out the PnP config tab if 3D isn't available, or we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Threshold") && //Filter out threshold tab if we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Contours") && //Filter out contours if we're doing AprilTags
!(!isAprilTag && tabConfig.tabName === "AprilTag") && //Filter out apriltag unless we actually are doing AprilTags
!(!isAruco && tabConfig.tabName === "Aruco") //Filter out aruco unless we actually are doing Aruco
return getTabGroups()
.map((tabGroup) =>
tabGroup.filter(
(tabConfig) =>
!(!allow3d && tabConfig.tabName === "3D") && //Filter out 3D tab any time 3D isn't calibrated
!((!allow3d || isAprilTag || isAruco) && tabConfig.tabName === "PnP") && //Filter out the PnP config tab if 3D isn't available, or we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Threshold") && //Filter out threshold tab if we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Contours") && //Filter out contours if we're doing AprilTags
!(!isAprilTag && tabConfig.tabName === "AprilTag") && //Filter out apriltag unless we actually are doing AprilTags
!(!isAruco && tabConfig.tabName === "Aruco") //Filter out aruco unless we actually are doing Aruco
)
)
);
.filter((it) => it.length); // Remove empty tab groups
});
onBeforeUpdate(() => {
Expand Down
30 changes: 15 additions & 15 deletions photon-client/src/components/settings/DeviceControlCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,18 @@ const offlineUpdate = ref();
const openOfflineUpdatePrompt = () => {
offlineUpdate.value.click();
};
const handleOfflineUpdate = (payload: Event) => {
const handleOfflineUpdate = (payload: Event & { target: (EventTarget & HTMLInputElement) | null }) => {
if (payload.target === null || !payload.target.files) return;
const formData = new FormData();
formData.append("jarData", payload.target.files[0]);
useStateStore().showSnackbarMessage({
message: "New Software Upload in Progress...",
color: "secondary",
timeout: -1
});
const formData = new FormData();
if (payload.target == null || !payload.target?.files) return;
const files: FileList = payload.target.files as FileList;
formData.append("jarData", files[0]);
axios
.post("/utils/offlineUpdate", formData, {
headers: { "Content-Type": "multipart/form-data" },
Expand Down Expand Up @@ -139,21 +138,17 @@ enum ImportType {
NetworkConfig,
ApriltagFieldLayout
}
const showImportDialog = ref(false);
const importType = ref<ImportType | number>(-1);
const importFile = ref(null);
const importFile = ref<File | null>(null);
const handleSettingsImport = () => {
if (importType.value === -1 || importFile.value === null) return;
const formData = new FormData();
formData.append("data", importFile.value);
let settingsEndpoint;
let settingsEndpoint: string;
switch (importType.value) {
case ImportType.AllSettings:
settingsEndpoint = "";
break;
case ImportType.HardwareConfig:
settingsEndpoint = "/hardwareConfig";
break;
Expand All @@ -166,6 +161,10 @@ const handleSettingsImport = () => {
case ImportType.ApriltagFieldLayout:
settingsEndpoint = "/aprilTagFieldLayout";
break;
default:
case ImportType.AllSettings:
settingsEndpoint = "";
break;
}
axios
Expand Down Expand Up @@ -249,7 +248,7 @@ const handleSettingsImport = () => {
<v-card-title>Import Settings</v-card-title>
<v-card-text>
Upload and apply previously saved or exported PhotonVision settings to this device
<v-row class="mt-6 ml-4">
<v-row class="mt-6 ml-4 mr-8">
<cv-select
v-model="importType"
label="Type"
Expand All @@ -262,14 +261,15 @@ const handleSettingsImport = () => {
'Apriltag Layout'
]"
:select-cols="10"
style="width: 100%"
/>
</v-row>
<v-row class="mt-6 ml-4 mr-8">
<v-file-input
v-model="importFile"
:disabled="importType === -1"
:error-messages="importType === -1 ? 'Settings type not selected' : ''"
:accept="importType === ImportType.AllSettings ? '.zip' : '.json'"
@change="(file) => (importFile = file)"
/>
</v-row>
<v-row
Expand Down
29 changes: 26 additions & 3 deletions photon-client/src/stores/settings/CameraSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,35 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
/**
* Take a snapshot for the calibration processes
*
* @param takeSnapshot whether or not to take a snapshot. Defaults to true
* @param cameraIndex the index of the camera that is currently in the calibration process
*/
takeCalibrationSnapshot(takeSnapshot = true, cameraIndex: number = useStateStore().currentCameraIndex) {
takeCalibrationSnapshot(cameraIndex: number = useStateStore().currentCameraIndex) {
const payload = {
takeCalibrationSnapshot: takeSnapshot,
takeCalibrationSnapshot: true,
cameraIndex: cameraIndex
};
useStateStore().websocket?.send(payload, true);
},
/**
* Save a snapshot of the input frame of the camera.
*
* @param cameraIndex the index of the camera
*/
saveInputSnapshot(cameraIndex: number = useStateStore().currentCameraIndex) {
const payload = {
saveInputSnapshot: true,
cameraIndex: cameraIndex
};
useStateStore().websocket?.send(payload, true);
},
/**
* Save a snapshot of the output frame of the camera.
*
* @param cameraIndex the index of the camera
*/
saveOutputSnapshot(cameraIndex: number = useStateStore().currentCameraIndex) {
const payload = {
saveOutputSnapshot: true,
cameraIndex: cameraIndex
};
useStateStore().websocket?.send(payload, true);
Expand Down
Loading

0 comments on commit 77c0502

Please sign in to comment.