Note: ai readme.
- CUDA AprilTag engine: GPU-accelerated AprilTag detector based on Team 971’s implementation (
frc971/orin/*.cu+third_party/apriltag). - Shared library: Builds
lib971apriltag.sovia CMake. - Bindings:
- Java/JNI for PhotonVision / WPILib (
GpuDetectorJNI.cc). - Rust wrapper using
cxx(src/bridge.rs,src/cpp/cuda_tags_wrapper.*,src/main.rsdemo).
- Java/JNI for PhotonVision / WPILib (
If you just want to see tags being detected, the Rust demo is the simplest way to test once the CUDA library is built.
- GPU platform
- Tested on NVIDIA Jetson (e.g., Orin) with JetPack 6.2.
- CUDA toolkit installed at
/usr/local/cuda.
- System packages (typical Jetson setup)
build-essential cmake ninja-buildopenjdk-17-jdklibopencv-dev(and/orlibopencv4.5-javaif using Java)protobuf-compiler libxrandr-dev libssh-dev
- Rust toolchain (for the demo / crate)
rustupwith a recent stable toolchain (edition 2024 is used).
Most of these are handled automatically if you use the install scripts below.
The fastest “it actually works” path on a fresh Jetson with JetPack:
-
Clone the repo
cd ~/Documentsgit clone <this-repo-url> CudaTagscd CudaTags
-
Run the installer (builds dependencies + CUDA library)
bash install/build.bash
This will:
- Install Java 17 and basic dependencies.
- Set CUDA / Java environment variables in
~/.bashrc. - Clone and build WPILib.
- Build
third_party/apriltagand this project. - Install
lib971apriltag.soto/usr/lib.
-
Open a new shell so the environment from
~/.bashrcis picked up. -
Run the Rust camera demo
cd ~/Documents/CudaTagscargo run --release
What you should see:
- A window named
camfrom OpenCV. - Live camera frames from
/dev/video0. - AprilTags outlined in red with their IDs drawn on the image.
- FPS and timing stats printed to stderr in the form:
[CudaTags-Rust] frame 640x480 channels=3 stride=... detections=N time_ms=...
If this works, you have a fully functioning CUDA + AprilTag + OpenCV stack.
If you want to build the GPU library separately (without using install/build.bash):
-
Build the upstream AprilTag library
cd ~/Documents/CudaTags/third_party/apriltagmkdir -p buildcd buildcmake ..make
-
Build CudaTags via CMake
cd ~/Documents/CudaTagsmkdir -p buildcd buildcmake ..make
This produces
build/lib971apriltag.so. -
Install the shared library (so Rust/Java can link it)
sudo cp lib971apriltag.so /usr/lib
Once lib971apriltag.so is installed into /usr/lib, you can:
- Use the Rust demo (
cargo run --release). - Use the Java/JNI integration as described below.
The pybind11 module lives under src/main/python/cpp and is packaged as cuda_tags.
-
Create / activate a Python environment:
cd ~/Documents/CudaTags python3 -m venv .venv source .venv/bin/activate
-
Build and install the package (this runs CMake through
scikit-buildand drops the extension into your environment):pip install -v .The module now ships with the CUDA detector and does not require manual copying of
.sofiles. -
(Optional) Generate Python stubs:
pip install pybind11-stubgen pybind11-stubgen cuda_tags --output-dir "$(python -c 'import sysconfig; print(sysconfig.get_path(\"purelib\"))')"
You can automate these steps via install/python_build.bash, which prepares the virtualenv, installs dependencies, builds the wheel, and refreshes the generated stubs.
Prefer a manual CMake build? Configure with
-DCUDATAGS_BUILD_PYTHON=ONto emit thecuda_tagsmodule next to the other targets.
The Rust crate in this repo (Cargo.toml, src/lib.rs, src/bridge.rs, src/main.rs) wraps the CUDA detector via cxx and runs a simple camera demo.
-
Entry point:
src/main.rs- Opens camera index
0with OpenCV (MJPG at 640×480 @ 30 FPS). - Calls
make_cuda_tag_detectorfrom the C++ layer to create a GPU detector. - Sends frames into the GPU, retrieves
DetectionResultvalues, and draws:- Tag outline (quadrilateral).
- Tag center.
- Tag ID text near the center.
- Overlays FPS, processing time (ms), and detections count on the frame.
- Press
Escto exit the window.
- Opens camera index
-
Bridge types:
src/bridge.rs- Defines
CameraMatrix,DistCoeffs,RustImage,TagType, andDetectionResult. - Exposes
make_cuda_tag_detectorandCudaTagsWrapper::processfrom C++.
- Defines
- To use a different camera index, change the line in
src/main.rs:let mut cam = videoio::VideoCapture::new(0, videoio::CAP_V4L2)?;
- To change resolution or FPS, adjust:
CAP_PROP_FRAME_WIDTH,CAP_PROP_FRAME_HEIGHT,CAP_PROP_FPS.
- Make sure the width/height passed to
make_cuda_tag_detectormatch the actual camera resolution.
For Java/WPILib/PhotonVision integration, the key file is GpuDetectorJNI.cc. It:
- Wraps the CUDA-based
frc971::apriltag::GpuDetector. - Exposes JNI methods for creating/destroying detectors and processing
cv::Matimages. - Produces an array of
edu.wpi.first.apriltag.AprilTagDetectionobjects with ID, Hamming distance, decision margin, homography, corners, and center.
To use it:
- Ensure
lib971apriltag.sois built and installed (see sections above). - Make sure your Java classpath and
java.library.pathcan find everything.- Example (from
test.sh):java -cp GpuDetectorJNI.jar -Djava.library.path=. org.photonvision.jni.GpuDetectorJNI
- Example (from
- From Java, you typically:
- Capture frames into an OpenCV
Mat. - Pass the image data to the JNI layer.
- Use the returned detections for localization or targeting.
- Capture frames into an OpenCV
The exact wiring depends on your PhotonVision / robot codebase, but this library is designed to drop into that ecosystem with minimal changes.
- CUDA / OpenCV include paths
CMakeLists.txtandbuild.rsassume CUDA headers at/usr/local/cuda/includeand OpenCV at/usr/include/opencv4.- Adjust those paths if your distro uses different locations.
- LLVM / Clang for Rust
cxxbuilds- On some systems you may need:
export LLVM_CONFIG_PATH=/usr/bin/llvm-config-14
- This is hinted at in
test.sh.
- On some systems you may need:
- Architecture-specific libraries
build.rslooks forlib/linux/<arch>when giving Rust a link search path, but installinglib971apriltag.soto/usr/libis usually enough.
- CUDA + AprilTag core
frc971/orin/– GPU implementation and helpers (thresholding, labeling, line fitting, etc.).third_party/apriltag/– Upstream AprilTag library.
- Bindings
GpuDetectorJNI.cc– Java/WPILib JNI bindings.src/cpp/cuda_tags_wrapper.*– C++ bridge for the Rustcxxlayer.src/bridge.rs– Rust side of thecxxbridge.
- Rust crate
Cargo.toml,src/lib.rs,src/main.rs.
- Build / install
CMakeLists.txt– CMake config forlib971apriltag.so.install/*.bash– Helper scripts to set up dependencies and build everything.
This repository includes the upstream AprilTag library under its own license (third_party/apriltag/LICENSE.md).
See LICENSE.txt in this repository for the overall project licensing details.