chore: 框架科学优化前的完整基线

在开始'设备契约层 + 目录重构 + 通止规装配'改造之前,先钉住当前可运行状态,
使后续任何删除/重构都可回退。

本基线包含:
- 现有 ROS 2 工作区全部源码(arm_application / arm_control / arm_bringup 等)
- 官方 flexiv_ros2 栈(含 flexiv_hardware / flexiv_controllers 等符号链接)
- 设备契约层 src/arm_interfaces(新增,46 项单测通过)
- devices/ 设备选型与品牌清单(新增)
- scripts/gen_site_example.py 与由它生成的 config/site.example.yaml

按 .gitignore 排除:build/ / install/ / log/ / config/site.yaml / 模型权重二进制。
This commit is contained in:
arm_dev
2026-09-23 10:53:06 +08:00
commit 6edb8d39ab
635 changed files with 1165230 additions and 0 deletions
+207
View File
@@ -0,0 +1,207 @@
#!/usr/bin/env python3
"""Control Studio device GripperDahuan / GripperDahuanModbus via Flexiv RDK.
Must run under RDK Python (rdk_py310). Uses a *lite* RDK instance so it can
share the robot with run_real.sh (ros2_control holds the normal RDK).
The controller talks RS485 itself (its own /dev/ttyUSB0), not the IPC serial.
/home/cc/rdk_py310/bin/python ~/ros2/scripts/rdk_gripper.py --list
/home/cc/rdk_py310/bin/python ~/ros2/scripts/rdk_gripper.py status
/home/cc/rdk_py310/bin/python ~/ros2/scripts/rdk_gripper.py init
/home/cc/rdk_py310/bin/python ~/ros2/scripts/rdk_gripper.py open
/home/cc/rdk_py310/bin/python ~/ros2/scripts/rdk_gripper.py close
"""
from __future__ import annotations
import argparse
import sys
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
from rdk_switch_tool import _iface_ipv4s # noqa: E402
def connect_lite(sn: str, iface: str = ""):
import flexivrdk
ips = _iface_ipv4s(iface)
if ips:
try:
return flexivrdk.Robot(sn, ips, True, True)
except TypeError:
pass
except RuntimeError as exc:
msg = str(exc).lower()
if "whitelist" not in msg and "filtered out" not in msg:
raise
return flexivrdk.Robot(sn, [], True, True)
def _fmt_params(p) -> str:
return (
f"width=[{p.min_width:.4f},{p.max_width:.4f}] m "
f"vel=[{p.min_vel:.4f},{p.max_vel:.4f}] m/s "
f"force=[{p.min_force:.1f},{p.max_force:.1f}] N"
)
def _fmt_states(s) -> str:
return f"width={s.width:.4f} m force={s.force:.2f} N moving={s.is_moving}"
def _clamp(val: float, lo: float, hi: float) -> float:
if lo > hi:
lo, hi = hi, lo
return max(lo, min(hi, val))
def _move(grip, params, width: float, vel: float, force: float) -> None:
vmin = float(params.min_vel)
vmax = float(params.max_vel)
if vmax <= 0:
vmax = 0.05
# Move velocity cannot be 0 (RDK).
vel = _clamp(vel, max(vmin, 1e-4), vmax)
force = _clamp(force, float(params.min_force), float(params.max_force))
width = _clamp(width, float(params.min_width), float(params.max_width))
print(f"Move width={width:.4f} m vel={vel:.4f} m/s force={force:.1f} N")
grip.Move(width, vel, force)
def main() -> int:
ap = argparse.ArgumentParser(description="Flexiv RDK gripper (GripperDahuanModbus)")
ap.add_argument("--sn", default="")
ap.add_argument("--iface", default="")
ap.add_argument("--device", default="", help="Studio Device name")
ap.add_argument("--force-n", type=float, default=0.0, help="force limit [N]; 0=mid")
ap.add_argument("--vel", type=float, default=0.0, help="speed [m/s]; 0=half max")
ap.add_argument(
"cmd",
nargs="?",
default="status",
choices=["list", "status", "init", "open", "close", "pos", "enable"],
)
ap.add_argument("value", nargs="?", default="", help="pos: meters or 0–1000")
args = ap.parse_args()
sys.path.insert(0, str(ROOT / "scripts" / "lib"))
from export_site_env import load_site, resolve_robot # type: ignore
data = load_site()
robot_cfg = resolve_robot(data)
g = data.get("gripper") or {}
sn = (args.sn or robot_cfg.get("sn") or "").strip()
iface = (args.iface or robot_cfg.get("iface") or "").strip()
device = (args.device or g.get("device_name") or "GripperDahuanModbus").strip()
if not sn:
print("ERROR: robot SN missing", file=sys.stderr)
return 2
import flexivrdk
print(f"=== RDK lite gripper SN={sn} device={device} iface={iface or 'auto'} ===")
robot = connect_lite(sn, iface)
dev = flexivrdk.Device(robot)
names = list(dev.list() or [])
if args.cmd == "list":
print("Studio devices:")
for n in names:
try:
en = dev.enabled(n)
cn = dev.connected(n)
except Exception:
en, cn = "?", "?"
mark = " <--" if n == device else ""
print(f" {n}: enabled={en} connected={cn}{mark}")
return 0
if device not in names:
print(
f"ERROR: device {device!r} not in Studio pool.\n available: {', '.join(names)}",
file=sys.stderr,
)
return 1
print(
f" Studio: enabled={dev.enabled(device)} connected={dev.connected(device)}"
)
if not dev.connected(device):
print(
"WARN: connected=False — 控制器自己的 /dev/ttyUSB0 没接到爪。\n"
" USB–RS485 要插 Flexiv 机箱 USB(不是工控机),A/B + 24V 到 PGEA。\n"
" 或用法兰工具口 485(腕部白绿+/绿-)。"
)
grip = flexivrdk.Gripper(robot)
if args.cmd in ("enable", "status", "init", "open", "close", "pos"):
try:
grip.Enable(device)
print(f"Enable [{device}] OK")
except Exception as exc:
print(f"ERROR: Enable failed: {exc}", file=sys.stderr)
return 1
params = grip.params()
print(" params:", _fmt_params(params))
print(" states:", _fmt_states(grip.states()))
force = float(args.force_n or g.get("force_n") or 0.0)
if force <= 0:
force = 0.5 * (float(params.min_force) + float(params.max_force))
vel = float(args.vel or g.get("vel_mps") or 0.0)
if vel <= 0:
vel = 0.5 * float(params.max_vel)
if args.cmd in ("enable", "status"):
if not dev.connected(device):
return 2
return 0
if args.cmd == "init":
print("Init (fingers home, ~10 s) …")
grip.Init()
time.sleep(2.0)
print(" states:", _fmt_states(grip.states()))
return 0
if args.cmd == "open":
_move(grip, params, float(params.max_width), vel, force)
time.sleep(0.4)
print(" states:", _fmt_states(grip.states()))
return 0
if args.cmd == "close":
_move(grip, params, float(params.min_width), vel, force)
time.sleep(0.4)
print(" states:", _fmt_states(grip.states()))
return 0
if args.cmd == "pos":
if args.value == "":
print("usage: pos <meters|0-1000>", file=sys.stderr)
return 2
raw = float(args.value)
if raw > 1.5:
span = float(params.max_width) - float(params.min_width)
width = float(params.min_width) + (raw / 1000.0) * span
else:
width = raw
_move(grip, params, width, vel, force)
time.sleep(0.4)
print(" states:", _fmt_states(grip.states()))
return 0
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as exc:
print(f"ERROR: {exc}", file=sys.stderr)
raise SystemExit(1)