mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-04 03:11:40 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72717cecf0 | ||
|
|
971ff3ac40 | ||
|
|
b80e436f02 | ||
|
|
be1a053cbe | ||
|
|
f4555dc545 | ||
|
|
54fdd1db51 | ||
|
|
1805785cc6 | ||
|
|
e62f6419b5 | ||
|
|
fa7824c616 | ||
|
|
9090aa6bcc | ||
|
|
5655ca6890 | ||
|
|
50fdfd8bce | ||
|
|
3120a6439b | ||
|
|
ab3e8c8db7 | ||
|
|
5144819ce2 | ||
|
|
d779fe23f0 | ||
|
|
b2a3f34433 | ||
|
|
b09a6d6a2d | ||
|
|
9893cf1f7e | ||
|
|
fc91daf397 | ||
|
|
a3e205cb6f | ||
|
|
553bed32b5 | ||
|
|
6c91feaf3f | ||
|
|
4ddb9aa08f | ||
|
|
4aadebdbb2 |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -151,6 +151,8 @@ jobs:
|
|||||||
|
|
||||||
# Building photonlib
|
# Building photonlib
|
||||||
photonlib-build-host:
|
photonlib-build-host:
|
||||||
|
env:
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: 10.14
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -143,3 +143,4 @@ build/*
|
|||||||
build
|
build
|
||||||
photon-lib/src/main/java/org/photonvision/PhotonVersion.java
|
photon-lib/src/main/java/org/photonvision/PhotonVersion.java
|
||||||
/photonlib-java-examples/bin/
|
/photonlib-java-examples/bin/
|
||||||
|
photon-lib/src/generate/native/include/PhotonVersion.h
|
||||||
|
|||||||
@@ -25,7 +25,3 @@ includeOtherLibs {
|
|||||||
^units/
|
^units/
|
||||||
^wpi/
|
^wpi/
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseUpdateExclude {
|
|
||||||
\.java$
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
@@ -47,7 +47,6 @@ spotless {
|
|||||||
}
|
}
|
||||||
java {
|
java {
|
||||||
target "**/*.java"
|
target "**/*.java"
|
||||||
licenseHeaderFile "$rootDir/LicenseHeader.txt"
|
|
||||||
targetExclude("photon-core/src/main/java/org/photonvision/PhotonVersion.java")
|
targetExclude("photon-core/src/main/java/org/photonvision/PhotonVersion.java")
|
||||||
targetExclude("photon-lib/src/main/java/org/photonvision/PhotonVersion.java")
|
targetExclude("photon-lib/src/main/java/org/photonvision/PhotonVersion.java")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,31 +87,56 @@
|
|||||||
</v-icon>
|
</v-icon>
|
||||||
</v-list-item-icon>
|
</v-list-item-icon>
|
||||||
<v-list-item-content>
|
<v-list-item-content>
|
||||||
<v-list-item-title>Advanced Mode</v-list-item-title>
|
<v-list-item-title>Compact Mode</v-list-item-title>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
<div style="position: absolute; bottom: 0; left: 0;">
|
<div style="position: absolute; bottom: 0; left: 0;">
|
||||||
<v-list-item>
|
<v-list-item>
|
||||||
<v-list-item-icon>
|
<v-list-item-icon>
|
||||||
<v-icon v-if="$store.state.settings.networkSettings.runNTServer">mdi-server</v-icon>
|
<v-icon v-if="$store.state.settings.networkSettings.runNTServer">
|
||||||
<img v-else-if="$store.state.ntConnectionInfo.connected" src="@/assets/robot.svg" alt="">
|
mdi-server
|
||||||
<img v-else class="pulse" style="border-radius: 100%" src="@/assets/robot-off.svg" alt="">
|
</v-icon>
|
||||||
|
<img
|
||||||
|
v-else-if="$store.state.ntConnectionInfo.connected"
|
||||||
|
src="@/assets/robot.svg"
|
||||||
|
alt=""
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
class="pulse"
|
||||||
|
style="border-radius: 100%"
|
||||||
|
src="@/assets/robot-off.svg"
|
||||||
|
alt=""
|
||||||
|
>
|
||||||
</v-list-item-icon>
|
</v-list-item-icon>
|
||||||
<v-list-item-content>
|
<v-list-item-content>
|
||||||
<v-list-item-title class="text-wrap" v-if="$store.state.settings.networkSettings.runNTServer">
|
<v-list-item-title
|
||||||
NetworkTables server running for {{$store.state.ntConnectionInfo.clients ? $store.state.ntConnectionInfo.clients : 'zero'}} clients!
|
v-if="$store.state.settings.networkSettings.runNTServer"
|
||||||
|
class="text-wrap"
|
||||||
|
>
|
||||||
|
NetworkTables server running for {{ $store.state.ntConnectionInfo.clients ? $store.state.ntConnectionInfo.clients : 'zero' }} clients!
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
<v-list-item-title class="text-wrap" v-else-if="$store.state.ntConnectionInfo.connected && $store.state.backendConnected">
|
<v-list-item-title
|
||||||
Robot connected! {{$store.state.ntConnectionInfo.address}}
|
v-else-if="$store.state.ntConnectionInfo.connected && $store.state.backendConnected"
|
||||||
|
class="text-wrap"
|
||||||
|
>
|
||||||
|
Robot connected! {{ $store.state.ntConnectionInfo.address }}
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
<v-list-item-title class="text-wrap" v-else>
|
<v-list-item-title
|
||||||
|
v-else
|
||||||
|
class="text-wrap"
|
||||||
|
>
|
||||||
Not connected to robot!
|
Not connected to robot!
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
<a
|
<router-link
|
||||||
href="/#/settings"
|
v-if="!$store.state.settings.networkSettings.runNTServer"
|
||||||
style="color:#FFD843"
|
to="settings"
|
||||||
>{{"Team: " + $store.state.settings.networkSettings.teamNumber}}</a>
|
class="accent--text"
|
||||||
|
@click="switchToSettingsTab"
|
||||||
|
>
|
||||||
|
Team number is {{ $store.state.settings.networkSettings.teamNumber }}
|
||||||
|
</router-link>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
@@ -121,9 +146,9 @@
|
|||||||
mdi-wifi
|
mdi-wifi
|
||||||
</v-icon>
|
</v-icon>
|
||||||
<v-icon
|
<v-icon
|
||||||
v-else
|
v-else
|
||||||
class="pulse"
|
class="pulse"
|
||||||
style="border-radius: 100%;"
|
style="border-radius: 100%;"
|
||||||
>
|
>
|
||||||
mdi-wifi-off
|
mdi-wifi-off
|
||||||
</v-icon>
|
</v-icon>
|
||||||
@@ -135,7 +160,6 @@
|
|||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
<v-main>
|
<v-main>
|
||||||
@@ -159,23 +183,27 @@
|
|||||||
<logs />
|
<logs />
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
<v-dialog
|
<v-dialog
|
||||||
v-model="needsTeamNumberSet"
|
v-model="needsTeamNumberSet"
|
||||||
width="500"
|
width="500"
|
||||||
dark
|
dark
|
||||||
persistent
|
persistent
|
||||||
>
|
>
|
||||||
<v-card
|
<v-card
|
||||||
dark
|
dark
|
||||||
color="primary"
|
color="primary"
|
||||||
flat
|
flat
|
||||||
>
|
>
|
||||||
<v-card-title>No team number set!</v-card-title>
|
<v-card-title>No team number set!</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
PhotonVision cannot connect to your robot! Please
|
PhotonVision cannot connect to your robot! Please
|
||||||
<a
|
<router-link
|
||||||
href="/#/settings"
|
to="settings"
|
||||||
style="color:#FFD843"
|
class="accent--text"
|
||||||
>head to the settings page</a> and set your team number.
|
@click="switchToSettingsTab"
|
||||||
|
>
|
||||||
|
vist the settings tab
|
||||||
|
</router-link>
|
||||||
|
and set your team number.
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@@ -219,12 +247,6 @@ export default {
|
|||||||
localStorage.setItem("compactMode", value);
|
localStorage.setItem("compactMode", value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// ...mapState({
|
|
||||||
// ntServerMode: state => state.settings.networkSettings.runNTServer,
|
|
||||||
// ntClients: state => state.ntConnectionInfo.clients,
|
|
||||||
// ntConnected: state => state.ntConnectionInfo.connected,
|
|
||||||
// backendConnected: state => state.backendConnected
|
|
||||||
// })
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
document.addEventListener("keydown", e => {
|
document.addEventListener("keydown", e => {
|
||||||
@@ -319,8 +341,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.previouslySelectedIndices = null;
|
this.previouslySelectedIndices = null;
|
||||||
}
|
},
|
||||||
,
|
|
||||||
switchToSettingsTab() {
|
switchToSettingsTab() {
|
||||||
this.axios.post('http://' + this.$address + '/api/sendMetrics', {})
|
this.axios.post('http://' + this.$address + '/api/sendMetrics', {})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
export default {
|
export default {
|
||||||
name: "CvImage",
|
name: "CvImage",
|
||||||
// eslint-disable-next-line vue/require-prop-types
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
props: ['address', 'scale', 'maxHeight', 'maxHeightMd', 'maxHeightXl', 'colorPicking', 'id', 'disconnected'],
|
props: ['address', 'scale', 'maxHeight', 'maxHeightMd', 'maxHeightLg', 'maxHeightXl', 'colorPicking', 'id', 'disconnected'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
seed: 1.0,
|
seed: 1.0,
|
||||||
@@ -37,7 +37,9 @@
|
|||||||
|
|
||||||
if (this.$vuetify.breakpoint.xl) {
|
if (this.$vuetify.breakpoint.xl) {
|
||||||
ret["max-height"] = this.maxHeightXl;
|
ret["max-height"] = this.maxHeightXl;
|
||||||
} else if (this.$vuetify.breakpoint.mdAndUp) {
|
} else if (this.$vuetify.breakpoint.lg) {
|
||||||
|
ret["max-height"] = this.maxHeightLg;
|
||||||
|
} else if (this.$vuetify.breakpoint.md) {
|
||||||
ret["max-height"] = this.maxHeightMd;
|
ret["max-height"] = this.maxHeightMd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-radio-group
|
<v-row
|
||||||
v-model="localValue"
|
dense
|
||||||
row
|
align="center"
|
||||||
dark
|
|
||||||
:mandatory="true"
|
|
||||||
>
|
>
|
||||||
<v-radio
|
<v-col :cols="12 - (inputCols || 8)">
|
||||||
v-for="(name,index) in list"
|
<tooltipped-label
|
||||||
:key="index"
|
:tooltip="tooltip"
|
||||||
color="#ffd843"
|
:text="name"
|
||||||
:label="name"
|
/>
|
||||||
:value="index"
|
</v-col>
|
||||||
:disabled="disabled"
|
<v-col :cols="inputCols || 8">
|
||||||
/>
|
<v-radio-group
|
||||||
</v-radio-group>
|
v-model="localValue"
|
||||||
|
row
|
||||||
|
dark
|
||||||
|
:mandatory="true"
|
||||||
|
>
|
||||||
|
<v-radio
|
||||||
|
v-for="(radioName,index) in list"
|
||||||
|
:key="index"
|
||||||
|
color="#ffd843"
|
||||||
|
:label="radioName"
|
||||||
|
:value="index"
|
||||||
|
:disabled="disabled"
|
||||||
|
/>
|
||||||
|
</v-radio-group>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import TooltippedLabel from "./cv-tooltipped-label";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Radio',
|
name: 'Radio',
|
||||||
|
components: {
|
||||||
|
TooltippedLabel
|
||||||
|
},
|
||||||
// eslint-disable-next-line vue/require-prop-types
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
props: ['value', 'list', 'disabled'],
|
props: ['name', 'value', 'list', 'disabled', 'inputCols', 'tooltip'],
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
hide-details
|
hide-details
|
||||||
class="align-center"
|
class="align-center"
|
||||||
dark
|
dark
|
||||||
color="accent"
|
:color="inverted ? 'rgba(255, 255, 255, 0.2)' : 'accent'"
|
||||||
|
:track-color="inverted ? 'accent' : undefined"
|
||||||
|
thumb-color="accent"
|
||||||
:step="step"
|
:step="step"
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
@mousedown="$emit('rollback', localValue)"
|
@mousedown="$emit('rollback', localValue)"
|
||||||
@@ -76,7 +78,7 @@ export default {
|
|||||||
TooltippedLabel,
|
TooltippedLabel,
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line vue/require-prop-types
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
props: ["name", "min", "max", "value", "step", "tooltip", "disabled"],
|
props: ["name", "min", "max", "value", "step", "tooltip", "disabled", "inverted"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
prependFocused: false,
|
prependFocused: false,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<v-tooltip
|
<v-tooltip
|
||||||
:disabled="tooltip === undefined"
|
:disabled="tooltip === undefined"
|
||||||
right
|
right
|
||||||
open-delay="600"
|
open-delay="300"
|
||||||
>
|
>
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-row align="center">
|
<v-row
|
||||||
|
align="center"
|
||||||
|
class="pl-6"
|
||||||
|
>
|
||||||
<v-col
|
<v-col
|
||||||
cols="10"
|
cols="10"
|
||||||
md="5"
|
md="5"
|
||||||
lg="10"
|
lg="10"
|
||||||
class="pt-0 pb-0 pl-6"
|
no-gutters
|
||||||
|
class="pa-0"
|
||||||
>
|
>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-if="isCameraNameEdit === false"
|
v-if="isCameraNameEdit === false"
|
||||||
@@ -59,7 +63,8 @@
|
|||||||
cols="10"
|
cols="10"
|
||||||
md="5"
|
md="5"
|
||||||
lg="10"
|
lg="10"
|
||||||
class="pt-0 pb-0 pl-6"
|
no-gutters
|
||||||
|
class="pa-0"
|
||||||
>
|
>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="currentPipelineIndex"
|
v-model="currentPipelineIndex"
|
||||||
@@ -139,14 +144,16 @@
|
|||||||
<v-col
|
<v-col
|
||||||
v-if="currentPipelineType >= 0"
|
v-if="currentPipelineType >= 0"
|
||||||
cols="10"
|
cols="10"
|
||||||
md="5"
|
md="11"
|
||||||
lg="10"
|
lg="10"
|
||||||
class="pt-0 pb-0 pl-6"
|
no-gutters
|
||||||
|
class="pa-0"
|
||||||
>
|
>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="currentPipelineType"
|
v-model="currentPipelineType"
|
||||||
name="Type"
|
name="Type"
|
||||||
:list="['Reflective', 'Shape']"
|
tooltip="Changes the pipeline type, which changes the type of processing that will happen on input frames"
|
||||||
|
:list="['Reflective Tape', 'Colored Shape']"
|
||||||
@input="e => showTypeDialog(e)"
|
@input="e => showTypeDialog(e)"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -176,12 +183,6 @@
|
|||||||
name="Name"
|
name="Name"
|
||||||
:error-message="checkPipelineName"
|
:error-message="checkPipelineName"
|
||||||
/>
|
/>
|
||||||
<!-- <CVselect-->
|
|
||||||
<!-- v-model="currentPipelineType"-->
|
|
||||||
<!-- name="Pipeline Type"-->
|
|
||||||
<!-- :list="['Reflective', 'Shape']"-->
|
|
||||||
<!-- :disabled="true"-->
|
|
||||||
<!-- />-->
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@@ -276,12 +277,12 @@ export default {
|
|||||||
for (let cam in this.cameraList) {
|
for (let cam in this.cameraList) {
|
||||||
if (this.cameraList.hasOwnProperty(cam)) {
|
if (this.cameraList.hasOwnProperty(cam)) {
|
||||||
if (this.newCameraName === this.cameraList[cam]) {
|
if (this.newCameraName === this.cameraList[cam]) {
|
||||||
return "A camera by that name already Exists"
|
return "A camera by that name already exists"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "A camera name can only contain letters, numbers and spaces"
|
return "A camera name can only contain letters, numbers, and spaces"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -384,7 +385,7 @@ export default {
|
|||||||
if (this.isPipelineNameEdit) {
|
if (this.isPipelineNameEdit) {
|
||||||
this.handleInputWithIndex("changePipelineName", this.newPipelineName);
|
this.handleInputWithIndex("changePipelineName", this.newPipelineName);
|
||||||
} else {
|
} else {
|
||||||
this.handleInputWithIndex("addNewPipeline", [this.newPipelineName, this.newPipelineType]); // 0 for reflective, 1 for colored shpae
|
this.handleInputWithIndex("addNewPipeline", [this.newPipelineName, this.currentPipelineType]); // 0 for reflective, 1 for colored shpae
|
||||||
}
|
}
|
||||||
this.discardPipelineNameChange();
|
this.discardPipelineNameChange();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ function initColorPicker() {
|
|||||||
canvas = document.createElement('canvas');
|
canvas = document.createElement('canvas');
|
||||||
|
|
||||||
image = document.querySelector('#normal-stream');
|
image = document.querySelector('#normal-stream');
|
||||||
canvas.width = image.width;
|
if (image !== null) {
|
||||||
canvas.height = image.height;
|
canvas.width = image.width;
|
||||||
|
canvas.height = image.height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Called on click of the image,
|
//Called on click of the image,
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ export default new Vuex.Store({
|
|||||||
connected: false,
|
connected: false,
|
||||||
address: "",
|
address: "",
|
||||||
clients: 0,
|
clients: 0,
|
||||||
|
},
|
||||||
|
networkInfo: {
|
||||||
possibleRios: ["Loading..."],
|
possibleRios: ["Loading..."],
|
||||||
deviceips: ["Loading..."],
|
deviceips: ["Loading..."],
|
||||||
},
|
},
|
||||||
@@ -55,7 +57,8 @@ export default new Vuex.Store({
|
|||||||
// Settings that apply to all pipeline types
|
// Settings that apply to all pipeline types
|
||||||
cameraExposure: 1,
|
cameraExposure: 1,
|
||||||
cameraBrightness: 2,
|
cameraBrightness: 2,
|
||||||
cameraGain: 3,
|
cameraRedGain: 3,
|
||||||
|
cameraBlueGain: 4,
|
||||||
inputImageRotationMode: 0,
|
inputImageRotationMode: 0,
|
||||||
cameraVideoModeIndex: 0,
|
cameraVideoModeIndex: 0,
|
||||||
streamingFrameDivisor: 0,
|
streamingFrameDivisor: 0,
|
||||||
@@ -64,10 +67,13 @@ export default new Vuex.Store({
|
|||||||
hsvHue: [0, 15],
|
hsvHue: [0, 15],
|
||||||
hsvSaturation: [0, 15],
|
hsvSaturation: [0, 15],
|
||||||
hsvValue: [0, 25],
|
hsvValue: [0, 25],
|
||||||
|
hueInverted: false,
|
||||||
contourArea: [0, 12],
|
contourArea: [0, 12],
|
||||||
contourRatio: [0, 12],
|
contourRatio: [0, 12],
|
||||||
contourFullness: [0, 12],
|
contourFullness: [0, 12],
|
||||||
contourSpecklePercentage: 5,
|
contourSpecklePercentage: 5,
|
||||||
|
contourFilterRangeX: 5,
|
||||||
|
contourFilterRangeY: 5,
|
||||||
contourGroupingMode: 0,
|
contourGroupingMode: 0,
|
||||||
contourIntersection: 0,
|
contourIntersection: 0,
|
||||||
contourSortMode: 0,
|
contourSortMode: 0,
|
||||||
@@ -151,6 +157,7 @@ export default new Vuex.Store({
|
|||||||
calibrationData: set('calibrationData'),
|
calibrationData: set('calibrationData'),
|
||||||
metrics: set('metrics'),
|
metrics: set('metrics'),
|
||||||
ntConnectionInfo: set('ntConnectionInfo'),
|
ntConnectionInfo: set('ntConnectionInfo'),
|
||||||
|
networkInfo: set('networkInfo'),
|
||||||
backendConnected: set('backendConnected'),
|
backendConnected: set('backendConnected'),
|
||||||
logString: (state, newStr) => {
|
logString: (state, newStr) => {
|
||||||
const str = state.logMessages;
|
const str = state.logMessages;
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
v-model="currentCameraIndex"
|
v-model="currentCameraIndex"
|
||||||
name="Camera"
|
name="Camera"
|
||||||
:list="$store.getters.cameraList"
|
:list="$store.getters.cameraList"
|
||||||
@input="handleInput('currentCamera',currentCameraIndex)"
|
|
||||||
:select-cols="$vuetify.breakpoint.mdAndUp ? 10 : 7"
|
:select-cols="$vuetify.breakpoint.mdAndUp ? 10 : 7"
|
||||||
|
@input="handleInput('currentCamera',currentCameraIndex)"
|
||||||
/>
|
/>
|
||||||
<CVnumberinput
|
<CVnumberinput
|
||||||
v-model="cameraSettings.fov"
|
v-model="cameraSettings.fov"
|
||||||
@@ -196,13 +196,24 @@
|
|||||||
@input="e => handlePipelineUpdate('cameraBrightness', e)"
|
@input="e => handlePipelineUpdate('cameraBrightness', e)"
|
||||||
/>
|
/>
|
||||||
<CVslider
|
<CVslider
|
||||||
v-if="$store.getters.currentPipelineSettings.cameraGain !== -1"
|
v-if="$store.getters.currentPipelineSettings.cameraRedGain !== -1"
|
||||||
v-model="$store.getters.currentPipelineSettings.cameraGain"
|
v-model="$store.getters.currentPipelineSettings.cameraRedGain"
|
||||||
name="Gain"
|
name="Red AWB Gain"
|
||||||
:min="0"
|
min="0"
|
||||||
:max="100"
|
max="100"
|
||||||
slider-cols="8"
|
tooltip="Controls red automatic white balance gain, which affects how the camera captures colors in different conditions"
|
||||||
@input="e => handlePipelineUpdate('cameraGain', e)"
|
:slider-cols="8"
|
||||||
|
@input="e => handlePipelineData('cameraRedGain', e)"
|
||||||
|
/>
|
||||||
|
<CVslider
|
||||||
|
v-if="$store.getters.currentPipelineSettings.cameraBlueGain !== -1"
|
||||||
|
v-model="$store.getters.currentPipelineSettings.cameraBlueGain"
|
||||||
|
name="Blue AWB Gain"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
|
||||||
|
:slider-cols="8"
|
||||||
|
@input="e => handlePipelineData('cameraBlueGain', e)"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
:class="fpsTooLow ? 'ml-2 mt-1' : 'mt-2'"
|
:class="fpsTooLow ? 'ml-2 mt-1' : 'mt-2'"
|
||||||
x-small
|
x-small
|
||||||
label
|
label
|
||||||
:color="fpsTooLow ? 'red' : 'transparent'"
|
:color="fpsTooLow ? 'error' : 'transparent'"
|
||||||
:text-color="fpsTooLow ? 'white' : 'grey'"
|
:text-color="fpsTooLow ? 'white' : 'grey'"
|
||||||
>
|
>
|
||||||
<span class="pr-1">{{ Math.round($store.state.pipelineResults.fps) }} FPS –</span>
|
<span class="pr-1">{{ Math.round($store.state.pipelineResults.fps) }} FPS –</span>
|
||||||
@@ -38,13 +38,6 @@
|
|||||||
<span v-else-if="!$store.getters.currentPipelineSettings.inputShouldShow">HSV thresholds are too broad; narrow them for better performance</span>
|
<span v-else-if="!$store.getters.currentPipelineSettings.inputShouldShow">HSV thresholds are too broad; narrow them for better performance</span>
|
||||||
<span v-else>stop viewing the color stream for better performance</span>
|
<span v-else>stop viewing the color stream for better performance</span>
|
||||||
</v-chip>
|
</v-chip>
|
||||||
<v-chip small label color="red" text-color="white" v-if="!$store.state.ntConnectionInfo.connected || $store.state.settings.networkSettings.runNTServer">
|
|
||||||
<span>
|
|
||||||
{{ $store.state.settings.networkSettings.runNTServer ?
|
|
||||||
"NetworkTables Server Enabled! Photonlib may not work" :
|
|
||||||
"NetworkTables not connected!" }}
|
|
||||||
</span>
|
|
||||||
</v-chip>
|
|
||||||
<v-switch
|
<v-switch
|
||||||
v-model="driverMode"
|
v-model="driverMode"
|
||||||
label="Driver Mode"
|
label="Driver Mode"
|
||||||
@@ -71,7 +64,8 @@
|
|||||||
:disconnected="!$store.state.backendConnected"
|
:disconnected="!$store.state.backendConnected"
|
||||||
scale="100"
|
scale="100"
|
||||||
:max-height="$store.getters.isDriverMode ? '40vh' : '300px'"
|
:max-height="$store.getters.isDriverMode ? '40vh' : '300px'"
|
||||||
:max-height-md="$store.getters.isDriverMode ? '50vh' : '320px'"
|
:max-height-md="$store.getters.isDriverMode ? '50vh' : '380px'"
|
||||||
|
:max-height-lg="$store.getters.isDriverMode ? '55vh' : '390px'"
|
||||||
:max-height-xl="$store.getters.isDriverMode ? '60vh' : '450px'"
|
:max-height-xl="$store.getters.isDriverMode ? '60vh' : '450px'"
|
||||||
:alt="'Stream' + idx"
|
:alt="'Stream' + idx"
|
||||||
:color-picking="$store.state.colorPicking && idx === 0"
|
:color-picking="$store.state.colorPicking && idx === 0"
|
||||||
@@ -90,23 +84,18 @@
|
|||||||
>
|
>
|
||||||
<v-card
|
<v-card
|
||||||
color="primary"
|
color="primary"
|
||||||
class="mt-3"
|
|
||||||
>
|
>
|
||||||
<!-- <v-btn @click="onCamNameChange">-->
|
|
||||||
<!-- Reload-->
|
|
||||||
<!-- </v-btn>-->
|
|
||||||
<camera-and-pipeline-select @camera-name-changed="reloadStreams" />
|
<camera-and-pipeline-select @camera-name-changed="reloadStreams" />
|
||||||
</v-card>
|
</v-card>
|
||||||
<v-card
|
<v-card
|
||||||
:disabled="$store.getters.isDriverMode || $store.state.colorPicking"
|
:disabled="$store.getters.isDriverMode || $store.state.colorPicking"
|
||||||
class="mt-6 mb-3"
|
class="mt-3"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
<v-row
|
<v-row
|
||||||
align="center"
|
align="center"
|
||||||
class="pl-3 pr-3"
|
class="pl-3 pr-3"
|
||||||
>
|
>
|
||||||
<!-- -->
|
|
||||||
<v-col lg="12">
|
<v-col lg="12">
|
||||||
<p style="color: white;">
|
<p style="color: white;">
|
||||||
Processing mode:
|
Processing mode:
|
||||||
@@ -206,21 +195,24 @@
|
|||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
<!-- snack bar and modal -->
|
|
||||||
<v-snackbar
|
<v-snackbar
|
||||||
v-model="snackbar"
|
v-model="showNTWarning"
|
||||||
:timeout="3000"
|
|
||||||
top
|
|
||||||
color="error"
|
color="error"
|
||||||
|
timeout="-1"
|
||||||
|
top
|
||||||
>
|
>
|
||||||
<span style="color:#000">Can not remove the only pipeline!</span>
|
{{ $store.state.settings.networkSettings.runNTServer ?
|
||||||
<v-btn
|
"NetworkTables server enabled! PhotonLib may not work." :
|
||||||
color="black"
|
"NetworkTables not connected! Are you on a network with a robot?" }}
|
||||||
text
|
<template v-slot:action>
|
||||||
@click="snackbar = false"
|
<v-btn
|
||||||
>
|
text
|
||||||
Close
|
@click="hideNTWarning = true"
|
||||||
</v-btn>
|
>
|
||||||
|
Hide
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
</v-snackbar>
|
</v-snackbar>
|
||||||
|
|
||||||
<v-dialog
|
<v-dialog
|
||||||
@@ -286,10 +278,10 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedTabsData: [0, 0, 0, 0],
|
selectedTabsData: [0, 0, 0, 0],
|
||||||
snackbar: false,
|
|
||||||
counterData: 0,
|
counterData: 0,
|
||||||
dialog: false,
|
dialog: false,
|
||||||
processingModeOverride: false
|
processingModeOverride: false,
|
||||||
|
hideNTWarning: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -434,7 +426,12 @@ export default {
|
|||||||
// return this.$store.state.ntConnectionInfo.connected && this.$store.state.backendConnected;
|
// return this.$store.state.ntConnectionInfo.connected && this.$store.state.backendConnected;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
showNTWarning: {
|
||||||
|
get() {
|
||||||
|
return (!this.$store.state.ntConnectionInfo.connected || this.$store.state.settings.networkSettings.runNTServer) && this.$store.state.settings.networkSettings.teamNumber > 0 && this.$store.state.backendConnected && !this.hideNTWarning;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$store.state.connectedCallbacks.push(this.reloadStreams)
|
this.$store.state.connectedCallbacks.push(this.reloadStreams)
|
||||||
|
|||||||
@@ -1,140 +1,169 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="contourArea"
|
v-model="contourArea"
|
||||||
name="Area"
|
name="Area"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="0.1"
|
step="0.01"
|
||||||
@input="handlePipelineData('contourArea')"
|
@input="handlePipelineData('contourArea')"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="contourRatio"
|
v-if="currentPipelineType() !== 3"
|
||||||
v-if="currentPipelineType() !== 3"
|
v-model="contourRatio"
|
||||||
name="Ratio (W/H)"
|
name="Ratio (W/H)"
|
||||||
tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
|
tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
@input="handlePipelineData('contourRatio')"
|
@input="handlePipelineData('contourRatio')"
|
||||||
|
/>
|
||||||
|
<CVselect
|
||||||
|
v-model="contourTargetOrientation"
|
||||||
|
name="Target Orientation"
|
||||||
|
tooltip="Used to determine how to calculate target landmarks, as well as aspect ratio"
|
||||||
|
:list="['Portrait', 'Landscape']"
|
||||||
|
@input="handlePipelineData('contourTargetOrientation')"
|
||||||
|
@rollback="e=> rollback('contourTargetOrientation', e)"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="contourFullness"
|
v-if="currentPipelineType() !== 3"
|
||||||
v-if="currentPipelineType() !== 3"
|
v-model="contourFullness"
|
||||||
name="Fullness"
|
name="Fullness"
|
||||||
tooltip="Min and max ratio between a contour's area and its bounding rectangle"
|
tooltip="Min and max ratio between a contour's area and its bounding rectangle"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
@input="handlePipelineData('contourFullness')"
|
@input="handlePipelineData('contourFullness')"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="contourPerimeter"
|
v-if="currentPipelineType() === 3"
|
||||||
v-if="currentPipelineType() === 3"
|
v-model="contourPerimeter"
|
||||||
name="Perimeter"
|
name="Perimeter"
|
||||||
tooltip="Min and max perimeter of the shape, in pixels"
|
tooltip="Min and max perimeter of the shape, in pixels"
|
||||||
min="0"
|
min="0"
|
||||||
max="4000"
|
max="4000"
|
||||||
@input="handlePipelineData('contourPerimeter')"
|
@input="handlePipelineData('contourPerimeter')"
|
||||||
/>
|
/>
|
||||||
<CVslider
|
<CVslider
|
||||||
v-model="contourSpecklePercentage"
|
v-model="contourSpecklePercentage"
|
||||||
name="Speckle Rejection"
|
name="Speckle Rejection"
|
||||||
tooltip="Rejects contours whose average area is less than the given percentage of the average area of all the other contours"
|
tooltip="Rejects contours whose average area is less than the given percentage of the average area of all the other contours"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('contourSpecklePercentage')"
|
@input="handlePipelineData('contourSpecklePercentage')"
|
||||||
/>
|
/>
|
||||||
<template v-if="currentPipelineType() !== 3">
|
<template v-if="currentPipelineType() !== 3">
|
||||||
<CVselect
|
<CVslider
|
||||||
v-model="contourGroupingMode"
|
v-model="contourFilterRangeX"
|
||||||
name="Target Grouping"
|
name="X filter tightness"
|
||||||
tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
|
tooltip="Rejects contours whose center X is further than X standard deviations above/below the mean X location"
|
||||||
:select-cols="largeBox"
|
min="0.1"
|
||||||
:list="['Single','Dual','2orMore']"
|
max="4"
|
||||||
@input="handlePipelineData('contourGroupingMode')"
|
step="0.1"
|
||||||
|
:slider-cols="largeBox"
|
||||||
|
@input="handlePipelineData('contourFilterRangeX')"
|
||||||
|
/>
|
||||||
|
<CVslider
|
||||||
|
v-model="contourFilterRangeY"
|
||||||
|
name="Y filter tightness"
|
||||||
|
tooltip="Rejects contours whose center Y is further than X standard deviations above/below the mean Y location"
|
||||||
|
min="0.1"
|
||||||
|
max="4"
|
||||||
|
step="0.1"
|
||||||
|
:slider-cols="largeBox"
|
||||||
|
@input="handlePipelineData('contourFilterRangeY')"
|
||||||
/>
|
/>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="contourIntersection"
|
v-model="contourGroupingMode"
|
||||||
name="Target Intersection"
|
name="Target Grouping"
|
||||||
tooltip="If target grouping is in dual mode it will use this dropdown to decide how targets are grouped with adjacent targets"
|
tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
|
||||||
:select-cols="largeBox"
|
:select-cols="largeBox"
|
||||||
:list="['None','Up','Down','Left','Right']"
|
:list="['Single','Dual','2orMore']"
|
||||||
:disabled="contourGroupingMode === 0"
|
@input="handlePipelineData('contourGroupingMode')"
|
||||||
@input="handlePipelineData('contourIntersection')"
|
/>
|
||||||
|
<CVselect
|
||||||
|
v-model="contourIntersection"
|
||||||
|
name="Target Intersection"
|
||||||
|
tooltip="If target grouping is in dual mode it will use this dropdown to decide how targets are grouped with adjacent targets"
|
||||||
|
:select-cols="largeBox"
|
||||||
|
:list="['None','Up','Down','Left','Right']"
|
||||||
|
:disabled="contourGroupingMode === 0"
|
||||||
|
@input="handlePipelineData('contourIntersection')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<!-- If we arent not a shape, we are a shape-->
|
<!-- If we arent not a shape, we are a shape-->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<v-divider class="mt-3"/>
|
<v-divider class="mt-3" />
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="contourShape"
|
v-model="contourShape"
|
||||||
name="Target Shape"
|
name="Target Shape"
|
||||||
tooltip="The shape of targets to look for"
|
tooltip="The shape of targets to look for"
|
||||||
:select-cols="largeBox"
|
:select-cols="largeBox"
|
||||||
:list="['Circle', 'Polygon', 'Triangle', 'Quadrilateral']"
|
:list="['Circle', 'Polygon', 'Triangle', 'Quadrilateral']"
|
||||||
@input="handlePipelineData('contourShape')"
|
@input="handlePipelineData('contourShape')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Accuracy % is only for polygons-->
|
<!-- Accuracy % is only for polygons-->
|
||||||
<CVslider
|
<CVslider
|
||||||
v-model="accuracyPercentage"
|
v-model="accuracyPercentage"
|
||||||
:disabled="currentPipelineSettings().contourShape < 1"
|
:disabled="currentPipelineSettings().contourShape < 1"
|
||||||
name="Shape Simplification"
|
name="Shape Simplification"
|
||||||
tooltip="How much we should simply the input contour before checking how many sides it has"
|
tooltip="How much we should simply the input contour before checking how many sides it has"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('accuracyPercentage')"
|
@input="handlePipelineData('accuracyPercentage')"
|
||||||
/>
|
/>
|
||||||
<!-- Similarly, the threshold is only for circles -->
|
<!-- Similarly, the threshold is only for circles -->
|
||||||
<CVslider
|
<CVslider
|
||||||
v-model="circleDetectThreshold"
|
v-model="circleDetectThreshold"
|
||||||
:disabled="currentPipelineSettings().contourShape !== 0"
|
:disabled="currentPipelineSettings().contourShape !== 0"
|
||||||
name="Circle match distance"
|
name="Circle match distance"
|
||||||
tooltip="How close the centroid of a contour must be to the center of a circle in order for them to be matched"
|
tooltip="How close the centroid of a contour must be to the center of a circle in order for them to be matched"
|
||||||
min="1"
|
min="1"
|
||||||
max="100"
|
max="100"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('circleDetectThreshold')"
|
@input="handlePipelineData('circleDetectThreshold')"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="contourRadius"
|
v-model="contourRadius"
|
||||||
:disabled="currentPipelineSettings().contourShape !== 0"
|
:disabled="currentPipelineSettings().contourShape !== 0"
|
||||||
name="Radius"
|
name="Radius"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="1"
|
step="1"
|
||||||
@input="handlePipelineData('contourRadius')"
|
label-cols="3"
|
||||||
|
@input="handlePipelineData('contourRadius')"
|
||||||
/>
|
/>
|
||||||
<CVslider
|
<CVslider
|
||||||
v-model="maxCannyThresh"
|
v-model="maxCannyThresh"
|
||||||
:disabled="currentPipelineSettings().contourShape !== 0"
|
:disabled="currentPipelineSettings().contourShape !== 0"
|
||||||
name="Max Canny Threshold"
|
name="Max Canny Threshold"
|
||||||
min="1"
|
min="1"
|
||||||
max="100"
|
max="100"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('maxCannyThresh')"
|
@input="handlePipelineData('maxCannyThresh')"
|
||||||
/>
|
/>
|
||||||
<CVslider
|
<CVslider
|
||||||
v-model="circleAccuracy"
|
v-model="circleAccuracy"
|
||||||
:disabled="currentPipelineSettings().contourShape !== 0"
|
:disabled="currentPipelineSettings().contourShape !== 0"
|
||||||
name="Circle Accuracy"
|
name="Circle Accuracy"
|
||||||
min="0"
|
min="1"
|
||||||
max="100"
|
max="100"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('circleAccuracy')"
|
@input="handlePipelineData('circleAccuracy')"
|
||||||
/>
|
/>
|
||||||
<v-divider class="mt-3"/>
|
<v-divider class="mt-3" />
|
||||||
</template>
|
</template>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="contourSortMode"
|
v-model="contourSortMode"
|
||||||
name="Target Sort"
|
name="Target Sort"
|
||||||
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
|
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
|
||||||
:select-cols="largeBox"
|
:select-cols="largeBox"
|
||||||
:list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Centermost']"
|
:list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Centermost']"
|
||||||
@input="handlePipelineData('contourSortMode')"
|
@input="handlePipelineData('contourSortMode')"
|
||||||
@rollback="e => rollback('contourSortMode', e)"
|
@rollback="e => rollback('contourSortMode', e)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -182,6 +211,14 @@ export default {
|
|||||||
this.$store.commit("mutatePipeline", {"contourRatio": val});
|
this.$store.commit("mutatePipeline", {"contourRatio": val});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
contourTargetOrientation: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters.currentPipelineSettings.contourTargetOrientation
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.commit("mutatePipeline", {"contourTargetOrientation": val});
|
||||||
|
}
|
||||||
|
},
|
||||||
contourFullness: {
|
contourFullness: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.contourFullness
|
return this.$store.getters.currentPipelineSettings.contourFullness
|
||||||
@@ -206,6 +243,25 @@ export default {
|
|||||||
this.$store.commit("mutatePipeline", {"contourSpecklePercentage": val});
|
this.$store.commit("mutatePipeline", {"contourSpecklePercentage": val});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
contourFilterRangeX: {
|
||||||
|
get() {
|
||||||
|
console.log(this.$store.getters.currentPipelineSettings.contourFilterRangeX)
|
||||||
|
return this.$store.getters.currentPipelineSettings.contourFilterRangeX
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
console.log("set")
|
||||||
|
console.log(val)
|
||||||
|
this.$store.commit("mutatePipeline", {"contourFilterRangeX": val});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contourFilterRangeY: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters.currentPipelineSettings.contourFilterRangeY
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.commit("mutatePipeline", {"contourFilterRangeY": val});
|
||||||
|
}
|
||||||
|
},
|
||||||
contourGroupingMode: {
|
contourGroupingMode: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.contourGroupingMode
|
return this.$store.getters.currentPipelineSettings.contourGroupingMode
|
||||||
|
|||||||
@@ -22,15 +22,26 @@
|
|||||||
@rollback="e => rollback('cameraBrightness', e)"
|
@rollback="e => rollback('cameraBrightness', e)"
|
||||||
/>
|
/>
|
||||||
<CVslider
|
<CVslider
|
||||||
v-if="cameraGain !== -1"
|
v-if="cameraRedGain !== -1"
|
||||||
v-model="cameraGain"
|
v-model="cameraRedGain"
|
||||||
name="Gain"
|
name="Red AWB Gain"
|
||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
tooltip="Controls automatic white balance gain, which affects how the camera captures colors in different conditions"
|
tooltip="Controls red automatic white balance gain, which affects how the camera captures colors in different conditions"
|
||||||
:slider-cols="largeBox"
|
:slider-cols="largeBox"
|
||||||
@input="handlePipelineData('cameraGain')"
|
@input="handlePipelineData('cameraRedGain')"
|
||||||
@rollback="e => rollback('cameraGain', e)"
|
@rollback="e => rollback('cameraRedGain', e)"
|
||||||
|
/>
|
||||||
|
<CVslider
|
||||||
|
v-if="cameraBlueGain !== -1"
|
||||||
|
v-model="cameraBlueGain"
|
||||||
|
name="Blue AWB Gain"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
|
||||||
|
:slider-cols="largeBox"
|
||||||
|
@input="handlePipelineData('cameraBlueGain')"
|
||||||
|
@rollback="e => rollback('cameraBlueGain', e)"
|
||||||
/>
|
/>
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="inputImageRotationMode"
|
v-model="inputImageRotationMode"
|
||||||
@@ -105,12 +116,20 @@
|
|||||||
this.$store.commit("mutatePipeline", {"cameraBrightness": parseInt(val)});
|
this.$store.commit("mutatePipeline", {"cameraBrightness": parseInt(val)});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cameraGain: {
|
cameraRedGain: {
|
||||||
get() {
|
get() {
|
||||||
return parseInt(this.$store.getters.currentPipelineSettings.cameraGain)
|
return parseInt(this.$store.getters.currentPipelineSettings.cameraRedGain)
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.commit("mutatePipeline", {"cameraGain": parseInt(val)});
|
this.$store.commit("mutatePipeline", {"cameraRedGain": parseInt(val)});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cameraBlueGain: {
|
||||||
|
get() {
|
||||||
|
return parseInt(this.$store.getters.currentPipelineSettings.cameraBlueGain)
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.commit("mutatePipeline", {"cameraBlueGain": parseInt(val)});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputImageRotationMode: {
|
inputImageRotationMode: {
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span class="white--text">Target Manipulation</span>
|
|
||||||
<v-divider class="mt-2" />
|
|
||||||
|
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="contourTargetOffsetPointEdge"
|
v-model="contourTargetOffsetPointEdge"
|
||||||
name="Target Offset Point"
|
name="Target Offset Point"
|
||||||
@@ -31,8 +28,7 @@
|
|||||||
|
|
||||||
@rollback="e=> rollback('outputShowMultipleTargets', e)"
|
@rollback="e=> rollback('outputShowMultipleTargets', e)"
|
||||||
/>
|
/>
|
||||||
<span class="white--text">Robot Offset</span>
|
<v-divider />
|
||||||
<v-divider class="mt-2" />
|
|
||||||
<CVselect
|
<CVselect
|
||||||
v-model="offsetRobotOffsetMode"
|
v-model="offsetRobotOffsetMode"
|
||||||
name="Robot Offset Mode"
|
name="Robot Offset Mode"
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
targetList: ['2020 High Goal Outer', '2020 High Goal Inner', '2019 Dual Target', 'Power Cell (7in)', '2016 High Goal'], //Keep in sync with TargetModel.java
|
targetList: ['2020 High Goal Outer', '2020 High Goal Inner', '2019 Dual Target', '2020 Power Cell (7in)','2022 Cargo Ball (9.5in)', '2016 High Goal'], //Keep in sync with TargetModel.java
|
||||||
snackbar: {
|
snackbar: {
|
||||||
color: "Success",
|
color: "Success",
|
||||||
text: ""
|
text: ""
|
||||||
|
|||||||
@@ -1,66 +1,79 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div :style="{'--averageHue': averageHue}">
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="hsvHue"
|
id="hue-slider"
|
||||||
name="Hue"
|
v-model="hsvHue"
|
||||||
tooltip="Describes color"
|
:class="hueInverted ? 'inverted-slider' : 'normal-slider'"
|
||||||
:min="0"
|
name="Hue"
|
||||||
:max="180"
|
tooltip="Describes color"
|
||||||
@input="handlePipelineData('hsvHue')"
|
:min="0"
|
||||||
@rollback="e => rollback('hue',e)"
|
:max="180"
|
||||||
|
:inverted="hueInverted"
|
||||||
|
@input="handlePipelineData('hsvHue')"
|
||||||
|
@rollback="e => rollback('hue',e)"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="hsvSaturation"
|
id="sat-slider"
|
||||||
name="Saturation"
|
v-model="hsvSaturation"
|
||||||
tooltip="Describes colorfulness; the smaller this value the 'whiter' the color becomes"
|
class="normal-slider"
|
||||||
:min="0"
|
name="Saturation"
|
||||||
:max="255"
|
tooltip="Describes colorfulness; the smaller this value the 'whiter' the color becomes"
|
||||||
@input="handlePipelineData('hsvSaturation')"
|
:min="0"
|
||||||
@rollback="e => rollback('saturation',e)"
|
:max="255"
|
||||||
|
@input="handlePipelineData('hsvSaturation')"
|
||||||
|
@rollback="e => rollback('saturation',e)"
|
||||||
/>
|
/>
|
||||||
<CVrangeSlider
|
<CVrangeSlider
|
||||||
v-model="hsvValue"
|
id="value-slider"
|
||||||
name="Value"
|
v-model="hsvValue"
|
||||||
tooltip="Describes lightness; the smaller this value the 'blacker' the color becomes"
|
class="normal-slider"
|
||||||
:min="0"
|
name="Value"
|
||||||
:max="255"
|
tooltip="Describes lightness; the smaller this value the 'blacker' the color becomes"
|
||||||
@input="handlePipelineData('hsvValue')"
|
:min="0"
|
||||||
@rollback="e => rollback('value',e)"
|
:max="255"
|
||||||
|
@input="handlePipelineData('hsvValue')"
|
||||||
|
@rollback="e => rollback('value',e)"
|
||||||
/>
|
/>
|
||||||
<template v-if="this.currentPipelineType() === 3">
|
<CVSwitch
|
||||||
|
v-model="hueInverted"
|
||||||
|
name="Invert hue"
|
||||||
|
tooltip="Selects the hue range outside of the hue slider bounds instead of inside"
|
||||||
|
@input="handlePipelineData('hueInverted')"
|
||||||
|
@rollback="e => rollback('hueInverted',e)"
|
||||||
|
/>
|
||||||
|
<template v-if="currentPipelineType() === 3">
|
||||||
<CVSwitch
|
<CVSwitch
|
||||||
v-model="erode"
|
v-model="erode"
|
||||||
name="Erode"
|
name="Erode"
|
||||||
tooltip="Removes pixels around the edges of white areas in the thresholded image"
|
tooltip="Removes pixels around the edges of white areas in the thresholded image"
|
||||||
@input="handlePipelineData('erode')"
|
@input="handlePipelineData('erode')"
|
||||||
@rollback="e => rollback('erode',e)"
|
@rollback="e => rollback('erode',e)"
|
||||||
/>
|
/>
|
||||||
<CVSwitch
|
<CVSwitch
|
||||||
v-model="dilate"
|
v-model="dilate"
|
||||||
class="mb-0"
|
class="mb-0"
|
||||||
name="Dilate"
|
name="Dilate"
|
||||||
tooltip="Adds pixels around the edges of white areas in the thresholded image"
|
tooltip="Adds pixels around the edges of white areas in the thresholded image"
|
||||||
@input="handlePipelineData('dilate')"
|
@input="handlePipelineData('dilate')"
|
||||||
@rollback="e => rollback('dilate',e)"
|
@rollback="e => rollback('dilate',e)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<v-divider class="mb-3 mt-3"/>
|
|
||||||
<div class="pt-3 white--text">
|
<div class="pt-3 white--text">
|
||||||
Color Picker
|
Color Picker
|
||||||
</div>
|
</div>
|
||||||
<v-divider
|
<v-divider
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
/>
|
/>
|
||||||
<v-row
|
<v-row
|
||||||
justify="center"
|
justify="center"
|
||||||
class="mt-3 mb-3"
|
class="mt-3 mb-3"
|
||||||
>
|
>
|
||||||
<template v-if="!$store.state.colorPicking">
|
<template v-if="!$store.state.colorPicking">
|
||||||
<v-btn
|
<v-btn
|
||||||
color="accent"
|
color="accent"
|
||||||
class="ma-2 black--text"
|
class="ma-2 black--text"
|
||||||
small
|
small
|
||||||
@click="setFunction(3)"
|
@click="setFunction(hueInverted ? 2 : 3)"
|
||||||
>
|
>
|
||||||
<v-icon left>
|
<v-icon left>
|
||||||
mdi-minus
|
mdi-minus
|
||||||
@@ -68,21 +81,21 @@
|
|||||||
Shrink Range
|
Shrink Range
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
color="accent"
|
color="accent"
|
||||||
class="ma-2 black--text"
|
class="ma-2 black--text"
|
||||||
small
|
small
|
||||||
@click="setFunction(1)"
|
@click="setFunction(1)"
|
||||||
>
|
>
|
||||||
<v-icon left>
|
<v-icon left>
|
||||||
mdi-plus-minus
|
mdi-plus-minus
|
||||||
</v-icon>
|
</v-icon>
|
||||||
Set To Average
|
{{ hueInverted ? "Exclude" : "Set to" }} Average
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
color="accent"
|
color="accent"
|
||||||
class="ma-2 black--text"
|
class="ma-2 black--text"
|
||||||
small
|
small
|
||||||
@click="setFunction(2)"
|
@click="setFunction(hueInverted ? 3: 2)"
|
||||||
>
|
>
|
||||||
<v-icon left>
|
<v-icon left>
|
||||||
mdi-plus
|
mdi-plus
|
||||||
@@ -92,16 +105,17 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<v-btn
|
<v-btn
|
||||||
color="accent"
|
color="accent"
|
||||||
class="ma-2 black--text"
|
class="ma-2 black--text"
|
||||||
style="width: 30%;"
|
style="width: 30%;"
|
||||||
small
|
small
|
||||||
@click="setFunction(0)"
|
@click="setFunction(0)"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
<v-divider class="mb-3" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -133,9 +147,41 @@ export default {
|
|||||||
this.$store.commit("mutatePipeline", {"hsvHue": val})
|
this.$store.commit("mutatePipeline", {"hsvHue": val})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
averageHue: {
|
||||||
|
get() {
|
||||||
|
var isInverted = this.$store.getters.currentPipelineSettings.hueInverted;
|
||||||
|
const arr = this.$store.getters.currentPipelineSettings.hsvHue;
|
||||||
|
var retVal = 0;
|
||||||
|
|
||||||
|
if (Array.isArray(arr)) {
|
||||||
|
retVal = (arr[0] + arr[1]);
|
||||||
|
} else {
|
||||||
|
retVal = (arr.first + arr.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isInverted){
|
||||||
|
retVal += 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(retVal > 360){
|
||||||
|
retVal -= 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hueInverted: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters.currentPipelineSettings.hueInverted;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.commit("mutatePipeline", {"hueInverted": val});
|
||||||
|
}
|
||||||
|
},
|
||||||
hsvSaturation: {
|
hsvSaturation: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.hsvSaturation
|
return this.$store.getters.currentPipelineSettings.hsvSaturation;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.commit("mutatePipeline", {"hsvSaturation": val})
|
this.$store.commit("mutatePipeline", {"hsvSaturation": val})
|
||||||
@@ -143,15 +189,15 @@ export default {
|
|||||||
},
|
},
|
||||||
hsvValue: {
|
hsvValue: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.hsvValue
|
return this.$store.getters.currentPipelineSettings.hsvValue;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.commit("mutatePipeline", {"hsvValue": val})
|
this.$store.commit("mutatePipeline", {"hsvValue": val});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
erode: {
|
erode: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.erode
|
return this.$store.getters.currentPipelineSettings.erode;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.commit("mutatePipeline", {"erode": val});
|
this.$store.commit("mutatePipeline", {"erode": val});
|
||||||
@@ -159,7 +205,7 @@ export default {
|
|||||||
},
|
},
|
||||||
dilate: {
|
dilate: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters.currentPipelineSettings.dilate
|
return this.$store.getters.currentPipelineSettings.dilate;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.commit("mutatePipeline", {"dilate": val});
|
this.$store.commit("mutatePipeline", {"dilate": val});
|
||||||
@@ -233,3 +279,31 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
#hue-slider >>> .v-slider {
|
||||||
|
background: linear-gradient( to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100% );
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0px 0px 5px #333, inset 0px 0px 3px #333;
|
||||||
|
}
|
||||||
|
#sat-slider >>> .v-slider {
|
||||||
|
background: linear-gradient( to right, #fff 0%, hsl(var(--averageHue), 100%, 50%) 100% );
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0px 0px 5px #333, inset 0px 0px 3px #333;
|
||||||
|
}
|
||||||
|
#value-slider >>> .v-slider {
|
||||||
|
background: linear-gradient( to right, #000 0%, hsl(var(--averageHue), 100%, 50%) 100% );
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0px 0px 5px #333, inset 0px 0px 3px #333;
|
||||||
|
}
|
||||||
|
>>> .v-slider__thumb {
|
||||||
|
outline: black solid thin;
|
||||||
|
}
|
||||||
|
.normal-slider >>> .v-slider__track-fill {
|
||||||
|
outline: black solid thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inverted-slider >>> .v-slider__track-background {
|
||||||
|
outline: black solid thin;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
<v-icon left>
|
<v-icon left>
|
||||||
mdi-restart
|
mdi-restart
|
||||||
</v-icon>
|
</v-icon>
|
||||||
Restart Photon
|
Restart PhotonVision
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col
|
<v-col
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
@click="restartDevice()"
|
@click="restartDevice()"
|
||||||
>
|
>
|
||||||
<v-icon left>
|
<v-icon left>
|
||||||
mdi-restart
|
mdi-restart-alert
|
||||||
</v-icon>
|
</v-icon>
|
||||||
Restart Device
|
Restart Device
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|||||||
@@ -10,46 +10,52 @@
|
|||||||
name="Team Number"
|
name="Team Number"
|
||||||
:rules="[v => (v > 0) || 'Team number must be greater than zero', v => (v < 10000) || 'Team number must have fewer than five digits']"
|
:rules="[v => (v > 0) || 'Team number must be greater than zero', v => (v < 10000) || 'Team number must have fewer than five digits']"
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
:label-cols="$vuetify.breakpoint.mdAndUp ? undefined : 7"
|
:label-cols="$vuetify.breakpoint.mdAndUp ? undefined : 5"
|
||||||
/>
|
/>
|
||||||
<v-chip label color="red" v-bind:style="$vuetify.breakpoint.xsOnly ? 'height: auto;' : ''" text-color="white" v-if="parseInt(teamNumber) < 1 && !runNTServer">
|
<v-banner
|
||||||
<span class="text-wrap">
|
v-show="(teamNumber < 1 || teamNumber > 10000) && !runNTServer"
|
||||||
Team number not set! NetworkTables cannot connect.
|
rounded
|
||||||
</span>
|
color="red"
|
||||||
</v-chip>
|
text-color="white"
|
||||||
|
>
|
||||||
|
Team number is unset or invalid. NetworkTables will not be able to connect.
|
||||||
|
</v-banner>
|
||||||
<CVradio
|
<CVradio
|
||||||
v-model="connectionType"
|
v-show="$store.state.settings.networkSettings.supported"
|
||||||
|
v-model="connectionType"
|
||||||
|
:input-cols="inputCols"
|
||||||
|
name="IP Assignment Mode"
|
||||||
|
tooltip="DHCP will make the radio (router) automatically assign an IP address; this may result in an IP address that changes across reboots. Static IP assignment means that you pick the IP address and it won't change."
|
||||||
:list="['DHCP','Static']"
|
:list="['DHCP','Static']"
|
||||||
:disabled="!$store.state.settings.networkSettings.supported"
|
|
||||||
/>
|
/>
|
||||||
<template v-if="!isDHCP">
|
<CVinput
|
||||||
<CVinput
|
v-if="!isDHCP"
|
||||||
v-model="staticIp"
|
v-model="staticIp"
|
||||||
:input-cols="inputCols"
|
:input-cols="inputCols"
|
||||||
:rules="[v => isIPv4(v) || 'Invalid IPv4 address']"
|
:rules="[v => isIPv4(v) || 'Invalid IPv4 address']"
|
||||||
name="IP"
|
name="IP"
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
<CVinput
|
<CVinput
|
||||||
v-model="hostname"
|
v-model="hostname"
|
||||||
:input-cols="inputCols"
|
:input-cols="inputCols"
|
||||||
:rules="[v => isHostname(v) || 'Invalid hostname']"
|
:rules="[v => isHostname(v) || 'Invalid hostname']"
|
||||||
name="Hostname"
|
name="Hostname"
|
||||||
/>
|
/>
|
||||||
Advanced
|
|
||||||
<v-divider/>
|
|
||||||
<CVSwitch
|
<CVSwitch
|
||||||
v-model="runNTServer"
|
v-model="runNTServer"
|
||||||
name="Run NetworkTables Server (Debugging Only!)"
|
name="Run NetworkTables Server (Debugging Only)"
|
||||||
tooltip="If enabled, this device will create a NT server. This is useful for home debugging, but should be disabled on-robot."
|
tooltip="If enabled, this device will create a NT server. This is useful for home debugging, but should be disabled on-robot."
|
||||||
class="mt-3 mb-3"
|
class="mt-3 mb-3"
|
||||||
:text-cols="$vuetify.breakpoint.mdAndUp ? undefined : 7"
|
:text-cols="$vuetify.breakpoint.mdAndUp ? undefined : 5"
|
||||||
/>
|
/>
|
||||||
<v-chip label color="red" text-color="white" v-if="runNTServer">
|
<v-banner
|
||||||
<span>
|
v-show="runNTServer"
|
||||||
Disable this switch if you're on a robot! Photonlib will NOT work.
|
rounded
|
||||||
</span>
|
color="red"
|
||||||
</v-chip>
|
text-color="white"
|
||||||
|
>
|
||||||
|
This switch is intended for testing; it should be off on a robot. PhotonLib will NOT work!
|
||||||
|
</v-banner>
|
||||||
</v-form>
|
</v-form>
|
||||||
<v-btn
|
<v-btn
|
||||||
color="accent"
|
color="accent"
|
||||||
@@ -60,55 +66,60 @@
|
|||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-divider class="mt-4 mb-4"/>
|
<v-divider class="mt-4 mb-4" />
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="6">
|
<v-col
|
||||||
|
cols="12"
|
||||||
|
sm="6"
|
||||||
|
>
|
||||||
<v-simple-table
|
<v-simple-table
|
||||||
fixed-header
|
fixed-header
|
||||||
height="100%"
|
height="100%"
|
||||||
dense
|
dense
|
||||||
>
|
>
|
||||||
<template v-slot:default>
|
<template v-slot:default>
|
||||||
<thead style="font-size: 1.25rem;">
|
<thead style="font-size: 1.25rem;">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
Device IPs
|
Device IPs
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(value, index) in $store.state.ntConnectionInfo.deviceips"
|
v-for="(value, index) in $store.state.networkInfo.deviceips"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<td>{{ value }}</td>
|
<td>{{ value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</template>
|
</template>
|
||||||
</v-simple-table>
|
</v-simple-table>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" sm="6">
|
<v-col
|
||||||
|
cols="12"
|
||||||
|
sm="6"
|
||||||
|
>
|
||||||
<v-simple-table
|
<v-simple-table
|
||||||
fixed-header
|
fixed-header
|
||||||
height="100%"
|
height="100%"
|
||||||
dense
|
dense
|
||||||
>
|
>
|
||||||
<template v-slot:default>
|
<template v-slot:default>
|
||||||
<thead style="font-size: 1.25rem;">
|
<thead style="font-size: 1.25rem;">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
Possible RoboRIOs
|
Possible RoboRIOs
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(value, index) in $store.state.ntConnectionInfo.possibleRios"
|
v-for="(value, index) in $store.state.networkInfo.possibleRios"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<td>{{ value }}</td>
|
<td>{{ value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</template>
|
</template>
|
||||||
</v-simple-table>
|
</v-simple-table>
|
||||||
@@ -150,7 +161,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
inputCols() {
|
inputCols() {
|
||||||
return this.$vuetify.breakpoint.smAndUp ? 10 : 7;
|
return this.$vuetify.breakpoint.mdAndUp ? 10 : 7;
|
||||||
},
|
},
|
||||||
isDHCP() {
|
isDHCP() {
|
||||||
return this.settings.connectionType === 0;
|
return this.settings.connectionType === 0;
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task writeCurrentVersionJava {
|
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)
|
versionString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common;
|
package org.photonvision.common;
|
||||||
|
|
||||||
public enum ProgramStatus {
|
public enum ProgramStatus {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
@@ -31,7 +32,6 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.photonvision.common.logging.LogGroup;
|
import org.photonvision.common.logging.LogGroup;
|
||||||
import org.photonvision.common.logging.Logger;
|
import org.photonvision.common.logging.Logger;
|
||||||
import org.photonvision.common.util.TimedTaskManager;
|
|
||||||
import org.photonvision.common.util.file.FileUtils;
|
import org.photonvision.common.util.file.FileUtils;
|
||||||
import org.photonvision.common.util.file.JacksonUtils;
|
import org.photonvision.common.util.file.JacksonUtils;
|
||||||
import org.photonvision.vision.pipeline.CVPipelineSettings;
|
import org.photonvision.vision.pipeline.CVPipelineSettings;
|
||||||
@@ -56,6 +56,7 @@ public class ConfigManager {
|
|||||||
final File configDirectoryFile;
|
final File configDirectoryFile;
|
||||||
|
|
||||||
private long saveRequestTimestamp = -1;
|
private long saveRequestTimestamp = -1;
|
||||||
|
private Thread settingsSaveThread;
|
||||||
|
|
||||||
public static ConfigManager getInstance() {
|
public static ConfigManager getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
@@ -96,7 +97,8 @@ public class ConfigManager {
|
|||||||
new File(Path.of(configDirectoryFile.toString(), NET_SET_FNAME).toUri());
|
new File(Path.of(configDirectoryFile.toString(), NET_SET_FNAME).toUri());
|
||||||
this.camerasFolder = new File(Path.of(configDirectoryFile.toString(), "cameras").toUri());
|
this.camerasFolder = new File(Path.of(configDirectoryFile.toString(), "cameras").toUri());
|
||||||
|
|
||||||
TimedTaskManager.getInstance().addTask("ConfigManager", this::checkSaveAndWrite, 1000);
|
settingsSaveThread = new Thread(this::saveAndWriteTask);
|
||||||
|
settingsSaveThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load() {
|
public void load() {
|
||||||
@@ -424,12 +426,24 @@ public class ConfigManager {
|
|||||||
saveRequestTimestamp = System.currentTimeMillis();
|
saveRequestTimestamp = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSaveAndWrite() {
|
private void saveAndWriteTask() {
|
||||||
// Only save if 1 second has past since the request was made
|
// Only save if 1 second has past since the request was made
|
||||||
if (saveRequestTimestamp > 0 && (System.currentTimeMillis() - saveRequestTimestamp) > 1000L) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
saveRequestTimestamp = -1;
|
if (saveRequestTimestamp > 0 && (System.currentTimeMillis() - saveRequestTimestamp) > 1000L) {
|
||||||
logger.debug("Saving to disk...");
|
saveRequestTimestamp = -1;
|
||||||
saveToDisk();
|
logger.debug("Saving to disk...");
|
||||||
|
saveToDisk();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("Exception waiting for settings semaphor", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unloadCameraConfigs() {
|
||||||
|
this.config.getCameraConfigurations().clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
public class HardwareSettings {
|
public class HardwareSettings {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.configuration;
|
package org.photonvision.common.configuration;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow;
|
package org.photonvision.common.dataflow;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow;
|
package org.photonvision.common.dataflow;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow;
|
package org.photonvision.common.dataflow;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow;
|
package org.photonvision.common.dataflow;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow;
|
package org.photonvision.common.dataflow;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.events;
|
package org.photonvision.common.dataflow.events;
|
||||||
|
|
||||||
import org.photonvision.common.dataflow.DataChangeDestination;
|
import org.photonvision.common.dataflow.DataChangeDestination;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.events;
|
package org.photonvision.common.dataflow.events;
|
||||||
|
|
||||||
import org.photonvision.common.dataflow.DataChangeDestination;
|
import org.photonvision.common.dataflow.DataChangeDestination;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.events;
|
package org.photonvision.common.dataflow.events;
|
||||||
|
|
||||||
import io.javalin.websocket.WsContext;
|
import io.javalin.websocket.WsContext;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.events;
|
package org.photonvision.common.dataflow.events;
|
||||||
|
|
||||||
import io.javalin.websocket.WsContext;
|
import io.javalin.websocket.WsContext;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.networktables;
|
package org.photonvision.common.dataflow.networktables;
|
||||||
|
|
||||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.networktables;
|
package org.photonvision.common.dataflow.networktables;
|
||||||
|
|
||||||
import edu.wpi.first.networktables.EntryNotification;
|
import edu.wpi.first.networktables.EntryNotification;
|
||||||
|
|||||||
@@ -14,22 +14,15 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.networktables;
|
package org.photonvision.common.dataflow.networktables;
|
||||||
|
|
||||||
import edu.wpi.first.cscore.CameraServerJNI;
|
|
||||||
import edu.wpi.first.networktables.LogMessage;
|
import edu.wpi.first.networktables.LogMessage;
|
||||||
import edu.wpi.first.networktables.NetworkTable;
|
import edu.wpi.first.networktables.NetworkTable;
|
||||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.photonvision.PhotonVersion;
|
import org.photonvision.PhotonVersion;
|
||||||
import org.photonvision.common.configuration.ConfigManager;
|
|
||||||
import org.photonvision.common.configuration.NetworkConfig;
|
import org.photonvision.common.configuration.NetworkConfig;
|
||||||
import org.photonvision.common.dataflow.DataChangeService;
|
import org.photonvision.common.dataflow.DataChangeService;
|
||||||
import org.photonvision.common.dataflow.events.OutgoingUIEvent;
|
import org.photonvision.common.dataflow.events.OutgoingUIEvent;
|
||||||
@@ -86,6 +79,7 @@ public class NetworkTablesManager {
|
|||||||
private void broadcastConnectedStatusImpl() {
|
private void broadcastConnectedStatusImpl() {
|
||||||
HashMap<String, Object> map = new HashMap<>();
|
HashMap<String, Object> map = new HashMap<>();
|
||||||
var subMap = new HashMap<String, Object>();
|
var subMap = new HashMap<String, Object>();
|
||||||
|
|
||||||
subMap.put("connected", ntInstance.isConnected());
|
subMap.put("connected", ntInstance.isConnected());
|
||||||
if (ntInstance.isConnected()) {
|
if (ntInstance.isConnected()) {
|
||||||
var connections = getInstance().ntInstance.getConnections();
|
var connections = getInstance().ntInstance.getConnections();
|
||||||
@@ -98,73 +92,6 @@ public class NetworkTablesManager {
|
|||||||
map.put("ntConnectionInfo", subMap);
|
map.put("ntConnectionInfo", subMap);
|
||||||
DataChangeService.getInstance()
|
DataChangeService.getInstance()
|
||||||
.publishEvent(new OutgoingUIEvent<>("networkTablesConnected", map));
|
.publishEvent(new OutgoingUIEvent<>("networkTablesConnected", map));
|
||||||
|
|
||||||
// Seperate from the above so we don't hold stuff up
|
|
||||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
|
||||||
subMap.put(
|
|
||||||
"deviceips",
|
|
||||||
Arrays.stream(CameraServerJNI.getNetworkInterfaces())
|
|
||||||
.filter(it -> !it.equals("0.0.0.0"))
|
|
||||||
.toArray());
|
|
||||||
logger.info("Searching for rios");
|
|
||||||
List<String> possibleRioList = new ArrayList<>();
|
|
||||||
for (var ip : CameraServerJNI.getNetworkInterfaces()) {
|
|
||||||
logger.info("Trying " + ip);
|
|
||||||
var possibleRioAddr = getPossibleRioAddress(ip);
|
|
||||||
if (possibleRioAddr != null) {
|
|
||||||
logger.info("Maybe found " + ip);
|
|
||||||
searchForHost(possibleRioList, possibleRioAddr);
|
|
||||||
} else {
|
|
||||||
logger.info("Didn't match RIO IP");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String name =
|
|
||||||
"roboRIO-"
|
|
||||||
+ ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
|
||||||
+ "-FRC.local";
|
|
||||||
searchForHost(possibleRioList, name);
|
|
||||||
name =
|
|
||||||
"roboRIO-"
|
|
||||||
+ ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
|
||||||
+ "-FRC.lan";
|
|
||||||
searchForHost(possibleRioList, name);
|
|
||||||
name =
|
|
||||||
"roboRIO-"
|
|
||||||
+ ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
|
||||||
+ "-FRC.frc-field.local";
|
|
||||||
searchForHost(possibleRioList, name);
|
|
||||||
subMap.put("possibleRios", possibleRioList.toArray());
|
|
||||||
DataChangeService.getInstance()
|
|
||||||
.publishEvent(new OutgoingUIEvent<>("networkTablesConnected", map));
|
|
||||||
}
|
|
||||||
|
|
||||||
String getPossibleRioAddress(String ip) {
|
|
||||||
try {
|
|
||||||
InetAddress addr = InetAddress.getByName(ip);
|
|
||||||
var address = addr.getAddress();
|
|
||||||
if (address[0] != (byte) (10 & 0xff)) return null;
|
|
||||||
address[3] = (byte) (2 & 0xff);
|
|
||||||
return InetAddress.getByAddress(address).getHostAddress();
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void searchForHost(List<String> list, String hostname) {
|
|
||||||
try {
|
|
||||||
logger.info("Looking up " + hostname);
|
|
||||||
InetAddress testAddr = InetAddress.getByName(hostname);
|
|
||||||
logger.info("Pinging " + hostname);
|
|
||||||
var canContact = testAddr.isReachable(500);
|
|
||||||
if (canContact) {
|
|
||||||
logger.info("Was able to connect to " + hostname);
|
|
||||||
if (!list.contains(hostname)) list.add(hostname);
|
|
||||||
} else {
|
|
||||||
logger.info("Unable to reach " + hostname);
|
|
||||||
}
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void broadcastVersion() {
|
private void broadcastVersion() {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.dataflow.websocket;
|
package org.photonvision.common.dataflow.websocket;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO;
|
package org.photonvision.common.hardware.GPIO;
|
||||||
|
|
||||||
import org.photonvision.common.configuration.HardwareConfig;
|
import org.photonvision.common.configuration.HardwareConfig;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO;
|
package org.photonvision.common.hardware.GPIO;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
import static org.photonvision.common.hardware.GPIO.pi.PigpioException.*;
|
import static org.photonvision.common.hardware.GPIO.pi.PigpioException.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
public class PigpioPulse {
|
public class PigpioPulse {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
import static org.photonvision.common.hardware.GPIO.pi.PigpioException.*;
|
import static org.photonvision.common.hardware.GPIO.pi.PigpioException.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.GPIO.pi;
|
package org.photonvision.common.hardware.GPIO.pi;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware;
|
package org.photonvision.common.hardware;
|
||||||
|
|
||||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||||
|
|||||||
@@ -14,13 +14,14 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware;
|
package org.photonvision.common.hardware;
|
||||||
|
|
||||||
public enum PiVersion {
|
public enum PiVersion {
|
||||||
PI_B("Pi Model B"),
|
PI_B("Pi Model B"),
|
||||||
COMPUTE_MODULE("Compute Module Rev"),
|
COMPUTE_MODULE("Compute Module Rev"),
|
||||||
ZERO_W("Pi Zero W Rev 1.1"),
|
ZERO_W("Pi Zero W Rev 1.1"),
|
||||||
ZERO_2_W("Raspberry Pi Zero 2 W"),
|
ZERO_2_W("Raspberry Pi Zero 2"),
|
||||||
PI_3("Pi 3"),
|
PI_3("Pi 3"),
|
||||||
PI_4("Pi 4"),
|
PI_4("Pi 4"),
|
||||||
COMPUTE_MODULE_3("Compute Module 3"),
|
COMPUTE_MODULE_3("Compute Module 3"),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware;
|
package org.photonvision.common.hardware;
|
||||||
|
|
||||||
import edu.wpi.first.util.RuntimeDetector;
|
import edu.wpi.first.util.RuntimeDetector;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware;
|
package org.photonvision.common.hardware;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware;
|
package org.photonvision.common.hardware;
|
||||||
|
|
||||||
import edu.wpi.first.networktables.EntryNotification;
|
import edu.wpi.first.networktables.EntryNotification;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
public class CPUMetrics extends MetricsBase {
|
public class CPUMetrics extends MetricsBase {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
public class DiskMetrics extends MetricsBase {
|
public class DiskMetrics extends MetricsBase {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
public class GPUMetrics extends MetricsBase {
|
public class GPUMetrics extends MetricsBase {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.hardware.metrics;
|
package org.photonvision.common.hardware.metrics;
|
||||||
|
|
||||||
public class RAMMetrics extends MetricsBase {
|
public class RAMMetrics extends MetricsBase {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.logging;
|
package org.photonvision.common.logging;
|
||||||
|
|
||||||
public enum LogGroup {
|
public enum LogGroup {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.logging;
|
package org.photonvision.common.logging;
|
||||||
|
|
||||||
public enum LogLevel {
|
public enum LogLevel {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.logging;
|
package org.photonvision.common.logging;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.networking;
|
package org.photonvision.common.networking;
|
||||||
|
|
||||||
import java.net.InterfaceAddress;
|
import java.net.InterfaceAddress;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.networking;
|
package org.photonvision.common.networking;
|
||||||
|
|
||||||
import org.photonvision.common.configuration.ConfigManager;
|
import org.photonvision.common.configuration.ConfigManager;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.networking;
|
package org.photonvision.common.networking;
|
||||||
|
|
||||||
public enum NetworkMode {
|
public enum NetworkMode {
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.photonvision.common.networking;
|
||||||
|
|
||||||
|
import edu.wpi.first.cscore.CameraServerJNI;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import org.photonvision.common.dataflow.DataChangeService;
|
||||||
|
import org.photonvision.common.dataflow.events.OutgoingUIEvent;
|
||||||
|
import org.photonvision.common.logging.LogGroup;
|
||||||
|
import org.photonvision.common.logging.Logger;
|
||||||
|
|
||||||
|
public class RoborioFinder {
|
||||||
|
private static RoborioFinder instance;
|
||||||
|
private static final Logger logger = new Logger(RoborioFinder.class, LogGroup.General);
|
||||||
|
|
||||||
|
public static RoborioFinder getInstance() {
|
||||||
|
if (instance == null) instance = new RoborioFinder();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findRios() {
|
||||||
|
HashMap<String, Object> map = new HashMap<>();
|
||||||
|
var subMap = new HashMap<String, Object>();
|
||||||
|
// Seperate from the above so we don't hold stuff up
|
||||||
|
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||||
|
subMap.put(
|
||||||
|
"deviceips",
|
||||||
|
Arrays.stream(CameraServerJNI.getNetworkInterfaces())
|
||||||
|
.filter(it -> !it.equals("0.0.0.0"))
|
||||||
|
.toArray());
|
||||||
|
logger.info("Searching for rios");
|
||||||
|
List<String> possibleRioList = new ArrayList<>();
|
||||||
|
for (var ip : CameraServerJNI.getNetworkInterfaces()) {
|
||||||
|
logger.info("Trying " + ip);
|
||||||
|
var possibleRioAddr = getPossibleRioAddress(ip);
|
||||||
|
if (possibleRioAddr != null) {
|
||||||
|
logger.info("Maybe found " + ip);
|
||||||
|
searchForHost(possibleRioList, possibleRioAddr);
|
||||||
|
} else {
|
||||||
|
logger.info("Didn't match RIO IP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String name =
|
||||||
|
// "roboRIO-"
|
||||||
|
// +
|
||||||
|
// ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
||||||
|
// + "-FRC.local";
|
||||||
|
// searchForHost(possibleRioList, name);
|
||||||
|
// name =
|
||||||
|
// "roboRIO-"
|
||||||
|
// +
|
||||||
|
// ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
||||||
|
// + "-FRC.lan";
|
||||||
|
// searchForHost(possibleRioList, name);
|
||||||
|
// name =
|
||||||
|
// "roboRIO-"
|
||||||
|
// +
|
||||||
|
// ConfigManager.getInstance().getConfig().getNetworkConfig().teamNumber
|
||||||
|
// + "-FRC.frc-field.local";
|
||||||
|
// searchForHost(possibleRioList, name);
|
||||||
|
// subMap.put("possibleRios", possibleRioList.toArray());
|
||||||
|
|
||||||
|
subMap.put("possibleRios", possibleRioList.toArray());
|
||||||
|
map.put("networkInfo", subMap);
|
||||||
|
DataChangeService.getInstance().publishEvent(new OutgoingUIEvent<>("deviceIpInfo", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPossibleRioAddress(String ip) {
|
||||||
|
try {
|
||||||
|
InetAddress addr = InetAddress.getByName(ip);
|
||||||
|
var address = addr.getAddress();
|
||||||
|
if (address[0] != (byte) (10 & 0xff)) return null;
|
||||||
|
address[3] = (byte) (2 & 0xff);
|
||||||
|
return InetAddress.getByAddress(address).getHostAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void searchForHost(List<String> list, String hostname) {
|
||||||
|
try {
|
||||||
|
logger.info("Looking up " + hostname);
|
||||||
|
InetAddress testAddr = InetAddress.getByName(hostname);
|
||||||
|
logger.info("Pinging " + hostname);
|
||||||
|
var canContact = testAddr.isReachable(500);
|
||||||
|
if (canContact) {
|
||||||
|
logger.info("Was able to connect to " + hostname);
|
||||||
|
if (!list.contains(hostname)) list.add(hostname);
|
||||||
|
} else {
|
||||||
|
logger.info("Unable to reach " + hostname);
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.scripting;
|
package org.photonvision.common.scripting;
|
||||||
|
|
||||||
public enum ScriptCommandType {
|
public enum ScriptCommandType {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.scripting;
|
package org.photonvision.common.scripting;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.scripting;
|
package org.photonvision.common.scripting;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.scripting;
|
package org.photonvision.common.scripting;
|
||||||
|
|
||||||
public enum ScriptEventType {
|
public enum ScriptEventType {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.scripting;
|
package org.photonvision.common.scripting;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
public class MemoryManager {
|
public class MemoryManager {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
public class ReflectionUtils {
|
public class ReflectionUtils {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util;
|
package org.photonvision.common.util;
|
||||||
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.file;
|
package org.photonvision.common.util.file;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.file;
|
package org.photonvision.common.util.file;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.json.JsonReadFeature;
|
import com.fasterxml.jackson.core.json.JsonReadFeature;
|
||||||
@@ -33,7 +34,7 @@ import java.nio.file.Path;
|
|||||||
|
|
||||||
public class JacksonUtils {
|
public class JacksonUtils {
|
||||||
public static <T> void serialize(Path path, T object) throws IOException {
|
public static <T> void serialize(Path path, T object) throws IOException {
|
||||||
serialize(path, object, false);
|
serialize(path, object, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void serialize(Path path, T object, boolean forceSync) throws IOException {
|
public static <T> void serialize(Path path, T object, boolean forceSync) throws IOException {
|
||||||
@@ -79,7 +80,7 @@ public class JacksonUtils {
|
|||||||
|
|
||||||
public static <T> void serialize(Path path, T object, Class<T> ref, StdSerializer<T> serializer)
|
public static <T> void serialize(Path path, T object, Class<T> ref, StdSerializer<T> serializer)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
serialize(path, object, ref, serializer, false);
|
serialize(path, object, ref, serializer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void serialize(
|
public static <T> void serialize(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.file;
|
package org.photonvision.common.util.file;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.java;
|
package org.photonvision.common.util.java;
|
||||||
|
|
||||||
public interface TriConsumer<T, U, V> {
|
public interface TriConsumer<T, U, V> {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.math;
|
package org.photonvision.common.util.math;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -14,9 +14,12 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.math;
|
package org.photonvision.common.util.math;
|
||||||
|
|
||||||
import edu.wpi.first.util.WPIUtilJNI;
|
import edu.wpi.first.util.WPIUtilJNI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MathUtils {
|
public class MathUtils {
|
||||||
MathUtils() {}
|
MathUtils() {}
|
||||||
@@ -63,6 +66,58 @@ public class MathUtils {
|
|||||||
return (int) Math.floor(map((double) value, inMin, inMax, outMin, outMax) + 0.5);
|
return (int) Math.floor(map((double) value, inMin, inMax, outMin, outMax) + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long wpiNanoTime() {
|
||||||
|
return microsToNanos(WPIUtilJNI.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the nTh percentile of a list
|
||||||
|
*
|
||||||
|
* @param list The list to evaluate
|
||||||
|
* @param p The percentile, in [0,100]
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getPercentile(List<Double> list, double p) {
|
||||||
|
if ((p > 100) || (p <= 0)) {
|
||||||
|
throw new IllegalArgumentException("invalid quantile value: " + p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.size() == 0) {
|
||||||
|
return Double.NaN;
|
||||||
|
}
|
||||||
|
if (list.size() == 1) {
|
||||||
|
return list.get(0); // always return single value for n = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort array. We avoid a third copy here by just creating the
|
||||||
|
// list directly.
|
||||||
|
double[] sorted = new double[list.size()];
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
sorted[i] = list.get(i);
|
||||||
|
}
|
||||||
|
Arrays.sort(sorted);
|
||||||
|
|
||||||
|
return evaluateSorted(sorted, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double evaluateSorted(final double[] sorted, final double p) {
|
||||||
|
double n = sorted.length;
|
||||||
|
double pos = p * (n + 1) / 100;
|
||||||
|
double fpos = Math.floor(pos);
|
||||||
|
int intPos = (int) fpos;
|
||||||
|
double dif = pos - fpos;
|
||||||
|
|
||||||
|
if (pos < 1) {
|
||||||
|
return sorted[0];
|
||||||
|
}
|
||||||
|
if (pos >= n) {
|
||||||
|
return sorted[sorted.length - 1];
|
||||||
|
}
|
||||||
|
double lower = sorted[intPos - 1];
|
||||||
|
double upper = sorted[intPos];
|
||||||
|
return lower + dif * (upper - lower);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linearly interpolates between two values.
|
* Linearly interpolates between two values.
|
||||||
*
|
*
|
||||||
@@ -75,8 +130,4 @@ public class MathUtils {
|
|||||||
public static double lerp(double startValue, double endValue, double t) {
|
public static double lerp(double startValue, double endValue, double t) {
|
||||||
return startValue + (endValue - startValue) * t;
|
return startValue + (endValue - startValue) * t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long wpiNanoTime() {
|
|
||||||
return microsToNanos(WPIUtilJNI.now());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.numbers;
|
package org.photonvision.common.util.numbers;
|
||||||
|
|
||||||
import org.opencv.core.Point;
|
import org.opencv.core.Point;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.numbers;
|
package org.photonvision.common.util.numbers;
|
||||||
|
|
||||||
public class IntegerCouple extends NumberCouple<Integer> {
|
public class IntegerCouple extends NumberCouple<Integer> {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.numbers;
|
package org.photonvision.common.util.numbers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.common.util.numbers;
|
package org.photonvision.common.util.numbers;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.raspi;
|
package org.photonvision.raspi;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -85,7 +86,7 @@ public class PicamJNI {
|
|||||||
|
|
||||||
public static boolean isSupported() {
|
public static boolean isSupported() {
|
||||||
return libraryLoaded
|
return libraryLoaded
|
||||||
&& !isVCSMSupported()
|
&& isVCSMSupported()
|
||||||
&& getSensorModel() != SensorModel.Disconnected
|
&& getSensorModel() != SensorModel.Disconnected
|
||||||
&& Platform.isRaspberryPi()
|
&& Platform.isRaspberryPi()
|
||||||
&& (Platform.currentPiVersion == PiVersion.PI_3
|
&& (Platform.currentPiVersion == PiVersion.PI_3
|
||||||
@@ -133,12 +134,18 @@ public class PicamJNI {
|
|||||||
public static native void setThresholds(
|
public static native void setThresholds(
|
||||||
double hL, double sL, double vL, double hU, double sU, double vU);
|
double hL, double sL, double vL, double hU, double sU, double vU);
|
||||||
|
|
||||||
|
public static native void setInvertHue(boolean shouldInvert);
|
||||||
|
|
||||||
public static native boolean setExposure(int exposure);
|
public static native boolean setExposure(int exposure);
|
||||||
|
|
||||||
public static native boolean setBrightness(int brightness);
|
public static native boolean setBrightness(int brightness);
|
||||||
|
|
||||||
|
// This adjusts the analog gain (normalized to 0-100); ignores the digital gain
|
||||||
public static native boolean setGain(int gain);
|
public static native boolean setGain(int gain);
|
||||||
|
|
||||||
|
// Adjusts the auto white balance gains, which are normalized 0-100 in the native code
|
||||||
|
public static native boolean setAwbGain(int red, int blue);
|
||||||
|
|
||||||
public static native boolean setRotation(int rotation);
|
public static native boolean setRotation(int rotation);
|
||||||
|
|
||||||
public static native void setShouldCopyColor(boolean shouldCopyColor);
|
public static native void setShouldCopyColor(boolean shouldCopyColor);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.calibration;
|
package org.photonvision.vision.calibration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.calibration;
|
package org.photonvision.vision.calibration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
public enum CameraQuirk {
|
public enum CameraQuirk {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
public enum CameraType {
|
public enum CameraType {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
import edu.wpi.first.cscore.VideoMode;
|
import edu.wpi.first.cscore.VideoMode;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
import edu.wpi.first.cameraserver.CameraServer;
|
import edu.wpi.first.cameraserver.CameraServer;
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.photonvision.vision.camera;
|
package org.photonvision.vision.camera;
|
||||||
|
|
||||||
import edu.wpi.first.cscore.VideoMode;
|
import edu.wpi.first.cscore.VideoMode;
|
||||||
|
import edu.wpi.first.math.Pair;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.photonvision.common.configuration.CameraConfiguration;
|
import org.photonvision.common.configuration.CameraConfiguration;
|
||||||
import org.photonvision.common.configuration.ConfigManager;
|
import org.photonvision.common.configuration.ConfigManager;
|
||||||
@@ -83,9 +85,10 @@ public class ZeroCopyPicamSource extends VisionSource {
|
|||||||
|
|
||||||
public static class PicamSettables extends VisionSourceSettables {
|
public static class PicamSettables extends VisionSourceSettables {
|
||||||
private FPSRatedVideoMode currentVideoMode;
|
private FPSRatedVideoMode currentVideoMode;
|
||||||
private double lastExposure;
|
private double lastExposure = 50;
|
||||||
private int lastBrightness;
|
private int lastBrightness = 50;
|
||||||
private int lastGain;
|
private int lastGain = 50;
|
||||||
|
private Pair<Integer, Integer> lastAwbGains = new Pair(18, 18);
|
||||||
|
|
||||||
public PicamSettables(CameraConfiguration configuration) {
|
public PicamSettables(CameraConfiguration configuration) {
|
||||||
super(configuration);
|
super(configuration);
|
||||||
@@ -117,9 +120,9 @@ public class ZeroCopyPicamSource extends VisionSource {
|
|||||||
videoModes.put(
|
videoModes.put(
|
||||||
1, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 640, 480, 85, 90, 1));
|
1, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 640, 480, 85, 90, 1));
|
||||||
videoModes.put(
|
videoModes.put(
|
||||||
2, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 960, 720, 45, 60, 1));
|
2, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 960, 720, 45, 49, 0.74));
|
||||||
videoModes.put(
|
videoModes.put(
|
||||||
3, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 1280, 720, 30, 45, 0.92));
|
3, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 1280, 720, 30, 45, 0.91));
|
||||||
videoModes.put(
|
videoModes.put(
|
||||||
4, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 1920, 1080, 15, 20, 0.72));
|
4, new FPSRatedVideoMode(VideoMode.PixelFormat.kUnknown, 1920, 1080, 15, 20, 0.72));
|
||||||
}
|
}
|
||||||
@@ -136,21 +139,38 @@ public class ZeroCopyPicamSource extends VisionSource {
|
|||||||
public void setExposure(double exposure) {
|
public void setExposure(double exposure) {
|
||||||
lastExposure = exposure;
|
lastExposure = exposure;
|
||||||
var failure = PicamJNI.setExposure((int) Math.round(exposure));
|
var failure = PicamJNI.setExposure((int) Math.round(exposure));
|
||||||
if (failure) logger.warn("Couldn't set Pi camera exposure");
|
if (failure) logger.warn("Couldn't set Pi Camera exposure");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBrightness(int brightness) {
|
public void setBrightness(int brightness) {
|
||||||
lastBrightness = brightness;
|
lastBrightness = brightness;
|
||||||
var failure = PicamJNI.setBrightness(brightness);
|
var failure = PicamJNI.setBrightness(brightness);
|
||||||
if (failure) logger.warn("Couldn't set Pi camera brightness");
|
if (failure) logger.warn("Couldn't set Pi Camera brightness");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setGain(int gain) {
|
public void setGain(int gain) {
|
||||||
lastGain = gain;
|
lastGain = gain;
|
||||||
var failure = PicamJNI.setGain(gain);
|
var failure = PicamJNI.setGain(gain);
|
||||||
if (failure) logger.warn("Couldn't set Pi camera gain");
|
if (failure) logger.warn("Couldn't set Pi Camera gain");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRedGain(int red) {
|
||||||
|
lastAwbGains = Pair.of(red, lastAwbGains.getSecond());
|
||||||
|
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlueGain(int blue) {
|
||||||
|
lastAwbGains = Pair.of(lastAwbGains.getFirst(), blue);
|
||||||
|
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAwbGain(int red, int blue) {
|
||||||
|
var failure = PicamJNI.setAwbGain(red, blue);
|
||||||
|
if (failure) logger.warn("Couldn't set Pi Camera AWB gains");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -164,17 +184,18 @@ public class ZeroCopyPicamSource extends VisionSource {
|
|||||||
var failure = PicamJNI.destroyCamera();
|
var failure = PicamJNI.destroyCamera();
|
||||||
if (failure)
|
if (failure)
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Couldn't destroy a zero copy Pi camera while switching video modes");
|
"Couldn't destroy a zero copy Pi Camera while switching video modes");
|
||||||
failure = PicamJNI.createCamera(mode.width, mode.height, mode.fpsActual);
|
failure = PicamJNI.createCamera(mode.width, mode.height, mode.fpsActual);
|
||||||
if (failure)
|
if (failure)
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Couldn't create a zero copy Pi camera while switching video modes");
|
"Couldn't create a zero copy Pi Camera while switching video modes");
|
||||||
|
|
||||||
// We don't store last settings on the native side, and when you change video mode these get
|
// We don't store last settings on the native side, and when you change video mode these get
|
||||||
// reset on MMAL's end
|
// reset on MMAL's end
|
||||||
setExposure(lastExposure);
|
setExposure(lastExposure);
|
||||||
setBrightness(lastBrightness);
|
setBrightness(lastBrightness);
|
||||||
setGain(lastGain);
|
setGain(lastGain);
|
||||||
|
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
|
||||||
|
|
||||||
currentVideoMode = mode;
|
currentVideoMode = mode;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user