"""
manual_controller
キー入力から手動操作の throttle / steer を計算するモジュール
"""
from PySide6.QtCore import Qt
from PySide6.QtGui import QKeyEvent
# 手動操作の throttle / steer 量
MANUAL_THROTTLE: float = 0.5
MANUAL_STEER: float = 0.4
class ManualController:
"""キー入力を throttle / steer に変換する
Qt のキーイベントを受け取り,
押下中のキーセットから操舵量を計算する
"""
def __init__(self) -> None:
self._pressed_keys: set[int] = set()
self.throttle: float = 0.0
self.steer: float = 0.0
def reset(self) -> None:
"""状態をリセットする"""
self._pressed_keys.clear()
self.throttle = 0.0
self.steer = 0.0
def handle_key_press(self, event: QKeyEvent) -> bool:
"""キー押下を処理する
Args:
event: Qt のキーイベント
Returns:
操舵量が更新された場合 True
"""
if event.isAutoRepeat():
return False
self._pressed_keys.add(event.key())
self._update()
return True
def handle_key_release(self, event: QKeyEvent) -> bool:
"""キー離上を処理する
Args:
event: Qt のキーイベント
Returns:
操舵量が更新された場合 True
"""
if event.isAutoRepeat():
return False
self._pressed_keys.discard(event.key())
self._update()
return True
def is_emergency_stop(self) -> bool:
"""Space キーによる緊急停止が発生したか判定する
緊急停止の場合は状態をリセットする
Returns:
緊急停止が発生した場合 True
"""
if Qt.Key.Key_Space in self._pressed_keys:
self.reset()
return True
return False
def _update(self) -> None:
"""押下中のキーから throttle と steer を計算する"""
keys = self._pressed_keys
# Space で緊急停止
if Qt.Key.Key_Space in keys:
self.reset()
return
# throttle: W/↑ で前進,S/↓ で後退
forward = (
Qt.Key.Key_W in keys or Qt.Key.Key_Up in keys
)
backward = (
Qt.Key.Key_S in keys
or Qt.Key.Key_Down in keys
)
if forward and not backward:
self.throttle = MANUAL_THROTTLE
elif backward and not forward:
self.throttle = -MANUAL_THROTTLE
else:
self.throttle = 0.0
# steer: A/← で左,D/→ で右
left = (
Qt.Key.Key_A in keys
or Qt.Key.Key_Left in keys
)
right = (
Qt.Key.Key_D in keys
or Qt.Key.Key_Right in keys
)
if left and not right:
self.steer = -MANUAL_STEER
elif right and not left:
self.steer = MANUAL_STEER
else:
self.steer = 0.0