mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3116f790ea | ||
|
|
0e013dc021 | ||
|
|
f74f6f1d42 | ||
|
|
11c60df3e0 | ||
|
|
3d9152a461 | ||
|
|
fbd239d15e | ||
|
|
7cd4a75323 | ||
|
|
973bb55e66 | ||
|
|
7bd8c44570 | ||
|
|
18e57f7872 | ||
|
|
ccb4cbed63 | ||
|
|
c19ee8b0fe | ||
|
|
e64c20346d | ||
|
|
f1a1ffd7fc | ||
|
|
c27ddf5ef9 | ||
|
|
8b669330eb | ||
|
|
ca6e307ea5 | ||
|
|
607682b687 | ||
|
|
4b94a64b06 | ||
|
|
63d9e945b8 | ||
|
|
0ad6b3acb3 | ||
|
|
02aed35c6e | ||
|
|
a8a352ed8c | ||
|
|
0cdab55e5b | ||
|
|
ba15844c28 | ||
|
|
6afff99640 | ||
|
|
d4d0545dc1 | ||
|
|
6b6a55b72e | ||
|
|
1e168f363e | ||
|
|
da3abade83 | ||
|
|
62cba9a4d3 | ||
|
|
3207795d0d | ||
|
|
e506e09a06 | ||
|
|
163f7ee704 | ||
|
|
e9c744c456 | ||
|
|
300419c151 | ||
|
|
1db3936965 | ||
|
|
6cc7e52de7 | ||
|
|
d4533a8900 | ||
|
|
90bb6cfffa | ||
|
|
cb094e4ff6 | ||
|
|
60c6ed9812 | ||
|
|
ee15cc172a | ||
|
|
1016e95242 | ||
|
|
19f1903959 | ||
|
|
53ebb6679e | ||
|
|
177132fa2a | ||
|
|
bbb230491a | ||
|
|
84ef71ace0 | ||
|
|
68736d802d | ||
|
|
d895a0c09f | ||
|
|
64a9d413bf | ||
|
|
a70e83ae2e | ||
|
|
47652d7a3c | ||
|
|
be78552db7 | ||
|
|
3acae550d6 | ||
|
|
9d55941ce5 | ||
|
|
51d92c7027 | ||
|
|
9206b47d67 | ||
|
|
6fc16264ce | ||
|
|
ad18f35477 | ||
|
|
0c6bd846bc | ||
|
|
19c1556472 | ||
|
|
3928ed5647 | ||
|
|
e408f3ad27 | ||
|
|
7957f4a625 | ||
|
|
1241dfdf68 | ||
|
|
4d109309c9 | ||
|
|
7560d18e09 | ||
|
|
f518e143d0 | ||
|
|
6fab87fa4c | ||
|
|
42c41785ac | ||
|
|
1a7eeb6282 | ||
|
|
98c0827236 | ||
|
|
57aa8ca0dd | ||
|
|
789af2ad26 | ||
|
|
9a5366bb83 | ||
|
|
77c09b9ce2 | ||
|
|
9ec27c1202 | ||
|
|
d653408873 | ||
|
|
24a24c9051 | ||
|
|
0e5eb3f35c | ||
|
|
4b15c73f64 | ||
|
|
a274e297cd | ||
|
|
d198605562 | ||
|
|
dfaad7ca22 | ||
|
|
2df82ec957 | ||
|
|
3661f485af | ||
|
|
7f9389f101 | ||
|
|
ca35bcd827 | ||
|
|
9227d09960 | ||
|
|
370126db38 | ||
|
|
1330235918 | ||
|
|
d392570659 | ||
|
|
a2d45dbca4 | ||
|
|
30965b20cf | ||
|
|
5bc942f532 | ||
|
|
97828bd325 | ||
|
|
6da21c4943 | ||
|
|
ecf1755e3e | ||
|
|
154d920e67 | ||
|
|
d2ee423749 | ||
|
|
7e3678b0a4 | ||
|
|
4a55d830e4 | ||
|
|
420020c0d5 | ||
|
|
077c8f4092 | ||
|
|
84e3a22baa | ||
|
|
b482321c0d | ||
|
|
d181e353a0 | ||
|
|
2386e44f3a | ||
|
|
fa5b604f16 | ||
|
|
67e8306819 | ||
|
|
1981b8debd | ||
|
|
ba9c21cf38 | ||
|
|
211c2a375c | ||
|
|
75b2fa1cc3 | ||
|
|
84b089b209 | ||
|
|
ce550705d7 | ||
|
|
3989617bde | ||
|
|
f1836e1321 | ||
|
|
d05f179a9a | ||
|
|
b1b03bed85 | ||
|
|
fa63fbf446 |
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,4 +1,7 @@
|
||||
*.cpp text eol=lf
|
||||
*.gradle text eol=lf
|
||||
*.h text eol=lf
|
||||
*.inc text eol=lf
|
||||
*.java text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
|
||||
21
.github/workflows/cmake.yml
vendored
21
.github/workflows/cmake.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Set up Python 3.8 (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
@@ -88,28 +88,13 @@ jobs:
|
||||
uses: lukka/run-vcpkg@v11.1
|
||||
with:
|
||||
vcpkgDirectory: ${{ runner.workspace }}/vcpkg
|
||||
vcpkgGitCommitId: 78b61582c9e093fda56a01ebb654be15a0033897 # HEAD on 2023-08-6
|
||||
vcpkgGitCommitId: 37c3e63a1306562f7f59c4c3c8892ddd50fdf992 # HEAD on 2024-02-24
|
||||
|
||||
- name: configure
|
||||
run: cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_BUILD_TYPE=Release -DWITH_JAVA=OFF -DWITH_EXAMPLES=ON -DUSE_SYSTEM_FMTLIB=ON -DUSE_SYSTEM_LIBUV=ON -DUSE_SYSTEM_EIGEN=ON -DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_INSTALL_OPTIONS=--clean-after-build -DVCPKG_TARGET_TRIPLET=x64-windows-release -DVCPKG_HOST_TRIPLET=x64-windows-release
|
||||
run: cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_BUILD_TYPE=Release -DWITH_JAVA=OFF -DWITH_EXAMPLES=ON -DUSE_SYSTEM_FMTLIB=ON -DUSE_SYSTEM_LIBUV=ON -DUSE_SYSTEM_EIGEN=OFF -DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_INSTALL_OPTIONS=--clean-after-build -DVCPKG_TARGET_TRIPLET=x64-windows-release -DVCPKG_HOST_TRIPLET=x64-windows-release
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
# Build wpiutil at full speed, wpimath depends on wpiutil
|
||||
- name: build wpiutil
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc) --target wpiutil/all
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
# Build wpimath slow to prevent OOM
|
||||
- name: build wpimath
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel 1 --target wpimath/all
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
# Build everything else fast
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
|
||||
8
.github/workflows/comment-command.yml
vendored
8
.github/workflows/comment-command.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: React Rocket
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const {owner, repo} = context.issue
|
||||
@@ -34,14 +34,14 @@ jobs:
|
||||
GITHUB_TOKEN: "${{ secrets.COMMENT_COMMAND_PAT_TOKEN }}"
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Run wpiformat
|
||||
|
||||
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
|
||||
16
.github/workflows/gradle.yml
vendored
16
.github/workflows/gradle.yml
vendored
@@ -70,13 +70,13 @@ jobs:
|
||||
artifact-name: Win64Debug
|
||||
architecture: x64
|
||||
task: "build"
|
||||
build-options: "-PciDebugOnly --max-workers 1"
|
||||
build-options: "-PciDebugOnly"
|
||||
outputs: "build/allOutputs"
|
||||
build-dir: "c:\\work"
|
||||
- os: windows-2022
|
||||
artifact-name: Win64Release
|
||||
architecture: x64
|
||||
build-options: "-PciReleaseOnly --max-workers 1"
|
||||
build-options: "-PciReleaseOnly"
|
||||
task: "copyAllOutputs"
|
||||
outputs: "build/allOutputs"
|
||||
build-dir: "c:\\work"
|
||||
@@ -84,13 +84,13 @@ jobs:
|
||||
artifact-name: WinArm64Debug
|
||||
architecture: x64
|
||||
task: "build"
|
||||
build-options: "-PciDebugOnly -Pbuildwinarm64 -Ponlywindowsarm64 --max-workers 1"
|
||||
build-options: "-PciDebugOnly -Pbuildwinarm64 -Ponlywindowsarm64"
|
||||
outputs: "build/allOutputs"
|
||||
build-dir: "c:\\work"
|
||||
- os: windows-2022
|
||||
artifact-name: WinArm64Release
|
||||
architecture: x64
|
||||
build-options: "-PciReleaseOnly -Pbuildwinarm64 -Ponlywindowsarm64 --max-workers 1"
|
||||
build-options: "-PciReleaseOnly -Pbuildwinarm64 -Ponlywindowsarm64"
|
||||
task: "copyAllOutputs"
|
||||
outputs: "build/allOutputs"
|
||||
build-dir: "c:\\work"
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
@@ -171,10 +171,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
java-version: 17
|
||||
- name: Set release environment variable
|
||||
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
run: |
|
||||
cat combiner/products/build/allOutputs/version.txt
|
||||
test -s combiner/products/build/allOutputs/version.txt
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
|
||||
10
.github/workflows/lint-format.yml
vendored
10
.github/workflows/lint-format.yml
vendored
@@ -23,11 +23,11 @@ jobs:
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat==2023.36
|
||||
run: pip3 install wpiformat==2024.32
|
||||
- name: Run
|
||||
run: wpiformat
|
||||
- name: Check output
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install wpiformat
|
||||
@@ -105,9 +105,9 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
java-version: 17
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew docs:zipDocs -PbuildServer -PdocWarningsAsErrors ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
|
||||
2
.github/workflows/pregenerate.yml
vendored
2
.github/workflows/pregenerate.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install jinja
|
||||
|
||||
2
.github/workflows/upstream-utils.yml
vendored
2
.github/workflows/upstream-utils.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Configure committer identity
|
||||
|
||||
@@ -12,11 +12,11 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
|
||||
## General Contribution Rules
|
||||
|
||||
- Everything in the library must work for the 3000+ teams that will be using it.
|
||||
- Everything in the library must work for the 4000+ teams that will be using it.
|
||||
- We need to be able to maintain submitted changes, even if you are no longer working on the project.
|
||||
- Tool suite changes must be generally useful to a broad range of teams
|
||||
- Excluding bug fixes, changes in one language generally need to have corresponding changes in other languages.
|
||||
- Some features, such the addition of C++11 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only.
|
||||
- Some features, such the addition of C++23 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only. New language features added to C++ must be wrappable in Python for [RobotPy](https://github.com/robotpy).
|
||||
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
|
||||
- Changes should have tests.
|
||||
- Code should be well documented.
|
||||
@@ -27,7 +27,8 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
- Bug reports and fixes
|
||||
- We will generally accept bug fixes without too much question. If they are only implemented for one language, we will implement them for any other necessary languages. Bug reports are also welcome, please submit them to our GitHub issue tracker.
|
||||
- While we do welcome improvements to the API, there are a few important rules to consider:
|
||||
- Features must be added to both WPILibC and WPILibJ, with rare exceptions.
|
||||
- Features must be added to Java (WPILibJ), C++ (WPILibC), with rare exceptions.
|
||||
- Most of Python (RobotPy) is created by wrapping WPILibC with pybind11 via robotpy-build. However, new features to the command framework should also be submitted to [robotpy-commands-v2](https://github.com/robotpy/robotpy-commands-v2) as the command framework is reimplemented in Python.
|
||||
- During competition season, we will not merge any new feature additions. We want to ensure that the API is stable during the season to help minimize issues for teams.
|
||||
- Ask about large changes before spending a bunch of time on them! You can create a new issue on our GitHub tracker for feature request/discussion and talk about it with us there.
|
||||
- Features that make it easier for teams with less experience to be more successful are more likely to be accepted.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2023 FIRST and other WPILib contributors
|
||||
Copyright (c) 2009-2024 FIRST and other WPILib contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1204,3 +1204,8 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
================
|
||||
2024 Field Image
|
||||
================
|
||||
2024 Field Image from MikLast: https://www.chiefdelphi.com/t/2024-crescendo-top-down-field-renders/447764
|
||||
|
||||
@@ -82,6 +82,7 @@ def main():
|
||||
# Write JSON
|
||||
with open(filename.replace(".csv", ".json"), "w") as f:
|
||||
json.dump(json_data, f, indent=2)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -16,6 +16,7 @@ import edu.wpi.first.math.geometry.Translation3d;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -221,6 +222,22 @@ public class AprilTagFieldLayout {
|
||||
new ObjectMapper().writeValue(path.toFile(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an official {@link AprilTagFieldLayout}.
|
||||
*
|
||||
* @param field The loadable AprilTag field layout.
|
||||
* @return AprilTagFieldLayout of the field.
|
||||
* @throws UncheckedIOException If the layout does not exist.
|
||||
*/
|
||||
public static AprilTagFieldLayout loadField(AprilTagFields field) {
|
||||
try {
|
||||
return loadFromResource(field.m_resourceFile);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(
|
||||
"Could not load AprilTagFieldLayout from " + field.m_resourceFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a field layout from a resource within a internal jar file.
|
||||
*
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
package edu.wpi.first.apriltag;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
/** Loadable AprilTag field layouts. */
|
||||
@@ -36,11 +35,6 @@ public enum AprilTagFields {
|
||||
* @throws UncheckedIOException If the layout does not exist
|
||||
*/
|
||||
public AprilTagFieldLayout loadAprilTagLayoutField() {
|
||||
try {
|
||||
return AprilTagFieldLayout.loadFromResource(m_resourceFile);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(
|
||||
"Could not load AprilTagFieldLayout from " + m_resourceFile, e);
|
||||
}
|
||||
return AprilTagFieldLayout.loadField(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,3 +125,37 @@ void frc::from_json(const wpi::json& json, AprilTagFieldLayout& layout) {
|
||||
layout.m_fieldWidth =
|
||||
units::meter_t{json.at("field").at("width").get<double>()};
|
||||
}
|
||||
|
||||
// Use namespace declaration for forward declaration
|
||||
namespace frc {
|
||||
|
||||
// C++ generated from resource files
|
||||
std::string_view GetResource_2022_rapidreact_json();
|
||||
std::string_view GetResource_2023_chargedup_json();
|
||||
std::string_view GetResource_2024_crescendo_json();
|
||||
|
||||
} // namespace frc
|
||||
|
||||
AprilTagFieldLayout AprilTagFieldLayout::LoadField(AprilTagField field) {
|
||||
std::string_view fieldString;
|
||||
switch (field) {
|
||||
case AprilTagField::k2022RapidReact:
|
||||
fieldString = GetResource_2022_rapidreact_json();
|
||||
break;
|
||||
case AprilTagField::k2023ChargedUp:
|
||||
fieldString = GetResource_2023_chargedup_json();
|
||||
break;
|
||||
case AprilTagField::k2024Crescendo:
|
||||
fieldString = GetResource_2024_crescendo_json();
|
||||
break;
|
||||
case AprilTagField::kNumFields:
|
||||
throw std::invalid_argument("Invalid Field");
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(fieldString);
|
||||
return json.get<AprilTagFieldLayout>();
|
||||
}
|
||||
|
||||
AprilTagFieldLayout frc::LoadAprilTagLayoutField(AprilTagField field) {
|
||||
return AprilTagFieldLayout::LoadField(field);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
|
||||
#include <wpi/json.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
// C++ generated from resource files
|
||||
std::string_view GetResource_2022_rapidreact_json();
|
||||
std::string_view GetResource_2023_chargedup_json();
|
||||
std::string_view GetResource_2024_crescendo_json();
|
||||
|
||||
AprilTagFieldLayout LoadAprilTagLayoutField(AprilTagField field) {
|
||||
std::string_view fieldString;
|
||||
switch (field) {
|
||||
case AprilTagField::k2022RapidReact:
|
||||
fieldString = GetResource_2022_rapidreact_json();
|
||||
break;
|
||||
case AprilTagField::k2023ChargedUp:
|
||||
fieldString = GetResource_2023_chargedup_json();
|
||||
break;
|
||||
case AprilTagField::k2024Crescendo:
|
||||
fieldString = GetResource_2024_crescendo_json();
|
||||
break;
|
||||
case AprilTagField::kNumFields:
|
||||
throw std::invalid_argument("Invalid Field");
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(fieldString);
|
||||
return json.get<AprilTagFieldLayout>();
|
||||
}
|
||||
|
||||
} // namespace frc
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <wpi/json_fwd.h>
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
#include "frc/geometry/Pose3d.h"
|
||||
|
||||
namespace frc {
|
||||
@@ -48,6 +49,14 @@ class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
kRedAllianceWallRightSide,
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
* @return AprilTagFieldLayout of the field
|
||||
*/
|
||||
static AprilTagFieldLayout LoadField(AprilTagField field);
|
||||
|
||||
AprilTagFieldLayout() = default;
|
||||
|
||||
/**
|
||||
@@ -152,4 +161,13 @@ void to_json(wpi::json& json, const AprilTagFieldLayout& layout);
|
||||
WPILIB_DLLEXPORT
|
||||
void from_json(const wpi::json& json, AprilTagFieldLayout& layout);
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
* @return AprilTagFieldLayout of the field
|
||||
*/
|
||||
WPILIB_DLLEXPORT AprilTagFieldLayout
|
||||
LoadAprilTagLayoutField(AprilTagField field);
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#include <wpi/SymbolExports.h>
|
||||
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
@@ -28,12 +26,4 @@ enum class AprilTagField {
|
||||
kNumFields,
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
*/
|
||||
WPILIB_DLLEXPORT AprilTagFieldLayout
|
||||
LoadAprilTagLayoutField(AprilTagField field);
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
}
|
||||
],
|
||||
"field": {
|
||||
"length": 16.451,
|
||||
"length": 16.541,
|
||||
"width": 8.211
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,14 @@ class LoadConfigTest {
|
||||
@ParameterizedTest
|
||||
@EnumSource(AprilTagFields.class)
|
||||
void testLoad(AprilTagFields field) {
|
||||
AprilTagFieldLayout layout = Assertions.assertDoesNotThrow(field::loadAprilTagLayoutField);
|
||||
AprilTagFieldLayout layout =
|
||||
Assertions.assertDoesNotThrow(() -> AprilTagFieldLayout.loadField(field));
|
||||
assertNotNull(layout);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test2022RapidReact() {
|
||||
AprilTagFieldLayout layout = AprilTagFields.k2022RapidReact.loadAprilTagLayoutField();
|
||||
AprilTagFieldLayout layout = AprilTagFieldLayout.loadField(AprilTagFields.k2022RapidReact);
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
Pose3d expectedPose =
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
|
||||
namespace frc {
|
||||
@@ -20,7 +21,7 @@ std::vector<AprilTagField> GetAllFields() {
|
||||
|
||||
TEST(AprilTagFieldsTest, TestLoad2022RapidReact) {
|
||||
AprilTagFieldLayout layout =
|
||||
LoadAprilTagLayoutField(AprilTagField::k2022RapidReact);
|
||||
AprilTagFieldLayout::LoadField(AprilTagField::k2022RapidReact);
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
auto expectedPose =
|
||||
@@ -53,7 +54,7 @@ class AllFieldsFixtureTest : public ::testing::TestWithParam<AprilTagField> {};
|
||||
|
||||
TEST_P(AllFieldsFixtureTest, CheckEntireEnum) {
|
||||
AprilTagField field = GetParam();
|
||||
EXPECT_NO_THROW(LoadAprilTagLayoutField(field));
|
||||
EXPECT_NO_THROW(AprilTagFieldLayout::LoadField(field));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ValuesEnumTestInstTests, AllFieldsFixtureTest,
|
||||
|
||||
@@ -27,6 +27,7 @@ import edu.wpi.first.networktables.StringArrayTopic;
|
||||
import edu.wpi.first.networktables.StringEntry;
|
||||
import edu.wpi.first.networktables.StringPublisher;
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -140,6 +141,7 @@ public final class CameraServer {
|
||||
if (m_choicesPublisher != null) {
|
||||
m_choicesPublisher.close();
|
||||
}
|
||||
Reference.reachabilityFence(m_videoListener);
|
||||
}
|
||||
|
||||
BooleanEntry m_booleanValueEntry;
|
||||
@@ -223,7 +225,7 @@ public final class CameraServer {
|
||||
// - "PropertyInfo/{Property}" - Property supporting information
|
||||
|
||||
// Listener for video events
|
||||
@SuppressWarnings({"PMD.UnusedPrivateField", "PMD.AvoidCatchingGenericException"})
|
||||
@SuppressWarnings("PMD.AvoidCatchingGenericException")
|
||||
private static final VideoListener m_videoListener =
|
||||
new VideoListener(
|
||||
event -> {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
@FILENAME_DEP_REPLACE@
|
||||
@WPIUTIL_DEP_REPLACE@
|
||||
@WPINET_DEP_REPLACE@
|
||||
find_dependency(OpenCV)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
|
||||
@@ -74,18 +74,62 @@ public class CameraServerCvJNI {
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a CV source.
|
||||
*
|
||||
* @param name Name.
|
||||
* @param pixelFormat OpenCV pixel format.
|
||||
* @param width Image width.
|
||||
* @param height Image height.
|
||||
* @param fps Frames per second.
|
||||
* @return CV source.
|
||||
*/
|
||||
public static native int createCvSource(
|
||||
String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put source frame.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param imageNativeObj Image native object handle.
|
||||
*/
|
||||
public static native void putSourceFrame(int source, long imageNativeObj);
|
||||
|
||||
/**
|
||||
* Creates a CV sink.
|
||||
*
|
||||
* @param name Name.
|
||||
* @param pixelFormat OpenCV pixel format.
|
||||
* @return CV sink handle.
|
||||
*/
|
||||
public static native int createCvSink(String name, int pixelFormat);
|
||||
|
||||
// /**
|
||||
// * Creates a CV sink callback.
|
||||
// *
|
||||
// * @param name Name.
|
||||
// * @param processFrame Process frame callback.
|
||||
// */
|
||||
// public static native int createCvSinkCallback(String name,
|
||||
// void (*processFrame)(long time));
|
||||
|
||||
/**
|
||||
* Returns sink frame handle.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param imageNativeObj Image native object handle.
|
||||
* @return Sink frame handle.
|
||||
*/
|
||||
public static native long grabSinkFrame(int sink, long imageNativeObj);
|
||||
|
||||
/**
|
||||
* Returns sink frame timeout in microseconds.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param imageNativeObj Image native object handle.
|
||||
* @param timeout Timeout in seconds.
|
||||
* @return Sink frame timeout in microseconds.
|
||||
*/
|
||||
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
|
||||
|
||||
/** Utility class. */
|
||||
|
||||
@@ -77,140 +77,521 @@ public class CameraServerJNI {
|
||||
//
|
||||
// Property Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns property kind.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property kind.
|
||||
*/
|
||||
public static native int getPropertyKind(int property);
|
||||
|
||||
/**
|
||||
* Returns property name.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property name.
|
||||
*/
|
||||
public static native String getPropertyName(int property);
|
||||
|
||||
/**
|
||||
* Returns property value.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property value.
|
||||
*/
|
||||
public static native int getProperty(int property);
|
||||
|
||||
/**
|
||||
* Sets property value.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @param value Property value.
|
||||
*/
|
||||
public static native void setProperty(int property, int value);
|
||||
|
||||
/**
|
||||
* Returns property minimum.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property minimum.
|
||||
*/
|
||||
public static native int getPropertyMin(int property);
|
||||
|
||||
/**
|
||||
* Returns property maximum.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property maximum.
|
||||
*/
|
||||
public static native int getPropertyMax(int property);
|
||||
|
||||
/**
|
||||
* Returns property step.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property step.
|
||||
*/
|
||||
public static native int getPropertyStep(int property);
|
||||
|
||||
/**
|
||||
* Returns property default value.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property default value.
|
||||
*/
|
||||
public static native int getPropertyDefault(int property);
|
||||
|
||||
/**
|
||||
* Returns property value as a string.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Property value as a string.
|
||||
*/
|
||||
public static native String getStringProperty(int property);
|
||||
|
||||
/**
|
||||
* Sets property value to a string.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @param value Property value string.
|
||||
*/
|
||||
public static native void setStringProperty(int property, String value);
|
||||
|
||||
/**
|
||||
* Returns enum of possible property value strings.
|
||||
*
|
||||
* @param property Property handle.
|
||||
* @return Enum of possible property value strings.
|
||||
*/
|
||||
public static native String[] getEnumPropertyChoices(int property);
|
||||
|
||||
//
|
||||
// Source Creation Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Creates a new USB camera by device.
|
||||
*
|
||||
* @param name USB camera name.
|
||||
* @param dev USB camera device number.
|
||||
* @return USB camera handle.
|
||||
*/
|
||||
public static native int createUsbCameraDev(String name, int dev);
|
||||
|
||||
/**
|
||||
* Creates a new USB camera by path.
|
||||
*
|
||||
* @param name USB camera name.
|
||||
* @param path USB camera path.
|
||||
* @return USB camera handle.
|
||||
*/
|
||||
public static native int createUsbCameraPath(String name, String path);
|
||||
|
||||
/**
|
||||
* Creates an HTTP camera.
|
||||
*
|
||||
* @param name HTTP camera name.
|
||||
* @param url HTTP camera stream URL.
|
||||
* @param kind HTTP camera kind.
|
||||
* @return HTTP camera handle.
|
||||
*/
|
||||
public static native int createHttpCamera(String name, String url, int kind);
|
||||
|
||||
/**
|
||||
* Creates an HTTP camera from multiple URLs.
|
||||
*
|
||||
* @param name HTTP camera name.
|
||||
* @param urls HTTP camera stream URLs.
|
||||
* @param kind HTTP camera kind.
|
||||
* @return HTTP camera handle.
|
||||
*/
|
||||
public static native int createHttpCameraMulti(String name, String[] urls, int kind);
|
||||
|
||||
/**
|
||||
* Creates a raw source.
|
||||
*
|
||||
* @param name Source name.
|
||||
* @param pixelFormat Pixel format.
|
||||
* @param width Image width.
|
||||
* @param height Image height.
|
||||
* @param fps Source frames per second.
|
||||
* @return Raw source handle.
|
||||
*/
|
||||
public static native int createRawSource(
|
||||
String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
//
|
||||
// Source Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns source kind.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source kind.
|
||||
*/
|
||||
public static native int getSourceKind(int source);
|
||||
|
||||
/**
|
||||
* Returns source name.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source name.
|
||||
*/
|
||||
public static native String getSourceName(int source);
|
||||
|
||||
/**
|
||||
* Returns source description.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source description.
|
||||
*/
|
||||
public static native String getSourceDescription(int source);
|
||||
|
||||
/**
|
||||
* Returns source's last frame time.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source's last frame time.
|
||||
*/
|
||||
public static native long getSourceLastFrameTime(int source);
|
||||
|
||||
/**
|
||||
* Sets source connection strategy.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param strategy Connection strategy.
|
||||
*/
|
||||
public static native void setSourceConnectionStrategy(int source, int strategy);
|
||||
|
||||
/**
|
||||
* Returns true if source is connected.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return True if source is connected.
|
||||
*/
|
||||
public static native boolean isSourceConnected(int source);
|
||||
|
||||
/**
|
||||
* Returns true if source is enabled.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return True if source is enabled.
|
||||
*/
|
||||
public static native boolean isSourceEnabled(int source);
|
||||
|
||||
/**
|
||||
* Returns source property.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param name Source property name.
|
||||
* @return Source property.
|
||||
*/
|
||||
public static native int getSourceProperty(int source, String name);
|
||||
|
||||
/**
|
||||
* Returns list of source property handles.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return List of source property handles.
|
||||
*/
|
||||
public static native int[] enumerateSourceProperties(int source);
|
||||
|
||||
/**
|
||||
* Returns source video mode.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source video mode.
|
||||
*/
|
||||
public static native VideoMode getSourceVideoMode(int source);
|
||||
|
||||
/**
|
||||
* Sets source video mode.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param pixelFormat Pixel format.
|
||||
* @param width Image width.
|
||||
* @param height Image height.
|
||||
* @param fps Source frames per second.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSourceVideoMode(
|
||||
int source, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Sets source pixel format.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param pixelFormat Source pixel format.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSourcePixelFormat(int source, int pixelFormat);
|
||||
|
||||
/**
|
||||
* Sets source resolution.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param width Image width.
|
||||
* @param height Image height.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSourceResolution(int source, int width, int height);
|
||||
|
||||
/**
|
||||
* Sets source FPS.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param fps Source frames per second.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSourceFPS(int source, int fps);
|
||||
|
||||
/**
|
||||
* Sets source configuration JSON.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param config Configuration JSON.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSourceConfigJson(int source, String config);
|
||||
|
||||
/**
|
||||
* Returns source configuration JSON.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Source configuration JSON.
|
||||
*/
|
||||
public static native String getSourceConfigJson(int source);
|
||||
|
||||
/**
|
||||
* Returns list of source's supported video modes.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return List of source's supported video modes.
|
||||
*/
|
||||
public static native VideoMode[] enumerateSourceVideoModes(int source);
|
||||
|
||||
/**
|
||||
* Returns list of source sinks.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return List of source sinks.
|
||||
*/
|
||||
public static native int[] enumerateSourceSinks(int source);
|
||||
|
||||
/**
|
||||
* Copies source.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return New source handle.
|
||||
*/
|
||||
public static native int copySource(int source);
|
||||
|
||||
/**
|
||||
* Releases source.
|
||||
*
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void releaseSource(int source);
|
||||
|
||||
//
|
||||
// Camera Source Common Property Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Sets camera brightness.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param brightness Brightness.
|
||||
*/
|
||||
public static native void setCameraBrightness(int source, int brightness);
|
||||
|
||||
/**
|
||||
* Returns camera brightness.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return Camera brightness.
|
||||
*/
|
||||
public static native int getCameraBrightness(int source);
|
||||
|
||||
/**
|
||||
* Sets camera white balance to auto.
|
||||
*
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void setCameraWhiteBalanceAuto(int source);
|
||||
|
||||
/**
|
||||
* Sets camera white balance to "hold current".
|
||||
*
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void setCameraWhiteBalanceHoldCurrent(int source);
|
||||
|
||||
/**
|
||||
* Sets camera white balance to the given value.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param value White balance.
|
||||
*/
|
||||
public static native void setCameraWhiteBalanceManual(int source, int value);
|
||||
|
||||
/**
|
||||
* Sets camera exposure to auto.
|
||||
*
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void setCameraExposureAuto(int source);
|
||||
|
||||
/**
|
||||
* Sets camera exposure to "hold current".
|
||||
*
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void setCameraExposureHoldCurrent(int source);
|
||||
|
||||
/**
|
||||
* Sets camera exposure to the given value.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param value Exposure.
|
||||
*/
|
||||
public static native void setCameraExposureManual(int source, int value);
|
||||
|
||||
//
|
||||
// UsbCamera Source Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Sets USB camera path.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param path USB camera path.
|
||||
*/
|
||||
public static native void setUsbCameraPath(int source, String path);
|
||||
|
||||
/**
|
||||
* Returns USB camera path.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return USB camera path.
|
||||
*/
|
||||
public static native String getUsbCameraPath(int source);
|
||||
|
||||
/**
|
||||
* Returns USB camera info.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return USB camera info.
|
||||
*/
|
||||
public static native UsbCameraInfo getUsbCameraInfo(int source);
|
||||
|
||||
//
|
||||
// HttpCamera Source Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns HTTP camera kind.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return HTTP camera kind.
|
||||
*/
|
||||
public static native int getHttpCameraKind(int source);
|
||||
|
||||
/**
|
||||
* Sets HTTP camera URLs.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param urls HTTP camera URLs.
|
||||
*/
|
||||
public static native void setHttpCameraUrls(int source, String[] urls);
|
||||
|
||||
/**
|
||||
* Returns HTTP camera URLs.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @return HTTP camera URLs.
|
||||
*/
|
||||
public static native String[] getHttpCameraUrls(int source);
|
||||
|
||||
//
|
||||
// Image Source Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Puts raw frame into source.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param frame Frame handle.
|
||||
*/
|
||||
public static native void putRawSourceFrame(int source, long frame);
|
||||
|
||||
/**
|
||||
* Puts raw frame into source.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param data Frame byte buffer.
|
||||
* @param size Frame size.
|
||||
* @param width Frame width.
|
||||
* @param height Frame height.
|
||||
* @param stride Frame stride.
|
||||
* @param pixelFormat Frame pixel format.
|
||||
*/
|
||||
public static native void putRawSourceFrameBB(
|
||||
int source, ByteBuffer data, int size, int width, int height, int stride, int pixelFormat);
|
||||
|
||||
/**
|
||||
* Puts raw frame into source.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param data Frame handle.
|
||||
* @param size Frame size.
|
||||
* @param width Frame width.
|
||||
* @param height Frame height.
|
||||
* @param stride Frame stride.
|
||||
* @param pixelFormat Frame pixel format.
|
||||
*/
|
||||
public static native void putRawSourceFrameData(
|
||||
int source, long data, int size, int width, int height, int stride, int pixelFormat);
|
||||
|
||||
/**
|
||||
* Notify source error.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param msg Error message.
|
||||
*/
|
||||
public static native void notifySourceError(int source, String msg);
|
||||
|
||||
/**
|
||||
* Sets whether source is connected.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param connected True if source is connected.
|
||||
*/
|
||||
public static native void setSourceConnected(int source, boolean connected);
|
||||
|
||||
/**
|
||||
* Sets source description.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param description Source description.
|
||||
*/
|
||||
public static native void setSourceDescription(int source, String description);
|
||||
|
||||
/**
|
||||
* Creates a source property.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param name Property name.
|
||||
* @param kind Property kind.
|
||||
* @param minimum Property minimum.
|
||||
* @param maximum Property maximum.
|
||||
* @param step Property step.
|
||||
* @param defaultValue Property default value.
|
||||
* @param value Property value.
|
||||
* @return Source property handle.
|
||||
*/
|
||||
public static native int createSourceProperty(
|
||||
int source,
|
||||
String name,
|
||||
@@ -221,88 +602,288 @@ public class CameraServerJNI {
|
||||
int defaultValue,
|
||||
int value);
|
||||
|
||||
/**
|
||||
* Sets list of possible property values.
|
||||
*
|
||||
* @param source Source handle.
|
||||
* @param property Property handle.
|
||||
* @param choices List of possible property values.
|
||||
*/
|
||||
public static native void setSourceEnumPropertyChoices(
|
||||
int source, int property, String[] choices);
|
||||
|
||||
//
|
||||
// Sink Creation Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Creates an MJPEG server.
|
||||
*
|
||||
* @param name MJPEG server name.
|
||||
* @param listenAddress IP address at which server should listen.
|
||||
* @param port Port on which server should listen.
|
||||
* @return MJPEG server handle.
|
||||
*/
|
||||
public static native int createMjpegServer(String name, String listenAddress, int port);
|
||||
|
||||
/**
|
||||
* Creates a raw sink.
|
||||
*
|
||||
* @param name Sink name.
|
||||
* @return Raw sink handle.
|
||||
*/
|
||||
public static native int createRawSink(String name);
|
||||
|
||||
//
|
||||
// Sink Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns sink kind.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink kind.
|
||||
*/
|
||||
public static native int getSinkKind(int sink);
|
||||
|
||||
/**
|
||||
* Returns sink name.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink name.
|
||||
*/
|
||||
public static native String getSinkName(int sink);
|
||||
|
||||
/**
|
||||
* Returns sink description.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink description.
|
||||
*/
|
||||
public static native String getSinkDescription(int sink);
|
||||
|
||||
/**
|
||||
* Returns sink property.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param name Property name.
|
||||
* @return Sink property handle.
|
||||
*/
|
||||
public static native int getSinkProperty(int sink, String name);
|
||||
|
||||
/**
|
||||
* Returns list of sink property handles.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return List of sink property handles.
|
||||
*/
|
||||
public static native int[] enumerateSinkProperties(int sink);
|
||||
|
||||
/**
|
||||
* Sets sink configuration JSON.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param config Configuration JSON.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setSinkConfigJson(int sink, String config);
|
||||
|
||||
/**
|
||||
* Returns sink configuration JSON.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink configuration JSON.
|
||||
*/
|
||||
public static native String getSinkConfigJson(int sink);
|
||||
|
||||
/**
|
||||
* Sets sink source.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param source Source handle.
|
||||
*/
|
||||
public static native void setSinkSource(int sink, int source);
|
||||
|
||||
/**
|
||||
* Returns sink source property.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param name Property name.
|
||||
* @return Sink source property handle.
|
||||
*/
|
||||
public static native int getSinkSourceProperty(int sink, String name);
|
||||
|
||||
/**
|
||||
* Returns sink source.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink source handle.
|
||||
*/
|
||||
public static native int getSinkSource(int sink);
|
||||
|
||||
/**
|
||||
* Copies sink.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return New sink handle.
|
||||
*/
|
||||
public static native int copySink(int sink);
|
||||
|
||||
/**
|
||||
* Releases sink.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
*/
|
||||
public static native void releaseSink(int sink);
|
||||
|
||||
//
|
||||
// MjpegServer Sink Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns MJPEG server listen address.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return MJPEG server listen address.
|
||||
*/
|
||||
public static native String getMjpegServerListenAddress(int sink);
|
||||
|
||||
/**
|
||||
* Returns MJPEG server port.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return MJPEG server port.
|
||||
*/
|
||||
public static native int getMjpegServerPort(int sink);
|
||||
|
||||
//
|
||||
// Image Sink Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Sets sink description.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param description Sink description.
|
||||
*/
|
||||
public static native void setSinkDescription(int sink, String description);
|
||||
|
||||
/**
|
||||
* Returns raw sink frame.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param frame Raw frame.
|
||||
* @param nativeObj Native object.
|
||||
* @return Raw sink frame handle.
|
||||
*/
|
||||
public static native long grabRawSinkFrame(int sink, RawFrame frame, long nativeObj);
|
||||
|
||||
/**
|
||||
* Returns raw sink frame timeout.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param frame Raw frame.
|
||||
* @param nativeObj Native object.
|
||||
* @param timeout Timeout in seconds.
|
||||
* @return Raw sink frame timeout.
|
||||
*/
|
||||
public static native long grabRawSinkFrameTimeout(
|
||||
int sink, RawFrame frame, long nativeObj, double timeout);
|
||||
|
||||
/**
|
||||
* Returns sink error message.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @return Sink error message.
|
||||
*/
|
||||
public static native String getSinkError(int sink);
|
||||
|
||||
/**
|
||||
* Sets sink enable.
|
||||
*
|
||||
* @param sink Sink handle.
|
||||
* @param enabled True if sink should be enabled.
|
||||
*/
|
||||
public static native void setSinkEnabled(int sink, boolean enabled);
|
||||
|
||||
//
|
||||
// Listener Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Adds listener.
|
||||
*
|
||||
* @param listener Video event callback.
|
||||
* @param eventMask Event mask.
|
||||
* @param immediateNotify True to immediately notify on event.
|
||||
* @return Listener handle.
|
||||
*/
|
||||
public static native int addListener(
|
||||
Consumer<VideoEvent> listener, int eventMask, boolean immediateNotify);
|
||||
|
||||
/**
|
||||
* Removes listener.
|
||||
*
|
||||
* @param handle Listener handle.
|
||||
*/
|
||||
public static native void removeListener(int handle);
|
||||
|
||||
/**
|
||||
* Creates listener poller.
|
||||
*
|
||||
* @return Listener poller handle.
|
||||
*/
|
||||
public static native int createListenerPoller();
|
||||
|
||||
/**
|
||||
* Destroys listener poller.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
*/
|
||||
public static native void destroyListenerPoller(int poller);
|
||||
|
||||
/**
|
||||
* Add polled listener.
|
||||
*
|
||||
* @param poller Poller handle.
|
||||
* @param eventMask Event mask.
|
||||
* @param immediateNotify True to immediately notify on event.
|
||||
* @return Polled listener handle.
|
||||
*/
|
||||
public static native int addPolledListener(int poller, int eventMask, boolean immediateNotify);
|
||||
|
||||
/**
|
||||
* Polls listener.
|
||||
*
|
||||
* @param poller Poller handle.
|
||||
* @return List of video events.
|
||||
* @throws InterruptedException if polling was interrupted.
|
||||
*/
|
||||
public static native VideoEvent[] pollListener(int poller) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Polls listener with timeout.
|
||||
*
|
||||
* @param poller Poller handle.
|
||||
* @param timeout Timeout in seconds.
|
||||
* @return List of video events.
|
||||
* @throws InterruptedException if polling was interrupted.
|
||||
*/
|
||||
public static native VideoEvent[] pollListenerTimeout(int poller, double timeout)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Cancels poll listener.
|
||||
*
|
||||
* @param poller Poller handle.
|
||||
*/
|
||||
public static native void cancelPollListener(int poller);
|
||||
|
||||
//
|
||||
// Telemetry Functions
|
||||
//
|
||||
|
||||
/** Telemetry kind. */
|
||||
public enum TelemetryKind {
|
||||
/** kSourceBytesReceived. */
|
||||
kSourceBytesReceived(1),
|
||||
@@ -315,23 +896,66 @@ public class CameraServerJNI {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns telemetry kind value.
|
||||
*
|
||||
* @return Telemetry kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets telemetry period.
|
||||
*
|
||||
* @param seconds Telemetry period in seconds.
|
||||
*/
|
||||
public static native void setTelemetryPeriod(double seconds);
|
||||
|
||||
/**
|
||||
* Returns telemetry elapsed time.
|
||||
*
|
||||
* @return Telemetry elapsed time.
|
||||
*/
|
||||
public static native double getTelemetryElapsedTime();
|
||||
|
||||
/**
|
||||
* Returns telemetry value.
|
||||
*
|
||||
* @param handle Telemetry handle.
|
||||
* @param kind Telemetry kind.
|
||||
* @return Telemetry value.
|
||||
*/
|
||||
public static native long getTelemetryValue(int handle, int kind);
|
||||
|
||||
/**
|
||||
* Returns telemetry value.
|
||||
*
|
||||
* @param handle Telemetry handle.
|
||||
* @param kind Telemetry kind.
|
||||
* @return Telemetry value.
|
||||
*/
|
||||
public static long getTelemetryValue(int handle, TelemetryKind kind) {
|
||||
return getTelemetryValue(handle, kind.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns telemetry average value.
|
||||
*
|
||||
* @param handle Telemetry handle.
|
||||
* @param kind Telemetry kind.
|
||||
* @return Telemetry average value.
|
||||
*/
|
||||
public static native double getTelemetryAverageValue(int handle, int kind);
|
||||
|
||||
/**
|
||||
* Returns telemetry average value.
|
||||
*
|
||||
* @param handle Telemetry handle.
|
||||
* @param kind Telemetry kind.
|
||||
* @return Telemetry average value.
|
||||
*/
|
||||
public static double getTelemetryAverageValue(int handle, TelemetryKind kind) {
|
||||
return getTelemetryAverageValue(handle, kind.getValue());
|
||||
}
|
||||
@@ -339,30 +963,80 @@ public class CameraServerJNI {
|
||||
//
|
||||
// Logging Functions
|
||||
//
|
||||
|
||||
/** Logger functional interface. */
|
||||
@FunctionalInterface
|
||||
public interface LoggerFunction {
|
||||
/**
|
||||
* Log a string.
|
||||
*
|
||||
* @param level Log level.
|
||||
* @param file Log file.
|
||||
* @param line Line number.
|
||||
* @param msg Log message.
|
||||
*/
|
||||
void apply(int level, String file, int line, String msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets logger.
|
||||
*
|
||||
* @param func Logger function.
|
||||
* @param minLevel Minimum logging level.
|
||||
*/
|
||||
public static native void setLogger(LoggerFunction func, int minLevel);
|
||||
|
||||
//
|
||||
// Utility Functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns list of USB cameras.
|
||||
*
|
||||
* @return List of USB cameras.
|
||||
*/
|
||||
public static native UsbCameraInfo[] enumerateUsbCameras();
|
||||
|
||||
/**
|
||||
* Returns list of sources.
|
||||
*
|
||||
* @return List of sources.
|
||||
*/
|
||||
public static native int[] enumerateSources();
|
||||
|
||||
/**
|
||||
* Returns list of sinks.
|
||||
*
|
||||
* @return List of sinks.
|
||||
*/
|
||||
public static native int[] enumerateSinks();
|
||||
|
||||
/**
|
||||
* Returns hostname.
|
||||
*
|
||||
* @return Hostname.
|
||||
*/
|
||||
public static native String getHostname();
|
||||
|
||||
/**
|
||||
* Returns list of network interfaces.
|
||||
*
|
||||
* @return List of network interfaces.
|
||||
*/
|
||||
public static native String[] getNetworkInterfaces();
|
||||
|
||||
/** Runs main run loop. */
|
||||
public static native void runMainRunLoop();
|
||||
|
||||
/**
|
||||
* Runs main run loop with timeout.
|
||||
*
|
||||
* @param timeoutSeconds Timeout in seconds.
|
||||
* @return 3 on timeout, 2 on signal, 1 on other.
|
||||
*/
|
||||
public static native int runMainRunLoopTimeout(double timeoutSeconds);
|
||||
|
||||
/** Stops main run loop. */
|
||||
public static native void stopMainRunLoop();
|
||||
|
||||
/** Utility class. */
|
||||
|
||||
@@ -6,6 +6,7 @@ package edu.wpi.first.cscore;
|
||||
|
||||
/** A source that represents a MJPEG-over-HTTP (IP) camera. */
|
||||
public class HttpCamera extends VideoCamera {
|
||||
/** HTTP camera kind. */
|
||||
public enum HttpCameraKind {
|
||||
/** Unknown camera kind. */
|
||||
kUnknown(0),
|
||||
@@ -22,6 +23,11 @@ public class HttpCamera extends VideoCamera {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HttpCameraKind value.
|
||||
*
|
||||
* @return HttpCameraKind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
/** A base class for single image reading sinks. */
|
||||
public abstract class ImageSink extends VideoSink {
|
||||
/**
|
||||
* Constructs an ImageSink.
|
||||
*
|
||||
* @param handle The image sink handle.
|
||||
*/
|
||||
protected ImageSink(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
/** A base class for single image providing sources. */
|
||||
public abstract class ImageSource extends VideoSource {
|
||||
/**
|
||||
* Constructs an ImageSource.
|
||||
*
|
||||
* @param handle The image source handle.
|
||||
*/
|
||||
protected ImageSource(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,32 @@ package edu.wpi.first.cscore;
|
||||
|
||||
/** A source that represents a video camera. */
|
||||
public class VideoCamera extends VideoSource {
|
||||
/** White balance. */
|
||||
public static class WhiteBalance {
|
||||
/** Fixed indoor white balance. */
|
||||
public static final int kFixedIndoor = 3000;
|
||||
|
||||
/** Fixed outdoor white balance 1. */
|
||||
public static final int kFixedOutdoor1 = 4000;
|
||||
|
||||
/** Fixed outdoor white balance 2. */
|
||||
public static final int kFixedOutdoor2 = 5000;
|
||||
|
||||
/** Fixed fluorescent white balance 1. */
|
||||
public static final int kFixedFluorescent1 = 5100;
|
||||
|
||||
/** Fixed fluorescent white balance 2. */
|
||||
public static final int kFixedFlourescent2 = 5200;
|
||||
|
||||
/** Default constructor. */
|
||||
public WhiteBalance() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VideoCamera.
|
||||
*
|
||||
* @param handle The video camera handle.
|
||||
*/
|
||||
protected VideoCamera(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package edu.wpi.first.cscore;
|
||||
/** Video event. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class VideoEvent {
|
||||
/** VideoEvent kind. */
|
||||
public enum Kind {
|
||||
/** Unknown video event. */
|
||||
kUnknown(0x0000),
|
||||
@@ -57,6 +58,11 @@ public class VideoEvent {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind value.
|
||||
*
|
||||
* @return The kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -139,39 +145,67 @@ public class VideoEvent {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/** The video event kind. */
|
||||
public Kind kind;
|
||||
|
||||
// Valid for kSource* and kSink* respectively
|
||||
/**
|
||||
* The source handle.
|
||||
*
|
||||
* <p>Valid for kSource* and kSink* respectively.
|
||||
*/
|
||||
public int sourceHandle;
|
||||
|
||||
/** The sink handle. */
|
||||
public int sinkHandle;
|
||||
|
||||
// Source/sink/property name
|
||||
/** Source/sink/property name. */
|
||||
public String name;
|
||||
|
||||
// Fields for kSourceVideoModeChanged event
|
||||
// Fields for kSourceVideoModeChanged event.
|
||||
|
||||
/** New source video mode. */
|
||||
public VideoMode mode;
|
||||
|
||||
// Fields for kSourceProperty* events
|
||||
// Fields for kSourceProperty* events.
|
||||
|
||||
/** Source property handle. */
|
||||
public int propertyHandle;
|
||||
|
||||
/** Source property kind. */
|
||||
public VideoProperty.Kind propertyKind;
|
||||
|
||||
/** Event value. */
|
||||
public int value;
|
||||
|
||||
/** Event value as a string. */
|
||||
public String valueStr;
|
||||
|
||||
// Listener that was triggered
|
||||
/** Listener that was triggered. */
|
||||
public int listener;
|
||||
|
||||
/**
|
||||
* Returns the source associated with the event (if any).
|
||||
*
|
||||
* @return The source associated with the event (if any).
|
||||
*/
|
||||
public VideoSource getSource() {
|
||||
return new VideoSource(CameraServerJNI.copySource(sourceHandle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sink associated with the event (if any).
|
||||
*
|
||||
* @return The sink associated with the event (if any).
|
||||
*/
|
||||
public VideoSink getSink() {
|
||||
return new VideoSink(CameraServerJNI.copySink(sinkHandle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property associated with the event (if any).
|
||||
*
|
||||
* @return The property associated with the event (if any).
|
||||
*/
|
||||
public VideoProperty getProperty() {
|
||||
return new VideoProperty(propertyHandle, propertyKind);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ package edu.wpi.first.cscore;
|
||||
public class VideoException extends RuntimeException {
|
||||
private static final long serialVersionUID = -9155939328084105145L;
|
||||
|
||||
/**
|
||||
* Constructs the exception with the given message.
|
||||
*
|
||||
* @param msg The exception message.
|
||||
*/
|
||||
public VideoException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ public class VideoListener implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the video listener handle is valid.
|
||||
*
|
||||
* @return True if the video listener handle is valid.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return m_handle != 0;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ public class VideoProperty {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -51,69 +56,152 @@ public class VideoProperty {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property name.
|
||||
*
|
||||
* @return Property name.
|
||||
*/
|
||||
public String getName() {
|
||||
return CameraServerJNI.getPropertyName(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property kind.
|
||||
*
|
||||
* @return Property kind.
|
||||
*/
|
||||
public Kind getKind() {
|
||||
return m_kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if property is valid.
|
||||
*
|
||||
* @return True if property is valid.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return m_kind != Kind.kNone;
|
||||
}
|
||||
|
||||
// Kind checkers
|
||||
/**
|
||||
* Returns true if property is a boolean.
|
||||
*
|
||||
* @return True if property is a boolean.
|
||||
*/
|
||||
public boolean isBoolean() {
|
||||
return m_kind == Kind.kBoolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if property is an integer.
|
||||
*
|
||||
* @return True if property is an integer.
|
||||
*/
|
||||
public boolean isInteger() {
|
||||
return m_kind == Kind.kInteger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if property is a string.
|
||||
*
|
||||
* @return True if property is a string.
|
||||
*/
|
||||
public boolean isString() {
|
||||
return m_kind == Kind.kString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if property is an enum.
|
||||
*
|
||||
* @return True if property is an enum.
|
||||
*/
|
||||
public boolean isEnum() {
|
||||
return m_kind == Kind.kEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property value.
|
||||
*
|
||||
* @return Property value.
|
||||
*/
|
||||
public int get() {
|
||||
return CameraServerJNI.getProperty(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets property value.
|
||||
*
|
||||
* @param value Property value.
|
||||
*/
|
||||
public void set(int value) {
|
||||
CameraServerJNI.setProperty(m_handle, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property minimum value.
|
||||
*
|
||||
* @return Property minimum value.
|
||||
*/
|
||||
public int getMin() {
|
||||
return CameraServerJNI.getPropertyMin(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property maximum value.
|
||||
*
|
||||
* @return Property maximum value.
|
||||
*/
|
||||
public int getMax() {
|
||||
return CameraServerJNI.getPropertyMax(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property step size.
|
||||
*
|
||||
* @return Property step size.
|
||||
*/
|
||||
public int getStep() {
|
||||
return CameraServerJNI.getPropertyStep(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns property default value.
|
||||
*
|
||||
* @return Property default value.
|
||||
*/
|
||||
public int getDefault() {
|
||||
return CameraServerJNI.getPropertyDefault(m_handle);
|
||||
}
|
||||
|
||||
// String-specific functions
|
||||
/**
|
||||
* Returns the string property value.
|
||||
*
|
||||
* <p>This function is string-specific.
|
||||
*
|
||||
* @return The string property value.
|
||||
*/
|
||||
public String getString() {
|
||||
return CameraServerJNI.getStringProperty(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the string property value.
|
||||
*
|
||||
* <p>This function is string-specific.
|
||||
*
|
||||
* @param value String property value.
|
||||
*/
|
||||
public void setString(String value) {
|
||||
CameraServerJNI.setStringProperty(m_handle, value);
|
||||
}
|
||||
|
||||
// Enum-specific functions
|
||||
/**
|
||||
* Returns the possible values for the enum property value.
|
||||
*
|
||||
* <p>This function is enum-specific.
|
||||
*
|
||||
* @return The possible values for the enum property value.
|
||||
*/
|
||||
public String[] getChoices() {
|
||||
return CameraServerJNI.getEnumPropertyChoices(m_handle);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,11 @@ public class VideoSink implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -48,6 +53,11 @@ public class VideoSink implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VideoSink.
|
||||
*
|
||||
* @param handle The video sink handle.
|
||||
*/
|
||||
protected VideoSink(int handle) {
|
||||
m_handle = handle;
|
||||
}
|
||||
@@ -60,10 +70,20 @@ public class VideoSink implements AutoCloseable {
|
||||
m_handle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the VideoSink is valid.
|
||||
*
|
||||
* @return True if the VideoSink is valid.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return m_handle != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the video sink handle.
|
||||
*
|
||||
* @return The video sink handle.
|
||||
*/
|
||||
public int getHandle() {
|
||||
return m_handle;
|
||||
}
|
||||
@@ -222,5 +242,6 @@ public class VideoSink implements AutoCloseable {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** The VideoSink handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import edu.wpi.first.util.PixelFormat;
|
||||
* (e.g. from a stereo or depth camera); these are called channels.
|
||||
*/
|
||||
public class VideoSource implements AutoCloseable {
|
||||
/** Video source kind. */
|
||||
public enum Kind {
|
||||
/** Unknown video source. */
|
||||
kUnknown(0),
|
||||
@@ -29,6 +30,11 @@ public class VideoSource implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -56,6 +62,11 @@ public class VideoSource implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ConnectionStrategy value.
|
||||
*
|
||||
* @return The ConnectionStrategy value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -80,6 +91,11 @@ public class VideoSource implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VideoSource.
|
||||
*
|
||||
* @param handle The video source handle.
|
||||
*/
|
||||
protected VideoSource(int handle) {
|
||||
m_handle = handle;
|
||||
}
|
||||
@@ -92,10 +108,20 @@ public class VideoSource implements AutoCloseable {
|
||||
m_handle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the VideoSource is valid.
|
||||
*
|
||||
* @return True if the VideoSource is valid.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return m_handle != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the video source handle.
|
||||
*
|
||||
* @return The video source handle.
|
||||
*/
|
||||
public int getHandle() {
|
||||
return m_handle;
|
||||
}
|
||||
@@ -379,5 +405,6 @@ public class VideoSource implements AutoCloseable {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Video source handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -58,33 +58,139 @@ class VideoProperty {
|
||||
|
||||
VideoProperty() = default;
|
||||
|
||||
/**
|
||||
* Returns property name.
|
||||
*
|
||||
* @return Property name.
|
||||
*/
|
||||
std::string GetName() const;
|
||||
|
||||
/**
|
||||
* Returns property kind.
|
||||
*
|
||||
* @return Property kind.
|
||||
*/
|
||||
Kind GetKind() const { return m_kind; }
|
||||
|
||||
/**
|
||||
* Returns true if property is valid.
|
||||
*
|
||||
* @return True if property is valid.
|
||||
*/
|
||||
explicit operator bool() const { return m_kind != kNone; }
|
||||
|
||||
// Kind checkers
|
||||
/**
|
||||
* Returns true if property is a boolean.
|
||||
*
|
||||
* @return True if property is a boolean.
|
||||
*/
|
||||
bool IsBoolean() const { return m_kind == kBoolean; }
|
||||
|
||||
/**
|
||||
* Returns true if property is an integer.
|
||||
*
|
||||
* @return True if property is an integer.
|
||||
*/
|
||||
bool IsInteger() const { return m_kind == kInteger; }
|
||||
|
||||
/**
|
||||
* Returns true if property is a string.
|
||||
*
|
||||
* @return True if property is a string.
|
||||
*/
|
||||
bool IsString() const { return m_kind == kString; }
|
||||
|
||||
/**
|
||||
* Returns true if property is an enum.
|
||||
*
|
||||
* @return True if property is an enum.
|
||||
*/
|
||||
bool IsEnum() const { return m_kind == kEnum; }
|
||||
|
||||
/**
|
||||
* Returns property value.
|
||||
*
|
||||
* @return Property value.
|
||||
*/
|
||||
int Get() const;
|
||||
|
||||
/**
|
||||
* Sets property value.
|
||||
*
|
||||
* @param value Property value.
|
||||
*/
|
||||
void Set(int value);
|
||||
|
||||
/**
|
||||
* Returns property minimum value.
|
||||
*
|
||||
* @return Property minimum value.
|
||||
*/
|
||||
int GetMin() const;
|
||||
|
||||
/**
|
||||
* Returns property maximum value.
|
||||
*
|
||||
* @return Property maximum value.
|
||||
*/
|
||||
int GetMax() const;
|
||||
|
||||
/**
|
||||
* Returns property step size.
|
||||
*
|
||||
* @return Property step size.
|
||||
*/
|
||||
int GetStep() const;
|
||||
|
||||
/**
|
||||
* Returns property default value.
|
||||
*
|
||||
* @return Property default value.
|
||||
*/
|
||||
int GetDefault() const;
|
||||
|
||||
// String-specific functions
|
||||
/**
|
||||
* Returns the string property value.
|
||||
*
|
||||
* <p>This function is string-specific.
|
||||
*
|
||||
* @return The string property value.
|
||||
*/
|
||||
std::string GetString() const;
|
||||
|
||||
/**
|
||||
* Returns the string property value as a reference to the given buffer.
|
||||
*
|
||||
* This function is string-specific.
|
||||
*
|
||||
* @param buf The backing storage to which to write the property value.
|
||||
* @return The string property value as a reference to the given buffer.
|
||||
*/
|
||||
std::string_view GetString(wpi::SmallVectorImpl<char>& buf) const;
|
||||
|
||||
/**
|
||||
* Sets the string property value.
|
||||
*
|
||||
* This function is string-specific.
|
||||
*
|
||||
* @param value String property value.
|
||||
*/
|
||||
void SetString(std::string_view value);
|
||||
|
||||
// Enum-specific functions
|
||||
/**
|
||||
* Returns the possible values for the enum property value.
|
||||
*
|
||||
* This function is enum-specific.
|
||||
*
|
||||
* @return The possible values for the enum property value.
|
||||
*/
|
||||
std::vector<std::string> GetChoices() const;
|
||||
|
||||
/**
|
||||
* Returns the last status.
|
||||
*
|
||||
* @return The last status.
|
||||
*/
|
||||
CS_Status GetLastStatus() const { return m_status; }
|
||||
|
||||
private:
|
||||
@@ -104,6 +210,9 @@ class VideoSource {
|
||||
friend class VideoSink;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Video source kind.
|
||||
*/
|
||||
enum Kind {
|
||||
/// Unknown video source.
|
||||
kUnknown = CS_SOURCE_UNKNOWN,
|
||||
@@ -359,6 +468,8 @@ class VideoSource {
|
||||
explicit VideoSource(CS_Source handle) : m_handle(handle) {}
|
||||
|
||||
mutable CS_Status m_status = 0;
|
||||
|
||||
/// Video source handle.
|
||||
CS_Source m_handle{0};
|
||||
};
|
||||
|
||||
@@ -367,11 +478,19 @@ class VideoSource {
|
||||
*/
|
||||
class VideoCamera : public VideoSource {
|
||||
public:
|
||||
/**
|
||||
* White balance.
|
||||
*/
|
||||
enum WhiteBalance {
|
||||
/// Fixed indoor white balance.
|
||||
kFixedIndoor = 3000,
|
||||
/// Fixed outdoor white balance 1.
|
||||
kFixedOutdoor1 = 4000,
|
||||
/// Fixed outdoor white balance 2.
|
||||
kFixedOutdoor2 = 5000,
|
||||
/// Fixed fluorescent white balance 1.
|
||||
kFixedFluorescent1 = 5100,
|
||||
/// Fixed fluorescent white balance 2.
|
||||
kFixedFlourescent2 = 5200
|
||||
};
|
||||
|
||||
@@ -479,6 +598,9 @@ class UsbCamera : public VideoCamera {
|
||||
*/
|
||||
class HttpCamera : public VideoCamera {
|
||||
public:
|
||||
/**
|
||||
* HTTP camera kind.
|
||||
*/
|
||||
enum HttpCameraKind {
|
||||
/// Unknown camera kind.
|
||||
kUnknown = CS_HTTP_UNKNOWN,
|
||||
@@ -743,8 +865,18 @@ class VideoSink {
|
||||
VideoSink& operator=(VideoSink other) noexcept;
|
||||
~VideoSink();
|
||||
|
||||
/**
|
||||
* Returns true if the VideoSink is valid.
|
||||
*
|
||||
* @return True if the VideoSink is valid.
|
||||
*/
|
||||
explicit operator bool() const { return m_handle != 0; }
|
||||
|
||||
/**
|
||||
* Returns the VideoSink handle.
|
||||
*
|
||||
* @return The VideoSink handle.
|
||||
*/
|
||||
int GetHandle() const { return m_handle; }
|
||||
|
||||
bool operator==(const VideoSink& other) const {
|
||||
@@ -988,17 +1120,23 @@ class ImageSink : public VideoSink {
|
||||
class VideoEvent : public RawEvent {
|
||||
public:
|
||||
/**
|
||||
* Get the source associated with the event (if any).
|
||||
* Returns the source associated with the event (if any).
|
||||
*
|
||||
* @return The source associated with the event (if any).
|
||||
*/
|
||||
VideoSource GetSource() const;
|
||||
|
||||
/**
|
||||
* Get the sink associated with the event (if any).
|
||||
* Returns the sink associated with the event (if any).
|
||||
*
|
||||
* @return The sink associated with the event (if any).
|
||||
*/
|
||||
VideoSink GetSink() const;
|
||||
|
||||
/**
|
||||
* Get the property associated with the event (if any).
|
||||
* Returns the property associated with the event (if any).
|
||||
*
|
||||
* @return The property associated with the event (if any).
|
||||
*/
|
||||
VideoProperty GetProperty() const;
|
||||
};
|
||||
|
||||
@@ -29,51 +29,8 @@ model {
|
||||
def applicationPath = binary.executable.file
|
||||
def icon = file("$project.projectDir/src/main/native/mac/datalogtool.icns")
|
||||
|
||||
// Create the macOS bundle.
|
||||
def bundleTask = project.tasks.create("bundleDataLogToolOsxApp" + binary.targetPlatform.architecture.name, Copy) {
|
||||
description("Creates a macOS application bundle for DataLogTool")
|
||||
from(file("$project.projectDir/Info.plist"))
|
||||
into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/Contents"))
|
||||
into("MacOS") {
|
||||
with copySpec {
|
||||
from binary.executable.file
|
||||
}
|
||||
}
|
||||
into("Resources") {
|
||||
with copySpec {
|
||||
from icon
|
||||
}
|
||||
}
|
||||
|
||||
inputs.property "HasDeveloperId", project.hasProperty("developerID")
|
||||
|
||||
doLast {
|
||||
if (project.hasProperty("developerID")) {
|
||||
// Get path to binary.
|
||||
exec {
|
||||
workingDir rootDir
|
||||
def args = [
|
||||
"sh",
|
||||
"-c",
|
||||
"codesign --force --strict --deep " +
|
||||
"--timestamp --options=runtime " +
|
||||
"--verbose -s ${project.findProperty("developerID")} " +
|
||||
"$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/"
|
||||
]
|
||||
commandLine args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the application path if we are creating a bundle.
|
||||
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name")
|
||||
project.build.dependsOn bundleTask
|
||||
}
|
||||
|
||||
// Create the ZIP.
|
||||
def task = project.tasks.create("copyDataLogToolExecutable" + binary.targetPlatform.architecture.name, Zip) {
|
||||
def task = project.tasks.create("copyDataLogToolExecutable" + binary.targetPlatform.operatingSystem.name + binary.targetPlatform.architecture.name, Zip) {
|
||||
description("Copies the DataLogTool executable to the outputs directory.")
|
||||
destinationDirectory = outputsFolder
|
||||
|
||||
@@ -85,13 +42,63 @@ model {
|
||||
into '/'
|
||||
}
|
||||
|
||||
from(applicationPath)
|
||||
if (binary.targetPlatform.operatingSystem.isWindows()) {
|
||||
def exePath = binary.executable.file.absolutePath
|
||||
exePath = exePath.substring(0, exePath.length() - 4)
|
||||
def pdbPath = new File(exePath + '.pdb')
|
||||
from(pdbPath)
|
||||
}
|
||||
|
||||
into(nativeUtils.getPlatformPath(binary))
|
||||
}
|
||||
|
||||
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
// Create the macOS bundle.
|
||||
def bundleTask = project.tasks.create("bundleDataLogToolOsxApp" + binary.targetPlatform.architecture.name, Copy) {
|
||||
description("Creates a macOS application bundle for DataLogTool")
|
||||
from(file("$project.projectDir/Info.plist"))
|
||||
into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/Contents"))
|
||||
into("MacOS") {
|
||||
with copySpec {
|
||||
from binary.executable.file
|
||||
}
|
||||
}
|
||||
into("Resources") {
|
||||
with copySpec {
|
||||
from icon
|
||||
}
|
||||
}
|
||||
|
||||
inputs.property "HasDeveloperId", project.hasProperty("developerID")
|
||||
|
||||
doLast {
|
||||
if (project.hasProperty("developerID")) {
|
||||
// Get path to binary.
|
||||
exec {
|
||||
workingDir rootDir
|
||||
def args = [
|
||||
"sh",
|
||||
"-c",
|
||||
"codesign --force --strict --deep " +
|
||||
"--timestamp --options=runtime " +
|
||||
"--verbose -s ${project.findProperty("developerID")} " +
|
||||
"$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/DataLogTool.app/"
|
||||
]
|
||||
commandLine args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the application path if we are creating a bundle.
|
||||
applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name")
|
||||
task.from(applicationPath)
|
||||
project.build.dependsOn bundleTask
|
||||
|
||||
bundleTask.dependsOn binary.tasks.link
|
||||
task.dependsOn(bundleTask)
|
||||
} else {
|
||||
task.from(applicationPath)
|
||||
}
|
||||
|
||||
task.dependsOn binary.tasks.link
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <string_view>
|
||||
|
||||
void Application(std::string_view saveDir);
|
||||
|
||||
#ifdef _WIN32
|
||||
int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
|
||||
int nCmdShow) {
|
||||
int argc = __argc;
|
||||
char** argv = __argv;
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
#endif
|
||||
std::string_view saveDir;
|
||||
if (argc == 2) {
|
||||
saveDir = argv[1];
|
||||
}
|
||||
|
||||
Application(saveDir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <string_view>
|
||||
|
||||
void Application(std::string_view saveDir);
|
||||
|
||||
#ifdef _WIN32
|
||||
int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
|
||||
int nCmdShow) {
|
||||
int argc = __argc;
|
||||
char** argv = __argv;
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
#endif
|
||||
std::string_view saveDir;
|
||||
if (argc == 2) {
|
||||
saveDir = argv[1];
|
||||
}
|
||||
|
||||
Application(saveDir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,13 @@ task generateJavaDocs(type: Javadoc) {
|
||||
options.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
|
||||
options.links("https://docs.opencv.org/4.x/javadoc/")
|
||||
options.addStringOption("tag", "pre:a:Pre-Condition")
|
||||
options.addBooleanOption("Xdoclint/package:-edu.wpi.first.math.proto," +
|
||||
options.addBooleanOption("Xdoclint/package:" +
|
||||
// TODO: v Document these, then remove them from the list
|
||||
"-edu.wpi.first.hal," +
|
||||
"-edu.wpi.first.hal.can," +
|
||||
"-edu.wpi.first.hal.simulation," +
|
||||
// TODO: ^ Document these, then remove them from the list
|
||||
"-edu.wpi.first.math.proto," +
|
||||
"-edu.wpi.first.math.controller.proto," +
|
||||
"-edu.wpi.first.math.controller.struct," +
|
||||
"-edu.wpi.first.math.geometry.proto," +
|
||||
|
||||
@@ -40,12 +40,10 @@ public class FieldConfig {
|
||||
|
||||
public FieldConfig() {}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public URL getImageUrl() {
|
||||
return getClass().getResource(Fields.kBaseResourceDir + m_fieldImage);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public InputStream getImageAsStream() {
|
||||
return getClass().getResourceAsStream(Fields.kBaseResourceDir + m_fieldImage);
|
||||
}
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
"field-image": "2024-field.png",
|
||||
"field-corners": {
|
||||
"top-left": [
|
||||
46,
|
||||
36
|
||||
150,
|
||||
79
|
||||
],
|
||||
"bottom-right": [
|
||||
1088,
|
||||
544
|
||||
2961,
|
||||
1476
|
||||
]
|
||||
},
|
||||
"field-size": [
|
||||
54.27083,
|
||||
26.2916
|
||||
26.9375
|
||||
],
|
||||
"field-unit": "foot"
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 2.2 MiB |
@@ -97,8 +97,6 @@ model {
|
||||
into '/'
|
||||
}
|
||||
|
||||
from(applicationPath)
|
||||
|
||||
if (binary.targetPlatform.operatingSystem.isWindows()) {
|
||||
def exePath = binary.executable.file.absolutePath
|
||||
exePath = exePath.substring(0, exePath.length() - 4)
|
||||
@@ -149,10 +147,13 @@ model {
|
||||
|
||||
// Reset the application path if we are creating a bundle.
|
||||
applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name")
|
||||
task.from(applicationPath)
|
||||
project.build.dependsOn bundleTask
|
||||
|
||||
bundleTask.dependsOn binary.tasks.link
|
||||
task.dependsOn(bundleTask)
|
||||
} else {
|
||||
task.from(applicationPath)
|
||||
}
|
||||
|
||||
task.dependsOn binary.tasks.link
|
||||
|
||||
@@ -96,7 +96,7 @@ static void NtInitialize() {
|
||||
auto inst = nt::GetDefaultInstance();
|
||||
auto poller = nt::CreateListenerPoller(inst);
|
||||
nt::AddPolledListener(poller, inst, NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
||||
nt::AddPolledLogger(poller, 0, 100);
|
||||
nt::AddPolledLogger(poller, NT_LOG_INFO, 100);
|
||||
gui::AddEarlyExecute([inst, poller] {
|
||||
auto win = gui::GetSystemWindow();
|
||||
if (!win) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "glass/other/FMS.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_stdlib.h>
|
||||
#include <wpi/SmallString.h>
|
||||
|
||||
#include "glass/DataSource.h"
|
||||
@@ -14,7 +15,7 @@ using namespace glass;
|
||||
static const char* stations[] = {"Invalid", "Red 1", "Red 2", "Red 3",
|
||||
"Blue 1", "Blue 2", "Blue 3"};
|
||||
|
||||
void glass::DisplayFMS(FMSModel* model) {
|
||||
void glass::DisplayFMS(FMSModel* model, bool editableDsAttached) {
|
||||
if (!model->Exists() || model->IsReadOnly()) {
|
||||
return DisplayFMSReadOnly(model);
|
||||
}
|
||||
@@ -31,10 +32,17 @@ void glass::DisplayFMS(FMSModel* model) {
|
||||
// DS Attached
|
||||
if (auto data = model->GetDsAttachedData()) {
|
||||
bool val = data->GetValue();
|
||||
if (ImGui::Checkbox("DS Attached", &val)) {
|
||||
model->SetDsAttached(val);
|
||||
if (editableDsAttached) {
|
||||
if (ImGui::Checkbox("DS Attached", &val)) {
|
||||
model->SetDsAttached(val);
|
||||
}
|
||||
data->EmitDrag();
|
||||
} else {
|
||||
ImGui::Selectable("DS Attached: ");
|
||||
data->EmitDrag();
|
||||
ImGui::SameLine();
|
||||
ImGui::TextUnformatted(val ? "Yes" : "No");
|
||||
}
|
||||
data->EmitDrag();
|
||||
}
|
||||
|
||||
// Alliance Station
|
||||
@@ -51,8 +59,7 @@ void glass::DisplayFMS(FMSModel* model) {
|
||||
if (auto data = model->GetMatchTimeData()) {
|
||||
double val = data->GetValue();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
if (ImGui::InputDouble("Match Time", &val, 0, 0, "%.1f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
if (ImGui::InputDouble("Match Time", &val, 0, 0, "%.1f")) {
|
||||
model->SetMatchTime(val);
|
||||
}
|
||||
data->EmitDrag();
|
||||
@@ -71,16 +78,12 @@ void glass::DisplayFMS(FMSModel* model) {
|
||||
}
|
||||
|
||||
// Game Specific Message
|
||||
// make buffer full 64 width, null terminated, for editability
|
||||
wpi::SmallString<64> gameSpecificMessage;
|
||||
model->GetGameSpecificMessage(gameSpecificMessage);
|
||||
gameSpecificMessage.resize(63);
|
||||
gameSpecificMessage.push_back('\0');
|
||||
wpi::SmallString<64> gameSpecificMessageBuf;
|
||||
std::string gameSpecificMessage{
|
||||
model->GetGameSpecificMessage(gameSpecificMessageBuf)};
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
if (ImGui::InputText("Game Specific", gameSpecificMessage.data(),
|
||||
gameSpecificMessage.size(),
|
||||
ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
model->SetGameSpecificMessage(gameSpecificMessage.data());
|
||||
if (ImGui::InputText("Game Specific", &gameSpecificMessage)) {
|
||||
model->SetGameSpecificMessage(gameSpecificMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,9 +147,10 @@ void glass::DisplayFMSReadOnly(FMSModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
wpi::SmallString<64> gameSpecificMessage;
|
||||
model->GetGameSpecificMessage(gameSpecificMessage);
|
||||
ImGui::Text("Game Specific: %s", exists ? gameSpecificMessage.c_str() : "?");
|
||||
wpi::SmallString<64> gameSpecificMessageBuf;
|
||||
std::string_view gameSpecificMessage =
|
||||
model->GetGameSpecificMessage(gameSpecificMessageBuf);
|
||||
ImGui::Text("Game Specific: %s", exists ? gameSpecificMessage.data() : "?");
|
||||
|
||||
if (!exists) {
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
@@ -222,8 +222,8 @@ class ObjectInfo {
|
||||
|
||||
class FieldInfo {
|
||||
public:
|
||||
static constexpr auto kDefaultWidth = 15.98_m;
|
||||
static constexpr auto kDefaultHeight = 8.21_m;
|
||||
static constexpr auto kDefaultWidth = 16.541052_m;
|
||||
static constexpr auto kDefaultHeight = 8.211_m;
|
||||
|
||||
explicit FieldInfo(Storage& storage);
|
||||
|
||||
@@ -343,7 +343,7 @@ static bool InputPose(frc::Pose2d* pose) {
|
||||
}
|
||||
|
||||
FieldInfo::FieldInfo(Storage& storage)
|
||||
: m_builtin{storage.GetString("builtin")},
|
||||
: m_builtin{storage.GetString("builtin", "2024 Crescendo")},
|
||||
m_filename{storage.GetString("image")},
|
||||
m_width{storage.GetFloat("width", kDefaultWidth.to<float>())},
|
||||
m_height{storage.GetFloat("height", kDefaultHeight.to<float>())},
|
||||
@@ -508,6 +508,16 @@ bool FieldInfo::LoadJson(std::span<const char> is, std::string_view filename) {
|
||||
height = units::convert<units::feet, units::meters>(height);
|
||||
}
|
||||
|
||||
// check scaling
|
||||
int fieldWidth = m_right - m_left;
|
||||
int fieldHeight = m_bottom - m_top;
|
||||
if (std::abs((fieldWidth / width) - (fieldHeight / height)) > 0.3) {
|
||||
fmt::print(stderr,
|
||||
"GUI: Field X and Y scaling substantially different: "
|
||||
"xscale={} yscale={}\n",
|
||||
(fieldWidth / width), (fieldHeight / height));
|
||||
}
|
||||
|
||||
if (!filename.empty()) {
|
||||
// the image filename is relative to the json file
|
||||
auto pathname = fs::path{filename}.replace_filename(image).string();
|
||||
@@ -560,23 +570,29 @@ FieldFrameData FieldInfo::GetFrameData(ImVec2 min, ImVec2 max) const {
|
||||
// fit the image into the window
|
||||
if (m_texture && m_imageHeight != 0 && m_imageWidth != 0) {
|
||||
gui::MaxFit(&min, &max, m_imageWidth, m_imageHeight);
|
||||
} else {
|
||||
gui::MaxFit(&min, &max, m_width, m_height);
|
||||
}
|
||||
|
||||
FieldFrameData ffd;
|
||||
ffd.imageMin = min;
|
||||
ffd.imageMax = max;
|
||||
|
||||
// size down the box by the image corners (if any)
|
||||
if (m_bottom > 0 && m_right > 0) {
|
||||
min.x += m_left * (max.x - min.x) / m_imageWidth;
|
||||
min.y += m_top * (max.y - min.y) / m_imageHeight;
|
||||
max.x -= (m_imageWidth - m_right) * (max.x - min.x) / m_imageWidth;
|
||||
max.y -= (m_imageHeight - m_bottom) * (max.y - min.y) / m_imageHeight;
|
||||
if (m_bottom > 0 && m_right > 0 && m_imageWidth != 0) {
|
||||
// size down the box by the image corners
|
||||
float scale = (max.x - min.x) / m_imageWidth;
|
||||
min.x += m_left * scale;
|
||||
min.y += m_top * scale;
|
||||
max.x -= (m_imageWidth - m_right) * scale;
|
||||
max.y -= (m_imageHeight - m_bottom) * scale;
|
||||
} else if ((max.x - min.x) > 40 && (max.y - min.y > 40)) {
|
||||
// ensure there's some padding
|
||||
min.x += 20;
|
||||
max.x -= 20;
|
||||
min.y += 20;
|
||||
max.y -= 20;
|
||||
}
|
||||
|
||||
// draw the field "active area" as a yellow boundary box
|
||||
gui::MaxFit(&min, &max, m_width, m_height);
|
||||
|
||||
ffd.min = min;
|
||||
ffd.max = max;
|
||||
ffd.scale = (max.x - min.x) / m_width;
|
||||
|
||||
@@ -46,8 +46,9 @@ class FMSModel : public Model {
|
||||
*
|
||||
* @param matchTimeEnabled If not null, a checkbox is displayed for
|
||||
* "enable match time" linked to this value
|
||||
* @param editableDsAttached If true, DS attached should be editable
|
||||
*/
|
||||
void DisplayFMS(FMSModel* model);
|
||||
void DisplayFMS(FMSModel* model, bool editableDsAttached);
|
||||
void DisplayFMSReadOnly(FMSModel* model);
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -63,7 +63,7 @@ void glass::AddStandardNetworkTablesViews(NetworkTablesProvider& provider) {
|
||||
[](Window* win, Model* model, const char*) {
|
||||
win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize);
|
||||
return MakeFunctionView(
|
||||
[=] { DisplayFMS(static_cast<FMSModel*>(model)); });
|
||||
[=] { DisplayFMS(static_cast<FMSModel*>(model), true); });
|
||||
});
|
||||
provider.Register(
|
||||
NTDigitalInputModel::kType,
|
||||
|
||||
@@ -20,7 +20,6 @@ generatedFileExclude {
|
||||
modifiableFileExclude {
|
||||
\.patch$
|
||||
\.png$
|
||||
\.py$
|
||||
\.so$
|
||||
}
|
||||
|
||||
|
||||
@@ -10,40 +10,56 @@ def main():
|
||||
# Gets the folder this script is in (the hal/ directory)
|
||||
HAL_ROOT = pathlib.Path(__file__).parent
|
||||
java_package = "edu/wpi/first/hal"
|
||||
(HAL_ROOT/"src/generated/main/native/include/hal").mkdir(parents=True, exist_ok=True)
|
||||
(HAL_ROOT/f"src/generated/main/java/{java_package}").mkdir(parents=True, exist_ok=True)
|
||||
usage_reporting_types_cpp = []
|
||||
# fmt: off
|
||||
(HAL_ROOT / "src/generated/main/native/include/hal").mkdir(parents=True, exist_ok=True)
|
||||
(HAL_ROOT / f"src/generated/main/java/{java_package}").mkdir(parents=True, exist_ok=True)
|
||||
# fmt: on
|
||||
usage_reporting_types_cpp = []
|
||||
usage_reporting_instances_cpp = []
|
||||
usage_reporting_types = []
|
||||
usage_reporting_instances = []
|
||||
with open(HAL_ROOT/"src/generate/Instances.txt") as instances:
|
||||
with open(HAL_ROOT / "src/generate/Instances.txt") as instances:
|
||||
for instance in instances:
|
||||
usage_reporting_instances_cpp.append(f" {instance.strip()},")
|
||||
usage_reporting_instances.append(
|
||||
f" /** {instance.strip()}. */\n"
|
||||
f" public static final int {instance.strip()};")
|
||||
f" public static final int {instance.strip()};"
|
||||
)
|
||||
|
||||
with open(HAL_ROOT/"src/generate/ResourceType.txt") as resource_types:
|
||||
with open(HAL_ROOT / "src/generate/ResourceType.txt") as resource_types:
|
||||
for resource_type in resource_types:
|
||||
usage_reporting_types_cpp.append(f" {resource_type.strip()},")
|
||||
usage_reporting_types.append(
|
||||
f" /** {resource_type.strip()}. */\n"
|
||||
f" public static final int {resource_type.strip()};")
|
||||
f" public static final int {resource_type.strip()};"
|
||||
)
|
||||
|
||||
with open(HAL_ROOT/"src/generate/FRCNetComm.java.in") as java_usage_reporting:
|
||||
contents = (java_usage_reporting.read()
|
||||
with open(HAL_ROOT / "src/generate/FRCNetComm.java.in") as java_usage_reporting:
|
||||
contents = (
|
||||
# fmt: off
|
||||
java_usage_reporting.read()
|
||||
.replace(r"${usage_reporting_types}", "\n".join(usage_reporting_types))
|
||||
.replace(r"${usage_reporting_instances}", "\n".join(usage_reporting_instances)))
|
||||
|
||||
with open(HAL_ROOT/f"src/generated/main/java/{java_package}/FRCNetComm.java", "w") as java_out:
|
||||
.replace(r"${usage_reporting_instances}", "\n".join(usage_reporting_instances))
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
with open(
|
||||
HAL_ROOT / f"src/generated/main/java/{java_package}/FRCNetComm.java", "w"
|
||||
) as java_out:
|
||||
java_out.write(contents)
|
||||
|
||||
with open(HAL_ROOT/"src/generate/FRCUsageReporting.h.in") as cpp_usage_reporting:
|
||||
contents = (cpp_usage_reporting.read()
|
||||
with open(HAL_ROOT / "src/generate/FRCUsageReporting.h.in") as cpp_usage_reporting:
|
||||
contents = (
|
||||
# fmt: off
|
||||
cpp_usage_reporting.read()
|
||||
.replace(r"${usage_reporting_types_cpp}", "\n".join(usage_reporting_types_cpp))
|
||||
.replace(r"${usage_reporting_instances_cpp}", "\n".join(usage_reporting_instances_cpp)))
|
||||
.replace(r"${usage_reporting_instances_cpp}", "\n".join(usage_reporting_instances_cpp))
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
with open(HAL_ROOT/"src/generated/main/native/include/hal/FRCUsageReporting.h", "w") as cpp_out:
|
||||
with open(
|
||||
HAL_ROOT / "src/generated/main/native/include/hal/FRCUsageReporting.h", "w"
|
||||
) as cpp_out:
|
||||
cpp_out.write(contents)
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@ public final class HAL extends JNIWrapper {
|
||||
*/
|
||||
public static native void exitMain();
|
||||
|
||||
/** Terminates the executable (at the native level). Does nothing in simulation. */
|
||||
public static native void terminate();
|
||||
|
||||
private static native void simPeriodicBeforeNative();
|
||||
|
||||
private static final List<Runnable> s_simPeriodicBefore = new ArrayList<>();
|
||||
|
||||
@@ -83,6 +83,8 @@ public class PowerDistributionJNI extends JNIWrapper {
|
||||
/**
|
||||
* Gets the temperature of the PowerDistribution.
|
||||
*
|
||||
* <p>Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param handle the module handle
|
||||
* @return the module temperature (celsius)
|
||||
* @see "HAL_GetPowerDistributionTemperature"
|
||||
@@ -129,7 +131,9 @@ public class PowerDistributionJNI extends JNIWrapper {
|
||||
public static native double getTotalCurrent(int handle);
|
||||
|
||||
/**
|
||||
* Gets the total power of the PowerDistribution.
|
||||
* Gets the total power of the Power Distribution Panel.
|
||||
*
|
||||
* <p>Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param handle the module handle
|
||||
* @return the total power (watts)
|
||||
@@ -138,7 +142,9 @@ public class PowerDistributionJNI extends JNIWrapper {
|
||||
public static native double getTotalPower(int handle);
|
||||
|
||||
/**
|
||||
* Gets the total energy of the PowerDistribution.
|
||||
* Gets the total energy of the Power Distribution Panel.
|
||||
*
|
||||
* <p>Not supported on the Rev PDH and does nothing.
|
||||
*
|
||||
* @param handle the module handle
|
||||
* @return the total energy (joules)
|
||||
@@ -147,7 +153,9 @@ public class PowerDistributionJNI extends JNIWrapper {
|
||||
public static native double getTotalEnergy(int handle);
|
||||
|
||||
/**
|
||||
* Resets the PowerDistribution accumulated energy.
|
||||
* Resets the Power Distribution Panel accumulated energy.
|
||||
*
|
||||
* <p>Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param handle the module handle
|
||||
* @see "HAL_ClearPowerDistributionStickyFaults"
|
||||
|
||||
@@ -7,6 +7,9 @@ package edu.wpi.first.hal.can;
|
||||
import edu.wpi.first.hal.communication.NIRioStatus;
|
||||
import edu.wpi.first.hal.util.UncleanStatusException;
|
||||
|
||||
/**
|
||||
* Checks the status of a CAN message and throws an exception of the appropriate type if necessary.
|
||||
*/
|
||||
public final class CANExceptionFactory {
|
||||
// FRC Error codes
|
||||
static final int ERR_CANSessionMux_InvalidBuffer = -44086;
|
||||
|
||||
@@ -16,11 +16,16 @@ import java.nio.IntBuffer;
|
||||
*/
|
||||
@SuppressWarnings("MethodName")
|
||||
public class CANJNI extends JNIWrapper {
|
||||
/** Flag for sending a CAN message once. */
|
||||
public static final int CAN_SEND_PERIOD_NO_REPEAT = 0;
|
||||
|
||||
/** Flag for stopping periodic CAN message sends. */
|
||||
public static final int CAN_SEND_PERIOD_STOP_REPEATING = -1;
|
||||
|
||||
/* Flags in the upper bits of the messageID */
|
||||
/** Mask for "is frame remote" in message ID. */
|
||||
public static final int CAN_IS_FRAME_REMOTE = 0x80000000;
|
||||
|
||||
/** Mask for "is frame 11 bits" in message ID. */
|
||||
public static final int CAN_IS_FRAME_11BIT = 0x40000000;
|
||||
|
||||
/** Default constructor. */
|
||||
|
||||
@@ -4,13 +4,24 @@
|
||||
|
||||
package edu.wpi.first.hal.communication;
|
||||
|
||||
/** NI RIO status. */
|
||||
public class NIRioStatus {
|
||||
/** RIO status offset. */
|
||||
public static final int kRioStatusOffset = -63000;
|
||||
|
||||
/** Success. */
|
||||
public static final int kRioStatusSuccess = 0;
|
||||
|
||||
/** Buffer invalid size. */
|
||||
public static final int kRIOStatusBufferInvalidSize = kRioStatusOffset - 80;
|
||||
|
||||
/** Operation timed out. */
|
||||
public static final int kRIOStatusOperationTimedOut = -52007;
|
||||
|
||||
/** Feature not supported. */
|
||||
public static final int kRIOStatusFeatureNotSupported = kRioStatusOffset - 193;
|
||||
|
||||
/** Resource not initialized. */
|
||||
public static final int kRIOStatusResourceNotInitialized = -52010;
|
||||
|
||||
/** Default constructor. */
|
||||
|
||||
@@ -198,6 +198,10 @@ void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
|
||||
return;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(led->ledBuffer, data, length * sizeof(HAL_AddressableLEDData));
|
||||
|
||||
asm("dmb");
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "AnalogInternal.h"
|
||||
#include "ConstantsInternal.h"
|
||||
#include "DigitalInternal.h"
|
||||
@@ -676,7 +678,7 @@ void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
|
||||
SET_SIZE(Enable_DutyCycle_Low);
|
||||
SET_SIZE(Enable_DutyCycle_High);
|
||||
#undef SET_SIZE
|
||||
dma->captureStore.captureSize = accum_size + 1;
|
||||
dma->captureStore.captureSize = accum_size + 2;
|
||||
}
|
||||
|
||||
uint32_t byteDepth = queueDepth * dma->captureStore.captureSize;
|
||||
@@ -734,12 +736,22 @@ enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
|
||||
static_cast<uint32_t>(timeoutSeconds * 1000),
|
||||
&remainingBytes, status);
|
||||
|
||||
if ((remainingBytes % dma->captureStore.captureSize) != 0) {
|
||||
fmt::print(
|
||||
"Remaining bytes {} is not a multiple of capture size {}. This is "
|
||||
"likely a "
|
||||
"bug in WPILib. Please report this issue with a copy of your code.\n",
|
||||
remainingBytes, dma->captureStore.captureSize);
|
||||
}
|
||||
|
||||
*remainingOut = remainingBytes / dma->captureStore.captureSize;
|
||||
|
||||
if (*status == 0) {
|
||||
uint32_t lower_sample =
|
||||
uint64_t upper_sample =
|
||||
dmaSample->readBuffer[dma->captureStore.captureSize - 1];
|
||||
dmaSample->timeStamp = HAL_ExpandFPGATime(lower_sample, status);
|
||||
uint64_t lower_sample =
|
||||
dmaSample->readBuffer[dma->captureStore.captureSize - 2];
|
||||
dmaSample->timeStamp = (upper_sample << 32) + lower_sample;
|
||||
if (*status != 0) {
|
||||
return HAL_DMA_ERROR;
|
||||
}
|
||||
|
||||
@@ -539,15 +539,25 @@ HAL_Bool HAL_RefreshDSData(void) {
|
||||
}
|
||||
// If newest state shows we have a DS attached, just use the
|
||||
// control word out of the cache, As it will be the one in sync
|
||||
// with the data. Otherwise use the state that shows disconnected.
|
||||
if (controlWord.dsAttached) {
|
||||
newestControlWord = currentRead->controlWord;
|
||||
} else {
|
||||
// Zero out the control word. When the DS has never been connected
|
||||
// this returns garbage. And there is no way we can detect that.
|
||||
std::memset(&controlWord, 0, sizeof(controlWord));
|
||||
newestControlWord = controlWord;
|
||||
// with the data. If no data has been updated, at this point,
|
||||
// and a DS wasn't attached previously, this will still return
|
||||
// a zeroed out control word, with is the correct state for
|
||||
// no new data.
|
||||
if (!controlWord.dsAttached) {
|
||||
// If the DS is not attached, we need to zero out the control word.
|
||||
// This is because HAL_RefreshDSData is called asynchronously from
|
||||
// the DS data. The dsAttached variable comes directly from netcomm
|
||||
// and could be updated before the caches are. If that happens,
|
||||
// we would end up returning the previous cached control word,
|
||||
// which is out of sync with the current control word and could
|
||||
// break invariants such as which alliance station is in used.
|
||||
// Also, when the DS has never been connected the rest of the fields
|
||||
// in control word are garbage, so we also need to zero out in that
|
||||
// case too
|
||||
std::memset(¤tRead->controlWord, 0,
|
||||
sizeof(currentRead->controlWord));
|
||||
}
|
||||
newestControlWord = currentRead->controlWord;
|
||||
}
|
||||
|
||||
uint32_t mask = tcpMask.exchange(0);
|
||||
|
||||
@@ -524,7 +524,7 @@ static bool killExistingProgram(int timeout, int mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetupNowRio(void) {
|
||||
static bool SetupNowRio(void) {
|
||||
nFPGA::nRoboRIO_FPGANamespace::g_currentTargetClass =
|
||||
nLoadOut::getTargetClass();
|
||||
|
||||
@@ -534,13 +534,13 @@ static void SetupNowRio(void) {
|
||||
status = dladdr(reinterpret_cast<void*>(tHMB::create), &info);
|
||||
if (status == 0) {
|
||||
fmt::print(stderr, "Failed to call dladdr on chipobject {}\n", dlerror());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
void* chipObjectLibrary = dlopen(info.dli_fname, RTLD_LAZY);
|
||||
if (chipObjectLibrary == nullptr) {
|
||||
fmt::print(stderr, "Failed to call dlopen on chipobject {}\n", dlerror());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<tHMB> hmb;
|
||||
@@ -548,9 +548,9 @@ static void SetupNowRio(void) {
|
||||
if (hmb == nullptr) {
|
||||
fmt::print(stderr, "Failed to open HMB on chipobject {}\n", status);
|
||||
dlclose(chipObjectLibrary);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
wpi::impl::SetupNowRio(chipObjectLibrary, std::move(hmb));
|
||||
return wpi::impl::SetupNowRio(chipObjectLibrary, std::move(hmb));
|
||||
}
|
||||
|
||||
HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
|
||||
@@ -593,7 +593,17 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
|
||||
setNewDataSem(nullptr);
|
||||
});
|
||||
|
||||
SetupNowRio();
|
||||
if (!SetupNowRio()) {
|
||||
fmt::print(stderr,
|
||||
"Failed to run SetupNowRio(). This is a fatal error. The "
|
||||
"process is being terminated.\n");
|
||||
std::fflush(stderr);
|
||||
// Attempt to force a segfault to get a better java log
|
||||
*reinterpret_cast<int*>(0) = 0;
|
||||
// If that fails, terminate
|
||||
std::terminate();
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@@ -82,6 +86,20 @@ Java_edu_wpi_first_hal_HAL_exitMain
|
||||
HAL_ExitMain();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_HAL
|
||||
* Method: terminate
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_HAL_terminate
|
||||
(JNIEnv*, jclass)
|
||||
{
|
||||
#ifdef __FRC_ROBORIO__
|
||||
::raise(SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_HAL
|
||||
* Method: simPeriodicBeforeNative
|
||||
|
||||
@@ -14,11 +14,24 @@
|
||||
|
||||
// These are copies of defines located in CANSessionMux.h prepended with HAL_
|
||||
|
||||
/**
|
||||
* Flag for sending a CAN message once.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_NO_REPEAT 0
|
||||
|
||||
/**
|
||||
* Flag for stopping periodic CAN message sends.
|
||||
*/
|
||||
#define HAL_CAN_SEND_PERIOD_STOP_REPEATING -1
|
||||
|
||||
/* Flags in the upper bits of the messageID */
|
||||
/**
|
||||
* Mask for "is frame remote" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_REMOTE 0x80000000
|
||||
|
||||
/**
|
||||
* Mask for "is frame 11 bits" in message ID.
|
||||
*/
|
||||
#define HAL_CAN_IS_FRAME_11BIT 0x40000000
|
||||
|
||||
#define HAL_ERR_CANSessionMux_InvalidBuffer -44086
|
||||
|
||||
@@ -101,7 +101,9 @@ int32_t HAL_GetPowerDistributionNumChannels(HAL_PowerDistributionHandle handle,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the temperature of the PowerDistribution.
|
||||
* Gets the temperature of the Power Distribution Panel.
|
||||
*
|
||||
* Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param[in] handle the module handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
@@ -156,7 +158,9 @@ double HAL_GetPowerDistributionTotalCurrent(HAL_PowerDistributionHandle handle,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the total power of the PowerDistribution.
|
||||
* Gets the total power of the Power Distribution Panel.
|
||||
*
|
||||
* Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param[in] handle the module handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
@@ -166,7 +170,9 @@ double HAL_GetPowerDistributionTotalPower(HAL_PowerDistributionHandle handle,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the total energy of the PowerDistribution.
|
||||
* Gets the total energy of the Power Distribution Panel.
|
||||
*
|
||||
* Not supported on the Rev PDH and returns 0.
|
||||
*
|
||||
* @param[in] handle the module handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
@@ -178,6 +184,8 @@ double HAL_GetPowerDistributionTotalEnergy(HAL_PowerDistributionHandle handle,
|
||||
/**
|
||||
* Resets the PowerDistribution accumulated energy.
|
||||
*
|
||||
* Not supported on the Rev PDH and does nothing.
|
||||
*
|
||||
* @param[in] handle the module handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
|
||||
@@ -44,6 +44,7 @@ struct JoystickDataCache {
|
||||
HAL_JoystickButtons buttons[kJoystickPorts];
|
||||
HAL_AllianceStationID allianceStation;
|
||||
double matchTime;
|
||||
HAL_ControlWord controlWord;
|
||||
};
|
||||
static_assert(std::is_standard_layout_v<JoystickDataCache>);
|
||||
// static_assert(std::is_trivial_v<JoystickDataCache>);
|
||||
@@ -65,6 +66,16 @@ void JoystickDataCache::Update() {
|
||||
}
|
||||
allianceStation = SimDriverStationData->allianceStationId;
|
||||
matchTime = SimDriverStationData->matchTime;
|
||||
|
||||
HAL_ControlWord tmpControlWord;
|
||||
std::memset(&tmpControlWord, 0, sizeof(tmpControlWord));
|
||||
tmpControlWord.enabled = SimDriverStationData->enabled;
|
||||
tmpControlWord.autonomous = SimDriverStationData->autonomous;
|
||||
tmpControlWord.test = SimDriverStationData->test;
|
||||
tmpControlWord.eStop = SimDriverStationData->eStop;
|
||||
tmpControlWord.fmsAttached = SimDriverStationData->fmsAttached;
|
||||
tmpControlWord.dsAttached = SimDriverStationData->dsAttached;
|
||||
this->controlWord = tmpControlWord;
|
||||
}
|
||||
|
||||
#define CHECK_JOYSTICK_NUMBER(stickNum) \
|
||||
@@ -322,20 +333,32 @@ HAL_Bool HAL_RefreshDSData(void) {
|
||||
if (gShutdown) {
|
||||
return false;
|
||||
}
|
||||
HAL_ControlWord controlWord;
|
||||
std::memset(&controlWord, 0, sizeof(controlWord));
|
||||
controlWord.enabled = SimDriverStationData->enabled;
|
||||
controlWord.autonomous = SimDriverStationData->autonomous;
|
||||
controlWord.test = SimDriverStationData->test;
|
||||
controlWord.eStop = SimDriverStationData->eStop;
|
||||
controlWord.fmsAttached = SimDriverStationData->fmsAttached;
|
||||
controlWord.dsAttached = SimDriverStationData->dsAttached;
|
||||
bool dsAttached = SimDriverStationData->dsAttached;
|
||||
std::scoped_lock lock{driverStation->cacheMutex};
|
||||
JoystickDataCache* prev = currentCache.exchange(nullptr);
|
||||
if (prev != nullptr) {
|
||||
currentRead = prev;
|
||||
}
|
||||
newestControlWord = controlWord;
|
||||
// If newest state shows we have a DS attached, just use the
|
||||
// control word out of the cache, As it will be the one in sync
|
||||
// with the data. If no data has been updated, at this point,
|
||||
// and a DS wasn't attached previously, this will still return
|
||||
// a zeroed out control word, with is the correct state for
|
||||
// no new data.
|
||||
if (!dsAttached) {
|
||||
// If the DS is not attached, we need to zero out the control word.
|
||||
// This is because HAL_RefreshDSData is called asynchronously from
|
||||
// the DS data. The dsAttached variable comes directly from netcomm
|
||||
// and could be updated before the caches are. If that happens,
|
||||
// we would end up returning the previous cached control word,
|
||||
// which is out of sync with the current control word and could
|
||||
// break invariants such as which alliance station is in used.
|
||||
// Also, when the DS has never been connected the rest of the fields
|
||||
// in control word are garbage, so we also need to zero out in that
|
||||
// case too
|
||||
std::memset(¤tRead->controlWord, 0, sizeof(currentRead->controlWord));
|
||||
}
|
||||
newestControlWord = currentRead->controlWord;
|
||||
return prev != nullptr;
|
||||
}
|
||||
|
||||
@@ -369,6 +392,7 @@ void NewDriverStationData() {
|
||||
if (gShutdown) {
|
||||
return;
|
||||
}
|
||||
SimDriverStationData->dsAttached = true;
|
||||
cacheToUpdate->Update();
|
||||
|
||||
JoystickDataCache* given = cacheToUpdate;
|
||||
|
||||
@@ -28,7 +28,7 @@ void DriverStationData::ResetData() {
|
||||
test.Reset(false);
|
||||
eStop.Reset(false);
|
||||
fmsAttached.Reset(false);
|
||||
dsAttached.Reset(true);
|
||||
dsAttached.Reset(false);
|
||||
allianceStationId.Reset(static_cast<HAL_AllianceStationID>(0));
|
||||
matchTime.Reset(-1.0);
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class DriverStationData {
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetEStopName> eStop{false};
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetFmsAttachedName> fmsAttached{
|
||||
false};
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetDsAttachedName> dsAttached{true};
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetDsAttachedName> dsAttached{false};
|
||||
SimDataValue<HAL_AllianceStationID, MakeAllianceStationIdValue,
|
||||
GetAllianceStationIdName>
|
||||
allianceStationId{static_cast<HAL_AllianceStationID>(0)};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
= Network Tables Alloy Model
|
||||
|
||||
Alloy (http://alloy.mit.edu/alloy/) is a formal logic tool that can analyze
|
||||
[Alloy](https://www.csail.mit.edu/research/alloy) is a formal logic tool that can analyze
|
||||
first-order logic expressions. Under the proposed sequence number -based
|
||||
protocol, assuming that all nodes start from the same state, Alloy is unable to
|
||||
find a way where two nodes with the same sequence number have different state
|
||||
|
||||
@@ -236,6 +236,12 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
boolean setDefault{{ t.TypeName }}({{ t.java.ValueType }} defaultValue);
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefault{{ t.TypeName }}({{ t.java.WrapValueType }} defaultValue);
|
||||
{% endif -%}
|
||||
{% endfor %}
|
||||
|
||||
@@ -608,6 +608,6 @@ public final class NetworkTableEntry implements Publisher, Subscriber {
|
||||
}
|
||||
|
||||
private final Topic m_topic;
|
||||
protected int m_handle;
|
||||
private final int m_handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,11 @@ public final class NetworkTableInstance implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the network mode value.
|
||||
*
|
||||
* @return The network mode value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.EnumSet;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** NetworkTables JNI. */
|
||||
public final class NetworkTablesJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
static RuntimeLoader<NetworkTablesJNI> loader = null;
|
||||
@@ -82,139 +83,494 @@ public final class NetworkTablesJNI {
|
||||
return new PubSubOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default instance handle.
|
||||
*
|
||||
* @return Default instance handle.
|
||||
*/
|
||||
public static native int getDefaultInstance();
|
||||
|
||||
/**
|
||||
* Creates an NT instance.
|
||||
*
|
||||
* @return NT instance handle.
|
||||
*/
|
||||
public static native int createInstance();
|
||||
|
||||
/**
|
||||
* Destroys an NT instance.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void destroyInstance(int inst);
|
||||
|
||||
/**
|
||||
* Returns NT instance from handle.
|
||||
*
|
||||
* @param handle NT instance handle.
|
||||
* @return NT instance.
|
||||
*/
|
||||
public static native int getInstanceFromHandle(int handle);
|
||||
|
||||
private static native int getEntryImpl(
|
||||
int topic, int type, String typeStr, PubSubOptions options);
|
||||
|
||||
/**
|
||||
* Returns NT entry handle.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param key NT entry key.
|
||||
* @return NT entry handle.
|
||||
*/
|
||||
public static native int getEntry(int inst, String key);
|
||||
|
||||
/**
|
||||
* Returns NT entry handle.
|
||||
*
|
||||
* @param topic NT entry topic.
|
||||
* @param type NT entry type.
|
||||
* @param typeStr NT entry type as a string.
|
||||
* @param options NT entry pubsub options.
|
||||
* @return NT entry handle.
|
||||
*/
|
||||
public static int getEntry(
|
||||
int topic, int type, String typeStr, PubSubOptions options) {
|
||||
return getEntryImpl(topic, type, typeStr, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns NT entry handle.
|
||||
*
|
||||
* @param topic NT entry topic.
|
||||
* @param type NT entry type.
|
||||
* @param typeStr NT entry type as a string.
|
||||
* @param options NT entry pubsub options.
|
||||
* @return NT entry handle.
|
||||
*/
|
||||
public static int getEntry(
|
||||
int topic, int type, String typeStr, PubSubOption... options) {
|
||||
return getEntryImpl(topic, type, typeStr, buildOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns NT entry name.
|
||||
*
|
||||
* @param entry NT entry handle.
|
||||
* @return NT entry name.
|
||||
*/
|
||||
public static native String getEntryName(int entry);
|
||||
|
||||
/**
|
||||
* Returns NT entry last change time in microseconds.
|
||||
*
|
||||
* @param entry NT entry handle.
|
||||
* @return NT entry last change time in microseconds.
|
||||
*/
|
||||
public static native long getEntryLastChange(int entry);
|
||||
|
||||
/**
|
||||
* Returns NT entry type.
|
||||
*
|
||||
* @param entry NT entry handle.
|
||||
* @return NT entry type.
|
||||
*/
|
||||
public static native int getType(int entry);
|
||||
|
||||
/* Topic functions */
|
||||
|
||||
/**
|
||||
* Returns list of topic handles.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param prefix Topic prefix.
|
||||
* @param types Topic types.
|
||||
* @return List of topic handles.
|
||||
*/
|
||||
public static native int[] getTopics(int inst, String prefix, int types);
|
||||
|
||||
/**
|
||||
* Returns list of topic handles.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param prefix Topic prefix.
|
||||
* @param types Topic types as strings.
|
||||
* @return List of topic handles.
|
||||
*/
|
||||
public static native int[] getTopicsStr(int inst, String prefix, String[] types);
|
||||
|
||||
/**
|
||||
* Returns list of topic infos.
|
||||
*
|
||||
* @param instObject NT instance.
|
||||
* @param inst NT instance handle.
|
||||
* @param prefix Topic prefix.
|
||||
* @param types Topic types.
|
||||
* @return List of topic infos.
|
||||
*/
|
||||
public static native TopicInfo[] getTopicInfos(
|
||||
NetworkTableInstance instObject, int inst, String prefix, int types);
|
||||
|
||||
/**
|
||||
* Returns list of topic infos.
|
||||
*
|
||||
* @param instObject NT instance.
|
||||
* @param inst NT instance handle.
|
||||
* @param prefix Topic prefix.
|
||||
* @param types Topic types as strings.
|
||||
* @return List of topic infos.
|
||||
*/
|
||||
public static native TopicInfo[] getTopicInfosStr(
|
||||
NetworkTableInstance instObject, int inst, String prefix, String[] types);
|
||||
|
||||
/**
|
||||
* Returns Topic handle.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param name Topic name.
|
||||
* @return Topic handle.
|
||||
*/
|
||||
public static native int getTopic(int inst, String name);
|
||||
|
||||
/**
|
||||
* Returns topic name.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return Topic name.
|
||||
*/
|
||||
public static native String getTopicName(int topic);
|
||||
|
||||
/**
|
||||
* Returns topic type.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return Topic type.
|
||||
*/
|
||||
public static native int getTopicType(int topic);
|
||||
|
||||
/**
|
||||
* Sets topic persistency.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param value True if topic should be persistent.
|
||||
*/
|
||||
public static native void setTopicPersistent(int topic, boolean value);
|
||||
|
||||
/**
|
||||
* Returns true if topic is persistent.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return True if topic is persistent.
|
||||
*/
|
||||
public static native boolean getTopicPersistent(int topic);
|
||||
|
||||
/**
|
||||
* Sets whether topic is retained.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param value True if topic should be retained.
|
||||
*/
|
||||
public static native void setTopicRetained(int topic, boolean value);
|
||||
|
||||
/**
|
||||
* Returns true if topic is retained.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return True if topic is retained.
|
||||
*/
|
||||
public static native boolean getTopicRetained(int topic);
|
||||
|
||||
/**
|
||||
* Sets topic caching.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param value True if topic should be cached.
|
||||
*/
|
||||
public static native void setTopicCached(int topic, boolean value);
|
||||
|
||||
/**
|
||||
* Returns true if topic is cached.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return True if topic is cached.
|
||||
*/
|
||||
public static native boolean getTopicCached(int topic);
|
||||
|
||||
/**
|
||||
* Returns topic type as string.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return Topic type as string.
|
||||
*/
|
||||
public static native String getTopicTypeString(int topic);
|
||||
|
||||
/**
|
||||
* Returns true if topic exists.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return True if topic exists.
|
||||
*/
|
||||
public static native boolean getTopicExists(int topic);
|
||||
|
||||
/**
|
||||
* Returns topic property.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param name Property name.
|
||||
* @return Topic property.
|
||||
*/
|
||||
public static native String getTopicProperty(int topic, String name);
|
||||
|
||||
/**
|
||||
* Sets topic property.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param name Property name.
|
||||
* @param value Property value.
|
||||
*/
|
||||
public static native void setTopicProperty(int topic, String name, String value);
|
||||
|
||||
/**
|
||||
* Deletes topic property.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param name Property name.
|
||||
*/
|
||||
public static native void deleteTopicProperty(int topic, String name);
|
||||
|
||||
/**
|
||||
* Returns topic properties.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @return Topic properties.
|
||||
*/
|
||||
public static native String getTopicProperties(int topic);
|
||||
|
||||
/**
|
||||
* Sets topic properties.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param properties Topic properties.
|
||||
*/
|
||||
public static native void setTopicProperties(int topic, String properties);
|
||||
|
||||
/**
|
||||
* Subscribes to topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param options Pubsub options.
|
||||
* @return Subscriber handle.
|
||||
*/
|
||||
public static native int subscribe(
|
||||
int topic, int type, String typeStr, PubSubOptions options);
|
||||
|
||||
/**
|
||||
* Subscribes to topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param options Pubsub options.
|
||||
* @return Subscriber handle.
|
||||
*/
|
||||
public static int subscribe(
|
||||
int topic, int type, String typeStr, PubSubOption... options) {
|
||||
return subscribe(topic, type, typeStr, buildOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from topic.
|
||||
*
|
||||
* @param sub Subscriber handle.
|
||||
*/
|
||||
public static native void unsubscribe(int sub);
|
||||
|
||||
/**
|
||||
* Publishes topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param options Pubsub options.
|
||||
* @return Publish handle.
|
||||
*/
|
||||
public static native int publish(
|
||||
int topic, int type, String typeStr, PubSubOptions options);
|
||||
|
||||
/**
|
||||
* Publishes topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param options Pubsub options.
|
||||
* @return Publish handle.
|
||||
*/
|
||||
public static int publish(
|
||||
int topic, int type, String typeStr, PubSubOption... options) {
|
||||
return publish(topic, type, typeStr, buildOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param properties Topic properties.
|
||||
* @param options Pubsub options.
|
||||
* @return Publish handle.
|
||||
*/
|
||||
public static native int publishEx(
|
||||
int topic, int type, String typeStr, String properties, PubSubOptions options);
|
||||
|
||||
/**
|
||||
* Publishes topic.
|
||||
*
|
||||
* @param topic Topic handle.
|
||||
* @param type Topic type.
|
||||
* @param typeStr Topic type as a string.
|
||||
* @param properties Topic properties.
|
||||
* @param options Pubsub options.
|
||||
* @return Publish handle.
|
||||
*/
|
||||
public static int publishEx(
|
||||
int topic, int type, String typeStr, String properties, PubSubOption... options) {
|
||||
return publishEx(topic, type, typeStr, properties, buildOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpublishes topic.
|
||||
*
|
||||
* @param pubentry Publish entry handle.
|
||||
*/
|
||||
public static native void unpublish(int pubentry);
|
||||
|
||||
/**
|
||||
* Releases NT entry.
|
||||
*
|
||||
* @param entry NT entry handle.
|
||||
*/
|
||||
public static native void releaseEntry(int entry);
|
||||
|
||||
/**
|
||||
* Relesaes pubsub entry.
|
||||
*
|
||||
* @param pubsubentry Pubsub entry handle.
|
||||
*/
|
||||
public static native void release(int pubsubentry);
|
||||
|
||||
/**
|
||||
* Returns topic from pubsub entry handle.
|
||||
*
|
||||
* @param pubsubentry Pubsub entry handle.
|
||||
* @return Topic handle.
|
||||
*/
|
||||
public static native int getTopicFromHandle(int pubsubentry);
|
||||
|
||||
/**
|
||||
* Subscribes to multiple topics.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param prefixes List of topic prefixes.
|
||||
* @param options Pubsub options.
|
||||
* @return Subscribe handle.
|
||||
*/
|
||||
public static native int subscribeMultiple(int inst, String[] prefixes, PubSubOptions options);
|
||||
|
||||
/**
|
||||
* Subscribes to multiple topics.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param prefixes List of topic prefixes.
|
||||
* @param options Pubsub options.
|
||||
* @return Subscribe handle.
|
||||
*/
|
||||
public static int subscribeMultiple(int inst, String[] prefixes, PubSubOption... options) {
|
||||
return subscribeMultiple(inst, prefixes, buildOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from multiple topics.
|
||||
*
|
||||
* @param sub Subscribe handle.
|
||||
*/
|
||||
public static native void unsubscribeMultiple(int sub);
|
||||
{% for t in types %}
|
||||
/**
|
||||
* Returns timestamped topic value as an atomic {{ t.TypeName }}.
|
||||
*
|
||||
* @param subentry Subentry handle.
|
||||
* @param defaultValue Default value.
|
||||
* @return Timestamped topic value.
|
||||
*/
|
||||
public static native Timestamped{{ t.TypeName }} getAtomic{{ t.TypeName }}(
|
||||
int subentry, {{ t.java.ValueType }} defaultValue);
|
||||
|
||||
/**
|
||||
* Returns queued timestamped topic values.
|
||||
*
|
||||
* @param subentry Subentry handle.
|
||||
* @return List of timestamped topic values.
|
||||
*/
|
||||
public static native Timestamped{{ t.TypeName }}[] readQueue{{ t.TypeName }}(int subentry);
|
||||
|
||||
/**
|
||||
* Returns queued topic values.
|
||||
*
|
||||
* @param subentry Subentry handle.
|
||||
* @return List of topic values.
|
||||
*/
|
||||
public static native {{ t.java.ValueType }}[] readQueueValues{{ t.TypeName }}(int subentry);
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Raw value buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setRaw(int entry, long time, byte[] value) {
|
||||
return setRaw(entry, time, value, 0, value.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Raw value buffer.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setRaw(int entry, long time, byte[] value, int start, int len);
|
||||
|
||||
/**
|
||||
* Sets raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Raw value buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setRaw(int entry, long time, ByteBuffer value) {
|
||||
int pos = value.position();
|
||||
return setRaw(entry, time, value, pos, value.capacity() - pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Raw value buffer.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setRaw(int entry, long time, ByteBuffer value, int start, int len) {
|
||||
if (value.isDirect()) {
|
||||
if (start < 0) {
|
||||
@@ -234,23 +590,84 @@ public final class NetworkTablesJNI {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets raw topic value buffer.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Raw value buffer.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
private static native boolean setRawBuffer(int entry, long time, ByteBuffer value, int start, int len);
|
||||
{% else %}
|
||||
/**
|
||||
* Sets topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param value Topic value.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean set{{ t.TypeName }}(int entry, long time, {{ t.java.ValueType }} value);
|
||||
{% endif %}
|
||||
/**
|
||||
* Returns topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param defaultValue Default value.
|
||||
* @return Topic value.
|
||||
*/
|
||||
public static native {{ t.java.ValueType }} get{{ t.TypeName }}(int entry, {{ t.java.ValueType }} defaultValue);
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets default raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setDefaultRaw(int entry, long time, byte[] defaultValue) {
|
||||
return setDefaultRaw(entry, time, defaultValue, 0, defaultValue.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setDefaultRaw(int entry, long time, byte[] defaultValue, int start, int len);
|
||||
|
||||
/**
|
||||
* Sets default raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setDefaultRaw(int entry, long time, ByteBuffer defaultValue) {
|
||||
int pos = defaultValue.position();
|
||||
return setDefaultRaw(entry, time, defaultValue, pos, defaultValue.limit() - pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default raw topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static boolean setDefaultRaw(int entry, long time, ByteBuffer defaultValue, int start, int len) {
|
||||
if (defaultValue.isDirect()) {
|
||||
if (start < 0) {
|
||||
@@ -270,25 +687,91 @@ public final class NetworkTablesJNI {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default raw topic value buffer.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @param start Value's offset into buffer.
|
||||
* @param len Length of value in buffer.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
private static native boolean setDefaultRawBuffer(int entry, long time, ByteBuffer defaultValue, int start, int len);
|
||||
{% else %}
|
||||
/**
|
||||
* Sets default topic value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param time Time in microseconds.
|
||||
* @param defaultValue Default value.
|
||||
* @return True if set succeeded.
|
||||
*/
|
||||
public static native boolean setDefault{{ t.TypeName }}(int entry, long time, {{ t.java.ValueType }} defaultValue);
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
/**
|
||||
* Returns queued subentry values.
|
||||
*
|
||||
* @param subentry Subentry handle.
|
||||
* @return List of queued subentry values.
|
||||
*/
|
||||
public static native NetworkTableValue[] readQueueValue(int subentry);
|
||||
|
||||
/**
|
||||
* Returns entry's NT value.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @return Entry's NT value.
|
||||
*/
|
||||
public static native NetworkTableValue getValue(int entry);
|
||||
|
||||
/**
|
||||
* Sets entry flags.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @param flags Entry flags.
|
||||
*/
|
||||
public static native void setEntryFlags(int entry, int flags);
|
||||
|
||||
/**
|
||||
* Returns entry flags.
|
||||
*
|
||||
* @param entry Entry handle.
|
||||
* @return Entry flags.
|
||||
*/
|
||||
public static native int getEntryFlags(int entry);
|
||||
|
||||
/**
|
||||
* Returns topic info.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param topic Topic handle.
|
||||
* @return Topic info.
|
||||
*/
|
||||
public static native TopicInfo getTopicInfo(NetworkTableInstance inst, int topic);
|
||||
|
||||
/**
|
||||
* Creates a listener poller.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @return Listener poller handle.
|
||||
*/
|
||||
public static native int createListenerPoller(int inst);
|
||||
|
||||
/**
|
||||
* Destroys listener poller.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
*/
|
||||
public static native void destroyListenerPoller(int poller);
|
||||
|
||||
/**
|
||||
* Converts NT event kinds to mask.
|
||||
*
|
||||
* @param kinds Enum set of NT event kinds.
|
||||
* @return NT event mask.
|
||||
*/
|
||||
private static int kindsToMask(EnumSet<NetworkTableEvent.Kind> kinds) {
|
||||
int mask = 0;
|
||||
for (NetworkTableEvent.Kind kind : kinds) {
|
||||
@@ -297,80 +780,316 @@ public final class NetworkTablesJNI {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
* @param prefixes Topic prefixes.
|
||||
* @param kinds Enum set of NT event kinds.
|
||||
* @return Listener handle.
|
||||
*/
|
||||
public static int addListener(int poller, String[] prefixes, EnumSet<NetworkTableEvent.Kind> kinds) {
|
||||
return addListener(poller, prefixes, kindsToMask(kinds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
* @param handle Topic handle.
|
||||
* @param kinds Enum set of NT event kinds.
|
||||
* @return Listener handle.
|
||||
*/
|
||||
public static int addListener(int poller, int handle, EnumSet<NetworkTableEvent.Kind> kinds) {
|
||||
return addListener(poller, handle, kindsToMask(kinds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
* @param prefixes Topic prefixes.
|
||||
* @param mask NT event mask.
|
||||
* @return Listener handle.
|
||||
*/
|
||||
public static native int addListener(int poller, String[] prefixes, int mask);
|
||||
|
||||
/**
|
||||
* Adds listener.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
* @param handle Topic handle.
|
||||
* @param mask NT event mask.
|
||||
* @return Listener handle.
|
||||
*/
|
||||
public static native int addListener(int poller, int handle, int mask);
|
||||
|
||||
/**
|
||||
* Returns NT events from listener queue.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param poller Listener poller handle.
|
||||
* @return List of NT events.
|
||||
*/
|
||||
public static native NetworkTableEvent[] readListenerQueue(
|
||||
NetworkTableInstance inst, int poller);
|
||||
|
||||
/**
|
||||
* Removes listener.
|
||||
*
|
||||
* @param listener Listener handle.
|
||||
*/
|
||||
public static native void removeListener(int listener);
|
||||
|
||||
/**
|
||||
* Returns network mode.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @return Network mode.
|
||||
*/
|
||||
public static native int getNetworkMode(int inst);
|
||||
|
||||
/**
|
||||
* Starts local-only operation. Prevents calls to startServer or startClient from taking effect.
|
||||
* Has no effect if startServer or startClient has already been called.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void startLocal(int inst);
|
||||
|
||||
/**
|
||||
* Stops local-only operation. startServer or startClient can be called after this call to start
|
||||
* a server or client.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void stopLocal(int inst);
|
||||
|
||||
/**
|
||||
* Starts a server using the specified filename, listening address, and port.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param persistFilename the name of the persist file to use
|
||||
* @param listenAddress the address to listen on, or empty to listen on any address
|
||||
* @param port3 port to communicate over (NT3)
|
||||
* @param port4 port to communicate over (NT4)
|
||||
*/
|
||||
public static native void startServer(
|
||||
int inst, String persistFilename, String listenAddress, int port3, int port4);
|
||||
|
||||
/**
|
||||
* Stops the server if it is running.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void stopServer(int inst);
|
||||
|
||||
/**
|
||||
* Starts a NT3 client. Use SetServer or SetServerTeam to set the server name and port.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param identity network identity to advertise (cannot be empty string)
|
||||
*/
|
||||
public static native void startClient3(int inst, String identity);
|
||||
|
||||
/**
|
||||
* Starts a NT4 client. Use SetServer or SetServerTeam to set the server name and port.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param identity network identity to advertise (cannot be empty string)
|
||||
*/
|
||||
public static native void startClient4(int inst, String identity);
|
||||
|
||||
/**
|
||||
* Stops the client if it is running.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void stopClient(int inst);
|
||||
|
||||
/**
|
||||
* Sets server address and port for client (without restarting client).
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param serverName server name
|
||||
* @param port port to communicate over
|
||||
*/
|
||||
public static native void setServer(int inst, String serverName, int port);
|
||||
|
||||
/**
|
||||
* Sets server addresses and ports for client (without restarting client). The client will
|
||||
* attempt to connect to each server in round robin fashion.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param serverNames array of server names
|
||||
* @param ports array of port numbers (0=default)
|
||||
*/
|
||||
public static native void setServer(int inst, String[] serverNames, int[] ports);
|
||||
|
||||
/**
|
||||
* Sets server addresses and port for client (without restarting client). Connects using commonly
|
||||
* known robot addresses for the specified team.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param team team number
|
||||
* @param port port to communicate over
|
||||
*/
|
||||
public static native void setServerTeam(int inst, int team, int port);
|
||||
|
||||
/**
|
||||
* Disconnects the client if it's running and connected. This will automatically start
|
||||
* reconnection attempts to the current server list.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void disconnect(int inst);
|
||||
|
||||
/**
|
||||
* Starts requesting server address from Driver Station. This connects to the Driver Station
|
||||
* running on localhost to obtain the server IP address.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param port server port to use in combination with IP from DS
|
||||
*/
|
||||
public static native void startDSClient(int inst, int port);
|
||||
|
||||
/**
|
||||
* Stops requesting server address from Driver Station.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void stopDSClient(int inst);
|
||||
|
||||
/**
|
||||
* Flushes all updated values immediately to the local client/server. This does not flush to the
|
||||
* network.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void flushLocal(int inst);
|
||||
|
||||
/**
|
||||
* Flushes all updated values immediately to the network. Note: This is rate-limited to protect
|
||||
* the network from flooding. This is primarily useful for synchronizing network updates with
|
||||
* user code.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
*/
|
||||
public static native void flush(int inst);
|
||||
|
||||
/**
|
||||
* Gets information on the currently established network connections. If operating as a client,
|
||||
* this will return either zero or one values.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @return array of connection information
|
||||
*/
|
||||
public static native ConnectionInfo[] getConnections(int inst);
|
||||
|
||||
/**
|
||||
* Return whether or not the instance is connected to another node.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @return True if connected.
|
||||
*/
|
||||
public static native boolean isConnected(int inst);
|
||||
|
||||
/**
|
||||
* Get the time offset between server time and local time. Add this value to local time to get
|
||||
* the estimated equivalent server time. In server mode, this always returns 0. In client mode,
|
||||
* this returns the time offset only if the client and server are connected and have exchanged
|
||||
* synchronization messages. Note the time offset may change over time as it is periodically
|
||||
* updated; to receive updates as events, add a listener to the "time sync" event.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @return Time offset in microseconds (optional)
|
||||
*/
|
||||
public static native OptionalLong getServerTimeOffset(int inst);
|
||||
|
||||
/**
|
||||
* Returns the current timestamp in microseconds.
|
||||
*
|
||||
* @return The current timestsamp in microseconds.
|
||||
*/
|
||||
public static native long now();
|
||||
|
||||
/**
|
||||
* Starts logging entry changes to a DataLog.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param log data log handle; lifetime must extend until StopEntryDataLog is called or the
|
||||
* instance is destroyed
|
||||
* @param prefix only store entries with names that start with this prefix; the prefix is not
|
||||
* included in the data log entry name
|
||||
* @param logPrefix prefix to add to data log entry names
|
||||
* @return Data logger handle
|
||||
*/
|
||||
private static native int startEntryDataLog(int inst, long log, String prefix, String logPrefix);
|
||||
|
||||
/**
|
||||
* Starts logging entry changes to a DataLog.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param log data log object; lifetime must extend until StopEntryDataLog is called or the
|
||||
* instance is destroyed
|
||||
* @param prefix only store entries with names that start with this prefix; the prefix is not
|
||||
* included in the data log entry name
|
||||
* @param logPrefix prefix to add to data log entry names
|
||||
* @return Data logger handle
|
||||
*/
|
||||
public static int startEntryDataLog(int inst, DataLog log, String prefix, String logPrefix) {
|
||||
return startEntryDataLog(inst, log.getImpl(), prefix, logPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops logging entry changes to a DataLog.
|
||||
*
|
||||
* @param logger data logger handle
|
||||
*/
|
||||
public static native void stopEntryDataLog(int logger);
|
||||
|
||||
/**
|
||||
* Starts logging connection changes to a DataLog.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param log data log handle; lifetime must extend until StopConnectionDataLog is called or the
|
||||
* instance is destroyed
|
||||
* @param name data log entry name
|
||||
* @return Data logger handle
|
||||
*/
|
||||
private static native int startConnectionDataLog(int inst, long log, String name);
|
||||
|
||||
/**
|
||||
* Starts logging connection changes to a DataLog.
|
||||
*
|
||||
* @param inst NT instance handle.
|
||||
* @param log data log object; lifetime must extend until StopConnectionDataLog is called or the
|
||||
* instance is destroyed
|
||||
* @param name data log entry name
|
||||
* @return Data logger handle
|
||||
*/
|
||||
public static int startConnectionDataLog(int inst, DataLog log, String name) {
|
||||
return startConnectionDataLog(inst, log.getImpl(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops logging connection changes to a DataLog.
|
||||
*
|
||||
* @param logger data logger handle
|
||||
*/
|
||||
public static native void stopConnectionDataLog(int logger);
|
||||
|
||||
/**
|
||||
* Add logger callback function. By default, log messages are sent to stderr; this function sends
|
||||
* log messages with the specified levels to the provided callback function instead. The callback
|
||||
* function will only be called for log messages with level greater than or equal to minLevel and
|
||||
* less than or equal to maxLevel; messages outside this range will be silently ignored.
|
||||
*
|
||||
* @param poller Listener poller handle.
|
||||
* @param minLevel minimum log level
|
||||
* @param maxLevel maximum log level
|
||||
* @return Listener handle
|
||||
*/
|
||||
public static native int addLogger(int poller, int minLevel, int maxLevel);
|
||||
|
||||
/** Utility class. */
|
||||
|
||||
@@ -517,6 +517,12 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
*/
|
||||
boolean setDefaultBooleanArray(boolean[] defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultBooleanArray(Boolean[] defaultValue);
|
||||
|
||||
|
||||
@@ -528,6 +534,12 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
*/
|
||||
boolean setDefaultIntegerArray(long[] defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultIntegerArray(Long[] defaultValue);
|
||||
|
||||
|
||||
@@ -539,6 +551,12 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
*/
|
||||
boolean setDefaultFloatArray(float[] defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultFloatArray(Float[] defaultValue);
|
||||
|
||||
|
||||
@@ -550,6 +568,12 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
*/
|
||||
boolean setDefaultDoubleArray(double[] defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultDoubleArray(Double[] defaultValue);
|
||||
|
||||
|
||||
|
||||
@@ -1009,5 +1009,5 @@ public final class NetworkTableEntry implements Publisher, Subscriber {
|
||||
}
|
||||
|
||||
private final Topic m_topic;
|
||||
protected int m_handle;
|
||||
private final int m_handle;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,11 @@ public final class NetworkTableInstance implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the network mode value.
|
||||
*
|
||||
* @return The network mode value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,5 +40,6 @@ public abstract class EntryBase implements Subscriber, Publisher {
|
||||
return NetworkTablesJNI.getEntryLastChange(m_handle);
|
||||
}
|
||||
|
||||
/** NetworkTables handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -7,16 +7,31 @@ package edu.wpi.first.networktables;
|
||||
/** NetworkTables log message. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final class LogMessage {
|
||||
/** Logging levels. */
|
||||
/** Critical logging level. */
|
||||
public static final int kCritical = 50;
|
||||
|
||||
/** Error logging level. */
|
||||
public static final int kError = 40;
|
||||
|
||||
/** Warning log level. */
|
||||
public static final int kWarning = 30;
|
||||
|
||||
/** Info log level. */
|
||||
public static final int kInfo = 20;
|
||||
|
||||
/** Debug log level. */
|
||||
public static final int kDebug = 10;
|
||||
|
||||
/** Debug log level 1. */
|
||||
public static final int kDebug1 = 9;
|
||||
|
||||
/** Debug log level 2. */
|
||||
public static final int kDebug2 = 8;
|
||||
|
||||
/** Debug log level 3. */
|
||||
public static final int kDebug3 = 7;
|
||||
|
||||
/** Debug log level 4. */
|
||||
public static final int kDebug4 = 6;
|
||||
|
||||
/** Log level of the message. */
|
||||
|
||||
@@ -6,6 +6,7 @@ package edu.wpi.first.networktables;
|
||||
|
||||
import edu.wpi.first.util.sendable.SendableBuilder;
|
||||
|
||||
/** Helper class for building Sendable dashboard representations for NetworkTables. */
|
||||
public interface NTSendableBuilder extends SendableBuilder {
|
||||
/**
|
||||
* Set the function that should be called to update the network table for things other than
|
||||
|
||||
@@ -330,7 +330,7 @@ public final class NetworkTable {
|
||||
* @return true if the table as a value assigned to the given key
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
return !("".equals(key)) && getTopic(key).exists();
|
||||
return !"".equals(key) && getTopic(key).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@ package edu.wpi.first.networktables;
|
||||
*/
|
||||
@SuppressWarnings("MemberName")
|
||||
public final class NetworkTableEvent {
|
||||
/** NetworkTable event kind. */
|
||||
public enum Kind {
|
||||
/**
|
||||
* Initial listener addition. Set this to receive immediate notification of matches to other
|
||||
@@ -61,6 +62,11 @@ public final class NetworkTableEvent {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NetworkTable event kind value.
|
||||
*
|
||||
* @return The NetworkTable event kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -39,10 +39,20 @@ public enum NetworkTableType {
|
||||
m_valueStr = valueStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NetworkTable type value.
|
||||
*
|
||||
* @return The NetworkTable type value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NetworkTable type value as as string.
|
||||
*
|
||||
* @return The NetworkTable type value as a string.
|
||||
*/
|
||||
public String getValueStr() {
|
||||
return m_valueStr;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,11 @@ public final class ProtobufTopic<T> extends Topic {
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protobuf.
|
||||
*
|
||||
* @return The protobuf.
|
||||
*/
|
||||
public Protobuf<T, ?> getProto() {
|
||||
return m_proto;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ public class PubSubOption {
|
||||
disableRemote,
|
||||
disableLocal,
|
||||
excludePublisher,
|
||||
excludeSelf
|
||||
excludeSelf,
|
||||
hidden
|
||||
}
|
||||
|
||||
PubSubOption(Kind kind, boolean value) {
|
||||
@@ -149,6 +150,18 @@ public class PubSubOption {
|
||||
return new PubSubOption(Kind.excludeSelf, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* For subscriptions, don't share the existence of the subscription with the network. Note this
|
||||
* means updates will not be received from the network unless another subscription overlaps with
|
||||
* this one, and the subscription will not appear in metatopics.
|
||||
*
|
||||
* @param enabled True to enable, false to disable
|
||||
* @return option
|
||||
*/
|
||||
public static PubSubOption hidden(boolean enabled) {
|
||||
return new PubSubOption(Kind.hidden, enabled);
|
||||
}
|
||||
|
||||
final Kind m_kind;
|
||||
final boolean m_bValue;
|
||||
final int m_iValue;
|
||||
|
||||
@@ -42,6 +42,9 @@ public class PubSubOptions {
|
||||
case excludeSelf:
|
||||
excludeSelf = option.m_bValue;
|
||||
break;
|
||||
case hidden:
|
||||
hidden = option.m_bValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -58,7 +61,8 @@ public class PubSubOptions {
|
||||
boolean prefixMatch,
|
||||
boolean disableRemote,
|
||||
boolean disableLocal,
|
||||
boolean excludeSelf) {
|
||||
boolean excludeSelf,
|
||||
boolean hidden) {
|
||||
this.pollStorage = pollStorage;
|
||||
this.periodic = periodic;
|
||||
this.excludePublisher = excludePublisher;
|
||||
@@ -69,6 +73,7 @@ public class PubSubOptions {
|
||||
this.disableRemote = disableRemote;
|
||||
this.disableLocal = disableLocal;
|
||||
this.excludeSelf = excludeSelf;
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
/** Default value of periodic. */
|
||||
@@ -123,4 +128,11 @@ public class PubSubOptions {
|
||||
|
||||
/** For entries, don't queue (for readQueue) value updates for the entry's internal publisher. */
|
||||
public boolean excludeSelf;
|
||||
|
||||
/**
|
||||
* For subscriptions, don't share the existence of the subscription with the network. Note this
|
||||
* means updates will not be received from the network unless another subscription overlaps with
|
||||
* this one, and the subscription will not appear in metatopics.
|
||||
*/
|
||||
public boolean hidden;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,11 @@ public final class StructArrayTopic<T> extends Topic {
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the struct.
|
||||
*
|
||||
* @return The struct.
|
||||
*/
|
||||
public Struct<T> getStruct() {
|
||||
return m_struct;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,11 @@ public final class StructTopic<T> extends Topic {
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the struct.
|
||||
*
|
||||
* @return The struct.
|
||||
*/
|
||||
public Struct<T> getStruct() {
|
||||
return m_struct;
|
||||
}
|
||||
|
||||
@@ -336,6 +336,9 @@ public class Topic {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/** NetworkTables instance. */
|
||||
protected NetworkTableInstance m_inst;
|
||||
|
||||
/** NetworkTables handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,17 @@ bool LocalStorage::MultiSubscriberData::Matches(std::string_view name,
|
||||
}
|
||||
|
||||
int LocalStorage::DataLoggerData::Start(TopicData* topic, int64_t time) {
|
||||
std::string_view typeStr = topic->typeStr;
|
||||
// NT and DataLog use different standard representations for int and int[]
|
||||
if (typeStr == "int") {
|
||||
typeStr = "int64";
|
||||
} else if (typeStr == "int[]") {
|
||||
typeStr = "int64[]";
|
||||
}
|
||||
return log.Start(fmt::format("{}{}", logPrefix,
|
||||
wpi::drop_front(topic->name, prefix.size())),
|
||||
topic->typeStr == "int" ? "int64" : topic->typeStr,
|
||||
DataLoggerEntry::MakeMetadata(topic->propertiesStr), time);
|
||||
typeStr, DataLoggerEntry::MakeMetadata(topic->propertiesStr),
|
||||
time);
|
||||
}
|
||||
|
||||
void LocalStorage::DataLoggerEntry::Append(const Value& v) {
|
||||
@@ -604,7 +611,7 @@ LocalStorage::SubscriberData* LocalStorage::Impl::AddLocalSubscriber(
|
||||
"published as '{}')",
|
||||
topic->name, config.typeStr, topic->typeStr);
|
||||
}
|
||||
if (m_network) {
|
||||
if (m_network && !subscriber->config.hidden) {
|
||||
DEBUG4("-> NetworkSubscribe({})", topic->name);
|
||||
m_network->Subscribe(subscriber->handle, {{topic->name}}, config);
|
||||
}
|
||||
@@ -633,7 +640,7 @@ LocalStorage::Impl::RemoveLocalSubscriber(NT_Subscriber subHandle) {
|
||||
listener.getSecond()->subscriber = nullptr;
|
||||
}
|
||||
}
|
||||
if (m_network) {
|
||||
if (m_network && !subscriber->config.hidden) {
|
||||
m_network->Unsubscribe(subscriber->handle);
|
||||
}
|
||||
}
|
||||
@@ -669,7 +676,7 @@ LocalStorage::MultiSubscriberData* LocalStorage::Impl::AddMultiSubscriber(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_network) {
|
||||
if (m_network && !subscriber->options.hidden) {
|
||||
DEBUG4("-> NetworkSubscribe");
|
||||
m_network->Subscribe(subscriber->handle, subscriber->prefixes,
|
||||
subscriber->options);
|
||||
@@ -689,7 +696,7 @@ LocalStorage::Impl::RemoveMultiSubscriber(NT_MultiSubscriber subHandle) {
|
||||
listener.getSecond()->multiSubscriber = nullptr;
|
||||
}
|
||||
}
|
||||
if (m_network) {
|
||||
if (m_network && !subscriber->options.hidden) {
|
||||
m_network->Unsubscribe(subscriber->handle);
|
||||
}
|
||||
}
|
||||
@@ -1121,12 +1128,16 @@ void LocalStorage::Impl::StartNetwork(net::NetworkInterface* network) {
|
||||
}
|
||||
}
|
||||
for (auto&& subscriber : m_subscribers) {
|
||||
network->Subscribe(subscriber->handle, {{subscriber->topic->name}},
|
||||
subscriber->config);
|
||||
if (!subscriber->config.hidden) {
|
||||
network->Subscribe(subscriber->handle, {{subscriber->topic->name}},
|
||||
subscriber->config);
|
||||
}
|
||||
}
|
||||
for (auto&& subscriber : m_multiSubscribers) {
|
||||
network->Subscribe(subscriber->handle, subscriber->prefixes,
|
||||
subscriber->options);
|
||||
if (!subscriber->options.hidden) {
|
||||
network->Subscribe(subscriber->handle, subscriber->prefixes,
|
||||
subscriber->options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -254,13 +254,13 @@ class LocalStorage final : public net::ILocalStorage {
|
||||
wpi::SmallVectorImpl<typename TypeInfo<T>::SmallElem>& buf,
|
||||
typename TypeInfo<T>::View defaultValue);
|
||||
|
||||
std::vector<Value> ReadQueueValue(NT_Handle subentry) {
|
||||
std::vector<Value> ReadQueueValue(NT_Handle subentry, unsigned int types) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
auto subscriber = m_impl.GetSubEntry(subentry);
|
||||
if (!subscriber) {
|
||||
return {};
|
||||
}
|
||||
return subscriber->pollStorage.ReadValue();
|
||||
return subscriber->pollStorage.ReadValue(types);
|
||||
}
|
||||
|
||||
template <ValidType T>
|
||||
|
||||
@@ -362,6 +362,7 @@ void NetworkClient::HandleLocal() {
|
||||
}
|
||||
|
||||
void NetworkClient::TcpConnected(uv::Tcp& tcp) {
|
||||
tcp.SetLogger(&m_logger);
|
||||
tcp.SetNoDelay(true);
|
||||
// Start the WS client
|
||||
if (m_logger.min_level() >= wpi::WPI_LOG_DEBUG4) {
|
||||
@@ -401,9 +402,8 @@ void NetworkClient::WsConnected(wpi::WebSocket& ws, uv::Tcp& tcp,
|
||||
INFO("CONNECTED NT4 to {} port {}", connInfo.remote_ip, connInfo.remote_port);
|
||||
m_connHandle = m_connList.AddConnection(connInfo);
|
||||
|
||||
m_wire =
|
||||
std::make_shared<net::WebSocketConnection>(ws, connInfo.protocol_version);
|
||||
m_wire->Start();
|
||||
m_wire = std::make_shared<net::WebSocketConnection>(
|
||||
ws, connInfo.protocol_version, m_logger);
|
||||
m_clientImpl = std::make_unique<net::ClientImpl>(
|
||||
m_loop.Now().count(), m_inst, *m_wire, m_logger, m_timeSyncUpdated,
|
||||
[this](uint32_t repeatMs) {
|
||||
|
||||
@@ -242,7 +242,7 @@ void NetworkServer::ServerConnection4::ProcessWsUpgrade() {
|
||||
m_info.protocol_version =
|
||||
protocol == "v4.1.networktables.first.wpi.edu" ? 0x0401 : 0x0400;
|
||||
m_wire = std::make_shared<net::WebSocketConnection>(
|
||||
*m_websocket, m_info.protocol_version);
|
||||
*m_websocket, m_info.protocol_version, m_logger);
|
||||
|
||||
if (protocol == "rtt.networktables.first.wpi.edu") {
|
||||
INFO("CONNECTED RTT client (from {})", m_connInfo);
|
||||
@@ -281,7 +281,6 @@ void NetworkServer::ServerConnection4::ProcessWsUpgrade() {
|
||||
INFO("CONNECTED NT4 client '{}' (from {})", dedupName, m_connInfo);
|
||||
m_info.remote_id = dedupName;
|
||||
m_server.AddConnection(this, m_info);
|
||||
m_wire->Start();
|
||||
m_websocket->closed.connect([this](uint16_t, std::string_view reason) {
|
||||
auto realReason = m_wire->GetDisconnectReason();
|
||||
INFO("DISCONNECTED NT4 client '{}' (from {}): {}", m_info.remote_id,
|
||||
@@ -500,6 +499,7 @@ void NetworkServer::Init() {
|
||||
if (!tcp) {
|
||||
return;
|
||||
}
|
||||
tcp->SetLogger(&m_logger);
|
||||
tcp->error.connect([logger = &m_logger](uv::Error err) {
|
||||
WPI_INFO(*logger, "NT4 socket error: {}", err.str());
|
||||
});
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
|
||||
using namespace nt;
|
||||
|
||||
std::vector<Value> ValueCircularBuffer::ReadValue() {
|
||||
std::vector<Value> ValueCircularBuffer::ReadValue(unsigned int types) {
|
||||
std::vector<Value> rv;
|
||||
rv.reserve(m_storage.size());
|
||||
for (auto&& val : m_storage) {
|
||||
if (types != 0 && (types & val.type()) == 0) {
|
||||
continue;
|
||||
}
|
||||
rv.emplace_back(std::move(val));
|
||||
}
|
||||
m_storage.reset();
|
||||
|
||||
@@ -24,7 +24,7 @@ class ValueCircularBuffer {
|
||||
m_storage.emplace_back(std::forward<Args...>(args...));
|
||||
}
|
||||
|
||||
std::vector<Value> ReadValue();
|
||||
std::vector<Value> ReadValue(unsigned int types);
|
||||
template <ValidType T>
|
||||
std::vector<Timestamped<typename TypeInfo<T>::Value>> Read();
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ static nt::PubSubOptions FromJavaPubSubOptions(JNIEnv* env, jobject joptions) {
|
||||
FIELD(disableRemote, "Z");
|
||||
FIELD(disableLocal, "Z");
|
||||
FIELD(excludeSelf, "Z");
|
||||
FIELD(hidden, "Z");
|
||||
|
||||
#undef FIELD
|
||||
|
||||
@@ -154,7 +155,8 @@ static nt::PubSubOptions FromJavaPubSubOptions(JNIEnv* env, jobject joptions) {
|
||||
FIELD(bool, Boolean, prefixMatch),
|
||||
FIELD(bool, Boolean, disableRemote),
|
||||
FIELD(bool, Boolean, disableLocal),
|
||||
FIELD(bool, Boolean, excludeSelf)};
|
||||
FIELD(bool, Boolean, excludeSelf),
|
||||
FIELD(bool, Boolean, hidden)};
|
||||
|
||||
#undef GET
|
||||
#undef FIELD
|
||||
|
||||
@@ -67,26 +67,28 @@ void ClientImpl::ProcessIncomingBinary(uint64_t curTimeMs,
|
||||
DEBUG4("BinaryMessage({})", id);
|
||||
|
||||
// handle RTT ping response (only use first one)
|
||||
if (!m_haveTimeOffset && id == -1) {
|
||||
if (!value.IsInteger()) {
|
||||
WARN("RTT ping response with non-integer type {}",
|
||||
static_cast<int>(value.type()));
|
||||
continue;
|
||||
}
|
||||
DEBUG4("RTT ping response time {} value {}", value.time(),
|
||||
value.GetInteger());
|
||||
if (m_wire.GetVersion() < 0x0401) {
|
||||
m_pongTimeMs = curTimeMs;
|
||||
}
|
||||
int64_t now = wpi::Now();
|
||||
int64_t rtt2 = (now - value.GetInteger()) / 2;
|
||||
if (rtt2 < m_rtt2Us) {
|
||||
m_rtt2Us = rtt2;
|
||||
int64_t serverTimeOffsetUs = value.server_time() + rtt2 - now;
|
||||
DEBUG3("Time offset: {}", serverTimeOffsetUs);
|
||||
m_outgoing.SetTimeOffset(serverTimeOffsetUs);
|
||||
m_haveTimeOffset = true;
|
||||
m_timeSyncUpdated(serverTimeOffsetUs, m_rtt2Us, true);
|
||||
if (id == -1) {
|
||||
if (!m_haveTimeOffset) {
|
||||
if (!value.IsInteger()) {
|
||||
WARN("RTT ping response with non-integer type {}",
|
||||
static_cast<int>(value.type()));
|
||||
continue;
|
||||
}
|
||||
DEBUG4("RTT ping response time {} value {}", value.time(),
|
||||
value.GetInteger());
|
||||
if (m_wire.GetVersion() < 0x0401) {
|
||||
m_pongTimeMs = curTimeMs;
|
||||
}
|
||||
int64_t now = wpi::Now();
|
||||
int64_t rtt2 = (now - value.GetInteger()) / 2;
|
||||
if (rtt2 < m_rtt2Us) {
|
||||
m_rtt2Us = rtt2;
|
||||
int64_t serverTimeOffsetUs = value.server_time() + rtt2 - now;
|
||||
DEBUG3("Time offset: {}", serverTimeOffsetUs);
|
||||
m_outgoing.SetTimeOffset(serverTimeOffsetUs);
|
||||
m_haveTimeOffset = true;
|
||||
m_timeSyncUpdated(serverTimeOffsetUs, m_rtt2Us, true);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -12,14 +12,15 @@ bool NetworkPing::Send(uint64_t curTimeMs) {
|
||||
if (curTimeMs < m_nextPingTimeMs) {
|
||||
return true;
|
||||
}
|
||||
// if we didn't receive a timely response to our last ping, disconnect
|
||||
uint64_t lastPing = m_wire.GetLastPingResponse();
|
||||
// if we haven't received data in a while, disconnect
|
||||
// (we should at least be getting PONG responses)
|
||||
uint64_t lastData = m_wire.GetLastReceivedTime();
|
||||
// DEBUG4("WS ping: lastPing={} curTime={} pongTimeMs={}\n", lastPing,
|
||||
// curTimeMs, m_pongTimeMs);
|
||||
if (lastPing == 0) {
|
||||
lastPing = m_pongTimeMs;
|
||||
if (lastData == 0) {
|
||||
lastData = m_pongTimeMs;
|
||||
}
|
||||
if (m_pongTimeMs != 0 && curTimeMs > (lastPing + kPingTimeoutMs)) {
|
||||
if (m_pongTimeMs != 0 && curTimeMs > (lastData + kPingTimeoutMs)) {
|
||||
m_wire.Disconnect("connection timed out");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1816,7 +1816,8 @@ void ServerImpl::SetValue(ClientData* client, TopicData* topic,
|
||||
}
|
||||
|
||||
for (auto&& tcd : topic->clients) {
|
||||
if (tcd.second.sendMode != ValueSendMode::kDisabled) {
|
||||
if (tcd.first != client &&
|
||||
tcd.second.sendMode != ValueSendMode::kDisabled) {
|
||||
tcd.first->SendValue(topic, value, tcd.second.sendMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <span>
|
||||
|
||||
#include <wpi/Endian.h>
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/SpanExtras.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/timestamp.h>
|
||||
@@ -52,7 +53,11 @@ class WebSocketConnection::Stream final : public wpi::raw_ostream {
|
||||
void WebSocketConnection::Stream::write_impl(const char* data, size_t len) {
|
||||
if (data == m_conn.m_bufs.back().base) {
|
||||
// flush_nonempty() case
|
||||
size_t amt = len - m_conn.m_bufs.back().len;
|
||||
WPI_DEBUG4(m_conn.m_logger, "conn: writing {} bytes (nonempty)", amt);
|
||||
m_conn.m_bufs.back().len = len;
|
||||
m_conn.m_framePos += amt;
|
||||
m_conn.m_written += amt;
|
||||
if (!m_disableAlloc) {
|
||||
#ifdef NT_ENABLE_WS_FRAG
|
||||
m_conn.m_frames.back().opcode &= ~wpi::WebSocket::kFlagFin;
|
||||
@@ -74,6 +79,7 @@ void WebSocketConnection::Stream::write_impl(const char* data, size_t len) {
|
||||
size_t amt = (std::min)(static_cast<int>(kAllocSize - buf.len),
|
||||
static_cast<int>(len));
|
||||
if (amt > 0) {
|
||||
WPI_DEBUG4(m_conn.m_logger, "conn: writing {} bytes", amt);
|
||||
std::memcpy(buf.base + buf.len, data, amt);
|
||||
buf.len += amt;
|
||||
m_conn.m_framePos += amt;
|
||||
@@ -101,8 +107,9 @@ void WebSocketConnection::Stream::write_impl(const char* data, size_t len) {
|
||||
}
|
||||
|
||||
WebSocketConnection::WebSocketConnection(wpi::WebSocket& ws,
|
||||
unsigned int version)
|
||||
: m_ws{ws}, m_version{version} {}
|
||||
unsigned int version,
|
||||
wpi::Logger& logger)
|
||||
: m_ws{ws}, m_logger{logger}, m_version{version} {}
|
||||
|
||||
WebSocketConnection::~WebSocketConnection() {
|
||||
for (auto&& buf : m_bufs) {
|
||||
@@ -113,19 +120,8 @@ WebSocketConnection::~WebSocketConnection() {
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketConnection::Start() {
|
||||
m_ws.pong.connect([selfweak = weak_from_this()](auto data) {
|
||||
if (data.size() != 8) {
|
||||
return;
|
||||
}
|
||||
if (auto self = selfweak.lock()) {
|
||||
self->m_lastPingResponse =
|
||||
wpi::support::endian::read64<wpi::support::native>(data.data());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void WebSocketConnection::SendPing(uint64_t time) {
|
||||
WPI_DEBUG4(m_logger, "conn: sending ping {}", time);
|
||||
auto buf = AllocBuf();
|
||||
buf.len = 8;
|
||||
wpi::support::endian::write64<wpi::support::native>(buf.base, time);
|
||||
@@ -142,6 +138,8 @@ void WebSocketConnection::SendPing(uint64_t time) {
|
||||
}
|
||||
|
||||
void WebSocketConnection::StartFrame(uint8_t opcode) {
|
||||
WPI_DEBUG4(m_logger, "conn: starting frame {}",
|
||||
static_cast<unsigned int>(opcode));
|
||||
m_frames.emplace_back(opcode, m_bufs.size(), m_bufs.size() + 1);
|
||||
m_bufs.emplace_back(AllocBuf());
|
||||
m_bufs.back().len = 0;
|
||||
@@ -177,6 +175,7 @@ int WebSocketConnection::Write(
|
||||
if (kind == kText) {
|
||||
os << (first ? '[' : ',');
|
||||
}
|
||||
WPI_DEBUG4(m_logger, "writing");
|
||||
writer(os);
|
||||
}
|
||||
++m_frames.back().count;
|
||||
@@ -188,6 +187,7 @@ int WebSocketConnection::Write(
|
||||
}
|
||||
|
||||
int WebSocketConnection::Flush() {
|
||||
WPI_DEBUG4(m_logger, "conn: flushing");
|
||||
m_lastFlushTime = wpi::Now();
|
||||
if (m_state == kEmpty) {
|
||||
return 0;
|
||||
@@ -252,6 +252,7 @@ void WebSocketConnection::Send(
|
||||
os << ']';
|
||||
}
|
||||
wpi::WebSocket::Frame frame{opcode, os.bufs()};
|
||||
WPI_DEBUG4(m_logger, "Send({})", static_cast<uint8_t>(opcode));
|
||||
m_ws.SendFrames({{frame}}, [selfweak = weak_from_this()](auto bufs, auto) {
|
||||
if (auto self = selfweak.lock()) {
|
||||
self->ReleaseBufs(bufs);
|
||||
@@ -265,7 +266,7 @@ void WebSocketConnection::Send(
|
||||
|
||||
void WebSocketConnection::Disconnect(std::string_view reason) {
|
||||
m_reason = reason;
|
||||
m_ws.Fail(1005, reason);
|
||||
m_ws.Fail(1001, reason);
|
||||
}
|
||||
|
||||
wpi::uv::Buffer WebSocketConnection::AllocBuf() {
|
||||
|
||||
@@ -15,19 +15,22 @@
|
||||
|
||||
#include "WireConnection.h"
|
||||
|
||||
namespace wpi {
|
||||
class Logger;
|
||||
} // namespace wpi
|
||||
|
||||
namespace nt::net {
|
||||
|
||||
class WebSocketConnection final
|
||||
: public WireConnection,
|
||||
public std::enable_shared_from_this<WebSocketConnection> {
|
||||
public:
|
||||
WebSocketConnection(wpi::WebSocket& ws, unsigned int version);
|
||||
WebSocketConnection(wpi::WebSocket& ws, unsigned int version,
|
||||
wpi::Logger& logger);
|
||||
~WebSocketConnection() override;
|
||||
WebSocketConnection(const WebSocketConnection&) = delete;
|
||||
WebSocketConnection& operator=(const WebSocketConnection&) = delete;
|
||||
|
||||
void Start();
|
||||
|
||||
unsigned int GetVersion() const final { return m_version; }
|
||||
|
||||
void SendPing(uint64_t time) final;
|
||||
@@ -51,7 +54,9 @@ class WebSocketConnection final
|
||||
|
||||
uint64_t GetLastFlushTime() const final { return m_lastFlushTime; }
|
||||
|
||||
uint64_t GetLastPingResponse() const final { return m_lastPingResponse; }
|
||||
uint64_t GetLastReceivedTime() const final {
|
||||
return m_ws.GetLastReceivedTime();
|
||||
}
|
||||
|
||||
void Disconnect(std::string_view reason) final;
|
||||
|
||||
@@ -70,6 +75,7 @@ class WebSocketConnection final
|
||||
void ReleaseBufs(std::span<wpi::uv::Buffer> bufs);
|
||||
|
||||
wpi::WebSocket& m_ws;
|
||||
wpi::Logger& m_logger;
|
||||
|
||||
class Stream;
|
||||
|
||||
@@ -92,7 +98,6 @@ class WebSocketConnection final
|
||||
State m_state = kEmpty;
|
||||
std::string m_reason;
|
||||
uint64_t m_lastFlushTime = 0;
|
||||
uint64_t m_lastPingResponse = 0;
|
||||
unsigned int m_version;
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user