Skip to content

Commit 5ae0df4

Browse files
committed
Hack in aruco-nano
1 parent 0b98f02 commit 5ae0df4

File tree

6 files changed

+174
-14
lines changed

6 files changed

+174
-14
lines changed

photon-core/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ dependencies {
1313
implementation 'org.zeroturnaround:zt-zip:1.14'
1414

1515
implementation "org.xerial:sqlite-jdbc:3.41.0.0"
16+
17+
def arucoVer = "dev-v2024.0.1-11-g5190e06"
18+
implementation "org.photonvision:photonmiscjni-jni:$arucoVer:$jniPlatform"
19+
implementation "org.photonvision:photonmiscjni-java:$arucoVer"
1620
}
1721

1822
task writeCurrentVersion {

photon-core/src/main/java/org/photonvision/common/hardware/Platform.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.photonvision.common.hardware;
1919

20+
import com.jogamp.common.os.Platform.OSType;
2021
import edu.wpi.first.util.RuntimeDetector;
2122
import java.io.BufferedReader;
2223
import java.io.IOException;
@@ -27,23 +28,32 @@
2728
@SuppressWarnings("unused")
2829
public enum Platform {
2930
// WPILib Supported (JNI)
30-
WINDOWS_64("Windows x64", false, OSType.WINDOWS, true),
31-
LINUX_32("Linux x86", false, OSType.LINUX, true),
32-
LINUX_64("Linux x64", false, OSType.LINUX, true),
31+
WINDOWS_64("Windows x64", "win/x64", false, OSType.WINDOWS, true),
32+
LINUX_32("Linux x86", "linux/x64", false, OSType.LINUX, true),
33+
LINUX_64("Linux x64", "linux/x86-64", false, OSType.LINUX, true),
3334
LINUX_RASPBIAN32(
34-
"Linux Raspbian 32-bit", true, OSType.LINUX, true), // Raspberry Pi 3/4 with a 32-bit image
35+
"Linux Raspbian 32-bit",
36+
"linuxarm32",
37+
true,
38+
OSType.LINUX,
39+
true), // Raspberry Pi 3/4 with a 32-bit image
3540
LINUX_RASPBIAN64(
36-
"Linux Raspbian 64-bit", true, OSType.LINUX, true), // Raspberry Pi 3/4 with a 64-bit image
37-
LINUX_AARCH64("Linux AARCH64", false, OSType.LINUX, true), // Jetson Nano, Jetson TX2
41+
"Linux Raspbian 64-bit",
42+
"linuxarm64",
43+
true,
44+
OSType.LINUX,
45+
true), // Raspberry Pi 3/4 with a 64-bit image
46+
LINUX_AARCH64(
47+
"Linux AARCH64", "linuxarm64", false, OSType.LINUX, true), // Jetson Nano, Jetson TX2
3848

3949
// PhotonVision Supported (Manual build/install)
40-
LINUX_ARM32("Linux ARM32", false, OSType.LINUX, true), // ODROID XU4, C1+
41-
LINUX_ARM64("Linux ARM64", false, OSType.LINUX, true), // ODROID C2, N2
50+
LINUX_ARM32("Linux ARM32", "linuxarm32", false, OSType.LINUX, true), // ODROID XU4, C1+
51+
LINUX_ARM64("Linux ARM64", "linuxarm64", false, OSType.LINUX, true), // ODROID C2, N2
4252

4353
// Completely unsupported
44-
WINDOWS_32("Windows x86", false, OSType.WINDOWS, false),
45-
MACOS("Mac OS", false, OSType.MACOS, false),
46-
UNKNOWN("Unsupported Platform", false, OSType.UNKNOWN, false);
54+
WINDOWS_32("Windows x86", "windowsx64", false, OSType.WINDOWS, false),
55+
MACOS("Mac OS", "osxuniversal", false, OSType.MACOS, false),
56+
UNKNOWN("Unsupported Platform", "", false, OSType.UNKNOWN, false);
4757

