完善释放控制:稳定/迅速行为预设、力曲线夹稳门控与会话记录。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
"""Grip behavior presets: extreme rapid open/close vs stable hold."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
|
||||
|
||||
# rapid = 迅速开合:优先跟手释放 / 再武装
|
||||
# stable = 夹持稳定:优先防误开、夹得住
|
||||
GRIP_BEHAVIOR_MODES = ("rapid", "stable")
|
||||
|
||||
GRIP_BEHAVIOR_LABELS = {
|
||||
"rapid": "迅速开合",
|
||||
"stable": "夹持稳定",
|
||||
}
|
||||
|
||||
# Keys owned by a behavior profile. Selecting a mode rewrites these fields.
|
||||
GRIP_BEHAVIOR_KEYS = (
|
||||
"filter_alpha",
|
||||
"shear_filter_alpha",
|
||||
"open_wait_stable_samples",
|
||||
"open_wait_stable_range_n",
|
||||
"open_wait_stable_trend_n",
|
||||
"grip_settle_seconds",
|
||||
"force_ramp_step",
|
||||
"force_ramp_interval",
|
||||
"adaptive_grip_enabled",
|
||||
"adaptive_force_interval",
|
||||
"release_open_speed",
|
||||
"release_open_accel",
|
||||
"release_open_decel",
|
||||
"release_arm_delay_seconds",
|
||||
"release_min_hold_seconds",
|
||||
"release_settle_seconds",
|
||||
"release_min_change",
|
||||
"release_touch_window_seconds",
|
||||
"release_side_touch_change",
|
||||
"release_confirm_window_seconds",
|
||||
"release_sample_timeout_seconds",
|
||||
"release_confirm_samples",
|
||||
"release_slow_confirm_samples",
|
||||
"release_normal_rate",
|
||||
"release_shear_rate",
|
||||
"release_slow_rate",
|
||||
"release_normal_change",
|
||||
"release_shear_change",
|
||||
"release_curve_history",
|
||||
"release_slope_window_seconds",
|
||||
"release_slope_settle_rate",
|
||||
"release_slope_min_points",
|
||||
"release_require_slope_settle",
|
||||
"release_slope_hold_seconds",
|
||||
"release_settle_normal_only",
|
||||
"release_side_shear_enabled",
|
||||
"release_side_normal_enabled",
|
||||
"release_shear_onset_enabled",
|
||||
"release_normal_onset_enabled",
|
||||
"rearm_seconds",
|
||||
"recover_stable_seconds",
|
||||
)
|
||||
|
||||
GRIP_BEHAVIOR_PROFILES = {
|
||||
"rapid": {
|
||||
"filter_alpha": 0.72,
|
||||
"shear_filter_alpha": 0.78,
|
||||
"open_wait_stable_samples": 3,
|
||||
"open_wait_stable_range_n": 0.04,
|
||||
"open_wait_stable_trend_n": 0.03,
|
||||
"grip_settle_seconds": 0.05,
|
||||
"force_ramp_step": 3,
|
||||
"force_ramp_interval": 0.04,
|
||||
"adaptive_grip_enabled": False,
|
||||
"adaptive_force_interval": 0.05,
|
||||
"release_open_speed": 85,
|
||||
"release_open_accel": 90,
|
||||
"release_open_decel": 90,
|
||||
# Almost no normal-contact lock; rely on curve/side-touch rejection.
|
||||
"release_arm_delay_seconds": 0.04,
|
||||
"release_min_hold_seconds": 0.0,
|
||||
"release_settle_seconds": 0.03,
|
||||
"release_min_change": 0.03,
|
||||
"release_touch_window_seconds": 0.28,
|
||||
"release_side_touch_change": 0.04,
|
||||
"release_confirm_window_seconds": 0.28,
|
||||
"release_sample_timeout_seconds": 0.25,
|
||||
"release_confirm_samples": 2,
|
||||
"release_slow_confirm_samples": 3,
|
||||
"release_normal_rate": 1.0,
|
||||
"release_shear_rate": 1.0,
|
||||
"release_slow_rate": 0.55,
|
||||
"release_normal_change": 0.14,
|
||||
"release_shear_change": 0.14,
|
||||
"release_curve_history": 6,
|
||||
"release_slope_window_seconds": 0.35,
|
||||
"release_slope_settle_rate": 0.8,
|
||||
"release_slope_min_points": 4,
|
||||
"release_require_slope_settle": False,
|
||||
"release_slope_hold_seconds": 0.0,
|
||||
"release_settle_normal_only": False,
|
||||
"release_side_shear_enabled": True,
|
||||
"release_side_normal_enabled": True,
|
||||
"release_shear_onset_enabled": True,
|
||||
"release_normal_onset_enabled": True,
|
||||
"rearm_seconds": 0.12,
|
||||
"recover_stable_seconds": 0.12,
|
||||
},
|
||||
"stable": {
|
||||
"filter_alpha": 0.42,
|
||||
"shear_filter_alpha": 0.52,
|
||||
"open_wait_stable_samples": 8,
|
||||
"open_wait_stable_range_n": 0.025,
|
||||
"open_wait_stable_trend_n": 0.015,
|
||||
"grip_settle_seconds": 0.2,
|
||||
"force_ramp_step": 1,
|
||||
"force_ramp_interval": 0.1,
|
||||
"adaptive_grip_enabled": True,
|
||||
"adaptive_force_interval": 0.08,
|
||||
"release_open_speed": 55,
|
||||
"release_open_accel": 70,
|
||||
"release_open_decel": 70,
|
||||
"release_arm_delay_seconds": 0.28,
|
||||
"release_min_hold_seconds": 0.65,
|
||||
"release_settle_seconds": 0.12,
|
||||
"release_min_change": 0.08,
|
||||
"release_touch_window_seconds": 0.14,
|
||||
"release_side_touch_change": 0.12,
|
||||
"release_confirm_window_seconds": 0.14,
|
||||
"release_sample_timeout_seconds": 0.2,
|
||||
"release_confirm_samples": 4,
|
||||
"release_slow_confirm_samples": 8,
|
||||
"release_normal_rate": 2.6,
|
||||
"release_shear_rate": 2.4,
|
||||
"release_slow_rate": 0.22,
|
||||
"release_normal_change": 0.42,
|
||||
"release_shear_change": 0.35,
|
||||
# Clean split: settle on normal plateau; open only via shear.
|
||||
"release_curve_history": 30,
|
||||
"release_slope_window_seconds": 0.8,
|
||||
"release_slope_settle_rate": 0.22,
|
||||
"release_slope_min_points": 10,
|
||||
"release_require_slope_settle": True,
|
||||
"release_slope_hold_seconds": 0.45,
|
||||
"release_settle_normal_only": True,
|
||||
"release_side_shear_enabled": True,
|
||||
"release_side_normal_enabled": False,
|
||||
"release_shear_onset_enabled": True,
|
||||
"release_normal_onset_enabled": False,
|
||||
"rearm_seconds": 0.55,
|
||||
"recover_stable_seconds": 0.55,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def normalize_grip_behavior_mode(mode) -> str:
|
||||
text = str(mode or "").strip().lower()
|
||||
aliases = {
|
||||
"fast": "rapid",
|
||||
"quick": "rapid",
|
||||
"snap": "rapid",
|
||||
"迅速": "rapid",
|
||||
"迅速开合": "rapid",
|
||||
"hold": "stable",
|
||||
"firm": "stable",
|
||||
"secure": "stable",
|
||||
"稳定": "stable",
|
||||
"夹持稳定": "stable",
|
||||
}
|
||||
text = aliases.get(text, text)
|
||||
if text not in GRIP_BEHAVIOR_PROFILES:
|
||||
raise ValueError(
|
||||
f"unsupported grip_behavior_mode: {mode!r}; "
|
||||
f"expected one of {list(GRIP_BEHAVIOR_PROFILES)}"
|
||||
)
|
||||
return text
|
||||
|
||||
|
||||
def grip_behavior_profile(mode: str) -> dict:
|
||||
mode = normalize_grip_behavior_mode(mode)
|
||||
return copy.deepcopy(GRIP_BEHAVIOR_PROFILES[mode])
|
||||
|
||||
|
||||
def apply_grip_behavior_profile(target, mode: str) -> str:
|
||||
"""Write profile fields onto a config object or dict. Returns normalized mode."""
|
||||
mode = normalize_grip_behavior_mode(mode)
|
||||
profile = GRIP_BEHAVIOR_PROFILES[mode]
|
||||
if isinstance(target, dict):
|
||||
target["grip_behavior_mode"] = mode
|
||||
for key, value in profile.items():
|
||||
target[key] = copy.deepcopy(value)
|
||||
return mode
|
||||
|
||||
setattr(target, "grip_behavior_mode", mode)
|
||||
for key, value in profile.items():
|
||||
if hasattr(target, key):
|
||||
setattr(target, key, copy.deepcopy(value))
|
||||
return mode
|
||||
@@ -13,6 +13,10 @@ from .rotation import (
|
||||
DEFAULT_ROTATION2,
|
||||
normalize_rotation_config,
|
||||
)
|
||||
from .behavior_profiles import (
|
||||
apply_grip_behavior_profile,
|
||||
normalize_grip_behavior_mode,
|
||||
)
|
||||
|
||||
|
||||
DEFAULT_CONTROL_CONFIG = str(
|
||||
@@ -78,6 +82,7 @@ class Demo02Config:
|
||||
force_ramp_step: int = 1
|
||||
force_ramp_interval: float = 0.1
|
||||
grip_settle_seconds: float = 0.1
|
||||
grip_behavior_mode: str = "stable"
|
||||
adaptive_grip_enabled: bool = True
|
||||
adaptive_shear_start_force: float = 0.10
|
||||
adaptive_shear_full_force: float = 0.60
|
||||
@@ -85,9 +90,32 @@ class Demo02Config:
|
||||
adaptive_force_max: int = 45
|
||||
adaptive_force_step: int = 1
|
||||
adaptive_force_interval: float = 0.15
|
||||
release_arm_delay_seconds: float = 0.8
|
||||
release_normal_change: float = 0.03
|
||||
release_shear_change: float = 0.03
|
||||
release_arm_delay_seconds: float = 0.12
|
||||
release_min_hold_seconds: float = 0.28
|
||||
release_settle_seconds: float = 0.06
|
||||
release_min_change: float = 0.04
|
||||
release_touch_window_seconds: float = 0.2
|
||||
release_side_touch_change: float = 0.06
|
||||
release_confirm_window_seconds: float = 0.2
|
||||
release_sample_timeout_seconds: float = 0.2
|
||||
release_confirm_samples: int = 2
|
||||
release_slow_confirm_samples: int = 5
|
||||
release_normal_rate: float = 1.6
|
||||
release_shear_rate: float = 1.6
|
||||
release_slow_rate: float = 0.4
|
||||
release_normal_change: float = 0.28
|
||||
release_shear_change: float = 0.28
|
||||
release_curve_history: int = 6
|
||||
release_slope_window_seconds: float = 0.8
|
||||
release_slope_settle_rate: float = 0.2
|
||||
release_slope_min_points: int = 8
|
||||
release_require_slope_settle: bool = False
|
||||
release_slope_hold_seconds: float = 0.0
|
||||
release_settle_normal_only: bool = True
|
||||
release_side_shear_enabled: bool = True
|
||||
release_side_normal_enabled: bool = True
|
||||
release_shear_onset_enabled: bool = True
|
||||
release_normal_onset_enabled: bool = True
|
||||
rearm_seconds: float = 0.5
|
||||
recover_normal_force: float = 0.02
|
||||
recover_shear_force: float = 0.02
|
||||
@@ -171,6 +199,14 @@ class Demo02Config:
|
||||
add("--force-ramp-step", type=int, default=get("force_ramp_step", cls.force_ramp_step))
|
||||
add("--force-ramp-interval", type=float, default=get("force_ramp_interval", cls.force_ramp_interval))
|
||||
add("--grip-settle-seconds", type=float, default=get("grip_settle_seconds", cls.grip_settle_seconds))
|
||||
add(
|
||||
"--grip-behavior-mode",
|
||||
type=str,
|
||||
choices=["rapid", "stable"],
|
||||
default=normalize_grip_behavior_mode(
|
||||
get("grip_behavior_mode", cls.grip_behavior_mode)
|
||||
),
|
||||
)
|
||||
add("--enable-adaptive-grip", dest="adaptive_grip_enabled", action="store_true", default=get("adaptive_grip_enabled", cls.adaptive_grip_enabled))
|
||||
add("--disable-adaptive-grip", dest="adaptive_grip_enabled", action="store_false")
|
||||
add("--adaptive-shear-start-force", type=float, default=get("adaptive_shear_start_force", cls.adaptive_shear_start_force))
|
||||
@@ -180,8 +216,43 @@ class Demo02Config:
|
||||
add("--adaptive-force-step", type=int, default=get("adaptive_force_step", cls.adaptive_force_step))
|
||||
add("--adaptive-force-interval", type=float, default=get("adaptive_force_interval", cls.adaptive_force_interval))
|
||||
add("--release-arm-delay-seconds", type=float, default=get("release_arm_delay_seconds", cls.release_arm_delay_seconds))
|
||||
add("--release-min-hold-seconds", type=float, default=get("release_min_hold_seconds", cls.release_min_hold_seconds))
|
||||
add("--release-settle-seconds", type=float, default=get("release_settle_seconds", cls.release_settle_seconds))
|
||||
add("--release-min-change", type=float, default=get("release_min_change", cls.release_min_change))
|
||||
add("--release-touch-window-seconds", type=float, default=get("release_touch_window_seconds", cls.release_touch_window_seconds))
|
||||
add("--release-side-touch-change", type=float, default=get("release_side_touch_change", cls.release_side_touch_change))
|
||||
add("--release-confirm-window-seconds", type=float, default=get("release_confirm_window_seconds", cls.release_confirm_window_seconds))
|
||||
add("--release-sample-timeout-seconds", type=float, default=get("release_sample_timeout_seconds", cls.release_sample_timeout_seconds))
|
||||
add("--release-confirm-samples", type=int, default=get("release_confirm_samples", cls.release_confirm_samples))
|
||||
add("--release-slow-confirm-samples", type=int, default=get("release_slow_confirm_samples", cls.release_slow_confirm_samples))
|
||||
add("--release-normal-rate", type=float, default=get("release_normal_rate", cls.release_normal_rate))
|
||||
add("--release-shear-rate", type=float, default=get("release_shear_rate", cls.release_shear_rate))
|
||||
add("--release-slow-rate", type=float, default=get("release_slow_rate", cls.release_slow_rate))
|
||||
add("--release-normal-change", type=float, default=get("release_normal_change", cls.release_normal_change))
|
||||
add("--release-shear-change", type=float, default=get("release_shear_change", cls.release_shear_change))
|
||||
add("--release-curve-history", type=int, default=get("release_curve_history", cls.release_curve_history))
|
||||
add("--release-slope-window-seconds", type=float, default=get("release_slope_window_seconds", cls.release_slope_window_seconds))
|
||||
add("--release-slope-settle-rate", type=float, default=get("release_slope_settle_rate", cls.release_slope_settle_rate))
|
||||
add("--release-slope-min-points", type=int, default=get("release_slope_min_points", cls.release_slope_min_points))
|
||||
add("--release-require-slope-settle", dest="release_require_slope_settle", action="store_true",
|
||||
default=get("release_require_slope_settle", cls.release_require_slope_settle))
|
||||
add("--no-release-require-slope-settle", dest="release_require_slope_settle", action="store_false")
|
||||
add("--release-slope-hold-seconds", type=float, default=get("release_slope_hold_seconds", cls.release_slope_hold_seconds))
|
||||
add("--release-settle-normal-only", dest="release_settle_normal_only", action="store_true",
|
||||
default=get("release_settle_normal_only", cls.release_settle_normal_only))
|
||||
add("--release-settle-all-channels", dest="release_settle_normal_only", action="store_false")
|
||||
add("--release-side-shear-enabled", dest="release_side_shear_enabled", action="store_true",
|
||||
default=get("release_side_shear_enabled", cls.release_side_shear_enabled))
|
||||
add("--no-release-side-shear", dest="release_side_shear_enabled", action="store_false")
|
||||
add("--release-side-normal-enabled", dest="release_side_normal_enabled", action="store_true",
|
||||
default=get("release_side_normal_enabled", cls.release_side_normal_enabled))
|
||||
add("--no-release-side-normal", dest="release_side_normal_enabled", action="store_false")
|
||||
add("--release-shear-onset-enabled", dest="release_shear_onset_enabled", action="store_true",
|
||||
default=get("release_shear_onset_enabled", cls.release_shear_onset_enabled))
|
||||
add("--no-release-shear-onset", dest="release_shear_onset_enabled", action="store_false")
|
||||
add("--release-normal-onset-enabled", dest="release_normal_onset_enabled", action="store_true",
|
||||
default=get("release_normal_onset_enabled", cls.release_normal_onset_enabled))
|
||||
add("--no-release-normal-onset", dest="release_normal_onset_enabled", action="store_false")
|
||||
add("--rearm-seconds", type=float, default=get("rearm_seconds", cls.rearm_seconds))
|
||||
add("--recover-normal-force", type=float, default=get("recover_normal_force", cls.recover_normal_force))
|
||||
add("--recover-shear-force", type=float, default=get("recover_shear_force", cls.recover_shear_force))
|
||||
@@ -208,4 +279,10 @@ class Demo02Config:
|
||||
values["shear_force_calibration"] = copy.deepcopy(
|
||||
config_data.get("shear_force_calibration", DEFAULT_SHEAR_FORCE_CALIBRATION)
|
||||
)
|
||||
values["grip_behavior_mode"] = normalize_grip_behavior_mode(
|
||||
values.get("grip_behavior_mode", cls.grip_behavior_mode)
|
||||
)
|
||||
return cls(**values)
|
||||
|
||||
def apply_grip_behavior_mode(self, mode: str) -> str:
|
||||
return apply_grip_behavior_profile(self, mode)
|
||||
|
||||
Reference in New Issue
Block a user