Compare commits

..

1 Commits

Author SHA1 Message Date
Alex Henning
8856927fd8 Added support for Jenkins to generate doxygen.
Change-Id: I2febfe42cc9301446f796376cfe8e1ef6744f19a
2014-08-12 15:06:43 -04:00
5522 changed files with 460559 additions and 541173 deletions

View File

@@ -1,166 +0,0 @@
---
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
- Regex: '^<.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
...

View File

@@ -1,76 +0,0 @@
Checks:
'bugprone-assert-side-effect,
bugprone-bool-pointer-implicit-conversion,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-exception-escape,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-virtual-near-miss,
cert-dcl58-cpp,
cert-err52-cpp,
cert-err60-cpp,
cert-mem57-cpp,
cert-oop57-cpp,
cert-oop58-cpp,
clang-diagnostic-*,
-clang-diagnostic-deprecated-declarations,
-clang-diagnostic-#warnings,
-clang-diagnostic-pedantic,
clang-analyzer-*,
cppcoreguidelines-slicing,
google-build-namespaces,
google-explicit-constructor,
google-global-names-in-headers,
google-readability-avoid-underscore-in-googletest-name,
google-readability-casting,
google-runtime-operator,
llvm-twine-local,
misc-definitions-in-headers,
misc-misplaced-const,
misc-new-delete-overloads,
misc-non-copyable-objects,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-use-default-member-init,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
readability-braces-around-statements'
FormatStyle: file
CheckOptions:
- key: bugprone-dangling-handle
value: 'wpi::StringRef;wpi::Twine'

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
*.gradle text eol=lf
*.java text eol=lf
*.md text eol=lf
*.xml text eol=lf

38
.github/CODEOWNERS vendored
View File

@@ -1,38 +0,0 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# More details are here: https://help.github.com/articles/about-codeowners/
# The '*' pattern is global owners.
# Order is important. The last matching pattern has the most precedence.
# The folders are ordered as a tree: by depth then alphabetically.
# This should make it easy to add new rules without breaking existing ones.
# Global rule:
* @wpilibsuite/wpilib
/cameraserver/ @wpilibsuite/camera-server
/cscore/ @wpilibsuite/camera-server
/hal/ @wpilibsuite/hardware
/hal/src/main/java/**/sim/ @wpilibsuite/simulation
/hal/src/main/native/include/mockdata/ @wpilibsuite/simulation
/hal/src/main/native/include/simulation/ @wpilibsuite/simulation
/hal/src/main/native/sim/ @wpilibsuite/simulation
/ntcore/ @wpilibsuite/network-tables
/simulation/ @wpilibsuite/simulation
/wpilibNewCommands/ @wpilibsuite/commandbased
/wpilibOldCommands/ @wpilibsuite/commandbased
/wpilibcExamples/ @wpilibsuite/wpilib @wpilibsuite/documentation
/wpilibjExamples/ @wpilibsuite/wpilib @wpilibsuite/documentation
/wpiutil/ @PeterJohnson

View File

@@ -1,30 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. ...
2. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows]
- Java version [e.g. 1.10.2]
- C++ version [e.g. 17]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,20 +0,0 @@
---
name: Question
about: Ask about features or parts of this project
title: ''
labels: ''
assignees: ''
---
**Describe the question you have.**
A clear and concise description of what you want clarification on.
**Describe the reason for your confusion.**
A clear and concise description of why the question requires clarification and what's confusing.
**Is your question related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Additional context**
Add any other context or screenshots about the question here.

View File

@@ -1,59 +0,0 @@
name: CMake
on: [pull_request, push]
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: Linux
container: wpilib/roborio-cross-ubuntu:2020-18.04
flags: ""
- os: macos-latest
name: macOS
container: ""
flags: "-DWITH_JAVA=OFF"
name: "Build - ${{ matrix.name }}"
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
if [ "$RUNNER_OS" == "macOS" ]; then
brew install opencv
fi
- name: configure
run: mkdir build && cd build && cmake ${{ matrix.flags }} ..
- name: build
working-directory: build
run: make -j3
- name: test
working-directory: build
run: make test
build-vcpkg:
name: "Build - Windows"
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Prepare vcpkg
uses: lukka/run-vcpkg@v4
with:
vcpkgArguments: opencv
vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
vcpkgGitCommitId: 544f8e4593764f78faa94bac2adb81cca5232943
vcpkgTriplet: x64-windows
- name: Configure & Build
uses: lukka/run-cmake@v3
with:
buildDirectory: ${{ runner.workspace }}/build/
cmakeAppendedArgs: -DWITH_JAVA=OFF
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
useVcpkgToolchainFile: true
- name: Run Tests
run: ctest -C "Debug"
working-directory: ${{ runner.workspace }}/build/

View File

@@ -1,58 +0,0 @@
name: Documentation
on: [push, workflow_dispatch]
env:
BASE_PATH: allwpilib/docs
jobs:
publish:
name: "Documentation - Publish"
runs-on: ubuntu-latest
if: github.repository_owner == 'wpilibsuite' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-java@v1
with:
java-version: 13
- name: Set environment variables (Development)
run: |
echo "TARGET_FOLDER=$BASE_PATH/development" >> $GITHUB_ENV
if: github.ref == 'refs/heads/master'
- name: Set environment variables (Tag)
run: |
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
echo "TARGET_FOLDER=$BASE_PATH/beta" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
- name: Set environment variables (Release)
run: |
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
echo "TARGET_FOLDER=$BASE_PATH/release" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'alpha') && !contains(github.ref, 'beta')
- name: Build with Gradle
run: ./gradlew docs:generateJavaDocs docs:doxygen -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
- name: Install SSH Client 🔑
uses: webfactory/ssh-agent@v0.4.1
with:
ssh-private-key: ${{ secrets.GH_DEPLOY_KEY }}
- name: Deploy Java 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
SSH: true
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
BRANCH: main
CLEAN: true
FOLDER: docs/build/docs/javadoc
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/java
- name: Deploy C++ 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
SSH: true
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
BRANCH: main
CLEAN: true
FOLDER: docs/build/docs/doxygen/html
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/cpp

View File

@@ -1,15 +0,0 @@
name: Gazebo
on: [pull_request, push]
jobs:
build:
name: "Build"
runs-on: ubuntu-latest
container: wpilib/gazebo-ubuntu:18.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Build with Gradle
run: ./gradlew build -PbuildServer -PmakeSim -Dorg.gradle.jvmargs=-Xmx2g

View File

@@ -1,10 +0,0 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1

View File

