### features
- added auto install and update
- added calibration status and accuracy message
- added 2020 loading station pnp model

### bugs
- fixed solve pnp model upload 
- fixed solve pnp draw
This commit is contained in:
Matt
2020-01-28 10:44:52 -08:00
committed by oriagranat9
parent a0b89168b4
commit 515faa182f
28 changed files with 368 additions and 161 deletions

View File

@@ -5,6 +5,12 @@
[9.819867, -17],
[19.625,0]
],
"2020 Loading Station": [
[-3.54,5.5],
[-3.54,-5.5],
[3.54,-5.5],
[3.54,5.5]
],
"2019 Dual Target": [
[-7.75, 3],
[-7.75, -3],

View File

@@ -17,10 +17,14 @@
<mini-map class="miniMapClass" :targets="targets" :horizontal-f-o-v="horizontalFOV"/>
</v-col>
<v-col>
<v-select v-model="selectedModel" :items="FRCtargets" item-text="name" item-value="data" dark color="#4baf62" item-color="green"/>
<v-select v-model="selectedModel" :items="FRCtargets" item-text="name" item-value="data" dark
color="#4baf62" item-color="green"/>
<v-btn small v-if="selectedModel !== null" @click="uploadPremade">Upload Premade</v-btn>
</v-col>
</v-row>
<v-snackbar v-model="snack" top :color="snackbar.color">
<span>{{snackbar.text}}</span>
</v-snackbar>
</div>
</template>
@@ -41,7 +45,12 @@
return {
is3D: false,
selectedModel: null,
FRCtargets: null
FRCtargets: null,
snackbar: {
color: "success",
text: ""
},
snack: false
}
},
methods: {
@@ -57,13 +66,50 @@
});
},
onParse(result) {
this.uploadModel(result.data);
if (result.data.length > 0) {
let data = [];
for (let item of result.data) {
let tmp = [];
tmp.push(Number(item[0]));
tmp.push(Number(item[1]));
if (isNaN(tmp[0]) || isNaN(tmp[1])) {
this.snackbar = {
color: "error",
text: "Error: cvs did parse correctly"
};
this.snack = true;
return;
}
data.push(tmp);
}
this.uploadModel(data);
} else {
this.snackbar = {
color: "error",
text: "Error: cvs did not contain any data"
};
this.snack = true;
}
},
uploadPremade() {
this.uploadModel(this.selectedModel);
},
uploadModel(model) {
this.axios.post("http://" + this.$address + "/api/vision/pnpModel", model);
this.axios.post("http://" + this.$address + "/api/vision/pnpModel", model).then((response) => {
this.snackbar = {
color: "success",
text: "File uploaded successfully"
};
this.snack = true;
}).catch((error) => {
this.snackbar = {
color: "error",
text: "An error occurred"
};
this.snack = true;
})
}
},
computed: {

View File

@@ -11,7 +11,7 @@
<component :is="selectedComponent" @update="$emit('save')"/>
</div>
</v-col>
<v-col class="colsClass" v-show="selectedTab === 1 || selectedTab === 2">
<v-col class="colsClass" v-show="selectedTab === 1">
<div class="videoClass">
<img :src="streamAddress" alt="Camera Stream">
</div>
@@ -34,18 +34,13 @@
data() {
return {
selectedTab: 0,
tabList:[General, Cameras]
}
},
computed: {
selectedComponent: {
get() {
switch (this.selectedTab) {
case 0:
return "General";
case 1:
return "Cameras";
}
return "";
return this.tabList[this.selectedTab];
}
},
streamAddress: {

View File

@@ -48,9 +48,21 @@
<span>Snapshot Amount: {{snapshotAmount}}</span>
</v-col>
</v-row>
<div v-if="isCalibrating">
<v-checkbox v-model="isAdvanced" label="Advanced Menu" dark/>
<div v-if="isAdvanced">
<CVslider name="Exposure" v-model="pipeline.exposure" :min="0" :max="100"
@input="handleData('exposure')"/>
<CVslider name="Brightness" v-model="pipeline.brightness" :min="0" :max="100"
@input="handleData('brightness')"/>
<CVslider name="Gain" v-if="pipeline.gain !== -1" v-model="pipeline.gain" :min="0" :max="100"
@input="handleData('gain')"/>
<CVselect name="FPS" v-model="pipeline.videoModeIndex" :list="stringFpsList" @input="changeFps"/>
</div>
</div>
</div>
<v-snackbar v-model="snack">
<span>Calibration Failed</span>
<v-snackbar v-model="snack" top :color="snackbar.color">
<span>{{snackbar.text}}</span>
</v-snackbar>
</div>
</template>
@@ -58,12 +70,14 @@
<script>
import CVselect from '../../components/cv-select'
import CVnumberinput from '../../components/cv-number-input'
import CVslider from '../../components/cv-slider'
export default {
name: 'CameraSettings',
components: {
CVselect,
CVnumberinput
CVnumberinput,
CVslider
},
data() {
return {
@@ -77,13 +91,24 @@
text: "Cancel Calibration",
color: "red"
},
snackbar: {
color: "success",
text: ""
},
squareSize: 1.0,
snapshotAmount: 0,
hasEnough: false,
snack: false
snack: false,
isAdvanced: false
}
},
methods: {
handleData(val) {
this.handleInput(val, this.pipeline[val]);
},
changeFps() {
this.handleInput('videoModeIndex', this.filteredFpsList[this.pipeline['videoModeIndex']]['actualIndex']);
},
sendCameraSettings() {
const self = this;
this.axios.post("http://" + this.$address + "/api/settings/camera", this.cameraSettings).then(
@@ -129,9 +154,13 @@
let connection_string = "/api/settings/endCalibration";
let data = {};
data['squareSize'] = this.squareSize;
self.axios.post("http://" + this.$address + connection_string, data).then(
function (response) {
if (response.status === 500) {
self.axios.post("http://" + this.$address + connection_string, data).then((response) => {
if (response.status === 200) {
self.snackbar = {
color: "success",
text: "calibration successful. \n" +
"accuracy: " + response.data['accuracy'].toFixed(5)
};
self.snack = true;
}
self.isCalibrating = false;
@@ -141,7 +170,19 @@
self.cancellationModeButton.text = "Cancel Calibration";
self.cancellationModeButton.color = "red";
}
);
).catch(() => {
self.snackbar = {
color: "error",
text: "calibration failed"
};
self.snack = true;
self.isCalibrating = false;
self.hasEnough = false;
self.snapshotAmount = 0;
self.calibrationModeButton.text = "Start Calibration";
self.cancellationModeButton.text = "Cancel Calibration";
self.cancellationModeButton.color = "red";
});
}
},
computed: {
@@ -186,6 +227,27 @@
return tmp_list;
}
},
filteredFpsList() {
let selectedRes = this.$store.state.resolutionList[this.resolutionIndex];
let tmpList = [];
for (let i in this.$store.state.resolutionList) {
let res = JSON.parse(JSON.stringify(this.$store.state.resolutionList[i]));
if (!tmpList.some(e => e['fps'] === res['fps'])) {
if (res.width === selectedRes.width && res.height === selectedRes.height) {
res['actualIndex'] = parseInt(i);
tmpList.push(res);
}
}
}
return tmpList;
},
stringFpsList() {
let tmp = [];
for (let i of this.filteredFpsList) {
tmp.push(i['fps']);
}
return tmp;
},
stringResolutionList: {
get() {
let tmp = [];
@@ -203,7 +265,9 @@
this.$store.commit('cameraSettings', value);
}
},
pipeline() {
return this.$store.state.pipeline
}
}
}
</script>

View File

@@ -1,5 +1,9 @@
<template>
<div>
<div style="margin-top: 15px">
<span>General Settings:</span>
<v-divider color="white"></v-divider>
</div>
<CVnumberinput v-model="settings.teamNumber" name="Team Number"/>
<CVradio v-model="settings.connectionType" :list="['DHCP','Static']"/>
<v-divider color="white"/>
@@ -9,6 +13,30 @@
<v-divider color="white"/>
<CVinput name="Hostname" v-model="settings.hostname"/>
<v-btn style="margin-top:10px" small color="#4baf62" @click="sendGeneralSettings">Save General Settings</v-btn>
<div style="margin-top: 20px">
<span>Install or Update:</span>
<v-divider color="white"></v-divider>
</div>
<div v-if="!isLoading">
<v-row dense align="center">
<v-col :cols="3">
<span>Choose a newer version: </span>
</v-col>
<v-col :cols="6">
<v-file-input accept=".jar" dark v-model="file"></v-file-input>
</v-col>
</v-row>
<v-btn small @click="installOrUpdate">{{fileUploadText}}</v-btn>
</div>
<div v-else style="text-align: center; margin-top: 20px">
<v-progress-circular color="white" :indeterminate="true" size="32"
width="4"></v-progress-circular>
<br>
<span>Please wait this may take a while</span>
</div>
<v-snackbar v-model="snack" top :color="snackbar.color">
<span>{{snackbar.text}}</span>
</v-snackbar>
</div>
</template>
@@ -25,26 +53,64 @@
CVinput
},
data() {
return {}
return {
file: undefined,
snackbar: {
color: "success",
text: ""
},
snack: false,
isLoading: false
}
},
methods: {
sendGeneralSettings() {
const self = this;
this.axios.post("http://" + this.$address + "/api/settings/general", this.settings).then(
function (response) {
if (response.status === 200){
if (response.status === 200) {
self.$store.state.saveBar = true;
}
}
)
},
installOrUpdate() {
let formData = new FormData();
formData.append('file', this.file);
if (this.file !== undefined) {
this.isLoading = true;
}
this.axios.post("http://" + this.$address + "/api/install", formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(() => {
this.snackbar = {
color: "success",
text: "Installation successful"
};
this.isLoading = false;
this.snack = true;
}).catch(error => {
this.snackbar = {
color: "error",
text: error.response.data
};
this.isLoading = false;
this.snack = true;
})
}
},
computed: {
isDisabled() {
if (this.settings.connectionType === 0) {
return true;
fileUploadText() {
if (this.file !== undefined) {
return "Install and update"
} else {
return "Install current version"
}
return false;
},
isDisabled() {
return this.settings.connectionType === 0;
},
settings: {
get() {