Skip to content

Commit e28a73e

Browse files
committed
Merge branch 'smooth_thrusters' of github.com:CWRUbotix/rov-25 into smooth_thrusters
2 parents 1a19fd2 + 652431f commit e28a73e

File tree

15 files changed

+97
-112
lines changed

15 files changed

+97
-112
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
repos:
33
- repo: https://github.com/astral-sh/ruff-pre-commit
44
# Ruff version.
5-
rev: v0.7.1
5+
rev: v0.8.1
66
hooks:
77
# Run the linter.
88
- id: ruff
@@ -11,7 +11,7 @@ repos:
1111
# Run the formatter.
1212
- id: ruff-format
1313
- repo: https://github.com/pre-commit/mirrors-clang-format
14-
rev: v19.1.2
14+
rev: v19.1.4
1515
hooks:
1616
- id: clang-format
1717
types_or: [c++, c]
@@ -21,6 +21,6 @@ repos:
2121
hooks:
2222
- id: trailing-whitespace
2323
- repo: https://github.com/google/yamlfmt
24-
rev: v0.13.0
24+
rev: v0.14.0
2525
hooks:
2626
- id: yamlfmt

src/pi/manipulators/manipulators/valve_manipulator_dry_run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
FREQ = 50
88

99
gpio_handle = lgpio.gpiochip_open(0)
10+
lgpio.gpio_claim_output(gpio_handle, SERVO_PIN)
1011

1112

1213
def test_gpio(width: int, freq: int = 50) -> None:

src/pi/manipulators/manipulators/valve_manipulator_node.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Final
2+
13
import lgpio
24
import rclpy
35
from rclpy.node import Node
@@ -6,7 +8,7 @@
68
from rov_msgs.msg import ValveManip
79

810
# Configuration
9-
SERVO_PIN = 12 # pin used to drive Valve Manip
11+
SERVO_PIN: Final = 12 # pin used to drive Valve Manip
1012

1113

1214
class ValveManipulator(Node):
@@ -17,6 +19,7 @@ def __init__(self) -> None:
1719
)
1820

1921
self.gpio_handle = lgpio.gpiochip_open(0)
22+
lgpio.gpio_claim_output(self.gpio_handle, SERVO_PIN)
2023
self.curr_active = False
2124

2225
def servo(self, width: int, freq: int = 50) -> None:

src/surface/flight_control/flight_control/manual_control_node.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ def __init__(self) -> None:
9393
self.arm_client = self.create_client(CommandBool, 'mavros/cmd/arming')
9494

9595
self.manip_buttons: dict[int, ManipButton] = {
96-
X_BUTTON: ManipButton('left'),
97-
O_BUTTON: ManipButton('right'),
96+
X_BUTTON: ManipButton('right'),
97+
O_BUTTON: ManipButton('left'),
9898
}
9999

100100
self.seen_left_cam = False
@@ -125,16 +125,14 @@ def joystick_to_pixhawk(self, msg: Joy) -> None:
125125

126126
def manip_callback(self, msg: Joy) -> None:
127127
buttons: MutableSequence[int] = msg.buttons
128-
129128
for button_id, manip_button in self.manip_buttons.items():
130129
just_pressed = buttons[button_id] == PRESSED
131-
132130
if manip_button.last_button_state is False and just_pressed:
133131
new_manip_state = not manip_button.is_active
134132
manip_button.is_active = new_manip_state
135-
136133
manip_msg = Manip(manip_id=manip_button.claw, activated=manip_button.is_active)
137134
self.manip_publisher.publish(manip_msg)
135+
138136
manip_button.last_button_state = just_pressed
139137

140138
def valve_manip_callback(self, msg: Joy) -> None:

src/surface/flight_control/flight_control/multiplexer.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,11 @@ def control_callback(self, msg: PixhawkInstruction) -> None:
137137
# TODO: look into maybe doing inheritance on a PixhawkInstruction
138138
msg = apply_function(msg, joystick_map)
139139
elif (
140-
(msg.author == PixhawkInstruction.KEYBOARD_CONTROL
141-
and self.state == AutonomousFlight.Request.STOP)
142-
or (msg.author == PixhawkInstruction.AUTONOMOUS_CONTROL
143-
and self.state == AutonomousFlight.Request.START)
140+
msg.author == PixhawkInstruction.KEYBOARD_CONTROL
141+
and self.state == AutonomousFlight.Request.STOP
142+
) or (
143+
msg.author == PixhawkInstruction.AUTONOMOUS_CONTROL
144+
and self.state == AutonomousFlight.Request.START
144145
):
145146
pass
146147
else:
Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,57 @@
1-
from PyQt6.QtWidgets import QPushButton, QWidget
2-
3-
4-
class IndicatorMixin(QWidget):
5-
_PROPERTY_NAME = 'widgetState'
6-
7-
# A component is running, enabled, or armed
8-
_ON = 'on'
1+
from enum import IntEnum
2+
from typing import Final
93

10-
# A component is disabled, not running, or disarmed, but could be enabled through this widget
11-
_OFF = 'off'
12-
13-
# A component is disabled, not expected to have any effect or perform its function because of
14-
# some external factor, either another widget or something external to the gui
15-
# For example, a the arm button when the pi is not connected
16-
_INACTIVE = 'inactive'
17-
18-
# Removes any state
19-
_NO_STATE = ''
20-
21-
def set_on(self) -> None:
22-
self.setProperty(IndicatorMixin._PROPERTY_NAME, IndicatorMixin._ON)
23-
self._update_style()
4+
from PyQt6.QtWidgets import QPushButton, QWidget
245