@@ -1,162 +0,0 @@
name: Gradle
on: [pull_request, push]
jobs:
build-docker:
strategy:
fail-fast: false
matrix:
include:
- container: wpilib/roborio-cross-ubuntu:2021-18.04
artifact-name: Athena
build-options: "-Ponlylinuxathena"
- container: wpilib/raspbian-cross-ubuntu:10-18.04
artifact-name: Raspbian
build-options: "-Ponlylinuxraspbian"
- container: wpilib/aarch64-cross-ubuntu:bionic-18.04
artifact-name: Aarch64
build-options: "-Ponlylinuxaarch64bionic"
- container: wpilib/ubuntu-base:18.04
artifact-name: Linux
build-options: "-Dorg.gradle.jvmargs=-Xmx2g"
name: "Build - ${{ matrix.artifact-name }}"
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set release environment variable
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew build -PbuildServer ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.artifact-name }}
path: build/allOutputs
build-host:
env:
MACOSX_DEPLOYMENT_TARGET: 10.14
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
artifact-name: Win64
architecture: x64
- os: windows-latest
artifact-name: Win32
architecture: x86
- os: macos-latest
artifact-name: macOS
architecture: x64
name: "Build - ${{ matrix.artifact-name }}"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-java@v1
with:
java-version: 11
architecture: ${{ matrix.architecture }}
- name: Import Developer ID Certificate
uses: wpilibsuite/import-signing-certificate@v1
with:
certificate-data: ${{ secrets.APPLE_CERTIFICATE_DATA }}
certificate-passphrase: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
- name: Set Keychain Lock Timeout
run: security set-keychain-settings -lut 3600
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
- name: Set release environment variable
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
shell: bash
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew build -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
- name: Sign Libraries with Developer ID
run: ./gradlew build -PbuildServer -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ env.EXTRA_GRADLE_ARGS }}
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.artifact-name }}
path: build/allOutputs
build-documentation:
name: "Build - Documentation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-java@v1
with:
java-version: 13
- name: Set release environment variable
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew docs:zipDocs -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
- uses: actions/upload-artifact@v2
with:
name: Documentation
path: docs/build/outputs
combine:
name: Combine
needs: [build-docker, build-host, build-documentation]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
repository: wpilibsuite/build-tools
- uses: actions/download-artifact@v2
with:
path: combiner/products/build/allOutputs
- name: Flatten Artifacts
run: rsync -a --delete combiner/products/build/allOutputs/*/* combiner/products/build/allOutputs/
- name: Check version number exists
run: |
cat combiner/products/build/allOutputs/version.txt
test -s combiner/products/build/allOutputs/version.txt
- uses: actions/setup-java@v1
with:
java-version: 11
- name: Combine
if: |
!startsWith(github.ref, 'refs/tags/v') &&
github.ref != 'refs/heads/master'
run: cd combiner && ./gradlew publish -Pallwpilib
- name: Combine (Master)
if: |
github.repository_owner == 'wpilibsuite' &&
github.ref == 'refs/heads/master'
run: cd combiner && ./gradlew publish -Pallwpilib
env:
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
- name: Combine (Release)
if: |
github.repository_owner == 'wpilibsuite' &&
startsWith(github.ref, 'refs/tags/v')
run: cd combiner && ./gradlew publish -Pallwpilib -PreleaseRepoPublish
env:
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
- uses: actions/upload-artifact@v2
with:
name: Maven
path: ~/releases

View File

@@ -1,52 +0,0 @@
name: Lint and Format
on: [pull_request]
jobs:
wpiformat:
name: "wpiformat"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install clang-format
run: sudo apt-get update -q && sudo apt-get install -y clang-format-10
- name: Install wpiformat
run: pip3 install wpiformat
- name: Run
run: wpiformat -clang 10
- name: Check Output
run: git --no-pager diff --exit-code HEAD
tidy:
name: "clang-tidy"
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2020-18.04
steps:
- uses: actions/checkout@v2
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install clang-format and clang-tidy
run: sudo apt-get update -q && sudo apt-get install -y clang-format-10 clang-tidy-10
- name: Install wpiformat
run: pip3 install wpiformat
- name: Create compile_commands.json
run: mkdir build-cmake && cd build-cmake && cmake -DWITH_OLD_COMMANDS=ON -DWITH_EXAMPLES=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ..
- name: List changed files
run: wpiformat -list-changed-files
- name: Run clang-tidy
run: wpiformat -clang 10 -no-format -tidy-changed -compile-commands=build-cmake

229
.gitignore vendored
View File

@@ -1,77 +1,21 @@
# WPIlib Specific
dependency-reduced-pom.xml
doxygen.log
build*/
!buildSrc/
# Created by the jenkins test script
test-reports
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
out/
# Created by http://www.gitignore.io
### Linux ###
wpilibc/build/
hal/build/
networktables/cpp/build/
build/
networktables/OutlineViewer/nbproject/private
*~
target/
dist/
bin/
.project
.cproject
.settings/
.classpath
**/dependency-reduced-pom.xml
# KDE directory preferences
.directory
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Java ###
#Java File extentions
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
@@ -79,148 +23,3 @@ Temporary Items
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### C++ ###
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
### CMake ###
CMakeCache.txt
CMakeFiles
cmake_install.cmake
install_manifest.txt
### Gradle ###
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
### Vagrant ###
.vagrant/
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
### Python ###
*.pyc
__pycache__
# Gradle wrapper
!gradle-wrapper.jar
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
#catkin stuff
package.xml
# Doxygen stuff
NO
# Simulation folder stuff
!simulation/install_resources/*
# VSCode
.vscode/
#classpaths and projects
.project
.classpath
#Visual Studio
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.cachefile
*.VC.db
*.VC.VC.opendb
*.VC.db-shm
*.VC.db-wal
*.sln
*.vcxproj
*.vcxproj.filters
# Visual Studio 2015 cache/options directory
.vs/
# compile_commands
compile_commands.json
# clang configuration and clangd cache
.clang
.clangd/
imgui.ini

5
.gitreview Normal file
View File

@@ -0,0 +1,5 @@
[gerrit]
host=usfirst.collab.net
port=29418
project=allwpilib
defaultbranch=master

View File

@@ -1,40 +0,0 @@
cppHeaderFileInclude {
\.h$
\.hpp$
\.inc$
\.inl$
}
cppSrcFileInclude {
\.cpp$
}
generatedFileExclude {
FRCNetComm\.java$
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
}
repoRootNameOverride {
wpilib
}
includeOtherLibs {
^Eigen/
^cameraserver/
^cscore
^drake/
^hal/
^imgui
^implot
^mockdata/
^networktables/
^ntcore
^opencv2/
^support/
^units/
^unsupported/
^vision/
^wpi/
^wpigui
^wpimath/
}

View File

@@ -1,3 +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.

View File

@@ -1,6 +0,0 @@
{
"enableCppIntellisense": true,
"currentLanguage": "cpp",
"projectYear": "2021",
"teamNumber": 0
}

29
Building.md Normal file
View File

@@ -0,0 +1,29 @@
Building everything requires Maven
mvn package -DembeddedJDKHome=/home/patrick/Downloads/arm-jdk1.7.0_45/
TODO... Explain maven....
TODO.. how to import into eclipse correctly...
Building C++ only
------------------
C++ requires cmake if not run from maven, and is much faster.
Make a new directory and then run:
```
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../arm-toolchain.cmake
make # multicore add -j(num of cpu cores + 1), so -j3 on dual core for faster compile
make install DESTDIR=/some/dir/you/want/to/put/all/headers/and/libs #optional
``
Alternatively, if you like IDEs, you can import it directly into QtDeveloper, or a number of other IDEs such as Code::Blocks or Eclipse. See CMake documentation for details.
Eclipse demo:
```
cd ..
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../allwpilib/arm-toolchain.cmake .. -G "Eclipse CDT4 - Unix Makefiles"
```
and then import that directory into eclipse. Eclipse will detect a CDT project and standard tools will work.
GCC versions
------------
Update arm-toolchain.cmake if the triplet changes (eg using Ubuntu repo arm compiler is arm-linux-gnueabi) or in a non-standard location. Currently it assumes that the compiler is on the path.

View File

@@ -1,219 +1,13 @@
# Disable in-source builds to prevent source tree corruption.
if(" ${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL " ${CMAKE_CURRENT_BINARY_DIR}")
message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
")
endif()
cmake_minimum_required(VERSION 2.8)
project(All-WPILib)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2 -Wall -Wextra -Wno-unused-parameter -fPIC")
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
project(allwpilib)
cmake_minimum_required(VERSION 3.3.0)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
set(WPILIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
INCLUDE(CPack)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
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)
# when building, don't use the install RPATH already
# (but later on when installing)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/wpilib/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)
# 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}/wpilib/lib" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/wpilib/lib")
ENDIF("${isSystemDir}" STREQUAL "-1")
# 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_CSCORE "Build cscore (needs OpenCV)" ON)
option(WITH_WPIMATH "Build wpimath" ON)
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (needs OpenCV)" ON)
option(WITH_OLD_COMMANDS "Build old commands" OFF)
option(WITH_EXAMPLES "Build examples" OFF)
option(WITH_TESTS "Build unit tests (requires internet connection)" ON)
option(WITH_GUI "Build GUI items" ON)
option(WITH_SIMULATION_MODULES "Build simulation modules" ON)
# Options for external HAL.
option(WITH_EXTERNAL_HAL "Use a separately built HAL" OFF)
set(EXTERNAL_HAL_FILE "" CACHE FILEPATH "Location to look for an external HAL CMake File")
# Options for using a package manager (vcpkg) for certain dependencies.
option(USE_VCPKG_LIBUV "Use vcpkg libuv" OFF)
option(USE_VCPKG_EIGEN "Use vcpkg 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")
# 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)
endif()
# We always want flat install with MSVC.
if (MSVC)
set(WITH_FLAT_INSTALL ON)
endif()
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 "
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 "${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
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 "
FATAL: Cannot build simulation modules with wpilib disabled.
Enable wpilib by setting WITH_WPILIB=ON
")
endif()
if (NOT WITH_WPIMATH AND WITH_WPILIB)
message(FATAL_ERROR "
FATAL: Cannot build wpilib without wpimath.
Enable wpimath by setting WITH_WPIMATH=ON
")
endif()
if (NOT WITH_OLD_COMMANDS AND WITH_EXAMPLES)
message(FATAL_ERROR "
FATAL: Cannot build examples with old commands disabled.
Enable old commands by setting WITH_OLD_COMMANDS=ON
")
endif()
set( wpilib_dest wpilib)
set( include_dest wpilib/include )
set( main_lib_dest wpilib/lib )
set( java_lib_dest wpilib/java )
set( jni_lib_dest wpilib/jni )
if (WITH_FLAT_INSTALL)
set (wpilib_config_dir ${wpilib_dest})
else()
set (wpilib_config_dir share/wpilib)
endif()
if (USE_VCPKG_LIBUV)
set (LIBUV_VCPKG_REPLACE "find_package(unofficial-libuv CONFIG)")
endif()
if (USE_VCPKG_EIGEN)
set (EIGEN_VCPKG_REPLACE "find_package(Eigen3 CONFIG)")
endif()
if (WITH_FLAT_INSTALL)
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-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)")
set(WPILIBOLDCOMMANDS_DEP_REPLACE "include(\${SELF_DIR}/wpilibOldcommands-config.cmake)")
else()
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
set(WPILIBNEWCOMMANDS_DEP_REPLACE "find_dependency(wpilibNewCommands)")
set(WPILIBOLDCOMMANDS_DEP_REPLACE "find_dependency(wpilibOldCommands)")
endif()
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
set(SELF_DIR "$\{SELF_DIR\}")
if (WITH_TESTS)
enable_testing()
add_subdirectory(googletest)
include(GoogleTest)
endif()
add_subdirectory(wpiutil)
add_subdirectory(ntcore)
if (WITH_WPIMATH)
add_subdirectory(wpimath)
endif()
if (WITH_GUI)
add_subdirectory(imgui)
add_subdirectory(wpigui)
add_subdirectory(glass)
endif()
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)
if (WITH_WPILIB)
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
add_subdirectory(hal)
add_subdirectory(wpilibj)
add_subdirectory(wpilibc)
add_subdirectory(wpilibNewCommands)
if (WITH_OLD_COMMANDS)
add_subdirectory(wpilibOldCommands)
endif()
if (WITH_EXAMPLES)
add_subdirectory(wpilibcExamples)
endif()
add_subdirectory(myRobot)
endif()
endif()
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})
file(GLOB_RECURSE NI_LIBS ni-libraries/*.so*)
get_filename_component(WPILIB_INCLUDES wpilibc/wpilibC++/include REALPATH)
get_filename_component(HAL_API_INCLUDES hal/include REALPATH)
get_filename_component(NWT_API_INCLUDES networktables/cpp/include REALPATH)
add_subdirectory(hal)
add_subdirectory(networktables/cpp)
add_subdirectory(wpilibc)

View File

@@ -1,131 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Exhibiting Gracious Professionalism® at all times. Gracious Professionalism
is a way of doing things that encourages high-quality work, emphasizes the
value of others, and respects individuals and the community.
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[conduct@wpilib.org](mailto:conduct@wpilib.org).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,56 +0,0 @@
# Contributing to WPILib
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules in the [code of conduct](https://github.com/wpilibsuite/allwpilib/blob/master/CODE_OF_CONDUCT.md), and behave with Gracious Professionalism.
- [General Contribution Rules](#general-contribution-rules)
- [What to Contribute](#what-to-contribute)
- [Coding Guidelines](#coding-guidelines)
- [Submitting Changes](#submitting-changes)
- [Pull Request Format](#pull-request-format)
- [Merge Process](#merge-process)
- [Licensing](#licensing)
## General Contribution Rules
- Everything in the library must work for the 3000+ teams that will be using it.
- We need to be able to maintain submitted changes, even if you are no longer working on the project.
- Tool suite changes must be generally useful to a broad range of teams
- Excluding bug fixes, changes in one language generally need to have corresponding changes in other languages.
- Some features, such the addition of C++11 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only.
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
- Changes should have tests.
- Code should be well documented.
- This involves writing tutorials and/or usage guides for your submitted feature. These articles are then hosted on the [WPILib](https://docs.wpilib.org/) documentation website. See the [frc-docs repository](https://github.com/wpilibsuite/frc-docs) for more information.
## What to Contribute
- Bug reports and fixes
- We will generally accept bug fixes without too much question. If they are only implemented for one language, we will implement them for any other necessary languages. Bug reports are also welcome, please submit them to our GitHub issue tracker.
- While we do welcome improvements to the API, there are a few important rules to consider:
- Features must be added to both WPILibC and WPILibJ, with rare exceptions.
- During competition season, we will not merge any new feature additions. We want to ensure that the API is stable during the season to help minimize issues for teams.
- Ask about large changes before spending a bunch of time on them! You can create a new issue on our GitHub tracker for feature request/discussion and talk about it with us there.
- Features that make it easier for teams with less experience to be more successful are more likely to be accepted.
- Features in WPILib should be broadly applicable to all teams. Anything that is team specific should not be submitted.
- As a rule, we are happy with the general structure of WPILib. We are not interested in major rewrites of all of WPILib. We are open to talking about ideas, but backwards compatibility is very important for WPILib, so be sure to keep this in mind when proposing major changes.
- Generally speaking, we do not accept code for specific sensors. We have to be able to test the sensor in hardware on the WPILib test bed. Additionally, hardware availability for teams is important. Therefore, as a general rule, the library only directly supports hardware that is in the Kit of Parts. If you are a company interested in getting a sensor into the Kit of Parts, please contact FIRST directly at frcparts@firstinspires.org.
## Coding Guidelines
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 10.0 with wpiformat.
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
## Submitting Changes
### Pull Request Format
Changes should be submitted as a Pull Request against the master branch of WPILib. For most changes, commits will be squashed upon merge. For particularly large changes, multiple commits are ok, but assume one commit unless asked otherwise. We may ask you to break a PR into multiple standalone PRs or commits for rebase within one PR to separate unrelated changes. No change will be merged unless it is up to date with the current master. We do this to make sure that the git history isn't too cluttered.
### Merge Process
When you first submit changes, GitHub Actions will attempt to run `./gradlew check` on your change. If this fails, you will need to fix any issues that it sees. Once Actions passes, we will begin the review process in more earnest. One or more WPILib team members will review your change. This will be a back-and-forth process with the WPILib team and the greater community. Once we are satisfied that your change is ready, we will allow our hosted instance to test it. This will run the full gamut of checks, including integration tests on actual hardware. Once all tests have passed and the team is satisfied, we will merge your change into the WPILib repository.
## Licensing
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](LICENSE.md).

View File

@@ -1,24 +0,0 @@
Copyright (c) 2009-2021 FIRST and other WPILib contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of FIRST, WPILib, nor the names of other WPILib
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,27 +0,0 @@
## Publishing Third Party Dependencies
Currently the 3rd party deps are imgui, opencv, and google test
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).
A variable needs to be added called `RUN_AZURE_ARTIFACTORY_RELEASE`, with a value of `true`. Then when the pipeline gets started, the final build outputs will be updated to artifactory.
To use newer versions of C++ dependencies, in `shared/config.gradle`, update the version related to the specific dependency.
For Java dependencies, there is likely a file related to the specific dependency in the shared folder. Update the version in there.
Note, changing artifact locations (This includes changing the artifact year currently, I have an issue open to change this) requires updating the `native-utils` plugin
## Publishing allwpilib
allwpilib publishes to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing desktop tools
Desktop tools publish to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing VS Code
Before publishing, make sure to update the gradlerio version in `vscode-wpilib/resources/gradle/version.txt` Also make sure the gradle wrapper version matches the wrapper required by gradlerio.
Upon pushing a tag, a release will be built, and the files will be uploaded to the releases on GitHub. For publishing to the marketplace, you need a Microsoft account and to be added as a maintainer.
## Publishing GradleRIO
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.

View File

@@ -1,130 +0,0 @@
# WPILib Maven Artifacts
WPILib publishes its built artifacts to our Maven server for use by downstream projects. This document explains these locations, and the meanings of artifact names, classifiers, and versions.
## Repositories
We provide two repositories. These repositories are:
* (Release) https://frcmaven.wpi.edu/artifactory/release/
* (Development) https://frcmaven.wpi.edu/artifactory/development/
The release repository is where official WPILib releases are pushed.
The development repository is where development releases of every commit to [master](https://github.com/wpilibsuite/allwpilib/tree/master) is pushed.
## Artifact classifiers
We provide two base types of artifacts.
The first types are Java artifacts. These are usually published as `jar` files. Usually, the actual jar file is published with no classifier. The sources are published with the `-sources` classifier, and the javadocs are published with the `-javadoc` classifier.
The second types are native artifacts. These are usually published as `zip` files (except for the `JNI` artifact types, which are `jar` files. See below for information on this). The `-sources` and `-headers` classifiers contain the sources and headers respecively for the library. Each artifact also contains a classifier for each platform we publish. This platform is in the format `{os}{arch}`. The platform artifact only contains the binaries for a specific platform. In addition, we provide a `-all` classifier. This classifer combines all of the platform artifacts into a single artifact. This is useful for tools that cannot determine what version to use during builds. However, we recommend using the platform specific classifier when possible. Note that the binary artifacts never contain the headers, you always need the `-headers` classifier to get those.
## Artifact Names
WPILib builds four different types of artifacts.
##### C++ Only Libraries
When we publish C++ only libraries, they are published with the base artifact name as their artifact name, with a `-cpp` extension. All dependencies for the library are linked as shared libraries to the binary.
Example:
```
edu.wpi.first.wpilibc:wpilibc-cpp:version:classifier@zip
```
#### Java Only Libraries
When we publish Java only libraries, they are published with the base artifact name as their artifact name, with a `-java` extension.
Example:
```
edu.wpi.first.wpilibj:wpilibj-java:version
```
#### C++/Java Libraries without JNI
For libraries that are both C++ and Java, but without a JNI component, the C++ component is published with the `basename-cpp` artifact name, and the Java component is published with the `basename-java` artifact name.
Example:
```
edu.wpi.first.wpiutil:wpiutil-cpp:version:classifier@zip (C++)
edu.wpi.first.wpiutil:wpiutil-java:version (Java)
```
#### C++/Java Libraries with JNI
For libraries that are both C++ and Java with a JNI component there are three different artifact names. For Java, the component is published as `basename-java`. For C++, the `basename-cpp` artifact contains the C++ artifacts with all dependencies linked as shared libraries to the binary. These binaries DO contain the JNI entry points. The `basename-jni` artifact contains identical C++ binaries to the `-cpp` artifact, however all of its dependencies are statically linked, and only the JNI and C entry points are exported.
The `-jni` artifact should only be used in cases where you want to create a self contained Java application where the native artifacts are embedded in the jar. Note in an extraction scenario, extending off of the library is never supported, which is why the C++ entry points are not exposed. The name of the library is randomly generated during extraction. For pretty much all cases, and if you ever want to extend from a native library, you should use the `-cpp` artifacts. GradleRIO uses the `-cpp` artifacts for all platforms, even desktop, for this reason.
Example:
```
edu.wpi.first.ntcore:ntcore-cpp:version:classifier@zip (C++)
edu.wpi.first.ntcore:ntcore-jni:version:classifier (JNI jar library)
edu.wpi.first.ntcore:ntcore-java:version (Java)
```
## Provided Artifacts
This repository provides the following artifacts. Below each artifact is its dependencies. Note if ever using the `-jni` artifacts, no dependencies are needed for native binaries.
For C++, if building with static dependencies, the listed order should be the link order in your linker.
All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* wpiutil
* hal
* wpiutil
* halsim
* imgui
* wpiutil
* ntcore
* wpiutil
* cscore
* opencv
* wpiutil
* cameraserver
* ntcore
* cscore
* opencv
* wpiutil
* wpilibj
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
* wpilibNewCommands
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
* wpilibNewCommands
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
### Third Party Artifacts
This repository provides the builds of the following third party software.
All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
* googletest
* imgui
* opencv

View File

@@ -1,73 +0,0 @@
# Installing Development Builds
This article contains instructions on building projects using a development build and a local WPILib build.
**Note:** This only applies to Java/C++ teams.
## Development Build
Development builds are the per-commit build hosted everytime a commit is pushed to the [allwpilib](https://github.com/wpilibsuite/allwpilib/) repository. These builds are then hosted on [artifactory](https://frcmaven.wpi.edu/artifactory/webapp/#/home).
In order to build a project using a development build, find the build.gradle file and open it. Then, add the following code below the plugin section and replace YEAR with the year of the development version.
```groovy
wpi.maven.useDevelopment = true
wpi.wpilibVersion = 'YEAR.+'
wpi.wpimathVersion = 'YEAR.+
```
The top of your ``build.gradle`` file should now look similar to the code below. Ignore any differences in versions.
Java
```groovy
plugins {
id "java"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
}
wpi.maven.useDevelopment = true
wpi.wpilibVersion = '2021.+'
wpi.wpimathVersion = '2021.+'
```
C++
```groovy
plugins {
id "cpp"
id "google-test-test-suite"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
}
wpi.maven.useDevelopment = true
wpi.wpilibVersion = '2021.+'
wpi.wpimathVersion = '2021.+'
```
## Local Build
Building with a local build is very similar to building with a development build. Ensure you have built and published WPILib by following the instructions attached [here](https://github.com/wpilibsuite/allwpilib#building-wpilib). Next, find the ``build.gradle`` file in your robot project and open it. Then, add the following code below the plugin section and replace ``YEAR`` with the year of the local version.
Java
```groovy
plugins {
id "java"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
}
wpi.maven.useFrcMavenLocalDevelopment = true
wpi.wpilibVersion = 'YEAR.424242.+'
wpi.wpimathVersion = 'YEAR.424242.+'
```
C++
```groovy
plugins {
id "cpp"
id "google-test-test-suite"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
}
wpi.maven.useFrcMavenLocalDevelopment = true
wpi.wpilibVersion = 'YEAR.424242.+'
wpi.wpimathVersion = 'YEAR.424242.+'
```

View File

@@ -1,151 +0,0 @@
# WPILib CMake Support
WPILib is normally built with Gradle, however for some systems, such as Linux based coprocessors, Gradle doesn't work correctly, especially if cscore is needed, which requires OpenCV. Furthermore, the CMake build can be used for C++ development because it provides better build caching compared to Gradle. We provide the CMake build for these cases. Although it is supported on Windows, these docs will only go over Linux builds.
## Libraries that get built
* wpiutil
* ntcore
* cscore
* cameraserver
* hal
* wpilib
* halsim
* wpigui
* wpimath
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.
## Prerequisites
The most common prerequisite is going to be OpenCV. OpenCV needs to be findable by CMake. On systems like the Jetson, this is installed by default. Otherwise, you will need to build OpenCV from source and install it.
In addition, if you want JNI and Java, you will need a JDK of at least version 11 installed. In addition, you need a `JAVA_HOME` environment variable set properly and set to the JDK directory.
If you are building with unit tests or simulation modules, you will also need an Internet connection for the initial setup process, as CMake will clone google-test and imgui from GitHub.
## Build Options
The following build options are available:
* `WITH_JAVA` (ON Default)
* This option will enable Java and JNI builds. If this is on, `WITH_SHARED_LIBS` must be on. Otherwise CMake will error.
* `WITH_SHARED_LIBS` (ON Default)
* This option will cause cmake to build static libraries instead of shared libraries. If this is off, `WITH_JAVA` must be off. Otherwise CMake will error.
* `WITH_TESTS` (ON Default)
* This option will build C++ unit tests. These can be run via `make test`.
* `WITH_CSCORE` (ON Default)
* This option will cause cscore to be built. Turning this off will implicitly disable cameraserver, the hal and wpilib as well, irrespective of their specific options. If this is off, the OpenCV build requirement is removed.
* `WITH_WPIMATH` (ON Default)
* This option will build the wpimath library. This option must be on to build wpilib.
* `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_SIMULATION_MODULES` (ON Default)
* This option will build simulation modules, including wpigui and the HALSim plugins.
* `WITH_EXTERNAL_HAL` (OFF Default)
* TODO
* `EXTERNAL_HAL_FILE`
* 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!
## Build Setup
The WPILib CMake build does not allow in source builds. Because the `build` directory is used by Gradle, we recommend a `build-cmake` directory in the root. This folder is included in the gitignore.
Once you have a build folder, run CMake configuration in that build directory with the following command.
```
cmake path/to/allwpilib/root
```
If you want to change any of the options, add `-DOPTIONHERE=VALUE` to the `cmake` command. This will check for any dependencies. If everything works properly this will succeed. If not, please check out the troubleshooting section for help.
If you want, you can also use `ccmake` in order to visually set these properties as well. [Here](https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html) is the link to the documentation for that program.
## Building
Once you have cmake setup. run `make` from the directory you configured CMake in. This will build all libraries possible. If you have a multicore system, we recommend running `make` with multiple jobs. The usual rule of thumb is 1.5x the number of cores you have. To run a multiple job build, run the following command with x being the number of jobs you want.
```
make -jx
```
The `ninja` generator is also supported, and can be enabled by passing `-GNinja` to the initial `cmake` command.
## Installing
After build, the easiest way to use the libraries is to install them. Run the following command to install the libraries. This will install them so that they can be used from external cmake projects.
```
sudo make install
```
## Using the installed libraries for C++.
Using the libraries from C++ is the easiest way to use the built libraries.
To do so, create a new folder to contain your project. Add the following code below to a `CMakeLists.txt` file in that directory.
```
cmake_minimum_required(VERSION 3.5)
project(vision_app) # Project Name Here
find_package(wpilib REQUIRED)
add_executable(my_vision_app main.cpp) # executable name as first parameter
target_link_libraries(my_vision_app cameraserver ntcore cscore wpiutil)
```
If you are using them, `wpilibc` and `hal` should be added before the `cameraserver` declaration in the `target_link_libraries` function.
Add a `main.cpp` file to contain your code, and create a build folder. Move into the build folder, and run
```
cmake /path/to/folder/containing/CMakeLists
```
After that, run `make`. That will create your executable. Then you should be able to run `./my_vision_app` to run your application.
## Using the installed libraries for Java
TODO
## Troubleshooting
Below are some common issues that are run into when building.
#### Missing OpenCV
If you are missing OpenCV, you will get an error message similar to this.
```
CMake Error at cscore/CMakeLists.txt:3 (find_package):
By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "OpenCV", but
CMake did not find one.
Could not find a package configuration file provided by "OpenCV" with any
of the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set
"OpenCV_DIR" to a directory containing one of the above files. If "OpenCV"
provides a separate development package or SDK, be sure it has been
installed.
```
If you get that, you need make sure opencv was installed, and then reattempt to configure. If that doesn't work, set the `OpenCV_DIR` variable to the directory where you built OpenCV.
#### Missing Java
If you are missing Java, you will get a message like the following.
```
CMake Error at /usr/share/cmake-3.5/Modules/FindPackageHandleStandardArgs.cmake:148 (message):
Could NOT find Java (missing: Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE
Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE)
```
If this happens, make sure you have a JDK of at least version 8 installed, and that your JAVA_HOME variable is set properly to point to the JDK.
In addition, if you do not need Java, you can disable it with `-DWITH_JAVA=OFF`.

154
README.md
View File

@@ -1,154 +0,0 @@
# WPILib Project
![CI](https://github.com/wpilibsuite/allwpilib/workflows/CI/badge.svg)
[![C++ Documentation](https://img.shields.io/badge/documentation-c%2B%2B-blue)](https://first.wpi.edu/wpilib/allwpilib/docs/development/cpp/)
[![Java Documentation](https://img.shields.io/badge/documentation-java-orange)](https://first.wpi.edu/wpilib/allwpilib/docs/development/java/)
Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WPILibC projects. These are the core libraries for creating robot programs for the roboRIO.
- [WPILib Project](#wpilib-project)
- [WPILib Mission](#wpilib-mission)
- [Building WPILib](#building-wpilib)
- [Requirements](#requirements)
- [Setup](#setup)
- [Building](#building)
- [Faster builds](#faster-builds)
- [Using Development Builds](#using-development-builds)
- [Custom toolchain location](#custom-toolchain-location)
- [Gazebo simulation](#gazebo-simulation)
- [Formatting/linting with wpiformat](#formattinglinting-with-wpiformat)
- [CMake](#cmake)
- [Publishing](#publishing)
- [Structure and Organization](#structure-and-organization)
- [Contributing to WPILib](#contributing-to-wpilib)
## WPILib Mission
The WPILib Mission is to enable FIRST Robotics teams to focus on writing game-specific software rather than focusing on hardware details - "raise the floor, don't lower the ceiling". We work to enable teams with limited programming knowledge and/or mentor experience to be as successful as possible, while not hampering the abilities of teams with more advanced programming capabilities. We support Kit of Parts control system components directly in the library. We also strive to keep parity between major features of each language (Java, C++, and NI's LabVIEW), so that teams aren't at a disadvantage for choosing a specific programming language. WPILib is an open source project, licensed under the BSD 3-clause license. You can find a copy of the license [here](LICENSE.md).
# Building WPILib
Using Gradle makes building WPILib very straightforward. It only has a few dependencies on outside tools, such as the ARM cross compiler for creating roboRIO binaries.
## Requirements
- [JDK 11](https://adoptopenjdk.net/)
- Note that the JRE is insufficient; the full JDK is required
- On Ubuntu, run `sudo apt install openjdk-11-jdk`
- On Windows, install the JDK 11 .msi from the link above
- On macOS, install the JDK 11 .pkg from the link above
- C++ compiler
- On Linux, install GCC 7 or greater
- On Windows, install [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio 2019)
- On macOS, install the Xcode command-line build tools via `xcode-select --install`
- ARM compiler toolchain
- Run `./gradlew installRoboRioToolchain` after cloning this repository
- If the WPILib installer was used, this toolchain is already installed
- Raspberry Pi toolchain (optional)
- Run `./gradlew installRaspbianToolchain` after cloning this repository
## Setup
Clone the WPILib repository and follow the instructions above for installing any required tooling.
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/master/README.md) for wpiformat setup instructions.
## Building
All build steps are executed using the Gradle wrapper, `gradlew`. Each target that Gradle can build is referred to as a task. The most common Gradle task to use is `build`. This will build all the outputs created by WPILib. To run, open a console and cd into the cloned WPILib directory. Then:
```bash
./gradlew build
```
To build a specific subproject, such as WPILibC, you must access the subproject and run the build task only on that project. Accessing a subproject in Gradle is quite easy. Simply use `:subproject_name:task_name` with the Gradle wrapper. For example, building just WPILibC:
```bash
./gradlew :wpilibc:build
```
The gradlew wrapper only exists in the root of the main project, so be sure to run all commands from there. All of the subprojects have build tasks that can be run. Gradle automatically determines and rebuilds dependencies, so if you make a change in the HAL and then run `./gradlew :wpilibc:build`, the HAL will be rebuilt, then WPILibC.
There are a few tasks other than `build` available. To see them, run the meta-task `tasks`. This will print a list of all available tasks, with a description of each task.
### Faster builds
`./gradlew build` builds _everything_, which includes debug and release builds for desktop and all installed cross compilers. Many developers don't need or want to build all of this. Therefore, common tasks have shortcuts to only build necessary components for common development and testing tasks.
`./gradlew testDesktopCpp` and `./gradlew testDesktopJava` will build and run the tests for `wpilibc` and `wpilibj` respectively. They will only build the minimum components required to run the tests.
`testDesktopCpp` and `testDesktopJava` tasks also exist for the projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibOldCommands`, `wpilibNewCommands` and `cameraserver`. These can be ran with `./gradlew :projectName:task`.
`./gradlew buildDesktopCpp` and `./gradlew buildDesktopJava` will compile `wpilibcExamples` and `wpilibjExamples` respectively. The results can't be ran, but they can compile.
### Using Development Builds
Please read the documentation available [here](OtherVersions.md)
### Custom toolchain location
If you have installed the FRC Toolchain to a directory other than the default, or if the Toolchain location is not on your System PATH, you can pass the `toolChainPath` property to specify where it is located. Example:
```bash
./gradlew build -PtoolChainPath=some/path/to/frc/toolchain/bin
```
### Gazebo simulation
If you also want simulation to be built, add -PmakeSim. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
```bash
./gradlew build -PmakeSim
```
If you prefer to use CMake directly, the you can still do so.
The common CMake tasks are wpilibcSim, frc_gazebo_plugins, and gz_msgs
```bash
mkdir build #run this in the root of allwpilib
cd build
cmake ..
make
```
### Formatting/linting
#### wpiformat
wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat` on Windows or `python3 -m wpiformat` on other platforms.
#### Java Code Quality Tools
The Java code quality tools (checkstyle, pmd, etc.) can be run with the `./gradlew javaFormat` task.
### CMake
CMake is also supported for building. See [README-CMAKE.md](README-CMAKE.md).
## Publishing
If you are building to test with other dependencies or just want to export the build as a Maven-style dependency, simply run the `publish` task. This task will publish all available packages to ~/releases/maven/development. If you need to publish the project to a different repo, you can specify it with `-Prepo=repo_name`. Valid options are:
- development - The default repo.
- beta - Publishes to ~/releases/maven/beta.
- stable - Publishes to ~/releases/maven/stable.
- release - Publishes to ~/releases/maven/release.
The maven artifacts are described in [MavenArtifacts.md](MavenArtifacts.md)
## Structure and Organization
The main WPILib code you're probably looking for is in WPILibJ and WPILibC. Those directories are split into shared, sim, and athena. Athena contains the WPILib code meant to run on your roboRIO. Sim is WPILib code meant to run on your computer with Gazebo, and shared is code shared between the two. Shared code must be platform-independent, since it will be compiled with both the ARM cross-compiler and whatever desktop compiler you are using (g++, msvc, etc...).
The Simulation directory contains extra simulation tools and libraries, such as gz_msgs and JavaGazebo. See sub-directories for more information.
The integration test directories for C++ and Java contain test code that runs on our test-system. When you submit code for review, it is tested by those programs. If you add new functionality you should make sure to write tests for it so we don't break it in the future.
The hal directory contains more C++ code meant to run on the roboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the ni-libraries folder.
The [styleguide repository](https://github.com/wpilibsuite/styleguide) contains our style guides for C++ and Java code. Anything submitted to the WPILib project needs to follow the code style guides outlined in there. For details about the style, please see the contributors document [here](CONTRIBUTING.md#coding-guidelines).
# Contributing to WPILib
See [CONTRIBUTING.md](CONTRIBUTING.md).

View File

@@ -1,858 +0,0 @@
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with WPILib
==============================================================================
The WPILib software contains code written by third parties. The copyrights,
license, and restrictions which apply to each piece of software is included
later in this file and/or inside of the individual applicable source files.
The disclaimer of warranty in the WPILib license above applies to all code in
WPILib, and nothing in any of the other licenses gives permission to use the
names of FIRST nor the names of the WPILib contributors to endorse or promote
products derived from this software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Locations
------- ---------
RoboRIO Libraries ni-libraries
Google Test gtest
LLVM wpiutil/src/main/native/include/wpi/{various files}
wpiutil/src/main/native/cpp/llvm/
wpiutil/src/main/native/cpp/leb128.cpp
wpiutil/src/test/native/cpp/leb128Test.cpp
JSON for Modern C++ wpiutil/src/main/native/include/wpi/json.h
wpiutil/src/main/native/cpp/json_*.cpp
wpiutil/src/test/native/cpp/json/
libuv wpiutil/src/main/native/include/uv.h
wpiutil/src/main/native/include/uv/
wpiutil/src/main/native/libuv/
sigslot wpiutil/src/main/native/include/wpi/Signal.h
wpiutil/src/test/native/cpp/sigslot/
tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}.cpp
wpiutil/src/main/native/include/wpi/TCP*.h
Bootstrap wpiutil/src/main/native/resources/bootstrap-*
CoreUI wpiutil/src/main/native/resources/coreui-*
Feather Icons wpiutil/src/main/native/resources/feather-*
jQuery wpiutil/src/main/native/resources/jquery-*
popper.js wpiutil/src/main/native/resources/popper-*
units wpimath/src/main/native/include/units/
Eigen wpimath/src/main/native/eigeninclude/
wpimath/src/main/native/include/unsupported/
StackWalker wpiutil/src/main/native/windows/StackWalker.*
Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineParameterizer.java
wpilibj/src/main/java/edu/wpi/first/wpilibj/trajectory/TrajectoryParameterizer.java
wpilibc/src/main/native/include/spline/SplineParameterizer.h
wpilibc/src/main/native/include/trajectory/TrajectoryParameterizer.h
wpilibc/src/main/native/cpp/trajectory/TrajectoryParameterizer.cpp
Portable File Dialogs wpigui/src/main/native/include/portable-file-dialogs.h
Drake wpimath/src/main/native/cpp/drake/common/drake_assert_and_throw.cpp
wpimath/src/main/native/cpp/drake/math/discrete_algebraic_riccati_equation.cpp
==============================================================================
Google Test License
==============================================================================
Copyright 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
JSON for Modern C++ License
==============================================================================
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
| | |__ | | | | | | version 2.1.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================
libuv License
==============================================================================
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
==============================================================================
sigslot License
==============================================================================
Sigslot, a signal-slot library
https://github.com/palacaze/sigslot
MIT License
Copyright (c) 2017 Pierre-Antoine Lacaze
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================
tcpsockets License
==============================================================================
Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
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.
==============================================================================
Bootstrap License
==============================================================================
Copyright (c) 2011-2018 Twitter, Inc.
Copyright (c) 2011-2018 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
==============================================================================
CoreUI License
==============================================================================
Copyright (c) 2018 creativeLabs tukasz Holeczek.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
==============================================================================
Feather Icons License
==============================================================================
Copyright (c) 2013-2017 Cole Bemis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================
jQuery License
==============================================================================
Copyright JS Foundation and other contributors, https://js.foundation/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
==============================================================================
popper.js License
==============================================================================
Copyright (c) 2016 Federico Zivolo and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=============
units License
=============
The MIT License (MIT)
Copyright (c) 2016 Nic Holthaus
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=============
Eigen license
=============
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
===================
StackWalker License
===================
Copyright (c) 2005-2013, Jochen Kalmbach
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Neither the name of Jochen Kalmbach nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================
Team 254 Library
================
MIT License
Copyright (c) 2018 Team 254
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=============
Drake Library
=============
All components of Drake are licensed under the BSD 3-Clause License
shown below. Where noted in the source code, some portions may
be subject to other permissive, non-viral licenses.
Copyright 2012-2016 Robot Locomotion Group @ CSAIL
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution. Neither the name of
the Massachusetts Institute of Technology nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=====================
Portable File Dialogs
=====================
Copyright © 2018—2020 Sam Hocevar <sam@hocevar.net>
This library is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What the **** You Want
to Public License, Version 2, as published by the WTFPL Task Force.
See http://www.wtfpl.net/ for more details.

10
arm-toolchain.cmake Normal file
View File

@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 2.8)
INCLUDE(CMakeForceCompiler)
set(ARM_PREFIX arm-none-linux-gnueabi)
set(CMAKE_SYSTEM_NAME Linux)
CMAKE_FORCE_CXX_COMPILER(${ARM_PREFIX}-g++ GNU)
CMAKE_FORCE_C_COMPILER(${ARM_PREFIX}-gcc GNU)
set(CMAKE_CXX_FLAGS "-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -Wall -Wno-psabi" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g" CACHE STRING "" FORCE) # still want debugging for release?
SET(CMAKE_FIND_ROOT_PATH $ENV{USER_HOME}/wpilib/toolchains/arm-none-linux-gnueabi-4.4.1/arm-none-linux-gnueabi/libc)

View File

@@ -1,91 +0,0 @@
# Testing steps for real hardware
trigger:
batch: true
branches:
include:
- master
stages:
- stage: Build
jobs:
- job: IntegrationTests
displayName: Integration Tests
pool:
vmImage: "Ubuntu 16.04"
container:
image: wpilib/roborio-cross-ubuntu:2021-18.04
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ""
gradleWrapperFile: "gradlew"
gradleOptions: "-Xmx3072m"
publishJUnitResults: false
testResultsFiles: "**/TEST-*.xml"
tasks: "copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput"
options: "-Ponlylinuxathena -PbuildServer"
- task: PublishPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- stage: TestBench
displayName: Test Bench
jobs:
- job: Cpp
displayName: C++
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- task: ShellScript@2
displayName: Run C++ Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
- task: PublishTestResults@2
displayName: Publish C++ Test Results
inputs:
testResultsFormat: "JUnit"
testResultsFiles: "*.xml"
testRunTitle: "C++ Test Report"
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"
- job: Java
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- task: ShellScript@2
displayName: Run Java Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: "java"
- task: PublishTestResults@2
displayName: Publish Java Test Results
inputs:
testResultsFormat: "JUnit"
testResultsFiles: "*.xml"
testRunTitle: "Java Test Report"
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"

