Aktualizuj ten plik, gdy odkryjesz nowa pulapke. Historia sesji jest w docs/LOG.md.
Platforma: podwozie-hoverboard + ramie SO-101 na wierzchu, docelowo sterowane z Raspberry Pi 5 (zamiast Windows PC).
- Raspberry Pi 5 (8 GB) - centralny kontroler. Jedzie na robocie, urzadzenia podpiete po USB: kamera D415 (USB3), ramie (adapter CH343), Xiao (USB-serial). System: Raspberry Pi OS Lite 64-bit na pendrivie USB (brak karty SD) - nie wyciagac pendrive'a z dzialajacego Pi, to dysk systemowy.
- Seeed Xiao RP2040 - kontroler hoverboardu, firmware
xiao_send_pwm.ino. Protokol po USB-serial:a<speed> b<steer>\n, watchdog 500 ms (brak komend = stop). Steruje H-bridge (PWM+DIR) na pinachLEFT_PWM_PIN/LEFT_DIR_PIN/RIGHT_PWM_PIN/RIGHT_DIR_PIN(D0-D3). Flagi w firmwareSWAP_LR/INVERT_DIRkorygujace montaz "do gory nogami" wzgledem oryginalnego zalozenia (zamiana L/R + odwrocenie kierunku obu silnikow) - patrz pulapka 3 nizej. - Hoverboard - 2x silnik + wlasny sterownik H-bridge, napedzany przez Xiao jak wyzej.
- Ramie SO-101 (TheRobotStudio/Hugging Face lerobot), serwa Feetech
STS3215, URDF w
so101_urdf/so101_new_calib.urdf. Kontroler przez adapter USB CH343 (VID:PID1a86:55d3). Kalibracja serw zapisana POZA repo:~/.cache/huggingface/lerobot/calibration/robots/so_follower/so101.json(id ramieniaso101) - na laptopie i osobno na Pi, trzeba kopiowac recznie (nie jest w gicie). - Kamera na robocie (sprawdzone 2026-09-27, pyrealsense2 na Pi): Intel RealSense D435 (PID 0B07, firmware 5.11.1.100, USB 3.2), siedzi na ramieniu. Pomiary w pulapkach 16-27 byly robione na D415 - dla D435 moga sie roznic (D435 ma szersze pole widzenia i inna martwa strefe).
- Kamera Intel RealSense D415 (wczesniej) - USB. Serial 105422060821, firmware 5.17.0.10. Montaz docelowy: platforma robota, 12 cm nad ziemia.
- udev / stabilne nazwy portow na Pi (
deploy/99-robot.rules):/dev/robot-arm= kontroler ramienia (CH343,1a86:55d3),/dev/robot-drive= Xiao (2e8a:000a). Na Windows nazwy portow to zwykle COM (numer zmienia sie po replugu - patrz pulapka 4). - Odrzucona platforma obliczeniowa: Jetson Nano P3450 - patrz pulapka "Jetson Nano" nizej.
Krotko: zasilanie 12 V z akumulatora jest osobnym, nierozwiazanym tematem (GitHub issue #8, przypisana osoba od elektroniki). Baterie AA 1,5 V NIE nadaja sie do zasilania Pi. Pi 5 + D415 na slabym zasilaniu (np. slaby powerbank/zasilacz) znika z sieci - na dobrym powerbanku dziala stabilnie. Szczegoly i decyzje - patrz issue #8.
-
NIE uruchamiac
lerobot calibrate. Nadpisuje recznie poprawiony offset barku (id2, patrz pulapka 3) i zakres znow przejdzie przez zero enkodera - ramie znowu bedzie jechalo "naokolo" zamiast prosto do celu. Backup pliku kalibracji sprzed poprawki jest na Pi:~/so101.json.bak-204746. -
lerobot adresuje serwa PO NAZWIE, ze sztywnej listy w kodzie (
lerobot/robots/so_follower/so_follower.py:shoulder_lift=id2,elbow_flex=id3). Pole"id"w plikuso101.jsonjest IGNOROWANE. Proba "naprawy" przez zamiane wpisowshoulder_lift/elbow_flexw pliku kalibracji zamienia tylko offsety/zakresy miedzy przegubami - kazdy z dwoch przegubow zostaje znormalizowany zakresem tego drugiego, wiec kierunek dalej wychodzi zly. To byla bledna diagnoza w jednej z sesji ("zamiana ID serw") - nie powtarzac. Nie naprawiac mapowania przez edycje JSON-a. -
Fizyczny zakres barku (id2,
shoulder_lift) przechodzil przez zero enkodera (Present 4095->0). Serwo w trybie pozycji nie przejdzie przez 0, wiec do celu po drugiej stronie jechalo "naokolo", w podloge (widac w nagraniu: -82 -> -151 -> +139 -> 128 st). Naprawa (bez recznej kalibracji, policzona z nagrania demonstracji):fix_shoulder_offset.pyustawiaHoming_Offseti limity tak, zeby srodek zakresu byl daleko od zera enkodera (id2: offset 1977, limity 1006..3089; id3 przywrocone do wartosci sprzed sesji). Zapisuje do EEPROM serw i doso101.json.Homing_Offsetna Feetech ma zakres +-2047 - wieksze przesuniecia licz modulo 4096. -
Ramie montowane "do gory nogami" wzgledem oryginalnego zalozenia projektu wymaga w firmware Xiao
SWAP_LR=trueiINVERT_DIR=true(zamiana L/R + odwrocenie kierunku obu silnikow). Bez tego robot jedzie w zla strone mimo poprawnych komend z wyzszej warstwy. -
Sterowanie roznicowe kolami:
steermusi byc wyraznie mniejsze nizspeed, inaczej jedno kolo idzie na minus i robot wiruje w miejscu zamiast jechac lukiem. -
Dwa mnozace sie suwaki predkosci (limit predkosci x predkosc trybu auto) potrafia zejsc do wartosci za niskiej, zeby fizycznie ruszyc silniki (martwa strefa PWM). Przy "robot nic nie robi" zawsze sprawdz realny
pwm_speed/pwm_steer, nie tylko czy komenda w ogole leci. -
COM port bywa niestabilny po zawieszeniu USB CDC (Windows error 31, "urzadzenie nie dziala") - zwykle pomaga fizyczny replug kabla; programowy disable/enable urzadzenia wymaga uprawnien admina.
-
Krok kol (
drive_step.py) jest mocno NIELINIOWY, nie licz go proporcjonalnie do czasu. Zmierzone przy--speed 150: 0.05 s (jeden tick 80 ms) ~ 2.9 cm do przodu, ale 0.1 s ~ 12.5 cm (jeden pomiar, nie 2x wiecej). Do tylu 0.05 s dawalo od 0.4 cm do kilku cm. Przy jezdzie robot lekko znosi w bok (zdarzylo sie 1.8 cm na jednym kroku). Kalibrowac pomiarem (suwmiarka/kamera), nie zakladac liniowosci. -
Ramie niewidoczne jako port COM = kabel USB kontrolera niepodlaczony albo brak zasilania serw. Porty Bluetooth COM3/5/7/8 to NIE ramie - nie mylic przy wyborze portu.
-
"There is no status packet!" na magistrali Feetech przy szybkich petlach ruchu. Przyczyna:
max_relative_targetw configu sprawia, ze KAZDYsend_actionrobi dodatkowysync_readPresent_Position - przy komendach co ~0.25 s zapycha to bus.sync_writenie czeka na odpowiedz, wiec blad wychodzi dopiero pozniej (np. wdisconnect), co myli przy diagnozie. Rozwiazanie w petlach: wlasne ograniczenie kroku w Pythonie +arm.config.max_relative_target = Nonena czas petli (tak robidance()/gong()/replay_csv.py). Interpolowane ruchy (move_toz wieloma krokami) tez zapychaja magistrale przy duzych katach - bezposredniesend_actionzmax_relative_target=None+ powtorki sa niezawodne. -
Gwaltowne losowe ruchy = ochrona przeciazeniowa STS3215 - serwa przestaja odpowiadac. Pomaga tylko fizyczne odlaczenie i ponowne podlaczenie USB/zasilania kontrolera. Duze zakresy ruchu - tylko z malym krokiem na tick.
-
Zero stopni w lerobot to NIE zero w URDF (prawdopodobnie). lerobot liczy
deg = (raw - (range_min+range_max)/2) * 360/4095, czyli 0 st to SRODEK zakresu nagranego przy kalibracji serw, a nie pozycja zerowa URDF. Przed FK/IK trzeba zmierzyc offset i znak kazdego przegubu. Poarm_control.py calibratekaty sie zmieniaja. -
Kazde
connect()na chwile wylacza torque (configure()) - ramie moze opasc pod grawitacja miedzy wywolaniami. Rob cala sekwencje ruchow w jednym polaczeniu, nie rozlaczaj i laczaj w petli. -
Przed zmiana rejestrow serwa (np.
Homing_Offset) wywolajbus.disable_torque()- zdejmuje tezLock, inaczej zapis do EEPROM nie wejdzie. -
record_demo.pynajpierw wysyla ramie do home. Przy zlej kalibracji home nie dojezdza tam gdzie trzeba i nagranie startuje z innej pozy niz zamierzona - jesli poczatek nagrania wyglada na "opadanie" ramienia, odtwarzaj replay od pozniejszego znacznika czasu, nie od 0 s. -
Punkt zamkniecia szczek chwytaka jest ok. 17 cm PRZED kamera (zmierzone suwmiarka). D415 widzi glebie dopiero od ok. 0.27-0.31 m (patrz pulapka 17), wiec w chwili faktycznego chwytu szyszka jest ZAWSZE w martwej strefie glebi - ostatni odcinek podjazdu jedzie sie "na slepo", z zapamietanej wczesniej pozycji. Nie da sie tego zobaczyc "na zywo" w momencie chwytu: przy pozie chwytu przedramie ramienia zaslania kamere (jest ok. 0.31 m przed obiektywem, czyli tez w martwej strefie). Konsekwencja projektowa: schemat postoj-skan-zapamietaj-jedz, nie ciagle sledzenie celu.
-
Martwa strefa glebi D415 - ZMIERZONA: 0.27 m przy 640x480 (poziomo, kamera 10 cm nad podlozem). Ziemia jest mierzona od ok. 0.27 m (dolne wiersze kadru) do ok. 1.1 m. Wczesniejszy szacunek "ok. 30 cm, niezmierzone" - uzywaj tej zmierzonej wartosci. Przy 1280x720 strefa jest wieksza (szacunek pamieciowy, niezmierzony dokladnie: ok. 45 cm).
-
Niskie pokrycie glebia przy ziemi to GEOMETRIA (martwa strefa), NIE ciemnosc/zmierzch. Pomiar wiersz po wierszu: 78.7% pokrycia przy medianie 0.39 m, 74.6% przy 0.33 m, 47.2% przy 0.27 m, tylko 2.4% nizej. Rozstrzygajace:
gainsensora glebi stoi na 16 z zakresu 16-248 (auto-ekspozycja juz na minimum wzmocnienia - sensor ma NADMIAR swiatla, nie niedobor). Nie trzeba czekac na inna pore dnia. Podbicie mocy projektora IR pomaga trocha (np. 31.0% -> 35.8%), ale to nie jest glowny czynnik. -
Lewa piata kadru D415 (kolumny 0-64 px) prawie nie ma glebi (pokrycie ~9.8% vs ~25-34% w srodku, ~3.8% w kolumnach 64-128 px). Przyczyna: prawy obiektyw stereo nie widzi tego, co lewy lapie przy swojej lewej krawedzi - stereo nie ma czego dopasowac. Podbicie lasera tego NIE naprawia (9.8% -> 4.4%, jeszcze gorzej) - brakuje drugiego punktu widzenia, nie swiatla. Nie celowac w obiekt lewa krawedzia kadru.
-
Filtry glebi (spatial + temporal) poprawiaja pokrycie i POGARSZAJA detekcje malych obiektow. Zmierzone parami na tych samych klatkach: filtry daja 22.30% -> 24.44% pokrycia w pasie 0.3-1.0 m (pewna poprawa), ale na tej samej nieruchomej scenie ze szyszkami spada liczba wykrytych obiektow (5/5 bez filtrow w 4 przebiegach na 4, 4/5 z filtrami w 2 na 4) - i zawsze gubiona byla NAJBLIZSZA szyszka. Wygladzanie zjada male obiekty.
hole_filling_filterodpada z zalozenia - zmysla glebie z sasiadow zamiast uzupelniac ja pomiarami, a detekcja "obiekt czy nie" decyduje dokladnie na tych danych. -
Otwarcie morfologiczne jadrem 5x5 zjada male obiekty. Ta sama szyszka mierzy 2.2 cm wysokosci przy progu 0.6 cm i tylko 1.0 cm przy progu 0.8 cm - nie dlatego, ze zmierzono ja inaczej, tylko dlatego, ze z cienszego paska erozja zostawia sam dol. Przy celach 20-50 px jadro 3x3 jest bezpieczniejsze. Objaw skrajny: klaster w ogole nie powstaje, wiec liczniki odrzucen pokazuja same zera i "nie ma czego tlumaczyc".
-
Piksele bez glebi deprojektuja sie do (0,0,0), czyli do pozornej odleglosci rownej offsetowi plaszczyzny. Domkniecie morfologiczne zalepia nimi dziury w masce obiektu. Geometrie (centroid, wysokosc, szerokosc) licz WYLACZNIE z pikseli faktycznie nad plaszczyzna ziemi, inaczej wysokosci wychodza absurdalne (np. 61 cm przy limicie 40 cm), a szerokosc chwytu skacze miedzy 14 a 44 cm na tej samej, nieruchomej scenie.
-
Offset dopasowanej plaszczyzny ziemi (RANSAC) to zmierzona wysokosc kamery - porownanie go z wysokoscia montazu to darmowy test, czy RANSAC zlapal faktycznie ZIEMIE, a nie sciane albo blat. Wylapalo dwa razy w jednej sesji przestawiona kamere. Bez tej kontroli wszystkie dystanse licza sie od zlej plaszczyzny i mimo to wygladaja wiarygodnie.
-
W kadrze na tym torze nie ma zadnego "brazu" - detekcja szyszek po kolorze (HSV) sie nie nadaje. Zmierzone HSV (OpenCV, zakres 0-179) o zmierzchu: murawa H
90 (cyjan), szyszki H148 (fiolet), a ogony rozkladow zachodza na siebie. Rozdziela je JASNOSC: szyszki V94, murawa V152. Prog na jasnosc dziala, ale jest kruchy - slonce albo cien go przesuwa. Przed strojeniem progow HSV zamroz balans bieli i ekspozycje (detect_object.py --white-balance --exposure), inaczej progi dobrane dzis nie trafiaja jutro. Domyslna detekcja idzie po GLEBI (dowolny ksztalt), kolor jest tylko opcja. -
opencv-python+opencv-python-headlesszainstalowane razem psuja GUI.cv2.imshowpada ("The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support"), bo headless nadpisuje binaria GUI w tym samym namespacecv2. Fix: odinstalowac oba i postawic od nowa tylkoopencv-python(na maszynie z ekranem).lerobotciagnieopencv-python-headlessjako zaleznosc - ten konflikt wraca po kazdympip install lerobot, sprawdzac za kazdym razem. Na Pi (headless, bez ekranu) jest odwrotnie: trzymac TYLKOopencv-python-headless(deploy/setup_pi.shodinstalowujeopencv-pythonpo instalacjirequirements-pi.txt). -
D415 znika z
rs.context().query_devices()po nieczystym zamknieciu procesu (crash przedpipeline.stop(), albo proces zabity przeztaskkill/kill -9) - Windows/librealsense zostawia uchwyt USB w zlym stanie. Objaw:RuntimeError: No device connectedalboHResult 0x800703e3przypipeline.start(), mimo ze kamera fizycznie podlaczona. Fix: sprawdzic zawisle procesy Pythona (tasklist | grep python/ps aux | grep python) i dobic je - zombie trzymaja uchwyt USB nawet gdy proces "juz wyszedl" wedlug wrappera. Fizyczny replug USB jako ostatecznosc. Zawsze zamykaj stream przezfinally: pipeline.stop(), nigdy golym Ctrl+C/kill -9. -
Laptop z portami USB 2.0 Type-A cofa D415 do trybu USB 2.1 i obcina tryby (848x480 dziala tylko na 10/6 Hz, koloru w tej rozdzielczosci nie ma wcale). To nie jest wina kabla - sprawdzone, ze porty Type-A sa fizycznie USB 2.0, USB 3 jest tylko na Type-C. 640x480@30 dziala i daje realnie 18-22 fps, co w zupelnosci wystarcza do skanu na postoju.
-
Jetson Nano P3450 odrzucony jako platforma. Max JetPack 4.6 = Ubuntu 18.04 + Python 3.6, a lerobot wymaga Pythona 3.10+. Dlatego wybrane Raspberry Pi 5 (8 GB).
-
Pinowanie lerobot / numpy (
constraints.txt,numpy==2.5.3):lerobotna Python 3.14 (laptop Windows) probuje przebudowac numpy ze zrodla i pada - brak gotowego kola (wheel) dla tej wersji Pythona oraz za stary kompilator GCC w systemie do budowy ze zrodel. Instalowaclerobotz--no-depsi doinstalowywac brakujace zaleznosci recznie (patrz docs/SETUP.md), zawsze z-c constraints.txt --only-binary=:all:gdzie sie da. Na Pi (Python 3.12,requirements-pi.txt) tego problemu nie ma - NIE uzywac tamconstraints.txt, jest tylko na Windows/Python 3.14. -
Siec
hacker-bloc(demo) miala tylko IPv6, GitHub tylko IPv4 - przez to nie dzialal anigit pullna Pi, ani ICS z laptopa dla Pi. Hotspot z telefonu dawal IPv4 i dzialal. Zobacz tez docs/SETUP.md (sekcja Pi) po biezacy sposob laczenia z Pi. -
pkill -f nazwaprzez SSH potrafi zabic sam siebie, gdy szukana nazwa wystepuje tez w tresci samej komendypkill(proces konczy sie z kodem 255, myli przy diagnozie). Zamiast tego:fuser -k port/tcpalbo zabij po konkretnym PID. -
Nie rob ciezkiego re-renderu calego DOM przy kazdym ticku WebSocketa (bylo co 30 ms) - realne klikniecia myszka/palcem w liscie/przyciskach zaczynaja sie gubic, mimo ze zautomatyzowany (precyzyjny) klik dalej dziala bez zarzutu. Rob diff/porownanie stanu i przebudowuj DOM tylko wtedy, gdy dane faktycznie sie zmienily (dotyczy panelu
web_control.py/frontend.html). -
Trzymaj pola trybu (np.
state.playback_name) w spojnosci przy KAZDEJ zmianie trybu (set_mode), nie tylko przy naturalnym zakonczeniu odtwarzania - inaczej UI panelu pokazuje "duchy" poprzedniego stanu. -
pinecone_config.jsonjest w gicie, adeploy/push_to_pi.shgo NADPISUJE na Pi przy kazdym pushu. Wartosc zmierzona i wpisana recznie na sprzecie (np. nowy prog HSV) przetrwa tylko do nastepnego pushu, jesli nie trafi do repo (commit/PR) - inaczej push przywraca stara wersje z brancha/mastera i pomiar przepada. Tak stracono raz wpisany na Pi prog HSV i sekcje "camera". Wartosci zmierzone na sprzecie wpisywac do configu W REPO, nie tylko lokalnie na Pi. -
Sesja tmux odpalona z NIEINTERAKTYWNEGO polaczenia ssh na Pi ginie po rozlaczeniu ssh - nawet z
nohup/setsidprzezyla tylko jedno rozlaczenie, przy drugim zniknela. Interaktywne narzedzia ramienia (np.tools/record_motion.py,tools/arm_play.py) odpalac we WLASNYM terminalu operatora, interaktywnie:ssh -t robot@<ip> "cd ~/hackaton && .venv/bin/python tools/...", nie z automatycznej (nieinteraktywnej) sesji. -
phyphox na iPhonie slucha na porcie 80, nie 8080 (8080 to Android; serwer
GCDWebServer). iPhone-hotspot ma adres 172.20.10.1, wiecheading.phyphox_url=http://172.20.10.1. Serwer znika, gdy phyphox pojdzie w tlo albo zgasnie ekran (Connection refused) - Blokada automatyczna ekranu: Nigdy, phyphox na wierzchu. Pomiar startuje sam (/control?cmd=start). Test:python tools/phyphox_check.py. -
Skret hovera: martwa strefa zalezy od tego, czy robot stal. Zmierzone zyroskopem telefonu (
tools/calibrate_turn.py): z miejsca rusza dopiero od |b| ~160, a juz krecacy sie kreci od ~100; 10 jednostek wyzej to +0.3..0.7 rad/s, przy tym samym b 160 raz 0.43, raz 1.08 rad/s. Stala tabelaxiao_steer_min/maxtego nie opisze - obrot po zyroskopie (pinecone_bot/turn_loop.py).xiao_steer_min60 z configu nie rusza robota wcale. -
Przed pomiarem kamera sprawdz, gdzie patrzy. Kamera siedzi na ramieniu; raz patrzyla w sufit i
calibrate_drive.py"zmierzyl" 2 cm, choc robot przejechal 40 cm. Narzedzie zapisuje terazframes/calibrate_drive.jpgi ostrzega, gdy glebia sie nie zmienia. -
./arm.sh movepo ruchu wylacza moment w serwach (lerobotdisconnect), ramie opada. Do trzymania pozycji (np. kamera poziomo) -tools/arm_web.py --no-homei jog przez panel alboPOST /api/cmd{"cmd":"jog","joint":"wrist_flex","step":5}. -
RealSense pamieta opcje po poprzednim procesie. Program z
camera.lock_autozamraza ekspozycje (np. 166 w cieniu); nastepny program bez blokady dostaje ta sama reczna ekspozycje i na sloncu obraz jest bialy.RealSenseCamerabezlock_autowlacza teraz auto z powrotem. -
Mapa do lokalizacji: nagrywac w tej samej pozie kamery, w ktorej robot bedzie sie lokalizowal (
motions/patrz.json,tools/arm_hold.py patrz), wolno, na koniec wrocic na start. Nagranieogrod1(329 s): RTAB-Map skleil tylko czesc, fragment przy plocie odpadl i ze startu przy plocie lokalizacja nie lapala. Punkty mapy brac do 6 m (plot 4-5 m od robota). -
tools/estop_server.pyzabija tylko programy z listyTARGETS. Nowy program, ktory jezdzi baza, trzeba tam dopisac (zygzak nie byl na liscie). -
deploy/push_to_pi.shnadpisuje pliki, ktore sa tylko na Pi. Kopiujemotions/ipinecone_config.jsonz laptopa (rsync, a bez rsyncscp -r- laptop z git-bash rsync nie ma). Prawdziwymotions/drop_box.jsoni zmierzone wartosci configu z Pi przepadaja (w repo jest placeholder). Bezpieczniej wysylac wybrane pliki:git archive origin/<branch> <sciezki> | ssh robot@172.20.10.4 "tar -x -C ~/hackaton". (zglosila sesja "Dostep do kamer", 2026-09-27)