├── .gitattributes ├── .gitignore ├── Cpp ├── build.gradle ├── cpp.gradle ├── dependencies.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── src │ └── main.cpp └── toolchains │ ├── arm.gradle │ ├── linux.gradle │ ├── mac.gradle │ ├── native.gradle │ └── windows.gradle └── Java ├── build.gradle ├── dependencies.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── readme.md └── src └── main └── java └── Main.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Force gradlew to have unix eols, so Windows does not break it 5 | gradlew text eol=lf 6 | 7 | # Custom for Visual Studio 8 | *.cs diff=csharp 9 | 10 | # Standard to msysgit 11 | *.doc diff=astextplain 12 | *.DOC diff=astextplain 13 | *.docx diff=astextplain 14 | *.DOCX diff=astextplain 15 | *.dot diff=astextplain 16 | *.DOT diff=astextplain 17 | *.pdf diff=astextplain 18 | *.PDF diff=astextplain 19 | *.rtf diff=astextplain 20 | *.RTF diff=astextplain 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### C++ ### 2 | # Compiled Object files 3 | *.slo 4 | *.lo 5 | *.o 6 | *.obj 7 | 8 | # Precompiled Headers 9 | *.gch 10 | *.pch 11 | 12 | # Compiled Dynamic libraries 13 | *.so 14 | *.dylib 15 | *.dll 16 | 17 | # Compiled Static libraries 18 | *.lai 19 | *.la 20 | *.a 21 | *.lib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | 28 | .vs/ 29 | *.def 30 | !ntcore.def 31 | !ntcore-jni.def 32 | *.opensdf 33 | *.vcxproj 34 | *.vcxproj.user 35 | *.sdf 36 | *.sublime-project 37 | *.sublime-workspace 38 | 39 | # Compiled Java files 40 | *.class 41 | 42 | # Build directories 43 | /.gradle 44 | /build* 45 | !build.gradle 46 | /native 47 | /arm 48 | /gmock/build 49 | /release 50 | 51 | 52 | # Created by https://www.gitignore.io/api/intellij,eclipse,netbeans,java,gradle,c++,cmake 53 | 54 | ### Intellij ### 55 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 56 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 57 | 58 | # User-specific stuff: 59 | .idea/* 60 | 61 | ## File-based project format: 62 | *.iws 63 | 64 | ## Plugin-specific files: 65 | 66 | # IntelliJ 67 | /out/ 68 | 69 | # mpeltonen/sbt-idea plugin 70 | .idea_modules/ 71 | 72 | # JIRA plugin 73 | atlassian-ide-plugin.xml 74 | 75 | # Crashlytics plugin (for Android Studio and IntelliJ) 76 | com_crashlytics_export_strings.xml 77 | crashlytics.properties 78 | crashlytics-build.properties 79 | fabric.properties 80 | 81 | ### Intellij Patch ### 82 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 83 | 84 | # *.iml 85 | # modules.xml 86 | 87 | 88 | ### Eclipse ### 89 | 90 | .metadata 91 | bin/ 92 | tmp/ 93 | *.tmp 94 | *.bak 95 | *.swp 96 | *~.nib 97 | local.properties 98 | .settings/ 99 | .loadpath 100 | .recommenders 101 | 102 | # Eclipse Core 103 | .project 104 | 105 | # External tool builders 106 | .externalToolBuilders/ 107 | 108 | # Locally stored "Eclipse launch configurations" 109 | *.launch 110 | 111 | # PyDev specific (Python IDE for Eclipse) 112 | *.pydevproject 113 | 114 | # CDT-specific (C/C++ Development Tooling) 115 | .cproject 116 | 117 | # JDT-specific (Eclipse Java Development Tools) 118 | .classpath 119 | 120 | # Java annotation processor (APT) 121 | .factorypath 122 | 123 | # PDT-specific (PHP Development Tools) 124 | .buildpath 125 | 126 | # sbteclipse plugin 127 | .target 128 | 129 | # Tern plugin 130 | .tern-project 131 | 132 | # TeXlipse plugin 133 | .texlipse 134 | 135 | # STS (Spring Tool Suite) 136 | .springBeans 137 | 138 | # Code Recommenders 139 | .recommenders/ 140 | 141 | 142 | ### NetBeans ### 143 | nbproject/private/ 144 | build/ 145 | nbbuild/ 146 | dist/ 147 | nbdist/ 148 | nbactions.xml 149 | .nb-gradle/ 150 | 151 | 152 | ### C++ ### 153 | # Compiled Object files 154 | *.slo 155 | *.lo 156 | *.o 157 | *.obj 158 | 159 | # Precompiled Headers 160 | *.gch 161 | *.pch 162 | 163 | # Compiled Dynamic libraries 164 | *.so 165 | *.dylib 166 | *.dll 167 | 168 | # Fortran module files 169 | *.mod 170 | 171 | # Compiled Static libraries 172 | *.lai 173 | *.la 174 | *.a 175 | *.lib 176 | 177 | # Executables 178 | *.exe 179 | *.out 180 | *.app 181 | 182 | 183 | ### CMake ### 184 | CMakeCache.txt 185 | CMakeFiles 186 | CMakeScripts 187 | Makefile 188 | cmake_install.cmake 189 | install_manifest.txt 190 | 191 | 192 | ### Java ### 193 | *.class 194 | 195 | # Mobile Tools for Java (J2ME) 196 | .mtj.tmp/ 197 | 198 | # Package Files # 199 | *.jar 200 | *.war 201 | *.ear 202 | 203 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 204 | hs_err_pid* 205 | 206 | 207 | ### Gradle ### 208 | .gradle 209 | build/ 210 | 211 | # Ignore Gradle GUI config 212 | gradle-app.setting 213 | 214 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 215 | !gradle-wrapper.jar 216 | 217 | # Cache of project 218 | .gradletasknamecache 219 | 220 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 221 | # gradle/wrapper/gradle-wrapper.properties 222 | 223 | #VSCode 224 | .vscode/ 225 | output/ -------------------------------------------------------------------------------- /Cpp/build.gradle: -------------------------------------------------------------------------------- 1 | // This is where you select which operating system to build for. 2 | // Uncomment the line below to build for windows 3 | ext.buildType = "windows" 4 | 5 | // Uncomment the line below to build for linux 6 | //ext.buildType = "linux" 7 | 8 | // Uncomment the 4 lines below starting with ext. to cross compile for a Raspberry Pi running raspbian. 9 | //ext.buildType = "arm-raspbian" // Do not change this string 10 | //ext.compilerPrefix = "arm-linux-gnueabihf-" // Should not have to change this string, see readme for more 11 | //ext.armSuffix = "-raspbian" // Do not change this string 12 | //ext.toolChainPath = "CHANGE_ME_PATH_TO_COMPILER_HERE" 13 | 14 | // Uncomment the 4 lines below starting with ext. to cross compile for an armhf device such as a Jetson or a Beaglebone Black 15 | //ext.buildType = "armhf" // Do not change this string 16 | //ext.compilerPrefix = "arm-linux-gnueabihf-" // Should not have to change this string, see readme for more 17 | //ext.armSuffix = "hf" // Do not change this string 18 | //ext.toolChainPath = "CHANGE_ME_PATH_TO_COMPILER_HERE" // See Readme to see what this needs to be specified to 19 | 20 | // Uncomment the 3 lines below starting with ext. to natively build for a Raspberry Pi running raspbian. Use this if you are building on the Pi itself 21 | //ext.buildType = "arm-raspbian" 22 | //ext.compilerPrefix = "" 23 | //ext.armSuffix = "-raspbian" 24 | 25 | // Uncomment the 3 lines below starting with ext. to natively build for an armhf device such as a Jetson or a Beaglebone Black. Use this if you are building on the device itself 26 | //ext.buildType = "armhf" 27 | //ext.compilerPrefix = "" 28 | //ext.armSuffix = "hf" 29 | 30 | // Set this to true to use the 32 bit built binary rather then the 64 bit binary 31 | // Usually keep this false 32 | ext.use32Bit = false 33 | 34 | 35 | // Shouldn't need to change anything below this point 36 | ext.getPlatformPath2 = { targetPlatform -> 37 | if (targetPlatform.architecture.arm) { 38 | return 'Linux/arm' 39 | } else if (targetPlatform.operatingSystem.linux) { 40 | if (targetPlatform.architecture.amd64) { 41 | return 'Linux/amd64' 42 | } else { 43 | return 'Linux/' + targetPlatform.architecture.name 44 | } 45 | } else if (targetPlatform.operatingSystem.windows) { 46 | if (targetPlatform.architecture.amd64) { 47 | return 'Windows/amd64' 48 | } else { 49 | return 'Windows/' + targetPlatform.architecture.name 50 | } 51 | } else if (targetPlatform.operatingSystem.macOsX) { 52 | if (targetPlatform.architecture.amd64) { 53 | return 'Mac OS X/x86_64' 54 | } else { 55 | return 'Mac OS X/' + targetPlatform.architecture.name 56 | } 57 | } else { 58 | return targetPlatform.operatingSystem.name + '/' + targetPlatform.architecture.name 59 | } 60 | } 61 | 62 | ext.getPlatformPath = { binary -> 63 | return getPlatformPath2(binary.targetPlatform) 64 | } 65 | 66 | 67 | apply from: 'dependencies.gradle' 68 | 69 | ext.setupDefines = { project, binaries -> 70 | binaries.all { 71 | if (project.hasProperty('debug')) { 72 | project.setupDebugDefines(cppCompiler, linker) 73 | } else { 74 | project.setupReleaseDefines(cppCompiler, linker) 75 | } 76 | tasks.withType(CppCompile) { 77 | project.addCsCoreLibraryLinks(it, linker, targetPlatform) 78 | project.addOpenCvLibraryLinks(it, linker, targetPlatform) 79 | project.addNtCoreLibraryLinks(it, linker, targetPlatform) 80 | project.addWpiUtilLibraryLinks(it, linker, targetPlatform) 81 | } 82 | } 83 | } 84 | 85 | repositories { 86 | mavenCentral() 87 | maven { 88 | url "http://first.wpi.edu/FRC/roborio/maven/release" 89 | } 90 | } 91 | 92 | apply from: 'cpp.gradle' 93 | 94 | def outputDir = file("${rootDir}/output") 95 | 96 | task copyToOutput(type: Copy) { 97 | dependsOn assemble 98 | destinationDir = outputDir 99 | model { 100 | binaries { 101 | withType(NativeExecutableBinarySpec) { binary -> 102 | from(binary.executableFile) { 103 | if (targetPlatform.operatingSystem.windows || targetPlatform.operatingSystem.linux) { 104 | if (targetPlatform.architecture.amd64) { 105 | into '64bit' 106 | } else { 107 | into '32bit' 108 | } 109 | } 110 | else { 111 | into 'arm' 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | clean { 120 | delete outputDir 121 | } 122 | 123 | build.dependsOn copyToOutput -------------------------------------------------------------------------------- /Cpp/cpp.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.os.OperatingSystem 2 | 3 | def appSetupModel = { project -> 4 | project.model { 5 | components { 6 | CameraVision(NativeExecutableSpec) { 7 | if (project.isArm) { 8 | targetPlatform 'arm' 9 | } else { 10 | if (buildType == "windows") { 11 | targetPlatform 'x86' 12 | } 13 | targetPlatform 'x64' 14 | } 15 | setupDefines(project, binaries) 16 | 17 | sources { 18 | cpp { 19 | source { 20 | srcDirs = ["${rootDir}/src"] 21 | includes = ['**/*.cpp'] 22 | } 23 | exportedHeaders { 24 | srcDirs = ["${rootDir}/include", project.wpiUtilInclude, project.openCvInclude, 25 | project.csCoreInclude, project.ntCoreInclude] 26 | includes = ['**/*.h'] 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | 35 | apply plugin: 'cpp' 36 | 37 | if (buildType == "windows" || buildType == "linux") { 38 | apply from: "${rootDir}/toolchains/native.gradle" 39 | } else { 40 | apply from: "${rootDir}/toolchains/arm.gradle" 41 | } 42 | 43 | appSetupModel(project) 44 | useWpiUtil(project) 45 | useOpenCv(project) 46 | useCsCore(project) 47 | useNtCore(project) -------------------------------------------------------------------------------- /Cpp/dependencies.gradle: -------------------------------------------------------------------------------- 1 | ext.useWpiUtil = { project -> 2 | project.tasks.create(name: "downloadWpiUtil") { 3 | description = 'Downloads the wpiutil maven dependency.' 4 | group = 'WPILib' 5 | def depFolder = "${project.buildDir}/dependencies" 6 | def utilZip = file("${depFolder}/wpiutil.zip") 7 | outputs.file(utilZip) 8 | def wpiUtil 9 | 10 | doFirst { 11 | def wpiUtilDependency 12 | def classifier 13 | if (buildType == "windows") { 14 | classifier = "windows2015" 15 | } else if (buildType == "linux") { 16 | classifier = "desktop" 17 | } else { 18 | classifier = buildType 19 | } 20 | wpiUtilDependency = project.dependencies.create("edu.wpi.first.wpilib:wpiutil:+:${classifier}@zip") 21 | def wpiUtilConfig = project.configurations.detachedConfiguration(wpiUtilDependency) 22 | wpiUtilConfig.setTransitive(false) 23 | wpiUtil = wpiUtilConfig.files[0].canonicalFile 24 | } 25 | 26 | doLast { 27 | copy { 28 | from wpiUtil 29 | rename 'wpiutil(.+)', 'wpiutil.zip' 30 | into depFolder 31 | } 32 | } 33 | } 34 | 35 | def wpiUtilUnzipLocation = "${project.buildDir}/wpiutil" 36 | 37 | // Create a task that will unzip the wpiutil files into a temporary build directory 38 | project.tasks.create(name: "unzipWpiUtil", type: Copy) { 39 | description = 'Unzips the wpiutil maven dependency so that the include files and libraries can be used' 40 | group = 'WPILib' 41 | dependsOn project.tasks.downloadWpiUtil 42 | from zipTree(project.tasks.downloadWpiUtil.outputs.files.singleFile) 43 | into wpiUtilUnzipLocation 44 | } 45 | 46 | project.ext.wpiUtil = wpiUtilUnzipLocation 47 | project.ext.wpiUtilInclude = "$wpiUtilUnzipLocation/include" 48 | 49 | project.ext.addWpiUtilLibraryLinks = { compileTask, linker, targetPlatform -> 50 | compileTask.dependsOn project.tasks.unzipWpiUtil 51 | String path = project.getPlatformPath2(targetPlatform) 52 | if (targetPlatform.operatingSystem.windows) { 53 | linker.args "${project.wpiUtil}/${path}/wpiutil.lib" 54 | } else { 55 | linker.args "${project.wpiUtil}/${path}/libwpiutil.a" 56 | } 57 | } 58 | } 59 | 60 | ext.useNtCore = { project -> 61 | project.tasks.create(name: "downloadNtCore") { 62 | description = 'Downloads the ntcore maven dependency.' 63 | group = 'WPILib' 64 | def depFolder = "${project.buildDir}/dependencies" 65 | def utilZip = file("${depFolder}/ntcore.zip") 66 | outputs.file(utilZip) 67 | def ntCore 68 | 69 | doFirst { 70 | def ntCoreDependency 71 | def classifier 72 | if (buildType == "windows") { 73 | classifier = "windows2015" 74 | } else if (buildType == "linux") { 75 | classifier = "desktop" 76 | } else { 77 | classifier = buildType 78 | } 79 | ntCoreDependency = project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:${classifier}@zip") 80 | def ntCoreConfig = project.configurations.detachedConfiguration(ntCoreDependency) 81 | ntCoreConfig.setTransitive(false) 82 | ntCore = ntCoreConfig.files[0].canonicalFile 83 | } 84 | 85 | doLast { 86 | copy { 87 | from ntCore 88 | rename 'NetworkTables(.+)', 'ntcore.zip' 89 | into depFolder 90 | } 91 | } 92 | } 93 | 94 | def ntCoreUnzipLocation = "${project.buildDir}/ntcore" 95 | 96 | // Create a task that will unzip the ntcore files into a temporary build directory 97 | project.tasks.create(name: "unzipNtCore", type: Copy) { 98 | description = 'Unzips the ntcore maven dependency so that the include files and libraries can be used' 99 | group = 'WPILib' 100 | dependsOn project.tasks.downloadNtCore 101 | from zipTree(project.tasks.downloadNtCore.outputs.files.singleFile) 102 | into ntCoreUnzipLocation 103 | } 104 | 105 | project.ext.ntCore = ntCoreUnzipLocation 106 | project.ext.ntCoreInclude = "$ntCoreUnzipLocation/include" 107 | 108 | project.ext.addNtCoreLibraryLinks = { compileTask, linker, targetPlatform -> 109 | compileTask.dependsOn project.tasks.unzipNtCore 110 | String path = project.getPlatformPath2(targetPlatform) 111 | if (targetPlatform.operatingSystem.windows) { 112 | linker.args "${project.ntCore}/${path}/ntcore.lib" 113 | } else { 114 | linker.args "${project.ntCore}/${path}/libntcore.a" 115 | } 116 | } 117 | } 118 | 119 | ext.useCsCore = { project -> 120 | project.tasks.create(name: "downloadCsCore") { 121 | description = 'Downloads the cscore maven dependency.' 122 | group = 'WPILib' 123 | def depFolder = "${project.buildDir}/dependencies" 124 | def cszip = file("${depFolder}/cscore.zip") 125 | outputs.file(cszip) 126 | def cscore 127 | 128 | doFirst { 129 | def csCoreDependency 130 | def classifier 131 | if (buildType == "windows") { 132 | classifier = "windows2015" 133 | } else { 134 | classifier = buildType 135 | } 136 | csCoreDependency = project.dependencies.create("edu.wpi.cscore.cpp:cscore:+:${classifier}@zip") 137 | def csCoreConfig = project.configurations.detachedConfiguration(csCoreDependency) 138 | csCoreConfig.setTransitive(false) 139 | cscore = csCoreConfig.files[0].canonicalFile 140 | } 141 | 142 | doLast { 143 | copy { 144 | from cscore 145 | rename 'cscore(.+)', 'cscore.zip' 146 | into depFolder 147 | } 148 | } 149 | } 150 | 151 | def csCoreUnzipLocation = "${project.buildDir}/cscore" 152 | 153 | // Create a task that will unzip the cscore files into a temporary build directory 154 | project.tasks.create(name: "unzipCsCore", type: Copy) { 155 | description = 'Unzips the cscore maven dependency so that the include files and libraries can be used' 156 | group = 'WPILib' 157 | dependsOn project.tasks.downloadCsCore 158 | from zipTree(project.tasks.downloadCsCore.outputs.files.singleFile) 159 | into csCoreUnzipLocation 160 | } 161 | 162 | project.ext.csCore = csCoreUnzipLocation 163 | project.ext.csCoreInclude = "$csCoreUnzipLocation/include" 164 | 165 | project.ext.addCsCoreLibraryLinks = { compileTask, linker, targetPlatform -> 166 | compileTask.dependsOn project.tasks.unzipCsCore 167 | String path = project.getPlatformPath2(targetPlatform) 168 | if (targetPlatform.operatingSystem.windows) { 169 | linker.args "${project.csCore}/${path}/cscore.lib" 170 | } else { 171 | linker.args "${project.csCore}/${path}/libcscore.a" 172 | } 173 | } 174 | } 175 | 176 | ext.getOpenCvPlatformPackage = { targetPlatform -> 177 | if (buildType == "armhf") { 178 | return "linux-armhf" 179 | } else if (buildType == "arm-raspbian") { 180 | return "linux-arm-raspbian" 181 | } else if (targetPlatform.architecture.arm && project.hasProperty('compilerPrefix') && project.hasProperty('armSuffix')) { 182 | return "linux-arm${project.armSuffix}" 183 | } else if (targetPlatform.architecture.arm) { 184 | return 'linux-arm' 185 | } else if (targetPlatform.operatingSystem.linux) { 186 | if (targetPlatform.architecture.amd64) { 187 | return 'linux-x86_64' 188 | } else { 189 | return 'linux-' + targetPlatform.architecture.name 190 | } 191 | } else if (targetPlatform.operatingSystem.windows) { 192 | if (targetPlatform.architecture.amd64) { 193 | return 'windows-x86_64_2015' 194 | } else { 195 | return 'windows-' + targetPlatform.architecture.name + '_2015' 196 | } 197 | } else if (targetPlatform.operatingSystem.macOsX) { 198 | if (targetPlatform.architecture.amd64) { 199 | return 'osx-x86_64' 200 | } else { 201 | return 'osx-' + targetPlatform.architecture.name 202 | } 203 | } else { 204 | return targetPlatform.operatingSystem.name + '-' + targetPlatform.architecture.name 205 | } 206 | } 207 | 208 | task downloadOpenCvHeaders() { 209 | description = 'Downloads the OpenCV Headers maven dependency.' 210 | group = 'WPILib' 211 | def depFolder = "${buildDir}/dependencies" 212 | def openCvHeadersZip = file("${depFolder}/opencv-headers.zip") 213 | outputs.file(openCvHeadersZip) 214 | def openCvHeaders 215 | 216 | doFirst { 217 | def openCvHeadersDependency = project.dependencies.create("org.opencv:opencv-headers:3.1.0@jar") 218 | def openCvHeadersConfig = project.configurations.detachedConfiguration(openCvHeadersDependency) 219 | openCvHeadersConfig.setTransitive(false) 220 | openCvHeaders = openCvHeadersConfig.files[0].canonicalFile 221 | } 222 | 223 | doLast { 224 | copy { 225 | from openCvHeaders 226 | rename 'opencv-headers(.+)', 'opencv-headers.zip' 227 | into depFolder 228 | } 229 | } 230 | } 231 | 232 | ext.useOpenCv = { project -> 233 | def openCvUnzipLocation = "${project.buildDir}/opencv" 234 | 235 | project.tasks.create(name: "unzipOpenCvHeaders", type: Copy) { 236 | description = 'Unzips the OpenCV maven dependency so that the include files and libraries can be used' 237 | group = 'OpenCv' 238 | dependsOn downloadOpenCvHeaders 239 | from zipTree(downloadOpenCvHeaders.outputs.files.singleFile) 240 | into "${openCvUnzipLocation}/include" 241 | } 242 | 243 | project.ext.openCv = openCvUnzipLocation 244 | project.ext.openCvInclude = "$openCvUnzipLocation/include" 245 | 246 | project.ext.addOpenCvLibraryLinks = { compileTask, linker, targetPlatform -> 247 | def openCvPlatform = project.getOpenCvPlatformPackage(targetPlatform) 248 | def openCvNativesFolder = "${project.openCv}/${openCvPlatform}" 249 | 250 | if (project.tasks.findByPath("unzipOpenCvNatives_${openCvPlatform}") == null) { 251 | project.tasks.create(name: "downloadOpenCvNatives_${openCvPlatform}") { 252 | description = 'Downloads the OpenCV natives maven dependency.' 253 | group = 'OpenCv' 254 | def depFolder = "${project.buildDir}/dependencies" 255 | def openCvNativesZip = file("${depFolder}/opencv-natives-${openCvPlatform}.zip") 256 | outputs.file(openCvNativesZip) 257 | def openCvNatives 258 | 259 | doFirst { 260 | def openCvNativesDependency = project.dependencies.create("org.opencv:opencv-natives:3.1.0:${openCvPlatform}@jar") 261 | def openCvNativesConfig = project.configurations.detachedConfiguration(openCvNativesDependency) 262 | openCvNativesConfig.setTransitive(false) 263 | openCvNatives = openCvNativesConfig.files[0].canonicalFile 264 | } 265 | 266 | doLast { 267 | copy { 268 | from openCvNatives 269 | rename 'opencv-natives(.+)', "opencv-natives-${openCvPlatform}.zip" 270 | into depFolder 271 | } 272 | } 273 | } 274 | 275 | project.tasks.create(name: "unzipOpenCvNatives_${openCvPlatform}", type: Copy) { 276 | description = 'Unzips the OpenCV maven dependency so that the include files and libraries can be used' 277 | group = 'OpenCv' 278 | dependsOn "downloadOpenCvNatives_${openCvPlatform}" 279 | from zipTree(project.tasks["downloadOpenCvNatives_${openCvPlatform}"].outputs.files.singleFile) 280 | into openCvNativesFolder 281 | exclude '**/MANIFEST.MF' 282 | } 283 | } 284 | 285 | compileTask.dependsOn "unzipOpenCvHeaders", "unzipOpenCvNatives_${openCvPlatform}" 286 | if (targetPlatform.operatingSystem.windows) { 287 | linker.args new String("${openCvNativesFolder}\\opencv.lib").replace('/', '\\') 288 | linker.args new String("${openCvNativesFolder}\\Release\\libjpeg.lib").replace('/', '\\') 289 | linker.args new String("${openCvNativesFolder}\\Release\\libpng.lib").replace('/', '\\') 290 | linker.args new String("${openCvNativesFolder}\\Release\\zlib.lib").replace('/', '\\') 291 | linker.args "kernel32.lib" 292 | linker.args "user32.lib" 293 | linker.args "gdi32.lib" 294 | linker.args "Ole32.lib" 295 | linker.args "OleAut32.lib" 296 | linker.args "comdlg32.lib" 297 | linker.args "advapi32.lib" 298 | linker.args "Vfw32.lib" 299 | } else { 300 | linker.args "-L${openCvNativesFolder}" 301 | linker.args "-lopencv" 302 | linker.args "-ldl" 303 | } 304 | } 305 | } -------------------------------------------------------------------------------- /Cpp/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpilibsuite/VisionBuildSamples/a98bf8a8819ae79b58e5738d05d357d465dc37a4/Cpp/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Cpp/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 04 18:53:29 PST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip 7 | -------------------------------------------------------------------------------- /Cpp/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /Cpp/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /Cpp/src/main.cpp: -------------------------------------------------------------------------------- 1 | // Workaround for working with GCC 5.4. Do not remove 2 | #define _GLIBCXX_USE_CXX11_ABI 0 3 | 4 | #include "cscore.h" 5 | #include "networktables/NetworkTable.h" 6 | #include "tables/ITable.h" 7 | #include 8 | #include 9 | #include "llvm/StringRef.h" 10 | #include "llvm/ArrayRef.h" 11 | #include 12 | #include 13 | #include 14 | 15 | cs::VideoCamera SetHttpCamera(llvm::StringRef cameraName, cs::MjpegServer& server); 16 | 17 | cs::UsbCamera SetUsbCamera(int cameraId, cs::MjpegServer& server); 18 | 19 | int main() { 20 | // Connect NetworkTables, and get access to the publishing table 21 | NetworkTable::SetClientMode(); 22 | // Set your team number here 23 | NetworkTable::SetTeam(9999); 24 | 25 | NetworkTable::Initialize(); 26 | 27 | // This is the network port you want to stream the raw received image to 28 | // By rules, this has to be between 1180 and 1190, so 1185 is a good choice 29 | int streamPort = 1185; 30 | 31 | // This stores our reference to our mjpeg server for streaming the input image 32 | cs::MjpegServer inputStream("MJPEG Server", streamPort); 33 | 34 | // Uncomment one of the 2 following camera options 35 | // The top one receives a stream from another device, and performs operations based on that 36 | // On windows, this one must be used since USB is not supported 37 | // The bottom one opens a USB camera, and performs operations on that, along with streaming 38 | // the input image so other devices can see it. 39 | 40 | // HTTP Camera 41 | /* 42 | // This is our camera name from the robot. this can be set in your robot code with the following command 43 | // CameraServer.getInstance().startAutomaticCapture("YourCameraNameHere"); 44 | // "USB Camera 0" is the default if no string is specified 45 | llvm::StringRef cameraName("USB Camera 0"); 46 | cs::VideoCamera camera = SetHttpCamera(cameraName, inputStream); 47 | // It is possible for the camera to be null. If it is, that means no camera could 48 | // be found using NetworkTables to connect to. Create an HttpCamera by giving a specified stream 49 | if (!camera) { 50 | camera = cs::HttpCamera{"CoprocessorCamera", "YourURLHere"}; 51 | inputStream.SetSource(camera); 52 | } 53 | */ 54 | 55 | 56 | 57 | /***********************************************/ 58 | 59 | // USB Camera 60 | /* 61 | // This gets the image from a USB camera 62 | // Usually this will be on device 0, but there are other overloads 63 | // that can be used 64 | cs::UsbCamera camera = SetUsbCamera(0, inputStream); 65 | // Set the resolution for our camera, since this is over USB 66 | camera.SetResolution(640,480); 67 | */ 68 | 69 | // This creates a CvSink for us to use. This grabs images from our selected camera, 70 | // and will allow us to use those images in opencv 71 | cs::CvSink imageSink("CV Image Grabber"); 72 | imageSink.SetSource(camera); 73 | 74 | // This creates a CvSource to use. This will take in a Mat image that has had OpenCV operations 75 | // operations 76 | cs::CvSource imageSource("CV Image Source", cs::VideoMode::PixelFormat::kMJPEG, 640, 480, 30); 77 | cs::MjpegServer cvStream("CV Image Stream", 1186); 78 | cvStream.SetSource(imageSource); 79 | 80 | // All Mats and Lists should be stored outside the loop to avoid allocations 81 | // as they are expensive to create 82 | cv::Mat inputImage; 83 | cv::Mat hsv; 84 | 85 | // Infinitely process image 86 | while (true) { 87 | // Grab a frame. If it has a frame time of 0, there was an error. 88 | // Just skip and continue 89 | auto frameTime = imageSink.GrabFrame(inputImage); 90 | if (frameTime == 0) continue; 91 | 92 | // Below is where you would do your OpenCV operations on the provided image 93 | // The sample below just changes color source to HSV 94 | cvtColor(inputImage, hsv, cv::COLOR_BGR2HSV); 95 | 96 | // Here is where you would write a processed image that you want to restreams 97 | // This will most likely be a marked up image of what the camera sees 98 | // For now, we are just going to stream the HSV image 99 | imageSource.PutFrame(hsv); 100 | } 101 | } 102 | 103 | cs::VideoCamera SetHttpCamera(llvm::StringRef cameraName, cs::MjpegServer& server) { 104 | // Start by grabbing the camera from NetworkTables 105 | auto publishingTable = NetworkTable::GetTable("CameraPublisher"); 106 | // Wait for robot to connect. Allow this to be attempted indefinitely 107 | while (true) { 108 | if (publishingTable->GetSubTables().size() > 0) { 109 | break; 110 | } 111 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 112 | } 113 | 114 | if (!publishingTable->ContainsSubTable(cameraName)) { 115 | return cs::VideoCamera(); 116 | } 117 | auto cameraTable = publishingTable->GetSubTable(cameraName); 118 | auto urls = cameraTable->GetStringArray("streams", llvm::ArrayRef()); 119 | if (urls.size() == 0) { 120 | return cs::VideoCamera(); 121 | } 122 | llvm::SmallVector fixedUrls; 123 | for (auto&& i : urls) { 124 | llvm::StringRef url{i}; 125 | if (url.startswith("mjpg")) { 126 | fixedUrls.emplace_back(url.split(":").second); 127 | } 128 | } 129 | cs::HttpCamera camera("CoprocessorCamera", fixedUrls); 130 | server.SetSource(camera); 131 | return camera; 132 | } 133 | 134 | cs::UsbCamera SetUsbCamera(int cameraId, cs::MjpegServer& server) { 135 | #ifdef _WIN32 136 | // On windows, return empty because this doesn't work 137 | throw std::exception("Cannot use USB cameras on windows"); 138 | #else 139 | cs::UsbCamera camera("CoprocessorCamera", cameraId); 140 | server.SetSource(camera); 141 | return camera; 142 | #endif 143 | } -------------------------------------------------------------------------------- /Cpp/toolchains/arm.gradle: -------------------------------------------------------------------------------- 1 | ext.isArm = true 2 | ext.buildPlatform = 'arm' 3 | 4 | def compilerPrefix = project.hasProperty('compilerPrefix') ? project.compilerPrefix : 'arm-frc-linux-gnueabi-' 5 | def toolChainPath = project.hasProperty('toolChainPath') ? project.toolChainPath : null 6 | model { 7 | platforms { 8 | arm { 9 | architecture 'arm' 10 | operatingSystem 'linux' 11 | } 12 | } 13 | toolChains { 14 | armGcc(Gcc) { 15 | if (toolChainPath != null) path(toolChainPath) 16 | target("arm") { 17 | // We use a custom-built cross compiler with the prefix arm-frc-linux-gnueabi- 18 | // If this ever changes, the prefix will need to be changed here 19 | cCompiler.executable = compilerPrefix + cCompiler.executable 20 | cppCompiler.executable = compilerPrefix + cppCompiler.executable 21 | linker.executable = compilerPrefix + linker.executable 22 | assembler.executable = compilerPrefix + assembler.executable 23 | // Gradle auto-adds the -m32 argument to the linker and compiler. Our compiler only supports 24 | // arm, and doesn't understand this flag, so it is removed from both 25 | cppCompiler.withArguments { args -> 26 | args << '-std=c++1y' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic' 27 | args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-rdynamic' 28 | //TODO: When the compiler allows us to actually call deprecated functions from within 29 | // deprecated function, remove this line (this will cause calling deprecated functions 30 | // to be treated as a warning rather than an error). 31 | args << '-Wno-error=deprecated-declarations' << '-pthread' 32 | args.remove('-m32') 33 | } 34 | linker.withArguments { args -> 35 | args << '-rdynamic' << '-pthread' 36 | args.remove('-m32') 37 | } 38 | staticLibArchiver.executable = compilerPrefix + staticLibArchiver.executable 39 | } 40 | } 41 | } 42 | } 43 | 44 | ext.binTools = { tool -> 45 | if (toolChainPath != null) return "${toolChainPath}/${compilerPrefix}${tool}" 46 | return "${compilerPrefix}${tool}" 47 | } 48 | 49 | ext.setupReleaseDefines = { cppCompiler, linker -> 50 | cppCompiler.args '-O2', '-g' 51 | } 52 | 53 | ext.setupDebugDefines = { cppCompiler, linker -> 54 | cppCompiler.args '-g', '-O0' 55 | } 56 | 57 | // Used only on Windows. 58 | ext.setupDef = { linker, deffile -> } 59 | 60 | ext.debugStripSetup = { 61 | if (!project.hasProperty('debug')) { 62 | project.tasks.whenObjectAdded { task -> 63 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 64 | def library = task.outputFile.absolutePath 65 | def debugLibrary = task.outputFile.absolutePath + ".debug" 66 | task.doLast { 67 | exec { commandLine binTools('objcopy'), '--only-keep-debug', library, debugLibrary } 68 | exec { commandLine binTools('strip'), '-g', library } 69 | exec { commandLine binTools('objcopy'), "--add-gnu-debuglink=$debugLibrary", library } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | ext.checkNativeSymbols = { getSymbolFunc -> 77 | project.tasks.whenObjectAdded { task -> 78 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 79 | def library = task.outputFile.absolutePath 80 | task.doLast { 81 | def nmOutput = new ByteArrayOutputStream() 82 | exec { 83 | commandLine binTools('nm'), library 84 | standardOutput nmOutput 85 | } 86 | // Remove '\r' so we can check for full string contents 87 | String nmSymbols = nmOutput.toString().replace('\r', '') 88 | 89 | def symbolList = getSymbolFunc() 90 | symbolList.each { 91 | //Add \n so we can check for the exact symbol 92 | def found = nmSymbols.contains(it + '\n') 93 | if (!found) { 94 | throw new GradleException("Found a definition that does not have a matching symbol ${it}") 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Cpp/toolchains/linux.gradle: -------------------------------------------------------------------------------- 1 | model { 2 | toolChains { 3 | gcc(Gcc) { 4 | target('x86') { 5 | cppCompiler.withArguments { args -> 6 | args << '-std=c++11' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic' 7 | args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-rdynamic' 8 | //TODO: When the compiler allows us to actually call deprecated functions from within 9 | // deprecated function, remove this line (this will cause calling deprecated functions 10 | // to be treated as a warning rather than an error). 11 | args << '-Wno-error=deprecated-declarations' << '-pthread' 12 | args << '-m32' 13 | } 14 | linker.withArguments { args -> 15 | args << '-rdynamic' << '-pthread' 16 | args << '-m32' 17 | } 18 | } 19 | target('x64') { 20 | cppCompiler.withArguments { args -> 21 | args << '-std=c++11' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic' 22 | args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-rdynamic' 23 | //TODO: When the compiler allows us to actually call deprecated functions from within 24 | // deprecated function, remove this line (this will cause calling deprecated functions 25 | // to be treated as a warning rather than an error). 26 | args << '-Wno-error=deprecated-declarations' << '-pthread' 27 | } 28 | linker.withArguments { args -> 29 | args << '-rdynamic' << '-pthread' 30 | } 31 | } 32 | } 33 | } 34 | } 35 | 36 | ext.setupReleaseDefines = { cppCompiler, linker -> 37 | cppCompiler.args '-O2', '-g' 38 | } 39 | 40 | ext.setupDebugDefines = { cppCompiler, linker -> 41 | cppCompiler.args '-g', '-O0' 42 | } 43 | 44 | // Used only on Windows. 45 | ext.setupDef = { linker, deffile -> } 46 | 47 | ext.debugStripSetup = { 48 | if (!project.hasProperty('debug')) { 49 | project.tasks.whenObjectAdded { task -> 50 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 51 | def library = task.outputFile.absolutePath 52 | def debugLibrary = task.outputFile.absolutePath + ".debug" 53 | task.doLast { 54 | exec { commandLine "objcopy", '--only-keep-debug', library, debugLibrary } 55 | exec { commandLine "strip", '-g', library } 56 | exec { commandLine "objcopy", "--add-gnu-debuglink=$debugLibrary", library } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | ext.checkNativeSymbols = { getSymbolFunc -> 64 | project.tasks.whenObjectAdded { task -> 65 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 66 | def library = task.outputFile.absolutePath 67 | task.doLast { 68 | def nmOutput = new ByteArrayOutputStream() 69 | exec { 70 | commandLine "nm", library 71 | standardOutput nmOutput 72 | } 73 | // Remove '\r' so we can check for full string contents 74 | String nmSymbols = nmOutput.toString().replace('\r', '') 75 | 76 | def symbolList = getSymbolFunc() 77 | symbolList.each { 78 | //Add \n so we can check for the exact symbol 79 | def found = nmSymbols.contains(it + '\n') 80 | if (!found) { 81 | throw new GradleException("Found a definition that does not have a matching symbol ${it}") 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Cpp/toolchains/mac.gradle: -------------------------------------------------------------------------------- 1 | model { 2 | toolChains { 3 | clang(Clang) { 4 | target('x86') { 5 | cppCompiler.withArguments { args -> 6 | args << '-std=c++11' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic-errors' 7 | args << '-fPIC' << '-m32' 8 | args << '-Wno-unused-parameter' << '-Wno-missing-field-initializers' << '-Wno-unused-private-field' 9 | } 10 | linker.withArguments { args -> 11 | args << '-m32' 12 | } 13 | } 14 | target('x64') { 15 | cppCompiler.withArguments { args -> 16 | args << '-std=c++11' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic-errors' 17 | args << '-fPIC' 18 | args << '-Wno-missing-field-initializers' << '-Wno-unused-private-field' << '-Wno-unused-parameter' 19 | } 20 | } 21 | } 22 | } 23 | } 24 | 25 | ext.setupReleaseDefines = { cppCompiler, linker -> 26 | cppCompiler.args '-O2' 27 | } 28 | 29 | ext.setupDebugDefines = { cppCompiler, linker -> 30 | cppCompiler.args '-g', '-O0' 31 | } 32 | 33 | // Used only on Windows. 34 | ext.setupDef = { linker, deffile -> } 35 | 36 | ext.debugStripSetup = { 37 | if (!project.hasProperty('debug')) { 38 | project.tasks.whenObjectAdded { task -> 39 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 40 | def library = task.outputFile.absolutePath 41 | task.doLast { 42 | exec { commandLine "dsymutil", library } 43 | exec { commandLine "strip", '-S', library } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | ext.checkNativeSymbols = { getSymbolFunc -> 51 | project.tasks.whenObjectAdded { task -> 52 | if (task.name.contains('link') && task.name.contains('SharedLibrary')) { 53 | def library = task.outputFile.absolutePath 54 | task.doLast { 55 | def nmOutput = new ByteArrayOutputStream() 56 | exec { 57 | commandLine "nm", library 58 | standardOutput nmOutput 59 | } 60 | // Remove '\r' so we can check for full string contents 61 | String nmSymbols = nmOutput.toString().replace('\r', '') 62 | 63 | def symbolList = getSymbolFunc() 64 | symbolList.each { 65 | //Add \n so we can check for the exact symbol 66 | def found = nmSymbols.contains(it + '\n') 67 | if (!found) { 68 | throw new GradleException("Found a definition that does not have a matching symbol ${it}") 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Cpp/toolchains/native.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.os.OperatingSystem 2 | 3 | ext.isArm = false 4 | ext.buildPlatform = OperatingSystem.current().getFamilyName() 5 | 6 | if (OperatingSystem.current().isLinux()) { 7 | apply from: "${rootDir}/toolchains/linux.gradle" 8 | } else if (OperatingSystem.current().isMacOsX()) { 9 | apply from: "${rootDir}/toolchains/mac.gradle" 10 | } else if (OperatingSystem.current().isWindows()) { 11 | apply from: "${rootDir}/toolchains/windows.gradle" 12 | } else { 13 | throw new GradleException("${name} does not support building on ${ext.buildPlatform}.") 14 | } 15 | 16 | model { 17 | platforms { 18 | x86 { 19 | architecture 'x86' 20 | } 21 | x64 { 22 | architecture 'x86_64' 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Cpp/toolchains/windows.gradle: -------------------------------------------------------------------------------- 1 | model { 2 | toolChains { 3 | visualCpp(VisualCpp) { 4 | eachPlatform { 5 | cppCompiler.withArguments { args -> 6 | args << '/EHsc' << '/DNOMINMAX' << '/D_SCL_SECURE_NO_WARNINGS' << '/D_WINSOCK_DEPRECATED_NO_WARNINGS' 7 | } 8 | } 9 | } 10 | } 11 | } 12 | 13 | ext.setupReleaseDefines = { cppCompiler, linker -> 14 | cppCompiler.args '/O2', '/Zi', '/FS' 15 | } 16 | 17 | ext.setupDebugDefines = { cppCompiler, linker -> 18 | cppCompiler.args '/Zi', '/FS' 19 | linker.args '/DEBUG' 20 | } 21 | 22 | ext.setupDef = { linker, deffile -> 23 | linker.args "/DEF:${deffile}" 24 | } 25 | 26 | // This is a noop on Windows. On gcc platforms, we strip the release binary and create a separate 27 | // debug library, but Windows already separates debug symbols into a .pdb file. 28 | ext.debugStripSetup = { } 29 | 30 | // This is a noop on Windows. The def file already implicilty checks for the symbols 31 | ext.checkNativeSymbols = { getSymbolFunc -> 32 | } 33 | -------------------------------------------------------------------------------- /Java/build.gradle: -------------------------------------------------------------------------------- 1 | // Do not mess with the following 6 lines 2 | plugins { 3 | id 'com.github.johnrengelman.shadow' version '1.2.4' 4 | } 5 | 6 | apply plugin: 'java' 7 | apply plugin: 'application' 8 | 9 | 10 | // This is where you select which operating system to build for. 11 | 12 | // Uncomment the line below to build for windows 13 | //ext.buildType = "windows" 14 | 15 | // Uncomment the line below to build for a Raspberry Pi running raspbian 16 | //ext.buildType = "arm-raspbian" 17 | 18 | // Uncomment the line below to build for an armhf device such as a Jetson or a Beaglebone Black 19 | //ext.buildType = "armhf" 20 | 21 | // Change the line below if you change the name of your main Java class 22 | mainClassName = 'Main' 23 | // Change the line below to change the name of the output jar 24 | def projectName = 'CameraVision' 25 | 26 | // Shouldn't need to change anything below this point 27 | apply from: 'dependencies.gradle' 28 | 29 | repositories { 30 | mavenCentral() 31 | maven { 32 | url "http://first.wpi.edu/FRC/roborio/maven/release" 33 | } 34 | } 35 | 36 | dependencies { 37 | compile ntcoreDep() 38 | compile cscoreDep() 39 | compile 'org.opencv:opencv-java:3.1.0' 40 | } 41 | 42 | jar { 43 | baseName = projectName 44 | } 45 | 46 | shadowJar { 47 | baseName = projectName 48 | } 49 | 50 | distributions { 51 | main { 52 | baseName = projectName 53 | contents { 54 | from (openCvUnzipLocation) { 55 | exclude 'META-INF' 56 | exclude '**/MANIFEST.MF' 57 | into 'bin/' 58 | } 59 | } 60 | } 61 | } 62 | 63 | def outputDirectory = file("${rootDir}/output") 64 | 65 | task writeExecuteScript() { 66 | dependsOn jar 67 | doLast { 68 | if (buildType == "windows") { 69 | def runFile = new File("${buildDir}/run${projectName}.bat") 70 | runFile.write "java -Djava.library.path=. -jar ${projectName}-all.jar" 71 | } else { 72 | def runFile = new File("${buildDir}/run${projectName}") 73 | runFile.write "java -Djava.library.path=. -jar ${projectName}-all.jar" 74 | } 75 | } 76 | } 77 | 78 | task copyToOutput(type: Copy) { 79 | dependsOn shadowJar 80 | dependsOn unzipOpenCv 81 | dependsOn writeExecuteScript 82 | destinationDir = outputDirectory 83 | from (file(shadowJar.archivePath)) { 84 | } 85 | from (openCvUnzipLocation) { 86 | exclude 'META-INF' 87 | exclude '**/MANIFEST.MF' 88 | } 89 | if (buildType == "windows") { 90 | from (file("${buildDir}/run${projectName}.bat")) { 91 | } 92 | } else { 93 | from (file("${buildDir}/run${projectName}")) { 94 | } 95 | } 96 | } 97 | 98 | task zipOutput(type: Zip) { 99 | baseName = projectName 100 | duplicatesStrategy = 'exclude' 101 | dependsOn shadowJar 102 | dependsOn unzipOpenCv 103 | destinationDir = outputDirectory 104 | from (file(shadowJar.archivePath)) { 105 | } 106 | from (openCvUnzipLocation) { 107 | exclude 'META-INF' 108 | exclude '**/MANIFEST.MF' 109 | } 110 | if (buildType == "windows") { 111 | from (file("${buildDir}/run${projectName}.bat")) { 112 | } 113 | } else { 114 | from (file("${buildDir}/run${projectName}")) { 115 | fileMode 0777 116 | } 117 | } 118 | } 119 | 120 | distZip.dependsOn unzipOpenCv 121 | distTar.dependsOn unzipOpenCv 122 | 123 | applicationDefaultJvmArgs = ["-Djava.library.path=${openCvUnzipLocation}"] 124 | 125 | build.dependsOn copyToOutput 126 | build.dependsOn zipOutput 127 | run.dependsOn unzipOpenCv 128 | 129 | clean { 130 | delete outputDirectory 131 | } 132 | -------------------------------------------------------------------------------- /Java/dependencies.gradle: -------------------------------------------------------------------------------- 1 | ext.ntcoreDep = { -> 2 | def classifier 3 | if (buildType == "windows") { 4 | classifier = "windows2015" 5 | } else if (buildType == "linux") { 6 | classifier = "desktop" 7 | } else { 8 | classifier = buildType 9 | } 10 | return "edu.wpi.first.wpilib.networktables.java:NetworkTables:+:$classifier" 11 | } 12 | 13 | ext.cscoreDep = { -> 14 | def classifier 15 | if (buildType == "windows") { 16 | classifier = "windows2015" 17 | } else { 18 | classifier = buildType 19 | } 20 | return "edu.wpi.cscore.java:cscore:+:$classifier" 21 | } 22 | 23 | ext.getOpenCvPlatformPackage = { -> 24 | if (buildType == "windows") { 25 | if (System.getProperty("os.arch") == "amd64") { 26 | return "windows-x86_64_2015" 27 | } else { 28 | return "windows-x86_2015" 29 | } 30 | } else if (buildType == "linux") { 31 | if (System.getProperty("os.arch") == "amd64") { 32 | return "linux-x86_64" 33 | } else { 34 | return "linux-x86" 35 | } 36 | } else if (buildType == "armhf") { 37 | return "linux-armhf" 38 | } else if (buildType == "arm-raspbian") { 39 | return "linux-arm-raspbian" 40 | } else { 41 | return buildType 42 | } 43 | } 44 | 45 | task downloadOpenCv() { 46 | description = 'Downloads the OpenCV Native maven dependency.' 47 | group = 'WPILib' 48 | def depFolder = "$buildDir/dependencies" 49 | def cvZip = file("$depFolder/opencv.zip") 50 | outputs.file(cvZip) 51 | def armOpenCv 52 | 53 | doFirst { 54 | def classifier = getOpenCvPlatformPackage() 55 | def armOpenCvDependency = project.dependencies.create("org.opencv:opencv-jni:3.1.0:$classifier@jar") 56 | def armOpenCvConfig = project.configurations.detachedConfiguration(armOpenCvDependency) 57 | armOpenCvConfig.setTransitive(false) 58 | armOpenCv = armOpenCvConfig.files[0].canonicalFile 59 | } 60 | 61 | doLast { 62 | copy { 63 | from armOpenCv 64 | rename 'opencv(.+)', 'opencv.zip' 65 | into depFolder 66 | } 67 | } 68 | } 69 | 70 | ext.openCvUnzipLocation = "$buildDir/opencv" 71 | 72 | // Create a task that will unzip the wpiutil files into a temporary build directory 73 | task unzipOpenCv(type: Copy) { 74 | description = 'Unzips the wpiutil maven dependency so that the include files and libraries can be used' 75 | group = 'WPILib' 76 | dependsOn downloadOpenCv 77 | 78 | from zipTree(downloadOpenCv.outputs.files.singleFile) 79 | into openCvUnzipLocation 80 | } -------------------------------------------------------------------------------- /Java/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpilibsuite/VisionBuildSamples/a98bf8a8819ae79b58e5738d05d357d465dc37a4/Java/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Java/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 04 18:53:29 PST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip 7 | -------------------------------------------------------------------------------- /Java/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /Java/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /Java/readme.md: -------------------------------------------------------------------------------- 1 | # Java sample vision system 2 | 3 | This is the WPILib sample build system for building Java based vision targeting for running on systems other than the roboRIO. This currently supports the following platforms 4 | 5 | * Windows 6 | * Raspberry Pi running Raspbian 7 | * Generic Armhf devices (such as the BeagleBone Black or the Jetson) 8 | 9 | It has been designed to be easy to setup and use, and only needs a few minor settings to pick which system you want to be ran on. It has samples for interfacing with NetworkTables and CsCore from 10 | any device, along with performing OpenCV operations. 11 | 12 | ## Choosing which system to build for 13 | As there is no way to autodetect which system you want to build for, such as building for a Raspberry Pi on a windows desktop, you have to manually select which system you want to build for. 14 | To do this, open the `build.gradle` file. Near the top at line 10 starts a group of comments explaining what to do. For a basic rundown, there are 3 lines that start with `ext.buildType =`. 15 | To select a device, just uncomment the system you want to build for. 16 | 17 | Note it is possible to easily switch which system you want to target. To do so, just switch which build type is uncommented. When you do this, you will have to run a clean `gradlew clean` in order to 18 | clear out any old artifacts. 19 | 20 | ## Choosing the camera type 21 | This sample includes 2 ways to get a camera image. The first way is from a stream coming from the roboRIO, which is created with `CameraServer.getInstance().startAutomaticCapture();`. This 22 | is the only method that is supported on windows. The second way is by opening a USB camera directly on the device. This will likely allow higher resolutions, however is only supported on Linux 23 | devices. 24 | 25 | To select between the types, open the `Main.java` file in `src/main/java`, and scroll down to the line that says "Selecting a Camera". Follow the directions there to select one. 26 | 27 | ## Building and running on the local device 28 | If you are running the build for your specific platform on the device you plan on running, you can use `gradlew run` to run the code directly. You can also run `gradlew build` to run a build. 29 | When doing this, the output files will be placed into `output\`. From there, you can run either the .bat file on windows or the shell script on unix in order to run your project. 30 | 31 | ## Building for another platform 32 | If you are building for another platform, trying to run `gradlew run` will not work, as the OpenCV binaries will not be set up correctly. In that case, when you run `gradlew build`, a zip file 33 | is placed in `output\`. This zip contains the built jar, the OpenCV library for your selected platform, and either a .bat file or shell script to run everything. All you have to do is copy 34 | this file to the system, extract it, then run the .bat or shell script to run your program 35 | 36 | ## What this gives you 37 | This sample gets an image either from a USB camera or an already existing stream. It then restreams the input image in it's raw form in order to make it viewable on another system. 38 | It then creates an OpenCV sink from the camera, which allows us to grab OpenCV images. It then creates an output stream for an OpenCV image, for instance so you can stream an annotated 39 | image. The default sample just performs a color conversion from BGR to HSV, however from there it is easy to create your own OpenCV processing in order to run everything. In addition, it is possible 40 | to run a pipeline generated from GRIP. In addition, a connection to NetworkTables is set up, so you can send data regarding the targets back to your robot. 41 | 42 | ## Other configuration options 43 | The build script provides a few other configuration options. These include selecting the main class name, and providing an output name for the project. 44 | Please see the `build.gradle` file for where to change these. -------------------------------------------------------------------------------- /Java/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | import edu.wpi.first.wpilibj.networktables.*; 4 | import edu.wpi.first.wpilibj.tables.*; 5 | import edu.wpi.cscore.*; 6 | import org.opencv.core.Mat; 7 | import org.opencv.imgproc.Imgproc; 8 | 9 | public class Main { 10 | public static void main(String[] args) { 11 | // Loads our OpenCV library. This MUST be included 12 | System.loadLibrary("opencv_java310"); 13 | 14 | // Connect NetworkTables, and get access to the publishing table 15 | NetworkTable.setClientMode(); 16 | // Set your team number here 17 | NetworkTable.setTeam(9999); 18 | 19 | NetworkTable.initialize(); 20 | 21 | 22 | // This is the network port you want to stream the raw received image to 23 | // By rules, this has to be between 1180 and 1190, so 1185 is a good choice 24 | int streamPort = 1185; 25 | 26 | // This stores our reference to our mjpeg server for streaming the input image 27 | MjpegServer inputStream = new MjpegServer("MJPEG Server", streamPort); 28 | 29 | // Selecting a Camera 30 | // Uncomment one of the 2 following camera options 31 | // The top one receives a stream from another device, and performs operations based on that 32 | // On windows, this one must be used since USB is not supported 33 | // The bottom one opens a USB camera, and performs operations on that, along with streaming 34 | // the input image so other devices can see it. 35 | 36 | // HTTP Camera 37 | /* 38 | // This is our camera name from the robot. this can be set in your robot code with the following command 39 | // CameraServer.getInstance().startAutomaticCapture("YourCameraNameHere"); 40 | // "USB Camera 0" is the default if no string is specified 41 | String cameraName = "USB Camera 0"; 42 | HttpCamera camera = setHttpCamera(cameraName, inputStream); 43 | // It is possible for the camera to be null. If it is, that means no camera could 44 | // be found using NetworkTables to connect to. Create an HttpCamera by giving a specified stream 45 | // Note if this happens, no restream will be created 46 | if (camera == null) { 47 | camera = new HttpCamera("CoprocessorCamera", "YourURLHere"); 48 | inputStream.setSource(camera); 49 | } 50 | */ 51 | 52 | 53 | 54 | /***********************************************/ 55 | 56 | // USB Camera 57 | /* 58 | // This gets the image from a USB camera 59 | // Usually this will be on device 0, but there are other overloads 60 | // that can be used 61 | UsbCamera camera = setUsbCamera(0, inputStream); 62 | // Set the resolution for our camera, since this is over USB 63 | camera.setResolution(640,480); 64 | */ 65 | 66 | // This creates a CvSink for us to use. This grabs images from our selected camera, 67 | // and will allow us to use those images in opencv 68 | CvSink imageSink = new CvSink("CV Image Grabber"); 69 | imageSink.setSource(camera); 70 | 71 | // This creates a CvSource to use. This will take in a Mat image that has had OpenCV operations 72 | // operations 73 | CvSource imageSource = new CvSource("CV Image Source", VideoMode.PixelFormat.kMJPEG, 640, 480, 30); 74 | MjpegServer cvStream = new MjpegServer("CV Image Stream", 1186); 75 | cvStream.setSource(imageSource); 76 | 77 | // All Mats and Lists should be stored outside the loop to avoid allocations 78 | // as they are expensive to create 79 | Mat inputImage = new Mat(); 80 | Mat hsv = new Mat(); 81 | 82 | // Infinitely process image 83 | while (true) { 84 | // Grab a frame. If it has a frame time of 0, there was an error. 85 | // Just skip and continue 86 | long frameTime = imageSink.grabFrame(inputImage); 87 | if (frameTime == 0) continue; 88 | 89 | // Below is where you would do your OpenCV operations on the provided image 90 | // The sample below just changes color source to HSV 91 | Imgproc.cvtColor(inputImage, hsv, Imgproc.COLOR_BGR2HSV); 92 | 93 | // Here is where you would write a processed image that you want to restreams 94 | // This will most likely be a marked up image of what the camera sees 95 | // For now, we are just going to stream the HSV image 96 | imageSource.putFrame(hsv); 97 | } 98 | } 99 | 100 | private static HttpCamera setHttpCamera(String cameraName, MjpegServer server) { 101 | // Start by grabbing the camera from NetworkTables 102 | NetworkTable publishingTable = NetworkTable.getTable("CameraPublisher"); 103 | // Wait for robot to connect. Allow this to be attempted indefinitely 104 | while (true) { 105 | try { 106 | if (publishingTable.getSubTables().size() > 0) { 107 | break; 108 | } 109 | Thread.sleep(500); 110 | } catch (Exception e) { 111 | // TODO Auto-generated catch block 112 | e.printStackTrace(); 113 | } 114 | } 115 | 116 | 117 | HttpCamera camera = null; 118 | if (!publishingTable.containsSubTable(cameraName)) { 119 | return null; 120 | } 121 | ITable cameraTable = publishingTable.getSubTable(cameraName); 122 | String[] urls = cameraTable.getStringArray("streams", null); 123 | if (urls == null) { 124 | return null; 125 | } 126 | ArrayList fixedUrls = new ArrayList(); 127 | for (String url : urls) { 128 | if (url.startsWith("mjpg")) { 129 | fixedUrls.add(url.split(":", 2)[1]); 130 | } 131 | } 132 | camera = new HttpCamera("CoprocessorCamera", fixedUrls.toArray(new String[0])); 133 | server.setSource(camera); 134 | return camera; 135 | } 136 | 137 | private static UsbCamera setUsbCamera(int cameraId, MjpegServer server) { 138 | // This gets the image from a USB camera 139 | // Usually this will be on device 0, but there are other overloads 140 | // that can be used 141 | UsbCamera camera = new UsbCamera("CoprocessorCamera", cameraId); 142 | server.setSource(camera); 143 | return camera; 144 | } 145 | } --------------------------------------------------------------------------------