View File

@@ -1,177 +0,0 @@
import edu.wpi.first.toolchain.*
plugins {
id 'base'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.1.0'
id 'edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin' version '2020.2'
id 'edu.wpi.first.NativeUtils' apply false
id 'edu.wpi.first.GradleJni' version '0.10.1'
id 'edu.wpi.first.GradleVsCode' version '0.11.0'
id 'idea'
id 'visual-studio'
id 'net.ltgt.errorprone' version '1.1.1' apply false
id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
id 'com.diffplug.spotless' version '5.5.0'
}
wpilibVersioning.buildServerMode = project.hasProperty('buildServer')
wpilibVersioning.releaseMode = project.hasProperty('releaseMode')
allprojects {
repositories {
mavenCentral()
}
if (project.hasProperty('releaseMode')) {
wpilibRepositories.addAllReleaseRepositories(it)
} else {
wpilibRepositories.addAllDevelopmentRepositories(it)
}
}
buildScan {
termsOfServiceUrl = 'https://gradle.com/terms-of-service'
termsOfServiceAgree = 'yes'
publishAlways()
}
ext.licenseFile = files("$rootDir/LICENSE.md", "$rootDir/ThirdPartyNotices.txt")
if (project.hasProperty("publishVersion")) {
wpilibVersioning.version.set(project.publishVersion)
}
wpilibVersioning.version.finalizeValue()
def outputsFolder = file("$buildDir/allOutputs")
def versionFile = file("$outputsFolder/version.txt")
task outputVersions() {
description = 'Prints the versions of wpilib to a file for use by the downstream packaging project'
group = 'Build'
outputs.files(versionFile)
doFirst {
buildDir.mkdir()
outputsFolder.mkdir()
}
doLast {
versionFile.write wpilibVersioning.version.get()
}
}
task libraryBuild() {}
build.dependsOn outputVersions
task copyAllOutputs(type: Copy) {
destinationDir outputsFolder
}
build.dependsOn copyAllOutputs
copyAllOutputs.dependsOn outputVersions
ext.addTaskToCopyAllOutputs = { task ->
copyAllOutputs.dependsOn task
copyAllOutputs.inputs.file task.archivePath
copyAllOutputs.from task.archivePath
}
subprojects {
apply plugin: 'eclipse'
apply plugin: 'idea'
def subproj = it
plugins.withType(NativeComponentPlugin) {
subproj.apply plugin: MultiBuilds
}
apply from: "${rootDir}/shared/java/javastyle.gradle"
// Disables doclint in java 8.
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
if (project.name != "docs") {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
}
// Sign outputs with Developer ID
if (project.hasProperty("developerID")) {
tasks.withType(AbstractLinkTask) { task ->
// Don't sign any executables because codesign complains
// about relative rpath.
if (!(task instanceof LinkExecutable)) {
doLast {
// Get path to binary.
String path = task.getLinkedFile().getAsFile().get().getAbsolutePath()
exec {
workingDir rootDir
def args = [
"sh",
"-c",
"codesign --force --strict --timestamp --options=runtime " +
"--verbose -s ${project.findProperty("developerID")} ${path}"
]
commandLine args
}
}
}
}
}
}
ext.getCurrentArch = {
return NativePlatforms.desktop
}
spotless {
java {
target fileTree('.') {
include '**/*.java'
exclude '**/build/**', '**/build-*/**'
}
toggleOffOn()
googleJavaFormat()
removeUnusedImports()
trimTrailingWhitespace()
endWithNewline()
}
groovyGradle {
target fileTree('.') {
include '**/*.gradle'
exclude '**/build/**', '**/build-*/**'
}
greclipse()
indentWithSpaces(4)
trimTrailingWhitespace()
endWithNewline()
}
format 'xml', {
target fileTree('.') {
include '**/*.xml'
exclude '**/build/**', '**/build-*/**'
}
eclipseWtp('xml')
trimTrailingWhitespace()
indentWithSpaces(2)
endWithNewline()
}
format 'misc', {
target fileTree('.') {
include '**/*.md', '**/.gitignore'
exclude '**/build/**', '**/build-*/**'
}
trimTrailingWhitespace()
indentWithSpaces(2)
endWithNewline()
}
}
wrapper {
gradleVersion = '6.0.1'
}

View File

@@ -1,9 +0,0 @@
repositories {
maven {
url "https://plugins.gradle.org/m2/"
mavenLocal()
}
}
dependencies {
implementation "edu.wpi.first:native-utils:2021.1.1"
}

View File

@@ -1,70 +0,0 @@
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import edu.wpi.first.toolchain.ToolchainExtension
import org.gradle.model.Mutate;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.NativeExecutableBinarySpec
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import groovy.transform.CompileDynamic
import org.gradle.nativeplatform.BuildTypeContainer
@CompileStatic
class DisableBuildingGTest implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@CompileDynamic
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
binary.buildable = false
}
@Validate
@CompileStatic
// TODO: Move this to tc plugin
void disableCrossTests(BinaryContainer binaries, ExtensionContainer extContainer) {
final ToolchainExtension ext = extContainer.getByType(ToolchainExtension.class);
for (GoogleTestTestSuiteBinarySpec binary : binaries.withType(GoogleTestTestSuiteBinarySpec.class)) {
if (ext.getCrossCompilers().findByName(binary.getTargetPlatform().getName()) != null) {
setBuildableFalseDynamically(binary)
}
}
}
}
}

View File

@@ -1,88 +0,0 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import org.gradle.model.Mutate;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.test.tasks.RunTestExecutable;
import org.gradle.platform.base.BinaryContainer;
import groovy.transform.CompileStatic;
@CompileStatic
class ExtraTasks implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@Mutate
@CompileStatic
void createNativeCompileTask(ModelMap<Task> tasks, BinaryContainer binaries) {
tasks.create('compileCpp', Task) { oTask ->
def task = (Task) oTask
task.group = 'build'
task.description = 'Uber task to compile all native code for this project'
binaries.each { binary ->
if (binary instanceof NativeBinarySpec && binary.buildable) {
binary.tasks.withType(AbstractNativeSourceCompileTask) { compileTask ->
task.dependsOn compileTask
}
}
}
}
}
@Mutate
@CompileStatic
void createNativeTestTask(ModelMap<Task> tasks, BinaryContainer binaries) {
tasks.create('testCpp', Task) { oTask ->
def task = (Task) oTask
task.group = 'build'
task.description = 'Uber task to run all native tests for project'
binaries.each { binary ->
if (binary instanceof GoogleTestTestSuiteBinarySpec && binary.buildable) {
binary.tasks.withType(RunTestExecutable) { testTask ->
task.dependsOn testTask
}
}
}
}
}
}
}

View File

@@ -1,48 +0,0 @@
import groovy.transform.CompileStatic
import javax.inject.Inject
import jaci.gradle.deploy.artifact.MavenArtifact
import jaci.gradle.deploy.context.DeployContext
import org.gradle.api.Project
import jaci.gradle.ActionWrapper
import java.util.function.Function
@CompileStatic
class JREArtifact extends MavenArtifact {
Function<DeployContext, Boolean> buildRequiresJre = (Function<DeployContext, Boolean>){ true }
void setJreDependency(String dep) {
dependency = project.dependencies.add(configuration(), dep)
}
@Inject
JREArtifact(String name, Project project) {
super(name, project)
configuration = project.configurations.create(configuration())
onlyIf = { DeployContext ctx ->
(buildRequiresJre.apply(ctx) && jreMissing(ctx)) || project.hasProperty("force-redeploy-jre")
}
predeploy << new ActionWrapper({ DeployContext ctx ->
ctx.logger.log('Deploying RoboRIO JRE (this will take a while)...')
})
directory = '/tmp'
filename = 'frcjre.ipk'
postdeploy << new ActionWrapper({ DeployContext ctx ->
ctx.logger.log('Installing JRE...')
ctx.execute('opkg remove frc2020-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk')
ctx.logger.log('JRE Deployed!')
})
}
String configuration() {
return name + 'frcjre'
}
boolean jreMissing(DeployContext ctx) {
return ctx.execute('if [[ -f "/usr/local/frc/JRE/bin/java" ]]; then echo OK; else echo MISSING; fi').result.contains("MISSING")
}
}

View File

@@ -1,74 +0,0 @@
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import edu.wpi.first.toolchain.ToolchainExtension
import org.gradle.model.Mutate;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
import org.gradle.nativeplatform.NativeExecutableBinarySpec
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import groovy.transform.CompileDynamic
import org.gradle.nativeplatform.BuildTypeContainer
@CompileStatic
class MultiBuilds implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@CompileDynamic
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
binary.buildable = false
}
@Mutate
@CompileStatic
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
def project = (Project) projectLayout.projectIdentifier
if (project.hasProperty('testRelease')) {
return
}
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
if (spec.buildType.name == 'release') {
Rules.setBuildableFalseDynamically(spec)
}
}
}
}
}

View File

@@ -1,172 +0,0 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.tasks.Delete
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.Copy;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import org.gradle.model.Mutate;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.nativeplatform.tasks.CreateStaticLibrary;
import org.gradle.nativeplatform.tasks.AbstractLinkTask;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import edu.wpi.first.nativeutils.tasks.ExportsGenerationTask
@CompileStatic
class SingleNativeBuild implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@Mutate
@CompileStatic
void removeMacSystemIncludes(ModelMap<Task> tasks, BinaryContainer binaries) {
binaries.each {
if (!(it instanceof NativeBinarySpec)) {
return
}
NativeBinarySpec nativeBin = (NativeBinarySpec)it
if (nativeBin.targetPlatform.operatingSystem.isMacOsX()) {
nativeBin.tasks.withType(AbstractNativeSourceCompileTask) { AbstractNativeSourceCompileTask compileTask->
compileTask.getSystemIncludes().setFrom()
}
}
}
}
@Mutate
@CompileStatic
void setupSingleNativeBuild(ModelMap<Task> tasks, ComponentSpecContainer components, BinaryContainer binaryContainer, ProjectLayout projectLayout) {
Project project = (Project) projectLayout.projectIdentifier;
def nativeName = project.extensions.extraProperties.get('nativeName')
NativeLibrarySpec base = null
def subs = []
components.each { component ->
if (component.name == "${nativeName}Base") {
base = (NativeLibrarySpec) component
} else if (component.name == "${nativeName}" || component.name == "${nativeName}JNI" || component.name == "${nativeName}JNICvStatic") {
subs << component
}
}
Delete deleteObjects = null
if (project.hasProperty('buildServer')) {
deleteObjects = project.tasks.create('deleteObjects', Delete)
project.tasks.named('build').configure { Task t ->
t.dependsOn deleteObjects
return
}
}
subs.each {
((NativeLibrarySpec) it).binaries.each { oBinary ->
if (oBinary.buildable == false) {
return
}
NativeBinarySpec binary = (NativeBinarySpec) oBinary
NativeBinarySpec baseBin = null
base.binaries.each { oTmpBaseBin ->
if (oTmpBaseBin.buildable == false) {
return
}
def tmpBaseBin = (NativeBinarySpec) oTmpBaseBin
if (tmpBaseBin.targetPlatform.name == binary.targetPlatform.name &&
tmpBaseBin.buildType == binary.buildType) {
baseBin = tmpBaseBin
}
}
if (binary instanceof StaticLibraryBinarySpec) {
File intoDir = ((CreateStaticLibrary)((StaticLibraryBinarySpec)binary).tasks.createStaticLib).outputFile.get().asFile.parentFile
File fromDir = ((CreateStaticLibrary)((StaticLibraryBinarySpec)baseBin).tasks.createStaticLib).outputFile.get().asFile.parentFile
def copyBasePdbName = "copyBasePdbFor" + binary.buildTask.name
def copyTask = project.tasks.register(copyBasePdbName, Copy) { Copy t ->
t.from (fromDir)
t.include '*.pdb'
t.into intoDir
t.dependsOn (((StaticLibraryBinarySpec)baseBin).tasks.createStaticLib)
}
((CreateStaticLibrary)((StaticLibraryBinarySpec)binary).tasks.createStaticLib).dependsOn(copyTask)
}
baseBin.tasks.withType(AbstractNativeSourceCompileTask) { oCompileTask ->
def compileTask = (AbstractNativeSourceCompileTask) oCompileTask
if (binary instanceof SharedLibraryBinarySpec) {
def sBinary = (SharedLibraryBinarySpec) binary
ObjectFilesToBinary link = (ObjectFilesToBinary) sBinary.tasks.link
ExportsGenerationTask exportsTask = binary.tasks.withType(ExportsGenerationTask)[0]
if (exportsTask != null) {
exportsTask.dependsOn compileTask
}
link.dependsOn compileTask
link.inputs.dir compileTask.objectFileDir
def tree = project.fileTree(compileTask.objectFileDir)
tree.include '**/*.o'
tree.include '**/*.obj'
link.source tree
if (project.hasProperty('buildServer')) {
deleteObjects.dependsOn link
deleteObjects.delete tree
}
} else if (binary instanceof StaticLibraryBinarySpec) {
def sBinary = (StaticLibraryBinarySpec) binary
ObjectFilesToBinary assemble = (ObjectFilesToBinary) sBinary.tasks.createStaticLib
assemble.dependsOn compileTask
assemble.inputs.dir compileTask.objectFileDir
def tree = project.fileTree(compileTask.objectFileDir)
tree.include '**/*.o'
tree.include '**/*.obj'
assemble.source tree
if (project.hasProperty('buildServer')) {
deleteObjects.dependsOn assemble
deleteObjects.delete tree
}
}
}
}
}
}
}
}

View File

@@ -1,24 +0,0 @@
cppHeaderFileInclude {
\.h$
\.inc$
}
cppSrcFileInclude {
\.cpp$
}
repoRootNameOverride {
cameraserver
}
includeOtherLibs {
^hal/
^networktables/
^opencv2/
^support/
^wpi/
}
includeGuardRoots {
cameraserver/src/main/native/include/
}

View File

@@ -1,70 +0,0 @@
project(cameraserver)
include(CompileWarnings)
include(AddTest)
find_package( OpenCV REQUIRED )
# Java bindings
if (WITH_JAVA)
find_package(Java REQUIRED)
include(UseJava)
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
#find java files, copy them locally
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)
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")
endif()
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>)
wpilib_target_warnings(cameraserver)
target_link_libraries(cameraserver PUBLIC ntcore cscore wpiutil ${OpenCV_LIBS})
set_property(TARGET cameraserver PROPERTY FOLDER "libraries")
install(TARGETS cameraserver EXPORT cameraserver DESTINATION "${main_lib_dest}")
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cameraserver")
if (WITH_JAVA AND MSVC)
install(TARGETS cameraserver RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
endif()
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})
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)
add_executable(multiCameraServer ${multiCameraServer_src})
wpilib_target_warnings(multiCameraServer)
target_link_libraries(multiCameraServer cameraserver)
set_property(TARGET multiCameraServer PROPERTY FOLDER "examples")
if (WITH_TESTS)
wpilib_add_test(cameraserver src/test/native/cpp)
target_link_libraries(cameraserver_test cameraserver gtest)
endif()

View File

@@ -1,95 +0,0 @@
ext {
nativeName = 'cameraserver'
devMain = 'edu.wpi.first.cameraserver.DevMain'
}
evaluationDependsOn(':ntcore')
evaluationDependsOn(':cscore')
evaluationDependsOn(':hal')
apply from: "${rootDir}/shared/javacpp/setupBuild.gradle"
dependencies {
implementation project(':wpiutil')
implementation project(':ntcore')
implementation project(':cscore')
devImplementation project(':wpiutil')
devImplementation project(':ntcore')
devImplementation project(':cscore')
}
ext {
sharedCvConfigs = [cameraserver : [],
cameraserverBase: [],
cameraserverDev : [],
cameraserverTest: []]
staticCvConfigs = [:]
useJava = true
useCpp = true
}
apply from: "${rootDir}/shared/opencv.gradle"
nativeUtils.exportsConfigs {
cameraserver {
x86ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
x64ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
}
}
model {
components {}
binaries {
all {
if (!it.buildable || !(it instanceof NativeBinarySpec)) {
return
}
lib project: ':ntcore', library: 'ntcore', linkage: 'shared'
lib project: ':cscore', library: 'cscore', linkage: 'shared'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
}
}
tasks {
def c = $.components
def found = false
def systemArch = getCurrentArch()
c.each {
if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") {
it.binaries.each {
if (!found) {
def arch = it.targetPlatform.name
if (arch == systemArch) {
def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'
found = true
}
}
}
}
}
}
}

View File

@@ -1,9 +0,0 @@
include(CMakeFindDependencyMacro)
@FILENAME_DEP_REPLACE@
@WPIUTIL_DEP_REPLACE@
@NTCORE_DEP_REPLACE@
@CSCORE_DEP_REPLACE@
find_dependency(OpenCV)
@FILENAME_DEP_REPLACE@
include(${SELF_DIR}/cameraserver.cmake)

View File

@@ -1,62 +0,0 @@
plugins {
id 'java'
id 'application'
id 'cpp'
id 'visual-studio'
}
apply plugin: 'edu.wpi.first.NativeUtils'
apply from: "${rootDir}/shared/config.gradle"
ext {
staticCvConfigs = [multiCameraServerCpp: []]
useJava = true
useCpp = true
skipDev = true
}
apply from: "${rootDir}/shared/opencv.gradle"
mainClassName = 'edu.wpi.Main'
apply plugin: 'com.github.johnrengelman.shadow'
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
implementation project(':wpiutil')
implementation project(':ntcore')
implementation project(':cscore')
implementation project(':cameraserver')
}
model {
components {
multiCameraServerCpp(NativeExecutableSpec) {
targetBuildTypes 'release'
sources {
cpp {
source {
srcDirs = ['src/main/native/cpp']
includes = ['**/*.cpp']
}
exportedHeaders {
srcDirs = ['src/main/native/include']
includes = ['**/*.h']
}
}
}
binaries.all { binary ->
lib project: ':cameraserver', library: 'cameraserver', linkage: 'static'
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
lib project: ':cscore', library: 'cscore', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
}
}
}
}

View File

@@ -1,196 +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;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cameraserver.CameraServer;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/*
JSON format:
{
"team": <team number>,
"ntmode": <"client" or "server", "client" if unspecified>
"cameras": [
{
"name": <camera name>
"path": <path, e.g. "/dev/video0">
"pixel format": <"MJPEG", "YUYV", etc> // optional
"width": <video mode width> // optional
"height": <video mode height> // optional
"fps": <video mode fps> // optional
"brightness": <percentage brightness> // optional
"white balance": <"auto", "hold", value> // optional
"exposure": <"auto", "hold", value> // optional
"properties": [ // optional
{
"name": <property name>
"value": <property value>
}
]
}
]
}
*/
public final class Main {
private static String configFile = "/boot/frc.json";
@SuppressWarnings("MemberName")
public static class CameraConfig {
public String name;
public String path;
public JsonObject config;
}
public static int team;
public static boolean server;
public static List<CameraConfig> cameras = new ArrayList<>();
private Main() {}
/** Report parse error. */
public static void parseError(String str) {
System.err.println("config error in '" + configFile + "': " + str);
}
/** Read single camera configuration. */
public static boolean readCameraConfig(JsonObject config) {
CameraConfig cam = new CameraConfig();
// name
JsonElement nameElement = config.get("name");
if (nameElement == null) {
parseError("could not read camera name");
return false;
}
cam.name = nameElement.getAsString();
// path
JsonElement pathElement = config.get("path");
if (pathElement == null) {
parseError("camera '" + cam.name + "': could not read path");
return false;
}
cam.path = pathElement.getAsString();
cam.config = config;
cameras.add(cam);
return true;
}
/** Read configuration file. */
@SuppressWarnings("PMD.CyclomaticComplexity")
public static boolean readConfig() {
// parse file
JsonElement top;
try {
top = new JsonParser().parse(Files.newBufferedReader(Paths.get(configFile)));
} catch (IOException ex) {
System.err.println("could not open '" + configFile + "': " + ex);
return false;
}
// top level must be an object
if (!top.isJsonObject()) {
parseError("must be JSON object");
return false;
}
JsonObject obj = top.getAsJsonObject();
// team number
JsonElement teamElement = obj.get("team");
if (teamElement == null) {
parseError("could not read team number");
return false;
}
team = teamElement.getAsInt();
// ntmode (optional)
if (obj.has("ntmode")) {
String str = obj.get("ntmode").getAsString();
if ("client".equalsIgnoreCase(str)) {
server = false;
} else if ("server".equalsIgnoreCase(str)) {
server = true;
} else {
parseError("could not understand ntmode value '" + str + "'");
}
}
// cameras
JsonElement camerasElement = obj.get("cameras");
if (camerasElement == null) {
parseError("could not read cameras");
return false;
}
JsonArray cameras = camerasElement.getAsJsonArray();
for (JsonElement camera : cameras) {
if (!readCameraConfig(camera.getAsJsonObject())) {
return false;
}
}
return true;
}
/** Start running the camera. */
public static void startCamera(CameraConfig config) {
System.out.println("Starting camera '" + config.name + "' on " + config.path);
VideoSource camera = CameraServer.getInstance().startAutomaticCapture(config.name, config.path);
Gson gson = new GsonBuilder().create();
camera.setConfigJson(gson.toJson(config.config));
}
/** Main. */
public static void main(String... args) {
if (args.length > 0) {
configFile = args[0];
}
// read configuration
if (!readConfig()) {
return;
}
// start NetworkTables
NetworkTableInstance ntinst = NetworkTableInstance.getDefault();
if (server) {
System.out.println("Setting up NetworkTables server");
ntinst.startServer();
} else {
System.out.println("Setting up NetworkTables client for team " + team);
ntinst.startClientTeam(team);
}
// start cameras
for (CameraConfig camera : cameras) {
startCamera(camera);
}
// loop forever
for (; ; ) {
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
return;
}
}
}
}

