diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 758b517b9a..15458a4bd6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,8 @@ jobs: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force + - name: Install RoboRIO Toolchain + run: ./gradlew installRoboRioToolchain - name: Install Java 17 uses: actions/setup-java@v4 with: @@ -158,14 +160,14 @@ jobs: - run: git fetch --tags --force - run: | chmod +x gradlew - ./gradlew photon-targeting:build photon-lib:build -Pbuildalldesktop -i - - run: ./gradlew photon-lib:publish photon-targeting:publish -Pbuildalldesktop + ./gradlew photon-targeting:build photon-lib:build -i + - run: ./gradlew photon-lib:publish photon-targeting:publish name: Publish env: ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }} if: github.event_name == 'push' && github.repository_owner == 'photonvision' # Copy artifacts to build/outputs/maven - - run: ./gradlew photon-lib:publish photon-targeting:publish -PcopyOfflineArtifacts -Pbuildalldesktop + - run: ./gradlew photon-lib:publish photon-targeting:publish -PcopyOfflineArtifacts - uses: actions/upload-artifact@v4 with: name: maven-${{ matrix.artifact-name }} @@ -218,7 +220,7 @@ jobs: combine: name: Combine needs: [build-photonlib-docker, build-photonlib-host] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 with: @@ -259,11 +261,11 @@ jobs: artifact-name: macOSArm architecture: x64 arch-override: macarm64 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: Linux architecture: x64 arch-override: linuxx64 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 architecture: x64 arch-override: linuxarm64 @@ -317,7 +319,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: jar-Linux extraOpts: -Djdk.lang.Process.launchMechanism=vfork - os: windows-latest @@ -356,10 +358,10 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: RaspberryPi - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-1/photonvision_raspi.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-4/photonvision_raspi.img.xz cpu: cortex-a7 image_additional_mb: 0 extraOpts: -Djdk.lang.Process.launchMechanism=vfork @@ -395,46 +397,52 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: RaspberryPi - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-1/photonvision_raspi.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_raspi.img.xz cpu: cortex-a7 image_additional_mb: 0 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: limelight2 - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-1/photonvision_limelight.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_limelight.img.xz cpu: cortex-a7 image_additional_mb: 0 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: limelight3 - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-1/photonvision_limelight3.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_limelight3.img.xz cpu: cortex-a7 image_additional_mb: 0 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: orangepi5 - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-3/photonvision_opi5.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_opi5.img.xz cpu: cortex-a8 image_additional_mb: 1024 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: orangepi5b - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-3/photonvision_opi5b.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_opi5b.img.xz cpu: cortex-a8 image_additional_mb: 1024 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: orangepi5plus - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-3/photonvision_opi5plus.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_opi5plus.img.xz cpu: cortex-a8 image_additional_mb: 1024 - - os: ubuntu-latest + - os: ubuntu-22.04 artifact-name: LinuxArm64 image_suffix: orangepi5pro - image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-3/photonvision_opi5pro.img.xz + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_opi5pro.img.xz + cpu: cortex-a8 + image_additional_mb: 1024 + - os: ubuntu-latest + artifact-name: LinuxArm64 + image_suffix: orangepi5max + image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/v2025.0.0-beta-6/photonvision_opi5max.img.xz cpu: cortex-a8 image_additional_mb: 1024 @@ -507,10 +515,19 @@ jobs: **/photonlib*.zip if: github.event_name == 'push' # Upload all jars and xz archives - - uses: softprops/action-gh-release@v1 + # Split into two uploads to work around max size limits in action-gh-releases + # https://github.com/softprops/action-gh-release/issues/353 + - uses: softprops/action-gh-release@v2.0.8 with: files: | - **/*.xz + **/*orangepi5*.xz + if: startsWith(github.ref, 'refs/tags/v') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: softprops/action-gh-release@v2.0.8 + with: + files: | + **/!(*orangepi5*).xz **/*.jar **/photonlib*.json **/photonlib*.zip diff --git a/.github/workflows/lint-format.yml b/.github/workflows/lint-format.yml index fb97eb77af..09f86fc6c6 100644 --- a/.github/workflows/lint-format.yml +++ b/.github/workflows/lint-format.yml @@ -37,7 +37,7 @@ jobs: with: python-version: 3.11 - name: Install wpiformat - run: pip3 install wpiformat==2024.37 + run: pip3 install wpiformat==2024.41 - name: Run run: wpiformat - name: Check output diff --git a/.github/workflows/photonvision-docs.yml b/.github/workflows/photonvision-docs.yml index e6cfd80bfb..f0809b1152 100644 --- a/.github/workflows/photonvision-docs.yml +++ b/.github/workflows/photonvision-docs.yml @@ -14,7 +14,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml.d similarity index 100% rename from .github/workflows/python.yml rename to .github/workflows/python.yml.d diff --git a/.gitignore b/.gitignore index 94aa5c90c6..d5386e1e64 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,5 @@ photon-lib/src/generate/native/cpp/PhotonVersion.cpp venv !photon-core/src/main/resources/models.zip +.venv/* +.venv diff --git a/README.md b/README.md index e841f2f328..9f42d5e2b7 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,20 @@ You can run one of the many built in examples straight from the command line, to Note that these are case sensitive! -* `-PArchOverride=foobar`: builds for a target system other than your current architecture. Valid overrides are: - * linuxathena +* `-PArchOverride=foobar`: builds for a target system other than your current architecture. [Valid overrides](https://github.com/wpilibsuite/wpilib-tool-plugin/blob/main/src/main/java/edu/wpi/first/tools/NativePlatforms.java) are: + * winx32 + * winx64 + * winarm64 + * macx64 + * macarm64 + * linuxx64 * linuxarm64 - * arm64 - * x86-64 - * x86 -- `-PtgtIp`: Specifies where `./gradlew deploy` should try to copy the fat JAR to + * linuxathena +- `-PtgtIP`: Specifies where `./gradlew deploy` should try to copy the fat JAR to - `-Pprofile`: enables JVM profiling +If you're cross-compiling, you'll need the wpilib toolchain installed. This can be done via Gradle: for example `./gradlew installArm64Toolchain` or `./gradlew installRoboRioToolchain` + ## Out-of-Source Dependencies PhotonVision uses the following additonal out-of-source repositories for building code. diff --git a/build.gradle b/build.gradle index 9d43a514b4..18aac2cc63 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,15 @@ import edu.wpi.first.toolchain.* plugins { + id "java" + id "cpp" id "com.diffplug.spotless" version "6.24.0" - id "edu.wpi.first.NativeUtils" version "2024.7.2" apply false + id "edu.wpi.first.NativeUtils" version "2024.6.1" apply false id "edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin" version "2020.2" id "edu.wpi.first.GradleRIO" version "2024.3.2" id 'edu.wpi.first.WpilibTools' version '1.3.0' id 'com.google.protobuf' version '0.9.4' apply false + id 'edu.wpi.first.GradleJni' version '1.1.0' } allprojects { @@ -28,12 +31,12 @@ ext.allOutputsFolder = file("$project.buildDir/outputs") apply from: "versioningHelper.gradle" ext { - wpilibVersion = "2025.0.0-alpha-1" + wpilibVersion = "2024.3.2" wpimathVersion = wpilibVersion openCVversion = "4.8.0-2" joglVersion = "2.4.0" javalinVersion = "5.6.2" - libcameraDriverVersion = "dev-v2023.1.0-12-gfb1eafb" + libcameraDriverVersion = "dev-v2023.1.0-14-g787ab59" rknnVersion = "dev-v2024.0.1-4-g0db16ac" frcYear = "2024" mrcalVersion = "dev-v2024.0.0-24-gc1efcf0"; @@ -64,7 +67,7 @@ spotless { java { target fileTree('.') { include '**/*.java' - exclude '**/build/**', '**/build-*/**', "photon-core\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "photon-lib\\src\\main\\java\\org\\photonvision\\PhotonVersion.java" + exclude '**/build/**', '**/build-*/**', "photon-core\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "photon-lib\\src\\main\\java\\org\\photonvision\\PhotonVersion.java", "**/src/generated/**" } toggleOffOn() googleJavaFormat() diff --git a/devTools/calibrationUtils.py b/devTools/calibrationUtils.py index e12b15b250..676382c579 100644 --- a/devTools/calibrationUtils.py +++ b/devTools/calibrationUtils.py @@ -3,7 +3,6 @@ from dataclasses import dataclass import json import os -from typing import Union import cv2 import numpy as np import mrcal diff --git a/docs/source/conf.py b/docs/source/conf.py index 09c6604cc1..dca2301a4d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -36,6 +36,7 @@ "sphinxcontrib.ghcontributors", "sphinx_design", "myst_parser", + "sphinx.ext.mathjax", ] # Configure OpenGraph support diff --git a/docs/source/docs/additional-resources/best-practices.md b/docs/source/docs/additional-resources/best-practices.md index b45ed05628..7dd11ecd0b 100644 --- a/docs/source/docs/additional-resources/best-practices.md +++ b/docs/source/docs/additional-resources/best-practices.md @@ -15,9 +15,9 @@ - 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. + - Point your robot at the AprilTags(s) and ensure you get a consistent tracking (you hold one AprilTag consistently, the ceiling lights aren't detected, etc.). + - If you have problems with your pipeline, go to the pipeline tuning section and retune the pipeline using the guide there. + - Move the robot close, far, angled, and around the field to ensure no extra AprilTags are found. - Go to a practice match to ensure everything is working correctly. - After field calibration, use the "Export Settings" button in the "Settings" page to create a backup. - Do this for each coprocessor on your robot that runs PhotonVision, and name your exports with meaningful names. @@ -26,4 +26,4 @@ - 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. +- Stream at as low of a resolution as possible while still detecting AprilTags to stay within field bandwidth limits. diff --git a/docs/source/docs/apriltag-pipelines/2D-tracking-tuning.md b/docs/source/docs/apriltag-pipelines/2D-tracking-tuning.md index 84e7606119..c9f205eb66 100644 --- a/docs/source/docs/apriltag-pipelines/2D-tracking-tuning.md +++ b/docs/source/docs/apriltag-pipelines/2D-tracking-tuning.md @@ -47,7 +47,7 @@ Pose iterations represents the amount of iterations done in order for the AprilT 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. +We recommend a value of 0 for the 16h5 and at most 3 for the 36h11 family. ### Decision Margin Cutoff diff --git a/docs/source/docs/apriltag-pipelines/multitag.md b/docs/source/docs/apriltag-pipelines/multitag.md index 102b36ce1f..da5169fb04 100644 --- a/docs/source/docs/apriltag-pipelines/multitag.md +++ b/docs/source/docs/apriltag-pipelines/multitag.md @@ -24,7 +24,7 @@ This multi-target pose estimate can be accessed using PhotonLib. We suggest usin ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java var result = camera.getLatestResult(); if (result.getMultiTagResult().estimatedPose.isPresent) { @@ -38,6 +38,11 @@ This multi-target pose estimate can be accessed using PhotonLib. We suggest usin if (result.MultiTagResult().result.isPresent) { frc::Transform3d fieldToCamera = result.MultiTagResult().result.best; } + + .. code-block:: Python + + # Coming Soon! + ``` :::{note} diff --git a/docs/source/docs/calibration/calibration.md b/docs/source/docs/calibration/calibration.md index f9f4782da1..e4e9fb3b3d 100644 --- a/docs/source/docs/calibration/calibration.md +++ b/docs/source/docs/calibration/calibration.md @@ -4,10 +4,10 @@ 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). +To calibrate a camera, images of a Charuco board (or chessboard) are taken. By comparing where the grid corners should be in object space (for example, a corner once every inch in an 8x6 grid) with where they appear in the camera image, we can find a least-squares estimate for intrinsic camera properties like focal lengths, center point, and distortion coefficients. For more on camera calibration, please review the [OpenCV documentation](https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html). :::{warning} -While any resolution can be calibrated, 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. +While any resolution can be calibrated, higher resolutions may be too performance-intensive for some coprocessors to handle. Therefore, we recommend experimenting to see what works best for your coprocessor. ::: :::{note} @@ -18,38 +18,27 @@ The calibration data collected during calibration is specific to each physical c Accurate camera calibration is required in order to get accurate pose measurements when using AprilTags and 3D mode. The tips below should help ensure success: -01. Practice calibration using your laptop webcam and . 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 (i.e., rotated only about an axis going left/right, up/down, or out-of-the-camera). -02. 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. -03. Use as big of a calibration target as your printer can print. -04. Ensure that your printed pattern has enough white border around it. -05. Ensure your camera stays in one position during the duration of the calibration. -06. Make sure you get all 12 images from varying distances and angles. -07. 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. -08. Have good lighting, having a diffusely lit target would be best (light specifically shining on the target without shadows). -09. 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. +01. Ensure your the images you take have the target in different positions and angles, with as big of a difference between angles as possible. It is important to make sure the target overlay still lines up with the board while doing this. Tilt no more than 45 degrees. +02. Use as big of a calibration target as your printer can print. +03. Ensure that your printed pattern has enough white border around it. +04. Ensure your camera stays in one position during the duration of the calibration. +05. Make sure you get all 12 images from varying distances and angles. +06. Take at least one image that covers the total image area, and generally ensure that you get even coverage of the lens with your image set. +07. Have good lighting, having a diffusely lit target would be best (light specifically shining on the target without shadows). +08. Ensure the calibration target is completely flat and does not bend or fold in any way. It should be mounted/taped down to something flat and then used for calibration, do not just hold it up. +09. Avoid having targets that are parallel to the lens of the camera / straight on towards the camera as much as possible. You want angles and variations within your calibration images. Following the ideas above should help in getting an accurate calibration. -## 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. +The Cameras tab of the UI houses PhotonVision's camera calibration tooling. It assists users with calibrating their cameras, as well as allows them to view previously calibrated resolutions. We support both charuco and chessboard calibrations. ### 2. Print out the calibration target. -In the Camera Calibration tab, we'll print out the calibration target using the "Download" button. This should be printed on 8.5x11 printer paper. This page shows using an 8x8 chessboard. +In the Camera Calibration tab, we'll print out the calibration target using the "Download" button. This should be printed on 8.5x11 printer paper. This page shows using an 8x8 charuco board (or chessboard depending on the selected calibration type). :::{warning} Ensure that there is no scaling applied during printing (it should be at 100%) and that the PDF is printed as is on regular printer paper. Check the square size with calipers or an accurate measuring device after printing to ensure squares are sized properly, and enter the true size of the square in the UI text box. For optimal results, various resources are available online to calibrate your specific printer if needed. @@ -57,11 +46,14 @@ Ensure that there is no scaling applied during printing (it should be at 100%) a ### 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." +We'll next select a resolution to calibrate and populate our pattern spacing, marker size, and board size. The provided chessboard and charuco board are an 8x8 grid of 1 inch square. The provided charuco board uses the 4x4 dictionary with a marker size of 0.75 inches (this board does not need the old OpenCV pattern selector selected). Printers are not perfect, and you need to measure your calibration target and enter the correct marker size (size of the aruco marker) and pattern spacing (aka size of the black square) using calipers or similar. Finally, once our entered data is correct, we'll click "start calibration." + +:::{warning} Old OpenCV Pattern selector. This should be used in the case that the calibration image is generated from a version of OpenCV before version 4.6.0. This would include targets created by calib.io. If this selector is not set correctly the calibration will be completely invalid. For more info view [this GitHub issue](https://github.com/opencv/opencv_contrib/issues/3291). +::: ### 4. Take at calibration images from various angles. -Now, we'll capture images of our 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. +Now, we'll capture images of our board from various angles. It's important to check that the board overlay matches the board in your image. The further the overdrawn points are from the true position of the chessboard corners, the less accurate the final calibration will be. We'll want to capture enough images to cover the whole camera's FOV (with a minimum of 12). Once we've got our images, we'll click "Finish calibration" and wait for the calibration process to complete. If all goes well, the mean error and FOVs will be shown in the table on the right. The FOV should be close to the camera's specified FOV (usually found in a datasheet) usually within + or - 10 degrees. The mean error should also be low, usually less than 1 pixel. ```{raw} html ``` -## Contour Simplification +## Contour Simplification (Non-Apriltag) 3D mode internally computes a polygon that approximates the target contour being tracked. This polygon is used to detect the extreme corners of the target. The contour simplification slider changes how far from the original contour the approximation is allowed to deviate. Note that the approximate polygon is drawn on the output image for tuning. diff --git a/docs/source/docs/simulation/hardware-in-the-loop-sim.md b/docs/source/docs/simulation/hardware-in-the-loop-sim.md index b23276b1df..5897d0b910 100644 --- a/docs/source/docs/simulation/hardware-in-the-loop-sim.md +++ b/docs/source/docs/simulation/hardware-in-the-loop-sim.md @@ -2,7 +2,7 @@ Hardware in the loop simulation is using a physical device, such as a supported co-processor running PhotonVision, to enhance simulation capabilities. This is useful for developing and validating code before the camera is attached to a robot, as well as reducing the work required to use WPILib simulation with PhotonVision. -Before continuing, ensure PhotonVision is installed on your target device. Instructions can be found {ref}`here ` for all devices. +Before continuing, ensure PhotonVision is installed on your device. Instructions can be found {ref}`here ` for all devices. Your coprocessor and computer running simulation will have to be connected to the same network, like a home router. Connecting the coprocessor directly to the computer will not work. diff --git a/docs/source/docs/simulation/index.md b/docs/source/docs/simulation/index.md index a63a143a97..a4f007cfee 100644 --- a/docs/source/docs/simulation/index.md +++ b/docs/source/docs/simulation/index.md @@ -4,7 +4,8 @@ :maxdepth: 0 :titlesonly: true -simulation -simulation-deprecated +simulation-java +simulation-cpp +simulation-python hardware-in-the-loop-sim ``` diff --git a/docs/source/docs/simulation/simulation-cpp.md b/docs/source/docs/simulation/simulation-cpp.md new file mode 100644 index 0000000000..ccb28de0be --- /dev/null +++ b/docs/source/docs/simulation/simulation-cpp.md @@ -0,0 +1,5 @@ +# Simulation Support in PhotonLib in C++ + +## What Is Supported? + +Nothing yet. diff --git a/docs/source/docs/simulation/simulation-deprecated.md b/docs/source/docs/simulation/simulation-deprecated.md deleted file mode 100644 index ba7be7e458..0000000000 --- a/docs/source/docs/simulation/simulation-deprecated.md +++ /dev/null @@ -1,103 +0,0 @@ -# Simulation Support in PhotonLib (Deprecated) - -:::{attention} -This page details the pre-2024 simulation support. For current Java simulation support, see {doc}`/docs/simulation/simulation`. -::: - -## What Is Supported? - -PhotonLib supports simulation of a camera and coprocessor running PhotonVision moving about a field on a robot. - -You can use this to help validate your robot code's behavior in simulation without needing a physical robot. - -## Simulation Vision World Model - -Sim-specific classes are provided to model sending one frame of a camera image through PhotonVision. Based on what targets are visible, results are published to NetworkTables. - -While processing, the given robot `Pose2d` is used to analyze which targets should be in view, and determine where they would have shown up in the camera image. - -Targets are considered in view if: - -1. Their centroid is within the field of view of the camera. -2. The camera is not in driver mode. -3. The target's in-image pixel size is greater than `minTargetArea` -4. The distance from the camera to the target is less than `maxLEDRange` - -:::{warning} -Not all network tables objects are updated in simulation. The interaction through PhotonLib remains the same. Actual camera images are also not simulated. -::: - -Latency of processing is not yet modeled. - -```{image} diagrams/SimArchitecture-deprecated.drawio.svg -:alt: A diagram comparing the architecture of a real PhotonVision process to a simulated -: one. -``` - -## Simulated Vision System - -A `SimVisionSystem` represents the camera and coprocessor running PhotonVision moving around on the field. - -It requires a number of pieces of configuration to accurately simulate your physical setup. Match them to your configuration in PhotonVision, and to your robot's physical dimensions. - -```{eval-rst} -.. tab-set-code:: - - .. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java - :language: java - :lines: 73-93 -``` - -After declaring the system, you should create and add one `SimVisionTarget` per target you are attempting to detect. - -```{eval-rst} -.. tab-set-code:: - - .. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java - :language: java - :lines: 95-111 -``` - -Finally, while running the simulation, process simulated camera frames by providing the robot's pose to the system. - -```{eval-rst} -.. tab-set-code:: - - .. rli:: https://raw.githubusercontent.com/PhotonVision/photonvision/80e16ece87c735e30755dea271a56a2ce217b588/photonlib-java-examples/simaimandrange/src/main/java/frc/robot/sim/DrivetrainSim.java - :language: java - :lines: 138-139 -``` - -This will cause most NetworkTables fields to update properly, representing any targets that are in view of the robot. - -Robot software which uses PhotonLib to interact with a camera running PhotonVision should work the same as though a real camera was hooked up and active. - -## Raw-Data Approach - -Users may wish to directly provide target information based on an existing detailed simulation. - -A `SimPhotonCamera` can be created for this purpose. It provides an interface where the user can supply target data via a list of `PhotonTrackedTarget` objects. - -```{eval-rst} -.. tab-set-code:: - - .. code-block:: java - - @Override - public void simulationInit() { - // ... - cam = new SimPhotonCamera("MyCamera"); - // ... - } - - @Override - public void simulationPeriodic() { - // ... - ArrayList visibleTgtList = new ArrayList(); - visibleTgtList.add(new PhotonTrackedTarget(yawDegrees, pitchDegrees, area, skew, camToTargetTrans)); // Repeat for each target that you see - cam.submitProcessedFrame(0.0, visibleTgtList); - // ... - } -``` - -Note that while there is less code and configuration required to get basic data into the simulation, this approach will cause the user to need to implement much more code on their end to calculate the relative positions of the robot and target. If you already have this, the raw interface may be helpful. However, if you don't, you'll likely want to be looking at the Simulated Vision System first. diff --git a/docs/source/docs/simulation/simulation.md b/docs/source/docs/simulation/simulation-java.md similarity index 89% rename from docs/source/docs/simulation/simulation.md rename to docs/source/docs/simulation/simulation-java.md index 2c23708d1d..7b4f99da97 100644 --- a/docs/source/docs/simulation/simulation.md +++ b/docs/source/docs/simulation/simulation-java.md @@ -1,14 +1,11 @@ -# Simulation Support in PhotonLib +# Simulation Support in PhotonLib in Java -:::{attention} -This page details the current simulation support for Java. For other languages, see {doc}`/docs/simulation/simulation-deprecated`. -::: ## What Is Simulated? Simulation is a powerful tool for validating robot code without access to a physical robot. Read more about [simulation in WPILib](https://docs.wpilib.org/en/stable/docs/software/wpilib-tools/robot-simulation/introduction.html). -PhotonLib can simulate cameras on the field and generate target data approximating what would be seen in reality. This simulation attempts to include the following: +In Java, PhotonLib can simulate cameras on the field and generate target data approximating what would be seen in reality. This simulation attempts to include the following: - Camera Properties - Field of Vision @@ -58,7 +55,7 @@ A `VisionSystemSim` represents the simulated world for one or more cameras, and ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // A vision system sim labelled as "main" in NetworkTables VisionSystemSim visionSim = new VisionSystemSim("main"); @@ -71,7 +68,7 @@ Vision targets require a `TargetModel`, which describes the shape of the target. ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // A 0.5 x 0.25 meter rectangular target TargetModel targetModel = new TargetModel(0.5, 0.25); @@ -82,7 +79,7 @@ These `TargetModel` are paired with a target pose to create a `VisionTargetSim`. ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // The pose of where the target is on the field. // Its rotation determines where "forward" or the target x-axis points. @@ -104,7 +101,7 @@ For convenience, an `AprilTagFieldLayout` can also be added to automatically cre ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // The layout of AprilTags which we want to add to the vision system AprilTagFieldLayout tagLayout = AprilTagFieldLayout.loadFromResource(AprilTagFields.k2024Crescendo.m_resourceFile); @@ -125,7 +122,7 @@ Before adding a simulated camera, we need to define its properties. This is done ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // The simulated camera properties SimCameraProperties cameraProp = new SimCameraProperties(); @@ -136,7 +133,7 @@ By default, this will create a 960 x 720 resolution camera with a 90 degree diag ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // A 640 x 480 camera with a 100 degree diagonal FOV. cameraProp.setCalibration(640, 480, Rotation2d.fromDegrees(100)); @@ -154,7 +151,7 @@ These properties are used in a `PhotonCameraSim`, which handles generating captu ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // The PhotonCamera used in the real robot code. PhotonCamera camera = new PhotonCamera("cameraName"); @@ -168,7 +165,7 @@ The `PhotonCameraSim` can now be added to the `VisionSystemSim`. We have to defi ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // Our camera is mounted 0.1 meters forward and 0.5 meters up from the robot pose, // (Robot pose is considered the center of rotation at the floor level, or Z = 0) @@ -190,7 +187,7 @@ If the camera is mounted on a mobile mechanism (like a turret) this transform ca ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // The turret the camera is mounted on is rotated 5 degrees Rotation3d turretRotation = new Rotation3d(0, 0, Math.toRadians(5)); @@ -207,7 +204,7 @@ To update the `VisionSystemSim`, we simply have to pass in the simulated robot p ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // Update with the simulated drivetrain pose. This should be called every loop in simulation. visionSim.update(robotPoseMeters); @@ -222,14 +219,14 @@ Each `VisionSystemSim` has its own built-in `Field2d` for displaying object pose ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // Get the built-in Field2d used by this VisionSystemSim visionSim.getDebugField(); ``` :::{figure} images/SimExampleField.png -*A* `VisionSystemSim`*'s internal* `Field2d` *customized with target images and colors, as seen in the* [swervedriveposeestsim](https://github.com/PhotonVision/photonvision/tree/2a6fa1b6ac81f239c59d724da5339f608897c510/photonlib-java-examples/swervedriveposeestsim) *example.* +*A* `VisionSystemSim`*'s internal* `Field2d` *customized with target images and colors* ::: A `PhotonCameraSim` can also draw and publish generated camera frames to a MJPEG stream similar to an actual PhotonVision process. @@ -237,7 +234,7 @@ A `PhotonCameraSim` can also draw and publish generated camera frames to a MJPEG ```{eval-rst} .. tab-set-code:: - .. code-block:: java + .. code-block:: Java // Enable the raw and processed streams. These are enabled by default. cameraSim.enableRawStream(true); @@ -251,5 +248,5 @@ A `PhotonCameraSim` can also draw and publish generated camera frames to a MJPEG These streams follow the port order mentioned in {ref}`docs/installation/networking:Camera Stream Ports`. For example, a single simulated camera will have its raw stream at `localhost:1181` and processed stream at `localhost:1182`, which can also be found in the CameraServer tab of Shuffleboard like a normal camera stream. :::{figure} images/SimExampleFrame.png -*A frame from the processed stream of a simulated camera viewing some 2023 AprilTags with the field wireframe enabled, as seen in the* [swervedriveposeestsim example](https://github.com/PhotonVision/photonvision/tree/2a6fa1b6ac81f239c59d724da5339f608897c510/photonlib-java-examples/swervedriveposeestsim). +*A frame from the processed stream of a simulated camera viewing some 2023 AprilTags with the field wireframe enabled* ::: diff --git a/docs/source/docs/simulation/simulation-python.md b/docs/source/docs/simulation/simulation-python.md new file mode 100644 index 0000000000..eb871c6bbe --- /dev/null +++ b/docs/source/docs/simulation/simulation-python.md @@ -0,0 +1,5 @@ +# Simulation Support in PhotonLib in Python + +## What Is Supported? + +Nothing Yet diff --git a/docs/source/index.md b/docs/source/index.md index a49e191315..f624ad155e 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -45,7 +45,7 @@ Welcome to the official documentation of PhotonVision! PhotonVision is the free, :link: docs/hardware/index :link-type: doc - Select appropriate hardware for high-quality and easy vision target detection. + Select appropriate hardware for high-quality and easy vision target detection. .. grid-item-card:: Contributing :link: docs/contributing/index diff --git a/photon-client/package-lock.json b/photon-client/package-lock.json index 5ce803504d..53c926e5d9 100644 --- a/photon-client/package-lock.json +++ b/photon-client/package-lock.json @@ -17,11 +17,12 @@ "three": "^0.160.0", "vue": "^2.7.14", "vue-router": "^3.6.5", + "vue-virtual-scroll-list": "^2.3.5", "vuetify": "^2.7.1" }, "devDependencies": { "@rushstack/eslint-patch": "^1.3.2", - "@types/node": "^16.11.45", + "@types/node": "^18.19.45", "@types/three": "^0.160.0", "@vitejs/plugin-vue2": "^2.3.1", "@vue/eslint-config-prettier": "^9.0.0", @@ -37,7 +38,7 @@ "terser": "^5.14.2", "typescript": "^5.3.3", "unplugin-vue-components": "^0.26.0", - "vite": "^4.5.1" + "vite": "^5.4.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -80,10 +81,26 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", "cpu": [ "arm" ], @@ -97,9 +114,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", "cpu": [ "arm64" ], @@ -113,9 +130,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", "cpu": [ "x64" ], @@ -129,9 +146,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", "cpu": [ "arm64" ], @@ -145,9 +162,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", "cpu": [ "x64" ], @@ -161,9 +178,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", "cpu": [ "arm64" ], @@ -177,9 +194,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", "cpu": [ "x64" ], @@ -193,9 +210,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", "cpu": [ "arm" ], @@ -209,9 +226,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", "cpu": [ "arm64" ], @@ -225,9 +242,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", "cpu": [ "ia32" ], @@ -241,9 +258,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", "cpu": [ "loong64" ], @@ -257,9 +274,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", "cpu": [ "mips64el" ], @@ -273,9 +290,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", "cpu": [ "ppc64" ], @@ -289,9 +306,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", "cpu": [ "riscv64" ], @@ -305,9 +322,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", "cpu": [ "s390x" ], @@ -321,9 +338,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -337,9 +354,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", "cpu": [ "x64" ], @@ -353,9 +370,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", "cpu": [ "x64" ], @@ -369,9 +386,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", "cpu": [ "x64" ], @@ -385,9 +402,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "cpu": [ "arm64" ], @@ -401,9 +418,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "cpu": [ "ia32" ], @@ -417,9 +434,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "cpu": [ "x64" ], @@ -666,6 +683,214 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz", + "integrity": "sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz", + "integrity": "sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz", + "integrity": "sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz", + "integrity": "sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz", + "integrity": "sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz", + "integrity": "sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz", + "integrity": "sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz", + "integrity": "sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz", + "integrity": "sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz", + "integrity": "sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz", + "integrity": "sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz", + "integrity": "sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz", + "integrity": "sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz", + "integrity": "sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz", + "integrity": "sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz", + "integrity": "sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rushstack/eslint-patch": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz", @@ -707,10 +932,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.69", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.69.tgz", - "integrity": "sha512-AfDKv5fWd9XStaEuqFa6PYcM8FgTqxVMsP4BPk60emeB9YX+pp2P0zZ8nU1BQg8hyPGFrMt7MGMRMis8IrcPyg==", - "dev": true + "version": "18.19.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.45.tgz", + "integrity": "sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/raf": { "version": "3.4.3", @@ -1965,9 +2193,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -1977,28 +2205,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/escalade": { @@ -3780,9 +4009,9 @@ "optional": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3868,9 +4097,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "funding": [ { "type": "opencollective", @@ -3887,8 +4116,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -4117,18 +4346,37 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz", + "integrity": "sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.21.0", + "@rollup/rollup-android-arm64": "4.21.0", + "@rollup/rollup-darwin-arm64": "4.21.0", + "@rollup/rollup-darwin-x64": "4.21.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.0", + "@rollup/rollup-linux-arm-musleabihf": "4.21.0", + "@rollup/rollup-linux-arm64-gnu": "4.21.0", + "@rollup/rollup-linux-arm64-musl": "4.21.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.0", + "@rollup/rollup-linux-riscv64-gnu": "4.21.0", + "@rollup/rollup-linux-s390x-gnu": "4.21.0", + "@rollup/rollup-linux-x64-gnu": "4.21.0", + "@rollup/rollup-linux-x64-musl": "4.21.0", + "@rollup/rollup-win32-arm64-msvc": "4.21.0", + "@rollup/rollup-win32-ia32-msvc": "4.21.0", + "@rollup/rollup-win32-x64-msvc": "4.21.0", "fsevents": "~2.3.2" } }, @@ -4395,9 +4643,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -4827,6 +5075,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unplugin": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.6.0.tgz", @@ -4966,32 +5220,33 @@ } }, "node_modules/vite": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", - "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", + "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.21.3", + "postcss": "^8.4.41", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -5009,6 +5264,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -5084,6 +5342,11 @@ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.6.5.tgz", "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==" }, + "node_modules/vue-virtual-scroll-list": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/vue-virtual-scroll-list/-/vue-virtual-scroll-list-2.3.5.tgz", + "integrity": "sha512-YFK6u5yltqtAOfTBcij/KGAS2SoZvzbNIAf9qTULauPObEp53xj22tDuohrrM2vNkgoD5kejXICIUBt2Q4ZDqQ==" + }, "node_modules/vuetify": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-2.7.1.tgz", diff --git a/photon-client/package.json b/photon-client/package.json index a2ab77c4ca..69a40a2991 100644 --- a/photon-client/package.json +++ b/photon-client/package.json @@ -2,6 +2,7 @@ "name": "photonclient", "version": "0.0.0", "private": true, + "type": "module", "scripts": { "dev": "vite", "build": "run-p build-only", @@ -23,11 +24,12 @@ "three": "^0.160.0", "vue": "^2.7.14", "vue-router": "^3.6.5", + "vue-virtual-scroll-list": "^2.3.5", "vuetify": "^2.7.1" }, "devDependencies": { "@rushstack/eslint-patch": "^1.3.2", - "@types/node": "^16.11.45", + "@types/node": "^18.19.45", "@types/three": "^0.160.0", "@vitejs/plugin-vue2": "^2.3.1", "@vue/eslint-config-prettier": "^9.0.0", @@ -43,6 +45,6 @@ "terser": "^5.14.2", "typescript": "^5.3.3", "unplugin-vue-components": "^0.26.0", - "vite": "^4.5.1" + "vite": "^5.4.2" } } diff --git a/photon-client/src/App.vue b/photon-client/src/App.vue index 518ad39833..a9abc26888 100644 --- a/photon-client/src/App.vue +++ b/photon-client/src/App.vue @@ -76,6 +76,24 @@ if (!is_demo) { } } +/* Custom scrollbar styles */ +::-webkit-scrollbar { + width: 12px; +} + +::-webkit-scrollbar-track { + background: #232c37; +} + +::-webkit-scrollbar-thumb { + background-color: #ffd843; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background-color: #e4c33c; +} + .main-container { background-color: #232c37; padding: 0 !important; diff --git a/photon-client/src/components/app/photon-camera-stream.vue b/photon-client/src/components/app/photon-camera-stream.vue index 34465e9389..03cca11086 100644 --- a/photon-client/src/components/app/photon-camera-stream.vue +++ b/photon-client/src/components/app/photon-camera-stream.vue @@ -11,12 +11,13 @@ const props = defineProps<{ id: string; }>(); +const emptyStreamSrc = "//:0"; const streamSrc = computed(() => { const port = useCameraSettingsStore().currentCameraSettings.stream[props.streamType === "Raw" ? "inputPort" : "outputPort"]; if (!useStateStore().backendConnected || port === 0) { - return loadingImage; + return emptyStreamSrc; } return `http://${inject("backendHostname")}:${port}/stream.mjpg`; @@ -24,14 +25,27 @@ const streamSrc = computed(() => { const streamDesc = computed(() => `${props.streamType} Stream View`); const streamStyle = computed(() => { if (useStateStore().colorPickingMode) { - return { width: "100%", cursor: "crosshair" }; + return { cursor: "crosshair" }; } - return { width: "100%" }; + return {}; +}); + +const containerStyle = computed(() => { + const resolution = useCameraSettingsStore().currentVideoFormat.resolution; + const rotation = useCameraSettingsStore().currentPipelineSettings.inputImageRotationMode; + if (rotation === 1 || rotation === 3) { + return { + aspectRatio: `${resolution.height}/${resolution.width}` + }; + } + return { + aspectRatio: `${resolution.width}/${resolution.height}` + }; }); const overlayStyle = computed(() => { - if (useStateStore().colorPickingMode || streamSrc.value == loadingImage) { + if (useStateStore().colorPickingMode || streamSrc.value == emptyStreamSrc) { return { display: "none" }; } else { return {}; @@ -57,13 +71,23 @@ const handleFullscreenRequest = () => { const mjpgStream: any = ref(null); onBeforeUnmount(() => { if (!mjpgStream.value) return; - mjpgStream.value["src"] = null; + mjpgStream.value["src"] = emptyStreamSrc; });