Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/upstream-watch.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Has anything we build on changed? Weekly (and from the Actions tab), checks PhotonVision, the 4143
# CUDA fork, frc971/bos, aos, allwpilib and NVIDIA's L4T against what this repo pins, tries our
# Has anything we build on changed? Weekly (and from the Actions tab), checks PhotonVision (releases, and the
# main commit we build on), frc971/bos, aos, allwpilib and NVIDIA's L4T against what this repo pins, tries our
# patches on the newest code, and keeps one issue per upstream (label upstream-watch). See
# scripts/ci/upstream_watch.py. A few minutes a run; free on a public repo.
name: Upstream watch
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Built by Spectrum 3847 with Claude Opus 5.5 (Anthropic) in Claude Code, which di

*Last updated September 24, 2026.*

> **Experimental alpha-7 branch:** this branch ports the SpectrumJetson CUDA and Jetson features to
> PhotonVision source that targets WPILib `2027.0.0-alpha-7`. It has not passed a build on the target
> Jetson or a real robot-network test. Do not install it in place of the tested JetPack 6 image.
> See [CUDA13-MIGRATION.md](docs/CUDA13-MIGRATION.md) for the exact pins and acceptance checklist.

## Headlines

Measured on the bench:
Expand Down Expand Up @@ -57,7 +62,7 @@ A camera frame goes over USB into PhotonVision on the Jetson. PhotonVision finds