View File

@@ -1,197 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <string>
#include <vector>
#include <networktables/NetworkTableInstance.h>
#include <wpi/StringRef.h>
#include <wpi/json.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
#include "cameraserver/CameraServer.h"
/*
JSON format:
{
"team": <team number>,
"ntmode": <"client" or "server", "client" if unspecified>
"cameras": [
{
"name": <camera name>
"path": <path, e.g. "/dev/video0">
"pixel format": <"MJPEG", "YUYV", etc> // optional
"width": <video mode width> // optional
"height": <video mode height> // optional
"fps": <video mode fps> // optional
"brightness": <percentage brightness> // optional
"white balance": <"auto", "hold", value> // optional
"exposure": <"auto", "hold", value> // optional
"properties": [ // optional
{
"name": <property name>
"value": <property value>
}
]
}
]
}
*/
#ifdef __RASPBIAN__
static const char* configFile = "/boot/frc.json";
#else
static const char* configFile = "frc.json";
#endif
namespace {
unsigned int team;
bool server = false;
struct CameraConfig {
std::string name;
std::string path;
wpi::json config;
};
std::vector<CameraConfig> cameras;
wpi::raw_ostream& ParseError() {
return wpi::errs() << "config error in '" << configFile << "': ";
}
bool ReadCameraConfig(const wpi::json& config) {
CameraConfig c;
// name
try {
c.name = config.at("name").get<std::string>();
} catch (const wpi::json::exception& e) {
ParseError() << "could not read camera name: " << e.what() << '\n';
return false;
}
// path
try {
c.path = config.at("path").get<std::string>();
} catch (const wpi::json::exception& e) {
ParseError() << "camera '" << c.name
<< "': could not read path: " << e.what() << '\n';
return false;
}
c.config = config;
cameras.emplace_back(std::move(c));
return true;
}
bool ReadConfig() {
// open config file
std::error_code ec;
wpi::raw_fd_istream is(configFile, ec);
if (ec) {
wpi::errs() << "could not open '" << configFile << "': " << ec.message()
<< '\n';
return false;
}
// parse file
wpi::json j;
try {
j = wpi::json::parse(is);
} catch (const wpi::json::parse_error& e) {
ParseError() << "byte " << e.byte << ": " << e.what() << '\n';
return false;
}
// top level must be an object
if (!j.is_object()) {
ParseError() << "must be JSON object\n";
return false;
}
// team number
try {
team = j.at("team").get<unsigned int>();
} catch (const wpi::json::exception& e) {
ParseError() << "could not read team number: " << e.what() << '\n';
return false;
}
// ntmode (optional)
if (j.count("ntmode") != 0) {
try {
auto str = j.at("ntmode").get<std::string>();
wpi::StringRef s(str);
if (s.equals_lower("client")) {
server = false;
} else if (s.equals_lower("server")) {
server = true;
} else {
ParseError() << "could not understand ntmode value '" << str << "'\n";
}
} catch (const wpi::json::exception& e) {
ParseError() << "could not read ntmode: " << e.what() << '\n';
}
}
// cameras
try {
for (auto&& camera : j.at("cameras")) {
if (!ReadCameraConfig(camera)) {
return false;
}
}
} catch (const wpi::json::exception& e) {
ParseError() << "could not read cameras: " << e.what() << '\n';
return false;
}
return true;
}
void StartCamera(const CameraConfig& config) {
wpi::outs() << "Starting camera '" << config.name << "' on " << config.path
<< '\n';
auto camera = frc::CameraServer::GetInstance()->StartAutomaticCapture(
config.name, config.path);
camera.SetConfigJson(config.config);
}
} // namespace
int main(int argc, char* argv[]) {
if (argc >= 2) {
configFile = argv[1];
}
// read configuration
if (!ReadConfig()) {
return EXIT_FAILURE;
}
// start NetworkTables
auto ntinst = nt::NetworkTableInstance::GetDefault();
if (server) {
wpi::outs() << "Setting up NetworkTables server\n";
ntinst.StartServer();
} else {
wpi::outs() << "Setting up NetworkTables client for team " << team << '\n';
ntinst.StartClientTeam(team);
}
// start cameras
for (auto&& camera : cameras) {
StartCamera(camera);
}
// loop forever
for (;;) {
std::this_thread::sleep_for(std::chrono::seconds(10));
}
}

View File

@@ -1,11 +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.cameraserver;
public final class DevMain {
public static void main(String[] args) {}
private DevMain() {}
}

View File

@@ -1,5 +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.
int main() {}

View File

@@ -1,836 +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.cameraserver;
import edu.wpi.cscore.AxisCamera;
import edu.wpi.cscore.CameraServerJNI;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.CvSource;
import edu.wpi.cscore.MjpegServer;
import edu.wpi.cscore.UsbCamera;
import edu.wpi.cscore.VideoEvent;
import edu.wpi.cscore.VideoException;
import edu.wpi.cscore.VideoListener;
import edu.wpi.cscore.VideoMode;
import edu.wpi.cscore.VideoMode.PixelFormat;
import edu.wpi.cscore.VideoProperty;
import edu.wpi.cscore.VideoSink;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Singleton class for creating and keeping camera servers. Also publishes camera information to
* NetworkTables.
*/
public final class CameraServer {
public static final int kBasePort = 1181;
@Deprecated public static final int kSize640x480 = 0;
@Deprecated public static final int kSize320x240 = 1;
@Deprecated public static final int kSize160x120 = 2;
private static final String kPublishName = "/CameraPublisher";
private static CameraServer server;
/** Get the CameraServer instance. */
public static synchronized CameraServer getInstance() {
if (server == null) {
server = new CameraServer();
}
return server;
}
private final AtomicInteger m_defaultUsbDevice;
private String m_primarySourceName;
private final Map<String, VideoSource> m_sources;
private final Map<String, VideoSink> m_sinks;
private final Map<Integer, NetworkTable> m_tables; // indexed by source handle
// source handle indexed by sink handle
private final Map<Integer, Integer> m_fixedSources;
private final NetworkTable m_publishTable;
private final VideoListener m_videoListener; // NOPMD
private final int m_tableListener; // NOPMD
private int m_nextPort;
private String[] m_addresses;
@SuppressWarnings("MissingJavadocMethod")
private static String makeSourceValue(int source) {
switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) {
case kUsb:
return "usb:" + CameraServerJNI.getUsbCameraPath(source);
case kHttp:
{
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
if (urls.length > 0) {
return "ip:" + urls[0];
} else {
return "ip:";
}
}
case kCv:
return "cv:";
default:
return "unknown:";
}
}
@SuppressWarnings("MissingJavadocMethod")
private static String makeStreamValue(String address, int port) {
return "mjpg:http://" + address + ":" + port + "/?action=stream";
}
@SuppressWarnings({"MissingJavadocMethod", "PMD.AvoidUsingHardCodedIP"})
private synchronized String[] getSinkStreamValues(int sink) {
// Ignore all but MjpegServer
if (VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink)) != VideoSink.Kind.kMjpeg) {
return new String[0];
}
// Get port
int port = CameraServerJNI.getMjpegServerPort(sink);
// Generate values
ArrayList<String> values = new ArrayList<>(m_addresses.length + 1);
String listenAddress = CameraServerJNI.getMjpegServerListenAddress(sink);
if (!listenAddress.isEmpty()) {
// If a listen address is specified, only use that
values.add(makeStreamValue(listenAddress, port));
} else {
// Otherwise generate for hostname and all interface addresses
values.add(makeStreamValue(CameraServerJNI.getHostname() + ".local", port));
for (String addr : m_addresses) {
if ("127.0.0.1".equals(addr)) {
continue; // ignore localhost
}
values.add(makeStreamValue(addr, port));
}
}
return values.toArray(new String[0]);
}
@SuppressWarnings({"MissingJavadocMethod", "PMD.AvoidUsingHardCodedIP"})
private synchronized String[] getSourceStreamValues(int source) {
// Ignore all but HttpCamera
if (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))
!= VideoSource.Kind.kHttp) {
return new String[0];
}
// Generate values
String[] values = CameraServerJNI.getHttpCameraUrls(source);
for (int j = 0; j < values.length; j++) {
values[j] = "mjpg:" + values[j];
}
if (CameraServerSharedStore.getCameraServerShared().isRoboRIO()) {
// Look to see if we have a passthrough server for this source
// Only do this on the roboRIO
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
int sinkSource = CameraServerJNI.getSinkSource(sink);
if (source == sinkSource
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
== VideoSink.Kind.kMjpeg) {
// Add USB-only passthrough
String[] finalValues = Arrays.copyOf(values, values.length + 1);
int port = CameraServerJNI.getMjpegServerPort(sink);
finalValues[values.length] = makeStreamValue("172.22.11.2", port);
return finalValues;
}
}
}
return values;
}
@SuppressWarnings({
"MissingJavadocMethod",
"PMD.AvoidUsingHardCodedIP",
"PMD.CyclomaticComplexity"
})
private synchronized void updateStreamValues() {
// Over all the sinks...
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
// Get the source's subtable (if none exists, we're done)
int source =
Objects.requireNonNullElseGet(
m_fixedSources.get(sink), () -> CameraServerJNI.getSinkSource(sink));
if (source == 0) {
continue;
}
NetworkTable table = m_tables.get(source);
if (table != null) {
// Don't set stream values if this is a HttpCamera passthrough
if (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))
== VideoSource.Kind.kHttp) {
continue;
}
// Set table value
String[] values = getSinkStreamValues(sink);
if (values.length > 0) {
table.getEntry("streams").setStringArray(values);
}
}
}
// Over all the sources...
for (VideoSource i : m_sources.values()) {
int source = i.getHandle();
// Get the source's subtable (if none exists, we're done)
NetworkTable table = m_tables.get(source);
if (table != null) {
// Set table value
String[] values = getSourceStreamValues(source);
if (values.length > 0) {
table.getEntry("streams").setStringArray(values);
}
}
}
}
@SuppressWarnings("MissingJavadocMethod")
private static String pixelFormatToString(PixelFormat pixelFormat) {
switch (pixelFormat) {
case kMJPEG:
return "MJPEG";
case kYUYV:
return "YUYV";
case kRGB565:
return "RGB565";
case kBGR:
return "BGR";
case kGray:
return "Gray";
default:
return "Unknown";
}
}
/// Provide string description of video mode.
/// The returned string is "{width}x{height} {format} {fps} fps".
@SuppressWarnings("MissingJavadocMethod")
private static String videoModeToString(VideoMode mode) {
return mode.width
+ "x"
+ mode.height
+ " "
+ pixelFormatToString(mode.pixelFormat)
+ " "
+ mode.fps
+ " fps";
}
@SuppressWarnings("MissingJavadocMethod")
private static String[] getSourceModeValues(int sourceHandle) {
VideoMode[] modes = CameraServerJNI.enumerateSourceVideoModes(sourceHandle);
String[] modeStrings = new String[modes.length];
for (int i = 0; i < modes.length; i++) {
modeStrings[i] = videoModeToString(modes[i]);
}
return modeStrings;
}
@SuppressWarnings({"MissingJavadocMethod", "PMD.CyclomaticComplexity"})
private static void putSourcePropertyValue(NetworkTable table, VideoEvent event, boolean isNew) {
String name;
String infoName;
if (event.name.startsWith("raw_")) {
name = "RawProperty/" + event.name;
infoName = "RawPropertyInfo/" + event.name;
} else {
name = "Property/" + event.name;
infoName = "PropertyInfo/" + event.name;
}
NetworkTableEntry entry = table.getEntry(name);
try {
switch (event.propertyKind) {
case kBoolean:
if (isNew) {
entry.setDefaultBoolean(event.value != 0);
} else {
entry.setBoolean(event.value != 0);
}
break;
case kInteger:
case kEnum:
if (isNew) {
entry.setDefaultDouble(event.value);
table
.getEntry(infoName + "/min")
.setDouble(CameraServerJNI.getPropertyMin(event.propertyHandle));
table
.getEntry(infoName + "/max")
.setDouble(CameraServerJNI.getPropertyMax(event.propertyHandle));
table
.getEntry(infoName + "/step")
.setDouble(CameraServerJNI.getPropertyStep(event.propertyHandle));
table
.getEntry(infoName + "/default")
.setDouble(CameraServerJNI.getPropertyDefault(event.propertyHandle));
} else {
entry.setDouble(event.value);
}
break;
case kString:
if (isNew) {
entry.setDefaultString(event.valueStr);
} else {
entry.setString(event.valueStr);
}
break;
default:
break;
}
} catch (VideoException ignored) {
// ignore
}
}
@SuppressWarnings({
"MissingJavadocMethod",
"PMD.UnusedLocalVariable",
"PMD.ExcessiveMethodLength",
"PMD.NPathComplexity"
})
private CameraServer() {
m_defaultUsbDevice = new AtomicInteger();
m_sources = new HashMap<>();
m_sinks = new HashMap<>();
m_fixedSources = new HashMap<>();
m_tables = new HashMap<>();
m_publishTable = NetworkTableInstance.getDefault().getTable(kPublishName);
m_nextPort = kBasePort;
m_addresses = new String[0];
// We publish sources to NetworkTables using the following structure:
// "/CameraPublisher/{Source.Name}/" - root
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
// - "streams" (string array): URLs that can be used to stream data
// - "description" (string): Description of the source
// - "connected" (boolean): Whether source is connected
// - "mode" (string): Current video mode
// - "modes" (string array): Available video modes
// - "Property/{Property}" - Property values
// - "PropertyInfo/{Property}" - Property supporting information
// Listener for video events
m_videoListener =
new VideoListener(
event -> {
switch (event.kind) {
case kSourceCreated:
{
// Create subtable for the camera
NetworkTable table = m_publishTable.getSubTable(event.name);
m_tables.put(event.sourceHandle, table);
table.getEntry("source").setString(makeSourceValue(event.sourceHandle));
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table
.getEntry("connected")
.setBoolean(CameraServerJNI.isSourceConnected(event.sourceHandle));
table
.getEntry("streams")
.setStringArray(getSourceStreamValues(event.sourceHandle));
try {
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
table.getEntry("mode").setDefaultString(videoModeToString(mode));
table
.getEntry("modes")
.setStringArray(getSourceModeValues(event.sourceHandle));
} catch (VideoException ignored) {
// Do nothing. Let the other event handlers update this if there is an error.
}
break;
}
case kSourceDestroyed:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("source").setString("");
table.getEntry("streams").setStringArray(new String[0]);
table.getEntry("modes").setStringArray(new String[0]);
}
break;
}
case kSourceConnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
// update the description too (as it may have changed)
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(true);
}
break;
}
case kSourceDisconnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("connected").setBoolean(false);
}
break;
}
case kSourceVideoModesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table
.getEntry("modes")
.setStringArray(getSourceModeValues(event.sourceHandle));
}
break;
}
case kSourceVideoModeChanged:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("mode").setString(videoModeToString(event.mode));
}
break;
}
case kSourcePropertyCreated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, true);
}
break;
}
case kSourcePropertyValueUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, false);
}
break;
}
case kSourcePropertyChoicesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
try {
String[] choices =
CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
table
.getEntry("PropertyInfo/" + event.name + "/choices")
.setStringArray(choices);
} catch (VideoException ignored) {
// ignore
}
}
break;
}
case kSinkSourceChanged:
case kSinkCreated:
case kSinkDestroyed:
case kNetworkInterfacesChanged:
{
m_addresses = CameraServerJNI.getNetworkInterfaces();
updateStreamValues();
break;
}
default:
break;
}
},
0x4fff,
true);
// Listener for NetworkTable events
// We don't currently support changing settings via NT due to
// synchronization issues, so just update to current setting if someone
// else tries to change it.
m_tableListener =
NetworkTableInstance.getDefault()
.addEntryListener(
kPublishName + "/",
event -> {
String relativeKey = event.name.substring(kPublishName.length() + 1);
// get source (sourceName/...)
int subKeyIndex = relativeKey.indexOf('/');
if (subKeyIndex == -1) {
return;
}
String sourceName = relativeKey.substring(0, subKeyIndex);
VideoSource source = m_sources.get(sourceName);
if (source == null) {
return;
}
// get subkey
relativeKey = relativeKey.substring(subKeyIndex + 1);
// handle standard names
String propName;
if ("mode".equals(relativeKey)) {
// reset to current mode
event.getEntry().setString(videoModeToString(source.getVideoMode()));
return;
} else if (relativeKey.startsWith("Property/")) {
propName = relativeKey.substring(9);
} else if (relativeKey.startsWith("RawProperty/")) {
propName = relativeKey.substring(12);
} else {
return; // ignore
}
// everything else is a property
VideoProperty property = source.getProperty(propName);
switch (property.getKind()) {
case kNone:
return;
case kBoolean:
// reset to current setting
event.getEntry().setBoolean(property.get() != 0);
return;
case kInteger:
case kEnum:
// reset to current setting
event.getEntry().setDouble(property.get());
return;
case kString:
// reset to current setting
event.getEntry().setString(property.getString());
return;
default:
return;
}
},
EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate);
}
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>You should call this method to see a camera feed on the dashboard. If you also want to
* perform vision processing on the roboRIO, use getVideo() to get access to the camera images.
*
* <p>The first time this overload is called, it calls {@link #startAutomaticCapture(int)} with
* device 0, creating a camera named "USB Camera 0". Subsequent calls increment the device number
* (e.g. 1, 2, etc).
*/
public UsbCamera startAutomaticCapture() {
UsbCamera camera = startAutomaticCapture(m_defaultUsbDevice.getAndIncrement());
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
return camera;
}
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>This overload calls {@link #startAutomaticCapture(String, int)} with a name of "USB Camera
* {dev}".
*
* @param dev The device number of the camera interface
*/
public UsbCamera startAutomaticCapture(int dev) {
UsbCamera camera = new UsbCamera("USB Camera " + dev, dev);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
return camera;
}
/**
* Start automatically capturing images to send to the dashboard.
*
* @param name The name to give the camera
* @param dev The device number of the camera interface
*/
public UsbCamera startAutomaticCapture(String name, int dev) {
UsbCamera camera = new UsbCamera(name, dev);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
return camera;
}
/**
* Start automatically capturing images to send to the dashboard.
*
* @param name The name to give the camera
* @param path The device path (e.g. "/dev/video0") of the camera
*/
public UsbCamera startAutomaticCapture(String name, String path) {
UsbCamera camera = new UsbCamera(name, path);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
return camera;
}
/**
* Start automatically capturing images to send to the dashboard from an existing camera.
*
* @param camera Camera
*/
public MjpegServer startAutomaticCapture(VideoSource camera) {
addCamera(camera);
MjpegServer server = addServer("serve_" + camera.getName());
server.setSource(camera);
return server;
}
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String)} with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
public AxisCamera addAxisCamera(String host) {
return addAxisCamera("Axis Camera", host);
}
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String[])} with name "Axis Camera".
*
* @param hosts Array of Camera host IPs/DNS names
*/
public AxisCamera addAxisCamera(String[] hosts) {
return addAxisCamera("Axis Camera", hosts);
}
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
public AxisCamera addAxisCamera(String name, String host) {
AxisCamera camera = new AxisCamera(name, host);
// Create a passthrough MJPEG server for USB access
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportAxisCamera(camera.getHandle());
return camera;
}
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param hosts Array of Camera host IPs/DNS names
*/
public AxisCamera addAxisCamera(String name, String[] hosts) {
AxisCamera camera = new AxisCamera(name, hosts);
// Create a passthrough MJPEG server for USB access
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportAxisCamera(camera.getHandle());
return camera;
}
/**
* Adds a virtual camera for switching between two streams. Unlike the other addCamera methods,
* this returns a VideoSink rather than a VideoSource. Calling setSource() on the returned object
* can be used to switch the actual source of the stream.
*/
public MjpegServer addSwitchedCamera(String name) {
// create a dummy CvSource
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
MjpegServer server = startAutomaticCapture(source);
synchronized (this) {
m_fixedSources.put(server.getHandle(), source.getHandle());
}
return server;
}
/**
* Get OpenCV access to the primary camera feed. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*/
public CvSink getVideo() {
VideoSource source;
synchronized (this) {
if (m_primarySourceName == null) {
throw new VideoException("no camera available");
}
source = m_sources.get(m_primarySourceName);
}
if (source == null) {
throw new VideoException("no camera available");
}
return getVideo(source);
}
/**
* 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).
*/
public CvSink getVideo(VideoSource camera) {
String name = "opencv_" + camera.getName();
synchronized (this) {
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);
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.
*
* @param name Camera name
*/
public CvSink getVideo(String name) {
VideoSource source;
synchronized (this) {
source = m_sources.get(name);
if (source == null) {
throw new VideoException("could not find camera " + name);
}
}
return getVideo(source);
}
/**
* Create a MJPEG stream with OpenCV input. This can be called to pass custom annotated images to
* the dashboard.
*
* @param name Name to give the stream
* @param width Width of the image being sent
* @param height Height of the image being sent
*/
public CvSource putVideo(String name, int width, int height) {
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, width, height, 30);
startAutomaticCapture(source);
return source;
}
/**
* Adds a MJPEG server at the next available port.
*
* @param name Server name
*/
public MjpegServer addServer(String name) {
int port;
synchronized (this) {
port = m_nextPort;
m_nextPort++;
}
return addServer(name, port);
}
/**
* Adds a MJPEG server.
*
* @param name Server name
*/
public MjpegServer addServer(String name, int port) {
MjpegServer server = new MjpegServer(name, port);
addServer(server);
return server;
}
/**
* Adds an already created server.
*
* @param server Server
*/
public void addServer(VideoSink server) {
synchronized (this) {
m_sinks.put(server.getName(), server);
}
}
/**
* Removes a server by name.
*
* @param name Server name
*/
public void removeServer(String name) {
synchronized (this) {
m_sinks.remove(name);
}
}
/**
* Get server for the primary camera feed.
*
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*/
public VideoSink getServer() {
synchronized (this) {
if (m_primarySourceName == null) {
throw new VideoException("no camera available");
}
return getServer("serve_" + m_primarySourceName);
}
}
/**
* Gets a server by name.
*
* @param name Server name
*/
public VideoSink getServer(String name) {
synchronized (this) {
return m_sinks.get(name);
}
}
/**
* Adds an already created camera.
*
* @param camera Camera
*/
public void addCamera(VideoSource camera) {
String name = camera.getName();
synchronized (this) {
if (m_primarySourceName == null) {
m_primarySourceName = name;
}
m_sources.put(name, camera);
}
}
/**
* Removes a camera by name.
*
* @param name Camera name
*/
public void removeCamera(String name) {
synchronized (this) {
m_sources.remove(name);
}
}
}

