Move docs in-source (#1357)
32
docs/source/docs/additional-resources/best-practices.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
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 target(s) and ensure you get a consistent tracking (you hold one target 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. You want to make your exposure as low as possible with a tight hue value to ensure no extra targets are detected.
|
||||
* Move the robot close, far, angled, and around the field to ensure no extra targets are found anywhere when looking for a target.
|
||||
* 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 targets to stay within bandwidth limits.
|
||||
54
docs/source/docs/additional-resources/config.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
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
|
||||
:width: 600
|
||||
:alt: Config directory structure
|
||||
|
||||
* 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.
|
||||
BIN
docs/source/docs/additional-resources/images/configDir.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
86
docs/source/docs/additional-resources/nt-api.rst
Normal file
@@ -0,0 +1,86 @@
|
||||
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.
|
||||
66
docs/source/docs/apriltag-pipelines/2D-tracking-tuning.rst
Normal file
@@ -0,0 +1,66 @@
|
||||
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
|
||||
:scale: 45 %
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
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 7+ 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.
|
||||
15
docs/source/docs/apriltag-pipelines/3D-tracking.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
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.
|
||||
12
docs/source/docs/apriltag-pipelines/about-apriltags.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
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>`_.
|
||||
49
docs/source/docs/apriltag-pipelines/coordinate-systems.rst
Normal file
@@ -0,0 +1,49 @@
|
||||
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
|
||||
:scale: 45 %
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/multiple-tags.png
|
||||
:scale: 45 %
|
||||
:align: center
|
||||
|
||||
|
|
||||
|
||||
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
|
||||
:scale: 45 %
|
||||
:align: center
|
||||
|
||||
|
|
||||
15
docs/source/docs/apriltag-pipelines/detector-types.rst
Normal 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.
|
||||
BIN
docs/source/docs/apriltag-pipelines/images/apriltag-coords.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/apriltag-tune.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/apriltag.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/camera-coord.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/field-layout.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/multiple-tags.png
Normal file
|
After Width: | Height: | Size: 427 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/multitag-ui.png
Normal file
|
After Width: | Height: | Size: 451 KiB |
BIN
docs/source/docs/apriltag-pipelines/images/pv-apriltag.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
11
docs/source/docs/apriltag-pipelines/index.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
AprilTag Detection
|
||||
==================
|
||||
|
||||
.. toctree::
|
||||
|
||||
about-apriltags
|
||||
detector-types
|
||||
2D-tracking-tuning
|
||||
3D-tracking
|
||||
multitag
|
||||
coordinate-systems
|
||||
53
docs/source/docs/apriltag-pipelines/multitag.rst
Normal file
@@ -0,0 +1,53 @@
|
||||
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
|
||||
:width: 600
|
||||
:alt: Multitarget enabled and running in the PhotonVision UI
|
||||
|
||||
.. 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++).
|
||||
|
||||
|
||||
|
||||
.. 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;
|
||||
}
|
||||
|
||||
.. 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
|
||||
:width: 600
|
||||
:alt: The currently saved field layout in the Photon UI
|
||||
|
||||
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.
|
||||
BIN
docs/source/docs/assets/AprilTag16h5.pdf
Normal file
BIN
docs/source/docs/assets/settings.png
Normal file
|
After Width: | Height: | Size: 143 KiB |
159
docs/source/docs/calibration/calibration.rst
Normal file
@@ -0,0 +1,159 @@
|
||||
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 chessboard (or grid of dots, or other target) are taken. by comparing where the grid corners (or dots) should be in object space (for example, a dot 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, resolutions lower than 960x720 are often too low to provide accurate results. Additionally, high resolutions may be too performance intensive for a coprocessor like a Raspberry Pi to handle (solutions to this are being looked into). Thus, we recommend 960x720 when using 3D mode.
|
||||
|
||||
.. 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:
|
||||
|
||||
1. Practice calibration using your laptop webcam and https://www.calibdb.net/. The target can be found on the website and should be printed out if possible. Once you print it out, try to line up your target with the overlay on the screen as best as possible. The point of this practice is to notice how you are prompted to place targets in certain positions on the screen that make sure you account for all regions of the sensor. The chessboard should (in general) not be facing parallel to the camera (straight on), nor should it be aligned with any of the camera axes (ie, rotated only about an axis going left/right, up/down, or out-of-the-camera).
|
||||
|
||||
2. 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.
|
||||
|
||||
3. Use as big of a calibration target as your printer can print.
|
||||
|
||||
4. Ensure that your printed pattern has enough white border around it.
|
||||
|
||||
5. Ensure your camera stays in one position during the duration of the calibration.
|
||||
|
||||
6. Make sure you get all 12 images from varying distances and angles.
|
||||
|
||||
7. 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.
|
||||
|
||||
8. Have good lighting, having a diffusely lit target would be best (light specifically shining on the target without shadows).
|
||||
|
||||
9. 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.
|
||||
|
||||
10. 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.
|
||||
|
||||
Calibration Steps
|
||||
-----------------
|
||||
|
||||
Your camera can be calibrated using either the utility built into PhotonVision, which performs all the calculations on your coprocessor, or using a website such as `calibdb <https://calibdb.net/>`_, which uses a USB webcam connected to your laptop. The integrated calibration utility is currently the only one that works with ribbon-cable CSI cameras or Limelights, but for USB webcams, calibdb is the preferred option.
|
||||
|
||||
Calibrating using calibdb
|
||||
-------------------------
|
||||
|
||||
Calibdb uses a modified chessboard/aruco marker combination target called `ChArUco targets. <https://docs.opencv.org/4.8.0/df/d4a/tutorial_charuco_detection.html>`_ The website currently only supports Chrome browser.
|
||||
|
||||
Download and print out (or display on a monitor) the calibration by clicking Show Pattern. Click "Calibrate" and align your camera with the ghost overlay of the calibration board. The website automatically calculates the next position and displays it for you. When complete, download the calibration (do **not** use the OpenCV format). Reconnect your camera to your coprocessor and navigate to the PhotonVision web interface's camera tab. Ensure the correct camera is selected, and click the "Import from CalibDB" button. Your calibration data will be automatically saved and applied!
|
||||
|
||||
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 dot 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 chessboard.
|
||||
|
||||
.. 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 and board size. The provided chessboard is 8 squares in width and height, and each square should be about 1in across. Mine measured with a caliper was 0.96in, but this will vary per printer. Finally, once our entered data is correct, we'll click "start calibration."
|
||||
|
||||
4. Take at calibration images from various angles.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Now, we'll capture images of our chessboard from various angles. The most important part of this step is to make sure that the chessboard overlay matches the chessboard 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 at least 12 images, trying to take one in each region of the camera sensor. 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 standard deviation will be shown in the table on the right.
|
||||
|
||||
.. 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 intrinsics.
|
||||
|
||||
.. image:: images/cal-details.png
|
||||
:width: 600
|
||||
:alt: Captured calibration images
|
||||
|
||||
.. 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
|
||||
:width: 600
|
||||
:alt: Captured calibration images
|
||||
|
||||
|
||||
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>`ap_ 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
|
||||
BIN
docs/source/docs/calibration/images/cal-details.png
Normal file
|
After Width: | Height: | Size: 462 KiB |
6201
docs/source/docs/calibration/images/camera-uncertainty.svg
Normal file
|
After Width: | Height: | Size: 341 KiB |
10773
docs/source/docs/calibration/images/mrcal-coverage.svg
Normal file
|
After Width: | Height: | Size: 600 KiB |
10306
docs/source/docs/calibration/images/residual-directions.svg
Normal file
|
After Width: | Height: | Size: 519 KiB |
10360
docs/source/docs/calibration/images/residual-magnitudes.svg
Normal file
|
After Width: | Height: | Size: 522 KiB |
BIN
docs/source/docs/calibration/images/unpacked-json.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
7
docs/source/docs/contributing/index.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
Contributing to PhotonVision Projects
|
||||
=====================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
photonvision/index
|
||||
photonvision-docs/index
|
||||
@@ -0,0 +1,32 @@
|
||||
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
|
||||
------------------------------------
|
||||
If you are planning on contributing, it is recommended to create a fork of the `main docs repository <https://github.com/PhotonVision/photonvision-docs>`_. To clone this fork, run the following command in a terminal window:
|
||||
|
||||
``git clone https://github.com/[your username]/photonvision-docs``
|
||||
|
||||
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 root project directory:
|
||||
|
||||
``python -m pip install -r requirements.txt``
|
||||
|
||||
Building the Documentation
|
||||
--------------------------
|
||||
In order to build the documentation, you can run the following command in the root project directory:
|
||||
|
||||
``make html``
|
||||
|
||||
.. note:: You may have to run ``./make html`` on Windows.
|
||||
|
||||
Opening the Documentation
|
||||
-------------------------
|
||||
The built documentation is located at ``build/html/index.html``.
|
||||
|
||||
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``
|
||||
@@ -0,0 +1,8 @@
|
||||
Contributing to PhotonVision Documentation
|
||||
==========================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
building-docs
|
||||
style-guide
|
||||
top-contributors
|
||||
@@ -0,0 +1,3 @@
|
||||
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>`_.
|
||||
@@ -0,0 +1,5 @@
|
||||
Top Contributors
|
||||
================
|
||||
|
||||
.. ghcontributors:: PhotonVision/photonvision-docs
|
||||
:limit: 10
|
||||
|
After Width: | Height: | Size: 92 KiB |
@@ -0,0 +1,267 @@
|
||||
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+. If you don't have this JDK with WPILib, 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 14.18.0 to Node 16.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
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
nvm install 20
|
||||
|
||||
so that it instead reads
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
nvm install 14.18.0
|
||||
|
||||
Compiling Instructions
|
||||
----------------------
|
||||
|
||||
Getting the Source Code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Get the source code from git:
|
||||
|
||||
.. code-block:: 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
|
||||
:width: 600
|
||||
:alt: Download source code from git
|
||||
|
||||
Install Necessary Node JS Dependencies
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the photon-client directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
npm install
|
||||
|
||||
Build and Copy UI to Java Source
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the root directory:
|
||||
|
||||
|
||||
.. 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:
|
||||
|
||||
.. 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``:
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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:
|
||||
|
||||
.. 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:
|
||||
|
||||
.. 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.
|
||||
|
||||
.. code-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"`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
{
|
||||
// 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`
|
||||
|
||||
.. code-block::
|
||||
|
||||
{
|
||||
// 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-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.
|
||||
|
||||
.. code-block::
|
||||
|
||||
~/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
|
||||
7
docs/source/docs/contributing/photonvision/index.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
Contributing to PhotonVision
|
||||
============================
|
||||
|
||||
.. toctree::
|
||||
|
||||
build-instructions
|
||||
top-contributors
|
||||
@@ -0,0 +1,5 @@
|
||||
Top Contributors
|
||||
================
|
||||
|
||||
.. ghcontributors:: PhotonVision/photonvision
|
||||
:limit: 10
|
||||
47
docs/source/docs/description.rst
Normal file
@@ -0,0 +1,47 @@
|
||||
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 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.
|
||||
41
docs/source/docs/examples/aimandrange.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
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>` and :ref:`Getting in Range of the Target <docs/examples/gettinginrangeofthetarget:Knowledge and Equipment Needed>`.
|
||||
|
||||
Code
|
||||
-------
|
||||
|
||||
Now that you know how to both aim and get in range of the target, it is time to combine them both at the same time. This example will take the previous two code examples and make them into one function using the same tools as before. With this example, you now have all the knowledge you need to use PhotonVision on your robot in any game.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/aimandrange/src/main/java/frc/robot/Robot.java
|
||||
:language: java
|
||||
:lines: 42-111
|
||||
:linenos:
|
||||
:lineno-start: 42
|
||||
|
||||
.. tab-item:: C++ (Header)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/aimandrange/src/main/include/Robot.h
|
||||
:language: cpp
|
||||
:lines: 27-71
|
||||
:linenos:
|
||||
:lineno-start: 27
|
||||
|
||||
.. tab-item:: C++ (Source)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/aimandrange/src/main/cpp/Robot.cpp
|
||||
:language: cpp
|
||||
:lines: 25-67
|
||||
:linenos:
|
||||
:lineno-start: 25
|
||||
46
docs/source/docs/examples/aimingatatarget.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
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>`_/`C++ <https://github.com/PhotonVision/photonvision/tree/master/photonlib-cpp-examples/aimattarget>`_).
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
------------------------------
|
||||
|
||||
- Robot with a vision system running PhotonVision
|
||||
- Target
|
||||
- Ability to track a target by properly tuning a pipeline
|
||||
|
||||
Code
|
||||
-------
|
||||
|
||||
Now that you have properly set up your vision system and have tuned a pipeline, you can now aim your robot/turret at the target using the data from PhotonVision. This data is reported over NetworkTables and includes: latency, whether there is a target detected or not, pitch, yaw, area, skew, and target pose relative to the robot. This data will be used/manipulated by our vendor dependency, PhotonLib. 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?>`.
|
||||
|
||||
For this simple example, only yaw is needed.
|
||||
|
||||
In this example, while the operator holds a button down, the robot will turn towards the goal 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>`_.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/aimattarget/src/main/java/frc/robot/Robot.java
|
||||
:language: java
|
||||
:lines: 41-98
|
||||
:linenos:
|
||||
:lineno-start: 41
|
||||
|
||||
.. tab-item:: C++ (Header)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/aimattarget/src/main/include/Robot.h
|
||||
:language: c++
|
||||
:lines: 27-53
|
||||
:linenos:
|
||||
:lineno-start: 27
|
||||
|
||||
.. tab-item:: C++ (Source)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/aimattarget/src/main/cpp/Robot.cpp
|
||||
:language: c++
|
||||
:lines: 25-52
|
||||
:linenos:
|
||||
:lineno-start: 25
|
||||
54
docs/source/docs/examples/gettinginrangeofthetarget.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Getting in Range of the Target
|
||||
==============================
|
||||
|
||||
The following example is from the PhotonLib example repository (`Java <https://github.com/PhotonVision/photonvision/tree/master/photonlib-java-examples/getinrange>`_/`C++ <https://github.com/PhotonVision/photonvision/tree/master/photonlib-cpp-examples/getinrange>`_).
|
||||
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
-----------------------------------------------
|
||||
|
||||
- Everything required in :ref:`Aiming at a Target <docs/examples/aimingatatarget:Knowledge and Equipment Needed>`.
|
||||
- Large space where your robot can move around freely
|
||||
|
||||
Code
|
||||
-------
|
||||
|
||||
In FRC, a mechanism usually has to be a certain distance away from its target in order to be effective and score. In the previous example, we showed how to aim your robot at the target. Now we will show how to move to a certain distance from the target.
|
||||
|
||||
For proper functionality of just this example, ensure that your robot is pointed towards the target.
|
||||
|
||||
While the operator holds down a button, the robot will drive towards the target and get in range.
|
||||
|
||||
This example uses P term of the PID loop and PhotonLib and the distance function of PhotonUtils.
|
||||
|
||||
.. warning:: The PhotonLib utility to calculate distance depends on the camera being at a different vertical height than the target. If this is not the case, a different method for estimating distance, such as target width or area, should be used. In general, this method becomes more accurate as range decreases and as the height difference increases.
|
||||
|
||||
.. note:: There is no strict minimum delta-height necessary for this method to be applicable, just a requirement that a delta exists.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/getinrange/src/main/java/frc/robot/Robot.java
|
||||
:language: java
|
||||
:lines: 42-107
|
||||
:linenos:
|
||||
:lineno-start: 42
|
||||
|
||||
.. tab-item:: C++ (Header)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/getinrange/src/main/include/Robot.h
|
||||
:language: c++
|
||||
:lines: 27-67
|
||||
:linenos:
|
||||
:lineno-start: 27
|
||||
|
||||
.. tab-item:: C++ (Source)
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-cpp-examples/getinrange/src/main/cpp/Robot.cpp
|
||||
:language: c++
|
||||
:lines: 25-58
|
||||
:linenos:
|
||||
:lineno-start: 25
|
||||
|
||||
.. hint:: The accuracy of the measurement of the camera's pitch (:code:`CAMERA_PITCH_RADIANS` in the above example), as well as the camera's FOV, will determine the overall accuracy of this method.
|
||||
11
docs/source/docs/examples/index.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
Code Examples
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
aimingatatarget
|
||||
gettinginrangeofthetarget
|
||||
aimandrange
|
||||
simaimandrange
|
||||
simposeest
|
||||
94
docs/source/docs/examples/simaimandrange.rst
Normal file
@@ -0,0 +1,94 @@
|
||||
Simulating Aiming and Getting in Range
|
||||
======================================
|
||||
|
||||
The following example comes from the PhotonLib example repository (`Java <https://github.com/PhotonVision/photonvision/tree/661f8b2c0495474015f6ea9a89d65f9788436a05/photonlib-java-examples/src/main/java/org/photonlib/examples/simaimandrange>`_/`C++ <https://github.com/PhotonVision/photonvision/tree/661f8b2c0495474015f6ea9a89d65f9788436a05/photonlib-cpp-examples/src/main/cpp/examples/simaimandrange>`_). Full code is available at those links.
|
||||
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
-----------------------------------------------
|
||||
|
||||
- Everything required in :ref:`Combining Aiming and Getting in Range <docs/examples/aimandrange:Knowledge and Equipment Needed>`.
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
The previous examples show how to run PhotonVision on a real robot, with a physical robot drivetrain moving around and interacting with the software.
|
||||
|
||||
This example builds upon that, adding support for simulating robot motion and incorporating that motion into a :code:`SimVisionSystem`. This allows you to test control algorithms on your development computer, without requiring access to a real robot.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<video width="85%" controls>
|
||||
<source src="../../_static/assets/simaimandrange.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
Walkthrough
|
||||
-----------
|
||||
|
||||
First, in the main :code:`Robot` source file, we add support to periodically update a new simulation-specific object. This logic only gets used while running in simulation:
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/Robot.java
|
||||
:language: java
|
||||
:lines: 118-128
|
||||
:linenos:
|
||||
:lineno-start: 118
|
||||
|
||||
Then, we add in the implementation of our new `DrivetrainSim` class. Please reference the `WPILib documentation on physics simulation <https://docs.wpilib.org/en/stable/docs/software/wpilib-tools/robot-simulation/physics-sim.html>`_.
|
||||
|
||||
Simulated Vision support is added with the following steps:
|
||||
|
||||
Creating the Simulated Vision System
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
First, we create a new :code:`SimVisionSystem` to represent our camera and coprocessor running PhotonVision.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 73-93
|
||||
:linenos:
|
||||
:lineno-start: 72
|
||||
|
||||
Next, we create objects to represent the physical location and size of the vision targets we are calibrated to detect. This example models the down-field high goal vision target from the 2020 and 2021 games.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 95-111
|
||||
:linenos:
|
||||
:lineno-start: 95
|
||||
|
||||
Finally, we add our target to the simulated vision system.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 116-117
|
||||
:linenos:
|
||||
:lineno-start: 113
|
||||
|
||||
|
||||
If you have additional targets you want to detect, you can add them in the same way as the first one.
|
||||
|
||||
|
||||
Updating the Simulated Vision System
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once we have all the properties of our simulated vision system defined, the work to do at runtime becomes very minimal. Simply pass in the robot's pose periodically to the simulated vision system.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/ebef19af3d926cf87292177c9a16d01b71219306/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 124-142
|
||||
:linenos:
|
||||
:lineno-start: 122
|
||||
|
||||
|
||||
The rest is done behind the scenes.
|
||||
129
docs/source/docs/examples/simposeest.rst
Normal file
@@ -0,0 +1,129 @@
|
||||
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/>`_). 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 builds upon WPILib's `Differential Drive Pose Estimator <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/differentialdriveposeestimator>`_. It adds a :code:`PhotonCamera` to gather estimates of the robot's position on the field. This in turn can be used for aligning with vision targets, and increasing accuracy of autonomous routines.
|
||||
|
||||
To support simulation, a :code:`SimVisionSystem` is used to drive data into the :code:`PhotonCamera`. The far high goal target from 2020 is modeled.
|
||||
|
||||
Walkthrough
|
||||
-----------
|
||||
|
||||
WPILib's :code:`Pose2d` class is used to represent robot positions on the field.
|
||||
|
||||
Three different :code:`Pose2d` positions are relevant for this example:
|
||||
|
||||
1) Desired Pose: The location some autonomous routine wants the robot to be in.
|
||||
2) Estimated Pose: The location the software `believes` the robot to be in, based on physics models and sensor feedback.
|
||||
3) Actual Pose: The locations the robot is actually at. The physics simulation generates this in simulation, but it cannot be directly measured on the real robot.
|
||||
|
||||
Estimating Pose
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The :code:`DrivetrainPoseEstimator` class is responsible for generating an estimated robot pose using sensor readings (including PhotonVision).
|
||||
|
||||
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:`DifferentialDrivePoseEstimator` class.
|
||||
|
||||
For both simulation and on-robot code, we create objects to represent the physical location and size of the vision targets we are calibrated to detect. This example models the down-field high goal vision target from the 2020 and 2021 games.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/Constants.java
|
||||
:language: java
|
||||
:lines: 83-106
|
||||
:linenos:
|
||||
:lineno-start: 83
|
||||
|
||||
|
||||
To incorporate PhotonVision, we need to create a :code:`PhotonCamera`:
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/DrivetrainPoseEstimator.java
|
||||
:language: java
|
||||
:lines: 46
|
||||
:linenos:
|
||||
:lineno-start: 46
|
||||
|
||||
During periodic execution, we read back camera results. If we see a target in the image, we pass the camera-measured pose of the robot to the :code:`DifferentialDrivePoseEstimator`.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/DrivetrainPoseEstimator.java
|
||||
:language: java
|
||||
:lines: 81-92
|
||||
:linenos:
|
||||
:lineno-start: 81
|
||||
|
||||
|
||||
That's it!
|
||||
|
||||
Simulating the Camera
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
First, we create a new :code:`SimVisionSystem` to represent our camera and coprocessor running PhotonVision.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 76-95
|
||||
:linenos:
|
||||
:lineno-start: 76
|
||||
|
||||
|
||||
Then, we add our target to the simulated vision system.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/DrivetrainSim.java
|
||||
:lines: 97-99
|
||||
:linenos:
|
||||
:lineno-start: 97
|
||||
|
||||
|
||||
If you have additional targets you want to detect, you can add them in the same way as the first one.
|
||||
|
||||
|
||||
Updating the Simulated Vision System
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once we have all the properties of our simulated vision system defined, the remaining work is minimal. Periodically, pass in the robot's pose to the simulated vision system.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Java
|
||||
:sync: java
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simposeest/src/main/java/frc/robot/DrivetrainSim.java
|
||||
:language: java
|
||||
:lines: 138-139
|
||||
:linenos:
|
||||
:lineno-start: 138
|
||||
|
||||
|
||||
The rest is done behind the scenes.
|
||||
112
docs/source/docs/hardware/customhardware.rst
Normal file
@@ -0,0 +1,112 @@
|
||||
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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"vendorFOV" : 98.9
|
||||
}
|
||||
|
||||
Cosmetic & Branding
|
||||
-------------------
|
||||
|
||||
To help differentiate your hardware from other solutions, some customization is allowed.
|
||||
|
||||
.. 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``:
|
||||
|
||||
.. 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
|
||||
}
|
||||
BIN
docs/source/docs/hardware/images/bootConfigTxt.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
docs/source/docs/hardware/images/motionblur.gif
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
9
docs/source/docs/hardware/index.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Hardware Selection
|
||||
==================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
selecting-hardware
|
||||
picamconfig
|
||||
customhardware
|
||||
55
docs/source/docs/hardware/picamconfig.rst
Normal file
@@ -0,0 +1,55 @@
|
||||
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:
|
||||
|
||||
.. code-block::
|
||||
|
||||
##############################################################
|
||||
### 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.
|
||||
101
docs/source/docs/hardware/selecting-hardware.rst
Normal file
@@ -0,0 +1,101 @@
|
||||
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&single=true&widget=true&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>
|
||||
BIN
docs/source/docs/installation/images/gh_actions_1.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
docs/source/docs/installation/images/gh_actions_2.png
Normal file
|
After Width: | Height: | Size: 139 KiB |
BIN
docs/source/docs/installation/images/gh_actions_3.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
docs/source/docs/installation/images/networking-diagram.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/source/docs/installation/images/pololu-diagram.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/source/docs/installation/images/release-page.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
docs/source/docs/installation/images/static.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
40
docs/source/docs/installation/index.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
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
|
||||
57
docs/source/docs/installation/networking.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
Networking
|
||||
==========
|
||||
|
||||
Physical Networking
|
||||
-------------------
|
||||
.. note:: When using PhotonVision off robot, you *MUST* plug the coprocessor into a physical router/radio. You can then connect your laptop/device used to view the webdashboard to the same network. Any other networking setup will not work and will not be supported in any capacity.
|
||||
|
||||
After imaging your coprocessor, run an ethernet cable from your coprocessor to a router/radio and power on your coprocessor by plugging it into the wall. Then connect whatever device you're using to view the webdashboard to the same network and navigate to photonvision.local:5800.
|
||||
|
||||
PhotonVision *STRONGLY* recommends the usage of a network switch on your robot. This is because the second radio port on the current FRC radios is known to be buggy and cause frequent connection issues that are detrimental during competition. An in-depth guide on how to install a network switch can be found `on FRC 900's website <https://team900.org/blog/ZebraSwitch/>`_.
|
||||
|
||||
|
||||
.. image:: images/networking-diagram.png
|
||||
:alt: Correctly set static IP
|
||||
|
||||
Digital Networking
|
||||
------------------
|
||||
PhotonVision *STRONGLY* recommends the usage of Static IPs as it increases reliability on the field and when using PhotonVision in general. To properly set up your static IP, follow the steps below:
|
||||
|
||||
.. warning:: Only use a static IP when connected to the **robot radio**, and never when testing at home, unless you are well versed in networking or have the relevant "know how".
|
||||
|
||||
1. Ensure your robot is on and you are connected to the robot network.
|
||||
2. Navigate to ``photonvision.local:5800`` (this may be different if you are using a Gloworm / Limelight) in your browser.
|
||||
3. Open the settings tab on the left pane.
|
||||
4. Under the Networking section, set your team number.
|
||||
5. Change your IP to Static.
|
||||
6. Set your coprocessor's IP address to “10.TE.AM.11”. More information on IP format can be found `here <https://docs.wpilib.org/en/stable/docs/networking/networking-introduction/ip-configurations.html#on-the-field-static-configuration>`_.
|
||||
|
||||
7. Click the “Save” button.
|
||||
8. Set your roboRIO to the following static IP address: “10.TE.AM.2”. This can be done via the `roboRIO web dashboard <https://docs.wpilib.org/en/stable/docs/software/roborio-info/roborio-web-dashboard.html#roborio-web-dashboard>`_.
|
||||
|
||||
Power-cycle your robot and then you will now be access the PhotonVision dashboard at ``10.TE.AM.11:5800``.
|
||||
|
||||
.. image:: images/static.png
|
||||
:alt: Correctly set static IP
|
||||
|
||||
Port Forwarding
|
||||
---------------
|
||||
|
||||
If you would like to access your Ethernet-connected vision device from a computer when tethered to the USB port on the roboRIO, you can use `WPILib's <https://docs.wpilib.org/en/stable/docs/networking/networking-utilities/portforwarding.html>`_ ``PortForwarder``.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
PortForwarder.add(5800, "photonvision.local", 5800);
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
wpi::PortForwarder::GetInstance().Add(5800, "photonvision.local", 5800);
|
||||
|
||||
.. note:: The address in the code above (``photonvision.local``) is the hostname of the coprocessor. This can be different depending on your hardware, and can be checked in the settings tab under "hostname".
|
||||
|
||||
Camera Stream Ports
|
||||
-------------------
|
||||
|
||||
The camera streams start at they begin at 1181 with two ports for each camera (ex. 1181 and 1182 for camera one, 1183 and 1184 for camera two, etc.). The easiest way to identify the port of the camera that you want is by double clicking on the stream, which opens it in a separate page. The port will be listed below the stream.
|
||||
53
docs/source/docs/installation/sw_install/advanced-cmd.rst
Normal file
@@ -0,0 +1,53 @@
|
||||
Advanced Command Line Usage
|
||||
===========================
|
||||
PhotonVision exposes some command line options which may be useful for customizing execution on Debian-based installations.
|
||||
|
||||
Running a JAR File
|
||||
------------------
|
||||
Assuming ``java`` has been installed, and the appropriate environment variables have been set upon installation (a package manager like ``apt`` should automatically set these), you can use ``java -jar`` to run a JAR file. If you downloaded the latest stable JAR of PhotonVision from the `GitHub releases page <https://github.com/PhotonVision/photonvision/releases>`_, you can run the following to start the program:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
java -jar /path/to/photonvision/photonvision.jar
|
||||
|
||||
Updating a JAR File
|
||||
-------------------
|
||||
When you need to update your JAR file, run the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wget https://git.io/JqkQ9 -O update.sh
|
||||
sudo chmod +x update.sh
|
||||
sudo ./update.sh
|
||||
sudo reboot now
|
||||
|
||||
Creating a ``systemd`` Service
|
||||
------------------------------
|
||||
You can also create a systemd service that will automatically run on startup. To do so, first navigate to ``/lib/systemd/system``. Create a file called ``photonvision.service`` (or name it whatever you want) using ``touch photonvision.service``. Then open this file in the editor of your choice and paste the following text:
|
||||
|
||||
.. code-block::
|
||||
|
||||
[Unit]
|
||||
Description=Service that runs PhotonVision
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/path/to/photonvision
|
||||
# Optional: run photonvision at "nice" -10, which is higher priority than standard
|
||||
# Nice=-10
|
||||
ExecStart=/usr/bin/java -jar /path/to/photonvision/photonvision.jar
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Then copy the ``.service`` file to ``/etc/systemd/system/`` using ``cp photonvision.service /etc/systemd/system/photonvision.service``. Then modify the file to have ``644`` permissions using ``chmod 644 /etc/systemd/system/photonvision.service``.
|
||||
|
||||
.. note::
|
||||
Many ARM processors have a big.LITTLE architecture where some of the CPU cores are more powerful than others. On this type of architecture, you may get more consistent performance by limiting which cores PhotonVision can use. To do this, add the parameter ``AllowedCPUs`` to the systemd service file in the ``[Service]`` section.
|
||||
|
||||
For instance, for an Orange Pi 5, cores 4 through 7 are the fast ones, and you can target those cores with the line ``AllowedCPUs=4-7``.
|
||||
|
||||
Installing the ``systemd`` Service
|
||||
----------------------------------
|
||||
To install the service, simply run ``systemctl enable photonvision.service``.
|
||||
|
||||
.. note:: It is recommended to reload configurations by running ``systemctl daemon-reload``.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"deviceName" : "Limelight 2+",
|
||||
"supportURL" : "https://limelightvision.io",
|
||||
"ledPins" : [ 13, 18 ],
|
||||
"ledsCanDim" : true,
|
||||
"ledPWMRange" : [ 0, 100 ],
|
||||
"ledPWMFrequency" : 30000,
|
||||
"vendorFOV" : 75.76079874010732
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"deviceName" : "Limelight 2",
|
||||
"supportURL" : "https://limelightvision.io",
|
||||
"ledPins" : [ 17, 18 ],
|
||||
"ledsCanDim" : false,
|
||||
"vendorFOV" : 75.76079874010732
|
||||
}
|
||||
59
docs/source/docs/installation/sw_install/gloworm.rst
Normal file
@@ -0,0 +1,59 @@
|
||||
Gloworm Installation
|
||||
====================
|
||||
While not currently in production, PhotonVision still supports Gloworm vision processing cameras.
|
||||
|
||||
Downloading the Gloworm Image
|
||||
-----------------------------
|
||||
Download the latest `Gloworm/Limelight release of PhotonVision <https://github.com/photonvision/photonvision/releases>`_; the image will be suffixed with "image_limelight2.xz". You do not need to extract the downloaded archive.
|
||||
|
||||
Flashing the Gloworm Image
|
||||
--------------------------
|
||||
Plug a USB C cable from your computer into the USB C port on Gloworm labeled with a download icon.
|
||||
|
||||
Use the 1.18.11 version of `Balena Etcher <https://github.com/balena-io/etcher/releases/tag/v1.18.11>`_ to flash an image onto the coprocessor.
|
||||
|
||||
Run BalenaEtcher as an administrator. Select the downloaded ``.zip`` file.
|
||||
|
||||
Select the compute module. If it doesn't show up after 30s try using another USB port, initialization may take a while. If prompted, install the recommended missing drivers.
|
||||
|
||||
Hit flash. Wait for flashing to complete, then disconnect your USB C cable.
|
||||
|
||||
.. warning:: Using a version of Balena Etcher older than 1.18.11 may cause bootlooping (the system will repeatedly boot and restart) when imaging your Gloworm. Updating to 1.18.11 will fix this issue.
|
||||
|
||||
Final Steps
|
||||
-----------
|
||||
Power your device per its documentation and connect it to a robot network.
|
||||
|
||||
You should be able to locate the camera at ``http://photonvision.local:5800/`` in your browser on your computer when connected to the robot.
|
||||
|
||||
Troubleshooting/Setting a Static IP
|
||||
-----------------------------------
|
||||
A static IP address may be used as an alternative to the mDNS ``photonvision.local`` address.
|
||||
|
||||
Download and run `Angry IP Scanner <https://angryip.org/download/#windows>`_ to find PhotonVision/your coprocessor on your network.
|
||||
|
||||
.. image:: images/angryIP.png
|
||||
|
||||
Once you find it, set the IP to a desired :ref:`static IP in PhotonVision. <docs/settings:Networking>`
|
||||
|
||||
Updating PhotonVision
|
||||
---------------------
|
||||
Download the latest stable .jar from `the releases page <https://github.com/PhotonVision/photonvision/releases>`_, go to the settings tab, and upload the .jar using the Offline Update button.
|
||||
|
||||
.. note:: If you are updating PhotonVision on a Gloworm/Limelight, download the LinuxArm64 .jar file.
|
||||
|
||||
As an alternative option - Export your settings, reimage your coprocessor using the instructions above, and import your settings back in.
|
||||
|
||||
Hardware Troubleshooting
|
||||
------------------------
|
||||
To turn the LED lights off or on you need to modify the ``ledMode`` network tables entry or the ``camera.setLED`` of PhotonLib.
|
||||
|
||||
|
||||
Support Links
|
||||
-------------
|
||||
|
||||
* `Website/Documentation <https://photonvision.github.io/gloworm-docs/docs/quickstart/#finding-gloworm>`__ (Note: Gloworm is no longer in production)
|
||||
|
||||
* `Image <https://github.com/gloworm-vision/pi-img-updator/releases>`__
|
||||
|
||||
* `Discord <https://discord.com/invite/DncQRky>`__
|
||||
BIN
docs/source/docs/installation/sw_install/images/angryIP.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
docs/source/docs/installation/sw_install/images/nano.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
34
docs/source/docs/installation/sw_install/index.rst
Normal file
@@ -0,0 +1,34 @@
|
||||
Software Installation
|
||||
=====================
|
||||
|
||||
Supported Coprocessors
|
||||
----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
raspberry-pi
|
||||
limelight
|
||||
orange-pi
|
||||
snakeyes
|
||||
|
||||
Desktop Environments
|
||||
----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
windows-pc
|
||||
linux-pc
|
||||
mac-os
|
||||
|
||||
Other
|
||||
-----
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
other-coprocessors
|
||||
advanced-cmd
|
||||
romi
|
||||
gloworm
|
||||
25
docs/source/docs/installation/sw_install/limelight.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Limelight Installation
|
||||
======================
|
||||
|
||||
Imaging
|
||||
-------
|
||||
Limelight imaging is a very similar process to Gloworm, but with extra steps.
|
||||
|
||||
|
||||
Base Install Steps
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Due to the similarities in hardware, follow the :ref:`Gloworm install instructions <docs/installation/sw_install/gloworm:Gloworm Installation>`.
|
||||
|
||||
|
||||
Hardware-Specific Steps
|
||||
-----------------------
|
||||
Download the hardwareConfig.json file for the version of your Limelight:
|
||||
|
||||
- :download:`Limelight Version 2 <files/Limelight2/hardwareConfig.json>`.
|
||||
- :download:`Limelight Version 2+ <files/Limelight2+/hardwareConfig.json>`.
|
||||
|
||||
.. note:: No hardware config is provided for the Limelight 3 as AprilTags do not require the LEDs (meaning nobody has reverse-engineered what I/O pins drive the LEDs) and the camera FOV is determined as part of calibration.
|
||||
|
||||
:ref:`Import the hardwareConfig.json file <docs/additional-resources/config:Importing and Exporting Settings>`. Again, this is **REQUIRED** or target measurements will be incorrect, and LEDs will not work.
|
||||
|
||||
After installation you should be able to `locate the camera <https://photonvision.github.io/gloworm-docs/docs/quickstart/#finding-gloworm>`_ at: ``http://photonvision.local:5800/`` (not ``gloworm.local``, as previously)
|
||||
41
docs/source/docs/installation/sw_install/linux-pc.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
Linux PC Installation
|
||||
=====================
|
||||
PhotonVision may be run on a Debian-based Linux Desktop PC for basic testing and evaluation.
|
||||
|
||||
.. note:: You do not need to install PhotonVision on a Windows PC in order to access the webdashboard (assuming you are using an external coprocessor like a Raspberry Pi).
|
||||
|
||||
Installing Java
|
||||
---------------
|
||||
PhotonVision requires a JDK installed and on the system path. JDK 11 is needed (different versions will not work). If you don't have JDK 11 already, run the following to install it:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ sudo apt-get install openjdk-11-jdk
|
||||
|
||||
.. warning:: Using a JDK other than JDK11 will cause issues when running PhotonVision and is not supported.
|
||||
|
||||
Downloading the Latest Stable Release of PhotonVision
|
||||
-----------------------------------------------------
|
||||
Go to the `GitHub releases page <https://github.com/PhotonVision/photonvision/releases>`_ and download the relevant .jar file for your coprocessor.
|
||||
|
||||
.. note::
|
||||
If your coprocessor has a 64 bit ARM based CPU architecture (OrangePi, Raspberry Pi, etc.), download the LinuxArm64.jar file.
|
||||
|
||||
If your coprocessor has an 64 bit x86 based CPU architecture (Mini PC, laptop, etc.), download the Linuxx64.jar file.
|
||||
|
||||
|
||||
.. warning:: Be careful to pick the latest stable release. "Draft" or "Pre-Release" versions are not stable and often have bugs.
|
||||
|
||||
Running PhotonVision
|
||||
--------------------
|
||||
To run PhotonVision, open a terminal window of your choice and run the following command:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ java -jar /path/to/photonvision/photonvision-xxx.jar
|
||||
|
||||
If your computer has a compatible webcam connected, PhotonVision should startup without any error messages. If there are error messages, your webcam isn't supported or another issue has occurred. If it is the latter, please open an issue on the `PhotonVision issues page <https://github.com/PhotonVision/photonvision/issues>`_.
|
||||
|
||||
Accessing the PhotonVision Interface
|
||||
------------------------------------
|
||||
Once the Java backend is up and running, you can access the main vision interface by navigating to ``localhost:5800`` inside your browser.
|
||||
41
docs/source/docs/installation/sw_install/mac-os.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
Mac OS Installation
|
||||
===================
|
||||
|
||||
.. warning:: Due to current `cscore <https://github.com/wpilibsuite/allwpilib/tree/main/cscore>`_ restrictions, the PhotonVision server backend may have issues running macOS.
|
||||
|
||||
.. note:: You do not need to install PhotonVision on a Windows PC in order to access the webdashboard (assuming you are using an external coprocessor like a Raspberry Pi).
|
||||
|
||||
VERY Limited macOS support is available.
|
||||
|
||||
Installing Java
|
||||
---------------
|
||||
PhotonVision requires a JDK installed and on the system path. JDK 11 is needed (different versions will not work). You may already have this if you have installed WPILib. If not, `download and install it from here <https://adoptium.net/temurin/releases?version=11>`_.
|
||||
|
||||
.. warning:: Using a JDK other than JDK11 will cause issues when running PhotonVision and is not supported.
|
||||
|
||||
Downloading the Latest Stable Release of PhotonVision
|
||||
-----------------------------------------------------
|
||||
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 Intel based Mac, download the macx64.jar file.
|
||||
|
||||
.. warning:: Be careful to pick the latest stable release. "Draft" or "Pre-Release" versions are not stable and often have bugs.
|
||||
|
||||
Running PhotonVision
|
||||
--------------------
|
||||
To run PhotonVision, open a terminal window of your choice and run the following command:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ java -jar /path/to/photonvision/photonvision-xxx.jar
|
||||
|
||||
.. warning:: Due to current `cscore <https://github.com/wpilibsuite/allwpilib/tree/main/cscore>`_ restrictions, the PhotonVision using test mode is all that is known to work currently.
|
||||
|
||||
Accessing the PhotonVision Interface
|
||||
------------------------------------
|
||||
Once the Java backend is up and running, you can access the main vision interface by navigating to ``localhost:5800`` inside your browser.
|
||||
|
||||
.. warning:: Due to current `cscore <https://github.com/wpilibsuite/allwpilib/tree/main/cscore>`_ restrictions, it is unlikely any streams will open from real webcams.
|
||||
37
docs/source/docs/installation/sw_install/orange-pi.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Orange Pi Installation
|
||||
======================
|
||||
|
||||
Downloading Linux Image
|
||||
-----------------------
|
||||
|
||||
Starting in 2024, PhotonVision provides pre-configured system images for Orange Pi 5 devices. Download the latest release of the PhotonVision Orange Pi 5 image (.xz file suffixed with ``orangepi5.xz``) from the `releases page <https://github.com/PhotonVision/photonvision/releases>`_. You do not need to extract the downloaded archive file. This image is configured with a ``pi`` user with password ``raspberry``.
|
||||
|
||||
For an Orange Pi 4, download the latest release of the Armbian Bullseye CLI image from `here <https://armbian.tnahosting.net/archive/orangepi4/archive/Armbian_23.02.2_Orangepi4_bullseye_current_5.15.93.img.xz>`_.
|
||||
|
||||
Flashing the Pi Image
|
||||
---------------------
|
||||
An 8GB or larger SD card is recommended.
|
||||
|
||||
Use the 1.18.11 version of `Balena Etcher <https://github.com/balena-io/etcher/releases/tag/v1.18.11>`_ to flash an image onto a Orange Pi. Select the downloaded image file, select your microSD card, and flash.
|
||||
|
||||
For more detailed instructions on using Etcher, please see the `Etcher website <https://www.balena.io/etcher/>`_.
|
||||
|
||||
.. warning:: Using a version of Balena Etcher older than 1.18.11 may cause bootlooping (the system will repeatedly boot and restart) when imaging your Orange Pi. Updating to 1.18.11 will fix this issue.
|
||||
|
||||
Alternatively, you can use the `Raspberry Pi Imager <https://www.raspberrypi.com/software/>`_ to flash the image.
|
||||
|
||||
Select "Choose OS" and then "Use custom" to select the downloaded image file. Select your microSD card and flash.
|
||||
|
||||
.. note:: If you are working on Linux, "dd" can be used in the command line to flash an image.
|
||||
|
||||
If you're using an Orange Pi 5, that's it! Orange Pi 4 users will need to install PhotonVision (see below).
|
||||
|
||||
Initial User Setup (Orange Pi 4 Only)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Insert the flashed microSD card into your Orange Pi and boot it up. The first boot may take a few minutes as the Pi expands the filesystem. Be sure not to unplug during this process.
|
||||
|
||||
Plug your Orange Pi into a display via HDMI and plug in a keyboard via USB once its powered up. For an Orange Pi 4, complete the initial set up which involves creating a root password and adding a user, as well as setting localization language. Additionally, choose “bash” when prompted.
|
||||
|
||||
Installing PhotonVision (Orange Pi 4 Only)
|
||||
------------------------------------------
|
||||
From here, you can follow :ref:`this guide <docs/installation/sw_install/other-coprocessors:Installing Photonvision>`.
|
||||
@@ -0,0 +1,36 @@
|
||||
Other Debian-Based Co-Processor Installation
|
||||
============================================
|
||||
|
||||
.. warning:: Working with unsupported coprocessors requires some level of "know how" of your target system. The install script has only been tested on Debian/Raspberry Pi OS Buster and Ubuntu Bionic. If any issues arise with your specific OS, please open an issue on our `issues page <https://github.com/PhotonVision/photonvision/issues>`_.
|
||||
|
||||
.. note:: We'd love to have your input! If you get PhotonVision working on another coprocessor, consider documenting your steps and submitting a `docs issue <https://github.com/PhotonVision/photonvision-docs/issues>`_., `pull request <https://github.com/PhotonVision/photonvision-docs/pulls>`_ , or `ping us on Discord <https://discord.com/invite/wYxTwym>`_. For example, Limelight and Romi install instructions came about because someone spent the time to figure it out, and did a writeup.
|
||||
|
||||
Installing PhotonVision
|
||||
-----------------------
|
||||
|
||||
We provide an `install script <https://git.io/JJrEP>`_ for other Debian-based systems (with ``apt``) that will automatically install PhotonVision and make sure that it runs on startup.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ wget https://git.io/JJrEP -O install.sh
|
||||
$ sudo chmod +x install.sh
|
||||
$ sudo ./install.sh
|
||||
$ sudo reboot now
|
||||
|
||||
.. note:: Your co-processor will require an Internet connection for this process to work correctly.
|
||||
|
||||
For installation on any other co-processors, we recommend reading the :ref:`advanced command line documentation <docs/installation/sw_install/advanced-cmd:Advanced Command Line Usage>`.
|
||||
|
||||
Updating PhotonVision
|
||||
---------------------
|
||||
|
||||
PhotonVision can be updated by downloading the latest jar file, copying it onto the processor, and restarting the service.
|
||||
|
||||
For example, from another computer, run the following commands. Substitute the correct username for "[user]" (e.g. Raspberry Pi uses "pi", Orange Pi uses "orangepi".)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ scp [jar name].jar [user]@photonvision.local:~/
|
||||
$ ssh [user]@photonvision.local
|
||||
$ sudo mv [jar name].jar /opt/photonvision/photonvision.jar
|
||||
$ sudo systemctl restart photonvision.service
|
||||
46
docs/source/docs/installation/sw_install/raspberry-pi.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
Raspberry Pi Installation
|
||||
=========================
|
||||
A Pre-Built Raspberry Pi image is available for ease of installation.
|
||||
|
||||
Downloading the Pi Image
|
||||
------------------------
|
||||
Download the latest release of the PhotonVision Raspberry image (.xz file) from the `releases page <https://github.com/PhotonVision/photonvision/releases>`_. You do not need to extract the downloaded ZIP file.
|
||||
|
||||
.. note:: Make sure you download the image that ends in '-RasberryPi.xz'.
|
||||
|
||||
Flashing the Pi Image
|
||||
---------------------
|
||||
An 8GB or larger card is recommended.
|
||||
|
||||
Use the 1.18.11 version of `Balena Etcher <https://github.com/balena-io/etcher/releases/tag/v1.18.11>`_ to flash an image onto a Raspberry Pi. Select the downloaded ``.tar.xz`` file, select your microSD card, and flash.
|
||||
|
||||
For more detailed instructions on using Etcher, please see the `Etcher website <https://www.balena.io/etcher/>`_.
|
||||
|
||||
.. warning:: Using a version of Balena Etcher older than 1.18.11 may cause bootlooping (the system will repeatedly boot and restart) when imaging your Raspberry Pi. Updating to 1.18.11 will fix this issue.
|
||||
|
||||
Alternatively, you can use the `Raspberry Pi Imager <https://www.raspberrypi.com/software/>`_ to flash the image.
|
||||
|
||||
Select "Choose OS" and then "Use custom" to select the downloaded image file. Select your microSD card and flash.
|
||||
|
||||
If you are using a non-standard Pi Camera connected to the CSI port, :ref:`additional configuration may be required. <docs/hardware/picamconfig:Pi Camera Configuration>`
|
||||
|
||||
Final Steps
|
||||
-----------
|
||||
Insert the flashed microSD card into your Raspberry Pi and boot it up. The first boot may take a few minutes as the Pi expands the filesystem. Be sure not to unplug during this process.
|
||||
|
||||
After the initial setup process, your Raspberry Pi should be configured for PhotonVision. You can verify this by making sure your Raspberry Pi and computer are connected to the same network and navigating to ``http://photonvision.local:5800`` in your browser on your computer.
|
||||
|
||||
Troubleshooting/Setting a Static IP
|
||||
-----------------------------------
|
||||
A static IP address may be used as an alternative to the mDNS ``photonvision.local`` address.
|
||||
|
||||
Download and run `Angry IP Scanner <https://angryip.org/download/#windows>`_ to find PhotonVision/your coprocessor on your network.
|
||||
|
||||
.. image:: images/angryIP.png
|
||||
|
||||
Once you find it, set the IP to a desired :ref:`static IP in PhotonVision. <docs/settings:Networking>`
|
||||
|
||||
Updating PhotonVision
|
||||
---------------------
|
||||
|
||||
To upgrade a Raspberry Pi device with PhotonVision already installed, follow the :ref:`Raspberry Pi update instructions<docs/installation/updating:offline update>`.
|
||||
21
docs/source/docs/installation/sw_install/romi.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
Romi Installation
|
||||
=================
|
||||
|
||||
The `Romi <https://docs.wpilib.org/en/latest/docs/romi-robot/index.html>`_ is a small robot that can be controlled with the WPILib software. The main controller is a Raspberry Pi that must be imaged with `WPILibPi <https://docs.wpilib.org/en/latest/docs/romi-robot/imaging-romi.html>`_ .
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The WPILibPi image includes FRCVision, which reserves USB cameras; to use PhotonVision, we need to edit the `/home/pi/runCamera` script to disable it. First we will need to make the file system writeable; the easiest way to do this is to go to ``10.0.0.2`` and choose "Writable" at the top.
|
||||
|
||||
SSH into the Raspberry Pi (using Windows command line, or a tool like `Putty <https://www.chiark.greenend.org.uk/~sgtatham/putty/>`_ ) at the Romi's default address ``10.0.0.2``. The default user is ``pi``, and the password is ``raspberry``.
|
||||
|
||||
Follow the process for installing PhotonVision on :ref:`"Other Debian-Based Co-Processor Installation" <docs/installation/sw_install/other-coprocessors:Other Debian-Based Co-Processor Installation>`. As it mentions this will require an internet connection so plugging into the ethernet jack on the Raspberry Pi will be the easiest solution. The pi must remain writable!
|
||||
|
||||
Next, from the SSH terminal, run ``sudo nano /home/pi/runCamera`` then arrow down to the start of the exec line and press "Enter" to add a new line. Then add ``#`` before the exec command to comment it out. Then, arrow up to the new line and type ``sleep 10000``. Hit "Ctrl + O" and then "Enter" to save the file. Finally press "Ctrl + X" to exit nano. Now, reboot the Romi by typing ``sudo reboot``.
|
||||
|
||||
.. image:: images/nano.png
|
||||
|
||||
After it reboots, you should be able to `locate the PhotonVision UI <https://photonvision.github.io/gloworm-docs/docs/quickstart/#finding-gloworm>`_ at: ``http://10.0.0.2:5800/``.
|
||||
|
||||
.. warning:: In order for settings, logs, etc. to be saved / take effect, ensure that PhotonVision is in writable mode.
|
||||
56
docs/source/docs/installation/sw_install/snakeyes.rst
Normal file
@@ -0,0 +1,56 @@
|
||||
SnakeEyes Installation
|
||||
======================
|
||||
A Pre-Built Raspberry Pi image with configuration for `the SnakeEyes Raspberry Pi Hat <https://www.playingwithfusion.com/productview.php?pdid=133&catid=1014>`_ is available for ease of setup.
|
||||
|
||||
Downloading the SnakeEyes Image
|
||||
-------------------------------
|
||||
Download the latest release of the SnakeEyes-specific PhotonVision Pi image from the `releases page <https://github.com/PlayingWithFusion/SnakeEyesDocs/releases>`_. You do not need to extract the downloaded ZIP file.
|
||||
|
||||
Flashing the SnakeEyes Image
|
||||
----------------------------
|
||||
An 8GB or larger card is recommended.
|
||||
|
||||
Use the 1.18.11 version of `Balena Etcher <https://github.com/balena-io/etcher/releases/tag/v1.18.11>`_ to flash an image onto a Raspberry Pi. Select the downloaded ``.zip`` file, select your microSD card, and flash.
|
||||
|
||||
For more detailed instructions on using Etcher, please see the `Etcher website <https://www.balena.io/etcher/>`_.
|
||||
|
||||
.. warning:: Using a version of Balena Etcher older than 1.18.11 may cause bootlooping (the system will repeatedly boot and restart) when imaging your Raspberry Pi. Updating to 1.18.11 will fix this issue.
|
||||
|
||||
Alternatively, you can use the `Raspberry Pi Imager <https://www.raspberrypi.com/software/>`_ to flash the image.
|
||||
|
||||
Select "Choose OS" and then "Use custom" to select the downloaded image file. Select your microSD card and flash.
|
||||
|
||||
Final Steps
|
||||
-----------
|
||||
Insert the flashed microSD card into your Raspberry Pi and boot it up. The first boot may take a few minutes as the Pi expands the filesystem. Be sure not to unplug during this process.
|
||||
|
||||
After the initial setup process, your Raspberry Pi should be configured for PhotonVision. You can verify this by making sure your Raspberry Pi and computer are connected to the same network and navigating to ``http://photonvision.local:5800`` in your browser on your computer.
|
||||
|
||||
Troubleshooting/Setting a Static IP
|
||||
-----------------------------------
|
||||
A static IP address may be used as an alternative to the mDNS ``photonvision.local`` address.
|
||||
|
||||
Download and run `Angry IP Scanner <https://angryip.org/download/#windows>`_ to find PhotonVision/your coprocessor on your network.
|
||||
|
||||
.. image:: images/angryIP.png
|
||||
|
||||
Once you find it, set the IP to a desired :ref:`static IP in PhotonVision. <docs/settings:Networking>`
|
||||
|
||||
Updating PhotonVision
|
||||
----------------------
|
||||
Download the latest xxxxx-LinuxArm64.jar from `our releases page <https://github.com/PhotonVision/photonvision/releases>`_, go to the settings tab, and upload the .jar using the Offline Update button.
|
||||
|
||||
As an alternative option - Export your settings, reimage your coprocessor using the instructions above, and import your settings back in.
|
||||
|
||||
Hardware Troubleshooting
|
||||
------------------------
|
||||
To turn the LED lights off or on you need to modify the ``ledMode`` network tables entry or the ``camera.setLED`` of PhotonLib.
|
||||
|
||||
Support Links
|
||||
-------------
|
||||
|
||||
* `Website <https://www.playingwithfusion.com/productview.php?pdid=133>`__
|
||||
|
||||
* `Image <https://github.com/PlayingWithFusion/SnakeEyesDocs/releases/latest>`__
|
||||
|
||||
* `Documentation <https://github.com/PlayingWithFusion/SnakeEyesDocs/blob/master/PhotonVision/readme.md>`__
|
||||
35
docs/source/docs/installation/sw_install/windows-pc.rst
Normal file
@@ -0,0 +1,35 @@
|
||||
Windows PC Installation
|
||||
=======================
|
||||
PhotonVision may be run on a Windows Desktop PC for basic testing and evaluation.
|
||||
|
||||
.. note:: You do not need to install PhotonVision on a Windows PC in order to access the webdashboard (assuming you are using an external coprocessor like a Raspberry Pi).
|
||||
|
||||
Install Bonjour
|
||||
---------------
|
||||
Bonjour provides more stable networking when using Windows PCs. Install `Bonjour here <https://support.apple.com/downloads/DL999/en_US/BonjourPSSetup.exe>`_ before continuing to ensure a stable experience while using PhotonVision.
|
||||
|
||||
Installing Java
|
||||
---------------
|
||||
PhotonVision requires a JDK installed and on the system path. **JDK 11 is needed** (different versions will not work). You may already have this if you have installed WPILib, but ensure that running ``java -version`` shows JDK 11. If not, `download and install it from here <https://adoptium.net/temurin/releases?version=11>`_ and ensure that the new JDK is being used.
|
||||
|
||||
.. warning:: Using a JDK other than JDK11 will cause issues when running PhotonVision and is not supported.
|
||||
|
||||
Downloading the Latest Stable Release of PhotonVision
|
||||
-----------------------------------------------------
|
||||
Go to the `GitHub releases page <https://github.com/PhotonVision/photonvision/releases>`_ and download the winx64.jar file.
|
||||
|
||||
Running PhotonVision
|
||||
--------------------
|
||||
To run PhotonVision, open a terminal window of your choice and run the following command:
|
||||
|
||||
.. code-block::
|
||||
|
||||
> java -jar C:\path\to\photonvision\NAME OF JAR FILE GOES HERE.jar
|
||||
|
||||
If your computer has a compatible webcam connected, PhotonVision should startup without any error messages. If there are error messages, your webcam isn't supported or another issue has occurred. If it is the latter, please open an issue on the `PhotonVision issues page <https://github.com/PhotonVision/photonvision/issues>`_.
|
||||
|
||||
.. warning:: Using an integrated laptop camera may cause issues when trying to run PhotonVision. If you are unable to run PhotonVision on a laptop with an integrated camera, try disabling the camera's driver in Windows Device Manager.
|
||||
|
||||
Accessing the PhotonVision Interface
|
||||
------------------------------------
|
||||
Once the Java backend is up and running, you can access the main vision interface by navigating to ``localhost:5800`` inside your browser.
|
||||
49
docs/source/docs/installation/updating.rst
Normal file
@@ -0,0 +1,49 @@
|
||||
Updating PhotonVision
|
||||
=====================
|
||||
|
||||
PhotonVision provides many different files on a single release page. Each release contains JAR files for performing "offline updates" of a device with PhotonVision already installed, as well as full image files to "flash" to supported coprocessors.
|
||||
|
||||
.. image:: images/release-page.png
|
||||
:alt: Example GitHub release page
|
||||
|
||||
In the example release above, we see:
|
||||
|
||||
- Image files for flashing directly to supported coprocessors.
|
||||
|
||||
- Raspberry Pi 3/4/5/CM4: follow our :ref:`Raspberry Pi flashing instructions<docs/installation/sw_install/raspberry-pi:raspberry pi installation>`.
|
||||
- For LimeLight devices: follow our :ref:`LimeLight flashing instructions<docs/installation/sw_install/limelight:imaging>`.
|
||||
- For Orange Pi 5 devices: follow our :ref:`Orange Pi flashing instructions<docs/installation/sw_install/orange-pi:orange pi installation>`.
|
||||
|
||||
- JAR files for the suite of supported operating systems for use with Offline Update. In general:
|
||||
|
||||
- Raspberry Pi, Limelight, and Orange Pi: use images suffixed with -linuxarm64.jar. For example: :code:`photonvision-v2024.1.1-linuxarm64.jar`
|
||||
- Beelink and other Intel/AMD-based Mini-PCs: use images suffixed with -linuxx64.jar. For example: :code:`photonvision-v2024.1.1-linuxx64.jar`
|
||||
|
||||
Offline Update
|
||||
--------------
|
||||
|
||||
Unless noted in the release page, an offline update allows you to quickly upgrade the version of PhotonVision running on a coprocessor with PhotonVision already installed on it.
|
||||
|
||||
Unless otherwise noted on the release page, config files should be backward compatible with previous version of PhotonVision, and this offline update process should preserve any pipelines and calibrations previously performed. For paranoia, we suggest exporting settings from the Settings tab prior to performing an offline update.
|
||||
|
||||
.. note:: Carefully review release notes to ensure that reflashing the device (for supported devices) or other installation steps are not required, as dependencies needed for PhotonVision may change between releases
|
||||
|
||||
Installing Pre-Release Versions
|
||||
-------------------------------
|
||||
|
||||
Pre-release/development version of PhotonVision can be tested by installing/downloading artifacts from Github Actions (see below), which are built automatically on commits to open pull requests and to PhotonVision's ``master`` branch, or by :ref:`compiling PhotonVision locally <docs/contributing/photonvision/build-instructions:Build Instructions>`.
|
||||
|
||||
.. warning:: If testing a pre-release version of PhotonVision with a robot, PhotonLib must be updated to match the version downloaded! If not, packet schema definitions may not match and unexpected things will occur.
|
||||
|
||||
Github Actions builds pre-release version of PhotonVision automatically on PRs and on each commit merged to master. To test a particular commit to master, navigate to the `PhotonVision commit list <https://github.com/PhotonVision/photonvision/commits/master/>`_ and click on the check mark (below). Scroll to "Build / Build fat JAR - PLATFORM", click details, and then summary. From here, JAR and image files can be downloaded to be flashed or uploaded using "Offline Update".
|
||||
|
||||
.. image:: images/gh_actions_1.png
|
||||
:alt: Github Actions Badge
|
||||
|
||||
.. image:: images/gh_actions_2.png
|
||||
:alt: Github Actions artifact list
|
||||
|
||||
Built JAR files (but not image files) can also be downloaded from PRs before they are merged. Navigate to the PR in GitHub, and select Checks at the top. Click on "Build" to display the same artifact list as above.
|
||||
|
||||
.. image:: images/gh_actions_3.png
|
||||
:alt: Github Actions artifacts from PR
|
||||
42
docs/source/docs/installation/wiring.rst
Normal file
@@ -0,0 +1,42 @@
|
||||
Wiring
|
||||
======
|
||||
|
||||
|
||||
Off-Robot Wiring
|
||||
----------------
|
||||
|
||||
Plugging your coprocessor into the wall via a power brick will suffice for off robot wiring.
|
||||
|
||||
.. note:: Please make sure your chosen power supply can provide enough power for your coprocessor. Undervolting (where enough power isn't being supplied) can cause many issues.
|
||||
|
||||
|
||||
On-Robot Wiring
|
||||
---------------
|
||||
|
||||
.. note:: We recommend users use the `SnakeEyes Pi Hat <https://www.playingwithfusion.com/productview.php?pdid=133>`_ as it provides passive power over ethernet (POE) and other useful features to simplify wiring and make your life easier.
|
||||
|
||||
Recommended: Coprocessor with Passive POE (Gloworm, Pi with SnakeEyes, Limelight)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Plug the `passive POE injector <https://www.revrobotics.com/rev-11-1210/>`_ into the coprocessor and wire it to PDP/PDH (NOT the VRM).
|
||||
|
||||
2. Add a breaker to relevant slot in your PDP/PDH
|
||||
|
||||
3. Run an ethernet cable from the passive POE injector to your network switch / radio (we *STRONGLY* recommend the usage of a network switch, see the `networking <networking.rst>`_ section for more info.)
|
||||
|
||||
Coprocessor without Passive POE
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
1a. Option 1: Get a micro USB (may be USB-C if using a newer Pi) pigtail cable and connect the wire ends to a regulator like `this <https://www.pololu.com/product/4082>`_. Then, wire the regulator into your PDP/PDH and the Micro USB / USB C into your coprocessor.
|
||||
|
||||
1b. Option 2: Use a USB power bank to power your coprocessor. Refer to this year's robot rulebook on legal implementations of this.
|
||||
|
||||
2. Run an ethernet cable from your Pi to your network switch / radio (we *STRONGLY* recommend the usage of a network switch, see the `networking <networking.rst>`_ section for more info.)
|
||||
|
||||
This diagram shows how to use the recommended regulator to power a coprocessor.
|
||||
|
||||
.. image:: images/pololu-diagram.png
|
||||
:alt: A flowchart-type diagram showing how to connect wires from the PDP or PDH to the recommended voltage regulator and then a Coprocessor.
|
||||
|
||||
.. note:: The regulator comes with optional screw terminals that may be used to connect the PDP/PDH and Coprocessor power wires if you do not wish to solder them.
|
||||
|
||||
Once you have wired your coprocessor, you are now ready to install PhotonVision.
|
||||
43
docs/source/docs/integration/advancedStrategies.rst
Normal file
@@ -0,0 +1,43 @@
|
||||
Advanced Strategies
|
||||
===================
|
||||
|
||||
Advanced strategies for using vision processing results involve working with the robot's *pose* on the field. A *pose* is a combination an X/Y coordinate, and an angle describing where the robot's front is pointed. It is always considered *relative* to some fixed point on the field.
|
||||
|
||||
WPILib provides a `Pose2d <https://docs.wpilib.org/en/stable/docs/software/advanced-controls/geometry/pose.html>`_ class to describe poses in software.
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
------------------------------
|
||||
|
||||
- A Coprocessor running PhotonVision
|
||||
- Accurate camera calibration to support "3D mode" required
|
||||
- A Drivetrain with wheels and sensors
|
||||
- Sufficient sensors to measure wheel rotation
|
||||
- Capable of closed-loop velocity control
|
||||
- A gyroscope or IMU measuring actual robot heading
|
||||
- Experience using some path-planning library (WPILib is our recommendation)
|
||||
|
||||
Path Planning in a Target-Centered Reference Frame
|
||||
--------------------------------------------------
|
||||
|
||||
When using 3D mode in PhotonVision, the `SolvePNP Algorithm <https://en.wikipedia.org/wiki/Perspective-n-Point>`_ is used to deduce the *camera\'s* position in a 3D coordinate system centered on the target itself.
|
||||
|
||||
A simple algorithm for using this measurement is:
|
||||
|
||||
#. Assume your robot needs to be at a fixed ``Pose2D`` *relative to the target*.
|
||||
#. When triggered:
|
||||
#. Read the most recent vision measurement - this is your *actual* pose.
|
||||
#. Generate a simple trajectory to the goal position
|
||||
#. Execute the trajectory
|
||||
|
||||
.. note:: There is not currently an example demonstrating this technique.
|
||||
|
||||
Global Pose Estimation
|
||||
----------------------
|
||||
|
||||
A more complex way to utilize a camera-supplied ``Pose2D`` is to incorporate it into an estimation of the robot's ``Pose2D`` in a global field reference frame.
|
||||
|
||||
When using this strategy, the measurements made by the camera are *fused* with measurements from other sensors, a model of expected robot behavior, and a matrix of weights that describes how trustworthy each sensor is. The result is a *best-guess* at the current pose on the field.
|
||||
|
||||
In turn, this best-guess position is used to path plan to the known positions on the field, which may or may not have vision targets nearby.
|
||||
|
||||
See the :ref:`Pose Estimation <docs/examples/simposeest:Knowledge and Equipment Needed>` example for more information.
|
||||
48
docs/source/docs/integration/aprilTagStrategies.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
AprilTag Strategies
|
||||
====================
|
||||
|
||||
.. note:: The same strategies covered in the simple and advanced strategy sections still apply to AprilTags, and we encourage you to read them first. This page will discuss the specific nuances to using AprilTags.
|
||||
|
||||
Simple Strategies
|
||||
-----------------
|
||||
|
||||
Prior to the introduction of AprilTags, the most common vision strategy for teams was to use the yaw of the detected target in order to turn to the target, and then score. This is still possible with AprilTags as the yaw of the tag is reported. Similarly, getting the distance to the target via trigonometry will also work. This is discussed in greater detail in the previous page.
|
||||
|
||||
Advanced Strategies
|
||||
-------------------
|
||||
AprilTags allows you find the robot pose on the field using data from the tags. A pose is a combination an X/Y coordinate, and an angle describing where the robot’s front is pointed. It is always considered relative to some fixed point on the field.
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Knowledge
|
||||
|
||||
* How to tune an AprilTag Pipeline (found in the pipeline tuning section)
|
||||
|
||||
Equipment
|
||||
|
||||
* A Coprocessor running PhotonVision - Accurate camera calibration to support “3D mode” required
|
||||
|
||||
* A Drivetrain with wheels and sensors (Sufficient sensors to measure wheel rotation and capable of closed-loop velocity control)
|
||||
|
||||
* A gyroscope or IMU measuring actual robot heading
|
||||
|
||||
Global Pose Estimation / Pose Estimation Strategies
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note:: See the previous page for more general information. Most of the information is the same except now the camera is supplying a ``Pose3D``.
|
||||
|
||||
The nature of how AprilTags will be laid out makes it very likely that you will get multiple pose measurements within a single frame from seeing multiple targets. This requires strategies to fuse these observations together and get a "best guess" as to where your robot is. The best way to do this is to use the corners from all visible AprilTags to estimate the robot's pose. This is done by using the ``PhotonPoseEstimator`` class and the "MULTI_TAG_PNP_ON_COPROCESSOR" strategy. Additional strategies include:
|
||||
|
||||
* A camera seeing multiple targets, taking the average of all the returned poses
|
||||
* A camera seeing one target, with an assumed height off the ground, picking the pose which places it to the assumed height
|
||||
* A camera seeing one target, and picking a pose most similar to the most recently observed pose
|
||||
* A camera seeing one target, and picking a pose most similar to one provided externally (ie, from previous loop's odometry)
|
||||
* A camera seeing one target, and picking the pose with the lowest ambiguity.
|
||||
|
||||
PhotonVision supports all of these different strategies via our ``PhotonPoseEstimator`` class that allows you to select one of the strategies above and get the relevant pose estimation.
|
||||
|
||||
Tuning Pose Estimators
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Coming soon!
|
||||
TODO: Add this back in once simposeest example is added.
|
||||
21
docs/source/docs/integration/background.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
Vision - Robot Integration Background
|
||||
=====================================
|
||||
|
||||
Vision Processing's Purpose
|
||||
---------------------------
|
||||
|
||||
Each year, the FRC game requires a fundamental operation: **Align the Robot to a Goal**.
|
||||
|
||||
Regardless of whether that alignment point is for picking up gamepieces, or for scoring, fast and effective robots must be able to align to them quickly and repeatably.
|
||||
|
||||
Software strategies can be used to help augment the ability of a human operator, or step in when a human operator is not allowed to control the robot.
|
||||
|
||||
*Vision Processing* is one key *input* to these software strategies. However, the inputs your coprocessor provides must be interpreted and converted (ultimately) to motor voltage commands.
|
||||
|
||||
There are many valid strategies for doing this transformation. Picking a strategy is a balancing act between:
|
||||
|
||||
1. Available team resources (time, programming skills, previous experience)
|
||||
2. Precision of alignment required
|
||||
3. Team willingness to take on risk
|
||||
|
||||
Simple strategies are low-risk - they require comparatively little effort to implement and tune, but have hard limits on the complexity of motion they can control on the robot. Advanced methods allow for more complex and precise movement, but take more effort to implement and tune. For this reason, it is more risky to attempt to use them.
|
||||
10
docs/source/docs/integration/index.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
Robot Integration
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
background
|
||||
simpleStrategies
|
||||
advancedStrategies
|
||||
aprilTagStrategies
|
||||
40
docs/source/docs/integration/simpleStrategies.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
Simple Strategies
|
||||
=================
|
||||
|
||||
Simple strategies for using vision processor outputs involve using the target's position in the 2D image to infer *range* and *angle* to the target.
|
||||
|
||||
Knowledge and Equipment Needed
|
||||
------------------------------
|
||||
|
||||
- A Coprocessor running PhotonVision
|
||||
- A Drivetrain with wheels
|
||||
|
||||
Angle Alignment
|
||||
---------------
|
||||
|
||||
The simplest way to use a vision processing result is to first determine how far left or right in the image the vision target should be for your robot to be "aligned" to the target. Then,
|
||||
|
||||
1. Read the current angle to the target from the vision Coprocessor.
|
||||
2. If too far in one direction, command the drivetrain to rotate in the opposite direction to compensate.
|
||||
|
||||
See the :ref:`Aiming at a Target <docs/examples/aimingatatarget:Knowledge and Equipment Needed>` example for more information.
|
||||
|
||||
.. note:: Sometimes, these strategies have also involved incorporating a gyroscope. This can be necessary due to the high latency of vision processing algorithms. However, advancements in the tools available (including PhotonVision) has made that unnecessary for most applications.
|
||||
|
||||
Range Alignment
|
||||
---------------
|
||||
|
||||
By looking at the position of the target in the "vertical" direction in the image, and applying some trionometery, the distance between the robot and the camera can be deduced.
|
||||
|
||||
1. Read the current distance to the target from the vision coprocessor.
|
||||
2. If too far in one direction, command the drivetrain to travel in the opposite direction to compensate.
|
||||
|
||||
See the :ref:`Getting in Range of the Target <docs/examples/gettinginrangeofthetarget:Knowledge and Equipment Needed>` example for more information.
|
||||
|
||||
|
||||
Angle + Range
|
||||
-------------
|
||||
|
||||
Since the previous two alignment strategies work on independent axes of the robot, there's no reason you can't do them simultaneously.
|
||||
|
||||
See the :ref:`Aim and Range <docs/examples/aimandrange:Knowledge and Equipment Needed>` example for more information.
|
||||
48
docs/source/docs/objectDetection/about-object-detection.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
About Object Detection
|
||||
======================
|
||||
|
||||
How does it work?
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
PhotonVision supports object detection using neural network accelerator hardware built into Orange Pi 5/5+ coprocessors. The Neural Processing Unit, or NPU, is `used by PhotonVision <https://github.com/PhotonVision/rknn_jni/tree/main>`_ to massively accelerate certain math operations like those needed for running ML-based object detection.
|
||||
|
||||
For the 2024 season, PhotonVision ships with a **pre-trained NOTE detector** (shown above), as well as a mechanism for swapping in custom models. Future development will focus on enabling lower friction management of multiple custom models.
|
||||
|
||||
.. image:: images/notes-ui.png
|
||||
|
||||
Tracking Objects
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Before you get started with object detection, 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 “Object Detection” type. You should see a screen similar to the image above.
|
||||
|
||||
PhotonVision currently ships with a NOTE detector based on a `YOLOv5 model <https://docs.ultralytics.com/yolov5/>`_. This model is trained to detect one or more object "classes" (such as cars, stoplights, or in our case, NOTES) in an input image. For each detected object, the model outputs a bounding box around where in the image the object is located, what class the object belongs to, and a unitless confidence between 0 and 1.
|
||||
|
||||
.... note:: This model output means that while its fairly easy to say that "this rectangle probably contains a NOTE", we don't have any information about the NOTE's orientation or location. Further math in user code would be required to make estimates about where an object is physically located relative to the camera.
|
||||
|
||||
Tuning and Filtering
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Compared to other pipelines, object detection exposes very few tuning handles. The Confidence slider changes the minimum confidence that the model needs to have in a given detection to consider it valid, as a number between 0 and 1 (with 0 meaning completely uncertain and 1 meaning maximally certain).
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<video width="85%" controls>
|
||||
<source src="../../_static/assets/objdetectFiltering.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
The same area, aspect ratio, and target orientation/sort parameters from :ref:`reflective pipelines <docs/reflectiveAndShape/contour-filtering:Reflective>` are also exposed in the object detection card.
|
||||
|
||||
Training Custom Models
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Coming soon!
|
||||
|
||||
Uploading Custom Models
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning:: PhotonVision currently ONLY supports YOLOv5 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.
|
||||
|
||||
Our `pre-trained NOTE model <https://github.com/PhotonVision/photonvision/blob/master/photon-server/src/main/resources/models/note-640-640-yolov5s.rknn>`_ is automatically extracted from the JAR when PhotonVision starts, only if a file named “note-640-640-yolov5s.rknn” and "labels.txt" does not exist in the folder ``photonvision_config/models/``. This technically allows power users to replace the model and label files with new ones without rebuilding Photon from source and uploading a new JAR.
|
||||
|
||||
Use a program like WinSCP or FileZilla to access your coprocessor's filesystem, and copy the new ``.rknn`` model file into /home/pi. Next, SSH into the coprocessor and ``sudo mv /path/to/new/model.rknn /opt/photonvision/photonvision_config/models/note-640-640-yolov5s.rknn``. Repeat this process with the labels file, which should contain one line per label the model outputs with no training newline. Next, restart PhotonVision via the web UI.
|
||||
BIN
docs/source/docs/objectDetection/images/notes-ui.png
Normal file
|
After Width: | Height: | Size: 358 KiB |
8
docs/source/docs/objectDetection/index.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
Object Detection
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 0
|
||||
:titlesonly:
|
||||
|
||||
about-object-detection
|
||||
52
docs/source/docs/pipelines/about-pipelines.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
:orphan:
|
||||
|
||||
About Pipelines
|
||||
===============
|
||||
|
||||
What is a pipeline?
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A vision pipeline represents a series of steps that are used to acquire an image, process it, and analyzing it to find a target. In most FRC games, this means processing an image in order to detect a piece of retroreflective tape or an AprilTag.
|
||||
|
||||
Types of Pipelines
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Reflective
|
||||
----------
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
----------------
|
||||
|
||||
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.
|
||||
|
||||
.. note:: In order to get 3D Pose data about AprilTags, you are required to :ref:`calibrate your camera<docs/calibration/calibration:Calibrating Your Camera>`.
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^
|
||||
Reflective and Colored Shape Pipelines have 4 steps (represented as 4 tabs):
|
||||
|
||||
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.
|
||||
|
||||
AprilTag / AruCo Pipelines have 3 steps:
|
||||
|
||||
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.
|
||||
BIN
docs/source/docs/pipelines/images/motionblur.gif
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
docs/source/docs/pipelines/images/pipelinetype.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
8
docs/source/docs/pipelines/index.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
Pipelines
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
|
||||
about-pipelines
|
||||
input
|
||||
output
|
||||
47
docs/source/docs/pipelines/input.rst
Normal file
@@ -0,0 +1,47 @@
|
||||
Camera Tuning / Input
|
||||
=====================
|
||||
|
||||
PhotonVision's "Input" tab contains settings that affect the image captured by the currently selected camera. This includes camera exposure and brightness, as well as resolution and orientation.
|
||||
|
||||
Resolution
|
||||
----------
|
||||
|
||||
Resolution changes the resolution of the image captured. While higher resolutions are often more accurate than lower resolutions, they also run at a slower update rate.
|
||||
|
||||
When using the reflective/colored shape pipeline, detection should be run as low of a resolution as possible as you are only trying to detect simple contours (essentially colored blobs).
|
||||
|
||||
When using the AprilTag pipeline, you should try to use as high of a resolution as you can while still maintaining a reasonable FPS measurement. This is because higher resolution allows you to detect tags with higher accuracy and from larger distances.
|
||||
|
||||
Exposure and brightness
|
||||
-----------------------
|
||||
|
||||
Camera exposure and brightness control how bright the captured image will be, although they function differently. Camera exposure changes how long the camera shutter lets in light, which changes the overall brightness of the captured image. This is in contrast to brightness, which is a post-processing effect that boosts the overall brightness of the image at the cost of desaturating colors (making colors look less distinct).
|
||||
|
||||
.. important:: For all pipelines, exposure time should be set as low as possible while still allowing for the target to be reliably tracked. This allows for faster processing as decreasing exposure will increase your camera FPS.
|
||||
|
||||
For reflective pipelines, after adjusting exposure and brightness, the target should be lit green (or the color of the vision tracking LEDs used). The more distinct the color of the target, the more likely it will be tracked reliably.
|
||||
|
||||
.. note:: Unlike with retroreflective tape, AprilTag tracking is not very dependent on lighting consistency. If you have trouble detecting tags due to low light, you may want to try increasing exposure, but this will likely decrease your achievable framerate.
|
||||
|
||||
|
||||
AprilTags and Motion Blur
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For AprilTag pipelines, your goal is 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
|
||||
|
||||
Orientation
|
||||
-----------
|
||||
|
||||
Orientation can be used to rotate the image prior to vision processing. This can be useful for cases where the camera is not oriented parallel to the ground. Do note that this operation can in some cases significantly reduce FPS.
|
||||
|
||||
Stream Resolution
|
||||
-----------------
|
||||
|
||||
This changes the resolution which is used to stream frames from PhotonVision. This does not change the resolution used to perform vision processing. This is useful to reduce bandwidth consumption on the field. In some high-resolution cases, decreasing stream resolution can increase processing FPS.
|
||||
25
docs/source/docs/pipelines/output.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Output
|
||||
======
|
||||
|
||||
The output card contains sections for target manipulation and offset modes.
|
||||
|
||||
Target Manipulation
|
||||
-------------------
|
||||
|
||||
In this section, the Target Offset Point changes where the "center" of the target is. This can be useful if the pitch/yaw of the middle of the top edge of the target is desired, rather than the center of mass of the target. The "top"/"bottom"/"left"/"right" of the target are defined by the Target Orientation selection. For example, a 400x200px target in landscape mode would have the "top" offset point located at the middle of the uppermost long edge of the target, while in portrait mode the "top" offset point would be located in the middle of the topmost short edge (in this case, either the left or right sides).
|
||||
|
||||
This section also includes a switch to enable processing and sending multiple targets, up to 5, simultaneously. This information is available through PhotonLib. Note that the :code:`GetPitch`/:code:`GetYaw` methods will report the pitch/yaw of the "best" (lowest indexed) target.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<video width="85%" controls>
|
||||
<source src="../../_static/assets/offsetandmultiple.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
Robot Offset
|
||||
------------
|
||||
|
||||
PhotonVision offers both single and dual point offset modes. In single point mode, the "Take Point" button will set the crosshair location to the center of the current "best" target.
|
||||
|
||||
In dual point mode, two snapshots are required. Take one snapshot with the target far away, and the other with the target closer. The position of the crosshair will be linearly interpolated between these two points based on the area of the current "best" target. This might be useful if single point is not accurate across the range of the tracking distance, or for significantly offset cameras.
|
||||
9
docs/source/docs/programming/index.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
:orphan:
|
||||
|
||||
Programming Reference
|
||||
=====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
photonlib/index
|
||||
37
docs/source/docs/programming/photonlib/adding-vendordep.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Installing PhotonLib
|
||||
====================
|
||||
|
||||
What is PhotonLib?
|
||||
------------------
|
||||
PhotonLib is the C++ and Java vendor dependency that accompanies PhotonVision. We created this vendor dependency to make it easier for teams to retrieve vision data from their integrated vision system.
|
||||
|
||||
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.
|
||||
|
||||
.. image:: images/adding-offline-library.png
|
||||
|
||||
Paste the following URL into the box that pops up:
|
||||
|
||||
``https://maven.photonvision.org/repository/internal/org/photonvision/photonlib-json/1.0/photonlib-json-1.0.json``
|
||||
|
||||
.. 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.
|
||||
|
||||
Offline Install - Java/C++
|
||||
--------------------------
|
||||
This installation option is currently a work-in-progress. For now, we recommend users use the online installation method.
|
||||
|
||||
Install - Python
|
||||
----------------
|
||||
Add photonlibpy to `pyproject.toml`.
|
||||
|
||||
.. code-block:: toml
|
||||
|
||||
# Other pip packages to install
|
||||
requires = [
|
||||
"photonlibpy",
|
||||
]
|
||||
|
||||
See `The WPILib/RobotPy docs <https://docs.wpilib.org/en/stable/docs/software/python/pyproject_toml.html>`_ for more information on using `pyproject.toml.`
|
||||
14
docs/source/docs/programming/photonlib/controlling-led.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
Controlling LEDs
|
||||
=================
|
||||
You can control the vision LEDs of supported hardware via PhotonLib using the ``setLED()`` method on a ``PhotonCamera`` instance. In Java and C++, an ``VisionLEDMode`` enum class is provided to choose values from. These values include, ``kOff``, ``kOn``, ``kBlink``, and ``kDefault``. ``kDefault`` uses the default LED value from the selected pipeline.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Blink the LEDs.
|
||||
camera.setLED(VisionLEDMode.kBlink);
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Blink the LEDs.
|
||||
camera.SetLED(photonlib::VisionLEDMode::kBlink);
|
||||
@@ -0,0 +1,53 @@
|
||||
Driver Mode and Pipeline Index/Latency
|
||||
======================================
|
||||
|
||||
After :ref:`creating a PhotonCamera <docs/programming/photonlib/getting-target-data:Constructing a PhotonCamera>`, one can toggle Driver Mode and change the Pipeline Index of the vision program from robot code.
|
||||
|
||||
Toggle Driver Mode
|
||||
------------------
|
||||
You can use the ``setDriverMode()``/``SetDriverMode()`` (Java and C++ respectively) to toggle driver mode from your robot program. Driver mode is an unfiltered / normal view of the camera to be used while driving the robot.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
// Set driver mode to on.
|
||||
camera.setDriverMode(true);
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
// Set driver mode to on.
|
||||
camera.SetDriverMode(true);
|
||||
|
||||
Setting the Pipeline Index
|
||||
--------------------------
|
||||
You can use the ``setPipelineIndex()``/``SetPipelineIndex()`` (Java and C++ respectively) to dynamically change the vision pipeline from your robot program.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
// Change pipeline to 2
|
||||
camera.setPipelineIndex(2);
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
// Change pipeline to 2
|
||||
camera.SetPipelineIndex(2);
|
||||
|
||||
Getting the Pipeline Latency
|
||||
----------------------------
|
||||
You can also get the pipeline latency from a pipeline result using the ``getLatencyMillis()``/``GetLatency()`` (Java and C++ respectively) methods on a ``PhotonPipelineResult``.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Get the pipeline latency.
|
||||
double latencySeconds = result.getLatencyMillis() / 1000.0;
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Get the pipeline latency.
|
||||
units::second_t latency = result.GetLatency();
|
||||
|
||||
.. note:: The C++ version of PhotonLib returns the latency in a unit container. For more information on the Units library, see `here <https://docs.wpilib.org/en/stable/docs/software/basic-programming/cpp-units.html>`_.
|
||||
241
docs/source/docs/programming/photonlib/getting-target-data.rst
Normal file
@@ -0,0 +1,241 @@
|
||||
Getting Target Data
|
||||
===================
|
||||
|
||||
Constructing a PhotonCamera
|
||||
---------------------------
|
||||
|
||||
What is a PhotonCamera?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
``PhotonCamera`` is a class in PhotonLib that allows a user to interact with one camera that is connected to hardware that is running PhotonVision. Through this class, users can retrieve yaw, pitch, roll, robot-relative pose, latency, and a wealth of other information.
|
||||
|
||||
|
||||
The ``PhotonCamera`` class has two constructors: one that takes a ``NetworkTable`` and another that takes in the name of the network table that PhotonVision is broadcasting information over. For ease of use, it is recommended to use the latter. The name of the NetworkTable (for the string constructor) should be the same as the camera's nickname (from the PhotonVision UI).
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-java-examples/src/main/java/org/photonlib/examples/aimattarget/Robot.java
|
||||
:language: java
|
||||
:lines: 51-52
|
||||
|
||||
.. rli:: https://github.com/PhotonVision/photonvision/raw/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-cpp-examples/src/main/cpp/examples/aimattarget/include/Robot.h
|
||||
:language: c++
|
||||
:lines: 42-43
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Change this to match the name of your camera as shown in the web ui
|
||||
self.camera = PhotonCamera("your_camera_name_here")
|
||||
|
||||
|
||||
.. warning:: Teams must have unique names for all of their cameras regardless of which coprocessor they are attached to.
|
||||
|
||||
Getting the Pipeline Result
|
||||
---------------------------
|
||||
|
||||
What is a Photon Pipeline Result?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
A ``PhotonPipelineResult`` is a container that contains all information about currently detected targets from a ``PhotonCamera``. You can retrieve the latest pipeline result using the PhotonCamera instance.
|
||||
|
||||
Use the ``getLatestResult()``/``GetLatestResult()`` (Java and C++ respectively) to obtain the latest pipeline result. An advantage of using this method is that it returns a container with information that is guaranteed to be from the same timestamp. This is important if you are using this data for latency compensation or in an estimator.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
|
||||
.. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-java-examples/src/main/java/org/photonlib/examples/aimattarget/Robot.java
|
||||
:language: java
|
||||
:lines: 79-80
|
||||
|
||||
.. rli:: https://github.com/PhotonVision/photonvision/raw/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-cpp-examples/src/main/cpp/examples/aimattarget/cpp/Robot.cpp
|
||||
:language: c++
|
||||
:lines: 35-36
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Query the latest result from PhotonVision
|
||||
result = self.camera.getLatestResult()
|
||||
|
||||
|
||||
|
||||
.. note:: Unlike other vision software solutions, using the latest result guarantees that all information is from the same timestamp. This is achievable because the PhotonVision backend sends a byte-packed string of data which is then deserialized by PhotonLib to get target data. For more information, check out the `PhotonLib source code <https://github.com/PhotonVision/photonvision/tree/master/photon-lib>`_.
|
||||
|
||||
|
||||
|
||||
Checking for Existence of Targets
|
||||
---------------------------------
|
||||
Each pipeline result has a ``hasTargets()``/``HasTargets()`` (Java and C++ respectively) method to inform the user as to whether the result contains any targets.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Check if the latest result has any targets.
|
||||
boolean hasTargets = result.hasTargets();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Check if the latest result has any targets.
|
||||
bool hasTargets = result.HasTargets();
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Check if the latest result has any targets.
|
||||
hasTargets = result.hasTargets()
|
||||
|
||||
.. 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.
|
||||
|
||||
|
||||
Getting a List of Targets
|
||||
-------------------------
|
||||
|
||||
What is a Photon Tracked Target?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
A tracked target contains information about each target from a pipeline result. This information includes yaw, pitch, area, and robot relative pose.
|
||||
|
||||
|
||||
You can get a list of tracked targets using the ``getTargets()``/``GetTargets()`` (Java and C++ respectively) method from a pipeline result.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Get a list of currently tracked targets.
|
||||
List<PhotonTrackedTarget> targets = result.getTargets();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Get a list of currently tracked targets.
|
||||
wpi::ArrayRef<photonlib::PhotonTrackedTarget> targets = result.GetTargets();
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Get a list of currently tracked targets.
|
||||
targets = result.getTargets()
|
||||
|
||||
Getting the Best Target
|
||||
-----------------------
|
||||
You can get the :ref:`best target <docs/reflectiveAndShape/contour-filtering:Contour Grouping and Sorting>` using ``getBestTarget()``/``GetBestTarget()`` (Java and C++ respectively) method from the pipeline result.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Get the current best target.
|
||||
PhotonTrackedTarget target = result.getBestTarget();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Get the current best target.
|
||||
photonlib::PhotonTrackedTarget target = result.GetBestTarget();
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# TODO - Not currently supported
|
||||
|
||||
|
||||
Getting Data From A Target
|
||||
--------------------------
|
||||
* double ``getYaw()``/``GetYaw()``: The yaw of the target in degrees (positive right).
|
||||
* 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).
|
||||
* double[] ``getCorners()``/``GetCorners()``: The 4 corners of the minimum bounding box rectangle.
|
||||
* Transform2d ``getCameraToTarget()``/``GetCameraToTarget()``: The camera to target transform. See `2d transform documentation here <https://docs.wpilib.org/en/latest/docs/software/advanced-controls/geometry/transformations.html#transform2d-and-twist2d>`_.
|
||||
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Get information from target.
|
||||
double yaw = target.getYaw();
|
||||
double pitch = target.getPitch();
|
||||
double area = target.getArea();
|
||||
double skew = target.getSkew();
|
||||
Transform2d pose = target.getCameraToTarget();
|
||||
List<TargetCorner> corners = target.getCorners();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Get information from target.
|
||||
double yaw = target.GetYaw();
|
||||
double pitch = target.GetPitch();
|
||||
double area = target.GetArea();
|
||||
double skew = target.GetSkew();
|
||||
frc::Transform2d pose = target.GetCameraToTarget();
|
||||
wpi::SmallVector<std::pair<double, double>, 4> corners = target.GetCorners();
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Get information from target.
|
||||
yaw = target.getYaw()
|
||||
pitch = target.getPitch()
|
||||
area = target.getArea()
|
||||
skew = target.getSkew()
|
||||
pose = target.getCameraToTarget()
|
||||
corners = target.getDetectedCorners()
|
||||
|
||||
Getting AprilTag Data From A Target
|
||||
-----------------------------------
|
||||
.. note:: All of the data above (**except skew**) is available when using AprilTags.
|
||||
|
||||
* int ``getFiducialId()``/``GetFiducialId()``: The ID of the detected fiducial marker.
|
||||
* double ``getPoseAmbiguity()``/``GetPoseAmbiguity()``: How ambiguous the pose of the target is (see below).
|
||||
* Transform3d ``getBestCameraToTarget()``/``GetBestCameraToTarget()``: Get the transform that maps camera space (X = forward, Y = left, Z = up) to object/fiducial tag space (X forward, Y left, Z up) with the lowest reprojection error.
|
||||
* Transform3d ``getAlternateCameraToTarget()``/``GetAlternateCameraToTarget()``: Get the transform that maps camera space (X = forward, Y = left, Z = up) to object/fiducial tag space (X forward, Y left, Z up) with the highest reprojection error.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Get information from target.
|
||||
int targetID = target.getFiducialId();
|
||||
double poseAmbiguity = target.getPoseAmbiguity();
|
||||
Transform3d bestCameraToTarget = target.getBestCameraToTarget();
|
||||
Transform3d alternateCameraToTarget = target.getAlternateCameraToTarget();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Get information from target.
|
||||
int targetID = target.GetFiducialId();
|
||||
double poseAmbiguity = target.GetPoseAmbiguity();
|
||||
frc::Transform3d bestCameraToTarget = target.getBestCameraToTarget();
|
||||
frc::Transform3d alternateCameraToTarget = target.getAlternateCameraToTarget();
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Get information from target.
|
||||
targetID = target.getFiducialId()
|
||||
poseAmbiguity = target.getPoseAmbiguity()
|
||||
bestCameraToTarget = target.getBestCameraToTarget()
|
||||
alternateCameraToTarget = target.getAlternateCameraToTarget()
|
||||
|
||||
Saving Pictures to File
|
||||
-----------------------
|
||||
A ``PhotonCamera`` can save still images from the input or output video streams to file. This is useful for debugging what a camera is seeing while on the field and confirming targets are being identified properly.
|
||||
|
||||
Images are stored within the PhotonVision configuration directory. Running the "Export" operation in the settings tab will download a .zip file which contains the image captures.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
// Capture pre-process camera stream image
|
||||
camera.takeInputSnapshot();
|
||||
|
||||
// Capture post-process camera stream image
|
||||
camera.takeOutputSnapshot();
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
// Capture pre-process camera stream image
|
||||
camera.TakeInputSnapshot();
|
||||
|
||||
// Capture post-process camera stream image
|
||||
camera.TakeOutputSnapshot();
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Capture pre-process camera stream image
|
||||
camera.takeInputSnapshot()
|
||||
|
||||
# Capture post-process camera stream image
|
||||
camera.takeOutputSnapshot()
|
||||
|
||||
.. note:: Saving images to file takes a bit of time and uses up disk space, so doing it frequently is not recommended. In general, the camera will save an image every 500ms. Calling these methods faster will not result in additional images. Consider tying image captures to a button press on the driver controller, or an appropriate point in an autonomous routine.
|
||||
|
After Width: | Height: | Size: 18 KiB |
12
docs/source/docs/programming/photonlib/index.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
PhotonLib: Robot Code Interface
|
||||
===============================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
adding-vendordep
|
||||
getting-target-data
|
||||
using-target-data
|
||||
robot-pose-estimator
|
||||
driver-mode-pipeline-index
|
||||
controlling-led
|
||||
113
docs/source/docs/programming/photonlib/robot-pose-estimator.rst
Normal file
@@ -0,0 +1,113 @@
|
||||
AprilTags and PhotonPoseEstimator
|
||||
=================================
|
||||
|
||||
.. note:: 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.
|
||||
|
||||
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>`_.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// The field from AprilTagFields will be different depending on the game.
|
||||
AprilTagFieldLayout aprilTagFieldLayout = AprilTagFields.k2024Crescendo.loadAprilTagLayoutField();
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// The parameter for LoadAPrilTagLayoutField will be different depending on the game.
|
||||
frc::AprilTagFieldLayout aprilTagFieldLayout = frc::LoadAprilTagLayoutField(frc::AprilTagField::k2024Crescendo);
|
||||
|
||||
|
||||
Creating a ``PhotonPoseEstimator``
|
||||
----------------------------------
|
||||
The PhotonPoseEstimator has a constructor that takes an ``AprilTagFieldLayout`` (see above), ``PoseStrategy``, ``PhotonCamera``, and ``Transform3d``. ``PoseStrategy`` has six 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.
|
||||
* LOWEST_AMBIGUITY
|
||||
* Choose the Pose with the lowest ambiguity.
|
||||
* CLOSEST_TO_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().
|
||||
* CLOSEST_TO_LAST_POSE
|
||||
* 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.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
//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.
|
||||
|
||||
// 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);
|
||||
|
||||
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()``.
|
||||
|
||||
.. 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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Additional ``PhotonPoseEstimator`` Methods
|
||||
------------------------------------------
|
||||
|
||||
``setReferencePose(Pose3d referencePose)``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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.
|
||||
97
docs/source/docs/programming/photonlib/using-target-data.rst
Normal file
@@ -0,0 +1,97 @@
|
||||
Using Target Data
|
||||
=================
|
||||
|
||||
A ``PhotonUtils`` class with helpful common calculations is included within ``PhotonLib`` to aid teams in using target data in order to get positional information on the field. This class contains two methods, ``calculateDistanceToTargetMeters()``/``CalculateDistanceToTarget()`` and ``estimateTargetTranslation2d()``/``EstimateTargetTranslation()`` (Java and C++ respectively).
|
||||
|
||||
Estimating Field Relative Pose with AprilTags
|
||||
---------------------------------------------
|
||||
``estimateFieldToRobotAprilTag(Transform3d cameraToTarget, Pose3d fieldRelativeTagPose, Transform3d cameraToRobot)`` returns your robot's ``Pose3d`` on the field using the pose of the AprilTag relative to the camera, pose of the AprilTag relative to the field, and the transform from the camera to the origin of the robot.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Calculate robot's field relative pose
|
||||
Pose3d robotPose = PhotonUtils.estimateFieldToRobotAprilTag(target.getBestCameraToTarget(), aprilTagFieldLayout.getTagPose(target.getFiducialId()), cameraToRobot);
|
||||
.. code-block:: c++
|
||||
|
||||
//TODO
|
||||
|
||||
Estimating Field Relative Pose (Traditional)
|
||||
--------------------------------------------
|
||||
|
||||
You can get your robot's ``Pose2D`` on the field using various camera data, target yaw, gyro angle, target pose, and camera position. This method estimates the target's relative position using ``estimateCameraToTargetTranslation`` (which uses pitch and yaw to estimate range and heading), and the robot's gyro to estimate the rotation of the target.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Calculate robot's field relative pose
|
||||
Pose2D robotPose = PhotonUtils.estimateFieldToRobot(
|
||||
kCameraHeight, kTargetHeight, kCameraPitch, kTargetPitch, Rotation2d.fromDegrees(-target.getYaw()), gyro.getRotation2d(), targetPose, cameraToRobot);
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Calculate robot's field relative pose
|
||||
frc::Pose2D robotPose = photonlib::EstimateFieldToRobot(
|
||||
kCameraHeight, kTargetHeight, kCameraPitch, kTargetPitch, frc::Rotation2d(units::degree_t(-target.GetYaw())), frc::Rotation2d(units::degree_t(gyro.GetRotation2d)), targetPose, cameraToRobot);
|
||||
|
||||
|
||||
Calculating Distance to Target
|
||||
------------------------------
|
||||
If your camera is at a fixed height on your robot and the height of the target is fixed, you can calculate the distance to the target based on your camera's pitch and the pitch to the target.
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
|
||||
.. rli:: https://github.com/PhotonVision/photonvision/raw/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-java-examples/src/main/java/org/photonlib/examples/getinrange/Robot.java
|
||||
:language: java
|
||||
:lines: 78-94
|
||||
|
||||
.. rli:: https://github.com/PhotonVision/photonvision/raw/a3bcd3ac4f88acd4665371abc3073bdbe5effea8/photonlib-cpp-examples/src/main/cpp/examples/getinrange/cpp/Robot.cpp
|
||||
:language: cpp
|
||||
:lines: 33-46
|
||||
|
||||
.. note:: The C++ version of PhotonLib uses the Units library. For more information, see `here <https://docs.wpilib.org/en/stable/docs/software/basic-programming/cpp-units.html>`_.
|
||||
|
||||
Calculating Distance Between Two Poses
|
||||
--------------------------------------
|
||||
``getDistanceToPose(Pose2d robotPose, Pose2d targetPose)`` allows you to calculate the distance between two poses. This is useful when using AprilTags, given that there may not be an AprilTag directly on the target.
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
double distanceToTarget = PhotonUtils.getDistanceToPose(robotPose, targetPose);
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
//TODO
|
||||
|
||||
Estimating Camera Translation to Target
|
||||
---------------------------------------
|
||||
You can get a `translation <https://docs.wpilib.org/en/latest/docs/software/advanced-controls/geometry/pose.html#translation>`_ to the target based on the distance to the target (calculated above) and angle to the target (yaw).
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
// Calculate a translation from the camera to the target.
|
||||
Translation2d translation = PhotonUtils.estimateCameraToTargetTranslation(
|
||||
distanceMeters, Rotation2d.fromDegrees(-target.getYaw()));
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// Calculate a translation from the camera to the target.
|
||||
frc::Translation2d translation = photonlib::PhotonUtils::EstimateCameraToTargetTranslationn(
|
||||
distance, frc::Rotation2d(units::degree_t(-target.GetYaw())));
|
||||
|
||||
.. note:: We are negating the yaw from the camera from CV (computer vision) conventions to standard mathematical conventions. In standard mathematical conventions, as you turn counter-clockwise, angles become more positive.
|
||||
|
||||
Getting the Yaw To a Pose
|
||||
-------------------------
|
||||
``getYawToPose(Pose2d robotPose, Pose2d targetPose)`` returns the ``Rotation2d`` between your robot and a target. This is useful when turning towards an arbitrary target on the field (ex. the center of the hub in 2022).
|
||||
|
||||
.. tab-set-code::
|
||||
.. code-block:: java
|
||||
|
||||
Rotation2d targetYaw = PhotonUtils.getYawToPose(robotPose, targetPose);
|
||||
.. code-block:: c++
|
||||
|
||||
//TODO
|
||||