Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/software/thunderscope/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package(default_visibility = ["//visibility:public"])
compile_pip_requirements(
name = "requirements",
src = "requirements.in",
requirements_darwin = "requirements_lock.darwin.txt",
requirements_txt = "requirements_lock.txt",
)

Expand Down
9 changes: 0 additions & 9 deletions src/software/thunderscope/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,15 +327,6 @@ class TrailValues:
class DiagnosticsConstants:
"""Constants for Robot Diagnostics"""

# Device names of the controllers supported for controlling robots
SUPPORTED_CONTROLLERS = {
"Microsoft Xbox One X pad",
"Microsoft X-Box One S pad",
"Microsoft X-Box 360 pad",
"Microsoft Xbox 360 pad",
"Generic X-Box pad",
}

BUTTON_PRESSED_THRESHOLD = 0.5
DEADZONE_PERCENTAGE = 0.20

Expand Down
2 changes: 1 addition & 1 deletion src/software/thunderscope/requirements.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
colorama==0.4.6
netifaces==0.11.0
evdev==1.7.0; sys_platform == "linux"
numpy==1.26.4
protobuf==6.31.1
pyserial==3.5
pygame==2.6.1
pyqtgraph==0.13.7
pyqtdarktheme-fork==2.3.2
PyQt6-Qt6==6.8.1
Expand Down
136 changes: 0 additions & 136 deletions src/software/thunderscope/requirements_lock.darwin.txt

This file was deleted.