View File

@@ -1,51 +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.cameraserver;
public interface CameraServerShared {
/**
* get the main thread id func.
*
* @return the robotMainThreadId
*/
Long getRobotMainThreadId();
/**
* Report an error to the driver station.
*
* @param error the error to set
*/
void reportDriverStationError(String error);
/**
* Report an video server usage.
*
* @param id the usage id
*/
void reportVideoServer(int id);
/**
* Report a usb camera usage.
*
* @param id the usage id
*/
void reportUsbCamera(int id);
/**
* Report an axis camera usage.
*
* @param id the usage id
*/
void reportAxisCamera(int id);
/**
* Get if running on a roboRIO.
*
* @return true if on roboRIO
*/
default boolean isRoboRIO() {
return false;
}
}

View File

@@ -1,43 +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.cameraserver;
public final class CameraServerSharedStore {
private static CameraServerShared cameraServerShared;
private CameraServerSharedStore() {}
/** get the CameraServerShared object. */
public static synchronized CameraServerShared getCameraServerShared() {
if (cameraServerShared == null) {
cameraServerShared =
new CameraServerShared() {
@Override
public void reportVideoServer(int id) {}
@Override
public void reportUsbCamera(int id) {}
@Override
public void reportDriverStationError(String error) {}
@Override
public void reportAxisCamera(int id) {}
@Override
public Long getRobotMainThreadId() {
return null;
}
};
}
return cameraServerShared;
}
/** set the CameraServerShared object. */
public static synchronized void setCameraServerShared(CameraServerShared shared) {
cameraServerShared = shared;
}
}

View File

@@ -1,22 +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.vision;
import org.opencv.core.Mat;
/**
* A vision pipeline is responsible for running a group of OpenCV algorithms to extract data from an
* image.
*
* @see VisionRunner
* @see VisionThread
*/
public interface VisionPipeline {
/**
* Processes the image input and sets the result objects. Implementations should make these
* objects accessible.
*/
void process(Mat image);
}

View File

@@ -1,121 +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.vision;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cameraserver.CameraServerSharedStore;
import org.opencv.core.Mat;
/**
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines from robot
* 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.
*
* @see VisionPipeline
* @see VisionThread
* @see <a href="package-summary.html">vision</a>
*/
public class VisionRunner<P extends VisionPipeline> {
private final CvSink m_cvSink = new CvSink("VisionRunner CvSink");
private final P m_pipeline;
private final Mat m_image = new Mat();
private final Listener<? super P> m_listener;
private volatile boolean m_enabled = true;
/**
* Listener interface for a callback that should run after a pipeline has processed its input.
*
* @param <P> the type of the pipeline this listener is for
*/
@FunctionalInterface
public interface Listener<P extends VisionPipeline> {
/**
* Called when the pipeline has run. This shouldn't take much time to run because it will delay
* later calls to the pipeline's {@link VisionPipeline#process process} method. Copying the
* outputs and code that uses the copies should be <i>synchronized</i> on the same mutex to
* prevent multiple threads from reading and writing to the same memory at the same time.
*
* @param pipeline the vision pipeline that ran
*/
void copyPipelineOutputs(P pipeline);
}
/**
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to the
* {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert user
* code when it is safe to access the pipeline's outputs.
*
* @param videoSource the video source to use to supply images for the pipeline
* @param pipeline the vision pipeline to run
* @param listener a function to call after the pipeline has finished running
*/
public VisionRunner(VideoSource videoSource, P pipeline, Listener<? super P> listener) {
this.m_pipeline = pipeline;
this.m_listener = listener;
m_cvSink.setSource(videoSource);
}
/**
* Runs the pipeline one time, giving it the next image from the video source specified in the
* constructor. This will block until the source either has an image or throws an error. If the
* source successfully supplied a frame, the pipeline's image input will be set, the pipeline will
* run, and the listener specified in the constructor will be called to notify it that the
* pipeline ran.
*
* <p>This method is exposed to allow teams to add additional functionality or have their own ways
* to run the pipeline. Most teams, however, should just use {@link #runForever} in its own thread
* using a {@link VisionThread}.
*/
public void runOnce() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
if (id != null && Thread.currentThread().getId() == id) {
throw new IllegalStateException(
"VisionRunner.runOnce() cannot be called from the main robot thread");
}
runOnceInternal();
}
private void runOnceInternal() {
long frameTime = m_cvSink.grabFrame(m_image);
if (frameTime == 0) {
// There was an error, report it
String error = m_cvSink.getError();
CameraServerSharedStore.getCameraServerShared().reportDriverStationError(error);
} else {
// No errors, process the image
m_pipeline.process(m_image);
m_listener.copyPipelineOutputs(m_pipeline);
}
}
/**
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must be run in a
* dedicated thread, and cannot be used in the main robot thread because it will freeze the robot
* program.
*
* <p><strong>Do not call this method directly from the main thread.</strong>
*
* @throws IllegalStateException if this is called from the main robot thread
* @see VisionThread
*/
public void runForever() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
if (id != null && Thread.currentThread().getId() == id) {
throw new IllegalStateException(
"VisionRunner.runForever() cannot be called from the main robot thread");
}
while (m_enabled && !Thread.interrupted()) {
runOnceInternal();
}
}
/** Stop a RunForever() loop. */
public void stop() {
m_enabled = false;
}
}

View File

@@ -1,42 +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.vision;
import edu.wpi.cscore.VideoSource;
/**
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread; it
* does not prevent the program from exiting when all other non-daemon threads have finished
* running.
*
* @see VisionPipeline
* @see VisionRunner
* @see Thread#setDaemon(boolean)
*/
public class VisionThread extends Thread {
/**
* Creates a vision thread that continuously runs a {@link VisionPipeline}.
*
* @param visionRunner the runner for a vision pipeline
*/
public VisionThread(VisionRunner<?> visionRunner) {
super(visionRunner::runForever, "WPILib Vision Thread");
setDaemon(true);
}
/**
* Creates a new vision thread that continuously runs the given vision pipeline. This is
* equivalent to {@code new VisionThread(new VisionRunner<>(videoSource, pipeline, listener))}.
*
* @param videoSource the source for images the pipeline should process
* @param pipeline the pipeline to run
* @param listener the listener to copy outputs from the pipeline after it runs
* @param <P> the type of the pipeline
*/
public <P extends VisionPipeline> VisionThread(
VideoSource videoSource, P pipeline, VisionRunner.Listener<? super P> listener) {
this(new VisionRunner<>(videoSource, pipeline, listener));
}
}

View File

@@ -1,85 +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.
/**
* Classes in the {@code edu.wpi.first.vision} package are designed to simplify using OpenCV vision
* processing code from a robot program.
*
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous: <br>
*
* <pre><code>
* public class Robot extends IterativeRobot
* implements VisionRunner.Listener&lt;MyFindTotePipeline&gt; {
*
* // A USB camera connected to the roboRIO.
* private {@link edu.wpi.cscore.VideoSource VideoSource} usbCamera;
*
* // A vision pipeline. This could be handwritten or generated by GRIP.
* // This has to implement {@link edu.wpi.first.vision.VisionPipeline}.
* // For this example, assume that it's perfect and will always see the tote.
* private MyFindTotePipeline findTotePipeline;
* private {@link edu.wpi.first.vision.VisionThread} findToteThread;
*
* // The object to synchronize on to make sure the vision thread doesn't
* // write to variables the main thread is using.
* private final Object visionLock = new Object();
*
* // The pipeline outputs we want
* private boolean pipelineRan = false; // lets us know when the pipeline has actually run
* private double angleToTote = 0;
* private double distanceToTote = 0;
*
* {@literal @}Override
* public void {@link edu.wpi.first.vision.VisionRunner.Listener#copyPipelineOutputs
* copyPipelineOutputs(MyFindTotePipeline pipeline)} {
* synchronized (visionLock) {
* // Take a snapshot of the pipeline's output because
* // it may have changed the next time this method is called!
* this.pipelineRan = true;
* this.angleToTote = pipeline.getAngleToTote();
* this.distanceToTote = pipeline.getDistanceToTote();
* }
* }
*
* {@literal @}Override
* public void robotInit() {
* usbCamera = CameraServer.getInstance().startAutomaticCapture(0);
* findTotePipeline = new MyFindTotePipeline();
* findToteThread = new VisionThread(usbCamera, findTotePipeline, this);
* }
*
* {@literal @}Override
* public void autonomousInit() {
* findToteThread.start();
* }
*
* {@literal @}Override
* public void autonomousPeriodic() {
* double angle;
* double distance;
* synchronized (visionLock) {
* if (!pipelineRan) {
* // Wait until the pipeline has run
* return;
* }
* // Copy the outputs to make sure they're all from the same run
* angle = this.angleToTote;
* distance = this.distanceToTote;
* }
* if (!aimedAtTote()) {
* turnToAngle(angle);
* } else if (!droveToTote()) {
* driveDistance(distance);
* } else if (!grabbedTote()) {
* grabTote();
* } else {
* // Tote was grabbed and we're done!
* return;
* }
* }
*
* }
* </code></pre>
*/
package edu.wpi.first.vision;

View File

@@ -1,751 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "cameraserver/CameraServer.h"
#include <atomic>
#include <vector>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/DenseMap.h>
#include <wpi/ManagedStatic.h>
#include <wpi/SmallString.h>
#include <wpi/StringMap.h>
#include <wpi/mutex.h>
#include <wpi/raw_ostream.h>
#include "cameraserver/CameraServerShared.h"
#include "ntcore_cpp.h"
using namespace frc;
static constexpr char const* kPublishName = "/CameraPublisher";
struct CameraServer::Impl {
Impl();
std::shared_ptr<nt::NetworkTable> GetSourceTable(CS_Source source);
std::vector<std::string> GetSinkStreamValues(CS_Sink sink);
std::vector<std::string> GetSourceStreamValues(CS_Source source);
void UpdateStreamValues();
wpi::mutex m_mutex;
std::atomic<int> m_defaultUsbDevice{0};
std::string m_primarySourceName;
wpi::StringMap<cs::VideoSource> m_sources;
wpi::StringMap<cs::VideoSink> m_sinks;
wpi::DenseMap<CS_Sink, CS_Source> m_fixedSources;
wpi::DenseMap<CS_Source, std::shared_ptr<nt::NetworkTable>> m_tables;
std::shared_ptr<nt::NetworkTable> m_publishTable{
nt::NetworkTableInstance::GetDefault().GetTable(kPublishName)};
cs::VideoListener m_videoListener;
int m_tableListener;
int m_nextPort;
std::vector<std::string> m_addresses;
};
CameraServer* CameraServer::GetInstance() {
struct Creator {
static void* call() { return new CameraServer{}; }
};
struct Deleter {
static void call(void* ptr) { delete static_cast<CameraServer*>(ptr); }
};
static wpi::ManagedStatic<CameraServer, Creator, Deleter> instance;
return &(*instance);
}
static wpi::StringRef MakeSourceValue(CS_Source source,
wpi::SmallVectorImpl<char>& buf) {
CS_Status status = 0;
buf.clear();
switch (cs::GetSourceKind(source, &status)) {
case CS_SOURCE_USB: {
wpi::StringRef prefix{"usb:"};
buf.append(prefix.begin(), prefix.end());
auto path = cs::GetUsbCameraPath(source, &status);
buf.append(path.begin(), path.end());
break;
}
case CS_SOURCE_HTTP: {
wpi::StringRef prefix{"ip:"};
buf.append(prefix.begin(), prefix.end());
auto urls = cs::GetHttpCameraUrls(source, &status);
if (!urls.empty()) {
buf.append(urls[0].begin(), urls[0].end());
}
break;
}
case CS_SOURCE_CV:
return "cv:";
default:
return "unknown:";
}
return wpi::StringRef{buf.begin(), buf.size()};
}
static std::string MakeStreamValue(const wpi::Twine& address, int port) {
return ("mjpg:http://" + address + wpi::Twine(':') + wpi::Twine(port) +
"/?action=stream")
.str();
}
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
CS_Source source) {
std::scoped_lock lock(m_mutex);
return m_tables.lookup(source);
}
std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
CS_Status status = 0;
// Ignore all but MjpegServer
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG) {
return {};
}
// Get port
int port = cs::GetMjpegServerPort(sink, &status);
// Generate values
std::vector<std::string> values;
auto listenAddress = cs::GetMjpegServerListenAddress(sink, &status);
if (!listenAddress.empty()) {
// If a listen address is specified, only use that
values.emplace_back(MakeStreamValue(listenAddress, port));
} else {
// Otherwise generate for hostname and all interface addresses
values.emplace_back(MakeStreamValue(cs::GetHostname() + ".local", port));
for (const auto& addr : m_addresses) {
if (addr == "127.0.0.1") {
continue; // ignore localhost
}
values.emplace_back(MakeStreamValue(addr, port));
}
}
return values;
}
std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
CS_Source source) {
CS_Status status = 0;
// Ignore all but HttpCamera
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP) {
return {};
}
// Generate values
auto values = cs::GetHttpCameraUrls(source, &status);
for (auto& value : values) {
value = "mjpg:" + value;
}
#ifdef __FRC_ROBORIO__
// Look to see if we have a passthrough server for this source
// Only do this on the roboRIO
for (const auto& i : m_sinks) {
CS_Sink sink = i.second.GetHandle();
CS_Source sinkSource = cs::GetSinkSource(sink, &status);
if (source == sinkSource &&
cs::GetSinkKind(sink, &status) == CS_SINK_MJPEG) {
// Add USB-only passthrough
int port = cs::GetMjpegServerPort(sink, &status);
values.emplace_back(MakeStreamValue("172.22.11.2", port));
break;
}
}
#endif
// Set table value
return values;
}
void CameraServer::Impl::UpdateStreamValues() {
std::scoped_lock lock(m_mutex);
// Over all the sinks...
for (const auto& i : m_sinks) {
CS_Status status = 0;
CS_Sink sink = i.second.GetHandle();
// Get the source's subtable (if none exists, we're done)
CS_Source source = m_fixedSources.lookup(sink);
if (source == 0) {
source = cs::GetSinkSource(sink, &status);
}
if (source == 0) {
continue;
}
auto table = m_tables.lookup(source);
if (table) {
// Don't set stream values if this is a HttpCamera passthrough
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) {
continue;
}
// Set table value
auto values = GetSinkStreamValues(sink);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
// Over all the sources...
for (const auto& i : m_sources) {
CS_Source source = i.second.GetHandle();
// Get the source's subtable (if none exists, we're done)
auto table = m_tables.lookup(source);
if (table) {
// Set table value
auto values = GetSourceStreamValues(source);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
}
static std::string PixelFormatToString(int pixelFormat) {
switch (pixelFormat) {
case cs::VideoMode::PixelFormat::kMJPEG:
return "MJPEG";
case cs::VideoMode::PixelFormat::kYUYV:
return "YUYV";
case cs::VideoMode::PixelFormat::kRGB565:
return "RGB565";
case cs::VideoMode::PixelFormat::kBGR:
return "BGR";
case cs::VideoMode::PixelFormat::kGray:
return "Gray";
default:
return "Unknown";
}
}
static std::string VideoModeToString(const cs::VideoMode& mode) {
std::string rv;
wpi::raw_string_ostream oss{rv};
oss << mode.width << "x" << mode.height;
oss << " " << PixelFormatToString(mode.pixelFormat) << " ";
oss << mode.fps << " fps";
return oss.str();
}
static std::vector<std::string> GetSourceModeValues(int source) {
std::vector<std::string> rv;
CS_Status status = 0;
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status)) {
rv.emplace_back(VideoModeToString(mode));
}
return rv;
}
static void PutSourcePropertyValue(nt::NetworkTable* table,
const cs::VideoEvent& event, bool isNew) {
wpi::SmallString<64> name;
wpi::SmallString<64> infoName;
if (wpi::StringRef{event.name}.startswith("raw_")) {
name = "RawProperty/";
name += event.name;
infoName = "RawPropertyInfo/";
infoName += event.name;
} else {
name = "Property/";
name += event.name;
infoName = "PropertyInfo/";
infoName += event.name;
}
wpi::SmallString<64> buf;
CS_Status status = 0;
nt::NetworkTableEntry entry = table->GetEntry(name);
switch (event.propertyKind) {
case CS_PROP_BOOLEAN:
if (isNew) {
entry.SetDefaultBoolean(event.value != 0);
} else {
entry.SetBoolean(event.value != 0);
}
break;
case CS_PROP_INTEGER:
case CS_PROP_ENUM:
if (isNew) {
entry.SetDefaultDouble(event.value);
table->GetEntry(infoName + "/min")
.SetDouble(cs::GetPropertyMin(event.propertyHandle, &status));
table->GetEntry(infoName + "/max")
.SetDouble(cs::GetPropertyMax(event.propertyHandle, &status));
table->GetEntry(infoName + "/step")
.SetDouble(cs::GetPropertyStep(event.propertyHandle, &status));
table->GetEntry(infoName + "/default")
.SetDouble(cs::GetPropertyDefault(event.propertyHandle, &status));
} else {
entry.SetDouble(event.value);
}
break;
case CS_PROP_STRING:
if (isNew) {
entry.SetDefaultString(event.valueStr);
} else {
entry.SetString(event.valueStr);
}
break;
default:
break;
}
}
CameraServer::Impl::Impl() : m_nextPort(kBasePort) {
// We publish sources to NetworkTables using the following structure:
// "/CameraPublisher/{Source.Name}/" - root
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
// - "streams" (string array): URLs that can be used to stream data
// - "description" (string): Description of the source
// - "connected" (boolean): Whether source is connected
// - "mode" (string): Current video mode
// - "modes" (string array): Available video modes
// - "Property/{Property}" - Property values
// - "PropertyInfo/{Property}" - Property supporting information
// Listener for video events
m_videoListener = cs::VideoListener{
[=](const cs::VideoEvent& event) {
CS_Status status = 0;
switch (event.kind) {
case cs::VideoEvent::kSourceCreated: {
// Create subtable for the camera
auto table = m_publishTable->GetSubTable(event.name);
{
std::scoped_lock lock(m_mutex);
m_tables.insert(std::make_pair(event.sourceHandle, table));
}
wpi::SmallString<64> buf;
table->GetEntry("source").SetString(
MakeSourceValue(event.sourceHandle, buf));
wpi::SmallString<64> descBuf;
table->GetEntry("description")
.SetString(cs::GetSourceDescription(event.sourceHandle, descBuf,
&status));
table->GetEntry("connected")
.SetBoolean(cs::IsSourceConnected(event.sourceHandle, &status));
table->GetEntry("streams").SetStringArray(
GetSourceStreamValues(event.sourceHandle));
auto mode = cs::GetSourceVideoMode(event.sourceHandle, &status);
table->GetEntry("mode").SetDefaultString(VideoModeToString(mode));
table->GetEntry("modes").SetStringArray(
GetSourceModeValues(event.sourceHandle));
break;
}
case cs::VideoEvent::kSourceDestroyed: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
table->GetEntry("source").SetString("");
table->GetEntry("streams").SetStringArray(
std::vector<std::string>{});
table->GetEntry("modes").SetStringArray(
std::vector<std::string>{});
}
break;
}
case cs::VideoEvent::kSourceConnected: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
// update the description too (as it may have changed)
wpi::SmallString<64> descBuf;
table->GetEntry("description")
.SetString(cs::GetSourceDescription(event.sourceHandle,
descBuf, &status));
table->GetEntry("connected").SetBoolean(true);
}
break;
}
case cs::VideoEvent::kSourceDisconnected: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
table->GetEntry("connected").SetBoolean(false);
}
break;
}
case cs::VideoEvent::kSourceVideoModesUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
table->GetEntry("modes").SetStringArray(
GetSourceModeValues(event.sourceHandle));
}
break;
}
case cs::VideoEvent::kSourceVideoModeChanged: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
table->GetEntry("mode").SetString(VideoModeToString(event.mode));
}
break;
}
case cs::VideoEvent::kSourcePropertyCreated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
PutSourcePropertyValue(table.get(), event, true);
}
break;
}
case cs::VideoEvent::kSourcePropertyValueUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
PutSourcePropertyValue(table.get(), event, false);
}
break;
}
case cs::VideoEvent::kSourcePropertyChoicesUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
wpi::SmallString<64> name{"PropertyInfo/"};
name += event.name;
name += "/choices";
auto choices =
cs::GetEnumPropertyChoices(event.propertyHandle, &status);
table->GetEntry(name).SetStringArray(choices);
}
break;
}
case cs::VideoEvent::kSinkSourceChanged:
case cs::VideoEvent::kSinkCreated:
case cs::VideoEvent::kSinkDestroyed:
case cs::VideoEvent::kNetworkInterfacesChanged: {
m_addresses = cs::GetNetworkInterfaces();
UpdateStreamValues();
break;
}
default:
break;
}
},
0x4fff, true};
// Listener for NetworkTable events
// We don't currently support changing settings via NT due to
// synchronization issues, so just update to current setting if someone
// else tries to change it.
wpi::SmallString<64> buf;
m_tableListener = nt::NetworkTableInstance::GetDefault().AddEntryListener(
kPublishName + wpi::Twine('/'),
[=](const nt::EntryNotification& event) {
wpi::StringRef relativeKey =
event.name.substr(wpi::StringRef(kPublishName).size() + 1);
// get source (sourceName/...)
auto subKeyIndex = relativeKey.find('/');
if (subKeyIndex == wpi::StringRef::npos) {
return;
}
wpi::StringRef sourceName = relativeKey.slice(0, subKeyIndex);
auto sourceIt = m_sources.find(sourceName);
if (sourceIt == m_sources.end()) {
return;
}
// get subkey
relativeKey = relativeKey.substr(subKeyIndex + 1);
// handle standard names
wpi::StringRef propName;
nt::NetworkTableEntry entry{event.entry};
if (relativeKey == "mode") {
// reset to current mode
entry.SetString(VideoModeToString(sourceIt->second.GetVideoMode()));
return;
} else if (relativeKey.startswith("Property/")) {
propName = relativeKey.substr(9);
} else if (relativeKey.startswith("RawProperty/")) {
propName = relativeKey.substr(12);
} else {
return; // ignore
}
// everything else is a property
auto property = sourceIt->second.GetProperty(propName);
switch (property.GetKind()) {
case cs::VideoProperty::kNone:
return;
case cs::VideoProperty::kBoolean:
entry.SetBoolean(property.Get() != 0);
return;
case cs::VideoProperty::kInteger:
case cs::VideoProperty::kEnum:
entry.SetDouble(property.Get());
return;
case cs::VideoProperty::kString:
entry.SetString(property.GetString());
return;
default:
return;
}
},
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_UPDATE);
}
CameraServer::CameraServer() : m_impl(new Impl) {}
CameraServer::~CameraServer() = default;
cs::UsbCamera CameraServer::StartAutomaticCapture() {
cs::UsbCamera camera = StartAutomaticCapture(m_impl->m_defaultUsbDevice++);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
cs::UsbCamera camera{"USB Camera " + wpi::Twine(dev), dev};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
int dev) {
cs::UsbCamera camera{name, dev};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
const wpi::Twine& path) {
cs::UsbCamera camera{name, path};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& host) {
return AddAxisCamera("Axis Camera", host);
}
cs::AxisCamera CameraServer::AddAxisCamera(const char* host) {
return AddAxisCamera("Axis Camera", host);
}
cs::AxisCamera CameraServer::AddAxisCamera(const std::string& host) {
return AddAxisCamera("Axis Camera", host);
}
cs::AxisCamera CameraServer::AddAxisCamera(wpi::ArrayRef<std::string> hosts) {
return AddAxisCamera("Axis Camera", hosts);
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
const wpi::Twine& host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportAxisCamera(camera.GetHandle());
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
const char* host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportAxisCamera(camera.GetHandle());
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
const std::string& host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportAxisCamera(camera.GetHandle());
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
wpi::ArrayRef<std::string> hosts) {
cs::AxisCamera camera{name, hosts};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportAxisCamera(camera.GetHandle());
return camera;
}
cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
// create a dummy CvSource
cs::CvSource source{name, cs::VideoMode::PixelFormat::kMJPEG, 160, 120, 30};
cs::MjpegServer server = StartAutomaticCapture(source);
m_impl->m_fixedSources[server.GetHandle()] = source.GetHandle();
return server;
}
cs::MjpegServer CameraServer::StartAutomaticCapture(
const cs::VideoSource& camera) {
AddCamera(camera);
auto server = AddServer(wpi::Twine("serve_") + camera.GetName());
server.SetSource(camera);
return server;
}
cs::CvSink CameraServer::GetVideo() {
cs::VideoSource source;
{
auto csShared = GetCameraServerShared();
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
csShared->SetCameraServerError("no camera available");
return cs::CvSink{};
}
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
if (it == m_impl->m_sources.end()) {
csShared->SetCameraServerError("no camera available");
return cs::CvSink{};
}
source = it->second;
}
return GetVideo(std::move(source));
}
cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
wpi::SmallString<64> name{"opencv_"};
name += camera.GetName();
{
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(name);
if (it != m_impl->m_sinks.end()) {
auto kind = it->second.GetKind();
if (kind != cs::VideoSink::kCv) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("expected OpenCV sink, but got " +
wpi::Twine(kind));
return cs::CvSink{};
}
return *static_cast<cs::CvSink*>(&it->second);
}
}
cs::CvSink newsink{name};
newsink.SetSource(camera);
AddServer(newsink);
return newsink;
}
cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
wpi::SmallString<64> nameBuf;
wpi::StringRef nameStr = name.toStringRef(nameBuf);
cs::VideoSource source;
{
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sources.find(nameStr);
if (it == m_impl->m_sources.end()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("could not find camera " + nameStr);
return cs::CvSink{};
}
source = it->second;
}
return GetVideo(source);
}
cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
int height) {
cs::CvSource source{name, cs::VideoMode::kMJPEG, width, height, 30};
StartAutomaticCapture(source);
return source;
}
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
int port;
{
std::scoped_lock lock(m_impl->m_mutex);
port = m_impl->m_nextPort++;
}
return AddServer(name, port);
}
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
cs::MjpegServer server{name, port};
AddServer(server);
return server;
}
void CameraServer::AddServer(const cs::VideoSink& server) {
std::scoped_lock lock(m_impl->m_mutex);
m_impl->m_sinks.try_emplace(server.GetName(), server);
}
void CameraServer::RemoveServer(const wpi::Twine& name) {
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
}
cs::VideoSink CameraServer::GetServer() {
wpi::SmallString<64> name;
{
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("no camera available");
return cs::VideoSink{};
}
name = "serve_";
name += m_impl->m_primarySourceName;
}
return GetServer(name);
}
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
wpi::SmallString<64> nameBuf;
wpi::StringRef nameStr = name.toStringRef(nameBuf);
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(nameStr);
if (it == m_impl->m_sinks.end()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("could not find server " + nameStr);
return cs::VideoSink{};
}
return it->second;
}
void CameraServer::AddCamera(const cs::VideoSource& camera) {
std::string name = camera.GetName();
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
m_impl->m_primarySourceName = name;
}
m_impl->m_sources.try_emplace(name, camera);
}
void CameraServer::RemoveCamera(const wpi::Twine& name) {
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sources.erase(name.toStringRef(nameBuf));
}
void CameraServer::SetSize(int size) {
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
return;
}
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
if (it == m_impl->m_sources.end()) {
return;
}
if (size == kSize160x120) {
it->second.SetResolution(160, 120);
} else if (size == kSize320x240) {
it->second.SetResolution(320, 240);
} else if (size == kSize640x480) {
it->second.SetResolution(640, 480);
}
}

