From 31de1138a5d067ca3031770873815d55af8917a8 Mon Sep 17 00:00:00 2001 From: Rowan McAlpin <87948250+rowan-mcalpin@users.noreply.github.com> Date: Sat, 30 Nov 2024 21:07:27 -0800 Subject: [PATCH 01/10] GamepadEx modifications, created GamepadActionRunner --- ftc/src/main/kotlin/GamepadActionRunner.kt | 28 ++++++++ ftc/src/main/kotlin/GamepadEx.kt | 80 +++++++++------------- ftc/src/main/kotlin/UniqueActionRunner.kt | 2 +- 3 files changed, 60 insertions(+), 50 deletions(-) create mode 100644 ftc/src/main/kotlin/GamepadActionRunner.kt diff --git a/ftc/src/main/kotlin/GamepadActionRunner.kt b/ftc/src/main/kotlin/GamepadActionRunner.kt new file mode 100644 index 0000000..c0589fb --- /dev/null +++ b/ftc/src/main/kotlin/GamepadActionRunner.kt @@ -0,0 +1,28 @@ +import com.qualcomm.robotcore.hardware.Gamepad + +/** + * This is an ActionRunner that runs actions automatically when certain buttons are pressed on the gamepads. + */ +class GamepadActionRunner(qualcommGamepad1: Gamepad, qualcommGamepad2: Gamepad): UniqueActionRunner() { + /** + * A GamepadEx reference used for mapping actions to buttons/joysticks/triggers + */ + val gamepad1 = GamepadEx(qualcommGamepad1) + + /** + * A GamepadEx reference used for mapping actions to buttons/joysticks/triggers + */ + val gamepad2 = GamepadEx(qualcommGamepad2) + + /** + * This function should be called every loop, as it handles updating the gamepads and running their mapped actions + */ + fun update() { + gamepad1.update().forEach { + runAsync(it) + } + gamepad2.update().forEach { + runAsync(it) + } + } +} \ No newline at end of file diff --git a/ftc/src/main/kotlin/GamepadEx.kt b/ftc/src/main/kotlin/GamepadEx.kt index a05e2c2..5086850 100644 --- a/ftc/src/main/kotlin/GamepadEx.kt +++ b/ftc/src/main/kotlin/GamepadEx.kt @@ -1,4 +1,3 @@ -import com.acmerobotics.dashboard.telemetry.TelemetryPacket import com.acmerobotics.roadrunner.Action import com.qualcomm.robotcore.hardware.Gamepad import kotlin.math.abs @@ -9,9 +8,6 @@ import kotlin.math.abs * @param gamepad the Qualcomm gamepad to observe. It should be `gamepad1` or `gamepad2`, unless you're doing something funky. */ class GamepadEx(gamepad: Gamepad) { - - private var runningActions: List = mutableListOf() - val a = Button("A") { gamepad.a } val b = Button("B") { gamepad.b } val x = Button("X") { gamepad.x } @@ -34,8 +30,6 @@ class GamepadEx(gamepad: Gamepad) { val controls = listOf(a, b, x, y, dpadUp, dpadDown, dpadLeft, dpadRight, leftBumper, rightBumper, leftTrigger, rightTrigger, leftStick, rightStick) - val updateAction = UpdateGamepadAction() - fun setTriggerThresholds(threshold: Float) { leftTrigger.threshold = threshold rightTrigger.threshold = threshold @@ -46,30 +40,15 @@ class GamepadEx(gamepad: Gamepad) { rightStick.threshold = threshold } - /** - * In order to map actions to gamepad buttons, this Action must be added. It handles updating the controls, and runs - * the actions as needed. This class should not be directly instantiated by the user, instead use the `updateAction` - * variable to reference the already-created instance of this class. - */ - inner class UpdateGamepadAction: Action { - override fun run(p: TelemetryPacket): Boolean { - controls.forEach { - it.update() - } - - val newRunningActionList = mutableListOf() - runningActions.forEach { action -> - action.preview(p.fieldOverlay()) - if (action.run(p)) { - newRunningActionList.add(action) - } - } - runningActions = newRunningActionList + fun update(): Array { + val actionsArray = mutableListOf() - return true + controls.forEach { + actionsArray.addAll(it.update()) } - } + return actionsArray.toTypedArray() + } /** * Wrapper for an individual button on a gamepad. @@ -112,25 +91,27 @@ class GamepadEx(gamepad: Gamepad) { /** * Updates the various values, and adds mapped actions if applicable */ - override fun update() { + override fun update(): List { + + val actionList = mutableListOf() + justPressed = controlToWatch.invoke() && !down justReleased = !controlToWatch.invoke() && down down = controlToWatch.invoke() // If there are mapped actions, request to run them if (justPressed && onPressActionMap != null) { - runningActions += onPressActionMap!! + actionList += onPressActionMap!! } if (justReleased && onReleaseActionMap != null) { - runningActions += onReleaseActionMap!! + actionList += onReleaseActionMap!! } if (down && heldActionMap != null) { - // We only want to add one instance of the heldAction at a time. - if (!runningActions.contains(heldActionMap!!)) { - runningActions += heldActionMap!! - } + actionList += heldActionMap!! } + + return actionList } override fun toString(): String { @@ -194,25 +175,25 @@ class GamepadEx(gamepad: Gamepad) { /** * Updates the various values, and adds mapped actions if applicable */ - override fun update() { + override fun update(): List { + val actionList = mutableListOf() justPressed = controlToWatch.invoke() > threshold && !down justReleased = controlToWatch.invoke() <= threshold && down amount = controlToWatch.invoke() // If there are mapped actions, request to run them if (justPressed && onPressActionMap != null) { - runningActions += onPressActionMap!! + actionList += onPressActionMap!! } if (justReleased && onReleaseActionMap != null) { - runningActions += onReleaseActionMap!! + actionList += onReleaseActionMap!! } if (down && heldActionMap != null) { - // We only want to add one instance of the heldAction at a time. - if (!runningActions.contains(heldActionMap!!)) { - runningActions += heldActionMap!! - } + actionList += heldActionMap!! } + + return actionList } /** @@ -287,7 +268,9 @@ class GamepadEx(gamepad: Gamepad) { /** * Updates the various values, and adds mapped actions if applicable */ - override fun update() { + override fun update(): List { + val actionList = mutableListOf() + button.update() justMoved = (abs(xToWatch.invoke()) > threshold || abs(yToWatch.invoke()) > threshold) && !moved @@ -298,18 +281,17 @@ class GamepadEx(gamepad: Gamepad) { // If there are mapped actions, request to run them if (justMoved && onMoveActionMap != null) { - runningActions += onMoveActionMap!! + actionList += onMoveActionMap!! } if (justCentered && onCenterActionMap != null) { - runningActions += onCenterActionMap!! + actionList += onCenterActionMap!! } if (moved && offCenterActionMap != null) { - // We only want to add one instance of the heldAction at a time. - if (!runningActions.contains(offCenterActionMap!!)) { - runningActions += offCenterActionMap!! - } + actionList += offCenterActionMap!! } + + return actionList } /** @@ -337,7 +319,7 @@ class GamepadEx(gamepad: Gamepad) { /** * Updates the various values, and adds mapped actions if applicable */ - fun update() + fun update(): List } } \ No newline at end of file diff --git a/ftc/src/main/kotlin/UniqueActionRunner.kt b/ftc/src/main/kotlin/UniqueActionRunner.kt index 1c9a51a..4d8c0e2 100644 --- a/ftc/src/main/kotlin/UniqueActionRunner.kt +++ b/ftc/src/main/kotlin/UniqueActionRunner.kt @@ -5,7 +5,7 @@ import com.qualcomm.robotcore.util.RobotLog.a import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract -class UniqueActionRunner: ActionRunner() { +open class UniqueActionRunner: ActionRunner() { private val uniqueActionsQueue = ArrayList() From bb356f2c50b3a9715f5b75b1d5fa77be190b1825 Mon Sep 17 00:00:00 2001 From: Rowan McAlpin <87948250+rowan-mcalpin@users.noreply.github.com> Date: Sat, 30 Nov 2024 21:21:27 -0800 Subject: [PATCH 02/10] Fix bug, add initialize() function --- .../expressway/ftc/GamepadActionRunner.kt | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ftc/src/main/kotlin/page/j5155/expressway/ftc/GamepadActionRunner.kt b/ftc/src/main/kotlin/page/j5155/expressway/ftc/GamepadActionRunner.kt index a06b0ea..d38ae41 100644 --- a/ftc/src/main/kotlin/page/j5155/expressway/ftc/GamepadActionRunner.kt +++ b/ftc/src/main/kotlin/page/j5155/expressway/ftc/GamepadActionRunner.kt @@ -5,16 +5,25 @@ import com.qualcomm.robotcore.hardware.Gamepad /** * This is an ActionRunner that runs actions automatically when certain buttons are pressed on the gamepads. */ -class GamepadActionRunner(qualcommGamepad1: Gamepad, qualcommGamepad2: Gamepad): UniqueActionRunner() { +class GamepadActionRunner: UniqueActionRunner() { /** - * A page.j5155.expressway.ftc.GamepadEx reference used for mapping actions to buttons/joysticks/triggers + * A GamepadEx reference used for mapping actions to buttons/joysticks/triggers */ - val gamepad1 = GamepadEx(qualcommGamepad1) + lateinit var gamepad1: GamepadEx /** - * A page.j5155.expressway.ftc.GamepadEx reference used for mapping actions to buttons/joysticks/triggers + * A GamepadEx reference used for mapping actions to buttons/joysticks/triggers */ - val gamepad2 = GamepadEx(qualcommGamepad2) + lateinit var gamepad2: GamepadEx + + /** + * This function initializes the gamepads. It MUST be called prior to the first time update() is called. Ideally is + * called as the first thing in the OpMode. + */ + fun initialize(gamepad1: Gamepad, gamepad2: Gamepad) { + this.gamepad1 = GamepadEx(gamepad1) + this.gamepad2 = GamepadEx(gamepad2) + } /** * This function should be called every loop, as it handles updating the gamepads and running their mapped actions From 25c72905e0f6edd5b39ca61b20f2d1155b54f2c4 Mon Sep 17 00:00:00 2001 From: Rowan McAlpin <87948250+rowan-mcalpin@users.noreply.github.com> Date: Sat, 30 Nov 2024 21:49:49 -0800 Subject: [PATCH 03/10] Added GamepadActionLinearOpMode wrapper --- .idea/gradle.xml | 2 -- .../kotlin/page/j5155/expressway/ftc/ActionLinearOpMode.kt | 2 +- .../page/j5155/expressway/ftc/GamepadActionLinearOpMode.kt | 3 +++ 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 ftc/src/main/kotlin/page/j5155/expressway/ftc/GamepadActionLinearOpMode.kt diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 886ab0f..1596386 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -6,7 +6,6 @@ -