65 changes: 62 additions & 3 deletions src/software/thunderscope/requirements_lock.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ darkdetect==0.7.1 \
--hash=sha256:3efe69f8ecd5f1b7f4fbb0d1d93f656b0e493c45cc49222380ffe2a529cbc866 \
--hash=sha256:47be3cf5134432ddb616bbffc927237718407914993c82809983e7ccebf49013
# via pyqtdarktheme-fork
evdev==1.7.0 ; sys_platform == "linux" \
--hash=sha256:95bd2a1e0c6ce2cd7a2ecc6e6cd9736ff794b3ad5cb54d81d8cbc2e414d0b870
# via -r software/thunderscope/requirements.in
netifaces==0.11.0 \
--hash=sha256:043a79146eb2907edf439899f262b3dfe41717d34124298ed281139a8b93ca32 \
--hash=sha256:08e3f102a59f9eaef70948340aeb6c89bd09734e0dca0f3b82720305729f63ea \
Expand Down Expand Up @@ -102,6 +99,68 @@ protobuf==6.31.1 \
--hash=sha256:a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39 \
--hash=sha256:d8cac4c982f0b957a4dc73a80e2ea24fab08e679c0de9deb835f4a12d69aca9a
# via -r software/thunderscope/requirements.in
pygame==2.6.1 \
--hash=sha256:00827aba089355925902d533f9c41e79a799641f03746c50a374dc5c3362e43d \
--hash=sha256:10e3d2a55f001f6c0a6eb44aa79ea7607091c9352b946692acedb2ac1482f1c9 \
--hash=sha256:1206125f14cae22c44565c9d333607f1d9f59487b1f1432945dfc809aeaa3e88 \
--hash=sha256:14f9dda45469b254c0f15edaaeaa85d2cc072ff6a83584a265f5d684c7f7efd8 \
--hash=sha256:15efaa11a80a65dd589a95bebe812fa5bfc7e14946b638a424c5bd9ac6cca1a4 \
--hash=sha256:163e66de169bd5670c86e27d0b74aad0d2d745e3b63cf4e7eb5b2bff1231ca8d \
--hash=sha256:173badf82fa198e6888017bea40f511cb28e69ecdd5a72b214e81e4dcd66c3b1 \
--hash=sha256:17498a2b043bc0e795faedef1b081199c688890200aef34991c1941caa2d2c89 \
--hash=sha256:20349195326a5e82a16e351ed93465a7845a7e2a9af55b7bc1b2110ea3e344e1 \
--hash=sha256:21160d9093533eb831f1b708e630706e5ac16b30750571ec27bc3b8364814f38 \
--hash=sha256:27eb17e3dc9640e4b4683074f1890e2e879827447770470c2aba9f125f74510b \
--hash=sha256:28b43190436037e428a5be28fc80cf6615304fd528009f2c688cc828f4ff104b \
--hash=sha256:2a3a1288e2e9b1e5834e425bedd5ba01a3cd4902b5c2bff8ed4a740ccfe98171 \
--hash=sha256:2a615d78b2364e86f541458ff41c2a46181b9a1e9eabd97b389282fdf04efbb3 \
--hash=sha256:325a84d072d52e3c2921eff02f87c6a74b7e77d71db3bdf53801c6c975f1b6c4 \
--hash=sha256:33006f784e1c7d7e466fcb61d5489da59cc5f7eb098712f792a225df1d4e229d \
--hash=sha256:3a9e7396be0d9633831c3f8d5d82dd63ba373ad65599628294b7a4f8a5a01a65 \
--hash=sha256:3acd8c009317190c2bfd81db681ecef47d5eb108c2151d09596d9c7ea9df5c0e \
--hash=sha256:3bede70ec708057e305815d6546012669226d1d80566785feca9b044216062e7 \
--hash=sha256:481cfe1bdbb7fe00acc5950c494c26f00240888619bdc396fc8c39a734797432 \
--hash=sha256:4a8ea113b1bf627322a025a1a5a87e3818a7f55ab3a4077ff1ae5c8c60576614 \
--hash=sha256:4c1623180e70a03c4a734deb9bac50fc9c82942ae84a3a220779062128e75f3b \
--hash=sha256:4ee7f2771f588c966fa2fa8b829be26698c9b4836f82ede5e4edc1a68594942e \
--hash=sha256:56fb02ead529cee00d415c3e007f75e0780c655909aaa8e8bf616ee09c9feb1f \
--hash=sha256:56ffca6059b165bbf64f4b4be23b8068f6a0e220780e4f96ec0bb5ac3c63ec39 \
--hash=sha256:5d09fd950725d187aa5207c0cb8eb9ab0d2f8ce9ab8d189c30eeb470e71b617e \
--hash=sha256:6582aa71a681e02e55d43150a9ab41394e6bf4d783d2962a10aea58f424be060 \
--hash=sha256:7103c60939bbc1e05cfc7ba3f1d2ad3bbf103b7828b82a7166a9ab6f51950146 \
--hash=sha256:7bffdd3eaf394d9645331d1c3a5df9d782ebcc3c5a78f3b657c7879a828dd111 \
--hash=sha256:811e7b925146d8149d79193652cbb83e0eca0aae66476b1cb310f0f4226b8b5c \
--hash=sha256:813af4fba5d0b2cb8e58f5d95f7910295c34067dcc290d34f1be59c48bd1ea6a \
--hash=sha256:816e85000c5d8b02a42b9834f761a5925ef3377d2924e3a7c4c143d2990ce5b8 \
--hash=sha256:818b4eaec9c4acb6ac64805d4ca8edd4062bebca77bd815c18739fe2842c97e9 \
--hash=sha256:84fc4054e25262140d09d39e094f6880d730199710829902f0d8ceae0213379e \
--hash=sha256:8a78fd030d98faab4a8e27878536fdff7518d3e062a72761c552f624ebba5a5f \
--hash=sha256:91476902426facd4bb0dad4dc3b2573bc82c95c71b135e0daaea072ed528d299 \
--hash=sha256:94afd1177680d92f9214c54966ad3517d18210c4fbc5d84a0192d218e93647e0 \
--hash=sha256:97ac4e13847b6b293ecaffa5ffce9886c98d09c03309406931cc592f0cea6366 \
--hash=sha256:9beeb647e555afb5657111fa83acb74b99ad88761108eaea66472e8b8547b55b \
--hash=sha256:9dd5c054d4bd875a8caf978b82672f02bec332f52a833a76899220c460bb4b58 \
--hash=sha256:a1bf7ab5311bbced70320f1a56701650b4c18231343ae5af42111eea91e0949a \
--hash=sha256:a4b8f04fceddd9a3ac30778d11f0254f59efcd1c382d5801271113cea8b4f2f3 \
--hash=sha256:a620883d589926f157b8f1d1f543183ac52e5c30507dea445e3927ae0bee1c54 \
--hash=sha256:ac3f033d2be4a9e23660a96afe2986df3a6916227538a6a0061bc218c5088507 \
--hash=sha256:ae6039f3a55d800db80e8010f387557b528d34d534435e0871326804df2a62f2 \
--hash=sha256:b46e68cd168f44d0224c670bb72186688fc692d7079715f79d04096757d703d0 \
--hash=sha256:b7f9f8e6f76de36f4725175d686601214af362a4f30614b4dae2240198e72e6f \
--hash=sha256:bbb7167c92103a2091366e9af26d4914ba3776666e8677d3c93551353fffa626 \
--hash=sha256:c0b11356ac96261162d54a2c2b41a41978f00525631b01ec9c4fe26b01c66595 \
--hash=sha256:c31dbdb5d0217f32764797d21c2752e258e5fb7e895326538d82b5f75a0cd856 \
--hash=sha256:c47a6938de93fa610accd4969e638c2aebcb29b2fca518a84c3a39d91ab47116 \
--hash=sha256:c8040ea2ab18c6b255af706ec01355c8a6b08dc48d77fd4ee783f8fc46a843bf \
--hash=sha256:ce8cc108b92de9b149b344ad2e25eedbe773af0dc41dfb24d1f07f679b558c60 \
--hash=sha256:d1a7f2b66ac2e4c9583b6d4c6d6f346fb10a3392c04163f537061f86a448ed5c \
--hash=sha256:d29eb9a93f12aa3d997b6e3c447ac85b2a4b142ab2548441523a8fcf5e216042 \
--hash=sha256:da3ad64d685f84a34ebe5daacb39fff14f1251acb34c098d760d63fee768f50c \
--hash=sha256:ef07c0103d79492c21fced9ad68c11c32efa6801ca1920ebfd0f15fb46c78b1c \
--hash=sha256:f3935459109da4bb0b3901da9904f0a3e52028a3332a355d298b1673a334cf21 \
--hash=sha256:f84f15d146d6aa93254008a626c56ef96fed276006202881a47b29757f0cd65a \
--hash=sha256:fb6e8d0547f30ddc845f4fd1e33070ef548233ad0dbf21f7ecea768883d1bbdc
# via -r software/thunderscope/requirements.in
pyqt-toast-notification==1.3.2 \
--hash=sha256:135736ec0f16bff41104dee3c60ac318e5d55ae3378bf26892c6d08c36088ae6 \
--hash=sha256:82688101202737736d51ab6c74a573b32266ecb7c8b0002f913407bd369737d9
Expand Down
29 changes: 23 additions & 6 deletions src/software/thunderscope/robot_diagnostics/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,41 @@ py_library(
],
)