View File

@@ -1,42 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "cameraserver/CameraServerShared.h"
#include <wpi/mutex.h>
namespace {
class DefaultCameraServerShared : public frc::CameraServerShared {
public:
void ReportUsbCamera(int id) override {}
void ReportAxisCamera(int id) override {}
void ReportVideoServer(int id) override {}
void SetCameraServerError(const wpi::Twine& error) override {}
void SetVisionRunnerError(const wpi::Twine& error) override {}
void ReportDriverStationError(const wpi::Twine& error) override {}
std::pair<std::thread::id, bool> GetRobotMainThreadId() const override {
return std::make_pair(std::thread::id(), false);
}
};
} // namespace
static std::unique_ptr<frc::CameraServerShared> cameraServerShared = nullptr;
static wpi::mutex setLock;
namespace frc {
CameraServerShared* GetCameraServerShared() {
std::unique_lock lock(setLock);
if (!cameraServerShared) {
cameraServerShared = std::make_unique<DefaultCameraServerShared>();
}
return cameraServerShared.get();
}
} // namespace frc
extern "C" {
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared) {
std::unique_lock lock(setLock);
cameraServerShared.reset(shared);
}
} // extern "C"

View File

@@ -1,58 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "vision/VisionRunner.h"
#include <thread>
#include <opencv2/core/mat.hpp>
#include "cameraserver/CameraServerShared.h"
using namespace frc;
VisionRunnerBase::VisionRunnerBase(cs::VideoSource videoSource)
: m_image(std::make_unique<cv::Mat>()),
m_cvSink("VisionRunner CvSink"),
m_enabled(true) {
m_cvSink.SetSource(videoSource);
}
// Located here and not in header due to cv::Mat forward declaration.
VisionRunnerBase::~VisionRunnerBase() = default;
void VisionRunnerBase::RunOnce() {
auto csShared = frc::GetCameraServerShared();
auto res = csShared->GetRobotMainThreadId();
if (res.second && (std::this_thread::get_id() == res.first)) {
csShared->SetVisionRunnerError(
"VisionRunner::RunOnce() cannot be called from the main robot thread");
return;
}
auto frameTime = m_cvSink.GrabFrame(*m_image);
if (frameTime == 0) {
auto error = m_cvSink.GetError();
csShared->ReportDriverStationError(error);
} else {
DoProcess(*m_image);
}
}
void VisionRunnerBase::RunForever() {
auto csShared = frc::GetCameraServerShared();
auto res = csShared->GetRobotMainThreadId();
if (res.second && (std::this_thread::get_id() == res.first)) {
csShared->SetVisionRunnerError(
"VisionRunner::RunForever() cannot be called from the main robot "
"thread");
return;
}
while (m_enabled) {
RunOnce();
}
}
void VisionRunnerBase::Stop() {
m_enabled = false;
}

View File

@@ -1,295 +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.
#pragma once
#include <stdint.h>
#include <memory>
#include <string>
#include <wpi/ArrayRef.h>
#include <wpi/Twine.h>
#include "cscore.h"
#include "cscore_cv.h"
namespace frc {
/**
* Singleton class for creating and keeping camera servers.
*
* Also publishes camera information to NetworkTables.
*/
class CameraServer {
public:
static constexpr uint16_t kBasePort = 1181;
static constexpr int kSize640x480 = 0;
static constexpr int kSize320x240 = 1;
static constexpr int kSize160x120 = 2;
/**
* Get the CameraServer instance.
*/
static CameraServer* GetInstance();
/**
* Start automatically capturing images to send to the dashboard.
*
* You should call this method to see a camera feed on the dashboard. If you
* also want to perform vision processing on the roboRIO, use getVideo() to
* get access to the camera images.
*
* The first time this overload is called, it calls StartAutomaticCapture()
* with device 0, creating a camera named "USB Camera 0". Subsequent calls
* increment the device number (e.g. 1, 2, etc).
*/
cs::UsbCamera StartAutomaticCapture();
/**
* Start automatically capturing images to send to the dashboard.
*
* This overload calls StartAutomaticCapture() with a name of "USB Camera
* {dev}".
*
* @param dev The device number of the camera interface
*/
cs::UsbCamera StartAutomaticCapture(int dev);
/**
* Start automatically capturing images to send to the dashboard.
*
* @param name The name to give the camera
* @param dev The device number of the camera interface
*/
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name, int dev);
/**
* Start automatically capturing images to send to the dashboard.
*
* @param name The name to give the camera
* @param path The device path (e.g. "/dev/video0") of the camera
*/
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name,
const wpi::Twine& path);
/**
* Start automatically capturing images to send to the dashboard from
* an existing camera.
*
* @param camera Camera
*/
cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
/**
* Adds an Axis IP camera.
*
* This overload calls AddAxisCamera() with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& host);
/**
* Adds an Axis IP camera.
*
* This overload calls AddAxisCamera() with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const char* host);
/**
* Adds an Axis IP camera.
*
* This overload calls AddAxisCamera() with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const std::string& host);
/**
* Adds an Axis IP camera.
*
* This overload calls AddAxisCamera() with name "Axis Camera".
*
* @param hosts Array of Camera host IPs/DNS names
*/
cs::AxisCamera AddAxisCamera(wpi::ArrayRef<std::string> hosts);
/**
* Adds an Axis IP camera.
*
* This overload calls AddAxisCamera() with name "Axis Camera".
*
* @param hosts Array of Camera host IPs/DNS names
*/
template <typename T>
cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const wpi::Twine& host);
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const char* host);
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const std::string& host);
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param hosts Array of Camera host IPs/DNS names
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
wpi::ArrayRef<std::string> hosts);
/**
* Adds an Axis IP camera.
*
* @param name The name to give the camera
* @param hosts Array of Camera host IPs/DNS names
*/
template <typename T>
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
std::initializer_list<T> hosts);
/**
* Adds a virtual camera for switching between two streams. Unlike the
* other addCamera methods, this returns a VideoSink rather than a
* VideoSource. Calling SetSource() on the returned object can be used
* to switch the actual source of the stream.
*/
cs::MjpegServer AddSwitchedCamera(const wpi::Twine& name);
/**
* Get OpenCV access to the primary camera feed. This allows you to
* get images from the camera for image processing on the roboRIO.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
*/
cs::CvSink GetVideo();
/**
* 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).
*/
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 name Camera name
*/
cs::CvSink GetVideo(const wpi::Twine& name);
/**
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
* annotated images to the dashboard.
*
* @param name Name to give the stream
* @param width Width of the image being sent
* @param height Height of the image being sent
*/
cs::CvSource PutVideo(const wpi::Twine& name, int width, int height);
/**
* Adds a MJPEG server at the next available port.
*
* @param name Server name
*/
cs::MjpegServer AddServer(const wpi::Twine& name);
/**
* Adds a MJPEG server.
*
* @param name Server name
*/
cs::MjpegServer AddServer(const wpi::Twine& name, int port);
/**
* Adds an already created server.
*
* @param server Server
*/
void AddServer(const cs::VideoSink& server);
/**
* Removes a server by name.
*
* @param name Server name
*/
void RemoveServer(const wpi::Twine& name);
/**
* Get server for the primary camera feed.
*
* This is only valid to call after a camera feed has been added with
* StartAutomaticCapture() or AddServer().
*/
cs::VideoSink GetServer();
/**
* Gets a server by name.
*
* @param name Server name
*/
cs::VideoSink GetServer(const wpi::Twine& name);
/**
* Adds an already created camera.
*
* @param camera Camera
*/
void AddCamera(const cs::VideoSource& camera);
/**
* Removes a camera by name.
*
* @param name Camera name
*/
void RemoveCamera(const wpi::Twine& name);
/**
* Sets the size of the image to use. Use the public kSize constants to set
* the correct mode, or set it directly on a camera and call the appropriate
* StartAutomaticCapture method.
*
* @deprecated Use SetResolution on the UsbCamera returned by
* StartAutomaticCapture() instead.
* @param size The size to use
*/
void SetSize(int size);
private:
CameraServer();
~CameraServer();
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace frc
#include "cameraserver/CameraServer.inc"

View File

@@ -1,31 +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.
#pragma once
#include <string>
#include <vector>
#include "cameraserver/CameraServer.h"
namespace frc {
template <typename T>
inline cs::AxisCamera CameraServer::AddAxisCamera(
std::initializer_list<T> hosts) {
return AddAxisCamera("Axis Camera", hosts);
}
template <typename T>
inline cs::AxisCamera CameraServer::AddAxisCamera(
const wpi::Twine& name, std::initializer_list<T> hosts) {
std::vector<std::string> vec;
vec.reserve(hosts.size());
for (const auto& host : hosts) {
vec.emplace_back(host);
}
return AddAxisCamera(name, vec);
}
} // namespace frc

View File

@@ -1,32 +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.
#pragma once
#include <memory>
#include <thread>
#include <utility>
#include <wpi/Twine.h>
namespace frc {
class CameraServerShared {
public:
virtual ~CameraServerShared() = default;
virtual void ReportUsbCamera(int id) = 0;
virtual void ReportAxisCamera(int id) = 0;
virtual void ReportVideoServer(int id) = 0;
virtual void SetCameraServerError(const wpi::Twine& error) = 0;
virtual void SetVisionRunnerError(const wpi::Twine& error) = 0;
virtual void ReportDriverStationError(const wpi::Twine& error) = 0;
virtual std::pair<std::thread::id, bool> GetRobotMainThreadId() const = 0;
};
CameraServerShared* GetCameraServerShared();
} // namespace frc
extern "C" {
// Takes ownership
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared);
} // extern "C"

View File

@@ -1,29 +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.
#pragma once
namespace cv {
class Mat;
} // namespace cv
namespace frc {
/**
* A vision pipeline is responsible for running a group of OpenCV algorithms to
* extract data from an image.
*
* @see VisionRunner
*/
class VisionPipeline {
public:
virtual ~VisionPipeline() = default;
/**
* Processes the image input and sets the result objects. Implementations
* should make these objects accessible.
*/
virtual void Process(cv::Mat& mat) = 0;
};
} // namespace frc

View File

@@ -1,97 +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.
#pragma once
#include <atomic>
#include <functional>
#include <memory>
#include "cscore.h"
#include "cscore_cv.h"
#include "vision/VisionPipeline.h"
namespace frc {
/**
* Non-template base class for VisionRunner.
*/
class VisionRunnerBase {
public:
/**
* Creates a new vision runner. It will take images from the {@code
* videoSource}, and call the virtual DoProcess() method.
*
* @param videoSource the video source to use to supply images for the
* pipeline
*/
explicit VisionRunnerBase(cs::VideoSource videoSource);
~VisionRunnerBase();
VisionRunnerBase(const VisionRunnerBase&) = delete;
VisionRunnerBase& operator=(const VisionRunnerBase&) = delete;
/**
* Runs the pipeline one time, giving it the next image from the video source
* specified in the constructor. This will block until the source either has
* an image or throws an error. If the source successfully supplied a frame,
* the pipeline's image input will be set, the pipeline will run, and the
* listener specified in the constructor will be called to notify it that the
* pipeline ran. This must be run in a dedicated thread, and cannot be used in
* the main robot thread because it will freeze the robot program.
*
* <p>This method is exposed to allow teams to add additional functionality or
* have their own ways to run the pipeline. Most teams, however, should just
* use {@link #runForever} in its own thread using a std::thread.</p>
*/
void RunOnce();
/**
* A convenience method that calls {@link #runOnce()} in an infinite loop.
* This must be run in a dedicated thread, and cannot be used in the main
* robot thread because it will freeze the robot program.
*
* <strong>Do not call this method directly from the main thread.</strong>
*/
void RunForever();
/**
* Stop a RunForever() loop.
*/
void Stop();
protected:
virtual void DoProcess(cv::Mat& image) = 0;
private:
std::unique_ptr<cv::Mat> m_image;
cs::CvSink m_cvSink;
std::atomic_bool m_enabled;
};
/**
* A vision runner is a convenient wrapper object to make it easy to run vision
* pipelines from robot code. The easiest way to use this is to run it in a
* std::thread and use the listener to take snapshots of the pipeline's outputs.
*
* @see VisionPipeline
*/
template <typename T>
class VisionRunner : public VisionRunnerBase {
public:
VisionRunner(cs::VideoSource videoSource, T* pipeline,
std::function<void(T&)> listener);
virtual ~VisionRunner() = default;
protected:
void DoProcess(cv::Mat& image) override;
private:
T* m_pipeline;
std::function<void(T&)> m_listener;
};
} // namespace frc
#include "VisionRunner.inc"

View File

@@ -1,34 +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.
#pragma once
#include "vision/VisionRunner.h"
namespace frc {
/**
* Creates a new vision runner. It will take images from the {@code
* videoSource}, send them to the {@code pipeline}, and call the {@code
* listener} when the pipeline has finished to alert user code when it is safe
* to access the pipeline's outputs.
*
* @param videoSource The video source to use to supply images for the pipeline
* @param pipeline The vision pipeline to run
* @param listener A function to call after the pipeline has finished running
*/
template <typename T>
VisionRunner<T>::VisionRunner(cs::VideoSource videoSource, T* pipeline,
std::function<void(T&)> listener)
: VisionRunnerBase(videoSource),
m_pipeline(pipeline),
m_listener(listener) {}
template <typename T>
void VisionRunner<T>::DoProcess(cv::Mat& image) {
m_pipeline->Process(image);
m_listener(*m_pipeline);
}
} // namespace frc

View File

@@ -1,7 +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.
int main() {
return 0;
}

2
cmake/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*~
target/

View File

@@ -1,14 +0,0 @@
include(CompileWarnings)
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)
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
endif()
if (MSVC)
target_compile_options(${name}_test PRIVATE /wd4251 /wd4101)
endif()
add_test(NAME ${name} COMMAND ${name}_test)
endmacro()

View File

@@ -1,7 +0,0 @@
macro(wpilib_target_warnings target)
if(NOT MSVC)
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter -Wno-error=deprecated-declarations)
else()
target_compile_options(${target} PRIVATE /wd4244 /wd4267 /wd4146 /WX /wd4996)
endif()
endmacro()

View File

@@ -1,26 +0,0 @@
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}")
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()

View File

@@ -1,5 +0,0 @@
macro(wpilib_link_macos_gui target)
if (APPLE)
set_target_properties(${target} PROPERTIES LINK_FLAGS "-framework Metal -framework QuartzCore")
endif()
endmacro()

View File

@@ -1,17 +0,0 @@
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})
ENDMACRO()
MACRO(ADD_ALL_SUBDIRECTORIES curdir)
SUBDIR_LIST (_SUBPROJECTS ${curdir})
FOREACH (dir ${_SUBPROJECTS})
ADD_SUBDIRECTORY (${dir})
ENDFOREACH ()
ENDMACRO()

151
cmake/pom.xml Normal file
View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.wpi.first.wpilib.cmake</groupId>
<artifactId>cpp-root</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>unix-properties</id>
<properties>
<cmakeGenerator>Unix Makefiles</cmakeGenerator>
</properties>
<activation>
<os>
<family>unix</family>
</os>
</activation>
</profile>
<profile>
<id>MAC-properties</id>
<properties>
<cmakeGenerator>Unix Makefiles</cmakeGenerator>
</properties>
<activation>
<os>
<family>mac</family>
</os>
</activation>
</profile>
<profile>
<id>windows-properties</id>
<properties>
<cmakeGenerator>MSYS Makefiles</cmakeGenerator>
</properties>
<activation>
<os>
<family>windows</family>
</os>
</activation>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>com.googlecode.cmake-maven-project</groupId>
<artifactId>cmake-maven-plugin</artifactId>
<version>2.8.11-b4</version>
<executions>
<execution>
<id>cmake</id>
<phase>generate-resources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<options>
<option>-DCMAKE_TOOLCHAIN_FILE=../../../arm-toolchain.cmake</option>
<option>-DCMAKE_INSTALL_PREFIX=target-root</option>
</options>
</configuration>
</execution>
<execution>
<id>cmake2</id>
<phase>generate-resources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<target>install</target>
</configuration>
</execution>
</executions>
<configuration>
<sourcePath>..</sourcePath>
<targetPath>${project.build.directory}/cmake</targetPath>
<projectDirectory>${project.build.directory}/cmake</projectDirectory>
<generator>${cmakeGenerator}</generator>
<buildType>release</buildType>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<!-- Set time stamp and version properties. -->
<execution>
<id>set-version-info</id>
<goals>
<goal>run</goal>
</goals>
<phase>process-sources</phase>
<configuration>
<target>
<tstamp>
<format property="timestamp" pattern="yyyy/MM/dd HH:mm:ss z"/>
</tstamp>
<tstamp>
<format property="version-info" pattern="yyyy.MMdd.HHmmss"/>
</tstamp>
<property name="version" value="${version-info}.${build-number}"/>
</target>
<exportAntProperties>true</exportAntProperties>
</configuration>
</execution>
<!-- Unzip the include files for cpp.zip. -->
<execution>
<id>unzip-cpp-includes</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo file="${project.build.directory}/cmake/target-root/so.properties">cpp-sos=${version-info}</echo>
<zip destfile="${project.build.directory}/${project.build.finalName}.zip" basedir="${project.build.directory}/cmake/target-root" />
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>zip-cpp-includes</id>
<phase>compile</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}.zip</file>
<type>zip</type>
</artifact>
<artifact>
<file>${project.build.directory}/cmake/target-root/lib/libHALAthena.a</file>
<type>a</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

18
cmake/run-cpp-tests.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Temporary method to deploy C++ integration tests to the RoboRIO
if [ $(which sshpass) ]
then
# Send stderr to /dev/null - the only thing printed to it is the login prompt
sshpass -p "" ssh admin@10.1.90.2 killall FRCUserProgram java 2> /dev/null
sshpass -p "" scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin 2> /dev/null
sshpass -p "" ssh admin@10.1.90.2 ./FRCUserProgram --gtest_color=yes $* 2> /dev/null
else
ssh admin@10.1.90.2 killall FRCUserProgram
scp target/cmake/wpilibc/wpilibC++IntegrationTests/FRCUserProgram admin@10.1.90.2:/home/admin
ssh admin@10.1.90.2 ./FRCUserProgram --gtest_color=yes $*
fi

View File

