Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29f76bc1c3 | ||
|
|
35c79b138c | ||
|
|
73cd2ab62c | ||
|
|
ae9f73130f | ||
|
|
c1b0c8a831 | ||
|
|
99b4dc8725 | ||
|
|
0c9502d8b9 | ||
|
|
c15c62698a | ||
|
|
7bbfe6f05b | ||
|
|
5349cae965 | ||
|
|
3ea9100845 | ||
|
|
ad1f51ba06 | ||
|
|
1b1f8029c8 | ||
|
|
1bb861545b | ||
|
|
a4295275ed | ||
|
|
0dfca8c04f | ||
|
|
3ed8d3a4f3 | ||
|
|
7f7d80bc3b | ||
|
|
89c0cc3a01 | ||
|
|
e514071094 | ||
|
|
38ee450117 | ||
|
|
23d5e5b34f | ||
|
|
75dee20d77 | ||
|
|
ed7fc6bbcc | ||
|
|
8a2c9f2ae0 | ||
|
|
c45c2a0a1f | ||
|
|
b86217a59a | ||
|
|
4ffd1fc600 | ||
|
|
a42aed1e7f | ||
|
|
20e2fe46ba | ||
|
|
1fb02a477d | ||
|
|
09f8d1c2a5 | ||
|
|
e754f5944e | ||
|
|
089233f4be | ||
|
|
b1f8598a03 | ||
|
|
b8d74522bd | ||
|
|
5ff025fdbf | ||
|
|
537cd7c564 | ||
|
|
1c42755451 | ||
|
|
63b1ff242c | ||
|
|
be490a7dea | ||
|
|
44893b14b0 | ||
|
|
d22abdfd76 | ||
|
|
cbdea5d0f1 | ||
|
|
9a88e565fb | ||
|
|
925defc868 | ||
|
|
843c1fed17 | ||
|
|
781126719a | ||
|
|
a93be9c816 | ||
|
|
1af3dab37a | ||
|
|
163dbe58e4 | ||
|
|
c26a7cc5ac | ||
|
|
6170958be9 | ||
|
|
ea9bd4ac93 | ||
|
|
aa15eedc7a | ||
|
|
1798b67dd3 | ||
|
|
f92cf62a54 | ||
|
|
3c332db4bf | ||
|
|
4e1d7bbb3d | ||
|
|
97dbcdd252 | ||
|
|
0ef7c803f9 | ||
|
|
410a4c75b7 | ||
|
|
edf42f5102 | ||
|
|
3e879cc30f | ||
|
|
c2127ac820 | ||
|
|
002373e395 | ||
|
|
de98f5f02d | ||
|
|
30645803e6 | ||
|
|
abbf3f2820 | ||
|
|
8d4024b8c8 | ||
|
|
f6736fc730 | ||
|
|
889c73ec91 | ||
|
|
8fe53f3b84 | ||
|
|
a3304818d2 | ||
|
|
4057205583 | ||
|
|
7f1936d609 | ||
|
|
f41a472308 |
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,6 +22,7 @@ If applicable, add screenshots to help explain your problem. Additionally, provi
|
||||
|
||||
**Platform:**
|
||||
- Hardware Platform (ex. Raspberry Pi 4, Windows x64):
|
||||
- How is it powered? (ex. Zinc-V, Pololu Buck Converter, Battery Bank):
|
||||
- Network Configuration (Connection between the Radio and any devices in between, such as a Network Switch):
|
||||
- PhotonVision Version:
|
||||
- Browser (with Version) (Chrome, Edge, Firefox, etc.):
|
||||
|
||||
17
.github/ISSUE_TEMPLATE/docs_issue.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Documentation Request
|
||||
about: Something needs to be documented/updated in the documentation
|
||||
title: ''
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Are you requesting documentation for a new feature, or updated documentation for an old feature?**
|
||||
Put the feature you are requesting documentation for here, along with whether the documentation is stale and needs to be updated, or whether the documentation does not exist, and needs to be created.
|
||||
|
||||
**Where is it?**
|
||||
Put the location of the documentation that needs to be updated here. If you're requesting documenation for a new feature, put where you think it should go.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
1
.github/pull_request_template.md
vendored
@@ -14,4 +14,5 @@ Merge checklist:
|
||||
- [ ] If this PR changes behavior or adds a feature, user documentation is updated
|
||||
- [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly
|
||||
- [ ] If this PR touches configuration, this is backwards compatible with settings back to v2024.3.1
|
||||
- [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated
|
||||
- [ ] If this PR addresses a bug, a regression test for it is added
|
||||
|
||||
3
.github/workflows/build.yml
vendored
@@ -557,7 +557,8 @@ jobs:
|
||||
rm: true
|
||||
files: |
|
||||
**/*.xz
|
||||
**/*.jar
|
||||
**/*linux*.jar
|
||||
**/*win*.jar
|
||||
**/photonlib*.json
|
||||
**/photonlib*.zip
|
||||
if: github.event_name == 'push'
|
||||
|
||||
17
.github/workflows/cut-new-tag.yml
vendored
@@ -1,17 +0,0 @@
|
||||
name: Cut a new tag
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag_name:
|
||||
type: string
|
||||
description: The full name of the new tag to push to the latest commit to main
|
||||
|
||||
jobs:
|
||||
push_tag:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: git tag ${{ github.event.inputs.tag_name }}
|
||||
- run: git push origin ${{ github.event.inputs.tag_name }}
|
||||
2
.github/workflows/lint-format.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.11
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat==2024.45
|
||||
run: pip3 install wpiformat==2025.33
|
||||
- name: Run
|
||||
run: wpiformat
|
||||
- name: Check output
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Photon Code Documentation
|
||||
name: Photon API Documentation
|
||||
|
||||
on:
|
||||
# Run on pushes to main and pushed tags, and on pull requests against main, but ignore the docs folder
|
||||
@@ -21,8 +21,8 @@ permissions:
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
name: "PhotonClient Build"
|
||||
build_demo:
|
||||
name: Build PhotonClient Demo
|
||||
defaults:
|
||||
run:
|
||||
working-directory: photon-client
|
||||
@@ -39,10 +39,11 @@ jobs:
|
||||
run: npm run build-demo
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: built-client
|
||||
name: built-demo
|
||||
path: photon-client/dist/
|
||||
|
||||
run_docs:
|
||||
run_api_docs:
|
||||
name: Build API Docs
|
||||
runs-on: "ubuntu-22.04"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -56,34 +57,56 @@ jobs:
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: temurin
|
||||
|
||||
- name: Build javadocs/doxygen
|
||||
run: |
|
||||
chmod +x gradlew
|
||||
./gradlew photon-docs:generateJavaDocs photon-docs:doxygen
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: built-docs
|
||||
path: photon-docs/build/docs
|
||||
|
||||
release:
|
||||
needs: [build-client, run_docs]
|
||||
|
||||
publish_api_docs:
|
||||
name: Publish API Docs
|
||||
needs: [run_api_docs]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
# Download literally every single artifact.
|
||||
# Download docs artifact
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
- run: find .
|
||||
- name: copy file via ssh password
|
||||
if: github.ref == 'refs/heads/main'
|
||||
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/
|
||||
name: built-docs
|
||||
- run: find .
|
||||
- name: Publish Docs To Development
|
||||
if: github.ref == 'refs/heads/main'
|
||||
uses: up9cloud/action-rsync@v1.4
|
||||
env:
|
||||
HOST: ${{ secrets.WEBMASTER_SSH_HOST }}
|
||||
USER: ${{ secrets.WEBMASTER_SSH_USERNAME }}
|
||||
KEY: ${{secrets.WEBMASTER_SSH_KEY}}
|
||||
TARGET: /var/www/html/photonvision-docs/development
|
||||
- name: Publish Docs To Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: up9cloud/action-rsync@v1.4
|
||||
env:
|
||||
HOST: ${{ secrets.WEBMASTER_SSH_HOST }}
|
||||
USER: ${{ secrets.WEBMASTER_SSH_USERNAME }}
|
||||
KEY: ${{ secrets.WEBMASTER_SSH_KEY }}
|
||||
TARGET: /var/www/html/photonvision-docs/release/
|
||||
|
||||
publish_demo:
|
||||
name: Publish PhotonClient Demo
|
||||
needs: [build_demo]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: built-demo
|
||||
- run: find .
|
||||
- name: Publish demo
|
||||
if: github.ref == 'refs/heads/main'
|
||||
uses: up9cloud/action-rsync@v1.4
|
||||
env:
|
||||
HOST: ${{ secrets.WEBMASTER_SSH_HOST }}
|
||||
USER: ${{ secrets.WEBMASTER_SSH_USERNAME }}
|
||||
KEY: ${{ secrets.WEBMASTER_SSH_KEY }}
|
||||
TARGET: /var/www/html/photonvision-demo
|
||||
@@ -1,4 +1,4 @@
|
||||
name: PhotonVision Sphinx Documentation Checks
|
||||
name: PhotonVision ReadTheDocs Checks
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -16,6 +16,7 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and Check Docs
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
48
.github/workflows/website.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: Website
|
||||
|
||||
on:
|
||||
push:
|
||||
# For now, run on all commits to main
|
||||
branches: [ main ]
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
rsync:
|
||||
name: Build and Sync Files
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install packages
|
||||
run: npm ci
|
||||
working-directory: website
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
working-directory: website
|
||||
- uses: up9cloud/action-rsync@v1.4
|
||||
if: github.ref == 'refs/heads/main'
|
||||
env:
|
||||
HOST: ${{ secrets.WEBMASTER_SSH_HOST }}
|
||||
USER: ${{ secrets.WEBMASTER_SSH_USERNAME }}
|
||||
KEY: ${{secrets.WEBMASTER_SSH_KEY}}
|
||||
SOURCE: website/dist/*
|
||||
TARGET: /var/www/html/photonvision-website
|
||||
|
||||
format-check:
|
||||
name: Check Formatting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Packages
|
||||
run: npm ci
|
||||
working-directory: website
|
||||
- name: Run Formatting Check
|
||||
run: npx prettier -c .
|
||||
working-directory: website
|
||||
24
.gitignore
vendored
@@ -1,19 +1,13 @@
|
||||
Python/__pycache__/WebSiteHandler\.cpython-37\.pyc
|
||||
|
||||
\.idea/
|
||||
|
||||
*.pyc
|
||||
|
||||
Python/app/__pycache__/
|
||||
|
||||
Python/app/handlers/__pycache__/
|
||||
|
||||
\.vscode/
|
||||
__pycache__/
|
||||
|
||||
/.vs
|
||||
|
||||
backend/settings/
|
||||
/.vscode/
|
||||
.vscode/
|
||||
# Docs
|
||||
_build
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
@@ -109,7 +103,6 @@ fabric.properties
|
||||
|
||||
# Temporary build files
|
||||
**/.gradle
|
||||
**/target
|
||||
**/src/main/java/META-INF
|
||||
**/.settings
|
||||
**/.classpath
|
||||
@@ -125,8 +118,6 @@ compile_commands.json
|
||||
.clangd/
|
||||
.cache/
|
||||
|
||||
New client/photon-client/*
|
||||
|
||||
*.prefs
|
||||
*.jfr
|
||||
.DS_Store
|
||||
@@ -146,7 +137,12 @@ photonlib-cpp-examples/*/vendordeps/*
|
||||
photonlib-cpp-examples/*/networktables.json.bck
|
||||
photonlib-java-examples/*/networktables.json.bck
|
||||
*.sqlite
|
||||
photon-server/src/main/resources/web/*
|
||||
venv
|
||||
.venv/*
|
||||
.venv
|
||||
networktables.json
|
||||
# Web stuff
|
||||
photon-server/src/main/resources/web/*
|
||||
node_modules
|
||||
dist
|
||||
components.d.ts
|
||||
|
||||
@@ -19,6 +19,9 @@ modifiableFileExclude {
|
||||
\.webp$
|
||||
\.ico$
|
||||
\.rknn$
|
||||
\.mp4$
|
||||
\.ttf$
|
||||
\.woff2$
|
||||
gradlew
|
||||
photon-lib/py/photonlibpy/generated/
|
||||
photon-targeting/src/main/native/cpp/photon/constrained_solvepnp/generate/
|
||||
|
||||
@@ -42,6 +42,7 @@ Note that these are case sensitive!
|
||||
* linuxathena
|
||||
- `-PtgtIP`: Specifies where `./gradlew deploy` should try to copy the fat JAR to
|
||||
- `-Pprofile`: enables JVM profiling
|
||||
- `-PwithSanitizers`: On Linux, enables `-fsanitize=address,undefined,leak`
|
||||
|
||||
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`
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ plugins {
|
||||
id "cpp"
|
||||
id "com.diffplug.spotless" version "6.24.0"
|
||||
id "edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin" version "2020.2"
|
||||
id "edu.wpi.first.GradleRIO" version "2025.3.1"
|
||||
id "edu.wpi.first.GradleRIO" version "2025.3.2"
|
||||
id 'edu.wpi.first.WpilibTools' version '1.3.0'
|
||||
id 'com.google.protobuf' version '0.9.3' apply false
|
||||
id 'edu.wpi.first.GradleJni' version '1.1.0'
|
||||
@@ -33,11 +33,10 @@ ext.allOutputsFolder = file("$project.buildDir/outputs")
|
||||
apply from: "versioningHelper.gradle"
|
||||
|
||||
ext {
|
||||
wpilibVersion = "2025.3.1"
|
||||
wpilibVersion = "2025.3.2"
|
||||
wpimathVersion = wpilibVersion
|
||||
openCVYear = "2025"
|
||||
openCVversion = "4.10.0-3"
|
||||
joglVersion = "2.4.0"
|
||||
javalinVersion = "5.6.2"
|
||||
libcameraDriverVersion = "v2025.0.3"
|
||||
rknnVersion = "dev-v2025.0.0-1-g33b6263"
|
||||
|
||||
9
docs/.gitignore
vendored
@@ -1,9 +0,0 @@
|
||||
build/*
|
||||
.DS_Store
|
||||
.vscode/*
|
||||
.idea/*
|
||||
source/_build
|
||||
source/docs/_build
|
||||
|
||||
venv/*
|
||||
.venv/*
|
||||
@@ -1,44 +1,59 @@
|
||||
alabaster==0.7.13
|
||||
Babel==2.13.1
|
||||
beautifulsoup4==4.12.2
|
||||
certifi==2023.11.17
|
||||
charset-normalizer==3.3.2
|
||||
alabaster==1.0.0
|
||||
anyio==4.9.0
|
||||
babel==2.17.0
|
||||
beautifulsoup4==4.13.3
|
||||
certifi==2025.1.31
|
||||
charset-normalizer==3.4.1
|
||||
click==8.1.8
|
||||
colorama==0.4.6
|
||||
doc8==0.11.2
|
||||
doc8==1.1.2
|
||||
docopt==0.6.2
|
||||
docutils==0.18.1
|
||||
furo==2023.9.10
|
||||
idna==3.4
|
||||
docutils==0.21.2
|
||||
furo==2024.8.6
|
||||
h11==0.14.0
|
||||
idna==3.10
|
||||
imagesize==1.4.1
|
||||
Jinja2==3.0.3
|
||||
MarkupSafe==2.1.3
|
||||
packaging==23.2
|
||||
pbr==6.0.0
|
||||
Jinja2==3.1.6
|
||||
markdown-it-py==3.0.0
|
||||
MarkupSafe==3.0.2
|
||||
mdit-py-plugins==0.4.2
|
||||
mdurl==0.1.2
|
||||
myst-parser==4.0.1
|
||||
packaging==24.2
|
||||
pbr==6.1.1
|
||||
pipreqs==0.4.13
|
||||
Pygments==2.17.1
|
||||
requests==2.31.0
|
||||
restructuredtext-lint==1.4.0
|
||||
six==1.16.0
|
||||
Pygments==2.19.1
|
||||
PyYAML==6.0.2
|
||||
requests==2.32.3
|
||||
restructuredtext_lint==1.4.0
|
||||
roman-numerals-py==3.1.0
|
||||
setuptools==77.0.3
|
||||
six==1.17.0
|
||||
sniffio==1.3.1
|
||||
snowballstemmer==2.2.0
|
||||
soupsieve==2.5
|
||||
Sphinx==7.2.6
|
||||
soupsieve==2.6
|
||||
Sphinx==8.2.3
|
||||
sphinx-autobuild==2024.10.3
|
||||
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
|
||||
sphinx-notfound-page==1.1.0
|
||||
sphinx-rtd-theme==3.0.2
|
||||
sphinx-tabs==3.4.7
|
||||
sphinx_design==0.6.1
|
||||
sphinxcontrib-applehelp==2.0.0
|
||||
sphinxcontrib-devhelp==2.0.0
|
||||
sphinxcontrib-ghcontributors==0.2.3
|
||||
sphinxcontrib-htmlhelp==2.0.4
|
||||
sphinxcontrib-htmlhelp==2.1.0
|
||||
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
|
||||
sphinxcontrib-qthelp==2.0.0
|
||||
sphinxcontrib-serializinghtml==2.0.0
|
||||
sphinxext-opengraph==0.9.1
|
||||
sphinxext-remoteliteralinclude==0.5.0
|
||||
starlette==0.46.1
|
||||
stevedore==5.4.1
|
||||
typing_extensions==4.12.2
|
||||
urllib3==2.3.0
|
||||
uvicorn==0.34.0
|
||||
watchfiles==1.0.4
|
||||
websockets==15.0.1
|
||||
yarg==0.1.10
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 12 KiB |
@@ -87,6 +87,9 @@ pygments_style = "sphinx"
|
||||
|
||||
html_theme_options = {
|
||||
"sidebar_hide_name": True,
|
||||
"top_of_page_buttons": ["view", "edit"],
|
||||
"source_edit_link": "https://github.com/PhotonVision/photonvision/edit/main/docs/source/{filename}",
|
||||
"source_view_link": "https://github.com/PhotonVision/photonvision/blob/main/docs/source/{filename}",
|
||||
"light_logo": "assets/PhotonVision-Header-onWhite.png",
|
||||
"dark_logo": "assets/PhotonVision-Header-noBG.png",
|
||||
"light_css_variables": {
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
- Some time before the competition, lock down the version you are using and do not upgrade unless you encounter a critical bug.
|
||||
- Have a copy of the installation image for the version you are using on your programming laptop, in case re-imaging (without internet) is needed.
|
||||
- Extensively test at your home setup. Practice tuning from scratch under different lighting conditions.
|
||||
- Use SmartDashboard / Shuffleboard to view your camera streams during practice.
|
||||
- Confirm you have followed all the recommendations under the Networking section in installation (network switch and static IP).
|
||||
- Confirm you have followed all the recommendations under the {ref}`Networking<docs/quick-start/networking:Networking>` documentation (network switch and static IP).
|
||||
- Only use high quality ethernet cables that have been rigorously tested.
|
||||
- Set up RIO USB port forwarding using the guide in the Networking section in installation.
|
||||
|
||||
## Camera Streaming
|
||||
- All camera streams are published under the NetworkTables table `CameraPublisher`.
|
||||
- The only subtable under `CameraPublisher` that will work for viewing a driver mode camera stream is the one that contains `Output` in the name.
|
||||
- To view a camera stream in a dashboard, drag the correct subtable from the NetworkTables tree into your dashboard.
|
||||
- Use the latest driver dashboard recommended by [WPILib](https://docs.wpilib.org/en/stable/docs/software/dashboards/dashboard-intro.html) on your driver station laptop.
|
||||
|
||||
## During the Competition
|
||||
|
||||
@@ -19,7 +23,7 @@
|
||||
- Make sure the field has match-accurate lighting conditions active.
|
||||
- Turn on your robot and pull up the dashboard on your driver station.
|
||||
- Point your robot at the targets and ensure you get a consistent tracking (you hold one targets 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.
|
||||
- If you have problems with your pipeline, retune the pipeline following the {ref}`camera tuning <docs/pipelines/input:Camera Tuning / Input>` documentation.
|
||||
- Move the robot close, far, angled, and around the field to ensure no extra targets are found.
|
||||
- Monitor camera feeds during 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.
|
||||
|
||||
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.8 KiB |
@@ -23,7 +23,7 @@ Using a JDK other than JDK17 will cause issues when running PhotonVision and is
|
||||
Go to the [GitHub releases page](https://github.com/PhotonVision/photonvision/releases) and download the relevant .jar file for your coprocessor.
|
||||
|
||||
:::{note}
|
||||
If you have an M1/M2 Mac, download the macarm64.jar file.
|
||||
If you have an M Series Mac, download the macarm64.jar file.
|
||||
|
||||
If you have an Intel based Mac, download the macx64.jar file.
|
||||
:::
|
||||
|
||||
@@ -12,7 +12,7 @@ Bonjour provides more stable networking when using Windows PCs. Install [Bonjour
|
||||
|
||||
## Installing Java
|
||||
|
||||
PhotonVision requires a JDK installed and on the system path. **JDK 17 is needed. Windows Users must use the JDK that ships with WPILib.** [Download and install it from here.](https://github.com/wpilibsuite/allwpilib/releases/tag/v2025.3.1) Either ensure the only Java on your PATH is the WPILIB Java or specify it to gradle with `-Dorg.gradle.java.home=C:\Users\Public\wpilib\2025\jdk`:
|
||||
PhotonVision requires a JDK installed and on the system path. **JDK 17 is needed. Windows Users must use the JDK that ships with WPILib.** [Download and install it from here.](https://github.com/wpilibsuite/allwpilib/releases/tag/v2025.3.2) Either ensure the only Java on your PATH is the WPILIB Java or specify it to gradle with `-Dorg.gradle.java.home=C:\Users\Public\wpilib\2025\jdk`:
|
||||
|
||||
```
|
||||
> ./gradlew run "-Dorg.gradle.java.home=C:\Users\Public\wpilib\2025\jdk"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 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>`.
|
||||
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.
|
||||
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:
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 427 KiB After Width: | Height: | Size: 304 KiB |
|
Before Width: | Height: | Size: 451 KiB After Width: | Height: | Size: 324 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -23,30 +23,41 @@ Ensure that your camera is calibrated and 3D mode is enabled. Navigate to the Ou
|
||||
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++).
|
||||
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()`/`multitagResult` (Java/C++/Python).
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: Java
|
||||
|
||||
var result = camera.getLatestResult();
|
||||
if (result.getMultiTagResult().estimatedPose.isPresent) {
|
||||
Transform3d fieldToCamera = result.getMultiTagResult().estimatedPose.best;
|
||||
var results = camera.getAllUnreadResults();
|
||||
for (var result : results) {
|
||||
var multiTagResult = result.getMultiTagResult();
|
||||
if (multiTagResult.isPresent()) {
|
||||
var fieldToCamera = multiTagResult.get().estimatedPose.best;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
auto result = camera.GetLatestResult();
|
||||
if (result.MultiTagResult().result.isPresent) {
|
||||
frc::Transform3d fieldToCamera = result.MultiTagResult().result.best;
|
||||
auto results = camera.GetAllUnreadResults();
|
||||
for (auto &result : results)
|
||||
{
|
||||
auto multiTagResult = result.MultiTagResult();
|
||||
if (multiTagResult.has_value()) {
|
||||
frc::Transform3d fieldToCamera = multiTagResult->estimatedPose.best;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
# Coming Soon!
|
||||
|
||||
results = camera.getAllUnreadResults()
|
||||
for result in results:
|
||||
multitagResult = result.multitagResult
|
||||
if multitagResult is not None:
|
||||
fieldToCamera = multitagResult.estimatedPose.best
|
||||
```
|
||||
|
||||
:::{note}
|
||||
|
||||
|
Before Width: | Height: | Size: 143 KiB |
@@ -18,7 +18,7 @@ The calibration data collected during calibration is specific to each physical c
|
||||
|
||||
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.
|
||||
01. Ensure 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.
|
||||
@@ -52,7 +52,7 @@ We'll next select a resolution to calibrate and populate our pattern spacing, ma
|
||||
:::
|
||||
|
||||
:::{note}
|
||||
If you have a [calib.io](https://calib.io/) CharuCo Target you will have to enter the paramaters of your target. For example if your taget says "9x12 | Chceker Size: 30 mm | Marker Size: 22 mm | Dictionary: AruCo DICT 5x5", you would have to set the board type to Dict_5x5_1000, the pattern spacing to 1.1811 in (30 mm converted to inches), the marker size 0.866142 in (22 mm converted to inches), the board width to 12 and the board height to 9. If you chose the wrong tag family the baord wont be detected duting calibration. If you swap the width and height your calibration will have a very high error.
|
||||
If you have a [calib.io](https://calib.io/) CharuCo Target you will have to enter the paramaters of your target. For example if your target says "9x12 | Checker Size: 30 mm | Marker Size: 22 mm | Dictionary: AruCo DICT 5x5", you would have to set the board type to Dict_5x5_1000, the pattern spacing to 1.1811 in (30 mm converted to inches), the marker size 0.866142 in (22 mm converted to inches), the board width to 12 and the board height to 9. If you chose the wrong tag family the board wont be detected during calibration. If you swap the width and height your calibration will have a very high error.
|
||||
:::
|
||||
|
||||
### 4. Take at calibration images from various angles.
|
||||
|
||||
|
Before Width: | Height: | Size: 462 KiB After Width: | Height: | Size: 375 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 86 KiB |
8
docs/source/docs/camera-specific-configuration/index.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Camera-Specifc Configuration
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 2
|
||||
|
||||
arducam-cameras
|
||||
picamconfig
|
||||
```
|
||||
@@ -23,6 +23,7 @@ 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:
|
||||
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 334 KiB After Width: | Height: | Size: 197 KiB |
@@ -69,6 +69,16 @@ In the root directory:
|
||||
``gradlew buildAndCopyUI``
|
||||
```
|
||||
|
||||
### Using hot reload on the UI
|
||||
|
||||
In the photon-client directory:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This allows you to make UI changes quickly without having to spend time rebuilding the jar. Hot reload is enabled, so changes that you make and save are reflected in the UI immediately. Running this command will give you the URL for accessing the UI, which is on a different port than normal. You must use the printed URL to use hot reload.
|
||||
|
||||
### Build and Run PhotonVision
|
||||
|
||||
To compile and run the project, issue the following command in the root directory:
|
||||
@@ -273,3 +283,9 @@ Using the [GitHub CLI](https://cli.github.com/), we can download artifacts from
|
||||
```
|
||||
~/photonvision$ gh run download 11759699679 -n jar-Linux
|
||||
```
|
||||
|
||||
#### MacOS Builds
|
||||
|
||||
MacOS builds are not published to releases as MacOS is not an officially
|
||||
supported platform. However, MacOS builds are still available from the MacOS
|
||||
build action, which can be found [here](https://github.com/PhotonVision/photonvision/actions/workflows/build.yml).
|
||||
|
||||
@@ -4,7 +4,7 @@ Diagrams generated by the [PlantUML UML editor](https://www.plantuml.com/plantum
|
||||
|
||||
## Initial Setup
|
||||
|
||||
When PhotonVision first starts, settings are loaded from disk and [VisionSources](https://javadocs.photonvision.org/org/photonvision/vision/processes/VisionSource.html) are created for every serialized & active [Camera Configuration](https://javadocs.photonvision.org/org/photonvision/common/configuration/CameraConfiguration.html)
|
||||
When PhotonVision first starts, settings are loaded from disk and [VisionSources](https://javadocs.photonvision.org/release/org/photonvision/vision/processes/VisionSource.html) are created for every serialized & active [Camera Configuration](https://javadocs.photonvision.org/release/org/photonvision/common/configuration/CameraConfiguration.html)
|
||||
|
||||

|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 166 KiB |
@@ -11,7 +11,7 @@ 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.
|
||||
PhotonVision offers a more affordable solution to vision, with costs being from your coprocessor(s) and camera(s). Teams may choose to run multiple cameras from one coprocessor. This makes it a great solution for teams with limited budgets.
|
||||
|
||||
### Easy to Use User Interface
|
||||
|
||||
|
||||
BIN
docs/source/docs/driver-mode/images/crosshair-switch.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 194 KiB |
BIN
docs/source/docs/driver-mode/images/driver-mode-dashboard.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
27
docs/source/docs/driver-mode/index.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Driver Mode
|
||||
|
||||
Driver Mode is a type of pipeline that doesn't run any vision processing, intended for viewing from a human.
|
||||
|
||||
## Enabling Driver Mode
|
||||
|
||||
To enable Driver Mode, toggle the switch at the top of the Dashboard page for a selected camera.
|
||||
|
||||
```{image} images/driver-mode-dashboard.png
|
||||
:align: center
|
||||
:alt: Driver Mode Toggle in the Dashboard Page
|
||||
```
|
||||
|
||||
Alternatively, visit the camera settings page and toggle the "Driver Mode" switch for a selected camera.
|
||||
|
||||
```{image} images/driver-mode-camera-settings.png
|
||||
:align: center
|
||||
:alt: Driver Mode Toggle in the Camera Settings Page
|
||||
```
|
||||
|
||||
## Hiding the Crosshair
|
||||
When Driver Mode is enabled, a green crosshair will be shown at the center of the camera stream. If you do not want to show the green crosshair at the center of the camera stream, toggle the "Crosshair" switch under the Input tab, as shown in the image below.
|
||||
|
||||
```{image} images/crosshair-switch.png
|
||||
:align: center
|
||||
:alt: Crosshair Switch
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# Combining Aiming and Getting in Range
|
||||
|
||||
The following example is from the PhotonLib example repository ([Java](https://github.com/PhotonVision/photonvision/tree/main/photonlib-java-examples/aimandrange)/[C++](https://github.com/PhotonVision/photonvision/tree/main/photonlib-cpp-examples/aimandrange)).
|
||||
The following example is from the PhotonLib example repository ([Java](https://github.com/PhotonVision/photonvision/tree/main/photonlib-java-examples/aimandrange)/[C++](https://github.com/PhotonVision/photonvision/tree/main/photonlib-cpp-examples/aimandrange)/[Python](https://github.com/PhotonVision/photonvision/tree/main/photonlib-python-examples/aimandrange))
|
||||
|
||||
## Knowledge and Equipment Needed
|
||||
|
||||
@@ -10,7 +10,7 @@ The following example is from the PhotonLib example repository ([Java](https://g
|
||||
|
||||
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.
|
||||
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::
|
||||
@@ -43,8 +43,8 @@ To do this, we'll use the *pitch* of the target in the camera image and trigonom
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/abe95dfaa055bbe3609f72cfcaaba0f96ee7978c/photonlib-python-examples/aimandrange/robot.py
|
||||
:language: python
|
||||
:lines: 44-95
|
||||
:lines: 52-91
|
||||
:linenos:
|
||||
:lineno-start: 44
|
||||
:lineno-start: 52
|
||||
|
||||
```
|
||||
|
||||
@@ -13,7 +13,7 @@ The following example is from the PhotonLib example repository ([Java](https://g
|
||||
|
||||
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?>`.
|
||||
Yaw is reported to the roboRIO over Network Tables. PhotonLib, our vendor 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).
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB |
@@ -4,6 +4,5 @@
|
||||
:maxdepth: 2
|
||||
|
||||
selecting-hardware
|
||||
picamconfig
|
||||
customhardware
|
||||
```
|
||||
|
||||
@@ -44,12 +44,20 @@ Before beginning, it is necessary to install the [rknn-toolkit2](https://github.
|
||||
## Uploading Custom Models
|
||||
|
||||
:::{warning}
|
||||
PhotonVision currently ONLY supports 640x640 Ultralytics YOLOv5, YOLOv8, and YOLO11 models trained and converted to `.rknn` format for RK3588 CPUs! Other models require different post-processing code and will NOT work. The model conversion process is also highly particular. Proceed with care.
|
||||
PhotonVision currently ONLY supports 640x640 Ultralytics YOLOv5, YOLOv8, and YOLOv11 models trained and converted to `.rknn` format for RK3588 CPUs! Other models require different post-processing code and will NOT work. The model conversion process is also highly particular. Proceed with care.
|
||||
:::
|
||||
|
||||
:::{warning}
|
||||
Non-quantized models are not supported! If you have the option, make sure quantization is enabled when exporting to .rknn format. This will represent the weights and activations of the model as 8-bit integers, instead of 32-bit floats which PhotonVision doesn't support. Quantized models are also much faster.
|
||||
:::
|
||||
|
||||
In the settings, under `Device Control`, there's an option to upload a new object detection model. Naming convention
|
||||
should be `name-verticalResolution-horizontalResolution-modelType`. The
|
||||
should be `name-verticalResolution-horizontalResolution-yolovXXX`. The
|
||||
`name` should only include alphanumeric characters, periods, and underscores. Additionally, the labels
|
||||
file ought to have the same name as the RKNN file, with `-labels` appended to the end. For
|
||||
example, if the RKNN file is named `Algae_1.03.2025-640-640-yolov5s.rknn`, the labels file should be
|
||||
named `Algae_1.03.2025-640-640-yolov5s-labels.txt`.
|
||||
|
||||
:::{note}
|
||||
Currently there is no way to delete custom models in the GUI, though this is a planned feature. To do this, you have to SSH into the coprocessor and delete the files manually from `/opt/photonvision/photonvision_config/models`.
|
||||
:::
|
||||
|
||||
|
Before Width: | Height: | Size: 358 KiB After Width: | Height: | Size: 246 KiB |
@@ -10,37 +10,61 @@ A vision pipeline represents a series of steps that are used to acquire an image
|
||||
|
||||
## Types of Pipelines
|
||||
|
||||
### Reflective
|
||||
### AprilTag / AruCo
|
||||
|
||||
This is the most common pipeline type and it is based on detecting targets with retroreflective tape. In the contours tab of this pipeline type, you can filter the area, width/height ratio, fullness, degree of speckle rejection.
|
||||
This pipeline type is based on detecting AprilTag fiducial markers. More information about AprilTags can be found in the [WPILib documentation](https://docs.wpilib.org/en/stable/docs/software/vision-processing/apriltag/apriltag-intro.html). This pipeline provides easy to use 3D pose information which allows localization.
|
||||
|
||||
:::{note}
|
||||
In order to get 3D Pose data about AprilTags, you are required to {ref}`calibrate your camera<docs/calibration/calibration:Calibrating Your Camera>`.
|
||||
:::
|
||||
|
||||
### Object Detection
|
||||
|
||||
This pipeline type is based on detecting objects using a neural network. The object detection pipeline uses a pre-trained model to detect objects in the camera stream.
|
||||
|
||||
:::{note}
|
||||
This pipeline type is only supported on the Orange Pi 5/5+ coprocessors due to its Neural Processing Unit used by PhotonVision to support running ML-based object detection.
|
||||
:::
|
||||
|
||||
### Driver Mode
|
||||
|
||||
Driver Mode is a type of pipeline that doesn't run any vision processing, intended for human viewing. For more information about Driver Mode, see the {ref}`Driver Mode documentation<docs/driver-mode/index:Driver Mode>`.
|
||||
|
||||
### Colored Shape
|
||||
|
||||
This pipeline type is based on detecting different shapes like circles, triangles, quadrilaterals, or a polygon. An example usage would be detecting yellow PowerCells from the 2020 FRC game. You can read more about the specific settings available in the contours page.
|
||||
|
||||
### AprilTag / AruCo
|
||||
### Reflective
|
||||
|
||||
This pipeline type is based on detecting AprilTag fiducial markers. More information about AprilTags can be found in the WPILib documentation. While being more performance intensive than the reflective and colored shape pipeline, it has the benefit of providing easy to use 3D pose information which allows localization.
|
||||
This pipeline type is based on detecting targets with reflective tape. In the contours tab of this pipeline type, you can filter the area, width/height ratio, fullness, degree of speckle rejection.
|
||||
|
||||
:::{note}
|
||||
In order to get 3D Pose data about AprilTags, you are required to {ref}`calibrate your camera<docs/calibration/calibration:Calibrating Your Camera>`.
|
||||
This pipeline type is not used anymore due to FRC's removal of retro-reflective tape from the game. It is still available as a pipeline for legacy purposes.
|
||||
:::
|
||||
|
||||
## Note About Multiple Cameras and Pipelines
|
||||
|
||||
When using more than one camera, it is important to keep in mind that all cameras run one pipeline each, all publish to NT, and all send both streams. This will have a noticeable affect on performance and we recommend users limit themselves to 1-2 cameras per coprocessor.
|
||||
|
||||
## Pipeline Steps
|
||||
## Pipeline Configuration
|
||||
|
||||
Reflective and Colored Shape Pipelines have 4 steps (represented as 4 tabs):
|
||||
Each pipeline has a set of tabs that are used to configure the pipeline. All pipelines follow a similar structure with an Input and Output tab, as well as a set of tabs that are specific to the pipeline type.
|
||||
|
||||
1. Input: This tab allows the raw camera image to be modified before it gets processed. Here, you can set exposure, brightness, gain, orientation, and resolution.
|
||||
2. Threshold (Only Reflective and Colored Shape): This tabs allows you to filter our specific colors/pixels in your camera stream through HSV tuning. The end goal here is having a black and white image that will only have your target lit up.
|
||||
3. Contours: After thresholding, contiguous white pixels are grouped together, and described by a curve that outlines the group. This curve is called a "contour" which represent various targets on your screen. Regardless of type, you can filter how the targets are grouped, their intersection, and how the targets are sorted. Other available filters will change based on different pipeline types.
|
||||
4. Output: Now that you have filtered all of your contours, this allows you to manipulate the detected target via orientation, the offset point, and offset.
|
||||
- Input: This tab allows the raw camera image to be modified before it gets processed. Here, you can set exposure, brightness, gain, orientation, and resolution.
|
||||
|
||||
AprilTag / AruCo Pipelines have 3 steps:
|
||||
- Output: This allows you to manipulate the detected target via the target offset point (for calculating pitch/yaw) and robot (crosshair) offset. In addition, it allows users to send additional (up to 5) outputs through PhotonLib.
|
||||
|
||||
1. Input: This is the same as the above.
|
||||
2. AprilTag: This step include AprilTag specific tuning parameters, such as decimate, blur, threads, pose iterations, and more.
|
||||
3. Output: This is the same as the above.
|
||||
Pipielines also have additional tabs that are specific to the pipeline type. Listed below are the tabs for each pipeline type.
|
||||
|
||||
### AprilTag / AruCo Pipelines
|
||||
|
||||
- AprilTag: This tab includes AprilTag specific tuning parameters, such as decimate, blur, threads, pose iterations, and more.
|
||||
|
||||
### Object Detection Pipelines
|
||||
|
||||
- Object Detection: This tab allows you to filter results from the neural network, such as confidence, area, and width/height ratio. The end goal of this tab is to filter out any false positives.
|
||||
|
||||
### Reflective and Colored Shape Pipelines
|
||||
|
||||
- Threshold: This tab allows you to filter out specific colors/pixels in your camera stream through HSV tuning. The end goal here is having a black and white image that will only have your target lit up.
|
||||
- Contours: After thresholding, contiguous white pixels are grouped together, and described by a curve that outlines the group. This curve is called a "contour" which represent various targets on your screen. Regardless of type, you can filter how the targets are grouped, their intersection, and how the targets are sorted. Other available filters will change based on different pipeline types.
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -8,24 +8,38 @@ PhotonLibPy is a minimal, pure-python implementation of PhotonLib.
|
||||
|
||||
## Online Install - Java/C++
|
||||
|
||||
Click on the WPI icon on the top right of your VS Code window or hit Ctrl+Shift+P (Cmd+Shift+P on macOS) to bring up the command palette. Type, "Manage Vendor Libraries" and select the "WPILib: Manage Vendor Libraries" option. Then, select the "Install new library (online)" option.
|
||||
Click on the WPILib logo in the activity bar to access the Vendor Dependencies interface.
|
||||
|
||||
```{image} images/adding-offline-library.png
|
||||
```{image} images/wpilib-vendor-dependencies.png
|
||||
:scale: 50%
|
||||
:align: center
|
||||
:alt: WPILib Vendor Dependencies
|
||||
```
|
||||
|
||||
Paste the following URL into the box that pops up:
|
||||
Select the install button for the "PhotonLib" dependency.
|
||||
|
||||
`https://maven.photonvision.org/repository/internal/org/photonvision/photonlib-json/1.0/photonlib-json-1.0.json`
|
||||
```{image} images/photonlib-install.png
|
||||
:scale: 50%
|
||||
:align: center
|
||||
:alt: PhotonLib Install Button
|
||||
```
|
||||
|
||||
:::{note}
|
||||
It is recommended to Build Robot Code at least once when connected to the Internet before heading to an area where Internet connectivity is limited (for example, a competition). This ensures that the relevant files are downloaded to your filesystem.
|
||||
The Dependency Manager will automatically build your program when it loses focus. This allows you to use the changed dependencies.
|
||||
:::
|
||||
|
||||
When an update is available for PhotonLib, a "To Latest" button will become available. This will update the vendordep to the latest version of PhotonLib.
|
||||
|
||||
```{image} images/photonlib-to-latest.png
|
||||
:align: center
|
||||
:alt: PhotonLib Update Button
|
||||
```
|
||||
|
||||
Refer to [The WPILib docs](https://docs.wpilib.org/en/stable/docs/software/vscode-overview/3rd-party-libraries.html#installing-libraries) for more details on installing vendor libraries.
|
||||
|
||||
## Offline Install - Java/C++
|
||||
|
||||
Download the latest PhotonLib release from our GitHub releases page (named something like `` photonlib-VERSION.zip` ``), and extract the contents to `$HOME/wpilib/YEAR`. This adds PhotonLib maven artifacts to your local maven repository. PhotonLib will now also appear available in the "install vendor libraries (offline)" menu in WPILib VSCode. Refer to [the WPILib docs](https://docs.wpilib.org/en/stable/docs/software/vscode-overview/3rd-party-libraries.html#installing-libraries) for more details on installing vendor libraries offline.
|
||||
Download the latest PhotonLib release from our [GitHub releases page](https://github.com/PhotonVision/photonvision/releases) (named in the format `photonlib-VERSION.zip`), and extract the contents to `~/wpilib/YYYY/vendordeps` (where YYYY is the year and ~ is `C:\Users\Public` on Windows). This adds PhotonLib maven artifacts to your local maven repository. PhotonLib will now also appear available in the "install vendor libraries (offline)" menu in WPILib VSCode. Refer to [the WPILib docs](https://docs.wpilib.org/en/stable/docs/software/vscode-overview/3rd-party-libraries.html#how-does-it-work) for more details on installing vendor libraries offline.
|
||||
|
||||
## Install - Python
|
||||
|
||||
@@ -44,5 +58,5 @@ See [The WPILib/RobotPy docs](https://docs.wpilib.org/en/stable/docs/software/py
|
||||
|
||||
In cases where you want to test a specific version of PhotonLib, make sure you have finished the steps in Online Install - Java/C++ and then manually change the version string in the PhotonLib vendordep json file(at ``/path/to/your/project/vendordep/photonlib.json``) to your desired version.
|
||||
|
||||
```{image} images/photonlib-vendordep-json.png
|
||||
```{image} images/photonlib-vendordep-json.jpg
|
||||
```
|
||||
|
||||
@@ -86,7 +86,7 @@ Each pipeline result has a `hasTargets()`/`HasTargets()` (Java and C++ respectiv
|
||||
```
|
||||
|
||||
:::{warning}
|
||||
In Java/C++, You must *always* check if the result has a target via `hasTargets()`/`HasTargets()` before getting targets or else you may get a null pointer exception. Further, you must use the same result in every subsequent call in that loop.
|
||||
In Java/C++, You must _always_ check if the result has a target via `hasTargets()`/`HasTargets()` before getting targets or else you may get a null pointer exception. Further, you must use the same result in every subsequent call in that loop.
|
||||
:::
|
||||
|
||||
## Getting a List of Targets
|
||||
@@ -140,7 +140,7 @@ You can get the {ref}`best target <docs/reflectiveAndShape/contour-filtering:Con
|
||||
|
||||
## Getting Data From A Target
|
||||
|
||||
- double `getYaw()`/`GetYaw()`: The yaw of the target in degrees (positive right).
|
||||
- double `getYaw()`/`GetYaw()`: The yaw of the target in degrees (positive left).
|
||||
- double `getPitch()`/`GetPitch()`: The pitch of the target in degrees (positive up).
|
||||
- double `getArea()`/`GetArea()`: The area (how much of the camera feed the bounding box takes up) as a percent (0-100).
|
||||
- double `getSkew()`/`GetSkew()`: The skew of the target in degrees (counter-clockwise positive).
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 357 KiB After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 98 KiB |
@@ -4,154 +4,163 @@
|
||||
For more information on how to methods to get AprilTag data, look {ref}`here <docs/programming/photonlib/getting-target-data:Getting AprilTag Data From A Target>`.
|
||||
:::
|
||||
|
||||
PhotonLib includes a `PhotonPoseEstimator` class, which allows you to combine the pose data from all tags in view in order to get a field relative pose. The `PhotonPoseEstimator` class works with one camera per object instance, but more than one instance may be created.
|
||||
PhotonLib includes a `PhotonPoseEstimator` class, which allows you to combine the pose data from all tags in view in order to get a field relative pose. For each camera, a separate instance of the `PhotonPoseEstimator` class should be created.
|
||||
|
||||
## Creating an `AprilTagFieldLayout`
|
||||
|
||||
`AprilTagFieldLayout` is used to represent a layout of AprilTags within a space (field, shop at home, classroom, etc.). WPILib provides a JSON that describes the layout of AprilTags on the field which you can then use in the AprilTagFieldLayout constructor. You can also specify a custom layout.
|
||||
|
||||
The API documentation can be found in here: [Java](https://github.wpilib.org/allwpilib/docs/release/java/edu/wpi/first/apriltag/AprilTagFieldLayout.html) and [C++](https://github.wpilib.org/allwpilib/docs/release/cpp/classfrc_1_1_april_tag_field_layout.html).
|
||||
The API documentation can be found in here: [Java](https://github.wpilib.org/allwpilib/docs/release/java/edu/wpi/first/apriltag/AprilTagFieldLayout.html), [C++](https://github.wpilib.org/allwpilib/docs/release/cpp/classfrc_1_1_april_tag_field_layout.html), and [Python](https://robotpy.readthedocs.io/projects/apriltag/en/stable/robotpy_apriltag/AprilTagFieldLayout.html#robotpy_apriltag.AprilTagFieldLayout).
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. code-block:: Java
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Constants.java
|
||||
:language: java
|
||||
:lines: 48-49
|
||||
|
||||
// The field from AprilTagFields will be different depending on the game.
|
||||
AprilTagFieldLayout aprilTagFieldLayout = AprilTagFieldLayout.loadField(AprilTagFields.kDefaultField);
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/poseest/src/main/include/Constants.h
|
||||
:language: c++
|
||||
:lines: 46-47
|
||||
|
||||
.. code-block:: C++
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 46
|
||||
```
|
||||
|
||||
// The parameter for LoadAPrilTagLayoutField will be different depending on the game.
|
||||
frc::AprilTagFieldLayout aprilTagFieldLayout = frc::LoadAprilTagLayoutField(frc::AprilTagField::kDefaultField);
|
||||
## Defining the Robot to Camera `Transform3d`
|
||||
|
||||
.. code-block:: Python
|
||||
Another necessary argument for creating a `PhotonPoseEstimator` is the `Transform3d` representing the robot-relative location and orientation of the camera. A `Transform3d` contains a `Translation3d` and a `Rotation3d`. The `Translation3d` is created in meters and the `Rotation3d` is created with radians. For more information on the coordinate system, please see the {ref}`Coordinate Systems <docs/apriltag-pipelines/coordinate-systems:Coordinate Systems>` documentation.
|
||||
|
||||
# Coming Soon!
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Constants.java
|
||||
:language: java
|
||||
:lines: 44-45
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/poseest/src/main/include/Constants.h
|
||||
:language: c++
|
||||
:lines: 43-45
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 33-36
|
||||
```
|
||||
|
||||
## Creating a `PhotonPoseEstimator`
|
||||
|
||||
The PhotonPoseEstimator has a constructor that takes an `AprilTagFieldLayout` (see above), `PoseStrategy`, `PhotonCamera`, and `Transform3d`. `PoseStrategy` has six possible values:
|
||||
The PhotonPoseEstimator has a constructor that takes an `AprilTagFieldLayout` (see above), `PoseStrategy`, `PhotonCamera`, and `Transform3d`. `PoseStrategy` has nine possible values:
|
||||
|
||||
- MULTI_TAG_PNP_ON_COPROCESSOR
|
||||
- Calculates a new robot position estimate by combining all visible tag corners. Recommended for all teams as it will be the most accurate.
|
||||
- Must configure the AprilTagFieldLayout properly in the UI, please see {ref}`here <docs/apriltag-pipelines/multitag:multitag localization>` for more information.
|
||||
- Calculates a new robot position estimate by combining all visible tag corners. Recommended for all teams as it will be the most accurate.
|
||||
- Must configure the AprilTagFieldLayout properly in the UI, please see {ref}`here <docs/apriltag-pipelines/multitag:multitag localization>` for more information.
|
||||
- LOWEST_AMBIGUITY
|
||||
- Choose the Pose with the lowest ambiguity.
|
||||
- Choose the Pose with the lowest ambiguity.
|
||||
- CLOSEST_TO_CAMERA_HEIGHT
|
||||
- Choose the Pose which is closest to the camera height.
|
||||
- Choose the Pose which is closest to the camera height.
|
||||
- CLOSEST_TO_REFERENCE_POSE
|
||||
- Choose the Pose which is closest to the pose from setReferencePose().
|
||||
- Choose the Pose which is closest to the pose from setReferencePose().
|
||||
- CLOSEST_TO_LAST_POSE
|
||||
- Choose the Pose which is closest to the last pose calculated.
|
||||
- Choose the Pose which is closest to the last pose calculated.
|
||||
- AVERAGE_BEST_TARGETS
|
||||
- Choose the Pose which is the average of all the poses from each tag.
|
||||
- Choose the Pose which is the average of all the poses from each tag.
|
||||
- MULTI_TAG_PNP_ON_RIO
|
||||
- A slower, older version of MULTI_TAG_PNP_ON_COPROCESSOR, not recommended for use.
|
||||
- A slower, older version of MULTI_TAG_PNP_ON_COPROCESSOR, not recommended for use.
|
||||
- PNP_DISTANCE_TRIG_SOLVE
|
||||
- Use distance data from best visible tag to compute a Pose. This runs on the RoboRIO in order
|
||||
to access the robot's yaw heading, and MUST have addHeadingData called every frame so heading
|
||||
data is up-to-date. Based on a reference implementation by [FRC Team 6328 Mechanical Advantage](https://www.chiefdelphi.com/t/frc-6328-mechanical-advantage-2025-build-thread/477314/98).
|
||||
- Use distance data from best visible tag to compute a Pose. This runs on the RoboRIO in order
|
||||
to access the robot's yaw heading, and MUST have addHeadingData called every frame so heading
|
||||
data is up-to-date. Based on a reference implementation by [FRC Team 6328 Mechanical Advantage](https://www.chiefdelphi.com/t/frc-6328-mechanical-advantage-2025-build-thread/477314/98).
|
||||
- CONSTRAINED_SOLVEPNP
|
||||
- Solve a constrained version of the Perspective-n-Point problem with the robot's drivebase
|
||||
flat on the floor. This computation takes place on the RoboRIO, and should not take more than 2ms.
|
||||
This also requires addHeadingData to be called every frame so heading data is up to date.
|
||||
If Multi-Tag PNP is enabled on the coprocessor, it will be used to provide an initial seed to
|
||||
the optimization algorithm -- otherwise, the multi-tag fallback strategy will be used as the
|
||||
seed.
|
||||
- Solve a constrained version of the Perspective-n-Point problem with the robot's drivebase
|
||||
flat on the floor. This computation takes place on the RoboRIO, and should not take more than 2ms.
|
||||
This also requires addHeadingData to be called every frame so heading data is up to date.
|
||||
If Multi-Tag PNP is enabled on the coprocessor, it will be used to provide an initial seed to
|
||||
the optimization algorithm -- otherwise, the multi-tag fallback strategy will be used as the
|
||||
seed.
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. code-block:: Java
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
|
||||
:language: java
|
||||
:lines: 65-66
|
||||
|
||||
//Forward Camera
|
||||
cam = new PhotonCamera("testCamera");
|
||||
Transform3d robotToCam = new Transform3d(new Translation3d(0.5, 0.0, 0.5), new Rotation3d(0,0,0)); //Cam mounted facing forward, half a meter forward of center, half a meter up from center.
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/poseest/src/main/include/Vision.h
|
||||
:language: c++
|
||||
:lines: 150-153
|
||||
|
||||
// Construct PhotonPoseEstimator
|
||||
PhotonPoseEstimator photonPoseEstimator = new PhotonPoseEstimator(aprilTagFieldLayout, PoseStrategy.CLOSEST_TO_REFERENCE_POSE, cam, robotToCam);
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
// Forward Camera
|
||||
std::shared_ptr<photonlib::PhotonCamera> cameraOne =
|
||||
std::make_shared<photonlib::PhotonCamera>("testCamera");
|
||||
// Camera is mounted facing forward, half a meter forward of center, half a
|
||||
// meter up from center.
|
||||
frc::Transform3d robotToCam =
|
||||
frc::Transform3d(frc::Translation3d(0.5_m, 0_m, 0.5_m),
|
||||
frc::Rotation3d(0_rad, 0_rad, 0_rad));
|
||||
|
||||
// ... Add other cameras here
|
||||
|
||||
// Assemble the list of cameras & mount locations
|
||||
std::vector<
|
||||
std::pair<std::shared_ptr<photonlib::PhotonCamera>, frc::Transform3d>>
|
||||
cameras;
|
||||
cameras.push_back(std::make_pair(cameraOne, robotToCam));
|
||||
|
||||
photonlib::RobotPoseEstimator estimator(
|
||||
aprilTags, photonlib::CLOSEST_TO_REFERENCE_POSE, cameras);
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
kRobotToCam = wpimath.geometry.Transform3d(
|
||||
wpimath.geometry.Translation3d(0.5, 0.0, 0.5),
|
||||
wpimath.geometry.Rotation3d.fromDegrees(0.0, -30.0, 0.0),
|
||||
)
|
||||
|
||||
self.cam = PhotonCamera("YOUR CAMERA NAME")
|
||||
|
||||
self.camPoseEst = PhotonPoseEstimator(
|
||||
loadAprilTagLayoutField(AprilTagField.kDefaultField),
|
||||
PoseStrategy.CLOSEST_TO_REFERENCE_POSE,
|
||||
self.cam,
|
||||
kRobotToCam
|
||||
)
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 45-50
|
||||
```
|
||||
|
||||
:::{note}
|
||||
Python still takes a `PhotonCamera` in the constructor, so you must create the camera as shown in the next section and then return and use it to create the `PhotonPoseEstimator`.
|
||||
:::
|
||||
|
||||
## Using a `PhotonPoseEstimator`
|
||||
|
||||
Calling `update()` on your `PhotonPoseEstimator` will return an `EstimatedRobotPose`, which includes a `Pose3d` of the latest estimated pose (using the selected strategy) along with a `double` of the timestamp when the robot pose was estimated. You should be updating your [drivetrain pose estimator](https://docs.wpilib.org/en/latest/docs/software/advanced-controls/state-space/state-space-pose-estimators.html) with the result from the `PhotonPoseEstimator` every loop using `addVisionMeasurement()`.
|
||||
The final prerequisite to using your `PhotonPoseEstimator` is creating a `PhotonCamera`. To do this, you must set the name of your camera in Photon Client. From there you can define the camera in code.
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/357d8a518a93f7a1f8084a79449249e613b605a7/photonlib-java-examples/apriltagExample/src/main/java/frc/robot/PhotonCameraWrapper.java
|
||||
:language: java
|
||||
:lines: 85-88
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
std::pair<frc::Pose2d, units::millisecond_t> getEstimatedGlobalPose(
|
||||
frc::Pose3d prevEstimatedRobotPose) {
|
||||
robotPoseEstimator.SetReferencePose(prevEstimatedRobotPose);
|
||||
units::millisecond_t currentTime = frc::Timer::GetFPGATimestamp();
|
||||
auto result = robotPoseEstimator.Update();
|
||||
if (result.second) {
|
||||
return std::make_pair<>(result.first.ToPose2d(),
|
||||
currentTime - result.second);
|
||||
} else {
|
||||
return std::make_pair(frc::Pose2d(), 0_ms);
|
||||
}
|
||||
}
|
||||
|
||||
.. code-block:: Python
|
||||
|
||||
# Coming Soon!
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
|
||||
:language: java
|
||||
:lines: 63
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/aimattarget/src/main/include/Robot.h
|
||||
:language: c++
|
||||
:lines: 55
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 44
|
||||
```
|
||||
|
||||
You should be updating your [drivetrain pose estimator](https://docs.wpilib.org/en/latest/docs/software/advanced-controls/state-space/state-space-pose-estimators.html) with the result from the `RobotPoseEstimator` every loop using `addVisionMeasurement()`. TODO: add example note
|
||||
Calling `update()` on your `PhotonPoseEstimator` will return an `EstimatedRobotPose`, which includes a `Pose3d` of the latest estimated pose (using the selected strategy) along with a `double` of the timestamp when the robot pose was estimated.
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Vision.java
|
||||
:language: java
|
||||
:lines: 93-116
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/poseest/src/main/include/Vision.h
|
||||
:language: c++
|
||||
:lines: 80-100
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 53
|
||||
```
|
||||
|
||||
You should be updating your [drivetrain pose estimator](https://docs.wpilib.org/en/latest/docs/software/advanced-controls/state-space/state-space-pose-estimators.html) with the result from the `PhotonPoseEstimator` every loop using `addVisionMeasurement()`.
|
||||
|
||||
```{eval-rst}
|
||||
.. tab-set-code::
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-java-examples/poseest/src/main/java/frc/robot/Robot.java
|
||||
:language: java
|
||||
:lines: 49
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-cpp-examples/poseest/src/main/include/Robot.h
|
||||
:language: c++
|
||||
:lines: 54-57
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/refs/heads/main/photonlib-python-examples/poseest/robot.py
|
||||
:language: python
|
||||
:lines: 54-57
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
||||
The complete examples for the `PhotonPoseEstimator` can be found in the following locations:
|
||||
|
||||
- [Java](https://github.com/PhotonVision/photonvision/tree/main/photonlib-java-examples/poseest)
|
||||
- [C++](https://github.com/PhotonVision/photonvision/tree/main/photonlib-cpp-examples/poseest)
|
||||
- [Python](https://github.com/PhotonVision/photonvision/tree/main/photonlib-python-examples/poseest)
|
||||
|
||||
## Additional `PhotonPoseEstimator` Methods
|
||||
|
||||
### `setReferencePose(Pose3d referencePose)`
|
||||
For more information on the `PhotonPoseEstimator` class, please see the API documentation.
|
||||
|
||||
Updates the stored reference pose when using the CLOSEST_TO_REFERENCE_POSE strategy.
|
||||
|
||||
### `setLastPose(Pose3d lastPose)`
|
||||
|
||||
Update the stored last pose. Useful for setting the initial estimate when using the CLOSEST_TO_LAST_POSE strategy.
|
||||
- [Java Documentation](https://javadocs.photonvision.org/release/org/photonvision/PhotonPoseEstimator.html)
|
||||
- [C++ Documentation](https://cppdocs.photonvision.org/release/classphoton_1_1_photon_pose_estimator.html)
|
||||
- [Python Documentation](https://pydocs.photonvision.org/release/reference/photonPoseEstimator/)
|
||||
|
||||
41
docs/source/docs/quick-start/camera-matching.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Camera Matching
|
||||
|
||||
## Activating and Deactivating Cameras
|
||||
|
||||
When you first plug in a camera, it will be detected and added to the list of cameras with the "Unassigned" status, as shown below. You can press the "Activate" button to enable PhotonVision to use the camera.
|
||||
|
||||
```{image} images/camera-matching/unassigned-camera.png
|
||||
:scale: 50%
|
||||
```
|
||||
|
||||
If a camera has been activated in the past, it will be listed as "Deactivated" in the camera list. You can press the "Activate" button to enable PhotonVision to use the camera.
|
||||
|
||||
```{image} images/camera-matching/deactivated-camera.png
|
||||
:scale: 50%
|
||||
```
|
||||
|
||||
Once a camera is activated, it will be listed as "Active" in the camera list. You can press the "Deactivate" button to stop PhotonVision from using the camera.
|
||||
|
||||
```{image} images/camera-matching/activated-camera.png
|
||||
:scale: 50%
|
||||
```
|
||||
|
||||
## Deleting Cameras
|
||||
|
||||
If you want to remove a camera from the list, you can press the delete button. This will clear all settings for that particular camera, including the calibration data and any other settings you have configured. It is recommended to make a backup of the camera's settings before deleting it, as this action cannot be undone.
|
||||
|
||||
## Matching Cameras
|
||||
|
||||
When you plug in a camera, PhotonVision will attempt to match it to a previously configured camera based on the physical USB port it is connected to. If you plug another camera into that port, the cameras will have a "Camera Mismatch" status, indicating that the camera is not recognized as the one that was previously configured.
|
||||
|
||||
Additionally, pressing on the Details button will show you the details of the camera mismatch, allowing you to compare the current camera with the previously configured camera.
|
||||
|
||||
```{image} images/camera-matching/camera-mismatch-details.png
|
||||
:scale: 50%
|
||||
```
|
||||
|
||||
```{note}
|
||||
Camera matching is based on the USB ports on the device. If you unplug a camera and plug it into a different port, PhotonVision will attempt to use settings from the camera that was previously configured in that port, causing unexpected behavior.
|
||||
```
|
||||
|
||||
To resolve the camera mismatch, you should ensure each camera is plugged into the same port that you configured it in.
|
||||
@@ -34,7 +34,7 @@ Innomaker and Arducam are common manufacturers of hardware designed specifically
|
||||
- Driver Camera
|
||||
- OV9281
|
||||
- OV9782
|
||||
- Pi Camera Module V1 {ref}`(More setup info)<docs/hardware/picamconfig:Pi Camera Configuration>`
|
||||
- Pi Camera Module V1 {ref}`(More setup info)<docs/camera-specific-configuration/picamconfig:Pi Camera Configuration>`
|
||||
|
||||
Feel free to get started with any color webcam you have sitting around.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 287 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 394 KiB After Width: | Height: | Size: 334 KiB |