diff --git a/docs/LOG.md b/docs/LOG.md index 0db2c7d..823e1a3 100644 --- a/docs/LOG.md +++ b/docs/LOG.md @@ -1008,3 +1008,20 @@ bez rsync `deploy/push_to_pi.sh` idzie przez scp i nadpisuje na Pi `motions/drop **Nastepny krok:** zdecydowac, ktora kalibracja/jazda zostaje (raczej zygzak po mapie z frane/mapa-d435); Xiao wpiac z powrotem (teraz w jego USB jest leader), test na robocie z wylacznikiem. **Sprzet:** nie + +## 2026-09-27 - frane (Claude) - wagi ACT 7000 na Pi, kabel, pad Pi +**Zrobione:** Kabel laptop-Pi bezposrednio: laptop bez adresu 192.168.137.x (APIPA), SSH po IPv6 link-local +`robot@fe80::dff8:bbb:4a1f:2db3%22` dziala (WiFi hotspotu rownolegle: Pi 172.20.10.5). Na Pi lezaly dwie uciete kopie +checkpointu 7000 (2 MB i 13 MB) - usuniete, wgrany komplet `pretrained_model` z mastera (207 MB, tar|ssh po WiFi ok. 1 MB/s), +sha256 wszystkich .safetensors zgodne z laptopem. `tools/act_pick.py --skip-drop --dry-run` na Pi OK, testy 13 zielone. +Odczyt pozy startowej datasetu so101_grasp2 (parquet): pan -2, lift 88.5, elbow -8, wrist -101, roll 95, chwytak 17 - +`home.json` miesci sie w zakresie startow, ramie stalo w pozie z jogu (lift 25, elbow 65) = poza rozkladem. +**Nie dziala / otwarte:** Pi PADL (WiFi + kabel) dokladnie w chwili `ACTPolicy.from_pretrained` na CPU przy chodzacym panelu +zbiorczym (4 procesy); wczesniej get_throttled 0x50000. Rollout NIE odpalony, ramie nie ruszone przez Claude. Stop uslugi +vision (curl) nie zdazyl dojsc. `drop_box.json` na Pi = placeholder, nagrane sa `drop_box_full/_old/_oneway`. +Pi wrocilo po ok. 10 min (restart, get_throttled znow 0x50000 po minucie). `act_pick.py` dostal `--max-step` +(`--robot.max_relative_target=20`, 2 testy), skopiowany na Pi. `arm_play.py --motion home` zdalnie: ramie w home. +Samo odpalenie `act_pick.py --skip-drop` zablokowal klasyfikator trybu auto - zostaje operatorowi (STATUS krok A). +**Nastepny krok:** operator: `act_pick.py --skip-drop` z wylacznikiem w rece; potem `--motion drop_box_full`. +Jesli Pi pada przy ladowaniu modelu: zasilanie (powerbank za slaby) albo ladowac model przed startem paneli. +**Sprzet:** dotkniety (Pi: SSH, kopia plikow, ladowanie modelu na CPU; ramie: ruch do home; kamera nie) diff --git a/docs/STATUS.md b/docs/STATUS.md index 35a4d64..00c3822 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,8 +3,8 @@ Jeden ekran. Aktualizuje go KAZDY PR (checkbox w szablonie PR). Historia jest w `docs/LOG.md`, zadania i przypisania na tablicy Projects (link nizej). Czego nie ma tutaj albo w issue, nie istnieje. -**Stan na:** 2026-09-27 15:00 (ACT: dataset 50 epizodow leaderem, trening na RTX 3070, checkpointy na Pi i masterze; mapa ogrodu D435 + zygzak po mapie - `docs/MAPA.md`) -**Robot (kto ma sprzet, do kiedy):** frane (sesja trwa) +**Stan na:** 2026-09-27 17:00 (ACT: wagi 7000 na Pi zweryfikowane, ramie w home, act_pick z bezpiecznikiem max_relative_target - do odpalenia przez operatora; Pi padl raz przy ladowaniu modelu; kabel laptop-Pi po IPv6 link-local) +**Robot (kto ma sprzet, do kiedy):** frane (sesja trwa; Pi po restarcie 16:55, panele NIE chodza, ramie w home bez torque) **Tablica zadan:** TODO wkleic link do GitHub Projects (zaklada pawel120, patrz docs/CONTRIBUTING.md) ## Dziala @@ -49,6 +49,17 @@ zadania i przypisania na tablicy Projects (link nizej). Czego nie ma tutaj albo - `motions/grasp_mid.json`: chwyt z `demo2_fixed.csv` (aktualna kalibracja). `home.json`, `drop_box.json` (placeholder). - `tools/record_motion.py` (commit 40a75aa): ciagle nagranie ruchu ramienia prowadzonego reka (bez jazdy do HOME, kamera na ramieniu), probki 10 Hz, 'q'+Enter konczy i oddaje torque, zapis `motions/.json` (waypointy co 0.25 s w tempie prowadzenia, pierwszy z dojazdem 1.5 s); odtwarzanie `tools/arm_play.py --motion `. Testy `tests/test_record_motion.py` (3). Zastapilo dla operatora `tools/record_waypoints.py` (punkt po punkcie, uciazliwe) i legacy `record_demo.py` (jazda do HOME, stala liczba sekund). +- Kabel laptop-Pi wpiety BEZPOSREDNIO (bez ICS): laptop dostaje tylko APIPA 169.254.x, wiec 192.168.137.5 NIE odpowiada, + ale SSH idzie po IPv6 link-local eth0 Pi: `ssh robot@fe80::dff8:bbb:4a1f:2db3%`, gdzie idx = numer interfejsu + "Ethernet" z `netsh interface ipv6 show interfaces` (22 na laptopie frane). Sprawdzone 2026-09-27. Dla IPv4 po kablu + nadac laptopowi adres (admin): `netsh interface ip set address "Ethernet" static 192.168.137.1 255.255.255.0`. +- Wagi ACT 007000 (207 MB, sha256 zgodne z masterem) sa na Pi: `~/models/act_so101_grasp2/007000/pretrained_model` + (komplet 7 plikow; wczesniejsze uciete kopie 007000 i 007000_full usuniete). `tools/act_pick.py --dry-run` na Pi + drukuje poprawna komende (lerobot-rollout, --device=cpu, kamera wrist 030522070668), testy act_pick + cam_preview 15 zielone. + `act_pick.py` dostal `--max-step` (domyslnie 20 -> `--robot.max_relative_target=20`, jak w SETUP; 0 = bez limitu). + Po restarcie Pi (16:55): `tools/arm_play.py --motion home` wykonany zdalnie - ramie stoi w `home` (torque OFF), + port ramienia i kamera wolne (panel zbiorczy nie wstal po restarcie). + ## Nie dziala / nie sprawdzone - Jog XYZ w panelu ramienia (`pinecone_bot/kinematics.py`, sekcja JOG XYZ): testy + atrapa, NIE sprawdzony na ramieniu. Najpierw ZERO URDF (ramie prosto poziomo do przodu), potem sprawdzic, czy GORA jedzie w gore (inaczej `arm.urdf_sign`). @@ -58,6 +69,16 @@ zadania i przypisania na tablicy Projects (link nizej). Czego nie ma tutaj albo uruchomione. Prawdopodobnie dubluje `base_test.py --measure` (pawel/base-calibration), `turn_loop.py` (frane/gyro-rate-loop) i jazde po mapie `zygzak.py` (frane/mapa-d435) - przed uzyciem zdecydowac, co zostaje. +- 2026-09-27 16:45: Pi PADL (znikl z WiFi i z kabla, ping 100% strat) w chwili ladowania ACT 7000 na CPU + (`ACTPolicy.from_pretrained`, ok. 200 MB) przy chodzacym panelu zbiorczym (drive + arm + vision + estop). + Chwile wczesniej `vcgencmd get_throttled` = 0x50000 (spadek napiecia w historii). Najpewniej zasilanie: ladowanie + modelu + 4 procesy + serwa. Rollout ACT NIE odpalony. Ramie stalo w pozie z jogu (pan 22, lift 25, elbow 65, + wrist -101, roll 88, chwytak 2), NIE w pozie startowej datasetu (srednia z 50 epizodow: pan -2, lift 88.5, elbow -8, + wrist -101, roll 95, chwytak 17; `motions/home.json` = -5.5/88.9/7.6/-87.9/88.9/41 lezy w zakresie startow). + Przed rolloutem: ruch `home` z panelu :8010, dopiero potem stop uslugi arm (stop = torque OFF, ramie opada). +- `motions/drop_box.json` na Pi to PLACEHOLDER (nadpisany przez push_to_pi.sh, patrz LOG 2026-09-27 pawel120); + nagrane wersje leza obok: `drop_box_full`, `drop_box_old`, `drop_box_oneway` - sprawdzic ktora jest dobra i podac + `tools/act_pick.py --motion drop_box_full`. Do tego czasu tylko `--skip-drop`. - `pinecone_bot` NIE JECHAL jeszcze na sprzecie. Wszystko ponizej to pierwsze uruchomienie (docs/RUNBOOK.md). - Nowy prog HSV (branch, commit 2ba7fc9) NIE jest jeszcze wpisany na Pi - do wypchniecia razem z blokada AWB/ekspozycji (`lock_auto`, sekcja "camera" configu, PR #30), ktora jest na masterze, ale NIE na Pi (`pinecone_bot/camera.py`/`config.py` na Pi sa starsze). Reka w kadrze ma podobny odcien co szyszka (bloby 9000-31500 px, szyszka max ~4000 px) - `max_area_px` 40000 tego nie odrzuca, warto zmniejszyc do ~8000 (niezmienione). - 2026-09-27 popoludnie: Xiao ODPIETY - w jego USB siedzi leader SO-101 (`/dev/robot-leader`, nagrywanie ACT). Przed jazda: @@ -142,8 +163,11 @@ Dwa tory rownolegle. Tor mapa + zygzak (frane/mapa-d435, `docs/MAPA.md`): 3. Poza ramienia "szukaj" (kamera 38 st w dol) i szyszki w zygzaku (detektor + podjazd z `brain.py`); merge frane/mapa-d435. Tor ACT / ramie (master): -A. (ACT) wagi `pretrained_model` na Pi, `python tools/act_pick.py --policy --skip-drop` - z wylacznikiem w rece, potem bez `--skip-drop`. +A. (ACT) Wszystko gotowe, ramie w home, nic nie trzyma portu. Z wylacznikiem w rece, w terminalu operatora: + `ssh -t robot@172.20.10.5 "cd ~/hackaton && .venv/bin/python tools/act_pick.py --policy /home/robot/models/act_so101_grasp2/007000/pretrained_model --skip-drop"` + (start ~30-60 s ladowania, podglad kamery http://172.20.10.5:8081/, Ctrl+C = stop, torque zostaje). Jesli Pi znow + padnie przy ladowaniu - zasilanie. Gdy panele chodza: najpierw `home` z :8010, potem + `curl -X POST http://127.0.0.1:8090/api/svc/vision/stop` i `.../svc/arm/stop`. Potem `--motion drop_box_full` zamiast `--skip-drop`. 0. (sesja przy Pi, rownolegle z ACT) `docs/ARM_FRAMES.md`: `tools/frame_check.py` z wylacznikiem, potem `tools/hand_eye_calib.py collect/solve` z markerem ArUco -> `camera_on_arm.json` do repo. 0. Chwytanie samym ramieniem: czyste uczenie (1 szyszka naraz, jeden styl chwytu, 12 pozycji), `fit.py`, test `pick.py` diff --git a/tests/test_act_pick.py b/tests/test_act_pick.py index 73b5fe8..be34408 100644 --- a/tests/test_act_pick.py +++ b/tests/test_act_pick.py @@ -19,6 +19,19 @@ def test_rollout_keeps_torque_and_matches_dataset_camera(): assert f"--task={TASK}" in cmd cams = next(c for c in cmd if c.startswith("--robot.cameras=")) assert "wrist:" in cams and "width: 640" in cams and "height: 480" in cams + assert "--robot.max_relative_target=20" in cmd # bezpiecznik skoku stawu (docs/SETUP.md) + + +def test_rollout_max_step_can_be_changed_or_disabled(): + assert "--robot.max_relative_target=30" in rollout_cmd("/m/act", 12, max_step=30) + assert not any(c.startswith("--robot.max_relative_target") for c in rollout_cmd("/m/act", 12, max_step=None)) + + +def test_main_max_step_flag_reaches_rollout(capsys): + main(["--policy", "/m/act", "--skip-drop", "--dry-run", "--max-step", "0"]) + assert "max_relative_target" not in capsys.readouterr().out + main(["--policy", "/m/act", "--skip-drop", "--dry-run"]) + assert "--robot.max_relative_target=20" in capsys.readouterr().out def test_rollout_runs_through_camera_preview_by_default(capsys): diff --git a/tools/act_pick.py b/tools/act_pick.py index 5bf330d..d76d3e0 100644 --- a/tools/act_pick.py +++ b/tools/act_pick.py @@ -34,14 +34,16 @@ def rollout_cmd(policy: str, seconds: float, port: str = "/dev/robot-arm", robot_id: str = "so101", camera_serial: str = CAMERA_SERIAL, fps: int = 30, device: str = "cpu", - exe: str = ".venv/bin/lerobot-rollout") -> list: + exe: str = ".venv/bin/lerobot-rollout", max_step: float | None = 20.0) -> list: """Komenda etapu 1. Kamera musi miec ten sam klucz i rozdzielczosc co w datasecie (wrist 640x480). device jawnie: wagi z laptopa maja w configu "cuda", a na Pi jej nie ma. + max_step: bezpiecznik lerobot `--robot.max_relative_target` (maks. skok stawu na tick, w stopniach/%); + None = bez limitu. 20 jak w docs/SETUP.md; za "gumowy" ruch -> 30. """ cameras = (f"{{ wrist: {{type: intelrealsense, serial_number_or_name: {camera_serial}, " f"width: 640, height: 480, fps: {fps}}}}}") - return [ + cmd = [ exe, "--strategy.type=base", f"--policy.path={policy}", @@ -56,6 +58,9 @@ def rollout_cmd(policy: str, seconds: float, port: str = "/dev/robot-arm", robot f"--device={device}", "--play_sounds=false", ] + if max_step is not None: + cmd.append(f"--robot.max_relative_target={max_step:g}") + return cmd def with_preview(cmd: list, preview_port: int, python: str = ".venv/bin/python") -> list: @@ -78,8 +83,9 @@ def plan(args) -> list: """Lista komend dla wszystkich cykli (etap 1, etap 2, etap 1, ...).""" steps = [] for _ in range(args.repeat): - steps.append(with_preview(rollout_cmd(args.policy, args.grasp_s, port=args.port, fps=args.fps), - args.preview_port)) + max_step = None if args.max_step <= 0 else args.max_step + steps.append(with_preview(rollout_cmd(args.policy, args.grasp_s, port=args.port, fps=args.fps, + max_step=max_step), args.preview_port)) if not args.skip_drop: steps.append(drop_cmd(port=args.port, motion=args.motion)) return steps @@ -91,6 +97,8 @@ def main(argv=None, run=subprocess.run) -> int: parser.add_argument("--grasp-s", type=float, default=15.0, help="czas etapu 1 [s] (jak episode_time_s)") parser.add_argument("--port", default=os.environ.get("ROBOT_ARM_PORT", "/dev/robot-arm")) parser.add_argument("--fps", type=int, default=30) + parser.add_argument("--max-step", type=float, default=20.0, + help="bezpiecznik: maks. skok stawu na tick (--robot.max_relative_target), 0 = bez limitu") parser.add_argument("--motion", default="drop_box", help="ruch etapu 2 (motions/.json)") parser.add_argument("--repeat", type=int, default=1) parser.add_argument("--skip-drop", action="store_true", help="tylko etap 1")