PhotonVision ships a Dev tag dated 2020 that never moves, and season-based versions besides
PhotonVision is the free, fast, and easy-to-use computer vision solution for the FIRST Robotics Competition.
At a glance
- What is it?
- The open-source vision stack for FIRST Robotics Competition, written in Java with C++ and a pnpm web UI, published under GPL-3.0. What is worth reading is the build surface: seven cross-compile targets, a deploy command that takes an IP and a password as separate Gradle properties, and five out-of-source repositories carrying the native acceleration.
- Who is it for?
- This fits a FRC team that wants vision software it can read, modify and ship, and that is comfortable with a Gradle toolchain and a WPILib cross-compile step. It does not fit someone who wants a library to import into another robot stack, since this is an application with a server, a web UI and a native image pipeline rather than a drop-in dependency.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A rolling Dev tag dated 2020 sits beside season-numbered releases
The release list has one entry that behaves differently from the others.
There is a release named Dev, labelled Latest Development Version, and its date is 2020-07-10. It is not an old release; it is a rolling tag for whatever is currently on the development branch, and its date is simply the last time the tag itself was moved in a way that GitHub records as a new release object.
The other two entries are ordinary and follow a season-based scheme: v2026.3.4 published 2026-04-10, and v2027.0.0-alpha-2 published 2026-05-27. The numbers are the competition year and a build counter, so a team starting a new season is expected to move from a 2026 release to a 2027 one.
The alpha designation matters more than the number. A 2027 season build that is still on an alpha means the current release line for the coming year is not finished.
Platform-specific jars and container images are published from the releases page rather than built by users, which is the intended path for most teams.
Deployment over SSH is three separate properties carrying an address and a password
The Gradle properties are documented as case sensitive, which is a warning that the build fails silently rather than loudly when a name is wrong.
Three of them exist purely to move the fat JAR to a robot:
- -PtgtIP is where ./gradlew deploy should copy the fat JAR to. - -PtgtUser is the custom username for that SSH connection. - -PtgtPw is the custom password for that SSH connection.
So the deploy target is three loose strings on the command line, with the credential in plain text in a shell history and in any CI log that echoes the invocation. There is no mention of a key file or an agent in the documented options.
The other properties cover the build rather than the transfer. -PArchOverride builds for a target other than the current architecture, with seven valid values: winx86-64, winarm64, macx86-64, macarm64, linuxx86-64, linuxarm64 and linuxathena. -Pprofile turns on JVM profiling, and -PwithSanitizers enables -fsanitize=address,undefined,leak on Linux.
Note that linuxathena is in the list, which reflects the coprocessor platform family the project targets rather than a general-purpose build option.
Cross-compiling means installing the WPILib toolchain through Gradle first
Building a native image for a coprocessor is a two-step operation, and the first step is easy to miss.
Gradle is used for all C++ and Java code, and pnpm is used for the web UI. When you cross-compile, the WPILib toolchain has to be installed, and the documented way to do that is through Gradle itself:
./gradlew installArm64Toolchain
./gradlew installSystemCoreToolchainThe two commands cover the ARM64 cross toolchain and the system core toolchain. Fetching these outside Gradle is not the supported path, which means the toolchain version is tied to the build script rather than to whatever is on the machine.
Tool versions for the rest of the repository are pinned in files rather than left to the host. A .nvmrc pins the Node version used for the web UI, and a .python-version pins Python, which is what the documentation toolchain needs. There is a .clang-format for the C++ side and two .wpiformat files tied to WPILib formatting.
That is four separate version pins for a project whose own versioning is season-based, and all of them have to agree before a cross-compiled image will build.
Five sibling repositories carry the native acceleration, two of them for third-party NPUs
PhotonVision is not self-contained at build time. It pulls from five out-of-source repositories, and the list explains what the hardware support actually costs.
One provides base system images for supported coprocessors. Another is a C++ driver for Raspberry Pi CSI cameras. The remaining three are JNI bindings: one for mrcal, one for RKNN, and one for the Rubik Pi NPU.
Two of those five exist to accelerate inference on hardware PhotonVision does not own. RKNN and the Rubik Pi NPU are vendor parts, and the bindings are maintained here as forks rather than consumed from the vendors, which means an upstream SDK change shows up as a bug in this project rather than as a version bump.
The CSI camera driver is the same story for the Raspberry Pi, where the camera stack moved to libcamera.
So a working coprocessor image is an assembly of six repositories, and none of the five are pinned to a version in this tree. Anyone reproducing a build needs to match them deliberately, because the default branch of each is what gets used.
Three serialization libraries ship together, and one module exists to hold them
The dependency list is long enough to be a specification of the system, and three groupings stand out.
Serialization appears three times over: Avaje jsonb, MessagePack for Java, and QuickBuffers. JSON as a schema reference is listed alongside them. That is a deliberate choice for a system that has to speak to coprocessors over a network, and it explains why the repository has both a photon-serde/ directory and a photon-serde-tests/ directory, with the serialization layer isolated enough to have its own test module.
Persistence is SQLite through the JDBC driver, which is how a coprocessor holds configuration and results on a device that may have limited storage.
The rest of the stack is identifiable by role. Javalin is the web server, picocli is the command line parser, OSHI reports host and hardware information, which is what coprocessor detection would use, diozero handles Raspberry Pi GPIO, and EJML is the linear algebra library behind pose and target solving. Commons IO and ZT ZIP handle files and archives, and build.gradle wires them together.
Apache Commons is credited specifically through Commons IO, and WPILib specifically through allwpilib and their build of OpenCV, so the vision maths comes from WPILib's fork rather than a stock OpenCV.
Three example projects ship, and the documentation is spread across four sites
The examples are unusually prominent for a project of this size, and they come in three languages.
There is a photonlib-java-examples directory, a photonlib-cpp-examples directory, and a photonlib-python-examples directory. The Java and C++ sets are the ones the README points at, describing each as containing a fully featured robot project, and noting that some include simulation support. They can be run straight from the command line rather than only inside a full team project.
Simulation support is worth pausing on, because a vision pipeline is exactly the kind of code that is painful to test on hardware. Running an example without a robot is the cheapest way to see whether a pipeline change works at all.
Documentation is split four ways: the main documentation site at docs.photonvision.org, a live Photon UI demo at demo.photonvision.org, Java javadocs at javadocs.photonvision.org, and C++ Doxygen output at cppdocs.photonvision.org. In the repository itself there is a docs/ directory, a separate photon-docs/ directory and a website/ directory, so there are three sources of documentation content in one checkout.
Compile instructions and the instructions for running the examples both live in the contributor documentation rather than in the README, which is why this README is short.
A fork of Chameleon Vision, shipped under GPL-3.0 with a license compliance folder
The project states that it was forked from Chameleon Vision, with thanks to everyone who worked on the original, which places it inside the FRC vision ecosystem rather than treating it as a greenfield tool.
The licence is the GNU General Public License, and the repository root carries an ExternalLicenses/ directory alongside LICENSE. That folder exists to hold the licences of everything bundled in, and its presence is a GPL obligation rather than a stylistic choice.
The bundled third-party list is long and specific. WPILib is credited through allwpilib and their OpenCV build. Apache Commons through Commons IO. Then picocli, diozero, EJML, Javalin, JSON, Avaje jsonb, MessagePack for Java, OSHI, QuickBuffers, SQLite JDBC and ZT ZIP.
For a team considering it, the licence is the practical point. GPL-3.0 is fine for a robot you own, and it is worth being deliberate about if any part of the pipeline is intended to end up inside a product you distribute.
There is no public issue tracker mentioned here; coordination runs through a Discord server and meeting notes held in the repository wiki.
Editorial conclusion
This fits a FRC team that wants vision software it can read, modify and ship, and that is comfortable with a Gradle toolchain and a WPILib cross-compile step. It does not fit someone who wants a library to import into another robot stack, since this is an application with a server, a web UI and a native image pipeline rather than a drop-in dependency. Two things to plan around. First, the native acceleration lives outside this repository in five sibling projects, including two bindings for third-party NPUs, so a build that only clones the main tree will not produce a working coprocessor image. Second, versions are season-based, moving from 2026.3.4 to a 2027.0.0 alpha, so pin a release rather than tracking main. The last push is dated 2026-10-01.
Frequently asked questions
What is PhotonVision used for?
It is the free computer vision solution for the FIRST Robotics Competition. It builds platform-specific jars and images that run on supported coprocessors, with a Java and C++ client library, a server and a web UI.
Is PhotonVision free to use?
Yes. It is described as free and open source, licensed under the GNU General Public License, with jars and images published from the repository releases page and no paid tier mentioned.
How do I build PhotonVision from source?
Gradle builds all C++ and Java code and pnpm builds the web UI. Cross-compiling requires the WPILib toolchain to be installed through Gradle with commands such as ./gradlew installArm64Toolchain and ./gradlew installSystemCoreToolchain. A .nvmrc and a .python-version pin the Node and Python versions.
What are the PhotonVision Gradle arguments?
They are case sensitive. -PArchOverride selects one of seven targets including linuxathena and macarm64, -PtgtIP, -PtgtUser and -PtgtPw control where ./gradlew deploy copies the fat JAR and the SSH credentials used to get it there, -Pprofile enables JVM profiling, and -PwithSanitizers enables address, undefined and leak sanitizers on Linux.
Does PhotonVision need anything outside its own repository to build?
Yes. Five out-of-source repositories are used, covering base coprocessor system images, a C++ driver for Raspberry Pi CSI cameras, and JNI bindings for mrcal, RKNN and the Rubik Pi NPU. The RKNN and Rubik Pi bindings are for third-party accelerator hardware.
Can I run PhotonVision examples without a robot?
The Java and C++ example directories each contain a fully featured robot project and some include simulation support, and the README states they can be run straight from the command line. A Python examples directory also exists.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/photonvision-photonvision)