mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-27 02:01:42 +00:00
Compare commits
271 Commits
v2024.1.1-
...
v2024.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
4809f3d0fc | ||
|
|
dd90965362 | ||
|
|
8659372d08 | ||
|
|
a2e4d0b15d | ||
|
|
0a46a3a618 | ||
|
|
7c26bc70ab | ||
|
|
f94e3d81b9 | ||
|
|
6bed82a18e | ||
|
|
4595f84719 | ||
|
|
707cb06105 | ||
|
|
3e40b9e5da | ||
|
|
106518c3f8 | ||
|
|
19cb2a8eb4 | ||
|
|
13f4460e00 | ||
|
|
4210f5635d | ||
|
|
0f060afb55 | ||
|
|
f29a7d2e50 | ||
|
|
6e58db398d | ||
|
|
4ac0720385 | ||
|
|
44db3e0ac0 | ||
|
|
73c7d87db7 | ||
|
|
25636b712f | ||
|
|
01fb98baaa | ||
|
|
5c424248c4 | ||
|
|
c486972c55 | ||
|
|
783acb9b72 | ||
|
|
99ab836894 | ||
|
|
ad0859a8c9 | ||
|
|
5579219716 | ||
|
|
98f06911c7 | ||
|
|
e1d49b975c | ||
|
|
8a0bf2b7a4 | ||
|
|
91d8837c11 | ||
|
|
e7c9f27683 | ||
|
|
8aca706217 | ||
|
|
7d3e4ddba9 | ||
|
|
ec3cb3dcba | ||
|
|
495585b25d | ||
|
|
f9aabc5ab2 | ||
|
|
c16946c0ec | ||
|
|
b7f4eb2811 | ||
|
|
f419a62b38 | ||
|
|
938bf45fd9 | ||
|
|
c34debe012 | ||
|
|
07183765de | ||
|
|
af46034b7f | ||
|
|
636ef58d94 | ||
|
|
cc631d2a69 | ||
|
|
09f76b32c2 | ||
|
|
47c5fd8620 | ||
|
|
24a76be694 | ||
|
|
9333951736 | ||
|
|
6a2d3c30a6 | ||
|
|
e07de37e64 | ||
|
|
141241d2d6 | ||
|
|
f2c2bab7dc | ||
|
|
5659038443 | ||
|
|
8aeee03626 | ||
|
|
55508706ff | ||
|
|
ab78b930e9 | ||
|
|
795d4be9fd | ||
|
|
7aa9ad44b8 | ||
|
|
92c81d0791 | ||
|
|
1ce617be07 | ||
|
|
2441b57156 | ||
|
|
21d1972d7a | ||
|
|
c29e8c66cf | ||
|
|
ab309e34ef | ||
|
|
22a322c9f3 | ||
|
|
1dba26c937 | ||
|
|
ef1cb3f41e | ||
|
|
aeb1a4aa33 | ||
|
|
c1178d5add | ||
|
|
4e4a468d4d | ||
|
|
d1793f077d | ||
|
|
43fb6e9f87 | ||
|
|
bcef6c5398 | ||
|
|
4059e0cd9f | ||
|
|
0b2cfb3abc | ||
|
|
df5e439b0c | ||
|
|
0ff7478968 | ||
|
|
6f23d32fe1 | ||
|
|
35a1c52788 | ||
|
|
e4e2bafdb1 | ||
|
|
3d201c71f7 | ||
|
|
f02984159f | ||
|
|
a004c9e05f | ||
|
|
0b4c6a1546 | ||
|
|
ab15dae887 | ||
|
|
9599c1f56f | ||
|
|
f87c64af8a | ||
|
|
8798700cec | ||
|
|
85c9ae6eff | ||
|
|
7c8b7a97ad | ||
|
|
d9b504bc84 | ||
|
|
906b810136 | ||
|
|
56e5b404d1 | ||
|
|
8723ee5c39 | ||
|
|
192a28af47 | ||
|
|
d40bdd70ba | ||
|
|
7bfadf32e5 | ||
|
|
a770110438 | ||
|
|
54a55b8b53 | ||
|
|
7d4e515a6b | ||
|
|
5200316c14 | ||
|
|
ddf79a25d4 | ||
|
|
a71adef316 | ||
|
|
39a0bf4b98 | ||
|
|
f5fc101fda | ||
|
|
38bf024c96 | ||
|
|
9d11544c18 | ||
|
|
28deba20f5 | ||
|
|
c2971c0bb3 | ||
|
|
41cfc961e4 | ||
|
|
14c3ade155 | ||
|
|
90757b9e90 | ||
|
|
2676b77873 | ||
|
|
d32c10487c | ||
|
|
9bc5fcf886 | ||
|
|
d431abba3b | ||
|
|
2bb1409b82 | ||
|
|
66172ab288 | ||
|
|
e8f8c0ceb0 | ||
|
|
890992a849 | ||
|
|
a583ca01e1 | ||
|
|
ca272de400 | ||
|
|
76ae090570 | ||
|
|
5172ab8fd0 | ||
|
|
96914143ba | ||
|
|
464e6121ef | ||
|
|
5dad46cd45 | ||
|
|
54ab65a63a | ||
|
|
7ed900ae3a | ||
|
|
74b85b76a9 | ||
|
|
30816111db | ||
|
|
5cc923de33 | ||
|
|
1144115da0 | ||
|
|
ac7d726ac3 | ||
|
|
e09be72ee0 | ||
|
|
0f9ebe92d9 | ||
|
|
9fa28eb07a | ||
|
|
ca684ac207 | ||
|
|
51eecef2bd | ||
|
|
4fcf0b25a1 | ||
|
|
9b8011aa67 | ||
|
|
e00a0e84c1 | ||
|
|
23dd591394 | ||
|
|
b0719942f0 | ||
|
|
7bc89c4322 | ||
|
|
841ea682d1 | ||
|
|
a74db52dae | ||
|
|
a7eb422662 | ||
|
|
544b231d4d | ||
|
|
31cd015970 | ||
|
|
9280054eab | ||
|
|
2aba97c610 | ||
|
|
c80b2d2017 | ||
|
|
3c0652c18a | ||
|
|
95716eb0cb | ||
|
|
423fd75fa8 | ||
|
|
dfdea9c992 | ||
|
|
ca81ced409 | ||
|
|
437cc91af5 | ||
|
|
25b7dca46b | ||
|
|
bb05e20247 | ||
|
|
35744a036e | ||
|
|
80d7ad58ea | ||
|
|
f8d983b154 | ||
|
|
4a44210ee3 | ||
|
|
bdc8620d55 | ||
|
|
0ca1e9b5f9 | ||
|
|
cc30824409 | ||
|
|
b1fad062f7 | ||
|
|
ead9ae5a69 | ||
|
|
cfbff32185 | ||
|
|
7d90d0bcc3 | ||
|
|
7755e45aac | ||
|
|
3985c031da | ||
|
|
7a87fe4b60 | ||
|
|
09f3ed6a5f | ||
|
|
79dd795bc0 | ||
|
|
e117274a67 | ||
|
|
a8b80ca256 | ||
|
|
b3a9c3e96b | ||
|
|
0f8129677b | ||
|
|
d105f9e3e9 | ||
|
|
c5f2f6a0fb | ||
|
|
c1a57e422a | ||
|
|
78ebc6e9ec | ||
|
|
9ada181866 | ||
|
|
95fa5ec72f | ||
|
|
b6f2d3cc14 | ||
|
|
cc2cbeb04c | ||
|
|
fa6b171e1c | ||
|
|
d504639bbe | ||
|
|
3a1194be40 | ||
|
|
70392cbbcb | ||
|
|
17c1bd5a83 | ||
|
|
e69a9efeba | ||
|
|
14dcd0d26f | ||
|
|
ec1d261984 | ||
|
|
63dbf5c614 | ||
|
|
b2e7be9250 | ||
|
|
201a42a3cd | ||
|
|
04a781b4d7 | ||
|
|
87a8a1ced4 |
@@ -145,6 +145,8 @@ LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
Macros:
|
||||
- 'HAL_ENUM(name)=enum name'
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
|
||||
@@ -49,7 +49,6 @@ Checks:
|
||||
google-build-namespaces,
|
||||
google-explicit-constructor,
|
||||
google-global-names-in-headers,
|
||||
google-readability-avoid-underscore-in-googletest-name,
|
||||
google-readability-casting,
|
||||
google-runtime-operator,
|
||||
misc-definitions-in-headers,
|
||||
|
||||
6
.gersemirc
Normal file
6
.gersemirc
Normal file
@@ -0,0 +1,6 @@
|
||||
color: false
|
||||
definitions: []
|
||||
line_length: 100
|
||||
list_expansion: favour-inlining
|
||||
quiet: false
|
||||
unsafe: false
|
||||
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -1,5 +1,13 @@
|
||||
*.cpp text
|
||||
*.gradle text eol=lf
|
||||
*.h text
|
||||
*.inc text
|
||||
*.java text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.xml text eol=lf
|
||||
|
||||
# Generated files
|
||||
hal/src/generated/** linguist-generated
|
||||
ntcore/src/generated/** linguist-generated
|
||||
wpimath/src/generated/** linguist-generated
|
||||
|
||||
6
.github/workflows/cmake.yml
vendored
6
.github/workflows/cmake.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- name: Install QuickBuffers (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.2/protoc-gen-quickbuf_1.3.2_amd64.deb && sudo apt install ./protoc-gen-quickbuf_1.3.2_amd64.deb
|
||||
run: wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.3/protoc-gen-quickbuf_1.3.3_amd64.deb && sudo apt install ./protoc-gen-quickbuf_1.3.3_amd64.deb
|
||||
|
||||
- name: Install opencv (macOS)
|
||||
run: brew install opencv protobuf@3 ninja
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: configure
|
||||
run: cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ${{ matrix.flags }}
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run vcpkg
|
||||
uses: lukka/run-vcpkg@v11.1
|
||||
|
||||
6
.github/workflows/comment-command.yml
vendored
6
.github/workflows/comment-command.yml
vendored
@@ -19,12 +19,12 @@ jobs:
|
||||
comment_id: context.payload.comment.id,
|
||||
content: "rocket",
|
||||
});
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.COMMENT_COMMAND_PAT_TOKEN }}
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Checkout PR
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
uses: actions/setup-java@v3
|
||||
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
@@ -16,7 +16,7 @@ jobs:
|
||||
if: github.repository_owner == 'wpilibsuite' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
concurrency: ci-docs-publish
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
42
.github/workflows/fix_compile_commands.py
vendored
Executable file
42
.github/workflows/fix_compile_commands.py
vendored
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Fix compile_commands.json generated by Gradle"
|
||||
)
|
||||
parser.add_argument("filename", help="compile_commands.json location")
|
||||
cmd_args = parser.parse_args()
|
||||
|
||||
# Read JSON
|
||||
with open(cmd_args.filename) as f:
|
||||
data = json.load(f)
|
||||
|
||||
for obj in data:
|
||||
out_args = []
|
||||
|
||||
# Filter out -isystem flags that cause false positives
|
||||
iter_args = iter(obj["arguments"])
|
||||
for arg in iter_args:
|
||||
if arg == "-isystem":
|
||||
next_arg = next(iter_args)
|
||||
|
||||
# /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/include/xmmintrin.h:54:1:
|
||||
# error: conflicting types for '_mm_prefetch' [clang-diagnostic-error]
|
||||
if not next_arg.startswith("/usr/lib/gcc/"):
|
||||
out_args += ["-isystem", next_arg]
|
||||
else:
|
||||
out_args.append(arg)
|
||||
|
||||
obj["arguments"] = out_args
|
||||
|
||||
# Write JSON
|
||||
with open(cmd_args.filename, "w") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -10,5 +10,5 @@ jobs:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
30
.github/workflows/gradle.yml
vendored
30
.github/workflows/gradle.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set release environment variable
|
||||
@@ -54,14 +54,14 @@ jobs:
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- name: Check free disk space
|
||||
run: df .
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-host:
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 11
|
||||
MACOSX_DEPLOYMENT_TARGET: 12
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -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"
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
- name: Check disk free space (Windows)
|
||||
run: wmic logicaldisk get caption, freespace
|
||||
if: matrix.os == 'windows-2022'
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: ${{ matrix.build-dir }}/${{ matrix.outputs }}
|
||||
@@ -168,13 +168,13 @@ jobs:
|
||||
name: "Build - Documentation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
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')
|
||||
@@ -183,7 +183,7 @@ jobs:
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Documentation
|
||||
path: docs/build/outputs
|
||||
@@ -206,13 +206,13 @@ jobs:
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
with:
|
||||
repository: wpilibsuite/build-tools
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
@@ -255,7 +255,7 @@ jobs:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
|
||||
35
.github/workflows/lint-format.yml
vendored
35
.github/workflows/lint-format.yml
vendored
@@ -15,11 +15,11 @@ jobs:
|
||||
name: "wpiformat"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
run: pip3 install wpiformat==2023.36
|
||||
- name: Run
|
||||
run: wpiformat
|
||||
- name: Check output
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Generate diff
|
||||
run: git diff HEAD > wpiformat-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wpiformat fixes
|
||||
path: wpiformat-fixes.patch
|
||||
@@ -53,11 +53,12 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
container: wpilib/roborio-cross-ubuntu:2023-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
@@ -67,21 +68,27 @@ jobs:
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Create compile_commands.json
|
||||
run: ./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
|
||||
run: |
|
||||
./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
|
||||
./.github/workflows/fix_compile_commands.py build/TargetedCompileCommands/linuxx86-64release/compile_commands.json
|
||||
./.github/workflows/fix_compile_commands.py build/TargetedCompileCommands/linuxx86-64debug/compile_commands.json
|
||||
- name: List changed files
|
||||
run: wpiformat -list-changed-files
|
||||
- name: Run clang-tidy
|
||||
run: wpiformat -no-format -tidy-changed -compile-commands=build/compile_commands/linuxx86-64 -vv
|
||||
- name: Run clang-tidy release
|
||||
run: wpiformat -no-format -tidy-changed -compile-commands=build/TargetedCompileCommands/linuxx86-64release -vv
|
||||
- name: Run clang-tidy debug
|
||||
run: wpiformat -no-format -tidy-changed -compile-commands=build/TargetedCompileCommands/linuxx86-64debug -vv
|
||||
javaformat:
|
||||
name: "Java format"
|
||||
runs-on: ubuntu-22.04
|
||||
container: wpilib/ubuntu-base:22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Run Java format
|
||||
@@ -95,12 +102,12 @@ jobs:
|
||||
name: "Documentation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
java-version: 17
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew docs:zipDocs -PbuildServer -PdocWarningsAsErrors ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
|
||||
46
.github/workflows/pregenerate.yml
vendored
Normal file
46
.github/workflows/pregenerate.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Check Pregenerated Files
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: "Update"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
- name: Install protobuf dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler && wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.3/protoc-gen-quickbuf-1.3.3-linux-x86_64.exe && chmod +x protoc-gen-quickbuf-1.3.3-linux-x86_64.exe
|
||||
- name: Run hal
|
||||
run: ./hal/generate_usage_reporting.py
|
||||
- name: Run ntcore
|
||||
run: ./ntcore/generate_topics.py
|
||||
- name: Run wpimath
|
||||
run: ./wpimath/generate_numbers.py && ./wpimath/generate_quickbuf.py protoc protoc-gen-quickbuf-1.3.3-linux-x86_64.exe
|
||||
- name: Add untracked files to index so they count as changes
|
||||
run: git add -A
|
||||
- name: Check output
|
||||
run: git --no-pager diff --exit-code HEAD
|
||||
- name: Generate diff
|
||||
run: git diff HEAD > pregenerated-files-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pregenerated-files-fixes
|
||||
path: pregenerated-files-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
4
.github/workflows/sanitizers.yml
vendored
4
.github/workflows/sanitizers.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
- name: Install QuickBuffers
|
||||
if: runner.os == 'Linux'
|
||||
run: wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.2/protoc-gen-quickbuf_1.3.2_amd64.deb && sudo apt install ./protoc-gen-quickbuf_1.3.2_amd64.deb
|
||||
run: wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.3/protoc-gen-quickbuf_1.3.3_amd64.deb && sudo apt install ./protoc-gen-quickbuf_1.3.3_amd64.deb
|
||||
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.3
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake -G Ninja -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++-14 -DWITH_JAVA=OFF ${{ matrix.cmake-flags }} ..
|
||||
|
||||
5
.github/workflows/upstream-utils.yml
vendored
5
.github/workflows/upstream-utils.yml
vendored
@@ -15,10 +15,11 @@ jobs:
|
||||
name: "Update"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.9
|
||||
|
||||
@@ -10,6 +10,7 @@ cppSrcFileInclude {
|
||||
}
|
||||
|
||||
modifiableFileExclude {
|
||||
cmake/toolchains/
|
||||
\.patch$
|
||||
gradlew
|
||||
}
|
||||
|
||||
311
CMakeLists.txt
311
CMakeLists.txt
@@ -1,12 +1,15 @@
|
||||
# Disable in-source builds to prevent source tree corruption.
|
||||
if(" ${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL " ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(FATAL_ERROR "
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: In-source builds are not allowed.
|
||||
You should create a separate directory for build files.
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
set(CMAKE_SYSTEM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
|
||||
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
|
||||
endif()
|
||||
@@ -16,7 +19,7 @@ project(allwpilib)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
# Make timestamps of extracted files from FetchContent the time of extraction
|
||||
if (POLICY CMP0135)
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
@@ -24,7 +27,7 @@ message(STATUS "Platform version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
|
||||
|
||||
set(WPILIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
INCLUDE(CPack)
|
||||
include(CPack)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
@@ -35,31 +38,32 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/bin)
|
||||
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${WPILIB_BINARY_DIR}/jar)
|
||||
|
||||
# use, i.e. don't skip the full RPATH for the build tree
|
||||
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
|
||||
# when building, don't use the install RPATH already
|
||||
# (but later on when installing)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
# add the automatically determined parts of the RPATH
|
||||
# which point to directories outside the build tree to the install RPATH
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
# the RPATH to be used when installing, but only if it's not a system directory
|
||||
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
IF("${isSystemDir}" STREQUAL "-1")
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
ENDIF("${isSystemDir}" STREQUAL "-1")
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
# Options for building certain parts of the repo. Everything is built by default.
|
||||
option(BUILD_SHARED_LIBS "Build with shared libs (needed for JNI)" ON)
|
||||
option(WITH_JAVA "Include Java and JNI in the build" ON)
|
||||
option(WITH_JAVA_SOURCE "Build Java source jars" ON)
|
||||
option(WITH_JAVA_SOURCE "Build Java source jars" ${WITH_JAVA})
|
||||
option(WITH_CSCORE "Build cscore (needs OpenCV)" ON)
|
||||
option(WITH_NTCORE "Build ntcore" ON)
|
||||
option(WITH_WPIMATH "Build wpimath" ON)
|
||||
option(WITH_WPIUNITS "Build wpiunits" ON)
|
||||
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (needs OpenCV)" ON)
|
||||
option(WITH_EXAMPLES "Build examples" OFF)
|
||||
option(WITH_TESTS "Build unit tests (requires internet connection)" ON)
|
||||
@@ -75,135 +79,154 @@ option(USE_SYSTEM_FMTLIB "Use system fmtlib" OFF)
|
||||
option(USE_SYSTEM_LIBUV "Use system libuv" OFF)
|
||||
option(USE_SYSTEM_EIGEN "Use system eigen" OFF)
|
||||
|
||||
# Options for installation.
|
||||
option(WITH_FLAT_INSTALL "Use a flat install directory" OFF)
|
||||
|
||||
# Options for location of OpenCV Java.
|
||||
set(OPENCV_JAVA_INSTALL_DIR "" CACHE PATH "Location to search for the OpenCV jar file")
|
||||
|
||||
# Options for compilation flags.
|
||||
option(NO_WERROR "Disable -Werror flag during compilation" OFF)
|
||||
|
||||
# Set default build type to release with debug info (i.e. release mode optimizations
|
||||
# are performed, but debug info still exists).
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
if (WITH_JAVA AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "
|
||||
if(WITH_JAVA AND NOT BUILD_SHARED_LIBS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build static libs with Java enabled.
|
||||
Static libs requires both BUILD_SHARED_LIBS=OFF and
|
||||
WITH_JAVA=OFF
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "
|
||||
if(WITH_SIMULATION_MODULES AND NOT BUILD_SHARED_LIBS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build static libs with simulation modules enabled.
|
||||
Static libs requires both BUILD_SHARED_LIBS=OFF and
|
||||
WITH_SIMULATION_MODULES=OFF
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_JAVA OR NOT WITH_CSCORE)
|
||||
if(NOT WITH_JAVA OR NOT WITH_CSCORE)
|
||||
if(NOT "${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
|
||||
message(WARNING "
|
||||
message(
|
||||
WARNING
|
||||
"
|
||||
WARNING: OpenCV Java dir set but java is not enabled!
|
||||
It will be ignored.
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT WITH_WPILIB AND WITH_SIMULATION_MODULES)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_WPILIB AND WITH_SIMULATION_MODULES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build simulation modules with wpilib disabled.
|
||||
Enable wpilib by setting WITH_WPILIB=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_CSCORE)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_CSCORE)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build cameraserver without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_GUI)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_GUI)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build GUI modules without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_SIMULATION_MODULES)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_SIMULATION_MODULES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build simulation modules without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_WPILIB)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_WPILIB)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build wpilib without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_WPIMATH AND WITH_WPILIB)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_WPIMATH AND WITH_WPILIB)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build wpilib without wpimath.
|
||||
Enable wpimath by setting WITH_WPIMATH=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
set( wpilib_dest "")
|
||||
set( include_dest include )
|
||||
set( java_lib_dest java )
|
||||
set( jni_lib_dest jni )
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (wpilib_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (wpilib_config_dir share/wpilib)
|
||||
if(NOT WITH_WPIUNITS AND WITH_WPIMATH AND WITH_JAVA)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build Java wpimath without wpiunits.
|
||||
Enable wpiunits by setting WITH_WPIUNITS=ON or disable the Java build by setting WITH_JAVA=OFF
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_LIBUV)
|
||||
set (LIBUV_SYSTEM_REPLACE "
|
||||
set(include_dest include)
|
||||
set(java_lib_dest java)
|
||||
set(jni_lib_dest jni)
|
||||
|
||||
if(USE_SYSTEM_LIBUV)
|
||||
set(LIBUV_SYSTEM_REPLACE
|
||||
"
|
||||
find_dependency(libuv CONFIG)
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_EIGEN)
|
||||
set (EIGEN_SYSTEM_REPLACE "find_package(Eigen3 CONFIG)")
|
||||
if(USE_SYSTEM_EIGEN)
|
||||
set(EIGEN_SYSTEM_REPLACE "find_package(Eigen3 CONFIG)")
|
||||
endif()
|
||||
|
||||
find_package(LIBSSH 0.7.1)
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
find_program(Quickbuf_EXECUTABLE
|
||||
NAMES protoc-gen-quickbuf
|
||||
DOC "The Quickbuf protoc plugin"
|
||||
)
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-config.cmake)")
|
||||
set(WPINET_DEP_REPLACE "include($\{SELF_DIR\}/wpinet-config.cmake)")
|
||||
set(NTCORE_DEP_REPLACE "include($\{SELF_DIR\}/ntcore-config.cmake)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cscore-config.cmake)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cameraserver-config.cmake)")
|
||||
set(HAL_DEP_REPLACE_IMPL "include(\${SELF_DIR}/hal-config.cmake)")
|
||||
set(WPIMATH_DEP_REPLACE "include($\{SELF_DIR\}/wpimath-config.cmake)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "include(\${SELF_DIR}/wpilibc-config.cmake)")
|
||||
set(WPILIBNEWCOMMANDS_DEP_REPLACE "include(\${SELF_DIR}/wpilibNewcommands-config.cmake)")
|
||||
else()
|
||||
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
|
||||
set(WPINET_DEP_REPLACE "find_dependency(wpinet)")
|
||||
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
|
||||
set(APRILTAG_DEP_REPLACE "find_dependency(apriltag)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
|
||||
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
|
||||
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
|
||||
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
|
||||
set(WPILIBJ_DEP_REPLACE "find_dependency(wpilibj)")
|
||||
set(WPILIBNEWCOMMANDS_DEP_REPLACE "find_dependency(wpilibNewCommands)")
|
||||
endif()
|
||||
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
|
||||
set(WPINET_DEP_REPLACE "find_dependency(wpinet)")
|
||||
set(WPIUNITS_DEP_REPLACE "find_dependency(wpiunits)")
|
||||
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
|
||||
|
||||
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
|
||||
set(SELF_DIR "$\{SELF_DIR\}")
|
||||
@@ -221,7 +244,15 @@ if(isMultiConfig)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES Ubsan)
|
||||
endif()
|
||||
else()
|
||||
set(allowedBuildTypes Asan Tsan Ubsan Debug Release RelWithDebInfo MinSizeRel)
|
||||
set(allowedBuildTypes
|
||||
Asan
|
||||
Tsan
|
||||
Ubsan
|
||||
Debug
|
||||
Release
|
||||
RelWithDebInfo
|
||||
MinSizeRel
|
||||
)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
|
||||
@@ -230,54 +261,90 @@ else()
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_ASAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Asan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Asan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_ASAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Asan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_ASAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
|
||||
"Linker flags to be used to create executables for Asan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Asan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Asan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address"
|
||||
CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Asan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS_TSAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Tsan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Tsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_TSAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Tsan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Tsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_TSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
|
||||
"Linker flags to be used to create executables for Tsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Tsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_TSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Tsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread"
|
||||
CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Tsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS_UBSAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Ubsan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Ubsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_UBSAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Ubsan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Ubsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_UBSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all" CACHE STRING
|
||||
"Linker flags to be used to create executables for Ubsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Ubsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_UBSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Ubsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined"
|
||||
CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Ubsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(googletest)
|
||||
include(GoogleTest)
|
||||
@@ -285,41 +352,49 @@ endif()
|
||||
|
||||
add_subdirectory(wpiutil)
|
||||
|
||||
if (WITH_NTCORE)
|
||||
if(WITH_NTCORE)
|
||||
add_subdirectory(wpinet)
|
||||
add_subdirectory(ntcore)
|
||||
endif()
|
||||
|
||||
if (WITH_WPIMATH)
|
||||
if(WITH_WPIMATH)
|
||||
if(WITH_JAVA)
|
||||
add_subdirectory(wpiunits)
|
||||
endif()
|
||||
add_subdirectory(wpimath)
|
||||
endif()
|
||||
|
||||
if (WITH_GUI)
|
||||
if(WITH_WPIUNITS AND NOT WITH_WPIMATH)
|
||||
# In case of building wpiunits standalone
|
||||
add_subdirectory(wpiunits)
|
||||
endif()
|
||||
|
||||
if(WITH_GUI)
|
||||
add_subdirectory(fieldImages)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(wpigui)
|
||||
add_subdirectory(glass)
|
||||
add_subdirectory(outlineviewer)
|
||||
add_subdirectory(sysid)
|
||||
if (LIBSSH_FOUND)
|
||||
if(LIBSSH_FOUND)
|
||||
add_subdirectory(roborioteamnumbersetter)
|
||||
add_subdirectory(datalogtool)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB OR WITH_SIMULATION_MODULES)
|
||||
if(WITH_WPILIB OR WITH_SIMULATION_MODULES)
|
||||
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(hal)
|
||||
endif()
|
||||
|
||||
if (WITH_CSCORE)
|
||||
if(WITH_CSCORE)
|
||||
set(CSCORE_DEP_REPLACE ${CSCORE_DEP_REPLACE_IMPL})
|
||||
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(cscore)
|
||||
add_subdirectory(cameraserver)
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB)
|
||||
if(WITH_WPILIB)
|
||||
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(apriltag)
|
||||
add_subdirectory(wpilibj)
|
||||
@@ -327,15 +402,15 @@ if (WITH_WPILIB)
|
||||
add_subdirectory(wpilibNewCommands)
|
||||
add_subdirectory(romiVendordep)
|
||||
add_subdirectory(xrpVendordep)
|
||||
if (WITH_EXAMPLES)
|
||||
if(WITH_EXAMPLES)
|
||||
add_subdirectory(wpilibcExamples)
|
||||
endif()
|
||||
add_subdirectory(myRobot)
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
|
||||
if(WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
|
||||
add_subdirectory(simulation)
|
||||
endif()
|
||||
|
||||
configure_file(wpilib-config.cmake.in ${WPILIB_BINARY_DIR}/wpilib-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/wpilib-config.cmake DESTINATION ${wpilib_config_dir})
|
||||
configure_file(wpilib-config.cmake.in ${WPILIB_BINARY_DIR}/wpilib-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/wpilib-config.cmake DESTINATION share/wpilib)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## Publishing Third Party Dependencies
|
||||
Currently the 3rd party deps are imgui, opencv, and google test
|
||||
Currently the 3rd party deps are imgui, opencv, google test, libssh, and apriltaglib
|
||||
|
||||
For publishing these dependencies, the version needs to be manually updated in the publish.gradle file of their respective repository.
|
||||
Then, in the azure build for the dependency you want to build for, manually start a pipeline build (As of current, this is the `Run Pipeline` button).
|
||||
@@ -24,4 +24,4 @@ Upon pushing a tag, a release will be built, and the files will be uploaded to t
|
||||
Before publishing, make sure to update the version in build.gradle. Publishing must happen locally, using the command `./gradlew publishPlugin`. This does require your API key for publishing to be set.
|
||||
|
||||
## Building the installer
|
||||
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. Then push, it will build the installer on azure.
|
||||
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. To publish a release build, upload a new tag, and a release will automatically be built and published to artifactory and cloudflare.
|
||||
|
||||
@@ -145,6 +145,11 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* wpinet
|
||||
* wpiutil
|
||||
|
||||
* wpiunits
|
||||
|
||||
* apriltag
|
||||
* wpiutil
|
||||
* wpimath
|
||||
|
||||
### Third Party Artifacts
|
||||
|
||||
@@ -152,6 +157,7 @@ This repository provides the builds of the following third party software.
|
||||
|
||||
All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
|
||||
|
||||
* apriltaglib
|
||||
* googletest
|
||||
* imgui
|
||||
* opencv
|
||||
|
||||
@@ -12,6 +12,7 @@ WPILib is normally built with Gradle, however for some systems, such as Linux ba
|
||||
* halsim
|
||||
* wpigui
|
||||
* wpimath
|
||||
* wpiunits
|
||||
* wpilibNewCommands
|
||||
|
||||
By default, all libraries except for the HAL and WPILib get built with a default CMake setup. The libraries are built as shared libraries, and include the JNI libraries as well as building the Java JARs.
|
||||
@@ -44,6 +45,8 @@ The following build options are available:
|
||||
* This option will cause ntcore to be built. Turning this off will implicitly disable wpinet and wpilib as well, irrespective of their specific options.
|
||||
* `WITH_WPIMATH` (ON Default)
|
||||
* This option will build the wpimath library. This option must be on to build wpilib.
|
||||
* `WITH_WPIUNITS` (ON Default)
|
||||
* This option will build the wpiunits library. This option must be on to build the Java wpimath library and requires `WITH_JAVA` to also be on.
|
||||
* `WITH_WPILIB` (ON Default)
|
||||
* This option will build the hal and wpilibc/j during the build. The HAL is the simulator hal, unless the external hal options are used. The cmake build has no capability to build for the RoboRIO.
|
||||
* `WITH_EXAMPLES` (ON Default)
|
||||
@@ -60,6 +63,8 @@ The following build options are available:
|
||||
* TODO
|
||||
* `OPENCV_JAVA_INSTALL_DIR`
|
||||
* Set this option to the location of the archive of the OpenCV Java bindings (it should be called opencv-xxx.jar, with the x'es being version numbers). NOTE: set it to the LOCATION of the file, not the file itself!
|
||||
* `NO_WERROR` (OFF Default)
|
||||
* This option will disable the `-Werror` compilation flag for non-MSVC builds.
|
||||
|
||||
## Build Setup
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,121 +4,146 @@ include(CompileWarnings)
|
||||
include(GenResources)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
fetchcontent_declare(
|
||||
apriltaglib
|
||||
GIT_REPOSITORY https://github.com/wpilibsuite/apriltag.git
|
||||
GIT_TAG 64be6ab26abf5e995321997fd0752c609a7e30f4
|
||||
GIT_REPOSITORY https://github.com/wpilibsuite/apriltag.git
|
||||
GIT_TAG 64be6ab26abf5e995321997fd0752c609a7e30f4
|
||||
)
|
||||
|
||||
# Don't use apriltag's CMakeLists.txt due to conflicting naming and JNI
|
||||
FetchContent_GetProperties(apriltaglib)
|
||||
fetchcontent_getproperties(apriltaglib)
|
||||
if(NOT apriltaglib_POPULATED)
|
||||
FetchContent_Populate(apriltaglib)
|
||||
fetchcontent_populate(apriltaglib)
|
||||
endif()
|
||||
|
||||
aux_source_directory(${apriltaglib_SOURCE_DIR}/common APRILTAGLIB_COMMON_SRC)
|
||||
file(GLOB TAG_FILES ${apriltaglib_SOURCE_DIR}/tag*.c)
|
||||
set(APRILTAGLIB_SRCS ${apriltaglib_SOURCE_DIR}/apriltag.c ${apriltaglib_SOURCE_DIR}/apriltag_pose.c ${apriltaglib_SOURCE_DIR}/apriltag_quad_thresh.c)
|
||||
set(APRILTAGLIB_SRCS
|
||||
${apriltaglib_SOURCE_DIR}/apriltag.c
|
||||
${apriltaglib_SOURCE_DIR}/apriltag_pose.c
|
||||
${apriltaglib_SOURCE_DIR}/apriltag_quad_thresh.c
|
||||
)
|
||||
|
||||
file(GLOB apriltag_jni_src src/main/native/cpp/jni/AprilTagJNI.cpp)
|
||||
|
||||
if (WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
if(WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
|
||||
set(CMAKE_JNI_TARGET true)
|
||||
set(CMAKE_JNI_TARGET true)
|
||||
|
||||
file(GLOB EJML_JARS "${WPILIB_BINARY_DIR}/wpimath/thirdparty/ejml/*.jar")
|
||||
file(GLOB JACKSON_JARS "${WPILIB_BINARY_DIR}/wpiutil/thirdparty/jackson/*.jar")
|
||||
find_file(OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/share/java
|
||||
NO_DEFAULT_PATH)
|
||||
file(GLOB EJML_JARS "${WPILIB_BINARY_DIR}/wpimath/thirdparty/ejml/*.jar")
|
||||
file(GLOB JACKSON_JARS "${WPILIB_BINARY_DIR}/wpiutil/thirdparty/jackson/*.jar")
|
||||
find_file(
|
||||
OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/share/java
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
set(CMAKE_JAVA_INCLUDE_PATH apriltag.jar ${EJML_JARS} ${JACKSON_JARS})
|
||||
set(CMAKE_JAVA_INCLUDE_PATH apriltag.jar ${EJML_JARS} ${JACKSON_JARS})
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
file(GLOB_RECURSE JAVA_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/main/native/resources/*.json)
|
||||
add_jar(apriltag_jar
|
||||
SOURCES ${JAVA_SOURCES}
|
||||
RESOURCES NAMESPACE "edu/wpi/first/apriltag" ${JAVA_RESOURCES}
|
||||
INCLUDE_JARS wpimath_jar ${EJML_JARS} wpiutil_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME apriltag
|
||||
GENERATE_NATIVE_HEADERS apriltag_jni_headers)
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
file(
|
||||
GLOB_RECURSE JAVA_RESOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/main/native/resources/*.json
|
||||
)
|
||||
add_jar(
|
||||
apriltag_jar
|
||||
SOURCES ${JAVA_SOURCES}
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/apriltag" ${JAVA_RESOURCES}
|
||||
INCLUDE_JARS wpimath_jar wpiunits_jar ${EJML_JARS} wpiutil_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME apriltag
|
||||
GENERATE_NATIVE_HEADERS apriltag_jni_headers
|
||||
)
|
||||
|
||||
get_property(APRILTAG_JAR_FILE TARGET apriltag_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${APRILTAG_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
install_jar(apriltag_jar DESTINATION ${java_lib_dest})
|
||||
install_jar_exports(TARGETS apriltag_jar FILE apriltag_jar.cmake DESTINATION share/apriltag)
|
||||
|
||||
set_property(TARGET apriltag_jar PROPERTY FOLDER "java")
|
||||
add_library(apriltagjni ${apriltag_jni_src})
|
||||
wpilib_target_warnings(apriltagjni)
|
||||
target_link_libraries(apriltagjni PUBLIC apriltag)
|
||||
|
||||
add_library(apriltagjni ${apriltag_jni_src})
|
||||
wpilib_target_warnings(apriltagjni)
|
||||
target_link_libraries(apriltagjni PUBLIC apriltag)
|
||||
set_property(TARGET apriltagjni PROPERTY FOLDER "libraries")
|
||||
|
||||
set_property(TARGET apriltagjni PROPERTY FOLDER "libraries")
|
||||
|
||||
target_link_libraries(apriltagjni PRIVATE apriltag_jni_headers)
|
||||
add_dependencies(apriltagjni apriltag_jar)
|
||||
|
||||
install(TARGETS apriltagjni EXPORT apriltagjni)
|
||||
target_link_libraries(apriltagjni PRIVATE apriltag_jni_headers)
|
||||
add_dependencies(apriltagjni apriltag_jar)
|
||||
|
||||
install(TARGETS apriltagjni EXPORT apriltagjni)
|
||||
endif()
|
||||
|
||||
if (WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB APRILTAG_SOURCES src/main/java/edu/wpi/first/apriltag/*.java)
|
||||
add_jar(apriltag_src_jar
|
||||
RESOURCES NAMESPACE "edu/wpi/first/apriltag" ${APRILTAG_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/apriltag/jni" src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java
|
||||
OUTPUT_NAME apriltag-sources)
|
||||
if(WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB APRILTAG_SOURCES src/main/java/edu/wpi/first/apriltag/*.java)
|
||||
add_jar(
|
||||
apriltag_src_jar
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/apriltag" ${APRILTAG_SOURCES}
|
||||
NAMESPACE
|
||||
"edu/wpi/first/apriltag/jni"
|
||||
src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java
|
||||
OUTPUT_NAME apriltag-sources
|
||||
)
|
||||
|
||||
get_property(APRILTAG_SRC_JAR_FILE TARGET apriltag_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${APRILTAG_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
get_property(APRILTAG_SRC_JAR_FILE TARGET apriltag_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${APRILTAG_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
set_property(TARGET apriltag_src_jar PROPERTY FOLDER "java")
|
||||
set_property(TARGET apriltag_src_jar PROPERTY FOLDER "java")
|
||||
endif()
|
||||
|
||||
generate_resources(src/main/native/resources/edu/wpi/first/apriltag generated/main/cpp APRILTAG frc apriltag_resources_src)
|
||||
|
||||
file(GLOB apriltag_native_src src/main/native/cpp/*.cpp)
|
||||
|
||||
add_library(apriltag ${apriltag_native_src} ${apriltag_resources_src} ${APRILTAGLIB_SRCS} ${APRILTAGLIB_COMMON_SRC} ${TAG_FILES})
|
||||
add_library(
|
||||
apriltag
|
||||
${apriltag_native_src}
|
||||
${apriltag_resources_src}
|
||||
${APRILTAGLIB_SRCS}
|
||||
${APRILTAGLIB_COMMON_SRC}
|
||||
${TAG_FILES}
|
||||
)
|
||||
set_target_properties(apriltag PROPERTIES DEBUG_POSTFIX "d")
|
||||
|
||||
set_property(TARGET apriltag PROPERTY FOLDER "libraries")
|
||||
target_compile_features(apriltag PUBLIC cxx_std_20)
|
||||
wpilib_target_warnings(apriltag)
|
||||
# disable warnings that apriltaglib can't handle
|
||||
if (MSVC)
|
||||
target_compile_options(apriltag PRIVATE /wd4018 /wd4005 /wd4996)
|
||||
if(MSVC)
|
||||
target_compile_options(apriltag PRIVATE /wd4018 /wd4005 /wd4996)
|
||||
else()
|
||||
target_compile_options(apriltag PRIVATE -Wno-sign-compare -Wno-gnu-zero-variadic-macro-arguments -Wno-type-limits)
|
||||
target_compile_options(
|
||||
apriltag
|
||||
PRIVATE -Wno-sign-compare -Wno-gnu-zero-variadic-macro-arguments -Wno-type-limits
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(apriltag wpimath)
|
||||
|
||||
target_include_directories(apriltag PUBLIC
|
||||
$<BUILD_INTERFACE:${apriltaglib_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/apriltag>)
|
||||
target_include_directories(
|
||||
apriltag
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${apriltaglib_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/apriltag>
|
||||
)
|
||||
|
||||
install(TARGETS apriltag EXPORT apriltag)
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/apriltag")
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (apriltag_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (apriltag_config_dir share/apriltag)
|
||||
endif()
|
||||
configure_file(apriltag-config.cmake.in ${WPILIB_BINARY_DIR}/apriltag-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/apriltag-config.cmake DESTINATION share/apriltag)
|
||||
install(EXPORT apriltag DESTINATION share/apriltag)
|
||||
|
||||
configure_file(apriltag-config.cmake.in ${WPILIB_BINARY_DIR}/apriltag-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/apriltag-config.cmake DESTINATION ${apriltag_config_dir})
|
||||
install(EXPORT apriltag DESTINATION ${apriltag_config_dir})
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
wpilib_add_test(apriltag src/test/native/cpp)
|
||||
target_include_directories(apriltag_test PRIVATE src/test/native/include)
|
||||
target_link_libraries(apriltag_test apriltag gmock_main)
|
||||
|
||||
28
apriltag/README.md
Normal file
28
apriltag/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# AprilTag
|
||||
|
||||
## Adding new field to AprilTagFields
|
||||
|
||||
### Adding field JSON
|
||||
|
||||
1. Add a field layout CSV file to `src/main/native/resources/edu/wpi/first/apriltag`
|
||||
1. See docstring in `convert_apriltag_layouts.py` for more
|
||||
2. Run `convert_apriltag_layouts.py` in the same directory as this readme to generate the JSON
|
||||
3. That script overwrites all generated JSONs, so undo undesired changes if necessary
|
||||
4. Update the field dimensions at the bottom of the JSON
|
||||
1. Length should be in meters from alliance wall to alliance wall
|
||||
2. Width should be in meters from inside guardrail plastic to plastic
|
||||
|
||||
### Java updates
|
||||
|
||||
1. Update `src/main/java/edu/wpi/first/apriltag/AprilTagFields.java`
|
||||
1. Add enum value for new field to `AprilTagFields`
|
||||
2. Update `AprilTagFields.kDefaultField` if necessary
|
||||
|
||||
### C++ updates
|
||||
|
||||
1. Update `src/main/native/include/frc/apriltag/AprilTagFields.h`
|
||||
1. Add enum value for new field to `AprilTagFields`
|
||||
2. Update `AprilTagFields::kDefaultField` if necessary
|
||||
2. Update `src/main/native/cpp/AprilTagFields.cpp`
|
||||
1. Add resource getter prototype like `std::string_view GetResource_2024_crescendo_json()`
|
||||
2. Add case for new field to switch in `LoadAprilTagLayoutField()`
|
||||
@@ -5,3 +5,6 @@ include(CMakeFindDependencyMacro)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
include(${SELF_DIR}/apriltag.cmake)
|
||||
if(@WITH_JAVA@)
|
||||
include(${SELF_DIR}/apriltag_jar.cmake)
|
||||
endif()
|
||||
|
||||
88
apriltag/convert_apriltag_layouts.py
Executable file
88
apriltag/convert_apriltag_layouts.py
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This script converts all AprilTag field layout CSV files in
|
||||
src/main/native/resources/edu/wpi/first/apriltag to the JSON format
|
||||
AprilTagFields expects.
|
||||
|
||||
The input CSV has the following format:
|
||||
|
||||
* Columns: ID, X, Y, Z, Rotation
|
||||
* ID is a positive integer
|
||||
* X, Y, and Z are decimal inches
|
||||
* Rotation is yaw in degrees
|
||||
|
||||
The values come from a table in the layout marking diagram (e.g.,
|
||||
https://firstfrc.blob.core.windows.net/frc2024/FieldAssets/2024LayoutMarkingDiagram.pdf).
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
|
||||
from wpimath import geometry, units
|
||||
import numpy as np
|
||||
|
||||
|
||||
def main():
|
||||
# Find AprilTag field layout CSVs
|
||||
filenames = [
|
||||
os.path.join(dp, f)
|
||||
for dp, dn, fn in os.walk("src/main/native/resources/edu/wpi/first/apriltag")
|
||||
for f in fn
|
||||
if f.endswith(".csv")
|
||||
]
|
||||
|
||||
for filename in filenames:
|
||||
json_data = {"tags": [], "field": {"length": 0.0, "width": 0.0}}
|
||||
|
||||
# Read CSV and fill in JSON data
|
||||
with open(filename, newline="") as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=",")
|
||||
|
||||
# Skip header
|
||||
next(reader)
|
||||
|
||||
for row in reader:
|
||||
# Unpack row elements
|
||||
id = int(row[0])
|
||||
x = float(row[1])
|
||||
y = float(row[2])
|
||||
z = float(row[3])
|
||||
rotation = float(row[4])
|
||||
|
||||
# Turn yaw into quaternion
|
||||
q = geometry.Rotation3d(
|
||||
units.radians(0.0),
|
||||
units.radians(0.0),
|
||||
units.degreesToRadians(rotation),
|
||||
).getQuaternion()
|
||||
|
||||
json_data["tags"].append(
|
||||
{
|
||||
"ID": id,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": units.inchesToMeters(x),
|
||||
"y": units.inchesToMeters(y),
|
||||
"z": units.inchesToMeters(z),
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": q.W(),
|
||||
"X": q.X(),
|
||||
"Y": q.Y(),
|
||||
"Z": q.Z(),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Write JSON
|
||||
with open(filename.replace(".csv", ".json"), "w") as f:
|
||||
json.dump(json_data, f, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -6,17 +6,28 @@ package edu.wpi.first.apriltag;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import edu.wpi.first.apriltag.jni.AprilTagJNI;
|
||||
import edu.wpi.first.math.geometry.Pose3d;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Represents an AprilTag's metadata. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class AprilTag {
|
||||
/** The tag's ID. */
|
||||
@JsonProperty(value = "ID")
|
||||
public int ID;
|
||||
|
||||
/** The tag's pose. */
|
||||
@JsonProperty(value = "pose")
|
||||
public Pose3d pose;
|
||||
|
||||
/**
|
||||
* Constructs an AprilTag.
|
||||
*
|
||||
* @param ID The tag's ID.
|
||||
* @param pose The tag's pose.
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
@JsonCreator
|
||||
public AprilTag(
|
||||
@@ -44,4 +55,28 @@ public class AprilTag {
|
||||
public String toString() {
|
||||
return "AprilTag(ID: " + ID + ", pose: " + pose + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 16h5 passed in.
|
||||
*
|
||||
* @param id id
|
||||
* @return A RawFrame containing the AprilTag image
|
||||
*/
|
||||
public static RawFrame generate16h5AprilTagImage(int id) {
|
||||
RawFrame frame = new RawFrame();
|
||||
AprilTagJNI.generate16h5AprilTagImage(frame, frame.getNativeObj(), id);
|
||||
return frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 36h11 passed in.
|
||||
*
|
||||
* @param id id
|
||||
* @return A RawFrame containing the AprilTag image
|
||||
*/
|
||||
public static RawFrame generate36h11AprilTagImage(int id) {
|
||||
RawFrame frame = new RawFrame();
|
||||
AprilTagJNI.generate36h11AprilTagImage(frame, frame.getNativeObj(), id);
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class AprilTagDetection {
|
||||
* @return Homography matrix
|
||||
*/
|
||||
public Matrix<N3, N3> getHomographyMatrix() {
|
||||
return new MatBuilder<>(Nat.N3(), Nat.N3()).fill(m_homography);
|
||||
return MatBuilder.fill(Nat.N3(), Nat.N3(), m_homography);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +95,7 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point X coordinate
|
||||
@@ -106,7 +106,7 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point Y coordinate
|
||||
@@ -117,7 +117,8 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets the corners of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. The first set of corner coordinates are the coordinates for the bottom left
|
||||
* corner.
|
||||
*
|
||||
* @return Corner point array (X and Y for each corner in order)
|
||||
*/
|
||||
|
||||
@@ -57,8 +57,21 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
*/
|
||||
public boolean debug;
|
||||
|
||||
/** Default constructor. */
|
||||
public Config() {}
|
||||
|
||||
/**
|
||||
* Constructs a detector configuration.
|
||||
*
|
||||
* @param numThreads How many threads should be used for computation.
|
||||
* @param quadDecimate Quad decimation.
|
||||
* @param quadSigma What Gaussian blur should be applied to the segmented image (used for quad
|
||||
* detection).
|
||||
* @param refineEdges When true, the edges of the each quad are adjusted to "snap to" strong
|
||||
* gradients nearby.
|
||||
* @param decodeSharpening How much sharpening should be done to decoded images.
|
||||
* @param debug Debug mode.
|
||||
*/
|
||||
Config(
|
||||
int numThreads,
|
||||
float quadDecimate,
|
||||
@@ -139,8 +152,21 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
*/
|
||||
public boolean deglitch;
|
||||
|
||||
/** Default constructor. */
|
||||
public QuadThresholdParameters() {}
|
||||
|
||||
/**
|
||||
* Constructs quad threshold parameters.
|
||||
*
|
||||
* @param minClusterPixels Threshold used to reject quads containing too few pixels.
|
||||
* @param maxNumMaxima How many corner candidates to consider when segmenting a group of pixels
|
||||
* into a quad.
|
||||
* @param criticalAngle Critical angle, in radians.
|
||||
* @param maxLineFitMSE When fitting lines to the contours, the maximum mean squared error
|
||||
* allowed.
|
||||
* @param minWhiteBlackDiff Minimum brightness offset.
|
||||
* @param deglitch Whether the thresholded image be should be deglitched.
|
||||
*/
|
||||
QuadThresholdParameters(
|
||||
int minClusterPixels,
|
||||
int maxNumMaxima,
|
||||
@@ -182,6 +208,7 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs an AprilTagDetector. */
|
||||
public AprilTagDetector() {
|
||||
m_native = AprilTagJNI.createDetector();
|
||||
}
|
||||
@@ -244,7 +271,7 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
* Adds a family of tags to be detected.
|
||||
*
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected maximum number of bits to correct
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @throws IllegalArgumentException if family name not recognized
|
||||
*/
|
||||
public void addFamily(String fam, int bitsCorrected) {
|
||||
@@ -270,6 +297,8 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
*
|
||||
* <p>The image must be grayscale.
|
||||
*
|
||||
* @param img 8-bit OpenCV Mat image
|
||||
* @return Results (array of AprilTagDetection)
|
||||
*/
|
||||
|
||||
@@ -44,8 +44,11 @@ import java.util.Optional;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
public class AprilTagFieldLayout {
|
||||
/** Common origin positions for the AprilTag coordinate system. */
|
||||
public enum OriginPosition {
|
||||
/** Blue alliance wall, right side. */
|
||||
kBlueAllianceWallRightSide,
|
||||
/** Red alliance wall, right side. */
|
||||
kRedAllianceWallRightSide,
|
||||
}
|
||||
|
||||
@@ -143,7 +146,7 @@ public class AprilTagFieldLayout {
|
||||
* @param origin The predefined origin
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setOrigin(OriginPosition origin) {
|
||||
public final void setOrigin(OriginPosition origin) {
|
||||
switch (origin) {
|
||||
case kBlueAllianceWallRightSide:
|
||||
setOrigin(new Pose3d());
|
||||
@@ -168,7 +171,7 @@ public class AprilTagFieldLayout {
|
||||
* @param origin The new origin for tag transformations
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setOrigin(Pose3d origin) {
|
||||
public final void setOrigin(Pose3d origin) {
|
||||
m_origin = origin;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,22 @@ package edu.wpi.first.apriltag;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
/** Loadable AprilTag field layouts. */
|
||||
public enum AprilTagFields {
|
||||
/** 2022 Rapid React. */
|
||||
k2022RapidReact("2022-rapidreact.json"),
|
||||
k2023ChargedUp("2023-chargedup.json");
|
||||
/** 2023 Charged Up. */
|
||||
k2023ChargedUp("2023-chargedup.json"),
|
||||
/** 2024 Crescendo. */
|
||||
k2024Crescendo("2024-crescendo.json");
|
||||
|
||||
/** Base resource directory. */
|
||||
public static final String kBaseResourceDir = "/edu/wpi/first/apriltag/";
|
||||
|
||||
/** Alias to the current game. */
|
||||
public static final AprilTagFields kDefaultField = k2023ChargedUp;
|
||||
public static final AprilTagFields kDefaultField = k2024Crescendo;
|
||||
|
||||
/** Resource filename. */
|
||||
public final String m_resourceFile;
|
||||
|
||||
AprilTagFields(String resourceFile) {
|
||||
|
||||
@@ -29,10 +29,19 @@ public class AprilTagPoseEstimator {
|
||||
this.cy = cy;
|
||||
}
|
||||
|
||||
/** Tag size, in meters. */
|
||||
public double tagSize;
|
||||
|
||||
/** Camera horizontal focal length, in pixels. */
|
||||
public double fx;
|
||||
|
||||
/** Camera vertical focal length, in pixels. */
|
||||
public double fy;
|
||||
|
||||
/** Camera horizontal focal center, in pixels. */
|
||||
public double cx;
|
||||
|
||||
/** Camera vertical focal center, in pixels. */
|
||||
public double cy;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,25 +8,41 @@ import edu.wpi.first.apriltag.AprilTagDetection;
|
||||
import edu.wpi.first.apriltag.AprilTagDetector;
|
||||
import edu.wpi.first.apriltag.AprilTagPoseEstimate;
|
||||
import edu.wpi.first.math.geometry.Transform3d;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
import edu.wpi.first.util.RuntimeLoader;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** AprilTag JNI. */
|
||||
public class AprilTagJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<AprilTagJNI> loader = null;
|
||||
|
||||
/** Sets whether JNI should be loaded in the static block. */
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
/**
|
||||
* Returns true if the JNI should be loaded in the static block.
|
||||
*
|
||||
* @return True if the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the JNI should be loaded in the static block.
|
||||
*
|
||||
* @param load Whether the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
|
||||
/** Utility class. */
|
||||
private Helper() {}
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -44,31 +60,119 @@ public class AprilTagJNI {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an AprilTag detector engine.
|
||||
*
|
||||
* @return The detector engine handle
|
||||
*/
|
||||
public static native long createDetector();
|
||||
|
||||
/**
|
||||
* Destroys an AprilTag detector engine.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
*/
|
||||
public static native void destroyDetector(long det);
|
||||
|
||||
/**
|
||||
* Sets the detector engine configuration.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param config A configuration
|
||||
*/
|
||||
public static native void setDetectorConfig(long det, AprilTagDetector.Config config);
|
||||
|
||||
/**
|
||||
* Gets the detector engine configuration.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @return The configuration
|
||||
*/
|
||||
public static native AprilTagDetector.Config getDetectorConfig(long det);
|
||||
|
||||
/**
|
||||
* Sets the detector engine quad threshold parameters.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param params Quad threshold parameters
|
||||
*/
|
||||
public static native void setDetectorQTP(
|
||||
long det, AprilTagDetector.QuadThresholdParameters params);
|
||||
|
||||
/**
|
||||
* Gets the detector engine quad threshold parameters.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @return Quad threshold parameters
|
||||
*/
|
||||
public static native AprilTagDetector.QuadThresholdParameters getDetectorQTP(long det);
|
||||
|
||||
/**
|
||||
* Adds a family of tags to be detected by the detector engine.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @return False if family can't be found
|
||||
*/
|
||||
public static native boolean addFamily(long det, String fam, int bitsCorrected);
|
||||
|
||||
/**
|
||||
* Removes a family of tags from the detector.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
*/
|
||||
public static native void removeFamily(long det, String fam);
|
||||
|
||||
/**
|
||||
* Unregister all families.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
*/
|
||||
public static native void clearFamilies(long det);
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param width The width of the image
|
||||
* @param height The height of the image
|
||||
* @param stride The number of bytes between image rows (often the same as width)
|
||||
* @param bufAddr The address of the image buffer
|
||||
* @return The results (array of AprilTagDetection)
|
||||
*/
|
||||
public static native AprilTagDetection[] detect(
|
||||
long det, int width, int height, int stride, long bufAddr);
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag using the homography method described in [1].
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @return Pose estimate
|
||||
*/
|
||||
public static native Transform3d estimatePoseHomography(
|
||||
double[] homography, double tagSize, double fx, double fy, double cx, double cy);
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag. This returns one or two possible poses for the tag, along with
|
||||
* the object-space error of each.
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param corners Corner point array (X and Y for each corner in order)
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @param nIters Number of iterations
|
||||
* @return Initial and (possibly) second pose estimates
|
||||
*/
|
||||
public static native AprilTagPoseEstimate estimatePoseOrthogonalIteration(
|
||||
double[] homography,
|
||||
double[] corners,
|
||||
@@ -79,6 +183,20 @@ public class AprilTagJNI {
|
||||
double cy,
|
||||
int nIters);
|
||||
|
||||
/**
|
||||
* Estimates tag pose. This method is an easier to use interface to
|
||||
* EstimatePoseOrthogonalIteration(), running 50 iterations and returning the pose with the lower
|
||||
* object-space error.
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param corners Corner point array (X and Y for each corner in order)
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @return Pose estimate
|
||||
*/
|
||||
public static native Transform3d estimatePose(
|
||||
double[] homography,
|
||||
double[] corners,
|
||||
@@ -87,4 +205,25 @@ public class AprilTagJNI {
|
||||
double fy,
|
||||
double cx,
|
||||
double cy);
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 16h5 passed in.
|
||||
*
|
||||
* @param frameObj generated frame (output parameter).
|
||||
* @param frame raw frame handle
|
||||
* @param id id
|
||||
*/
|
||||
public static native void generate16h5AprilTagImage(RawFrame frameObj, long frame, int id);
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 36h11 passed in.
|
||||
*
|
||||
* @param frameObj generated frame (output parameter).
|
||||
* @param frame raw frame handle
|
||||
* @param id id
|
||||
*/
|
||||
public static native void generate36h11AprilTagImage(RawFrame frameObj, long frame, int id);
|
||||
|
||||
/** Utility class. */
|
||||
private AprilTagJNI() {}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,53 @@
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <wpi/json.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4200)
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
|
||||
#include "apriltag.h"
|
||||
#include "tag16h5.h"
|
||||
#include "tag36h11.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static bool FamilyToImage(wpi::RawFrame* frame, apriltag_family_t* family,
|
||||
int id) {
|
||||
image_u8_t* image = apriltag_to_image(family, id);
|
||||
size_t totalDataSize = image->height * image->stride;
|
||||
bool rv = frame->Reserve(totalDataSize);
|
||||
std::memcpy(frame->data, image->buf, totalDataSize);
|
||||
frame->size = totalDataSize;
|
||||
frame->width = image->width;
|
||||
frame->height = image->height;
|
||||
frame->stride = image->stride;
|
||||
frame->pixelFormat = WPI_PIXFMT_GRAY;
|
||||
image_u8_destroy(image);
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool AprilTag::Generate36h11AprilTagImage(wpi::RawFrame* frame, int id) {
|
||||
apriltag_family_t* tagFamily = tag36h11_create();
|
||||
bool rv = FamilyToImage(frame, tagFamily, id);
|
||||
tag36h11_destroy(tagFamily);
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool AprilTag::Generate16h5AprilTagImage(wpi::RawFrame* frame, int id) {
|
||||
apriltag_family_t* tagFamily = tag16h5_create();
|
||||
bool rv = FamilyToImage(frame, tagFamily, id);
|
||||
tag16h5_destroy(tagFamily);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void frc::to_json(wpi::json& json, const AprilTag& apriltag) {
|
||||
json = wpi::json{{"ID", apriltag.ID}, {"pose", apriltag.pose}};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ AprilTagFieldLayout::AprilTagFieldLayout(std::string_view path) {
|
||||
throw std::runtime_error(fmt::format("Cannot open file: {}", path));
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(fileBuffer->begin(), fileBuffer->end());
|
||||
wpi::json json = wpi::json::parse(fileBuffer->GetCharBuffer());
|
||||
|
||||
for (const auto& tag : json.at("tags").get<std::vector<AprilTag>>()) {
|
||||
m_apriltags[tag.ID] = tag;
|
||||
@@ -49,6 +49,15 @@ units::meter_t AprilTagFieldLayout::GetFieldWidth() const {
|
||||
return m_fieldWidth;
|
||||
}
|
||||
|
||||
std::vector<AprilTag> AprilTagFieldLayout::GetTags() const {
|
||||
std::vector<AprilTag> tags;
|
||||
tags.reserve(m_apriltags.size());
|
||||
for (const auto& tag : m_apriltags) {
|
||||
tags.emplace_back(tag.second);
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
void AprilTagFieldLayout::SetOrigin(OriginPosition origin) {
|
||||
switch (origin) {
|
||||
case OriginPosition::kBlueAllianceWallRightSide:
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -21,6 +22,9 @@ AprilTagFieldLayout LoadAprilTagLayoutField(AprilTagField field) {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
// 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 <jni.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#define WPI_RAWFRAME_JNI
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/jni_util.h>
|
||||
|
||||
#include "edu_wpi_first_apriltag_jni_AprilTagJNI.h"
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagDetector.h"
|
||||
#include "frc/apriltag/AprilTagPoseEstimator.h"
|
||||
|
||||
@@ -24,6 +29,7 @@ static JClass quaternionCls;
|
||||
static JClass rotation3dCls;
|
||||
static JClass transform3dCls;
|
||||
static JClass translation3dCls;
|
||||
static JClass rawFrameCls;
|
||||
static JException illegalArgEx;
|
||||
static JException nullPointerEx;
|
||||
|
||||
@@ -36,7 +42,8 @@ static const JClassInit classes[] = {
|
||||
{"edu/wpi/first/math/geometry/Quaternion", &quaternionCls},
|
||||
{"edu/wpi/first/math/geometry/Rotation3d", &rotation3dCls},
|
||||
{"edu/wpi/first/math/geometry/Transform3d", &transform3dCls},
|
||||
{"edu/wpi/first/math/geometry/Translation3d", &translation3dCls}};
|
||||
{"edu/wpi/first/math/geometry/Translation3d", &translation3dCls},
|
||||
{"edu/wpi/first/util/RawFrame", &rawFrameCls}};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"java/lang/IllegalArgumentException", &illegalArgEx},
|
||||
@@ -587,4 +594,41 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose
|
||||
return MakeJObject(env, estimator.Estimate(harr, carr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_apriltag_jni_AprilTagJNI
|
||||
* Method: generate16h5AprilTagImage
|
||||
* Signature: (Ljava/lang/Object;JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate16h5AprilTagImage
|
||||
(JNIEnv* env, jclass, jobject frameObj, jlong framePtr, jint id)
|
||||
{
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
if (!frame) {
|
||||
nullPointerEx.Throw(env, "frame is null");
|
||||
return;
|
||||
}
|
||||
bool newData = AprilTag::Generate16h5AprilTagImage(frame, id);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame, newData);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_apriltag_jni_AprilTagJNI
|
||||
* Method: generate36h11AprilTagImage
|
||||
* Signature: (Ljava/lang/Object;JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate36h11AprilTagImage
|
||||
(JNIEnv* env, jclass, jobject frameObj, jlong framePtr, jint id)
|
||||
{
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
if (!frame) {
|
||||
nullPointerEx.Throw(env, "frame is null");
|
||||
return;
|
||||
}
|
||||
// function might reallocate
|
||||
bool newData = AprilTag::Generate36h11AprilTagImage(frame, id);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame, newData);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/SymbolExports.h>
|
||||
#include <wpi/json_fwd.h>
|
||||
|
||||
@@ -11,15 +12,20 @@
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Represents an AprilTag's metadata.
|
||||
*/
|
||||
struct WPILIB_DLLEXPORT AprilTag {
|
||||
/// The tag's ID.
|
||||
int ID;
|
||||
|
||||
/// The tag's pose.
|
||||
Pose3d pose;
|
||||
|
||||
/**
|
||||
* Checks equality between this AprilTag and another object.
|
||||
*/
|
||||
bool operator==(const AprilTag&) const = default;
|
||||
|
||||
static bool Generate36h11AprilTagImage(wpi::RawFrame* frame, int id);
|
||||
static bool Generate16h5AprilTagImage(wpi::RawFrame* frame, int id);
|
||||
};
|
||||
|
||||
WPILIB_DLLEXPORT
|
||||
|
||||
@@ -93,7 +93,7 @@ class WPILIB_DLLEXPORT AprilTagDetection final {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always
|
||||
* wrap counter-clock wise around the tag.
|
||||
* wrap counter-clock wise around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point
|
||||
@@ -104,7 +104,8 @@ class WPILIB_DLLEXPORT AprilTagDetection final {
|
||||
|
||||
/**
|
||||
* Gets the corners of the tag in image pixel coordinates. These always
|
||||
* wrap counter-clock wise around the tag.
|
||||
* wrap counter-clock wise around the tag. The first set of corner coordinates
|
||||
* are the coordinates for the bottom left corner.
|
||||
*
|
||||
* @param cornersBuf Corner point array (X and Y for each corner in order)
|
||||
* @return Corner point array (copy of cornersBuf span)
|
||||
|
||||
@@ -205,7 +205,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
* Adds a family of tags to be detected.
|
||||
*
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @return False if family can't be found
|
||||
*/
|
||||
bool AddFamily(std::string_view fam, int bitsCorrected = 2);
|
||||
@@ -226,6 +226,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
* The image must be grayscale.
|
||||
*
|
||||
* @param width width of the image
|
||||
* @param height height of the image
|
||||
@@ -237,6 +238,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
* The image must be grayscale.
|
||||
*
|
||||
* @param width width of the image
|
||||
* @param height height of the image
|
||||
|
||||
@@ -38,8 +38,13 @@ namespace frc {
|
||||
* towards the opposing alliance). */
|
||||
class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
public:
|
||||
/**
|
||||
* Common origin positions for the AprilTag coordinate system.
|
||||
*/
|
||||
enum class OriginPosition {
|
||||
/// Blue alliance wall, right side.
|
||||
kBlueAllianceWallRightSide,
|
||||
/// Red alliance wall, right side.
|
||||
kRedAllianceWallRightSide,
|
||||
};
|
||||
|
||||
@@ -74,6 +79,12 @@ class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
*/
|
||||
units::meter_t GetFieldWidth() const;
|
||||
|
||||
/**
|
||||
* Returns a vector of all the april tags used in this layout.
|
||||
* @return list of tags
|
||||
*/
|
||||
std::vector<AprilTag> GetTags() const;
|
||||
|
||||
/**
|
||||
* Sets the origin based on a predefined enumeration of coordinate frame
|
||||
* origins. The origins are calculated from the field dimensions.
|
||||
|
||||
@@ -12,9 +12,16 @@
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Loadable AprilTag field layouts.
|
||||
*/
|
||||
enum class AprilTagField {
|
||||
/// 2022 Rapid React.
|
||||
k2022RapidReact,
|
||||
/// 2023 Charged Up.
|
||||
k2023ChargedUp,
|
||||
/// 2024 Crescendo.
|
||||
k2024Crescendo,
|
||||
|
||||
// This is a placeholder for denoting the last supported field. This should
|
||||
// always be the last entry in the enum and should not be used by users
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
ID,X,Y,Z,Rotation
|
||||
1,593.68,9.68,53.38,120
|
||||
2,637.21,34.79,53.38,120
|
||||
3,652.73,196.17,57.13,180
|
||||
4,652.73,218.42,57.13,180
|
||||
5,578.77,323.00,53.38,270
|
||||
6,72.5,323.00,53.38,270
|
||||
7,-1.50,218.42,57.13,0
|
||||
8,-1.50,196.17,57.13,0
|
||||
9,14.02,34.79,53.38,60
|
||||
10,57.54,9.68,53.38,60
|
||||
11,468.69,146.19,52.00,300
|
||||
12,468.69,177.10,52.00,60
|
||||
13,441.74,161.62,52.00,180
|
||||
14,209.48,161.62,52.00,0
|
||||
15,182.73,177.10,52.00,120
|
||||
16,182.73,146.19,52.00,240
|
||||
|
@@ -0,0 +1,296 @@
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"ID": 1,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 15.079471999999997,
|
||||
"y": 0.24587199999999998,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 2,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.185134,
|
||||
"y": 0.883666,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 3,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.579342,
|
||||
"y": 4.982717999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 4,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.579342,
|
||||
"y": 5.547867999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 5,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 14.700757999999999,
|
||||
"y": 8.2042,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.7071067811865475,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.7071067811865476
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 6,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 1.8415,
|
||||
"y": 8.2042,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.7071067811865475,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.7071067811865476
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 7,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": -0.038099999999999995,
|
||||
"y": 5.547867999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 8,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": -0.038099999999999995,
|
||||
"y": 4.982717999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 9,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 0.356108,
|
||||
"y": 0.883666,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 10,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 1.4615159999999998,
|
||||
"y": 0.24587199999999998,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 11,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.904726,
|
||||
"y": 3.7132259999999997,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.8660254037844387,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 12,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.904726,
|
||||
"y": 4.49834,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 13,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.220196,
|
||||
"y": 4.105148,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 14,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 5.320792,
|
||||
"y": 4.105148,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 15,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 4.641342,
|
||||
"y": 4.49834,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 16,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 4.641342,
|
||||
"y": 3.7132259999999997,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.4999999999999998,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844387
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"field": {
|
||||
"length": 16.451,
|
||||
"width": 8.211
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.apriltag;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AprilTagGenerationTest {
|
||||
@Test
|
||||
void test36h11() {
|
||||
var frame = AprilTag.generate36h11AprilTagImage(1);
|
||||
assertEquals(PixelFormat.kGray, frame.getPixelFormat());
|
||||
assertEquals(10, frame.getWidth());
|
||||
assertEquals(10, frame.getHeight());
|
||||
int stride = frame.getStride();
|
||||
assertEquals(stride * 10, frame.getSize());
|
||||
// check the diagonal values
|
||||
var data = frame.getData();
|
||||
assertEquals(-1, data.get(stride * 0 + 0)); // outer border is white
|
||||
assertEquals(0, data.get(stride * 1 + 1)); // inner border is black
|
||||
assertEquals(-1, data.get(stride * 2 + 2));
|
||||
assertEquals(-1, data.get(stride * 3 + 3));
|
||||
assertEquals(-1, data.get(stride * 4 + 4));
|
||||
assertEquals(0, data.get(stride * 5 + 5));
|
||||
assertEquals(0, data.get(stride * 6 + 6));
|
||||
assertEquals(-1, data.get(stride * 7 + 7));
|
||||
assertEquals(0, data.get(stride * 8 + 8)); // inner border
|
||||
assertEquals(-1, data.get(stride * 9 + 9)); // outer border
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import edu.wpi.first.math.geometry.Pose3d;
|
||||
import edu.wpi.first.math.geometry.Rotation3d;
|
||||
import edu.wpi.first.math.util.Units;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -28,7 +27,7 @@ class LoadConfigTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test2022RapidReact() throws IOException {
|
||||
void test2022RapidReact() {
|
||||
AprilTagFieldLayout layout = AprilTagFields.k2022RapidReact.loadAprilTagLayoutField();
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
|
||||
@@ -23,7 +23,7 @@ plugins {
|
||||
id 'net.ltgt.errorprone' version '3.1.0' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
id 'com.diffplug.spotless' version '6.20.0' apply false
|
||||
id 'com.github.spotbugs' version '5.1.3' apply false
|
||||
id 'com.github.spotbugs' version '6.0.2' apply false
|
||||
id 'com.google.protobuf' version '0.9.3' apply false
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ buildScan {
|
||||
publishAlways()
|
||||
}
|
||||
|
||||
import com.github.spotbugs.snom.Effort
|
||||
ext.spotbugsEffort = Effort.MAX
|
||||
|
||||
ext.licenseFile = files("$rootDir/LICENSE.md", "$rootDir/ThirdPartyNotices.txt")
|
||||
|
||||
if (project.hasProperty("publishVersion")) {
|
||||
@@ -171,5 +174,5 @@ ext.getCurrentArch = {
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '8.4'
|
||||
gradleVersion = '8.5'
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ repositories {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation "edu.wpi.first:native-utils:2024.3.1"
|
||||
implementation "edu.wpi.first:native-utils:2024.5.2"
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ project(cameraserver)
|
||||
include(CompileWarnings)
|
||||
include(AddTest)
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
# Java bindings
|
||||
if (WITH_JAVA)
|
||||
if(WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
@@ -15,28 +15,42 @@ if (WITH_JAVA)
|
||||
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
|
||||
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin NO_DEFAULT_PATH)
|
||||
find_file(
|
||||
OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
|
||||
add_jar(cameraserver_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar cscore_jar ntcore_jar ${OPENCV_JAR_FILE} OUTPUT_NAME cameraserver)
|
||||
|
||||
get_property(CAMERASERVER_JAR_FILE TARGET cameraserver_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CAMERASERVER_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
set_property(TARGET cameraserver_jar PROPERTY FOLDER "java")
|
||||
add_jar(
|
||||
cameraserver_jar
|
||||
${JAVA_SOURCES}
|
||||
INCLUDE_JARS wpiutil_jar cscore_jar ntcore_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME cameraserver
|
||||
)
|
||||
|
||||
install_jar(cameraserver_jar DESTINATION ${java_lib_dest})
|
||||
install_jar_exports(
|
||||
TARGETS cameraserver_jar
|
||||
FILE cameraserver_jar.cmake
|
||||
DESTINATION share/cameraserver
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WITH_JAVA_SOURCE)
|
||||
if(WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB CAMERASERVER_SOURCES src/main/java/edu/wpi/first/cameraserver/*.java)
|
||||
file(GLOB VISION_SOURCES src/main/java/edu/wpi/first/vision/*.java)
|
||||
add_jar(cameraserver_src_jar
|
||||
RESOURCES NAMESPACE "edu/wpi/first/cameraserver" ${CAMERASERVER_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/vision" ${VISION_SOURCES}
|
||||
OUTPUT_NAME cameraserver-sources)
|
||||
add_jar(
|
||||
cameraserver_src_jar
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/cameraserver" ${CAMERASERVER_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/vision" ${VISION_SOURCES}
|
||||
OUTPUT_NAME cameraserver-sources
|
||||
)
|
||||
|
||||
get_property(CAMERASERVER_SRC_JAR_FILE TARGET cameraserver_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CAMERASERVER_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
@@ -44,13 +58,15 @@ if (WITH_JAVA_SOURCE)
|
||||
set_property(TARGET cameraserver_src_jar PROPERTY FOLDER "java")
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE
|
||||
cameraserver_native_src src/main/native/cpp/*.cpp)
|
||||
file(GLOB_RECURSE cameraserver_native_src src/main/native/cpp/*.cpp)
|
||||
add_library(cameraserver ${cameraserver_native_src})
|
||||
set_target_properties(cameraserver PROPERTIES DEBUG_POSTFIX "d")
|
||||
target_include_directories(cameraserver PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cameraserver>)
|
||||
target_include_directories(
|
||||
cameraserver
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cameraserver>
|
||||
)
|
||||
wpilib_target_warnings(cameraserver)
|
||||
target_link_libraries(cameraserver PUBLIC ntcore cscore wpiutil ${OpenCV_LIBS})
|
||||
|
||||
@@ -59,15 +75,9 @@ set_property(TARGET cameraserver PROPERTY FOLDER "libraries")
|
||||
install(TARGETS cameraserver EXPORT cameraserver)
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cameraserver")
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (cameraserver_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (cameraserver_config_dir share/cameraserver)
|
||||
endif()
|
||||
|
||||
configure_file(cameraserver-config.cmake.in ${WPILIB_BINARY_DIR}/cameraserver-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
|
||||
install(EXPORT cameraserver DESTINATION ${cameraserver_config_dir})
|
||||
configure_file(cameraserver-config.cmake.in ${WPILIB_BINARY_DIR}/cameraserver-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cameraserver-config.cmake DESTINATION share/cameraserver)
|
||||
install(EXPORT cameraserver DESTINATION share/cameraserver)
|
||||
|
||||
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)
|
||||
add_executable(multiCameraServer ${multiCameraServer_src})
|
||||
@@ -76,7 +86,7 @@ target_link_libraries(multiCameraServer cameraserver)
|
||||
|
||||
set_property(TARGET multiCameraServer PROPERTY FOLDER "examples")
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
wpilib_add_test(cameraserver src/test/native/cpp)
|
||||
target_link_libraries(cameraserver_test cameraserver gtest)
|
||||
endif()
|
||||
|
||||
@@ -7,3 +7,6 @@ find_dependency(OpenCV)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
include(${SELF_DIR}/cameraserver.cmake)
|
||||
if(@WITH_JAVA@)
|
||||
include(${SELF_DIR}/cameraserver_jar.cmake)
|
||||
endif()
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class Main {
|
||||
// parse file
|
||||
JsonElement top;
|
||||
try {
|
||||
top = new JsonParser().parse(Files.newBufferedReader(Paths.get(configFile)));
|
||||
top = JsonParser.parseReader(Files.newBufferedReader(Paths.get(configFile)));
|
||||
} catch (IOException ex) {
|
||||
System.err.println("could not open '" + configFile + "': " + ex);
|
||||
return false;
|
||||
|
||||
@@ -105,7 +105,7 @@ bool ReadConfig() {
|
||||
// parse file
|
||||
wpi::json j;
|
||||
try {
|
||||
j = wpi::json::parse(fileBuffer->begin(), fileBuffer->end());
|
||||
j = wpi::json::parse(fileBuffer->GetCharBuffer());
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
fmt::print(stderr, "config error in '{}': byte {}: {}\n", configFile,
|
||||
e.byte, e.what());
|
||||
|
||||
@@ -14,7 +14,6 @@ import edu.wpi.first.cscore.VideoEvent;
|
||||
import edu.wpi.first.cscore.VideoException;
|
||||
import edu.wpi.first.cscore.VideoListener;
|
||||
import edu.wpi.first.cscore.VideoMode;
|
||||
import edu.wpi.first.cscore.VideoMode.PixelFormat;
|
||||
import edu.wpi.first.cscore.VideoSink;
|
||||
import edu.wpi.first.cscore.VideoSource;
|
||||
import edu.wpi.first.networktables.BooleanEntry;
|
||||
@@ -27,6 +26,8 @@ import edu.wpi.first.networktables.StringArrayPublisher;
|
||||
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;
|
||||
@@ -39,6 +40,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* NetworkTables.
|
||||
*/
|
||||
public final class CameraServer {
|
||||
/** CameraServer base port. */
|
||||
public static final int kBasePort = 1181;
|
||||
|
||||
private static final String kPublishName = "/CameraPublisher";
|
||||
@@ -114,7 +116,7 @@ public final class CameraServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
public void close() {
|
||||
if (m_booleanValueEntry != null) {
|
||||
m_booleanValueEntry.close();
|
||||
}
|
||||
@@ -139,6 +141,7 @@ public final class CameraServer {
|
||||
if (m_choicesPublisher != null) {
|
||||
m_choicesPublisher.close();
|
||||
}
|
||||
Reference.reachabilityFence(m_videoListener);
|
||||
}
|
||||
|
||||
BooleanEntry m_booleanValueEntry;
|
||||
@@ -222,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 -> {
|
||||
@@ -686,7 +689,7 @@ public final class CameraServer {
|
||||
*/
|
||||
public static MjpegServer addSwitchedCamera(String name) {
|
||||
// create a dummy CvSource
|
||||
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
|
||||
CvSource source = new CvSource(name, PixelFormat.kMJPEG, 160, 120, 30);
|
||||
MjpegServer server = startAutomaticCapture(source);
|
||||
synchronized (CameraServer.class) {
|
||||
m_fixedSources.put(server.getHandle(), source.getHandle());
|
||||
@@ -745,6 +748,34 @@ public final class CameraServer {
|
||||
return newsink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
|
||||
* image processing on the roboRIO.
|
||||
*
|
||||
* @param camera Camera (e.g. as returned by startAutomaticCapture).
|
||||
* @param pixelFormat Desired pixelFormat of the camera
|
||||
* @return OpenCV sink for the specified camera
|
||||
*/
|
||||
public static CvSink getVideo(VideoSource camera, PixelFormat pixelFormat) {
|
||||
String name = "opencv_" + camera.getName();
|
||||
|
||||
synchronized (CameraServer.class) {
|
||||
VideoSink sink = m_sinks.get(name);
|
||||
if (sink != null) {
|
||||
VideoSink.Kind kind = sink.getKind();
|
||||
if (kind != VideoSink.Kind.kCv) {
|
||||
throw new VideoException("expected OpenCV sink, but got " + kind);
|
||||
}
|
||||
return (CvSink) sink;
|
||||
}
|
||||
}
|
||||
|
||||
CvSink newsink = new CvSink(name, pixelFormat);
|
||||
newsink.setSource(camera);
|
||||
addServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
|
||||
* image processing on the roboRIO.
|
||||
@@ -773,7 +804,7 @@ public final class CameraServer {
|
||||
* @return OpenCV source for the MJPEG stream
|
||||
*/
|
||||
public static CvSource putVideo(String name, int width, int height) {
|
||||
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, width, height, 30);
|
||||
CvSource source = new CvSource(name, PixelFormat.kMJPEG, width, height, 30);
|
||||
startAutomaticCapture(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cameraserver;
|
||||
|
||||
/** CameraServer shared functions. */
|
||||
public interface CameraServerShared {
|
||||
/**
|
||||
* get the main thread id func.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cameraserver;
|
||||
|
||||
/** Storage for CameraServerShared instance. */
|
||||
public final class CameraServerSharedStore {
|
||||
private static CameraServerShared cameraServerShared;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.opencv.core.Mat;
|
||||
* code. The easiest way to use this is to run it in a {@link VisionThread} and use the listener to
|
||||
* take snapshots of the pipeline's outputs.
|
||||
*
|
||||
* @param <P> Vision pipeline type.
|
||||
* @see VisionPipeline
|
||||
* @see VisionThread
|
||||
* @see <a href="package-summary.html">vision</a>
|
||||
|
||||
@@ -21,6 +21,7 @@ public class VisionThread extends Thread {
|
||||
*
|
||||
* @param visionRunner the runner for a vision pipeline
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public VisionThread(VisionRunner<?> visionRunner) {
|
||||
super(visionRunner::runForever, "WPILib Vision Thread");
|
||||
setDaemon(true);
|
||||
|
||||
@@ -622,6 +622,33 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera,
|
||||
cs::VideoMode::PixelFormat pixelFormat) {
|
||||
auto& inst = ::GetInstance();
|
||||
wpi::SmallString<64> name{"opencv_"};
|
||||
name += camera.GetName();
|
||||
|
||||
{
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
auto it = inst.m_sinks.find(name);
|
||||
if (it != inst.m_sinks.end()) {
|
||||
auto kind = it->second.GetKind();
|
||||
if (kind != cs::VideoSink::kCv) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("expected OpenCV sink, but got {}",
|
||||
static_cast<int>(kind));
|
||||
return cs::CvSink{};
|
||||
}
|
||||
return *static_cast<cs::CvSink*>(&it->second);
|
||||
}
|
||||
}
|
||||
|
||||
cs::CvSink newsink{name.str(), pixelFormat};
|
||||
newsink.SetSource(camera);
|
||||
AddServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
@@ -638,6 +665,23 @@ cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
return GetVideo(source);
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name,
|
||||
cs::VideoMode::PixelFormat pixelFormat) {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
{
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
auto it = inst.m_sources.find(name);
|
||||
if (it == inst.m_sources.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("could not find camera {}", name);
|
||||
return cs::CvSink{};
|
||||
}
|
||||
source = it->second;
|
||||
}
|
||||
return GetVideo(source, pixelFormat);
|
||||
}
|
||||
|
||||
cs::CvSource CameraServer::PutVideo(std::string_view name, int width,
|
||||
int height) {
|
||||
::GetInstance();
|
||||
|
||||
@@ -22,10 +22,8 @@ namespace frc {
|
||||
*/
|
||||
class CameraServer {
|
||||
public:
|
||||
/// CameraServer base port.
|
||||
static constexpr uint16_t kBasePort = 1181;
|
||||
static constexpr int kSize640x480 = 0;
|
||||
static constexpr int kSize320x240 = 1;
|
||||
static constexpr int kSize160x120 = 2;
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -191,6 +189,17 @@ class CameraServer {
|
||||
*/
|
||||
static cs::CvSink GetVideo(const cs::VideoSource& camera);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
*
|
||||
* @param camera Camera (e.g. as returned by startAutomaticCapture).
|
||||
* @param pixelFormat The desired pixelFormat of captured frames from the
|
||||
* camera
|
||||
*/
|
||||
static cs::CvSink GetVideo(const cs::VideoSource& camera,
|
||||
cs::VideoMode::PixelFormat pixelFormat);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
@@ -199,6 +208,17 @@ class CameraServer {
|
||||
*/
|
||||
static cs::CvSink GetVideo(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
*
|
||||
* @param name Camera name
|
||||
* @param pixelFormat The desired pixelFormat of captured frames from the
|
||||
* camera
|
||||
*/
|
||||
static cs::CvSink GetVideo(std::string_view name,
|
||||
cs::VideoMode::PixelFormat pixelFormat);
|
||||
|
||||
/**
|
||||
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
|
||||
* annotated images to the dashboard.
|
||||
|
||||
@@ -4,10 +4,10 @@ macro(wpilib_add_test name srcdir)
|
||||
file(GLOB_RECURSE test_src ${srcdir}/*.cpp)
|
||||
add_executable(${name}_test ${test_src})
|
||||
wpilib_target_warnings(${name}_test)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
|
||||
endif()
|
||||
if (MSVC)
|
||||
if(MSVC)
|
||||
target_compile_options(${name}_test PRIVATE /wd4101 /wd4251)
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND ${name}_test)
|
||||
|
||||
@@ -1,28 +1,56 @@
|
||||
macro(wpilib_target_warnings target)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter ${WPILIB_TARGET_WARNINGS})
|
||||
set(WARNING_FLAGS
|
||||
-Wall
|
||||
-pedantic
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
${WPILIB_TARGET_WARNINGS}
|
||||
)
|
||||
if(NOT NO_WERROR)
|
||||
set(WARNING_FLAGS ${WARNING_FLAGS} -Werror)
|
||||
endif()
|
||||
|
||||
target_compile_options(${target} PRIVATE ${WARNING_FLAGS})
|
||||
else()
|
||||
target_compile_options(${target} PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /WX /D_CRT_SECURE_NO_WARNINGS ${WPILIB_TARGET_WARNINGS})
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE
|
||||
/wd4146
|
||||
/wd4244
|
||||
/wd4251
|
||||
/wd4267
|
||||
/WX
|
||||
/D_CRT_SECURE_NO_WARNINGS
|
||||
${WPILIB_TARGET_WARNINGS}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Suppress C++-specific OpenCV warning; C compiler rejects it with an error
|
||||
# https://github.com/opencv/opencv/issues/20269
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>)
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
|
||||
)
|
||||
elseif(UNIX AND APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion>)
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion>
|
||||
)
|
||||
endif()
|
||||
|
||||
# Suppress warning "enumeration types with a fixed underlying type are a
|
||||
# Clang extension"
|
||||
if(APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C>:-Wno-fixed-enum-extension>)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C>:-Wno-fixed-enum-extension>)
|
||||
endif()
|
||||
|
||||
# Compress debug info with GCC
|
||||
if ((${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR
|
||||
${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") AND
|
||||
${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||
target_compile_options(${target} PRIVATE -gz=zlib)
|
||||
if(
|
||||
(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
|
||||
AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"
|
||||
)
|
||||
target_compile_options(${target} PRIVATE -gz=zlib)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
macro(download_and_check source destination)
|
||||
file(DOWNLOAD ${source} ${destination} STATUS download_status)
|
||||
list(GET download_status 0 status_code)
|
||||
list(GET download_status 1 status_message)
|
||||
file(DOWNLOAD ${source} ${destination} STATUS download_status)
|
||||
list(GET download_status 0 status_code)
|
||||
list(GET download_status 1 status_message)
|
||||
|
||||
if(${status_code} EQUAL 0)
|
||||
message(VERBOSE "Download of \"${source}\" successful.")
|
||||
else()
|
||||
message(FATAL_ERROR "Download of \"${source}\" failed: ${status_message}")
|
||||
endif()
|
||||
if(${status_code} EQUAL 0)
|
||||
message(VERBOSE "Download of \"${source}\" successful.")
|
||||
else()
|
||||
message(FATAL_ERROR "Download of \"${source}\" failed: ${status_message}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -38,30 +38,28 @@ if(LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBSSH_FOUND TRUE)
|
||||
else()
|
||||
find_path(LIBSSH_INCLUDE_DIR
|
||||
NAMES
|
||||
libssh/libssh.h
|
||||
find_path(
|
||||
LIBSSH_INCLUDE_DIR
|
||||
NAMES libssh/libssh.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
)
|
||||
|
||||
find_library(LIBSSH_LIBRARY
|
||||
NAMES
|
||||
ssh.so
|
||||
libssh.so
|
||||
libssh.dylib
|
||||
find_library(
|
||||
LIBSSH_LIBRARY
|
||||
NAMES ssh.so libssh.so libssh.dylib
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
if(LIBSSH_INCLUDE_DIR AND LIBSSH_LIBRARY)
|
||||
@@ -71,34 +69,60 @@ else()
|
||||
else()
|
||||
set(LIBSSH_HEADER_PATH ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h)
|
||||
endif()
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MAJOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_MAJOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+"
|
||||
)
|
||||
if(NOT LIBSSH_VERSION_MAJOR)
|
||||
message(STATUS "LIBSSH_VERSION_MAJOR not found, assuming libssh is too old and cannot be used!")
|
||||
message(
|
||||
STATUS
|
||||
"LIBSSH_VERSION_MAJOR not found, assuming libssh is too old and cannot be used!"
|
||||
)
|
||||
set(LIBSSH_INCLUDE_DIR "LIBSSH_INCLUDE_DIR-NOTFOUND")
|
||||
set(LIBSSH_LIBRARY "LIBSSH_LIBRARY-NOTFOUND")
|
||||
else()
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR})
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MINOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_MINOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR})
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_PATCH
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_PATCH
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH})
|
||||
|
||||
set(LIBSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH})
|
||||
set(LIBSSH_VERSION
|
||||
${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH}
|
||||
)
|
||||
|
||||
if(LIBSSH_VERSION VERSION_LESS 0.8.0)
|
||||
# libssh_threads also needs to be linked for these versions
|
||||
string(REPLACE "libssh.so" "libssh_threads.so"
|
||||
string(
|
||||
REPLACE
|
||||
"libssh.so"
|
||||
"libssh_threads.so"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_LIBRARY}
|
||||
)
|
||||
string(REPLACE "libssh.dylib" "libssh_threads.dylib"
|
||||
string(
|
||||
REPLACE
|
||||
"libssh.dylib"
|
||||
"libssh_threads.dylib"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
string(REPLACE "ssh.so" "ssh_threads.so"
|
||||
string(
|
||||
REPLACE
|
||||
"ssh.so"
|
||||
"ssh_threads.so"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
@@ -110,7 +134,10 @@ else()
|
||||
set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY} ${LIBSSH_THREADS_LIBRARY})
|
||||
mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
|
||||
|
||||
find_package_handle_standard_args(LIBSSH FOUND_VAR LIBSSH_FOUND
|
||||
find_package_handle_standard_args(
|
||||
LIBSSH
|
||||
FOUND_VAR LIBSSH_FOUND
|
||||
REQUIRED_VARS LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES
|
||||
VERSION_VAR LIBSSH_VERSION)
|
||||
VERSION_VAR LIBSSH_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
set(scripts_dir "${CMAKE_CURRENT_LIST_DIR}/../scripts")
|
||||
macro(generate_resources inputDir outputDir prefix namespace outputFiles)
|
||||
file(GLOB inputFiles ${inputDir}/*)
|
||||
set(${outputFiles})
|
||||
foreach(input ${inputFiles})
|
||||
get_filename_component(inputBase ${input} NAME)
|
||||
if("${inputBase}" MATCHES "^\\.")
|
||||
continue()
|
||||
endif()
|
||||
set(output "${outputDir}/${inputBase}.cpp")
|
||||
list(APPEND ${outputFiles} "${output}")
|
||||
macro(
|
||||
generate_resources
|
||||
inputDir
|
||||
outputDir
|
||||
prefix
|
||||
namespace
|
||||
outputFiles
|
||||
)
|
||||
file(GLOB inputFiles ${inputDir}/*)
|
||||
set(${outputFiles})
|
||||
foreach(input ${inputFiles})
|
||||
get_filename_component(inputBase ${input} NAME)
|
||||
if("${inputBase}" MATCHES "^\\.")
|
||||
continue()
|
||||
endif()
|
||||
set(output "${outputDir}/${inputBase}.cpp")
|
||||
list(APPEND ${outputFiles} "${output}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${output}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-Dinput=${input}"
|
||||
"-Doutput=${output}"
|
||||
"-Dprefix=${prefix}"
|
||||
"-Dnamespace=${namespace}"
|
||||
-P "${scripts_dir}/GenResource.cmake"
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${scripts_dir}/GenResource.cmake
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
add_custom_command(
|
||||
OUTPUT ${output}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} "-Dinput=${input}" "-Doutput=${output}" "-Dprefix=${prefix}"
|
||||
"-Dnamespace=${namespace}" -P "${scripts_dir}/GenResource.cmake"
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${scripts_dir}/GenResource.cmake
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
macro(wpilib_link_macos_gui target)
|
||||
if (APPLE)
|
||||
set_target_properties(${target} PROPERTIES LINK_FLAGS "-framework Metal -framework QuartzCore")
|
||||
if(APPLE)
|
||||
set_target_properties(
|
||||
${target}
|
||||
PROPERTIES LINK_FLAGS "-framework Metal -framework QuartzCore"
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
macro(subdir_list result curdir)
|
||||
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
set(dirlist "")
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${curdir}/${child})
|
||||
list(APPEND dirlist ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result} ${dirlist})
|
||||
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
set(dirlist "")
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${curdir}/${child})
|
||||
list(APPEND dirlist ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result} ${dirlist})
|
||||
endmacro()
|
||||
|
||||
macro(add_all_subdirectories curdir)
|
||||
subdir_list(_SUBPROJECTS ${curdir})
|
||||
foreach(dir ${_SUBPROJECTS})
|
||||
add_subdirectory(${dir})
|
||||
endforeach()
|
||||
subdir_list(_SUBPROJECTS ${curdir})
|
||||
foreach(dir ${_SUBPROJECTS})
|
||||
add_subdirectory(${dir})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
@@ -1,23 +1,35 @@
|
||||
# Parameters: input output prefix namespace
|
||||
FILE(READ ${input} fileHex HEX)
|
||||
STRING(LENGTH "${fileHex}" fileHexSize)
|
||||
MATH(EXPR fileSize "${fileHexSize} / 2")
|
||||
file(READ ${input} fileHex HEX)
|
||||
string(LENGTH "${fileHex}" fileHexSize)
|
||||
math(EXPR fileSize "${fileHexSize} / 2")
|
||||
|
||||
GET_FILENAME_COMPONENT(inputBase ${input} NAME)
|
||||
STRING(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
|
||||
SET(funcName "GetResource_${funcName}")
|
||||
get_filename_component(inputBase ${input} NAME)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
|
||||
set(funcName "GetResource_${funcName}")
|
||||
|
||||
FILE(WRITE "${output}" "#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
|
||||
file(
|
||||
WRITE
|
||||
"${output}"
|
||||
"#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {"
|
||||
)
|
||||
|
||||
STRING(REGEX MATCHALL ".." outputData "${fileHex}")
|
||||
STRING(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
|
||||
FILE(APPEND "${output}" " 0x${outputData} };\n")
|
||||
FILE(APPEND "${output}" "const unsigned char* ${prefix}${funcName}(size_t* len) {\n *len = ${fileSize};\n return contents;\n}\n}\n")
|
||||
string(REGEX MATCHALL ".." outputData "${fileHex}")
|
||||
string(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
|
||||
file(APPEND "${output}" " 0x${outputData} };\n")
|
||||
file(
|
||||
APPEND
|
||||
"${output}"
|
||||
"const unsigned char* ${prefix}${funcName}(size_t* len) {\n *len = ${fileSize};\n return contents;\n}\n}\n"
|
||||
)
|
||||
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
ENDIF()
|
||||
FILE(APPEND "${output}" "std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "}\n")
|
||||
ENDIF()
|
||||
if(NOT namespace STREQUAL "")
|
||||
file(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
endif()
|
||||
file(
|
||||
APPEND
|
||||
"${output}"
|
||||
"std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n"
|
||||
)
|
||||
if(NOT namespace STREQUAL "")
|
||||
file(APPEND "${output}" "}\n")
|
||||
endif()
|
||||
|
||||
@@ -190,12 +190,12 @@ struct RelayHandle {
|
||||
HAL_RelayHandle handle = 0;
|
||||
};
|
||||
|
||||
#define ASSERT_LAST_ERROR_STATUS(status, x) \
|
||||
do { \
|
||||
ASSERT_EQ(status, HAL_USE_LAST_ERROR); \
|
||||
const char* lastErrorMessageInMacro = HAL_GetLastError(&status); \
|
||||
static_cast<void>(lastErrorMessageInMacro); \
|
||||
ASSERT_EQ(status, x); \
|
||||
#define ASSERT_LAST_ERROR_STATUS(status, x) \
|
||||
do { \
|
||||
ASSERT_EQ(status, HAL_USE_LAST_ERROR); \
|
||||
[[maybe_unused]] const char* lastErrorMessageInMacro = \
|
||||
HAL_GetLastError(&status); \
|
||||
ASSERT_EQ(status, x); \
|
||||
} while (0)
|
||||
|
||||
} // namespace hlt
|
||||
|
||||
@@ -5,10 +5,9 @@ include(CompileWarnings)
|
||||
include(AddTest)
|
||||
include(LinkMacOSGUI)
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
file(GLOB
|
||||
cscore_native_src src/main/native/cpp/*.cpp)
|
||||
file(GLOB cscore_native_src src/main/native/cpp/*.cpp)
|
||||
file(GLOB cscore_linux_src src/main/native/linux/*.cpp)
|
||||
file(GLOB cscore_osx_src src/main/native/osx/*.cpp)
|
||||
file(GLOB cscore_osx_objc_src src/main/native/objcpp/*.mm)
|
||||
@@ -18,10 +17,15 @@ add_library(cscore ${cscore_native_src})
|
||||
set_target_properties(cscore PROPERTIES DEBUG_POSTFIX "d")
|
||||
|
||||
if(NOT MSVC)
|
||||
if (APPLE)
|
||||
if(APPLE)
|
||||
target_sources(cscore PRIVATE ${cscore_osx_src} ${cscore_osx_objc_src})
|
||||
target_compile_options(cscore PRIVATE "-fobjc-arc")
|
||||
set_target_properties(cscore PROPERTIES LINK_FLAGS "-framework CoreFoundation -framework AVFoundation -framework Foundation -framework CoreMedia -framework CoreVideo")
|
||||
set_target_properties(
|
||||
cscore
|
||||
PROPERTIES
|
||||
LINK_FLAGS
|
||||
"-framework CoreFoundation -framework AVFoundation -framework Foundation -framework CoreMedia -framework CoreVideo"
|
||||
)
|
||||
else()
|
||||
target_sources(cscore PRIVATE ${cscore_linux_src})
|
||||
endif()
|
||||
@@ -31,9 +35,12 @@ else()
|
||||
target_compile_definitions(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
target_include_directories(cscore PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cscore>)
|
||||
target_include_directories(
|
||||
cscore
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cscore>
|
||||
)
|
||||
target_include_directories(cscore PRIVATE src/main/native/cpp)
|
||||
wpilib_target_warnings(cscore)
|
||||
target_link_libraries(cscore PUBLIC wpinet wpiutil ${OpenCV_LIBS})
|
||||
@@ -43,15 +50,9 @@ set_property(TARGET cscore PROPERTY FOLDER "libraries")
|
||||
install(TARGETS cscore EXPORT cscore)
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cscore")
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (cscore_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (cscore_config_dir share/cscore)
|
||||
endif()
|
||||
|
||||
configure_file(cscore-config.cmake.in ${WPILIB_BINARY_DIR}/cscore-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
|
||||
install(EXPORT cscore DESTINATION ${cscore_config_dir})
|
||||
configure_file(cscore-config.cmake.in ${WPILIB_BINARY_DIR}/cscore-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cscore-config.cmake DESTINATION share/cscore)
|
||||
install(EXPORT cscore DESTINATION share/cscore)
|
||||
|
||||
subdir_list(cscore_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
|
||||
foreach(example ${cscore_examples})
|
||||
@@ -68,7 +69,7 @@ foreach(example ${cscore_examples})
|
||||
add_executable(cscore_${example} ${cscore_example_src})
|
||||
wpilib_target_warnings(cscore_${example})
|
||||
|
||||
if (${example} STREQUAL "usbviewer")
|
||||
if(${example} STREQUAL "usbviewer")
|
||||
wpilib_link_macos_gui(cscore_${example})
|
||||
endif()
|
||||
|
||||
@@ -78,7 +79,7 @@ foreach(example ${cscore_examples})
|
||||
endforeach()
|
||||
|
||||
# Java bindings
|
||||
if (WITH_JAVA)
|
||||
if(WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
@@ -90,36 +91,68 @@ if (WITH_JAVA)
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
endif()
|
||||
|
||||
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/share/java NO_DEFAULT_PATH)
|
||||
find_file(OPENCV_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
|
||||
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dylib
|
||||
opencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib ${OpenCV_INSTALL_PATH}/lib/jni NO_DEFAULT_PATH)
|
||||
find_file(
|
||||
OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/share/java
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_file(
|
||||
OPENCV_JNI_FILE
|
||||
NAMES
|
||||
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
|
||||
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dylib
|
||||
opencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/bin/Release
|
||||
${OpenCV_INSTALL_PATH}/bin/Debug
|
||||
${OpenCV_INSTALL_PATH}/lib
|
||||
${OpenCV_INSTALL_PATH}/lib/jni
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
file(GLOB
|
||||
cscore_jni_src src/main/native/cpp/jni/CameraServerJNI.cpp)
|
||||
file(GLOB cscore_jni_src src/main/native/cpp/jni/CameraServerJNI.cpp)
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
set(CMAKE_JNI_TARGET true)
|
||||
|
||||
add_jar(cscore_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar ${OPENCV_JAR_FILE} OUTPUT_NAME cscore GENERATE_NATIVE_HEADERS cscore_jni_headers)
|
||||
add_jar(
|
||||
cscore_jar
|
||||
${JAVA_SOURCES}
|
||||
INCLUDE_JARS wpiutil_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME cscore
|
||||
GENERATE_NATIVE_HEADERS cscore_jni_headers
|
||||
)
|
||||
|
||||
get_property(CSCORE_JAR_FILE TARGET cscore_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CSCORE_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
install_jar(cscore_jar DESTINATION ${java_lib_dest})
|
||||
install_jar_exports(TARGETS cscore_jar FILE cscore_jar.cmake DESTINATION share/cscore)
|
||||
install(FILES ${OPENCV_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
if (MSVC)
|
||||
if(MSVC)
|
||||
install(FILES ${OPENCV_JNI_FILE} DESTINATION "${jni_lib_dest}")
|
||||
|
||||
foreach(cvFile ${OpenCV_LIBS})
|
||||
find_file(${cvFile}Loc NAMES ${cvFile}${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib NO_DEFAULT_PATH)
|
||||
find_file(
|
||||
${cvFile}Loc
|
||||
NAMES
|
||||
${cvFile}${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/bin/Release
|
||||
${OpenCV_INSTALL_PATH}/bin/Debug
|
||||
${OpenCV_INSTALL_PATH}/lib
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
install(FILES ${${cvFile}Loc} DESTINATION "${jni_lib_dest}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set_property(TARGET cscore_jar PROPERTY FOLDER "java")
|
||||
|
||||
add_library(cscorejni ${cscore_jni_src})
|
||||
wpilib_target_warnings(cscorejni)
|
||||
target_link_libraries(cscorejni PUBLIC cscore wpiutil ${OpenCV_LIBS})
|
||||
@@ -130,18 +163,20 @@ if (WITH_JAVA)
|
||||
add_dependencies(cscorejni cscore_jar)
|
||||
|
||||
install(TARGETS cscorejni EXPORT cscorejni)
|
||||
|
||||
endif()
|
||||
|
||||
if (WITH_JAVA_SOURCE)
|
||||
if(WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB CSCORE_SOURCES src/main/java/edu/wpi/first/cscore/*.java)
|
||||
file(GLOB CSCORE_RAW_SOURCES src/main/java/edu/wpi/first/cscore/raw/*.java)
|
||||
add_jar(cscore_src_jar
|
||||
RESOURCES NAMESPACE "edu/wpi/first/cscore" ${CSCORE_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/cscore/raw" ${CSCORE_RAW_SOURCES}
|
||||
OUTPUT_NAME cscore-sources)
|
||||
add_jar(
|
||||
cscore_src_jar
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/cscore" ${CSCORE_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/cscore/raw" ${CSCORE_RAW_SOURCES}
|
||||
OUTPUT_NAME cscore-sources
|
||||
)
|
||||
|
||||
get_property(CSCORE_SRC_JAR_FILE TARGET cscore_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CSCORE_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
@@ -149,7 +184,7 @@ if (WITH_JAVA_SOURCE)
|
||||
set_property(TARGET cscore_src_jar PROPERTY FOLDER "java")
|
||||
endif()
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
wpilib_add_test(cscore src/test/native/cpp)
|
||||
target_link_libraries(cscore_test cscore gmock)
|
||||
endif()
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
@FILENAME_DEP_REPLACE@
|
||||
@WPIUTIL_DEP_REPLACE@
|
||||
@WPINET_DEP_REPLACE@
|
||||
find_dependency(OpenCV)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
include(${SELF_DIR}/cscore.cmake)
|
||||
if(@WITH_JAVA@)
|
||||
include(${SELF_DIR}/cscore_jar.cmake)
|
||||
endif()
|
||||
|
||||
@@ -9,21 +9,36 @@ import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.opencv.core.Core;
|
||||
|
||||
/** CameraServer CV JNI. */
|
||||
public class CameraServerCvJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<Core> loader = null;
|
||||
|
||||
/** Sets whether JNI should be loaded in the static block. */
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
/**
|
||||
* Returns true if the JNI should be loaded in the static block.
|
||||
*
|
||||
* @return True if the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the JNI should be loaded in the static block.
|
||||
*
|
||||
* @param load Whether the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
|
||||
/** Utility class. */
|
||||
private Helper() {}
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -59,17 +74,64 @@ 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);
|
||||
|
||||
public static native int createCvSink(String name);
|
||||
/**
|
||||
* 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. */
|
||||
private CameraServerCvJNI() {}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
@@ -16,9 +17,20 @@ public class CvSink extends ImageSink {
|
||||
* get each new image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Source pixel format
|
||||
*/
|
||||
public CvSink(String name, PixelFormat pixelFormat) {
|
||||
super(CameraServerCvJNI.createCvSink(name, pixelFormat.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
|
||||
* get each new image. Defaults to kBGR for pixelFormat
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
public CvSink(String name) {
|
||||
super(CameraServerCvJNI.createCvSink(name));
|
||||
this(name, PixelFormat.kBGR);
|
||||
}
|
||||
|
||||
/// Create a sink for accepting OpenCV images in a separate thread.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ public class CvSource extends ImageSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
public CvSource(String name, PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,15 @@ 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),
|
||||
/** MJPG Streamer camera. */
|
||||
kMJPGStreamer(1),
|
||||
/** CS Core camera. */
|
||||
kCSCore(2),
|
||||
/** Axis camera. */
|
||||
kAxis(3);
|
||||
|
||||
private final int value;
|
||||
@@ -18,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,14 +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,27 +7,49 @@ package edu.wpi.first.cscore;
|
||||
/** Video event. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class VideoEvent {
|
||||
/** VideoEvent kind. */
|
||||
public enum Kind {
|
||||
/** Unknown video event. */
|
||||
kUnknown(0x0000),
|
||||
/** Source Created event. */
|
||||
kSourceCreated(0x0001),
|
||||
/** Source Destroyed event. */
|
||||
kSourceDestroyed(0x0002),
|
||||
/** Source Connected event. */
|
||||
kSourceConnected(0x0004),
|
||||
/** Source Disconnected event. */
|
||||
kSourceDisconnected(0x0008),
|
||||
/** Source Video Modes Updated event. */
|
||||
kSourceVideoModesUpdated(0x0010),
|
||||
/** Source VideoMode Changed event. */
|
||||
kSourceVideoModeChanged(0x0020),
|
||||
/** Source Property Created event. */
|
||||
kSourcePropertyCreated(0x0040),
|
||||
/** Source Property Value Updated event. */
|
||||
kSourcePropertyValueUpdated(0x0080),
|
||||
/** Source Property Choices Updated event. */
|
||||
kSourcePropertyChoicesUpdated(0x0100),
|
||||
/** Sink Source Changed event. */
|
||||
kSinkSourceChanged(0x0200),
|
||||
/** Sink Created event. */
|
||||
kSinkCreated(0x0400),
|
||||
/** Sink Destroyed event. */
|
||||
kSinkDestroyed(0x0800),
|
||||
/** Sink Enabled event. */
|
||||
kSinkEnabled(0x1000),
|
||||
/** Sink Disabled event. */
|
||||
kSinkDisabled(0x2000),
|
||||
/** Network Interfaces Changed event. */
|
||||
kNetworkInterfacesChanged(0x4000),
|
||||
/** Telemetry Updated event. */
|
||||
kTelemetryUpdated(0x8000),
|
||||
/** Sink Property Created event. */
|
||||
kSinkPropertyCreated(0x10000),
|
||||
/** Sink Property Value Updated event. */
|
||||
kSinkPropertyValueUpdated(0x20000),
|
||||
/** Sink Property Choices Updated event. */
|
||||
kSinkPropertyChoicesUpdated(0x40000),
|
||||
/** Usb Cameras Changed event. */
|
||||
kUsbCamerasChanged(0x80000);
|
||||
|
||||
private final int value;
|
||||
@@ -36,6 +58,11 @@ public class VideoEvent {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind value.
|
||||
*
|
||||
* @return The kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -118,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;
|
||||
}
|
||||
@@ -102,7 +107,7 @@ public class VideoListener implements AutoCloseable {
|
||||
listener.accept(event);
|
||||
} catch (Throwable throwable) {
|
||||
System.err.println(
|
||||
"Unhandled exception during listener callback: " + throwable.toString());
|
||||
"Unhandled exception during listener callback: " + throwable);
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,38 +4,12 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Video mode. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class VideoMode {
|
||||
public enum PixelFormat {
|
||||
kUnknown(0),
|
||||
kMJPEG(1),
|
||||
kYUYV(2),
|
||||
kRGB565(3),
|
||||
kBGR(4),
|
||||
kGray(5),
|
||||
kY16(6),
|
||||
kUYVY(7);
|
||||
|
||||
private final int value;
|
||||
|
||||
PixelFormat(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private static final PixelFormat[] m_pixelFormatValues = PixelFormat.values();
|
||||
|
||||
public static PixelFormat getPixelFormatFromInt(int pixelFormat) {
|
||||
return m_pixelFormatValues[pixelFormat];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new video mode.
|
||||
*
|
||||
@@ -45,7 +19,7 @@ public class VideoMode {
|
||||
* @param fps The camera's frames per second.
|
||||
*/
|
||||
public VideoMode(int pixelFormat, int width, int height, int fps) {
|
||||
this.pixelFormat = getPixelFormatFromInt(pixelFormat);
|
||||
this.pixelFormat = PixelFormat.getFromInt(pixelFormat);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.fps = fps;
|
||||
|
||||
@@ -6,11 +6,17 @@ package edu.wpi.first.cscore;
|
||||
|
||||
/** A source or sink property. */
|
||||
public class VideoProperty {
|
||||
/** VideoProperty property types. */
|
||||
public enum Kind {
|
||||
/** No specific property. */
|
||||
kNone(0),
|
||||
/** Boolean property. */
|
||||
kBoolean(1),
|
||||
/** Integer property. */
|
||||
kInteger(2),
|
||||
/** String property. */
|
||||
kString(4),
|
||||
/** Enum property. */
|
||||
kEnum(8);
|
||||
|
||||
private final int value;
|
||||
@@ -19,6 +25,11 @@ public class VideoProperty {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -45,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);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,15 @@ package edu.wpi.first.cscore;
|
||||
* (e.g. from a stereo or depth camera); these are called channels.
|
||||
*/
|
||||
public class VideoSink implements AutoCloseable {
|
||||
/** Video sink types. */
|
||||
public enum Kind {
|
||||
/** Unknown video sink type. */
|
||||
kUnknown(0),
|
||||
/** MJPEG video sink. */
|
||||
kMjpeg(2),
|
||||
/** CV video sink. */
|
||||
kCv(4),
|
||||
/** Raw video sink. */
|
||||
kRaw(8);
|
||||
|
||||
private final int value;
|
||||
@@ -21,6 +26,11 @@ public class VideoSink implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -43,6 +53,11 @@ public class VideoSink implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VideoSink.
|
||||
*
|
||||
* @param handle The video sink handle.
|
||||
*/
|
||||
protected VideoSink(int handle) {
|
||||
m_handle = handle;
|
||||
}
|
||||
@@ -55,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;
|
||||
}
|
||||
@@ -217,5 +242,6 @@ public class VideoSink implements AutoCloseable {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** The VideoSink handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -4,16 +4,24 @@
|
||||
|
||||
package edu.wpi.first.cscore;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
|
||||
/**
|
||||
* A source for video that provides a sequence of frames. Each frame may consist of multiple images
|
||||
* (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),
|
||||
/** USB video source. */
|
||||
kUsb(1),
|
||||
/** HTTP video source. */
|
||||
kHttp(2),
|
||||
/** CV video source. */
|
||||
kCv(4),
|
||||
/** Raw video source. */
|
||||
kRaw(8);
|
||||
|
||||
private final int value;
|
||||
@@ -22,6 +30,11 @@ public class VideoSource implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kind value.
|
||||
*
|
||||
* @return The Kind value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -49,6 +62,11 @@ public class VideoSource implements AutoCloseable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ConnectionStrategy value.
|
||||
*
|
||||
* @return The ConnectionStrategy value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -73,6 +91,11 @@ public class VideoSource implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a VideoSource.
|
||||
*
|
||||
* @param handle The video source handle.
|
||||
*/
|
||||
protected VideoSource(int handle) {
|
||||
m_handle = handle;
|
||||
}
|
||||
@@ -85,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;
|
||||
}
|
||||
@@ -235,7 +268,7 @@ public class VideoSource implements AutoCloseable {
|
||||
* @param fps desired FPS
|
||||
* @return True if set successfully
|
||||
*/
|
||||
public boolean setVideoMode(VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
public boolean setVideoMode(PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
return CameraServerJNI.setSourceVideoMode(m_handle, pixelFormat.getValue(), width, height, fps);
|
||||
}
|
||||
|
||||
@@ -245,7 +278,7 @@ public class VideoSource implements AutoCloseable {
|
||||
* @param pixelFormat desired pixel format
|
||||
* @return True if set successfully
|
||||
*/
|
||||
public boolean setPixelFormat(VideoMode.PixelFormat pixelFormat) {
|
||||
public boolean setPixelFormat(PixelFormat pixelFormat) {
|
||||
return CameraServerJNI.setSourcePixelFormat(m_handle, pixelFormat.getValue());
|
||||
}
|
||||
|
||||
@@ -372,5 +405,6 @@ public class VideoSource implements AutoCloseable {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Video source handle. */
|
||||
protected int m_handle;
|
||||
}
|
||||
|
||||
@@ -1,156 +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.
|
||||
|
||||
package edu.wpi.first.cscore.raw;
|
||||
|
||||
import edu.wpi.first.cscore.CameraServerJNI;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Class for storing raw frame data between image read call.
|
||||
*
|
||||
* <p>Data is reused for each frame read, rather then reallocating every frame.
|
||||
*/
|
||||
public class RawFrame implements AutoCloseable {
|
||||
private final long m_framePtr;
|
||||
private ByteBuffer m_dataByteBuffer;
|
||||
private long m_dataPtr;
|
||||
private int m_totalData;
|
||||
private int m_width;
|
||||
private int m_height;
|
||||
private int m_pixelFormat;
|
||||
|
||||
/** Construct a new RawFrame. */
|
||||
public RawFrame() {
|
||||
m_framePtr = CameraServerJNI.allocateRawFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the RawFrame, releasing native resources. Any images currently using the data will be
|
||||
* invalidated.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
CameraServerJNI.freeRawFrame(m_framePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from JNI to set data in class.
|
||||
*
|
||||
* @param dataByteBuffer A ByteBuffer pointing to the frame data.
|
||||
* @param dataPtr A long (a char* in native code) pointing to the frame data.
|
||||
* @param totalData The total length of the data stored in the frame.
|
||||
* @param width The width of the frame.
|
||||
* @param height The height of the frame.
|
||||
* @param pixelFormat The PixelFormat of the frame.
|
||||
*/
|
||||
public void setData(
|
||||
ByteBuffer dataByteBuffer,
|
||||
long dataPtr,
|
||||
int totalData,
|
||||
int width,
|
||||
int height,
|
||||
int pixelFormat) {
|
||||
m_dataByteBuffer = dataByteBuffer;
|
||||
m_dataPtr = dataPtr;
|
||||
m_totalData = totalData;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_pixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pointer to native representation of this frame.
|
||||
*
|
||||
* @return The pointer to native representation of this frame.
|
||||
*/
|
||||
public long getFramePtr() {
|
||||
return m_framePtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a ByteBuffer pointing to the frame data. This ByteBuffer is backed by the frame directly.
|
||||
* Its lifetime is controlled by the frame. If a new frame gets read, it will overwrite the
|
||||
* current one.
|
||||
*
|
||||
* @return A ByteBuffer pointing to the frame data.
|
||||
*/
|
||||
public ByteBuffer getDataByteBuffer() {
|
||||
return m_dataByteBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a long (is a char* in native code) pointing to the frame data. This pointer is backed by
|
||||
* the frame directly. Its lifetime is controlled by the frame. If a new frame gets read, it will
|
||||
* overwrite the current one.
|
||||
*
|
||||
* @return A long pointing to the frame data.
|
||||
*/
|
||||
public long getDataPtr() {
|
||||
return m_dataPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total length of the data stored in the frame.
|
||||
*
|
||||
* @return The total length of the data stored in the frame.
|
||||
*/
|
||||
public int getTotalData() {
|
||||
return m_totalData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the frame.
|
||||
*
|
||||
* @return The width of the frame.
|
||||
*/
|
||||
public int getWidth() {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the frame.
|
||||
*
|
||||
* @param width The width of the frame.
|
||||
*/
|
||||
public void setWidth(int width) {
|
||||
this.m_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the frame.
|
||||
*
|
||||
* @return The height of the frame.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the frame.
|
||||
*
|
||||
* @param height The height of the frame.
|
||||
*/
|
||||
public void setHeight(int height) {
|
||||
this.m_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PixelFormat of the frame.
|
||||
*
|
||||
* @return The PixelFormat of the frame.
|
||||
*/
|
||||
public int getPixelFormat() {
|
||||
return m_pixelFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PixelFormat of the frame.
|
||||
*
|
||||
* @param pixelFormat The PixelFormat of the frame.
|
||||
*/
|
||||
public void setPixelFormat(int pixelFormat) {
|
||||
this.m_pixelFormat = pixelFormat;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package edu.wpi.first.cscore.raw;
|
||||
|
||||
import edu.wpi.first.cscore.CameraServerJNI;
|
||||
import edu.wpi.first.cscore.ImageSink;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as raw bytes.
|
||||
@@ -32,7 +33,7 @@ public class RawSink extends ImageSink {
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error message); the frame time
|
||||
* is in the same time base as wpi::Now(), and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrame(RawFrame frame) {
|
||||
public long grabFrame(RawFrame frame) {
|
||||
return grabFrame(frame, 0.225);
|
||||
}
|
||||
|
||||
@@ -45,8 +46,8 @@ public class RawSink extends ImageSink {
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error message); the frame time
|
||||
* is in the same time base as wpi::Now(), and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrame(RawFrame frame, double timeout) {
|
||||
return CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
|
||||
public long grabFrame(RawFrame frame, double timeout) {
|
||||
return CameraServerJNI.grabRawSinkFrameTimeout(m_handle, frame, frame.getNativeObj(), timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +58,7 @@ public class RawSink extends ImageSink {
|
||||
* @return Frame time, or 0 on error (call getError() to obtain the error message); the frame time
|
||||
* is in the same time base as wpi::Now(), and is in 1 us increments.
|
||||
*/
|
||||
protected long grabFrameNoTimeout(RawFrame frame) {
|
||||
return CameraServerJNI.grabSinkFrame(m_handle, frame);
|
||||
public long grabFrameNoTimeout(RawFrame frame) {
|
||||
return CameraServerJNI.grabRawSinkFrame(m_handle, frame, frame.getNativeObj());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ package edu.wpi.first.cscore.raw;
|
||||
import edu.wpi.first.cscore.CameraServerJNI;
|
||||
import edu.wpi.first.cscore.ImageSource;
|
||||
import edu.wpi.first.cscore.VideoMode;
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A source for user code to provide video frames as raw bytes.
|
||||
@@ -35,7 +38,7 @@ public class RawSource extends ImageSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public RawSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
public RawSource(String name, PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerJNI.createRawSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
@@ -44,35 +47,41 @@ public class RawSource extends ImageSource {
|
||||
*
|
||||
* @param image raw frame image
|
||||
*/
|
||||
protected void putFrame(RawFrame image) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, image);
|
||||
public void putFrame(RawFrame image) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, image.getNativeObj());
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param data raw frame data pointer
|
||||
* @param data raw frame native data pointer
|
||||
* @param size total size in bytes
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param stride size of each row in bytes
|
||||
* @param pixelFormat pixel format
|
||||
* @param totalData length of data in total
|
||||
*/
|
||||
protected void putFrame(long data, int width, int height, int pixelFormat, int totalData) {
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, data, width, height, pixelFormat, totalData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param data raw frame data pointer
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param pixelFormat pixel format
|
||||
* @param totalData length of data in total
|
||||
*/
|
||||
protected void putFrame(
|
||||
long data, int width, int height, VideoMode.PixelFormat pixelFormat, int totalData) {
|
||||
CameraServerJNI.putRawSourceFrame(
|
||||
m_handle, data, width, height, pixelFormat.getValue(), totalData);
|
||||
long data, int size, int width, int height, int stride, PixelFormat pixelFormat) {
|
||||
CameraServerJNI.putRawSourceFrameData(
|
||||
m_handle, data, size, width, height, stride, pixelFormat.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param data raw frame native ByteBuffer
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param stride size of each row in bytes
|
||||
* @param pixelFormat pixel format
|
||||
*/
|
||||
public void putFrame(
|
||||
ByteBuffer data, int width, int height, int stride, PixelFormat pixelFormat) {
|
||||
if (!data.isDirect()) {
|
||||
throw new UnsupportedOperationException("ByteBuffer must be direct");
|
||||
}
|
||||
CameraServerJNI.putRawSourceFrameBB(
|
||||
m_handle, data, data.limit(), width, height, stride, pixelFormat.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,18 @@
|
||||
using namespace cs;
|
||||
|
||||
CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
VideoMode::PixelFormat pixelFormat)
|
||||
: SinkImpl{name, logger, notifier, telemetry}, m_pixelFormat{pixelFormat} {
|
||||
m_active = true;
|
||||
// m_thread = std::thread(&CvSinkImpl::ThreadMain, this);
|
||||
}
|
||||
|
||||
CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {}
|
||||
: SinkImpl{name, logger, notifier, telemetry}, m_pixelFormat{pixelFormat} {}
|
||||
|
||||
CvSinkImpl::~CvSinkImpl() {
|
||||
Stop();
|
||||
@@ -65,7 +67,7 @@ uint64_t CvSinkImpl::GrabFrame(cv::Mat& image) {
|
||||
return 0; // signal error
|
||||
}
|
||||
|
||||
if (!frame.GetCv(image)) {
|
||||
if (!frame.GetCv(image, m_pixelFormat)) {
|
||||
// Shouldn't happen, but just in case...
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
return 0;
|
||||
@@ -91,7 +93,7 @@ uint64_t CvSinkImpl::GrabFrame(cv::Mat& image, double timeout) {
|
||||
return 0; // signal error
|
||||
}
|
||||
|
||||
if (!frame.GetCv(image)) {
|
||||
if (!frame.GetCv(image, m_pixelFormat)) {
|
||||
// Shouldn't happen, but just in case...
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
return 0;
|
||||
@@ -127,20 +129,23 @@ void CvSinkImpl::ThreadMain() {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Sink CreateCvSink(std::string_view name, CS_Status* status) {
|
||||
CS_Sink CreateCvSink(std::string_view name, VideoMode::PixelFormat pixelFormat,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(
|
||||
CS_SINK_CV, std::make_shared<CvSinkImpl>(name, inst.logger, inst.notifier,
|
||||
inst.telemetry));
|
||||
inst.telemetry, pixelFormat));
|
||||
}
|
||||
|
||||
CS_Sink CreateCvSinkCallback(std::string_view name,
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(
|
||||
CS_SINK_CV, std::make_shared<CvSinkImpl>(name, inst.logger, inst.notifier,
|
||||
inst.telemetry, processFrame));
|
||||
CS_SINK_CV,
|
||||
std::make_shared<CvSinkImpl>(name, inst.logger, inst.notifier,
|
||||
inst.telemetry, pixelFormat, processFrame));
|
||||
}
|
||||
|
||||
static constexpr unsigned SinkMask = CS_SINK_CV | CS_SINK_RAW;
|
||||
@@ -206,15 +211,19 @@ void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status) {
|
||||
|
||||
extern "C" {
|
||||
|
||||
CS_Sink CS_CreateCvSink(const char* name, CS_Status* status) {
|
||||
return cs::CreateCvSink(name, status);
|
||||
CS_Sink CS_CreateCvSink(const char* name, enum WPI_PixelFormat pixelFormat,
|
||||
CS_Status* status) {
|
||||
return cs::CreateCvSink(
|
||||
name, static_cast<VideoMode::PixelFormat>(pixelFormat), status);
|
||||
}
|
||||
|
||||
CS_Sink CS_CreateCvSinkCallback(const char* name, void* data,
|
||||
CS_Sink CS_CreateCvSinkCallback(const char* name,
|
||||
enum WPI_PixelFormat pixelFormat, void* data,
|
||||
void (*processFrame)(void* data, uint64_t time),
|
||||
CS_Status* status) {
|
||||
return cs::CreateCvSinkCallback(
|
||||
name, [=](uint64_t time) { processFrame(data, time); }, status);
|
||||
name, static_cast<VideoMode::PixelFormat>(pixelFormat),
|
||||
[=](uint64_t time) { processFrame(data, time); }, status);
|
||||
}
|
||||
|
||||
void CS_SetSinkDescription(CS_Sink sink, const char* description,
|
||||
|
||||
@@ -25,9 +25,9 @@ class SourceImpl;
|
||||
class CvSinkImpl : public SinkImpl {
|
||||
public:
|
||||
CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
Telemetry& telemetry, VideoMode::PixelFormat pixelFormat);
|
||||
CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
Telemetry& telemetry, VideoMode::PixelFormat pixelFormat,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
~CvSinkImpl() override;
|
||||
|
||||
@@ -42,6 +42,7 @@ class CvSinkImpl : public SinkImpl {
|
||||
std::atomic_bool m_active; // set to false to terminate threads
|
||||
std::thread m_thread;
|
||||
std::function<void(uint64_t time)> m_processFrame;
|
||||
VideoMode::PixelFormat m_pixelFormat;
|
||||
};
|
||||
|
||||
} // namespace cs
|
||||
|
||||
@@ -709,8 +709,9 @@ Image* Frame::GetImageImpl(int width, int height,
|
||||
return ConvertImpl(cur, pixelFormat, requiredJpegQuality, defaultJpegQuality);
|
||||
}
|
||||
|
||||
bool Frame::GetCv(cv::Mat& image, int width, int height) {
|
||||
Image* rawImage = GetImage(width, height, VideoMode::kBGR);
|
||||
bool Frame::GetCv(cv::Mat& image, int width, int height,
|
||||
VideoMode::PixelFormat pixelFormat) {
|
||||
Image* rawImage = GetImage(width, height, pixelFormat);
|
||||
if (!rawImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -219,10 +219,11 @@ class Frame {
|
||||
defaultQuality);
|
||||
}
|
||||
|
||||
bool GetCv(cv::Mat& image) {
|
||||
return GetCv(image, GetOriginalWidth(), GetOriginalHeight());
|
||||
bool GetCv(cv::Mat& image, VideoMode::PixelFormat pixelFormat) {
|
||||
return GetCv(image, GetOriginalWidth(), GetOriginalHeight(), pixelFormat);
|
||||
}
|
||||
bool GetCv(cv::Mat& image, int width, int height);
|
||||
bool GetCv(cv::Mat& image, int width, int height,
|
||||
VideoMode::PixelFormat pixelFormat);
|
||||
|
||||
private:
|
||||
Image* ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
|
||||
|
||||
@@ -72,6 +72,23 @@ class Image {
|
||||
return cv::Mat{height, width, type, m_data.data()};
|
||||
}
|
||||
|
||||
int GetStride() const {
|
||||
switch (pixelFormat) {
|
||||
case VideoMode::kYUYV:
|
||||
case VideoMode::kRGB565:
|
||||
case VideoMode::kY16:
|
||||
case VideoMode::kUYVY:
|
||||
return 2 * width;
|
||||
case VideoMode::kBGR:
|
||||
return 3 * width;
|
||||
case VideoMode::kGray:
|
||||
return width;
|
||||
case VideoMode::kMJPEG:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cv::_InputArray AsInputArray() { return cv::_InputArray{m_data}; }
|
||||
|
||||
bool Is(int width_, int height_) {
|
||||
|
||||
@@ -40,7 +40,7 @@ void RawSinkImpl::Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
|
||||
uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image) {
|
||||
SetEnabled(true);
|
||||
|
||||
auto source = GetSource();
|
||||
@@ -60,7 +60,7 @@ uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
|
||||
return GrabFrameImpl(image, frame);
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) {
|
||||
uint64_t RawSinkImpl::GrabFrame(WPI_RawFrame& image, double timeout) {
|
||||
SetEnabled(true);
|
||||
|
||||
auto source = GetSource();
|
||||
@@ -80,11 +80,11 @@ uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) {
|
||||
return GrabFrameImpl(image, frame);
|
||||
}
|
||||
|
||||
uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame,
|
||||
uint64_t RawSinkImpl::GrabFrameImpl(WPI_RawFrame& rawFrame,
|
||||
Frame& incomingFrame) {
|
||||
Image* newImage = nullptr;
|
||||
|
||||
if (rawFrame.pixelFormat == CS_PixelFormat::CS_PIXFMT_UNKNOWN) {
|
||||
if (rawFrame.pixelFormat == WPI_PixelFormat::WPI_PIXFMT_UNKNOWN) {
|
||||
// Always get incoming image directly on unknown
|
||||
newImage = incomingFrame.GetExistingImage(0);
|
||||
} else {
|
||||
@@ -106,13 +106,13 @@ uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
CS_AllocateRawFrameData(&rawFrame, newImage->size());
|
||||
WPI_AllocateRawFrameData(&rawFrame, newImage->size());
|
||||
rawFrame.height = newImage->height;
|
||||
rawFrame.width = newImage->width;
|
||||
rawFrame.stride = newImage->GetStride();
|
||||
rawFrame.pixelFormat = newImage->pixelFormat;
|
||||
rawFrame.totalData = newImage->size();
|
||||
std::copy(newImage->data(), newImage->data() + rawFrame.totalData,
|
||||
rawFrame.data);
|
||||
rawFrame.size = newImage->size();
|
||||
std::copy(newImage->data(), newImage->data() + rawFrame.size, rawFrame.data);
|
||||
|
||||
return incomingFrame.GetTime();
|
||||
}
|
||||
@@ -159,7 +159,7 @@ CS_Sink CreateRawSinkCallback(std::string_view name,
|
||||
inst.telemetry, processFrame));
|
||||
}
|
||||
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) {
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, WPI_RawFrame& image, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_RAW) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
@@ -168,7 +168,7 @@ uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) {
|
||||
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image);
|
||||
}
|
||||
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame& image, double timeout,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || data->kind != CS_SINK_RAW) {
|
||||
@@ -192,12 +192,12 @@ CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
|
||||
name, [=](uint64_t time) { processFrame(data, time); }, status);
|
||||
}
|
||||
|
||||
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* image,
|
||||
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct WPI_RawFrame* image,
|
||||
CS_Status* status) {
|
||||
return cs::GrabSinkFrame(sink, *image, status);
|
||||
}
|
||||
|
||||
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* image,
|
||||
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct WPI_RawFrame* image,
|
||||
double timeout, CS_Status* status) {
|
||||
return cs::GrabSinkFrameTimeout(sink, *image, timeout, status);
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ class RawSinkImpl : public SinkImpl {
|
||||
|
||||
void Stop();
|
||||
|
||||
uint64_t GrabFrame(CS_RawFrame& frame);
|
||||
uint64_t GrabFrame(CS_RawFrame& frame, double timeout);
|
||||
uint64_t GrabFrame(WPI_RawFrame& frame);
|
||||
uint64_t GrabFrame(WPI_RawFrame& frame, double timeout);
|
||||
|
||||
private:
|
||||
void ThreadMain();
|
||||
|
||||
uint64_t GrabFrameImpl(CS_RawFrame& rawFrame, Frame& incomingFrame);
|
||||
uint64_t GrabFrameImpl(WPI_RawFrame& rawFrame, Frame& incomingFrame);
|
||||
|
||||
std::atomic_bool m_active; // set to false to terminate threads
|
||||
std::thread m_thread;
|
||||
|
||||
@@ -21,7 +21,7 @@ RawSourceImpl::RawSourceImpl(std::string_view name, wpi::Logger& logger,
|
||||
|
||||
RawSourceImpl::~RawSourceImpl() = default;
|
||||
|
||||
void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
|
||||
void RawSourceImpl::PutFrame(const WPI_RawFrame& image) {
|
||||
int type;
|
||||
switch (image.pixelFormat) {
|
||||
case VideoMode::kYUYV:
|
||||
@@ -39,10 +39,11 @@ void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
|
||||
type = CV_8UC1;
|
||||
break;
|
||||
}
|
||||
cv::Mat finalImage{image.height, image.width, type, image.data};
|
||||
cv::Mat finalImage{image.height, image.width, type, image.data,
|
||||
static_cast<size_t>(image.stride)};
|
||||
std::unique_ptr<Image> dest =
|
||||
AllocImage(static_cast<VideoMode::PixelFormat>(image.pixelFormat),
|
||||
image.width, image.height, image.totalData);
|
||||
image.width, image.height, image.size);
|
||||
finalImage.copyTo(dest->AsMat());
|
||||
|
||||
SourceImpl::PutFrame(std::move(dest), wpi::Now());
|
||||
@@ -57,7 +58,7 @@ CS_Source CreateRawSource(std::string_view name, const VideoMode& mode,
|
||||
inst.telemetry, mode));
|
||||
}
|
||||
|
||||
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
|
||||
void PutSourceFrame(CS_Source source, const WPI_RawFrame& image,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_RAW) {
|
||||
@@ -75,7 +76,7 @@ CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
|
||||
status);
|
||||
}
|
||||
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct WPI_RawFrame* image,
|
||||
CS_Status* status) {
|
||||
return cs::PutSourceFrame(source, *image, status);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class RawSourceImpl : public ConfigurableSourceImpl {
|
||||
~RawSourceImpl() override;
|
||||
|
||||
// Raw-specific functions
|
||||
void PutFrame(const CS_RawFrame& image);
|
||||
void PutFrame(const WPI_RawFrame& image);
|
||||
|
||||
private:
|
||||
std::atomic_bool m_connected{true};
|
||||
|
||||
@@ -181,7 +181,7 @@ CS_Bool CS_SetSourceVideoMode(CS_Source source, const CS_VideoMode* mode,
|
||||
}
|
||||
|
||||
CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source,
|
||||
enum CS_PixelFormat pixelFormat,
|
||||
enum WPI_PixelFormat pixelFormat,
|
||||
int width, int height, int fps,
|
||||
CS_Status* status) {
|
||||
return cs::SetSourceVideoMode(
|
||||
@@ -193,7 +193,7 @@ CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source,
|
||||
}
|
||||
|
||||
CS_Bool CS_SetSourcePixelFormat(CS_Source source,
|
||||
enum CS_PixelFormat pixelFormat,
|
||||
enum WPI_PixelFormat pixelFormat,
|
||||
CS_Status* status) {
|
||||
return cs::SetSourcePixelFormat(
|
||||
source,
|
||||
@@ -541,25 +541,4 @@ void CS_FreeNetworkInterfaces(char** interfaces, int count) {
|
||||
std::free(interfaces);
|
||||
}
|
||||
|
||||
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) {
|
||||
if (frame->dataLength >= requestedSize) {
|
||||
return;
|
||||
}
|
||||
if (frame->data) {
|
||||
frame->data =
|
||||
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));
|
||||
} else {
|
||||
frame->data = static_cast<char*>(wpi::safe_malloc(requestedSize));
|
||||
}
|
||||
frame->dataLength = requestedSize;
|
||||
}
|
||||
|
||||
void CS_FreeRawFrameData(CS_RawFrame* frame) {
|
||||
if (frame->data) {
|
||||
std::free(frame->data);
|
||||
frame->data = nullptr;
|
||||
frame->dataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#define WPI_RAWFRAME_JNI
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/jni_util.h>
|
||||
|
||||
#include "cscore_cpp.h"
|
||||
#include "cscore_cv.h"
|
||||
#include "cscore_raw.h"
|
||||
#include "cscore_runloop.h"
|
||||
@@ -44,7 +46,7 @@ static const JClassInit classes[] = {
|
||||
{"edu/wpi/first/cscore/UsbCameraInfo", &usbCameraInfoCls},
|
||||
{"edu/wpi/first/cscore/VideoMode", &videoModeCls},
|
||||
{"edu/wpi/first/cscore/VideoEvent", &videoEventCls},
|
||||
{"edu/wpi/first/cscore/raw/RawFrame", &rawFrameCls}};
|
||||
{"edu/wpi/first/util/RawFrame", &rawFrameCls}};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"edu/wpi/first/cscore/VideoException", &videoEx},
|
||||
@@ -1221,48 +1223,78 @@ Java_edu_wpi_first_cscore_CameraServerCvJNI_putSourceFrame
|
||||
}
|
||||
}
|
||||
|
||||
// int width, int height, int pixelFormat, int totalData
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: putRawSourceFrameBB
|
||||
* Signature: (ILjava/lang/Object;IIII)V
|
||||
* Method: putRawSourceFrame
|
||||
* Signature: (IJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrameBB
|
||||
(JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width,
|
||||
jint height, jint pixelFormat, jint totalData)
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrame
|
||||
(JNIEnv* env, jclass, jint source, jlong framePtr)
|
||||
{
|
||||
CS_RawFrame rawFrame;
|
||||
rawFrame.data =
|
||||
reinterpret_cast<char*>(env->GetDirectBufferAddress(byteBuffer));
|
||||
rawFrame.totalData = totalData;
|
||||
rawFrame.pixelFormat = pixelFormat;
|
||||
rawFrame.width = width;
|
||||
rawFrame.height = height;
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
if (!frame) {
|
||||
nullPointerEx.Throw(env, "frame is null");
|
||||
return;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, rawFrame, &status);
|
||||
cs::PutSourceFrame(source, *frame, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: putRawSourceFrame
|
||||
* Signature: (IJIIII)V
|
||||
* Method: putRawSourceFrameBB
|
||||
* Signature: (ILjava/lang/Object;IIIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrame
|
||||
(JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height,
|
||||
jint pixelFormat, jint totalData)
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrameBB
|
||||
(JNIEnv* env, jclass, jint source, jobject data, jint size, jint width,
|
||||
jint height, jint stride, jint pixelFormat)
|
||||
{
|
||||
CS_RawFrame rawFrame;
|
||||
rawFrame.data = reinterpret_cast<char*>(static_cast<intptr_t>(ptr));
|
||||
rawFrame.totalData = totalData;
|
||||
rawFrame.pixelFormat = pixelFormat;
|
||||
rawFrame.width = width;
|
||||
rawFrame.height = height;
|
||||
WPI_RawFrame frame; // use WPI_Frame because we don't want the destructor
|
||||
frame.data = static_cast<uint8_t*>(env->GetDirectBufferAddress(data));
|
||||
if (!frame.data) {
|
||||
nullPointerEx.Throw(env, "data is null");
|
||||
return;
|
||||
}
|
||||
frame.freeFunc = nullptr;
|
||||
frame.freeCbData = nullptr;
|
||||
frame.size = size;
|
||||
frame.width = width;
|
||||
frame.height = height;
|
||||
frame.stride = stride;
|
||||
frame.pixelFormat = pixelFormat;
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, rawFrame, &status);
|
||||
cs::PutSourceFrame(source, frame, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: putRawSourceFrameData
|
||||
* Signature: (IJIIIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_putRawSourceFrameData
|
||||
(JNIEnv* env, jclass, jint source, jlong data, jint size, jint width,
|
||||
jint height, jint stride, jint pixelFormat)
|
||||
{
|
||||
WPI_RawFrame frame; // use WPI_Frame because we don't want the destructor
|
||||
frame.data = reinterpret_cast<uint8_t*>(data);
|
||||
if (!frame.data) {
|
||||
nullPointerEx.Throw(env, "data is null");
|
||||
return;
|
||||
}
|
||||
frame.freeFunc = nullptr;
|
||||
frame.freeCbData = nullptr;
|
||||
frame.size = size;
|
||||
frame.width = width;
|
||||
frame.height = height;
|
||||
frame.stride = stride;
|
||||
frame.pixelFormat = pixelFormat;
|
||||
CS_Status status = 0;
|
||||
cs::PutSourceFrame(source, frame, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -1392,18 +1424,20 @@ Java_edu_wpi_first_cscore_CameraServerJNI_createMjpegServer
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerCvJNI
|
||||
* Method: createCvSink
|
||||
* Signature: (Ljava/lang/String;)I
|
||||
* Signature: (Ljava/lang/String;I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerCvJNI_createCvSink
|
||||
(JNIEnv* env, jclass, jstring name)
|
||||
(JNIEnv* env, jclass, jstring name, jint pixelFormat)
|
||||
{
|
||||
if (!name) {
|
||||
nullPointerEx.Throw(env, "name cannot be null");
|
||||
return 0;
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val = cs::CreateCvSink(JStringRef{env, name}.str(), &status);
|
||||
auto val = cs::CreateCvSink(
|
||||
JStringRef{env, name}.str(),
|
||||
static_cast<cs::VideoMode::PixelFormat>(pixelFormat), &status);
|
||||
CheckStatus(env, status);
|
||||
return val;
|
||||
}
|
||||
@@ -1721,72 +1755,47 @@ Java_edu_wpi_first_cscore_CameraServerCvJNI_grabSinkFrameTimeout
|
||||
}
|
||||
}
|
||||
|
||||
static void SetRawFrameData(JNIEnv* env, jobject rawFrameObj,
|
||||
jobject byteBuffer, bool didChangeDataPtr,
|
||||
const CS_RawFrame& frame) {
|
||||
static jmethodID setMethod =
|
||||
env->GetMethodID(rawFrameCls, "setData", "(Ljava/nio/ByteBuffer;JIIII)V");
|
||||
jlong framePtr = static_cast<jlong>(reinterpret_cast<intptr_t>(frame.data));
|
||||
|
||||
if (didChangeDataPtr) {
|
||||
byteBuffer = env->NewDirectByteBuffer(frame.data, frame.dataLength);
|
||||
}
|
||||
|
||||
env->CallVoidMethod(
|
||||
rawFrameObj, setMethod, byteBuffer, framePtr,
|
||||
static_cast<jint>(frame.totalData), static_cast<jint>(frame.width),
|
||||
static_cast<jint>(frame.height), static_cast<jint>(frame.pixelFormat));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: grabRawSinkFrameImpl
|
||||
* Signature: (ILjava/lang/Object;JLjava/lang/Object;III)J
|
||||
* Method: grabRawSinkFrame
|
||||
* Signature: (ILjava/lang/Object;J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameImpl
|
||||
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
|
||||
jobject byteBuffer, jint width, jint height, jint pixelFormat)
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrame
|
||||
(JNIEnv* env, jclass, jint sink, jobject frameObj, jlong framePtr)
|
||||
{
|
||||
CS_RawFrame* ptr =
|
||||
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
|
||||
auto origDataPtr = ptr->data;
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->pixelFormat = pixelFormat;
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
auto origData = frame->data;
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrame(static_cast<CS_Sink>(sink), *ptr, &status);
|
||||
auto rv = cs::GrabSinkFrame(static_cast<CS_Sink>(sink), *frame, &status);
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame,
|
||||
origData != frame->data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: grabRawSinkFrameTimeoutImpl
|
||||
* Signature: (ILjava/lang/Object;JLjava/lang/Object;IIID)J
|
||||
* Method: grabRawSinkFrameTimeout
|
||||
* Signature: (ILjava/lang/Object;JD)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
|
||||
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
|
||||
jobject byteBuffer, jint width, jint height, jint pixelFormat,
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_grabRawSinkFrameTimeout
|
||||
(JNIEnv* env, jclass, jint sink, jobject frameObj, jlong framePtr,
|
||||
jdouble timeout)
|
||||
{
|
||||
CS_RawFrame* ptr =
|
||||
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
|
||||
auto origDataPtr = ptr->data;
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->pixelFormat = pixelFormat;
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
auto origData = frame->data;
|
||||
CS_Status status = 0;
|
||||
auto rv = cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *ptr, timeout,
|
||||
&status);
|
||||
auto rv = cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *frame,
|
||||
timeout, &status);
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame,
|
||||
origData != frame->data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -2199,34 +2208,6 @@ Java_edu_wpi_first_cscore_CameraServerJNI_setLogger
|
||||
minLevel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: allocateRawFrame
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_allocateRawFrame
|
||||
(JNIEnv*, jclass)
|
||||
{
|
||||
cs::RawFrame* rawFrame = new cs::RawFrame{};
|
||||
intptr_t rawFrameIntPtr = reinterpret_cast<intptr_t>(rawFrame);
|
||||
return static_cast<jlong>(rawFrameIntPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: freeRawFrame
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_cscore_CameraServerJNI_freeRawFrame
|
||||
(JNIEnv*, jclass, jlong rawFrame)
|
||||
{
|
||||
cs::RawFrame* ptr =
|
||||
reinterpret_cast<cs::RawFrame*>(static_cast<intptr_t>(rawFrame));
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_cscore_CameraServerJNI
|
||||
* Method: runMainRunLoop
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <wpi/RawFrame.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstddef>
|
||||
#else
|
||||
@@ -84,20 +86,6 @@ enum CS_LogLevel {
|
||||
CS_LOG_DEBUG4 = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* Pixel formats
|
||||
*/
|
||||
enum CS_PixelFormat {
|
||||
CS_PIXFMT_UNKNOWN = 0,
|
||||
CS_PIXFMT_MJPEG,
|
||||
CS_PIXFMT_YUYV,
|
||||
CS_PIXFMT_RGB565,
|
||||
CS_PIXFMT_BGR,
|
||||
CS_PIXFMT_GRAY,
|
||||
CS_PIXFMT_Y16,
|
||||
CS_PIXFMT_UYVY
|
||||
};
|
||||
|
||||
/**
|
||||
* Video mode
|
||||
*/
|
||||
@@ -302,11 +290,11 @@ void CS_GetSourceVideoMode(CS_Source source, CS_VideoMode* mode,
|
||||
CS_Bool CS_SetSourceVideoMode(CS_Source source, const CS_VideoMode* mode,
|
||||
CS_Status* status);
|
||||
CS_Bool CS_SetSourceVideoModeDiscrete(CS_Source source,
|
||||
enum CS_PixelFormat pixelFormat,
|
||||
enum WPI_PixelFormat pixelFormat,
|
||||
int width, int height, int fps,
|
||||
CS_Status* status);
|
||||
CS_Bool CS_SetSourcePixelFormat(CS_Source source,
|
||||
enum CS_PixelFormat pixelFormat,
|
||||
enum WPI_PixelFormat pixelFormat,
|
||||
CS_Status* status);
|
||||
CS_Bool CS_SetSourceResolution(CS_Source source, int width, int height,
|
||||
CS_Status* status);
|
||||
@@ -382,8 +370,10 @@ void CS_SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
|
||||
*/
|
||||
CS_Sink CS_CreateMjpegServer(const char* name, const char* listenAddress,
|
||||
int port, CS_Status* status);
|
||||
CS_Sink CS_CreateCvSink(const char* name, CS_Status* status);
|
||||
CS_Sink CS_CreateCvSinkCallback(const char* name, void* data,
|
||||
CS_Sink CS_CreateCvSink(const char* name, enum WPI_PixelFormat pixelFormat,
|
||||
CS_Status* status);
|
||||
CS_Sink CS_CreateCvSinkCallback(const char* name,
|
||||
enum WPI_PixelFormat pixelFormat, void* data,
|
||||
void (*processFrame)(void* data, uint64_t time),
|
||||
CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/json_fwd.h>
|
||||
|
||||
@@ -60,14 +61,14 @@ struct UsbCameraInfo {
|
||||
*/
|
||||
struct VideoMode : public CS_VideoMode {
|
||||
enum PixelFormat {
|
||||
kUnknown = CS_PIXFMT_UNKNOWN,
|
||||
kMJPEG = CS_PIXFMT_MJPEG,
|
||||
kYUYV = CS_PIXFMT_YUYV,
|
||||
kRGB565 = CS_PIXFMT_RGB565,
|
||||
kBGR = CS_PIXFMT_BGR,
|
||||
kGray = CS_PIXFMT_GRAY,
|
||||
kY16 = CS_PIXFMT_Y16,
|
||||
kUYVY = CS_PIXFMT_UYVY
|
||||
kUnknown = WPI_PIXFMT_UNKNOWN,
|
||||
kMJPEG = WPI_PIXFMT_MJPEG,
|
||||
kYUYV = WPI_PIXFMT_YUYV,
|
||||
kRGB565 = WPI_PIXFMT_RGB565,
|
||||
kBGR = WPI_PIXFMT_BGR,
|
||||
kGray = WPI_PIXFMT_GRAY,
|
||||
kY16 = WPI_PIXFMT_Y16,
|
||||
kUYVY = WPI_PIXFMT_UYVY
|
||||
};
|
||||
VideoMode() {
|
||||
pixelFormat = 0;
|
||||
@@ -316,8 +317,10 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
|
||||
*/
|
||||
CS_Sink CreateMjpegServer(std::string_view name, std::string_view listenAddress,
|
||||
int port, CS_Status* status);
|
||||
CS_Sink CreateCvSink(std::string_view name, CS_Status* status);
|
||||
CS_Sink CreateCvSink(std::string_view name, VideoMode::PixelFormat pixelFormat,
|
||||
CS_Status* status);
|
||||
CS_Sink CreateCvSinkCallback(std::string_view name,
|
||||
VideoMode::PixelFormat pixelFormat,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user