forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Prebuilt Release @ 67fd9c2
This commit is contained in:
42
artifacts/package_runtime/panda/board/body/__init__.py
Normal file
42
artifacts/package_runtime/panda/board/body/__init__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# python helpers for the body panda
|
||||
import struct
|
||||
|
||||
from panda import Panda
|
||||
|
||||
class PandaBody(Panda):
|
||||
|
||||
MOTOR_LEFT: int = 1
|
||||
MOTOR_RIGHT: int = 2
|
||||
|
||||
# ****************** Motor Control *****************
|
||||
@staticmethod
|
||||
def _ensure_valid_motor(motor: int) -> None:
|
||||
if motor not in (PandaBody.MOTOR_LEFT, PandaBody.MOTOR_RIGHT):
|
||||
raise ValueError("motor must be MOTOR_LEFT or MOTOR_RIGHT")
|
||||
|
||||
def motor_set_speed(self, motor: int, speed: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
assert -100 <= speed <= 100, "speed must be between -100 and 100"
|
||||
speed_param = speed if speed >= 0 else (256 + speed)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe0, motor, speed_param, b'')
|
||||
|
||||
def motor_set_target_rpm(self, motor: int, rpm: float) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
target_deci_rpm = int(round(rpm * 10.0))
|
||||
assert -32768 <= target_deci_rpm <= 32767, "target rpm out of range (-3276.8 to 3276.7)"
|
||||
target_param = target_deci_rpm if target_deci_rpm >= 0 else (target_deci_rpm + (1 << 16))
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, motor, target_param, b'')
|
||||
|
||||
def motor_stop(self, motor: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe1, motor, 0, b'')
|
||||
|
||||
def motor_get_encoder_state(self, motor: int) -> tuple[int, float]:
|
||||
self._ensure_valid_motor(motor)
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xe2, motor, 0, 8)
|
||||
position, rpm_milli = struct.unpack("<ii", dat)
|
||||
return position, rpm_milli / 1000.0
|
||||
|
||||
def motor_reset_encoder(self, motor: int) -> None:
|
||||
self._ensure_valid_motor(motor)
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, motor, 0, b'')
|
||||
49
artifacts/package_runtime/panda/board/body/flash.py
Normal file
49
artifacts/package_runtime/panda/board/body/flash.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from panda import Panda
|
||||
|
||||
BODY_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
BOARD_DIR = os.path.abspath(os.path.join(BODY_DIR, ".."))
|
||||
REPO_ROOT = os.path.abspath(os.path.join(BOARD_DIR, ".."))
|
||||
DEFAULT_FIRMWARE = os.path.join(BOARD_DIR, "obj", "body_h7.bin.signed")
|
||||
|
||||
|
||||
def build_body() -> None:
|
||||
subprocess.check_call(
|
||||
f"scons -C {REPO_ROOT} -j$(nproc) board/obj/body_h7.bin.signed",
|
||||
shell=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("firmware", nargs="?", help="Optional path to firmware binary to flash")
|
||||
parser.add_argument("--all", action="store_true", help="Flash all Panda devices")
|
||||
parser.add_argument(
|
||||
"--wait-usb",
|
||||
action="store_true",
|
||||
help="Wait for the panda to reconnect over USB after flashing (defaults to skipping reconnect).",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
firmware_path = os.path.abspath(args.firmware) if args.firmware is not None else DEFAULT_FIRMWARE
|
||||
|
||||
build_body()
|
||||
|
||||
if not os.path.isfile(firmware_path):
|
||||
parser.error(f"firmware file not found: {firmware_path}")
|
||||
|
||||
if args.all:
|
||||
serials = Panda.list()
|
||||
print(f"found {len(serials)} panda(s) - {serials}")
|
||||
else:
|
||||
serials = [None]
|
||||
|
||||
for s in serials:
|
||||
with Panda(serial=s) as p:
|
||||
print("flashing", p.get_usb_serial())
|
||||
p.flash(firmware_path, reconnect=args.wait_usb)
|
||||
exit(1 if len(serials) == 0 else 0)
|
||||
Reference in New Issue
Block a user