@@ -1,23 +0,0 @@
# Parameters: input output prefix namespace
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}")
FILE(WRITE "${output}" "#include <stddef.h>\n#include <wpi/StringRef.h>\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")
IF(NOT namespace STREQUAL "")
FILE(APPEND "${output}" "namespace ${namespace} {\n")
ENDIF()
FILE(APPEND "${output}" "wpi::StringRef ${funcName}() {\n return wpi::StringRef(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
IF(NOT namespace STREQUAL "")
FILE(APPEND "${output}" "}\n")
ENDIF()

View File

@@ -1,4 +0,0 @@
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
set(GNU_MACHINE "arm-frc2021-linux-gnueabi" CACHE STRING "GNU compiler triple")
set(SOFTFP yes)
include("${CMAKE_CURRENT_LIST_DIR}/arm.toolchain.cmake")

View File

@@ -1,98 +0,0 @@
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
set(GNU_MACHINE "arm-raspbian10-linux-gnueabi" CACHE STRING "GNU compiler triple")
if(COMMAND toolchain_save_config)
return() # prevent recursive call
endif()
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR arm)
else()
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/opencv/platforms/linux/gnu.toolchain.cmake")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
set(FLOAT_ABI_SUFFIX "")
if(NOT SOFTFP)
set(FLOAT_ABI_SUFFIX "hf")
endif()
endif()
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
endif()
if(NOT DEFINED CMAKE_C_COMPILER)
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_LINKER)
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
else()
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
endif()
if(NOT DEFINED CMAKE_AR)
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
else()
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
endif()
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
endif()
if(NOT DEFINED CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
else()
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
endif()
if(USE_NEON)
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
set(ENABLE_NEON TRUE)
elseif(USE_VFPV3)
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
set(ENABLE_VFPV3 TRUE)
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
endif()
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
ARM_LINUX_SYSROOT
ENABLE_NEON
ENABLE_VFPV3
CUDA_TOOLKIT_ROOT_DIR
)
toolchain_save_config()

View File

@@ -1,97 +0,0 @@
if(COMMAND toolchain_save_config)
return() # prevent recursive call
endif()
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR arm)
else()
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/gnu.toolchain.cmake")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
set(FLOAT_ABI_SUFFIX "")
if(NOT SOFTFP)
set(FLOAT_ABI_SUFFIX "hf")
endif()
endif()
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
endif()
if(NOT DEFINED CMAKE_C_COMPILER)
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_LINKER)
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
else()
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
endif()
if(NOT DEFINED CMAKE_AR)
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
else()
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
endif()
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
endif()
if(NOT DEFINED CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(CMAKE_CXX_FLAGS "-mthumb ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-mthumb ${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
else()
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
endif()
if(USE_NEON)
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
set(ENABLE_NEON TRUE)
elseif(USE_VFPV3)
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
set(ENABLE_VFPV3 TRUE)
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
endif()
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
ARM_LINUX_SYSROOT
ENABLE_NEON
ENABLE_VFPV3
CUDA_TOOLKIT_ROOT_DIR
)
toolchain_save_config()

View File

@@ -1,134 +0,0 @@
cmake_minimum_required(VERSION 2.8)
# load settings in case of "try compile"
set(TOOLCHAIN_CONFIG_FILE "${WPILIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
get_property(__IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if(__IN_TRY_COMPILE)
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # WPILIB_BINARY_DIR is different
macro(toolchain_save_config)
# nothing
endmacro()
else()
macro(toolchain_save_config)
set(__config "#message(\"Load TOOLCHAIN config...\")\n")
get_cmake_property(__variableNames VARIABLES)
set(__vars_list ${ARGN})
list(APPEND __vars_list
${TOOLCHAIN_CONFIG_VARS}
CMAKE_SYSTEM_NAME
CMAKE_SYSTEM_VERSION
CMAKE_SYSTEM_PROCESSOR
CMAKE_C_COMPILER
CMAKE_CXX_COMPILER
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS
CMAKE_SKIP_RPATH
CMAKE_FIND_ROOT_PATH
GCC_COMPILER_VERSION
)
foreach(__var ${__variableNames})
foreach(_v ${__vars_list})
if("x${__var}" STREQUAL "x${_v}")
if(${__var} MATCHES " ")
set(__config "${__config}set(${__var} \"${${__var}}\")\n")
else()
set(__config "${__config}set(${__var} ${${__var}})\n")
endif()
endif()
endforeach()
endforeach()
if(EXISTS "${TOOLCHAIN_CONFIG_FILE}")
file(READ "${TOOLCHAIN_CONFIG_FILE}" __config_old)
endif()
if("${__config_old}" STREQUAL "${__config}")
# nothing
else()
#message("Update TOOLCHAIN config: ${__config}")
file(WRITE "${TOOLCHAIN_CONFIG_FILE}" "${__config}")
endif()
unset(__config)
unset(__config_old)
unset(__vars_list)
unset(__variableNames)
endmacro()
endif() # IN_TRY_COMPILE
if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
endif()
macro(__cmake_find_root_save_and_reset)
foreach(v
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
)
set(__save_${v} ${${v}})
set(${v} NEVER)
endforeach()
endmacro()
macro(__cmake_find_root_restore)
foreach(v
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
)
set(${v} ${__save_${v}})
unset(__save_${v})
endforeach()
endmacro()
# macro to find programs on the host OS
macro(find_host_program)
__cmake_find_root_save_and_reset()
if(CMAKE_HOST_WIN32)
SET(WIN32 1)
SET(UNIX)
elseif(CMAKE_HOST_APPLE)
SET(APPLE 1)
SET(UNIX)
endif()
find_program(${ARGN})
SET(WIN32)
SET(APPLE)
SET(UNIX 1)
__cmake_find_root_restore()
endmacro()
# macro to find packages on the host OS
macro(find_host_package)
__cmake_find_root_save_and_reset()
if(CMAKE_HOST_WIN32)
SET(WIN32 1)
SET(UNIX)
elseif(CMAKE_HOST_APPLE)
SET(APPLE 1)
SET(UNIX)
endif()
find_package(${ARGN})
SET(WIN32)
SET(APPLE)
SET(UNIX 1)
__cmake_find_root_restore()
endmacro()
set(CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries.")

View File

@@ -1,38 +0,0 @@
cHeaderFileInclude {
_c\.h$
}
cppHeaderFileInclude {
(?<!_c)\.h$
\.hpp$
\.inc$
\.inl$
}
cppSrcFileInclude {
\.cpp$
}
licenseUpdateExclude {
src/main/native/cpp/default_init_allocator\.h$
}
includeGuardRoots {
cscore/src/main/native/cpp/
cscore/src/main/native/include/
cscore/src/main/native/linux/
cscore/src/main/native/osx/
cscore/src/main/native/windows/
cscore/src/main/test/native/cpp/
}
repoRootNameOverride {
cscore
}
includeOtherLibs {
^opencv2/
^support/
^tcpsockets/
^wpi/
}

View File

@@ -1,150 +0,0 @@
project(cscore)
include(SubDirList)
include(CompileWarnings)
include(AddTest)
include(LinkMacOSGUI)
find_package( OpenCV REQUIRED )
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_windows_src src/main/native/windows/*.cpp)
add_library(cscore ${cscore_native_src})
set_target_properties(cscore PROPERTIES DEBUG_POSTFIX "d")
if(NOT MSVC)
if (APPLE)
target_sources(cscore PRIVATE ${cscore_osx_src})
else()
target_sources(cscore PRIVATE ${cscore_linux_src})
endif()
else()
target_sources(cscore PRIVATE ${cscore_windows_src})
target_compile_definitions(cscore PUBLIC -DNOMINMAX)
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 PRIVATE src/main/native/cpp)
wpilib_target_warnings(cscore)
target_link_libraries(cscore PUBLIC wpiutil ${OpenCV_LIBS})
set_property(TARGET cscore PROPERTY FOLDER "libraries")
install(TARGETS cscore EXPORT cscore DESTINATION "${main_lib_dest}")
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})
SUBDIR_LIST(cscore_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
foreach(example ${cscore_examples})
file(GLOB cscore_example_src examples/${example}/*.cpp)
unset(add_libs)
if(${example} STREQUAL "usbviewer")
if(TARGET wpigui)
set(add_libs wpigui)
else()
unset(cscore_example_src)
endif()
endif()
if(cscore_example_src)
add_executable(cscore_${example} ${cscore_example_src})
wpilib_target_warnings(cscore_${example})
if (${example} STREQUAL "usbviewer")
wpilib_link_macos_gui(cscore_${example})
endif()
target_link_libraries(cscore_${example} cscore ${add_libs})
set_property(TARGET cscore_${example} PROPERTY FOLDER "examples")
endif()
endforeach()
# Java bindings
if (WITH_JAVA)
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
#find java files, copy them locally
if("${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
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 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 NO_DEFAULT_PATH)
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)
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
set(CMAKE_JAVA_COMPILE_FLAGS "-h" "${CMAKE_CURRENT_BINARY_DIR}/jniheaders")
add_jar(cscore_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar ${OPENCV_JAR_FILE} OUTPUT_NAME cscore)
else()
add_jar(cscore_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar ${OPENCV_JAR_FILE} OUTPUT_NAME cscore GENERATE_NATIVE_HEADERS cscore_jni_headers)
endif()
get_property(CSCORE_JAR_FILE TARGET cscore_jar PROPERTY JAR_FILE)
install(FILES ${CSCORE_JAR_FILE} DESTINATION "${java_lib_dest}")
install(FILES ${OPENCV_JAR_FILE} DESTINATION "${java_lib_dest}")
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)
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})
set_property(TARGET cscorejni PROPERTY FOLDER "libraries")
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
target_include_directories(cscorejni PRIVATE ${JNI_INCLUDE_DIRS})
target_include_directories(cscorejni PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/jniheaders")
else()
target_link_libraries(cscorejni PRIVATE cscore_jni_headers)
endif()
add_dependencies(cscorejni cscore_jar)
if (MSVC)
install(TARGETS cscorejni RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
endif()
install(TARGETS cscorejni EXPORT cscorejni DESTINATION "${main_lib_dest}")
endif()
if (WITH_TESTS)
wpilib_add_test(cscore src/test/native/cpp)
target_link_libraries(cscore_test cscore gmock)
endif()

View File

@@ -1,241 +0,0 @@
import org.gradle.internal.os.OperatingSystem
ext {
nativeName = 'cscore'
devMain = 'edu.wpi.cscore.DevMain'
}
// Removed because having the objective-cpp plugin added breaks
// embedded tools and its toolchain check. It causes an obj-cpp
// source set to be added to all binaries, even cross binaries
// with no support.
// if (OperatingSystem.current().isMacOsX()) {
// apply plugin: 'objective-cpp'
// }
apply from: "${rootDir}/shared/jni/setupBuild.gradle"
model {
components {
cscoreJNICvStatic(JniNativeLibrarySpec) {
baseName = 'cscorejnicvstatic'
enableCheckTask true
javaCompileTasks << compileJava
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian)
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic)
sources {
cpp {
source {
srcDirs 'src/main/native/cpp'
include '**/jni/*.cpp'
}
exportedHeaders {
srcDir 'src/main/native/include'
include '**/*.h'
}
}
}
binaries.all {
if (it instanceof StaticLibraryBinarySpec) {
it.buildable = false
return
}
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
if (it.targetPlatform.operatingSystem.linux) {
it.linker.args '-Wl,--version-script=' + file('src/main/native/LinuxSymbolScript.txt')
} else if (it.targetPlatform.operatingSystem.macOsX) {
it.linker.args '-exported_symbols_list'
it.linker.args file('src/main/native/MacSymbolScript.txt').toString()
}
}
}
}
}
ext {
sharedCvConfigs = [cscore : [],
cscoreBase: [],
cscoreDev : [],
cscoreTest: [],
cscoreJNIShared: []]
staticCvConfigs = [cscoreJNI: [],
cscoreJNICvStatic: []]
useJava = true
useCpp = true
cvStaticBuild = true
splitSetup = {
if (it.targetPlatform.operatingSystem.isMacOsX()) {
it.sources {
// macObjCpp(ObjectiveCppSourceSet) {
// source {
// srcDirs = ['src/main/native/objcpp']
// include '**/*.mm'
// }
// exportedHeaders {
// srcDirs 'src/main/native/include'
// include '**/*.h'
// }
// }
cscoreMacCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/osx'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
include '**/*.h'
}
}
}
} else if (it.targetPlatform.operatingSystem.isLinux()) {
it.sources {
cscoreLinuxCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/linux'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
include '**/*.h'
}
}
}
} else if (it.targetPlatform.operatingSystem.isWindows()) {
it.sources {
cscoreWindowsCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/windows'
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include', 'src/main/native/cpp'
include '**/*.h'
}
}
}
}
}
}
def examplesMap = [:];
File examplesTree = file("$projectDir/examples")
examplesTree.list(new FilenameFilter() {
@Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
}).each {
sharedCvConfigs.put(it, [])
examplesMap.put(it, [])
}
apply from: "${rootDir}/shared/opencv.gradle"
nativeUtils.exportsConfigs {
cscore {
x86ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
x64ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
}
cscoreJNI {
x86SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x64SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
}
cscoreJNICvStatic {
x86SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x64SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
}
}
model {
components {
examplesMap.each { key, value ->
if (key == "usbviewer") {
if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
"${key}"(NativeExecutableSpec) {
targetBuildTypes 'debug'
binaries.all {
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
lib project: ':wpigui', library: 'wpigui', linkage: 'static'
lib library: 'cscore', linkage: 'shared'
nativeUtils.useRequiredLibrary(it, 'imgui_static')
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {
it.buildable = false
return
}
if (it.targetPlatform.operatingSystem.isWindows()) {
it.linker.args << 'Gdi32.lib' << 'Shell32.lib' << 'd3d11.lib' << 'd3dcompiler.lib'
} else if (it.targetPlatform.operatingSystem.isMacOsX()) {
it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore'
} else {
it.linker.args << '-lX11'
}
}
sources {
cpp {
source {
srcDirs 'examples/' + "${key}"
include '**/*.cpp'
}
}
}
}
}
} else {
"${key}"(NativeExecutableSpec) {
targetBuildTypes 'debug'
binaries.all {
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
lib library: 'cscore', linkage: 'shared'
}
sources {
cpp {
source {
srcDirs 'examples/' + "${key}"
include '**/*.cpp'
}
}
}
}
}
}
}
}

View File

@@ -1,7 +0,0 @@
include(CMakeFindDependencyMacro)
@FILENAME_DEP_REPLACE@
@WPIUTIL_DEP_REPLACE@
find_dependency(OpenCV)
@FILENAME_DEP_REPLACE@
include(${SELF_DIR}/cscore.cmake)

View File

@@ -1,84 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <wpi/SmallString.h>
#include <wpi/raw_ostream.h>
#include "cscore.h"
int main() {
CS_Status status = 0;
wpi::SmallString<64> buf;
for (const auto& caminfo : cs::EnumerateUsbCameras(&status)) {
wpi::outs() << caminfo.dev << ": " << caminfo.path << " (" << caminfo.name
<< ")\n";
if (!caminfo.otherPaths.empty()) {
wpi::outs() << "Other device paths:\n";
for (auto&& path : caminfo.otherPaths) {
wpi::outs() << " " << path << '\n';
}
}
cs::UsbCamera camera{"usbcam", caminfo.dev};
wpi::outs() << "Properties:\n";
for (const auto& prop : camera.EnumerateProperties()) {
wpi::outs() << " " << prop.GetName();
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
wpi::outs() << " (bool): "
<< "value=" << prop.Get()
<< " default=" << prop.GetDefault();
break;
case cs::VideoProperty::kInteger:
wpi::outs() << " (int): "
<< "value=" << prop.Get() << " min=" << prop.GetMin()
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
<< " default=" << prop.GetDefault();
break;
case cs::VideoProperty::kString:
wpi::outs() << " (string): " << prop.GetString(buf);
break;
case cs::VideoProperty::kEnum: {
wpi::outs() << " (enum): "
<< "value=" << prop.Get();
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
if (choices[i].empty()) {
continue;
}
wpi::outs() << "\n " << i << ": " << choices[i];
}
break;
}
default:
break;
}
wpi::outs() << '\n';
}
wpi::outs() << "Video Modes:\n";
for (const auto& mode : camera.EnumerateVideoModes()) {
wpi::outs() << " PixelFormat:";
switch (mode.pixelFormat) {
case cs::VideoMode::kMJPEG:
wpi::outs() << "MJPEG";
break;
case cs::VideoMode::kYUYV:
wpi::outs() << "YUYV";
break;
case cs::VideoMode::kRGB565:
wpi::outs() << "RGB565";
break;
default:
wpi::outs() << "Unknown";
break;
}
wpi::outs() << " Width:" << mode.width;
wpi::outs() << " Height:" << mode.height;
wpi::outs() << " FPS:" << mode.fps << '\n';
}
}
}

View File

@@ -1,35 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <iostream>
#include <opencv2/core/core.hpp>
#include "cscore.h"
#include "cscore_cv.h"
int main() {
cs::HttpCamera camera{"httpcam", "http://localhost:8081/?action=stream"};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::CvSink cvsink{"cvsink"};
cvsink.SetSource(camera);
cs::CvSource cvsource{"cvsource", cs::VideoMode::kMJPEG, 320, 240, 30};
cs::MjpegServer cvMjpegServer{"cvhttpserver", 8083};
cvMjpegServer.SetSource(cvsource);
cv::Mat test;
cv::Mat flip;
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
std::cout << "error: " << cvsink.GetError() << std::endl;
continue;
}
std::cout << "got frame at time " << time << " size " << test.size()
<< std::endl;
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}
}

View File

@@ -1,108 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <chrono>
#include <thread>
#include <wpi/SmallString.h>
#include <wpi/raw_ostream.h>
#include "cscore.h"
int main(int argc, char** argv) {
if (argc < 2) {
wpi::errs() << "Usage: settings camera [prop val] ... -- [prop val]...\n";
wpi::errs() << " Example: settings 1 brightness 30 raw_contrast 10\n";
return 1;
}
int id;
if (wpi::StringRef{argv[1]}.getAsInteger(10, id)) {
wpi::errs() << "Expected number for camera\n";
return 2;
}
cs::UsbCamera camera{"usbcam", id};
// Set prior to connect
int arg = 2;
wpi::StringRef propName;
for (; arg < argc && wpi::StringRef{argv[arg]} != "--"; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal)) {
camera.GetProperty(propName).SetString(propVal);
} else {
camera.GetProperty(propName).Set(intVal);
}
propName = wpi::StringRef{};
}
}
if (arg < argc && wpi::StringRef{argv[arg]} == "--") {
++arg;
}
// Wait to connect
while (!camera.IsConnected()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// Set rest
propName = wpi::StringRef{};
for (; arg < argc; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal)) {
camera.GetProperty(propName).SetString(propVal);
} else {
camera.GetProperty(propName).Set(intVal);
}
propName = wpi::StringRef{};
}
}
// Print settings
wpi::SmallString<64> buf;
wpi::outs() << "Properties:\n";
for (const auto& prop : camera.EnumerateProperties()) {
wpi::outs() << " " << prop.GetName();
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
wpi::outs() << " (bool): "
<< "value=" << prop.Get()
<< " default=" << prop.GetDefault();
break;
case cs::VideoProperty::kInteger:
wpi::outs() << " (int): "
<< "value=" << prop.Get() << " min=" << prop.GetMin()
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
<< " default=" << prop.GetDefault();
break;
case cs::VideoProperty::kString:
wpi::outs() << " (string): " << prop.GetString(buf);
break;
case cs::VideoProperty::kEnum: {
wpi::outs() << " (enum): "
<< "value=" << prop.Get();
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
if (choices[i].empty()) {
continue;
}
wpi::outs() << "\n " << i << ": " << choices[i];
}
break;
}
default:
break;
}
wpi::outs() << '\n';
}
}

View File

@@ -1,37 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <iostream>
#include <opencv2/core/core.hpp>
#include "cscore.h"
#include "cscore_cv.h"
int main() {
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::MjpegServer mjpegServer{"httpserver", 8081};
mjpegServer.SetSource(camera);
cs::CvSink cvsink{"cvsink"};
cvsink.SetSource(camera);
cs::CvSource cvsource{"cvsource", cs::VideoMode::kMJPEG, 320, 240, 30};
cs::MjpegServer cvMjpegServer{"cvhttpserver", 8082};
cvMjpegServer.SetSource(cvsource);
cv::Mat test;
cv::Mat flip;
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
std::cout << "error: " << cvsink.GetError() << std::endl;
continue;
}
std::cout << "got frame at time " << time << " size " << test.size()
<< std::endl;
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}
}

View File

@@ -1,33 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <wpi/raw_ostream.h>
#include "cscore.h"
int main() {
wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
wpi::outs() << "IPv4 network addresses:\n";
for (const auto& addr : cs::GetNetworkInterfaces()) {
wpi::outs() << " " << addr << '\n';
}
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::MjpegServer mjpegServer{"httpserver", 8081};
mjpegServer.SetSource(camera);
CS_Status status = 0;
cs::AddListener(
[&](const cs::RawEvent& event) {
wpi::outs() << "FPS=" << camera.GetActualFPS()
<< " MBPS=" << (camera.GetActualDataRate() / 1000000.0)
<< '\n';
},
cs::RawEvent::kTelemetryUpdated, false, &status);
cs::SetTelemetryPeriod(1.0);
std::getchar();
}

View File

@@ -1,115 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <atomic>
#include <thread>
#include <vector>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui.h>
#include <imgui_internal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <wpi/raw_ostream.h>
#include <wpi/spinlock.h>
#include <wpigui.h>
#include "cscore.h"
#include "cscore_cv.h"
namespace gui = wpi::gui;
int main() {
std::atomic<cv::Mat*> latestFrame{nullptr};
std::vector<cv::Mat*> sharedFreeList;
wpi::spinlock sharedFreeListMutex;
std::vector<cv::Mat*> sourceFreeList;
std::atomic<bool> stopCamera{false};
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 640, 480, 30);
cs::CvSink cvsink{"cvsink"};
cvsink.SetSource(camera);
std::thread thr([&] {
cv::Mat frame;
while (!stopCamera) {
// get frame from camera
uint64_t time = cvsink.GrabFrame(frame);
if (time == 0) {
wpi::outs() << "error: " << cvsink.GetError() << '\n';
continue;
}
// get or create a mat, prefer sourceFreeList over sharedFreeList
cv::Mat* out;
if (!sourceFreeList.empty()) {
out = sourceFreeList.back();
sourceFreeList.pop_back();
} else {
{
std::scoped_lock lock(sharedFreeListMutex);
for (auto mat : sharedFreeList) {
sourceFreeList.emplace_back(mat);
}
sharedFreeList.clear();
}
if (!sourceFreeList.empty()) {
out = sourceFreeList.back();
sourceFreeList.pop_back();
} else {
out = new cv::Mat;
}
}
// convert to RGBA
cv::cvtColor(frame, *out, cv::COLOR_BGR2RGBA);
// make available
auto prev = latestFrame.exchange(out);
// put prev on free list
if (prev) {
sourceFreeList.emplace_back(prev);
}
}
});
gui::CreateContext();
gui::Initialize("Hello World", 1024, 768);
gui::Texture tex;
gui::AddEarlyExecute([&] {
auto frame = latestFrame.exchange(nullptr);
if (frame) {
// create or update texture
if (!tex || frame->cols != tex.GetWidth() ||
frame->rows != tex.GetHeight()) {
tex = gui::Texture(gui::kPixelRGBA, frame->cols, frame->rows,
frame->data);
} else {
tex.Update(frame->data);
}
// put back on shared freelist
std::scoped_lock lock(sharedFreeListMutex);
sharedFreeList.emplace_back(frame);
}
ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Video")) {
// render to window (best fit)
if (tex && tex.GetWidth() != 0 && tex.GetHeight() != 0) {
auto drawList = ImGui::GetWindowDrawList();
ImVec2 windowPos = ImGui::GetWindowPos();
ImVec2 imageMin = ImGui::GetWindowContentRegionMin();
ImVec2 imageMax = ImGui::GetWindowContentRegionMax();
gui::MaxFit(&imageMin, &imageMax, tex.GetWidth(), tex.GetHeight());
drawList->AddImage(tex, windowPos + imageMin, windowPos + imageMax);
}
}
ImGui::End();
});
gui::Main();
stopCamera = true;
thr.join();
}

