Compare commits

...

2 Commits

Author SHA1 Message Date
Vasista Vovveti
553bed32b5 [photonlib] Target macOS 10.14 (#402) 2022-01-16 15:04:03 -05:00
Declan
6c91feaf3f Make small cosmetic improvments across the user interface (#396) 2022-01-16 11:25:37 -05:00
13 changed files with 366 additions and 317 deletions

View File

@@ -151,6 +151,8 @@ jobs:
# Building photonlib
photonlib-build-host:
env:
MACOSX_DEPLOYMENT_TARGET: 10.14
strategy:
fail-fast: false
matrix:

View File

@@ -87,31 +87,56 @@
</v-icon>
</v-list-item-icon>
<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>
<div style="position: absolute; bottom: 0; left: 0;">
<v-list-item>
<v-list-item-icon>
<v-icon v-if="$store.state.settings.networkSettings.runNTServer">mdi-server</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-icon v-if="$store.state.settings.networkSettings.runNTServer">
mdi-server
</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-content>
<v-list-item-title class="text-wrap" v-if="$store.state.settings.networkSettings.runNTServer">
NetworkTables server running for {{$store.state.ntConnectionInfo.clients ? $store.state.ntConnectionInfo.clients : 'zero'}} clients!
<v-list-item-title
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 class="text-wrap" v-else-if="$store.state.ntConnectionInfo.connected && $store.state.backendConnected">
Robot connected! {{$store.state.ntConnectionInfo.address}}
<v-list-item-title
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 class="text-wrap" v-else>
<v-list-item-title
v-else
class="text-wrap"
>
Not connected to robot!
</v-list-item-title>
<a
href="/#/settings"
style="color:#FFD843"
>{{"Team: " + $store.state.settings.networkSettings.teamNumber}}</a>
<router-link
v-if="!$store.state.settings.networkSettings.runNTServer"
to="settings"
class="accent--text"
@click="switchToSettingsTab"
>
Team number is {{ $store.state.settings.networkSettings.teamNumber }}
</router-link>
</v-list-item-content>
</v-list-item>
@@ -121,9 +146,9 @@
mdi-wifi
</v-icon>
<v-icon
v-else
class="pulse"
style="border-radius: 100%;"
v-else
class="pulse"
style="border-radius: 100%;"
>
mdi-wifi-off
</v-icon>
@@ -135,7 +160,6 @@
</v-list-item-content>
</v-list-item>
</div>
</v-list>
</v-navigation-drawer>
<v-main>
@@ -159,23 +183,27 @@
<logs />
</v-dialog>
<v-dialog
v-model="needsTeamNumberSet"
width="500"
dark
persistent
v-model="needsTeamNumberSet"
width="500"
dark
persistent
>
<v-card
dark
color="primary"
flat
dark
color="primary"
flat
>
<v-card-title>No team number set!</v-card-title>
<v-card-text>
PhotonVision cannot connect to your robot! Please
<a
href="/#/settings"
style="color:#FFD843"
>head to the settings page</a> and set your team number.
<router-link
to="settings"
class="accent--text"
@click="switchToSettingsTab"
>
vist the settings tab
</router-link>
and set your team number.
</v-card-text>
</v-card>
</v-dialog>
@@ -219,12 +247,6 @@ export default {
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() {
document.addEventListener("keydown", e => {
@@ -319,8 +341,7 @@ export default {
}
}
this.previouslySelectedIndices = null;
}
,
},
switchToSettingsTab() {
this.axios.post('http://' + this.$address + '/api/sendMetrics', {})
}

View File

@@ -13,7 +13,7 @@
export default {
name: "CvImage",
// 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() {
return {
seed: 1.0,
@@ -37,7 +37,9 @@
if (this.$vuetify.breakpoint.xl) {
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;
}

View File

@@ -1,28 +1,46 @@
<template>
<div>
<v-radio-group
v-model="localValue"
row
dark
:mandatory="true"
<v-row
dense
align="center"
>
<v-radio
v-for="(name,index) in list"
:key="index"
color="#ffd843"
:label="name"
:value="index"
:disabled="disabled"
/>
</v-radio-group>
<v-col :cols="12 - (inputCols || 8)">
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col :cols="inputCols || 8">
<v-radio-group
v-model="localValue"
row
dark
:mandatory="true"
>
<v-radio
v-for="(name,index) in list"
:key="index"
color="#ffd843"
:label="name"
:value="index"
:disabled="disabled"
/>
</v-radio-group>
</v-col>
</v-row>
</div>
</template>
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: 'Radio',
components: {
TooltippedLabel
},
// eslint-disable-next-line vue/require-prop-types
props: ['value', 'list', 'disabled'],
props: ['name', 'value', 'list', 'disabled', 'inputCols', 'tooltip'],
data() {
return {}
},

View File

@@ -3,7 +3,7 @@
<v-tooltip
:disabled="tooltip === undefined"
right
open-delay="600"
open-delay="300"
>
<template v-slot:activator="{ on, attrs }">
<span

View File

@@ -1,11 +1,15 @@
<template>
<div>
<v-row align="center">
<v-row
align="center"
class="pl-6"
>
<v-col
cols="10"
md="5"
lg="10"
class="pt-0 pb-0 pl-6"
no-gutters
class="pa-0"
>
<CVselect
v-if="isCameraNameEdit === false"
@@ -59,7 +63,8 @@
cols="10"
md="5"
lg="10"
class="pt-0 pb-0 pl-6"
no-gutters
class="pa-0"
>
<CVselect
v-model="currentPipelineIndex"
@@ -139,14 +144,16 @@
<v-col
v-if="currentPipelineType >= 0"
cols="10"
md="5"
md="11"
lg="10"
class="pt-0 pb-0 pl-6"
no-gutters
class="pa-0"
>
<CVselect
v-model="currentPipelineType"
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)"
/>
</v-col>
@@ -176,12 +183,6 @@
name="Name"
:error-message="checkPipelineName"
/>
<!-- <CVselect-->
<!-- v-model="currentPipelineType"-->
<!-- name="Pipeline Type"-->
<!-- :list="['Reflective', 'Shape']"-->
<!-- :disabled="true"-->
<!-- />-->
</v-card-text>
<v-divider />
<v-card-actions>
@@ -276,12 +277,12 @@ export default {
for (let cam in this.cameraList) {
if (this.cameraList.hasOwnProperty(cam)) {
if (this.newCameraName === this.cameraList[cam]) {
return "A camera by that name already Exists"
return "A camera by that name already exists"
}
}
}
} else {
return "A camera name can only contain letters, numbers and spaces"
return "A camera name can only contain letters, numbers, and spaces"
}
}
return "";

View File

@@ -20,8 +20,8 @@
v-model="currentCameraIndex"
name="Camera"
:list="$store.getters.cameraList"
@input="handleInput('currentCamera',currentCameraIndex)"
:select-cols="$vuetify.breakpoint.mdAndUp ? 10 : 7"
@input="handleInput('currentCamera',currentCameraIndex)"
/>
<CVnumberinput
v-model="cameraSettings.fov"

View File

@@ -30,7 +30,7 @@
:class="fpsTooLow ? 'ml-2 mt-1' : 'mt-2'"
x-small
label
:color="fpsTooLow ? 'red' : 'transparent'"
:color="fpsTooLow ? 'error' : 'transparent'"
:text-color="fpsTooLow ? 'white' : 'grey'"
>
<span class="pr-1">{{ Math.round($store.state.pipelineResults.fps) }}&nbsp;FPS &ndash;</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>stop viewing the color stream for better performance</span>
</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-model="driverMode"
label="Driver Mode"
@@ -71,7 +64,8 @@
:disconnected="!$store.state.backendConnected"
scale="100"
: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'"
:alt="'Stream' + idx"
:color-picking="$store.state.colorPicking && idx === 0"
@@ -90,23 +84,18 @@
>
<v-card
color="primary"
class="mt-3"
>
<!-- <v-btn @click="onCamNameChange">-->
<!-- Reload-->
<!-- </v-btn>-->
<camera-and-pipeline-select @camera-name-changed="reloadStreams" />
</v-card>
<v-card
:disabled="$store.getters.isDriverMode || $store.state.colorPicking"
class="mt-6 mb-3"
class="mt-3"
color="primary"
>
<v-row
align="center"
class="pl-3 pr-3"
>
<!-- -->
<v-col lg="12">
<p style="color: white;">
Processing mode:
@@ -206,21 +195,24 @@
</v-col>
</v-row>
</v-container>
<!-- snack bar and modal -->
<v-snackbar
v-model="snackbar"
:timeout="3000"
top
v-model="showNTWarning"
color="error"
timeout="-1"
top
>
<span style="color:#000">Can not remove the only pipeline!</span>
<v-btn
color="black"
text
@click="snackbar = false"
>
Close
</v-btn>
{{ $store.state.settings.networkSettings.runNTServer ?
"NetworkTables server enabled! PhotonLib may not work." :
"NetworkTables not connected! Are you on a network with a robot?" }}
<template v-slot:action>
<v-btn
text
@click="hideNTWarning = true"
>
Hide
</v-btn>
</template>
</v-snackbar>
<v-dialog
@@ -286,10 +278,10 @@ export default {
data() {
return {
selectedTabsData: [0, 0, 0, 0],
snackbar: false,
counterData: 0,
dialog: false,
processingModeOverride: false
processingModeOverride: false,
hideNTWarning: false,
}
},
computed: {
@@ -434,7 +426,12 @@ export default {
// return this.$store.state.ntConnectionInfo.connected && this.$store.state.backendConnected;
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() {
this.$store.state.connectedCallbacks.push(this.reloadStreams)

View File

@@ -1,140 +1,141 @@
<template>
<div>
<CVrangeSlider
v-model="contourArea"
name="Area"
min="0"
max="100"
step="0.1"
@input="handlePipelineData('contourArea')"
v-model="contourArea"
name="Area"
min="0"
max="100"
step="0.1"
@input="handlePipelineData('contourArea')"
/>
<CVrangeSlider
v-model="contourRatio"
v-if="currentPipelineType() !== 3"
name="Ratio (W/H)"
tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
min="0"
max="100"
step="0.1"
@input="handlePipelineData('contourRatio')"
v-if="currentPipelineType() !== 3"
v-model="contourRatio"
name="Ratio (W/H)"
tooltip="Min and max ratio between the width and height of a contour's bounding rectangle"
min="0"
max="100"
step="0.1"
@input="handlePipelineData('contourRatio')"
/>
<CVrangeSlider
v-model="contourFullness"
v-if="currentPipelineType() !== 3"
name="Fullness"
tooltip="Min and max ratio between a contour's area and its bounding rectangle"
min="0"
max="100"
@input="handlePipelineData('contourFullness')"
v-if="currentPipelineType() !== 3"
v-model="contourFullness"
name="Fullness"
tooltip="Min and max ratio between a contour's area and its bounding rectangle"
min="0"
max="100"
@input="handlePipelineData('contourFullness')"
/>
<CVrangeSlider
v-model="contourPerimeter"
v-if="currentPipelineType() === 3"
name="Perimeter"
tooltip="Min and max perimeter of the shape, in pixels"
min="0"
max="4000"
@input="handlePipelineData('contourPerimeter')"
v-if="currentPipelineType() === 3"
v-model="contourPerimeter"
name="Perimeter"
tooltip="Min and max perimeter of the shape, in pixels"
min="0"
max="4000"
@input="handlePipelineData('contourPerimeter')"
/>
<CVslider
v-model="contourSpecklePercentage"
name="Speckle Rejection"
tooltip="Rejects contours whose average area is less than the given percentage of the average area of all the other contours"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('contourSpecklePercentage')"
v-model="contourSpecklePercentage"
name="Speckle Rejection"
tooltip="Rejects contours whose average area is less than the given percentage of the average area of all the other contours"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('contourSpecklePercentage')"
/>
<template v-if="currentPipelineType() !== 3">
<CVselect
v-model="contourGroupingMode"
name="Target Grouping"
tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
:select-cols="largeBox"
:list="['Single','Dual','2orMore']"
@input="handlePipelineData('contourGroupingMode')"
v-model="contourGroupingMode"
name="Target Grouping"
tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
:select-cols="largeBox"
:list="['Single','Dual','2orMore']"
@input="handlePipelineData('contourGroupingMode')"
/>
<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')"
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>
<!-- If we arent not a shape, we are a shape-->
<template v-else>
<v-divider class="mt-3"/>
<v-divider class="mt-3" />
<CVselect
v-model="contourShape"
name="Target Shape"
tooltip="The shape of targets to look for"
:select-cols="largeBox"
:list="['Circle', 'Polygon', 'Triangle', 'Quadrilateral']"
@input="handlePipelineData('contourShape')"
v-model="contourShape"
name="Target Shape"
tooltip="The shape of targets to look for"
:select-cols="largeBox"
:list="['Circle', 'Polygon', 'Triangle', 'Quadrilateral']"
@input="handlePipelineData('contourShape')"
/>
<!-- Accuracy % is only for polygons-->
<CVslider
v-model="accuracyPercentage"
:disabled="currentPipelineSettings().contourShape < 1"
name="Shape Simplification"
tooltip="How much we should simply the input contour before checking how many sides it has"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('accuracyPercentage')"
v-model="accuracyPercentage"
:disabled="currentPipelineSettings().contourShape < 1"
name="Shape Simplification"
tooltip="How much we should simply the input contour before checking how many sides it has"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('accuracyPercentage')"
/>
<!-- Similarly, the threshold is only for circles -->
<CVslider
v-model="circleDetectThreshold"
:disabled="currentPipelineSettings().contourShape !== 0"
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"
min="1"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('circleDetectThreshold')"
v-model="circleDetectThreshold"
:disabled="currentPipelineSettings().contourShape !== 0"
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"
min="1"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('circleDetectThreshold')"
/>
<CVrangeSlider
v-model="contourRadius"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Radius"
min="0"
max="100"
step="1"
@input="handlePipelineData('contourRadius')"
v-model="contourRadius"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Radius"
min="0"
max="100"
step="1"
label-cols="3"
@input="handlePipelineData('contourRadius')"
/>
<CVslider
v-model="maxCannyThresh"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Max Canny Threshold"
min="1"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('maxCannyThresh')"
v-model="maxCannyThresh"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Max Canny Threshold"
min="1"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('maxCannyThresh')"
/>
<CVslider
v-model="circleAccuracy"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Circle Accuracy"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('circleAccuracy')"
v-model="circleAccuracy"
:disabled="currentPipelineSettings().contourShape !== 0"
name="Circle Accuracy"
min="0"
max="100"
:slider-cols="largeBox"
@input="handlePipelineData('circleAccuracy')"
/>
<v-divider class="mt-3"/>
<v-divider class="mt-3" />
</template>
<CVselect
v-model="contourSortMode"
name="Target Sort"
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
:select-cols="largeBox"
:list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Centermost']"
@input="handlePipelineData('contourSortMode')"
@rollback="e => rollback('contourSortMode', e)"
v-model="contourSortMode"
name="Target Sort"
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
:select-cols="largeBox"
:list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Centermost']"
@input="handlePipelineData('contourSortMode')"
@rollback="e => rollback('contourSortMode', e)"
/>
</div>
</template>

View File

@@ -1,8 +1,5 @@
<template>
<div>
<span class="white--text">Target Manipulation</span>
<v-divider class="mt-2" />
<CVselect
v-model="contourTargetOffsetPointEdge"
name="Target Offset Point"
@@ -31,8 +28,7 @@
@rollback="e=> rollback('outputShowMultipleTargets', e)"
/>
<span class="white--text">Robot Offset</span>
<v-divider class="mt-2" />
<v-divider />
<CVselect
v-model="offsetRobotOffsetMode"
name="Robot Offset Mode"

View File

@@ -1,66 +1,65 @@
<template>
<div>
<CVrangeSlider
v-model="hsvHue"
name="Hue"
tooltip="Describes color"
:min="0"
:max="180"
@input="handlePipelineData('hsvHue')"
@rollback="e => rollback('hue',e)"
v-model="hsvHue"
name="Hue"
tooltip="Describes color"
:min="0"
:max="180"
@input="handlePipelineData('hsvHue')"
@rollback="e => rollback('hue',e)"
/>
<CVrangeSlider
v-model="hsvSaturation"
name="Saturation"
tooltip="Describes colorfulness; the smaller this value the 'whiter' the color becomes"
:min="0"
:max="255"
@input="handlePipelineData('hsvSaturation')"
@rollback="e => rollback('saturation',e)"
v-model="hsvSaturation"
name="Saturation"
tooltip="Describes colorfulness; the smaller this value the 'whiter' the color becomes"
:min="0"
:max="255"
@input="handlePipelineData('hsvSaturation')"
@rollback="e => rollback('saturation',e)"
/>
<CVrangeSlider
v-model="hsvValue"
name="Value"
tooltip="Describes lightness; the smaller this value the 'blacker' the color becomes"
:min="0"
:max="255"
@input="handlePipelineData('hsvValue')"
@rollback="e => rollback('value',e)"
v-model="hsvValue"
name="Value"
tooltip="Describes lightness; the smaller this value the 'blacker' the color becomes"
:min="0"
:max="255"
@input="handlePipelineData('hsvValue')"
@rollback="e => rollback('value',e)"
/>
<template v-if="this.currentPipelineType() === 3">
<template v-if="currentPipelineType() === 3">
<CVSwitch
v-model="erode"
name="Erode"
tooltip="Removes pixels around the edges of white areas in the thresholded image"
@input="handlePipelineData('erode')"
@rollback="e => rollback('erode',e)"
v-model="erode"
name="Erode"
tooltip="Removes pixels around the edges of white areas in the thresholded image"
@input="handlePipelineData('erode')"
@rollback="e => rollback('erode',e)"
/>
<CVSwitch
v-model="dilate"
class="mb-0"
name="Dilate"
tooltip="Adds pixels around the edges of white areas in the thresholded image"
@input="handlePipelineData('dilate')"
@rollback="e => rollback('dilate',e)"
v-model="dilate"
class="mb-0"
name="Dilate"
tooltip="Adds pixels around the edges of white areas in the thresholded image"
@input="handlePipelineData('dilate')"
@rollback="e => rollback('dilate',e)"
/>
</template>
<v-divider class="mb-3 mt-3"/>
<div class="pt-3 white--text">
Color Picker
</div>
<v-divider
class="mt-3"
class="mt-3"
/>
<v-row
justify="center"
class="mt-3 mb-3"
justify="center"
class="mt-3 mb-3"
>
<template v-if="!$store.state.colorPicking">
<v-btn
color="accent"
class="ma-2 black--text"
small
@click="setFunction(3)"
color="accent"
class="ma-2 black--text"
small
@click="setFunction(3)"
>
<v-icon left>
mdi-minus
@@ -68,10 +67,10 @@
Shrink Range
</v-btn>
<v-btn
color="accent"
class="ma-2 black--text"
small
@click="setFunction(1)"
color="accent"
class="ma-2 black--text"
small
@click="setFunction(1)"
>
<v-icon left>
mdi-plus-minus
@@ -79,10 +78,10 @@
Set To Average
</v-btn>
<v-btn
color="accent"
class="ma-2 black--text"
small
@click="setFunction(2)"
color="accent"
class="ma-2 black--text"
small
@click="setFunction(2)"
>
<v-icon left>
mdi-plus
@@ -92,16 +91,17 @@
</template>
<template v-else>
<v-btn
color="accent"
class="ma-2 black--text"
style="width: 30%;"
small
@click="setFunction(0)"
color="accent"
class="ma-2 black--text"
style="width: 30%;"
small
@click="setFunction(0)"
>
Cancel
</v-btn>
</template>
</v-row>
<v-divider class="mb-3" />
</div>
</template>

View File

@@ -143,7 +143,7 @@
<v-icon left>
mdi-restart
</v-icon>
Restart Photon
Restart PhotonVision
</v-btn>
</v-col>
<v-col
@@ -155,7 +155,7 @@
@click="restartDevice()"
>
<v-icon left>
mdi-restart
mdi-restart-alert
</v-icon>
Restart Device
</v-btn>

View File

@@ -10,46 +10,52 @@
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']"
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">
<span class="text-wrap">
Team number not set! NetworkTables cannot connect.
</span>
</v-chip>
<v-banner
v-show="(teamNumber < 1 || teamNumber > 10000) && !runNTServer"
rounded
color="red"
text-color="white"
>
Team number is unset or invalid. NetworkTables will not be able to connect.
</v-banner>
<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']"
:disabled="!$store.state.settings.networkSettings.supported"
/>
<template v-if="!isDHCP">
<CVinput
v-model="staticIp"
:input-cols="inputCols"
:rules="[v => isIPv4(v) || 'Invalid IPv4 address']"
name="IP"
/>
</template>
<CVinput
v-if="!isDHCP"
v-model="staticIp"
:input-cols="inputCols"
:rules="[v => isIPv4(v) || 'Invalid IPv4 address']"
name="IP"
/>
<CVinput
v-model="hostname"
:input-cols="inputCols"
:rules="[v => isHostname(v) || 'Invalid hostname']"
name="Hostname"
/>
Advanced
<v-divider/>
<CVSwitch
v-model="runNTServer"
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."
class="mt-3 mb-3"
:text-cols="$vuetify.breakpoint.mdAndUp ? undefined : 7"
v-model="runNTServer"
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."
class="mt-3 mb-3"
:text-cols="$vuetify.breakpoint.mdAndUp ? undefined : 5"
/>
<v-chip label color="red" text-color="white" v-if="runNTServer">
<span>
Disable this switch if you're on a robot! Photonlib will NOT work.
</span>
</v-chip>
<v-banner
v-show="runNTServer"
rounded
color="red"
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-btn
color="accent"
@@ -60,55 +66,60 @@
>
Save
</v-btn>
<v-divider class="mt-4 mb-4"/>
<v-divider class="mt-4 mb-4" />
<v-row>
<v-col cols="12" sm="6">
<v-col
cols="12"
sm="6"
>
<v-simple-table
fixed-header
height="100%"
dense
fixed-header
height="100%"
dense
>
<template v-slot:default>
<thead style="font-size: 1.25rem;">
<tr>
<th>
Device IPs
</th>
</tr>
<tr>
<th>
Device IPs
</th>
</tr>
</thead>
<tbody>
<tr
<tr
v-for="(value, index) in $store.state.ntConnectionInfo.deviceips"
:key="index"
>
<td>{{ value }}</td>
</tr>
>
<td>{{ value }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</v-col>
<v-col cols="12" sm="6">
<v-col
cols="12"
sm="6"
>
<v-simple-table
fixed-header
height="100%"
dense
fixed-header
height="100%"
dense
>
<template v-slot:default>
<thead style="font-size: 1.25rem;">
<tr>
<th>
Possible RoboRIOs
</th>
</tr>
<tr>
<th>
Possible RoboRIOs
</th>
</tr>
</thead>
<tbody>
<tr
<tr
v-for="(value, index) in $store.state.ntConnectionInfo.possibleRios"
:key="index"
>
<td>{{ value }}</td>
</tr>
>
<td>{{ value }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
@@ -150,7 +161,7 @@ export default {
},
computed: {
inputCols() {
return this.$vuetify.breakpoint.smAndUp ? 10 : 7;
return this.$vuetify.breakpoint.mdAndUp ? 10 : 7;
},
isDHCP() {
return this.settings.connectionType === 0;