Skip to content

Commit c2c8b13

Browse files
committed
Merge branch 'main' into no-systemcore
2 parents 47149ce + dad7f0a commit c2c8b13

File tree

27 files changed

+436
-546
lines changed

27 files changed

+436
-546
lines changed

.github/pull_request_template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Merge checklist:
1212
- [ ] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes
1313
- [ ] The description documents the _what_ and _why_
14+
- [ ] This PR has been [linted](https://docs.photonvision.org/en/latest/docs/contributing/linting.html).
1415
- [ ] If this PR changes behavior or adds a feature, user documentation is updated
1516
- [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly
1617
- [ ] If this PR touches configuration, this is backwards compatible with settings back to v2025.3.2

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ spotless {
9292
format 'misc', {
9393
target fileTree('.') {
9494
include '**/*.md', '**/.gitignore'
95-
exclude '**/build/**', '**/build-*/**'
95+
exclude '**/build/**', '**/build-*/**', '**/node_modules/**'
9696
}
9797
trimTrailingWhitespace()
9898
indentWithSpaces(2)

docs/source/docs/contributing/building-photon.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ This section contains the build instructions from the source code available at [
1818

1919
[pnpm](https://pnpm.io/) is the package manager used to download dependencies for the UI. To install pnpm, follow [the instructions on the official pnpm website](https://pnpm.io/installation).
2020

21+
**Cross-Compilation Toolchains (Optional):**
22+
23+
If you plan to deploy PhotonVision to a coprocessor like a Raspberry Pi, you will need to install the appropriate cross-compilation toolchain for your platform. For `linuxarm64` devices, this can be accomplished by running `./gradlew installArm64Toolchain` in the root folder of the project.
24+
2125
## Compiling Instructions
2226

2327
### Getting the Source Code

docs/source/docs/contributing/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
```{toctree}
44
building-photon
55
building-docs
6+
linting
67
developer-docs/index
78
design-descriptions/index
89
```
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Linting the PhotonVision Codebase
2+
3+
## Versions
4+
5+
:::{note}
6+
If you work on other projects that use different versions of the same linters as PhotonVision, you may find it beneficial to use a [venv](https://docs.python.org/3/library/venv.html) instead of installing the linters globally. This will allow you to have different versions of the same linter installed for different projects.
7+
:::
8+
9+
The correct versions for each linter can be found under the linting workflow located [here](https://github.com/PhotonVision/photonvision/tree/main/.github/workflows). For *doc8*, the version can be found in `docs/requirements.txt`. If you've linted, and are still unable to pass CI, please check the versions of your linters.
10+
11+
## Frontend
12+
13+
### Linting the frontend
14+
15+
In order to lint the frontend, run `pnpm -C photon-client lint && pnpm -C photon-client format`. This should be done from the base level of the repo.
16+
17+
## Backend
18+
19+
### wpiformat installation
20+
21+
To lint the backend, PhotonVision uses *wpiformat* and *spotless*. Spotless is included with gradle, which means installation is not needed. To install wpiformat, run `pipx install wpiformat`. To install a specific version, run `pipx install wpiformat==<version>`.
22+
23+
### Linting the backend
24+
25+
To lint, run `./gradlew spotlessApply` and `wpiformat`.
26+
27+
## Documentation
28+
29+
### doc8 installation
30+
31+
To install *doc8*, the python tool we use to lint our documentation, run `pipx install doc8`. To install a specific version, run `pipx install doc8==<version>`.
32+
33+
### Linting the documentation
34+
35+
To lint the documentation, run `doc8 docs` from the root level of the docs.
36+
37+
## Alias
38+
39+
The following [alias](https://www.computerworld.com/article/1373210/how-to-use-aliases-in-linux-shell-commands.html) can be added to your shell config, which will allow you to lint the entirety of the PhotonVision project by running `pvLint`. The alias will work on Linux, macOS, Git Bash on Windows, and WSL.
40+
41+
```sh
42+
alias pvLint='wpiformat -v && ./gradlew spotlessApply && pnpm -C photon-client lint && pnpm -C photon-client format && doc8 docs'
43+
```

docs/source/docs/objectDetection/opi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ PhotonVision currently ONLY supports 640x640 Ultralytics YOLOv5, YOLOv8, and YOL
1414
Only quantized models are supported, so take care when exporting to select the option for quantization.
1515
:::
1616

17-
PhotonVision now ships with a {{ '[Python Notebook](https://github.com/PhotonVision/photonvision/blob/{}/scripts/rknn_conversion.ipynb)'.format(git_tag_ref) }} that you can use in [Google Colab](https://colab.research.google.com) or in a local environment. In Google Colab, you can simply paste the PhotonVision GitHub URL into the "GitHub" tab and select the `rknn_conversion.ipynb` notebook without needing to manually download anything.
17+
PhotonVision now ships with a {{ '[Python Notebook](https://github.com/PhotonVision/photonvision/blob/{}/scripts/rknn_conversion.ipynb)'.format(git_tag_ref) }} that you can use in [Google Colab](https://colab.research.google.com) or in a local **Linux** environment (since `rknn-toolkit2` only supports Linux). In Google Colab, you can simply paste the PhotonVision GitHub URL into the "GitHub" tab and select the `rknn_conversion.ipynb` notebook without needing to manually download anything.
1818

1919
Please ensure that the model you are attempting to convert is among the {ref}`supported models <docs/objectDetection/opi:Supported Models>` and using the PyTorch format.

docs/source/docs/objectDetection/rubik.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ PhotonVision currently ONLY supports 640x640 Ultralytics YOLOv8 and YOLOv11 mode
1414
Only quantized models are supported, so take care when exporting to select the option for quantization.
1515
:::
1616

17-
PhotonVision now ships with a {{ '[Python Notebook](https://github.com/PhotonVision/photonvision/blob/{}/scripts/rubik_conversion.ipynb)'.format(git_tag_ref) }} that you can use in [Google Colab](https://colab.research.google.com) or in a local environment. In Google Colab, you can simply paste the PhotonVision GitHub URL into the "GitHub" tab and select the `rubik_conversion.ipynb` notebook without needing to manually download anything.
17+
PhotonVision now ships with a {{ '[Python Notebook](https://github.com/PhotonVision/photonvision/blob/{}/scripts/rubik_conversion.ipynb)'.format(git_tag_ref) }} that you can use in [Google Colab](https://colab.research.google.com), [Kaggle](https://kaggle.com/code), or in a local environment. In Google Colab, you can simply paste the PhotonVision GitHub URL into the "GitHub" tab and select the `rubik_conversion.ipynb` notebook without needing to manually download anything.
1818

1919
Please ensure that the model you are attempting to convert is among the {ref}`supported models <docs/objectDetection/rubik:Supported Models>` and using the PyTorch format.
2020

photon-client/src/components/app/photon-error-snackbar.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,15 @@ import { useStateStore } from "@/stores/StateStore";
1313
<p style="padding: 0; margin: 0; text-align: center">
1414
{{ useStateStore().snackbarData.message }}
1515
</p>
16+
<v-progress-linear
17+
v-if="useStateStore().snackbarData.progressBar != -1"
18+
v-model="useStateStore().snackbarData.progressBar"
19+
height="15"
20+
:color="useStateStore().snackbarData.progressBarColor"
21+
>
22+
<template #default="{ value }">
23+
<strong> {{ Math.ceil(value) }}% </strong>
24+
</template>
25+
</v-progress-linear>
1626
</v-snackbar>
1727
</template>

photon-client/src/components/cameras/CameraCalibrationInfoCard.vue

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { CameraCalibrationResult, VideoFormat } from "@/types/SettingTypes"
33
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
44
import { useStateStore } from "@/stores/StateStore";
55
import { computed, inject, ref } from "vue";
6-
import { getResolutionString, parseJsonFile } from "@/lib/PhotonUtils";
6+
import { axiosPost, getResolutionString, parseJsonFile } from "@/lib/PhotonUtils";
77
import { useTheme } from "vuetify";
88
99
const theme = useTheme();
@@ -12,6 +12,18 @@ const props = defineProps<{
1212
videoFormat: VideoFormat;
1313
}>();
1414
15+
const confirmRemoveDialog = ref({ show: false, vf: {} as VideoFormat });
16+
17+
const removeCalibration = (vf: VideoFormat) => {
18+
axiosPost("/calibration/remove", "delete a camera calibration", {
19+
cameraUniqueName: useCameraSettingsStore().currentCameraSettings.uniqueName,
20+
width: vf.resolution.width,
21+
height: vf.resolution.height
22+
});
23+
24+
confirmRemoveDialog.value.show = false;
25+
};
26+
1527
const exportCalibration = ref();
1628
const openExportCalibrationPrompt = () => {
1729
exportCalibration.value.click();
@@ -93,18 +105,30 @@ const calibrationImageURL = (index: number) =>
93105
</script>
94106
<template>
95107
<v-card color="surface" dark>
96-
<div class="d-flex flex-wrap pt-2 pl-2 pr-2">
108+
<div class="d-flex flex-wrap pt-2 pl-2 pr-2 align-center">
97109
<v-col cols="12" md="6">
98110
<v-card-title class="pa-0"> Calibration Details </v-card-title>
99111
</v-col>
100-
<v-col cols="6" md="3" class="d-flex align-center pt-0 pt-md-3 pl-6 pl-md-3">
112+
<v-col cols="12" md="6" class="d-flex align-center pt-0 pt-md-3">
113+
<v-btn
114+
color="error"
115+
:disabled="!currentCalibrationCoeffs"
116+
class="mr-2"
117+
style="flex: 1"
118+
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
119+
@click="() => (confirmRemoveDialog = { show: true, vf: props.videoFormat })"
120+
>
121+
<v-icon start size="large">mdi-delete</v-icon>
122+
<span>Delete</span>
123+
</v-btn>
101124
<v-btn
102125
color="buttonPassive"
103-
style="width: 100%"
126+
class="mr-2"
127+
style="flex: 1"
104128
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
105129
@click="openUploadPhotonCalibJsonPrompt"
106130
>
107-
<v-icon start size="large"> mdi-import</v-icon>
131+
<v-icon start size="large">mdi-import</v-icon>
108132
<span>Import</span>
109133
</v-btn>
110134
<input
@@ -114,12 +138,10 @@ const calibrationImageURL = (index: number) =>
114138
style="display: none"
115139
@change="importCalibration"
116140
/>
117-
</v-col>
118-
<v-col cols="6" md="3" class="d-flex align-center pt-0 pt-md-3 pr-6 pr-md-3">
119141
<v-btn
120142
color="buttonPassive"
121143
:disabled="!currentCalibrationCoeffs"
122-
style="width: 100%"
144+
style="flex: 1"
123145
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
124146
@click="openExportCalibrationPrompt"
125147
>
@@ -289,6 +311,33 @@ const calibrationImageURL = (index: number) =>
289311
</v-data-table>
290312
</v-card-text>
291313
</v-card>
314+
315+
<v-dialog v-model="confirmRemoveDialog.show" width="600">
316+
<v-card color="surface" dark>
317+
<v-card-title>Delete Calibration</v-card-title>
318+
<v-card-text class="pt-0">
319+
Are you sure you want to delete the calibration for {{ confirmRemoveDialog.vf.resolution.width }}x{{
320+
confirmRemoveDialog.vf.resolution.height
321+
}}? This cannot be undone.
322+
<v-card-actions class="pt-5 pb-0 pr-0" style="justify-content: flex-end">
323+
<v-btn
324+
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
325+
color="primary"
326+
@click="() => (confirmRemoveDialog.show = false)"
327+
>
328+
Cancel
329+
</v-btn>
330+
<v-btn
331+
:variant="theme.global.name.value === 'LightTheme' ? 'elevated' : 'outlined'"
332+
color="error"
333+
@click="removeCalibration(confirmRemoveDialog.vf)"
334+
>
335+
Delete
336+
</v-btn>
337+
</v-card-actions>
338+
</v-card-text>
339+
</v-card>
340+
</v-dialog>
292341
</template>
293342

294343
<style scoped>

photon-client/src/components/cameras/CameraSettingsCard.vue

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
66
import { useStateStore } from "@/stores/StateStore";
77
import { computed, ref, watchEffect } from "vue";
88
import { type CameraSettingsChangeRequest, ValidQuirks } from "@/types/SettingTypes";
9-
import axios from "axios";
109
import { useTheme } from "vuetify";
10+
import { axiosPost } from "@/lib/PhotonUtils";
1111
1212
const theme = useTheme();
1313
@@ -120,36 +120,10 @@ const deleteThisCamera = () => {
120120
121121
const payload = { cameraUniqueName: useStateStore().currentCameraUniqueName };
122122
123-
axios
124-
.post("/utils/nukeOneCamera", payload)
125-
.then(() => {
126-
useStateStore().showSnackbarMessage({
127-
message: "Successfully dispatched the delete command. Waiting for backend to start back up",
128-
color: "success"
129-
});
130-
})
131-
.catch((error) => {
132-
if (error.response) {
133-
useStateStore().showSnackbarMessage({
134-
message: "The backend is unable to fulfil the request to delete this camera.",
135-
color: "error"
136-
});
137-
} else if (error.request) {
138-
useStateStore().showSnackbarMessage({
139-
message: "Error while trying to process the request! The backend didn't respond.",
140-
color: "error"
141-
});
142-
} else {
143-
useStateStore().showSnackbarMessage({
144-
message: "An error occurred while trying to process the request.",
145-
color: "error"
146-
});
147-
}
148-
})
149-
.finally(() => {
150-
deletingCamera.value = false;
151-
showDeleteCamera.value = false;
152-
});
123+
axiosPost("/utils/nukeOneCamera", "delete this camera", payload).finally(() => {
124+
deletingCamera.value = false;
125+
showDeleteCamera.value = false;
126+
});
153127
};
154128
const wrappedCameras = computed<SelectItem[]>(() =>
155129
Object.keys(useCameraSettingsStore().cameras).map((cameraUniqueName) => ({

0 commit comments

Comments
 (0)