Minden ami „robot”

Beszélgettünk…

a robottal. Nem volt könnyű összehozni a kommunikációt, de végül csináltam egy C# wrappert a Mindstorms SDK GhostAPI-ja köré. A múltkor említett MS-féle implementáció sajnos túlságosan magasszintű volt, és ami a legfőbb gond: mindent közvetlenül akart irányítani az RCX-en, én meg elhatároztam, hogy a robot magától fog tudni a labirintus cellái között mozogni.

http://www.pinvoke.net/ segítségével, meg egy C-s header fájllal elkészült az wrapper, aztán egy C++ példa alapján sikerült átküldeni egy számot a robotra, amit az beszorzott kettővel, és végül a PC visszaolvasta az eredményt. Numerikus coprocinak kicsit lassú, de azért működik…

Időközben csináltam (gányoltam) egy labirintus editort, amit összekötöttem a robottal, és most a billentyűzetről távirányítással tudom vezérelni. A múltkor már említett akadályérzékelőt is felhasználva megcsináltam a labirintus felderítést is. Ezzel a Verseny24 labirintus témaköre lényegében kész. Már csak pár algoritmust kéne lekódolni, hogy a tudást felhasználva magától derítse fel a labirintust a robot, találja meg két pont között a legrövidebb utat, segítsen egy bajbajutott társának (MűanyagTál 1.0) eljutni A-ból B-be, satöbbi. Tkp. egész életemben ilyenekkel foglalkozom, úgyhogy ez a rész annyira nem vonz.

Ilyen a labirintus editor. A robot úgy néz ki mint egy tank, de a valóságban sokkal aranyosabb.

Még egy LEGO-LOGO program hiányzik, és azzal 5 évvel a verseny után végre kész is lesz minden (vagy inkább: meg lesz oldva minden).

Még több robot

Folytattam a robotépítést és a Verseny24 feladatokat. Most éppen egy labirintusban mozgó roboton dolgozok. A labirintus cellákra osztott, minden cellának négy szomszédja van (kivéve a labirintus szélét természetesen). A cellák szigszalaggal vannak kijelölve, és a navigációt elősegítendő, mindegyik közepén vezet egy út, szintén szigszalagból. Az alábbi képen falak (akadályok) még nincsenek a labirintusban, ez csak az egész alapja. 2×4 cellát látunk, de a jobb szélső cellák széle lemaradt a képről.

Első lépésként csináltam egy cellák között mozgó robotot. Ahhoz, hogy egyet előrelépjünk két fekete-fehér kereszteződésen kell áthaladni. A múltkori vonalkövető robot tapasztalatait felhasználva a feladat viszonylag egyszerű, mégis elég sokat szívtam vele a fényérzékelő tökéletlensége miatt. A parketta és a fehér szigszalag fényessége között ugyanis nagyon kicsi az eltérés, ráadásul a fekete és fehér szigszalag határán az érzékelő időnként parkettát észlelt. Utóbbit csak a metszéspontok kihangsúlyozásával (még több fehér szigszalag, a képen T betűhöz hasonló végződések) tudtam orvosolni.

Többszöri ‘szarok az egészre’ után, végül mégis sikerült a sima navigáció. Ezen felbátorova, kicsit bonyolítottam a feladaton, és akadályokat tettem a labirintusba. Most a robot csak akkor hajtja végre a mozgást, ha útközben nem ütközik bele semmibe. Ellenkező esetben egyszerűen visszamegy a kiindulási pontra. A videón a ‘menj egyet hátra’ parancsot látjuk meghiúsulni egy flakon miatt (Vitaflóra, citrusfélék tápoldata).

YouTube előnézeti kép

A felvételen hallható csipogás a tesztoutput része:

  • 1 csipogás: hoppá, itt egy érdekes vonal. (Forgáskor illetve haladáskor mást jelent az érdekes.)
  • 2 csipogás: hazaértem
  • bonyolult csipogás: nem  sikerült a feladat.

A robot véges memóriája miatt a következő mérföldkő a számítógép-robot kommunikáció. Aztán akár csinálhatok egy labirintus feltérképező robotot is.

A robot

Pénteken egy ügyes húzással belegyömöszöltem a laptop táskába a LEGO Mindstorms készletünket, és kicsempésztem az irodából. Reggel fél háromig játszottam vele. Utána kicsit lepihentem, de hajnali hétnél tovább nem sikerült bírni, úgyhogy folytattam, ahol abbahagytam.

Először csináltam egy fasza robotot, ami a múltkori közös próbálkozásunkkal ellentétben TUD kanyarodni.

Ezután jöhetett a programozás. LEGO robotot NQC-ben (is) szokás programozni, amiről azt kell tudni, hogy nagyon fapados nyelv. A név kifejtése Not Quite C, de szerintem a C-re csak a szintaxisa hasonlít.