```mermaid
flowchart LR
CAM["2-4x Thriftiest Cam<br/>USB 2.0, MJPEG 1280x800"] --> PV["PhotonVision 2026 fork<br/>(4143 CUDA version + our patches)"]
CAM["2-4x Thriftiest Cam<br/>USB 2.0, MJPEG 1280x800"] --> PV["PhotonVision alpha-7 source<br/>(CUDA features, unverified)"]
PV --> DET["971 CUDA AprilTag<br/>detector on the GPU"]
DET --> PV
PV -->|NetworkTables| SC["SystemCore<br/>2027 alpha-6 robot code"]
Expand All @@ -71,7 +76,7 @@ flowchart LR
| Power mode | MAXN SUPER (the fastest mode, which gives the board its "Super" name) |
| Cameras | 2 Thrifty Bot [Thriftiest Cams](https://www.thethriftybot.com/products/thriftiest-cam) ([docs](https://docs.thethriftybot.com/electrical/thriftiest-cam/latest/overview)) for AprilTags: OV9281, mono, global shutter, 1280x800, USB 2.0. On the bench also: 2 "Global Shutter Camera" (32e4:0144) and a colour USB camera (32e4:62f0) for game pieces |
| Power | From the robot through a 15 V boost regulator board, which kept the Jetson running down to a 5 V input (tested 2026-09-25) |
| Vision software | FRC-Team-4143's PhotonVision fork (2026 version), merged with upstream PhotonVision v2026.3.4, plus our patches |
| Vision software | PhotonVision source `1f419c9d` targets WPILib `2027.0.0-alpha-7`. The CUDA features are ported in this branch but remain unverified on Jetson. |
| Tag detector | Austin Schuh's current CUDA detector (from 971 / RealtimeRoboticsGroup), built from frc971/bos |
| Game pieces | YOLO models on the GPU through TensorRT 10.3 (our backend), FUEL model by Team 2826 |
| Robot side | Stock PhotonLib v2027.0.0-alpha-2 in `2026-FM-SystemCore`, team 8515 |
Expand Down Expand Up @@ -118,10 +123,10 @@ The vision stack has four parts. Two are built on the Jetson, one on the laptop,

| # | Part | Built where | Script | Notes |
| --- | --- | --- | --- | --- |
| 1 | PhotonVision service | Jetson (installer) | `jetson/03-photonvision.sh` | Installs the systemd service that starts PhotonVision at boot. We then replace its jar with the fork. |
| 2 | allwpilib `v2026.2.1` | Jetson | `jetson/04-build-allwpilib.sh` | Libraries the CUDA detector links against. Must be the **v2026.2.1 tag**: its `main` branch has moved on and won't compile with the detector. Took 17 minutes. |
| 1 | PhotonVision service | Jetson (installer) | `jetson/03-photonvision.sh` | Installs the systemd service that starts PhotonVision at boot. |
| 2 | allwpilib `v2027.0.0-alpha-7` | Jetson | `jetson/04-build-allwpilib.sh` | Fetches the exact tag object and commit used by the alpha-7 source. This has not been built on the target Jetson. |
| 3 | CUDA detector `lib971apriltag.so` | Jetson | `jetson/07-build-bos-detector.sh`, then `08-select-detector.sh bos --mwbd 20 --jpeg nvjpg` | Austin Schuh's current code (see below) plus our JNI wrapper in `detector/`. `--jpeg nvjpg` decodes the camera JPEGs on the Jetson's JPEG hardware (`libspectrumnvjpg.so`, see Performance), gray and colour; it uses ~180 MB of memory per camera. Leave it out to decode on the CPU. |
| 4 | PhotonVision fork jar | Laptop | `host/03-build-photonvision-fork.sh`, then `jetson/06-install-fork-jar.sh` | The 4143 fork, upstream v2026.3.4 (patch 00) and our patches 01–73. It builds on the laptop in about 30 s instead of taxing the Jetson. The Jetson runs it on Java 17. The build also bundles the training site (`training/`) as the sidebar's Documentation page, so the course works on the robot with no internet. |
| 4 | PhotonVision alpha-7 jar | Laptop | `host/03-build-photonvision-fork.sh`, then `jetson/06-install-fork-jar.sh` | Applies `patches/photonvision-2027-alpha7-migration.patch` to an exact source commit and runs on Java 25. The build also bundles the training site (`training/`) as the sidebar's Documentation page, so the course works on the robot with no internet. Real Jetson and robot-network tests are still required. |
| 5 | Camera driver with a bandwidth cap | Jetson | `jetson/11-uvcvideo-payload-cap.sh --install` | Needed for 3–4 cameras on the USB-A ports (see Performance). |
| 6 | TensorRT backend `libspectrumtrt.so` | Jetson | built by `07-build-bos-detector.sh`; install to `/usr/lib` | Game-piece detection. Models go in with `jetson/12-install-yolo-model.sh`. |
| 7 | USB controller watchdog | Jetson | `jetson/14-usb-watchdog.sh --install` | Resets the USB controller if the kernel says it died, so the cameras come back without a person. It never reboots (see Known issues). |
Expand Down
33 changes: 28 additions & 5 deletions detector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@ if(NOT EXISTS "${BOS_DIR}/third_party/971apriltag/apriltag.h")
message(FATAL_ERROR "BOS_DIR must point at a frc971/bos checkout")
endif()

set(ALLWPILIB_DIR "" CACHE PATH "AllWPILib v2027.0.0-alpha-7 source checkout")
set(ALLWPILIB_INCLUDE_DIR "${ALLWPILIB_DIR}/wpiutil/src/main/native/include")
if(NOT EXISTS "${ALLWPILIB_INCLUDE_DIR}/wpi/util/RawFrame.h" OR
NOT EXISTS "${ALLWPILIB_INCLUDE_DIR}/wpi/util/PixelFormat.h")
message(FATAL_ERROR "ALLWPILIB_DIR must contain the v2027.0.0-alpha-7 wpiutil headers")
Comment thread
Project516 marked this conversation as resolved.
endif()
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES "${ALLWPILIB_INCLUDE_DIR}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
check_cxx_source_compiles([=[
#include <wpi/util/PixelFormat.h>
#include <wpi/util/RawFrame.h>
int main() {
WPI_RawFrame frame{};
return frame.pixelFormat == WPI_PIXFMT_MJPEG ? 0 : 1;
}
]=] SPECTRUM_WPIUTIL_CXX20_HEADERS)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
if(NOT SPECTRUM_WPIUTIL_CXX20_HEADERS)
message(FATAL_ERROR "The JNI bridge must compile as C++20 with AllWPILib alpha-7 headers")
endif()

# Same globals frc971/bos's top-level CMakeLists.txt sets for its subprojects.
find_package(CUDAToolkit REQUIRED)
include_directories(${CUDAToolkit_INCLUDE_DIRS})
Expand All @@ -45,10 +68,10 @@ find_package(JPEG REQUIRED) # libjpeg-turbo (libjpeg-turbo8-dev), for decodeMjp
add_library(971apriltag_jni SHARED GpuDetectorJNI.cc far_search.cc fault_kernel.cu)
set_target_properties(971apriltag_jni PROPERTIES OUTPUT_NAME 971apriltag)
target_include_directories(971apriltag_jni PRIVATE ${BOS_DIR} ${JNI_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS})
${OpenCV_INCLUDE_DIRS} ${ALLWPILIB_INCLUDE_DIR})
# bos uses ABSL_FLAG (use_neon, debug_blob_index) but its CMake does not link absl::flags.
find_package(Threads REQUIRED)
target_link_libraries(971apriltag_jni PRIVATE 971apriltag absl::flags wpiutil CUDA::cudart JPEG::JPEG
target_link_libraries(971apriltag_jni PRIVATE 971apriltag absl::flags CUDA::cudart JPEG::JPEG
${JNI_LIBRARIES} Threads::Threads ${CMAKE_DL_LIBS})
# Fail at link time, not in the JVM, if a symbol is missing.
target_link_options(971apriltag_jni PRIVATE -Wl,--no-undefined)
Expand Down Expand Up @@ -94,19 +117,19 @@ endif()
# PhotonVision. Build it alone with --target fieldcal_detect.
add_executable(fieldcal_detect fieldcal_detect.cc)
target_include_directories(fieldcal_detect PRIVATE ${BOS_DIR})
target_link_libraries(fieldcal_detect PRIVATE 971apriltag absl::flags wpiutil CUDA::cudart JPEG::JPEG
target_link_libraries(fieldcal_detect PRIVATE 971apriltag absl::flags CUDA::cudart JPEG::JPEG
Threads::Threads ${CMAKE_DL_LIBS})

# SpectrumJetson: the far-tag search's bench test (far_search_test.cc): synthetic tags, no camera.
# tests/far-search/run.sh builds and runs it on the Jetson.
add_executable(far_search_test far_search_test.cc far_search.cc)
target_include_directories(far_search_test PRIVATE ${BOS_DIR} ${OpenCV_INCLUDE_DIRS})
target_link_libraries(far_search_test PRIVATE 971apriltag absl::flags wpiutil CUDA::cudart JPEG::JPEG
target_link_libraries(far_search_test PRIVATE 971apriltag absl::flags CUDA::cudart JPEG::JPEG
${OpenCV_LIBS} Threads::Threads ${CMAKE_DL_LIBS})

# SpectrumJetson: far_replay, a whole Rewind session through the detector with the far-tag search
# deciding as it does live (far_replay.cc). A command-line tool; tests/far-search/replay.sh.
add_executable(far_replay far_replay.cc far_search.cc)
target_include_directories(far_replay PRIVATE ${BOS_DIR} ${OpenCV_INCLUDE_DIRS})
target_link_libraries(far_replay PRIVATE 971apriltag absl::flags wpiutil CUDA::cudart JPEG::JPEG
target_link_libraries(far_replay PRIVATE 971apriltag absl::flags CUDA::cudart JPEG::JPEG
${OpenCV_LIBS} Threads::Threads ${CMAKE_DL_LIBS})
Loading
Loading