From df45bc2d73a7b6f99bed2a315f25eb8a88fe39eb Mon Sep 17 00:00:00 2001 From: amquake Date: Tue, 24 Oct 2023 19:39:38 -0700 Subject: [PATCH] Re-enable OpenCV ArUco detector for AprilTags (#916) - Fixes ArUco on picam - Adds `ArucoPoseEstimatorPipe` for single-tag pose estimation - Previously, `Aruco.estimatePoseSingleMarkers()` was used for tag pose estimation. This uses the default `SOLVEPNP_ITERATIVE` solver and I believe the method is removed in opencv 4.8. The `SOLVEPNP_IPPE_SQUARE` solver implemented is more appropriate for markers. - Pipeline architecture cleanup - Re-enables ArUco pipeline in UI - Multi-tag support ArUco detector support is still considered experimental at this time. This should enable a baseline of support for initial testing, but expect some quirks to remain across platforms. --- .../dashboard/CameraAndPipelineSelectCard.vue | 8 +- .../components/dashboard/tabs/ArucoTab.vue | 68 +++++-- .../components/dashboard/tabs/OutputTab.vue | 6 +- .../components/dashboard/tabs/TargetsTab.vue | 9 +- photon-client/src/types/PipelineTypes.ts | 35 +++- .../common/configuration/ConfigManager.java | 3 +- .../vision/aruco/ArucoDetectionResult.java | 28 +-- .../vision/aruco/ArucoDetectorParams.java | 77 ------- .../vision/aruco/PhotonArucoDetector.java | 146 +++++-------- .../vision/pipe/impl/ArucoDetectionPipe.java | 107 ++++++++-- .../pipe/impl/ArucoDetectionPipeParams.java | 94 +++++++-- .../pipe/impl/ArucoPoseEstimatorPipe.java | 140 +++++++++++++ .../vision/pipeline/AprilTagPipeline.java | 3 +- .../pipeline/AprilTagPipelineSettings.java | 2 +- .../vision/pipeline/ArucoPipeline.java | 191 ++++++++++++++---- .../pipeline/ArucoPipelineSettings.java | 26 ++- .../vision/target/TargetModel.java | 10 +- .../vision/target/TrackedTarget.java | 75 ++++--- .../vision/pipeline/AprilTagTest.java | 39 ++-- .../vision/pipeline/ArucoPipelineTest.java | 69 +++++-- 20 files changed, 744 insertions(+), 392 deletions(-) delete mode 100644 photon-core/src/main/java/org/photonvision/vision/aruco/ArucoDetectorParams.java create mode 100644 photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoPoseEstimatorPipe.java diff --git a/photon-client/src/components/dashboard/CameraAndPipelineSelectCard.vue b/photon-client/src/components/dashboard/CameraAndPipelineSelectCard.vue index 11544a34d1..cec1db4f9e 100644 --- a/photon-client/src/components/dashboard/CameraAndPipelineSelectCard.vue +++ b/photon-client/src/components/dashboard/CameraAndPipelineSelectCard.vue @@ -151,8 +151,8 @@ const pipelineTypesWrapper = computed<{ name: string; value: number }[]>(() => { const pipelineTypes = [ { name: "Reflective", value: WebsocketPipelineType.Reflective }, { name: "Colored Shape", value: WebsocketPipelineType.ColoredShape }, - { name: "AprilTag", value: WebsocketPipelineType.AprilTag } - // { name: "Aruco", value: WebsocketPipelineType.Aruco } + { name: "AprilTag", value: WebsocketPipelineType.AprilTag }, + { name: "Aruco", value: WebsocketPipelineType.Aruco } ]; if (useCameraSettingsStore().isDriverMode) { @@ -353,8 +353,8 @@ useCameraSettingsStore().$subscribe((mutation, state) => { :items="[ { name: 'Reflective', value: WebsocketPipelineType.Reflective }, { name: 'Colored Shape', value: WebsocketPipelineType.ColoredShape }, - { name: 'AprilTag', value: WebsocketPipelineType.AprilTag } - // { name: 'Aruco', value: WebsocketPipelineType.Aruco } + { name: 'AprilTag', value: WebsocketPipelineType.AprilTag }, + { name: 'Aruco', value: WebsocketPipelineType.Aruco } ]" /> diff --git a/photon-client/src/components/dashboard/tabs/ArucoTab.vue b/photon-client/src/components/dashboard/tabs/ArucoTab.vue index 13b2807ed6..596a17d00a 100644 --- a/photon-client/src/components/dashboard/tabs/ArucoTab.vue +++ b/photon-client/src/components/dashboard/tabs/ArucoTab.vue @@ -2,6 +2,9 @@ import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore"; import { PipelineType } from "@/types/PipelineTypes"; import PvSlider from "@/components/common/pv-slider.vue"; +import PvSwitch from "@/components/common/pv-switch.vue"; +import PvRangeSlider from "@/components/common/pv-range-slider.vue"; +import PvSelect from "@/components/common/pv-select.vue"; import { computed, getCurrentInstance } from "vue"; import { useStateStore } from "@/stores/StateStore"; @@ -20,37 +23,60 @@ const interactiveCols = computed( diff --git a/photon-client/src/components/dashboard/tabs/OutputTab.vue b/photon-client/src/components/dashboard/tabs/OutputTab.vue index bc9fb8ca0c..e1e270af8a 100644 --- a/photon-client/src/components/dashboard/tabs/OutputTab.vue +++ b/photon-client/src/components/dashboard/tabs/OutputTab.vue @@ -86,7 +86,8 @@ const interactiveCols = computed( />