From 9ec8cd83f1f86447d3cf21b7c04723f0585eae94 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Wed, 20 Sep 2023 10:07:16 -0700 Subject: [PATCH] Remove project generator Fixes #516. --- .github/workflows/build.yml | 6 - .github/workflows/integration-test.yml | 59 -- README.md | 16 +- ThirdPartyNotices.txt | 497 ------------ build.gradle | 6 +- settings.gradle | 15 - sysid-application/build.gradle | 58 -- sysid-application/config/native.gradle | 12 - .../native/cpp/AnalysisTest.cpp | 245 ------ .../native/cpp/Main.cpp | 11 - .../native/cpp/GenerationTest.cpp | 381 --------- .../native/cpp/Main.cpp | 11 - .../native/cpp/IntegrationUtils.cpp | 96 --- .../native/include/IntegrationUtils.h | 45 -- sysid-application/src/main/native/cpp/App.cpp | 17 - .../main/native/cpp/deploy/DeploySession.cpp | 222 ------ .../src/main/native/cpp/deploy/SshSession.cpp | 142 ---- .../native/cpp/generation/ConfigManager.cpp | 193 ----- .../native/cpp/generation/HardwareType.cpp | 103 --- .../src/main/native/cpp/view/Generator.cpp | 745 ------------------ .../native/include/sysid/DeployLibraries.h | 13 - .../include/sysid/deploy/DeploySession.h | 96 --- .../native/include/sysid/deploy/SshSession.h | 85 -- .../include/sysid/generation/ConfigManager.h | 244 ------ .../include/sysid/generation/HardwareType.h | 128 --- .../native/include/sysid/view/Generator.h | 263 ------- .../main/native/include/sysid/view/UILayout.h | 5 +- .../test/native/cpp/deploy/DeployJSONTest.cpp | 30 - .../cpp/generation/HardwareTypeTest.cpp | 52 -- sysid-library/build.gradle | 37 - sysid-library/gradle.properties | 1 - .../src/main/cpp/generation/SysIdSetup.cpp | 554 ------------- .../cpp/logging/SysIdDrivetrainLogger.cpp | 45 -- .../logging/SysIdGeneralMechanismLogger.cpp | 37 - .../src/main/cpp/logging/SysIdLogger.cpp | 167 ---- .../include/sysid/generation/SysIdSetup.h | 172 ---- .../sysid/logging/SysIdDrivetrainLogger.h | 64 -- .../logging/SysIdGeneralMechanismLogger.h | 46 -- .../main/include/sysid/logging/SysIdLogger.h | 140 ---- .../analysis-test/gradle.properties | 1 - .../analysis-test/src/main/cpp/Arm.cpp | 16 - .../analysis-test/src/main/cpp/Drivetrain.cpp | 85 -- .../analysis-test/src/main/cpp/Elevator.cpp | 16 - .../analysis-test/src/main/cpp/Robot.cpp | 165 ---- .../src/main/cpp/SimpleMotor.cpp | 19 - .../analysis-test/src/main/include/Arm.h | 83 -- .../src/main/include/Constants.h | 83 -- .../src/main/include/Drivetrain.h | 131 --- .../analysis-test/src/main/include/Elevator.h | 83 -- .../src/main/include/SimpleMotor.h | 66 -- .../main/include/interface/SysIdDrivetrain.h | 22 - .../include/interface/SysIdGeneralMechanism.h | 15 - sysid-projects/build.gradle | 128 --- sysid-projects/deploy/example.txt | 1 - sysid-projects/drive/gradle.properties | 1 - .../drive/src/main/cpp/DriveRobot.cpp | 212 ----- sysid-projects/drive/src/main/empty/empty.cpp | 3 - .../drive/src/main/include/DriveRobot.h | 76 -- sysid-projects/mechanism/gradle.properties | 1 - .../mechanism/src/main/cpp/MechanismRobot.cpp | 154 ---- .../mechanism/src/main/empty/empty.cpp | 3 - .../src/main/include/MechanismRobot.h | 56 -- sysid-projects/resources.gradle | 36 - vendordeps/NavX.json | 39 - vendordeps/PhoenixProAnd5.json | 458 ----------- vendordeps/REVLib.json | 73 -- vendordeps/playingwithfusion2023.json | 70 -- 67 files changed, 4 insertions(+), 7151 deletions(-) delete mode 100644 .github/workflows/integration-test.yml delete mode 100644 ThirdPartyNotices.txt delete mode 100644 sysid-application/src/integrationtest-analysis/native/cpp/AnalysisTest.cpp delete mode 100644 sysid-application/src/integrationtest-analysis/native/cpp/Main.cpp delete mode 100644 sysid-application/src/integrationtest-generation/native/cpp/GenerationTest.cpp delete mode 100644 sysid-application/src/integrationtest-generation/native/cpp/Main.cpp delete mode 100644 sysid-application/src/integrationtest-utils/native/cpp/IntegrationUtils.cpp delete mode 100644 sysid-application/src/integrationtest-utils/native/include/IntegrationUtils.h delete mode 100644 sysid-application/src/main/native/cpp/deploy/DeploySession.cpp delete mode 100644 sysid-application/src/main/native/cpp/deploy/SshSession.cpp delete mode 100644 sysid-application/src/main/native/cpp/generation/ConfigManager.cpp delete mode 100644 sysid-application/src/main/native/cpp/generation/HardwareType.cpp delete mode 100644 sysid-application/src/main/native/cpp/view/Generator.cpp delete mode 100644 sysid-application/src/main/native/include/sysid/DeployLibraries.h delete mode 100644 sysid-application/src/main/native/include/sysid/deploy/DeploySession.h delete mode 100644 sysid-application/src/main/native/include/sysid/deploy/SshSession.h delete mode 100644 sysid-application/src/main/native/include/sysid/generation/ConfigManager.h delete mode 100644 sysid-application/src/main/native/include/sysid/generation/HardwareType.h delete mode 100644 sysid-application/src/main/native/include/sysid/view/Generator.h delete mode 100644 sysid-application/src/test/native/cpp/deploy/DeployJSONTest.cpp delete mode 100644 sysid-application/src/test/native/cpp/generation/HardwareTypeTest.cpp delete mode 100644 sysid-library/build.gradle delete mode 100644 sysid-library/gradle.properties delete mode 100644 sysid-library/src/main/cpp/generation/SysIdSetup.cpp delete mode 100644 sysid-library/src/main/cpp/logging/SysIdDrivetrainLogger.cpp delete mode 100644 sysid-library/src/main/cpp/logging/SysIdGeneralMechanismLogger.cpp delete mode 100644 sysid-library/src/main/cpp/logging/SysIdLogger.cpp delete mode 100644 sysid-library/src/main/include/sysid/generation/SysIdSetup.h delete mode 100644 sysid-library/src/main/include/sysid/logging/SysIdDrivetrainLogger.h delete mode 100644 sysid-library/src/main/include/sysid/logging/SysIdGeneralMechanismLogger.h delete mode 100644 sysid-library/src/main/include/sysid/logging/SysIdLogger.h delete mode 100644 sysid-projects/analysis-test/gradle.properties delete mode 100644 sysid-projects/analysis-test/src/main/cpp/Arm.cpp delete mode 100644 sysid-projects/analysis-test/src/main/cpp/Drivetrain.cpp delete mode 100644 sysid-projects/analysis-test/src/main/cpp/Elevator.cpp delete mode 100644 sysid-projects/analysis-test/src/main/cpp/Robot.cpp delete mode 100644 sysid-projects/analysis-test/src/main/cpp/SimpleMotor.cpp delete mode 100644 sysid-projects/analysis-test/src/main/include/Arm.h delete mode 100644 sysid-projects/analysis-test/src/main/include/Constants.h delete mode 100644 sysid-projects/analysis-test/src/main/include/Drivetrain.h delete mode 100644 sysid-projects/analysis-test/src/main/include/Elevator.h delete mode 100644 sysid-projects/analysis-test/src/main/include/SimpleMotor.h delete mode 100644 sysid-projects/analysis-test/src/main/include/interface/SysIdDrivetrain.h delete mode 100644 sysid-projects/analysis-test/src/main/include/interface/SysIdGeneralMechanism.h delete mode 100644 sysid-projects/build.gradle delete mode 100644 sysid-projects/deploy/example.txt delete mode 100644 sysid-projects/drive/gradle.properties delete mode 100644 sysid-projects/drive/src/main/cpp/DriveRobot.cpp delete mode 100644 sysid-projects/drive/src/main/empty/empty.cpp delete mode 100644 sysid-projects/drive/src/main/include/DriveRobot.h delete mode 100644 sysid-projects/mechanism/gradle.properties delete mode 100644 sysid-projects/mechanism/src/main/cpp/MechanismRobot.cpp delete mode 100644 sysid-projects/mechanism/src/main/empty/empty.cpp delete mode 100644 sysid-projects/mechanism/src/main/include/MechanismRobot.h delete mode 100644 sysid-projects/resources.gradle delete mode 100644 vendordeps/NavX.json delete mode 100644 vendordeps/PhoenixProAnd5.json delete mode 100644 vendordeps/REVLib.json delete mode 100644 vendordeps/playingwithfusion2023.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e492e66..6725dd5e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,9 +37,6 @@ jobs: distribution: 'zulu' java-version: 11 - - name: Install Toolchain - run: ./gradlew installRoborioToolchain - - name: Build with Gradle run: ./gradlew build -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }} @@ -82,9 +79,6 @@ jobs: distribution: 'zulu' java-version: 13 - - name: Install Toolchain - run: ./gradlew installRoborioToolchain - - name: Build with Gradle run: ./gradlew build -PbuildServer ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }} diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml deleted file mode 100644 index de97eb19..00000000 --- a/.github/workflows/integration-test.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Integration Test - -on: [push, pull_request] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - build: - strategy: - fail-fast: false - matrix: - include: - - os: windows-2022 - artifact-name: Win64 - test-type: Analysis - # Windows generation test hangs - #- os: windows-2022 - # artifact-name: Win64 - # test-type: Generation - - os: ubuntu-22.04 - artifact-name: Linux - test-type: Analysis - # Linux generation test hangs - #- os: ubuntu-22.04 - # artifact-name: Linux - # test-type: Generation - # macOS analysis test hangs - # - os: macos-11 - # artifact-name: macOS - # test-type: Analysis - # macOS generation test returns failure with no error message - # - os: macos-11 - # artifact-name: macOS - # test-type: Generation - - name: "${{ matrix.test-type }} - ${{ matrix.artifact-name }}" - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: 13 - - - name: Install RoboRIO Toolchain - run: ./gradlew installRoborioToolchain - - - name: Run Integration Tests - run: ./gradlew run${{ matrix.test-type }}IntegrationTests -PwithIntegration - - - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: Upload Bad Json - path: jsons/ - if-no-files-found: ignore diff --git a/README.md b/README.md index f467414e..a44e35d5 100644 --- a/README.md +++ b/README.md @@ -55,18 +55,14 @@ Go to the directory that the repository is cloned in and run `./gradlew run` to ### Generating And Running SysId Robot Code -1. Use the Generator Widget to create a config.json -2. If you are characterizing a mechanism (Arm, Simple Motor, Elevator), deploy the project in `sysid-projects/mechanism` to your robot (`./gradlew :sysid-projects:mechanism:deploy`). For drivetrain charactarization (Drivetrains, Romi), deploy the project in `sysid-projects/drive` to your robot. +1. Add sysid vendordep to your robot code and call the logging function. +2. Deploy your robot code. 3. Connect the logger to your robot and perform the required tests. ## Building and Running SysId SysId uses Gradle to build. To build debug and release versions of the main executable and run tests, run `./gradlew build`. During development, you can use `./gradlew run` to build and run the debug executable. -SysId also has integration tests, which involves launching a robot program with simulation physics, characterizing it and verifying the gains. These tests are not enabled by default; instead, you need to pass the `-PwithIntegration` flag into Gradle. Use `./gradlew runAnalysisIntegrationTests -PwithIntegration` or `./gradlew runGenerationIntegrationTests -PwithIntegration` to run just the analysis or project generation integration tests respectively. - -There is also a robot project in `sysid-projects/analysis-test` that you can use to test out SysId. To launch the robot program, simply run `./gradlew :sysid-projects:analysis-test:simulateCpp`. - ### Requirements - [JDK 11](https://adoptium.net/temurin/releases/?version=11) @@ -83,14 +79,6 @@ There is also a robot project in `sysid-projects/analysis-test` that you can use ## Logging Projects -SysId comes with projects that interface with the telemetry manager to provide the necessary data for analysis. These projects are stored in the `sysid-projects` folder and take in a `config.json` file in the `sysid-projects/deploy` directory to setup the robot hardware for analysis. - -There is a `drivetrain` project for drivetrain analysis and a `mechanism` project for simple-motor, elevator, and arm analyses. - -### Running the Projects - -The executable generated from building is currently hardcoded to save to the proper project and these projects can be run normally from VSCode or the command line. - ### Time Plotting Script There is a python script in the `scripts` directory that will plot sysid data with respect to time. This is mainly intended for developers in the case that a dataset breaks sysid. diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt deleted file mode 100644 index 497cf8cc..00000000 --- a/ThirdPartyNotices.txt +++ /dev/null @@ -1,497 +0,0 @@ -============================================================================== -Copyrights and Licenses for Third Party Software Distributed with sysid -============================================================================== -The sysid 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 sysid license above applies to all code in -sysid, 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: - -libssh: Linked from https://github.com/wpilibsuite/thirdparty-libssh - -============================================================================== -libssh License -============================================================================== -GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - Linking with OpenSSL - - 17. In addition, as a special exception, we give permission to link the code -of its release of libssh with the OpenSSL project's "OpenSSL" library (or with -modified versions of it that use the same license as the "OpenSSL" library), -and distribute the linked executables. You must obey the GNU Lesser General -Public License in all respects for all of the code used other than "OpenSSL". -If you modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do so, delete -this exception statement from your version. - - END OF TERMS AND CONDITIONS diff --git a/build.gradle b/build.gradle index 5569f173..9f122738 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ doxygen { project_name 'SysId' project_logo 'sysid-application/src/main/native/resources/sysid-128.png' project_number wpilibVersioning.version.get() - source 'sysid-application/src/integrationtest-utils', 'sysid-application/src/main/native/cpp', 'sysid-application/src/main/native/include', 'sysid-library/src', 'sysid-projects/src' + source 'sysid-application/src/main/native/cpp', 'sysid-application/src/main/native/include' quiet true recursive true strip_code_comments false @@ -94,10 +94,6 @@ task runAnalysisIntegrationTests { dependsOn ":sysid-application:runAnalysisIntegrationTests" } -task runGenerationIntegrationTests { - dependsOn ":sysid-application:runGenerationIntegrationTests" -} - copyAllOutputs.dependsOn outputVersions project.build.dependsOn outputVersions project.build.dependsOn copyAllOutputs diff --git a/settings.gradle b/settings.gradle index e5515657..dd2327c3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,20 +29,5 @@ pluginManagement { Properties props = System.getProperties() props.setProperty("org.gradle.internal.native.headers.unresolved.dependencies.ignore", "true") -// Add libsysid (common library used by robot projects) -include "sysid-library" - -// Add project used for analysis integration tests. -include "sysid-projects:analysis-test" - -// Add robot projects -include "sysid-projects:drive" -include "sysid-projects:mechanism" - -// Make sure each child in sysid-projects points to the correct build file. -project(":sysid-projects").children.each { child -> - child.setBuildFileName("../build.gradle") -} - // Add the main application. include "sysid-application" diff --git a/sysid-application/build.gradle b/sysid-application/build.gradle index 2bc2d157..92dd7714 100644 --- a/sysid-application/build.gradle +++ b/sysid-application/build.gradle @@ -14,7 +14,6 @@ if (OperatingSystem.current().isWindows()) ext { imguiVersion = "1.89.1-1" - libsshVersion = "0.95-6" } // Apply NativeUtils configuration. @@ -85,10 +84,6 @@ model { } exportedHeaders.srcDirs "src/main/native/include" } - binaries.all { - lib project: ":sysid-projects:drive", library: "embeddedBinary", linkage: "static" - lib project: ":sysid-projects:mechanism", library: "embeddedBinary", linkage: "static" - } if (OperatingSystem.current().isWindows()) { sources.rc { source { @@ -115,47 +110,10 @@ model { it.cppCompiler.define("RUNNING_SYSID_TESTS") } } - sysidAnalysisIntegrationTest(GoogleTestTestSuiteSpec) { - testing $.components.sysid - sources.cpp { - source { - srcDirs "src/integrationtest-analysis/native/cpp", "src/integrationtest-utils/native/cpp" - include "**/*.cpp", "**/*.h" - } - exportedHeaders.srcDirs "src/integrationtest-utils/native/include" - } - binaries.all { - nativeUtils.useRequiredLibrary(it, "googletest_static"); - it.cppCompiler.define("RUNNING_SYSID_TESTS") - if (!project.hasProperty("withIntegration")) { - it.buildable = false - } - } - } - sysidGenerationIntegrationTest(GoogleTestTestSuiteSpec) { - testing $.components.sysid - sources.cpp { - source { - srcDirs "src/integrationtest-generation/native/cpp", "src/integrationtest-utils/native/cpp" - include "**/*.cpp", "**/*.h" - } - exportedHeaders.srcDirs "src/integrationtest-utils/native/include" - } - binaries.all { - nativeUtils.useRequiredLibrary(it, "googletest_static") - it.cppCompiler.define("RUNNING_SYSID_TESTS") - if (!project.hasProperty("withIntegration")) { - it.buildable = false - } - } - } } binaries { withType(NativeBinarySpec).all { - lib project: ":sysid-projects:drive", library: "embeddedBinary", linkage: "static" - lib project: ":sysid-projects:mechanism", library: "embeddedBinary", linkage: "static" nativeUtils.useRequiredLibrary(it, "gui") - nativeUtils.useRequiredLibrary(it, "ssh") it.cppCompiler.define("LIBSSH_STATIC") it.cppCompiler.define("PROJECT_ROOT_DIR", "$rootDir") @@ -194,22 +152,6 @@ model { run.dependsOn bin.tasks.install } } - $.testSuites.sysidAnalysisIntegrationTest.binaries.each { bin -> - if (bin.buildable && bin.name.contains("release")) { - Task run = project.tasks.create("runAnalysisIntegrationTests", Exec) { - commandLine bin.tasks.install.runScriptFile.get().asFile.toString() - } - run.dependsOn bin.tasks.install - } - } - $.testSuites.sysidGenerationIntegrationTest.binaries.each { bin -> - if (bin.buildable && bin.name.contains("release")) { - Task run = project.tasks.create("runGenerationIntegrationTests", Exec) { - commandLine bin.tasks.install.runScriptFile.get().asFile.toString() - } - run.dependsOn bin.tasks.install - } - } } } diff --git a/sysid-application/config/native.gradle b/sysid-application/config/native.gradle index ca2d5180..b17af68a 100644 --- a/sysid-application/config/native.gradle +++ b/sysid-application/config/native.gradle @@ -41,15 +41,6 @@ nativeUtils { version = imguiVersion targetPlatforms.addAll(nativeUtils.wpi.platforms.allPlatforms) } - libssh_static(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { - groupId = "edu.wpi.first.thirdparty.frc2023" - artifactId = "libssh" - headerClassifier = "headers" - sourceClassifier = "sources" - ext = "zip" - version = libsshVersion - targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms) - } // Combined gui(getNativeDependencyTypeClass('AllPlatformsCombinedNativeDependency')) { @@ -58,9 +49,6 @@ nativeUtils { "imgui_static", "wpimath_static", "ntcore_static", "wpinet_static", "wpiutil_static"] } - ssh(getNativeDependencyTypeClass('AllPlatformsCombinedNativeDependency')) { - dependencies = ["libssh_static"] - } } } diff --git a/sysid-application/src/integrationtest-analysis/native/cpp/AnalysisTest.cpp b/sysid-application/src/integrationtest-analysis/native/cpp/AnalysisTest.cpp deleted file mode 100644 index f9a6a6b7..00000000 --- a/sysid-application/src/integrationtest-analysis/native/cpp/AnalysisTest.cpp +++ /dev/null @@ -1,245 +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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "IntegrationUtils.h" -#include "sysid/Util.h" -#include "sysid/analysis/AnalysisManager.h" -#include "sysid/analysis/AnalysisType.h" -#include "sysid/telemetry/TelemetryManager.h" - -using namespace std::chrono_literals; - -// The constants that are defined in our integration test program. -constexpr double Kv = 1.98; -constexpr double Ka = 0.2; -constexpr double Kv_angular = 1.5; -constexpr double Ka_angular = 0.3; -constexpr double kTrackWidth = 0.762; - -// 36000 max samples / 9 samples per entry -constexpr size_t kMaxDataSize = 4000; - -// Calculated by finding the voltage required to hold the arm horizontal in the -// simulation program. -constexpr double kElevatorG = 0.002; -constexpr double kArmG = 0.125; - -// Create our test fixture class so we can reuse the same logic for various test -// mechanisms. -class AnalysisTest : public ::testing::Test { - public: - static constexpr const char* kTests[] = {"slow-forward", "slow-backward", - "fast-forward", "fast-backward"}; - - static void SetUpTestSuite() { - m_nt = nt::NetworkTableInstance::GetDefault(); - m_enable = - m_nt.GetTable("SmartDashboard")->GetBooleanTopic("SysIdRun").Publish(); - m_kill = - m_nt.GetTable("SmartDashboard")->GetBooleanTopic("SysIdKill").Publish(); - m_overflow = m_nt.GetTable("SmartDashboard") - ->GetBooleanTopic("SysIdOverflow") - .Subscribe(false); - - // Setup logger. - m_logger.SetLogger([](unsigned int level, const char* file, - unsigned int line, - const char* msg) { fmt::print("{}\n", msg); }); - - LaunchSim("sysid-projects:analysis-test"); - - Connect(m_nt, m_kill); - } - - void UploadJSON(std::string_view path) { - std::string jsonFolderPath = - fmt::format("{}/jsons/", EXPAND_STRINGIZE(PROJECT_ROOT_DIR)); - -#ifdef _WIN32 - std::string failCommand = - fmt::format("if not exist \"{}\" mkdir \"{}\" && copy \"{}\" \"{}\"", - jsonFolderPath, jsonFolderPath, path, jsonFolderPath); -#else - std::string failCommand = fmt::format("mkdir -p {} && cp -v {} {}", - jsonFolderPath, path, jsonFolderPath); -#endif - fmt::print(stderr, "Running: {}\n", failCommand); - std::system(failCommand.c_str()); - } - - void Initialize(sysid::AnalysisType mechanism) { - // Make a new manager - m_manager = - std::make_unique(m_settings, m_logger, m_nt); - - // Change the default settings a little bit. - m_settings.quasistaticRampRate = 0.75; - m_settings.mechanism = mechanism; - - if (mechanism == sysid::analysis::kArm) { - m_settings.units = "Radians"; - } else { - m_settings.units = "Meters"; - } - } - - void AnalyzeJSON() { - // Save the JSON and make sure that everything checks out. - auto path = m_manager->SaveJSON(EXPAND_STRINGIZE(PROJECT_ROOT_DIR)); - try { - auto analyzerSettings = sysid::AnalysisManager::Settings{}; - sysid::AnalysisManager analyzer{path, analyzerSettings, m_logger}; - - analyzer.PrepareData(); - - const auto& [ff, trackWidth] = analyzer.CalculateFeedforward(); - const auto& ffGains = std::get<0>(ff); - - fmt::print(stderr, "Ks: {}\nKv: {}\nKa: {}\n", ffGains[0], ffGains[1], - ffGains[2]); - if (m_settings.mechanism != sysid::analysis::kDrivetrainAngular) { - EXPECT_NEAR(Kv, ffGains[1], 0.003); - EXPECT_NEAR(Ka, ffGains[2], 0.003); - } else { - EXPECT_NEAR(Kv_angular, ffGains[1], 0.003); - EXPECT_NEAR(Ka_angular, ffGains[2], 0.003); - } - - if (m_settings.mechanism == sysid::analysis::kElevator) { - fmt::print(stderr, "Kg: {}\n", ffGains[3]); - EXPECT_NEAR(kElevatorG, ffGains[3], 0.003); - } else if (m_settings.mechanism == sysid::analysis::kArm) { - fmt::print(stderr, "Kg: {}\n", ffGains[3]); - EXPECT_NEAR(kArmG, ffGains[3], 0.04); - } - - if (trackWidth) { - fmt::print(stderr, "Trackwidth: {}\n", *trackWidth); - EXPECT_NEAR(kTrackWidth, *trackWidth, 0.1); - } - - if (HasFailure()) { // If it failed, write to jsons folder for artifact - // upload - UploadJSON(path); - } - } catch (std::exception& e) { - fmt::print(stderr, "Teardown Failed: {}\n", e.what()); - UploadJSON(path); - ADD_FAILURE(); - } - -// Delete the JSON. -#ifdef _WIN32 - std::string del = "del " + path; -#else - std::string del = "rm " + path; -#endif - std::system(del.c_str()); - } - - void VerifyOverflow() { - ASSERT_TRUE(m_overflow.Get()); - - // Make sure the sent data isn't too large - ASSERT_LE(m_manager->GetCurrentDataSize(), kMaxDataSize); - } - - static void TearDownTestSuite() { KillNT(m_nt, m_kill); } - - void RunTest(const char* test, double duration) { - m_manager->BeginTest(test); - - // Enable the robot. - m_enable.Set(true); - fmt::print(stderr, "Running: {}\n", test); - - ASSERT_FALSE(m_overflow.Get()); - - // Start the test and let it run for specified duration. - double start = wpi::Now() * 1E-6; - while (wpi::Now() * 1E-6 - start < duration) { - m_manager->Update(); - std::this_thread::sleep_for(5ms); - m_nt.Flush(); - } - - // Wait at least one second while the mechanism stops. - start = wpi::Now() * 1E-6; - while (m_manager->IsActive() || wpi::Now() * 1E-6 - start < 1.0) { - m_enable.Set(false); - m_manager->Update(); - std::this_thread::sleep_for(5ms); - m_nt.Flush(); - } - } - - void RunFullTests() { - for (auto& test : kTests) { - // Run each test for 3 seconds - RunTest(test, 3); - } - } - - void RunOverflowTest() { RunTest(kTests[0], 25); } - - private: - static inline nt::NetworkTableInstance m_nt; - - static inline nt::BooleanPublisher m_enable; - static inline nt::BooleanPublisher m_kill; - static inline nt::BooleanSubscriber m_overflow; - - static inline std::unique_ptr m_manager; - static inline sysid::TelemetryManager::Settings m_settings; - - static inline wpi::Logger m_logger; -}; - -TEST_F(AnalysisTest, Drivetrain) { - Initialize(sysid::analysis::kDrivetrain); - RunFullTests(); - AnalyzeJSON(); -} - -TEST_F(AnalysisTest, DrivetrainAngular) { - Initialize(sysid::analysis::kDrivetrainAngular); - RunFullTests(); - AnalyzeJSON(); -} - -TEST_F(AnalysisTest, Flywheel) { - Initialize(sysid::analysis::kSimple); - RunFullTests(); - AnalyzeJSON(); -} - -TEST_F(AnalysisTest, Elevator) { - Initialize(sysid::analysis::kElevator); - RunFullTests(); - AnalyzeJSON(); -} - -TEST_F(AnalysisTest, Arm) { - Initialize(sysid::analysis::kArm); - RunFullTests(); - AnalyzeJSON(); -} - -TEST_F(AnalysisTest, Overflow) { - Initialize(sysid::analysis::kDrivetrain); - RunOverflowTest(); - VerifyOverflow(); -} diff --git a/sysid-application/src/integrationtest-analysis/native/cpp/Main.cpp b/sysid-application/src/integrationtest-analysis/native/cpp/Main.cpp deleted file mode 100644 index e993c1f1..00000000 --- a/sysid-application/src/integrationtest-analysis/native/cpp/Main.cpp +++ /dev/null @@ -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 - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - return ret; -} diff --git a/sysid-application/src/integrationtest-generation/native/cpp/GenerationTest.cpp b/sysid-application/src/integrationtest-generation/native/cpp/GenerationTest.cpp deleted file mode 100644 index 5dc2b987..00000000 --- a/sysid-application/src/integrationtest-generation/native/cpp/GenerationTest.cpp +++ /dev/null @@ -1,381 +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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IntegrationUtils.h" -#include "sysid/Util.h" -#include "sysid/generation/ConfigManager.h" -#include "sysid/generation/HardwareType.h" -#include "sysid/view/Generator.h" - -using namespace std::chrono_literals; - -const wpi::SmallVector kTalonEncs{ - sysid::encoder::kBuiltInSetting, sysid::encoder::kCTRETachometer}; -const wpi::SmallVector kSMaxEncs{ - sysid::encoder::kSMaxEncoderPort, sysid::encoder::kSMaxDataPort}; -const wpi::SmallVector kBuiltInEncs{ - sysid::encoder::kBuiltInSetting}; -const wpi::SmallVector kGeneralEncs{ - // sysid::encoder::kCANCoder, - sysid::encoder::kRoboRIO}; - -wpi::StringMap> - motorControllerEncoderMap = { - {std::string{sysid::motorcontroller::kPWM.name}, kGeneralEncs}, - {std::string{sysid::motorcontroller::kVictorSPX.name}, kGeneralEncs}, - {std::string{sysid::motorcontroller::kTalonSRX.name}, kTalonEncs}, - {std::string{sysid::motorcontroller::kTalonFX.name}, kBuiltInEncs}, - {std::string{sysid::motorcontroller::kTalonFXPro.name}, kBuiltInEncs}, - {std::string{sysid::motorcontroller::kSPARKMAXBrushless.name}, - kSMaxEncs}, - {std::string{sysid::motorcontroller::kSPARKMAXBrushed.name}, kSMaxEncs}, - {std::string{sysid::motorcontroller::kVenom.name}, kBuiltInEncs}}; - -const wpi::SmallVector kPigeonCtors{ - "0", "WPI_TalonSRX-1", "WPI_TalonSRX-2", "WPI_TalonSRX-10"}; -const wpi::SmallVector kAnalogCtors{"0"}; -const wpi::SmallVector kNavXCtors{ - "SerialPort (USB)", "I2C (MXP)", "SerialPort (MXP)", "SPI (MXP)"}; -const wpi::SmallVector kADXRS450Ctors{"SPI (MXP)", - "SPI (Onboard CS0)"}; -const wpi::SmallVector kADIS16448Ctors{ - "SPI (MXP)", "SPI (Onboard CS0)", "SPI (Onboard CS1)", "SPI (Onboard CS2)", - "SPI (Onboard CS3)"}; -const wpi::SmallVector kADIS16470Ctors{ - "SPI (Onboard CS0)", "SPI (Onboard CS1)", "SPI (Onboard CS2)", - "SPI (Onboard CS3)", "SPI (MXP)"}; -wpi::StringMap> gyroCtorMap = { - {std::string{sysid::gyro::kAnalogGyro.name}, kAnalogCtors}, - {std::string{sysid::gyro::kPigeon.name}, kPigeonCtors}, - {std::string{sysid::gyro::kPigeon2.name}, kAnalogCtors}, - {std::string{sysid::gyro::kPigeon2Pro.name}, kAnalogCtors}, - {std::string{sysid::gyro::kADXRS450.name}, kADXRS450Ctors}, - {std::string{sysid::gyro::kNavX.name}, kNavXCtors}, - {std::string{sysid::gyro::kADIS16448.name}, kADIS16448Ctors}, - {std::string{sysid::gyro::kADIS16470.name}, kADIS16470Ctors}, - {std::string{sysid::gyro::kNoGyroOption.name}, kAnalogCtors}}; - -class GenerationTest : public ::testing::Test { - public: - void Initialize(std::string_view directory) { - m_nt = nt::NetworkTableInstance::GetDefault(); - m_kill = - m_nt.GetTable("SmartDashboard")->GetBooleanTopic("SysIdKill").Publish(); - m_mechanism = - m_nt.GetTable("SmartDashboard")->GetStringTopic("SysIdTest").Publish(); - m_mechErrorPub = m_nt.GetTable("SmartDashboard") - ->GetBooleanTopic("SysIdWrongMech") - .Publish(); - m_mechErrorSub = m_nt.GetTable("SmartDashboard") - ->GetBooleanTopic("SysIdWrongMech") - .Subscribe(false); - m_enable = - m_nt.GetTable("SmartDashboard")->GetBooleanTopic("SysIdRun").Publish(); - - // Get the path to write the json - m_jsonPath = std::filesystem::path{EXPAND_STRINGIZE(PROJECT_ROOT_DIR)} / - "sysid-projects" / "deploy" / "config.json"; - m_directory = directory; - - // Wait between tests - std::this_thread::sleep_for(2s); - } - - void FindInLog(std::string_view str, std::string_view prefix = "Setup") { - auto searchString = fmt::format("{} {}", prefix, str); - fmt::print(stderr, "Searching for: {}\n", searchString); - bool found = wpi::contains(m_logContent, searchString); - EXPECT_TRUE(found); - - // Prints out stored output to help with debugging - if (!found) { - fmt::print(stderr, "******\nOutput Searched Through:\n{}\n******\n", - m_logContent); - } - } - - void TestHardwareConfig(std::string_view motorController, - std::string_view encoder) { - FindInLog(motorController); - - std::string encoderString; - if (encoder == sysid::encoder::kBuiltInSetting.name) { - encoderString = fmt::format("{}+{}", encoder, motorController); - } else if (wpi::starts_with(motorController, "SPARK MAX") && - (encoder == sysid::encoder::kSMaxDataPort.name || - encoder == sysid::encoder::kSMaxEncoderPort.name)) { - if (encoder == sysid::encoder::kSMaxEncoderPort.name) { - encoderString = fmt::format("{} {}", motorController, encoder); - } else { - encoderString = fmt::format("SPARK MAX {}", encoder); - } - } else { - encoderString = encoder; - } - - FindInLog(encoderString); - - std::string voltageAccessor; - if (motorController == sysid::motorcontroller::kSPARKMAXBrushless.name || - motorController == sysid::motorcontroller::kSPARKMAXBrushed.name) { - voltageAccessor = "SPARK MAX"; - } else if (motorController == sysid::motorcontroller::kTalonSRX.name || - motorController == sysid::motorcontroller::kVictorSPX.name || - motorController == sysid::motorcontroller::kTalonFX.name) { - voltageAccessor = "CTRE"; - } else if (motorController == sysid::motorcontroller::kTalonFXPro.name) { - voltageAccessor = "CTRE (Pro)"; - } else if (motorController == sysid::motorcontroller::kVenom.name) { - voltageAccessor = "Venom"; - } else { - voltageAccessor = "General"; - } - FindInLog(fmt::format("{} voltage", voltageAccessor), "Recording"); - } - - void TestHardwareConfig(std::string_view motorController, - std::string_view encoder, std::string_view gyro, - std::string_view gyroCtor) { - TestHardwareConfig(motorController, encoder); - // FIXME: Add in gyro specific conditions once CTRE and REV simulations work - if (gyro == sysid::gyro::kNoGyroOption.name) { - FindInLog(gyro); - } else if (gyro == sysid::gyro::kPigeon.name) { - std::string pigeonPortStr; - if (wpi::starts_with(gyroCtor, "WPI_TalonSRX")) { - auto portStr = wpi::split(gyroCtor, "-").second; - if (portStr == "10") { - // If the motor controller pigeon plugged into hasn't been declared - pigeonPortStr = - fmt::format("{} (plugged to other motorcontroller)", portStr); - - } else { - // If the motor controller is plugged into an already declared pigeon - pigeonPortStr = - fmt::format("{} (plugged to drive motorcontroller)", portStr); - } - } else { - // Pigeon is plugged into CAN - pigeonPortStr = fmt::format("{} (CAN)", gyroCtor); - } - FindInLog(fmt::format("Pigeon, {}", pigeonPortStr)); - } else if (gyro == sysid::gyro::kPigeon2.name) { - FindInLog(fmt::format("Pigeon2, {} (CAN)", gyroCtor)); - } else if (gyro == sysid::gyro::kPigeon2Pro.name) { - FindInLog(fmt::format("Pigeon2, {} (CAN) (Pro)", gyroCtor)); - } else if (gyro == sysid::gyro::kADXRS450.name || - gyro == sysid::gyro::kADIS16448.name || - gyro == sysid::gyro::kADIS16470.name) { - FindInLog(gyro); - FindInLog(fmt::format("{}", gyroCtor)); - } else if (gyro == sysid::gyro::kRomiGyro.name) { - FindInLog("Romi"); - } else { - FindInLog(fmt::format("{}, {}", gyro, gyroCtor)); - } - } - - void Run() { - LaunchSim(m_directory); - - Connect(m_nt, m_kill); - - fmt::print(stderr, - "Waiting for 250 ms after connecting to see if program doesn't " - "crash\n"); - // Makes sure the program didn't crash after 250ms - std::this_thread::sleep_for(250ms); - ASSERT_TRUE(m_nt.IsConnected()); - - // Wait longer for output to be flushed - fmt::print(stderr, "Post test sleep (2s)\n"); - std::this_thread::sleep_for(2s); - - m_logContent = KillNT(m_nt, m_kill); - } - - void LaunchAndConnect() { - LaunchSim(m_directory); - Connect(m_nt, m_kill); - } - - void SetMechanism(std::string_view mechanismName) { - m_mechanism.Set(mechanismName); - m_nt.Flush(); - - // Wait some time for NT to update - std::this_thread::sleep_for(250ms); - } - - void VerifyMechStatus(bool shouldFail) { - // Enable robot to trigger autonomous init. - m_enable.Set(true); - m_nt.Flush(); - - // Wait some time for NT to update and then disable - std::this_thread::sleep_for(250ms); - m_enable.Set(false); - - // Test to see if the error flag is proper - ASSERT_EQ(m_mechErrorSub.Get(), shouldFail); - } - - void EndSimulation() { KillNT(m_nt, m_kill); } - - void TearDown() override { - // Set kill, enable, and wrong mechanism entry to false for future tests - m_kill.Set(false); - m_mechErrorPub.Set(false); - m_enable.Set(false); - - // Make sure client is gone - m_nt.StopClient(); - } - - std::string m_directory; - std::string m_logContent; - std::filesystem::path m_jsonPath; - - sysid::ConfigSettings m_settings; - sysid::ConfigManager m_manager{m_settings, m_logger}; - - private: - nt::NetworkTableInstance m_nt; - - nt::BooleanPublisher m_kill; - nt::StringPublisher m_mechanism; - nt::BooleanPublisher m_mechErrorPub; - nt::BooleanSubscriber m_mechErrorSub; - nt::BooleanPublisher m_enable; - static wpi::Logger m_logger; -}; -wpi::Logger GenerationTest::m_logger; - -TEST_F(GenerationTest, GeneralMechanism) { - Initialize("sysid-projects:mechanism"); - constexpr size_t size = 2; - for (auto&& motorController : sysid::motorcontroller::kMotorControllers) { - m_settings.motorControllers = - wpi::SmallVector(size, motorController); - for (auto&& encoder : motorControllerEncoderMap[motorController.name]) { - m_settings.encoderType = encoder; - fmt::print(stderr, "Testing: {} and {}\n", motorController.name, - encoder.name); - auto json = m_manager.Generate(size); - sysid::SaveFile(json.dump(), m_jsonPath); - - Run(); - if (HasFatalFailure()) { - TearDown(); - return; - } - - TestHardwareConfig(motorController.name, encoder.name); - } - } -} - -TEST_F(GenerationTest, Drivetrain) { - Initialize("sysid-projects:drive"); - constexpr size_t size = 2; - - m_settings.motorControllers = wpi::SmallVector( - size, sysid::motorcontroller::kTalonSRX); - - m_settings.encoderType = sysid::encoder::kBuiltInSetting; - - // Encoders + Motor controllers already tested, now just need to test the - // gyros - for (auto&& gyro : sysid::gyro::kGyros) { - if (gyro == sysid::gyro::kRomiGyro) { - continue; - } - m_settings.gyro = gyro; - for (auto&& gyroCtor : gyroCtorMap[gyro.name]) { - m_settings.gyroCtor = gyroCtor; - fmt::print(stderr, "Testing: {} using {}\n", gyro.name, gyroCtor); - auto json = m_manager.Generate(size); - sysid::SaveFile(json.dump(), m_jsonPath); - - Run(); - if (HasFatalFailure()) { - TearDown(); - return; - } - TestHardwareConfig(m_settings.motorControllers[0].name, - m_settings.encoderType.name, gyro.name, gyroCtor); - } - } - - // m_settings = sysid::kRomiConfig; - // auto json = m_manager.Generate(size); - // sysid::SaveFile(json.dump(), m_jsonPath); - // fmt::print(stderr, "Testing: Romi Config\n"); - // Run(); - if (HasFatalFailure()) { - TearDown(); - return; - } - TestHardwareConfig(m_settings.motorControllers[0].name, - m_settings.encoderType.name, m_settings.gyro.name, - m_settings.gyroCtor); -} - -TEST_F(GenerationTest, WrongMechDrivetrain) { - Initialize("sysid-projects:drive"); - // Save default config to path - m_settings = sysid::ConfigSettings(); - auto json = m_manager.Generate(2); - sysid::SaveFile(json.dump(), m_jsonPath); - - LaunchAndConnect(); - - // Makes sure Drivetrain works - SetMechanism("Drivetrain"); - VerifyMechStatus(false); - - // Makes sure Arm fails - SetMechanism("Arm"); - VerifyMechStatus(true); - - EndSimulation(); -} - -TEST_F(GenerationTest, WrongMechGeneralMechanism) { - Initialize("sysid-projects:mechanism"); - // Save default config to path - m_settings = sysid::ConfigSettings(); - auto json = m_manager.Generate(1); - sysid::SaveFile(json.dump(), m_jsonPath); - - LaunchAndConnect(); - - // Makes sure Arm works - SetMechanism("Arm"); - VerifyMechStatus(false); - - // Makes sure Drivetrain fails - SetMechanism("Drivetrain"); - VerifyMechStatus(true); - - EndSimulation(); -} diff --git a/sysid-application/src/integrationtest-generation/native/cpp/Main.cpp b/sysid-application/src/integrationtest-generation/native/cpp/Main.cpp deleted file mode 100644 index e993c1f1..00000000 --- a/sysid-application/src/integrationtest-generation/native/cpp/Main.cpp +++ /dev/null @@ -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 - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - int ret = RUN_ALL_TESTS(); - return ret; -} diff --git a/sysid-application/src/integrationtest-utils/native/cpp/IntegrationUtils.cpp b/sysid-application/src/integrationtest-utils/native/cpp/IntegrationUtils.cpp deleted file mode 100644 index a7b67f64..00000000 --- a/sysid-application/src/integrationtest-utils/native/cpp/IntegrationUtils.cpp +++ /dev/null @@ -1,96 +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 "IntegrationUtils.h" - -#include - -#include -#include -#include - -void LaunchSim(std::string_view projectDirectory) { - // Install the robot program. - std::string installCmd = - fmt::format("cd {}/ && {} :{}:installSimulateNativeRelease -Pintegration", - EXPAND_STRINGIZE(PROJECT_ROOT_DIR), LAUNCH, projectDirectory); - fmt::print(stderr, "Executing: {}\n", installCmd); - - int result = std::system(installCmd.c_str()); - - // Exit the test if we could not install the robot program. - if (result != 0) { - fmt::print(stderr, "The robot program could not be installed.\n"); - std::exit(1); - } - - // Run the robot program. - std::string runCmd = - fmt::format("cd {}/ && {} :{}:simulateNativeRelease -Pintegration {}", - EXPAND_STRINGIZE(PROJECT_ROOT_DIR), LAUNCH_DETACHED, - projectDirectory, DETACHED_SUFFIX); - fmt::print(stderr, "Executing: {}\n", runCmd); - - // Start capturing console output before gradle command to capture program - // data - ::testing::internal::CaptureStdout(); - - result = std::system(runCmd.c_str()); - - // Exit the test if we could not run the robot program. - if (result != 0) { - fmt::print(stderr, "The robot program could not be started.\n"); - std::exit(1); - } -} - -void Connect(nt::NetworkTableInstance nt, nt::BooleanPublisher& kill) { - nt.SetServer("localhost", nt::NetworkTableInstance::kDefaultPort4); - nt.StartClient4("localhost"); - - kill.Set(false); - nt.Flush(); - - // Wait for NT to connect or fail it if it times out. - auto time = wpi::Now(); - while (!nt.IsConnected()) { - if (wpi::Now() - time > 1.5E7) { - fmt::print(stderr, "The robot program crashed\n"); - auto capturedStdout = ::testing::internal::GetCapturedStdout(); - fmt::print(stderr, - "\n******\nRobot Program Captured Output:\n{}\n******\n", - capturedStdout); - std::exit(1); - } - } -} - -std::string KillNT(nt::NetworkTableInstance nt, nt::BooleanPublisher& kill) { - // Before killing sim, store any captured console output. - auto capturedStdout = ::testing::internal::GetCapturedStdout(); - - fmt::print(stderr, "Killing program\n"); - auto time = wpi::Now(); - - while (nt.IsConnected()) { - // Kill program - kill.Set(true); - nt.Flush(); - if (wpi::Now() - time > 3E7) { - EXPECT_TRUE(false); - return capturedStdout; - } - } - - fmt::print(stderr, "Killed robot program\n"); - - // Set kill entry to false for future tests - kill.Set(false); - nt.Flush(); - - // Stop NT Client - nt.StopClient(); - - return capturedStdout; -} diff --git a/sysid-application/src/integrationtest-utils/native/include/IntegrationUtils.h b/sysid-application/src/integrationtest-utils/native/include/IntegrationUtils.h deleted file mode 100644 index 203b66a0..00000000 --- a/sysid-application/src/integrationtest-utils/native/include/IntegrationUtils.h +++ /dev/null @@ -1,45 +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 -#include - -#include -#include - -#include "sysid/Util.h" - -/** - * Launches a robot simulation using std::system - * - * @param projectDirectory the relative path of the robot project folder from - * the root directory. - */ -void LaunchSim(std::string_view projectDirectory); - -/** - * Connects to a Simulation NT Entry and configures the kill variable to not - * prematurely kill the simulated code. This assumes that the simulated code - * uses a NT kill entry to end the simulation. - * - * @param nt the Network Tables Intstance - * @param kill the Network Tables Entry responsible for killing the simulated - * code. - */ -void Connect(nt::NetworkTableInstance nt, nt::BooleanPublisher& kill); - -/** - * Connects to a Simulation NT Entry and configures the kill variable to kill - * the robot code. This assumes that the simulated code uses a NT kill entry to - * end the simulation. - * - * @param nt the Network Tables Instance - * @param kill the Network Tables Entry responsible for killing the simulated - * code. - * - * @return captured console output during the robot simulation. - */ -std::string KillNT(nt::NetworkTableInstance nt, nt::BooleanPublisher& kill); diff --git a/sysid-application/src/main/native/cpp/App.cpp b/sysid-application/src/main/native/cpp/App.cpp index 9ca3e632..28f1814d 100644 --- a/sysid-application/src/main/native/cpp/App.cpp +++ b/sysid-application/src/main/native/cpp/App.cpp @@ -18,13 +18,11 @@ #include #include #include -#include #include #include #include #include "sysid/view/Analyzer.h" -#include "sysid/view/Generator.h" #include "sysid/view/JSONConverter.h" #include "sysid/view/Logger.h" #include "sysid/view/UILayout.h" @@ -35,7 +33,6 @@ static std::unique_ptr gWindowManager; glass::Window* gLoggerWindow; glass::Window* gAnalyzerWindow; -glass::Window* gGeneratorWindow; glass::Window* gProgramLogWindow; static glass::MainMenuBar gMainMenu; @@ -100,9 +97,6 @@ void Application(std::string_view saveDir) { // Set the number of workers for the libuv threadpool. uv_os_setenv("UV_THREADPOOL_SIZE", "6"); - // Initialize libssh. - ssh_init(); - // Initialize window manager and add views. auto& storage = glass::GetStorageRoot().GetChild("SysId"); gWindowManager = std::make_unique(storage); @@ -117,17 +111,8 @@ void Application(std::string_view saveDir) { gProgramLogWindow = gWindowManager->AddWindow( "Program Log", std::make_unique(&gLog)); - gGeneratorWindow = gWindowManager->AddWindow( - "Generator", std::make_unique(storage, gLogger)); - // Set default positions and sizes for windows. - // Generator window position/size - gGeneratorWindow->SetDefaultPos(sysid::kGeneratorWindowPos.x, - sysid::kGeneratorWindowPos.y); - gGeneratorWindow->SetDefaultSize(sysid::kGeneratorWindowSize.x, - sysid::kGeneratorWindowSize.y); - // Logger window position/size gLoggerWindow->SetDefaultPos(sysid::kLoggerWindowPos.x, sysid::kLoggerWindowPos.y); @@ -216,8 +201,6 @@ void Application(std::string_view saveDir) { sysid::kAppWindowSize.y); gui::Main(); - ssh_finalize(); - glass::DestroyContext(); gui::DestroyContext(); } diff --git a/sysid-application/src/main/native/cpp/deploy/DeploySession.cpp b/sysid-application/src/main/native/cpp/deploy/DeploySession.cpp deleted file mode 100644 index db215ccf..00000000 --- a/sysid-application/src/main/native/cpp/deploy/DeploySession.cpp +++ /dev/null @@ -1,222 +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 "sysid/deploy/DeploySession.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "sysid/DeployLibraries.h" -#include "sysid/deploy/SshSession.h" - -using namespace sysid; - -// Macros to make logging easier. -#define INFO(fmt, ...) WPI_INFO(m_logger, fmt, __VA_ARGS__) -#define ERROR(fmt, ...) WPI_INFO(m_logger, fmt, __VA_ARGS__) -#define SUCCESS(fmt, ...) WPI_LOG(m_logger, kLogSuccess, fmt, __VA_ARGS__) - -// roboRIO SSH constants. -static constexpr int kPort = 22; -static constexpr std::string_view kUsername = "admin"; -static constexpr std::string_view kPassword = ""; - -// These are auto-generated by the build system. -namespace sysid { -std::string_view GetResource_drive_frcUserProgram(); -std::string_view GetResource_mechanism_frcUserProgram(); -} // namespace sysid - -// Lock for Execute(). Only one instance of Execute() should be running at a -// time (even across separate instances). -wpi::mutex s_mutex; - -DeploySession::DeploySession(std::string_view team, bool drive, - wpi::json config, wpi::Logger& logger) - : m_drive{drive}, m_config(std::move(config)), m_logger{logger} { - // Check whether we have an IP/hostname or team number. - auto maybeTeam = wpi::parse_integer(team, 10); - - // Depending on whether we have a team number, get a list of plausible - // addresses or just set the list to the provided IP/hostname. - m_addresses = maybeTeam.has_value() ? GetAddressesToTry(maybeTeam.value()) - : std::vector{std::string{team}}; -} - -void DeploySession::Execute(wpi::uv::Loop& lp) { - // Lock mutex. - std::scoped_lock lock{s_mutex}; - - // First, we will attempt to resolve the hostnames of all the plausible - // addresses. For every successful resolution, we will attempt a connection. - // The first address to connect wins and the deploy will execute. - for (auto&& host : m_addresses) { - INFO("Attempting to resolve {} hostname.", host); - - // Create a request object for the call. - auto req = std::make_shared(); - - // Set the error handler for the request. - req->error = [this, &host, &lp](wpi::uv::Error e) { - m_visited.fetch_add(1); - lp.error(e); - INFO("Could not resolve {}: {}.", host, e.str()); - }; - - // Set the address-resolved handler for the request. - req->resolved.connect([this, &host, &lp](const addrinfo& i) { - // Convert to IP address. - wpi::SmallString<16> ip; - wpi::uv::AddrToName(reinterpret_cast(i.ai_addr)->sin_addr, - &ip); - INFO("Resolved {} to {}.", host, ip); - - // Attempt an SSH connection in a separate worker thread. If the - // connection is successful, continue the deploy from there. - // First, create a request object for the call. - auto wreq = std::make_shared(); - - // Connect after work handler. - wreq->afterWork.connect([this] { m_visited.fetch_add(1); }); - - // Connect work handler. - // We capture ip by value because the ref might be gone when the - // callback is invoked. - wreq->work.connect([this, &host, ip] { - INFO("Trying to establish SSH connection to {}.", host); - try { - // Check if a connection has already been established. If it - // has, then we don't want to waste time and resources trying - // to establish another one. - if (m_connected) { - return; - } - - // Try to start a connection. - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - INFO("SSH connection to {} was successful.", host); - - // If we were successful, continue with the deploy (after - // making sure that no other thread also reached this location - // at the same time). - if (m_connected.exchange(true)) { - return; - } - - SUCCESS("{}", "roboRIO Connected!"); - - try { - // As far as I can tell, the order of this doesn't matter. - // It only comments out some stuff for the LabVIEW runtime that - // apparently isn't needed, and dramatically reduces memory usage. - // See https://github.com/wpilibsuite/EclipsePlugins/pull/154 - session.Execute( - "sed -i -e 's/^StartupDLLs/;StartupDLLs/' " - "/etc/natinst/share/ni-rt.ini"); - - // Pre-Deploy - session.Execute( - "sed -i -e 's/\"exec /\"/' /usr/local/frc/bin/frcRunRobot.sh"); - session.Execute( - ". /etc/profile.d/natinst-path.sh; " - "/usr/local/frc/bin/frcKillRobot.sh " - "-t 2> /dev/null"); - session.Execute("rm -f \"/home/lvuser/frcUserProgram\""); - session.Execute("mkdir -p /home/lvuser/deploy"); - session.Execute( - "chmod -R 777 /home/lvuser/deploy || true; chown -R admin:ni " - "/home/lvuser/deploy"); - - // Deploy libraries - auto libraries = sysid::GetLibrariesToDeploy(); - wpi::SmallString<64> deployFolder; - for (auto&& library : libraries) { - deployFolder.clear(); - deployFolder.append("/usr/local/frc/third-party/lib/"); - deployFolder.append(library.first); - session.Put(deployFolder.str(), library.second); - } - - // Deploy - session.Put("/home/lvuser/frcUserProgram", - m_drive ? GetResource_drive_frcUserProgram() - : GetResource_mechanism_frcUserProgram()); - session.Put("/home/lvuser/deploy/config.json", m_config.dump()); - - // Post-Deploy - session.Execute( - "chmod -R 777 /home/lvuser/deploy || true; chown -R lvuser:ni " - "/home/lvuser/deploy"); - session.Execute( - "chmod -R 777 /usr/local/frc/third-party/lib || true; chown -R " - "lvuser:ni /usr/local/frc/third-party/lib"); - session.Execute( - "echo ' \"/home/lvuser/frcUserProgram\" ' > " - "/home/lvuser/robotCommand"); - session.Execute( - "chmod +x /home/lvuser/robotCommand; chown lvuser " - "/home/lvuser/robotCommand"); - session.Execute( - "chmod +x \"/home/lvuser/frcUserProgram\"; chown lvuser " - "\"/home/lvuser/frcUserProgram\""); - session.Execute( - "setcap cap_sys_nice+eip \"/home/lvuser/frcUserProgram\""); - session.Execute("sync"); - session.Execute("ldconfig"); - session.Execute( - ". /etc/profile.d/natinst-path.sh; " - "/usr/local/frc/bin/frcKillRobot.sh -t -r 2> /dev/null"); - - SUCCESS("{}", "Deploy Complete!"); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - } - } catch (const SshSession::SshException& e) { - INFO("SSH connection to {} failed.", host); - } - }); - - // Queue the work. - wpi::uv::QueueWork(lp, wreq); - }); - - // Resolve. - wpi::uv::GetAddrInfo(lp, req, host); - } -} - -std::vector DeploySession::GetAddressesToTry(int team) { - return { - // These 3 should catch the roboRIO when it's connected to a radio or - // a computer via USB. - fmt::format("roborio-{}-FRC.local", team), - fmt::format("10.{}.{}.2", team / 100, team % 100), "172.22.11.2", - - // The remaining cases are for weird environments, like a home network, - // practice field, or otherwise. - fmt::format("roborio-{}-FRC", team), - fmt::format("roborio-{}-FRC.lan", team), - fmt::format("roborio-{}.frc-field.local", team)}; -} - -DeploySession::Status DeploySession::GetStatus() const { - // If we haven't visited everything yet, then we are still in progress. - if (m_visited < m_addresses.size()) { - return Status::kInProgress; - } - - // If we have visited all locations, then there was either a discovery error - // or we are done (indicated by whether m_connected is set). - return m_connected ? Status::kDone : Status::kDiscoveryFailure; -} diff --git a/sysid-application/src/main/native/cpp/deploy/SshSession.cpp b/sysid-application/src/main/native/cpp/deploy/SshSession.cpp deleted file mode 100644 index 068998e5..00000000 --- a/sysid-application/src/main/native/cpp/deploy/SshSession.cpp +++ /dev/null @@ -1,142 +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 "sysid/deploy/SshSession.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include - -using namespace sysid; - -#define INFO(fmt, ...) WPI_INFO(m_logger, fmt, __VA_ARGS__) - -SshSession::SshSession(std::string_view host, int port, std::string_view user, - std::string_view pass, wpi::Logger& logger) - : m_host{host}, - m_port{port}, - m_username{user}, - m_password{pass}, - m_logger{logger} { - // Create a new SSH session. - m_session = ssh_new(); - if (!m_session) { - throw SshException("The SSH session could not be allocated."); - } - - // Set the host, user, and port. - ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_USER, m_username.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port); - - // Set timeout to 3 seconds. - int64_t timeout = 3L; - ssh_options_set(m_session, SSH_OPTIONS_TIMEOUT, &timeout); - - // Set other miscellaneous options. - ssh_options_set(m_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, "no"); -} - -SshSession::~SshSession() { - ssh_disconnect(m_session); - ssh_free(m_session); -} - -void SshSession::Open() { - // Connect to the server. - int rc = ssh_connect(m_session); - if (rc != SSH_OK) { - throw SshException(ssh_get_error(m_session)); - } - - // Authenticate with password. - rc = ssh_userauth_password(m_session, nullptr, m_password.c_str()); - if (rc != SSH_AUTH_SUCCESS) { - throw SshException(ssh_get_error(m_session)); - } -} - -void SshSession::Execute(std::string_view cmd) { - // Allocate a new channel. - ssh_channel channel = ssh_channel_new(m_session); - if (!channel) { - throw SshException(ssh_get_error(m_session)); - } - - // Open the channel. - int rc = ssh_channel_open_session(channel); - if (rc != SSH_OK) { - throw SshException(ssh_get_error(m_session)); - } - - // Execute the command. - std::string command{cmd}; - rc = ssh_channel_request_exec(channel, command.c_str()); - if (rc != SSH_OK) { - ssh_channel_close(channel); - ssh_channel_free(channel); - throw SshException(ssh_get_error(m_session)); - } - INFO("{}", cmd); - - // Log output. - char buf[512]; - int read = ssh_channel_read(channel, buf, sizeof(buf), 0); - if (read != 0) { - INFO("{}", cmd); - } - - // Close and free channel. - ssh_channel_close(channel); - ssh_channel_free(channel); -} - -void SshSession::Put(std::string_view path, std::string_view contents) { - // Allocate the SFTP session. - sftp_session sftp = sftp_new(m_session); - if (!sftp) { - throw SshException(ssh_get_error(m_session)); - } - - // Initialize. - int rc = sftp_init(sftp); - if (rc != SSH_OK) { - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - - std::string nullTerminatedPath = std::string{path}; - // Copy. - sftp_file file = sftp_open(sftp, nullTerminatedPath.c_str(), - O_WRONLY | O_CREAT | O_TRUNC, S_IFMT); - if (!file) { - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - - // Send 150K at a time. - static constexpr size_t kChunkSize = 150000; - for (size_t i = 0; i < contents.size(); i += kChunkSize) { - size_t len = (std::min)(kChunkSize, contents.size() - i); - size_t written = sftp_write(file, contents.data() + i, len); - if (written != len) { - sftp_close(file); - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - } - - INFO("[SFTP] Deployed {}!", path); - - // Close file, free memory. - sftp_close(file); - sftp_free(sftp); -} diff --git a/sysid-application/src/main/native/cpp/generation/ConfigManager.cpp b/sysid-application/src/main/native/cpp/generation/ConfigManager.cpp deleted file mode 100644 index df346bc5..00000000 --- a/sysid-application/src/main/native/cpp/generation/ConfigManager.cpp +++ /dev/null @@ -1,193 +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 "sysid/generation/ConfigManager.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sysid/Util.h" - -using namespace sysid; - -ConfigManager::ConfigManager(ConfigSettings& config, wpi::Logger& logger) - : m_config{config}, m_logger{logger} {} - -wpi::json ConfigManager::Generate(size_t occupied) { - // Create the JSON to return. - wpi::json json; - - // Keep a CANivore name vector around that we can push our names into - std::vector canivoreNames; - - // Add motor ports. - json["primary motor ports"] = - SliceVector(m_config.primaryMotorPorts, occupied); - json["secondary motor ports"] = - SliceVector(m_config.secondaryMotorPorts, occupied); - - // Add motor types. - std::vector motorControllers; - for (size_t i = 0; i < occupied; i++) { - motorControllers.push_back(m_config.motorControllers[i].name); - } - json["motor controllers"] = motorControllers; - - // Add CANivore busses - canivoreNames.clear(); - for (size_t i = 0; i < occupied; i++) { - canivoreNames.push_back(std::string(m_config.canivoreNames[i].data())); - } - json["canivore names"] = canivoreNames; - - // Add motor inversions. - json["primary motors inverted"] = - SliceVector(m_config.primaryMotorsInverted, occupied); - json["secondary motors inverted"] = - SliceVector(m_config.secondaryMotorsInverted, occupied); - - // Add encoder ports. - json["primary encoder ports"] = m_config.primaryEncoderPorts; - json["secondary encoder ports"] = m_config.secondaryEncoderPorts; - json["encoder canivore name"] = - std::string(m_config.encoderCANivoreName.data()); - - // Add encoder type. - json["encoder type"] = m_config.encoderType.name; - - // Add encoder inversions. - json["primary encoder inverted"] = m_config.primaryEncoderInverted; - json["secondary encoder inverted"] = m_config.secondaryEncoderInverted; - - // Add encoder units -> real world units conversion constant. - json["counts per rotation"] = m_config.cpr; - json["gearing numerator"] = m_config.gearingNumerator; - json["gearing denominator"] = m_config.gearingDenominator; - - // Add gyro type and constructor. - json["gyro"] = m_config.gyro.name; - json["gyro ctor"] = m_config.gyroCtor; - json["gyro canivore name"] = std::string(m_config.gyroCANivoreName.data()); - - // Add advanced encoder settings. - json["encoding"] = m_config.encoding; - json["number of samples per average"] = m_config.numSamples; - json["velocity measurement period"] = m_config.period; - - json["is drivetrain"] = m_config.isDrive; - - // Return JSON. - return json; -} - -void ConfigManager::ReadJSON(std::string_view path) { - constexpr const char* json_keys[] = {"primary motor ports", - "secondary motor ports", - "motor controllers", - "canivore names", - "primary motors inverted", - "secondary motors inverted", - "primary encoder ports", - "secondary encoder ports", - "encoder canivore name", - "encoder type", - "primary encoder inverted", - "secondary encoder inverted", - "counts per rotation", - "gearing numerator", - "gearing denominator", - "gyro", - "gyro ctor", - "gyro canivore name", - "encoding", - "number of samples per average", - "velocity measurement period", - "is drivetrain"}; - - // Read JSON from the specified path. - std::error_code ec; - wpi::raw_fd_istream is{path, ec}; - - if (ec) { - throw std::runtime_error(fmt::format("Unable to read: {}", path)); - } - - wpi::json json_file; - is >> json_file; - WPI_INFO(m_logger, "Read {}", path); - - for (auto&& key : json_keys) { - if (json_file.find(std::string_view(key)) == json_file.end()) { - throw std::runtime_error(fmt::format( - "{} was not present in config file. Please check its formatting.", - key)); - } - } - - m_config.primaryMotorPorts = - json_file.at("primary motor ports").get>(); - m_config.secondaryMotorPorts = - json_file.at("secondary motor ports").get>(); - - // Parse motor controllers - auto motorControllers = - json_file.at("motor controllers").get>(); - m_config.motorControllers.clear(); - for (auto&& controller : motorControllers) { - m_config.motorControllers.push_back( - sysid::motorcontroller::FromMotorControllerName(controller)); - } - - m_config.primaryMotorsInverted = - json_file.at("primary motors inverted").get>(); - m_config.secondaryMotorsInverted = json_file.at("secondary motors inverted") - .get>(); - - m_config.encoderType = sysid::encoder::FromEncoderName( - json_file.at("encoder type").get()); - m_config.primaryEncoderPorts = - json_file.at("primary encoder ports").get>(); - m_config.secondaryEncoderPorts = - json_file.at("secondary encoder ports").get>(); - - m_config.primaryEncoderInverted = - json_file.at("primary encoder inverted").get(); - m_config.secondaryEncoderInverted = - json_file.at("secondary encoder inverted").get(); - - m_config.cpr = json_file.at("counts per rotation").get(); - m_config.gearingNumerator = json_file.at("gearing numerator").get(); - m_config.gearingDenominator = - json_file.at("gearing denominator").get(); - - m_config.gyro = - sysid::gyro::FromGyroName(json_file.at("gyro").get()); - m_config.gyroCtor = json_file.at("gyro ctor").get(); - - m_config.encoding = json_file.at("encoding").get(); - m_config.numSamples = - json_file.at("number of samples per average").get(); - m_config.period = json_file.at("velocity measurement period").get(); - - m_config.isDrive = json_file.at("is drivetrain").get(); -} - -void ConfigManager::SaveJSON(std::string_view path, size_t occupied) { - auto config_json = Generate(occupied); - sysid::SaveFile(config_json.dump(2), std::filesystem::path{path}); - WPI_INFO(m_logger, "Wrote Config JSON to: {}", path); -} - -template -std::vector ConfigManager::SliceVector(wpi::SmallVector m_data, - size_t size) { - return std::vector(m_data.begin(), m_data.begin() + size); -} diff --git a/sysid-application/src/main/native/cpp/generation/HardwareType.cpp b/sysid-application/src/main/native/cpp/generation/HardwareType.cpp deleted file mode 100644 index 80622c8d..00000000 --- a/sysid-application/src/main/native/cpp/generation/HardwareType.cpp +++ /dev/null @@ -1,103 +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 "sysid/generation/HardwareType.h" - -#include -#include - -#include - -using namespace sysid; - -HardwareType sysid::motorcontroller::FromMotorControllerName( - std::string_view name) { - if (name == "PWM") { - return sysid::motorcontroller::kPWM; - } - if (name == "TalonSRX") { - return sysid::motorcontroller::kTalonSRX; - } - if (name == "VictorSPX") { - return sysid::motorcontroller::kVictorSPX; - } - if (name == "TalonFX") { - return sysid::motorcontroller::kTalonFX; - } - if (name == "TalonFX (Pro)") { - return sysid::motorcontroller::kTalonFXPro; - } - if (name == "SPARK MAX (Brushless)") { - return sysid::motorcontroller::kSPARKMAXBrushless; - } - if (name == "SPARK MAX (Brushed)") { - return sysid::motorcontroller::kSPARKMAXBrushed; - } - if (name == "Venom") { - return sysid::motorcontroller::kVenom; - } - throw std::runtime_error( - fmt::format("Unsupported Motor Controller Name: {}", name)); -} - -HardwareType sysid::encoder::FromEncoderName(std::string_view name) { - if (name == "roboRIO quadrature") { - return sysid::encoder::kRoboRIO; - } - if (name == "CANCoder") { - return sysid::encoder::kCANCoder; - } - if (name == "CANcoder (Pro)") { - return sysid::encoder::kCANcoderPro; - } - if (name == "Built-in") { - return sysid::encoder::kBuiltInSetting; - } - if (name == "Tachometer") { - return sysid::encoder::kCTRETachometer; - } - if (name == "Encoder Port") { - return sysid::encoder::kSMaxEncoderPort; - } - if (name == "Data Port") { - return sysid::encoder::kSMaxDataPort; - } - throw std::runtime_error(fmt::format("Unsupported Encoder Name: {}", name)); -} - -HardwareType sysid::gyro::FromGyroName(std::string_view name) { - if (name == "Analog Gyro") { - return sysid::gyro::kAnalogGyro; - } - if (name == "ADXRS450") { - return sysid::gyro::kADXRS450; - } - if (name == "NavX") { - return sysid::gyro::kNavX; - } - if (name == "Pigeon") { - return sysid::gyro::kPigeon; - } - - if (name == "Pigeon2") { - return sysid::gyro::kPigeon2; - } - - if (name == "ADIS16470") { - return sysid::gyro::kADIS16470; - } - - if (name == "ADIS16448") { - return sysid::gyro::kADIS16448; - } - - if (name == "Romi") { - return sysid::gyro::kRomiGyro; - } - - if (name == "None") { - return sysid::gyro::kNoGyroOption; - } - throw std::runtime_error(fmt::format("Unsupported Gyro Name: {}", name)); -} diff --git a/sysid-application/src/main/native/cpp/view/Generator.cpp b/sysid-application/src/main/native/cpp/view/Generator.cpp deleted file mode 100644 index 8f7f03a6..00000000 --- a/sysid-application/src/main/native/cpp/view/Generator.cpp +++ /dev/null @@ -1,745 +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 "sysid/view/Generator.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sysid/Util.h" -#include "sysid/analysis/AnalysisType.h" -#include "sysid/generation/ConfigManager.h" -#include "sysid/view/UILayout.h" - -using namespace sysid; - -Generator::Generator(glass::Storage& storage, wpi::Logger& logger) - : m_unitsPerRotation{storage.GetDouble("Units Per Rotation", 1.0)}, - m_analysisType{storage.GetString("Analysis Type", "Simple")}, - m_logger{logger}, - m_team{ - storage.GetChild("NetworkTables Settings").GetString("serverTeam")} { - // Create configuration manager to generate JSONs. - m_manager = std::make_unique(m_settings, m_logger); - - // Initialize the deploy logger. First set the min log level so that debug - // messages are not swallowed. - m_deployLogger.set_min_level(wpi::WPI_LOG_DEBUG); - - // Set the on-log action. - m_deployLogger.SetLogger([this](unsigned int level, const char* file, - unsigned int line, const char* msg) { - // Append the message and level to the log. - std::scoped_lock lock{m_deployMutex}; - m_deployLog.push_back({msg, level}); - }); -} - -/** - * Finds the index of a certain string in a C-style array - * - * @tparam X The size of the array - * - * @param arr The array to search through - * @param value The string value to find - * - * @return The index of the string value - */ -template -static int GetNewIdx(const char* const (&arr)[X], std::string_view value) { - auto it = std::find(std::cbegin(arr), std::cend(arr), value); - if (it == std::cend(arr)) { - // Throws with array to help with debugging - std::string array; - for (auto&& element : arr) { - array += fmt::format("{}, ", element); - } - throw std::runtime_error(fmt::format("{} not found in: {}", value, array)); - } else { - return std::distance(std::cbegin(arr), it); - } -} - -/** - * Finds the index of a certain string in a standard array - * - * @tparam X The size of the array - * - * @param arr The array to search through - * @param value The string value to find - * - * @return The index of the string value - */ -template -static int GetNewIdx(const std::array& arr, - std::string_view value) { - auto it = std::find(std::begin(arr), std::end(arr), value); - if (it == std::cend(arr)) { - // Throws with array to help with debugging - std::string array; - for (auto&& element : arr) { - array += fmt::format("{}, ", element); - } - throw std::runtime_error(fmt::format("{} not found in: {}", value, array)); - } else { - return std::distance(std::cbegin(arr), it); - } -} - -void Generator::RoboRIOEncoderSetup(bool drive) { - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt("A##1", &m_settings.primaryEncoderPorts[0], 0, 0); - ImGui::SameLine(ImGui::GetFontSize() * 4); - - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt("B##1", &m_settings.primaryEncoderPorts[1], 0, 0); - ImGui::SameLine(); - ImGui::Checkbox(drive ? "Left Encoder Inverted" : "Encoder Inverted", - &m_settings.primaryEncoderInverted); - - if (drive) { - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt("A##2", &m_settings.secondaryEncoderPorts[0], 0, 0); - ImGui::SameLine(ImGui::GetFontSize() * 4); - - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt("B##2", &m_settings.secondaryEncoderPorts[1], 0, 0); - - ImGui::SameLine(); - ImGui::Checkbox("Right Encoder Inverted", - &m_settings.secondaryEncoderInverted); - } - - ImGui::Checkbox("Reduce Encoding", &m_settings.encoding); - CreateTooltip( - "This helps reduce encoder noise for high CPR encoders such as the " - "CTRE Magnetic Encoder and REV Throughbore Encoder"); -} - -void Generator::CANCoderSetup(bool drive, bool usePro) { - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt(drive ? "L CANCoder Port" : "CANCoder Port", - &m_settings.primaryEncoderPorts[0], 0, 0); - ImGui::SameLine(); - ImGui::Checkbox(drive ? "Left Encoder Inverted" : "Encoder Inverted", - &m_settings.primaryEncoderInverted); - if (drive) { - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - ImGui::InputInt("R CANCoder Port", &m_settings.secondaryEncoderPorts[1], 0, - 0); - ImGui::SameLine(); - ImGui::Checkbox("Right Encoder Inverted", - &m_settings.secondaryEncoderInverted); - } - - ImGui::SetNextItemWidth(80); - ImGui::InputText("CANcoder CANivore Name", - m_settings.encoderCANivoreName.data(), - m_settings.encoderCANivoreName.size()); - - m_settings.cancoderUsingPro = usePro; -} - -void Generator::RegularEncoderSetup(bool drive) { - ImGui::Checkbox(drive ? "Left Encoder Inverted" : "Encoder Inverted", - &m_settings.primaryEncoderInverted); - if (drive) { - ImGui::SameLine(); - ImGui::Checkbox("Right Encoder Inverted", - &m_settings.secondaryEncoderInverted); - } -} - -void Generator::UpdateFromConfig() { - // Get Occupied Ports - m_occupied = m_settings.motorControllers.size(); - - // Storing important information for Idx settings - const auto& mainMotorController = m_settings.motorControllers[0]; - const auto& encoderTypeName = m_settings.encoderType.displayName; - - // Set Previous Main Controller to current to not reset encoder selection - m_prevMainMotorController = mainMotorController; - - // Setting right Idxs for the GUI - if (mainMotorController == sysid::motorcontroller::kTalonSRX || - mainMotorController == sysid::motorcontroller::kTalonFX || - mainMotorController == sysid::motorcontroller::kTalonFXPro) { - if (mainMotorController == sysid::motorcontroller::kTalonFX || - mainMotorController == sysid::motorcontroller::kTalonFXPro) { - m_encoderIdx = GetNewIdx(ArrayConcat(kBuiltInEncoders, kGeneralEncoders), - encoderTypeName); - } else { - m_encoderIdx = GetNewIdx(ArrayConcat(kTalonSRXEncoders, kGeneralEncoders), - encoderTypeName); - } - - } else if (mainMotorController == sysid::motorcontroller::kSPARKMAXBrushed || - mainMotorController == - sysid::motorcontroller::kSPARKMAXBrushless) { - m_encoderIdx = GetNewIdx(ArrayConcat(kSparkMaxEncoders, kGeneralEncoders), - encoderTypeName); - } else if (mainMotorController == sysid::motorcontroller::kVenom) { - m_encoderIdx = GetNewIdx(ArrayConcat(kBuiltInEncoders, kGeneralEncoders), - encoderTypeName); - } else { - m_encoderIdx = GetNewIdx(kGeneralEncoders, encoderTypeName); - } - - const auto& gyroNames = kGyroNames.names; - m_gyroIdx = GetNewIdx(gyroNames, m_settings.gyro.displayName); - - if (mainMotorController == sysid::motorcontroller::kTalonFX) { - m_numSamplesIdx = GetNewIdx(kCTREBuiltInNumSamples, - std::to_string(m_settings.numSamples)); - m_periodIdx = GetNewIdx(kCTREPeriods, std::to_string(m_settings.period)); - } else if (mainMotorController == - sysid::motorcontroller::kSPARKMAXBrushless) { - m_numSamplesIdx = - GetNewIdx(kREVBuiltInNumSamples, std::to_string(m_settings.numSamples)); - m_periodIdx = GetNewIdx(kREVPeriods, std::to_string(m_settings.period)); - } - - // Read in Gyro Constructors - if (m_settings.gyro == sysid::gyro::kPigeon) { - auto pos = m_settings.gyroCtor.find("WPI_TalonSRX"); - if (pos != std::string_view::npos) { - m_gyroPort = std::stoi(m_settings.gyroCtor.substr(pos + 13)); - m_isTalon = true; - } else { - m_gyroPort = std::stoi(m_settings.gyroCtor); - m_isTalon = false; - } - } else if (m_settings.gyro == sysid::gyro::kADXRS450) { - m_gyroParam = GetNewIdx(sysid::kADXRS450Ctors, m_settings.gyroCtor); - } else if (m_settings.gyro == sysid::gyro::kNavX) { - m_gyroParam = GetNewIdx(sysid::kNavXCtors, m_settings.gyroCtor); - } else if (m_settings.gyro == sysid::gyro::kADIS16448) { - m_gyroParam = GetNewIdx(sysid::kADIS16448Ctors, m_settings.gyroCtor); - } else if (m_settings.gyro == sysid::gyro::kADIS16470) { - m_gyroParam = GetNewIdx(sysid::kADIS16470Ctors, m_settings.gyroCtor); - } else { - m_gyroPort = std::stoi(m_settings.gyroCtor); - } - - // Set Analysis Type - m_analysisIdx = m_settings.isDrive ? 1 : 0; -} - -void Generator::Display() { - // Get Hardware Device Names - const auto& motorControllerNames = kMotorControllerNames.names; - const auto& gyroNames = kGyroNames.names; - // Add team / IP selection. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - ImGui::InputText("Team/IP", &m_team); - - // Add Config Reading Button - if (ImGui::Button("Load Config")) { - m_loadConfigSelector = std::make_unique( - "Open Config", "", - std::vector{"JSON File", SYSID_PFD_JSON_EXT}); - } - - m_settings.isDrive = m_analysisIdx > 0; - - // Add deploy button. - // FIXME: Open Romi project in simulation once desktop programs are supported. - ImGui::SameLine(); - if (ImGui::Button("Deploy")) { - // Create the deploy session, - m_deploySession = std::make_unique( - m_team, m_analysisIdx == 1, m_manager->Generate(m_occupied), - m_deployLogger); - - // Execute the deploy. - m_deployRunner.ExecSync( - [this](wpi::uv::Loop& lp) { m_deploySession->Execute(lp); }); - - // Open the deploy popup. - ImGui::OpenPopup("Deploy Status"); - } - // Add analysis type selection. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - ImGui::Combo("Analysis Type", &m_analysisIdx, kAnalysisTypes, - IM_ARRAYSIZE(kAnalysisTypes)); - m_analysisType = kAnalysisTypes[m_analysisIdx]; - - // If we are a Romi project, we can end here because there is no generation to - // be done. - if (m_analysisType == "Romi") { - return; - } - - // Add section for motor and motor controller selection. - ImGui::Separator(); - ImGui::Spacing(); - ImGui::Text("Motor / Motor Controller Selection"); - - // Add buttons to add and/or remove motor ports. - ImGui::SameLine(); - if (ImGui::Button("+")) { - m_occupied++; - } - if (m_occupied > 1) { - ImGui::SameLine(); - if (ImGui::Button("-")) { - m_occupied--; - } - } - - // Add motor port selection. - bool drive = m_analysisType == "Drivetrain"; - - // Iterate through the number of ports we have available (from m_occupied) and - // add UI elements. - for (size_t i = 0; i < m_occupied; ++i) { - // Create aliases so it's easier to work on vectors. - auto& pm = m_settings.primaryMotorPorts; - auto& sm = m_settings.secondaryMotorPorts; - auto& mc = m_settings.motorControllers; - auto& pi = m_settings.primaryMotorsInverted; - auto& si = m_settings.secondaryMotorsInverted; - auto& cn = m_settings.canivoreNames; - - // Ensure that our vector contains i+1 elements. - if (pm.size() == i) { - pm.emplace_back((drive ? 2 : 1) * i); - sm.emplace_back(pm.size() + i); - mc.emplace_back(motorControllerNames[0]); - pi.emplace_back(false); - si.emplace_back(false); - cn.emplace_back(std::array{'r', 'i', 'o', '\0'}); - } - - // Make sure elements have unique IDs. - ImGui::Spacing(); - ImGui::PushID(i); - - // Add motor controller selector. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - std::string motorControllerName; - if (drive) { - motorControllerName = fmt::format("Motor Controller Pair {}", i); - } else { - motorControllerName = fmt::format("Motor Controller {}", i); - } - - if (ImGui::BeginCombo(motorControllerName.c_str(), mc[i].displayName)) { - for (size_t n = 0; n < kMotorControllerNames.size; ++n) { - bool selected = mc[i].displayName == motorControllerNames[n]; - if (ImGui::Selectable(motorControllerNames[n], selected)) { - mc[i] = sysid::motorcontroller::FromMotorControllerName( - motorControllerNames[n]); - } - if (selected) { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - // Add primary (left for drivetrain) motor ports. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - std::string primaryName; - if (drive) { - primaryName += "L "; - } - if (m_settings.motorControllers[i] == sysid::motorcontroller::kPWM) { - primaryName += "Motor Port"; - } else { - primaryName += "Motor CAN ID"; - } - ImGui::InputInt(primaryName.c_str(), &pm[i], 0, 0); - - // Add inverted setting. - ImGui::SameLine(); - ImGui::Checkbox(drive ? "L Inverted" : "Inverted", &pi[i]); - - // Add right side drivetrain ports (if the analysis type is drivetrain). - if (drive) { - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); - std::string secondaryName = "R "; - if (m_settings.motorControllers[i] == sysid::motorcontroller::kPWM) { - secondaryName += "Motor Port"; - } else { - secondaryName += "Motor CAN ID"; - } - ImGui::InputInt(secondaryName.c_str(), &sm[i], 0, 0); - - // Add inverted setting. - ImGui::SameLine(); - ImGui::Checkbox("R Inverted", &si[i]); - } - - // Add CANivore name if we are using a CTRE motor controller - if (m_settings.motorControllers[i] == sysid::motorcontroller::kTalonFX || - m_settings.motorControllers[i] == sysid::motorcontroller::kTalonFXPro) { - ImGui::SetNextItemWidth(80); - ImGui::InputText("Motor CANivore Name", - m_settings.canivoreNames[i].data(), - m_settings.canivoreNames[i].size()); - } - - ImGui::PopID(); - - // If we selected Spark Max with Brushed mode, set our flag to true. - m_isSparkMaxBrushed = mc[i] == sysid::motorcontroller::kSPARKMAXBrushed; - } - - // Add section for encoders. - ImGui::Separator(); - ImGui::Spacing(); - ImGui::Text("Encoder Selection"); - - // Reset Encoder Selection if a new motor controller is chosen - HardwareType mainMotorController{m_settings.motorControllers[0]}; - if (m_prevMainMotorController != mainMotorController) { - m_encoderIdx = 0; - } - m_prevMainMotorController = mainMotorController; - - // Add encoder selection. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - if (mainMotorController == sysid::motorcontroller::kTalonSRX || - mainMotorController == sysid::motorcontroller::kTalonFX || - mainMotorController == sysid::motorcontroller::kTalonFXPro) { - if (mainMotorController == sysid::motorcontroller::kTalonFX || - mainMotorController == sysid::motorcontroller::kTalonFXPro) { - GetEncoder(ArrayConcat(kBuiltInEncoders, kGeneralEncoders)); - if (m_encoderIdx == 0) { - // Built in encoder on TalonFX can't be inverted. - } else if (m_encoderIdx == 1 || m_encoderIdx == 2) { - CANCoderSetup(drive, m_encoderIdx == 2); - } else { - RoboRIOEncoderSetup(drive); - } - } else { - GetEncoder(ArrayConcat(kTalonSRXEncoders, kGeneralEncoders)); - if (m_encoderIdx <= 1) { - RegularEncoderSetup(drive); - } else if (m_encoderIdx == 2 || m_encoderIdx == 3) { - CANCoderSetup(drive, m_encoderIdx == 3); - } else { - RoboRIOEncoderSetup(drive); - } - } - } else if (mainMotorController == sysid::motorcontroller::kSPARKMAXBrushed || - mainMotorController == - sysid::motorcontroller::kSPARKMAXBrushless) { - GetEncoder(ArrayConcat(kSparkMaxEncoders, kGeneralEncoders)); - if (m_encoderIdx <= 1) { - if (!(m_encoderIdx == 0 && - mainMotorController == - sysid::motorcontroller::kSPARKMAXBrushless)) { - // You're not allowed to invert the NEO Built-in encoder - RegularEncoderSetup(drive); - } - } else if (m_encoderIdx == 2 || m_encoderIdx == 3) { - CANCoderSetup(drive, m_encoderIdx == 3); - } else { - RoboRIOEncoderSetup(drive); - } - } else if (mainMotorController == sysid::motorcontroller::kVenom) { - GetEncoder(ArrayConcat(kBuiltInEncoders, kGeneralEncoders)); - if (m_encoderIdx == 0) { - RegularEncoderSetup(drive); - } else if (m_encoderIdx == 1 || m_encoderIdx == 2) { - CANCoderSetup(drive, m_encoderIdx == 2); - } else { - RoboRIOEncoderSetup(drive); - } - } else { - GetEncoder(kGeneralEncoders); - if (m_encoderIdx == 0 || m_encoderIdx == 1) { - CANCoderSetup(drive, m_encoderIdx == 1); - } else { - RoboRIOEncoderSetup(drive); - } - } - - // Venom built-in encoder, TalonFX Pro built-in encoder, and CANcoder Pro - // can't change number of samples or measurement window. - if (!((mainMotorController == sysid::motorcontroller::kVenom && - m_settings.encoderType == sysid::encoder::kBuiltInSetting) || - (mainMotorController == sysid::motorcontroller::kTalonFXPro && - m_settings.encoderType == sysid::encoder::kBuiltInSetting) || - m_settings.encoderType == sysid::encoder::kCANcoderPro)) { - // Samples Per Average Setting - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); - if (mainMotorController == sysid::motorcontroller::kSPARKMAXBrushless && - m_settings.encoderType == sysid::encoder::kSMaxEncoderPort) { - if (ImGui::Combo("Samples Per Average", &m_numSamplesIdx, - kREVBuiltInNumSamples, - IM_ARRAYSIZE(kREVBuiltInNumSamples))) { - m_settings.numSamples = - std::stoi(kREVBuiltInNumSamples[m_numSamplesIdx]); - } - } else if (mainMotorController == sysid::motorcontroller::kTalonFX && - m_settings.encoderType == sysid::encoder::kBuiltInSetting) { - if (ImGui::Combo("Samples Per Average", &m_numSamplesIdx, - kCTREBuiltInNumSamples, - IM_ARRAYSIZE(kCTREBuiltInNumSamples))) { - m_settings.numSamples = - std::stoi(kCTREBuiltInNumSamples[m_numSamplesIdx]); - } - } else { - ImGui::InputInt("Samples Per Average", &m_settings.numSamples, 0, 0); - } - CreateTooltip( - "This helps reduce encoder noise by averaging collected samples " - "together. A value from 5-10 is reccomended for encoders with high " - "CPRs."); - - // Add Velocity Measurement Period - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); - if (mainMotorController == sysid::motorcontroller::kSPARKMAXBrushless && - m_settings.encoderType == sysid::encoder::kSMaxEncoderPort) { - if (ImGui::Combo("Time Measurement Window", &m_periodIdx, kREVPeriods, - IM_ARRAYSIZE(kREVPeriods)) || - m_settings.period == 1) { - m_settings.period = std::stoi(kREVPeriods[m_periodIdx]); - } - } else if (mainMotorController == sysid::motorcontroller::kTalonFX && - m_settings.encoderType == sysid::encoder::kBuiltInSetting) { - if (ImGui::Combo("Time Measurement Window", &m_periodIdx, kCTREPeriods, - IM_ARRAYSIZE(kCTREPeriods)) || - m_settings.period == 1) { - m_settings.period = std::stoi(kCTREPeriods[m_periodIdx]); - } - } - } - - // Add gyro selection if selected is drivetrain. - if (drive) { - // Create section for gyros. - ImGui::Separator(); - ImGui::Spacing(); - ImGui::Text("Gyro"); - - // Add gyro combo box. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - ImGui::Combo("Gyro", &m_gyroIdx, gyroNames, kGyroNames.size); - - ImGui::SetNextItemWidth(ImGui::GetFontSize() * kTextBoxWidthMultiple); - - auto gyroType = - sysid::gyro::FromGyroName(std::string_view{gyroNames[m_gyroIdx]}); - - // Handle each gyro and its special cases. - if (gyroType == sysid::gyro::kPigeon) { - ImGui::InputInt("CAN ID", &m_gyroPort, 0, 0); - ImGui::SameLine(); - ImGui::Checkbox("Is Talon", &m_isTalon); - CreateTooltip( - "Check this checkbox if the Pigeon is hooked up to a TalonSRX"); - - m_settings.gyroCtor = std::to_string(m_gyroPort); - - // Indicate Gyro is connected to TalonSRX - if (m_isTalon) { - m_settings.gyroCtor = "WPI_TalonSRX-" + m_settings.gyroCtor; - } - } else if (gyroType == sysid::gyro::kPigeon2 || - gyroType == sysid::gyro::kPigeon2Pro) { - ImGui::InputInt("CAN ID", &m_gyroPort, 0, 0); - - ImGui::SetNextItemWidth(80); - ImGui::InputText("Gyro CANivore Name", m_settings.gyroCANivoreName.data(), - m_settings.gyroCANivoreName.size()); - m_settings.gyroCtor = std::to_string(m_gyroPort) + ", " + - std::string{m_settings.gyroCANivoreName.begin(), - m_settings.gyroCANivoreName.end()}; - } else if (gyroType == sysid::gyro::kADXRS450) { - ImGui::Combo("SPI Port", &m_gyroParam, kADXRS450Ctors, - IM_ARRAYSIZE(kADXRS450Ctors)); - m_settings.gyroCtor = std::string(kADXRS450Ctors[m_gyroParam]); - } else if (gyroType == sysid::gyro::kNavX) { - ImGui::Combo("Port", &m_gyroParam, kNavXCtors, IM_ARRAYSIZE(kNavXCtors)); - m_settings.gyroCtor = std::string(kNavXCtors[m_gyroParam]); - } else if (m_settings.gyro == sysid::gyro::kADIS16448) { - ImGui::Combo("SPI Port", &m_gyroParam, kADIS16448Ctors, - IM_ARRAYSIZE(kADIS16448Ctors)); - m_settings.gyroCtor = std::string(kADIS16448Ctors[m_gyroParam]); - } else if (m_settings.gyro == sysid::gyro::kADIS16470) { - ImGui::Combo("SPI Port", &m_gyroParam, kADIS16470Ctors, - IM_ARRAYSIZE(kADIS16470Ctors)); - m_settings.gyroCtor = std::string(kADIS16470Ctors[m_gyroParam]); - } else if (m_settings.gyro == sysid::gyro::kAnalogGyro) { - ImGui::InputInt("Analog Port", &m_gyroPort, 0, 0); - - // AnalogGyro port cannot be greater than 1. - if (m_gyroPort > 1) { - m_gyroPort = 1; - } - m_settings.gyroCtor = std::to_string(m_gyroPort); - } - - // Avoid accessing bad gyro ctor indices. - if (gyroType != m_settings.gyro) { - m_gyroParam = 0; - } - m_settings.gyro = gyroType; - } - - // Add section for other parameters. - ImGui::Separator(); - ImGui::Spacing(); - ImGui::Text("Encoder Parameters"); - - // Add encoder resolution. - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); - ImGui::InputDouble("Counts Per Revolution", &m_settings.cpr, 0.0, 0.0, - "%.2f"); - sysid::CreateTooltip( - "This is the number of encoder counts per revolution for your encoder.\n" - "Common values for this are here:\nCTRE Magnetic Encoder: 4096\nFalcon " - "500 Integrated: 2048\nFalcon 500 running Phoenix Pro (Pro already " - "handles this value): 1\nREV Throughbore: 8192\nNEO (and NEO 550) " - "Integrated " - "Encoders (REV already handles this value): 1"); - - // Add gearing - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); - ImGui::InputDouble("##1", &m_settings.gearingNumerator, 0.0, 0.0, "%.2f"); - ImGui::SameLine(); - ImGui::Text(":"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); - ImGui::InputDouble("##2", &m_settings.gearingDenominator, 0.0, 0.0, "%.2f"); - ImGui::SameLine(); - ImGui::Text("Gearing"); - - // Ensure no division by zero or weird gearing behaviour - if (m_settings.gearingNumerator <= 0) { - m_settings.gearingNumerator = 1.0; - } - - if (m_settings.gearingDenominator <= 0) { - m_settings.gearingDenominator = 1.0; - } - - sysid::CreateTooltip( - "This is the gearing between the encoder and the output shaft. For " - "example, if the encoder is mounted to the magnetic shaft on the kit " - "chassis, there is no gearing in between the encoder and the output " - "shaft hence the gearing is 1:1. However, if the encoder was an " - "integrated encoder on the motor in the kit chassis gearbox, the gearing " - "would be 10.71:1."); - // Have a save button at the bottom - if (ImGui::Button("Save")) { - // Open a file popup - m_saveConfigSelector = std::make_unique( - "Save Config", "config.json", - std::vector{"JSON File", SYSID_PFD_JSON_EXT}, - pfd::opt::force_path); - } - - if (m_saveConfigSelector && m_saveConfigSelector->ready() && - !m_saveConfigSelector->result().empty()) { - auto path = m_saveConfigSelector->result(); - m_manager->SaveJSON(path, m_occupied); - m_saveConfigSelector.reset(); - } - - if (m_loadConfigSelector && m_loadConfigSelector->ready() && - !m_loadConfigSelector->result().empty()) { - try { - auto path = m_loadConfigSelector->result()[0]; - m_manager->ReadJSON(path); - UpdateFromConfig(); - m_loadConfigSelector.reset(); - } catch (const std::exception& e) { - m_errorPopup = true; - m_errorMessage = std::string{e.what()}; - WPI_ERROR(m_logger, "{}", - "An error occurred when attempting to load the previous config " - "JSON."); - m_loadConfigSelector.reset(); - } - } - - // Error Popup - CreateErrorPopup(m_errorPopup, m_errorMessage); - - // Define the deploy popup (and set default size). - auto size = ImGui::GetIO().DisplaySize; - ImGui::SetNextWindowSize(ImVec2(size.x / 2, size.y * 0.8)); - - if (ImGui::BeginPopupModal("Deploy Status")) { - static ImVec4 kColorWarning{1.0f, 0.7f, 0.0f, 1.0f}; - static ImVec4 kColorError{1.0f, 0.4f, 0.4f, 1.0f}; - static ImVec4 kColorSuccess{0.2f, 1.0f, 0.2f, 1.0f}; - static ImVec4 kColorDebug{0.5f, 0.5f, 0.5f, 1.0f}; - - // We are accessing a shared resource (deploy log), so lock mutex. - std::scoped_lock lock{m_deployMutex}; - - // Check whether the user is using SPARK MAX in Brushed mode. Display a - // warning message if so. - if (m_isSparkMaxBrushed) { - ImGui::TextColored( - kColorWarning, - "You have selected SPARK MAX (Brushed)!\nMake sure that you " - "are controlling a BRUSHED motor (not NEO / NEO 550)!"); - } - - // Get the deploy status. - auto status = m_deploySession->GetStatus(); - - // If there are no messages in the log and we are in progress, then we are - // still discovering the roboRIO. - if (status == DeploySession::Status::kInProgress && m_deployLog.empty()) { - ImGui::Text("Discovering roboRIO %c", - "|/-\\"[static_cast(ImGui::GetTime() / 0.05f) & 3]); - } - - // Show log messages from the event loop runner. - for (auto&& message : m_deployLog) { - ImVec4 color{1.0f, 1.0f, 1.0f, 1.0f}; - switch (message.level) { - case kLogSuccess: - color = kColorSuccess; - break; - case wpi::WPI_LOG_ERROR: - color = kColorError; - break; - case wpi::WPI_LOG_DEBUG: - color = kColorDebug; - break; - } - ImGui::TextColored(color, "%s", message.message.c_str()); - } - - // Show error if we had a discovery failure. - if (status == DeploySession::Status::kDiscoveryFailure) { - ImGui::TextColored(kColorError, - "Could not discover roboRIO.\nAre you connected to " - "the robot and is it on?"); - } - - // Check if we are done with the deploy. If we are, then we can show the - // close button. - if (status == DeploySession::Status::kDiscoveryFailure || - status == DeploySession::Status::kDone) { - if (ImGui::Button("Close")) { - m_deploySession.reset(); - m_deployLog.clear(); - ImGui::CloseCurrentPopup(); - } - } - ImGui::EndPopup(); - } -} diff --git a/sysid-application/src/main/native/include/sysid/DeployLibraries.h b/sysid-application/src/main/native/include/sysid/DeployLibraries.h deleted file mode 100644 index 1bb0274f..00000000 --- a/sysid-application/src/main/native/include/sysid/DeployLibraries.h +++ /dev/null @@ -1,13 +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 -#include -#include - -namespace sysid { -std::vector> GetLibrariesToDeploy(); -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/deploy/DeploySession.h b/sysid-application/src/main/native/include/sysid/deploy/DeploySession.h deleted file mode 100644 index 605219cc..00000000 --- a/sysid-application/src/main/native/include/sysid/deploy/DeploySession.h +++ /dev/null @@ -1,96 +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 -#include -#include -#include - -#include -#include -#include - -namespace sysid { -// Define an integer for a successful message in the log (shown in green on the -// GUI). -static constexpr unsigned int kLogSuccess = 31; - -/** - * Represents a single deploy session. - * - * An instance of this class must be kept alive in memory until GetStatus() - * returns kDiscoveryFailure or kDone. Otherwise, the deploy will fail! - */ -class DeploySession { - public: - /** - * Represents the status of the deploy session. - */ - enum class Status { kInProgress, kDiscoveryFailure, kDone }; - - /** - * Constructs an instance of the deploy session. - * - * @param team The team number (or an IP address/hostname). - * @param drive Whether the drive program should be deployed to the roboRIO. - * If this is set to false, the mechanism project will be - * deployed. - * @param config The generation configuration file to be sent to the roboRIO. - * @param logger A reference to a logger where log messages should be sent. - */ - DeploySession(std::string_view team, bool drive, wpi::json config, - wpi::Logger& logger); - - /** - * Executes the deploy. This can be called from any thread. - * - * @param lp A reference to a libuv event loop to run the deploy on. - */ - void Execute(wpi::uv::Loop& lp); - - /** - * Returns the state of the deploy session. - * - * @return the deploy session state as a Status - */ - Status GetStatus() const; - - /** - * Returns a list of hostnames and/or addresses to try while discovering the - * roboRIO. - * - * @param team The team number. - * @return A vector of hostnames/addresses to try during discovery. - */ - static std::vector GetAddressesToTry(int team); - - /** - * Returns the stored JSON object - * - * @return The stored JSON object - */ - const wpi::json& GetJSON() const { return m_config; } - - private: - // General deploy parameters from the constructor. - bool m_drive; - wpi::json m_config; - - // Logger reference where log messages will be sent. - wpi::Logger& m_logger; - - // List of addresses that we can try during the discovery process. - std::vector m_addresses; - - // Whether we have an active SSH connection to the roboRIO and deploying - // artifacts. - std::atomic_bool m_connected = false; - - // The number of hostnames that have completed their resolution/connection - // attempts. - std::atomic_uint m_visited = 0; -}; -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/deploy/SshSession.h b/sysid-application/src/main/native/include/sysid/deploy/SshSession.h deleted file mode 100644 index a25c20b0..00000000 --- a/sysid-application/src/main/native/include/sysid/deploy/SshSession.h +++ /dev/null @@ -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. - -#pragma once - -#include -#include -#include - -#include -#include - -namespace sysid { -/** - * This class is a C++ implementation of the SshSessionController in - * wpilibsuite/deploy-utils. It handles connecting to an SSH server, running - * commands, and transferring files. - */ -class SshSession { - public: - /** - * This is the exception that will be thrown by any of the methods in this - * class if something goes wrong. - */ - class SshException : public std::runtime_error { - public: - /** - * Creates an SshException - * - * @param msg The error message - */ - explicit SshException(const char* msg) : runtime_error(msg) {} - }; - - /** - * Constructs a new session controller. - * - * @param host The hostname of the server to connect to. - * @param port The port that the sshd server is operating on. - * @param user The username to login as. - * @param pass The password for the given username. - * @param logger A reference to a logger to log messages to. - */ - SshSession(std::string_view host, int port, std::string_view user, - std::string_view pass, wpi::Logger& logger); - - /** - * Destroys the controller object. This also disconnects the session from the - * server. - */ - ~SshSession(); - - /** - * Opens the SSH connection to the given host. - */ - void Open(); - - /** - * Executes a command and logs the output (if there is any). - * - * @param cmd The command to execute on the server. - */ - void Execute(std::string_view cmd); - - /** - * Puts a file on the server using SFTP. - * - * @param path The path to the file to put (on the server). - * @param contents The contents of the file. - */ - void Put(std::string_view path, std::string_view contents); - - private: - ssh_session m_session; - std::string m_host; - - int m_port; - - std::string m_username; - std::string m_password; - - wpi::Logger& m_logger; -}; -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/generation/ConfigManager.h b/sysid-application/src/main/native/include/sysid/generation/ConfigManager.h deleted file mode 100644 index c7addcb8..00000000 --- a/sysid-application/src/main/native/include/sysid/generation/ConfigManager.h +++ /dev/null @@ -1,244 +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 -#include -#include -#include -#include - -#include -#include -#include - -#include "sysid/generation/HardwareType.h" - -namespace sysid { -/** - * This represents the settings for configuring a robot project -- including - * hardware information such as motor ports, controllers, encoder ports, - * inversions, etc. It also includes numerical data such as EPR. - */ -struct ConfigSettings { - /** - * Maximum length of a CANivore name is 32 characters - */ - static constexpr int kMaxCANivoreNameLength = 32; - - /** - * Ports for the primary motor controllers. For general mechanisms this is the - * motor ports that will be used. For drivetrains these are the left-side - * motor controllers. - */ - wpi::SmallVector primaryMotorPorts = {0, 1}; - - /** - * Ports for the secondary motor controllers. For general mechanisms this - * won't be used. For drivetrains these are the right-side motor controllers. - */ - wpi::SmallVector secondaryMotorPorts = {2, 3}; - - /** - * The motor controller types that should be configured - */ - wpi::SmallVector motorControllers = { - sysid::motorcontroller::kPWM, sysid::motorcontroller::kPWM}; - - /** - * The CANivore name if it's on a Non-RIO bus - */ - wpi::SmallVector, 3> canivoreNames = - {{'r', 'i', 'o', '\0'}, {'r', 'i', 'o', '\0'}}; - - /** - * If the primary motor controllers (general mechanism motors / left - * drivetrain motors) should be inverted or not. - */ - wpi::SmallVector primaryMotorsInverted = {false, false}; - - /** - * If the secondary motor controllers (right drivetrain motors) should be - * inverted or not. - */ - wpi::SmallVector secondaryMotorsInverted = {false, false}; - - /** - * The type of encoder that's used. - */ - HardwareType encoderType = sysid::encoder::kRoboRIO; - - /** - * The encoder ports that are used as the primary encoder (general mechanism - * encoder / left drivetrain encoder). If they're plugged into the roboRIO it - * stores both ports, if its a CANCoder the port number is the first index. - */ - std::array primaryEncoderPorts = {0, 1}; - - /** - * The encoder ports that are used as the secondary encoder (right drivetrain - * encoder). If they're plugged into the roboRIO it stores both ports, if its - * a CANCoder the port number is the first index. - */ - std::array secondaryEncoderPorts = {2, 3}; - - /** - * CANivore names for the CANcoder sensors if they're not on the RIO bus. - */ - std::array encoderCANivoreName = {'r', 'i', 'o', - '\0'}; - - /** - * If the primary encoder (general mechanism motors / left drivetrain encoder) - * should be inverted or not. - */ - bool primaryEncoderInverted = false; - - /** - * If the secondary encoder (right drivetrain encoder) should be inverted or - * not. - */ - bool secondaryEncoderInverted = false; - - /** - * If using a CANcoder and it's using Pro. - */ - bool cancoderUsingPro = false; - - /** - * The counts per revolution of the encoder. - */ - double cpr = 1.0; - - /** - * The numerator for the gear ratio. - */ - double gearingNumerator = 1.0; - - /** - * The denominator for the gear ratio - */ - double gearingDenominator = 1.0; - - /** - * The type of gyro to configure. - */ - HardwareType gyro = sysid::gyro::kAnalogGyro; - - /** - * The gyro constructor to use. - */ - std::string gyroCtor = "0"; - - /** - * The CANivore name of a Pigeon2 if it's on a Non-RIO bus - */ - std::array gyroCANivoreName = {'r', 'i', 'o', - '\0'}; - - /** - * If the encoder is plugged into the roboRIO, there's the option to set it's - * encoding setting to reduce noise. - */ - bool encoding = false; - - /** - * The number of samples that should be used to calculate velocity. - */ - int numSamples = 1; - - /** - * The period of time in which the velocity is calculated. - */ - int period = 1; - - /** - * If the configuration is for a drivetrain. - */ - bool isDrive = false; -}; - -// Pre-built configuration for the Romi -- all Romis have the same setup. -const ConfigSettings kRomiConfig{{0}, - {1}, - {sysid::motorcontroller::kPWM}, - {{'r', 'i', 'o', '\0'}}, - {true}, - {false}, - sysid::encoder::kRoboRIO, - {4, 5}, - {6, 7}, - {{'r', 'i', 'o', '\0'}}, - false, - false, - false, - 1440.0, - 1.0, - 1.0, - sysid::gyro::kRomiGyro, - "", - {'r', 'i', 'o', '\0'}}; - -/** - * This class manages generating the JSON configuration from a reference to the - * settings struct. - */ -class ConfigManager { - public: - /** - * Constructs an instance of the ConfigManager that can generate config - * settings to save to a robot project. - * - * @param settings The settings for this instance of a ConfigManager. - * @param logger A reference to the logger to which log messages should be - * sent. - */ - ConfigManager(ConfigSettings& settings, wpi::Logger& logger); - - /** - * Generates the JSON from the settings struct provided in the constructor. - * - * @param occupied The number of occupied motor ports. Due to the way the GUI - * works, the number of elements in the vector is not - * necessarily how many ports the user actually wants -- this - * is kept track of in a separate variable. - * @return The generated JSON. - */ - wpi::json Generate(size_t occupied); - - /** - * Reads in a JSON and saves it as the stored settings - * - * @param path The path to the JSON - */ - void ReadJSON(std::string_view path); - - /** - * Writes the stored settings to a JSON - * - * @param path The path to save the JSON to - * @param occupied The number of motor controllers that will be used - */ - void SaveJSON(std::string_view path, size_t occupied); - - private: - // Configuration settings for this instance. - ConfigSettings& m_config; - - // Reference to logger for log messages. - wpi::Logger& m_logger; - - /** - * Returns a slice of a vector starting at its start element and ending at the - * specified size. - * - * @param m_data The vector to be sliced. - * @param size The desired size of the vector. - * @return A version of `m_data` that is `size` long. - */ - template - static std::vector SliceVector(wpi::SmallVector m_data, size_t size); -}; -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/generation/HardwareType.h b/sysid-application/src/main/native/include/sysid/generation/HardwareType.h deleted file mode 100644 index 6ad447c1..00000000 --- a/sysid-application/src/main/native/include/sysid/generation/HardwareType.h +++ /dev/null @@ -1,128 +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 -#include - -namespace sysid { -/** - * Stores information of a specific hardware device that sysid supports so that - * it can be easily identified, used, and displayed. - */ -struct HardwareType { - /** - * The name of the hardware device to facillitate comparisons - */ - std::string_view name; - - /** - * The display name of the hardware device to facilitate GUI display - */ - const char* displayName; - - /** - * Creates a HardwareType object from a device name. - * - * @param deviceName The name of the hardware device. - */ - constexpr explicit HardwareType(std::string_view deviceName) - : name{deviceName}, displayName{name.data()} {} - - /** - * Equality operator between HardwareTypes - * - * @param rhs Another HardwareType - * @returns True if they are equal - */ - constexpr bool operator==(const HardwareType& rhs) const { - return name == rhs.name; - } - - /** - * Inequality operator between HardwareTypes - * - * @param rhs Another HardwareType - * @returns True if they are not equal - */ - constexpr bool operator!=(const HardwareType& rhs) const { - return !operator==(rhs); - } -}; - -namespace motorcontroller { - -constexpr HardwareType kPWM{"PWM"}; -constexpr HardwareType kTalonSRX{"TalonSRX"}; -constexpr HardwareType kVictorSPX{"VictorSPX"}; -constexpr HardwareType kTalonFX{"TalonFX"}; -constexpr HardwareType kTalonFXPro{"TalonFX (Pro)"}; -constexpr HardwareType kSPARKMAXBrushless{"SPARK MAX (Brushless)"}; -constexpr HardwareType kSPARKMAXBrushed{"SPARK MAX (Brushed)"}; -constexpr HardwareType kVenom{"Venom"}; - -constexpr std::array kMotorControllers = { - kPWM, kTalonSRX, kVictorSPX, kTalonFX, - kTalonFXPro, kSPARKMAXBrushless, kSPARKMAXBrushed, kVenom}; - -/** - * Returns an existing motor controller HardwareType from a string_view. Throws - * if the passed name doesn't exist. - * - * @param name The name of the motor controller. - * @return The motor controller HardwareType associated with the inputted name. - */ -HardwareType FromMotorControllerName(std::string_view name); -} // namespace motorcontroller - -namespace encoder { -constexpr HardwareType kRoboRIO{"roboRIO quadrature"}; -constexpr HardwareType kCANCoder{"CANCoder"}; -constexpr HardwareType kCANcoderPro{"CANcoder (Pro)"}; -constexpr HardwareType kBuiltInSetting{"Built-in"}; -constexpr HardwareType kCTRETachometer{"Tachometer"}; -constexpr HardwareType kSMaxEncoderPort{"Encoder Port"}; -constexpr HardwareType kSMaxDataPort{"Data Port"}; - -constexpr std::array kEncoders = { - kRoboRIO, kCANCoder, kCANcoderPro, kBuiltInSetting, - kCTRETachometer, kSMaxEncoderPort, kSMaxDataPort}; - -/** - * Returns an existing encoder HardwareType from a string_view. Throws if the - * passed name doesn't exist. - * - * @param name The name of the encoder. - * @return The encoder HardwareType associated with the inputted name. - */ -HardwareType FromEncoderName(std::string_view name); -} // namespace encoder - -namespace gyro { -constexpr HardwareType kAnalogGyro{"Analog Gyro"}; -constexpr HardwareType kADXRS450{"ADXRS450"}; -constexpr HardwareType kADIS16448{"ADIS16448"}; -constexpr HardwareType kADIS16470{"ADIS16470"}; -constexpr HardwareType kNavX{"NavX"}; -constexpr HardwareType kPigeon{"Pigeon"}; -constexpr HardwareType kPigeon2{"Pigeon2"}; -constexpr HardwareType kPigeon2Pro{"Pigeon2 (Pro)"}; -constexpr HardwareType kRomiGyro{"Romi"}; -constexpr HardwareType kNoGyroOption{"None"}; - -constexpr std::array kGyros = { - kAnalogGyro, kADXRS450, kNavX, kPigeon, kPigeon2, - kADIS16448, kADIS16470, kRomiGyro, kNoGyroOption}; - -/** - * Returns an existing gyro HardwareType from a string_view. Throws if the - * passed name doesn't exist. - * - * @param name The name of the gyro. - * @return The gyro HardwareType associated with the inputted name. - */ -HardwareType FromGyroName(std::string_view name); -} // namespace gyro -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/view/Generator.h b/sysid-application/src/main/native/include/sysid/view/Generator.h deleted file mode 100644 index 5a73b6db..00000000 --- a/sysid-application/src/main/native/include/sysid/view/Generator.h +++ /dev/null @@ -1,263 +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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sysid/deploy/DeploySession.h" -#include "sysid/generation/ConfigManager.h" -#include "sysid/generation/HardwareType.h" - -namespace glass { -class Storage; -} // namespace glass - -namespace sysid { -/** - * Constexpr way of storing a const char* array of HardwareType names to be used - * with ImGui's const char* setup. Adapted from: - * https://stackoverflow.com/a/34465458 - * - * @tparam S The size of the array storing the HardwareTypes that will be used. - */ -template -struct DisplayNameStorage { - /** - * A const char* array to hold all the HardwareType names - */ - const char* names[S]{}; - - /** - * An int to pass into the size parameter of functions like `ImGui::Combo` - */ - const int size{S}; - - /** - * Constructs a constexpr DisplayNameStorage object - * - * @param devices The array of hardware devices to store display names for. - */ - explicit constexpr DisplayNameStorage(std::array devices) { - for (size_t i = 0; i < S; i++) { - names[i] = devices[i].displayName; - } - } -}; - -// Options -static constexpr auto kMotorControllerNames = - DisplayNameStorage(sysid::motorcontroller::kMotorControllers); - -static constexpr std::array kGeneralEncoders{ - sysid::encoder::kCANCoder.displayName, - sysid::encoder::kCANcoderPro.displayName, - sysid::encoder::kRoboRIO.displayName}; - -static constexpr std::array kTalonSRXEncoders{ - sysid::encoder::kBuiltInSetting.displayName, - sysid::encoder::kCTRETachometer.displayName}; - -static constexpr std::array kBuiltInEncoders{ - sysid::encoder::kBuiltInSetting.displayName}; - -static constexpr std::array kSparkMaxEncoders{ - sysid::encoder::kSMaxEncoderPort.displayName, - sysid::encoder::kSMaxDataPort.displayName}; - -static constexpr auto kGyroNames = DisplayNameStorage(sysid::gyro::kGyros); -static constexpr const char* kNavXCtors[] = {"SerialPort (USB)", "I2C (MXP)", - "SerialPort (MXP)", "SPI (MXP)"}; - -static constexpr const char* kADXRS450Ctors[] = {"SPI (Onboard CS0)", - "SPI (MXP)"}; - -static constexpr const char* kADIS16448Ctors[] = { - "SPI (MXP)", "SPI (Onboard CS0)", "SPI (Onboard CS1)", "SPI (Onboard CS2)", - "SPI (Onboard CS3)"}; - -static constexpr const char* kADIS16470Ctors[] = { - "SPI (Onboard CS0)", "SPI (Onboard CS1)", "SPI (Onboard CS2)", - "SPI (Onboard CS3)", "SPI (MXP)"}; - -// https://codedocs.revrobotics.com/cpp/classrev_1_1_spark_max_relative_encoder.html#ad2220467e1725840dbe77db4278a8d80 -static constexpr const char* kREVBuiltInNumSamples[] = {"1", "2", "4", "8"}; - -// https://codedocs.revrobotics.com/cpp/classrev_1_1_spark_max_relative_encoder.html#a8922f3c305ef6e57d7f639a17496c45d -static constexpr const char* kREVPeriods[] = { - "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", - "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", - "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", - "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", - "56", "57", "58", "59", "60", "61", "62", "63", "64"}; - -// https://docs.ctre-phoenix.com/en/stable/ch14_MCSensor.html#changing-velocity-measurement-parameters -static constexpr const char* kCTREBuiltInNumSamples[] = {"1", "2", "4", "8", - "16", "32", "64"}; -static constexpr const char* kCTREPeriods[] = {"1", "5", "10", "20", - "25", "50", "100"}; - -/** - * The generator GUI takes care of providing the user with a user interface to - * select their project parameters and then deploying the robot program to a - * roboRIO. - */ -class Generator : public glass::View { - public: - /** - * Creates a Generator Widget - * - * @param storage Glass Storage - * @param logger The program logger - */ - Generator(glass::Storage& storage, wpi::Logger& logger); - - /** - * Displays the generator widget. - */ - void Display() override; - - /** - * The supported project types. - */ - static constexpr const char* kAnalysisTypes[] = {"General Mechanism", - "Drivetrain", "Romi"}; - - private: - /** - * Helper method to display widgets to select the CTRE Encoder Velocity Period - */ - void SelectCTREVelocityPeriod(); - - /** - * Updates GUI based on the stored config - */ - void UpdateFromConfig(); - - /** - * Displays the widgets to invert a motor controller specific encoder. - * - * @param drive True if the encoder setup is for a Drivetrain. - */ - void RegularEncoderSetup(bool drive); - - /** - * Displays the widgets to setup encoders plugged into the roboRIO - * - * @param drive True if the encoder setup is for a Drivetrain. - */ - void RoboRIOEncoderSetup(bool drive); - - /** - * Displays the widgets to setup the CANCoder - * - * @param drive True if the encoder setup is for a Drivetrain. - * @param usePro True if CANcoder is using Pro firmware - */ - void CANCoderSetup(bool drive, bool usePro); - - /** - * Displays the encoder options for a specific combination of motor controller - * encoders. - * - * @tparam Size The size of the encoder array - * @param encoders The array of motor controller specific encoders and general - * encoders. - */ - template - void GetEncoder(const std::array& encoders) { - ImGui::Combo("Encoder", &m_encoderIdx, encoders.data(), encoders.size()); - m_settings.encoderType = - sysid::encoder::FromEncoderName(encoders[m_encoderIdx]); - if (m_settings.motorControllers[0] == - sysid::motorcontroller::kSPARKMAXBrushless && - m_settings.encoderType == sysid::encoder::kSMaxEncoderPort) { - // Spark Max built-in encoder number of samples must be within 8 to 64 - // inclusive - m_settings.numSamples = 8; - } - } - - // Configuration manager along with its settings -- used to generate the JSON - // configuration. - std::unique_ptr m_manager; - ConfigSettings m_settings; - - // Persistent storage pointers for project generation. - double& m_unitsPerRotation; - std::string& m_analysisType; - - // Indices for combo boxes. - int m_analysisIdx = 0; - int m_encoderIdx = 0; - int m_gyroIdx = 0; - int m_unitsIdx = 0; - int m_numSamplesIdx = 0; - int m_periodIdx = 0; - - HardwareType m_prevMainMotorController = sysid::motorcontroller::kPWM; - - // Keeps track of the number of motor ports the user wants. - size_t m_occupied = 1; - - // CTRE Pigeon-specific parameters. - int m_gyroPort = 1; - int m_gyroParam = 0; - bool m_isTalon = false; - - // Whether the user is running Spark MAX in Brushed Mode. - bool m_isSparkMaxBrushed = false; - - // Error Popup - bool m_errorPopup = false; - std::string m_errorMessage = ""; - - // Selectors for files - std::unique_ptr m_saveConfigSelector; - std::unique_ptr m_loadConfigSelector; - // Logger - wpi::Logger& m_logger; - - // The team number for the deploy process -- can also be a hostname or IP - // address of a RoboRIO. This points to the same location in memory as the - // "team" field in the Logger GUI. - std::string& m_team; - - // Create a separate logger for the deploy process. We can display all output - // messages in the modal popup during the deploy. - wpi::Logger m_deployLogger; - - // Create an event loop runner (runs a libuv event loop in a separate thread) - // for the deploy process. - wpi::EventLoopRunner m_deployRunner; - - // Represents the currently running or most recent deploy session. - std::unique_ptr m_deploySession; - - // Represents storage for a log message sent from the deploy event loop. - struct DeployLogMessage { - std::string message; - unsigned int level; - }; - - // A vector of log messages from the deploy event loop. - std::vector m_deployLog; - - // Mutex for accessing the deploy log. Because the event loop runs on a - // separate thread, this mutex must be locked when reading/writing to the log. - wpi::mutex m_deployMutex; -}; // namespace sysid -} // namespace sysid diff --git a/sysid-application/src/main/native/include/sysid/view/UILayout.h b/sysid-application/src/main/native/include/sysid/view/UILayout.h index 4d11e391..732a1aaf 100644 --- a/sysid-application/src/main/native/include/sysid/view/UILayout.h +++ b/sysid-application/src/main/native/include/sysid/view/UILayout.h @@ -62,10 +62,7 @@ inline constexpr Vector2d kLeftColSize{ 310, kAppWindowSize.y - kLeftColPos.y - kWindowGap}; // Left column contents -inline constexpr Vector2d kGeneratorWindowPos = kLeftColPos; -inline constexpr Vector2d kGeneratorWindowSize{kLeftColSize.x, 300}; -inline constexpr Vector2d kLoggerWindowPos = - kGeneratorWindowPos + Vector2d{0, kGeneratorWindowSize.y + kWindowGap}; +inline constexpr Vector2d kLoggerWindowPos = kLeftColPos; inline constexpr Vector2d kLoggerWindowSize{ kLeftColSize.x, kAppWindowSize.y - kWindowGap - kLoggerWindowPos.y}; diff --git a/sysid-application/src/test/native/cpp/deploy/DeployJSONTest.cpp b/sysid-application/src/test/native/cpp/deploy/DeployJSONTest.cpp deleted file mode 100644 index 2195a3a7..00000000 --- a/sysid-application/src/test/native/cpp/deploy/DeployJSONTest.cpp +++ /dev/null @@ -1,30 +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 -#include -#include - -#include "sysid/deploy/DeploySession.h" -#include "sysid/generation/ConfigManager.h" - -TEST(DeployTest, JSONGeneration) { - wpi::Logger m_logger; - sysid::ConfigSettings m_config; - sysid::ConfigManager m_configManager{m_config, m_logger}; - sysid::DeploySession m_session{"0", false, m_configManager.Generate(1), - m_logger}; - - const auto& json = m_session.GetJSON(); - - // Verify that it is valid JSON data - try { - wpi::json::parse(json.dump()); - } catch (wpi::json::parse_error err) { - FAIL(); - } - - // Make sure its an object - ASSERT_TRUE(json.is_object()); -} diff --git a/sysid-application/src/test/native/cpp/generation/HardwareTypeTest.cpp b/sysid-application/src/test/native/cpp/generation/HardwareTypeTest.cpp deleted file mode 100644 index a24b89f4..00000000 --- a/sysid-application/src/test/native/cpp/generation/HardwareTypeTest.cpp +++ /dev/null @@ -1,52 +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 -#include -#include -#include - -#include - -#include "sysid/generation/HardwareType.h" - -/** - * Tests to see if a HardwareType conversion function works on a given test - * array. It iterates through the test array and sees if the function returns - * the right HardwareType when given the string associated with said - * HardwareType. - * - * @tparam S The size of the test array - * - * @param testArray The test array of HardwareTypes - * @param func The function that should return the corresponding HardwareType - * based off of a passed string - */ -template -static void TestConversionFunction( - std::array testArray, - std::function func) { - for (auto& it : testArray) { - auto hardwareType = func(it.name); - EXPECT_EQ(hardwareType, it); - } -} - -TEST(HardwareTypeTest, FromMotorControllerName) { - TestConversionFunction(sysid::motorcontroller::kMotorControllers, - sysid::motorcontroller::FromMotorControllerName); - EXPECT_THROW(sysid::motorcontroller::FromMotorControllerName(""), - std::runtime_error); -} - -TEST(HardwareTypeTest, FromEncoderName) { - TestConversionFunction(sysid::encoder::kEncoders, - sysid::encoder::FromEncoderName); - EXPECT_THROW(sysid::encoder::FromEncoderName(""), std::runtime_error); -} - -TEST(HardwareTypeTest, FromGyroName) { - TestConversionFunction(sysid::gyro::kGyros, sysid::gyro::FromGyroName); - EXPECT_THROW(sysid::gyro::FromGyroName(""), std::runtime_error); -} diff --git a/sysid-library/build.gradle b/sysid-library/build.gradle deleted file mode 100644 index e721019a..00000000 --- a/sysid-library/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -plugins { - id "cpp" -} - -apply from: "${rootDir}/config.gradle" -nativeUtils.withCrossRoboRIO() - -model { - components { - libsysid(NativeLibrarySpec) { - targetPlatform nativeUtils.wpi.nativePlatforms.roborio - if (!project.hasProperty("skipDesktopRobots")) - targetPlatform nativeUtils.wpi.nativePlatforms.desktop - - sources.cpp { - source { - srcDirs "src/main/cpp" - include "**/*.cpp" - } - exportedHeaders.srcDirs "src/main/include" - } - - binaries.all { - if (it instanceof SharedLibraryBinarySpec) - it.buildable = false - - it.cppCompiler.define("PROJECT_ROOT_DIR", "$rootDir") - - if (project.hasProperty("integration")) - it.cppCompiler.define("INTEGRATION") - } - - nativeUtils.wpi.vendorDeps.nativeVendor.cpp(it) - nativeUtils.useRequiredLibrary(it, 'wpilib_executable_shared') - } - } -} diff --git a/sysid-library/gradle.properties b/sysid-library/gradle.properties deleted file mode 100644 index d2fff1eb..00000000 --- a/sysid-library/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -nativeutils.vendordep.folder.path=../vendordeps diff --git a/sysid-library/src/main/cpp/generation/SysIdSetup.cpp b/sysid-library/src/main/cpp/generation/SysIdSetup.cpp deleted file mode 100644 index 7b6c4354..00000000 --- a/sysid-library/src/main/cpp/generation/SysIdSetup.cpp +++ /dev/null @@ -1,554 +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 "sysid/generation/SysIdSetup.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -// #include -#include -#include -#include -#include -#include - -#ifdef __FRC_ROBORIO__ -#include "AHRS.h" -#endif - -// Based on https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html -#define EXPAND_STRINGIZE(s) STRINGIZE(s) -#define STRINGIZE(s) #s - -using namespace ctre::phoenixpro; - -namespace sysid { - -wpi::json GetConfigJson() { - std::string path; - - if constexpr (frc::RobotBase::IsSimulation()) { -#if defined(PROJECT_ROOT_DIR) && defined(INTEGRATION) - // TODO: Fix problems with this so that we don't need this ifdef - path = fmt::format("{}/sysid-projects/deploy/config.json", - EXPAND_STRINGIZE(PROJECT_ROOT_DIR)); -#endif - } else { - path = fmt::format("{}/config.json", frc::filesystem::GetDeployDirectory()); - } - - std::error_code ec; - wpi::raw_fd_istream is{path, ec}; - if (ec) { - fmt::print("File error: {}\n", path); - throw std::runtime_error("Unable to read file"); - } - - wpi::json outJson; - is >> outJson; - return outJson; -} - -void AddMotorController( - int port, std::string_view controller, bool inverted, - std::string_view canivore, - std::vector>* controllers) { - if (controller == "TalonSRX" || controller == "VictorSPX" || - controller == "TalonFX") { - if (controller == "TalonSRX") { - fmt::print("Setup TalonSRX\n"); - controllers->push_back(std::make_unique(port)); - } else if (controller == "TalonFX") { - fmt::print("Setup TalonFX\n"); - controllers->emplace_back(std::make_unique( - port, std::string{canivore.begin(), canivore.end()})); - } else { - fmt::print("Setup VictorSPX\n"); - controllers->emplace_back(std::make_unique(port)); - } - - auto* ctreController = - dynamic_cast(controllers->back().get()); - ctreController->ConfigFactoryDefault(); - ctreController->SetInverted(inverted); - ctreController->SetNeutralMode(motorcontrol::NeutralMode::Brake); - } else if (controller == "TalonFX (Pro)") { - fmt::print("Setup TalonFX (Pro)\n"); - controllers->emplace_back(std::make_unique( - port, std::string{canivore.begin(), canivore.end()})); - auto* ctreController = - dynamic_cast(controllers->back().get()); - configs::TalonFXConfiguration configs{}; - configs.MotorOutput.Inverted = - inverted ? ctre::phoenixpro::signals::InvertedValue:: - CounterClockwise_Positive - : ctre::phoenixpro::signals::InvertedValue::Clockwise_Positive; - ctreController->GetConfigurator().Apply(configs); - } else if (controller == "SPARK MAX (Brushless)" || - controller == "SPARK MAX (Brushed)") { - if (controller == "SPARK MAX (Brushless)") { - fmt::print("Setup SPARK MAX (Brushless)\n"); - controllers->emplace_back(std::make_unique( - port, rev::CANSparkMax::MotorType::kBrushless)); - } else { - fmt::print("Setup SPARK MAX (Brushed)\n"); - controllers->emplace_back(std::make_unique( - port, rev::CANSparkMax::MotorType::kBrushed)); - } - - auto* sparkMax = static_cast(controllers->back().get()); - sparkMax->RestoreFactoryDefaults(); - sparkMax->SetInverted(inverted); - sparkMax->SetIdleMode(rev::CANSparkMax::IdleMode::kBrake); - } else if (controller == "Venom") { - fmt::print("Setup Venom\n"); - controllers->emplace_back(std::make_unique(port)); - - auto* venom = static_cast(controllers->back().get()); - - venom->SetInverted(inverted); - venom->SetBrakeCoastMode(frc::CANVenom::BrakeCoastMode::kBrake); - controllers->emplace_back(std::make_unique(port)); - } else { - fmt::print("Setup PWM\n"); - controllers->emplace_back(std::make_unique(port)); - auto* spark = static_cast(controllers->back().get()); - spark->SetInverted(inverted); - } -} - -static sensors::SensorVelocityMeasPeriod getCTREVelocityPeriod(int period) { - switch (period) { - case 1: - return sensors::SensorVelocityMeasPeriod::Period_1Ms; - case 2: - return sensors::SensorVelocityMeasPeriod::Period_2Ms; - case 5: - return sensors::SensorVelocityMeasPeriod::Period_5Ms; - case 10: - return sensors::SensorVelocityMeasPeriod::Period_10Ms; - case 25: - return sensors::SensorVelocityMeasPeriod::Period_25Ms; - case 50: - return sensors::SensorVelocityMeasPeriod::Period_50Ms; - default: - return sensors::SensorVelocityMeasPeriod::Period_100Ms; - } -} - -static void SetupCTREEncoder(frc::MotorController* controller, - FeedbackDevice feedbackDevice, int period, - double cpr, int numSamples, bool encoderInverted, - std::function& position, - std::function& rate) { - auto* talonController = dynamic_cast(controller); - talonController->ConfigSelectedFeedbackSensor(feedbackDevice); - talonController->SetSensorPhase(encoderInverted); - talonController->ConfigVelocityMeasurementWindow(numSamples); - - // Determine velocity measurement period - auto talonPeriod = getCTREVelocityPeriod(period); - - talonController->ConfigVelocityMeasurementPeriod(talonPeriod); - position = [=] { return talonController->GetSelectedSensorPosition() / cpr; }; - rate = [=] { - return talonController->GetSelectedSensorVelocity() / cpr / - 0.1; // Conversion factor from 100 ms to seconds - }; -} - -void SetDefaultDataCollection(std::function& position, - std::function& rate) { - fmt::print("Setting default\n"); - position = [&] { return 0.0; }; - rate = [&] { return 0.0; }; -} - -void SetupEncoders( - std::string_view encoderType, bool isEncoding, int period, double cpr, - double gearing, int numSamples, std::string_view controllerName, - frc::MotorController* controller, bool encoderInverted, - const std::vector& encoderPorts, - const std::string& encoderCANivoreName, std::unique_ptr& cancoder, - std::unique_ptr& cancoderPro, - std::unique_ptr& revEncoderPort, - std::unique_ptr& revDataPort, - std::unique_ptr& encoder, std::function& position, - std::function& rate) { - double combinedCPR = cpr * gearing; - frc::SmartDashboard::PutNumber("SysIdCPR", cpr); - frc::SmartDashboard::PutNumber("SysIdGearing", gearing); - frc::SmartDashboard::PutNumber("SysIdConversionFactor", combinedCPR); - -#ifndef __FRC_ROBORIO__ - fmt::print("Setting default rates\n"); - SetDefaultDataCollection(position, rate); -#endif - if (encoderType == "Built-in") { - if (controllerName == "TalonFX (Pro)") { - fmt::print("Setup Built-in+TalonFX (Pro)\n"); - position = [=] { - return dynamic_cast(controller) - ->GetPosition() - .GetValue() - .value() / - gearing; - }; - rate = [=] { - return dynamic_cast(controller) - ->GetVelocity() - .GetValue() - .value() / - gearing; - }; - } else if (wpi::starts_with(controllerName, "Talon")) { - FeedbackDevice feedbackDevice; - if (controllerName == "TalonSRX") { - fmt::print("Setup Built-in+TalonSRX\n"); - feedbackDevice = FeedbackDevice::QuadEncoder; - } else { - fmt::print("Setup Built-in+TalonFX\n"); - feedbackDevice = FeedbackDevice::IntegratedSensor; - } - SetupCTREEncoder(controller, feedbackDevice, period, combinedCPR, - numSamples, encoderInverted, position, rate); - } else { // Venom - fmt::print("Setup Built-in+Venom\n"); - auto* venom = static_cast(controller); - position = [=] { return venom->GetPosition() / gearing; }; - rate = [=] { - return venom->GetSpeed() / gearing / - 60; // Conversion from RPM to rotations per second - }; - } - } else if (encoderType == "Encoder Port") { - auto* sparkMax = static_cast(controller); - if (controllerName != "SPARK MAX (Brushless)") { - fmt::print("Setup SPARK MAX (Brushed) Encoder Port\n"); - revEncoderPort = - std::make_unique(sparkMax->GetEncoder( - rev::SparkMaxRelativeEncoder::Type::kQuadrature, cpr)); - revEncoderPort->SetInverted(encoderInverted); - } else { - fmt::print("Setup SPARK MAX (Brushless) Encoder Port\n"); - revEncoderPort = - std::make_unique(sparkMax->GetEncoder( - rev::SparkMaxRelativeEncoder::Type::kHallSensor)); - } - - revEncoderPort->SetMeasurementPeriod(period); - revEncoderPort->SetAverageDepth(numSamples); - - position = [=, &revEncoderPort] { - return revEncoderPort->GetPosition() / gearing; - }; - rate = [=, &revEncoderPort] { - return revEncoderPort->GetVelocity() / gearing / 60; - }; - } else if (encoderType == "Data Port") { - fmt::print("Setup SPARK MAX Data Port\n"); - auto* sparkMax = static_cast(controller); - revDataPort = std::make_unique( - sparkMax->GetAlternateEncoder( - rev::SparkMaxAlternateEncoder::Type::kQuadrature, cpr)); - revDataPort->SetInverted(encoderInverted); - revDataPort->SetMeasurementPeriod(period); - revDataPort->SetAverageDepth(numSamples); - position = [=, &revDataPort] { - return revDataPort->GetPosition() / gearing; - }; - rate = [=, &revDataPort] { - return revDataPort->GetVelocity() / gearing / 60; - }; - } else if (encoderType == "Tachometer") { - fmt::print("Setup Tachometer\n"); - SetupCTREEncoder(controller, FeedbackDevice::Tachometer, period, - combinedCPR, numSamples, encoderInverted, position, rate); - } else if (encoderType == "CANCoder") { - fmt::print("Setup CANCoder\n"); - cancoder = std::make_unique(encoderPorts[0], encoderCANivoreName); - cancoder->ConfigSensorDirection(encoderInverted); - - sensors::SensorVelocityMeasPeriod cancoderPeriod = - getCTREVelocityPeriod(period); - - cancoder->ConfigVelocityMeasurementPeriod(cancoderPeriod); - cancoder->ConfigVelocityMeasurementWindow(numSamples); - - position = [=, &cancoder] { return cancoder->GetPosition() / combinedCPR; }; - rate = [=, &cancoder] { return cancoder->GetVelocity() / combinedCPR; }; - } else if (encoderType == "CANcoder (Pro)") { - fmt::print("Setup CANCoder (Pro)\n"); - cancoderPro = std::make_unique(encoderPorts[0], - encoderCANivoreName); - configs::CANcoderConfiguration cfg; - cfg.MagnetSensor.SensorDirection = - encoderInverted ? ctre::phoenixpro::signals::SensorDirectionValue:: - Clockwise_Positive - : ctre::phoenixpro::signals::SensorDirectionValue:: - CounterClockwise_Positive; - cancoderPro->GetConfigurator().Apply(cfg); - - position = [=, &cancoderPro] { - return cancoderPro->GetPosition().GetValue().value() / combinedCPR; - }; - rate = [=, &cancoderPro] { - return cancoderPro->GetVelocity().GetValue().value() / combinedCPR; - }; - } else { - fmt::print("Setup roboRIO quadrature\n"); - if (isEncoding) { - encoder = std::make_unique( - encoderPorts[0], encoderPorts[1], encoderInverted, - frc::CounterBase::EncodingType::k1X); - } else { - encoder = std::make_unique(encoderPorts[0], encoderPorts[1], - encoderInverted); - } - - encoder->SetDistancePerPulse(1 / combinedCPR); - encoder->SetReverseDirection(encoderInverted); - encoder->SetSamplesToAverage(numSamples); - position = [&] { return encoder->GetDistance(); }; - rate = [&] { return encoder->GetRate(); }; - } -} - -static frc::SPI::Port GetSPIPort(std::string_view name) { - if (name == "SPI (Onboard CS0)") { - fmt::print("Setup SPI (Onboard CS0)\n"); - return frc::SPI::Port::kOnboardCS0; - } else if (name == "SPI (Onboard CS1)") { - fmt::print("Setup SPI (Onboard CS1)\n"); - return frc::SPI::Port::kOnboardCS1; - } else if (name == "SPI (Onboard CS2)") { - fmt::print("Setup SPI (Onboard CS2)\n"); - return frc::SPI::Port::kOnboardCS2; - } else if (name == "SPI (Onboard CS3)") { - fmt::print("Setup SPI (Onboard CS3)\n"); - return frc::SPI::Port::kOnboardCS3; - } else if (name == "SPI (MXP)") { - fmt::print("Setup SPI (MXP)\n"); - return frc::SPI::Port::kMXP; - } else { - throw std::runtime_error( - fmt::format("{} is not a supported SPI Port\n", name)); - } -} - -void SetupGyro( - std::string_view gyroType, std::string_view gyroCtor, - const std::vector& leftPorts, const std::vector& rightPorts, - const std::vector& controllerNames, - const std::vector>& leftControllers, - const std::vector>& rightControllers, - std::unique_ptr& gyro, - std::unique_ptr& ADIS16448Gyro, - std::unique_ptr& ADIS16470Gyro, - std::unique_ptr& pigeon, - std::unique_ptr& pigeonpro, - std::unique_ptr& tempTalon, - const std::string& gyroCANivoreName, std::function& gyroPosition, - std::function& gyroRate) { -#ifndef __FRC_ROBORIO__ - sysid::SetDefaultDataCollection(gyroPosition, gyroRate); -#endif - if (gyroType == "Pigeon2 (Pro)") { - std::string portStr; - portStr = gyroCtor; - int canID = std::stoi(portStr); - pigeonpro = std::make_unique( - canID, gyroCANivoreName); - fmt::print("Setup Pigeon2 (Pro), {}\n", portStr); - - // setup functions - gyroPosition = [&] { - return units::radian_t{pigeonpro->GetYaw().GetValue()}.value(); - }; - - gyroRate = [&] { - return units::radians_per_second_t{ - pigeonpro->GetAngularVelocityZ().GetValue()} - .value(); - }; - } else if (wpi::starts_with(gyroType, "Pigeon")) { - std::string portStr; - if (wpi::contains(gyroCtor, "WPI_TalonSRX")) { - portStr = wpi::split(gyroCtor, "-").second; - } else { - portStr = gyroCtor; - } - - // converts gyroCtor into port # - int srxPort = std::stoi(portStr); - if (wpi::contains(gyroCtor, "WPI_TalonSRX")) { - std::vector ports = leftPorts; - ports.insert(ports.end(), rightPorts.begin(), rightPorts.end()); - // Check if there is a Talon Port in Left Ports - auto findPort = std::find(ports.begin(), ports.end(), srxPort); - - WPI_TalonSRX* talon; - if (findPort != ports.end()) { - // If the object already exists, find it and store it - if (std::distance(ports.begin(), findPort) < - std::distance(leftPorts.begin(), leftPorts.end())) { - talon = dynamic_cast( - leftControllers.at(findPort - ports.begin()).get()); - } else { - talon = dynamic_cast( - rightControllers.at(findPort - ports.begin() - leftPorts.size()) - .get()); - } - portStr = fmt::format("{} (plugged to drive motorcontroller)", portStr); - } else { - // If it isn't tied to an existing Talon, create a new object - tempTalon = std::make_unique(srxPort); - talon = tempTalon.get(); - portStr = fmt::format("{} (plugged to other motorcontroller)", portStr); - } - pigeon = std::make_unique(talon); - fmt::print("Setup Pigeon, {}\n", portStr); - } else { - portStr = fmt::format("{} (CAN)", portStr); - - if (gyroType == "Pigeon") { - pigeon = std::make_unique(srxPort); - fmt::print("Setup Pigeon, {}\n", portStr); - } else { - pigeon = std::make_unique( - srxPort, gyroCANivoreName); - fmt::print("Setup Pigeon2, {}\n", portStr); - } - } - - // setup functions - gyroPosition = [&] { - double xyz[3]; - pigeon->GetAccumGyro(xyz); - units::degree_t pos{xyz[2]}; - return units::radian_t{pos}.value(); - }; - - gyroRate = [&] { - double xyz_dps[3]; - pigeon->GetRawGyro(xyz_dps); - units::degrees_per_second_t rate{xyz_dps[2]}; - return units::radians_per_second_t{rate}.value(); - }; - } else if (wpi::starts_with(gyroType, "ADIS")) { - auto port = GetSPIPort(gyroCtor); - if (gyroType == "ADIS16448") { - fmt::print("Setup ADIS16448\n"); - // Calibration time of 8 seconds: - // https://github.com/juchong/ADIS16448-RoboRIO-Driver-Examples/blob/master/c%2B%2B/src/main/cpp/Robot.cpp#L48 - ADIS16448Gyro = std::make_unique( - frc::ADIS16448_IMU::IMUAxis::kZ, port, - frc::ADIS16448_IMU::CalibrationTime::_8s); - gyroPosition = [&] { - return units::radian_t{ADIS16448Gyro->GetAngle()}.value(); - }; - - gyroRate = [&] { - return units::radians_per_second_t{ADIS16448Gyro->GetRate()}.value(); - }; - } else if (gyroType == "ADIS16470") { - fmt::print("Setup ADIS16470\n"); - // Calibration time of 8 seconds: - // https://github.com/juchong/ADIS16470-RoboRIO-Driver-Examples/blob/master/c%2B%2B/src/main/cpp/Robot.cpp#L52 - ADIS16470Gyro = std::make_unique( - frc::ADIS16470_IMU::IMUAxis::kZ, port, - frc::ADIS16470_IMU::CalibrationTime::_8s); - gyroPosition = [&] { - return units::radian_t{ADIS16470Gyro->GetAngle()}.value(); - }; - - gyroRate = [&] { - return units::radians_per_second_t{ADIS16470Gyro->GetRate()}.value(); - }; - } - } else if (gyroType != "None") { - if (gyroType == "ADXRS450") { - auto port = GetSPIPort(gyroCtor); - fmt::print("Setup ADXRS450\n"); - gyro = std::make_unique(port); - - } else if (gyroType == "NavX") { - if (gyroCtor == "SerialPort (USB)") { - fmt::print("Setup NavX, SerialPort (USB)\n"); -#ifdef __FRC_ROBORIO__ - gyro = std::make_unique(frc::SerialPort::Port::kUSB); -#endif - } else if (gyroCtor == "I2C (MXP)") { - fmt::print("Setup NavX, I2C (MXP)\n"); -#ifdef __FRC_ROBORIO__ - gyro = std::make_unique(frc::I2C::Port::kMXP); -#endif - } else if (gyroCtor == "SerialPort (MXP)") { - fmt::print("Setup NavX, SerialPort (MXP)\n"); -#ifdef __FRC_ROBORIO__ - gyro = std::make_unique(frc::SerialPort::Port::kMXP); -#endif - } else { - fmt::print("Setup NavX, SPI (MXP)\n"); -#ifdef __FRC_ROBORIO__ - gyro = std::make_unique(frc::SPI::Port::kMXP); -#endif - } - // // FIXME: Update Romi Gyro once vendordep is out - } else if (gyroType == "Romi") { - fmt::print("Setup Romi\n"); - // #ifndef __FRC_ROBORIO__ - // gyro = std::make_unique(); - // #endif - } else if (gyroType == "Analog Gyro") { - try { - fmt::print("Setup Analog Gyro, {}\n", gyroCtor); - gyro = - std::make_unique(std::stoi(std::string{gyroCtor})); - } catch (std::invalid_argument& e) { - fmt::print("Setup Analog Gyro, 0\n"); - gyro = std::make_unique(0); - } - } -#ifdef __FRC_ROBORIO__ - gyroPosition = [&] { - return units::radian_t{units::degree_t{gyro->GetAngle()}}.value(); - }; - - gyroRate = [&] { - return units::radians_per_second_t{ - units::degrees_per_second_t{gyro->GetRate()}} - .value(); - }; -#endif - // Default behaviour is to make the gyro functions return zero - } else { - fmt::print("Setup None\n"); - SetDefaultDataCollection(gyroPosition, gyroRate); - } -} - -void SetMotorControllers( - units::volt_t motorVoltage, - const std::vector>& controllers) { - for (auto&& controller : controllers) { - auto* ctreController = dynamic_cast(controller.get()); - if (ctreController) { - ctreController->SetControl( - controls::VoltageOut{motorVoltage, true, false}); - } else { - controller->SetVoltage(motorVoltage); - } - } -} - -} // namespace sysid diff --git a/sysid-library/src/main/cpp/logging/SysIdDrivetrainLogger.cpp b/sysid-library/src/main/cpp/logging/SysIdDrivetrainLogger.cpp deleted file mode 100644 index 1d4986f3..00000000 --- a/sysid-library/src/main/cpp/logging/SysIdDrivetrainLogger.cpp +++ /dev/null @@ -1,45 +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 "sysid/logging/SysIdDrivetrainLogger.h" - -#include - -#include - -using namespace sysid; - -units::volt_t SysIdDrivetrainLogger::GetLeftMotorVoltage() const { - return m_primaryMotorVoltage; -} - -units::volt_t SysIdDrivetrainLogger::GetRightMotorVoltage() const { - return m_secondaryMotorVoltage; -} - -void SysIdDrivetrainLogger::Log(double leftVoltage, double rightVoltage, - double leftPosition, double rightPosition, - double leftVelocity, double rightVelocity, - double measuredAngle, double angularRate) { - UpdateData(); - if (m_data.size() < kDataVectorSize) { - std::array arr{m_timestamp, leftVoltage, rightVoltage, - leftPosition, rightPosition, leftVelocity, - rightVelocity, measuredAngle, angularRate}; - m_data.insert(m_data.end(), arr.cbegin(), arr.cend()); - } - - m_primaryMotorVoltage = units::volt_t{(m_rotate ? -1 : 1) * m_motorVoltage}; - m_secondaryMotorVoltage = units::volt_t{m_motorVoltage}; -} - -void SysIdDrivetrainLogger::Reset() { - SysIdLogger::Reset(); - m_primaryMotorVoltage = 0_V; - m_secondaryMotorVoltage = 0_V; -} - -bool SysIdDrivetrainLogger::IsWrongMechanism() const { - return m_mechanism != "Drivetrain" && m_mechanism != "Drivetrain (Angular)"; -} diff --git a/sysid-library/src/main/cpp/logging/SysIdGeneralMechanismLogger.cpp b/sysid-library/src/main/cpp/logging/SysIdGeneralMechanismLogger.cpp deleted file mode 100644 index cf0822aa..00000000 --- a/sysid-library/src/main/cpp/logging/SysIdGeneralMechanismLogger.cpp +++ /dev/null @@ -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 "sysid/logging/SysIdGeneralMechanismLogger.h" - -#include - -#include - -using namespace sysid; - -units::volt_t SysIdGeneralMechanismLogger::GetMotorVoltage() const { - return m_primaryMotorVoltage; -} - -void SysIdGeneralMechanismLogger::Log(double voltage, double measuredPosition, - double measuredVelocity) { - UpdateData(); - if (m_data.size() < kDataVectorSize) { - std::array arr{m_timestamp, voltage, measuredPosition, - measuredVelocity}; - m_data.insert(m_data.end(), arr.cbegin(), arr.cend()); - } - - m_primaryMotorVoltage = units::volt_t{m_motorVoltage}; -} - -void SysIdGeneralMechanismLogger::Reset() { - SysIdLogger::Reset(); - m_primaryMotorVoltage = 0_V; -} - -bool SysIdGeneralMechanismLogger::IsWrongMechanism() const { - return m_mechanism != "Arm" && m_mechanism != "Elevator" && - m_mechanism != "Simple"; -} diff --git a/sysid-library/src/main/cpp/logging/SysIdLogger.cpp b/sysid-library/src/main/cpp/logging/SysIdLogger.cpp deleted file mode 100644 index 8a85570d..00000000 --- a/sysid-library/src/main/cpp/logging/SysIdLogger.cpp +++ /dev/null @@ -1,167 +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 "sysid/logging/SysIdLogger.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace sysid; - -void SysIdLogger::InitLogging() { - m_mechanism = frc::SmartDashboard::GetString("SysIdTest", ""); - if (m_mechanism == "") { - fmt::print( - "WARNING: Robot enabled before connecting SysId. Connect SysId, then " - "reenable the robot.\n"); - } else { - frc::SmartDashboard::PutBoolean("SysIdWrongMech", IsWrongMechanism()); - } - - m_testType = frc::SmartDashboard::GetString("SysIdTestType", ""); - m_rotate = frc::SmartDashboard::GetBoolean("SysIdRotate", false); - m_voltageCommand = frc::SmartDashboard::GetNumber("SysIdVoltageCommand", 0.0); - m_startTime = frc::Timer::GetFPGATimestamp().value(); - m_data.clear(); - frc::SmartDashboard::PutString("SysIdTelemetry", ""); - m_ackNum = frc::SmartDashboard::GetNumber("SysIdAckNumber", 0); -} - -double SysIdLogger::MeasureVoltage( - const std::vector>& controllers, - const std::vector& controllerNames) { - double sum = 0.0; - for (size_t i = 0; i < controllers.size(); ++i) { - auto&& controller = controllers[i].get(); - if (wpi::starts_with(controllerNames[i], "SPARK MAX")) { - auto* smax = static_cast(controller); - sum += smax->GetBusVoltage() * smax->GetAppliedOutput(); - if constexpr (frc::RobotBase::IsSimulation()) { - fmt::print("Recording SPARK MAX voltage\n"); - } - } else if (controllerNames[i] == "TalonFX (Pro)") { - auto* ctreController = - dynamic_cast(controller); - sum += ctreController->GetDutyCycle().GetValue().value() * - ctreController->GetSupplyVoltage().GetValue().value(); - if constexpr (frc::RobotBase::IsSimulation()) { - fmt::print("Recording CTRE (Pro) voltage\n"); - } - } else if (wpi::starts_with(controllerNames[i], "Talon") || - wpi::starts_with(controllerNames[i], "Victor")) { - auto* ctreController = dynamic_cast(controller); - sum += ctreController->GetMotorOutputVoltage(); - if constexpr (frc::RobotBase::IsSimulation()) { - fmt::print("Recording CTRE voltage\n"); - } - } else if (controllerNames[i] == "Venom") { - auto* venom = static_cast(controller); - sum += venom->GetOutputVoltage(); - if constexpr (frc::RobotBase::IsSimulation()) { - fmt::print("Recording Venom voltage\n"); - } - } else { - sum += controllers[i]->Get() * - frc::RobotController::GetBatteryVoltage().value(); - if constexpr (frc::RobotBase::IsSimulation()) { - fmt::print("Recording General voltage\n"); - } - } - } - - return sum / controllers.size(); -} - -void SysIdLogger::SendData() { - fmt::print("Collected: {} data points.\n", m_data.size()); - - frc::SmartDashboard::PutBoolean("SysIdOverflow", - m_data.size() >= kDataVectorSize); - - std::stringstream ss; - for (size_t i = 0; i < m_data.size(); ++i) { - ss << std::to_string(m_data[i]); - if (i < m_data.size() - 1) { - ss << ","; - } - } - - std::string type = m_testType == "Dynamic" ? "fast" : "slow"; - std::string direction = m_voltageCommand > 0 ? "forward" : "backward"; - std::string test = fmt::format("{}-{}", type, direction); - - frc::SmartDashboard::PutString("SysIdTelemetry", - fmt::format("{};{}", test, ss.str())); - frc::SmartDashboard::PutNumber("SysIdAckNumber", ++m_ackNum); - - Reset(); -} - -void SysIdLogger::ClearWhenReceived() { - if (frc::SmartDashboard::GetNumber("SysIdAckNumber", 0.0) > m_ackNum) { - frc::SmartDashboard::PutString("SysIdTelemetry", ""); - m_ackNum = frc::SmartDashboard::GetNumber("SysIdAckNumber", 0.0); - } -} - -void SysIdLogger::UpdateThreadPriority() { - if constexpr (!frc::RobotBase::IsSimulation()) { - if (!frc::Notifier::SetHALThreadPriority(true, kHALThreadPriority) || - !frc::SetCurrentThreadPriority(true, kThreadPriority)) { - throw std::runtime_error("Setting the RT Priority failed\n"); - } - } -} - -SysIdLogger::SysIdLogger() { - fmt::print("Initializing logger\n"); - m_data.reserve(kDataVectorSize); - frc::LiveWindow::DisableAllTelemetry(); - frc::SmartDashboard::PutNumber("SysIdVoltageCommand", 0.0); - frc::SmartDashboard::PutString("SysIdTestType", ""); - frc::SmartDashboard::PutString("SysIdTest", ""); - frc::SmartDashboard::PutBoolean("SysIdRotate", false); - frc::SmartDashboard::PutBoolean("SysIdOverflow", false); - frc::SmartDashboard::PutBoolean("SysIdWrongMech", false); - frc::SmartDashboard::PutNumber("SysIdAckNumber", m_ackNum); -} - -void SysIdLogger::UpdateData() { - m_timestamp = frc::Timer::GetFPGATimestamp().value(); - - // Don't let robot move if it's characterizing the wrong mechanism - if (!IsWrongMechanism()) { - if (m_testType == "Quasistatic") { - m_motorVoltage = m_voltageCommand * (m_timestamp - m_startTime); - } else if (m_testType == "Dynamic") { - m_motorVoltage = m_voltageCommand; - } else { - m_motorVoltage = 0.0; - } - } else { - m_motorVoltage = 0.0; - } -} - -void SysIdLogger::Reset() { - m_motorVoltage = 0.0; - m_timestamp = 0.0; - m_startTime = 0.0; - m_data.clear(); -} diff --git a/sysid-library/src/main/include/sysid/generation/SysIdSetup.h b/sysid-library/src/main/include/sysid/generation/SysIdSetup.h deleted file mode 100644 index 71ef8286..00000000 --- a/sysid-library/src/main/include/sysid/generation/SysIdSetup.h +++ /dev/null @@ -1,172 +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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Keep CTRE includes below ADIS16448_IMU header to allow Windows to build */ -#include -#include -#include -#include - -namespace sysid { - -wpi::json GetConfigJson(); - -/** - * Instantiates and adds a motor controller to a vector containing speed - * controller pointers. - * - * @param[in] port The port number that the motor controller is plugged into. - * @param[in] controller The type of motor controller, should be one of these: - * "PWM", "TalonSRX", "VictorSPX", "TalonFX", "TalonFX - * (Pro)" "SPARK MAX (Brushless)", "SPARK AX (Brushed)", "Venom" - * @param[in] inverted True if the motor controller should be inverted, false if - * not. - * @param[in] canivore Name of the CANivore bus the motor controller is on. - * @param[in, out] controllers A reference to the vector storing the motor - * controller objects - */ -void AddMotorController( - int port, std::string_view controller, bool inverted, - std::string_view canivore, - std::vector>* controllers); - -/** - * Sets all the motor controllers stored to a certain voltage - * - * @param[in] motorVoltage The voltage the motors should be set to. - * @param[in] controllers The vector that the motor controllers are being stored - * in. - */ -void SetMotorControllers( - units::volt_t motorVoltage, - const std::vector>& controllers); - -/** - * Sets up an encoder for data collection by settings a position and rate - * function to report the right encoder values. - * - * @param[in] encoderType The type of encoder used, should be one of these: - * "Built-in", "Tachometer", "CANCoder", - * "CANcoder (Pro)", "roboRIO quadrature", - * "Encoder Port", "Data Port" - * @param[in] isEncoding True if the encoder should be in an encoding setting - * (only applies to Encoders plugged into a roboRIO) - * @param[in] period The measurement period used to calculate velocity of the - * encoder (doesn't apply to roboRIO encoders) - * @param[in] cpr The counts per revolution of the encoder - * @param[in] gearing The gear ratio from the encoder shaft to the wheel shaft. - * @param[in] numSamples The number of samples that should be taken for a - * velocity measurement - * @param[in] controllerName The main motor controller being used in the setup. - * @param[in] controller A pointer to the main motor controller object being - * used in the setup. - * @param[in] encoderInverted True if the encoder is supposed to be inverted - * (doesn't apply to NEO Integrated Encoders) - * @param[in] encoderPorts Port number for the encoder if its not plugged into a - * motor controller. 2 ports should be used for roboRIO - * encoders, 1 port should be used for CANCoder. - * @param[in] encoderCANivoreName The name of the CANivore bus the encoder is - * on. - * @param[in, out] cancoder A reference to a CANCoder object - * @param[in, out] cancoderPro A reference to a CANcoder Pro object - * @param[in, out] revEncoderPort A reference to a REV Encoder Port object - * @param[in, out] revDataPort A reference to a REV Data Port object - * @param[in, out] encoder A reference to a roboRIO encoder object - * @param[out] position A reference to a function that is supposed to return the - * encoder position - * @param[out] rate A reference to a function that is supposed to return the - * encoder rate - */ -void SetupEncoders( - std::string_view encoderType, bool isEncoding, int period, double cpr, - double gearing, int numSamples, std::string_view controllerName, - frc::MotorController* controller, bool encoderInverted, - const std::vector& encoderPorts, - const std::string& encoderCANivoreName, std::unique_ptr& cancoder, - std::unique_ptr& cancoderPro, - std::unique_ptr& revEncoderPort, - std::unique_ptr& revDataPort, - std::unique_ptr& encoder, std::function& position, - std::function& rate); - -/** - * Sets up an encoder for data collection by settings a position and rate - * function to report the right encoder values. - * - * @param[in] gyroType The type of gyro to configure. Options include: "Analog - * Gyro", "ADXRS450", "NavX", "Pigeon", "Romi", "None" - * @param[in] gyroCtor The type of constructor to use with the gyro. This varies - * based on the gyro. - * @param[in] leftPorts All of the specified ports on the left side of the - * drivetrain. Intended to be used when there's a Pigeon - * IMU plugged into a drive motor controller. - * @param[in] rightPorts All of the specified ports on the right side of the - * drivetrain. Intended to be used when there's a Pigeon - * IMU plugged into a drive motor controller. - * @param[in] controllerNames The motor controllers being used in the setup. - * @param[in] leftControllers A vector of stored motor controller objects for - * the left side of the drivetrain. Intended to be - * used when there's a Pigeon IMU plugged into a - * drive motor controller. - * @param[in] rightControllers A vector of stored motor controller objects for - * the right side of the drivetrain. Intended to be - * used when there's a Pigeon IMU plugged into a - * drive motor controller. - * @param[in, out] gyro A pointer to a WPILib Gyro object. - * @param[in, out] ADIS16448Gyro A pointer to an ADIS16448_IMU object. - * @param[in, out] ADIS16470Gyro A pointer to an ADIS16470_IMU object. - * @param[in, out] pigeon A pointer to a Pigeon IMU Object - * @param[in, out] pigeonpro A pointer to a Pigeon2 Pro Object - * @param[in, out] tempTalon A pointer to a TalonSRX object mean to store a - * Talon that the Pigeon IMU is plugged into. - * @param[in] gyroCANivoreName A reference to the name of the CANivore the Gyro - * is plugged into. - * @param[out] gyroPosition A reference to a function that is supposed to return - * the gyro position - * @param[out] gyroRate A reference to a function that is supposed to return the - * gyro rate - */ -void SetupGyro( - std::string_view gyroType, std::string_view gyroCtor, - const std::vector& leftPorts, const std::vector& rightPorts, - const std::vector& controllerNames, - const std::vector>& leftControllers, - const std::vector>& rightControllers, - std::unique_ptr& gyro, - std::unique_ptr& ADIS16448Gyro, - std::unique_ptr& ADIS16470Gyro, - std::unique_ptr& pigeon, - std::unique_ptr& pigeonpro, - std::unique_ptr& tempTalon, - const std::string& gyroCANivoreName, std::function& gyroPosition, - std::function& gyroRate); - -/** - * Sets specified data collection functions to return zero. This is to avoid - * runtime crashes for when the functions aren't defined. - * - * @param[out] position The position data collection function - * @param[out] rate The rate data collection function - */ -void SetDefaultDataCollection(std::function& position, - std::function& rate); -} // namespace sysid diff --git a/sysid-library/src/main/include/sysid/logging/SysIdDrivetrainLogger.h b/sysid-library/src/main/include/sysid/logging/SysIdDrivetrainLogger.h deleted file mode 100644 index 71e6ce9b..00000000 --- a/sysid-library/src/main/include/sysid/logging/SysIdDrivetrainLogger.h +++ /dev/null @@ -1,64 +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 - -#include "sysid/logging/SysIdLogger.h" - -namespace sysid { - -/** - * Serves to provide methods for robot projects seeking to send and receive data - * in occurdence to the SysId drivetrain protocols. - */ -class SysIdDrivetrainLogger : public SysIdLogger { - public: - /** - * The users should their left motors to what this returns AFTER calling log. - * - * @returns The voltage that the left motor(s) should be set to. - */ - units::volt_t GetLeftMotorVoltage() const; - - /** - * The users should set their right motors to what this returns AFTER calling - * log. - * - * @returns The voltage that the right motor(s) should be set to. - */ - units::volt_t GetRightMotorVoltage() const; - - /** - * Logs data for a drivetrain mechanism. - * - * When SendData() is called it outputs data in the form: timestamp, l - * voltage, r voltage, l position, r position, l velocity, r velocity, angle, - * angular rate - * - * @param leftVoltage the recorded voltage of the left motors - * @param rightVoltage the recorded voltage of the right motors - * @param leftPosition the recorded rotations of the left shaft - * @param rightPosition the recorded rotations of the right shaft - * @param leftVelocity the recorded rotations per second of the left shaft - * @param rightVelocity the recorded rotations per second or the right shaft - * @param measuredAngle the recorded angle of they gyro - * @param angularRate the recorded angular rate of the gyro in radians per - * second - */ - void Log(double leftVoltage, double rightVoltage, double leftPosition, - double rightPosition, double leftVelocity, double rightVelocity, - double measuredAngle, double angularRate); - - void Reset() override; - - bool IsWrongMechanism() const override; - - private: - units::volt_t m_primaryMotorVoltage = 0_V; - units::volt_t m_secondaryMotorVoltage = 0_V; -}; - -} // namespace sysid diff --git a/sysid-library/src/main/include/sysid/logging/SysIdGeneralMechanismLogger.h b/sysid-library/src/main/include/sysid/logging/SysIdGeneralMechanismLogger.h deleted file mode 100644 index 48d81c0c..00000000 --- a/sysid-library/src/main/include/sysid/logging/SysIdGeneralMechanismLogger.h +++ /dev/null @@ -1,46 +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 - -#include "sysid/logging/SysIdLogger.h" - -namespace sysid { - -/** - * Serves to provide methods for robot projects seeking to send and receive data - * in occurdence to the SysId general mechanism protocols. - */ -class SysIdGeneralMechanismLogger : public SysIdLogger { - public: - /** - * The users should set their motors to what this returns AFTER calling log. - * - * @returns The voltage that the mechanism motor(s) should be set to. - */ - units::volt_t GetMotorVoltage() const; - - /** - * Logs data for a single-sided mechanism (Elevator, Simple, Arm). - * - * When SendData() is called it outputs data in the form: timestamp, voltage, - * position, velocity. - * - * @param voltage the recorded voltage of the motors - * @param measuredPosition the recorded rotations of the shaft - * @param measuredVelocity the recorded rotations per second of the shaft - */ - void Log(double voltage, double measuredPosition, double measuredVelocity); - - void Reset() override; - - bool IsWrongMechanism() const override; - - private: - units::volt_t m_primaryMotorVoltage = 0_V; -}; - -} // namespace sysid diff --git a/sysid-library/src/main/include/sysid/logging/SysIdLogger.h b/sysid-library/src/main/include/sysid/logging/SysIdLogger.h deleted file mode 100644 index d23fbcbc..00000000 --- a/sysid-library/src/main/include/sysid/logging/SysIdLogger.h +++ /dev/null @@ -1,140 +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 -#include -#include -#include - -#include - -namespace sysid { - -/** - * Base class that serves to provide methods for robot projects seeking to send - * and receive data in occurdence to the SysId application's protocols. - */ -class SysIdLogger { - public: - /** - * Code that should be run to initialize the logging routine. Should be called - * in `AutonomousInit()`. - */ - void InitLogging(); - - /** - * Sends data after logging is complete. - * - * Called in DisabledInit(). - */ - void SendData(); - - /** - * Clears the data entry when sysid logger acknowledges that it received data. - */ - void ClearWhenReceived(); - - /** - * Makes the current execution thread of the logger a real-time thread which - * will make it scheduled more consistently. - */ - static void UpdateThreadPriority(); - - /** - * Utility function for getting motor controller voltage - * - * @param controllers A set of motor controllers powering a mechanism. - * @param controllerNames The names of the motor controllers. - * @return The average of the measured voltages of the motor controllers. - */ - static double MeasureVoltage( - const std::vector>& controllers, - const std::vector& controllerNames); - - protected: - /** - * The initial size of the data collection vectors, set to be large enough so - * that we avoid resizing the vector during data collection. Determined by: 20 - * seconds of test data * 200 samples/second * 9 doubles/sample(320kB of - * reserved data). - */ - static constexpr size_t kDataVectorSize = 36000; - - /** - * The commanded motor voltage. Either as a rate (V/s) for the quasistatic - * test or as a voltage (V) for the dynamic test. - */ - double m_voltageCommand = 0.0; - - /** - * The voltage that the motors should be set to. - */ - double m_motorVoltage = 0.0; - - /** - * Keeps track of the current timestamp for data collection purposes. - */ - double m_timestamp = 0.0; - - /** - * The timestamp of when the test starts. Mainly used to keep track of the - * test running for too long. - */ - double m_startTime = 0.0; - - /** - * Determines for Drivetrain tests if the robot should be spinning (value sent - * via NT). - */ - bool m_rotate = false; - - /** - * The test that is running (e.g. Quasistatic or Dynamic). - */ - std::string m_testType; - - /** - * The mechanism that is being characterized (sent via NT). - */ - std::string m_mechanism; - - /** - * Stores all of the collected data. - */ - std::vector m_data; - - int m_ackNum = 0; - - /** - * Creates the SysId logger, disables live view telemetry, sets up the - * following NT Entries: "SysIdAutoSpeed", "SysIdRotate", "SysIdTelemetry" - */ - SysIdLogger(); - - /** - * Updates the autospeed and robotVoltage - */ - void UpdateData(); - - /** - * Reset data before next test. - */ - virtual void Reset(); - - /** - * Determines if the logger is collecting data for an unsupported mechanism. - * - * @returns True if the logger is characterizing an unsupported mechanism - * type. - */ - virtual bool IsWrongMechanism() const = 0; - - private: - static constexpr int kThreadPriority = 15; - static constexpr int kHALThreadPriority = 40; -}; - -} // namespace sysid diff --git a/sysid-projects/analysis-test/gradle.properties b/sysid-projects/analysis-test/gradle.properties deleted file mode 100644 index 5836aad4..00000000 --- a/sysid-projects/analysis-test/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -nativeutils.vendordep.folder.path=../../vendordeps diff --git a/sysid-projects/analysis-test/src/main/cpp/Arm.cpp b/sysid-projects/analysis-test/src/main/cpp/Arm.cpp deleted file mode 100644 index 026f2a5f..00000000 --- a/sysid-projects/analysis-test/src/main/cpp/Arm.cpp +++ /dev/null @@ -1,16 +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 "Arm.h" - -#include - -void Arm::SimulationPeriodic() { - m_armSimulator.SetInputVoltage(units::volt_t{m_leader.Get()} * - frc::RobotController::GetInputVoltage()); - m_armSimulator.Update(5_ms); - - m_encoderSim.SetDistance(m_armSimulator.GetAngle().value()); - m_encoderSim.SetRate(m_armSimulator.GetVelocity().value()); -} diff --git a/sysid-projects/analysis-test/src/main/cpp/Drivetrain.cpp b/sysid-projects/analysis-test/src/main/cpp/Drivetrain.cpp deleted file mode 100644 index f772099a..00000000 --- a/sysid-projects/analysis-test/src/main/cpp/Drivetrain.cpp +++ /dev/null @@ -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. - -#include "Drivetrain.h" - -#include - -#include - -void Drivetrain::SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds) { - auto leftFeedforward = m_feedforward.Calculate(speeds.left); - auto rightFeedforward = m_feedforward.Calculate(speeds.right); - double leftOutput = m_leftPIDController.Calculate(m_leftEncoder.GetRate(), - speeds.left.value()); - double rightOutput = m_rightPIDController.Calculate(m_rightEncoder.GetRate(), - speeds.right.value()); - - m_leftGroup.SetVoltage(units::volt_t{leftOutput} + leftFeedforward); - m_rightGroup.SetVoltage(units::volt_t{rightOutput} + rightFeedforward); -} - -void Drivetrain::Drive(units::meters_per_second_t xSpeed, - units::radians_per_second_t rot) { - SetSpeeds(m_kinematics.ToWheelSpeeds({xSpeed, 0_mps, rot})); -} - -void Drivetrain::UpdateOdometry() { - m_odometry.Update(m_gyro.GetRotation2d(), - units::meter_t(m_leftEncoder.GetDistance()), - units::meter_t(m_rightEncoder.GetDistance())); -} - -void Drivetrain::ResetOdometry(const frc::Pose2d& pose) { - m_leftEncoder.Reset(); - m_rightEncoder.Reset(); - m_drivetrainSimulator.SetPose(pose); - m_odometry.ResetPosition(m_gyro.GetRotation2d(), 0_m, 0_m, pose); -} - -void Drivetrain::SimulationPeriodic() { - // To update our simulation, we set motor voltage inputs, update the - // simulation, and write the simulated positions and velocities to our - // simulated encoder and gyro. We negate the right side so that positive - // voltages make the right side move forward. - m_drivetrainSimulator.SetInputs(units::volt_t{m_leftLeader.Get()} * - frc::RobotController::GetInputVoltage(), - units::volt_t{m_rightLeader.Get()} * - frc::RobotController::GetInputVoltage()); - m_drivetrainSimulator.Update(5_ms); - - m_leftEncoderSim.SetDistance(m_drivetrainSimulator.GetLeftPosition().value()); - m_leftEncoderSim.SetRate(m_drivetrainSimulator.GetLeftVelocity().value()); - m_rightEncoderSim.SetDistance( - m_drivetrainSimulator.GetRightPosition().value()); - m_rightEncoderSim.SetRate(m_drivetrainSimulator.GetRightVelocity().value()); - - units::degree_t heading = m_drivetrainSimulator.GetHeading().Degrees(); - - // If heading jumped down more than pi, the angle wrapped CCW, so increment - // the counter. - if (heading - m_prevHeading < units::radian_t{-std::numbers::pi}) { - ++m_angleWraps; - } - - // If heading jumped up more than pi, the angle wrapped CW, so decrement the - // counter. - if (heading - m_prevHeading > units::radian_t{std::numbers::pi}) { - --m_angleWraps; - } - - m_prevHeading = heading; - - m_gyroSim.SetAngle(-units::degree_t{ - heading + m_angleWraps * units::radian_t{2.0 * std::numbers::pi}} - .value()); - m_gyroSim.SetRate((m_drivetrainSimulator.GetRightVelocity().value() - - m_drivetrainSimulator.GetLeftVelocity().value()) / - Constants::Drivetrain::kTrackWidth.value()); -} - -void Drivetrain::Periodic() { - UpdateOdometry(); - m_fieldSim.SetRobotPose(m_odometry.GetPose()); -} diff --git a/sysid-projects/analysis-test/src/main/cpp/Elevator.cpp b/sysid-projects/analysis-test/src/main/cpp/Elevator.cpp deleted file mode 100644 index 79b5b0c4..00000000 --- a/sysid-projects/analysis-test/src/main/cpp/Elevator.cpp +++ /dev/null @@ -1,16 +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 "Elevator.h" - -#include - -void Elevator::SimulationPeriodic() { - m_elevatorSimulator.SetInputVoltage(units::volt_t{m_leader.Get()} * - frc::RobotController::GetInputVoltage()); - m_elevatorSimulator.Update(5_ms); - - m_encoderSim.SetDistance(m_elevatorSimulator.GetPosition().value()); - m_encoderSim.SetRate(m_elevatorSimulator.GetVelocity().value()); -} diff --git a/sysid-projects/analysis-test/src/main/cpp/Robot.cpp b/sysid-projects/analysis-test/src/main/cpp/Robot.cpp deleted file mode 100644 index f67d99f3..00000000 --- a/sysid-projects/analysis-test/src/main/cpp/Robot.cpp +++ /dev/null @@ -1,165 +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 -#include - -#include -#include -#include -#include -#include -#include - -#include "Arm.h" -#include "Drivetrain.h" -#include "Elevator.h" -#include "SimpleMotor.h" -#include "interface/SysIdDrivetrain.h" -#include "interface/SysIdGeneralMechanism.h" -#include "sysid/logging/SysIdDrivetrainLogger.h" -#include "sysid/logging/SysIdGeneralMechanismLogger.h" - -class Robot : public frc::TimedRobot { - public: - Robot() : frc::TimedRobot(5_ms) { m_driveLogger.UpdateThreadPriority(); } - void RobotInit() override { - // Flush NetworkTables every loop. This ensures that robot pose and other - // values are sent during every iteration. - SetNetworkTablesFlushEnabled(true); - frc::SmartDashboard::PutString("SysIdTest", "Drivetrain"); - } - - void DisabledInit() override { - m_mechanism->SetMotor(0_V); - - m_driveMechanism->SetLMotor(0_V); - m_driveMechanism->SetRMotor(0_V); - - m_arm.ResetReadings(); - if (m_test == "Drivetrain" || m_test == "Drivetrain (Angular)") { - m_driveLogger.SendData(); - } else { - m_generalLogger.SendData(); - } - } - - void DisabledPeriodic() override { - m_arm.ResetReadings(); - if (m_test == "Drivetrain" || m_test == "Drivetrain (Angular)") { - m_driveLogger.ClearWhenReceived(); - } else { - m_generalLogger.ClearWhenReceived(); - } - } - - void RobotPeriodic() override { - m_drive.Periodic(); - m_flywheel.Periodic(); - m_arm.Periodic(); - } - - void AutonomousInit() override { - m_test = frc::SmartDashboard::GetString("SysIdTest", "Simple"); - if (m_test == "Drivetrain" || m_test == "Drivetrain (Angular)") { - m_driveLogger.InitLogging(); - } else { - m_generalLogger.InitLogging(); - } - - m_elevator.UpdateInitialSpeed(); - m_arm.ResetReadings(); - - if (m_test == "Simple") { - m_mechanism = &m_flywheel; - } else if (m_test == "Elevator") { - m_mechanism = &m_elevator; - } else if (m_test == "Arm") { - m_mechanism = &m_arm; - } - } - - void AutonomousPeriodic() override { - if (m_test == "Drivetrain" || m_test == "Drivetrain (Angular)") { - m_driveLogger.Log(m_driveLogger.GetLeftMotorVoltage().value(), - m_driveLogger.GetRightMotorVoltage().value(), - m_driveMechanism->GetLEncDistance(), - m_driveMechanism->GetREncDistance(), - m_driveMechanism->GetLEncVelocity(), - m_driveMechanism->GetREncVelocity(), - m_driveMechanism->GetGyroAngle(), - m_driveMechanism->GetGyroAngularRate()); - m_driveMechanism->SetLMotor(m_driveLogger.GetLeftMotorVoltage()); - m_driveMechanism->SetRMotor(m_driveLogger.GetRightMotorVoltage()); - } else { - m_generalLogger.Log(m_generalLogger.GetMotorVoltage().value(), - m_mechanism->GetPosition(), - m_mechanism->GetVelocity()); - m_mechanism->SetMotor(m_generalLogger.GetMotorVoltage()); - } - } - - void TeleopPeriodic() override { - // Get the x speed. We are inverting this because Xbox controllers return - // negative values when we push forward. - const auto xSpeed = -m_speedLimiter.Calculate(m_controller.GetLeftY()) * - Drivetrain::kMaxSpeed; - - // Get the rate of angular rotation. We are inverting this because we want a - // positive value when we pull to the left (remember, CCW is positive in - // mathematics). Xbox controllers return positive values when you pull to - // the right by default. - auto rot = -m_rotLimiter.Calculate(m_controller.GetRightX()) * - Drivetrain::kMaxAngularSpeed; - - m_drive.Drive(xSpeed, rot); - } - - void SimulationPeriodic() override { - m_drive.SimulationPeriodic(); - m_flywheel.SimulationPeriodic(); - m_elevator.SimulationPeriodic(); - m_arm.SimulationPeriodic(); - - frc::SmartDashboard::PutString("ServerTest", m_test); - -#ifdef INTEGRATION - bool enable = frc::SmartDashboard::GetBoolean("SysIdRun", false); - frc::sim::DriverStationSim::SetAutonomous(enable); - frc::sim::DriverStationSim::SetEnabled(enable); - frc::sim::DriverStationSim::NotifyNewData(); -#endif - - if (frc::SmartDashboard::GetBoolean("SysIdKill", false)) { - EndCompetition(); - } - } - - private: - frc::XboxController m_controller{0}; - - // Slew rate limiters to make joystick inputs more gentle; 1/3 sec from 0 - // to 1. - frc::SlewRateLimiter m_speedLimiter{3 / 1_s}; - frc::SlewRateLimiter m_rotLimiter{3 / 1_s}; - - Drivetrain m_drive; - SimpleMotor m_flywheel; - Elevator m_elevator; - Arm m_arm; - - SysIdGeneralMechanism* m_mechanism = &m_flywheel; - SysIdDrivetrain* m_driveMechanism = &m_drive; - sysid::SysIdGeneralMechanismLogger m_generalLogger; - sysid::SysIdDrivetrainLogger m_driveLogger; - - std::string m_test = "Drivetrain"; - std::vector m_data; -}; - -#ifndef RUNNING_FRC_TESTS -int main() { // NOLINT (bugprone-exception-escape) - return frc::StartRobot(); -} -#endif diff --git a/sysid-projects/analysis-test/src/main/cpp/SimpleMotor.cpp b/sysid-projects/analysis-test/src/main/cpp/SimpleMotor.cpp deleted file mode 100644 index 3bf55115..00000000 --- a/sysid-projects/analysis-test/src/main/cpp/SimpleMotor.cpp +++ /dev/null @@ -1,19 +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 "SimpleMotor.h" - -#include - -void SimpleMotor::SimulationPeriodic() { - m_flywheelSimulator.SetInputVoltage(units::volt_t{m_leader.Get()} * - frc::RobotController::GetInputVoltage()); - m_flywheelSimulator.Update(5_ms); - - auto delta = m_flywheelSimulator.GetAngularVelocity().value() * 5_ms; - distance += delta.value(); - - m_encoderSim.SetDistance(distance); - m_encoderSim.SetRate(m_flywheelSimulator.GetAngularVelocity().value()); -} diff --git a/sysid-projects/analysis-test/src/main/include/Arm.h b/sysid-projects/analysis-test/src/main/include/Arm.h deleted file mode 100644 index c83b237a..00000000 --- a/sysid-projects/analysis-test/src/main/include/Arm.h +++ /dev/null @@ -1,83 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Constants.h" -#include "interface/SysIdGeneralMechanism.h" - -/** - * Represents an arm mechanism. - */ -class Arm : public SysIdGeneralMechanism { - public: - Arm() { - // Set the distance per pulse for the flywheel encoders. We can simply use - // the 1 divided by the resolution as that denotes one rotation of the - // flywheel. - m_encoder.SetDistancePerPulse(2 * std::numbers::pi / kEncoderResolution); - - m_encoder.Reset(); - } - - void SetMotor(units::volt_t value) override { m_group.SetVoltage(value); } - - double GetPosition() override { return m_encoder.GetDistance(); } - double GetVelocity() override { return m_encoder.GetRate(); } - - void SimulationPeriodic(); - - void ResetReadings() { - m_armSimulator.SetState( - Eigen::Matrix{std::numbers::pi / 2, 0.0}); - m_armSimulator.Update(5_ms); - m_encoderSim.SetRate(0); - m_encoderSim.SetDistance(std::numbers::pi / 2); - } - - void Periodic() { - frc::SmartDashboard::PutNumber("Arm Speed", m_encoder.GetRate()); - frc::SmartDashboard::PutNumber("Arm Position", m_encoder.GetDistance()); - frc::SmartDashboard::PutNumber("Current Draw", - m_armSimulator.GetCurrentDraw().value()); - frc::SmartDashboard::PutBoolean("Hit Top Limit", - m_armSimulator.HasHitUpperLimit()); - frc::SmartDashboard::PutBoolean("Hit bottom Limit", - m_armSimulator.HasHitLowerLimit()); - } - - private: - static constexpr int kEncoderResolution = 4096; - double distance = 0; - - frc::PWMVictorSPX m_leader{Constants::Arm::kLeaderPort}; - frc::PWMVictorSPX m_follower{Constants::Arm::kFollowerPort}; - - frc::MotorControllerGroup m_group{m_leader, m_follower}; - - frc::Encoder m_encoder{Constants::Arm::kEncoderPorts[0], - Constants::Arm::kEncoderPorts[1]}; - - // Simulation classes help us simulate our robot - frc::sim::EncoderSim m_encoderSim{m_encoder}; - frc::LinearSystem<2, 1, 1> m_armSystem = - frc::LinearSystemId::IdentifyPositionSystem( - Constants::Arm::kV, Constants::Arm::kA); - frc::sim::SingleJointedArmSim m_armSimulator{ - m_armSystem, frc::DCMotor::Vex775Pro(4), 1000, - 1000_in, -Constants::Arm::kAngle, Constants::Arm::kAngle, - true}; -}; diff --git a/sysid-projects/analysis-test/src/main/include/Constants.h b/sysid-projects/analysis-test/src/main/include/Constants.h deleted file mode 100644 index 6d7804a7..00000000 --- a/sysid-projects/analysis-test/src/main/include/Constants.h +++ /dev/null @@ -1,83 +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 - -#include -#include -#include -#include -#include -#include -#include - -namespace Constants { - -namespace Drivetrain { - -// Ports -constexpr int kLeftLeaderPort = 1; -constexpr int kLeftFollowerPort = 2; -constexpr int kRightLeaderPort = 3; -constexpr int kRightFollowerPort = 4; - -constexpr int kLeftEncoderPorts[2] = {0, 1}; -constexpr int kRightEncoderPorts[2] = {2, 3}; - -constexpr int kGyroPort = 0; - -// Measurement Constants -constexpr units::meter_t kTrackWidth = 0.381_m * 2; -constexpr double kWheelRadius = 0.0508; // meters -constexpr int kEncoderResolution = 4096; - -// Feedforward Gains -constexpr auto kV = 1.98_V / 1_mps; -constexpr auto kA = 0.2_V / 1_mps_sq; - -constexpr auto kAngularKV = 1.5_V / 1_mps; -constexpr auto kAngularKA = 0.3_V / 1_mps_sq; - -} // namespace Drivetrain - -namespace SimpleMotor { -constexpr int kLeaderPort = 5; -constexpr int kFollowerPort = 6; - -constexpr int kEncoderPorts[2] = {4, 5}; - -constexpr auto kV = 1.98_V / 1_rad_per_s; -constexpr auto kA = 0.2_V / 1_rad_per_s_sq; - -} // namespace SimpleMotor - -namespace Elevator { - -constexpr int kLeaderPort = 7; -constexpr int kFollowerPort = 8; - -constexpr int kEncoderPorts[2] = {6, 7}; - -constexpr auto kV = 1.98_V / 1_rad_per_s; -constexpr auto kA = 0.2_V / 1_rad_per_s_sq; - -constexpr units::meter_t kHeight{std::numeric_limits::max()}; -} // namespace Elevator - -namespace Arm { -constexpr int kLeaderPort = 9; -constexpr int kFollowerPort = 10; - -constexpr int kEncoderPorts[2] = {8, 9}; - -constexpr auto kV = 1.98_V / 1_rad_per_s; -constexpr auto kA = 0.2_V / 1_rad_per_s_sq; - -constexpr units::degree_t kAngle{std::numeric_limits::max()}; - -} // namespace Arm - -} // namespace Constants diff --git a/sysid-projects/analysis-test/src/main/include/Drivetrain.h b/sysid-projects/analysis-test/src/main/include/Drivetrain.h deleted file mode 100644 index 5178825b..00000000 --- a/sysid-projects/analysis-test/src/main/include/Drivetrain.h +++ /dev/null @@ -1,131 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Constants.h" -#include "interface/SysIdDrivetrain.h" - -/** - * Represents a differential drive style drivetrain. - */ -class Drivetrain : public SysIdDrivetrain { - public: - Drivetrain() { - m_gyro.Reset(); - // Set the distance per pulse for the drive encoders. We can simply use the - // distance traveled for one rotation of the wheel divided by the encoder - // resolution. - m_leftEncoder.SetDistancePerPulse( - 2 * std::numbers::pi * Constants::Drivetrain::kWheelRadius / - Constants::Drivetrain::kEncoderResolution); - m_rightEncoder.SetDistancePerPulse( - 2 * std::numbers::pi * Constants::Drivetrain::kWheelRadius / - Constants::Drivetrain::kEncoderResolution); - - m_leftEncoder.Reset(); - m_rightEncoder.Reset(); - - frc::SmartDashboard::PutData("Field", &m_fieldSim); - } - - static constexpr units::meters_per_second_t kMaxSpeed = - 3.0_mps; // 3 meters per second - static constexpr units::radians_per_second_t kMaxAngularSpeed{ - std::numbers::pi}; // 1/2 rotation per second - - void SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds); - void Drive(units::meters_per_second_t xSpeed, - units::radians_per_second_t rot); - void UpdateOdometry(); - void ResetOdometry(const frc::Pose2d& pose); - - double GetLEncDistance() override { return m_leftEncoder.GetDistance(); } - double GetLEncVelocity() override { return m_leftEncoder.GetRate(); } - void SetLMotor(units::volt_t value) override { - m_leftGroup.SetVoltage(value); - } - - void SetRMotor(units::volt_t value) override { - m_rightGroup.SetVoltage(value); - } - - double GetREncDistance() override { return m_rightEncoder.GetDistance(); } - double GetREncVelocity() override { return m_rightEncoder.GetRate(); } - - double GetGyroAngle() override { return GetGyro().value(); } - double GetGyroAngularRate() override { return m_gyro.GetRate(); } - - double GetSpeed() { return (m_leftGroup.Get() + m_rightGroup.Get()) / 2; } - - units::radian_t GetGyro() { return units::degree_t(-m_gyro.GetAngle()); } - - frc::Pose2d GetPose() const { return m_odometry.GetPose(); } - - void SimulationPeriodic(); - void Periodic(); - - private: - frc::PWMVictorSPX m_leftLeader{Constants::Drivetrain::kLeftLeaderPort}; - frc::PWMVictorSPX m_leftFollower{Constants::Drivetrain::kLeftFollowerPort}; - frc::PWMVictorSPX m_rightLeader{Constants::Drivetrain::kRightLeaderPort}; - frc::PWMVictorSPX m_rightFollower{Constants::Drivetrain::kRightFollowerPort}; - - frc::MotorControllerGroup m_leftGroup{m_leftLeader, m_leftFollower}; - frc::MotorControllerGroup m_rightGroup{m_rightLeader, m_rightFollower}; - - frc::Encoder m_leftEncoder{Constants::Drivetrain::kLeftEncoderPorts[0], - Constants::Drivetrain::kLeftEncoderPorts[1]}; - frc::Encoder m_rightEncoder{Constants::Drivetrain::kRightEncoderPorts[0], - Constants::Drivetrain::kRightEncoderPorts[1]}; - - frc2::PIDController m_leftPIDController{8.5, 0.0, 0.0}; - frc2::PIDController m_rightPIDController{8.5, 0.0, 0.0}; - - frc::AnalogGyro m_gyro{Constants::Drivetrain::kGyroPort}; - units::degree_t m_prevHeading = 0_deg; - int m_angleWraps = 0; - - frc::DifferentialDriveKinematics m_kinematics{ - Constants::Drivetrain::kTrackWidth}; - frc::DifferentialDriveOdometry m_odometry{m_gyro.GetRotation2d(), 0_m, 0_m}; - - // Gains are for example purposes only - must be determined for your own - // robot! - frc::SimpleMotorFeedforward m_feedforward{1_V, 3_V / 1_mps}; - - // Simulation classes help us simulate our robot - frc::sim::AnalogGyroSim m_gyroSim{m_gyro}; - frc::sim::EncoderSim m_leftEncoderSim{m_leftEncoder}; - frc::sim::EncoderSim m_rightEncoderSim{m_rightEncoder}; - frc::Field2d m_fieldSim; - frc::LinearSystem<2, 2, 2> m_drivetrainSystem = - frc::LinearSystemId::IdentifyDrivetrainSystem( - Constants::Drivetrain::kV, Constants::Drivetrain::kA, - Constants::Drivetrain::kAngularKV, Constants::Drivetrain::kAngularKA); - frc::sim::DifferentialDrivetrainSim m_drivetrainSimulator{ - m_drivetrainSystem, Constants::Drivetrain::kTrackWidth, - frc::DCMotor::CIM(2), 8, 2_in}; -}; diff --git a/sysid-projects/analysis-test/src/main/include/Elevator.h b/sysid-projects/analysis-test/src/main/include/Elevator.h deleted file mode 100644 index 1103baed..00000000 --- a/sysid-projects/analysis-test/src/main/include/Elevator.h +++ /dev/null @@ -1,83 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Constants.h" -#include "interface/SysIdGeneralMechanism.h" - -/** - * Represents an elevator mechanism. - */ -class Elevator : public SysIdGeneralMechanism { - public: - Elevator() { - // Set the distance per pulse for the flywheel encoders. We can simply use - // the 1 divided by the resolution as that denotes one rotation of the - // flywheel. - m_encoder.SetDistancePerPulse(2 * std::numbers::pi / kEncoderResolution); - - m_encoder.Reset(); - } - - void SetMotor(units::volt_t value) override { m_group.SetVoltage(value); } - - double GetPosition() override { return m_encoder.GetDistance(); } - double GetVelocity() override { return m_encoder.GetRate() - m_initSpeed; } - - void SimulationPeriodic(); - - void ResetReadings() { - m_elevatorSimulator.SetState(Eigen::Matrix{0.0, 0.0}); - m_encoderSim.SetRate(0); - m_encoderSim.SetDistance(0); - } - - void Periodic() { - frc::SmartDashboard::PutNumber("Elevator Speed", m_encoder.GetRate()); - frc::SmartDashboard::PutNumber("Elevator Position", - m_encoder.GetDistance()); - } - - void UpdateInitialSpeed() { m_initSpeed = m_encoder.GetRate(); } - - private: - static constexpr int kEncoderResolution = 4096; - double distance = 0; - - double m_initSpeed = 0; - - frc::PWMVictorSPX m_leader{Constants::Elevator::kLeaderPort}; - frc::PWMVictorSPX m_follower{Constants::Elevator::kFollowerPort}; - - frc::MotorControllerGroup m_group{m_leader, m_follower}; - - frc::Encoder m_encoder{Constants::Elevator::kEncoderPorts[0], - Constants::Elevator::kEncoderPorts[1]}; - - // Simulation classes help us simulate our robot - frc::sim::EncoderSim m_encoderSim{m_encoder}; - frc::LinearSystem<2, 1, 1> m_elevatorSystem = - frc::LinearSystemId::IdentifyPositionSystem( - Constants::Elevator::kV, Constants::Elevator::kA); - frc::sim::ElevatorSim m_elevatorSimulator{m_elevatorSystem, - frc::DCMotor::Vex775Pro(4), - 1000, - 2_in, - -Constants::Elevator::kHeight, - Constants::Elevator::kHeight, - true}; -}; diff --git a/sysid-projects/analysis-test/src/main/include/SimpleMotor.h b/sysid-projects/analysis-test/src/main/include/SimpleMotor.h deleted file mode 100644 index d036a014..00000000 --- a/sysid-projects/analysis-test/src/main/include/SimpleMotor.h +++ /dev/null @@ -1,66 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Constants.h" -#include "interface/SysIdGeneralMechanism.h" - -/** - * Represents a flywheel mechanism. - */ -class SimpleMotor : public SysIdGeneralMechanism { - public: - SimpleMotor() { - // Set the distance per pulse for the flywheel encoders. We can simply use - // the 1 divided by the resolution as that denotes one rotation of the - // flywheel. - m_encoder.SetDistancePerPulse(2 * std::numbers::pi / kEncoderResolution); - - m_encoder.Reset(); - } - - void SetMotor(units::volt_t value) override { m_group.SetVoltage(value); } - - double GetPosition() override { return m_encoder.GetDistance(); } - double GetVelocity() override { return m_encoder.GetRate(); } - - void SimulationPeriodic(); - - void Periodic() { - frc::SmartDashboard::PutNumber("Flywheel Speed", m_encoder.GetRate()); - } - - private: - static constexpr int kEncoderResolution = 4096; - double distance = 0; - - frc::PWMVictorSPX m_leader{Constants::SimpleMotor::kLeaderPort}; - frc::PWMVictorSPX m_follower{Constants::SimpleMotor::kFollowerPort}; - - frc::MotorControllerGroup m_group{m_leader, m_follower}; - - frc::Encoder m_encoder{Constants::SimpleMotor::kEncoderPorts[0], - Constants::SimpleMotor::kEncoderPorts[1]}; - - // Simulation classes help us simulate our robot - frc::sim::EncoderSim m_encoderSim{m_encoder}; - frc::LinearSystem<1, 1, 1> m_flywheelSystem = - frc::LinearSystemId::IdentifyVelocitySystem( - Constants::SimpleMotor::kV, Constants::SimpleMotor::kA); - frc::sim::FlywheelSim m_flywheelSimulator{m_flywheelSystem, - frc::DCMotor::Vex775Pro(2), 1.0}; -}; diff --git a/sysid-projects/analysis-test/src/main/include/interface/SysIdDrivetrain.h b/sysid-projects/analysis-test/src/main/include/interface/SysIdDrivetrain.h deleted file mode 100644 index c1761ccf..00000000 --- a/sysid-projects/analysis-test/src/main/include/interface/SysIdDrivetrain.h +++ /dev/null @@ -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. - -#pragma once - -#include - -class SysIdDrivetrain { - public: - virtual void SetLMotor(units::volt_t value) = 0; - virtual void SetRMotor(units::volt_t value) = 0; - - virtual double GetLEncDistance() = 0; - virtual double GetREncDistance() = 0; - - virtual double GetLEncVelocity() = 0; - virtual double GetREncVelocity() = 0; - - virtual double GetGyroAngle() = 0; - virtual double GetGyroAngularRate() = 0; -}; diff --git a/sysid-projects/analysis-test/src/main/include/interface/SysIdGeneralMechanism.h b/sysid-projects/analysis-test/src/main/include/interface/SysIdGeneralMechanism.h deleted file mode 100644 index b1b9820b..00000000 --- a/sysid-projects/analysis-test/src/main/include/interface/SysIdGeneralMechanism.h +++ /dev/null @@ -1,15 +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 - -class SysIdGeneralMechanism { - public: - virtual double GetPosition() = 0; - virtual double GetVelocity() = 0; - - virtual void SetMotor(units::volt_t value) = 0; -}; diff --git a/sysid-projects/build.gradle b/sysid-projects/build.gradle deleted file mode 100644 index f3d5ddc6..00000000 --- a/sysid-projects/build.gradle +++ /dev/null @@ -1,128 +0,0 @@ -plugins { - id "cpp" - id "google-test-test-suite" -} - -apply from: "${rootDir}/config.gradle" -nativeUtils.withCrossRoboRIO() - -def exeGenerateTask = nativeUtils.generateResources('generateExeResources').get() -exeGenerateTask.outputDirectory = project.file('build/generated/exe') -exeGenerateTask.prefix = project.name -exeGenerateTask.namespace = 'sysid' -def libCreateTask = null -def libGenerateTask = null - -if (project.name == 'drive') { - libGenerateTask = nativeUtils.generateResources('generateLibResources').get() - libGenerateTask.outputDirectory = project.file('build/generated/lib') - libGenerateTask.prefix = 'libraries' - libGenerateTask.namespace = 'sysid' - - apply from: '../resources.gradle' - libCreateTask = createLibDeployTask(libGenerateTask) -} - -model { - components { - frcUserProgram(NativeExecutableSpec) { - targetPlatform nativeUtils.wpi.nativePlatforms.roborio - if (!project.hasProperty("skipDesktopRobots")) - targetPlatform nativeUtils.wpi.nativePlatforms.desktop - - sources.cpp { - source { - srcDirs 'src/main/cpp' - include '**/*.cpp' - } - exportedHeaders.srcDirs 'src/main/include' - } - - binaries.all { - it.cppCompiler.define("PROJECT_ROOT_DIR", "$projectDir") - if (project.hasProperty("integration")) { - it.cppCompiler.define("INTEGRATION") - } - lib project: ":sysid-library", library: "libsysid", linkage: "static" - - nativeUtils.wpi.vendorDeps.nativeVendor.cpp(it) - - // In order for vendors to work correctly, we must always build with shared wpilib - nativeUtils.useRequiredLibrary(it, 'wpilib_executable_shared') - } - } - embeddedBinary(NativeLibrarySpec) { - targetPlatform nativeUtils.wpi.nativePlatforms.desktop - - sources.cpp { - source { - srcDirs 'src/main/empty', 'build/generated/exe', 'build/generated/lib', 'build/generated/libdeploy' - } - } - - binaries.all { - if (it instanceof SharedLibraryBinarySpec) { - it.buildable = false - return - } - it.tasks.withType(AbstractNativeSourceCompileTask) { - dependsOn exeGenerateTask - if (libCreateTask != null) { - dependsOn libCreateTask - } - } - } - } - } - tasks { - $.components.frcUserProgram.binaries.each { bin -> - // Create a task that installs the desktop executable with shared linking. - if (bin.targetPlatform.name == nativeUtils.wpi.nativePlatforms.desktop && bin.name.toLowerCase().contains("release")) - project.tasks.create("installDesktopExe") { - dependsOn bin.tasks.install - ext.setProperty("runScriptFile${project.name}", - bin.tasks.install.runScriptFile.get().asFile.toString()) - } - - // Create a task that installs and copies the roboRIO executable and libraries. - if (project.name != "analysis-test" && bin.targetPlatform.name == nativeUtils.wpi.nativePlatforms.roborio && - bin.name.toLowerCase().contains("release")) { - exeGenerateTask.source.from(bin.tasks.install.executableFile) - exeGenerateTask.dependsOn bin.tasks.install - // Only copy the libs once, from the drive mechanism - if (libGenerateTask != null) { - libGenerateTask.source.from(bin.tasks.install.libs.filter { - !it.toString().endsWith('.so.debug') - }) - libGenerateTask.dependsOn bin.tasks.install - } - } - } - } -} - -task installSimulateNativeRelease { - dependsOn 'installFrcUserProgram' + nativeUtils.wpi.nativePlatforms.desktop.capitalize() + 'ReleaseExecutable' -} - -class CustomExec extends AbstractExecTask { - @Inject - public CustomExec() { - super(CustomExec.class); - getOutputs().upToDateWhen(spec -> false); - } - - - @TaskAction - @Override - protected void exec() { - def installTask = project.tasks.named('installFrcUserProgram' + project.nativeUtils.wpi.nativePlatforms.desktop.capitalize() + 'ReleaseExecutable').get() - println installTask - setExecutable(installTask.getRunScriptFile().get().getAsFile()) - super.exec() - } -} - -task simulateNativeRelease(type: CustomExec) { - dependsOn(installSimulateNativeRelease) -} diff --git a/sysid-projects/deploy/example.txt b/sysid-projects/deploy/example.txt deleted file mode 100644 index 3b94f915..00000000 --- a/sysid-projects/deploy/example.txt +++ /dev/null @@ -1 +0,0 @@ -Placeholder diff --git a/sysid-projects/drive/gradle.properties b/sysid-projects/drive/gradle.properties deleted file mode 100644 index 5836aad4..00000000 --- a/sysid-projects/drive/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -nativeutils.vendordep.folder.path=../../vendordeps diff --git a/sysid-projects/drive/src/main/cpp/DriveRobot.cpp b/sysid-projects/drive/src/main/cpp/DriveRobot.cpp deleted file mode 100644 index 86e53346..00000000 --- a/sysid-projects/drive/src/main/cpp/DriveRobot.cpp +++ /dev/null @@ -1,212 +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 "DriveRobot.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sysid/generation/SysIdSetup.h" - -DriveRobot::DriveRobot() : frc::TimedRobot(5_ms) { - m_json = sysid::GetConfigJson(); - - try { - fmt::print("Read JSON\n"); - - std::vector leftPorts = - m_json.at("primary motor ports").get>(); - m_controllerNames = - m_json.at("motor controllers").get>(); - std::vector leftEncoderPorts = - m_json.at("primary encoder ports").get>(); - std::vector leftMotorsInverted = - m_json.at("primary motors inverted").get>(); - - std::vector rightPorts = - m_json.at("secondary motor ports").get>(); - std::vector rightEncoderPorts = - m_json.at("secondary encoder ports").get>(); - std::vector rightMotorsInverted = - m_json.at("secondary motors inverted").get>(); - - std::vector canivoreNames = - m_json.at("canivore names").get>(); - std::string encoderCANivoreName = - m_json.at("encoder canivore name").get(); - std::string gyroCANivoreName = - m_json.at("gyro canivore name").get(); - - std::string encoderType = m_json.at("encoder type").get(); - bool leftEncoderInverted = - m_json.at("primary encoder inverted").get(); - bool rightEncoderInverted = - m_json.at("secondary encoder inverted").get(); - double cpr = m_json.at("counts per rotation").get(); - double gearingNumerator = m_json.at("gearing numerator").get(); - double gearingDenominator = m_json.at("gearing denominator").get(); - double gearing = gearingNumerator / gearingDenominator; - - std::string gyroType = m_json.at("gyro").get(); - std::string gyroCtor = m_json.at("gyro ctor").get(); - - bool isEncoding = m_json.at("encoding").get(); - - int numSamples = m_json.at("number of samples per average").get(); - - int period = m_json.at("velocity measurement period").get(); - - fmt::print("Setup motors\n"); - for (size_t i = 0; i < leftPorts.size(); i++) { - sysid::AddMotorController(leftPorts[i], m_controllerNames[i], - leftMotorsInverted[i], canivoreNames[i], - &m_leftControllers); - sysid::AddMotorController(rightPorts[i], m_controllerNames[i], - rightMotorsInverted[i], canivoreNames[i], - &m_rightControllers); - } - - fmt::print("Setup encoders\n"); - sysid::SetupEncoders( - encoderType, isEncoding, period, cpr, gearing, numSamples, - m_controllerNames[0], m_leftControllers.at(0).get(), - leftEncoderInverted, leftEncoderPorts, encoderCANivoreName, - m_leftCancoder, m_leftCancoderPro, m_leftRevEncoderPort, - m_leftRevDataPort, m_leftEncoder, m_leftPosition, m_leftRate); - sysid::SetupEncoders( - encoderType, isEncoding, period, cpr, gearing, numSamples, - m_controllerNames[0], m_rightControllers.at(0).get(), - rightEncoderInverted, rightEncoderPorts, encoderCANivoreName, - m_rightCancoder, m_rightCancoderPro, m_rightRevEncoderPort, - m_rightRevDataPort, m_rightEncoder, m_rightPosition, m_rightRate); - - fmt::print("Setup gyro\n"); - sysid::SetupGyro(gyroType, gyroCtor, leftPorts, rightPorts, - m_controllerNames, m_leftControllers, m_rightControllers, - m_gyro, m_ADIS16448Gyro, m_ADIS16470Gyro, m_pigeon, - m_pigeonPro, m_tempTalon, gyroCANivoreName, m_gyroPosition, - m_gyroRate); - } catch (std::exception& e) { - fmt::print("Project failed: {}\n", e.what()); - std::exit(-1); - } - m_logger.UpdateThreadPriority(); - std::fflush(stdout); - -#ifdef INTEGRATION - frc::SmartDashboard::PutBoolean("SysIdRun", false); - // TODO use std::exit or EndCompetition once CTRE bug is fixed - std::set_terminate([]() { std::_Exit(0); }); -#endif -} - -void DriveRobot::RobotInit() {} - -void DriveRobot::RobotPeriodic() {} - -/** - * This autonomous (along with the chooser code above) shows how to select - * between different autonomous modes using the dashboard. The sendable - * chooser code works with the Java SmartDashboard. If you prefer the LabVIEW - * Dashboard, remove all of the chooser code and uncomment the GetString line - * to get the auto name from the text box below the Gyro. - * - * You can add additional auto modes by adding additional comparisons to the - * if-else structure below with additional strings. If using the - * SendableChooser make sure to add them to the chooser code above as well. - */ -void DriveRobot::AutonomousInit() { - m_logger.InitLogging(); -} - -/** - * Outputs data in the format: timestamp, l voltage, r voltage, l position, r - * position, l velocity, r velocity, angle, angular rate - */ -void DriveRobot::AutonomousPeriodic() { - m_logger.Log(m_logger.MeasureVoltage(m_leftControllers, m_controllerNames), - m_logger.MeasureVoltage(m_rightControllers, m_controllerNames), - m_leftPosition(), m_rightPosition(), m_leftRate(), m_rightRate(), - m_gyroPosition(), m_gyroRate()); - sysid::SetMotorControllers(m_logger.GetLeftMotorVoltage(), m_leftControllers); - sysid::SetMotorControllers(m_logger.GetRightMotorVoltage(), - m_rightControllers); -} - -void DriveRobot::TeleopInit() {} - -void DriveRobot::TeleopPeriodic() { - PushNTDiagnostics(); -} - -void DriveRobot::DisabledInit() { - sysid::SetMotorControllers(0_V, m_leftControllers); - sysid::SetMotorControllers(0_V, m_rightControllers); - fmt::print("Robot disabled\n"); - m_logger.SendData(); -} - -void DriveRobot::SimulationPeriodic() { -#ifdef INTEGRATION - - bool enable = frc::SmartDashboard::GetBoolean("SysIdRun", false); - frc::sim::DriverStationSim::SetAutonomous(enable); - frc::sim::DriverStationSim::SetEnabled(enable); - frc::sim::DriverStationSim::NotifyNewData(); - - if (frc::SmartDashboard::GetBoolean("SysIdKill", false)) { - // TODO use std::exit or EndCompetition once CTRE bug is fixed - std::terminate(); - } -#endif -} - -void DriveRobot::DisabledPeriodic() { - PushNTDiagnostics(); -} - -void DriveRobot::TestInit() {} - -void DriveRobot::TestPeriodic() { - PushNTDiagnostics(); -} - -void DriveRobot::PushNTDiagnostics() { - try { - frc::SmartDashboard::PutNumber( - "Left Voltage", - m_logger.MeasureVoltage(m_leftControllers, m_controllerNames)); - frc::SmartDashboard::PutNumber( - "Right Voltage", - m_logger.MeasureVoltage(m_rightControllers, m_controllerNames)); - - frc::SmartDashboard::PutNumber("Left Position", m_leftPosition()); - frc::SmartDashboard::PutNumber("Right Position", m_rightPosition()); - frc::SmartDashboard::PutNumber("Left Velocity", m_leftRate()); - frc::SmartDashboard::PutNumber("Right Velocity", m_rightRate()); - - frc::SmartDashboard::PutNumber("Gyro Reading", m_gyroPosition()); - frc::SmartDashboard::PutNumber("Gyro Rate", m_gyroRate()); - } catch (std::exception& e) { - fmt::print("Project failed: {}\n", e.what()); - std::exit(-1); - } -} - -#ifndef RUNNING_FRC_TESTS -int main() { - return frc::StartRobot(); -} -#endif diff --git a/sysid-projects/drive/src/main/empty/empty.cpp b/sysid-projects/drive/src/main/empty/empty.cpp deleted file mode 100644 index 85c04a34..00000000 --- a/sysid-projects/drive/src/main/empty/empty.cpp +++ /dev/null @@ -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. diff --git a/sysid-projects/drive/src/main/include/DriveRobot.h b/sysid-projects/drive/src/main/include/DriveRobot.h deleted file mode 100644 index 8ee7f748..00000000 --- a/sysid-projects/drive/src/main/include/DriveRobot.h +++ /dev/null @@ -1,76 +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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Keep CTRE includes below ADIS16448_IMU header to allow Windows to build */ -#include -#include -#include - -#include "sysid/logging/SysIdDrivetrainLogger.h" - -class DriveRobot : public frc::TimedRobot { - public: - DriveRobot(); - void RobotInit() override; - void RobotPeriodic() override; - void AutonomousInit() override; - void AutonomousPeriodic() override; - void TeleopInit() override; - void TeleopPeriodic() override; - void SimulationPeriodic() override; - void DisabledInit() override; - void DisabledPeriodic() override; - void TestInit() override; - void TestPeriodic() override; - - void PushNTDiagnostics(); - - private: - std::vector> m_rightControllers; - std::vector> m_leftControllers; - std::vector m_controllerNames; - std::function m_leftPosition; - std::function m_leftRate; - std::function m_rightPosition; - std::function m_rightRate; - std::function m_gyroPosition; - std::function m_gyroRate; - wpi::json m_json; - std::unique_ptr m_leftRevEncoderPort; - std::unique_ptr m_leftRevDataPort; - std::unique_ptr m_rightRevEncoderPort; - std::unique_ptr m_rightRevDataPort; - std::unique_ptr m_leftEncoder; - std::unique_ptr m_rightEncoder; - std::unique_ptr m_gyro; - std::unique_ptr m_ADIS16448Gyro; - std::unique_ptr m_ADIS16470Gyro; - - std::unique_ptr m_leftCancoder; - std::unique_ptr m_rightCancoder; - std::unique_ptr m_leftCancoderPro; - std::unique_ptr m_rightCancoderPro; - std::unique_ptr m_tempTalon; - std::unique_ptr m_pigeon; - std::unique_ptr m_pigeonPro; - - sysid::SysIdDrivetrainLogger m_logger; -}; diff --git a/sysid-projects/mechanism/gradle.properties b/sysid-projects/mechanism/gradle.properties deleted file mode 100644 index 5836aad4..00000000 --- a/sysid-projects/mechanism/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -nativeutils.vendordep.folder.path=../../vendordeps diff --git a/sysid-projects/mechanism/src/main/cpp/MechanismRobot.cpp b/sysid-projects/mechanism/src/main/cpp/MechanismRobot.cpp deleted file mode 100644 index 02186abd..00000000 --- a/sysid-projects/mechanism/src/main/cpp/MechanismRobot.cpp +++ /dev/null @@ -1,154 +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 "MechanismRobot.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -MechanismRobot::MechanismRobot() : frc::TimedRobot(5_ms) { - try { - m_json = sysid::GetConfigJson(); - fmt::print("Reading JSON\n"); - std::vector ports = - m_json.at("primary motor ports").get>(); - m_controllerNames = - m_json.at("motor controllers").get>(); - std::vector canivoreNames = - m_json.at("canivore names").get>(); - std::vector encoderPorts = - m_json.at("primary encoder ports").get>(); - std::vector motorsInverted = - m_json.at("primary motors inverted").get>(); - std::string encoderCANivoreName = - m_json.at("encoder canivore name").get(); - - std::string encoderType = m_json.at("encoder type").get(); - bool encoderInverted = m_json.at("primary encoder inverted").get(); - - double cpr = m_json.at("counts per rotation").get(); - double gearingNumerator = m_json.at("gearing numerator").get(); - double gearingDenominator = m_json.at("gearing denominator").get(); - double gearing = gearingNumerator / gearingDenominator; - - bool isEncoding = m_json.at("encoding").get(); - - int numSamples = m_json.at("number of samples per average").get(); - - int period = m_json.at("velocity measurement period").get(); - - fmt::print("Initializing Motors\n"); - for (size_t i = 0; i < ports.size(); i++) { - sysid::AddMotorController(ports[i], m_controllerNames[i], - motorsInverted[i], canivoreNames[i], - &m_controllers); - } - - fmt::print("Initializing encoder\n"); - sysid::SetupEncoders( - encoderType, isEncoding, period, cpr, gearing, numSamples, - m_controllerNames[0], m_controllers.front().get(), encoderInverted, - encoderPorts, encoderCANivoreName, m_cancoder, m_cancoderPro, - m_revEncoderPort, m_revDataPort, m_encoder, m_position, m_rate); - } catch (std::exception& e) { - fmt::print("Project failed: {}\n", e.what()); - std::exit(-1); - } - std::fflush(stdout); -#ifdef INTEGRATION - frc::SmartDashboard::PutBoolean("SysIdRun", false); - // TODO use std::exit or EndCompetition once CTRE bug is fixed - std::set_terminate([]() { std::_Exit(0); }); -#endif -} - -void MechanismRobot::RobotInit() {} - -void MechanismRobot::RobotPeriodic() {} - -/** - * This autonomous (along with the chooser code above) shows how to select - * between different autonomous modes using the dashboard. The sendable chooser - * code works with the Java SmartDashboard. If you prefer the LabVIEW Dashboard, - * remove all of the chooser code and uncomment the GetString line to get the - * auto name from the text box below the Gyro. - * - * You can add additional auto modes by adding additional comparisons to the - * if-else structure below with additional strings. If using the SendableChooser - * make sure to add them to the chooser code above as well. - */ -void MechanismRobot::AutonomousInit() { - m_logger.InitLogging(); -} - -/** - * Outputs data in the format: timestamp, voltage, position, velocity - */ -void MechanismRobot::AutonomousPeriodic() { - m_logger.Log(m_logger.MeasureVoltage(m_controllers, m_controllerNames), - m_position(), m_rate()); - sysid::SetMotorControllers(m_logger.GetMotorVoltage(), m_controllers); -} - -void MechanismRobot::TeleopInit() {} - -void MechanismRobot::TeleopPeriodic() { - PushNTDiagnostics(); -} - -void MechanismRobot::DisabledInit() { - sysid::SetMotorControllers(0_V, m_controllers); - fmt::print("Robot Disabled\n"); - m_logger.SendData(); -} - -void MechanismRobot::SimulationPeriodic() { -#ifdef INTEGRATION - - bool enable = frc::SmartDashboard::GetBoolean("SysIdRun", false); - frc::sim::DriverStationSim::SetAutonomous(enable); - frc::sim::DriverStationSim::SetEnabled(enable); - frc::sim::DriverStationSim::NotifyNewData(); - - if (frc::SmartDashboard::GetBoolean("SysIdKill", false)) { - // TODO use std::exit or EndCompetition once CTRE bug is fixed - std::terminate(); - } -#endif -} - -void MechanismRobot::DisabledPeriodic() { - PushNTDiagnostics(); -} - -void MechanismRobot::TestInit() {} - -void MechanismRobot::TestPeriodic() { - PushNTDiagnostics(); -} - -void MechanismRobot::PushNTDiagnostics() { - try { - frc::SmartDashboard::PutNumber( - "Voltage", m_logger.MeasureVoltage(m_controllers, m_controllerNames)); - frc::SmartDashboard::PutNumber("Position", m_position()); - frc::SmartDashboard::PutNumber("Rate", m_rate()); - } catch (std::exception& e) { - fmt::print("Project failed: {}\n", e.what()); - std::exit(-1); - } -} - -#ifndef RUNNING_FRC_TESTS -int main() { - return frc::StartRobot(); -} -#endif diff --git a/sysid-projects/mechanism/src/main/empty/empty.cpp b/sysid-projects/mechanism/src/main/empty/empty.cpp deleted file mode 100644 index 85c04a34..00000000 --- a/sysid-projects/mechanism/src/main/empty/empty.cpp +++ /dev/null @@ -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. diff --git a/sysid-projects/mechanism/src/main/include/MechanismRobot.h b/sysid-projects/mechanism/src/main/include/MechanismRobot.h deleted file mode 100644 index 23eeae3d..00000000 --- a/sysid-projects/mechanism/src/main/include/MechanismRobot.h +++ /dev/null @@ -1,56 +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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "sysid/generation/SysIdSetup.h" -#include "sysid/logging/SysIdGeneralMechanismLogger.h" - -/* Keep CTRE includes below other headers to allow Windows to build */ -#include -#include - -class MechanismRobot : public frc::TimedRobot { - public: - MechanismRobot(); - void RobotInit() override; - void RobotPeriodic() override; - void AutonomousInit() override; - void AutonomousPeriodic() override; - void TeleopInit() override; - void TeleopPeriodic() override; - void SimulationPeriodic() override; - void DisabledInit() override; - void DisabledPeriodic() override; - void TestInit() override; - void TestPeriodic() override; - - void PushNTDiagnostics(); - - private: - std::vector> m_controllers; - std::vector m_controllerNames; - std::function m_position; - std::function m_rate; - wpi::json m_json; - std::unique_ptr m_revEncoderPort; - std::unique_ptr m_revDataPort; - std::unique_ptr m_cancoder; - std::unique_ptr m_cancoderPro; - std::unique_ptr m_encoder; - sysid::SysIdGeneralMechanismLogger m_logger; -}; diff --git a/sysid-projects/resources.gradle b/sysid-projects/resources.gradle deleted file mode 100644 index ebaeee35..00000000 --- a/sysid-projects/resources.gradle +++ /dev/null @@ -1,36 +0,0 @@ -ext.createLibDeployTask = { libGenerateTask -> - def libCreateTask = project.tasks.create('createLibDeployResources') { - dependsOn libGenerateTask - inputs.dir libGenerateTask.outputDirectory - outputs.file project.file('build/generated/libdeploy/libstodeploy.cpp') - doLast { - def outputFile = project.file('build/generated/libdeploy/libstodeploy.cpp') - outputFile.parentFile.mkdirs() - outputFile.withWriter { out -> - out.println '''#include - #include - #include - namespace sysid {''' - def files = libGenerateTask.outputDirectory.asFileTree.files - files.each { - def baseFuncName = it.name.substring(0, it.name.length() - 4) - def funcName = "GetResource_libraries_${baseFuncName}" - out.println "std::string_view ${funcName}();" - } - out.println '' - out.println '''std::vector> GetLibrariesToDeploy() { - std::vector> libraries;''' - files.each { - def baseFuncName = it.name.substring(0, it.name.length() - 4) - def nameWithoutSo = baseFuncName.substring(0, baseFuncName.length() - 3) - def funcName = "GetResource_libraries_${baseFuncName}" - out.println " libraries.emplace_back(std::make_pair(\"${nameWithoutSo}.so\", ${funcName}()));" - } - out.println ' return libraries;' - out.println '}' - out.println '} // namespace sysid' - } - } - } - return libCreateTask -} diff --git a/vendordeps/NavX.json b/vendordeps/NavX.json deleted file mode 100644 index 5c042782..00000000 --- a/vendordeps/NavX.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "fileName": "NavX.json", - "name": "KauaiLabs_navX_FRC", - "version": "2023.0.3", - "uuid": "cb311d09-36e9-4143-a032-55bb2b94443b", - "mavenUrls": [ - "https://dev.studica.com/maven/release/2023/" - ], - "jsonUrl": "https://dev.studica.com/releases/2023/NavX.json", - "javaDependencies": [ - { - "groupId": "com.kauailabs.navx.frc", - "artifactId": "navx-frc-java", - "version": "2023.0.3" - } - ], - "jniDependencies": [], - "cppDependencies": [ - { - "groupId": "com.kauailabs.navx.frc", - "artifactId": "navx-frc-cpp", - "version": "2023.0.3", - "headerClassifier": "headers", - "sourcesClassifier": "sources", - "sharedLibrary": false, - "libName": "navx_frc", - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxraspbian", - "linuxarm32", - "linuxarm64", - "linux86-64", - "osxuniversal", - "windowsx86-64" - ] - } - ] -} diff --git a/vendordeps/PhoenixProAnd5.json b/vendordeps/PhoenixProAnd5.json deleted file mode 100644 index 6eee62fa..00000000 --- a/vendordeps/PhoenixProAnd5.json +++ /dev/null @@ -1,458 +0,0 @@ -{ - "fileName": "PhoenixProAnd5.json", - "name": "CTRE-Phoenix (Pro And v5)", - "version": "23.0.5", - "frcYear": 2023, - "uuid": "3fcf3402-e646-4fa6-971e-18afe8173b1a", - "mavenUrls": [ - "https://maven.ctr-electronics.com/release/" - ], - "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenixpro/PhoenixProAnd5-frc2023-latest.json", - "javaDependencies": [ - { - "groupId": "com.ctre.phoenix", - "artifactId": "api-java", - "version": "5.30.4" - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "wpiapi-java", - "version": "5.30.4" - }, - { - "groupId": "com.ctre.phoenixpro", - "artifactId": "wpiapi-java", - "version": "23.0.5" - } - ], - "jniDependencies": [ - { - "groupId": "com.ctre.phoenix", - "artifactId": "cci", - "version": "5.30.4", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix.sim", - "artifactId": "cci-sim", - "version": "5.30.4", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro", - "artifactId": "tools", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "tools-sim", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simTalonSRX", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simTalonFX", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simVictorSPX", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simPigeonIMU", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simCANCoder", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProTalonFX", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProCANcoder", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProPigeon2", - "version": "23.0.5", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - } - ], - "cppDependencies": [ - { - "groupId": "com.ctre.phoenix", - "artifactId": "wpiapi-cpp", - "version": "5.30.4", - "libName": "CTRE_Phoenix_WPI", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "api-cpp", - "version": "5.30.4", - "libName": "CTRE_Phoenix", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix", - "artifactId": "cci", - "version": "5.30.4", - "libName": "CTRE_PhoenixCCI", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenixpro", - "artifactId": "tools", - "version": "23.0.5", - "libName": "CTRE_PhoenixTools", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenix.sim", - "artifactId": "wpiapi-cpp-sim", - "version": "5.30.4", - "libName": "CTRE_Phoenix_WPISim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix.sim", - "artifactId": "api-cpp-sim", - "version": "5.30.4", - "libName": "CTRE_PhoenixSim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix.sim", - "artifactId": "cci-sim", - "version": "5.30.4", - "libName": "CTRE_PhoenixCCISim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "tools-sim", - "version": "23.0.5", - "libName": "CTRE_PhoenixTools_Sim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simTalonSRX", - "version": "23.0.5", - "libName": "CTRE_SimTalonSRX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simTalonFX", - "version": "23.0.5", - "libName": "CTRE_SimTalonFX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simVictorSPX", - "version": "23.0.5", - "libName": "CTRE_SimVictorSPX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simPigeonIMU", - "version": "23.0.5", - "libName": "CTRE_SimPigeonIMU", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simCANCoder", - "version": "23.0.5", - "libName": "CTRE_SimCANCoder", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProTalonFX", - "version": "23.0.5", - "libName": "CTRE_SimProTalonFX", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProCANcoder", - "version": "23.0.5", - "libName": "CTRE_SimProCANcoder", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "simProPigeon2", - "version": "23.0.5", - "libName": "CTRE_SimProPigeon2", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenixpro", - "artifactId": "wpiapi-cpp", - "version": "23.0.5", - "libName": "CTRE_PhoenixPro_WPI", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxathena" - ], - "simMode": "hwsim" - }, - { - "groupId": "com.ctre.phoenixpro.sim", - "artifactId": "wpiapi-cpp-sim", - "version": "23.0.5", - "libName": "CTRE_PhoenixPro_WPISim", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ], - "simMode": "swsim" - } - ] -} diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json deleted file mode 100644 index 0d55b632..00000000 --- a/vendordeps/REVLib.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "fileName": "REVLib.json", - "name": "REVLib", - "version": "2023.1.2", - "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", - "mavenUrls": [ - "https://maven.revrobotics.com/" - ], - "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2023.json", - "javaDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-java", - "version": "2023.1.2" - } - ], - "jniDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-driver", - "version": "2023.1.2", - "skipInvalidPlatforms": true, - "isJar": false, - "validPlatforms": [ - "windowsx86-64", - "windowsx86", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-cpp", - "version": "2023.1.2", - "libName": "REVLib", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "windowsx86", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - }, - { - "groupId": "com.revrobotics.frc", - "artifactId": "REVLib-driver", - "version": "2023.1.2", - "libName": "REVLibDriver", - "headerClassifier": "headers", - "sharedLibrary": false, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "windowsx86", - "linuxarm64", - "linuxx86-64", - "linuxathena", - "linuxarm32", - "osxuniversal" - ] - } - ] -} diff --git a/vendordeps/playingwithfusion2023.json b/vendordeps/playingwithfusion2023.json deleted file mode 100644 index 3a9fae90..00000000 --- a/vendordeps/playingwithfusion2023.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "fileName": "playingwithfusion2023.json", - "name": "PlayingWithFusion", - "version": "2023.01.17", - "uuid": "14b8ad04-24df-11ea-978f-2e728ce88125", - "jsonUrl": "https://www.playingwithfusion.com/frc/playingwithfusion2023.json", - "mavenUrls": [ - "https://www.playingwithfusion.com/frc/maven/" - ], - "javaDependencies": [ - { - "groupId": "com.playingwithfusion.frc", - "artifactId": "PlayingWithFusion-java", - "version": "2023.01.17" - } - ], - "jniDependencies": [ - { - "groupId": "com.playingwithfusion.frc", - "artifactId": "PlayingWithFusion-driver", - "version": "2023.01.17", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "linuxathena", - "linuxraspbian", - "linuxaarch64bionic", - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ] - } - ], - "cppDependencies": [ - { - "groupId": "com.playingwithfusion.frc", - "artifactId": "PlayingWithFusion-cpp", - "version": "2023.01.17", - "headerClassifier": "headers", - "sharedLibrary": false, - "libName": "PlayingWithFusion", - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxraspbian", - "linuxaarch64bionic", - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ] - }, - { - "groupId": "com.playingwithfusion.frc", - "artifactId": "PlayingWithFusion-driver", - "version": "2023.01.17", - "headerClassifier": "headers", - "sharedLibrary": true, - "libName": "PlayingWithFusionDriver", - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "linuxathena", - "linuxraspbian", - "linuxaarch64bionic", - "windowsx86-64", - "linuxx86-64", - "osxuniversal" - ] - } - ] -}