diff --git a/photon-core/build.gradle b/photon-core/build.gradle
index 396388a773..aa30f0c379 100644
--- a/photon-core/build.gradle
+++ b/photon-core/build.gradle
@@ -55,6 +55,10 @@ dependencies {
}
testImplementation group: 'org.junit-pioneer' , name: 'junit-pioneer', version: '2.2.0'
+
+ def arucoVer = "dev-v2024.0.1-15-g0d7210c"
+ implementation "org.photonvision:photonaruconano-jni:$arucoVer:$jniPlatform"
+ implementation "org.photonvision:photonaruconano-java:$arucoVer"
}
task writeCurrentVersion {
diff --git a/photon-core/src/main/java/org/photonvision/jni/ArucoNanoDetectorJNI.java b/photon-core/src/main/java/org/photonvision/jni/ArucoNanoDetectorJNI.java
new file mode 100644
index 0000000000..e63d347af7
--- /dev/null
+++ b/photon-core/src/main/java/org/photonvision/jni/ArucoNanoDetectorJNI.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision.jni;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.photonvision.ArucoNanoV5Detector;
+import org.photonvision.ArucoNanoV5Detector.DetectionResult;
+import org.photonvision.common.util.TestUtils;
+import org.photonvision.vision.aruco.ArucoDetectionResult;
+import org.photonvision.vision.opencv.CVMat;
+
+public class ArucoNanoDetectorJNI extends PhotonJNICommon {
+ private boolean isLoaded;
+ private static ArucoNanoDetectorJNI instance = null;
+
+ private ArucoNanoDetectorJNI() {
+ isLoaded = false;
+ }
+
+ public static ArucoNanoDetectorJNI getInstance() {
+ if (instance == null) instance = new ArucoNanoDetectorJNI();
+
+ return instance;
+ }
+
+ public static synchronized void forceLoad() throws IOException {
+ forceLoad(getInstance(), ArucoNanoDetectorJNI.class, List.of("photonmiscjnijni"));
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return isLoaded;
+ }
+
+ @Override
+ public void setLoaded(boolean state) {
+ isLoaded = state;
+ }
+
+ public static List detect(CVMat in) {
+ DetectionResult[] ret = ArucoNanoV5Detector.detect(in.getMat().getNativeObjAddr(), 0);
+
+ return List.of(ret).stream()
+ .map(it -> new ArucoDetectionResult(it.xCorners, it.yCorners, it.id))
+ .collect(Collectors.toList());
+ }
+
+ public static void main(String[] args) throws IOException {
+ TestUtils.loadLibraries();
+ forceLoad();
+ }
+}
diff --git a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoDetectionPipe.java b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoDetectionPipe.java
index 4d0cdb55e9..00e8fe694e 100644
--- a/photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoDetectionPipe.java
+++ b/photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoDetectionPipe.java
@@ -26,6 +26,7 @@
import org.opencv.core.TermCriteria;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.Objdetect;
+import org.photonvision.jni.ArucoNanoDetectorJNI;
import org.photonvision.vision.aruco.ArucoDetectionResult;
import org.photonvision.vision.aruco.PhotonArucoDetector;
import org.photonvision.vision.opencv.CVMat;
@@ -43,6 +44,8 @@ public class ArucoDetectionPipe
@Override
protected List process(CVMat in) {
+ if (in.getMat().empty()) return List.of();
+
var imgMat = in.getMat();
// Sanity check -- image should not be empty
@@ -51,8 +54,10 @@ protected List process(CVMat in) {
return List.of();
}
- var detections = photonDetector.detect(imgMat);
- // manually do corner refinement ourselves
+ // var detections = photonDetector.detect(imgMat);
+ var detections = ArucoNanoDetectorJNI.detect(in);
+
+ // manually do corner refinement ourselves (todo do we have to with aruco-nano?)
if (params.useCornerRefinement) {
for (var detection : detections) {
double[] xCorners = detection.getXCorners();
@@ -93,7 +98,9 @@ protected List process(CVMat in) {
}
}
}
- return List.of(detections);
+
+ // return List.of(detections);
+ return (detections);
}
@Override
diff --git a/photon-server/src/main/java/org/photonvision/Main.java b/photon-server/src/main/java/org/photonvision/Main.java
index 8ae7c8fd92..32b3ffc6e8 100644
--- a/photon-server/src/main/java/org/photonvision/Main.java
+++ b/photon-server/src/main/java/org/photonvision/Main.java
@@ -38,6 +38,7 @@
import org.photonvision.common.networking.NetworkManager;
import org.photonvision.common.util.TestUtils;
import org.photonvision.common.util.numbers.IntegerCouple;
+import org.photonvision.jni.ArucoNanoDetectorJNI;
import org.photonvision.jni.RknnDetectorJNI;
import org.photonvision.mrcal.MrCalJNILoader;
import org.photonvision.raspi.LibCameraJNILoader;
@@ -343,6 +344,13 @@ public static void main(String[] args) {
logger.error("Failed to load native libraries!", e);
}
+ try {
+ ArucoNanoDetectorJNI.forceLoad();
+ logger.info("Native libraries loaded.");
+ } catch (Exception e) {
+ logger.error("Failed to load native libraries!", e);
+ }
+
try {
if (Platform.isRaspberryPi()) {
LibCameraJNILoader.forceLoad();