py_library(
name = "keyboard_controller",
srcs = ["keyboard_controller.py"],
deps = [
":controller_base",
"//software/thunderscope:constants",
requirement("pyqtgraph"),
],
)

py_library(
name = "handheld_controller",
srcs = ["handheld_controller.py"],
deps = [
":controller_base",
"//software/thunderscope:constants",
requirement("pygame"),
],
)

py_library(
name = "controller_base",
srcs = ["controller_base.py"],
)

py_library(
name = "handheld_controller_widget",
srcs = ["handheld_controller_widget.py"],
deps = [
":controller_base",
":handheld_controller",
":keyboard_controller",
"//software/thunderscope:constants",
requirement("pyqtgraph"),
] + select({
# TODO: remove this selection when we replace evdev to
# other macos supported libs.
"@platforms//os:linux": [requirement("evdev")],
"//conditions:default": [],
}),
],
)

py_library(
Expand Down
56 changes: 56 additions & 0 deletions src/software/thunderscope/robot_diagnostics/controller_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from abc import ABC, abstractmethod


class IControllerBase(ABC):
"""Abstract base class for controller input sources."""

@abstractmethod
def name(self) -> str:
"""Get the display name of the input source."""

@abstractmethod
def connected(self) -> bool:
"""Return true if the input source is active and available."""

@abstractmethod
def close(self) -> None:
"""Release any resources held by the input source."""

def update(self) -> None:
"""Refresh controller input state. Called once per frame before reading inputs.
Override for polled backends; push-based controllers can leave this as a no-op.
"""

@abstractmethod
def get_move_velocity(self) -> tuple[float, float, float]:
"""Return (x, y, angular) velocity, each normalized to [-1, 1] with deadzone applied.
Positive x = forward, positive y = strafe left, positive angular = CCW.
"""

@abstractmethod
def get_speed_factor(self) -> float:
"""Return 1.0 normally, or SPEED_SLOWDOWN_FACTOR when slowdown input is active."""

@abstractmethod
def is_dribbler_held(self) -> bool:
"""Return True if the dribbler engage input is active."""

@abstractmethod
def get_kick_power_step(self) -> int:
"""Return -1, 0, or +1 for kick/chip power step direction.
Non-zero only once per new input (edge-detected).
"""

@abstractmethod
def get_dribbler_step(self) -> int:
"""Return -1, 0, or +1 for dribbler RPM step direction.
Non-zero only once per new input (edge-detected).
"""

@abstractmethod
def is_kick_fired(self) -> bool:
"""Return True once per kick button press (rising edge only)."""

@abstractmethod
def is_chip_fired(self) -> bool:
"""Return True once per chip button press (rising edge only)."""
Loading
Loading