mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-21 01:01:41 +00:00
* Rebase solvePNP on master * added 3D tab minimap and csv reader * More solvePNP * Create draw pipe for pnp data * SolvePNP piping work * Move sorting into solvepnppipe * Create calibration pipeline * Update CalibrateSolvePNPPipeline.java * add camera tilt angle * Add calibration slider and snapshot button to 3D view * Mirror updates in the socket handler * add 3d calibration mode to the pipeline manager * created calibration functions in ui and backend * Start plumbing calibration * Add snapshot and other handling to the RequestHandler * added select resolution before starting calibration * Rename solvePNPPipe to bounding box solve pnp pipe * Update BoundingBoxSolvePNPPipe.java * Add Mat serializer and CameraCalibrationConfig * Begun calibration saving, fixed UI/Backend snapshot count mismatch * Add (unplumbed) option to set checkerboard size This will allow users to change the units their calibration is in * Create chessboard.png * Fix calibration NPE * changed string serialization to a json send * bug fixed cancellation button * Fix spelling of snapshot in 3d.vue * Plumb resolution change * Set resolution during config, start on config serialization * Update .gitignore * Config fixes * Start transition away from cvpipeline3d * fix NPE on uncalibrated cameras * clear list on fail * Fix video mode index error * ignore getters in camera calibration config * Create json constructor for jsonmat * get solvePNP mostly returning sane values * Fix solvePNP bug and add unit test * FIx calibration mat truncation * added capture amount model upload and minimap data * Standardize on meters in calibration and bounding box * fix json out of bounds and handle null calibration more gracefully * don't put text on calibrate image, go back to inches * convert distance to meters this means calibration will need to be in inches * Actually save raw contor * Update GroupContoursPipe.java * Add all calibration return to camera capture * hard code 2019 target * bugfixed draw2d added fail calib popup, merge end and cancel added the res index to the calib start * Clarify error message and draw more fancy rectangles * Cleanup memory in solvepnp * re did minimap component * fix npe if left/right is null * remove references to 2d * try-catch running the current pipeline * Add method to find corners using the harris corner detector * Possibly fix left/right missmatch * Fix 3D Tab error * FIx file permissions, mat serializer adjustments * fixed mini map for field coordinates * mini map changes fov * Update SolvePNPPipe.java * get rid of target corners * some memory leak fixes * fixed mini map location * added position under minimap * changed player fov look * put all targets in the web send * re did target send to ui added target tables, bugfix calibration * fixed y position * Add tilt angle to capture properties * maybe fix y axis in minimap * Add square size to onCalibrationEnding * Possibly add square size to UI * fix NPE with pitch * Fix bug with sending multiple targets * Only instantiate 3d stuff if we are in 3d mode * Fix array list exceptions * Fix bug in sort contors list was truncated too early * added download chess, tilt setting and ordinal tilt, * added square size connection * removed unused code * Update pom version to 2.1-RELEASE * Send camera calibrations to UI * Stream pose list to a LIst * Only stream necessary parts of the aux list entry * Make broadcastMessage synchronized to prevent ConcurrentModificationExceptions * added fps counter changed squaresize steps bug fixes in tables * bugfix camera settings cam wont change Authored-by: oriagranat9 <oriagranat9@gmail.com>
165 lines
5.7 KiB
Vue
165 lines
5.7 KiB
Vue
<template>
|
|
<div>
|
|
<v-row style="width: 400px;" align="center">
|
|
<canvas id="canvasId" width="800" height="800"/>
|
|
</v-row>
|
|
<v-row style="width: 400px;" align="center" justify="middle">
|
|
<v-simple-table
|
|
style="text-align: center;background-color: transparent; display: block;margin: auto"
|
|
dense dark>
|
|
<template v-slot:default>
|
|
<thead>
|
|
<tr>
|
|
<th class="text-center">Target</th>
|
|
<th class="text-center">X</th>
|
|
<th class="text-center">Y</th>
|
|
<th class="text-center">Angle</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="(target, index) in targets" :key="index">
|
|
<td>{{ index}}</td>
|
|
<td>{{ target.pose.translation.x.toFixed(2) }}</td>
|
|
<td>{{ target.pose.translation.y.toFixed(2) }}</td>
|
|
<td>{{ target.pose.rotation.radians.toFixed(2) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</template>
|
|
</v-simple-table>
|
|
</v-row>
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: "MiniMap",
|
|
props: {
|
|
targets: Array,
|
|
horizontalFOV: Number
|
|
},
|
|
data() {
|
|
return {
|
|
ctx: undefined,
|
|
canvas: undefined,
|
|
x: 0,
|
|
y: 0,
|
|
targetWidth: 40,
|
|
targetHeight: 6
|
|
}
|
|
},
|
|
watch: {
|
|
targets: {
|
|
deep: true,
|
|
handler() {
|
|
this.draw();
|
|
}
|
|
},
|
|
horizontalFOV() {
|
|
this.draw();
|
|
}
|
|
},
|
|
methods: {
|
|
draw() {
|
|
this.clearBoard();
|
|
this.drawPlayer();
|
|
for (let index in this.targets) {
|
|
this.drawTarget(index, this.targets[index].pose);
|
|
}
|
|
},
|
|
drawTarget(index, target) {
|
|
// first save the untranslated/unrotated context
|
|
let x = 800 - (160 * target.translation.x); // getting meters as pixels
|
|
let y = 400 - (160 * target.translation.y);
|
|
this.ctx.save();
|
|
this.ctx.beginPath();
|
|
// move the rotation point to the center of the rect
|
|
this.ctx.translate(y + this.targetWidth / 2, x + this.targetHeight / 2); // wpi lib makes x forward and back and y left to right
|
|
// rotate the rect
|
|
this.ctx.rotate(target.rotation.radians);
|
|
|
|
// draw the rect on the transformed context
|
|
// Note: after transforming [0,0] is visually [x,y]
|
|
// so the rect needs to be offset accordingly when drawn
|
|
this.ctx.rect(-this.targetWidth / 2, -this.targetHeight / 2, this.targetWidth, this.targetHeight);
|
|
|
|
this.ctx.fillStyle = "#01a209";
|
|
this.ctx.fill();
|
|
|
|
// restore the context to its untranslated/unrotated state
|
|
this.ctx.restore();
|
|
this.ctx.fillStyle = "whitesmoke";
|
|
this.ctx.beginPath();
|
|
this.ctx.arc(y + this.targetWidth / 2, x + this.targetHeight / 2, 3, 0, 2 * Math.PI, true);
|
|
this.ctx.fill();
|
|
this.ctx.fillText(index, y - 30, x - 5);
|
|
|
|
},
|
|
drawPlayer() {
|
|
this.ctx.beginPath();
|
|
this.ctx.moveTo(400, 820);
|
|
this.ctx.lineTo(400 + this.hLen, 650);
|
|
this.ctx.lineTo(400 - this.hLen, 650);
|
|
this.ctx.closePath();
|
|
this.ctx.fillStyle = this.grad;
|
|
this.ctx.fill();
|
|
this.ctx.beginPath();
|
|
this.ctx.moveTo(400, 820);
|
|
this.ctx.lineTo(400 + this.hLen, 650);
|
|
this.ctx.stroke();
|
|
this.ctx.moveTo(400, 820);
|
|
this.ctx.lineTo(400 - this.hLen, 650);
|
|
this.ctx.stroke();
|
|
|
|
},
|
|
clearBoard() {
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); // clearing the canvas
|
|
}
|
|
},
|
|
computed: {
|
|
hLen: {
|
|
get() {
|
|
return Math.tan(this.horizontalFOV / 2 * Math.PI / 180) * 150;
|
|
}
|
|
}
|
|
},
|
|
mounted: function () {
|
|
const canvas = document.getElementById("canvasId"); // getting the canvas element
|
|
const ctx = canvas.getContext("2d"); // getting the canvas context
|
|
this.canvas = canvas; // setting the canvas as a vue variable
|
|
this.ctx = ctx; // setting the canvas context as a vue variable
|
|
this.grad = this.ctx.createLinearGradient(400, 800, 400, 600);
|
|
this.grad.addColorStop(0, "rgb(119,119,119)");
|
|
this.grad.addColorStop(0.05, "rgba(14,92,22,0.96)");
|
|
this.grad.addColorStop(0.8, "rgba(43,43,43,0.48)");
|
|
|
|
// setting canvas context values for drawing
|
|
|
|
|
|
this.ctx.font = "26px Arial";
|
|
this.ctx.strokeStyle = "whitesmoke";
|
|
this.ctx.lineWidth = 2;
|
|
|
|
this.$nextTick(function () {
|
|
this.drawPlayer();
|
|
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
#canvasId {
|
|
width: 400px;
|
|
height: 400px;
|
|
background-color: #2b2b2b;
|
|
border-radius: 5px;
|
|
border: 2px solid grey;
|
|
box-shadow: 0 0 5px 1px;
|
|
}
|
|
|
|
th {
|
|
width: 80px;
|
|
text-align: center;
|
|
}
|
|
</style> |