├── .gitattributes ├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── .prettierrc ├── Path ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── technototes │ │ └── path │ │ ├── command │ │ ├── MecanumDriveCommand.java │ │ ├── RegenerativeTrajectoryCommand.java │ │ ├── RegenerativeTrajectorySequenceCommand.java │ │ ├── ResetGyroCommand.java │ │ ├── TrajectoryCommand.java │ │ └── TrajectorySequenceCommand.java │ │ ├── geometry │ │ ├── ConfigurablePose.java │ │ ├── ConfigurablePoseD.java │ │ └── ConfigurableVector.java │ │ ├── subsystem │ │ ├── DeadWheelConstants.java │ │ ├── DistanceSensorLocalizer.java │ │ ├── MecanumConstants.java │ │ ├── PathingMecanumDrivebaseSubsystem.java │ │ ├── TankConstants.java │ │ ├── TankDrivebaseSubsystem.java │ │ ├── ThreeDeadWheelLocalizer.java │ │ └── TwoDeadWheelLocalizer.java │ │ ├── trajectorysequence │ │ ├── EmptySequenceException.java │ │ ├── TrajectoryPath.java │ │ ├── TrajectorySequence.java │ │ ├── TrajectorySequenceBuilder.java │ │ ├── TrajectorySequenceRunner.java │ │ └── sequencesegment │ │ │ ├── SequenceSegment.java │ │ │ ├── TrajectorySegment.java │ │ │ ├── TurnSegment.java │ │ │ └── WaitSegment.java │ │ └── util │ │ ├── AxesSigns.java │ │ ├── BNO055IMUUtil.java │ │ ├── DashboardUtil.java │ │ ├── LoggingUtil.java │ │ ├── LynxModuleUtil.java │ │ └── RegressionUtil.java │ └── res │ └── values │ └── strings.xml ├── RobotLibrary ├── .gitignore ├── build.gradle └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── technototes │ │ │ └── library │ │ │ ├── RobotLibrary.java │ │ │ ├── command │ │ │ ├── ChoiceCommand.java │ │ │ ├── Command.java │ │ │ ├── CommandGroup.java │ │ │ ├── CommandScheduler.java │ │ │ ├── ConditionalCommand.java │ │ │ ├── IterativeCommand.java │ │ │ ├── MethodCommand.java │ │ │ ├── ParallelCommandGroup.java │ │ │ ├── ParallelDeadlineGroup.java │ │ │ ├── ParallelRaceGroup.java │ │ │ ├── SequentialCommandGroup.java │ │ │ └── WaitCommand.java │ │ │ ├── control │ │ │ ├── AxisBase.java │ │ │ ├── Binding.java │ │ │ ├── ButtonBase.java │ │ │ ├── CommandAxis.java │ │ │ ├── CommandBinding.java │ │ │ ├── CommandButton.java │ │ │ ├── CommandGamepad.java │ │ │ ├── CommandInput.java │ │ │ ├── GamepadBase.java │ │ │ ├── GamepadDpad.java │ │ │ ├── GamepadStick.java │ │ │ └── Stick.java │ │ │ ├── general │ │ │ ├── CanBeEnabled.java │ │ │ ├── Invertible.java │ │ │ └── Periodic.java │ │ │ ├── hardware │ │ │ ├── DummyDevice.java │ │ │ ├── FailedDevice.java │ │ │ ├── HardwareDevice.java │ │ │ ├── Sensored.java │ │ │ ├── motor │ │ │ │ ├── CRServo.java │ │ │ │ ├── EncodedMotor.java │ │ │ │ └── Motor.java │ │ │ ├── sensor │ │ │ │ ├── AdafruitIMU.java │ │ │ │ ├── AnalogSensor.java │ │ │ │ ├── ColorDistanceSensor.java │ │ │ │ ├── ColorSensor.java │ │ │ │ ├── DigitalSensor.java │ │ │ │ ├── IColorSensor.java │ │ │ │ ├── IDistanceSensor.java │ │ │ │ ├── IGyro.java │ │ │ │ ├── ILightSensor.java │ │ │ │ ├── IMU.java │ │ │ │ ├── Rev2MDistanceSensor.java │ │ │ │ ├── Sensor.java │ │ │ │ └── encoder │ │ │ │ │ ├── Encoder.java │ │ │ │ │ ├── ExternalEncoder.java │ │ │ │ │ └── MotorEncoder.java │ │ │ └── servo │ │ │ │ ├── MotorAsServo.java │ │ │ │ ├── Servo.java │ │ │ │ └── ServoProfiler.java │ │ │ ├── logger │ │ │ ├── Log.java │ │ │ ├── LogConfig.java │ │ │ ├── Loggable.java │ │ │ ├── Logger.java │ │ │ └── entry │ │ │ │ ├── BooleanEntry.java │ │ │ │ ├── Entry.java │ │ │ │ ├── NumberEntry.java │ │ │ │ └── StringEntry.java │ │ │ ├── structure │ │ │ └── CommandOpMode.java │ │ │ ├── subsystem │ │ │ ├── Subsystem.java │ │ │ └── drivebase │ │ │ │ ├── DrivebaseSubsystem.java │ │ │ │ ├── SimpleMecanumDrivebaseSubsystem.java │ │ │ │ └── TankDrivebaseSubsystem.java │ │ │ └── util │ │ │ ├── Alliance.java │ │ │ ├── Characters.java │ │ │ ├── Color.java │ │ │ ├── Differential.java │ │ │ ├── Integral.java │ │ │ ├── MapUtils.java │ │ │ ├── MathUtils.java │ │ │ ├── Range.java │ │ │ └── SmartConsumer.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── technototes │ └── library │ ├── TestTest.java │ ├── command │ ├── CancelCommandTest.java │ ├── CommandForTesting.java │ ├── CommandGroupTest.java │ ├── CommandTest.java │ ├── ConditionalCommandTest.java │ ├── RequirementCommandTest.java │ └── SimpleCommandTest.java │ ├── gamepad │ └── GamepadTest.java │ ├── hardware │ ├── MockServo.java │ └── ServoProfilerTest.java │ ├── opmode │ └── OpModeTest.java │ └── util │ └── DifferentialTest.java ├── Vision ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── technototes │ │ └── vision │ │ ├── HSVRange.java │ │ ├── hardware │ │ ├── Camera.java │ │ ├── InternalCamera.java │ │ ├── SwitchableWebcam.java │ │ └── Webcam.java │ │ └── subsystem │ │ └── BasicVisionSubsystem.java │ └── res │ └── values │ └── strings.xml ├── build.dependencies.gradle ├── build.gradle ├── bun.lockb ├── docs ├── TechnoLib │ ├── allclasses-index.html │ ├── allpackages-index.html │ ├── com │ │ └── technototes │ │ │ └── library │ │ │ ├── RobotLibrary.html │ │ │ ├── command │ │ │ ├── ChoiceCommand.html │ │ │ ├── Command.CommandState.html │ │ │ ├── Command.html │ │ │ ├── CommandGroup.html │ │ │ ├── CommandScheduler.html │ │ │ ├── ConditionalCommand.html │ │ │ ├── IterativeCommand.html │ │ │ ├── MethodCommand.html │ │ │ ├── ParallelCommandGroup.html │ │ │ ├── ParallelDeadlineGroup.html │ │ │ ├── ParallelRaceGroup.html │ │ │ ├── SequentialCommandGroup.html │ │ │ ├── WaitCommand.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ ├── control │ │ │ ├── AxisBase.html │ │ │ ├── Binding.Type.html │ │ │ ├── Binding.html │ │ │ ├── ButtonBase.html │ │ │ ├── CommandAxis.html │ │ │ ├── CommandBinding.html │ │ │ ├── CommandButton.html │ │ │ ├── CommandGamepad.html │ │ │ ├── CommandInput.html │ │ │ ├── GamepadBase.Axis.html │ │ │ ├── GamepadBase.Button.html │ │ │ ├── GamepadBase.html │ │ │ ├── GamepadDpad.html │ │ │ ├── GamepadStick.html │ │ │ ├── Stick.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ ├── general │ │ │ ├── CanBeEnabled.html │ │ │ ├── Invertible.html │ │ │ ├── Periodic.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ ├── hardware │ │ │ ├── DummyDevice.html │ │ │ ├── FailedDevice.html │ │ │ ├── HardwareDevice.html │ │ │ ├── Sensored.html │ │ │ ├── motor │ │ │ │ ├── CRServo.html │ │ │ │ ├── EncodedMotor.html │ │ │ │ ├── Motor.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ ├── sensor │ │ │ │ ├── AnalogSensor.html │ │ │ │ ├── ColorDistanceSensor.html │ │ │ │ ├── ColorSensor.html │ │ │ │ ├── DigitalSensor.html │ │ │ │ ├── IColorSensor.html │ │ │ │ ├── IDistanceSensor.html │ │ │ │ ├── IGyro.html │ │ │ │ ├── ILightSensor.html │ │ │ │ ├── IMU.AxesSigns.html │ │ │ │ ├── IMU.html │ │ │ │ ├── Rev2MDistanceSensor.html │ │ │ │ ├── Sensor.html │ │ │ │ ├── encoder │ │ │ │ │ ├── Encoder.html │ │ │ │ │ ├── ExternalEncoder.html │ │ │ │ │ ├── MotorEncoder.Direction.html │ │ │ │ │ ├── MotorEncoder.html │ │ │ │ │ ├── package-summary.html │ │ │ │ │ └── package-tree.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ └── servo │ │ │ │ ├── MotorAsServo.html │ │ │ │ ├── Servo.html │ │ │ │ ├── ServoProfiler.Constraints.html │ │ │ │ ├── ServoProfiler.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ ├── logger │ │ │ ├── Log.Boolean.html │ │ │ ├── Log.Logs.html │ │ │ ├── Log.Number.html │ │ │ ├── Log.html │ │ │ ├── LogConfig.AllowList.html │ │ │ ├── LogConfig.DenyList.html │ │ │ ├── LogConfig.Disabled.html │ │ │ ├── LogConfig.Run.html │ │ │ ├── LogConfig.html │ │ │ ├── Loggable.html │ │ │ ├── Logger.html │ │ │ ├── entry │ │ │ │ ├── BooleanEntry.html │ │ │ │ ├── Entry.html │ │ │ │ ├── NumberEntry.html │ │ │ │ ├── StringEntry.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ ├── structure │ │ │ ├── CommandOpMode.OpModeState.html │ │ │ ├── CommandOpMode.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ ├── subsystem │ │ │ ├── Subsystem.html │ │ │ ├── drivebase │ │ │ │ ├── DrivebaseSubsystem.html │ │ │ │ ├── SimpleMecanumDrivebaseSubsystem.html │ │ │ │ ├── TankDrivebaseSubsystem.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ │ └── util │ │ │ ├── Alliance.Blue.html │ │ │ ├── Alliance.Red.html │ │ │ ├── Alliance.Selector.html │ │ │ ├── Alliance.html │ │ │ ├── Characters.html │ │ │ ├── Color.html │ │ │ ├── Differential.DifferentialPriority.html │ │ │ ├── Differential.html │ │ │ ├── Integral.html │ │ │ ├── MapUtils.html │ │ │ ├── MathUtils.html │ │ │ ├── Range.html │ │ │ ├── SmartConsumer.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ ├── constant-values.html │ ├── copy.svg │ ├── deprecated-list.html │ ├── element-list │ ├── help-doc.html │ ├── index-all.html │ ├── index.html │ ├── jquery-ui.overrides.css │ ├── legal │ │ ├── ADDITIONAL_LICENSE_INFO │ │ ├── ASSEMBLY_EXCEPTION │ │ ├── LICENSE │ │ ├── jquery.md │ │ └── jqueryUI.md │ ├── member-search-index.js │ ├── module-search-index.js │ ├── overview-summary.html │ ├── overview-tree.html │ ├── package-search-index.js │ ├── resources │ │ ├── glass.png │ │ └── x.png │ ├── script-dir │ │ ├── images │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ ├── ui-bg_glass_65_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_454545_256x240.png │ │ │ ├── ui-icons_888888_256x240.png │ │ │ └── ui-icons_cd0a0a_256x240.png │ │ ├── jquery-3.5.1.min.js │ │ ├── jquery-ui.min.css │ │ ├── jquery-ui.min.js │ │ └── jquery-ui.structure.min.css │ ├── script.js │ ├── search.js │ ├── src-html │ │ └── com │ │ │ └── technototes │ │ │ └── library │ │ │ ├── RobotLibrary.html │ │ │ ├── command │ │ │ ├── ChoiceCommand.html │ │ │ ├── Command.CommandState.html │ │ │ ├── Command.html │ │ │ ├── CommandGroup.html │ │ │ ├── CommandScheduler.html │ │ │ ├── ConditionalCommand.html │ │ │ ├── IterativeCommand.html │ │ │ ├── MethodCommand.html │ │ │ ├── ParallelCommandGroup.html │ │ │ ├── ParallelDeadlineGroup.html │ │ │ ├── ParallelRaceGroup.html │ │ │ ├── SequentialCommandGroup.html │ │ │ └── WaitCommand.html │ │ │ ├── control │ │ │ ├── AxisBase.html │ │ │ ├── Binding.Type.html │ │ │ ├── Binding.html │ │ │ ├── ButtonBase.html │ │ │ ├── CommandAxis.html │ │ │ ├── CommandBinding.html │ │ │ ├── CommandButton.html │ │ │ ├── CommandGamepad.html │ │ │ ├── CommandInput.html │ │ │ ├── GamepadBase.Axis.html │ │ │ ├── GamepadBase.Button.html │ │ │ ├── GamepadBase.html │ │ │ ├── GamepadDpad.html │ │ │ ├── GamepadStick.html │ │ │ └── Stick.html │ │ │ ├── general │ │ │ ├── CanBeEnabled.html │ │ │ ├── Invertible.html │ │ │ └── Periodic.html │ │ │ ├── hardware │ │ │ ├── DummyDevice.html │ │ │ ├── FailedDevice.html │ │ │ ├── HardwareDevice.html │ │ │ ├── Sensored.html │ │ │ ├── motor │ │ │ │ ├── CRServo.html │ │ │ │ ├── EncodedMotor.html │ │ │ │ └── Motor.html │ │ │ ├── sensor │ │ │ │ ├── AnalogSensor.html │ │ │ │ ├── ColorDistanceSensor.html │ │ │ │ ├── ColorSensor.html │ │ │ │ ├── DigitalSensor.html │ │ │ │ ├── IColorSensor.html │ │ │ │ ├── IDistanceSensor.html │ │ │ │ ├── IGyro.html │ │ │ │ ├── ILightSensor.html │ │ │ │ ├── IMU.AxesSigns.html │ │ │ │ ├── IMU.html │ │ │ │ ├── Rev2MDistanceSensor.html │ │ │ │ ├── Sensor.html │ │ │ │ └── encoder │ │ │ │ │ ├── Encoder.html │ │ │ │ │ ├── ExternalEncoder.html │ │ │ │ │ ├── MotorEncoder.Direction.html │ │ │ │ │ └── MotorEncoder.html │ │ │ └── servo │ │ │ │ ├── MotorAsServo.html │ │ │ │ ├── Servo.html │ │ │ │ ├── ServoProfiler.Constraints.html │ │ │ │ └── ServoProfiler.html │ │ │ ├── logger │ │ │ ├── Log.Boolean.html │ │ │ ├── Log.Logs.html │ │ │ ├── Log.Number.html │ │ │ ├── Log.html │ │ │ ├── LogConfig.AllowList.html │ │ │ ├── LogConfig.DenyList.html │ │ │ ├── LogConfig.Disabled.html │ │ │ ├── LogConfig.Run.html │ │ │ ├── LogConfig.html │ │ │ ├── Loggable.html │ │ │ ├── Logger.html │ │ │ └── entry │ │ │ │ ├── BooleanEntry.html │ │ │ │ ├── Entry.html │ │ │ │ ├── NumberEntry.html │ │ │ │ └── StringEntry.html │ │ │ ├── structure │ │ │ ├── CommandOpMode.OpModeState.html │ │ │ └── CommandOpMode.html │ │ │ ├── subsystem │ │ │ ├── Subsystem.html │ │ │ └── drivebase │ │ │ │ ├── DrivebaseSubsystem.html │ │ │ │ ├── SimpleMecanumDrivebaseSubsystem.html │ │ │ │ └── TankDrivebaseSubsystem.html │ │ │ └── util │ │ │ ├── Alliance.Blue.html │ │ │ ├── Alliance.Red.html │ │ │ ├── Alliance.Selector.html │ │ │ ├── Alliance.html │ │ │ ├── Characters.html │ │ │ ├── Color.html │ │ │ ├── Differential.DifferentialPriority.html │ │ │ ├── Differential.html │ │ │ ├── Integral.html │ │ │ ├── MapUtils.html │ │ │ ├── MathUtils.html │ │ │ ├── Range.html │ │ │ └── SmartConsumer.html │ ├── stylesheet.css │ ├── tag-search-index.js │ └── type-search-index.js └── index.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── index.html ├── notes.md ├── package.json ├── readme.md ├── scripts └── os.ts └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | **/yarn.lock -diff 2 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Gradle 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 3 | 4 | name: Java CI with Gradle 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v3 21 | with: 22 | distribution: temurin 23 | java-version: 17 24 | - name: Grant execute permission for gradlew 25 | run: chmod +x gradlew 26 | - name: Build with Gradle 27 | run: ./gradlew build 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /tempMergeFolder 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-java"], 3 | "printWidth": 100, 4 | "trailingComma": "all", 5 | "singleQuote": true, 6 | "proseWrap": "always", 7 | "tabWidth": 2, 8 | "useTabs": false, 9 | "endOfLine": "lf", 10 | "overrides": [ 11 | { 12 | "files": ".prettierrc", 13 | "options": { "parser": "json" } 14 | }, 15 | { 16 | "files": "*.json", 17 | "options": { "parser": "json" } 18 | }, 19 | { 20 | "files": "*.java", 21 | "options": { "tabWidth": 4, "printWidth": 120 } 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /Path/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Path/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | namespace = 'com.technototes.path' 5 | 6 | lint { 7 | disable 'ExpiredTargetSdkVersion' 8 | } 9 | 10 | defaultConfig { 11 | minSdkVersion 24 12 | targetSdkVersion 28 13 | } 14 | 15 | compileSdkVersion 29 16 | 17 | compileOptions { 18 | sourceCompatibility JavaVersion.VERSION_1_8 19 | targetCompatibility JavaVersion.VERSION_1_8 20 | } 21 | } 22 | 23 | dependencies { 24 | 25 | implementation project(':RobotLibrary') 26 | 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation('org.ejml:ejml-simple:0.39') { 29 | exclude group: 'org.ejml', module: 'ejml-all' 30 | } 31 | 32 | implementation 'org.apache.commons:commons-math3:3.6.1' 33 | 34 | 35 | implementation 'com.acmerobotics.dashboard:dashboard:0.4.15' 36 | implementation 'com.acmerobotics.roadrunner:core:0.5.6' 37 | 38 | 39 | testImplementation(platform('org.junit:junit-bom:5.7.0')) 40 | testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.0') 41 | testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.0') 42 | testImplementation('org.mockito:mockito-core:3.5.11') 43 | testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.0" 44 | 45 | } 46 | 47 | task javadoc(type: Javadoc) { 48 | source = android.sourceSets.main.java.srcDirs 49 | classpath = project.files(android.getBootClasspath().join(File.pathSeparator)) 50 | failOnError false 51 | destinationDir = file("../docs/Path/") 52 | options { 53 | linkSource true 54 | encoding = 'utf-8' 55 | } 56 | } 57 | 58 | afterEvaluate { 59 | javadoc.classpath += files(android.libraryVariants.collect { variant -> 60 | variant.javaCompileProvider.get().classpath.files 61 | }) 62 | } 63 | 64 | apply from: '../build.dependencies.gradle' 65 | -------------------------------------------------------------------------------- /Path/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/MecanumDriveCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.acmerobotics.roadrunner.drive.DriveSignal; 4 | import com.acmerobotics.roadrunner.geometry.Pose2d; 5 | import com.acmerobotics.roadrunner.geometry.Vector2d; 6 | import com.technototes.library.command.Command; 7 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 8 | import java.util.function.DoubleSupplier; 9 | 10 | public class MecanumDriveCommand implements Command { 11 | 12 | public PathingMecanumDrivebaseSubsystem subsystem; 13 | public DoubleSupplier x, y, r; 14 | 15 | public MecanumDriveCommand( 16 | PathingMecanumDrivebaseSubsystem sub, 17 | DoubleSupplier xSup, 18 | DoubleSupplier ySup, 19 | DoubleSupplier rSup 20 | ) { 21 | addRequirements(sub); 22 | subsystem = sub; 23 | x = xSup; 24 | y = ySup; 25 | r = rSup; 26 | } 27 | 28 | @Override 29 | public void execute() { 30 | Vector2d input = new Vector2d(-y.getAsDouble() * subsystem.speed, -x.getAsDouble() * subsystem.speed).rotated( 31 | -subsystem.getExternalHeading() 32 | ); 33 | 34 | subsystem.setWeightedDrivePower( 35 | new Pose2d(input.getX(), input.getY(), -Math.pow(r.getAsDouble() * subsystem.speed, 3)) 36 | ); 37 | } 38 | 39 | @Override 40 | public boolean isFinished() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public void end(boolean cancel) { 46 | if (cancel) subsystem.setDriveSignal(new DriveSignal()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/RegenerativeTrajectoryCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.acmerobotics.roadrunner.trajectory.Trajectory; 5 | import com.acmerobotics.roadrunner.trajectory.TrajectoryBuilder; 6 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 7 | import java.util.function.BiFunction; 8 | import java.util.function.Function; 9 | import java.util.function.Supplier; 10 | 11 | public class RegenerativeTrajectoryCommand extends TrajectoryCommand { 12 | 13 | public Supplier trajFunc; 14 | 15 | public RegenerativeTrajectoryCommand( 16 | PathingMecanumDrivebaseSubsystem sub, 17 | Function, Trajectory> t 18 | ) { 19 | super(sub, t); 20 | trajFunc = () -> t.apply(sub::trajectoryBuilder); 21 | } 22 | 23 | public RegenerativeTrajectoryCommand(PathingMecanumDrivebaseSubsystem sub, Supplier t) { 24 | super(sub, t); 25 | trajFunc = t; 26 | } 27 | 28 | public RegenerativeTrajectoryCommand( 29 | PathingMecanumDrivebaseSubsystem sub, 30 | BiFunction, T, Trajectory> t, 31 | T mux 32 | ) { 33 | super(sub, t, mux); 34 | trajFunc = () -> t.apply(sub::trajectoryBuilder, mux); 35 | } 36 | 37 | public RegenerativeTrajectoryCommand(PathingMecanumDrivebaseSubsystem sub, Function t, T mux) { 38 | super(sub, t, mux); 39 | trajFunc = () -> t.apply(mux); 40 | } 41 | 42 | @Override 43 | public void initialize() { 44 | subsystem.followTrajectoryAsync(trajFunc.get()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/RegenerativeTrajectorySequenceCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 5 | import com.technototes.path.trajectorysequence.TrajectorySequence; 6 | import com.technototes.path.trajectorysequence.TrajectorySequenceBuilder; 7 | import java.util.function.BiFunction; 8 | import java.util.function.Function; 9 | import java.util.function.Supplier; 10 | 11 | public class RegenerativeTrajectorySequenceCommand extends TrajectorySequenceCommand { 12 | 13 | public Supplier trajFunc; 14 | 15 | public RegenerativeTrajectorySequenceCommand( 16 | PathingMecanumDrivebaseSubsystem sub, 17 | Function, TrajectorySequence> t 18 | ) { 19 | super(sub, t); 20 | trajFunc = () -> t.apply(sub::trajectorySequenceBuilder); 21 | } 22 | 23 | public RegenerativeTrajectorySequenceCommand(PathingMecanumDrivebaseSubsystem sub, Supplier t) { 24 | super(sub, t); 25 | trajFunc = t; 26 | } 27 | 28 | public RegenerativeTrajectorySequenceCommand( 29 | PathingMecanumDrivebaseSubsystem sub, 30 | BiFunction, T, TrajectorySequence> t, 31 | T mux 32 | ) { 33 | super(sub, t, mux); 34 | trajFunc = () -> t.apply(sub::trajectorySequenceBuilder, mux); 35 | } 36 | 37 | public RegenerativeTrajectorySequenceCommand( 38 | PathingMecanumDrivebaseSubsystem sub, 39 | Function t, 40 | T mux 41 | ) { 42 | super(sub, t, mux); 43 | trajFunc = () -> t.apply(mux); 44 | } 45 | 46 | @Override 47 | public void initialize() { 48 | subsystem.followTrajectorySequenceAsync(trajFunc.get()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/ResetGyroCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.technototes.library.command.Command; 4 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 5 | 6 | public class ResetGyroCommand implements Command { 7 | 8 | public PathingMecanumDrivebaseSubsystem subsystem; 9 | 10 | public ResetGyroCommand(PathingMecanumDrivebaseSubsystem s) { 11 | subsystem = s; 12 | } 13 | 14 | @Override 15 | public void execute() { 16 | subsystem.zeroExternalHeading(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/TrajectoryCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.acmerobotics.roadrunner.trajectory.Trajectory; 5 | import com.acmerobotics.roadrunner.trajectory.TrajectoryBuilder; 6 | import com.technototes.library.command.Command; 7 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 8 | import java.util.function.BiFunction; 9 | import java.util.function.Function; 10 | import java.util.function.Supplier; 11 | 12 | public class TrajectoryCommand implements Command { 13 | 14 | public Trajectory trajectory; 15 | public PathingMecanumDrivebaseSubsystem subsystem; 16 | 17 | public TrajectoryCommand(PathingMecanumDrivebaseSubsystem sub, Trajectory t) { 18 | addRequirements(sub); 19 | subsystem = sub; 20 | trajectory = t; 21 | } 22 | 23 | public TrajectoryCommand( 24 | PathingMecanumDrivebaseSubsystem sub, 25 | Function, Trajectory> t 26 | ) { 27 | addRequirements(sub); 28 | subsystem = sub; 29 | trajectory = t.apply(sub::trajectoryBuilder); 30 | } 31 | 32 | public TrajectoryCommand(PathingMecanumDrivebaseSubsystem sub, Supplier t) { 33 | addRequirements(sub); 34 | subsystem = sub; 35 | trajectory = t.get(); 36 | } 37 | 38 | public TrajectoryCommand( 39 | PathingMecanumDrivebaseSubsystem sub, 40 | BiFunction, T, Trajectory> t, 41 | T mux 42 | ) { 43 | addRequirements(sub); 44 | subsystem = sub; 45 | trajectory = t.apply(sub::trajectoryBuilder, mux); 46 | } 47 | 48 | public TrajectoryCommand(PathingMecanumDrivebaseSubsystem sub, Function t, T mux) { 49 | addRequirements(sub); 50 | subsystem = sub; 51 | trajectory = t.apply(mux); 52 | } 53 | 54 | @Override 55 | public void initialize() { 56 | subsystem.followTrajectoryAsync(trajectory); 57 | } 58 | 59 | @Override 60 | public void execute() { 61 | subsystem.update(); 62 | } 63 | 64 | @Override 65 | public boolean isFinished() { 66 | return !subsystem.isBusy(); 67 | } 68 | 69 | @Override 70 | public void end(boolean cancel) { 71 | if (cancel) subsystem.stop(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/command/TrajectorySequenceCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.command; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.technototes.library.command.Command; 5 | import com.technototes.path.subsystem.PathingMecanumDrivebaseSubsystem; 6 | import com.technototes.path.trajectorysequence.TrajectorySequence; 7 | import com.technototes.path.trajectorysequence.TrajectorySequenceBuilder; 8 | import java.util.function.BiFunction; 9 | import java.util.function.Function; 10 | import java.util.function.Supplier; 11 | 12 | public class TrajectorySequenceCommand implements Command { 13 | 14 | public TrajectorySequence trajectory; 15 | public PathingMecanumDrivebaseSubsystem subsystem; 16 | 17 | public TrajectorySequenceCommand(PathingMecanumDrivebaseSubsystem sub, TrajectorySequence t) { 18 | addRequirements(sub); 19 | subsystem = sub; 20 | trajectory = t; 21 | } 22 | 23 | public TrajectorySequenceCommand( 24 | PathingMecanumDrivebaseSubsystem sub, 25 | Function, TrajectorySequence> t 26 | ) { 27 | addRequirements(sub); 28 | subsystem = sub; 29 | trajectory = t.apply(sub::trajectorySequenceBuilder); 30 | } 31 | 32 | public TrajectorySequenceCommand(PathingMecanumDrivebaseSubsystem sub, Supplier t) { 33 | addRequirements(sub); 34 | subsystem = sub; 35 | trajectory = t.get(); 36 | } 37 | 38 | public TrajectorySequenceCommand( 39 | PathingMecanumDrivebaseSubsystem sub, 40 | BiFunction, T, TrajectorySequence> t, 41 | T mux 42 | ) { 43 | addRequirements(sub); 44 | subsystem = sub; 45 | trajectory = t.apply(sub::trajectorySequenceBuilder, mux); 46 | } 47 | 48 | public TrajectorySequenceCommand( 49 | PathingMecanumDrivebaseSubsystem sub, 50 | Function t, 51 | T mux 52 | ) { 53 | addRequirements(sub); 54 | subsystem = sub; 55 | trajectory = t.apply(mux); 56 | } 57 | 58 | @Override 59 | public void initialize() { 60 | subsystem.followTrajectorySequenceAsync(trajectory); 61 | } 62 | 63 | @Override 64 | public void execute() { 65 | subsystem.update(); 66 | } 67 | 68 | @Override 69 | public boolean isFinished() { 70 | return !subsystem.isBusy(); 71 | } 72 | 73 | @Override 74 | public void end(boolean cancel) { 75 | if (cancel) subsystem.stop(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/geometry/ConfigurableVector.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.geometry; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Vector2d; 4 | import java.util.function.Function; 5 | import java.util.function.UnaryOperator; 6 | 7 | @SuppressWarnings("unchecked") 8 | public class ConfigurableVector { 9 | 10 | public double x, y; 11 | 12 | public ConfigurableVector(Vector2d pose) { 13 | x = pose.getX(); 14 | y = pose.getY(); 15 | } 16 | 17 | public ConfigurableVector(double x, double y) { 18 | this(new Vector2d(x, y)); 19 | } 20 | 21 | public ConfigurableVector() { 22 | this(new Vector2d()); 23 | } 24 | 25 | public ConfigurableVector set(double newX, double newY) { 26 | return set(new Vector2d(newX, newY)); 27 | } 28 | 29 | public ConfigurableVector set(Vector2d vec) { 30 | x = vec.getX(); 31 | y = vec.getY(); 32 | return this; 33 | } 34 | 35 | public ConfigurableVector setX(double val) { 36 | x = val; 37 | return this; 38 | } 39 | 40 | public ConfigurableVector setY(double val) { 41 | y = val; 42 | return this; 43 | } 44 | 45 | public ConfigurableVector mutateVec(UnaryOperator callback) { 46 | return set(mapVec(callback)); 47 | } 48 | 49 | public ConfigurableVector mutateX(UnaryOperator callback) { 50 | return setX(mapX(callback)); 51 | } 52 | 53 | public ConfigurableVector mutateY(UnaryOperator callback) { 54 | return setY(mapY(callback)); 55 | } 56 | 57 | public T mapVec(Function callback) { 58 | return callback.apply(toVec()); 59 | } 60 | 61 | public T mapX(Function callback) { 62 | return callback.apply(getX()); 63 | } 64 | 65 | public T mapY(Function callback) { 66 | return callback.apply(getY()); 67 | } 68 | 69 | public Vector2d toVec() { 70 | return new Vector2d(getX(), getY()); 71 | } 72 | 73 | public double getX() { 74 | return x; 75 | } 76 | 77 | public double getY() { 78 | return y; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/subsystem/DeadWheelConstants.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.subsystem; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | import java.lang.reflect.Field; 9 | 10 | @SuppressWarnings("unused") 11 | @FunctionalInterface 12 | public interface DeadWheelConstants { 13 | Class getConstant(); 14 | 15 | default double getDouble(Class a) { 16 | for (Field f : getConstant().getFields()) { 17 | try { 18 | if (f.isAnnotationPresent(a)) { 19 | System.out.println(a.toString() + " as " + f.getDouble(null)); 20 | return f.getDouble(null); 21 | } 22 | } catch (IllegalAccessException e) { 23 | System.err.println(f.getType() + " is inaccessible for some reason"); 24 | } 25 | } 26 | return 0; 27 | } 28 | 29 | default boolean getBoolean(Class a) { 30 | for (Field f : getConstant().getFields()) { 31 | try { 32 | if (f.isAnnotationPresent(a)) { 33 | System.out.println(a.toString() + " as " + f.getBoolean(null)); 34 | return f.getBoolean(null); 35 | } 36 | } catch (IllegalAccessException e) { 37 | System.err.println(f.getType() + " is inaccessible for some reason"); 38 | } 39 | } 40 | return false; 41 | } 42 | 43 | @Retention(RetentionPolicy.RUNTIME) 44 | @Target(ElementType.FIELD) 45 | @interface LateralDistance { 46 | } 47 | 48 | @Retention(RetentionPolicy.RUNTIME) 49 | @Target(ElementType.FIELD) 50 | @interface ForwardOffset { 51 | } 52 | 53 | @Retention(RetentionPolicy.RUNTIME) 54 | @Target(ElementType.FIELD) 55 | @interface EncoderOverflow { 56 | } 57 | 58 | @Retention(RetentionPolicy.RUNTIME) 59 | @Target(ElementType.FIELD) 60 | @interface GearRatio { 61 | } 62 | 63 | @Retention(RetentionPolicy.RUNTIME) 64 | @Target(ElementType.FIELD) 65 | @interface TicksPerRev { 66 | } 67 | 68 | @Retention(RetentionPolicy.RUNTIME) 69 | @Target(ElementType.FIELD) 70 | @interface WheelRadius { 71 | } 72 | 73 | static double encoderTicksToInches(double ticks, double rad, double rat, double rev) { 74 | return (rad * 2 * Math.PI * rat * ticks) / rev; 75 | } 76 | 77 | static double rpmToVelocity(double rpm, double rad, double rat) { 78 | return (rpm * rat * 2 * Math.PI * rad) / 60.0; 79 | } 80 | 81 | static double getMotorVelocityF(double ticksPerSecond) { 82 | return 32767 / ticksPerSecond; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/subsystem/ThreeDeadWheelLocalizer.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.subsystem; 2 | 3 | import static com.technototes.path.subsystem.DeadWheelConstants.*; 4 | 5 | import androidx.annotation.NonNull; 6 | import com.acmerobotics.roadrunner.geometry.Pose2d; 7 | import com.acmerobotics.roadrunner.localization.ThreeTrackingWheelLocalizer; 8 | import com.technototes.library.hardware.sensor.encoder.MotorEncoder; 9 | import com.technototes.library.subsystem.Subsystem; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | /* 14 | * Sample tracking wheel localizer implementation assuming the standard configuration: 15 | * 16 | * /--------------\ 17 | * | ____ | 18 | * | ---- | 19 | * | || || | 20 | * | || || | 21 | * | | 22 | * | | 23 | * \--------------/ 24 | * 25 | */ 26 | public class ThreeDeadWheelLocalizer extends ThreeTrackingWheelLocalizer implements Subsystem { 27 | 28 | protected MotorEncoder leftEncoder, rightEncoder, frontEncoder; 29 | protected double lateralDistance, forwardOffset, gearRatio, wheelRadius, ticksPerRev; 30 | 31 | protected boolean encoderOverflow; 32 | 33 | public ThreeDeadWheelLocalizer(MotorEncoder l, MotorEncoder r, MotorEncoder f, DeadWheelConstants constants) { 34 | super( 35 | Arrays.asList( 36 | new Pose2d(0, constants.getDouble(LateralDistance.class) / 2, 0), // left 37 | new Pose2d(0, -constants.getDouble(LateralDistance.class) / 2, 0), // right 38 | new Pose2d(constants.getDouble(ForwardOffset.class), 0, Math.toRadians(90)) // front 39 | ) 40 | ); 41 | leftEncoder = l; 42 | rightEncoder = r; 43 | frontEncoder = f; 44 | 45 | lateralDistance = constants.getDouble(LateralDistance.class); 46 | forwardOffset = constants.getDouble(ForwardOffset.class); 47 | encoderOverflow = constants.getBoolean(EncoderOverflow.class); 48 | gearRatio = constants.getDouble(GearRatio.class); 49 | ticksPerRev = constants.getDouble(TicksPerRev.class); 50 | wheelRadius = constants.getDouble(WheelRadius.class); 51 | } 52 | 53 | public double encoderTicksToInches(double ticks) { 54 | return ((getWheelRadius() * 2 * Math.PI * getGearRatio() * ticks) / getTicksPerRev()); 55 | } 56 | 57 | @NonNull 58 | @Override 59 | public List getWheelPositions() { 60 | return Arrays.asList( 61 | encoderTicksToInches(leftEncoder.getCurrentPosition()), 62 | encoderTicksToInches(rightEncoder.getCurrentPosition()), 63 | encoderTicksToInches(frontEncoder.getCurrentPosition()) 64 | ); 65 | } 66 | 67 | @NonNull 68 | @Override 69 | public List getWheelVelocities() { 70 | // TODO: If your encoder velocity can exceed 32767 counts / second (such as the REV Through Bore and other 71 | // competing magnetic encoders), change Encoder.getRawVelocity() to Encoder.getCorrectedVelocity() to enable a 72 | // compensation method 73 | 74 | return Arrays.asList( 75 | encoderTicksToInches(leftEncoder.getCorrectedVelocity()), 76 | encoderTicksToInches(rightEncoder.getCorrectedVelocity()), 77 | encoderTicksToInches(frontEncoder.getCorrectedVelocity()) 78 | ); 79 | } 80 | 81 | public double getTicksPerRev() { 82 | return ticksPerRev; 83 | } 84 | 85 | public double getWheelRadius() { 86 | return wheelRadius; 87 | } 88 | 89 | public double getGearRatio() { 90 | return gearRatio; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/EmptySequenceException.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence; 2 | 3 | public class EmptySequenceException extends RuntimeException {} 4 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/TrajectorySequence.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.technototes.path.trajectorysequence.sequencesegment.SequenceSegment; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class TrajectorySequence { 9 | 10 | private final List sequenceList; 11 | 12 | public TrajectorySequence(List sequenceList) { 13 | if (sequenceList.size() == 0) throw new EmptySequenceException(); 14 | 15 | this.sequenceList = Collections.unmodifiableList(sequenceList); 16 | } 17 | 18 | public Pose2d start() { 19 | return sequenceList.get(0).getStartPose(); 20 | } 21 | 22 | public Pose2d end() { 23 | return sequenceList.get(sequenceList.size() - 1).getEndPose(); 24 | } 25 | 26 | public double duration() { 27 | double total = 0.0; 28 | 29 | for (SequenceSegment segment : sequenceList) { 30 | total += segment.getDuration(); 31 | } 32 | 33 | return total; 34 | } 35 | 36 | public SequenceSegment get(int i) { 37 | return sequenceList.get(i); 38 | } 39 | 40 | public int size() { 41 | return sequenceList.size(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/sequencesegment/SequenceSegment.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence.sequencesegment; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.acmerobotics.roadrunner.trajectory.TrajectoryMarker; 5 | import java.util.List; 6 | 7 | public abstract class SequenceSegment { 8 | 9 | private final double duration; 10 | private final Pose2d startPose; 11 | private final Pose2d endPose; 12 | private final List markers; 13 | 14 | protected SequenceSegment(double duration, Pose2d startPose, Pose2d endPose, List markers) { 15 | this.duration = duration; 16 | this.startPose = startPose; 17 | this.endPose = endPose; 18 | this.markers = markers; 19 | } 20 | 21 | public double getDuration() { 22 | return this.duration; 23 | } 24 | 25 | public Pose2d getStartPose() { 26 | return startPose; 27 | } 28 | 29 | public Pose2d getEndPose() { 30 | return endPose; 31 | } 32 | 33 | public List getMarkers() { 34 | return markers; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/sequencesegment/TrajectorySegment.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence.sequencesegment; 2 | 3 | import com.acmerobotics.roadrunner.trajectory.Trajectory; 4 | import java.util.Collections; 5 | 6 | public final class TrajectorySegment extends SequenceSegment { 7 | 8 | private final Trajectory trajectory; 9 | 10 | public TrajectorySegment(Trajectory trajectory) { 11 | // Note: Markers are already stored in the `Trajectory` itself. 12 | // This class should not hold any markers 13 | super(trajectory.duration(), trajectory.start(), trajectory.end(), Collections.emptyList()); 14 | this.trajectory = trajectory; 15 | } 16 | 17 | public Trajectory getTrajectory() { 18 | return this.trajectory; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/sequencesegment/TurnSegment.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence.sequencesegment; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.acmerobotics.roadrunner.profile.MotionProfile; 5 | import com.acmerobotics.roadrunner.trajectory.TrajectoryMarker; 6 | import com.acmerobotics.roadrunner.util.Angle; 7 | import java.util.List; 8 | 9 | public final class TurnSegment extends SequenceSegment { 10 | 11 | private final double totalRotation; 12 | private final MotionProfile motionProfile; 13 | 14 | public TurnSegment( 15 | Pose2d startPose, 16 | double totalRotation, 17 | MotionProfile motionProfile, 18 | List markers 19 | ) { 20 | super( 21 | motionProfile.duration(), 22 | startPose, 23 | new Pose2d(startPose.getX(), startPose.getY(), Angle.norm(startPose.getHeading() + totalRotation)), 24 | markers 25 | ); 26 | this.totalRotation = totalRotation; 27 | this.motionProfile = motionProfile; 28 | } 29 | 30 | public final double getTotalRotation() { 31 | return this.totalRotation; 32 | } 33 | 34 | public final MotionProfile getMotionProfile() { 35 | return this.motionProfile; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/trajectorysequence/sequencesegment/WaitSegment.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.trajectorysequence.sequencesegment; 2 | 3 | import com.acmerobotics.roadrunner.geometry.Pose2d; 4 | import com.acmerobotics.roadrunner.trajectory.TrajectoryMarker; 5 | import java.util.List; 6 | 7 | public final class WaitSegment extends SequenceSegment { 8 | 9 | public WaitSegment(Pose2d pose, double seconds, List markers) { 10 | super(seconds, pose, pose, markers); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/util/AxesSigns.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.util; 2 | 3 | /** 4 | * IMU axes signs in the order XYZ (after remapping). 5 | */ 6 | public enum AxesSigns { 7 | PPP(0b000), 8 | PPN(0b001), 9 | PNP(0b010), 10 | PNN(0b011), 11 | NPP(0b100), 12 | NPN(0b101), 13 | NNP(0b110), 14 | NNN(0b111); 15 | 16 | public final int bVal; 17 | 18 | AxesSigns(int bVal) { 19 | this.bVal = bVal; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/util/BNO055IMUUtil.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.util; 2 | 3 | import com.qualcomm.hardware.bosch.BNO055IMU; 4 | import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; 5 | 6 | /** 7 | * Various utility functions for the BNO055 IMU. 8 | */ 9 | public class BNO055IMUUtil { 10 | 11 | /** 12 | * Remap BNO055 IMU axes and signs. For reference, the default order is {@link AxesOrder#ZYX}. 13 | * Call after {@link BNO055IMU#initialize(BNO055IMU.Parameters)}. Although this isn't 14 | * mentioned in the datasheet, the axes order appears to affect the onboard sensor fusion. 15 | * 16 | * Adapted from this post. 17 | * 18 | * @param imu IMU 19 | * @param order axes order 20 | * @param signs axes signs 21 | */ 22 | public static void remapAxes(BNO055IMU imu, AxesOrder order, AxesSigns signs) { 23 | try { 24 | // the indices correspond with the 2-bit encodings specified in the datasheet 25 | int[] indices = order.indices(); 26 | int axisMapConfig = 0; 27 | axisMapConfig |= (indices[0] << 4); 28 | axisMapConfig |= (indices[1] << 2); 29 | axisMapConfig |= (indices[2] << 0); 30 | 31 | // the BNO055 driver flips the first orientation vector so we also flip here 32 | int axisMapSign = signs.bVal ^ (0b100 >> indices[0]); 33 | 34 | // Enter CONFIG mode 35 | imu.write8(BNO055IMU.Register.OPR_MODE, BNO055IMU.SensorMode.CONFIG.bVal & 0x0F); 36 | 37 | Thread.sleep(100); 38 | 39 | // Write the AXIS_MAP_CONFIG register 40 | imu.write8(BNO055IMU.Register.AXIS_MAP_CONFIG, axisMapConfig & 0x3F); 41 | 42 | // Write the AXIS_MAP_SIGN register 43 | imu.write8(BNO055IMU.Register.AXIS_MAP_SIGN, axisMapSign & 0x07); 44 | 45 | // Switch back to the previous mode 46 | imu.write8(BNO055IMU.Register.OPR_MODE, imu.getParameters().mode.bVal & 0x0F); 47 | 48 | Thread.sleep(100); 49 | } catch (InterruptedException e) { 50 | Thread.currentThread().interrupt(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/util/DashboardUtil.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.util; 2 | 3 | import com.acmerobotics.dashboard.canvas.Canvas; 4 | import com.acmerobotics.roadrunner.geometry.Pose2d; 5 | import com.acmerobotics.roadrunner.geometry.Vector2d; 6 | import com.acmerobotics.roadrunner.path.Path; 7 | import java.util.List; 8 | 9 | /** 10 | * Set of helper functions for drawing Road Runner paths and trajectories on dashboard canvases. 11 | */ 12 | public class DashboardUtil { 13 | 14 | private static final double DEFAULT_RESOLUTION = 2.0; // distance units; presumed inches 15 | private static final double ROBOT_RADIUS = 9; // in 16 | 17 | public static void drawPoseHistory(Canvas canvas, List poseHistory) { 18 | double[] xPoints = new double[poseHistory.size()]; 19 | double[] yPoints = new double[poseHistory.size()]; 20 | for (int i = 0; i < poseHistory.size(); i++) { 21 | Pose2d pose = poseHistory.get(i); 22 | xPoints[i] = pose.getX(); 23 | yPoints[i] = pose.getY(); 24 | } 25 | canvas.strokePolyline(xPoints, yPoints); 26 | } 27 | 28 | public static void drawSampledPath(Canvas canvas, Path path, double resolution) { 29 | int samples = (int) Math.ceil(path.length() / resolution); 30 | double[] xPoints = new double[samples]; 31 | double[] yPoints = new double[samples]; 32 | double dx = path.length() / (samples - 1); 33 | for (int i = 0; i < samples; i++) { 34 | double displacement = i * dx; 35 | Pose2d pose = path.get(displacement); 36 | xPoints[i] = pose.getX(); 37 | yPoints[i] = pose.getY(); 38 | } 39 | canvas.strokePolyline(xPoints, yPoints); 40 | } 41 | 42 | public static void drawSampledPath(Canvas canvas, Path path) { 43 | drawSampledPath(canvas, path, DEFAULT_RESOLUTION); 44 | } 45 | 46 | public static void drawRobot(Canvas canvas, Pose2d pose) { 47 | canvas.strokeCircle(pose.getX(), pose.getY(), ROBOT_RADIUS); 48 | Vector2d v = pose.headingVec().times(ROBOT_RADIUS); 49 | double x1 = pose.getX() + v.getX() / 2, y1 = pose.getY() + v.getY() / 2; 50 | double x2 = pose.getX() + v.getX(), y2 = pose.getY() + v.getY(); 51 | canvas.strokeLine(x1, y1, x2, y2); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Path/src/main/java/com/technototes/path/util/LoggingUtil.java: -------------------------------------------------------------------------------- 1 | package com.technototes.path.util; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import org.firstinspires.ftc.robotcore.internal.system.AppUtil; 8 | 9 | /** 10 | * Utility functions for log files. 11 | */ 12 | public class LoggingUtil { 13 | 14 | public static final File ROAD_RUNNER_FOLDER = new File(AppUtil.ROOT_FOLDER + "/RoadRunner/"); 15 | 16 | private static final long LOG_QUOTA = 25 * 1024 * 1024; // 25MB log quota for now 17 | 18 | private static void buildLogList(List logFiles, File dir) { 19 | for (File file : dir.listFiles()) { 20 | if (file.isDirectory()) { 21 | buildLogList(logFiles, file); 22 | } else { 23 | logFiles.add(file); 24 | } 25 | } 26 | } 27 | 28 | private static void pruneLogsIfNecessary() { 29 | List logFiles = new ArrayList<>(); 30 | buildLogList(logFiles, ROAD_RUNNER_FOLDER); 31 | Collections.sort(logFiles, (lhs, rhs) -> Long.compare(lhs.lastModified(), rhs.lastModified())); 32 | 33 | long dirSize = 0; 34 | for (File file : logFiles) { 35 | dirSize += file.length(); 36 | } 37 | 38 | while (dirSize > LOG_QUOTA) { 39 | if (logFiles.size() == 0) break; 40 | File fileToRemove = logFiles.remove(0); 41 | dirSize -= fileToRemove.length(); 42 | //noinspection ResultOfMethodCallIgnored 43 | fileToRemove.delete(); 44 | } 45 | } 46 | 47 | /** 48 | * Obtain a log file with the provided name 49 | */ 50 | public static File getLogFile(String name) { 51 | //noinspection ResultOfMethodCallIgnored 52 | ROAD_RUNNER_FOLDER.mkdirs(); 53 | 54 | pruneLogsIfNecessary(); 55 | 56 | return new File(ROAD_RUNNER_FOLDER, name); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Path/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /RobotLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /RobotLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | namespace = 'com.technototes.library' 5 | 6 | lint { 7 | disable 'ExpiredTargetSdkVersion' 8 | } 9 | 10 | defaultConfig { 11 | minSdkVersion 24 12 | targetSdkVersion 28 13 | } 14 | 15 | compileSdkVersion 29 16 | 17 | compileOptions { 18 | sourceCompatibility JavaVersion.VERSION_1_8 19 | targetCompatibility JavaVersion.VERSION_1_8 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation('org.ejml:ejml-simple:0.39') { 26 | exclude group: 'org.ejml', module: 'ejml-all' 27 | } 28 | 29 | testImplementation(platform('org.junit:junit-bom:5.7.0')) 30 | testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.0') 31 | testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0' 32 | testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.0') 33 | testImplementation('org.mockito:mockito-core:3.5.11') 34 | testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.0" 35 | } 36 | 37 | tasks.withType(Test) { 38 | useJUnitPlatform() 39 | } 40 | 41 | repositories { 42 | maven { url 'https://jitpack.io' } 43 | mavenCentral() 44 | } 45 | 46 | task javadoc(type: Javadoc) { 47 | source = android.sourceSets.main.java.srcDirs 48 | classpath = project.files(android.getBootClasspath().join(File.pathSeparator)) 49 | failOnError false 50 | destinationDir = file("../docs/TechnoLib/") 51 | options { 52 | linkSource true 53 | encoding = 'utf-8' 54 | } 55 | } 56 | 57 | afterEvaluate { 58 | javadoc.classpath += files(android.libraryVariants.collect { variant -> 59 | variant.javaCompileProvider.get().classpath.files 60 | }) 61 | } 62 | 63 | apply from: '../build.dependencies.gradle' 64 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/RobotLibrary.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library; 2 | 3 | /** Root class for the Robot Library (I will put important stuff here) 4 | * @author Alex Stedman 5 | * 6 | */ 7 | @SuppressWarnings("unused") 8 | public class RobotLibrary { 9 | 10 | /** Get library version 11 | * 12 | * @return Library version 13 | */ 14 | public static String getVersion() { 15 | return "2.0.1"; 16 | } 17 | 18 | /** Get if the library is a pre release 19 | * 20 | * @return If this library version is a pre release 21 | */ 22 | public static boolean isPreRelease() { 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/ChoiceCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import android.util.Pair; 4 | import java.util.Arrays; 5 | import java.util.function.BooleanSupplier; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * A command that allows choosing among a number of commands based on variety of conditions 10 | */ 11 | @SuppressWarnings("unused") 12 | public class ChoiceCommand extends ParallelRaceGroup { 13 | 14 | /** 15 | * Each pair represents a condition to check, and the command to execute if that condition is 16 | * true 17 | * 18 | * @param cs The pair of BooleanSupplier (function that returns true/false) and Command to 19 | * execute if the function is true 20 | */ 21 | @SafeVarargs 22 | public ChoiceCommand(Pair... cs) { 23 | super( 24 | Arrays.stream(cs) 25 | .map(p -> new ConditionalCommand(p.first, p.second)) 26 | .collect(Collectors.toList()) 27 | .toArray(new Command[] {}) 28 | ); 29 | } 30 | 31 | /** 32 | * This is a simplistic ChoiceCommand that is simply a single conditional command 33 | * I *think* this will wwait until b is true 34 | * 35 | * @param b The function to invoke to determine if the command should be run 36 | * @param c The command to be run 37 | */ 38 | public ChoiceCommand(BooleanSupplier b, Command c) { 39 | this(new Pair<>(b, c)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/CommandGroup.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Root class for all command groups (Sequential, Parallel, etc...) 8 | * WARNING: You probably will be better served by the specific CommandGroup subclasses, rather than 9 | * using this one directly. 10 | * 11 | * @author Alex Stedman 12 | */ 13 | public abstract class CommandGroup implements Command { 14 | 15 | /** 16 | * This is a map from the command to whether it has been run 17 | */ 18 | protected Map commandMap; 19 | /** 20 | * Should a cancelled command be considered 'finished' 21 | */ 22 | protected boolean countCancel; 23 | /** 24 | * Have *any* of the command list been cancelled 25 | */ 26 | protected boolean anyCancelled; 27 | 28 | /** 29 | * Create a command group with commands 30 | * 31 | * @param countCancel true if a cancelled command is considered 'finished' 32 | * @param commands Commands for group 33 | */ 34 | public CommandGroup(boolean countCancel, Command... commands) { 35 | commandMap = new HashMap<>(); 36 | addCommands(commands); 37 | this.countCancel = countCancel; 38 | } 39 | 40 | /** 41 | * Add a command to the group 42 | * 43 | * @param commands The command 44 | * @return this 45 | */ 46 | public CommandGroup addCommands(Command... commands) { 47 | for (Command c : commands) { 48 | schedule(c); 49 | commandMap.put(c, false); 50 | } 51 | return this; 52 | } 53 | 54 | /** 55 | * Specify that this CommandGroup should count a cancellation as 'completed' 56 | * 57 | * @return this CommandGroup 58 | */ 59 | public CommandGroup countCancel() { 60 | countCancel = true; 61 | return this; 62 | } 63 | 64 | /** 65 | * Specify that this CommandGroup should NOT count cancellation as 'completed' 66 | * 67 | * @return this CommandGroup 68 | */ 69 | public CommandGroup ignoreCancel() { 70 | countCancel = false; 71 | return this; 72 | } 73 | 74 | /** 75 | * This should schedule the command as part of this command group, I think. 76 | * TODO: Is this correct? 77 | * 78 | * @param c The command to add to the command group 79 | */ 80 | public abstract void schedule(Command c); 81 | 82 | /** 83 | * Mark all commands in the group as not yet run 84 | */ 85 | @Override 86 | public void initialize() { 87 | commandMap.replaceAll((command, bool) -> false); 88 | anyCancelled = false; 89 | } 90 | 91 | @Override 92 | public void execute() { 93 | // makes true if command just finished 94 | commandMap.replaceAll( 95 | (command, bool) -> (countCancel ? command.justFinished() : command.justFinishedNoCancel()) || bool 96 | ); 97 | anyCancelled = commandMap.keySet().stream().anyMatch(Command::isCancelled) || anyCancelled; 98 | } 99 | 100 | /** 101 | * MUST IMPLEMENT IN SUBCLASSES: 102 | * 103 | * @return True if this CommandGroup is finished 104 | */ 105 | @Override 106 | public abstract boolean isFinished(); 107 | 108 | /** 109 | * This stops the command group from executing 110 | * 111 | * @param cancel True if the command was cancelled, False if it ended naturally 112 | */ 113 | @Override 114 | public void end(boolean cancel) { 115 | commandMap.keySet().forEach(Command::cancel); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/ConditionalCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import androidx.annotation.Nullable; 4 | import java.util.function.BooleanSupplier; 5 | 6 | /** 7 | * Simple class for commands that require a certain condition to be true to run 8 | *

9 | * This encapsulates *two* different capabilities. 10 | * 1. A ConditionalCommand with only a condition, but no commands, is a a "wait" command. 11 | * It will only finish once the condition is true. 12 | * 2. A ConditionalCommand with a condition and a true (and optionally false) command 13 | * is a generic "if/else" command: If the condition is true, execute the 'true command', 14 | * if not true, execute the 'false command' if it is supplied. 15 | *

16 | * TODO: This makes the class a little clunky. It wouldn't be terrible to break the functionality 17 | * TODO: out into multiple classes instead 18 | * 19 | * @author Alex Stedman 20 | */ 21 | public class ConditionalCommand implements Command { 22 | 23 | private BooleanSupplier supplier; 24 | 25 | @Nullable 26 | private Command trueCommand, falseCommand; 27 | 28 | /** 29 | * This makes a "wait" command 30 | * 31 | * @param condition The BooleanSupplier that will be waited upon until true 32 | */ 33 | public ConditionalCommand(BooleanSupplier condition) { 34 | supplier = condition; 35 | trueCommand = null; 36 | falseCommand = null; 37 | } 38 | 39 | /** 40 | * Make a conditional command 41 | * 42 | * @param condition The condition 43 | * @param command The command to run when the condition is true. 44 | */ 45 | public ConditionalCommand(BooleanSupplier condition, Command command) { 46 | supplier = condition; 47 | trueCommand = command; 48 | CommandScheduler.scheduleWithOther(this, trueCommand, condition); 49 | falseCommand = null; 50 | } 51 | 52 | /** 53 | * Make a conditional command 54 | * 55 | * @param condition The condition 56 | * @param trueC The command to run when the condition is true 57 | * @param falseC The command to run when the condition is false 58 | */ 59 | public ConditionalCommand(BooleanSupplier condition, Command trueC, Command falseC) { 60 | supplier = condition; 61 | trueCommand = trueC; 62 | falseCommand = falseC; 63 | CommandScheduler.scheduleWithOther(this, trueCommand, condition); 64 | CommandScheduler.scheduleWithOther(this, falseCommand, () -> !condition.getAsBoolean()); 65 | } 66 | 67 | @Override 68 | public void execute() {} 69 | 70 | @Override 71 | public boolean isFinished() { 72 | if (trueCommand == null) return supplier.getAsBoolean(); 73 | if (falseCommand == null) return trueCommand.justFinished(); 74 | return trueCommand.justFinished() || falseCommand.justFinished(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/IterativeCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import java.util.function.BooleanSupplier; 4 | import java.util.function.Function; 5 | 6 | public class IterativeCommand extends SequentialCommandGroup { 7 | 8 | /** 9 | * iterative command for anything 10 | *

11 | * TODO: Figure out what this is good for. It looks weirdly specific. I wonder what Alex was 12 | * doing with it 13 | * 14 | * @param func 15 | * @param start 16 | * @param end 17 | * @param accum 18 | * @param 19 | */ 20 | public IterativeCommand(Function func, T start, T end, Function accum) { 21 | for (T t = start; !t.equals(end); t = accum.apply(t)) addCommands(func.apply(t)); 22 | } 23 | 24 | public IterativeCommand( 25 | Function func, 26 | T start, 27 | T end, 28 | Function accum, 29 | BooleanSupplier stopCondition 30 | ) { 31 | for (T t = start; !t.equals(end); t = accum.apply(t)) addCommands(func.apply(t)); 32 | } 33 | 34 | /** 35 | * iterative command for an int 36 | * 37 | * @param func 38 | * @param loops 39 | */ 40 | public IterativeCommand(Function func, int loops) { 41 | this(func, 0, loops, i -> i + 1); 42 | } 43 | 44 | public IterativeCommand(Function func, int loops, BooleanSupplier stopCondition) { 45 | this(func, 0, loops, i -> i + 1, stopCondition); 46 | } 47 | 48 | // TODO make limitless but 10 will make sure i dont yeet to much 49 | public IterativeCommand(Function func, BooleanSupplier stopCondition) { 50 | this(func, 0, 10, i -> i + 1, stopCondition); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/ParallelCommandGroup.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | /** 4 | * Command group to run commands in parallel until all of them finish 5 | * 6 | * @author Alex Stedman 7 | */ 8 | public class ParallelCommandGroup extends CommandGroup { 9 | 10 | /** 11 | * Make parallel command group 12 | * 13 | * @param commands The commands for the group 14 | */ 15 | public ParallelCommandGroup(Command... commands) { 16 | super(true, commands); 17 | } 18 | 19 | @Override 20 | public void schedule(Command c) { 21 | CommandScheduler.scheduleWithOther(this, c); 22 | } 23 | 24 | /** 25 | * @return True if *all* of the commands are finished 26 | */ 27 | @Override 28 | public boolean isFinished() { 29 | // if there is no unfinished commands its done 30 | return !commandMap.containsValue(false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/ParallelDeadlineGroup.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | /** 4 | * Command group to run commands in parallel until one particular command completes 5 | * 6 | * @author Alex Stedman 7 | */ 8 | public class ParallelDeadlineGroup extends CommandGroup { 9 | 10 | private Command deadline; 11 | 12 | /** 13 | * Make parallel deadline group 14 | * 15 | * @param command the deadline condition (Once this is complete, the rest are cancelled) 16 | * @param commands The other commands for the group 17 | */ 18 | public ParallelDeadlineGroup(Command command, Command... commands) { 19 | super(true, commands); 20 | addCommands(command); 21 | deadline = command; 22 | } 23 | 24 | /** 25 | * Add another command to the group to be run while waiting for the 'deadline' command to finish 26 | * 27 | * @param c The command to add to the command group 28 | */ 29 | @Override 30 | public void schedule(Command c) { 31 | CommandScheduler.scheduleWithOther(this, c); 32 | } 33 | 34 | /** 35 | * @return True if the 'deadline' command has finished 36 | */ 37 | @Override 38 | public boolean isFinished() { 39 | return deadline.justFinished(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/ParallelRaceGroup.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | /** 4 | * Command group to run commands in parallel until *one* is finished 5 | * 6 | * @author Alex Stedman 7 | */ 8 | public class ParallelRaceGroup extends CommandGroup { 9 | 10 | /** 11 | * Make parallel race group 12 | * 13 | * @param commands The commands for the group 14 | */ 15 | public ParallelRaceGroup(Command... commands) { 16 | super(true, commands); 17 | } 18 | 19 | /** 20 | * Add one more command to the list of commands that will be run at the same time 21 | * 22 | * @param c The command to add to the group 23 | */ 24 | @Override 25 | public void schedule(Command c) { 26 | CommandScheduler.scheduleWithOther(this, c); 27 | } 28 | 29 | /** 30 | * Is this finished? 31 | * 32 | * @return True if *any* of the commands are finished, false if *none* have finished. 33 | */ 34 | @Override 35 | public boolean isFinished() { 36 | // if there is a single finished command 37 | return commandMap.containsValue(true); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/SequentialCommandGroup.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | /** 4 | * A grouping command which runs a list of commands in sequence 5 | * 6 | * @author Alex Stedman 7 | */ 8 | public class SequentialCommandGroup extends CommandGroup { 9 | 10 | protected Command lastCommand; 11 | 12 | /** 13 | * Make sequential command group. By default if a command is cancelled, the next commend in 14 | * the sequence is run. 15 | * 16 | * @param commands The commands to run 17 | */ 18 | public SequentialCommandGroup(Command... commands) { 19 | super(true, commands); 20 | } 21 | 22 | /** 23 | * This allows you to append another command to the Sequential Command Group 24 | * 25 | * @param c The command to add to the end of the list 26 | */ 27 | @Override 28 | public void schedule(Command c) { 29 | if (lastCommand == null) { 30 | CommandScheduler.scheduleWithOther(this, c); 31 | } else { 32 | CommandScheduler.scheduleAfterOther(lastCommand, c); 33 | } 34 | lastCommand = c; 35 | } 36 | 37 | /** 38 | * Returns if all the commands are finished 39 | * 40 | * @return Is the command group finished 41 | */ 42 | @Override 43 | public boolean isFinished() { 44 | return lastCommand.justFinished() || (anyCancelled && !countCancel); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/command/WaitCommand.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import java.util.function.DoubleSupplier; 4 | 5 | /** 6 | * A command to do nothing but wait for a span of time. 7 | * In an ideal world, you wouldn't need this. But the world is far from ideal... 8 | * 9 | * @author Alex Stedman 10 | */ 11 | public class WaitCommand implements Command { 12 | 13 | /** 14 | * @return the number of seconds the command will wait 15 | */ 16 | public double getSeconds() { 17 | return supplier.getAsDouble(); 18 | } 19 | 20 | private DoubleSupplier supplier; 21 | 22 | /** 23 | * Create a wait command for a fixed number of seconds 24 | * 25 | * @param sec The number of seconds (can be non-whole numbers!) 26 | */ 27 | public WaitCommand(double sec) { 28 | supplier = () -> sec; 29 | } 30 | 31 | /** 32 | * Create a wait command for a number of seconds that can be calculated when the commannd is 33 | * triggered 34 | * 35 | * @param sup The DoublerSupplier function which calculates the number of seconds to wait 36 | */ 37 | public WaitCommand(DoubleSupplier sup) { 38 | supplier = sup; 39 | } 40 | 41 | @Override 42 | public void execute() {} 43 | 44 | @Override 45 | public boolean isFinished() { 46 | return supplier.getAsDouble() <= getRuntime().seconds(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/AxisBase.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import com.technototes.library.general.Periodic; 4 | import java.util.function.DoubleSupplier; 5 | 6 | /** The class to extend custom gamepad axis from 7 | * @author Alex Stedman 8 | */ 9 | public class AxisBase extends ButtonBase implements DoubleSupplier, Periodic { 10 | 11 | /** The default trigger threshold 12 | * 13 | */ 14 | public static final double DEFAULT_TRIGGER_THRESHOLD = 0.05; 15 | 16 | private double triggerThreshold; 17 | protected DoubleSupplier doubleSupplier; 18 | 19 | /** Make a GamepadAxis with the supplier 20 | * 21 | * @param d The supplier to make the axis around 22 | */ 23 | public AxisBase(DoubleSupplier d) { 24 | this(d, DEFAULT_TRIGGER_THRESHOLD); 25 | } 26 | 27 | /** Make a GamepadAxis with the supplier and the threshold for the stick to behave as a button 28 | * 29 | * @param d The supplier to make the axis around 30 | * @param t The threshold 31 | */ 32 | public AxisBase(DoubleSupplier d, double t) { 33 | super(() -> Math.abs(d.getAsDouble()) >= t); 34 | doubleSupplier = d; 35 | triggerThreshold = t; 36 | } 37 | 38 | /** Returns the double from the axis 39 | * 40 | * @return The double 41 | */ 42 | @Override 43 | public double getAsDouble() { 44 | if (isDisabled()) return 0; 45 | return getInverted() ? -doubleSupplier.getAsDouble() : doubleSupplier.getAsDouble(); 46 | } 47 | 48 | /** Gets the trigger threshold 49 | * 50 | * @return The threshold 51 | */ 52 | public double getTriggerThreshold() { 53 | return triggerThreshold; 54 | } 55 | 56 | /** Set threshold 57 | * @param threshold the new threshold 58 | */ 59 | public AxisBase setTriggerThreshold(double threshold) { 60 | triggerThreshold = threshold; 61 | return this; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/Binding.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | /** Class for bindings to extend 6 | * @author Alex Stedman 7 | * 8 | */ 9 | public interface Binding extends BooleanSupplier { 10 | /** Button type 11 | * 12 | */ 13 | enum Type { 14 | NONE_ACTIVE, 15 | SOME_ACTIVE, 16 | ALL_ACTIVE, 17 | } 18 | 19 | T[] getSuppliers(); 20 | 21 | Type getDefaultType(); 22 | 23 | @Override 24 | default boolean getAsBoolean() { 25 | return get(getDefaultType()); 26 | } 27 | 28 | /** Get this as boolean for the type 29 | * 30 | * @param type The type to get boolean as 31 | * @return If the binding meets the criteria 32 | */ 33 | default boolean get(Type type) { 34 | boolean on = false, off = getSuppliers().length == 0; 35 | for (T s : getSuppliers()) { 36 | if (s.getAsBoolean()) { 37 | on = true; 38 | } else { 39 | off = true; 40 | } 41 | } 42 | switch (type) { 43 | case NONE_ACTIVE: 44 | return !on; 45 | case ALL_ACTIVE: 46 | return !off; 47 | default: 48 | return on; 49 | } 50 | } 51 | 52 | default boolean get() { 53 | return get(getDefaultType()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/CommandAxis.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import com.technototes.library.command.Command; 4 | import java.util.function.DoubleSupplier; 5 | import java.util.function.Function; 6 | 7 | /** 8 | * Class for command axis for the gamepad 9 | * 10 | * @author Alex Stedman 11 | */ 12 | public class CommandAxis extends AxisBase implements CommandInput { 13 | 14 | /** 15 | * Make a command axis 16 | * 17 | * @param supplier The axis supplier 18 | */ 19 | public CommandAxis(DoubleSupplier supplier) { 20 | super(supplier); 21 | } 22 | 23 | /** 24 | * Make a command axis 25 | * 26 | * @param supplier The axis supplier 27 | * @param threshold The threshold to trigger to make the axis behave as a button 28 | */ 29 | public CommandAxis(DoubleSupplier supplier, double threshold) { 30 | super(supplier, threshold); 31 | } 32 | 33 | @Override 34 | public CommandAxis getInstance() { 35 | return this; 36 | } 37 | 38 | @Override 39 | public CommandAxis setTriggerThreshold(double threshold) { 40 | super.setTriggerThreshold(threshold); 41 | return this; 42 | } 43 | 44 | public CommandAxis schedulePressed(Function f) { 45 | return whilePressed(f.apply(this)); 46 | } 47 | 48 | public CommandAxis schedule(Function f) { 49 | return schedule(f.apply(this.getAsDouble())); 50 | } 51 | 52 | @Override 53 | public CommandAxis setInverted(boolean invert) { 54 | return (CommandAxis) super.setInverted(invert); 55 | } 56 | 57 | public CommandButton getAsButton() { 58 | return new CommandButton(this); 59 | } 60 | 61 | public CommandButton getAsButton(double threshold) { 62 | return new CommandButton(() -> (threshold >= 0) ? (getAsDouble() >= threshold) : (getAsDouble() < threshold)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/CommandBinding.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | /** Command implementation of {@link Binding} 4 | * @author Alex Stedman 5 | */ 6 | public class CommandBinding extends CommandButton implements Binding { 7 | 8 | private CommandInput[] inputs; 9 | private Type defaultType; 10 | 11 | public CommandBinding(CommandInput... b) { 12 | this(Type.ALL_ACTIVE, b); 13 | } 14 | 15 | public CommandBinding(Type type, CommandInput... b) { 16 | super(null); 17 | inputs = b; 18 | defaultType = type; 19 | booleanSupplier = this::get; 20 | } 21 | 22 | @Override 23 | public CommandInput[] getSuppliers() { 24 | return inputs; 25 | } 26 | 27 | @Override 28 | public Type getDefaultType() { 29 | return defaultType; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/CommandButton.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import com.technototes.library.command.Command; 4 | import java.util.function.BooleanSupplier; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | 8 | /** Class for command buttons for gamepad 9 | * @author Alex Stedman 10 | */ 11 | public class CommandButton extends ButtonBase implements CommandInput { 12 | 13 | /** Make command button 14 | * 15 | * @param supplier The supplier for the button 16 | */ 17 | public CommandButton(BooleanSupplier supplier) { 18 | super(supplier); 19 | } 20 | 21 | @Override 22 | public CommandButton getInstance() { 23 | return this; 24 | } 25 | 26 | public CommandButton schedule(Function f) { 27 | return schedule(f.apply(this.getAsBoolean())); 28 | } 29 | 30 | public CommandButton schedule(Consumer f) { 31 | return schedule(() -> f.accept(this.getAsBoolean())); 32 | } 33 | 34 | @Override 35 | public CommandButton setInverted(boolean invert) { 36 | return (CommandButton) super.setInverted(invert); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/CommandGamepad.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import com.qualcomm.robotcore.hardware.Gamepad; 4 | import com.technototes.library.command.Command; 5 | import com.technototes.library.command.CommandScheduler; 6 | import java.util.function.BiConsumer; 7 | import java.util.function.BiFunction; 8 | 9 | /** Class for command gamepads that specifies class params 10 | * @author Alex Stedman 11 | */ 12 | public class CommandGamepad extends GamepadBase { 13 | 14 | /** Make command gamepad 15 | * 16 | * @param gamepad The normal gamepad 17 | */ 18 | public CommandGamepad(Gamepad gamepad) { 19 | super(gamepad, CommandButton.class, CommandAxis.class); 20 | } 21 | 22 | public CommandGamepad scheduleLeftStick(BiFunction f) { 23 | return scheduleStick(leftStick, f); 24 | } 25 | 26 | public CommandGamepad scheduleLeftStick(BiConsumer f) { 27 | return scheduleStick(leftStick, f); 28 | } 29 | 30 | public CommandGamepad scheduleRightStick(BiFunction f) { 31 | return scheduleStick(rightStick, f); 32 | } 33 | 34 | public CommandGamepad scheduleRightStick(BiConsumer f) { 35 | return scheduleStick(rightStick, f); 36 | } 37 | 38 | public CommandGamepad scheduleDpad(BiFunction f) { 39 | return scheduleStick(dpad, f); 40 | } 41 | 42 | public CommandGamepad scheduleDpad(BiConsumer f) { 43 | return scheduleStick(dpad, f); 44 | } 45 | 46 | public CommandGamepad scheduleStick(Stick s, BiFunction f) { 47 | CommandScheduler.scheduleJoystick(f.apply(s.getXAxis(), s.getXAxis())); 48 | return this; 49 | } 50 | 51 | public CommandGamepad scheduleStick(Stick s, BiConsumer f) { 52 | CommandScheduler.scheduleJoystick(() -> f.accept(s.getXAxis(), s.getXAxis())); 53 | return this; 54 | } 55 | 56 | @Override 57 | public CommandGamepad enable() { 58 | return (CommandGamepad) super.enable(); 59 | } 60 | 61 | @Override 62 | public CommandGamepad disable() { 63 | return (CommandGamepad) super.disable(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/GamepadDpad.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | /** A class for dpads 4 | * @author Alex Stedman 5 | * @param The gamepad button class 6 | */ 7 | public class GamepadDpad implements Stick { 8 | 9 | private boolean enabled = true; 10 | /** The objects for the dpad buttons 11 | * 12 | */ 13 | public T up, down, left, right; 14 | 15 | /** Create dpad with 4 buttons 16 | * 17 | * @param u Up button 18 | * @param d Down button 19 | * @param l Left button 20 | * @param r Right button 21 | */ 22 | public GamepadDpad(T u, T d, T l, T r) { 23 | up = u; 24 | down = d; 25 | left = l; 26 | right = r; 27 | } 28 | 29 | /** Return x axis double (treating dpad as stick) 30 | * 31 | * @return The double 32 | */ 33 | @Override 34 | public double getXAxis() { 35 | return (right.getAsBoolean() ? (left.getAsBoolean() ? 0 : 1) : (left.getAsBoolean() ? -1 : 0)); 36 | } 37 | 38 | /** Return y axis double (treating dpad as stick) 39 | * 40 | * @return The double 41 | */ 42 | @Override 43 | public double getYAxis() { 44 | return (up.getAsBoolean() ? (down.getAsBoolean() ? 0 : 1) : (down.getAsBoolean() ? -1 : 0)); 45 | } 46 | 47 | @Override 48 | public void periodic() { 49 | if (isDisabled()) return; 50 | up.periodic(); 51 | down.periodic(); 52 | left.periodic(); 53 | right.periodic(); 54 | } 55 | 56 | @Override 57 | public GamepadDpad setEnabled(boolean enable) { 58 | enabled = enable; 59 | up.setEnabled(enabled); 60 | down.setEnabled(enabled); 61 | left.setEnabled(enabled); 62 | right.setEnabled(enabled); 63 | return this; 64 | } 65 | 66 | @Override 67 | public boolean isEnabled() { 68 | return enabled; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/GamepadStick.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | /** A class for gamepad sticks 4 | * @author Alex Stedman 5 | * @param The class for the gamepad axis 6 | * @param The class for the gamepad buttons 7 | */ 8 | public class GamepadStick implements Stick { 9 | 10 | private boolean enabled = true; 11 | /** The objects for the stick axis 12 | * 13 | */ 14 | public T xAxis, yAxis; 15 | /** The objects for the stick button 16 | * 17 | */ 18 | public U stickButton; 19 | 20 | /** Make a gamepad stick 21 | * 22 | * @param x The x joystick axis 23 | * @param y The y joystick axis 24 | * @param b The joystick button 25 | */ 26 | public GamepadStick(T x, T y, U b) { 27 | xAxis = x; 28 | yAxis = y; 29 | stickButton = b; 30 | } 31 | 32 | @Override 33 | public void periodic() { 34 | if (isDisabled()) return; 35 | xAxis.periodic(); 36 | yAxis.periodic(); 37 | stickButton.periodic(); 38 | } 39 | 40 | @Override 41 | public double getXAxis() { 42 | return xAxis.getAsDouble(); 43 | } 44 | 45 | @Override 46 | public double getYAxis() { 47 | return yAxis.getAsDouble(); 48 | } 49 | 50 | @Override 51 | public GamepadStick setEnabled(boolean enable) { 52 | enabled = enable; 53 | xAxis.setEnabled(enabled); 54 | yAxis.setEnabled(enabled); 55 | stickButton.setEnabled(enabled); 56 | return this; 57 | } 58 | 59 | @Override 60 | public boolean isEnabled() { 61 | return enabled; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/control/Stick.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.control; 2 | 3 | import com.technototes.library.general.CanBeEnabled; 4 | import com.technototes.library.general.Periodic; 5 | import java.util.function.DoubleSupplier; 6 | 7 | /** Interface for objects that behave as sticks 8 | * @author Alex Stedman 9 | */ 10 | public interface Stick extends Periodic, CanBeEnabled { 11 | /** Return x axis double 12 | * 13 | * @return The double 14 | */ 15 | double getXAxis(); 16 | /** Return y axis double 17 | * 18 | * @return The double 19 | */ 20 | double getYAxis(); 21 | 22 | /** Return x axis supplier 23 | * 24 | * @return The double supplier 25 | */ 26 | default DoubleSupplier getXSupplier() { 27 | return this::getXAxis; 28 | } 29 | 30 | /** Return y axis supplier 31 | * 32 | * @return The double supplier 33 | */ 34 | default DoubleSupplier getYSupplier() { 35 | return this::getYAxis; 36 | } 37 | 38 | /** Returns the angle of the stick 39 | * 40 | * @return The angle 41 | */ 42 | default double getAngle() { 43 | return -Math.atan2(getYAxis(), getXAxis()); 44 | } 45 | 46 | /** Returns the stick's distance from the center 47 | * 48 | * @return The distance 49 | */ 50 | default double getDistanceFromCenter() { 51 | return Math.sqrt(getXAxis() * getXAxis() + getYAxis() * getYAxis()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/general/CanBeEnabled.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.general; 2 | 3 | /** 4 | * Interface for anything that can be enabled/disabled 5 | * 6 | *

7 | * You must have "setEnabled" and "isEnabled" functions. Everything else has 8 | * functional implementations in the interface 9 | * 10 | * @param An Enable-able interface/class type 11 | */ 12 | 13 | public interface CanBeEnabled> { 14 | /** 15 | * Enable the object 16 | * 17 | * @return The object 18 | */ 19 | default T enable() { 20 | return setEnabled(true); 21 | } 22 | 23 | /** 24 | * Disable the object 25 | * 26 | * @return the object 27 | */ 28 | default T disable() { 29 | return setEnabled(false); 30 | } 31 | 32 | /** 33 | * Set whether or not the device is enabled 34 | * 35 | * @param enable True for enabled, false for disabled 36 | * @return The object 37 | */ 38 | T setEnabled(boolean enable); 39 | 40 | /** 41 | * Toggle whether this object is enabled or not 42 | * 43 | * @return The object 44 | */ 45 | default T toggleEnabled() { 46 | return setEnabled(!isEnabled()); 47 | } 48 | 49 | /** 50 | * @return Is this object enabled? 51 | */ 52 | boolean isEnabled(); 53 | 54 | /** 55 | * @return Is this object disabled? 56 | */ 57 | default boolean isDisabled() { 58 | return !isEnabled(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/general/Invertible.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.general; 2 | 3 | /** 4 | * Interface for anything that can be inverted 5 | * 6 | * @author Alex Stedman 7 | */ 8 | @SuppressWarnings("unused") 9 | public interface Invertible> { 10 | /** 11 | * Set the inversion (true -> Is inverted, false -> Not inverted) 12 | * 13 | * @param invert Inversion value 14 | * @return this 15 | */ 16 | T setInverted(boolean invert); 17 | 18 | /** 19 | * Toggle inversion 20 | * 21 | * @return this 22 | */ 23 | default T invert() { 24 | return setInverted(!getInverted()); 25 | } 26 | 27 | /** 28 | * Get current inversion 29 | * 30 | * @return Current inversion 31 | */ 32 | boolean getInverted(); 33 | } 34 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/general/Periodic.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.general; 2 | 3 | /** An interface for classes to have the periodic function 4 | * @author Alex Stedman 5 | */ 6 | @FunctionalInterface 7 | public interface Periodic { 8 | /** The periodic function 9 | */ 10 | void periodic(); 11 | } 12 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/DummyDevice.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | import com.qualcomm.robotcore.hardware.HardwareDevice; 4 | 5 | /** 6 | * This isn't worth actually doing. You have to redo your configuration constantly if you create 7 | * a device that isn't part of the core runtime :( 8 | * 9 | * @param The type of the device 10 | */ 11 | public class DummyDevice implements HardwareDevice { 12 | 13 | private final T internal; 14 | 15 | public DummyDevice(T inter) { 16 | internal = inter; 17 | } 18 | 19 | @Override 20 | public Manufacturer getManufacturer() { 21 | return Manufacturer.Unknown; 22 | } 23 | 24 | @Override 25 | public String getDeviceName() { 26 | return internal.toString(); 27 | } 28 | 29 | @Override 30 | public String getConnectionInfo() { 31 | return "dummy device"; 32 | } 33 | 34 | @Override 35 | public int getVersion() { 36 | return 0; 37 | } 38 | 39 | @Override 40 | public void resetDeviceConfigurationForOpMode() {} 41 | 42 | @Override 43 | public void close() {} 44 | 45 | public T get() { 46 | return internal; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/FailedDevice.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | public class FailedDevice implements com.qualcomm.robotcore.hardware.HardwareDevice { 4 | 5 | protected String name; 6 | 7 | protected FailedDevice(String deviceName) { 8 | name = deviceName; 9 | } 10 | 11 | @Override 12 | public Manufacturer getManufacturer() { 13 | return Manufacturer.Other; 14 | } 15 | 16 | @Override 17 | public String getDeviceName() { 18 | return name; 19 | } 20 | 21 | @Override 22 | public String getConnectionInfo() { 23 | return "NC"; 24 | } 25 | 26 | @Override 27 | public int getVersion() { 28 | return 0; 29 | } 30 | 31 | @Override 32 | public void resetDeviceConfigurationForOpMode() {} 33 | 34 | @Override 35 | public void close() {} 36 | } 37 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/HardwareDevice.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | import android.util.Log; 4 | import com.qualcomm.robotcore.hardware.HardwareMap; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | /** 10 | * Class for hardware devices 11 | * This just adds an extra layer of indirection that doesn't feel like it's worth the hassle. 12 | * 13 | * @param The class for the default device (ones found in ftcsdk) 14 | * @author Alex Stedman 15 | */ 16 | @SuppressWarnings("unused") 17 | public abstract class HardwareDevice { 18 | 19 | /** 20 | * Hardware map object for stuff 21 | */ 22 | public static HardwareMap hardwareMap = null; 23 | protected static Map> names = new HashMap<>(); 24 | 25 | public static void initMap(HardwareMap h) { 26 | hardwareMap = h; 27 | } 28 | 29 | public static Set> devices = null; 30 | 31 | private T device; 32 | 33 | /** 34 | * The name of the hardware used for logging & hardware creation 35 | */ 36 | protected String name; 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | /** 43 | * Make a hardware device 44 | * 45 | * @param device The default device 46 | */ 47 | public HardwareDevice(T device, String deviceName) { 48 | this.device = device; 49 | name = deviceName; 50 | names.put(deviceName, this); 51 | } 52 | 53 | /** 54 | * Make a hardware device with the string to get from hardwaremap 55 | * 56 | * @param deviceName The device name 57 | */ 58 | @SuppressWarnings("unchecked cast") 59 | protected HardwareDevice(String deviceName) { 60 | device = hardwareMap.tryGet( 61 | (Class) com.qualcomm.robotcore.hardware.HardwareDevice.class/*T.class*/, 62 | deviceName 63 | ); 64 | name = deviceName; 65 | names.put(name, this); 66 | /* if (device == null) { 67 | Log.e("DEVICE FAILURE", deviceName); 68 | } */ 69 | } 70 | 71 | /** 72 | * Get encapsulated device 73 | * 74 | * @return The device 75 | */ 76 | protected T getRawDevice() { 77 | // TODO: Assert that we've got a device, yeah? 78 | return device; 79 | } 80 | 81 | protected boolean realHardware() { 82 | return device != null; 83 | } 84 | 85 | /** 86 | * Get the logging expression 87 | */ 88 | protected String logData(String info) { 89 | return String.format("%s: %s", name, info); 90 | } 91 | 92 | /** 93 | * This is used for logging stuff by name and/or device type 94 | * @return 95 | */ 96 | public abstract String LogLine(); 97 | } 98 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/Sensored.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | import java.util.function.DoubleSupplier; 4 | 5 | /** 6 | * Class for hardware devices with a sensor value 7 | *

8 | * This name is just bad. I'd also like to add normalization to it, so we could scale input values 9 | * to consistent ranges (triggers, joystick axes, distance sensors, servo ranges, etc...) 10 | * 11 | * @author Alex Stedman 12 | */ 13 | @SuppressWarnings("unused") 14 | public interface Sensored extends DoubleSupplier { 15 | /** 16 | * Get the sensor value 17 | * 18 | * @return The value 19 | */ 20 | double getSensorValue(); 21 | 22 | @Override 23 | default double getAsDouble() { 24 | return getSensorValue(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/AnalogSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import com.qualcomm.robotcore.hardware.AnalogInput; 4 | 5 | /** Class for analog sensors 6 | * @author Alex Stedman 7 | */ 8 | @SuppressWarnings("unused") 9 | public class AnalogSensor extends Sensor { 10 | 11 | private double val; 12 | 13 | /** Make an analog sensor 14 | * 15 | * @param device The analog device 16 | */ 17 | public AnalogSensor(AnalogInput device, String nm) { 18 | super(device, nm); 19 | } 20 | 21 | /** Make an analog sensor 22 | * 23 | * @param deviceName The device name in hardware map 24 | */ 25 | public AnalogSensor(String deviceName) { 26 | super(deviceName); 27 | } 28 | 29 | @Override 30 | public String LogLine() { 31 | return logData(String.format("%f1.4", val)); 32 | } 33 | 34 | public double getSensorValue() { 35 | AnalogInput device = getRawDevice(); 36 | if (device != null) { 37 | val = device.getMaxVoltage(); 38 | } 39 | return val; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ColorDistanceSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import com.qualcomm.robotcore.hardware.ColorRangeSensor; 4 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; 5 | 6 | public class ColorDistanceSensor extends Sensor implements IDistanceSensor, IColorSensor { 7 | 8 | private DistanceUnit distanceUnit; 9 | private double dist; 10 | private double light; 11 | private int color; 12 | 13 | public ColorDistanceSensor(String name) { 14 | super(name); 15 | distanceUnit = DistanceUnit.CM; 16 | } 17 | 18 | @Override 19 | public String LogLine() { 20 | int alpha = (color >> 24) & 0xFF; 21 | if (alpha != 0 && alpha != 0xFF) { 22 | return logData( 23 | String.format( 24 | "d:%f1.2%s A(%d)R(%d)G(%d)B(%d) [%f1.3]", 25 | dist, 26 | distanceUnit, 27 | alpha, 28 | (color >> 16) & 0xFF, 29 | (color >> 8) & 0xFF, 30 | color & 0xFF, 31 | light 32 | ) 33 | ); 34 | } else { 35 | return logData( 36 | String.format( 37 | "d:%f1.2%s R(%d)G(%d)B(%d) [%f1.3]", 38 | dist, 39 | distanceUnit, 40 | (color >> 16) & 0xFF, 41 | (color >> 8) & 0xFF, 42 | color & 0xFF, 43 | light 44 | ) 45 | ); 46 | } 47 | } 48 | 49 | public ColorDistanceSensor(ColorRangeSensor device, String nm) { 50 | super(device, nm); 51 | } 52 | 53 | @Override 54 | public double getDistance(DistanceUnit unit) { 55 | ColorRangeSensor device = getRawDevice(); 56 | double val = dist; 57 | if (device != null) { 58 | val = device.getDistance(unit); 59 | dist = distanceUnit.fromUnit(unit, val); 60 | } 61 | return val; 62 | } 63 | 64 | @Override 65 | public ColorDistanceSensor onUnit(DistanceUnit unit) { 66 | distanceUnit = unit; 67 | return this; 68 | } 69 | 70 | @Override 71 | public DistanceUnit getUnit() { 72 | return distanceUnit; 73 | } 74 | 75 | @Override 76 | public int argb() { 77 | ColorRangeSensor device = getRawDevice(); 78 | if (device != null) { 79 | color = device.argb(); 80 | } 81 | return color; 82 | } 83 | 84 | public double getLight() { 85 | ColorRangeSensor device = getRawDevice(); 86 | if (device != null) { 87 | light = device.getRawLightDetected(); 88 | } 89 | return light; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ColorSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | /** Class for color sensors 4 | * @author Alex Stedman 5 | */ 6 | @SuppressWarnings("unused") 7 | public class ColorSensor extends Sensor implements IColorSensor { 8 | 9 | public int val; 10 | 11 | /** Make a color Sensor 12 | * 13 | * @param device The hardware device 14 | */ 15 | public ColorSensor(com.qualcomm.robotcore.hardware.ColorSensor device, String nm) { 16 | super(device, nm); 17 | } 18 | 19 | /** Make a color sensor 20 | * 21 | * @param deviceName The device name in hardware map 22 | */ 23 | public ColorSensor(String deviceName) { 24 | super(deviceName); 25 | } 26 | 27 | @Override 28 | public String LogLine() { 29 | int alpha = (val >> 24) & 0xFF; 30 | if (alpha != 0 && alpha != 0xFF) { 31 | return logData( 32 | String.format("A(%d)R(%d)G(%d)B(%d)", alpha, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF) 33 | ); 34 | } else { 35 | return logData(String.format("R(%d)G(%d)B(%d)", (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)); 36 | } 37 | } 38 | 39 | @Override 40 | public int argb() { 41 | com.qualcomm.robotcore.hardware.ColorSensor device = getRawDevice(); 42 | if (device != null) { 43 | val = device.argb(); 44 | } 45 | return val; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/DigitalSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import com.qualcomm.robotcore.hardware.DigitalChannel; 4 | 5 | /** Class for digital sensors 6 | * @author Alex Stedman 7 | */ 8 | @SuppressWarnings("unused") 9 | public class DigitalSensor extends Sensor { 10 | 11 | private boolean val; 12 | 13 | /** Make a digital sensor 14 | * 15 | * @param device The device 16 | */ 17 | public DigitalSensor(DigitalChannel device, String nm) { 18 | super(device, nm); 19 | val = false; 20 | } 21 | 22 | /** Make a digital sensor 23 | * 24 | * @param deviceName The device name in hardware map 25 | */ 26 | public DigitalSensor(String deviceName) { 27 | super(deviceName); 28 | } 29 | 30 | @Override 31 | public String LogLine() { 32 | return logData(val ? "T" : "F"); 33 | } 34 | 35 | /** Get the sensor value as a boolean 36 | * 37 | * @return Sensor value as boolean 38 | */ 39 | public boolean getValue() { 40 | DigitalChannel device = getRawDevice(); 41 | if (device != null) { 42 | val = device.getState(); 43 | } 44 | return val; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IColorSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import android.graphics.Color; 4 | import androidx.annotation.ColorInt; 5 | 6 | public interface IColorSensor { 7 | /** Get the RGB red of the sensor 8 | * 9 | * @return Red 10 | */ 11 | default int red() { 12 | return (argb() >> 16) & 0xff; 13 | } 14 | 15 | /** Get the RGB green of the sensor 16 | * 17 | * @return Green 18 | */ 19 | default int green() { 20 | return (argb() >> 8) & 0xff; 21 | } 22 | 23 | /** Get the RGB blue of the sensor 24 | * 25 | * @return Blue 26 | */ 27 | default int blue() { 28 | return (argb()) & 0xff; 29 | } 30 | 31 | /** Get the alpha (transparency) of the color 32 | * 33 | * @return Alpha 34 | */ 35 | default int alpha() { 36 | return (argb() >> 24) & 0xff; 37 | } 38 | 39 | /** Get HSV as an int 40 | * 41 | * @return HSV 42 | */ 43 | default int hsv() { 44 | float[] f = this.hsvArray(); 45 | return ((int) f[0] << 16) | ((int) f[1] << 8) | (int) f[2]; 46 | } 47 | 48 | default int rgb() { 49 | return (argb()) & 0x00ffffff; 50 | } 51 | 52 | @ColorInt 53 | int argb(); 54 | 55 | default float[] hsvArray() { 56 | float[] f = new float[3]; 57 | 58 | Color.RGBToHSV(red(), green(), blue(), f); 59 | return f; 60 | } 61 | 62 | /** Get HSV hue 63 | * 64 | * @return Hue 65 | */ 66 | default int hue() { 67 | return (int) this.hsvArray()[0]; 68 | } 69 | 70 | /** Get HSV saturation 71 | * 72 | * @return Saturation 73 | */ 74 | default int saturation() { 75 | return (int) this.hsvArray()[1]; 76 | } 77 | 78 | /** Get HSV value (not entire HSV, just 'V') 79 | * 80 | * @return Value 81 | */ 82 | default int value() { 83 | return (int) this.hsvArray()[2]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IDistanceSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; 4 | 5 | public interface IDistanceSensor { 6 | default double getDistance() { 7 | return getDistance(getUnit()); 8 | } 9 | 10 | double getDistance(DistanceUnit unit); 11 | 12 | IDistanceSensor onUnit(DistanceUnit distanceUnit); 13 | 14 | DistanceUnit getUnit(); 15 | } 16 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IGyro.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; 4 | 5 | /** 6 | * An interface for a single-angle gyroscope 7 | */ 8 | public interface IGyro { 9 | /** 10 | * Set the units for the various values 11 | */ 12 | void setUnits(AngleUnit u); 13 | 14 | /** 15 | * Get the units the gyroscope is set to 16 | */ 17 | AngleUnit getUnits(); 18 | 19 | /** 20 | * Get the heading (in specified units) 21 | */ 22 | double getHeading(AngleUnit u); 23 | 24 | /** 25 | * Sets the current heading (in default units) 26 | * 27 | * @param newHeading The new heading (in default units) 28 | * @param u The angle units of the new heading 29 | */ 30 | void setHeading(double newHeading, AngleUnit u); 31 | 32 | /** 33 | * Gets the current angular velocity (in specified units) 34 | */ 35 | double getVelocity(AngleUnit u); 36 | 37 | default void degrees() { 38 | setUnits(AngleUnit.DEGREES); 39 | } 40 | 41 | default void radians() { 42 | setUnits(AngleUnit.RADIANS); 43 | } 44 | 45 | /** 46 | * Zeroes the current heading (in default units) 47 | */ 48 | default void zero() { 49 | setHeading(0, getUnits()); 50 | } 51 | 52 | /** 53 | * Get the heading (in default units) 54 | */ 55 | default double getHeading() { 56 | return getHeading(getUnits()); 57 | } 58 | 59 | /** 60 | * Get the heading (in degrees) 61 | */ 62 | default double getHeadingInDegrees() { 63 | return getHeading(AngleUnit.DEGREES); 64 | } 65 | 66 | /** 67 | * Get the heading (in radians) 68 | */ 69 | default double getHeadingInRadians() { 70 | return getHeading(AngleUnit.RADIANS); 71 | } 72 | 73 | /** 74 | * Gets the current angular velocity (in default units) 75 | */ 76 | default double getVelocity() { 77 | return getVelocity(getUnits()); 78 | } 79 | 80 | /** 81 | * Gets the current angular velocity (in radians) 82 | */ 83 | default double getVelocityInDegrees() { 84 | return getVelocity(AngleUnit.DEGREES); 85 | } 86 | 87 | /** 88 | * Gets the current angular velocity (in degrees) 89 | */ 90 | default double getVelocityInRadians() { 91 | return getVelocity(AngleUnit.RADIANS); 92 | } 93 | 94 | /** 95 | * Sets the current heading (in default units) 96 | * 97 | * @param newHeading The new heading (in default units) 98 | */ 99 | default void setHeading(double newHeading) { 100 | setHeading(newHeading, getUnits()); 101 | } 102 | 103 | /** 104 | * Sets the current heading (in default units) 105 | * 106 | * @param newHeading The new heading (in default units) 107 | */ 108 | default void setHeadingInDegrees(double newHeading) { 109 | setHeading(newHeading, AngleUnit.DEGREES); 110 | } 111 | 112 | /** 113 | * Sets the current heading (in default units) 114 | * 115 | * @param newHeading The new heading (in default units) 116 | */ 117 | default void setHeadingInRadians(double newHeading) { 118 | setHeading(newHeading, AngleUnit.RADIANS); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ILightSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | public interface ILightSensor {} 4 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/Rev2MDistanceSensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import com.qualcomm.robotcore.hardware.DistanceSensor; 4 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; 5 | 6 | /** 7 | * Class for the Rev '2m' range sensors 8 | * Note for users: The Rev 2m range sensor is actually only useful at about 1.1 - 1.2m :/ 9 | * 10 | * @author Alex Stedman 11 | */ 12 | @SuppressWarnings("unused") 13 | public class Rev2MDistanceSensor extends Sensor implements IDistanceSensor { 14 | 15 | private DistanceUnit distanceUnit; 16 | private double dist; 17 | 18 | /** 19 | * Create a range sensor 20 | * 21 | * @param device The sensor device 22 | */ 23 | public Rev2MDistanceSensor(DistanceSensor device, String nm) { 24 | super(device, nm); 25 | } 26 | 27 | /** 28 | * Create a range sensor 29 | * 30 | * @param deviceName The device name 31 | */ 32 | public Rev2MDistanceSensor(String deviceName) { 33 | super(deviceName); 34 | } 35 | 36 | @Override 37 | public String LogLine() { 38 | return logData(String.format("%f1.3%s", this.dist, this.distanceUnit)); 39 | } 40 | 41 | /** 42 | * Get the value with a specified distance Unit 43 | * 44 | * @param distanceUnit The unit 45 | * @return The distance 46 | */ 47 | @Override 48 | public double getDistance(DistanceUnit distanceUnit) { 49 | DistanceSensor device = getRawDevice(); 50 | if (device != null) { 51 | dist = device.getDistance(distanceUnit); 52 | } 53 | return dist; 54 | } 55 | 56 | /** 57 | * Get the current distance unit 58 | * 59 | * @return The distance unit 60 | */ 61 | @Override 62 | public DistanceUnit getUnit() { 63 | return distanceUnit; 64 | } 65 | 66 | /** 67 | * Set the distance unit 68 | * 69 | * @param distanceUnit The unit 70 | * @return This 71 | */ 72 | @Override 73 | public Rev2MDistanceSensor onUnit(DistanceUnit distanceUnit) { 74 | this.distanceUnit = distanceUnit; 75 | return this; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/Sensor.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor; 2 | 3 | import com.technototes.library.hardware.HardwareDevice; 4 | 5 | /** 6 | * Root class for sensors 7 | * 8 | * @param The Sensor hardware device 9 | * @author Alex Stedman 10 | */ 11 | @SuppressWarnings("unused") 12 | public abstract class Sensor extends HardwareDevice { 13 | 14 | /** 15 | * Create a sensor 16 | * 17 | * @param device The device 18 | */ 19 | public Sensor(T device, String nm) { 20 | super(device, nm); 21 | } 22 | 23 | /** 24 | * Create sensor 25 | * 26 | * @param deviceName The device name in hardware map 27 | */ 28 | public Sensor(String deviceName) { 29 | super(deviceName); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/encoder/Encoder.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor.encoder; 2 | 3 | import com.technototes.library.hardware.Sensored; 4 | 5 | /** Interfaces for encoders to use 6 | * @author Alex Stedman 7 | */ 8 | public interface Encoder extends Sensored { 9 | /** zero the encoder 10 | * 11 | */ 12 | void zeroEncoder(); 13 | 14 | default double getPosition() { 15 | return getSensorValue(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/encoder/ExternalEncoder.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.sensor.encoder; 2 | 3 | import com.qualcomm.robotcore.hardware.AnalogInput; 4 | import com.technototes.library.hardware.sensor.Sensor; 5 | 6 | /** 7 | * A wrapper around an AnalogInput that enables "zeroing" for usefulness 8 | */ 9 | public class ExternalEncoder extends Sensor implements Encoder { 10 | 11 | private double zero = 0; 12 | private double val = 0; 13 | 14 | /** 15 | * Create an ExternalEncoder from an arbitrary AnalogInput 16 | * 17 | * @param device the AnalogInput device 18 | */ 19 | public ExternalEncoder(AnalogInput device, String nm) { 20 | super(device, nm); 21 | } 22 | 23 | /** 24 | * Create an ExternalEncoder from an arbitrary AnalogInput device 25 | * 26 | * @param deviceName the name of the AnalogInput device 27 | */ 28 | public ExternalEncoder(String deviceName) { 29 | super(deviceName); 30 | } 31 | 32 | @Override 33 | public String LogLine() { 34 | return logData(String.format("%f1.3 (raw: %f1.3)", val - zero, val)); 35 | } 36 | 37 | /** 38 | * Set the current device value as "zero" 39 | */ 40 | @Override 41 | public void zeroEncoder() { 42 | AnalogInput device = getRawDevice(); 43 | if (device != null) { 44 | zero = device.getVoltage(); 45 | } 46 | } 47 | 48 | /** 49 | * Get the sensor value (relative to the assigned zero) 50 | * 51 | * @return the value of the input 52 | */ 53 | @Override 54 | public double getSensorValue() { 55 | AnalogInput device = getRawDevice(); 56 | if (device != null) { 57 | val = device.getVoltage(); 58 | } 59 | return val - zero; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/hardware/servo/MotorAsServo.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware.servo; 2 | 3 | import com.qualcomm.robotcore.hardware.DcMotor; 4 | import com.qualcomm.robotcore.hardware.DcMotorEx; 5 | import com.technototes.library.hardware.HardwareDevice; 6 | import com.technototes.library.hardware.Sensored; 7 | import java.io.InvalidClassException; 8 | 9 | /** 10 | * This is to use a motor as a servo using the built-in capabilities (instead of doing it manually) 11 | * 12 | * One rather important feature would be to hand control back & forth between a normal encoded 13 | * motor. The alternative would be to extend EncodedMotor to just "do" this stuff automatically. 14 | * Honestly, that probably makes more sense, but requires some thought about state transitions. 15 | * 16 | * @param 17 | * Not Yet Implemented! 18 | * TODO: Implement this 19 | * 20 | */ 21 | public class MotorAsServo extends HardwareDevice implements Sensored { 22 | 23 | public MotorAsServo(T device, String deviceName) throws InvalidClassException { 24 | super(device, deviceName); 25 | throw new InvalidClassException("com.technototes.library.hardware.servo.MotorAsServo", "Not Yet Implemented"); 26 | } 27 | 28 | protected MotorAsServo(String deviceName) throws InvalidClassException { 29 | super(deviceName); 30 | throw new InvalidClassException("com.technototes.library.hardware.servo.MotorAsServo", "Not Yet Implemented"); 31 | } 32 | 33 | /** 34 | * @return 35 | */ 36 | @Override 37 | public String LogLine() { 38 | return null; 39 | } 40 | 41 | /** 42 | * @return 43 | */ 44 | @Override 45 | public double getSensorValue() { 46 | return 0; 47 | } 48 | 49 | /** 50 | * @return 51 | */ 52 | @Override 53 | public double getAsDouble() { 54 | return getSensorValue(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/Log.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 5 | import static java.lang.annotation.ElementType.METHOD; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Repeatable; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.lang.annotation.Target; 13 | 14 | /** The root annotation for annotation logging, also doubles as a basic string log 15 | * @author Alex Stedman 16 | */ 17 | @Documented 18 | @Repeatable(Log.Logs.class) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 21 | public @interface Log { 22 | /** Store index for this annotation (position in telemetry) 23 | * 24 | * @return The index 25 | */ 26 | int index() default -1; 27 | 28 | /** Store priority for this log entry (to pick the most wanted entry over others with same index) 29 | * 30 | * @return The priority 31 | */ 32 | int priority() default -1; 33 | 34 | /** Store the name for this annotation to be be beside 35 | * 36 | * @return The name as a string 37 | */ 38 | String name() default ""; 39 | 40 | /** The format for the logged String 41 | * 42 | * @return The format 43 | */ 44 | String format() default "%s"; 45 | 46 | @Documented 47 | @Retention(RetentionPolicy.RUNTIME) 48 | @Target({ ElementType.FIELD, ElementType.METHOD }) 49 | @interface Logs { 50 | Log[] value(); 51 | } 52 | 53 | /** Log a number 54 | * 55 | */ 56 | @Retention(RetentionPolicy.RUNTIME) 57 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 58 | @interface Number { 59 | /** Store index for this annotation (position in telemetry) 60 | * 61 | * @return The index 62 | */ 63 | int index() default -1; 64 | 65 | /** Store priority for this log entry (to pick the most wanted entry over others with same index) 66 | * 67 | * @return The priority 68 | */ 69 | int priority() default -1; 70 | 71 | /** Store the name for this annotation to be be beside 72 | * 73 | * @return The name as a string 74 | */ 75 | String name() default ""; 76 | } 77 | 78 | @Retention(RetentionPolicy.RUNTIME) 79 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 80 | @interface Boolean { 81 | /** Store index for this annotation (position in telemetry) 82 | * 83 | * @return The index 84 | */ 85 | int index() default -1; 86 | 87 | /** Store priority for this log entry (to pick the most wanted entry over others with same index) 88 | * 89 | * @return The priority 90 | */ 91 | int priority() default -1; 92 | 93 | /** Store the string when the annotated method returns true 94 | * 95 | * @return The string 96 | */ 97 | String trueValue() default "true"; 98 | 99 | /** Store the string when the annotated method returns false 100 | * 101 | * @return The string 102 | */ 103 | String falseValue() default "false"; 104 | 105 | /** Store the name for this annotation to be be beside 106 | * 107 | * @return The name as a string 108 | */ 109 | String name() default ""; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/LogConfig.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 5 | import static java.lang.annotation.ElementType.METHOD; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** Annotations for configuring Logs 12 | * @author Alex Stedman 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface LogConfig { 16 | /** Annotation for determining when logged item will be sent to Telemetry 17 | * 18 | */ 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 21 | @interface Run { 22 | /** Run the log during the teleop Period 23 | * 24 | * @return The above condition 25 | */ 26 | boolean duringRun() default true; 27 | 28 | /** Run the log during the init Period 29 | * 30 | * @return The above condition 31 | */ 32 | boolean duringInit() default false; 33 | } 34 | 35 | /** Annotation for allowing Opmodes to log this item 36 | * 37 | */ 38 | @Retention(RetentionPolicy.RUNTIME) 39 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 40 | @interface AllowList { 41 | /** The allowed opmodes 42 | * 43 | * @return Opmode Classes 44 | */ 45 | Class[] value(); 46 | } 47 | 48 | /** Annotation for denying Opmodes to log this item 49 | * 50 | */ 51 | @Retention(RetentionPolicy.RUNTIME) 52 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 53 | @interface DenyList { 54 | /** The denied opmodes 55 | * 56 | * @return Opmode Classes 57 | */ 58 | Class[] value(); 59 | } 60 | 61 | /** Annotation to completely disable the entry 62 | * 63 | */ 64 | @Retention(RetentionPolicy.RUNTIME) 65 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD }) 66 | @interface Disabled { 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/Loggable.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger; 2 | 3 | /** All classes with annotations for logging must extend this all the way up the hierarchy up to the op mode 4 | * @author Alex Stedman 5 | */ 6 | public interface Loggable {} 7 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/entry/BooleanEntry.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger.entry; 2 | 3 | import com.technototes.library.util.Color; 4 | import java.util.function.Supplier; 5 | 6 | public class BooleanEntry extends Entry { 7 | 8 | private String trueEntry, falseEntry; 9 | 10 | public BooleanEntry(String n, Supplier s, int index, String wt, String wf) { 11 | super(n, s, index); 12 | trueEntry = wt; 13 | falseEntry = wf; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return (get() ? trueEntry : falseEntry); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/entry/Entry.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger.entry; 2 | 3 | import java.util.function.Supplier; 4 | 5 | /** 6 | * The root class for logging entries 7 | * 8 | * @param The type of value being stored by the entry 9 | * @author Alex Stedman 10 | */ 11 | public abstract class Entry implements Supplier { 12 | 13 | /** 14 | * The index (in the list) of the entry 15 | */ 16 | protected int x; 17 | /** 18 | * The priority (in the telemetry list) of the entry 19 | */ 20 | protected int priority; 21 | /** 22 | * The function called to get the value to display 23 | */ 24 | protected Supplier supplier; 25 | /** 26 | * The name of the Entry 27 | */ 28 | protected String name; 29 | 30 | /** 31 | * Create an entry with name, value, index 32 | * 33 | * @param n Name of the entry 34 | * @param s Value function to display 35 | * @param index Index of the entry 36 | */ 37 | public Entry(String n, Supplier s, int index) { 38 | x = index; 39 | supplier = s; 40 | name = n; 41 | } 42 | 43 | /** 44 | * Set's the priority for this log line (handy for telemetry overflow) 45 | * 46 | * @param p The priority 47 | * @return Self (for chaining) 48 | */ 49 | public Entry setPriority(int p) { 50 | priority = p; 51 | return this; 52 | } 53 | 54 | @Override 55 | public T get() { 56 | return supplier.get(); 57 | } 58 | 59 | /** 60 | * The String for the logged item 61 | * 62 | * @return The String 63 | */ 64 | @Override 65 | public String toString() { 66 | return supplier.get().toString(); 67 | } 68 | 69 | /** 70 | * Get the name 71 | * 72 | * @return The name 73 | */ 74 | public String getName() { 75 | return name; 76 | } 77 | 78 | /** 79 | * Get the index for the entry 80 | * 81 | * @return The index 82 | */ 83 | public int getIndex() { 84 | return x; 85 | } 86 | 87 | /** 88 | * Set index 89 | * 90 | * @param i New index 91 | * @return this 92 | */ 93 | public Entry setIndex(int i) { 94 | x = i; 95 | return this; 96 | } 97 | 98 | /** 99 | * Get Priority for the entry 100 | * 101 | * @return The priority 102 | */ 103 | public int getPriority() { 104 | return priority; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/entry/NumberEntry.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger.entry; 2 | 3 | import com.technototes.library.util.Color; 4 | import java.util.function.Supplier; 5 | 6 | public class NumberEntry extends Entry { 7 | 8 | protected Color numberColor; 9 | 10 | public NumberEntry(String n, Supplier s, int x) { 11 | super(n, s, x); 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return numberColor.format(get()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/logger/entry/StringEntry.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.logger.entry; 2 | 3 | import java.util.function.Supplier; 4 | 5 | public class StringEntry extends Entry { 6 | 7 | private String format; 8 | 9 | public StringEntry(String n, Supplier s, int x, String f) { 10 | super(n, s, x); 11 | format = f; 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return String.format(format, get()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/subsystem/Subsystem.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.subsystem; 2 | 3 | import com.technototes.library.command.Command; 4 | import com.technototes.library.command.CommandScheduler; 5 | import com.technototes.library.general.Periodic; 6 | 7 | public interface Subsystem extends Periodic { 8 | default void register() { 9 | CommandScheduler.register(this); 10 | } 11 | 12 | default Subsystem setDefaultCommand(Command c) { 13 | CommandScheduler.scheduleDefault(c, this); 14 | return this; 15 | } 16 | 17 | default Command getDefaultCommand() { 18 | return CommandScheduler.getDefault(this); 19 | } 20 | 21 | @Override 22 | default void periodic() {} 23 | } 24 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/subsystem/drivebase/DrivebaseSubsystem.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.subsystem.drivebase; 2 | 3 | import com.qualcomm.robotcore.hardware.DcMotorSimple; 4 | import com.technototes.library.hardware.motor.Motor; 5 | import com.technototes.library.subsystem.Subsystem; 6 | import java.util.function.DoubleSupplier; 7 | 8 | /** 9 | * Class for DriveBase subsystems 10 | * 11 | * @param The type of motors for the drivebase 12 | * @author Alex Stedman The motors for the drivebase 13 | */ 14 | public abstract class DrivebaseSubsystem implements Subsystem { 15 | 16 | protected Motor[] motors; 17 | 18 | /** 19 | * Override this to get the gyroscope heading. 20 | * Or pass it in to the constructor. Which ever works best for your drivebase implementation. 21 | */ 22 | protected DoubleSupplier gyroSupplier = () -> 0; 23 | 24 | /** 25 | * Create a drivebase subsystem 26 | * 27 | * @param motors The drive motors 28 | */ 29 | public DrivebaseSubsystem(Motor... motors) { 30 | this.motors = motors; 31 | } 32 | 33 | /** 34 | * Create a drivebase subsystem 35 | * 36 | * @param gyro The gyro supplier 37 | * @param motors The drive motors 38 | */ 39 | public DrivebaseSubsystem(DoubleSupplier gyro, Motor... motors) { 40 | this.motors = motors; 41 | gyroSupplier = gyro; 42 | } 43 | 44 | /** 45 | * This will give you a *positive* value to scale the value to such that 46 | * the largest value of the list will be |1| (negative or positive). 47 | *

48 | * This is helpful for an X-Drive drivebase, as the algorithm for calucating 49 | * motor power will often give a collection of values, all of which are smaller than 1. 50 | * 51 | * @param powers The list of values you're setting 52 | * @return The number to divide the values by to set the largest to 1/-1 53 | */ 54 | public double getScale(double... powers) { 55 | double max = 0; 56 | for (double d : powers) { 57 | max = Math.max(Math.abs(d), max); 58 | } 59 | return max; 60 | } 61 | 62 | /** 63 | * Get the Gyro angle 64 | * 65 | * @return Gyro angle from supplier 66 | */ 67 | public double getGyro() { 68 | return gyroSupplier.getAsDouble(); 69 | } 70 | 71 | /** 72 | * Override this one, I guess? Not sure how useful it is. 73 | * 74 | * @return the speed? 75 | */ 76 | public double getSpeed() { 77 | return 1; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/subsystem/drivebase/TankDrivebaseSubsystem.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.subsystem.drivebase; 2 | 3 | import com.qualcomm.robotcore.hardware.DcMotorSimple; 4 | import com.qualcomm.robotcore.util.Range; 5 | import com.technototes.library.hardware.motor.Motor; 6 | 7 | /** 8 | * Class for drivebase subsystems 9 | * 10 | * @param The type of motor for the drivebase 11 | * @author Alex Stedman 12 | */ 13 | public class TankDrivebaseSubsystem extends DrivebaseSubsystem { 14 | 15 | /** 16 | * Drive motors 17 | */ 18 | protected Motor leftSide() { 19 | return motors[0]; 20 | } 21 | 22 | protected Motor rightSide() { 23 | return motors[1]; 24 | } 25 | 26 | /** 27 | * Create tank drivebase 28 | * 29 | * @param leftMotor The motor/motorgroup for the left side of the drivebase 30 | * @param rightMotor The motor/motorgroup for the right side of the drivebase 31 | */ 32 | public TankDrivebaseSubsystem(Motor leftMotor, Motor rightMotor) { 33 | super(leftMotor, rightMotor); 34 | } 35 | 36 | public void arcadeDrive(double y, double x) { 37 | double lp = y + x; 38 | double rp = -y + x; 39 | double scale = getScale(lp, rp); 40 | double speed = Range.clip(Math.abs(y) + Math.abs(x), 0, 1); 41 | scale = scale == 0 ? 0 : speed / scale; 42 | drive(lp * scale, rp * scale); 43 | } 44 | 45 | public void stop() { 46 | drive(0, 0); 47 | } 48 | 49 | public void drive(double l, double r) { 50 | motors[0].setPower(l * getSpeed()); 51 | motors[1].setPower(r * getSpeed()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/Characters.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | public class Characters { 4 | 5 | public static final String BLUE_CIRCLE = "\uD83D\uDD35"; 6 | public static final String RED_SQUARE = "\uD83D\uDFE5"; 7 | public static final String DUCK = "\uD83E\uDD86"; 8 | public static final String CYCLE = "♻️"; 9 | public static final String GAMEPAD = "\uD83C\uDFAE"; 10 | } 11 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/Color.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | /** Enum for Colors and some formatting 4 | * @author Alex Stedman 5 | */ 6 | public enum Color { 7 | RED("FF2222"), 8 | ORANGE("EA5D00"), 9 | YELLOW("FFBF00"), 10 | LIME("69FF00"), 11 | GREEN("00D318"), 12 | CYAN("00E5E5"), 13 | BLUE("1E39CE"), 14 | PURPLE("5A00E2"), 15 | MAGENTA("BE00FF"), 16 | PINK("FF3ADC"), 17 | BLACK("000000"), 18 | WHITE("FFFFFF"), 19 | LIGHT_GRAY("808080"), 20 | DARK_GRAY("404040"), 21 | NO_COLOR("FFFFFF"); 22 | 23 | String hexValue; 24 | 25 | Color(String hex) { 26 | hexValue = hex; 27 | } 28 | 29 | /** Get the hex value 30 | * 31 | * @return The hex for the color 32 | */ 33 | public String getHexValue() { 34 | return hexValue; 35 | } 36 | 37 | /** Format the supplied object with the HTML to become this color 38 | * 39 | * @param object The object 40 | * @return The formatted String 41 | */ 42 | public String format(Object object) { 43 | return ("" + object + ""); 44 | } 45 | 46 | /** Format the supplied object with the HTML and a format String to become this color 47 | * 48 | * @param objects The objects 49 | * @param format The format for the supplied String 50 | * @return The formatted String 51 | */ 52 | public String format(String format, Object... objects) { 53 | return format(String.format(format, objects)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/Integral.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | import com.qualcomm.robotcore.util.ElapsedTime; 4 | 5 | /** 6 | * A simple Observation-based integral calculator over time 7 | */ 8 | public class Integral { 9 | 10 | private double accumulator; 11 | private ElapsedTime deltaTime; 12 | 13 | /** 14 | * Initialize it with the value c 15 | * 16 | * @param c Initial value 17 | */ 18 | public Integral(double c) { 19 | accumulator = c; 20 | deltaTime = new ElapsedTime(); 21 | } 22 | 23 | /** 24 | * Initialize it with a value of 0 25 | */ 26 | public Integral() { 27 | this(0); 28 | } 29 | 30 | /** 31 | * Set the value to C 32 | * 33 | * @param c the value 34 | * @return this 35 | */ 36 | public Integral set(double c) { 37 | accumulator = c; 38 | return this; 39 | } 40 | 41 | /** 42 | * Set the value to zero 43 | * 44 | * @return this 45 | */ 46 | public Integral zero() { 47 | return set(0); 48 | } 49 | 50 | /** 51 | * Update the accumulated value for the number of seconds since last update 52 | * 53 | * @param change the value that was observed since last integration 54 | * @return the current accumulations 55 | */ 56 | public double update(double change) { 57 | accumulator += change * deltaTime.seconds(); 58 | deltaTime.reset(); 59 | return accumulator; 60 | } 61 | 62 | /** 63 | * Get the current accumulation 64 | * 65 | * @return the current accumulation 66 | */ 67 | public double getValue() { 68 | return accumulator; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/MapUtils.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | import android.util.Pair; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class MapUtils { 8 | 9 | @SafeVarargs 10 | public static Map of(Pair... entries) { 11 | Map map = new HashMap<>(); 12 | for (Pair e : entries) { 13 | map.put(e.first, e.second); 14 | } 15 | return map; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/Range.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | /** 4 | * Helper class for tracking a range 5 | * 6 | * Adds minimal value over com.qualcomm.robotcore.util.Range, which is the reason for deprecation 7 | */ 8 | @Deprecated 9 | public class Range { 10 | 11 | /** 12 | * The minimum value of the range 13 | */ 14 | public double min; 15 | 16 | /** 17 | * The maximum value of the range 18 | */ 19 | public double max; 20 | 21 | /** 22 | * Create a range with the given minimum and maximum 23 | * 24 | * @param mi Min value 25 | * @param ma Max value 26 | */ 27 | public Range(double mi, double ma) { 28 | min = mi; 29 | max = ma; 30 | if (mi > ma) { 31 | throw new IllegalArgumentException("Minimum is greater than maximum"); 32 | } 33 | } 34 | 35 | /** 36 | * Check if the value is in the range 37 | * 38 | * @param val The value to check 39 | * @return True if in (inclusive) range, false otherwise 40 | */ 41 | public boolean inRange(double val) { 42 | return val >= min && val <= max; 43 | } 44 | 45 | /** 46 | * Scale the range by a given value 47 | * 48 | * @param scalar The amount to scale the range by 49 | */ 50 | public void scale(double scalar) { 51 | min *= scalar; 52 | max *= scalar; 53 | if (min > max) { 54 | double tmp = min; 55 | min = max; 56 | max = tmp; 57 | } 58 | } 59 | 60 | /** 61 | * Get the 'middle' of the range 62 | * 63 | * @return the average of min & max 64 | */ 65 | public double middle() { 66 | return (min + max) / 2; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/java/com/technototes/library/util/SmartConsumer.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * This is a functional interface, when 'accept' is invoked, will only invoke the 'consume' method 8 | * when a different value is provided. It basically removed duplicates. 9 | *

10 | * TODO: This seems like the HashMap is completely unnecessary. Maybe I'm not following the java 11 | * TODO: object model, but I don't see how map ever has more than a single value in it... 12 | * 13 | * @param The type of the value to be accepted/consumed 14 | */ 15 | @FunctionalInterface 16 | public interface SmartConsumer { 17 | /** 18 | * The map of values that have been consumed. 19 | */ 20 | Map, Object> map = new HashMap<>(); 21 | 22 | /** 23 | * The 'consume' function 24 | */ 25 | void consume(T t); 26 | 27 | /** The public interface for a SmartConsumer: accept should be invoked, not consume :) 28 | * 29 | * @param t The value being consumed/accepted 30 | * @return 31 | */ 32 | default SmartConsumer accept(T t) { 33 | if (!t.equals(getLast())) { 34 | consume(t); 35 | map.put(this, t); 36 | } 37 | return this; 38 | } 39 | 40 | default T getLast() { 41 | return (T) map.get(this); 42 | } 43 | 44 | static void reset() { 45 | map.clear(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /RobotLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/TestTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | public class TestTest { 6 | 7 | @Test 8 | public void test() { 9 | System.out.println("test"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/command/CancelCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import com.qualcomm.robotcore.util.ElapsedTime; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class CancelCommandTest { 10 | 11 | class cmd implements Command { 12 | 13 | @Override 14 | public void execute() { 15 | // System.out.println(getRuntime().seconds()); 16 | } 17 | 18 | @Override 19 | public boolean isFinished() { 20 | return false; 21 | } 22 | } 23 | 24 | @BeforeEach 25 | public void setup() { 26 | CommandScheduler.resetScheduler(); 27 | } 28 | 29 | @Test 30 | public void scheduleCommand() { 31 | Command c = new cmd(); 32 | ElapsedTime t = new ElapsedTime(); 33 | t.reset(); 34 | CommandScheduler.scheduleOnce(c.cancelUpon(() -> c.getRuntime().seconds() > 1)); 35 | int finCount = 0; 36 | while (t.seconds() < 5.5) { 37 | CommandScheduler.run(); 38 | if (c.justFinished()) finCount++; //System.out.println("finish"); 39 | // System.out.println(e++); 40 | } 41 | assertEquals(5, finCount); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/command/CommandForTesting.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | public class CommandForTesting implements Command { 4 | 5 | public int initialized = 0; 6 | public int executed = 0; 7 | public int ended = 0; 8 | public int canceled = 0; 9 | 10 | @Override 11 | public void initialize() { 12 | initialized++; 13 | } 14 | 15 | @Override 16 | public void execute() { 17 | executed++; 18 | } 19 | 20 | @Override 21 | public void end(boolean cancel) { 22 | ended++; 23 | if (cancel) { 24 | canceled++; 25 | } 26 | } 27 | 28 | /* 29 | RESET, 30 | STARTED, 31 | INITIALIZING, 32 | EXECUTING, 33 | FINISHED, 34 | INTERRUPTED, 35 | CANCELLED, 36 | */ 37 | private int lastRes = 0; 38 | 39 | public int check(int i, int x, int e, int c) { 40 | int iCheck = (initialized == i) ? 0 : 1000; 41 | int xCheck = (executed == x) ? 0 : 100; 42 | int eCheck = (ended == e) ? 0 : 10; 43 | int cCheck = (canceled == c) ? 0 : 1; 44 | lastRes = iCheck + xCheck + eCheck + cCheck; 45 | return lastRes; 46 | } 47 | 48 | public String lastResult() { 49 | return String.format("%d %d %d %d", initialized, executed, ended, canceled); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/command/CommandGroupTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class CommandGroupTest { 7 | 8 | Command c1 = () -> print(1), c2 = () -> print(2), c3 = () -> print(3), c4 = () -> print(4), c5 = () -> print(5); 9 | 10 | @BeforeEach 11 | public void setup() { 12 | CommandScheduler.resetScheduler(); 13 | } 14 | 15 | @Test 16 | public void scheduleCommand() { 17 | CommandGroup g = new SequentialCommandGroup(c1, c2, c3, c4, c5); 18 | CommandScheduler.schedule(g); 19 | for (int i = 0; i < 100; i++) { 20 | CommandScheduler.run(); 21 | // System.out.println(e++);' 22 | } 23 | } 24 | 25 | public void print(int i) { 26 | System.out.println(i); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/command/CommandTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class CommandTest { 7 | 8 | Command c = this::act; 9 | 10 | public void act() { 11 | System.out.println("it do"); 12 | } 13 | 14 | @BeforeEach 15 | public void setup() { 16 | CommandScheduler.resetScheduler(); 17 | } 18 | 19 | @Test 20 | public void scheduleCommand() { 21 | long i = System.currentTimeMillis(); 22 | int e = 0; 23 | CommandScheduler.schedule(c.sleep(1)); 24 | while (System.currentTimeMillis() - i < 10500) { 25 | CommandScheduler.run(); 26 | if (c.justFinished()) System.out.println("finish"); 27 | // System.out.println(e++); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/command/RequirementCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.command; 2 | 3 | import com.technototes.library.subsystem.Subsystem; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class RequirementCommandTest { 8 | 9 | public static class DummySubsystem implements Subsystem { 10 | 11 | public void method1() { 12 | System.out.print(1); 13 | } 14 | 15 | public void method2() { 16 | System.out.print(2); 17 | } 18 | 19 | public void method3() { 20 | System.out.print(3); 21 | } 22 | } 23 | 24 | public DummySubsystem subsystem; 25 | public Command command1, command2, command3; 26 | 27 | @BeforeEach 28 | public void setup() { 29 | subsystem = new DummySubsystem(); 30 | CommandScheduler.resetScheduler(); 31 | command1 = Command.create(subsystem::method1, subsystem); 32 | command2 = Command.create(subsystem::method2, subsystem); 33 | command3 = Command.create(subsystem::method3, subsystem); 34 | } 35 | 36 | @Test 37 | public void run() { 38 | int[] i = new int[1]; 39 | CommandScheduler.schedule(command1, () -> i[0] == 0); 40 | CommandScheduler.schedule(command2, () -> i[0] == 1); 41 | CommandScheduler.schedule(command3, () -> i[0] == 2); 42 | 43 | for (i[0] = 0; i[0] < 100; i[0]++) { 44 | CommandScheduler.run(); 45 | System.out.println(" - " + command1.getState() + " - " + command2.getState() + " - " + command3.getState()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/gamepad/GamepadTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.gamepad; 2 | 3 | import com.qualcomm.robotcore.hardware.Gamepad; 4 | import com.technototes.library.control.CommandButton; 5 | import com.technototes.library.control.CommandGamepad; 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class GamepadTest { 11 | 12 | private Gamepad gamepad; 13 | private CommandGamepad commandGamepad; 14 | 15 | @BeforeEach 16 | public void setup() { 17 | gamepad = new Gamepad(); 18 | commandGamepad = new CommandGamepad(gamepad); 19 | } 20 | 21 | @Test 22 | public void buttonTest() { 23 | CommandButton commandButton = commandGamepad.xbox_a; 24 | gamepad.a = false; 25 | commandButton.periodic(); 26 | gamepad.a = true; 27 | commandButton.periodic(); 28 | Assertions.assertTrue(commandButton.isPressed()); 29 | Assertions.assertTrue(commandButton.isJustPressed()); 30 | Assertions.assertTrue(commandButton.isToggled()); 31 | Assertions.assertTrue(commandButton.isJustToggled()); 32 | commandButton.periodic(); 33 | Assertions.assertTrue(commandButton.isPressed()); 34 | Assertions.assertFalse(commandButton.isJustPressed()); 35 | Assertions.assertTrue(commandButton.isToggled()); 36 | Assertions.assertFalse(commandButton.isJustToggled()); 37 | gamepad.a = false; 38 | commandButton.periodic(); 39 | gamepad.a = true; 40 | commandButton.periodic(); 41 | Assertions.assertTrue(commandButton.isInverseToggled()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/hardware/MockServo.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | import com.qualcomm.robotcore.hardware.Servo; 4 | import com.qualcomm.robotcore.hardware.ServoController; 5 | 6 | public class MockServo implements Servo { 7 | 8 | public MockServo() {} 9 | 10 | @Override 11 | public ServoController getController() { 12 | return null; 13 | } 14 | 15 | @Override 16 | public int getPortNumber() { 17 | return 0; 18 | } 19 | 20 | @Override 21 | public void setDirection(Direction direction) {} 22 | 23 | @Override 24 | public Direction getDirection() { 25 | return null; 26 | } 27 | 28 | double pos; 29 | 30 | @Override 31 | public void setPosition(double position) { 32 | pos = position; 33 | } 34 | 35 | @Override 36 | public double getPosition() { 37 | return pos; 38 | } 39 | 40 | @Override 41 | public void scaleRange(double min, double max) {} 42 | 43 | @Override 44 | public Manufacturer getManufacturer() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getDeviceName() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public String getConnectionInfo() { 55 | return null; 56 | } 57 | 58 | @Override 59 | public int getVersion() { 60 | return 0; 61 | } 62 | 63 | @Override 64 | public void resetDeviceConfigurationForOpMode() {} 65 | 66 | @Override 67 | public void close() {} 68 | } 69 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/hardware/ServoProfilerTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.hardware; 2 | 3 | import com.qualcomm.robotcore.util.ElapsedTime; 4 | import com.technototes.library.hardware.servo.Servo; 5 | import com.technototes.library.hardware.servo.ServoProfiler; 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class ServoProfilerTest { 9 | 10 | public ServoProfiler servoController; 11 | public Servo servo; 12 | public ElapsedTime time; 13 | 14 | @Test 15 | public void test() { 16 | servo = new Servo(new MockServo(), "mockServo").startAt(0); 17 | servoController = new ServoProfiler(servo).setConstraints(1, 0.4, 1); 18 | time = new ElapsedTime(); 19 | time.reset(); 20 | servoController.setTargetPosition(0.7); 21 | while (!servoController.isAtTarget()) { 22 | System.out.println(time.seconds() + ": " + servoController.update().getCurrentPosition()); 23 | try { 24 | Thread.sleep(100); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/opmode/OpModeTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.opmode; 2 | 3 | import com.qualcomm.robotcore.eventloop.opmode.OpMode; 4 | import com.qualcomm.robotcore.hardware.Gamepad; 5 | import com.technototes.library.structure.CommandOpMode; 6 | 7 | public class OpModeTest { 8 | 9 | private OpMode opMode; 10 | // SDK 8.1.1 doesn't let us make a hardware map with a null appContext 11 | // private HardwareMap hardwareMap; 12 | private Gamepad g1, g2; 13 | 14 | public void setup() { 15 | opMode = new TestOpMode(); 16 | g1 = new Gamepad(); 17 | g2 = new Gamepad(); 18 | opMode.gamepad1 = g1; 19 | opMode.gamepad2 = g2; 20 | opMode.hardwareMap = null; 21 | } 22 | 23 | public void run() {} 24 | 25 | public class TestOpMode extends CommandOpMode { 26 | 27 | @Override 28 | public void universalLoop() { 29 | System.out.println(getOpModeState()); 30 | } 31 | } 32 | 33 | public boolean callToInitNeeded = false, callToStartNeeded = false, looping = false; 34 | 35 | public void runActiveOpMode() { 36 | // 37 | // opMode.time = opMode.getRuntime(); 38 | // 39 | // 40 | // 41 | // if (callToInitNeeded) { 42 | // 43 | // // The point about resetting the hardware is to have it in the same state 44 | // // every time for the *user's* code so that they can simplify their initialization 45 | // // logic. There's no point in bothering / spending the time for the default opmode. 46 | // 47 | // opMode.resetStartTime(); 48 | // opMode.internalPreInit(); 49 | // opMode.init(); 50 | // looping = false; 51 | // callToInitNeeded = false; 52 | // } 53 | // 54 | // /* 55 | // * NOTE: it's important that we use else if here, to avoid more than one user method 56 | // * being called during any one iteration. That, in turn, is important to make sure 57 | // * that if the force-stop logic manages to capture rogue user code, we can cleanly 58 | // * terminate the opmode immediately, without any other user methods being called. 59 | // */ 60 | // 61 | // else if (callToStartNeeded) { 62 | // opMode.inter 63 | // opMode.start(); 64 | // looping = true; 65 | // callToStartNeeded = false; 66 | // } 67 | // 68 | // else if (!looping) { 69 | // opMode.init_loop(); 70 | // } else if (looping) { 71 | // opMode.loop(); 72 | // } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /RobotLibrary/src/test/java/com/technototes/library/util/DifferentialTest.java: -------------------------------------------------------------------------------- 1 | package com.technototes.library.util; 2 | 3 | import java.util.function.DoubleConsumer; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class DifferentialTest { 8 | 9 | public Differential differential; 10 | 11 | public double d1, d2; 12 | public DoubleConsumer i1 = d -> d1 = d; 13 | public DoubleConsumer i2 = d -> d2 = d; 14 | 15 | @BeforeEach 16 | public void setup() { 17 | differential = new Differential(i1, i2); 18 | } 19 | 20 | @Test 21 | public void test() { 22 | check(0, 0); 23 | differential.setOutputs(0.2, 0.2); 24 | check(0.4, 0); 25 | differential.setAverageOutput(0.9); 26 | check(1, 0.7); 27 | 28 | differential.setPriority(Differential.DifferentialPriority.AVERAGE); 29 | check(1, 0.8); 30 | 31 | differential.setPriority(Differential.DifferentialPriority.DIFFERENCE); 32 | check(1, 0.6); 33 | 34 | differential.setOutputs(-0.4, -0.7); 35 | differential.setPriority(Differential.DifferentialPriority.NEUTRAL); 36 | check(-1, 0.3); 37 | 38 | differential.setPriority(Differential.DifferentialPriority.AVERAGE); 39 | check(-1, 0.2); 40 | 41 | differential.setPriority(Differential.DifferentialPriority.DIFFERENCE); 42 | check(-1, 0.4); 43 | 44 | differential.setLimits(0, 1); 45 | differential.setPriority(Differential.DifferentialPriority.NEUTRAL); 46 | check(0, 0.3); 47 | } 48 | 49 | public void check(double a1, double a2) { 50 | assert Math.abs(d1 - a1) + Math.abs(d2 - a2) < 0.00001; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Vision/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Vision/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | namespace = 'com.technototes.vision' 5 | 6 | lint { 7 | disable 'ExpiredTargetSdkVersion' 8 | } 9 | 10 | defaultConfig { 11 | minSdkVersion 24 12 | targetSdkVersion 28 13 | } 14 | 15 | compileSdkVersion 29 16 | 17 | compileOptions { 18 | sourceCompatibility JavaVersion.VERSION_1_8 19 | targetCompatibility JavaVersion.VERSION_1_8 20 | } 21 | } 22 | 23 | dependencies { 24 | 25 | implementation project(':RobotLibrary') 26 | 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation('org.ejml:ejml-simple:0.39') { 29 | exclude group: 'org.ejml', module: 'ejml-all' 30 | } 31 | 32 | implementation 'org.openftc:easyopencv:1.7.3' 33 | 34 | testImplementation(platform('org.junit:junit-bom:5.7.0')) 35 | testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.0') 36 | testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.0') 37 | testImplementation('org.mockito:mockito-core:3.5.11') 38 | testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.0" 39 | 40 | } 41 | 42 | task javadoc(type: Javadoc) { 43 | source = android.sourceSets.main.java.srcDirs 44 | classpath = project.files(android.getBootClasspath().join(File.pathSeparator)) 45 | failOnError false 46 | destinationDir = file("../docs/Vision/") 47 | options { 48 | linkSource true 49 | encoding = 'utf-8' 50 | } 51 | } 52 | 53 | afterEvaluate { 54 | javadoc.classpath += files(android.libraryVariants.collect { variant -> 55 | variant.javaCompileProvider.get().classpath.files 56 | }) 57 | } 58 | 59 | apply from: '../build.dependencies.gradle' 60 | -------------------------------------------------------------------------------- /Vision/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Vision/src/main/java/com/technototes/vision/HSVRange.java: -------------------------------------------------------------------------------- 1 | package com.technototes.vision; 2 | 3 | import org.opencv.core.Scalar; 4 | 5 | /** 6 | * This is used to detect colors in a particular HSV 'range' 7 | */ 8 | /** 9 | * This is used to detect colors in a particular HSV 'range' 10 | */ 11 | public class HSVRange { 12 | 13 | int hueLow, hueHigh; 14 | int satLow, satHigh; 15 | int valLow, valHigh; 16 | 17 | // Private constructor for wrap around/truncation stuff 18 | private HSVRange(int hLo, int hHi, HSVRange copyFrom) { 19 | hueLow = hLo; 20 | hueHigh = hHi; 21 | satLow = copyFrom.satLow; 22 | satHigh = copyFrom.satHigh; 23 | valLow = copyFrom.valLow; 24 | valHigh = copyFrom.valHigh; 25 | } 26 | 27 | /** 28 | * Create an HSV color range, around 'hue' (0-180, 2 degrees) 29 | * 30 | * @param hue The hue (0-179): each unit is *2* degrees! 31 | * @param hRange The +/- on the hue for detection 32 | * @param sLo The low saturation range 33 | * @param sHi The high saturation range 34 | * @param vLo The low value range 35 | * @param vHi The high value range 36 | */ 37 | public HSVRange(int hue, int hRange, int sLo, int sHi, int vLo, int vHi) { 38 | while (hue > 180) { 39 | hue -= 180; 40 | } 41 | while (hue < 0) { 42 | hue += 180; 43 | } 44 | hueLow = hue - Math.min(Math.abs(hRange), 89); 45 | hueHigh = hue + Math.min(Math.abs(hRange), 89); 46 | satLow = Math.min(sLo, sHi); 47 | satHigh = Math.max(sLo, sHi); 48 | valLow = Math.min(vLo, vHi); 49 | valHigh = Math.max(vLo, vHi); 50 | } 51 | 52 | /** 53 | * @return An HSVRange for the 'low end' of the hue range, if it's below 0, null otherwise 54 | */ 55 | public HSVRange makeWrapAround() { 56 | if (hueLow >= 0) { 57 | return null; 58 | } 59 | return new HSVRange(180 + hueLow, 180, this); 60 | } 61 | 62 | /** 63 | * @return An HSVRange for the positive part of a hue range if it spans across 0, null otherwise 64 | */ 65 | public HSVRange truncateRange() { 66 | if (hueLow < 0) { 67 | return new HSVRange(0, hueHigh, this); 68 | } 69 | return null; 70 | } 71 | 72 | /** 73 | * @param newHue The new hue for an existing HSVrange 74 | * @param hRange The new range for an existing HSVRange 75 | * @return A new HSVRange using the current Saturation and Values, with a new hue & hue range 76 | */ 77 | public HSVRange newHue(int newHue, int hRange) { 78 | return new HSVRange(newHue, hRange, satLow, satHigh, valLow, valHigh); 79 | } 80 | 81 | /** 82 | * @return A Scalar for OpenCV use for color detection for the low end 83 | */ 84 | public Scalar lowEdge() { 85 | return new Scalar(hueLow, satLow, valLow); 86 | } 87 | 88 | /** 89 | * @return A Scalar for OpenCV use for color detection for the high end 90 | */ 91 | public Scalar highEdge() { 92 | return new Scalar(hueHigh, satHigh, valHigh); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Vision/src/main/java/com/technototes/vision/hardware/InternalCamera.java: -------------------------------------------------------------------------------- 1 | package com.technototes.vision.hardware; 2 | 3 | import com.technototes.library.hardware.DummyDevice; 4 | import org.openftc.easyopencv.OpenCvCameraFactory; 5 | import org.openftc.easyopencv.OpenCvInternalCamera; 6 | 7 | /** 8 | * This is a Camera for use with a phone's internal camera 9 | */ 10 | @SuppressWarnings("unused") 11 | public class InternalCamera extends Camera> { 12 | 13 | /** 14 | * Create the front-facing internal camera 15 | */ 16 | public InternalCamera() { 17 | this(OpenCvInternalCamera.CameraDirection.FRONT); 18 | } 19 | 20 | /** 21 | * Create a camera (using the one on the phone for the CameraDirection) 22 | * 23 | * @param dir The direction (FRONT or REAR, probably) 24 | */ 25 | public InternalCamera(OpenCvInternalCamera.CameraDirection dir) { 26 | super(new DummyDevice<>(dir)); 27 | createCamera(); 28 | } 29 | 30 | /** 31 | * Get which internal camera is being used 32 | * 33 | * @return FRONT or REAR, probably (TODO) 34 | */ 35 | public OpenCvInternalCamera.CameraDirection getCameraDirection() { 36 | return getRawDevice().get(); 37 | } 38 | 39 | /** 40 | * Create an OpenCvInternalCamera from this Camera 41 | * 42 | * @return the OpenCvInternalCamera device 43 | */ 44 | @Override 45 | public OpenCvInternalCamera createCamera() { 46 | return OpenCvCameraFactory.getInstance() 47 | .createInternalCamera( 48 | getCameraDirection(), 49 | hardwareMap.appContext 50 | .getResources() 51 | .getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()) 52 | ); 53 | } 54 | 55 | // TODO: Should we log something? 56 | @Override 57 | public String LogLine() { 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Vision/src/main/java/com/technototes/vision/hardware/Webcam.java: -------------------------------------------------------------------------------- 1 | package com.technototes.vision.hardware; 2 | 3 | import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; 4 | import org.openftc.easyopencv.OpenCvCameraFactory; 5 | import org.openftc.easyopencv.OpenCvWebcam; 6 | 7 | /** 8 | * Acquire webcamera is just a quit constructor away :) 9 | */ 10 | public class Webcam extends Camera { 11 | 12 | /** 13 | * TODO: I'm not sure where WebcamName comes from. I should read up. 14 | * 15 | * @param device The WebcamName for the camera? 16 | */ 17 | public Webcam(WebcamName device) { 18 | super(device); 19 | } 20 | 21 | /** 22 | * Create a webcam device configured on the device with the given name 23 | * 24 | * @param device The name of the device as configured in "Robot Configuration" 25 | */ 26 | public Webcam(String device) { 27 | super(device); 28 | } 29 | 30 | // TODO: Should we log something? 31 | @Override 32 | public String LogLine() { 33 | return null; 34 | } 35 | 36 | /** 37 | * Create an OpenCvWebcam, which can then be used in your vision pipeline 38 | * 39 | * @return The OpenCvWebcam to use 40 | */ 41 | @Override 42 | public OpenCvWebcam createCamera() { 43 | return OpenCvCameraFactory.getInstance() 44 | .createWebcam( 45 | getRawDevice(), 46 | hardwareMap.appContext 47 | .getResources() 48 | .getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()) 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Vision/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /build.dependencies.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | google() // Needed for androidx 4 | maven { url = 'https://maven.brott.dev/' } 5 | maven { url 'https://jitpack.io' } 6 | } 7 | 8 | dependencies { 9 | implementation 'org.firstinspires.ftc:RobotCore:10.1.0' 10 | implementation 'org.firstinspires.ftc:RobotServer:10.1.0' 11 | implementation 'org.firstinspires.ftc:Hardware:10.1.0' 12 | implementation 'org.firstinspires.ftc:FtcCommon:10.1.0' 13 | implementation 'androidx.appcompat:appcompat:1.3.1' 14 | } 15 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | mavenCentral() 7 | google() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.2.0' 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | mavenCentral() 19 | google() 20 | } 21 | } 22 | 23 | repositories { 24 | mavenCentral() 25 | } 26 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/bun.lockb -------------------------------------------------------------------------------- /docs/TechnoLib/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 27 | 28 | 29 | 31 | 33 | 34 | -------------------------------------------------------------------------------- /docs/TechnoLib/element-list: -------------------------------------------------------------------------------- 1 | com.technototes.library 2 | com.technototes.library.command 3 | com.technototes.library.control 4 | com.technototes.library.general 5 | com.technototes.library.hardware 6 | com.technototes.library.hardware.motor 7 | com.technototes.library.hardware.sensor 8 | com.technototes.library.hardware.sensor.encoder 9 | com.technototes.library.hardware.servo 10 | com.technototes.library.logger 11 | com.technototes.library.logger.entry 12 | com.technototes.library.structure 13 | com.technototes.library.subsystem 14 | com.technototes.library.subsystem.drivebase 15 | com.technototes.library.util 16 | -------------------------------------------------------------------------------- /docs/TechnoLib/jquery-ui.overrides.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | .ui-state-active, 27 | .ui-widget-content .ui-state-active, 28 | .ui-widget-header .ui-state-active, 29 | a.ui-button:active, 30 | .ui-button:active, 31 | .ui-button.ui-state-active:hover { 32 | /* Overrides the color of selection used in jQuery UI */ 33 | background: #f8981d; 34 | } 35 | -------------------------------------------------------------------------------- /docs/TechnoLib/legal/ADDITIONAL_LICENSE_INFO: -------------------------------------------------------------------------------- 1 | Please see ..\java.base\ADDITIONAL_LICENSE_INFO 2 | -------------------------------------------------------------------------------- /docs/TechnoLib/legal/ASSEMBLY_EXCEPTION: -------------------------------------------------------------------------------- 1 | Please see ..\java.base\ASSEMBLY_EXCEPTION 2 | -------------------------------------------------------------------------------- /docs/TechnoLib/legal/LICENSE: -------------------------------------------------------------------------------- 1 | Please see ..\java.base\LICENSE 2 | -------------------------------------------------------------------------------- /docs/TechnoLib/legal/jquery.md: -------------------------------------------------------------------------------- 1 | ## jQuery v3.5.1 2 | 3 | ### jQuery License 4 | 5 | ``` 6 | jQuery v 3.5.1 7 | Copyright JS Foundation and other contributors, https://js.foundation/ 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | ****************************************** 29 | 30 | The jQuery JavaScript Library v3.5.1 also includes Sizzle.js 31 | 32 | Sizzle.js includes the following license: 33 | 34 | Copyright JS Foundation and other contributors, https://js.foundation/ 35 | 36 | This software consists of voluntary contributions made by many 37 | individuals. For exact contribution history, see the revision history 38 | available at https://github.com/jquery/sizzle 39 | 40 | The following license applies to all parts of this software except as 41 | documented below: 42 | 43 | ==== 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining 46 | a copy of this software and associated documentation files (the 47 | "Software"), to deal in the Software without restriction, including 48 | without limitation the rights to use, copy, modify, merge, publish, 49 | distribute, sublicense, and/or sell copies of the Software, and to 50 | permit persons to whom the Software is furnished to do so, subject to 51 | the following conditions: 52 | 53 | The above copyright notice and this permission notice shall be 54 | included in all copies or substantial portions of the Software. 55 | 56 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 57 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 59 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 60 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 61 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 62 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 63 | 64 | ==== 65 | 66 | All files located in the node_modules and external directories are 67 | externally maintained libraries used by this software which have their 68 | own licenses; we recommend you read them, as their terms may differ from 69 | the terms above. 70 | 71 | ********************* 72 | 73 | ``` 74 | -------------------------------------------------------------------------------- /docs/TechnoLib/legal/jqueryUI.md: -------------------------------------------------------------------------------- 1 | ## jQuery UI v1.12.1 2 | 3 | ### jQuery UI License 4 | ``` 5 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 6 | 7 | This software consists of voluntary contributions made by many 8 | individuals. For exact contribution history, see the revision history 9 | available at https://github.com/jquery/jquery-ui 10 | 11 | The following license applies to all parts of this software except as 12 | documented below: 13 | 14 | ==== 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining 17 | a copy of this software and associated documentation files (the 18 | "Software"), to deal in the Software without restriction, including 19 | without limitation the rights to use, copy, modify, merge, publish, 20 | distribute, sublicense, and/or sell copies of the Software, and to 21 | permit persons to whom the Software is furnished to do so, subject to 22 | the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be 25 | included in all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 31 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 32 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 33 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | 35 | ==== 36 | 37 | Copyright and related rights for sample code are waived via CC0. Sample 38 | code is defined as all source code contained within the demos directory. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | All files located in the node_modules and external directories are 45 | externally maintained libraries used by this software which have their 46 | own licenses; we recommend you read them, as their terms may differ from 47 | the terms above. 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/TechnoLib/module-search-index.js: -------------------------------------------------------------------------------- 1 | moduleSearchIndex = []; 2 | updateSearchResults(); 3 | -------------------------------------------------------------------------------- /docs/TechnoLib/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RobotLibrary API 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 18 | 19 | 20 |

21 | 24 |

index.html

25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/TechnoLib/package-search-index.js: -------------------------------------------------------------------------------- 1 | packageSearchIndex = [ 2 | { l: 'All Packages', u: 'allpackages-index.html' }, 3 | { l: 'com.technototes.library' }, 4 | { l: 'com.technototes.library.command' }, 5 | { l: 'com.technototes.library.control' }, 6 | { l: 'com.technototes.library.general' }, 7 | { l: 'com.technototes.library.hardware' }, 8 | { l: 'com.technototes.library.hardware.motor' }, 9 | { l: 'com.technototes.library.hardware.sensor' }, 10 | { l: 'com.technototes.library.hardware.sensor.encoder' }, 11 | { l: 'com.technototes.library.hardware.servo' }, 12 | { l: 'com.technototes.library.logger' }, 13 | { l: 'com.technototes.library.logger.entry' }, 14 | { l: 'com.technototes.library.structure' }, 15 | { l: 'com.technototes.library.subsystem' }, 16 | { l: 'com.technototes.library.subsystem.drivebase' }, 17 | { l: 'com.technototes.library.util' }, 18 | ]; 19 | updateSearchResults(); 20 | -------------------------------------------------------------------------------- /docs/TechnoLib/resources/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/resources/glass.png -------------------------------------------------------------------------------- /docs/TechnoLib/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/resources/x.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_glass_65_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_glass_65_dadada_1x400.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/docs/TechnoLib/script-dir/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /docs/TechnoLib/script-dir/jquery-ui.structure.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.12.1 - 2018-12-06 2 | * http://jqueryui.com 3 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 4 | 5 | .ui-helper-hidden { 6 | display: none; 7 | } 8 | .ui-helper-hidden-accessible { 9 | border: 0; 10 | clip: rect(0 0 0 0); 11 | height: 1px; 12 | margin: -1px; 13 | overflow: hidden; 14 | padding: 0; 15 | position: absolute; 16 | width: 1px; 17 | } 18 | .ui-helper-reset { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | outline: 0; 23 | line-height: 1.3; 24 | text-decoration: none; 25 | font-size: 100%; 26 | list-style: none; 27 | } 28 | .ui-helper-clearfix:before, 29 | .ui-helper-clearfix:after { 30 | content: ''; 31 | display: table; 32 | border-collapse: collapse; 33 | } 34 | .ui-helper-clearfix:after { 35 | clear: both; 36 | } 37 | .ui-helper-zfix { 38 | width: 100%; 39 | height: 100%; 40 | top: 0; 41 | left: 0; 42 | position: absolute; 43 | opacity: 0; 44 | filter: Alpha(Opacity=0); 45 | } 46 | .ui-front { 47 | z-index: 100; 48 | } 49 | .ui-state-disabled { 50 | cursor: default !important; 51 | pointer-events: none; 52 | } 53 | .ui-icon { 54 | display: inline-block; 55 | vertical-align: middle; 56 | margin-top: -0.25em; 57 | position: relative; 58 | text-indent: -99999px; 59 | overflow: hidden; 60 | background-repeat: no-repeat; 61 | } 62 | .ui-widget-icon-block { 63 | left: 50%; 64 | margin-left: -8px; 65 | display: block; 66 | } 67 | .ui-widget-overlay { 68 | position: fixed; 69 | top: 0; 70 | left: 0; 71 | width: 100%; 72 | height: 100%; 73 | } 74 | .ui-autocomplete { 75 | position: absolute; 76 | top: 0; 77 | left: 0; 78 | cursor: default; 79 | } 80 | .ui-menu { 81 | list-style: none; 82 | padding: 0; 83 | margin: 0; 84 | display: block; 85 | outline: 0; 86 | } 87 | .ui-menu .ui-menu { 88 | position: absolute; 89 | } 90 | .ui-menu .ui-menu-item { 91 | margin: 0; 92 | cursor: pointer; 93 | list-style-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); 94 | } 95 | .ui-menu .ui-menu-item-wrapper { 96 | position: relative; 97 | padding: 3px 1em 3px 0.4em; 98 | } 99 | .ui-menu .ui-menu-divider { 100 | margin: 5px 0; 101 | height: 0; 102 | font-size: 0; 103 | line-height: 0; 104 | border-width: 1px 0 0 0; 105 | } 106 | .ui-menu .ui-state-focus, 107 | .ui-menu .ui-state-active { 108 | margin: -1px; 109 | } 110 | .ui-menu-icons { 111 | position: relative; 112 | } 113 | .ui-menu-icons .ui-menu-item-wrapper { 114 | padding-left: 2em; 115 | } 116 | .ui-menu .ui-icon { 117 | position: absolute; 118 | top: 0; 119 | bottom: 0; 120 | left: 0.2em; 121 | margin: auto 0; 122 | } 123 | .ui-menu .ui-menu-icon { 124 | left: auto; 125 | right: 0; 126 | } 127 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/RobotLibrary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library;
 18 | 002
 19 | 003/** Root class for the Robot Library (I will put important stuff here)
 20 | 004 * @author Alex Stedman
 21 | 005 *
 22 | 006 */
 23 | 007@SuppressWarnings("unused")
 24 | 008public class RobotLibrary {
 25 | 009
 26 | 010    /** Get library version
 27 | 011     *
 28 | 012     * @return Library version
 29 | 013     */
 30 | 014    public static String getVersion() {
 31 | 015        return "2.0.1";
 32 | 016    }
 33 | 017
 34 | 018    /** Get if the library is a pre release
 35 | 019     *
 36 | 020     * @return If this library version is a pre release
 37 | 021     */
 38 | 022    public static boolean isPreRelease() {
 39 | 023        return false;
 40 | 024    }
 41 | 025}
 42 | 
 43 | 
 44 | 
 45 | 
 46 | 
 47 | 
 48 | 
 49 | 
 50 | 
 51 | 
 52 | 
 53 | 
 54 | 
 55 | 
 56 | 
 57 | 
 58 | 
 59 | 
 60 | 
 61 | 
 62 | 
 63 | 
 64 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
 96 | 
 97 | 
 98 | 
 99 | 
100 | 
101 | 
102 | 
103 |
104 |
105 | 106 | 107 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/general/Periodic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.general;
18 | 002
19 | 003/** An interface for classes to have the periodic function
20 | 004 * @author Alex Stedman
21 | 005 */
22 | 006@FunctionalInterface
23 | 007public interface Periodic {
24 | 008    /** The periodic function
25 | 009     */
26 | 010    void periodic();
27 | 011}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 | 
82 | 
83 | 
84 | 
85 | 
86 | 
87 | 
88 | 
89 |
90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/hardware/Sensored.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.hardware;
 18 | 002
 19 | 003import java.util.function.DoubleSupplier;
 20 | 004
 21 | 005/**
 22 | 006 * Class for hardware devices with a sensor value
 23 | 007 * <p>
 24 | 008 * This name is just bad. I'd also like to add normalization to it, so we could scale input values
 25 | 009 * to consistent ranges (triggers, joystick axes, distance sensors, servo ranges, etc...)
 26 | 010 *
 27 | 011 * @author Alex Stedman
 28 | 012 */
 29 | 013@SuppressWarnings("unused")
 30 | 014public interface Sensored extends DoubleSupplier {
 31 | 015    /**
 32 | 016     * Get the sensor value
 33 | 017     *
 34 | 018     * @return The value
 35 | 019     */
 36 | 020    double getSensorValue();
 37 | 021
 38 | 022    @Override
 39 | 023    default double getAsDouble() {
 40 | 024        return getSensorValue();
 41 | 025    }
 42 | 026}
 43 | 
 44 | 
 45 | 
 46 | 
 47 | 
 48 | 
 49 | 
 50 | 
 51 | 
 52 | 
 53 | 
 54 | 
 55 | 
 56 | 
 57 | 
 58 | 
 59 | 
 60 | 
 61 | 
 62 | 
 63 | 
 64 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
 96 | 
 97 | 
 98 | 
 99 | 
100 | 
101 | 
102 | 
103 | 
104 |
105 |
106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/hardware/sensor/IDistanceSensor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.hardware.sensor;
18 | 002
19 | 003import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit;
20 | 004
21 | 005public interface IDistanceSensor {
22 | 006    default double getDistance() {
23 | 007        return getDistance(getUnit());
24 | 008    }
25 | 009
26 | 010    double getDistance(DistanceUnit unit);
27 | 011
28 | 012    IDistanceSensor onUnit(DistanceUnit distanceUnit);
29 | 013
30 | 014    DistanceUnit getUnit();
31 | 015}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 | 
82 | 
83 | 
84 | 
85 | 
86 | 
87 | 
88 | 
89 | 
90 | 
91 | 
92 | 
93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/hardware/sensor/ILightSensor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.hardware.sensor;
18 | 002
19 | 003public interface ILightSensor {}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 |
82 |
83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/hardware/sensor/encoder/Encoder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 18 | 19 | 20 |
21 |
22 |
001package com.technototes.library.hardware.sensor.encoder;
 23 | 002
 24 | 003import com.technototes.library.hardware.Sensored;
 25 | 004
 26 | 005/** Interfaces for encoders to use
 27 | 006 * @author Alex Stedman
 28 | 007 */
 29 | 008public interface Encoder extends Sensored {
 30 | 009    /** zero the encoder
 31 | 010     *
 32 | 011     */
 33 | 012    void zeroEncoder();
 34 | 013
 35 | 014    default double getPosition() {
 36 | 015        return getSensorValue();
 37 | 016    }
 38 | 017}
 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 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
 96 | 
 97 | 
 98 | 
 99 | 
100 |
101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/logger/Loggable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.logger;
18 | 002
19 | 003/** All classes with annotations for logging must extend this all the way up the hierarchy up to the op mode
20 | 004 * @author Alex Stedman
21 | 005 */
22 | 006public interface Loggable {}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 | 
82 | 
83 | 
84 |
85 |
86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/logger/entry/BooleanEntry.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.logger.entry;
 18 | 002
 19 | 003import com.technototes.library.util.Color;
 20 | 004import java.util.function.Supplier;
 21 | 005
 22 | 006public class BooleanEntry extends Entry<Boolean> {
 23 | 007
 24 | 008    private String trueEntry, falseEntry;
 25 | 009
 26 | 010    public BooleanEntry(String n, Supplier<Boolean> s, int index, String wt, String wf) {
 27 | 011        super(n, s, index);
 28 | 012        trueEntry = wt;
 29 | 013        falseEntry = wf;
 30 | 014    }
 31 | 015
 32 | 016    @Override
 33 | 017    public String toString() {
 34 | 018        return (get() ? trueEntry : falseEntry);
 35 | 019    }
 36 | 020}
 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 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
 96 | 
 97 | 
98 |
99 |
100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/logger/entry/NumberEntry.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.logger.entry;
 18 | 002
 19 | 003import com.technototes.library.util.Color;
 20 | 004import java.util.function.Supplier;
 21 | 005
 22 | 006public class NumberEntry extends Entry<Number> {
 23 | 007
 24 | 008    protected Color numberColor;
 25 | 009
 26 | 010    public NumberEntry(String n, Supplier<Number> s, int x) {
 27 | 011        super(n, s, x);
 28 | 012    }
 29 | 013
 30 | 014    @Override
 31 | 015    public String toString() {
 32 | 016        return numberColor.format(get());
 33 | 017    }
 34 | 018}
 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 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
96 |
97 |
98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/logger/entry/StringEntry.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.logger.entry;
 18 | 002
 19 | 003import java.util.function.Supplier;
 20 | 004
 21 | 005public class StringEntry extends Entry<String> {
 22 | 006
 23 | 007    private String format;
 24 | 008
 25 | 009    public StringEntry(String n, Supplier<String> s, int x, String f) {
 26 | 010        super(n, s, x);
 27 | 011        format = f;
 28 | 012    }
 29 | 013
 30 | 014    @Override
 31 | 015    public String toString() {
 32 | 016        return String.format(format, get());
 33 | 017    }
 34 | 018}
 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 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
96 |
97 |
98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/subsystem/Subsystem.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.subsystem;
 18 | 002
 19 | 003import com.technototes.library.command.Command;
 20 | 004import com.technototes.library.command.CommandScheduler;
 21 | 005import com.technototes.library.general.Periodic;
 22 | 006
 23 | 007public interface Subsystem extends Periodic {
 24 | 008    default void register() {
 25 | 009        CommandScheduler.register(this);
 26 | 010    }
 27 | 011
 28 | 012    default Subsystem setDefaultCommand(Command c) {
 29 | 013        CommandScheduler.scheduleDefault(c, this);
 30 | 014        return this;
 31 | 015    }
 32 | 016
 33 | 017    default Command getDefaultCommand() {
 34 | 018        return CommandScheduler.getDefault(this);
 35 | 019    }
 36 | 020
 37 | 021    @Override
 38 | 022    default void periodic() {}
 39 | 023}
 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 | 
 65 | 
 66 | 
 67 | 
 68 | 
 69 | 
 70 | 
 71 | 
 72 | 
 73 | 
 74 | 
 75 | 
 76 | 
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 
 96 | 
 97 | 
 98 | 
 99 | 
100 | 
101 |
102 |
103 | 104 | 105 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/util/Characters.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.util;
18 | 002
19 | 003public class Characters {
20 | 004
21 | 005    public static final String BLUE_CIRCLE = "\uD83D\uDD35";
22 | 006    public static final String RED_SQUARE = "\uD83D\uDFE5";
23 | 007    public static final String DUCK = "\uD83E\uDD86";
24 | 008    public static final String CYCLE = "♻️";
25 | 009    public static final String GAMEPAD = "\uD83C\uDFAE";
26 | 010}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 | 
82 | 
83 | 
84 | 
85 | 
86 | 
87 | 
88 |
89 |
90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/TechnoLib/src-html/com/technototes/library/util/MapUtils.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source code 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
001package com.technototes.library.util;
18 | 002
19 | 003import android.util.Pair;
20 | 004import java.util.HashMap;
21 | 005import java.util.Map;
22 | 006
23 | 007public class MapUtils {
24 | 008
25 | 009    @SafeVarargs
26 | 010    public static <T, U> Map<T, U> of(Pair<T, U>... entries) {
27 | 011        Map<T, U> map = new HashMap<>();
28 | 012        for (Pair<T, U> e : entries) {
29 | 013            map.put(e.first, e.second);
30 | 014        }
31 | 015        return map;
32 | 016    }
33 | 017}
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 | 
65 | 
66 | 
67 | 
68 | 
69 | 
70 | 
71 | 
72 | 
73 | 
74 | 
75 | 
76 | 
77 | 
78 | 
79 | 
80 | 
81 | 
82 | 
83 | 
84 | 
85 | 
86 | 
87 | 
88 | 
89 | 
90 | 
91 | 
92 | 
93 | 
94 | 
95 |
96 |
97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/TechnoLib/tag-search-index.js: -------------------------------------------------------------------------------- 1 | tagSearchIndex = [{ l: 'Constant Field Values', h: '', u: 'constant-values.html' }]; 2 | updateSearchResults(); 3 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # TechnoLib documentation 2 | 3 | - [TechnoLib](https://technototes.github.io/TechnoLib/TechnoLib) 4 | - [Path](https://technototes.github.io/TechnoLib/Path) 5 | - [Vision](https://technototes.github.io/TechnoLib/Vision) 6 | - [Source Code](https://github.com/technototes/TechnoLib/) 7 | 8 | > TechnoLib is an FTC Library for everyone: 9 | 10 | - WPILib inspired command structure 11 | - Tons of simple implementations to provide abstractions, and teach you the basics 12 | - EasyOpenCV integration for vision 13 | - RoadRunner integration for path-following 14 | - Annotation based Telemetry 15 | 16 | **The goal of TechnoLib is not only to provide versatile resources that assist in software 17 | development and strengthen code structure, but to also abstract out redundancy.** 18 | 19 | ## Installation 20 | 21 | But if this library is so good, it must be hard to install right? wrong: 22 | 23 | - Add this right before the dependencies{} block in TeamCode/build.gradle: 24 | ``` 25 | repositories{ 26 | ` maven { url = 'https://maven.brott.dev/' } 27 | maven { url 'https://jitpack.io' } 28 | } 29 | ``` 30 | - And add this to the dependencies block in TeamCode/build.gradle: 31 | `implementation 'com.github.technototes:TechnoLib:1.1.2'` 32 | **(replace 1.1.2 with the latest release)** 33 | - Build the code and you are good to go 34 | 35 | ## Ease of Use 36 | 37 | But if this library is so powerful, won't it be hard to use? Nope, in fact its easier than without 38 | the library 39 | 40 | - Complex subsystems have already been written for you 41 | - Plenty of simple things to make your life easier 42 | - Test implementation so you can see how to make this work 43 | 44 | ## Documentation 45 | 46 | There are not currently any good 'stand alone' examples. The best place for you to get an idea of 47 | how this stuff works is in our robot code. It's all public on github: idea of how this stuff works 48 | is in our robot code. It's all public on github: 49 | 50 | - Freight Frenzy (2021-2022)' s 51 | [16750 robot source code](https://github.com/technototes/FreightFrenzy2021/tree/master/OspreyCode/src/main/java/org/firstinspires/ftc/teamcode) 52 | ( this is a more advanced usage, written by the library's primary autho) 53 | - Freight Frenzy (2021-2022)' s 54 | [20403 robot source code](https://github.com/technototes/FreightFrenzy2021/tree/master/SeagullCode/src/main/java/org/firstinspires/ftc/teamcode) 55 | ( This is a simpler usage, written by students who mostly learned by example) 56 | - And here's a PowerPlay (2022-2023) based example 57 | ["learning" bot](https://github.com/technototes/PowerPlay2022/tree/main/ForTeaching/src/main/java/org/firstinspires/ftc/forteaching/TechnoBot) 58 | ( This is a very basic example of a few concepts, include vision) 59 | 60 | Good luck! 61 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | android.enableJetifier=true 13 | android.useAndroidX=true 14 | org.gradle.jvmargs=-Xmx1536m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 27 22:08:26 PDT 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip 4 | distributionPath=wrapper/dists 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TechnoLib Documentation 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /notes.md: -------------------------------------------------------------------------------- 1 | # Notes for Kevin 2 | 3 | (I'm the software mentor for 16750/20403 and have picked up ownership of TechnLib from Alex Stedman, 4 | the original author, as he's doing silly things like "attending college") 5 | 6 | ## Hardware details to keep in mind 7 | 8 | The analog sticks are vertically inverted: When you push the stick up/away, the Y value decreases. 9 | 10 | The shoulder triggers' range is from 0 to 1, not -1 to 1. 11 | 12 | I'm not currently sure what orientation the SDK 8.1+ IMU calls 0 degrees. 13 | 14 | ## Simulation 15 | 16 | This has been in my head since my first year (2019, SkyStone) 17 | 18 | There ought to be a simulator for this stuff. It would let programmers work more independently to 19 | validate basic stuff. I've never built a simulator, but I'm a semi competent developer, so (famous 20 | last words) how hard can it be? ftcsim and vrs both lack some amount of flexibility, why doing a lot 21 | more than what I really need/want for a team who's building a real bot. 22 | 23 | The core things that would need simulated: 24 | 25 | - Motors (with encoders) 26 | - Servos (in both CR and Servo mode) 27 | - Sensors (pick the order to get them going) 28 | - IMU 29 | - Bump 30 | - Color 31 | - 2M range 32 | - Range 33 | 34 | Probably not worth simulating: 35 | 36 | - Vision. I could support connecting a webcam so the students could use an actual webcam, but I'm 37 | not about to deal with AprilTags and TFOD. ML sucks. It doesn't work at level level of determinism 38 | that makes me thing I could do anything useful with it. It's quantum physics, if the probability 39 | of weird stuff happening is 10^-2 instead of 10^-20000000. Thanks, but no thanks. 40 | - Controllers. Just wire them up from the computer 41 | 42 | Where do things get messy? I'd need some mechanism to translate rotational motion. I don't have the 43 | interest to do a full physics simulator, so I could potentially make this pretty rudimentary. 44 | 45 | ### What's next? 46 | 47 | Get through this season, then maybe start horsing around with this? Maybe learn Kotlin, since it 48 | looks _much_ less verbose than Java (Seriously, Java, you've had almost 30 years. Why do you still 49 | hate developers so much?) 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "technolib", 3 | "version": "1.3.1", 4 | "description": "TechnoLib automation scripts", 5 | "main": "build/automation.js", 6 | "repository": "https://github.com/technototes/TechnoLib.git", 7 | "author": "Kevin Frei ", 8 | "license": "MIT", 9 | "scripts": { 10 | "build": "bun run gradle build", 11 | "fulldoc": "bun run doc && bun run format", 12 | "docs": "bun run gradle javadoc", 13 | "doc": "bun run gradle javadoc", 14 | "format": "tools format bun", 15 | "gradle": "bun run os gradle", 16 | "gradle:win": ".\\\\gradlew", 17 | "gradle:def": "./gradlew", 18 | "os": "bun run scripts/os.ts" 19 | }, 20 | "devDependencies": { 21 | "@freik/workspace": "^0.6.4", 22 | "prettier": "3.3.3", 23 | "prettier-plugin-java": "2.6.4" 24 | }, 25 | "packageManager": "bun@1.1.27" 26 | } 27 | -------------------------------------------------------------------------------- /scripts/os.ts: -------------------------------------------------------------------------------- 1 | // This is a bun-specific replacement for the run-script-os NodeJS thing 2 | // It takes a script, and invokes the "script:os" command 3 | // if the script:win/mac/lin command doesn't exist, it falls back to the script:def command 4 | import path from 'path'; 5 | import fs from 'fs/promises'; 6 | import os from 'os'; 7 | import { chkObjectOf, hasFieldType, hasStrField, isString } from '@freik/typechk'; 8 | import Bun from 'bun'; 9 | 10 | const osmap = new Map([ 11 | ['win32', 'win'], 12 | ['darwin', 'mac'], 13 | ['linux', 'lin'], 14 | ]); 15 | 16 | async function main() { 17 | // argv[1] is this script's name, so find the package.json file from there 18 | const pkg = path.resolve(path.join(path.dirname(Bun.argv[1]), '..', 'package.json')); 19 | const args = Bun.argv.slice(2); 20 | const pkgj = JSON.parse(await fs.readFile(pkg, 'utf8')); 21 | if (!hasFieldType(pkgj, 'scripts', chkObjectOf(isString))) { 22 | throw new Error('No scripts field in package.json'); 23 | } 24 | const scriptName = args[0]; 25 | const suffix = osmap.get(os.platform()) || 'def'; 26 | const script = `${scriptName}:${suffix}`; 27 | const scriptdef = `${scriptName}:def`; 28 | const theScript = hasStrField(pkgj.scripts, script) 29 | ? script 30 | : hasStrField(pkgj.scripts, scriptdef) 31 | ? scriptdef 32 | : undefined; 33 | if (!isString(theScript)) { 34 | throw new Error(`No script found for ${scriptName} for ${os.platform()}`); 35 | } 36 | const cmds = args 37 | .slice(1) 38 | .map((v) => Bun.$.escape(v)) 39 | .join(' '); 40 | await Bun.$`bun run ${theScript} ${{ raw: cmds }}`; 41 | } 42 | 43 | main().catch((err) => console.error(err)); 44 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':RobotLibrary' 2 | include ':Path' 3 | include ':Vision' 4 | --------------------------------------------------------------------------------