25-
def set_off(self) -> None:
26-
self.setProperty(IndicatorMixin._PROPERTY_NAME, IndicatorMixin._OFF)
27-
self._update_style()
286

29-
def set_inactive(self) -> None:
30-
self.setProperty(IndicatorMixin._PROPERTY_NAME, IndicatorMixin._INACTIVE)
31-
self._update_style()
7+
class WidgetState(IntEnum):
8+
ON = 1
9+
OFF = 2
10+
INACTIVE = 3
11+
NONE = 4
3212

33-
def remove_state(self) -> None:
34-
self.setProperty(IndicatorMixin._PROPERTY_NAME, IndicatorMixin._NO_STATE)
35-
self._update_style()
3613

37-
def _update_style(self) -> None:
38-
style = self.style()
39-
if style is not None:
40-
style.polish(self)
14+
class IndicatorMixin(QWidget):
15+
# The stylesheets that correspond to each widget state
16+
_STYLESHEETS: Final[dict[WidgetState, str]] = {
17+
# Stylesheet for when a component is running, enabled, or armed
18+
WidgetState.ON: 'QWidget { background-color: limegreen; }',
19+
# Stylesheet for when a component is disabled, not running, or disarmed, but could be
20+
# enabled through this widget
21+
WidgetState.OFF: 'QWidget { background-color: red; }',
22+
# Stylesheet for when a component is disabled, not expected to have any effect or perform
23+
# its function because of some external factor, either another widget or something
24+
# external to the gui. For example, a the arm button when the pi is not connected
25+
WidgetState.INACTIVE: 'QWidget { background-color: silver; }',
26+
WidgetState.NONE: '',
27+
}
28+
29+
def set_initial_stylesheet(self, extra_styles: str = '') -> None:
30+
"""
31+
Store the original stylesheet of the widget so changing state does not remove styles.
32+
33+
Parameters
34+
----------
35+
extra_styles : str, optional
36+
an additional stylesheet that will be constant for the widget, by default ''
37+
"""
38+
self._original_stylesheet = self.styleSheet() + extra_styles
39+
self.current_state = WidgetState.NONE
40+
41+
def set_state(self, new_state: WidgetState) -> None:
42+
"""
43+
Set a new state for the widget.
44+
45+
Parameters
46+
----------
47+
new_state : WidgetState
48+
The new state for the widget
49+
"""
50+
self.current_state = new_state
51+
self.setStyleSheet(self._original_stylesheet + self._STYLESHEETS[self.current_state])
4152

4253

4354
class ButtonIndicator(QPushButton, IndicatorMixin):
44-
pass
55+
def __init__(self, text: str = '', extra_styles: str = '') -> None:
56+
super().__init__(text)
57+
self.set_initial_stylesheet(extra_styles)

src/surface/gui/gui/styles/dark.qss

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/surface/gui/gui/styles/light.qss

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/surface/gui/gui/styles/watermelon.qss

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/surface/gui/gui/widgets/arm.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from PyQt6.QtWidgets import QHBoxLayout, QWidget
44

55
from gui.gui_node import GUINode
6-
from gui.styles.custom_styles import ButtonIndicator
6+
from gui.styles.custom_styles import ButtonIndicator, WidgetState
77
from rov_msgs.msg import VehicleState
88

99

@@ -25,8 +25,8 @@ def __init__(self) -> None:
2525
layout = QHBoxLayout()
2626
self.setLayout(layout)
2727

28-
self.arm_button = ButtonIndicator()
29-
self.disarm_button = ButtonIndicator()
28+
self.arm_button = ButtonIndicator(extra_styles=self.BUTTON_STYLESHEET)
29+
self.disarm_button = ButtonIndicator(extra_styles=self.BUTTON_STYLESHEET)
3030

3131
self.arm_button.setText('Arm')
3232
self.disarm_button.setText('Disarm')
@@ -37,10 +37,8 @@ def __init__(self) -> None:
3737
self.arm_button.setMinimumHeight(self.BUTTON_HEIGHT)
3838
self.disarm_button.setMinimumHeight(self.BUTTON_HEIGHT)
3939

40-
self.arm_button.setStyleSheet(self.BUTTON_STYLESHEET)
41-
self.disarm_button.setStyleSheet(self.BUTTON_STYLESHEET)
42-
self.arm_button.set_inactive()
43-
self.disarm_button.set_inactive()
40+
self.arm_button.set_state(WidgetState.INACTIVE)
41+
self.disarm_button.set_state(WidgetState.INACTIVE)
4442

4543
self.arm_button.clicked.connect(self.arm_clicked)
4644
self.disarm_button.clicked.connect(self.disarm_clicked)
@@ -79,11 +77,11 @@ def arm_status(self, res: CommandBool.Response) -> None:
7977
def vehicle_state_callback(self, msg: VehicleState) -> None:
8078
if msg.pixhawk_connected:
8179
if msg.armed:
82-
self.arm_button.set_on()
83-
self.disarm_button.remove_state()
80+
self.arm_button.set_state(WidgetState.ON)
81+
self.disarm_button.set_state(WidgetState.NONE)
8482
else:
85-
self.arm_button.remove_state()
86-
self.disarm_button.set_off()
83+
self.arm_button.set_state(WidgetState.NONE)
84+
self.disarm_button.set_state(WidgetState.OFF)
8785
else:
88-
self.arm_button.set_inactive()
89-
self.disarm_button.set_inactive()
86+
self.arm_button.set_state(WidgetState.INACTIVE)
87+
self.disarm_button.set_state(WidgetState.INACTIVE)

0 commit comments

Comments
 (0)