2023-08-21 01:51:35 -04:00
< script setup lang = "ts" >
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore" ;
2024-01-02 11:03:16 -05:00
import { type ActivePipelineSettings , PipelineType } from "@/types/PipelineTypes" ;
2023-08-21 01:51:35 -04:00
import { useStateStore } from "@/stores/StateStore" ;
2024-01-02 11:03:16 -05:00
import { angleModulus , toDeg } from "@/lib/MathUtils" ;
import { computed } from "vue" ;
2023-10-21 11:09:55 -04:00
2024-01-02 11:03:16 -05:00
// TODO fix pipeline typing in order to fix this, the store settings call should be able to infer that only valid pipeline type settings are exposed based on pre-checks for the entire config section
// Defer reference to store access method
const currentPipelineSettings = computed < ActivePipelineSettings > (
( ) => useCameraSettingsStore ( ) . currentPipelineSettings
) ;
2023-12-28 12:40:50 -05:00
2023-12-19 15:47:53 -05:00
const calculateStdDev = ( values : number [ ] ) : number => {
if ( values . length < 2 ) return 0 ;
2023-12-28 12:40:50 -05:00
// Use mean of cosine/sine components to handle angle wrapping
const cosines = values . map ( ( it ) => Math . cos ( it ) ) ;
const sines = values . map ( ( it ) => Math . sin ( it ) ) ;
const cosmean = cosines . reduce ( ( sum , number ) => sum + number , 0 ) / values . length ;
const sinmean = sines . reduce ( ( sum , number ) => sum + number , 0 ) / values . length ;
// Borrowed from WPILib's Rotation2d
const hypot = Math . hypot ( cosmean , sinmean ) ;
2024-01-02 11:03:16 -05:00
const mean = hypot > 1 e - 6 ? Math . atan2 ( sinmean / hypot , cosmean / hypot ) : 0 ;
2023-12-19 15:47:53 -05:00
2024-01-02 11:03:16 -05:00
return Math . sqrt ( values . map ( ( x ) => Math . pow ( angleModulus ( x - mean ) , 2 ) ) . reduce ( ( a , b ) => a + b ) / values . length ) ;
2023-12-19 15:47:53 -05:00
} ;
const resetCurrentBuffer = ( ) => {
// Need to clear the array in place
2024-03-22 20:19:51 -04:00
if ( useStateStore ( ) . currentMultitagBuffer ) useStateStore ( ) . currentMultitagBuffer ! . length = 0 ;
2023-12-19 15:47:53 -05:00
} ;
2023-08-21 01:51:35 -04:00
< / script >
< template >
< div >
2024-01-02 11:03:16 -05:00
< v-row align = "start" class = "pb-4" >
< v-simple-table dense class = "pt-2 pb-12" >
2023-08-21 01:51:35 -04:00
< template # default >
2024-01-02 11:03:16 -05:00
< thead >
2023-08-21 01:51:35 -04:00
< tr >
< th
2023-08-31 16:56:58 -04:00
v - if = "
2024-01-02 11:03:16 -05:00
currentPipelineSettings . pipelineType === PipelineType . AprilTag ||
currentPipelineSettings . pipelineType === PipelineType . Aruco
2023-08-31 16:56:58 -04:00
"
2024-01-02 11:03:16 -05:00
class = "text-center white--text"
2023-08-21 01:51:35 -04:00
>
Fiducial ID
< / th >
2024-01-15 22:28:34 -05:00
< template v-if = "currentPipelineSettings.pipelineType === PipelineType.ObjectDetection" >
< th class = "text-center white--text" > Class < / th >
< th class = "text-center white--text" > Confidence < / th >
< / template >
2023-08-21 01:51:35 -04:00
< template v-if = "!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled" >
2024-01-02 11:03:16 -05:00
< th class = "text-center white--text" > Pitch & theta ; & deg ; < / th >
< th class = "text-center white--text" > Yaw & theta ; & deg ; < / th >
< th class = "text-center white--text" > Skew & theta ; & deg ; < / th >
< th class = "text-center white--text" > Area % < / th >
2023-08-21 01:51:35 -04:00
< / template >
< template v-else >
2024-01-02 11:03:16 -05:00
< th class = "text-center white--text" > X meters < / th >
< th class = "text-center white--text" > Y meters < / th >
< th class = "text-center white--text" > Z Angle & theta ; & deg ; < / th >
2023-08-21 01:51:35 -04:00
< / template >
2023-08-31 16:56:58 -04:00
< template
v - if = "
2024-01-02 11:03:16 -05:00
( currentPipelineSettings . pipelineType === PipelineType . AprilTag ||
currentPipelineSettings . pipelineType === PipelineType . Aruco ) &&
2023-08-31 16:56:58 -04:00
useCameraSettingsStore ( ) . currentPipelineSettings . solvePNPEnabled
"
>
2024-01-02 11:03:16 -05:00
< th class = "text-center white--text" > Ambiguity Ratio < / th >
2023-08-21 01:51:35 -04:00
< / template >
< / tr >
< / thead >
< tbody >
2024-01-02 11:03:16 -05:00
< tr
v - for = "(target, index) in useStateStore().currentPipelineResults?.targets"
: key = "index"
class = "white--text"
>
2023-08-31 16:56:58 -04:00
< td
v - if = "
2024-01-02 11:03:16 -05:00
currentPipelineSettings . pipelineType === PipelineType . AprilTag ||
currentPipelineSettings . pipelineType === PipelineType . Aruco
2023-08-31 16:56:58 -04:00
"
2024-01-02 11:03:16 -05:00
class = "text-center"
2023-08-31 16:56:58 -04:00
>
2023-08-21 01:51:35 -04:00
{ { target . fiducialId } }
< / td >
2024-01-15 22:28:34 -05:00
< td
v - if = "currentPipelineSettings.pipelineType === PipelineType.ObjectDetection"
class = "text-center white--text"
>
{ { useStateStore ( ) . currentPipelineResults ? . classNames [ target . classId ] } }
< / td >
< td
v - if = "currentPipelineSettings.pipelineType === PipelineType.ObjectDetection"
class = "text-center white--text"
>
{ { target . confidence . toFixed ( 2 ) } }
< / td >
2023-08-21 01:51:35 -04:00
< template v-if = "!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled" >
2024-01-02 11:03:16 -05:00
< td class = "text-center" > { { target . pitch . toFixed ( 2 ) } } & deg ; < / td >
< td class = "text-center" > { { target . yaw . toFixed ( 2 ) } } & deg ; < / td >
< td class = "text-center" > { { target . skew . toFixed ( 2 ) } } & deg ; < / td >
< td class = "text-center" > { { target . area . toFixed ( 2 ) } } & deg ; < / td >
2023-08-21 01:51:35 -04:00
< / template >
2023-10-21 11:09:55 -04:00
< template v-else >
2024-01-02 11:03:16 -05:00
< td class = "text-center" > { { target . pose ? . x . toFixed ( 2 ) } } & nbsp ; m < / td >
< td class = "text-center" > { { target . pose ? . y . toFixed ( 2 ) } } & nbsp ; m < / td >
< td class = "text-center" > { { toDeg ( target . pose ? . angle _z || 0 ) . toFixed ( 2 ) } } & deg ; < / td >
2023-08-21 01:51:35 -04:00
< / template >
2023-08-31 16:56:58 -04:00
< template
v - if = "
2024-01-02 11:03:16 -05:00
( currentPipelineSettings . pipelineType === PipelineType . AprilTag ||
currentPipelineSettings . pipelineType === PipelineType . Aruco ) &&
2023-08-31 16:56:58 -04:00
useCameraSettingsStore ( ) . currentPipelineSettings . solvePNPEnabled
"
>
2024-01-02 11:03:16 -05:00
< td class = "text-center" >
{ { target . ambiguity >= 0 ? target . ambiguity . toFixed ( 2 ) : "(In Multi-Target)" } }
< / td >
2023-08-21 01:51:35 -04:00
< / template >
< / tr >
< / tbody >
< / template >
< / v-simple-table >
< / v-row >
2023-12-19 15:47:53 -05:00
< v-container
2023-10-17 10:20:00 -04:00
v - if = "
2024-01-02 11:03:16 -05:00
( currentPipelineSettings . pipelineType === PipelineType . AprilTag ||
currentPipelineSettings . pipelineType === PipelineType . Aruco ) &&
currentPipelineSettings . doMultiTarget &&
2023-10-21 11:09:55 -04:00
useCameraSettingsStore ( ) . isCurrentVideoFormatCalibrated &&
useCameraSettingsStore ( ) . currentPipelineSettings . solvePNPEnabled
2023-10-17 10:20:00 -04:00
"
>
2023-12-19 15:47:53 -05:00
< v-row class = "pb-4 white--text" >
< v-card-subtitle class = "ma-0 pa-0 pb-4" style = "font-size: 16px"
> Multi - tag pose , field - to - camera < / v - c a r d - s u b t i t l e
>
2024-01-02 11:03:16 -05:00
< v-simple-table dense >
< template # default >
< thead >
< tr class = "white--text" >
< th class = "text-center white--text" > X meters < / th >
< th class = "text-center white--text" > Y meters < / th >
< th class = "text-center white--text" > Z meters < / th >
< th class = "text-center white--text" > X Angle & theta ; & deg ; < / th >
< th class = "text-center white--text" > Y Angle & theta ; & deg ; < / th >
< th class = "text-center white--text" > Z Angle & theta ; & deg ; < / th >
< th class = "text-center white--text" > Tags < / th >
< / tr >
< / thead >
< tbody v-show = "useStateStore().currentPipelineResults?.multitagResult" >
< tr >
< td class = "text-center white--text" >
{ { useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . x . toFixed ( 2 ) } } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ { useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . y . toFixed ( 2 ) } } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ { useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . z . toFixed ( 2 ) } } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ {
toDeg ( useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . angle _x || 0 ) . toFixed (
2
)
} } & deg ;
< / td >
< td class = "text-center white--text" >
{ {
toDeg ( useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . angle _y || 0 ) . toFixed (
2
)
} } & deg ;
< / td >
< td class = "text-center white--text" >
{ {
toDeg ( useStateStore ( ) . currentPipelineResults ? . multitagResult ? . bestTransform . angle _z || 0 ) . toFixed (
2
)
} } & deg ;
< / td >
< td class = "text-center white--text" >
{ { useStateStore ( ) . currentPipelineResults ? . multitagResult ? . fiducialIDsUsed } }
< / td >
< / tr >
< / tbody >
< / template >
2023-12-19 15:47:53 -05:00
< / v-simple-table >
< / v-row >
< v-row class = "pb-4 white--text" style = "display: flex; flex-direction: column" >
< v-card-subtitle class = "ma-0 pa-0 pb-4 pr-4" style = "font-size: 16px"
2023-12-28 12:40:50 -05:00
> Multi - tag pose standard deviation over the last
{ { useStateStore ( ) . currentMultitagBuffer ? . length || "NaN" } } / 100 samples
2023-12-19 15:47:53 -05:00
< / v-card-subtitle >
< v-btn color = "secondary" class = "mb-4 mt-1" style = "width: min-content" depressed @click ="resetCurrentBuffer"
> Reset Samples < / v - b t n
>
2024-01-02 11:03:16 -05:00
< v-simple-table dense >
< template # default >
< thead >
< tr >
< th class = "text-center white--text" > X meters < / th >
< th class = "text-center white--text" > Y meters < / th >
< th class = "text-center white--text" > Z meters < / th >
< th class = "text-center white--text" > X Angle & theta ; & deg ; < / th >
< th class = "text-center white--text" > Y Angle & theta ; & deg ; < / th >
< th class = "text-center white--text" > Z Angle & theta ; & deg ; < / th >
< / tr >
< / thead >
< tbody v-show = "useStateStore().currentPipelineResults?.multitagResult" >
< tr >
< td class = "text-center white--text" >
{ {
calculateStdDev ( useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => v . bestTransform . x ) || [ ] ) . toFixed (
5
)
} } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ {
calculateStdDev ( useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => v . bestTransform . y ) || [ ] ) . toFixed (
5
)
} } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ {
calculateStdDev ( useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => v . bestTransform . z ) || [ ] ) . toFixed (
5
)
} } & nbsp ; m
< / td >
< td class = "text-center white--text" >
{ {
calculateStdDev (
useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => toDeg ( v . bestTransform . angle _x ) ) || [ ]
) . toFixed ( 5 )
} } & deg ;
< / td >
< td class = "text-center white--text" >
{ {
calculateStdDev (
useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => toDeg ( v . bestTransform . angle _y ) ) || [ ]
) . toFixed ( 5 )
} } & deg ;
< / td >
< td class = "text-center white--text" >
{ {
calculateStdDev (
useStateStore ( ) . currentMultitagBuffer ? . map ( ( v ) => toDeg ( v . bestTransform . angle _z ) ) || [ ]
) . toFixed ( 5 )
} } & deg ;
< / td >
< / tr >
< / tbody >
< / template >
2023-12-19 15:47:53 -05:00
< / v-simple-table >
< / v-row >
< / v-container >
2023-08-21 01:51:35 -04:00
< / div >
< / template >
< style scoped lang = "scss" >
. v - data - table {
background - color : # 006492 ! important ;
2024-01-02 11:03:16 -05:00
width : 100 % ;
font - size : 1 rem ! important ;
2023-08-21 01:51:35 -04:00
2024-01-02 11:03:16 -05:00
thead {
tr {
th {
font - size : 1 rem ! important ;
color : white ! important ;
}
}
2023-08-21 01:51:35 -04:00
}
2024-01-02 11:03:16 -05:00
tbody {
: hover {
td {
background - color : # 005281 ! important ;
}
}
tr {
td {
font - size : 1 rem ! important ;
color : white ! important ;
}
}
2023-08-21 01:51:35 -04:00
}
: : - webkit - scrollbar {
width : 0 ;
height : 0.55 em ;
border - radius : 5 px ;
}
: : - webkit - scrollbar - track {
- webkit - box - shadow : inset 0 0 6 px rgba ( 0 , 0 , 0 , 0.3 ) ;
border - radius : 10 px ;
}
: : - webkit - scrollbar - thumb {
background - color : # ffd843 ;
border - radius : 10 px ;
}
}
< / style >