4858
private enum OSType {
4959
WINDOWS,
@@ -54,6 +64,7 @@ private enum OSType {
5464

5565
private static final ShellExec shell = new ShellExec(true, false);
5666
public final String description;
67+
public final String nativeLibraryFolderName;
5768
public final boolean isPi;
5869
public final OSType osType;
5970
public final boolean isSupported;
@@ -62,11 +73,17 @@ private enum OSType {
6273
private static final Platform currentPlatform = getCurrentPlatform();
6374
private static final boolean isRoot = checkForRoot();
6475

65-
Platform(String description, boolean isPi, OSType osType, boolean isSupported) {
76+
Platform(
77+
String description,
78+
String nativeLibFolderName,
79+
boolean isPi,
80+
OSType osType,
81+
boolean isSupported) {
6682
this.description = description;
6783
this.isPi = isPi;
6884
this.osType = osType;
6985
this.isSupported = isSupported;
86+
this.nativeLibraryFolderName = nativeLibFolderName;
7087
}
7188

7289
//////////////////////////////////////////////////////
@@ -89,6 +106,10 @@ public static String getPlatformName() {
89106
}
90107
}
91108

109+
public static final String getNativeLibraryFolderName() {
110+
return currentPlatform.nativeLibraryFolderName;
111+
}
112+
92113
public static boolean isRoot() {
93114
return isRoot;
94115
}
@@ -212,4 +233,9 @@ private static boolean fileHasText(String filename, String text) {
212233
return false;
213234
}
214235
}
236+
237+
public static boolean isWindows() {
238+
var p = getCurrentPlatform();
239+
return (p == WINDOWS_32 || p == WINDOWS_64);
240+
}
215241
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.photonvision.jni;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
import java.util.stream.Collector;
6+
import java.util.stream.Collectors;
7+
8+
import org.photonvision.ArucoNanoV5Detector;
9+
import org.photonvision.ArucoNanoV5Detector.DetectionResult;
10+
import org.photonvision.common.util.TestUtils;
11+
import org.photonvision.vision.aruco.ArucoDetectionResult;
12+
import org.photonvision.vision.opencv.CVMat;
13+
14+
public class ArucoNanoDetector extends PhotonJniCommon {
15+
public static synchronized void forceLoad() throws IOException {
16+
forceLoad(ArucoNanoDetector.class, List.of("photonmiscjnijni"));
17+
}
18+
19+
public static List<ArucoDetectionResult> detect(CVMat in) {
20+
DetectionResult[] ret = ArucoNanoV5Detector.detect(in.getMat().getNativeObjAddr(), 0);
21+
22+
return List.of(ret).stream().map(it->new ArucoDetectionResult(
23+
it.xCorners, it.yCorners, it.id
24+
)).collect(Collectors.toList());
25+
}
26+
27+
public static void main(String[] args) throws IOException {
28+
TestUtils.loadLibraries();
29+
forceLoad();
30+
}
31+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (C) Photon Vision.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
package org.photonvision.jni;
19+
20+
import java.io.File;
21+
import java.io.FileOutputStream;
22+
import java.io.IOException;
23+
import java.util.List;
24+
import org.photonvision.common.hardware.Platform;
25+
import org.photonvision.common.logging.LogGroup;
26+
import org.photonvision.common.logging.Logger;
27+
28+
public abstract class PhotonJniCommon {
29+
static boolean libraryLoaded = false;
30+
protected static Logger logger = null;
31+
32+
protected static synchronized void forceLoad(Class<?> clazz, List<String> libraries)
33+
throws IOException {
34+
if (libraryLoaded) return;
35+
if (logger == null) logger = new Logger(clazz, LogGroup.Camera);
36+
37+
for (var libraryName : libraries) {
38+
try {
39+
// We always extract the shared object (we could hash each so, but that's a lot of work)
40+
var arch_name = Platform.getNativeLibraryFolderName();
41+
var nativeLibName = System.mapLibraryName(libraryName);
42+
var in = clazz.getResourceAsStream("/" + arch_name + "/" + nativeLibName);
43+
44+
if (in == null) {
45+
libraryLoaded = false;
46+
return;
47+
}
48+
49+
// It's important that we don't mangle the names of these files on Windows at least
50+
File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName);
51+
FileOutputStream fos = new FileOutputStream(temp);
52+
53+
int read = -1;
54+
byte[] buffer = new byte[1024];
55+
while ((read = in.read(buffer)) != -1) {
56+
fos.write(buffer, 0, read);
57+
}
58+
fos.close();
59+
in.close();
60+
61+
System.load(temp.getAbsolutePath());
62+
63+
logger.info("Successfully loaded shared object " + temp.getName());
64+
65+
} catch (UnsatisfiedLinkError e) {
66+
logger.error("Couldn't load shared object " + libraryName, e);
67+
e.printStackTrace();
68+
// logger.error(System.getProperty("java.library.path"));
69+
break;
70+
}
71+
}
72+
libraryLoaded = true;
73+
}
74+
75+
protected static synchronized void forceLoad(Class<?> clazz, String libraryName)
76+
throws IOException {
77+
forceLoad(clazz, List.of(libraryName));
78+
}
79+
80+
public static boolean isWorking() {
81+
return libraryLoaded;
82+
}
83+
}

photon-core/src/main/java/org/photonvision/vision/pipe/impl/ArucoDetectionPipe.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.opencv.core.TermCriteria;
2727
import org.opencv.imgproc.Imgproc;
2828
import org.opencv.objdetect.Objdetect;
29+
import org.photonvision.jni.ArucoNanoDetector;
2930
import org.photonvision.vision.aruco.ArucoDetectionResult;
3031
import org.photonvision.vision.aruco.PhotonArucoDetector;
3132
import org.photonvision.vision.opencv.CVMat;
@@ -43,8 +44,13 @@ public class ArucoDetectionPipe
4344

4445
@Override
4546
protected List<ArucoDetectionResult> process(CVMat in) {
47+
if (in.getMat().empty()) return List.of();
48+
4649
var imgMat = in.getMat();
47-
var detections = photonDetector.detect(imgMat);
50+
51+
// var detections = photonDetector.detect(imgMat);
52+
var detections = ArucoNanoDetector.detect(in);
53+
4854
// manually do corner refinement ourselves
4955
if (params.useCornerRefinement) {
5056
for (var detection : detections) {
@@ -86,7 +92,9 @@ protected List<ArucoDetectionResult> process(CVMat in) {
8692
}
8793
}
8894
}
89-
return List.of(detections);
95+
96+
// return List.of(detections);
97+
return (detections);
9098
}
9199

92100
@Override

photon-server/src/main/java/org/photonvision/Main.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.photonvision.common.networking.NetworkManager;
3838
import org.photonvision.common.util.TestUtils;
3939
import org.photonvision.common.util.numbers.IntegerCouple;
40+
import org.photonvision.jni.ArucoNanoDetector;
4041
import org.photonvision.raspi.LibCameraJNI;
4142
import org.photonvision.server.Server;
4243
import org.photonvision.vision.camera.FileVisionSource;
@@ -309,6 +310,13 @@ public static void main(String[] args) {
309310
logger.error("Failed to load native libraries!", e);
310311
}
311312

313+
try {
314+
ArucoNanoDetector.forceLoad();
315+
logger.info("Native libraries loaded.");
316+
} catch (Exception e) {
317+
logger.error("Failed to load native libraries!", e);
318+
}
319+
312320
try {
313321
if (Platform.isRaspberryPi()) {
314322
LibCameraJNI.forceLoad();

0 commit comments

Comments
 (0)