Compare commits

...

149 Commits

Author SHA1 Message Date
Matt M
d9ada4c26c dont download 2024-11-07 11:31:50 -08:00
Matt M
535e5d02f9 oops 2024-11-07 11:20:10 -08:00
Matt M
38f40bf03d oops 2024-11-07 11:19:22 -08:00
Matt M
7cc491536b oops 2024-11-07 11:15:31 -08:00
Matt M
66ccc35840 kill all other workflows 2024-11-07 11:14:43 -08:00
Matt M
812dc61b33 asdf 2024-11-07 11:12:39 -08:00
Matt M
dbbdc14c7c Fix TSP table 2024-11-06 13:34:33 -08:00
Matt
cf73f981b7 Publish vendor JSON in releases 2024-11-06 13:34:33 -08:00
Kouyang07
a99a8e750b Fixed Python code block being in C++ block (#1527) 2024-11-06 12:41:13 -05:00
William Toth
a0b22cd8a3 Update docs to specify that WPILib JDK is required on Windows (#1522) 2024-11-04 23:27:49 -05:00
Cameron (3539)
5d55d215ec Another config matching bug (#1518)
This is quite an odd issue/fix. 

So this is what happened... Photonvision booted with the camera
connected and the camera was working...
After a short time the camera stopped working (for some reason maybe
static, maybe temp, maybe wiring, idk).
During this time pv showed

Jul 04 06:25:18 BackLeft java[643]: [2024-07-04 06:25:18] [CSCore -
PvCSCoreLogger] [ERROR] CS: ERROR 40: ioctl VIDIOC_QBUF failed at
UsbCameraImpl.cpp:723: Invalid argument (UsbUtil.cpp:156)
Jul 04 06:25:18 BackLeft java[643]: [2024-07-04 06:25:18] [CSCore -
PvCSCoreLogger] [WARN] CS: WARNING 30: BackLeft: could not queue buffer
0 (UsbCameraImpl.cpp:724)

I went over and played with the wire. The camera fully disconnected but
it ended up "reconnecting"
When the camera was "reconnected" photonvision detected a "new camera"
except this time with no otherpaths (aka no usb path, or by id path).
That resulted in pv creating a new camera configuration for a camera
with no otherpaths
Cscore then started to report errors that look like it attempted to
connect to the same camera twice

This fixes it by filtering out USB cameras that have no otherpath on
linux.
2024-11-04 21:50:18 -05:00
Craig Schardt
625dacb020 Add QuadThresholdParameters to AprilTag config (#1519)
This works around a change made to the default QuadThresholdParameters in the WPILib AprilTagDetector for 2025.
https://github.com/wpilibsuite/allwpilib/pull/6847
2024-11-03 21:53:53 -06:00
Matt
fc8ecac376 Create TSP Server in C++ photonlib (#1516)
Automatically starts a TCP server in C++. Also adds warnings to Python.
2024-11-01 23:32:38 -07:00
Jade
75e2498f53 Fix typos (#1508)
Signed-off-by: Jade Turner <spacey-sooty@proton.me>
2024-11-01 23:51:16 -04:00
Matt
7a4ea3dd56 Assert that version checking won't throw on startup (#1512)
# Overview

Previously if the coproc came up later, getProperty would return the
string literal "null", which made us print the BFW. Add tests to make
sure that we don't do that anymore by rebooting a sim coproc +
robot in a combination of different orders.
2024-11-01 23:50:21 -04:00
Jade
5e1a93950e Fix photon-targetting being a seperate project (#1504) 2024-10-31 22:23:52 -07:00
Jade
380546cee0 Remove nonsensical settings.gradles (#1506) 2024-10-31 22:23:12 -07:00
Cameron (3539)
d7a7610917 Fix videomode is null (#1513)
There is a weird edge case at least with arducam/broken arducams/used
arducams where cscore will see it when pv starts but not be able to
connect to it. If we always read out the "current" video mode instead of
null when it is disconnected things will work. If the camera is
disconnected while we try to change the video mode when we get the
current video mode it will tell us what we wanted to set it to. Then
when the camera reconnects it will be in that video mode.
2024-10-31 23:13:36 -04:00
Matt
37aaa49b32 Create timesync JNI for testing client (#1433) 2024-10-31 08:27:19 -07:00
Cameron (3539)
937bafa8e2 Bump to WPILib 2025 Beta 1 & remove C++ protobuf (#1484)
Remove C++ protobuf support until
https://github.com/wpilibsuite/allwpilib/issues/7250 is addressed.
Developers should upgrade to wpilib vscode 2025 beta 1.

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-10-31 02:59:39 -04:00
Matt
3d18ded3f6 Link to wpilib javadocs in ours (#1509)
![image](https://github.com/user-attachments/assets/d197b637-bf52-4a03-bf55-32a45fff8b06)
2024-10-29 17:11:53 -07:00
Jade
daa5842fb5 Remove explicit NativeUtils specification (#1495) 2024-10-28 09:18:12 -07:00
Emmy Chow
6f52267c26 Install script improvements (#1456) 2024-10-27 15:07:28 -07:00
Craig Schardt
acbae88d34 Reduce log spam if network monitor fails (#1494)
This prevents spamming of the logs by the network interface device
monitor by:

- checking to make sure the device file exists before starting the
monitoring task
- only logging once if it throws an exception, but keep trying in case
the exception is transient
2024-10-27 16:33:14 -05:00
42
986c7020c3 docs: update link to PhotonVision running examples (#1493) 2024-10-26 15:15:34 -07:00
42
eb7a56abaf docs: fix incorrect link to PhotonVision compiling instructions (#1492) 2024-10-26 14:37:02 -07:00
Matt
d04c4b8231 Re-set config save default state to true (#1489)
Previously, no config updates were ever saved out. At all. Oops.
2024-10-25 23:41:48 -04:00
Matt
f8e25ced89 Add aliases, allow v2024.3.1 setting import (#1487)
Was easy enough to add annotations. Ongoing work to remove these hacks post 2025 is tracked in https://github.com/PhotonVision/photonvision/pull/1487
2024-10-25 23:04:08 -04:00
Matt
f906295c39 Create "Hide calibration corners" switch, default to mrcal on if possible (#1462) 2024-10-25 10:05:03 -07:00
Matt
aee432127a Add AWB slider/toggle (#1477)
Also reworks OV9782 defaults. Probably doesn't work on windows. We should hide these sliders probably. 

Co-authored-by: Cameron (3539) <theforgelover@gmail.com>
2024-10-25 00:27:40 -07:00
Matt
385059c233 Big scary buttons (#1471) 2024-10-24 20:48:02 -07:00
Cameron (3539)
9b61ed156c Fix VisionSourceManagerTest typo (#1486) 2024-10-22 22:23:29 -04:00
Cameron (3539)
8eaa6904dd Equal only by usb paths (#1481)
This bug would only appear when there are cameras with the same naming.
Old config matching would also match using the by-id this was
problematic. When one camera is disconnected it would assign the by-id
path to the other camera with the
same name. When the camera is replugged in it would not be reassigned
the by-id path and would fail the camerainfo equals check.
2024-10-21 10:37:00 -04:00
Matt
7da2ec1948 Fix PhotonCamera typestring checks (#1480)
Previously NT would quietly drop readQueue changes.
2024-10-20 22:21:24 -07:00
Cameron (3539)
7224561b76 Add slider debounce (#1479)
Sliders for exposure and brightness would spam messages on the backend.
This used to cause crashes and can cause it to get quite laggy /
delayed. This will add a 20ms debounce which won't send the value to the
backend until the value hasn't changed for 20ms.

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-10-21 00:48:01 -04:00
Craig Schardt
4c84c87cf4 Bump Raspberry Pi images to v2025.0.0-beta-6 (#1483)
Fixes #1482
2024-10-20 22:59:25 -05:00
Craig Schardt
8ff0d93c1f Improve network management (#1478)
This PR changes the way that photonvision interacts with nmcli to control networking on the coprocessor. Instead of modifying an existing connection, Photonvision adds new connections for DHCP and Static IP configurations. It then activiates the proper one at startup and any time that the network configuration is changed.


It also now uses the interface name and not the connection name and checks that the interface is available before making any changes. If the saved interface is not found, it updates the stored interface name and applies the network settings to the current interface. This should minimize the failure to control the network if the network interface wasn't available when PhotonVision first booted.

One other benefit of not altering the default configuration is that, if PhotonVision fails to run for any reason, the device can be accessed using the original networking configuration.

The code has been tested on an OrangePi5 and and a Raspberry Pi 4.

Addresses: #1261
2024-10-20 22:23:50 -05:00
Cameron (3539)
b38de6b506 Calibration Rotation! (#1464)
Rotate camera calibration coefficients based on camera rotation. Probably. Seems to work. Maybe.

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-10-19 01:23:23 -04:00
Cameron (3539)
388b3fa2ef Default 36h11 (#1470) 2024-10-14 22:33:03 -04:00
Cameron (3539)
028b6ea62f Fix reflective null points (#1469) 2024-10-14 20:31:19 -04:00
Cameron (3539)
c961f1e22e Fix apriltag detection draw bug (#1467)
We accidentally copied more settings then we wanted. This adds an
annotation that we can mark variables with that will prevent them from
being copied when we switch pipeline types.
2024-10-14 20:30:27 -04:00
Cameron (3539)
189da52a77 Fix aruco draw (#1468)
Someone hard-coded the 16h5 model. Additionally, the April tag pipeline
redistorts the points before drawing them, so let's do that as well.
2024-10-14 20:15:08 -04:00
Cameron (3539)
48fc88c5e9 ChArUco: adjust detector params, hide unused (#1463) 2024-10-13 16:42:53 -04:00
Matt
30ee91379e Copy common fields when changing pipeline type (#1461)
Preserve common AdvancedPipelineSettings fields when switching pipeline types. This includes camera resolution, exposure settings, and stuff
2024-10-13 14:52:13 -04:00
Matt
353a8eaaec Add FMS info to snapshot names (#1460)
Supersedes #464

Co-authored-by: Ofir Siboni <050ofir@gmail.com>
2024-10-13 12:47:57 -04:00
Cameron (3539)
09b1bb9e22 Fix client log view (#1459)
Someone forgot to add the timestamp.
2024-10-13 02:13:21 -04:00
Matt
26f3a9977b Create AprilTag pipeline by default (#1458) 2024-10-13 01:38:25 -04:00
Cameron (3539)
0766d0e802 Fix large calibration datasets crashes (#1453)
The target list in networktables is limited to 127 items. When you
capture more than 127 calibration images it breaks this limit and errors
out and dies. Do not publish calibration targets to nt. And also move cal images into their own folder
2024-10-13 01:29:17 -04:00
Cameron (3539)
d9b6199cf0 Dont send SolvePNPEnabled in drivermode. (#1454)
There are no settings for solvePNPEnabled while in driver mode but the
UI tries to set it. Let us not do that.
Fixes #1377

Co-authored-by: Chris Gerth <gerth2@users.noreply.github.com>
2024-10-10 23:27:16 -05:00
Chris Gerth
91da7af171 latest is correct is not correct (#1455)
Ubuntu 24 borked for most of our CI. something to do with glibc


https://discord.com/channels/725836368059826228/725846784131203222/1294138369177157832

it always should have been at a fixed version. Now it is.
2024-10-10 23:13:58 -05:00
Cameron (3539)
471c90e8fa UI Message Passing (#1448)
Bring the UI setting changes in thread with the camera.
2024-10-08 23:06:43 -04:00
Cameron (3539)
142e22ff24 Object detection OOM crash (#1451)
Don't return before we release the object.
2024-10-08 22:01:51 -04:00
Cameron (3539)
c4b273e737 Reduce pipeline use-after-free errors (#1447) 2024-10-07 11:35:18 -04:00
Stephen Just
cd9dd07282 Camera view updated to better respond to state (#1437) 2024-10-05 22:26:14 -07:00
George Horsey
3225c079d3 Update calibration.md OpenCV Docs Link (#1445)
Link had ">" at the end of the URL causing a 404 error.
2024-09-30 23:40:41 -04:00
Craig Schardt
95d55dc977 Add-OrangePi5max-image (#1444)
Completes #1420
2024-09-30 22:21:44 -05:00
Jade
95236e5045 [docs] Fix usage of getTagPose (#1442) 2024-09-29 11:43:02 -04:00
Jade
30e930f051 [docs] Fix invalid max error bits recommendation (#1443) 2024-09-29 11:42:19 -04:00
Jade
68adfe6034 [docs] Remove gerth2 links (#1441)
Resolves https://github.com/PhotonVision/photonvision/issues/1418
2024-09-29 09:55:36 -04:00
Christopher Mahoney
abe95dfaa0 Update poseest.md (#1439)
This space is the root cause of failures in #1437.

RE: #1430
2024-09-29 06:55:46 -05:00
Chris Gerth
354f11a6d6 Fix broken links (#1430) 2024-09-24 18:19:49 -05:00
Banks T
b7cab0431d See3Cam_24CUG Quirks (#1302)
Co-authored-by: Matt <matthew.morley.ca@gmail.com>
Co-authored-by: Chris Gerth <chrisgerth010592@gmail.com>
2024-09-24 18:18:59 -05:00
Chris Gerth
a8daff3ed4 Revised 9782 defaults (#1431)
revised order to prevent some randomness around init
2024-09-24 00:02:16 -05:00
Matt
a0c85fc95f Create photon-targeting-JNI framework (#1428)
Initial framework for adding JNI libraries. Auto generated JNI headers and sticks native libraries into the JAR (and adds to class path for testing)
2024-09-23 22:44:09 -04:00
Matt
f33218c49c Add message UUID and type names to hash and message defintion (#1409) 2024-09-22 22:27:13 -04:00
Stephen Just
360298cc24 Fix error being printed to console on Chrome when navigating UI (#1429)
Chrome prints an error to the console when you have `<img src="null" />`

The path `//:0` can be used for an empty image and Chrome will not raise
an error.
2024-09-21 16:11:58 -04:00
Christopher Mahoney
27cb69c094 Support selecting Object Detection models (#1359)
This PR is for part 1 of #1354. It focuses on adding a model selection
interface for models that exist in `photonvision_config/models/`. Upon
completion we can ship more than 1 model and users could upload their
own through `ssh` without deleting the shipped model. This PR also adds
the abstractions need to support more DNN backends (say OpenCV, or RPI
AI Kit)

Up next is adding a CRUD interface for managing models through the UI.
2024-09-21 16:08:00 -04:00
Craig Schardt
24fb6af5f4 Fix setting gain to max on cameras that don't have a gain quirk (#1424) 2024-09-15 23:40:27 -04:00
Cameron (3539)
546058593e Roll Back to 2024.3.2 (#1423)
Roll back to 2024.3.2 to get some good testing on actual robots.
2024-09-15 20:01:11 -04:00
Chris Gerth
9e6a066561 Examples Clean-Up (#1408) 2024-09-15 00:10:02 -04:00
Christopher Mahoney
596c87519c fix: reflection bug in onDataChangeEvent (#1416) 2024-09-12 14:08:57 -04:00
Drew Williams
06f0f7d66f Fixes windows not allowing auto exposure prop for the ov2311 (#1407) 2024-09-03 22:17:10 -04:00
Devon Doyle
c38b50911d [photon-client] Log Viewer Improvements (#1385)
Fixes the following issues with the client log viewer:
- Inconsistent and excessive spacing between log entries
- Lack of responsiveness to window size or scaling

Adds the following features to the log viewer:
- Auto-scroll if scrolled to the bottom
- Ability to clear logs on button click
- Search function to filter logs
- Displays the time the frontend captured a log and displays that timestamp in hh::mm::ss in the log viewer
- Allows logs to be filtered to be after a certain time
- General styling refinements to increase usability

---------

Co-authored-by: Sriman Achanta <68172138+srimanachanta@users.noreply.github.com>
2024-08-31 18:22:07 -04:00
Matt
169595e56e Auto-generate packet dataclasses with Jinja (#1374) 2024-08-31 13:44:19 -04:00
Mohammad Durrani
c19d54c633 Removed CalibDB (#1396) 2024-08-31 12:31:49 -04:00
Matt
738e3646f7 Photonlibpy - Best Target Function #1223 (#1406)
Supercedes https://github.com/PhotonVision/photonvision/pull/1223

---------

Co-authored-by: vladb <vlad.bondar@frc5113.com>
2024-08-31 12:30:09 -04:00
Jade
50ea32c82d Fix getTarget docs (#1404) 2024-08-29 01:20:03 -04:00
Stephen Just
8c09cd2cb3 Populate CameraSettingsStore with placeholder value if no cameras are present (#1401) 2024-08-25 08:10:45 -04:00
Stephen Just
c33fd8362d [photon-client] Bump node to V18 (#1402)
* Bumps minimum NodeJS requirement to v18 (already used as part of
official builds)
* Prerequisite for latest VueJS
2024-08-24 22:58:33 -04:00
Cameron (3539)
2e4be684be Update RPI Image 7/4/24 (#1373)
Bump libcamera version to support new pi image.
2024-08-22 21:10:03 -04:00
Cameron (3539)
ed6cf0f5dc Document Charuco (#1398)
You know... I made those charuco changes now I need to document how it
works... basic stuff.

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-08-19 20:35:02 -04:00
Mohammad Durrani
4643f86438 Switch from RST to MyST Markdown (#1395) 2024-08-18 14:05:23 -04:00
vic123
0493ef9133 Document how to install PhotonLib of specific version (#1392) 2024-08-18 00:37:45 -04:00
Craig Schardt
c5c2a7a6f9 Add OrangePi5b image to generated images (#1394) 2024-08-17 14:20:19 -04:00
Chris Gerth
f1d1d325e0 Move to using Absolute Exposure Range (#1352)
Uses logic in
https://github.com/PhotonVision/photon-libcamera-gl-driver/pull/16 to
push the ov9281 down to its true minimum exposure.

Updates UI to list the exposure settings in ~~microseconds.~~ Native
units - not everyone works in microseconds.

Does its darndest to actually try to set the exposure in
~~microseconds.~~ Native Units. To do this...

Lifecam is funky when doing this - [cscore limits the exposure settings
to certain quantized
values](https://github.com/wpilibsuite/allwpilib/blob/main/cscore/src/main/native/linux/UsbCameraImpl.cpp#L129).
Add a new camera quirk to allow that.

~~Updated camera quirks to re-evaluate every camera load (rather than
recalling from settings - this shouldn't be necessary)~~ This should be
rolled back, needed for arducam type selection.

Updated camera quirk matching logic to make PID/VID optional, and
basename optional (and only match trailing characters). This enables
mirroring CSCore's logic for identifying lifecams by name.

Updated the USBCamera to primarily use cscore's exposed property names.

Since camera manufacturers use a potpourri of names for the same
thing....

For nice-to-have settings: new soft-set logic to try all possible names,
but gracefully pass if the property isn't there.
For required settings: Search a list for the first setting that's
supported, fail if none are supported.

More logging of camera properties to help debug.

Note: most of this work is because cscore doesn't directly expose a
massaged exposure-setting-absolute API (and, given what we've seen,
probably _shouldn't_, this struggle is not for the faint of heart).

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-08-17 10:02:59 -05:00
Craig Schardt
dbe566cb55 Update install.sh for OPi5 Ubuntu 24.04 (#1390)
This updates the install script to work correctly on Ubuntu 24.04
versions of the Orange Pi 5 images.

Changes include:
- installing libatomic1
- disabling networkd-wait-online if using Network Manager
- using systemctl instead of service to detect if photonvision is
running
- detecting if this is a RK3588 cpu and enabling all cores
2024-08-13 10:54:26 -04:00
Matt
c3302045d9 Add rsync & sphinx-autobuild docs (#1391) 2024-08-12 11:01:04 -04:00
Jade
ac1fc2a46b Add API docs to sidebar (#1383) 2024-08-04 21:58:54 -04:00
Matt
67463a020a Use ReadQueue for PhotonCamera timestamps (#1316)
This removes the extra GetLastChange call to keep everything properly
atomic.

Closes #1303
2024-08-04 14:23:46 -04:00
Craig Schardt
37e9d40762 Use new OrangePi5 images and add OrangePi5 Pro (#1388) 2024-08-03 21:57:35 -04:00
Matt
974a926e75 Run wpiformat (#1379) 2024-08-02 11:57:34 -04:00
Cameron (3539)
d1e7fd4db9 Revert "Use pnpm instead of npm" (#1382)
Reverts PhotonVision/photonvision#1375

Causes white screen UI Bug, "the way we currently strap everything with
vue2 and vuetify has a lot of footguns in it, and using a newer package
manager where each subdependency gets its own version of node is causing
incorrect dependency resolution which also means we can't fix this
without either updating node or patching those dependencies id say just
revert the PR for now until I or someone else can do the vue3 update"
2024-07-31 12:45:10 -04:00
MADMAN-Modding
10f74bb623 Fixed spelling error (#1376) 2024-07-24 16:38:49 -04:00
Sriman Achanta
3c58b05af7 Use pnpm instead of npm (#1375)
Pnpm is like npm except instead of keeping multiple copies of
dependencies, it shares a single copy for multiple dependencies
significantly reducing build time and the space needed to hold all the
dependencies. Read [here](https://pnpm.io/motivation) for more info.

This changes our CI to use pnpm and allows developers to choose to use
pnpm instead of npm. Also, pnpm has a built-in node version manager so
devs no longer need to use nvm to work on photonvision. All npm
functionality (including photon-server gradle tasks) still functions
using npm so this isn't breaking. We should make a docs change to
suggest to use pnpm.
2024-07-24 00:45:19 -04:00
Matt
9ad9b8288a Update docs on docs about docs (#1360) 2024-07-04 17:15:51 -04:00
Cameron (3539)
fab75918da Fix OV9782 typos (#1358)
There were a couple of typos in the last OV9782 fix, this addresses
those. Additionally, remove Matt's comment that he forgot.
2024-07-01 22:14:22 -04:00
Gautam
173b6d9ca8 Adds support for OV9782's quirks (#1284)
The OV9782 camera has a specific exposure range, so a camera quirk for
it needs to exist. The default white balance is also pretty bad, so it
must be adjusted.

Closes #1204

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
Co-authored-by: Cameron (3539) <theforgelover@gmail.com>
2024-07-01 18:54:20 -04:00
Matt
e7e59ed2d4 Rename .readthedocs to match RTD 2024-06-30 20:47:13 -07:00
Matt
dcc7ddc19b Move docs in-source (#1357) 2024-06-30 16:10:12 -04:00
Matt
0cdd9a74d0 Bump wpilib to 2025.0.0-alpha-1 and break non-FRC JDKs (#1356)
Windows users will have to add
`"-Dorg.gradle.java.home=C:\Users\Public\wpilib\2024\jdk"` to gradle
invocations, ie `./gradlew run
"-Dorg.gradle.java.home=C:\Users\Public\wpilib\2024\jdk"`, due to MSVC
ABI breakages and other stupidity
2024-06-30 02:08:58 -04:00
Cameron (3539)
8c45fef62a Support more charuco boards (#1348)
Add support for the old opencv charuco board like calibio. 

Add support for other tag families while calibrating.

Fix calibration issue index out of range with charuco missing points.
2024-06-20 21:29:00 -04:00
Cameron (3539)
1d9810505a fix CSI camera null quirks error (#1349)
temp fix for this issue with csi cameras
2024-06-19 19:09:52 -04:00
Matt
8f0cc0ab8b Revert "Warn when getBestCameraToTarget returns 0, 0, 0 (#1334)" (#1351)
This reverts commit 6ff7b3e143. See #1351 for context
2024-06-17 22:38:16 -04:00
Cameron (3539)
0105df9ad4 Bump libcamera driver version (#1346)
* Update build.gradle
2024-06-12 18:06:25 -04:00
Matt
292c7a10d4 Only publish to maven on main fork (#1345) 2024-06-11 16:31:05 -04:00
Matt
230e73749f Only download necessary files in release step (#1344) 2024-06-11 09:36:34 -05:00
Matt
655909cc84 Create combine job and offline vendordep ZIP (#1343)
* Create combine job

* Update build.yml

* Bump max workers in photonlib

* Oops

* actually kill entirely

* Maybe fix test

* Don't run tests

* Update OpenCVTest.java

* Update build.yml

* Use upload-artifact@v4

* Update build.yml

* Update build.yml
2024-06-10 20:37:01 -05:00
Matt
5289948b83 Add photon.pb.h/PhotonVersion to cpp headers zip & create combined sources zip (#1335)
Combined sources zip is useful for robotpy to build both targeting & lib in the same build
2024-06-09 17:18:57 -04:00
Cameron (3539)
7b19a951ca Camera Lost Stream (#1341)
* Fix no stream on camera unplug.

* Spotless remove datarate

* Make Static Frames Class

* lint and format
2024-06-06 20:46:46 -05:00
Cameron (3539)
db531f1b6a Fix libcamera not found bug (#1326)
* Update build.yml
2024-06-02 16:16:43 -04:00
Jade
6ff7b3e143 Warn when getBestCameraToTarget returns 0, 0, 0 (#1334)
Resolves https://github.com/PhotonVision/photonvision/issues/915
2024-06-01 13:28:00 -04:00
Jade
e34b114669 Change default AprilTag family to 36h11 (#1333)
Change default AprilTag family to 36h11

Resolves https://github.com/PhotonVision/photonvision/issues/1226
2024-05-30 20:30:40 -04:00
Matt
f792b46eb7 Fix mac released jar naming (#1332) 2024-05-29 20:13:24 -04:00
Matt
19b4802094 Allow opencv8 distortion model in PhotonCamera (#1317)
We previously assumed only OpenCV5 but mrcal uses opencv8
2024-05-29 17:28:35 -04:00
Matt
fcca858a37 Update maven URL to reposilite (#1330)
Also bumps to new builds of artifacts (NFC)
2024-05-29 12:29:08 -05:00
Matt
9eae7a4431 Disable transitive deps for rknn-jni (#1329) 2024-05-26 18:43:06 -05:00
Matt
0eeedf49fc Publish generated proto sources (#1328) 2024-05-26 14:02:37 -05:00
Matt
98633e9150 Bump wpilib to latest dev (#1327) 2024-05-26 14:02:07 -05:00
Matt
ed08e2a78f Move PhotonVersion to C++ file (#949)
This was supposed to speed up incremental compilation, but not sure it actually does. It's better form tm tho and fixes a robotpy-wrapper weirdness
2024-05-24 23:22:31 -04:00
amquake
12cb082f1b Update README.md (#1321) 2024-05-19 20:37:13 -04:00
Drew Williams
74a051d721 [PhotonLib C++] Fix SetVersionCheckEnabled to actually disable version checking (#1323)
* change verifyversion to use member variable

* Revert "change verifyversion to use member variable"

This reverts commit 4439839c8f.

* Removed inline specifier for versioncheck variable

---------

Co-authored-by: Drew Williams <DrewW@iARx.com>
2024-05-19 20:36:44 -04:00
Craftzman7
9e58f5ed02 Disable Arm32 Builds (#1325)
Disables Arm32 builds and removes mention of the build option in the README.
2024-05-19 20:35:40 -04:00
Matt
713fad6f6b Allow file uploads of any size and better report active cameras in PhotonCamera error print (#1298)
Previously reported itself which was confusing. New print:

```
Error at org.photonvision.PhotonCamera.verifyVersion(PhotonCamera.java:378): Found the following PhotonVision cameras active on NetworkTables:
 ==> HD_Pro_Webcam_C920
 ==> Arducam_OV9281_USB_Camera
```
2024-05-10 14:58:18 -04:00
Matt
1708376df8 Expose object detection class id/conf in photonlib (#1266)
* Implement class id/conf in photonlib

* Maybe fix things

* run lint

* Update Packet.java comments

* Update Packet.java comments again

* Update comments

* oops

* Update packet.py

---------

Co-authored-by: Chris Gerth <gerth2@users.noreply.github.com>
2024-05-10 14:52:16 -04:00
Matt
113951100e Add sequence ID, capture, publish and recieve timestamp to PhotonPipelineResult (#1305)
Closes #1304
2024-05-10 14:04:34 -04:00
Programmers3539
70c2cdebe0 Charuco Support (#1312)
Add charuco calibration to photonvision. Currently does not support generating custom charuco boards. This does not support https://calib.io/pages/camera-calibration-pattern-generator. Currently only supports the 4X4_50 family. Also removes all dotboard calibration. Fixes using the lowest possible fps while doing calibration (now uses the highest fps available for each resolution).
2024-05-10 13:12:13 -04:00
Matt
560f379109 Bump libcamera to fix picam v1, remove duplicate opencv (#1263) 2024-05-10 11:09:01 -05:00
Matt
00c2a25730 Undistort corner pitch/yaw using opencv (#1250)
* Undistort pitch/yaw

* Actually implement lol

* Update TargetCalculations.java

* fix yawpitch test units

* format

---------

Co-authored-by: amquake <noleetarrr@gmail.com>
2024-05-02 21:17:28 -04:00
Drew Williams
6535710fc4 Change sim to use 36h11 tags when doing multitag (#1314) 2024-04-29 16:19:03 -04:00
Matt
c9a696225d Kill deprecated things (#1311) 2024-04-27 11:32:36 -05:00
Devon Doyle
010688006a [Client] Fix issue with clearing multitag buffer (#1299)
* fix improper state reference

* add parentheses for clarity

* fix buffer array reactivity + loop optimization
2024-03-22 20:19:51 -04:00
Matt
2d8b1ec66d Properly handle empty frames from cscore (#1296) 2024-03-21 23:23:56 -04:00
Devon Doyle
15da06b24c Sticky calibration camera display card (#1294)
* Stick camera card in calibration view to top

* Spacing
2024-03-21 15:39:07 -04:00
Devon Doyle
97d2050a99 Fix mjpg stream accumulation (#1293)
Fixes bug where switching tabs/etc causes buildup of connected mjpg streams in network, eventually slowing down streams and causing stream failure until refresh. Accomplishes this by directly setting the source of stream elements to null before unmount, allowing chrome/edge to close the connection.

Fixes #1106
2024-03-20 22:53:15 -04:00
Matt
c89acea5a6 Run updated wpiformat (#1291) 2024-03-18 20:54:06 -04:00
Matt
fa5d58147a Recreate user pipeline on type change (#1290)
* Recreate user pipeline on type change

* Fix typo

---------

Co-authored-by: shueja <32416547+shueja@users.noreply.github.com>
2024-03-18 20:50:32 -04:00
Matt
e74afb9688 Release letterboxed frame (#1289) 2024-03-18 17:20:14 -07:00
Matt
5dc70e4d3f Run resize in CPU and more aggressively release rknn resources (#1287)
With the latest dev opi image, i saw this stack trace when object detection stopped working (threads hanging forever on detect(). The stack pointed me to somewhere inside the RGA. Based on this i moved resize into CPU (as our [native code already is lazy](6934abb26c/src/main/native/cpp/yolo_common.cpp (L227))), and was not able to see more crashes

[message.txt](https://github.com/PhotonVision/photonvision/files/14630158/message.txt)

Includes also a quick hack to add a shutdown hook that releases pipelines at exit.
2024-03-18 16:36:14 -04:00
Matt
5597f5acd9 Set default pipeline idx in PipelineManager constructor (#1286)
Addresses #1285
2024-03-18 13:21:41 -04:00
Matt
fae3116951 Bump to 2024.3.2 (#1283) 2024-03-17 23:00:22 -05:00
Gautam
def37b92ba Add proper exposure range for OV2311 (#1282) 2024-03-16 20:28:52 -04:00
Phill Tran
5b878fe3a3 Disable camera orientation option when camera is calibrated (#1277)
* Disable camera orientation option when camera is calibrated.

* Flip logic on if camera is calibrated when disabling camera orientation rotation

* Add comment on why orientation is disabled when camera is calibrated

* Add v banner warning regarding rotating calibrated camera bug

* Run lint

---------

Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2024-03-15 10:39:04 -04:00
Matt
d9c2a382f1 Update build.yml (#1276) 2024-03-14 00:32:08 -05:00
Matt
e125632960 Free native resources in apriltag pipelines (#1272)
Addresses memory leak when switching between apriltag/aruco pipelines
2024-03-14 01:22:32 -04:00
Matt
d8f82bf9ee Opencv cal: CALIB_USE_LU and use camera focal length guess (#1268) 2024-03-09 08:31:54 -05:00
Matt
587ac478f4 Bump mrcal to include solver fixes (#1265) 2024-03-06 10:51:49 -05:00
Matt
bad676f67c Pipe cscore logs through photonvision (#1260)
This means we can see even more logs about mjpeg server status as well
2024-03-04 23:27:39 -05:00
Matt
71128d1569 Create smoketest mode (#1264)
Create test mode that exists after confirming libraries load OK
2024-03-04 23:24:23 -05:00
Matt
7cec141341 Fix CSI camera matching (#1258)
* previously CSI cameras would always have a new config made and would never match
2024-02-27 09:07:42 -05:00
841 changed files with 67788 additions and 11098 deletions

View File

@@ -1,366 +1,64 @@
name: Build
on:
# Run on pushes to master and pushed tags, and on pull requests against master, but ignore the docs folder
push:
branches: [ master ]
tags:
- 'v*'
paths:
- '**'
- '!docs/**'
- '.github/**'
pull_request:
branches: [ master ]
paths:
- '**'
- '!docs/**'
- '.github/**'
jobs:
build-client:
name: "PhotonClient Build"
defaults:
run:
working-directory: photon-client
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install Dependencies
run: npm ci
- name: Build Production Client
run: npm run build
- uses: actions/upload-artifact@v4
with:
name: built-client
path: photon-client/dist/
build-examples:
name: "Build Examples"
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch --tags --force
- name: Install Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
# Need to publish to maven local first, so that C++ sim can pick it up
# Still haven't figured out how to make the vendordep file be copied before trying to build examples
- name: Publish photonlib to maven local
run: |
chmod +x gradlew
./gradlew publishtomavenlocal -x check
- name: Build Java examples
working-directory: photonlib-java-examples
run: |
chmod +x gradlew
./gradlew copyPhotonlib -x check
./gradlew build -x check --max-workers 2
- name: Build C++ examples
working-directory: photonlib-cpp-examples
run: |
chmod +x gradlew
./gradlew copyPhotonlib -x check
./gradlew build -x check --max-workers 2
build-gradle:
name: "Gradle Build"
runs-on: ubuntu-22.04
steps:
# Checkout code.
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch --tags --force
- name: Install Java 17
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- name: Install mrcal deps
run: sudo apt-get update && sudo apt-get install -y libcholmod3 liblapack3 libsuitesparseconfig5
- name: Gradle Build
run: |
chmod +x gradlew
./gradlew build -x check --max-workers 2
- name: Gradle Tests
run: ./gradlew testHeadless -i --max-workers 1 --stacktrace
- name: Gradle Coverage
run: ./gradlew jacocoTestReport --max-workers 1
- name: Publish Coverage Report
uses: codecov/codecov-action@v3
with:
file: ./photon-server/build/reports/jacoco/test/jacocoTestReport.xml
- name: Publish Core Coverage Report
uses: codecov/codecov-action@v3
with:
file: ./photon-core/build/reports/jacoco/test/jacocoTestReport.xml
build-offline-docs:
name: "Build Offline Docs"
build-photonlib-vendorjson:
name: "Build Vendor JSON"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
repository: 'PhotonVision/photonvision-docs.git'
ref: master
- uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install sphinx sphinx_rtd_theme sphinx-tabs sphinxext-opengraph doc8
pip install -r requirements.txt
- name: Build the docs
run: |
make html
- uses: actions/upload-artifact@master
with:
name: built-docs
path: build/html
build-photonlib-host:
env:
MACOSX_DEPLOYMENT_TARGET: 12
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
artifact-name: Win64
architecture: x64
- os: macos-12
artifact-name: macOS
architecture: x64
- os: ubuntu-22.04
artifact-name: Linux
fetch-depth: 0
name: "Photonlib - Build Host - ${{ matrix.artifact-name }}"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
# grab all tags
- run: git fetch --tags --force
- run: |
chmod +x gradlew
./gradlew photon-lib:build --max-workers 1
- run: ./gradlew photon-lib:publish photon-targeting:publish
name: Publish
env:
ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }}
if: github.event_name == 'push'
build-photonlib-docker:
strategy:
fail-fast: false
matrix:
include:
- container: wpilib/roborio-cross-ubuntu:2024-22.04
artifact-name: Athena
- container: wpilib/raspbian-cross-ubuntu:bullseye-22.04
artifact-name: Raspbian
- container: wpilib/aarch64-cross-ubuntu:bullseye-22.04
artifact-name: Aarch64
runs-on: ubuntu-22.04
container: ${{ matrix.container }}
name: "Photonlib - Build Docker - ${{ matrix.artifact-name }}"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Config Git
run: |
git config --global --add safe.directory /__w/photonvision/photonvision
- name: Build PhotonLib
run: |
# Generate the JSON and give it the ""standard""" name maven gives it
- run: |
chmod +x gradlew
./gradlew photon-lib:build --max-workers 1
- name: Publish
run: |
chmod +x gradlew
./gradlew photon-lib:publish photon-targeting:publish
env:
ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }}
if: github.event_name == 'push'
build-package:
needs: [build-client, build-gradle, build-offline-docs]
./gradlew photon-lib:generateVendorJson
export VERSION=$(git describe --tags --match=v*)
mv photon-lib/build/generated/vendordeps/photonlib.json photon-lib/build/generated/vendordeps/photonlib-$(git describe --tags --match=v*).json
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
artifact-name: Win64
architecture: x64
arch-override: none
- os: macos-latest
artifact-name: macOS
architecture: x64
arch-override: none
- os: ubuntu-latest
artifact-name: Linux
architecture: x64
arch-override: none
- os: macos-latest
artifact-name: macOSArm
architecture: x64
arch-override: macarm64
- os: ubuntu-latest
artifact-name: LinuxArm32
architecture: x64
arch-override: linuxarm32
- os: ubuntu-latest
artifact-name: LinuxArm64
architecture: x64
arch-override: linuxarm64
runs-on: ${{ matrix.os }}
name: "Build fat JAR - ${{ matrix.artifact-name }}"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Java 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- run: |
rm -rf photon-server/src/main/resources/web/*
mkdir -p photon-server/src/main/resources/web/docs
if: ${{ (matrix.os) != 'windows-latest' }}
- run: |
del photon-server\src\main\resources\web\*.*
mkdir photon-server\src\main\resources\web\docs
if: ${{ (matrix.os) == 'windows-latest' }}
- uses: actions/download-artifact@v4
with:
name: built-client
path: photon-server/src/main/resources/web/
- uses: actions/download-artifact@v4
with:
name: built-docs
path: photon-server/src/main/resources/web/docs
- run: |
chmod +x gradlew
./gradlew photon-server:shadowJar --max-workers 2 -PArchOverride=${{ matrix.arch-override }}
if: ${{ (matrix.arch-override != 'none') }}
- run: |
chmod +x gradlew
./gradlew photon-server:shadowJar --max-workers 2
if: ${{ (matrix.arch-override == 'none') }}
# Upload it here so it shows up in releases
- uses: actions/upload-artifact@v4
with:
name: jar-${{ matrix.artifact-name }}
path: photon-server/build/libs
build-image:
needs: [build-package]
name: photonlib-vendor-json
path: photon-lib/build/generated/vendordeps/photonlib-*.json
if: ${{ github.event_name != 'pull_request' }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
artifact-name: LinuxArm64
image_suffix: RaspberryPi
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2024.0.4/photonvision_raspi.img.xz
cpu: cortex-a7
image_additional_mb: 0
- os: ubuntu-latest
artifact-name: LinuxArm64
image_suffix: limelight2
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2024.0.4/photonvision_limelight.img.xz
cpu: cortex-a7
image_additional_mb: 0
- os: ubuntu-latest
artifact-name: LinuxArm64
image_suffix: limelight3
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2024.0.5/photonvision_limelight3.img.xz
cpu: cortex-a7
image_additional_mb: 0
- os: ubuntu-latest
artifact-name: LinuxArm64
image_suffix: orangepi5
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2024.0.9/photonvision_opi5.img.xz
cpu: cortex-a8
image_additional_mb: 4096
- os: ubuntu-latest
artifact-name: LinuxArm64
image_suffix: orangepi5plus
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2024.0.9/photonvision_opi5plus.img.xz
cpu: cortex-a8
image_additional_mb: 4096
runs-on: ${{ matrix.os }}
name: "Build image - ${{ matrix.image_url }}"
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/download-artifact@v4
with:
name: jar-${{ matrix.artifact-name }}
- uses: pguyot/arm-runner-action@v2
name: Generate image
id: generate_image
with:
base_image: ${{ matrix.image_url }}
image_additional_mb: ${{ matrix.image_additional_mb }}
optimize_image: yes
cpu: ${{ matrix.cpu }}
# We do _not_ wanna copy photon into the image. Bind mount instead
bind_mount_repository: true
commands: |
chmod +x scripts/armrunner.sh
./scripts/armrunner.sh
- name: Compress image
run: |
new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar))
new_image_name=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}")
mv ${{ steps.generate_image.outputs.image }} $new_image_name
sudo xz -T 0 -v $new_image_name
- uses: actions/upload-artifact@v4
name: Upload image
with:
name: image-${{ matrix.image_suffix }}
path: photonvision*.xz
release:
needs: [build-package, build-image]
dispatch:
name: dispatch
needs: [build-photonlib-vendorjson]
runs-on: ubuntu-22.04
steps:
# Download literally every single artifact. This also downloads client and docs,
# but the filtering below won't pick these up (I hope)
- uses: actions/download-artifact@v4
- run: find
# Push to dev release
- uses: pyTooling/Actions/releaser@r0
- uses: peter-evans/repository-dispatch@v3
# if: |
# github.repository == 'mcm001/photonvision' &&
# startsWith(github.ref, 'refs/tags/v')
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag: 'Dev'
rm: true
files: |
**/*.xz
**/*.jar
**/photonlib*.json
if: github.event_name == 'push'
# Upload all jars and xz archives
- uses: softprops/action-gh-release@v1
with:
files: |
**/*.xz
**/*.jar
**/photonlib*.json
if: startsWith(github.ref, 'refs/tags/v')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.VENDOR_JSON_REPO_PUSH_TOKEN }}
repository: PhotonVision/vendor-json-repo
event-type: tag
client-payload: '{"run_id": "${{ github.run_id }}", "package_version": "${{ github.ref_name }}"}'

View File

@@ -1,86 +0,0 @@
name: Documentation
on:
push:
# For now, run on all commits to master
branches: [ master ]
# and also all tags starting with v
tags:
- 'v*'
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-client:
name: "PhotonClient Build"
defaults:
run:
working-directory: photon-client
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install Dependencies
run: npm ci
- name: Build Production Client
run: npm run build-demo
- uses: actions/upload-artifact@v4
with:
name: built-client
path: photon-client/dist/
run_docs:
runs-on: "ubuntu-22.04"
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch --tags --force
- name: Install Java 17
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- name: Build javadocs/doxygen
run: |
chmod +x gradlew
./gradlew docs:generateJavaDocs docs:doxygen
- uses: actions/upload-artifact@v4
with:
name: built-docs
path: docs/build/docs
release:
needs: [build-client, run_docs]
runs-on: ubuntu-22.04
steps:
# Download literally every single artifact.
- uses: actions/download-artifact@v4
- run: find .
- name: copy file via ssh password
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.WEBMASTER_SSH_HOST }}
username: ${{ secrets.WEBMASTER_SSH_USERNAME }}
password: ${{ secrets.WEBMASTER_SSH_KEY }}
port: ${{ secrets.WEBMASTER_SSH_PORT }}
source: "*"
target: /var/www/html/photonvision-docs/

View File

@@ -1,88 +0,0 @@
name: Lint and Format
on:
push:
branches: [ master ]
tags:
- 'v*'
pull_request:
branches: [ master ]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
wpiformat:
name: "wpiformat"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install wpiformat
run: pip3 install wpiformat
- name: Run
run: wpiformat
- name: Check output
run: git --no-pager diff --exit-code HEAD
- name: Generate diff
run: git diff HEAD > wpiformat-fixes.patch
if: ${{ failure() }}
- uses: actions/upload-artifact@v3
with:
name: wpiformat fixes
path: wpiformat-fixes.patch
if: ${{ failure() }}
javaformat:
name: "Java Formatting"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- run: |
chmod +x gradlew
./gradlew spotlessCheck
client-lint-format:
name: "PhotonClient Lint and Formatting"
defaults:
run:
working-directory: photon-client
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Dependencies
run: npm ci
- name: Check Linting
run: npm run lint-ci
- name: Check Formatting
run: npm run format-ci
server-index:
name: "Check server index.html not changed"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Check index.html not changed
run: git --no-pager diff --exit-code origin/master photon-server/src/main/resources/web/index.html

View File

@@ -1,60 +0,0 @@
name: Build and Distribute PhotonLibPy
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
on:
push:
branches: [ master ]
tags:
- 'v*'
pull_request:
branches: [ master ]
jobs:
buildAndDeploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel pytest
- name: Build wheel
working-directory: ./photon-lib/py
run: |
python setup.py sdist bdist_wheel
- name: Run Unit Tests
working-directory: ./photon-lib/py
run: |
pip install --no-cache-dir dist/*.whl
pytest
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: dist
path: ./photon-lib/py/dist/
- name: Publish package distributions to TestPyPI
# Only upload on tags
if: startsWith(github.ref, 'refs/tags/v')
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: ./photon-lib/py/dist/
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing

4
.gitignore vendored
View File

@@ -162,5 +162,9 @@ photonlib-cpp-examples/*/networktables.json.bck
photonlib-java-examples/*/networktables.json.bck
*.sqlite
photon-server/src/main/resources/web/index.html
photon-lib/src/generate/native/cpp/PhotonVersion.cpp
venv
.venv/*
.venv

30
.readthedocs.yaml Normal file
View File

@@ -0,0 +1,30 @@
version: 2
sphinx:
builder: html
configuration: docs/source/conf.py
fail_on_warning: true
build:
os: ubuntu-22.04
tools:
python: "3.11"
apt_packages:
- graphviz
jobs:
post_checkout:
# Cancel building pull requests when there aren't changed in the docs directory or YAML file.
# You can add any other files or directories that you'd like here as well,
# like your docs requirements file, or other files that will change your docs build.
#
# If there are no changes (git diff exits with 0) we force the command to return with 183.
# This is a special exit code on Read the Docs that will cancel the build immediately.
- |
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/master -- docs/ .readthedocs.yaml;
then
exit 183;
fi
python:
install:
- requirements: docs/requirements.txt

View File

@@ -1,10 +1,10 @@
# Photon Vision
# PhotonVision
[![CI](https://github.com/PhotonVision/photonvision/workflows/CI/badge.svg)](https://github.com/PhotonVision/photonvision/actions?query=workflow%3ACI) [![codecov](https://codecov.io/gh/PhotonVision/photonvision/branch/master/graph/badge.svg)](https://codecov.io/gh/PhotonVision/photonvision) [![Discord](https://img.shields.io/discord/725836368059826228?color=%23738ADB&label=Join%20our%20Discord&logo=discord&logoColor=white)](https://discord.gg/wYxTwym)
PhotonVision is the free, fast, and easy-to-use computer vision solution for the *FIRST* Robotics Competition. You can read an overview of our features [on our website](https://photonvision.org). You can find our comprehensive documentation [here](https://docs.photonvision.org).
A copy of the latest Raspberry Pi image is available [here](https://github.com/PhotonVision/photon-pi-gen/releases). A copy of the latest standalone JAR is available [here](https://github.com/PhotonVision/photonvision/releases). If you are a Gloworm user you can find the latest Gloworm image [here](https://github.com/gloworm-vision/pi-gen/releases).
The latest release of platform-specific jars and images is found [here](https://github.com/PhotonVision/photonvision/releases).
If you are interested in contributing code or documentation to the project, please [read our getting started page for contributors](https://docs.photonvision.org/en/latest/docs/contributing/index.html) and **[join the Discord](https://discord.gg/wYxTwym) to introduce yourself!** We hope to provide a welcoming community to anyone who is interested in helping.
@@ -14,54 +14,40 @@ If you are interested in contributing code or documentation to the project, plea
<img src="https://contrib.rocks/image?repo=PhotonVision/photonvision" />
</a>
## Documentation
- Our main documentation page: [docs.photonvision.org](https://docs.photonvision.org)
- Photon UI demo: [demo.photonvision.org](https://demo.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-client/))
- Javadocs: [javadocs.photonvision.org](https://javadocs.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-docs/javadoc/))
- C++ Doxygen [cppdocs.photonvision.org](https://cppdocs.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-docs/doxygen/html/))
## Building
Gradle is used for all C++ and Java code, and NPM is used for the web UI. Instructions to compile PhotonVision yourself can be found [in our docs](https://docs.photonvision.org/en/latest/docs/contributing/building-photon.html#compiling-instructions).
You can run one of the many built in examples straight from the command line, too! They contain a fully featured robot project, and some include simulation support. The projects can be found inside the [`photonlib-java-examples`](photonlib-java-examples) and [`photonlib-cpp-examples`](photonlib-cpp-examples) subdirectories, respectively. Instructions for running these examples directly from the repo are found [in the docs](https://docs.photonvision.org/en/latest/docs/contributing/building-photon.html#running-examples).
## Gradle Arguments
Note that these are case sensitive!
* `-PArchOverride=foobar`: builds for a target system other than your current architecture. Valid overrides are:
* linuxathena
* linuxarm32
* `-PArchOverride=foobar`: builds for a target system other than your current architecture. [Valid overrides](https://github.com/wpilibsuite/wpilib-tool-plugin/blob/main/src/main/java/edu/wpi/first/tools/NativePlatforms.java) are:
* winx32
* winx64
* winarm64
* macx64
* macarm64
* linuxx64
* linuxarm64
* arm32
* arm64
* x86-64
* x86
- `-PtgtIp`: Specifies where `./gradlew deploy` should try to copy the fat JAR to
* linuxathena
- `-PtgtIP`: Specifies where `./gradlew deploy` should try to copy the fat JAR to
- `-Pprofile`: enables JVM profiling
## Building
Gradle is used for all C++ and Java code, and NPM is used for the web UI. Instructions to compile PhotonVision yourself can be found [in our docs](https://docs.photonvision.org/en/latest/docs/contributing/photonvision/build-instructions.html?highlight=npm%20install#compiling-instructions).
You can run one of the many built in examples straight from the command line, too! They contain a fully featured robot project, and some include simulation support. The projects can be found inside the `photonlib-java-examples` and `photonlib-cpp-examples` subdirectories, respectively. The projects currently available include:
- photonlib-java-examples:
- aimandrange:simulateJava
- aimattarget:simulateJava
- getinrange:simulateJava
- simaimandrange:simulateJava
- simposeest:simulateJava
- photonlib-cpp-examples:
- aimandrange:simulateNative
- getinrange:simulateNative
To run them, use the commands listed below. Photonlib must first be published to your local maven repository, then the `copyPhotonlib` task will copy the generated vendordep json file into each example. After that, the simulateJava/simulateNative task can be used like a normal robot project. Robot simulation with attached debugger is technically possible by using simulateExternalJava and modifying the launch script it exports, though unsupported.
```
~/photonvision$ ./gradlew publishToMavenLocal
~/photonvision$ cd photonlib-java-examples
~/photonvision/photonlib-java-examples$ ./gradlew copyPhotonlib
~/photonvision/photonlib-java-examples$ ./gradlew <example-name>:simulateJava
~/photonvision$ cd photonlib-cpp-examples
~/photonvision/photonlib-cpp-examples$ ./gradlew copyPhotonlib
~/photonvision/photonlib-cpp-examples$ ./gradlew <example-name>:simulateNative
```
If you're cross-compiling, you'll need the wpilib toolchain installed. This can be done via Gradle: for example `./gradlew installArm64Toolchain` or `./gradlew installRoboRioToolchain`
## Out-of-Source Dependencies
PhotonVision uses the following additonal out-of-source repositories for building code.
PhotonVision uses the following additional out-of-source repositories for building code.
- Base system images for Raspberry Pi & Orange Pi: https://github.com/PhotonVision/photon-image-modifier
- C++ driver for Raspberry Pi CSI cameras: https://github.com/PhotonVision/photon-libcamera-gl-driver
@@ -69,10 +55,17 @@ PhotonVision uses the following additonal out-of-source repositories for buildin
- Custom build of OpenCV with GStreamer/Protobuf/other custom flags: https://github.com/PhotonVision/thirdparty-opencv
- JNI code for aruco-nano: https://github.com/PhotonVision/aruconano-jni
## Additional packages
For now, using mrcal requires installing these additional packages on Linux systems:
```
sudo apt install libcholmod3 liblapack3 libsuitesparseconfig5
```
## Acknowledgments
PhotonVision was forked from [Chameleon Vision](https://github.com/Chameleon-Vision/chameleon-vision/). Thank you to everyone who worked on the original project.
PhotonVision was forked from [Chameleon Vision](https://github.com/Chameleon-Vision/chameleon-vision/). Thank you to everyone who worked on the original project.
* [WPILib](https://github.com/wpilibsuite) - Specifically [cscore](https://github.com/wpilibsuite/allwpilib/tree/master/cscore), [CameraServer](https://github.com/wpilibsuite/allwpilib/tree/master/cameraserver), [NTCore](https://github.com/wpilibsuite/allwpilib/tree/master/ntcore), and [OpenCV](https://github.com/wpilibsuite/thirdparty-opencv).
@@ -85,25 +78,9 @@ PhotonVision was forked from [Chameleon Vision](https://github.com/Chameleon-Vis
* [FasterXML](https://github.com/FasterXML) - Specifically [jackson](https://github.com/FasterXML/jackson)
## License
PhotonVision is licensed under the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html)
PhotonVision is licensed under the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.html).
## Meeting Notes
Our meeting notes can be found in the wiki section of this repository.
* [2020 Meeting Notes](https://github.com/PhotonVision/photonvision/wiki/2020-Meeting-Notes)
* [2021 Meeting Notes](https://github.com/PhotonVision/photonvision/wiki/2021-Meeting-Notes)
## Additional packages
For now, using mrcal requires installing these additional packages on Linux systems:
```
sudo apt install libcholmod3 liblapack3 libsuitesparseconfig5
```
## Documentation
- Our main documentation page: [docs.photonvision.org](https://docs.photonvision.org)
- Photon UI demo: [demo.photonvision.org](https://demo.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-client/))
- Javadocs: [javadocs.photonvision.org](https://javadocs.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-docs/javadoc/))
- C++ Doxygen [cppdocs.photonvision.org](https://cppdocs.photonvision.org) (or [manual link](https://photonvision.github.io/photonvision/built-docs/doxygen/html/))
Our [meeting notes](https://github.com/PhotonVision/photonvision/wiki/PhotonVision-Meeting-Notes) can be found in the wiki section of this repository.

View File

@@ -1,38 +1,45 @@
import edu.wpi.first.toolchain.*
plugins {
id "java"
id "cpp"
id "com.diffplug.spotless" version "6.24.0"
id "edu.wpi.first.NativeUtils" version "2024.6.1" apply false
id "edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin" version "2020.2"
id "edu.wpi.first.GradleRIO" version "2024.3.1"
id "edu.wpi.first.GradleRIO" version "2025.1.1-beta-1"
id 'edu.wpi.first.WpilibTools' version '1.3.0'
id 'com.google.protobuf' version '0.9.4' apply false
id 'com.google.protobuf' version '0.9.3' apply false
id 'edu.wpi.first.GradleJni' version '1.1.0'
}
allprojects {
repositories {
mavenCentral()
mavenLocal()
maven { url = "https://maven.photonvision.org/repository/internal/" }
maven { url = "https://maven.photonvision.org/repository/snapshots/" }
maven { url = "https://maven.photonvision.org/releases" }
maven { url = "https://maven.photonvision.org/snapshots" }
maven { url = "https://jogamp.org/deployment/maven/" }
}
wpilibRepositories.addAllReleaseRepositories(it)
wpilibRepositories.addAllDevelopmentRepositories(it)
}
ext.localMavenURL = file("$project.buildDir/outputs/maven")
ext.allOutputsFolder = file("$project.buildDir/outputs")
// Configure the version number.
apply from: "versioningHelper.gradle"
ext {
wpilibVersion = "2024.3.1"
wpilibVersion = "2025.1.1-beta-1"
wpimathVersion = wpilibVersion
openCVversion = "4.8.0-2"
joglVersion = "2.4.0-rc-20200307"
openCVYear = "2024"
openCVversion = "4.8.0-4"
joglVersion = "2.4.0"
javalinVersion = "5.6.2"
photonGlDriverLibVersion = "dev-v2023.1.0-9-g75fc678"
rknnVersion = "dev-v2024.0.0-64-gc0836a6"
frcYear = "2024"
mrcalVersion = "dev-v2024.0.0-7-gc976aaa";
libcameraDriverVersion = "dev-v2023.1.0-14-g787ab59"
rknnVersion = "dev-v2024.0.1-4-g0db16ac"
frcYear = "2025"
mrcalVersion = "dev-v2024.0.0-24-gc1efcf0";
pubVersion = versionString
@@ -50,13 +57,17 @@ ext {
println("Building for platform " + jniPlatform + " wpilib: " + wpilibNativeName)
println("Using Wpilib: " + wpilibVersion)
println("Using OpenCV: " + openCVversion)
photonMavenURL = 'https://maven.photonvision.org/' + (isDev ? 'snapshots' : 'releases');
println("Publishing Photonlib to " + photonMavenURL)
}
spotless {
java {
target fileTree('.') {
include '**/*.java'
exclude '**/build/**', '**/build-*/**', "photon-core\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "photon-lib\\src\\main\\java\\org\\photonvision\\PhotonVersion.java"
exclude '**/build/**', '**/build-*/**', "photon-core\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "photon-lib\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "**/src/generated/**"
}
toggleOffOn()
googleJavaFormat()
@@ -104,3 +115,17 @@ wrapper {
ext.getCurrentArch = {
return NativePlatforms.desktop
}
subprojects {
tasks.withType(JavaCompile) {
options.compilerArgs.add '-XDstringConcat=inline'
options.encoding = 'UTF-8'
}
// Enables UTF-8 support in Javadoc
tasks.withType(Javadoc) {
options.addStringOption("charset", "utf-8")
options.addStringOption("docencoding", "utf-8")
options.addStringOption("encoding", "utf-8")
}
}

View File

@@ -3,7 +3,6 @@ import base64
from dataclasses import dataclass
import json
import os
from typing import Union
import cv2
import numpy as np
import mrcal
@@ -162,9 +161,9 @@ def __convert_cal_to_mrcal_cameramodel(
"indices_point_camintrinsics_camextrinsics": None,
"lensmodel": model,
"imagersizes": np.array([imagersize], dtype=np.int32),
"calobject_warp": np.array(cal.calobjectWarp)
if len(cal.calobjectWarp) > 0
else None,
"calobject_warp": (
np.array(cal.calobjectWarp) if len(cal.calobjectWarp) > 0 else None
),
# We always do all the things
"do_optimize_intrinsics_core": True,
"do_optimize_intrinsics_distortions": True,

9
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
build/*
.DS_Store
.vscode/*
.idea/*
source/_build
source/docs/_build
venv/*
.venv/*

16
docs/.styleguide Normal file
View File

@@ -0,0 +1,16 @@
modifiableFileExclude {
\.jpg$
\.jpeg$
\.png$
\.gif$
\.so$
\.pdf$
\.mp4$
\.dll$
\.webp$
\.ico$
\.rknn$
\.svg$
gradlew
}

395
docs/LICENSE Normal file
View File

@@ -0,0 +1,395 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

24
docs/Makefile Normal file
View File

@@ -0,0 +1,24 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS = -W --keep-going
SPHINXBUILD = sphinx-build
SOURCEDIR = source
LINTER = doc8
LINTEROPTS = --ignore D001 # D001 is linelength
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
lint:
@$(LINTER) $(LINTEROPTS) $(SOURCEDIR)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

9
docs/README.MD Normal file
View File

@@ -0,0 +1,9 @@
# PhotonVision ReadTheDocs
[![Documentation Status](https://readthedocs.org/projects/photonvision-docs/badge/?version=latest)](https://docs.photonvision.org/en/latest/?badge=latest)
PhotonVision is a free open-source vision processing software for FRC teams.
This repository is the source code for our ReadTheDocs documentation, which can be found [here](https://docs.photonvision.org).
[Contribution and formatting guidelines for this project](https://docs.photonvision.org/en/latest/docs/contributing/photonvision-docs/index.html)

36
docs/make.bat Normal file
View File

@@ -0,0 +1,36 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
set SPHINXOPTS=-W --keep-going
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

44
docs/requirements.txt Normal file
View File

@@ -0,0 +1,44 @@
alabaster==0.7.13
Babel==2.13.1
beautifulsoup4==4.12.2
certifi==2023.11.17
charset-normalizer==3.3.2
colorama==0.4.6
doc8==0.11.2
docopt==0.6.2
docutils==0.18.1
furo==2023.9.10
idna==3.4
imagesize==1.4.1
Jinja2==3.0.3
MarkupSafe==2.1.3
packaging==23.2
pbr==6.0.0
pipreqs==0.4.13
Pygments==2.17.1
requests==2.31.0
restructuredtext-lint==1.4.0
six==1.16.0
snowballstemmer==2.2.0
soupsieve==2.5
Sphinx==7.2.6
sphinx-basic-ng==1.0.0b2
sphinx-notfound-page==1.0.0
sphinx-rtd-theme==1.3.0
sphinx-tabs==3.4.4
sphinx_design==0.5.0
sphinxcontrib-applehelp==1.0.7
sphinxcontrib-devhelp==1.0.5
sphinxcontrib-ghcontributors==0.2.3
sphinxcontrib-htmlhelp==2.0.4
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.6
sphinxcontrib-serializinghtml==1.1.9
sphinxext-opengraph==0.9.0
sphinxext-remoteliteralinclude==0.4.0
stevedore==5.1.0
urllib3==2.1.0
yarg==0.1.9
sphinx-autobuild==2024.4.16
myst_parser==3.0.1

7
docs/source/404.md Normal file
View File

@@ -0,0 +1,7 @@
---
orphan: true
---
# Requested Page Not Found
This page you were looking for was not found. If you think this is a mistake, [file an issue on our GitHub.](https://github.com/PhotonVision/photonvision-docs/issues)

20
docs/source/Makefile Normal file
View File

@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,17 @@
/*!
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
@font-face {
font-family: FontAwesome;
src: url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);
src: url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"), url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"), url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"), url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"), url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");
font-weight: 400;
font-style:normal
}
.code-block-caption>.headerlink, dl dt>.headerlink, h1>.headerlink, h2>.headerlink, h3>.headerlink, h4>.headerlink, h5>.headerlink, h6>.headerlink, p.caption>.headerlink, table>caption>.headerlink {
font-family: FontAwesome;
font-size: 0.75em;
}

View File

@@ -0,0 +1,74 @@
{# Import the theme's layout. #}
{% extends '!layout.html' %}
{%- block extrahead %}
<script>
if (localStorage.getItem("colorTheme") === "dark") {
document.documentElement.setAttribute('data-theme', 'dark');
} else if (localStorage.getItem("colorTheme") === "light") {
document.documentElement.setAttribute('data-theme', 'light');
} else {
var userPrefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if (userPrefersDark) {
document.documentElement.setAttribute('data-theme', 'dark');
} else {
document.documentElement.setAttribute('data-theme', 'light');
}
}
</script>
{# Call the parent block #}
{{ super() }}
{% endblock %}
{%- block extrafooter %}
{# Add custom things to the head HTML tag #}
<div class="dark-mode-toggle-container">
<strong class="light-label md-icon">&#xE430</strong>
<div class="dark-mode-toggle">
<input type="checkbox" id="switch" name="theme"/><label class="toggle" for="switch">Toggle</label>
</div>
<strong class="dark-label md-icon">&#xE42D</strong>
</div>
<script>
var checkbox = document.querySelector('input[name=theme]');
var element = document.documentElement.getAttribute('data-theme');
if (element == 'dark') {
// Auto check the checkbox if the set theme is "dark".
checkbox.checked = true;
}
checkbox.addEventListener('change', function() {
if (this.checked) {
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem("colorTheme", "dark");
} else {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem("colorTheme", "light");
}
});
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', event => {
if (event.matches) {
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem("colorTheme", "dark");
checkbox.checked = true;
} else {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem("colorTheme", "light");
checkbox.checked = false;
}
});
</script>
{# Call the parent block #}
{{ super() }}
{%- endblock %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

134
docs/source/conf.py Normal file
View File

@@ -0,0 +1,134 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = "PhotonVision"
copyright = "2024, PhotonVision"
author = "Banks Troutman, Matt Morley"
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx_rtd_theme",
"sphinx.ext.autosectionlabel",
"sphinx.ext.todo",
"sphinx_tabs.tabs",
"notfound.extension",
"sphinxext.remoteliteralinclude",
"sphinxext.opengraph",
"sphinxcontrib.ghcontributors",
"sphinx_design",
"myst_parser",
"sphinx.ext.mathjax",
"sphinx.ext.graphviz",
]
# Configure OpenGraph support
ogp_site_url = "https://docs.photonvision.org/en/latest/"
ogp_site_name = "PhotonVision Documentation"
ogp_image = "https://raw.githubusercontent.com/PhotonVision/photonvision-docs/master/source/assets/RectLogo.png"
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# Enable hover content on glossary term
hoverxref_roles = ["term"]
# Autosection labels prefix document path and filename
autosectionlabel_prefix_document = True
# -- Options for HTML output -------------------------------------------------
html_title = "PhotonVision Docs"
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "furo"
html_favicon = "assets/RoundLogo.png"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
source_suffix = [".rst", ".md"]
def setup(app):
app.add_css_file("css/pv-icons.css")
pygments_style = "sphinx"
html_theme_options = {
"sidebar_hide_name": True,
"light_logo": "assets/PhotonVision-Header-onWhite.png",
"dark_logo": "assets/PhotonVision-Header-noBG.png",
"light_css_variables": {
"font-stack": "-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif;",
"admonition-font-size": "1rem",
"admonition-title-font-size": "1rem",
"color-background-primary": "#ffffff",
"color-background-secondary": "#f7f7f7",
"color-background-hover": "#efeff400",
"color-background-hover--transparent": "#efeff400",
"color-brand-primary": "#006492",
"color-brand-content": "#006492",
"color-foreground-primary": "#2d2d2d",
"color-foreground-secondary": "#39a4d5",
"color-foreground-muted": "#2d2d2d",
"color-foreground-border": "#ffffff",
"color-background-border": "ffffff",
"color-api-overall": "#101010",
},
"dark_css_variables": {
"color-background-primary": "#242c37",
"color-background-secondary": "#006492",
"color-background-hover": "#efeff400",
"color-background-hover--transparent": "#efeff400",
"color-brand-primary": "#ffd843",
"color-brand-secondary": "#39a4d5",
"color-brand-content": "#ffd843",
"color-foreground-primary": "#ffffff",
"color-foreground-secondary": "#ffffff",
"color-foreground-muted": "#ffffff",
"color-foreground-border": "transparent",
"color-background-border": "transparent",
"color-api-overall": "#101010",
"color-inline-code-background": "#0d0d0d",
},
}
suppress_warnings = ["epub.unknown_project_files"]
sphinx_tabs_valid_builders = ["epub", "linkcheck"]
# Excluded links for linkcheck
# These should be periodically checked by hand to ensure that they are still functional
linkcheck_ignore = ["https://www.raspberrypi.com/software/"]
# MyST configuration (https://myst-parser.readthedocs.io/en/latest/configuration.html)
myst_enable_extensions = ["colon_fence"]

View File

@@ -0,0 +1,29 @@
# Best Practices For Competition
## Before Competition
- Ensure you have spares of the relevant electronics if you can afford it (switch, coprocessor, cameras, etc.).
- Download the latest release .jar onto your computer and update your Pi if necessary (only update if the release is labeled "critical" or similar, we do not recommend updating right before an event in case there are unforeseen bugs).
- Test out PhotonVision at your home setup.
- Ensure that you have set up SmartDashboard / Shuffleboard to view your camera streams during matches.
- Follow all the recommendations under the Networking section in installation (network switch and static IP).
- Use high quality ethernet cables that have been rigorously tested.
- Set up port forwarding using the guide in the Networking section in installation.
## During the Competition
- Make sure you take advantage of the field calibration time given at the start of the event:
- Bring your robot to the field at the allotted time.
- Turn on your robot and pull up the dashboard on your driver station.
- Point your robot at the AprilTags(s) and ensure you get a consistent tracking (you hold one AprilTag consistently, the ceiling lights aren't detected, etc.).
- If you have problems with your pipeline, go to the pipeline tuning section and retune the pipeline using the guide there.
- Move the robot close, far, angled, and around the field to ensure no extra AprilTags are found.
- Go to a practice match to ensure everything is working correctly.
- After field calibration, use the "Export Settings" button in the "Settings" page to create a backup.
- Do this for each coprocessor on your robot that runs PhotonVision, and name your exports with meaningful names.
- This will contain camera information/calibration, pipeline information, network settings, etc.
- In the event of software/hardware failures (IE lost SD Card, broken device), you can then use the "Import Settings" button and select "All Settings" to restore your settings.
- This effectively works as a snapshot of your PhotonVision data that can be restored at any point.
- Before every match, check the ethernet connection going into your coprocessor and that it is seated fully.
- Ensure that exposure is as low as possible and that you don't have the dashboard up when you don't need it to reduce bandwidth.
- Stream at as low of a resolution as possible while still detecting AprilTags to stay within field bandwidth limits.

View File

@@ -0,0 +1,50 @@
# Filesystem Directory
PhotonVision stores and loads settings in the {code}`photonvision_config` directory, in the same folder as the PhotonVision JAR is stored. On the Pi image as well as the Gloworm, this is in the {code}`/opt/photonvision` directory. The contents of this directory can be exported as a zip archive from the settings page of the interface, under "export settings". This export will contain everything detailed below. These settings can later be uploaded using "import settings", to restore configurations from previous backups.
## Directory Structure
The directory structure is outlined below.
```{image} images/configDir.png
:alt: Config directory structure
:width: 600
```
- calibImgs
- Images saved from the last run of the calibration routine
- cameras
- Contains a subfolder for each camera. This folder contains the following files:
- pipelines folder, which contains a {code}`json` file for each user-created pipeline.
- config.json, which contains all camera-specific configuration. This includes FOV, pitch, current pipeline index, and calibration data
- drivermode.json, which contains settings for the driver mode pipeline
- imgSaves
- Contains images saved with the input/output save commands.
- logs
- Contains timestamped logs in the format {code}`photonvision-YYYY-MM-D_HH-MM-SS.log`. Note that on Pi or Gloworm these timestamps will likely be significantly behind the real time.
- hardwareSettings.json
- Contains hardware settings. Currently this includes only the LED brightness.
- networkSettings.json
- Contains network settings, including team number (or remote network tables address), static/dynamic settings, and hostname.
## Importing and Exporting Settings
The entire settings directory can be exported as a ZIP archive from the settings page.
```{raw} html
<video width="85%" controls>
<source src="../../_static/assets/import-export-settings.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
```
A variety of files can be imported back into PhotonVision:
- ZIP Archive ({code}`.zip`)
- Useful for restoring a full configuration from a different PhotonVision instance.
- Single Config File
- Currently-supported Files
- {code}`hardwareConfig.json`
- {code}`hardwareSettings.json`
- {code}`networkSettings.json`
- Useful for simple hardware or network configuration tasks without overwriting all settings.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,70 @@
# NetworkTables API
## About
:::{warning}
PhotonVision interfaces with PhotonLib, our vendor dependency, using NetworkTables. If you are running PhotonVision on a robot (ie. with a RoboRIO), you should **turn the NetworkTables server switch (in the settings tab) off** in order to get PhotonLib to work. Also ensure that you set your team number. The NetworkTables server should only be enabled if you know what you're doing!
:::
## API
:::{warning}
NetworkTables is not a supported setup/viable option when using PhotonVision as we only send one target at a time (this is problematic when using AprilTags, which will return data from multiple tags at once). We recommend using PhotonLib.
:::
The tables below contain the the name of the key for each entry that PhotonVision sends over the network and a short description of the key. The entries should be extracted from a subtable with your camera's nickname (visible in the PhotonVision UI) under the main `photonvision` table.
### Getting Target Information
| Key | Type | Description |
| --------------- | ---------- | ------------------------------------------------------------------------ |
| `rawBytes` | `byte[]` | A byte-packed string that contains target info from the same timestamp. |
| `latencyMillis` | `double` | The latency of the pipeline in milliseconds. |
| `hasTarget` | `boolean` | Whether the pipeline is detecting targets or not. |
| `targetPitch` | `double` | The pitch of the target in degrees (positive up). |
| `targetYaw` | `double` | The yaw of the target in degrees (positive right). |
| `targetArea` | `double` | The area (percent of bounding box in screen) as a percent (0-100). |
| `targetSkew` | `double` | The skew of the target in degrees (counter-clockwise positive). |
| `targetPose` | `double[]` | The pose of the target relative to the robot (x, y, z, qw, qx, qy, qz) |
| `targetPixelsX` | `double` | The target crosshair location horizontally, in pixels (origin top-right) |
| `targetPixelsY` | `double` | The target crosshair location vertically, in pixels (origin top-right) |
### Changing Settings
| Key | Type | Description |
| --------------- | --------- | --------------------------- |
| `pipelineIndex` | `int` | Changes the pipeline index. |
| `driverMode` | `boolean` | Toggles driver mode. |
### Saving Images
PhotonVision can save images to file on command. The image is saved when PhotonVision detects the command went from `false` to `true`.
PhotonVision will automatically set these back to `false` after 500ms.
Be careful saving images rapidly - it will slow vision processing performance and take up disk space very quickly.
Images are returned as part of the .zip package from the "Export" operation in the Settings tab.
| Key | Type | Description |
| ------------------ | --------- | ------------------------------------------------- |
| `inputSaveImgCmd` | `boolean` | Triggers saving the current input image to file. |
| `outputSaveImgCmd` | `boolean` | Triggers saving the current output image to file. |
:::{warning}
If you manage to make calls to these commands faster than 500ms (between calls), additional photos will not be captured.
:::
### Global Entries
These entries are global, meaning that they should be called on the main `photonvision` table.
| Key | Type | Description |
| --------- | ----- | -------------------------------------------------------- |
| `ledMode` | `int` | Sets the LED Mode (-1: default, 0: off, 1: on, 2: blink) |
:::{warning}
Setting the LED mode to -1 (default) when `multiple` cameras are connected may result in unexpected behavior. {ref}`This is a known limitation of PhotonVision. <docs/troubleshooting/common-errors:LED Control>`
Single camera operation should work without issue.
:::

View File

@@ -0,0 +1,54 @@
# 2D AprilTag Tuning / Tracking
## Tracking Apriltags
Before you get started tracking AprilTags, ensure that you have followed the previous sections on installation, wiring and networking. Next, open the Web UI, go to the top right card, and switch to the "AprilTag" or "Aruco" type. You should see a screen similar to the one below.
```{image} images/apriltag.png
:align: center
```
You are now able to detect and track AprilTags in 2D (yaw, pitch, roll, etc.). In order to get 3D data from your AprilTags, please see {ref}`here. <docs/apriltag-pipelines/3D-tracking:3D Tracking>`
## Tuning AprilTags
AprilTag pipelines come with reasonable defaults to get you up and running with tracking. However, in order to optimize your performance and accuracy, you must tune your AprilTag pipeline using the settings below. Note that the settings below are different between the AprilTag and Aruco detectors but the concepts are the same.
```{image} images/apriltag-tune.png
:align: center
:scale: 45 %
```
### Target Family
Target families are defined by two numbers (before and after the h). The first number is the number of bits the tag is able to encode (which means more tags are available in the respective family) and the second is the hamming distance. Hamming distance describes the ability for error correction while identifying tag ids. A high hamming distance generally means that it will be easier for a tag to be identified even if there are errors. However, as hamming distance increases, the number of available tags decreases. The 2024 FRC game will be using 36h11 tags, which can be found [here](https://github.com/AprilRobotics/apriltag-imgs/tree/master/tag36h11).
### Decimate
Decimation (also known as down-sampling) is the process of reducing the sampling frequency of a signal (in our case, the image). Increasing decimate will lead to an increased detection rate while decreasing detection distance. We recommend keeping this at the default value.
### Blur
This controls the sigma of Gaussian blur for tag detection. In clearer terms, increasing blur will make the image blurrier, decreasing it will make it closer to the original image. We strongly recommend that you keep blur to a minimum (0) due to it's high performance intensity unless you have an extremely noisy image.
### Threads
Threads refers to the threads within your coprocessor's CPU. The theoretical maximum is device dependent, but we recommend that users to stick to one less than the amount of CPU threads that your coprocessor has. Increasing threads will increase performance at the cost of increased CPU load, temperature increase, etc. It may take some experimentation to find the most optimal value for your system.
### Refine Edges
The edges of the each polygon are adjusted to "snap to" high color differences surrounding it. It is recommended to use this in tandem with decimate as it can increase the quality of the initial estimate.
### Pose Iterations
Pose iterations represents the amount of iterations done in order for the AprilTag algorithm to converge on its pose solution(s). A smaller number between 0-100 is recommended. A smaller amount of iterations cause a more noisy set of poses when looking at the tag straight on, while higher values much more consistently stick to a (potentially wrong) pair of poses. WPILib contains many useful filter classes in order to account for a noisy tag reading.
### Max Error Bits
Max error bits, also known as hamming distance, is the number of positions at which corresponding pieces of data / tag are different. Put more generally, this is the number of bits (think of these as squares in the tag) that need to be changed / corrected in the tag to correctly detect it. A higher value means that more tags will be detected while a lower value cuts out tags that could be "questionable" in terms of detection.
We recommend a value of 0 for the 16h5 and at most 3 for the 36h11 family.
### Decision Margin Cutoff
The decision margin cutoff is how much “margin” the detector has left before it rejects a tag; increasing this rejects poorer tags. We recommend you keep this value around a 30.

View File

@@ -0,0 +1,13 @@
# 3D Tracking
3D AprilTag tracking will allow you to track the real-world position and rotation of a tag relative to the camera's image sensor. This is useful for robot pose estimation and other applications like autonomous scoring. In order to use 3D tracking, you must first {ref}`calibrate your camera <docs/calibration/calibration:Calibrating Your Camera>`. Once you have, you need to enable 3D mode in the UI and you will now be able to get 3D pose information from the tag! For information on getting and using this information in your code, see {ref}`the programming reference. <docs/programming/index:Programming Reference>`.
## Ambiguity
Translating from 2D to 3D using data from the calibration and the four tag corners can lead to "pose ambiguity", where it appears that the AprilTag pose is flipping between two different poses. You can read more about this issue `here. <https://docs.wpilib.org/en/stable/docs/software/vision-processing/apriltag/apriltag-intro.html#d-to-3d-ambiguity>` Ambiguity is calculated as the ratio of reprojection errors between two pose solutions (if they exist), where reprojection error is the error corresponding to the image distance between where the apriltag's corners are detected vs where we expect to see them based on the tag's estimated camera relative pose.
There are a few steps you can take to resolve/mitigate this issue:
1. Mount cameras at oblique angles so it is less likely that the tag will be seen straight on.
2. Use the {ref}`MultiTag system <docs/apriltag-pipelines/multitag:MultiTag Localization>` in order to combine the corners from multiple tags to get a more accurate and unambiguous pose.
3. Reject all tag poses where the ambiguity ratio (available via PhotonLib) is greater than 0.2.

View File

@@ -0,0 +1,14 @@
# About Apriltags
```{image} images/pv-apriltag.png
:align: center
:scale: 20 %
```
AprilTags are a common type of visual fiducial marker. Visual fiducial markers are artificial landmarks added to a scene to allow "localization" (finding your current position) via images. In simpler terms, tags mark known points of reference that you can use to find your current location. They are similar to QR codes in which they encode information, however, they hold only a single number. By placing AprilTags in known locations around the field and detecting them using PhotonVision, you can easily get full field localization / pose estimation. Alternatively, you can use AprilTags the same way you used retroreflective tape, simply using them to turn to goal without any pose estimation.
A more technical explanation can be found in the [WPILib documentation](https://docs.wpilib.org/en/latest/docs/software/vision-processing/apriltag/apriltag-intro.html).
:::{note}
You can get FIRST's [official PDF of the targets used in 2024 here](https://firstfrc.blob.core.windows.net/frc2024/FieldAssets/Apriltag_Images_and_User_Guide.pdf).
:::

View File

@@ -0,0 +1,40 @@
# Coordinate Systems
## Field and Robot Coordinate Frame
PhotonVision follows the WPILib conventions for the robot and field coordinate systems, as defined [here](https://docs.wpilib.org/en/stable/docs/software/advanced-controls/geometry/coordinate-systems.html).
You define the camera to robot transform in the robot coordinate frame.
## Camera Coordinate Frame
OpenCV by default uses x-left/y-down/z-out for camera transforms. PhotonVision applies a base rotation to this transformation to make robot to tag transforms more in line with the WPILib coordinate system. The x, y, and z axes are also shown in red, green, and blue in the 3D mini-map and targeting overlay in the UI.
- The origin is the focal point of the camera lens
- The x-axis points out of the camera
- The y-axis points to the left
- The z-axis points upwards
```{image} images/camera-coord.png
:align: center
:scale: 45 %
```
```{image} images/multiple-tags.png
:align: center
:scale: 45 %
```
## AprilTag Coordinate Frame
The AprilTag coordinate system is defined as follows, relative to the center of the AprilTag itself, and when viewing the tag as a robot would. Again, PhotonVision changes this coordinate system to be more in line with WPILib. This means that a robot facing a tag head-on would see a robot-to-tag transform with a translation only in x, and a rotation of 180 degrees about z. The tag coordinate system is also shown with x/y/z in red/green/blue in the UI target overlay and mini-map.
- The origin is the center of the tag
- The x-axis is normal to the plane the tag is printed on, pointing outward from the visible side of the tag.
- The y-axis points to the right
- The z-axis points upwards
```{image} images/apriltag-coords.png
:align: center
:scale: 45 %
```

View File

@@ -0,0 +1,15 @@
# AprilTag Pipeline Types
PhotonVision offers two different AprilTag pipeline types based on different implementations of the underlying algorithm. Each one has its advantages / disadvantages, which are detailed below.
:::{note}
Note that both of these pipeline types detect AprilTag markers and are just two different algorithms for doing so.
:::
## AprilTag
The AprilTag pipeline type is based on the [AprilTag](https://april.eecs.umich.edu/software/apriltag.html) library from the University of Michigan and we recommend it for most use cases. It is (to our understanding) most accurate pipeline type, but is also ~2x slower than AruCo. This was the pipeline type used by teams in the 2023 season and is well tested.
## AruCo
The AruCo pipeline is based on the [AruCo](https://docs.opencv.org/4.8.0/d9/d6a/group__aruco.html) library implementation from OpenCV. It is ~2x higher fps and ~2x lower latency than the AprilTag pipeline type, but is less accurate. We recommend this pipeline type for teams that need to run at a higher framerate or have a lower powered device. This pipeline type is new for the 2024 season and is not as well tested as AprilTag.

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,10 @@
# AprilTag Detection
```{toctree}
about-apriltags
detector-types
2D-tracking-tuning
3D-tracking
multitag
coordinate-systems
```

View File

@@ -0,0 +1,65 @@
# MultiTag Localization
PhotonVision can combine AprilTag detections from multiple simultaneously observed AprilTags from a particular camera with information about where tags are expected to be located on the field to produce a better estimate of where the camera (and therefore robot) is located on the field. PhotonVision can calculate this multi-target result on your coprocessor, reducing CPU usage on your RoboRio. This result is sent over NetworkTables along with other detected targets as part of the `PhotonPipelineResult` provided by PhotonLib.
:::{warning}
MultiTag requires an accurate field layout JSON to be uploaded! Differences between this layout and the tags' physical location will drive error in the estimated pose output.
:::
## Enabling MultiTag
Ensure that your camera is calibrated and 3D mode is enabled. Navigate to the Output tab and enable "Do Multi-Target Estimation". This enables MultiTag to use the uploaded field layout JSON to calculate your camera's pose in the field. This 3D transform will be shown as an additional table in the "targets" tab, along with the IDs of AprilTags used to compute this transform.
```{image} images/multitag-ui.png
:alt: Multitarget enabled and running in the PhotonVision UI
:width: 600
```
:::{note}
By default, enabling multi-target will disable calculating camera-to-target transforms for each observed AprilTag target to increase performance; the X/Y/angle numbers shown in the target table of the UI are instead calculated using the tag's expected location (per the field layout JSON) and the field-to-camera transform calculated using MultiTag. If you additionally want the individual camera-to-target transform calculated using SolvePNP for each target, enable "Always Do Single-Target Estimation".
:::
This multi-target pose estimate can be accessed using PhotonLib. We suggest using {ref}`the PhotonPoseEstimator class <docs/programming/photonlib/robot-pose-estimator:AprilTags and PhotonPoseEstimator>` with the `MULTI_TAG_PNP_ON_COPROCESSOR` strategy to simplify code, but the transform can be directly accessed using `getMultiTagResult`/`MultiTagResult()` (Java/C++).
```{eval-rst}
.. tab-set-code::
.. code-block:: Java
var result = camera.getLatestResult();
if (result.getMultiTagResult().estimatedPose.isPresent) {
Transform3d fieldToCamera = result.getMultiTagResult().estimatedPose.best;
}
.. code-block:: C++
auto result = camera.GetLatestResult();
if (result.MultiTagResult().result.isPresent) {
frc::Transform3d fieldToCamera = result.MultiTagResult().result.best;
}
.. code-block:: Python
# Coming Soon!
```
:::{note}
The returned field to camera transform is a transform from the fixed field origin to the camera's coordinate system. This does not change based on alliance color, and by convention is on the BLUE ALLIANCE wall.
:::
## Updating the Field Layout
PhotonVision ships by default with the [2024 field layout JSON](https://github.com/wpilibsuite/allwpilib/blob/main/apriltag/src/main/native/resources/edu/wpi/first/apriltag/2024-crescendo.json). The layout can be inspected by navigating to the settings tab and scrolling down to the "AprilTag Field Layout" card, as shown below.
```{image} images/field-layout.png
:alt: The currently saved field layout in the Photon UI
:width: 600
```
An updated field layout can be uploaded by navigating to the "Device Control" card of the Settings tab and clicking "Import Settings". In the pop-up dialog, select the "AprilTag Layout" type and choose an updated layout JSON (in the same format as the WPILib field layout JSON linked above) using the paperclip icon, and select "Import Settings". The AprilTag layout in the "AprilTag Field Layout" card below should be updated to reflect the new layout.
:::{note}
Currently, there is no way to update this layout using PhotonLib, although this feature is under consideration.
:::

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

View File

@@ -0,0 +1,147 @@
# Calibrating Your Camera
:::{important}
In order to detect AprilTags and use 3D mode, your camera must be calibrated at the desired resolution! Inaccurate calibration will lead to poor performance.
:::
To calibrate a camera, images of a Charuco board (or chessboard) are taken. By comparing where the grid corners should be in object space (for example, a corner once every inch in an 8x6 grid) with where they appear in the camera image, we can find a least-squares estimate for intrinsic camera properties like focal lengths, center point, and distortion coefficients. For more on camera calibration, please review the [OpenCV documentation](https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html).
:::{warning}
While any resolution can be calibrated, higher resolutions may be too performance-intensive for some coprocessors to handle. Therefore, we recommend experimenting to see what works best for your coprocessor.
:::
:::{note}
The calibration data collected during calibration is specific to each physical camera, as well as each individual resolution.
:::
## Calibration Tips
Accurate camera calibration is required in order to get accurate pose measurements when using AprilTags and 3D mode. The tips below should help ensure success:
01. Ensure your the images you take have the target in different positions and angles, with as big of a difference between angles as possible. It is important to make sure the target overlay still lines up with the board while doing this. Tilt no more than 45 degrees.
02. Use as big of a calibration target as your printer can print.
03. Ensure that your printed pattern has enough white border around it.
04. Ensure your camera stays in one position during the duration of the calibration.
05. Make sure you get all 12 images from varying distances and angles.
06. Take at least one image that covers the total image area, and generally ensure that you get even coverage of the lens with your image set.
07. Have good lighting, having a diffusely lit target would be best (light specifically shining on the target without shadows).
08. Ensure the calibration target is completely flat and does not bend or fold in any way. It should be mounted/taped down to something flat and then used for calibration, do not just hold it up.
09. Avoid having targets that are parallel to the lens of the camera / straight on towards the camera as much as possible. You want angles and variations within your calibration images.
Following the ideas above should help in getting an accurate calibration.
## Calibrating using PhotonVision
### 1. Navigate to the calibration section in the UI.
The Cameras tab of the UI houses PhotonVision's camera calibration tooling. It assists users with calibrating their cameras, as well as allows them to view previously calibrated resolutions. We support both charuco and chessboard calibrations.
### 2. Print out the calibration target.
In the Camera Calibration tab, we'll print out the calibration target using the "Download" button. This should be printed on 8.5x11 printer paper. This page shows using an 8x8 charuco board (or chessboard depending on the selected calibration type).
:::{warning}
Ensure that there is no scaling applied during printing (it should be at 100%) and that the PDF is printed as is on regular printer paper. Check the square size with calipers or an accurate measuring device after printing to ensure squares are sized properly, and enter the true size of the square in the UI text box. For optimal results, various resources are available online to calibrate your specific printer if needed.
:::
### 3. Select calibration resolution and fill in appropriate target data.
We'll next select a resolution to calibrate and populate our pattern spacing, marker size, and board size. The provided chessboard and charuco board are an 8x8 grid of 1 inch square. The provided charuco board uses the 4x4 dictionary with a marker size of 0.75 inches (this board does not need the old OpenCV pattern selector selected). Printers are not perfect, and you need to measure your calibration target and enter the correct marker size (size of the aruco marker) and pattern spacing (aka size of the black square) using calipers or similar. Finally, once our entered data is correct, we'll click "start calibration."
:::{warning} Old OpenCV Pattern selector. This should be used in the case that the calibration image is generated from a version of OpenCV before version 4.6.0. This would include targets created by calib.io. If this selector is not set correctly the calibration will be completely invalid. For more info view [this GitHub issue](https://github.com/opencv/opencv_contrib/issues/3291).
:::
### 4. Take at calibration images from various angles.
Now, we'll capture images of our board from various angles. It's important to check that the board overlay matches the board in your image. The further the overdrawn points are from the true position of the chessboard corners, the less accurate the final calibration will be. We'll want to capture enough images to cover the whole camera's FOV (with a minimum of 12). Once we've got our images, we'll click "Finish calibration" and wait for the calibration process to complete. If all goes well, the mean error and FOVs will be shown in the table on the right. The FOV should be close to the camera's specified FOV (usually found in a datasheet) usually within + or - 10 degrees. The mean error should also be low, usually less than 1 pixel.
```{raw} html
<video width="85%" controls>
<source src="../../_static/assets/calibration_small.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
```
## Accessing Calibration Images
Details about a particular calibration can be viewed by clicking on that resolution in the calibrations tab. This tab allows you to download raw calibration data, upload a previous calibration, and inspect details about calculated camera intrinsic.
```{image} images/cal-details.png
:alt: Captured calibration images
:width: 600
```
:::{note}
More info on what these parameters mean can be found in [OpenCV's docs](https://docs.opencv.org/4.8.0/d4/d94/tutorial_camera_calibration.html)
:::
- Fx/Fy: Estimated camera focal length, in mm
- Fx/Cy: Estimated camera optical center, in pixels. This should be at about the center of the image
- Distortion: OpenCV camera model distortion coefficients
- FOV: calculated using estimated focal length and image size. Useful for gut-checking calibration results
- Mean Err: Mean reprojection error, or distance between expected and observed chessboard cameras for the full calibration dataset
Below these outputs are the snapshots collected for calibration, along with a per-snapshot mean reprojection error. A snapshot with a larger reprojection error might indicate a bad snapshot, due to effects such as motion blur or misidentified chessboard corners.
Calibration images can also be extracted from the downloaded JSON file using [this Python script](https://raw.githubusercontent.com/PhotonVision/photonvision/master/devTools/calibrationUtils.py). This script will unpack calibration images, and also generate a VNL file for use [with mrcal](https://mrcal.secretsauce.net/).
```
python3 /path/to/calibrationUtils.py path/to/photon_calibration.json /path/to/output/folder
```
```{image} images/unpacked-json.png
:alt: Captured calibration images
:width: 600
```
## Investigating Calibration Data with mrcal
[mrcal](https://mrcal.secretsauce.net/tour.html) is a command-line tool for camera calibration and visualization. PhotonVision has the option to use the mrcal backend during camera calibration to estimate intrinsics. mrcal can also be used post-calibration to inspect snapshots and provide feedback. These steps will closely follow the [mrcal tour](https://mrcal.secretsauce.net/tour-initial-calibration.html) -- I'm aggregating commands and notes here, but the mrcal documentation is much more thorough.
Start by [Installing mrcal](https://mrcal.secretsauce.net/install.html). Note that while mrcal *calibration* using PhotonVision is supported on all platforms, but investigation right now only works on Linux. Some users have also reported luck using [WSL 2 on Windows](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps) as well. You may also need to install `feedgnuplot`. On Ubuntu systems, these commands should be run from a standalone terminal and *not* the one [built into vscode](https://github.com/ros2/ros2/issues/1406).
Let's run `calibrationUtils.py` as described above, and then cd into the output folder. From here, you can follow the mrcal tour, just replacing the VNL filename and camera imager size as necessary. My camera calibration was at 1280x720, so I've set the XY limits to that below.
```
$ cd /path/to/output/folder
$ ls
matt@photonvision:~/Documents/Downloads/2024-01-02_lifecam_1280$ ls
corners.vnl img0.png img10.png img11.png img12.png img13.png img1.png
img2.png img3.png img4.png img5.png img6.png img7.png img8.png
img9.png cameramodel_0.cameramodel
$ < corners.vnl \
vnl-filter -p x,y | \
feedgnuplot --domain --square --set 'xrange [0:1280] noextend' --set 'yrange [720:0] noextend'
```
```{image} images/mrcal-coverage.svg
:alt: A diagram showing the locations of all detected chessboard corners.
```
As you can see, we didn't do a fantastic job of covering our whole camera sensor -- there's a big gap across the whole right side, for example. We also only have 14 calibration images. We've also got our "cameramodel" file, which can be used by mrcal to display additional debug info.
Let's inspect our reprojection error residuals. We expect their magnitudes and directions to be random -- if there's patterns in the colors shown, then our calibration probably doesn't fully explain our physical camera sensor.
```
$ mrcal-show-residuals --magnitudes --set 'cbrange [0:1.5]' ./camera-0.cameramodel
$ mrcal-show-residuals --directions --unset key ./camera-0.cameramodel
```
```{image} images/residual-magnitudes.svg
:alt: A diagram showing residual magnitudes
```
```{image} images/residual-directions.svg
:alt: A diagram showing residual directions
```
Clearly we don't have anywhere near enough data to draw any meaningful conclusions (yet). But for fun, let's dig into [camera uncertainty estimation](https://mrcal.secretsauce.net/tour-uncertainty.html). This diagram shows how expected projection error changes due to noise in calibration inputs. Lower projection error across a larger area of the sensor imply a better calibration that more fully covers the whole sensor. For my calibration data, you can tell the projection error isolines (lines of constant expected projection error) are skewed to the left, following my dataset (which was also skewed left).
```
$ mrcal-show-projection-uncertainty --unset key ./cameramodel_0.cameramodel
```
```{image} images/camera-uncertainty.svg
:alt: A diagram showing camera uncertainty
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 341 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 600 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 519 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -0,0 +1,33 @@
# Building the PhotonVision Documentation
To build the PhotonVision documentation, you will require [Git](https://git-scm.com) and [Python 3.6 or greater](https://www.python.org).
## Cloning the Documentation Repository
Documentation lives within the main PhotonVision repository within the `docs` sub-folder. If you are planning on contributing, it is recommended to create a fork of the [PhotonVision repository](https://github.com/PhotonVision/photonvision). To clone this fork, run the following command in a terminal window:
`git clone https://github.com/[your username]/photonvision`
## Installing Python Dependencies
You must install a set of Python dependencies in order to build the documentation. To do so, you can run the following command in the docs sub-folder:
`~/photonvision/docs$ python -m pip install -r requirements.txt`
## Building the Documentation
In order to build the documentation, you can run the following command in the docs sub-folder. This will automatically build docs every time a file changes, and serves them locally at `localhost:8000` by default.
`~/photonvision/docs$ sphinx-autobuild --open-browser source/_build/html`
## Opening the Documentation
The built documentation is located at `docs/build/html/index.html` relative to the root project directory, or can be accessed via the local web server if using sphinx-autobuild.
## Docs Builds on Pull Requests
Pre-merge builds of docs can be found at: `https://photonvision-docs--PRNUMBER.org.readthedocs.build/en/PRNUMBER/index.html`. These docs are republished on every commit to a pull request made to PhotonVision/photonvision-docs. For example, PR 325 would have pre-merge documentation published to `https://photonvision-docs--325.org.readthedocs.build/en/325/index.html`. Additionally, the pull request will have a link directly to the pre-release build of the docs. This build only runs when there is a change to files in the docs sub-folder.
## Style Guide
PhotonVision follows the frc-docs style guide which can be found [here](https://docs.wpilib.org/en/stable/docs/contributing/style-guide.html). In order to run the linter locally (which builds on doc8 and checks for compliance with the style guide), follow the instructions [on GitHub](https://github.com/wpilibsuite/ohnoyoudidnt).

View File

@@ -0,0 +1,286 @@
# Build Instructions
This section contains the build instructions from the source code available at [our GitHub page](https://github.com/PhotonVision/photonvision).
## Development Setup
### Prerequisites
**Java Development Kit:**
This project requires Java Development Kit (JDK) 17 to be compiled. This is the same Java version that comes with WPILib for 2025+. **Windows Users must use the JDK that ships with WPILib.** For other platforms, you can follow the instructions to install JDK 17 for your platform [here](https://bell-sw.com/pages/downloads/#jdk-17-lts).
**Node JS:**
The UI is written in Node JS. To compile the UI, Node 18.20.4 to Node 20.0.0 is required. To install Node JS follow the instructions for your platform [on the official Node JS website](https://nodejs.org/en/download/). However, modify this line
```bash
nvm install 20
```
so that it instead reads
```javascript
nvm install 18.20.4
```
## Compiling Instructions
### Getting the Source Code
Get the source code from git:
```bash
git clone https://github.com/PhotonVision/photonvision
```
or alternatively download the source code from GitHub and extract the zip:
```{image} assets/git-download.png
:alt: Download source code from git
:width: 600
```
### Install Necessary Node JS Dependencies
In the photon-client directory:
```bash
npm install
```
### Build and Copy UI to Java Source
In the root directory:
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew buildAndCopyUI``
.. tab-item:: macOS
``./gradlew buildAndCopyUI``
.. tab-item:: Windows (cmd)
``gradlew buildAndCopyUI``
```
### Build and Run PhotonVision
To compile and run the project, issue the following command in the root directory:
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew run``
.. tab-item:: macOS
``./gradlew run``
.. tab-item:: Windows (cmd)
``gradlew run``
```
Running the following command under the root directory will build the jar under `photon-server/build/libs`:
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew shadowJar``
.. tab-item:: macOS
``./gradlew shadowJar``
.. tab-item:: Windows (cmd)
``gradlew shadowJar``
```
### Build and Run PhotonVision on a Raspberry Pi Coprocessor
As a convenience, the build has a built-in `deploy` command which builds, deploys, and starts the current source code on a coprocessor.
An architecture override is required to specify the deploy target's architecture.
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew clean``
``./gradlew deploy -PArchOverride=linuxarm64``
.. tab-item:: macOS
``./gradlew clean``
``./gradlew deploy -PArchOverride=linuxarm64``
.. tab-item:: Windows (cmd)
``gradlew clean``
``gradlew deploy -PArchOverride=linuxarm64``
```
The `deploy` command is tested against Raspberry Pi coprocessors. Other similar coprocessors may work too.
### Using PhotonLib Builds
The build process includes the following task:
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew generateVendorJson``
.. tab-item:: macOS
``./gradlew generateVendorJson``
.. tab-item:: Windows (cmd)
``gradlew generateVendorJson``
```
This generates a vendordep JSON of your local build at `photon-lib/build/generated/vendordeps/photonlib.json`.
The photonlib source can be published to your local maven repository after building:
```{eval-rst}
.. tab-set::
.. tab-item:: Linux
``./gradlew publishToMavenLocal``
.. tab-item:: macOS
``./gradlew publishToMavenLocal``
.. tab-item:: Windows (cmd)
``gradlew publishToMavenLocal``
```
After adding the generated vendordep to your project, add the following to your project's `build.gradle` under the `plugins {}` block.
```Java
repositories {
mavenLocal()
}
```
### Debugging PhotonVision Running Locally
One way is by running the program using gradle with the {code}`--debug-jvm` flag. Run the program with {code}`./gradlew run --debug-jvm`, and attach to it with VSCode by adding the following to {code}`launch.json`. Note args can be passed with {code}`--args="foobar"`.
```
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to Remote Program",
"request": "attach",
"hostName": "localhost",
"port": "5005",
"projectName": "photon-core",
}
]
}
```
PhotonVision can also be run using the gradle tasks plugin with {code}`"args": "--debug-jvm"` added to launch.json.
### Debugging PhotonVision Running on a CoProcessor
Set up a VSCode configuration in {code}`launch.json`
```
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to CoProcessor",
"request": "attach",
"hostName": "photonvision.local",
"port": "5801",
"projectName": "photon-core"
},
]
}
```
Stop any existing instance of PhotonVision.
Launch the program with the following additional argument to the JVM: {code}`java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5801 photonvision.jar`
Once the program says it is listening on port 5801, launch the debug configuration in VSCode.
The program will wait for the VSCode debugger to attach before proceeding.
### Running examples
You can run one of the many built in examples straight from the command line, too! They contain a fully featured robot project, and some include simulation support. The projects can be found inside the photonlib-*-examples subdirectories for each language.
#### Running C++/Java
PhotonLib must first be published to your local maven repository, then the copy PhotonLib task will copy the generated vendordep json file into each example. After that, the simulateJava/simulateNative task can be used like a normal robot project. Robot simulation with attached debugger is technically possible by using simulateExternalJava and modifying the launch script it exports, though not yet supported.
```
~/photonvision$ ./gradlew publishToMavenLocal
~/photonvision$ cd photonlib-java-examples
~/photonvision/photonlib-java-examples$ ./gradlew copyPhotonlib
~/photonvision/photonlib-java-examples$ ./gradlew <example-name>:simulateJava
~/photonvision$ cd photonlib-cpp-examples
~/photonvision/photonlib-cpp-examples$ ./gradlew copyPhotonlib
~/photonvision/photonlib-cpp-examples$ ./gradlew <example-name>:simulateNative
```
#### Running Python
PhotonLibPy must first be built into a wheel.
```
> cd photon-lib/py
> buildAndTest.bat
```
Then, you must enable using the development wheels. robotpy will use pip behind the scenes, and this bat file tells pip about your development artifacts.
Note: This is best done in a virtual environment.
```
> enableUsingDevBuilds.bat
```
Then, run the examples:
```
> cd photonlib-python-examples
> run.bat <example name>
```

View File

@@ -0,0 +1,61 @@
# Calibration and Image Rotation
## Rotating Points
To stay consistent with the OpenCV camera coordinate frame, we put the origin in the top left, with X right, Y down, and Z out (as required by the right-hand rule). Intuitively though, if I ask you to rotate an image 90 degrees clockwise though, you'd probably rotate it about -Z in this coordinate system. Just be aware of this inconsistency.
![](images/image_corner_frames.png)
If we have any one point in any of those coordinate systems, we can transform it into any of the other ones using standard geometry libraries by performing relative transformations (like in this pseudocode):
```
Translation2d tag_corner1 = new Translation2d();
Translation2d rotated = tag_corner1.relativeTo(ORIGIN_ROTATED_90_CCW);
```
## Image Distortion
The distortion coefficients for OPENCV8 is given in order `[k1 k2 p1 p2 k3 k4 k5 k6]`. Mrcal names these coefficients `[k_0 k_1, k_2, k_3, k_4, k_5, k_6, k_7]`.
```{math}
\begin{align*}
\vec P &\equiv \frac{\vec p_{xy}}{p_z} \\
r &\equiv \left|\vec P\right| \\
\vec P_\mathrm{radial} &\equiv \frac{ 1 + k_0 r^2 + k_1 r^4 + k_4 r^6}{ 1 + k_5 r^2 + k_6 r^4 + k_7 r^6} \vec P \\
\vec P_\mathrm{tangential} &\equiv
\left[ \begin{aligned}
2 k_2 P_0 P_1 &+ k_3 \left(r^2 + 2 P_0^2 \right) \\
2 k_3 P_0 P_1 &+ k_2 \left(r^2 + 2 P_1^2 \right)
\end{aligned}\right] \\
\vec q &= \vec f_{xy} \left( \vec P_\mathrm{radial} + \vec P_\mathrm{tangential} \right) + \vec c_{xy}
\end{align*}
```
From this, we observe at `k_0, k_1, k_4, k_5, k_6, k_7` depend only on the norm of {math}`\vec P`, and will be constant given a rotated image. However, `k_2` and `k_3` go with {math}`P_0 \cdot P_1`, `k_3` with {math}`P_0^2`, and `k_2` with {math}`P_1^2`.
Let's try a concrete example. With a 90 degree CCW rotation, we have {math}`P0=-P_{1\mathrm{rotated}}` and {math}`P1=P_{0\mathrm{rotated}}`. Let's substitute in
```{math}
\begin{align*}
\left[ \begin{aligned}
2 k_2 P_0 P_1 &+ k_3 \left(r^2 + 2 P_0^2 \right) \\
2 k_3 P_0 P_1 &+ k_2 \left(r^2 + 2 P_1^2 \right)
\end{aligned}\right] &=
\left[ \begin{aligned}
2 k_{2\mathrm{rotated}} (-P_{1\mathrm{rotated}}) P_{0\mathrm{rotated}} &+ k_{3\mathrm{rotated}} \left(r^2 + 2 (-P_{1\mathrm{rotated}})^2 \right) \\
2 k_{3\mathrm{rotated}} (-P_{1\mathrm{rotated}}) P_{0\mathrm{rotated}} &+ k_{2\mathrm{rotated}} \left(r^2 + 2 P_{0\mathrm{rotated}}^2 \right)
\end{aligned}\right] \\
&=
\left[ \begin{aligned}
-2 k_{2\mathrm{rotated}} P_{1\mathrm{rotated}} P_{0\mathrm{rotated}} &+ k_{3\mathrm{rotated}} \left(r^2 + 2 P_{1\mathrm{rotated}}^2 \right) \\
-2 k_{3\mathrm{rotated}} P_{1\mathrm{rotated}} P_{0\mathrm{rotated}} &+ k_{2\mathrm{rotated}} \left(r^2 + 2 P_{0\mathrm{rotated}}^2 \right)
\end{aligned}\right]
\end{align*}
```
By inspection, this results in just applying another 90 degree rotation to the k2/k3 parameters. Proof is left as an exercise for the reader. Note that we can repeat this rotation to yield equations for tangential distortion for 180 and 270 degrees.
```{math}
k_2'=-k_3
k_3'=k_2
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,7 @@
# Software Architecture Design Descriptions
```{toctree}
:maxdepth: 1
image-rotation
time-sync
```

View File

@@ -0,0 +1,111 @@
# Time Synchronization Protocol Specification, Version 1.0
Protocol Revision 1.0, 08/25/2024
## Background
In a distributed compute environment like robots, time synchronization between computers is increasingly important. Currently, [NetworkTables Version 4.1](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc) provides support for time synchronization of clients with the NetworkTables server using binary PING/PONG messages sent over WebSockets. This approach, while fundamentally the same as is described in this memo, has demonstrated some opportunities for improvement:
- PING/PONG messages are processed in the same queue as other NetworkTables messages. Depending on the underlying implementation and processor speed, this can incur message processing delays and increase client-calculated Round-Trip Time (RTT), and cause messages to arrive at the server timestamped in the future.
- Messages use WebSockets over TCP for their transport layer. We don't need the robustness guarantees of TCP as our connection is stateless.
For these reasons, a time synchronization solution separate from NetworkTables communication was desired. Architecture decisions made to address these issues are:
- Use the User Datagram Protocol (UDP) transport layer, as we don't need the robustness guarantees afforded by TCP. As a Client, if a PING isn't replied to, we'll just try again at the start of the next PING window. As a bonus, we are free to use UDP port 5810 as NetworkTables only uses TCP Port 5810/5811 as of Version 4.1.
- Use a separate thread from the current NetworkTables libUV runner.
## Prior Art
The [NetworkTables 4.1 timestamp synchronization](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc#timestamps) approach, an implementation of [Cristian's Algorithm](https://en.wikipedia.org/wiki/Cristian%27s_algorithm). We also implement Cristians Algorithm.
The [Precision Time Protocol](https://en.wikipedia.org/wiki/Precision_Time_Protocol#Synchronization) at it's core does something similar with Sync/Delay_Req/Delay_Resp. We do not have (guaranteed) access to hardware timestamping, but we utilize this PING/PONG pattern to estimate total round-trip time.
## Roles
```{graphviz}
digraph CristianAlgorithm {
ratio=0.5;
bgcolor="transparent";
node [
fontcolor = "#e6e6e6",
style = filled,
color = "#e6e6e6",
fillcolor = "#333333"
fontsize=10;
]
edge [
color = "#e6e6e6",
fontcolor = "#e6e6e6"
fontsize=10;
]
rankdir=LR;
node [shape=box, style=filled, color=lightblue];
user_send [label="User Sends T1"];
server_receive [label="Server Receives T1"];
server_send [label="Server Sends T2"];
user_receive [label="User Receives T2"];
user_compute [label="User Computes Time"];
user_send -> server_receive [label="T1 (Request)"];
server_receive -> server_send [label="T1 received by server"];
server_send -> user_receive [label="T2 sent by server"];
user_receive -> user_compute [label="T2 received by user"];
user_compute -> user_send [label="Computed Time: T3 = T2 + (deltaT2 - deltaT1)/2"];
}
```
Time Synchronization Protocol (TSP) participants can assume either a server role or a client role. The server role is responsible for listening for incoming time synchronization requests from clients and replying appropriately. The client role is responsible for sending "Ping" messages to the server and listening for "Pong" replies to estimate the offset between the server and client time bases.
All time values shall use units of microseconds. The epoch of the time base this is measured against is unspecified.
Clients shall periodically (e.g. every few seconds) send, in a manner that minimizes transmission delays, a **TSP Ping Message** that contains the client's current local time.
When the server receives a **TSP Ping Message** from any client, it shall respond to the client, in a manner that minimizes transmission delays, with a **TSP Pong message** encoding a timestamp of its (the server's) current local time (in microseconds), and the client-provided data value.
When the client receives a **TSP Pong Message** from the server, it shall verify that the `Client Local Time` corresponds to the currently in-flight TSP Ping message; if not, it shall drop this packet. The round trip time (RTT) shall be computed from the delta between the message's data value and the current local time. If the RTT is less than that from previous measurements, the client shall use the timestamp in the message plus ½ the RTT as the server time equivalent to the current local time, and use this equivalence to compute server time base timestamps from local time for future messages.
## Transport
Communication between server and clients shall occur over the User Datagram Protocol (UDP) Port 5810.
## Message Format
The message format forgoes CRCs (as these are provided by the Ethernet physical layer) or packet delimination (as our packetsa are assumed be under the network MTU). **TSP Ping** and **TSP Pong** messages shall be encoded in a manor compatible with a WPILib packed struct with respect to byte alignment and endienness.
### TSP Ping
| Offset | Format | Data | Notes |
| ------ | ------ | ---- | ----- |
| 0 | uint8 | Protocol version | This field shall always set to 1 (0b1) for TSP Version 1. |
| 1 | uint8 | Message ID | This field shall always be set to 1 (0b1). |
| 2 | uint64 | Client Local Time | The client's local time value, at the time this Ping message was sent. |
### TSP Pong
| Offset | Format | Data | Notes |
| ------ | ------ | ---- | ----- |
| 0 | uint8 | Protocol version | This field shall always set to 1 (0b1) for TSP Version 1.
| 1 | uint8 | Message ID | This field shall always be set to 2 (0b2).
| 2 | uint64 | Client Local Time | The client's local time value from the Ping message that this Pong is generated in response to.
| 10 | uint64 | Server Local Time | The current time at the server, at the time this Pong message was sent.
## Optional Protocol Extensions
Clients may publish statistics to NetworkTables. If they do, they shall publish to a key that is globally unique per participant in the Time Synronization network. If a client implements this, it shall provide the following publishers:
| Key | Type | Notes |
| ------ | ------ | ---- |
| offset_us | Integer | The time offset that, when added to the client's local clock, provides server time |
| ping_tx_count | Integer | The total number of TSP Ping packets transmitted |
| ping_rx_count | Integer | The total number of TSP Ping packets received |
| pong_rx_time_us | Integer | The time, in client local time, that the last pong was received |
| rtt2_us | Integer | The time in us from last complete (ping transmission to pong reception) |
PhotonVision has chosen to publish to the sub-table `/photonvision/.timesync/{DEVICE_HOSTNAME}`. Future implementations of this protocol may decide to implement this as a structured data type.

View File

@@ -0,0 +1,5 @@
# PhotonVision Developer Documentation
```{toctree}
photonlib-backups
```

View File

@@ -0,0 +1,16 @@
# Photonlib Developer Docs
Our maven server is located at https://maven.photonvision.org/#/. This server runs [Reposilite](https://hub.docker.com/r/dzikoysk/reposilite) in Docker, and uses Caddy for serving requests.
## Backing up using Rsync
The Clarkson Open Source Institute at Clarkson University provides a mirror of our artifacts available [online](https://mirror.clarkson.edu/photonvision). Learn more about them at [their homepage](https://mirror.clarkson.edu/home).
Artifacts from our Maven server can also be backed up locally to a folder called `photonlib-backup` using the following command, which excludes "snapshots" for space reasons:
```
rsync -avzrHy --no-perms --no-group --no-owner --ignore-errors --exclude ".~tmp~" --exclude "snapshots/org/photonvision/photontargeting*" \
--exclude "snapshots/org/photonvision/photonlib*" maven.photonvision.org::reposilite-data \
/path/to/photonlib-backup
```

View File

@@ -0,0 +1,8 @@
# Contributing to PhotonVision Projects
```{toctree}
building-photon
building-docs
developer-docs/index
design-descriptions/index
```

View File

@@ -0,0 +1,46 @@
# About PhotonVision
## Description
PhotonVision is a free, fast, and easy-to-use vision processing solution for the *FIRST*Robotics Competition. PhotonVision is designed to get vision working on your robot *quickly*, without the significant cost of other similar solutions.
Using PhotonVision, teams can go from setting up a camera and coprocessor to detecting and tracking AprilTags and other targets by simply tuning sliders. With an easy to use interface, comprehensive documentation, and a feature rich vendor dependency, no experience is necessary to use PhotonVision. No matter your resources, using PhotonVision is easy compared to its alternatives.
## Advantages
PhotonVision has a myriad of advantages over similar solutions, including:
### Affordable
Compared to alternatives, PhotonVision is much cheaper to use (at the cost of your coprocessor and camera) compared to alternatives that cost \$400. This allows your team to save money while still being competitive.
### Easy to Use User Interface
The PhotonVision user interface is simple and modular, making things easier for the user. With a simpler interface, you can focus on what matters most, tracking targets, rather than how to use our UI. A major unique quality is that the PhotonVision UI includes an offline copy of our documentation for your ease of access at competitions.
### PhotonLib Vendor Dependency
The PhotonLib vendor dependency allows you to easily get necessary target data (without having to work directly with NetworkTables) while also providing utility methods to get distance and position on the field. This helps your team focus less on getting data and more on using it to do cool things. This also has the benefit of having a structure that ensures all data is from the same timestamp, which is helpful for latency compensation.
### User Calibration
Using PhotonVision allows the user to calibrate for their specific camera, which will get you the best tracking results. This is extremely important as every camera (even if it is the same model) will have it's own quirks and user calibration allows for those to be accounted for.
### High FPS Processing
Compared to alternative solutions, PhotonVision boasts higher frames per second which allows for a smoother video stream and detection of targets to ensure you aren't losing out on any performance.
### Low Latency
PhotonVision provides low latency processing to make sure you get vision measurements as fast as possible, which makes complex vision tasks easier. We guarantee that all measurements are sent from the same timestamp, making life easier for your programmers.
### Fully Open Source and Active Developer Community
You can find all of our code on [GitHub](https://github.com/PhotonVision), including code for our main program, documentation, vendor dependency (PhotonLib), and more. This helps you see everything working behind the scenes and increases transparency. This also allows users to make pull requests for features that they want to add in to PhotonVision that will be reviewed by the development team. PhotonVision is licensed under the GNU General Public License (GPLv3) which you can learn more about [here](https://www.gnu.org/licenses/quick-guide-gplv3.html).
### Multi-Camera Support
You can use multiple cameras within PhotonVision, allowing you to see multiple angles without the need to buy multiple coprocessors. This makes vision processing more affordable and simpler for your team.
### Comprehensive Documentation
Using our comprehensive documentation, you will be able to easily start vision processing by following a series of simple steps.

View File

@@ -0,0 +1,50 @@
# Combining Aiming and Getting in Range
The following example is from the PhotonLib example repository ([Java](https://github.com/PhotonVision/photonvision/tree/master/photonlib-java-examples/aimandrange)/[C++](https://github.com/PhotonVision/photonvision/tree/master/photonlib-cpp-examples/aimandrange)).
## Knowledge and Equipment Needed
- Everything required in {ref}`Aiming at a Target <docs/examples/aimingatatarget:Knowledge and Equipment Needed>`.
## Code
Now that you know how to aim toward the AprilTag, let's also drive the correct distance from the AprilTag.
To do this, we'll use the *pitch* of the target in the camera image and trigonometry to figure out how far away the robot is from the AprilTag. Then, like before, we'll use the P term of a PID controller to drive the robot to the correct distance.
```{eval-rst}
.. tab-set::
.. tab-item:: Java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/aimandrange/src/main/java/frc/robot/Robot.java
:language: java
:lines: 84-131
:linenos:
:lineno-start: 84
.. tab-item:: C++ (Header)
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/aimandrange/src/main/include/Robot.h
:language: c++
:lines: 25-63
:linenos:
:lineno-start: 25
.. tab-item:: C++ (Source)
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/aimandrange/src/main/cpp/Robot.cpp
:language: c++
:lines: 58-107
:linenos:
:lineno-start: 58
.. tab-item:: Python
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/aimandrange/robot.py
:language: python
:lines: 44-95
:linenos:
:lineno-start: 44
```

View File

@@ -0,0 +1,55 @@
# Aiming at a Target
The following example is from the PhotonLib example repository ([Java](https://github.com/PhotonVision/photonvision/tree/master/photonlib-java-examples/aimattarget)).
## Knowledge and Equipment Needed
- A Robot
- A camera mounted rigidly to the robot's frame, cenetered and pointed forward.
- A coprocessor running PhotonVision with an AprilTag or Aurco 2D Pipeline.
- [A printout of Apriltag 7](https://firstfrc.blob.core.windows.net/frc2024/FieldAssets/Apriltag_Images_and_User_Guide.pdf), mounted on a rigid and flat surface.
## Code
Now that you have properly set up your vision system and have tuned a pipeline, you can now aim your robot at an AprilTag using the data from PhotonVision. The *yaw* of the target is the critical piece of data that will be needed first.
Yaw is reported to the roboRIO over Network Tables. PhotonLib, our vender dependency, is the easiest way to access this data. The documentation for the Network Tables API can be found {ref}`here <docs/additional-resources/nt-api:Getting Target Information>` and the documentation for PhotonLib {ref}`here <docs/programming/photonlib/adding-vendordep:What is PhotonLib?>`.
In this example, while the operator holds a button down, the robot will turn towards the AprilTag using the P term of a PID loop. To learn more about how PID loops work, how WPILib implements them, and more, visit [Advanced Controls (PID)](https://docs.wpilib.org/en/stable/docs/software/advanced-control/introduction/index.html) and [PID Control in WPILib](https://docs.wpilib.org/en/stable/docs/software/advanced-controls/controllers/pidcontroller.html#pid-control-in-wpilib).
```{eval-rst}
.. tab-set::
.. tab-item:: Java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/aimattarget/src/main/java/frc/robot/Robot.java
:language: java
:lines: 77-117
:linenos:
:lineno-start: 77
.. tab-item:: C++ (Header)
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/aimattarget/src/main/include/Robot.h
:language: c++
:lines: 25-60
:linenos:
:lineno-start: 25
.. tab-item:: C++ (Source)
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/aimattarget/src/main/cpp/Robot.cpp
:language: c++
:lines: 56-96
:linenos:
:lineno-start: 56
.. tab-item:: Python
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/aimattarget/robot.py
:language: python
:lines: 46-70
:linenos:
:lineno-start: 46
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 MiB

View File

@@ -0,0 +1,9 @@
# Code Examples
```{toctree}
:maxdepth: 1
aimingatatarget
aimandrange
poseest
```

View File

@@ -0,0 +1,211 @@
# Using WPILib Pose Estimation, Simulation, and PhotonVision Together
The following example comes from the PhotonLib example repository ([Java](https://github.com/PhotonVision/photonvision/tree/master/photonlib-java-examples/poseest)/[C++](https://github.com/PhotonVision/photonvision/tree/master/photonlib-cpp-examples/poseest)/[Python](https://github.com/PhotonVision/photonvision/tree/master/photonlib-python-examples/poseest)). Full code is available at that links.
## Knowledge and Equipment Needed
- Everything required in {ref}`Combining Aiming and Getting in Range <docs/examples/aimandrange:Knowledge and Equipment Needed>`, plus some familiarity with WPILib pose estimation functionality.
## Background
This example demonstrates integration of swerve drive control, a basic swerve physics simulation, and PhotonLib's simulated vision system functionality.
## Walkthrough
### Estimating Pose
The {code}`Drivetrain` class includes functionality to fuse multiple sensor readings together (including PhotonVision) into a best-guess of the pose on the field.
Please reference the [WPILib documentation](https://docs.wpilib.org/en/stable/docs/software/advanced-controls/state-space/state-space-pose_state-estimators.html) on using the {code}`SwerveDrivePoseEstimator` class.
We use the 2024 game's AprilTag Locations:
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
:language: java
:lines: 68-68
:linenos:
:lineno-start: 68
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/include/Constants.h
:language: c++
:lines: 42-43
:linenos:
:lineno-start: 42
.. tab-item:: Python
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/poseest/robot.py
:language: python
:lines: 46-46
:linenos:
:lineno-start: 46
```
To incorporate PhotonVision, we need to create a {code}`PhotonCamera`:
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
:language: java
:lines: 57-57
:linenos:
:lineno-start: 57
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/include/Vision.h
:language: c++
:lines: 145-145
:linenos:
:lineno-start: 145
.. tab-item:: Python
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/poseest/robot.py
:language: python
:lines: 44-44
:linenos:
:lineno-start: 44
```
During periodic execution, we read back camera results. If we see AprilTags in the image, we calculate the camera-measured pose of the robot and pass it to the {code}`Drivetrain`.
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Robot.java
:language: java
:lines: 64-74
:linenos:
:lineno-start: 64
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/cpp/Robot.cpp
:language: c++
:lines: 38-46
:linenos:
:lineno-start: 38
.. tab-item:: Python
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/poseest/robot.py
:language: python
:lines: 54-56
:linenos:
:lineno-start: 54
```
### Simulating the Camera
First, we create a new {code}`VisionSystemSim` to represent our camera and coprocessor running PhotonVision, and moving around our simulated field.
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
:language: java
:lines: 65-69
:linenos:
:lineno-start: 65
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/include/Vision.h
:language: c++
:lines: 49-52
:linenos:
:lineno-start: 49
.. tab-item:: Python
# Coming Soon!
```
Then, we add configure the simulated vision system to match the camera system being simulated.
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
:language: java
:lines: 69-82
:linenos:
:lineno-start: 69
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/include/Vision.h
:language: c++
:lines: 53-65
:linenos:
:lineno-start: 53
.. tab-item:: Python
# Coming Soon!
```
### Updating the Simulated Vision System
During simulation, we periodically update the simulated vision system.
```{eval-rst}
.. tab-set::
.. tab-item:: Java
:sync: java
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-java-examples/poseest/src/main/java/frc/robot/Robot.java
:language: java
:lines: 114-132
:linenos:
:lineno-start: 114
.. tab-item:: C++
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-cpp-examples/poseest/src/main/cpp/Robot.cpp
:language: c++
:lines: 95-109
:linenos:
:lineno-start: 95
.. tab-item:: Python
# Coming Soon!
```
The rest is done behind the scenes.
```{image} images/poseest_demo.gif
:alt: Simulated swerve drive and vision system working together in teleoperated mode.
:width: 1200
```

View File

@@ -0,0 +1,121 @@
# Deploying on Custom Hardware
## Configuration
By default, PhotonVision attempts to make minimal assumptions of the hardware it runs on. However, it may be configured to enable custom LED control, branding, and other functionality.
`hardwareConfig.json` is the location for this configuration. It is included when settings are exported, and can be uploaded as part of a .zip, or on its own.
## LED Support
For Raspberry-Pi based hardware, PhotonVision can use [PiGPIO](https://abyz.me.uk/rpi/pigpio/) to control IO pins. The mapping of which pins control which LED's is part of the hardware config. The pins are active-high: set high when LED's are commanded on, and set low when commanded off.
```{eval-rst}
.. tab-set-code::
.. code-block:: json
{
"ledPins" : [ 13 ],
"ledSetCommand" : "",
"ledsCanDim" : true,
"ledPWMRange" : [ 0, 100 ],
"ledPWMSetRange" : "",
"ledPWMFrequency" : 0,
"ledDimCommand" : "",
"ledBlinkCommand" : "",
"statusRGBPins" : [ ],
}
```
:::{note}
No hardware boards with status RGB LED pins or non-dimming LED's have been tested yet. Please reach out to the development team if these features are desired, they can assist with configuration and testing.
:::
## Hardware Interaction Commands
For Non-Raspberry-Pi hardware, users must provide valid hardware-specific commands for some parts of the UI interaction (including performance metrics, and executing system restarts).
Leaving a command blank will disable the associated functionality.
```{eval-rst}
.. tab-set-code::
.. code-block:: json
{
"cpuTempCommand" : "",
"cpuMemoryCommand" : "",
"cpuUtilCommand" : "",
"gpuMemoryCommand" : "",
"gpuTempCommand" : "",
"ramUtilCommand" : "",
"restartHardwareCommand" : "",
}
```
:::{note}
These settings have no effect if PhotonVision detects it is running on a Raspberry Pi. See [the MetricsBase class](https://github.com/PhotonVision/photonvision/blob/dbd631da61b7c86b70fa6574c2565ad57d80a91a/photon-core/src/main/java/org/photonvision/common/hardware/metrics/MetricsBase.java) for the commands utilized.
:::
## Known Camera FOV
If your hardware contains a camera with a known field of vision, it can be entered into the hardware configuration. This will prevent users from editing it in the GUI.
```{eval-rst}
.. tab-set-code::
.. code-block:: json
{
"vendorFOV" : 98.9
}
```
## Cosmetic & Branding
To help differentiate your hardware from other solutions, some customization is allowed.
```{eval-rst}
.. tab-set-code::
.. code-block:: json
{
"deviceName" : "Super Cool Custom Hardware",
"deviceLogoPath" : "",
"supportURL" : "https://cat-bounce.com/",
}
```
:::{note}
Not all configuration is currently presented in the User Interface. Additional file uploads may be needed to support custom images.
:::
## Example
Here is a complete example `hardwareConfig.json`:
```{eval-rst}
.. tab-set-code::
.. code-block:: json
{
"deviceName" : "Blinky McBlinkface",
"deviceLogoPath" : "",
"supportURL" : "https://www.youtube.com/watch?v=b-CvLWbfZhU",
"ledPins" : [2, 13],
"ledSetCommand" : "",
"ledsCanDim" : true,
"ledPWMRange" : [ 0, 100 ],
"ledPWMSetRange" : "",
"ledPWMFrequency" : 0,
"ledDimCommand" : "",
"ledBlinkCommand" : "",
"statusRGBPins" : [ ],
"cpuTempCommand" : "",
"cpuMemoryCommand" : "",
"cpuUtilCommand" : "",
"gpuMemoryCommand" : "",
"gpuTempCommand" : "",
"ramUtilCommand" : "",
"restartHardwareCommand" : "",
"vendorFOV" : 72.5
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@@ -0,0 +1,9 @@
# Hardware Selection
```{toctree}
:maxdepth: 2
selecting-hardware
picamconfig
customhardware
```

View File

@@ -0,0 +1,58 @@
# Pi Camera Configuration
## Background
The Raspberry Pi CSI Camera port is routed through and processed by the GPU. Since the GPU boots before the CPU, it must be configured properly for the attached camera. Additionally, this configuration cannot be changed without rebooting.
The GPU is not always capable of detecting other cameras automatically. The file `/boot/config.txt` is parsed by the GPU at boot time to determine what camera, if any, is expected to be attached. This file must be updated for some cameras.
:::{warning}
Incorrect camera configuration will cause the camera to not be detected. It looks exactly the same as if the camera was unplugged.
:::
## Updating `config.txt`
After flashing the pi image onto an SD card, open the `boot` segment in a file browser.
:::{note}
Windows may report "There is a problem with this drive". This should be ignored.
:::
Locate `config.txt` in the folder, and open it with your favorite text editor.
```{image} images/bootConfigTxt.png
```
Within the file, find this block of text:
```
##############################################################
### PHOTONVISION CAM CONFIG
### Comment/Uncomment to change which camera is supported
### Picam V1, V2 or HQ: uncomment (remove leading # ) from camera_auto_detect=1,
### and comment out all following lines
### IMX290/327/OV9281/Any other cameras that require additional overlays:
### Comment out (add a # ) to camera_auto_detect=1, and uncomment the line for
### the sensor you're trying to user
cameraAutoDetect=1
# dtoverlay=imx290,clock-frequency=74250000
# dtoverlay=imx290,clock-frequency=37125000
# dtoverlay=imx378
# dtoverlay=ov9281
##############################################################
```
Remove the leading `#` character to uncomment the line associated with your camera. Add a `#` in front of other cameras.
:::{warning}
Leave lines outside the PhotonVision Camera Config block untouched. They are necessary for proper raspberry pi functionality.
:::
Save the file, close the editor, and eject the drive. The boot configuration should now be ready for your selected camera.
## Additional Information
See [the libcamera documentation](https://github.com/raspberrypi/documentation/blob/679fab721855a3e8f17aa51819e5c2a7c447e98d/documentation/asciidoc/computers/camera/rpicam_configuration.adoc) for more details on configuring cameras.

View File

@@ -0,0 +1,96 @@
# Selecting Hardware
In order to use PhotonVision, you need a coprocessor and a camera. This page will help you select the right hardware for your team depending on your budget, needs, and experience.
## Choosing a Coprocessor
### Minimum System Requirements
- Ubuntu 22.04 LTS or Windows 10/11
- We don't recommend using Windows for anything except testing out the system on a local machine.
- CPU: ARM Cortex-A53 (the CPU on Raspberry Pi 3) or better
- At least 8GB of storage
- 2GB of RAM
- PhotonVision isn't very RAM intensive, but you'll need at least 2GB to run the OS and PhotonVision.
- The following IO:
- At least 1 USB or MIPI-CSI port for the camera
- Note that we only support using the Raspberry Pi's MIPI-CSI port, other MIPI-CSI ports from other coprocessors may not work.
- Ethernet port for networking
### Coprocessor Recommendations
When selecting a coprocessor, it is important to consider various factors, particularly when it comes to AprilTag detection. Opting for a coprocessor with a more powerful CPU can generally result in higher FPS AprilTag detection, leading to more accurate pose estimation. However, it is important to note that there is a point of diminishing returns, where the benefits of a more powerful CPU may not outweigh the additional cost. Below is a list of supported hardware, along with some notes on each.
- Orange Pi 5 (\$99)
- This is the recommended coprocessor for most teams. It has a powerful CPU that can handle AprilTag detection at high FPS, and is relatively cheap compared to processors of a similar power.
- Raspberry Pi 4/5 (\$55-\$80)
- This is the recommended coprocessor for teams on a budget. It has a less powerful CPU than the Orange Pi 5, but is still capable of running PhotonVision at a reasonable FPS.
- Mini PCs (such as Beelink N5095)
- This coprocessor will likely have similar performance to the Orange Pi 5 but has a higher performance ceiling (when using more powerful CPUs). Do note that this would require extra effort to wire to the robot / get set up. More information can be found in the set up guide [here.](https://docs.google.com/document/d/1lOSzG8iNE43cK-PgJDDzbwtf6ASyf4vbW8lQuFswxzw/edit?usp=drivesdk)
- Other coprocessors can be used but may require some extra work / command line usage in order to get it working properly.
## Choosing a Camera
PhotonVision works with Pi Cameras and most USB Cameras, the recommendations below are known to be working and have been tested. Other cameras such as webcams, virtual cameras, etc. are not officially supported and may not work. It is important to note that fisheye cameras should only be used as a driver camera and not for detecting targets.
PhotonVision relies on [CSCore](https://github.com/wpilibsuite/allwpilib/tree/main/cscore) to detect and process cameras, so camera support is determined based off compatibility with CScore along with native support for the camera within your OS (ex. [V4L compatibility](https://en.wikipedia.org/wiki/Video4Linux) if using a Linux machine like a Raspberry Pi).
:::{note}
Logitech Cameras and integrated laptop cameras will not work with PhotonVision due to oddities with their drivers. We recommend using a different camera.
:::
:::{note}
We do not currently support the usage of two of the same camera on the same coprocessor. You can only use two or more cameras if they are of different models or they are from Arducam, which has a [tool that allows for cameras to be renamed](https://docs.arducam.com/UVC-Camera/Serial-Number-Tool-Guide/).
:::
### Recommended Cameras
For colored shape detection, any non-fisheye camera supported by PhotonVision will work. We recommend the Pi Camera V1 or a high fps USB camera.
For driver camera, we recommend a USB camera with a fisheye lens, so your driver can see more of the field.
For AprilTag detection, we recommend you use a global shutter camera that has ~100 degree diagonal FOV. This will allow you to see more AprilTags in frame, and will allow for more accurate pose estimation. You also want a camera that supports high FPS, as this will allow you to update your pose estimator at a higher frequency.
- Recommendations For AprilTag Detection
- Arducam USB OV9281
- This is the recommended camera for AprilTag detection as it is a high FPS, global shutter camera USB camera that has a ~70 degree FOV.
- Innomaker OV9281
- Spinel AR0144
- Pi Camera Module V1
- The V1 is strongly preferred over the V2 due to the V2 having undesirable FOV choices
### AprilTags and Motion Blur
When detecting AprilTags, you want to reduce the "motion blur" as much as possible. Motion blur is the visual streaking/smearing on the camera stream as a result of movement of the camera or object of focus. You want to mitigate this as much as possible because your robot is constantly moving and you want to be able to read as many tags as you possibly can. The possible solutions to this include:
1. Cranking your exposure as low as it goes and increasing your gain/brightness. This will decrease the effects of motion blur and increase FPS.
2. Using a global shutter (as opposed to rolling shutter) camera. This should eliminate most, if not all motion blur.
3. Only rely on tags when not moving.
```{image} images/motionblur.gif
:align: center
```
### Using Multiple Cameras
Using multiple cameras on your robot will help you detect more AprilTags at once and improve your pose estimation as a result. In order to use multiple cameras, you will need to create multiple PhotonPoseEstimators and add all of their measurements to a single drivetrain pose estimator. Please note that the accuracy of your robot to camera transform is especially important when using multiple cameras as any error in the transform will cause your pose estimations to "fight" each other. For more information, see {ref}`the programming reference. <docs/programming/index:programming reference>`.
## Performance Matrix
```{raw} html
<embed>
<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-1vTojOew2d2NQY4PRA98vjkS1ECZ2YNvods-aOdk2x-Q4aF_7r4mcwlyTe8GjUKmUxEiVgGNnJNhEdyd/pubhtml?gid=1779881081&amp;single=true&amp;widget=true&amp;headers=false" width="760" height="500" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
</embed>
```
Please submit performance data to be added to the matrix here:
```{raw} html
<embed>
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLSf5iK3pX0Tn8bxpRYgcTAy4scUu14rUvJqkTyfzoKc-GiV7Vg/viewform?embedded=true" width="760" height="500" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
</embed>
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -0,0 +1,38 @@
# Installation & Setup
This page will help you install PhotonVision on your coprocessor, wire it, and properly setup the networking in order to start tracking targets.
## Step 1: Software Install
This section will walk you through how to install PhotonVision on your coprocessor. Your coprocessor is the device that has the camera and you are using to detect targets (ex. if you are using a Limelight / Raspberry Pi, that is your coprocessor and you should follow those instructions).
:::{warning}
You only need to install PhotonVision on the coprocessor/device that is being used to detect targets, you do NOT need to install it on the device you use to view the webdashboard. All you need to view the webdashboard is for a device to be on the same network as your vision coprocessor and an internet browser.
:::
```{toctree}
:maxdepth: 3
sw_install/index
updating
```
## Step 2: Wiring
This section will walk you through how to wire your coprocessor to get power.
```{toctree}
:maxdepth: 1
wiring
```
## Step 3: Networking
This section will walk you though how to connect your coprocessor to a network. This section is very important (and easy to get wrong), so we recommend you read it thoroughly.
```{toctree}
:maxdepth: 1
networking
```

Some files were not shown because too many files have changed in this diff Show More