Running WPILib code on the driver station - ntcorejni could not be loaded

We have been trying to run vision processing code on the driver laptop, since the Limelight and RoboRIO are too slow to do so quickly. We intend on using NetworkTables to connect to the RoboRIO to send back the position of the tracked object. When we try to run our project, we get the following error:

java.io.IOException: ntcorejni could not be loaded from path or an embedded resource.
    attempted to load for platform /windows/x86-64/
Last Load Error:
no ntcorejni in java.library.path: 

(paths omitted)

A common cause of this error is missing the C++ runtime.
Download the latest at https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads

        at edu.wpi.first.util.RuntimeLoader.loadLibrary(RuntimeLoader.java:94)
        at edu.wpi.first.networktables.NetworkTablesJNI.<clinit>(NetworkTablesJNI.java:34)
        at edu.wpi.first.networktables.NetworkTableInstance.getDefault(NetworkTableInstance.java:85)
        at frc.visionclient.Main.main(Main.java:25)

Here is the code:

package frc.visionclient;

import org.opencv.core.Rect;
import org.opencv.imgproc.Imgproc;

import edu.wpi.first.cscore.HttpCamera;
import edu.wpi.first.cscore.VideoSource;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.vision.VisionThread;

public final class Main {

  public static final Object imgLock = new Object();

  public static void main(String[] args) {
    NetworkTableInstance nt = NetworkTableInstance.getDefault();
    NetworkTable table = nt.getTable("fakenews");
    NetworkTableEntry tx = table.getEntry("x");
    NetworkTableEntry ty = table.getEntry("y");

    VideoSource camera = new HttpCamera("limelight", "http://10.17.68.13:5800/");

    VisionThread visionThread = new VisionThread(camera, new GripPipeline(), pipeline -> {
      if (!pipeline.filterContoursOutput().isEmpty()) {
        Rect r = Imgproc.boundingRect(pipeline.filterContoursOutput().get(0));
        synchronized (Main.imgLock) {
          double x = r.x + (r.width / 2);
          double y = r.y + (r.height / 2);
          tx.setDouble(x);
          ty.setDouble(y);
          System.out.println("X: " + x + ",  Y: " + y);
        }
      }
    });
    visionThread.start();
  }
}

We already followed the instructions from Using Shuffleboard/NetworkTables in non-robot code, however this did not fix the problem. Thanks for any help or insight.

Can you post your build.gradle? How does your dependencies compare to this: https://github.com/frc1444/robot2021/blob/fd1c2e2dc4f411c5f59217c7b2ce23b674690942/gdx/build.gradle#L15?

It’s also worth noting that the above code has not been tested on Windows in a while.

Can you describe what kind of vision processing you’re doing? While it’s likely that your driver laptop has more processing power then a Limelight, it has a distinct latency disadvantage in that it has to receive camera images over wireless, and then transmit data back to the robot wirelessly, where as the Limelight process it’s local camera and only has to transmit data to the roboRIO over a wired network.

We did vision processing on the driver station for years, but as soon as the Limelight was available, we switched and never looked back.

1 Like

Here was our build.gradle file:

plugins {
    id "java"
    id "edu.wpi.first.GradleRIO" version "2022.3.1"
}

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

def ROBOT_MAIN_CLASS = "frc.robot.Main"

// Define my targets (RoboRIO) and artifacts (deployable files)
// This is added by GradleRIO's backing project DeployUtils.
deploy {
    targets {
        roborio(getTargetTypeClass('RoboRIO')) {
            // Team number is loaded either from the .wpilib/wpilib_preferences.json
            // or from command line. If not found an exception will be thrown.
            // You can use getTeamOrDefault(team) instead of getTeamNumber if you
            // want to store a team number in this file.
            team = project.frc.getTeamNumber()
            debug = project.frc.getDebugOrDefault(false)

            artifacts {
                // First part is artifact name, 2nd is artifact type
                // getTargetTypeClass is a shortcut to get the class type using a string

                frcJava(getArtifactTypeClass('FRCJavaArtifact')) {
                }

                // Static files artifact
                frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) {
                    files = project.fileTree('src/main/deploy')
                    directory = '/home/lvuser/deploy'
                }
            }
        }
    }
}

def deployArtifact = deploy.targets.roborio.artifacts.frcJava

// Set to true to use debug for JNI.
wpi.java.debugJni = false

// Set this to true to enable desktop support.
def includeDesktopSupport = false

repositories {
    maven {
        url 'https://first.wpi.edu/FRC/roborio/maven/release'
    }
}

// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries.
// Also defines JUnit 4.
dependencies {
    implementation wpi.java.deps.wpilib()
    implementation wpi.java.vendor.java()

    roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio)
    roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio)

    roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio)
    roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio)

    nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
    nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
    simulationDebug wpi.sim.enableDebug()

    nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
    nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
    simulationRelease wpi.sim.enableRelease()

    testImplementation 'junit:junit:4.13.1'

    implementation group: 'edu.wpi.first.ntcore', name: 'ntcore-java', version: '2022.3.1'
    implementation "edu.wpi.first.ntcore:ntcore-java:2022.3.1"
    implementation "edu.wpi.first.ntcore:ntcore-jni:2022.3.1"
    implementation "edu.wpi.first.ntcore:ntcore-jni:2022.3.1:linuxx86-64"
    implementation "edu.wpi.first.wpilibj:wpilibj-java:2022.3.1"
    implementation "edu.wpi.first.wpiutil:wpiutil-java:2022.3.1"
    implementation "edu.wpi.first.cscore:cscore-java:2022.3.1"
    implementation "edu.wpi.first.hal:hal-java:2022.3.1"
    implementation "edu.wpi.first.hal:hal-jni:2022.3.1"
    implementation "edu.wpi.first.hal:hal-jni:2022.3.1:linuxx86-64"
}

// Simulation configuration (e.g. environment variables).
wpi.sim.addGui().defaultEnabled = true
wpi.sim.addDriverstation()

// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar')
// in order to make them all available at runtime. Also adding the manifest so WPILib
// knows where to look for our Robot Class.
jar {
    from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
    manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS)
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

// Configure jar and deploy tasks
deployArtifact.jarTask = jar
wpi.java.configureExecutableTasks(jar)
wpi.java.configureTestTasks(test)

While writing this, I noticed that we were using linuxx86-64 as the system version. I changed this to ${wpi.platforms.desktop} as suggested and it is now missing cscorejni instead.

Your dependencies {} block is missing cscore-jni (you should have similar lines to the ntcore ones for cscore as well).

Thanks! The project now builds properly when we are just using NetworkTables, however we cannot figure out how to add OpenCV as a dependency.

            devImplementation "edu.wpi.first.thirdparty.frc2022.opencv:opencv-java:4.5.2-1"

devImplementation does not seem to exist:

Could not find method devImplementation() for arguments [edu.wpi.first.thirdparty.frc2022.opencv:opencv-java:4.5.2-1] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

I tried changing this to implementation, but it results in the same error as before.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.