Hogy érezzük miről is van szó: függvények nincsenek. Van subrutin, de ebből csak összesen 8 tárolható a robotban. Aztán van még inline függvény, aminek a sub-tól eltérően lehetnek paraméterei, de visszatérési értéke ennek sincs. A trükk az, hogy a függvény törzse fordításkor a hívás helyére másolódik, amivel kicselezhető a firmware szabta nyolcas korlát, cserébe viszont hamarabb kifogyunk a memóriából…

Mivel a nyelv csak az int-et ismeri adattípusként, lebegőpontos műveletek nincsenek. Így aztán már egy szimpla kerekítési problémán is gondolkodni kell. Pozitív számokra ugye 0.5-öt hozzáad az ember, és elhagyja a tizedesjegyeket. Ez még éppen érthető, de ehhez képest itt még az osztás előtt hozzá kell adni a számlálóhoz a nevező felét. Brrr.

Hogy mondjak valami jót is: vannak párhuzamosan futtatható taszkok. Bár erre egyelőre nem volt szükség. (Gondolom az is gagyi egyébként.)

Mindenesetre megcsináltam pár algó+robot változatot a vonalkövetés problémára. Ez amolyan Hello World! robotéknál. Adott egy fehér háttéren, egy annál sötétebb színű, önmagába záródó vonal. Ezen kell egy fényérzékelővel felszerelt robotot elveztetni.

A legegyszerűbb megoldás talán a következő:

while true
if <az érzékelő a vonalon van> then
<kanyarodjunk jobbra>
else
<kanyarodjunk balra>

Ehhez csak a fenti érzékelést, és a két cselekvést végrehajtani képes robotra van szükségünk. Hallgatólagosan feltettük azt is, hogy a robotunk nem helyben kanyarodik, hanem, mondjuk egy autóhoz hasonlóan, kanyarodás közben kicsit előre is halad.

Ha minden jól ment, akkor robotunk szépen cikkcakkban végig fog menni a vonal jobb szélén.

Jó, jó, de honnan tudjuk, hogy az ‘érzékelő a vonalon van’? Először a fényérzékelővel bemérjük a vonal fényességét (mondjuk 29%), meg a háttér fényességét (55%), az kettő átlaga 42%. Ha a fényérzékelő ennél kevesebbet mutat, úgy ítéljük meg, hogy a vonalon vagyunk:

<az érzékelő a vonalon van> = ÉRZÉKELŐ_PILLANATNYI_ÁLLAPOTA < ÁTLAG

A manuális kalibrálásnál jópofább, ha a robot magától tanulja meg az értékeket. Ehhez csak az érzékelő eddigi minimum és maximum értékeit kell tárolni, amiből az ÁTLAG számolható.

Fejleszhetünk az algoritmuson úgy is, hogy a fényességi tartományt 2 helyett 3 részre osztjuk, és a középsőben a robot előre halad. Aztán lehet még tovább bontogatni, és az egyes tartományokhoz különböző kanyarodási sebességeket rendelni.

YouTube előnézeti kép

Itt aludtam el.

Reggel elkezdtem kutatni a .NET-es kommunikáció után. A fő célom ezúttal egy Morse-kód leolvasó robot elkészítése volt, ami a végén feltölti PC-re az adatokat, és a gép ebből kiszámolja a szöveges megfelelőt. (Ezt még Verseny24-en kellett megoldanunk annó 2002-ben.)

Találtam egy microsoftos blogot, ahol készítettek egy wrappert a LEGO Mindstorms SDK-s robot-PC kommunikáció köré. Ezzel közvetlenül lehet a robotot irányítani, azaz nem kell NQC-vel szívni. C#-ban megírja az ember, amit szeretne, a framework pedig infrán lekommunikálja az egészet a robottal. Talán mondanom se kell, mekkora felüdülést jelentenek az NQC után az olyan apróságok, mint pl., hogy a szenzorok változásáról egy .NET event formájában kapok hírt, vagy hogy a kib*szott kerekítéshez meghívhatom a Math.Round() metódust…

Sajnos semmi sincs ingyen, két kommunkációval kapcsolatos hátránya azért van a dolognak:

  1. nagyon lassú
  2. az adatok közvetítéséhez az infra portoknak végig látni kell egymást. Kanyargó robotnál ez gondot jelenthet.

Szerencsére, a Morse olvasásnál elég egyenesen előre menni, és jókora fogaskerék áttétekkel nagyon lassan haladó robot is lehet építeni, így mindkét probléma orvosolható. Már csak egy darab parkettát kellett találnom a pincében, meg szigetelőszalagot, hogy felvéshessem a HELLO szó betűit, amit aztán másodikra sikerült is dekódolni.