Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RKNN Object Detection #1

Merged
merged 42 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
319e55f
initial
laviRZ Jan 3, 2024
5d9021e
bad model crash fix
laviRZ Jan 3, 2024
a7867df
spotless and remove name of detection
laviRZ Jan 4, 2024
4b14f20
model upload
laviRZ Jan 4, 2024
8bdb592
fix model path
laviRZ Jan 4, 2024
f17d036
add confidence to TrackedTarget, add class and confidence to UI
laviRZ Jan 5, 2024
1e274f3
threshold slider, working dummy dll
laviRZ Jan 5, 2024
75680e4
send actual class instead of 0
laviRZ Jan 5, 2024
0dedd89
0.1 minimum threshold, only embed detections if processed stream is e…
laviRZ Jan 5, 2024
748d90b
rknnrt
laviRZ Jan 5, 2024
b449337
missing import
laviRZ Jan 5, 2024
1e85cec
unpack to /usr/lib
laviRZ Jan 5, 2024
ec7a3ca
libraryLoaded bug
laviRZ Jan 5, 2024
2a40391
try delete before unpacking
laviRZ Jan 5, 2024
e74d97d
delete if found
laviRZ Jan 5, 2024
6a8186a
unpack fix
laviRZ Jan 7, 2024
c5ce102
Update libjnish.so
laviRZ Jan 7, 2024
9240e52
unpack to temp, unpack rknnrt to /usr/lib
laviRZ Jan 7, 2024
5dab11a
don't unpack twice
laviRZ Jan 7, 2024
6f54d8b
don't unpack if exists
laviRZ Jan 7, 2024
fc8a4b5
refactoring, bugfixes
laviRZ Jan 9, 2024
da289fe
spotless
laviRZ Jan 9, 2024
f7431c0
loadedLibraries bugfix
laviRZ Jan 9, 2024
2de8c8b
multicore
laviRZ Jan 9, 2024
edbb60e
Merge remote-tracking branch 'upstream/master' into rknn
laviRZ Jan 9, 2024
01510f5
Update PhotonJNICommon.java
laviRZ Jan 9, 2024
e79649c
spotless
laviRZ Jan 9, 2024
702fff4
bugfixes after merge
laviRZ Jan 9, 2024
e2f6e9f
load rknnrt regularly and not through /usr/lib
laviRZ Jan 10, 2024
c65240f
first pass at model selection
laviRZ Jan 11, 2024
f683dea
un-static models.zip unpacking function
laviRZ Jan 11, 2024
0deba44
show targets, fix confidence slider bug
laviRZ Jan 12, 2024
3ecb1fb
infer number of classes
laviRZ Jan 12, 2024
6dc8e59
Update models.zip
laviRZ Jan 14, 2024
5b854cd
Merge remote-tracking branch 'upstream/master' into rknn
laviRZ Jan 14, 2024
2e65c97
rknn readme, and changed default model
laviRZ Jan 15, 2024
2dd1c23
add conesandcubes models
laviRZ Jan 15, 2024
e036cc7
unpack models in pipeline
laviRZ Jan 15, 2024
4416d1b
spotless
laviRZ Jan 15, 2024
07f9951
wpiformat
laviRZ Jan 15, 2024
a8bce75
Update RKNNTab.vue
laviRZ Jan 15, 2024
3788c3b
run prettier
laviRZ Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,5 @@ photonlib-java-examples/*/networktables.json.bck
photon-server/src/main/resources/web/index.html

venv

!photon-core/src/main/resources/models.zip
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const changeCurrentCameraIndex = (index: number) => {
case PipelineType.Aruco:
pipelineType.value = WebsocketPipelineType.Aruco;
break;
case PipelineType.RKNN:
pipelineType.value = WebsocketPipelineType.RKNN;
break;
}
};

Expand Down Expand Up @@ -152,7 +155,8 @@ const pipelineTypesWrapper = computed<{ name: string; value: number }[]>(() => {
{ name: "Reflective", value: WebsocketPipelineType.Reflective },
{ name: "Colored Shape", value: WebsocketPipelineType.ColoredShape },
{ name: "AprilTag", value: WebsocketPipelineType.AprilTag },
{ name: "Aruco", value: WebsocketPipelineType.Aruco }
{ name: "Aruco", value: WebsocketPipelineType.Aruco },
{ name: "RKNN", value: WebsocketPipelineType.RKNN }
];

if (useCameraSettingsStore().isDriverMode) {
Expand Down Expand Up @@ -208,6 +212,9 @@ useCameraSettingsStore().$subscribe((mutation, state) => {
case PipelineType.Aruco:
pipelineType.value = WebsocketPipelineType.Aruco;
break;
case PipelineType.RKNN:
pipelineType.value = WebsocketPipelineType.RKNN;
break;
}
});
</script>
Expand Down Expand Up @@ -354,7 +361,8 @@ useCameraSettingsStore().$subscribe((mutation, state) => {
{ name: 'Reflective', value: WebsocketPipelineType.Reflective },
{ name: 'Colored Shape', value: WebsocketPipelineType.ColoredShape },
{ name: 'AprilTag', value: WebsocketPipelineType.AprilTag },
{ name: 'Aruco', value: WebsocketPipelineType.Aruco }
{ name: 'Aruco', value: WebsocketPipelineType.Aruco },
{ name: 'RKNN', value: WebsocketPipelineType.RKNN }
]"
/>
</v-card-text>
Expand Down
26 changes: 21 additions & 5 deletions photon-client/src/components/dashboard/ConfigOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import OutputTab from "@/components/dashboard/tabs/OutputTab.vue";
import TargetsTab from "@/components/dashboard/tabs/TargetsTab.vue";
import PnPTab from "@/components/dashboard/tabs/PnPTab.vue";
import Map3DTab from "@/components/dashboard/tabs/Map3DTab.vue";
import RKNNTab from "@/components/dashboard/tabs/RKNNTab.vue";
import { WebsocketPipelineType } from "@/types/WebsocketDataTypes";

interface ConfigOption {
Expand Down Expand Up @@ -55,6 +56,10 @@ const allTabs = Object.freeze({
map3dTab: {
tabName: "3D",
component: Map3DTab
},
rknnTab: {
tabName: "RKNN",
component: RKNNTab
}
});

Expand All @@ -75,21 +80,29 @@ const getTabGroups = (): ConfigOption[][] => {
allTabs.contoursTab,
allTabs.apriltagTab,
allTabs.arucoTab,
allTabs.rknnTab,
allTabs.outputTab
],
[allTabs.targetsTab, allTabs.pnpTab, allTabs.map3dTab]
];
} else if (lgAndDown) {
return [
[allTabs.inputTab],
[allTabs.thresholdTab, allTabs.contoursTab, allTabs.apriltagTab, allTabs.arucoTab, allTabs.outputTab],
[
allTabs.thresholdTab,
allTabs.contoursTab,
allTabs.apriltagTab,
allTabs.arucoTab,
allTabs.rknnTab,
allTabs.outputTab
],
[allTabs.targetsTab, allTabs.pnpTab, allTabs.map3dTab]
];
} else if (xl) {
return [
[allTabs.inputTab],
[allTabs.thresholdTab],
[allTabs.contoursTab, allTabs.apriltagTab, allTabs.arucoTab, allTabs.outputTab],
[allTabs.contoursTab, allTabs.apriltagTab, allTabs.arucoTab, allTabs.rknnTab, allTabs.outputTab],
[allTabs.targetsTab, allTabs.pnpTab, allTabs.map3dTab]
];
}
Expand All @@ -103,17 +116,20 @@ const tabGroups = computed<ConfigOption[][]>(() => {
const allow3d = useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled;
const isAprilTag = useCameraSettingsStore().currentWebsocketPipelineType === WebsocketPipelineType.AprilTag;
const isAruco = useCameraSettingsStore().currentWebsocketPipelineType === WebsocketPipelineType.Aruco;
const isRKNN = useCameraSettingsStore().currentWebsocketPipelineType === WebsocketPipelineType.RKNN;

return getTabGroups()
.map((tabGroup) =>
tabGroup.filter(
(tabConfig) =>
!(!allow3d && tabConfig.tabName === "3D") && //Filter out 3D tab any time 3D isn't calibrated
!((!allow3d || isAprilTag || isAruco) && tabConfig.tabName === "PnP") && //Filter out the PnP config tab if 3D isn't available, or we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Threshold") && //Filter out threshold tab if we're doing AprilTags
!((isAprilTag || isAruco) && tabConfig.tabName === "Contours") && //Filter out contours if we're doing AprilTags
!((isAprilTag || isAruco || isRKNN) && tabConfig.tabName === "Threshold") && //Filter out threshold tab if we're doing AprilTags or RKNN
!((isAprilTag || isAruco || isRKNN) && tabConfig.tabName === "Contours") && //Filter out contours if we're doing AprilTags or RKNN
!(!isAprilTag && tabConfig.tabName === "AprilTag") && //Filter out apriltag unless we actually are doing AprilTags
!(!isAruco && tabConfig.tabName === "Aruco") //Filter out aruco unless we actually are doing Aruco
!(!isAruco && tabConfig.tabName === "Aruco") && //Filter out aruco unless we actually are doing Aruco
!(!isRKNN && tabConfig.tabName === "RKNN") && //Filter out RKNN unless we actually are doing RKNN
!(isRKNN && tabConfig.tabName === "Output") //Filter out output tab if we're doing RKNN
)
)
.filter((it) => it.length); // Remove empty tab groups
Expand Down
62 changes: 62 additions & 0 deletions photon-client/src/components/dashboard/tabs/RKNNTab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { PipelineType } from "@/types/PipelineTypes";
import PvSlider from "@/components/common/pv-slider.vue";
import pvSelect from "@/components/common/pv-select.vue";
import { computed, getCurrentInstance } from "vue";
import { useStateStore } from "@/stores/StateStore";
import type { ActivePipelineSettings } from "@/types/PipelineTypes";
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";

// 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
);

const currentSelectedModelIndex = computed(() => {
const cps = currentPipelineSettings.value;
return cps.pipelineType === PipelineType.RKNN
? useCameraSettingsStore().availableModels.indexOf(cps.selectedModel)
: 0;
});

const getModelName = (index: number) => {
const cps = currentPipelineSettings.value;
return cps.pipelineType === PipelineType.RKNN ? useCameraSettingsStore().availableModels[index] : "";
};

console.log("available: " + useCameraSettingsStore().availableModels);
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>

<template>
<div v-if="currentPipelineSettings.pipelineType === PipelineType.RKNN">
<pv-slider
v-model="currentPipelineSettings.confidenceThreshold"
class="pt-2"
:slider-cols="interactiveCols"
label="Confidence Threshold"
tooltip="Any detections with a confidence below this threshold will be discarded. Minimum value is 0.1."
:min="0.1"
:max="1"
:step="0.01"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ confidenceThreshold: value }, false)"
/>
<pv-select
:select-cols="interactiveCols"
:value="currentSelectedModelIndex"
label="RKNN Model"
tooltip="The RKNN model to use for inference."
:items="useCameraSettingsStore().availableModels"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ selectedModel: getModelName(value) }, false)
"
/>
</div>
</template>
8 changes: 8 additions & 0 deletions photon-client/src/components/dashboard/tabs/TargetsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ const resetCurrentBuffer = () => {
>
Fiducial ID
</th>
<template v-if="currentPipelineSettings.pipelineType === PipelineType.RKNN">
<th class="text-center white--text">Class</th>
<th class="text-center white--text">Confidence</th>
</template>
<template v-if="!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<th class="text-center white--text">Pitch &theta;&deg;</th>
<th class="text-center white--text">Yaw &theta;&deg;</th>
Expand Down Expand Up @@ -85,6 +89,10 @@ const resetCurrentBuffer = () => {
>
{{ target.fiducialId }}
</td>
<template v-if="currentPipelineSettings.pipelineType === PipelineType.RKNN">
<td class="text-center">{{ target.fiducialId }}</td>
<td class="text-center">{{ target.ambiguity.toFixed(2) }}</td>
</template>
<template v-if="!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<td class="text-center">{{ target.pitch.toFixed(2) }}&deg;</td>
<td class="text-center">{{ target.yaw.toFixed(2) }}&deg;</td>
Expand Down
17 changes: 14 additions & 3 deletions photon-client/src/components/settings/DeviceControlCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ enum ImportType {
HardwareConfig,
HardwareSettings,
NetworkConfig,
ApriltagFieldLayout
ApriltagFieldLayout,
RKNNModel
}
const showImportDialog = ref(false);
const importType = ref<ImportType | number>(-1);
Expand All @@ -162,6 +163,9 @@ const handleSettingsImport = () => {
case ImportType.ApriltagFieldLayout:
settingsEndpoint = "/aprilTagFieldLayout";
break;
case ImportType.RKNNModel:
settingsEndpoint = "/rknnModel";
break;
default:
case ImportType.AllSettings:
settingsEndpoint = "";
Expand Down Expand Up @@ -259,7 +263,8 @@ const handleSettingsImport = () => {
'Hardware Config',
'Hardware Settings',
'Network Config',
'Apriltag Layout'
'Apriltag Layout',
'RKNN Model'
]"
:select-cols="10"
style="width: 100%"
Expand All @@ -270,7 +275,13 @@ const handleSettingsImport = () => {
v-model="importFile"
:disabled="importType === -1"
:error-messages="importType === -1 ? 'Settings type not selected' : ''"
:accept="importType === ImportType.AllSettings ? '.zip' : '.json'"
:accept="
importType === ImportType.AllSettings
? '.zip'
: importType === ImportType.RKNNModel
? '.rknn'
: '.json'
"
/>
</v-row>
<v-row
Expand Down
6 changes: 5 additions & 1 deletion photon-client/src/stores/settings/CameraSettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
},
isCSICamera(): boolean {
return this.currentCameraSettings.isCSICamera;
},
availableModels(): string[] {
return this.currentCameraSettings.availableModels || [];
}
},
actions: {
Expand Down Expand Up @@ -104,7 +107,8 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
pipelineNicknames: d.pipelineNicknames,
currentPipelineIndex: d.currentPipelineIndex,
pipelineSettings: d.currentPipelineSettings,
cameraQuirks: d.cameraQuirks
cameraQuirks: d.cameraQuirks,
availableModels: d.availableModels
}));
},
/**
Expand Down
29 changes: 26 additions & 3 deletions photon-client/src/types/PipelineTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export enum PipelineType {
Reflective = 2,
ColoredShape = 3,
AprilTag = 4,
Aruco = 5
Aruco = 5,
RKNN = 6
}

export enum AprilTagFamily {
Expand Down Expand Up @@ -281,14 +282,36 @@ export const DefaultArucoPipelineSettings: ArucoPipelineSettings = {
doSingleTargetAlways: false
};

export interface RKNNPipelineSettings extends PipelineSettings {
pipelineType: PipelineType.RKNN;
confidenceThreshold: number;
selectedModel: string;
}

export type ConfigurableRKNNPipelineSettings = Partial<Omit<RKNNPipelineSettings, "pipelineType">> &
ConfigurablePipelineSettings;
export const DefaultRKNNPipelineSettings: RKNNPipelineSettings = {
...DefaultPipelineSettings,
pipelineType: PipelineType.RKNN,
cameraGain: 43,
targetModel: TargetModel.RapidReactCircularCargoBall,
ledMode: false,
outputShowMultipleTargets: false,
cameraExposure: 13,
confidenceThreshold: 0.35,
selectedModel: "model"
};

export type ActivePipelineSettings =
| ReflectivePipelineSettings
| ColoredShapePipelineSettings
| AprilTagPipelineSettings
| ArucoPipelineSettings;
| ArucoPipelineSettings
| RKNNPipelineSettings;

export type ActiveConfigurablePipelineSettings =
| ConfigurableReflectivePipelineSettings
| ConfigurableColoredShapePipelineSettings
| ConfigurableAprilTagPipelineSettings
| ConfigurableArucoPipelineSettings;
| ConfigurableArucoPipelineSettings
| ConfigurableRKNNPipelineSettings;
2 changes: 2 additions & 0 deletions photon-client/src/types/SettingTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ export interface CameraSettings {

cameraQuirks: QuirkyCamera;
isCSICamera: boolean;

availableModels?: string[];
}

export interface CameraSettingsChangeRequest {
Expand Down
4 changes: 3 additions & 1 deletion photon-client/src/types/WebsocketDataTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export interface WebsocketCameraSettingsUpdate {
pipelineNicknames: string[];
videoFormatList: WebsocketVideoFormat;
cameraQuirks: QuirkyCamera;
availableModels?: string[];
}
export interface WebsocketNTUpdate {
connected: boolean;
Expand Down Expand Up @@ -101,5 +102,6 @@ export enum WebsocketPipelineType {
Reflective = 0,
ColoredShape = 1,
AprilTag = 2,
Aruco = 3
Aruco = 3,
RKNN = 4
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ public Path getCalibDir() {
return Path.of(configDirectoryFile.toString(), "calibImgs");
}

public Path getRKNNModelsPath() {
return Path.of(configDirectoryFile.toString() + "/models");
}

public static final String LOG_PREFIX = "photonvision-";
public static final String LOG_EXT = ".log";
public static final String LOG_DATE_TIME_FORMAT = "yyyy-M-d_hh-mm-ss";
Expand Down Expand Up @@ -261,6 +265,17 @@ public boolean saveUploadedAprilTagFieldLayout(Path uploadPath) {
return m_provider.saveUploadedAprilTagFieldLayout(uploadPath);
}

public boolean saveUploadedRKNNModel(Path uploadPath) {
var modelPath = Path.of(getRKNNModelsPath().toString(), uploadPath.getFileName().toString());
try {
Files.copy(uploadPath, modelPath, StandardCopyOption.REPLACE_EXISTING);
return true;
} catch (IOException e) {
logger.error("Exception copying uploaded RKNN model!", e);
return false;
}
}

public void requestSave() {
logger.trace("Requesting save...");
saveRequestTimestamp = System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,7 @@ public static class UICameraConfiguration {
public boolean isFovConfigurable = true;
public QuirkyCamera cameraQuirks;
public boolean isCSICamera;

public String[] availableModels;
}
}
Loading