View File

@@ -1,95 +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.cscore;
import edu.wpi.cscore.VideoMode.PixelFormat;
import edu.wpi.cscore.raw.RawFrame;
import java.nio.ByteBuffer;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
public class RawCVMatSink extends ImageSink {
RawFrame frame = new RawFrame();
Mat tmpMat;
ByteBuffer origByteBuffer;
int width;
int height;
int pixelFormat;
int bgrValue = PixelFormat.kBGR.getValue();
private int getCVFormat(PixelFormat pixelFormat) {
int type = 0;
switch (pixelFormat) {
case kYUYV:
case kRGB565:
type = CvType.CV_8UC2;
break;
case kBGR:
type = CvType.CV_8UC3;
break;
case kGray:
case kMJPEG:
default:
type = CvType.CV_8UC1;
break;
}
return type;
}
/**
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
* get each new image.
*
* @param name Source name (arbitrary unique identifier)
*/
public RawCVMatSink(String name) {
super(CameraServerJNI.createRawSink(name));
}
/**
* Wait for the next frame and get the image. Times out (returning 0) after 0.225 seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error message)
*/
public long grabFrame(Mat image) {
return grabFrame(image, 0.225);
}
/**
* Wait for the next frame and get the image. Times out (returning 0) after timeout seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
frame.setWidth(0);
frame.setHeight(0);
frame.setPixelFormat(bgrValue);
long rv = CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
if (rv <= 0) {
return rv;
}
if (frame.getDataByteBuffer() != origByteBuffer
|| width != frame.getWidth()
|| height != frame.getHeight()
|| pixelFormat != frame.getPixelFormat()) {
origByteBuffer = frame.getDataByteBuffer();
height = frame.getHeight();
width = frame.getWidth();
pixelFormat = frame.getPixelFormat();
tmpMat =
new Mat(
frame.getHeight(),
frame.getWidth(),
getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)),
origByteBuffer);
}
tmpMat.copyTo(image);
return rv;
}
}

View File

@@ -1,60 +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.cscore;
import edu.wpi.cscore.VideoMode.PixelFormat;
import org.opencv.core.Mat;
public class RawCVMatSource extends ImageSource {
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
public RawCVMatSource(String name, VideoMode mode) {
super(
CameraServerJNI.createRawSource(
name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
}
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
public RawCVMatSource(
String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerJNI.createRawSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
* Put an OpenCV image and notify sinks.
*
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images are supported. If the
* format, depth or channel order is different, use Mat.convertTo() and/or cvtColor() to convert
* it first.
*
* @param image OpenCV image
*/
public void putFrame(Mat image) {
int channels = image.channels();
if (channels != 1 && channels != 3) {
throw new VideoException("Unsupported Image Type");
}
int imgType = channels == 1 ? PixelFormat.kGray.getValue() : PixelFormat.kBGR.getValue();
CameraServerJNI.putRawSourceFrame(
m_handle,
image.dataAddr(),
image.width(),
image.height(),
imgType,
(int) image.total() * channels);
}
}

View File

@@ -1,18 +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.cscore;
import edu.wpi.first.wpiutil.RuntimeDetector;
public final class DevMain {
/** Main method. */
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(RuntimeDetector.getPlatformPath());
System.out.println(CameraServerJNI.getHostname());
}
private DevMain() {}
}

View File

@@ -1,11 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <iostream>
#include "cscore.h"
int main() {
std::cout << cs::GetHostname() << std::endl;
}

View File

@@ -1,40 +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.cscore;
/** A source that represents an Axis IP camera. */
public class AxisCamera extends HttpCamera {
private static String hostToUrl(String host) {
return "http://" + host + "/mjpg/video.mjpg";
}
private static String[] hostToUrl(String[] hosts) {
String[] urls = new String[hosts.length];
for (int i = 0; i < hosts.length; i++) {
urls[i] = hostToUrl(hosts[i]);
}
return urls;
}
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
public AxisCamera(String name, String host) {
super(name, hostToUrl(host), HttpCameraKind.kAxis);
}
/**
* Create a source for an Axis IP camera.
*
* @param name Source name (arbitrary unique identifier)
* @param hosts Array of Camera host IPs/DNS names
*/
public AxisCamera(String name, String[] hosts) {
super(name, hostToUrl(hosts), HttpCameraKind.kAxis);
}
}

View File

@@ -1,70 +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.cscore;
import edu.wpi.first.wpiutil.RuntimeLoader;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.opencv.core.Core;
public class CameraServerCvJNI {
static boolean libraryLoaded = false;
static RuntimeLoader<Core> loader = null;
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static boolean getExtractOnStaticLoad() {
return extractOnStaticLoad.get();
}
public static void setExtractOnStaticLoad(boolean load) {
extractOnStaticLoad.set(load);
}
}
static {
String opencvName = Core.NATIVE_LIBRARY_NAME;
if (Helper.getExtractOnStaticLoad()) {
try {
CameraServerJNI.forceLoad();
loader =
new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibraryHashed();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
libraryLoaded = true;
}
}
/** Force load the library. */
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
CameraServerJNI.forceLoad();
loader =
new RuntimeLoader<>(
Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibrary();
libraryLoaded = true;
}
public static native int createCvSource(
String name, int pixelFormat, int width, int height, int fps);
public static native void putSourceFrame(int source, long imageNativeObj);
public static native int createCvSink(String name);
// public static native int createCvSinkCallback(String name,
// void (*processFrame)(long time));
public static native long grabSinkFrame(int sink, long imageNativeObj);
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
}

View File

@@ -1,376 +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.cscore;
import edu.wpi.cscore.raw.RawFrame;
import edu.wpi.first.wpiutil.RuntimeLoader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
public class CameraServerJNI {
static boolean libraryLoaded = false;
static RuntimeLoader<CameraServerJNI> loader = null;
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static boolean getExtractOnStaticLoad() {
return extractOnStaticLoad.get();
}
public static void setExtractOnStaticLoad(boolean load) {
extractOnStaticLoad.set(load);
}
}
static {
if (Helper.getExtractOnStaticLoad()) {
try {
loader =
new RuntimeLoader<>(
"cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
libraryLoaded = true;
}
}
/** Force load the library. */
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
loader =
new RuntimeLoader<>(
"cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
libraryLoaded = true;
}
//
// Property Functions
//
public static native int getPropertyKind(int property);
public static native String getPropertyName(int property);
public static native int getProperty(int property);
public static native void setProperty(int property, int value);
public static native int getPropertyMin(int property);
public static native int getPropertyMax(int property);
public static native int getPropertyStep(int property);
public static native int getPropertyDefault(int property);
public static native String getStringProperty(int property);
public static native void setStringProperty(int property, String value);
public static native String[] getEnumPropertyChoices(int property);
//
// Source Creation Functions
//
public static native int createUsbCameraDev(String name, int dev);
public static native int createUsbCameraPath(String name, String path);
public static native int createHttpCamera(String name, String url, int kind);
public static native int createHttpCameraMulti(String name, String[] urls, int kind);
public static native int createRawSource(
String name, int pixelFormat, int width, int height, int fps);
//
// Source Functions
//
public static native int getSourceKind(int source);
public static native String getSourceName(int source);
public static native String getSourceDescription(int source);
public static native long getSourceLastFrameTime(int source);
public static native void setSourceConnectionStrategy(int source, int strategy);
public static native boolean isSourceConnected(int source);
public static native boolean isSourceEnabled(int source);
public static native int getSourceProperty(int source, String name);
public static native int[] enumerateSourceProperties(int source);
public static native VideoMode getSourceVideoMode(int source);
public static native boolean setSourceVideoMode(
int source, int pixelFormat, int width, int height, int fps);
public static native boolean setSourcePixelFormat(int source, int pixelFormat);
public static native boolean setSourceResolution(int source, int width, int height);
public static native boolean setSourceFPS(int source, int fps);
public static native boolean setSourceConfigJson(int source, String config);
public static native String getSourceConfigJson(int source);
public static native VideoMode[] enumerateSourceVideoModes(int source);
public static native int[] enumerateSourceSinks(int source);
public static native int copySource(int source);
public static native void releaseSource(int source);
//
// Camera Source Common Property Fuctions
//
public static native void setCameraBrightness(int source, int brightness);
public static native int getCameraBrightness(int source);
public static native void setCameraWhiteBalanceAuto(int source);
public static native void setCameraWhiteBalanceHoldCurrent(int source);
public static native void setCameraWhiteBalanceManual(int source, int value);
public static native void setCameraExposureAuto(int source);
public static native void setCameraExposureHoldCurrent(int source);
public static native void setCameraExposureManual(int source, int value);
//
// UsbCamera Source Functions
//
public static native void setUsbCameraPath(int source, String path);
public static native String getUsbCameraPath(int source);
public static native UsbCameraInfo getUsbCameraInfo(int source);
//
// HttpCamera Source Functions
//
public static native int getHttpCameraKind(int source);
public static native void setHttpCameraUrls(int source, String[] urls);
public static native String[] getHttpCameraUrls(int source);
//
// Image Source Functions
//
public static native void putRawSourceFrameBB(
int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
public static native void putRawSourceFrame(
int source, long data, int width, int height, int pixelFormat, int totalData);
public static void putRawSourceFrame(int source, RawFrame raw) {
putRawSourceFrame(
source,
raw.getDataPtr(),
raw.getWidth(),
raw.getHeight(),
raw.getPixelFormat(),
raw.getTotalData());
}
public static native void notifySourceError(int source, String msg);
public static native void setSourceConnected(int source, boolean connected);
public static native void setSourceDescription(int source, String description);
public static native int createSourceProperty(
int source,
String name,
int kind,
int minimum,
int maximum,
int step,
int defaultValue,
int value);
public static native void setSourceEnumPropertyChoices(
int source, int property, String[] choices);
//
// Sink Creation Functions
//
public static native int createMjpegServer(String name, String listenAddress, int port);
public static native int createRawSink(String name);
//
// Sink Functions
//
public static native int getSinkKind(int sink);
public static native String getSinkName(int sink);
public static native String getSinkDescription(int sink);
public static native int getSinkProperty(int sink, String name);
public static native int[] enumerateSinkProperties(int sink);
public static native boolean setSinkConfigJson(int sink, String config);
public static native String getSinkConfigJson(int sink);
public static native void setSinkSource(int sink, int source);
public static native int getSinkSourceProperty(int sink, String name);
public static native int getSinkSource(int sink);
public static native int copySink(int sink);
public static native void releaseSink(int sink);
//
// MjpegServer Sink Functions
//
public static native String getMjpegServerListenAddress(int sink);
public static native int getMjpegServerPort(int sink);
//
// Image Sink Functions
//
public static native void setSinkDescription(int sink, String description);
private static native long grabRawSinkFrameImpl(
int sink,
RawFrame rawFrame,
long rawFramePtr,
ByteBuffer byteBuffer,
int width,
int height,
int pixelFormat);
private static native long grabRawSinkFrameTimeoutImpl(
int sink,
RawFrame rawFrame,
long rawFramePtr,
ByteBuffer byteBuffer,
int width,
int height,
int pixelFormat,
double timeout);
public static long grabSinkFrame(int sink, RawFrame rawFrame) {
return grabRawSinkFrameImpl(
sink,
rawFrame,
rawFrame.getFramePtr(),
rawFrame.getDataByteBuffer(),
rawFrame.getWidth(),
rawFrame.getHeight(),
rawFrame.getPixelFormat());
}
public static long grabSinkFrameTimeout(int sink, RawFrame rawFrame, double timeout) {
return grabRawSinkFrameTimeoutImpl(
sink,
rawFrame,
rawFrame.getFramePtr(),
rawFrame.getDataByteBuffer(),
rawFrame.getWidth(),
rawFrame.getHeight(),
rawFrame.getPixelFormat(),
timeout);
}
public static native String getSinkError(int sink);
public static native void setSinkEnabled(int sink, boolean enabled);
//
// Listener Functions
//
public static native int addListener(
Consumer<VideoEvent> listener, int eventMask, boolean immediateNotify);
public static native void removeListener(int handle);
//
// Telemetry Functions
//
public enum TelemetryKind {
kSourceBytesReceived(1),
kSourceFramesReceived(2);
private final int value;
TelemetryKind(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static native void setTelemetryPeriod(double seconds);
public static native double getTelemetryElapsedTime();
public static native long getTelemetryValue(int handle, int kind);
public static long getTelemetryValue(int handle, TelemetryKind kind) {
return getTelemetryValue(handle, kind.getValue());
}
public static native double getTelemetryAverageValue(int handle, int kind);
public static double getTelemetryAverageValue(int handle, TelemetryKind kind) {
return getTelemetryAverageValue(handle, kind.getValue());
}
//
// Logging Functions
//
@FunctionalInterface
public interface LoggerFunction {
void apply(int level, String file, int line, String msg);
}
public static native void setLogger(LoggerFunction func, int minLevel);
//
// Utility Functions
//
public static native UsbCameraInfo[] enumerateUsbCameras();
public static native int[] enumerateSources();
public static native int[] enumerateSinks();
public static native String getHostname();
public static native String[] getNetworkInterfaces();
public static native long allocateRawFrame();
public static native void freeRawFrame(long frame);
}

View File

@@ -1,68 +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.cscore;
import org.opencv.core.Mat;
/**
* A sink for user code to accept video frames as OpenCV images. These sinks require the WPILib
* OpenCV builds. For an alternate OpenCV, see the documentation how to build your own with RawSink.
*/
public class CvSink extends ImageSink {
/**
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
* get each new image.
*
* @param name Source name (arbitrary unique identifier)
*/
public CvSink(String name) {
super(CameraServerCvJNI.createCvSink(name));
}
/// Create a sink for accepting OpenCV images in a separate thread.
/// A thread will be created that calls WaitForFrame() and calls the
/// processFrame() callback each time a new frame arrives.
/// @param name Source name (arbitrary unique identifier)
/// @param processFrame Frame processing function; will be called with a
/// time=0 if an error occurred. processFrame should call GetImage()
/// or GetError() as needed, but should not call (except in very
/// unusual circumstances) WaitForImage().
// public CvSink(wpi::StringRef name,
// std::function<void(uint64_t time)> processFrame) {
// super(CameraServerJNI.createCvSinkCallback(name, processFrame));
// }
/**
* Wait for the next frame and get the image. Times out (returning 0) after 0.225 seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error message)
*/
public long grabFrame(Mat image) {
return grabFrame(image, 0.225);
}
/**
* Wait for the next frame and get the image. Times out (returning 0) after timeout seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
}
/**
* Wait for the next frame and get the image. May block forever. The provided image will have
* three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrameNoTimeout(Mat image) {
return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
}
}

View File

@@ -1,51 +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.cscore;
import org.opencv.core.Mat;
/**
* A source that represents a video camera. These sources require the WPILib OpenCV builds. For an
* alternate OpenCV, see the documentation how to build your own with RawSource.
*/
public class CvSource extends ImageSource {
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
public CvSource(String name, VideoMode mode) {
super(
CameraServerCvJNI.createCvSource(
name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
}
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
* Put an OpenCV image and notify sinks.
*
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images are supported. If the
* format, depth or channel order is different, use Mat.convertTo() and/or cvtColor() to convert
* it first.
*
* @param image OpenCV image
*/
public void putFrame(Mat image) {
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
}
}

View File

@@ -1,105 +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.cscore;
/** A source that represents a MJPEG-over-HTTP (IP) camera. */
public class HttpCamera extends VideoCamera {
public enum HttpCameraKind {
kUnknown(0),
kMJPGStreamer(1),
kCSCore(2),
kAxis(3);
private final int value;
HttpCameraKind(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* Convert from the numerical representation of kind to an enum type.
*
* @param kind The numerical representation of kind
* @return The kind
*/
public static HttpCameraKind getHttpCameraKindFromInt(int kind) {
switch (kind) {
case 1:
return HttpCameraKind.kMJPGStreamer;
case 2:
return HttpCameraKind.kCSCore;
case 3:
return HttpCameraKind.kAxis;
default:
return HttpCameraKind.kUnknown;
}
}
/**
* Create a source for a MJPEG-over-HTTP (IP) camera.
*
* @param name Source name (arbitrary unique identifier)
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
*/
public HttpCamera(String name, String url) {
super(CameraServerJNI.createHttpCamera(name, url, HttpCameraKind.kUnknown.getValue()));
}
/**
* Create a source for a MJPEG-over-HTTP (IP) camera.
*
* @param name Source name (arbitrary unique identifier)
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
* @param kind Camera kind (e.g. kAxis)
*/
public HttpCamera(String name, String url, HttpCameraKind kind) {
super(CameraServerJNI.createHttpCamera(name, url, kind.getValue()));
}
/**
* Create a source for a MJPEG-over-HTTP (IP) camera.
*
* @param name Source name (arbitrary unique identifier)
* @param urls Array of Camera URLs
*/
public HttpCamera(String name, String[] urls) {
super(CameraServerJNI.createHttpCameraMulti(name, urls, HttpCameraKind.kUnknown.getValue()));
}
/**
* Create a source for a MJPEG-over-HTTP (IP) camera.
*
* @param name Source name (arbitrary unique identifier)
* @param urls Array of Camera URLs
* @param kind Camera kind (e.g. kAxis)
*/
public HttpCamera(String name, String[] urls, HttpCameraKind kind) {
super(CameraServerJNI.createHttpCameraMulti(name, urls, kind.getValue()));
}
/**
* Get the kind of HTTP camera.
*
* <p>Autodetection can result in returning a different value than the camera was created with.
*/
public HttpCameraKind getHttpCameraKind() {
return getHttpCameraKindFromInt(CameraServerJNI.getHttpCameraKind(m_handle));
}
/** Change the URLs used to connect to the camera. */
public void setUrls(String[] urls) {
CameraServerJNI.setHttpCameraUrls(m_handle, urls);
}
/** Get the URLs used to connect to the camera. */
public String[] getUrls() {
return CameraServerJNI.getHttpCameraUrls(m_handle);
}
}

View File

@@ -1,34 +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.cscore;
public abstract class ImageSink extends VideoSink {
protected ImageSink(int handle) {
super(handle);
}
/**
* Set sink description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSinkDescription(m_handle, description);
}
/** Get error string. Call this if WaitForFrame() returns 0 to determine what the error is. */
public String getError() {
return CameraServerJNI.getSinkError(m_handle);
}
/**
* Enable or disable getting new frames. Disabling will cause processFrame (for callback-based
* CvSinks) to not be called and WaitForFrame() to not return. This can be used to save processor
* resources when frames are not needed.
*/
public void setEnabled(boolean enabled) {
CameraServerJNI.setSinkEnabled(m_handle, enabled);
}
}

View File

@@ -1,147 +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.cscore;
public abstract class ImageSource extends VideoSource {
protected ImageSource(int handle) {
super(handle);
}
/**
* Signal sinks that an error has occurred. This should be called instead of NotifyFrame when an
* error occurs.
*/
public void notifyError(String msg) {
CameraServerJNI.notifySourceError(m_handle, msg);
}
/**
* Set source connection status. Defaults to true.
*
* @param connected True for connected, false for disconnected
*/
public void setConnected(boolean connected) {
CameraServerJNI.setSourceConnected(m_handle, connected);
}
/**
* Set source description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSourceDescription(m_handle, description);
}
/**
* Create a property.
*
* @param name Property name
* @param kind Property kind
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createProperty(
String name,
VideoProperty.Kind kind,
int minimum,
int maximum,
int step,
int defaultValue,
int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(
m_handle, name, kind.getValue(), minimum, maximum, step, defaultValue, value));
}
/**
* Create an integer property.
*
* @param name Property name
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createIntegerProperty(
String name, int minimum, int maximum, int step, int defaultValue, int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(
m_handle,
name,
VideoProperty.Kind.kInteger.getValue(),
minimum,
maximum,
step,
defaultValue,
value));
}
/**
* Create a boolean property.
*
* @param name Property name
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(
m_handle,
name,
VideoProperty.Kind.kBoolean.getValue(),
0,
1,
1,
defaultValue ? 1 : 0,
value ? 1 : 0));
}
/**
* Create a string property.
*
* @param name Property name
* @param value Current value
* @return Property
*/
public VideoProperty createStringProperty(String name, String value) {
VideoProperty prop =
new VideoProperty(
CameraServerJNI.createSourceProperty(
m_handle, name, VideoProperty.Kind.kString.getValue(), 0, 0, 0, 0, 0));
prop.setString(value);
return prop;
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
*/
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
* @deprecated Use {@code setEnumPropertyChoices} instead.
*/
@Deprecated
@SuppressWarnings("MethodName")
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
setEnumPropertyChoices(property, choices);
}
}

View File

@@ -1,91 +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.cscore;
/** A sink that acts as a MJPEG-over-HTTP network server. */
public class MjpegServer extends VideoSink {
/**
* Create a MJPEG-over-HTTP server sink.
*
* @param name Sink name (arbitrary unique identifier)
* @param listenAddress TCP listen address (empty string for all addresses)
* @param port TCP port number
*/
public MjpegServer(String name, String listenAddress, int port) {
super(CameraServerJNI.createMjpegServer(name, listenAddress, port));
}
/**
* Create a MJPEG-over-HTTP server sink.
*
* @param name Sink name (arbitrary unique identifier)
* @param port TCP port number
*/
public MjpegServer(String name, int port) {
this(name, "", port);
}
/** Get the listen address of the server. */
public String getListenAddress() {
return CameraServerJNI.getMjpegServerListenAddress(m_handle);
}
/** Get the port number of the server. */
public int getPort() {
return CameraServerJNI.getMjpegServerPort(m_handle);
}
/**
* Set the stream resolution for clients that don't specify it.
*
* <p>It is not necessary to set this if it is the same as the source resolution.
*
* <p>Setting this different than the source resolution will result in increased CPU usage,
* particularly for MJPEG source cameras, as it will decompress, resize, and recompress the image,
* instead of using the camera's MJPEG image directly.
*
* @param width width, 0 for unspecified
* @param height height, 0 for unspecified
*/
public void setResolution(int width, int height) {
CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "width"), width);
CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "height"), height);
}
/**
* Set the stream frames per second (FPS) for clients that don't specify it.
*
* <p>It is not necessary to set this if it is the same as the source FPS.
*
* @param fps FPS, 0 for unspecified
*/
public void setFPS(int fps) {
CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "fps"), fps);
}
/**
* Set the compression for clients that don't specify it.
*
* <p>Setting this will result in increased CPU usage for MJPEG source cameras as it will
* decompress and recompress the image instead of using the camera's MJPEG image directly.
*
* @param quality JPEG compression quality (0-100), -1 for unspecified
*/
public void setCompression(int quality) {
CameraServerJNI.setProperty(CameraServerJNI.getSinkProperty(m_handle, "compression"), quality);
}
/**
* Set the default compression used for non-MJPEG sources. If not set, 80 is used. This function
* has no effect on MJPEG source cameras; use SetCompression() instead to force recompression of
* MJPEG source images.
*
* @param quality JPEG compression quality (0-100)
*/
public void setDefaultCompression(int quality) {
CameraServerJNI.setProperty(
CameraServerJNI.getSinkProperty(m_handle, "default_compression"), quality);
}
}

Some files were not shown because too many files have changed in this diff Show More