Skip to content

Commit 4f549ba

Browse files
authored
Use the tool plugin to include photon-targeting into photon-core (#2137)
## Description This allows photon-targeting to be loaded using the same mechanism as the rest of the WPILib libraries, fixing issues with libraries not being able to find and load their dependent libraries. ## Meta Merge checklist: - [x] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes - [x] The description documents the _what_ and _why_ - [x] If this PR changes behavior or adds a feature, user documentation is updated - [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly - [ ] If this PR touches configuration, this is backwards compatible with settings back to v2025.3.2 - [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated - [ ] If this PR addresses a bug, a regression test for it is added
1 parent b531fe6 commit 4f549ba

File tree

21 files changed

+100
-280
lines changed

21 files changed

+100
-280
lines changed

photon-core/build.gradle

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,26 @@ apply from: "${rootDir}/shared/common.gradle"
88
wpilibTools.deps.wpilibVersion = wpi.versions.wpilibVersion.get()
99

1010
def nativeConfigName = 'wpilibNatives'
11-
def nativeConfig = configurations.create(nativeConfigName)
12-
11+
configurations {
12+
wpilibNatives
13+
}
1314
def nativeTasks = wpilibTools.createExtractionTasks {
1415
configurationName = nativeConfigName
1516
}
1617

1718
nativeTasks.addToSourceSetResources(sourceSets.main)
1819

19-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpimath")
20-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpinet")
21-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpiutil")
22-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("ntcore")
23-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("cscore")
24-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("apriltag")
25-
nativeConfig.dependencies.add wpilibTools.deps.wpilib("hal")
26-
nativeConfig.dependencies.add wpilibTools.deps.wpilibOpenCv("frc" + openCVYear, wpi.versions.opencvVersion.get())
27-
2820
dependencies {
21+
wpilibNatives project(path: ':photon-targeting', configuration: 'wpilibNatives')
22+
wpilibNatives wpilibTools.deps.wpilib("wpimath")
23+
wpilibNatives wpilibTools.deps.wpilib("wpinet")
24+
wpilibNatives wpilibTools.deps.wpilib("wpiutil")
25+
wpilibNatives wpilibTools.deps.wpilib("ntcore")
26+
wpilibNatives wpilibTools.deps.wpilib("cscore")
27+
wpilibNatives wpilibTools.deps.wpilib("apriltag")
28+
wpilibNatives wpilibTools.deps.wpilib("hal")
29+
wpilibNatives wpilibTools.deps.wpilibOpenCv("frc" + openCVYear, wpi.versions.opencvVersion.get())
30+
2931
// Zip
3032
implementation 'org.zeroturnaround:zt-zip:1.14'
3133

photon-core/src/main/java/org/photonvision/common/dataflow/networktables/TimeSyncManager.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.photonvision.common.logging.LogGroup;
2626
import org.photonvision.common.logging.Logger;
2727
import org.photonvision.common.util.TimedTaskManager;
28-
import org.photonvision.jni.PhotonTargetingJniLoader;
2928
import org.photonvision.jni.TimeSyncClient;
3029
import org.photonvision.jni.TimeSyncServer;
3130

@@ -43,10 +42,6 @@ public class TimeSyncManager {
4342
IntegerPublisher m_lastPongTimePub;
4443

4544
public TimeSyncManager(NetworkTable kRootTable) {
46-
if (!PhotonTargetingJniLoader.isWorking) {
47-
logger.error("PhotonTargetingJNI was not loaded! Cannot do time-sync");
48-
}
49-
5045
this.ntInstance = kRootTable.getInstance();
5146

5247
// Need this subtable to be unique per coprocessor. TODO: consider using MAC address or
@@ -65,18 +60,10 @@ public TimeSyncManager(NetworkTable kRootTable) {
6560

6661
// Since we're spinning off tasks in a new thread, be careful and start it seperately
6762
public void start() {
68-
if (!PhotonTargetingJniLoader.isWorking) {
69-
logger.error("PhotonTargetingJNI was not loaded! Cannot start");
70-
}
71-
7263
TimedTaskManager.getInstance().addTask("TimeSyncManager::tick", this::tick, 1000);
7364
}
7465

7566
public synchronized long getOffset() {
76-
if (!PhotonTargetingJniLoader.isWorking) {
77-
return 0;
78-
}
79-
8067
// if we're a client, return the offset to server time
8168
if (m_client != null) return m_client.getOffset();
8269
// if we're a server, our time (nt::Now) is the same as network time
@@ -88,10 +75,6 @@ public synchronized long getOffset() {
8875
}
8976

9077
synchronized void setConfig(NetworkConfig config) {
91-
if (!PhotonTargetingJniLoader.isWorking) {
92-
return;
93-
}
94-
9578
if (m_client == null && m_server == null) {
9679
throw new RuntimeException("Neither client nor server are null?");
9780
}

photon-core/src/main/java/org/photonvision/common/util/TestUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
import java.nio.file.Path;
2727
import org.opencv.core.Mat;
2828
import org.opencv.highgui.HighGui;
29-
import org.photonvision.jni.WpilibLoader;
29+
import org.photonvision.jni.LibraryLoader;
3030
import org.photonvision.vision.calibration.CameraCalibrationCoefficients;
3131
import org.photonvision.vision.pipeline.result.CVPipelineResult;
3232
import org.photonvision.vision.target.TrackedTarget;
3333

3434
public class TestUtils {
3535
public static boolean loadLibraries() {
36-
return WpilibLoader.loadLibraries();
36+
return LibraryLoader.loadWpiLibraries() && LibraryLoader.loadTargeting();
3737
}
3838

3939
@SuppressWarnings("unused")

photon-core/src/test/java/org/photonvision/hardware/HardwareTest.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,18 @@
2020
import static org.junit.jupiter.api.Assertions.assertFalse;
2121
import static org.junit.jupiter.api.Assertions.assertTrue;
2222

23-
import java.io.IOException;
2423
import org.junit.jupiter.api.Test;
2524
import org.photonvision.common.hardware.GPIO.CustomGPIO;
2625
import org.photonvision.common.hardware.GPIO.GPIOBase;
2726
import org.photonvision.common.hardware.GPIO.pi.PigpioPin;
2827
import org.photonvision.common.hardware.Platform;
2928
import org.photonvision.common.hardware.metrics.MetricsManager;
3029
import org.photonvision.common.util.TestUtils;
31-
import org.photonvision.jni.PhotonTargetingJniLoader;
3230

3331
public class HardwareTest {
3432
@Test
3533
public void testHardware() {
36-
try {
37-
TestUtils.loadLibraries();
38-
PhotonTargetingJniLoader.load();
39-
} catch (UnsatisfiedLinkError | IOException e) {
40-
e.printStackTrace();
41-
}
34+
TestUtils.loadLibraries();
4235
MetricsManager mm = new MetricsManager();
4336

4437
if (!Platform.isRaspberryPi()) return;

photon-core/src/test/java/org/photonvision/vision/frame/consumer/FileSaveFrameConsumerTest.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,20 @@
4141
import org.photonvision.common.configuration.ConfigManager;
4242
import org.photonvision.common.dataflow.networktables.NetworkTablesManager;
4343
import org.photonvision.common.util.TestUtils;
44-
import org.photonvision.jni.PhotonTargetingJniLoader;
45-
import org.photonvision.jni.WpilibLoader;
44+
import org.photonvision.jni.LibraryLoader;
4645
import org.photonvision.vision.frame.provider.FileFrameProvider;
4746

4847
public class FileSaveFrameConsumerTest {
4948
NetworkTableInstance inst = null;
5049

5150
@BeforeAll
52-
public static void init() throws UnsatisfiedLinkError, IOException {
53-
if (!WpilibLoader.loadLibraries()) {
51+
public static void init() throws IOException {
52+
if (!LibraryLoader.loadWpiLibraries()) {
5453
fail();
5554
}
5655

57-
try {
58-
if (!PhotonTargetingJniLoader.load()) fail();
59-
} catch (UnsatisfiedLinkError | IOException e) {
60-
e.printStackTrace();
61-
fail(e);
56+
if (!LibraryLoader.loadTargeting()) {
57+
fail();
6258
}
6359
}
6460

photon-core/src/test/java/org/photonvision/vision/processes/VisionModuleManagerTest.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import static org.junit.jupiter.api.Assertions.fail;
2323

2424
import edu.wpi.first.cscore.VideoMode;
25-
import java.io.IOException;
2625
import java.util.Arrays;
2726
import java.util.HashMap;
2827
import java.util.List;
@@ -32,7 +31,7 @@
3231
import org.photonvision.common.configuration.ConfigManager;
3332
import org.photonvision.common.dataflow.CVPipelineResultConsumer;
3433
import org.photonvision.common.util.TestUtils;
35-
import org.photonvision.jni.PhotonTargetingJniLoader;
34+
import org.photonvision.jni.LibraryLoader;
3635
import org.photonvision.vision.camera.PVCameraInfo;
3736
import org.photonvision.vision.camera.QuirkyCamera;
3837
import org.photonvision.vision.camera.USBCameras.USBCameraSource;
@@ -48,12 +47,7 @@ public static void init() {
4847
System.out.print(classpathStr);
4948

5049
TestUtils.loadLibraries();
51-
try {
52-
if (!PhotonTargetingJniLoader.load()) fail();
53-
} catch (UnsatisfiedLinkError | IOException e) {
54-
e.printStackTrace();
55-
fail(e);
56-
}
50+
if (!LibraryLoader.loadTargeting()) fail();
5751
}
5852

5953
private static class TestSource extends VisionSource {

photon-core/src/test/java/org/photonvision/vision/processes/VisionSourceManagerTest.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package org.photonvision.vision.processes;
1919

20-
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2120
import static org.junit.jupiter.api.Assertions.assertEquals;
2221
import static org.junit.jupiter.api.Assertions.assertTrue;
2322

@@ -33,7 +32,6 @@
3332
import org.photonvision.common.configuration.ConfigManager;
3433
import org.photonvision.common.util.TestUtils;
3534
import org.photonvision.common.util.file.JacksonUtils;
36-
import org.photonvision.jni.PhotonTargetingJniLoader;
3735
import org.photonvision.vision.camera.PVCameraInfo;
3836

3937
public class VisionSourceManagerTest {
@@ -59,9 +57,7 @@ public void teardown() {
5957

6058
@BeforeAll
6159
public static void loadLibraries() {
62-
TestUtils.loadLibraries();
63-
assertDoesNotThrow(PhotonTargetingJniLoader::load);
64-
assertTrue(PhotonTargetingJniLoader.isWorking);
60+
assertTrue(TestUtils.loadLibraries());
6561

6662
// Broadcast all still calls into configmanager (ew) so set that up here
6763
ConfigManager.getInstance().load();

photon-lib/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@ def nativeTasks = wpilibTools.createExtractionTasks {
363363

364364
nativeTasks.addToSourceSetResources(sourceSets.test)
365365

366+
dependencies {
367+
wpilibNatives project(":photon-targeting")
368+
}
366369
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpimath")
367370
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpinet")
368371
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpiutil")

photon-lib/src/main/java/org/photonvision/timesync/TimeSyncSingleton.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
package org.photonvision.timesync;
2626

27+
import edu.wpi.first.util.RuntimeLoader;
2728
import java.io.IOException;
28-
import org.photonvision.jni.PhotonTargetingJniLoader;
2929
import org.photonvision.jni.TimeSyncServer;
3030

3131
/** Helper to hold a single TimeSyncServer instance with some default config */
@@ -35,12 +35,11 @@ public class TimeSyncSingleton {
3535
public static boolean load() {
3636
if (INSTANCE == null) {
3737
try {
38-
if (!PhotonTargetingJniLoader.load()) {
39-
return false;
40-
}
41-
} catch (UnsatisfiedLinkError | IOException e) {
38+
RuntimeLoader.loadLibrary("photontargetingJNI");
39+
} catch (IOException e) {
40+
// Don't want to return early. We want to create the TimeSyncServer so the program crashes
41+
// because we need it in order to function.
4242
e.printStackTrace();
43-
return false;
4443
}
4544

4645
INSTANCE = new TimeSyncServer(5810);

photon-lib/src/test/java/org/photonvision/PhotonCameraTest.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import edu.wpi.first.math.geometry.Rotation2d;
3636
import edu.wpi.first.networktables.NetworkTableInstance;
3737
import edu.wpi.first.networktables.NetworkTablesJNI;
38+
import edu.wpi.first.util.RuntimeLoader;
3839
import edu.wpi.first.wpilibj.DataLogManager;
3940
import edu.wpi.first.wpilibj.Timer;
4041
import edu.wpi.first.wpilibj.simulation.SimHooks;
@@ -55,9 +56,8 @@
5556
import org.junit.jupiter.params.provider.Arguments;
5657
import org.junit.jupiter.params.provider.MethodSource;
5758
import org.photonvision.common.dataflow.structures.Packet;
58-
import org.photonvision.jni.PhotonTargetingJniLoader;
59+
import org.photonvision.jni.LibraryLoader;
5960
import org.photonvision.jni.TimeSyncClient;
60-
import org.photonvision.jni.WpilibLoader;
6161
import org.photonvision.simulation.PhotonCameraSim;
6262
import org.photonvision.targeting.PhotonPipelineMetadata;
6363
import org.photonvision.targeting.PhotonPipelineResult;
@@ -68,8 +68,9 @@ class PhotonCameraTest {
6868
NetworkTableInstance inst = null;
6969

7070
@BeforeAll
71-
public static void load_wpilib() {
72-
WpilibLoader.loadLibraries();
71+
public static void load() throws IOException {
72+
LibraryLoader.loadWpiLibraries();
73+
RuntimeLoader.loadLibrary("photontargetingJNI");
7374
}
7475

7576
@BeforeEach
@@ -111,9 +112,6 @@ public void testEmpty() {
111112
@Test
112113
@Order(3)
113114
public void testTimeSyncServerWithPhotonCamera() throws InterruptedException, IOException {
114-
load_wpilib();
115-
PhotonTargetingJniLoader.load();
116-
117115
inst.stopClient();
118116
inst.startServer();
119117

0 commit comments

Comments
 (0)