From a3fe930438642eb13f0bc8b1fbb7bb5cd57796a5 Mon Sep 17 00:00:00 2001 From: blankey1337 <42594751+blankey1337@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:04:15 -0800 Subject: [PATCH] Fix lint errors and add project guidelines - Fixed lint errors in lift_axis.py (E701, E402) - Added .cursor/rules/project-guidelines.mdc for project-specific rules - Added scripts/setup_hooks.sh to install pre-commit hook for local linting --- .cursor/rules/project-guidelines.mdc | 28 ++++++++++++ scripts/setup_hooks.sh | 31 +++++++++++++ .../src/lerobot/robots/alohamini/lift_axis.py | 45 ++++++++++++------- 3 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 .cursor/rules/project-guidelines.mdc create mode 100755 scripts/setup_hooks.sh diff --git a/.cursor/rules/project-guidelines.mdc b/.cursor/rules/project-guidelines.mdc new file mode 100644 index 0000000..b8cae11 --- /dev/null +++ b/.cursor/rules/project-guidelines.mdc @@ -0,0 +1,28 @@ +--- +description: AlohaMini Project Guidelines +globs: ["**/*"] +alwaysApply: true +--- + +# AlohaMini Project Rules + +## Coding Style +- Follow PEP 8 guidelines for Python code. +- Use `ruff` for linting. Ensure no errors are present before committing. +- Prefer explicit variable names over single letters (except for math coordinates like x, y, z). +- Add type hints to function signatures. + +## Git Workflow +- Create feature branches for new development (`feature/name`). +- Create chore branches for maintenance (`chore/name`). +- Use descriptive commit messages. +- Ensure pre-commit hooks are installed (`scripts/setup_hooks.sh`) to run linting locally. + +## Project Structure +- `software/src/lerobot/robots/alohamini`: Robot-specific implementations. +- `software/examples`: Example scripts and debug tools. +- `hardware`: CAD files and BOM. + +## Documentation +- Update README.md or docs/ when adding new major features. +- Keep the BOM updated if hardware requirements change. \ No newline at end of file diff --git a/scripts/setup_hooks.sh b/scripts/setup_hooks.sh new file mode 100755 index 0000000..3e41b3c --- /dev/null +++ b/scripts/setup_hooks.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Script to install git pre-commit hook +# + +HOOK_DIR=".git/hooks" +HOOK_FILE="$HOOK_DIR/pre-commit" + +if [ ! -d "$HOOK_DIR" ]; then + echo "Error: .git directory not found. Are you in the root of the repo?" + exit 1 +fi + +echo "#!/bin/sh +# +# Pre-commit hook to run ruff linting +# + +echo \"Running ruff linting...\" +ruff check . + +if [ \$? -ne 0 ]; then + echo \"Linting failed. Please fix the errors before committing.\" + exit 1 +fi + +echo \"Linting passed.\" +" > "$HOOK_FILE" + +chmod +x "$HOOK_FILE" +echo "Pre-commit hook installed successfully." diff --git a/software/src/lerobot/robots/alohamini/lift_axis.py b/software/src/lerobot/robots/alohamini/lift_axis.py index a3b699d..689cc5d 100644 --- a/software/src/lerobot/robots/alohamini/lift_axis.py +++ b/software/src/lerobot/robots/alohamini/lift_axis.py @@ -69,25 +69,31 @@ def __init__( self._configured = False def attach(self) -> None: - if not self.enabled: return + if not self.enabled: + return if self.cfg.name not in self._bus.motors: self._bus.motors[self.cfg.name] = Motor(self.cfg.motor_id, self.cfg.motor_model, MotorNormMode.DEGREES) def configure(self) -> None: - if not self.enabled: return - if self._configured: return + if not self.enabled: + return + if self._configured: + return self._bus.write("Operating_Mode", self.cfg.name, OperatingMode.VELOCITY.value) self._last_tick = float(self._bus.read("Present_Position", self.cfg.name, normalize=False)) self._extended_ticks = 0.0 self._configured = True def _update_extended_ticks(self) -> None: - if not self.enabled: return + if not self.enabled: + return cur = float(self._bus.read("Present_Position", self.cfg.name, normalize=False)) # 0..4095 delta = cur - self._last_tick half = self._ticks_per_rev * 0.5 - if delta > +half: delta -= self._ticks_per_rev - elif delta < -half: delta += self._ticks_per_rev + if delta > +half: + delta -= self._ticks_per_rev + elif delta < -half: + delta += self._ticks_per_rev self._extended_ticks += delta self._last_tick = cur @@ -95,7 +101,8 @@ def _extended_deg(self) -> float: return self.cfg.dir_sign * self._extended_ticks * self._deg_per_tick def get_height_mm(self) -> float: - if not self.enabled: return 0.0 + if not self.enabled: + return 0.0 self._update_extended_ticks() raw_mm = (self._extended_deg() - self._z0_deg) * self._mm_per_deg #print(f"[lift_axis.get_height_mm] raw_mm={raw_mm:.2f}, extended_deg={self._extended_deg():.2f}, z0_deg={self._z0_deg:.2f}") # debug @@ -103,7 +110,8 @@ def get_height_mm(self) -> float: # Homing (down to hard stop β†’ rebound, set z=0mm) def home(self, use_current: bool = True) -> None: - if not self.enabled: return + if not self.enabled: + return self.configure() name = self.cfg.name # 向下 @@ -126,13 +134,15 @@ def home(self, use_current: bool = True) -> None: print(f"[lift_axis.home] Present_Current={cur_ma} mA") # debug print(f"[lift_axis.home] Present_Position={now_tick} ticks") # debug - except Exception: cur_ma = 0 + except Exception: + cur_ma = 0 if (use_current and cur_ma >= self.cfg.home_stall_current_ma) or (not moved): print(f"[lift_axis.home] Stalled at current={cur_ma} mA, moved={moved}") # debug stuck += 1 else: stuck = 0 - if stuck >= 2: break + if stuck >= 2: + break #self._bus.write("Goal_Velocity", name, 0) self._bus.write("Torque_Enable", name, 0) print("Disable torque output (motor will be released)") @@ -147,17 +157,20 @@ def home(self, use_current: bool = True) -> None: def set_height_target_mm(self, height_mm: float) -> None: - if not self.enabled: return + if not self.enabled: + return self._target_mm = max(self.cfg.soft_min_mm, min(self.cfg.soft_max_mm, height_mm)) def clear_target(self) -> None: - if not self.enabled: return + if not self.enabled: + return self._target_mm = None self._bus.write("Goal_Velocity", self.cfg.name, 0.0) def update(self) -> None: """Call every frame (recommended 50–100 Hz)""" - if not self.enabled or self._target_mm is None: return + if not self.enabled or self._target_mm is None: + return cur_mm = self.get_height_mm() err = self._target_mm - cur_mm # Position reached? @@ -178,7 +191,8 @@ def update(self) -> None: # Lightweight coupling with action/obs def contribute_observation(self, obs: Dict[str, float]) -> None: """Export convenient observation fields: height_mm and velocity""" - if not self.enabled: return + if not self.enabled: + return obs[f"{self.cfg.name}.height_mm"] = self.get_height_mm() try: obs[f"{self.cfg.name}.vel"] = int(self._bus.read("Present_Velocity", self.cfg.name, normalize=False)) @@ -192,7 +206,8 @@ def apply_action(self, action: Dict[str, float]) -> None: - f"{name}.vel" : target velocity (advanced) """ #print(f"[lift_axis.apply_action] action={action}") # debug - if not self.enabled: return + if not self.enabled: + return key_h = f"{self.cfg.name}.height_mm" key_v = f"{self.cfg.name}.vel" if key_h in action: