Files
ros_contorl/scripts/rdk_release_movel.py
T
arm_dev 7af9e3d4b6 贴面后不再抬回悬高;MoveL 切回关节后不再把整段位移当前进速度。
搜孔开局会抬到悬高再落回 hole_hover_z_m,螺纹还没咬合臂就离开孔口。没有接触传感器,到位只认 final_gap 算出的法兰高度,贴面后停在这个 Z。09:25 厂家 MoveL 切回 NRT_JOINT_POSITION 的第一拍把整段关节差算成 1.686 rad/s,前瞻再推 0.07 rad,光心从 5 mm 冲到 276 mm 后急停。切回后钉住结束瞬间的关节角并清零速度,JTC 还指着出发前的关节时不放行。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-19 11:30:49 +08:00

177 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""D435 这一点用厂家 MoveL 送到工具尖,再把真机控制栈拉回来。
RDK 同时只能有一个连接。混合流程里 `run_real.sh` 已经占着它,
所以顺序是:停真机栈 → MoveL(`--keep-z --go`)→ 用 `--no-stop` 把栈拉回来。
`--no-stop` 是为了不扫 `install/`:感知和伺服还在跑,扫了会把自己杀掉。
YOLO 不在这里关。
"""
from __future__ import annotations
import argparse
import os
import signal
import subprocess
import sys
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts" / "lib"))
from rdk_release import is_control_stack_cmd # noqa: E402
RDK_PYTHON = os.environ.get("RDK_PYTHON", "/home/cc/rdk_py310/bin/python")
def _procs() -> list[tuple[int, str]]:
out: list[tuple[int, str]] = []
proc = Path("/proc")
for entry in proc.iterdir():
if not entry.name.isdigit():
continue
pid = int(entry.name)
if pid == os.getpid():
continue
try:
raw = (entry / "cmdline").read_bytes().replace(b"\x00", b" ")
except OSError:
continue
cmd = raw.decode("utf-8", "replace").strip()
if cmd:
out.append((pid, cmd))
return out
def _control_pids() -> list[tuple[int, str]]:
return [(pid, cmd) for pid, cmd in _procs() if is_control_stack_cmd(cmd)]
def _term(pids: list[int]) -> None:
for pid in pids:
try:
os.kill(pid, signal.SIGTERM)
except OSError:
pass
deadline = time.monotonic() + 8.0
while time.monotonic() < deadline:
alive = []
for pid in pids:
try:
os.kill(pid, 0)
except OSError:
continue
alive.append(pid)
if not alive:
return
time.sleep(0.2)
pids = alive
for pid in pids:
try:
os.kill(pid, signal.SIGKILL)
except OSError:
pass
def _service_up() -> bool:
try:
listed = subprocess.run(
["timeout", "3", "ros2", "service", "list"],
capture_output=True,
text=True,
check=False,
)
except OSError:
return False
return "/controller_manager/list_controllers" in (listed.stdout or "")
def _controller_active() -> bool:
if not _service_up():
return False
try:
call = subprocess.run(
[
"timeout", "3", "ros2", "service", "call",
"/controller_manager/list_controllers",
"controller_manager_msgs/srv/ListControllers",
],
capture_output=True,
text=True,
check=False,
)
except OSError:
return False
text = (call.stdout or "") + (call.stderr or "")
return "name='rizon_arm_controller', state='active'" in text
def _wait_controller(up: bool, timeout_s: float) -> bool:
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
active = _controller_active()
if active == up:
return True
time.sleep(0.5)
return _controller_active() == up
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--xyz", nargs=3, type=float, required=True, metavar=("X", "Y", "Z"))
ap.add_argument("--arm", default=os.environ.get("SITE_ROBOT_ARM", "89"))
ap.add_argument("--vel", type=float, default=0.3, help="TCP 线速度 m/s,交给 SDK vel")
ap.add_argument("--acc", type=float, default=1.5, help="TCP 加速度 m/s²,交给 SDK acc")
args = ap.parse_args()
held = _control_pids()
if held:
print(f"放开 RDK:停 {len(held)} 个真机控制进程(感知不停)")
for pid, cmd in held:
print(f" {pid} {cmd[:160]}")
_term([pid for pid, _cmd in held])
if not _wait_controller(False, 20.0):
print("ERROR: 控制器服务还在,MoveL 会和它抢 RDK", file=sys.stderr)
return 1
else:
print("真机控制栈没在跑,直接 MoveL")
x, y, z = (float(v) for v in args.xyz)
movel = [
RDK_PYTHON,
str(ROOT / "scripts" / "rdk_goto_xyz.py"),
"--xyz", f"{x}", f"{y}", f"{z}",
"--keep-z", "--go",
"--vel", f"{float(args.vel)}",
"--acc", f"{float(args.acc)}",
]
print("厂家 MoveL:XY 对准 D435 这一点,工具尖高度保持当前")
got = subprocess.run(movel, check=False)
if got.returncode != 0:
print(f"ERROR: MoveL 退出码 {got.returncode}", file=sys.stderr)
if held:
log_path = Path("/tmp/run_all_real_restart.log")
print(f"拉回真机栈(--no-stop,不扫感知) log={log_path}")
log_f = log_path.open("ab")
subprocess.Popen(
["bash", str(ROOT / "scripts" / "run_real.sh"), "--no-stop", "--arm", str(args.arm)],
stdout=log_f,
stderr=subprocess.STDOUT,
start_new_session=True,
)
if not _wait_controller(True, 120.0):
print(
"ERROR: 控制栈没回到 ACTIVE。看 /tmp/run_all_real_restart.log",
file=sys.stderr,
)
return 1
print("rizon_arm_controller 已回到 ACTIVE")
return 0 if got.returncode == 0 else int(got.returncode)
if __name__ == "__main__":
raise SystemExit(main())