Tento návod má slúžiť na pomoc s orientáciou sa v kóde. Snažil som sa ho písať tak, aby bol zrozumiteľný aj pre ľudí, ktorí sa v daných častiach kódu nevyznajú. Pre jeho čítanie je však stále treba minimálne pozerať si príslušné javadoc komentáre k linkovaným triedam a metódam. Tiež je vhodné mať pri čítaní otvorený Eclipse a prechádzať sa po kóde (pomocou Ctrl+click na triedu/metódu/field, a right-click → References → Workspace na tom istom), o ktorom čitateľ zrovna číta.
Pre zorientovanie sa v určitej oblasti neznámeho kódu tiež môže zafungovať nechať si v celej wiki vyhľadať názov triedy z toho kódu. Je tak šanca, že sa tak nájde práve relevantná časť návodu.
Inak sa dá návod čítať aj postupne od hora dole, s občasným prečítaním niektorého z linkovaných odkazov.
Návod reprezentuje aktuálnu verziu kódu v čase jeho písania, bude ho teda potrebné priebežne dopĺňať. Z toho dôvodu je dobré mať podrobné a užitočné hlavne javadoc komentáre, pretože je u nich väčší predpoklad, že budú updatované zároveň s kódom. Prinajmenšom je treba označiť už neaktuálne časti návodu.
Test framework je v súčanosti popísaný o niečo podrobnejšie a lepšie než samotný agent. Ten by sa dal ešte mierne vylepšiť. Tiež by sa dali niektoré spomenutia tried a metód zmeniť na odkazy - nie u všetkých to tak totiž je (väčšinou to ale je splnené pri prvom spomenutí v nejakej sekcii).
Kód agenta sa skladá z 3 základných častí, ktoré sú reprezentované ako samotné projekty v Eclipse. Jim a TestFramework závisia na RoboCupLibrary a po novom aj TestFramework závisí na Jim, čo robí celú knižnicu (RoboCupLibrary) tak trochu zbytočnou. Pôvodná myšlienka bola mať spoločné časti agenta a test frameworku na jednom mieste, no pridaním informácií o stave sveta agentov do test frameworku sa medzi tieto „spoločné časti“ zaradila obrovská časť kódu samotného agenta. Takže teraz aj tak test framework závisí na triedach z projektu samotného agenta.
Obsahuje samotného agenta - robota, ktorý sa pripojí k serveru a hrá futbal.
Na to, aby agent správne fungoval, musí pred jeho spustením byť spustený server. Ak sa má agent podľa nastavenia pripojiť k test frameworku (čo väčšinou nie je nutné, test framework toto nastavenie u agentov ktorých spúšťa prepíše cez command line argument), mal by byť spustený aj ten.
Spustenie agenta do momentu kým bude pripravený je pomerne zdĺhavá záležitosť. Najväčšiu časť si ukrojí načítanie JRuby. Celkovo sa dá na pomerne slabšom PC rátať s cca. 10 sekundovým štartom.
Vstupným bodom agenta je trieda sk.fiit.jim.init.Main''
. Na začiatku dôjde k nasledovným operáciam
moves
Správanie agenta je riadené kódom, ktorý sa dá rozdeliť do viacerých vrstiev
Planner''
. Štruktúra a použitie týchto skriptov je podrobnejšie popísané v sekcii Plánovacie skripty.
Na načítanie pohybov z XML súborov slúži trieda SkillsFromXmlLoader''
. Objekty pohybov a fáz sú spravované triedami LowSkills''
a Phases''
, odkiaľ sa dajú získať podľa názvu metódou get. Keďže načítanie pohybov je hrozne pomalé, ukladá sa ich parsovaná podoba do súboru ./movecache, ktorý sa pri budúcom načítaní použije, pokiaľ od jeho vytvorenia nebol žiadny pohyb zmenený. V takom prípade sa súbor vytvorí nanovo.
Agent má jednoduché GUI v triede ReplanWindow''
umožňujúce znovunačítanie pohybov a preplánovanie. Tieto akcie sú určené na to, aby sa zmeny vykonané v pohyboch alebo plánovacom skripte prejavili hneď, bez potreby reštartu agenta. Preplánovanie v súčanosti znamená opätovné spustenie všetkých ruby skriptov. Keďže v súbore plánovačov by malo byť na konci zavolanie metódy reset, spôsobí to resetnutie všetkých plánovačov (toto dosť divné riešenie sme zdedili a zatiaľ sme nemali potrebu ho meniť). Nežiadúcim efektom ( TODO: možný bug) je, že pri znovunačítaní nastavení sa opäť použije defaultný plánovač, aj ak bol predtým zmenený metódou Planner.setPlanner''
Agent je pripojený k serveru na porte 3100.
O komunikáciu so serverom sa stará trieda Communication''
. Pripojenie sa inicializuje metódou start, tá volá metódu mainLoop spúšťajúcu hlavný cyklus. Počas jeho častí môžu sa skladá výsledná správa volaním metódy addToMessage. Tá sa na konci každého vykonania cyklu odošle.
Komunikácia s test frameworkom je popísaná na stránke Komunikácia agenta s test frameworkom
Časti odkazované zo sekcie Beh agenta.
Obsahuje triedy spoločné pre agenta a test framework.
V súčasnosti je tam určitá duplicita funkcionality medzi triedami Vector3 a Vector3D. Toto by sa malo vyriešiť používaním len triedy Vector3D.
Test framework pôvodne slúžil len k vykonávaniu vopred pripravených automatických testov na zmeranie schopností agenta. Dnes okrem toho plní aj úlohu akéhosi ovládacieho centra pre prácu s viacerými agentami a serverom pri ručnom testovaní, tvorbe anotácii a ďalších podobných úlohách.
Test framework obsahuje mnoho funkcionality, ktorá môže byť využívaná viacerými front-endmi, tu nazývanými implementácie (triedy dediace Implementation''
). V praxi je však plne použiteľná len jedna, LocalImplementation''
. Okrem nej existuje ešte experimentálna implementácia MpiImplementation''
, zamýšľaná za účelom behu veľkého množstva náročných výpočtov na školských strojoch (viď analýza tejto možnosti ). Momentálne však nie je plne funkčná. Tento návod bude popisovať len funkčnosť lokálnej implementácie, aj keď väčšina častí nie je závislá na konkrétnej implementácii.
Vstupným bodom test frameworku je trieda sk.fiit.testframework.init.Init''
. Má za úlohu načítať konfiguráciu, na základe tej vybrať príslušnú implementáciu (front-end) a spustiť ostatné časti programu. To zahŕňa:
ProcessQueue''
. Sem sa vkladajú test casy volaním metódy enqueueTestCase''
. Toto je podrobnejšie popísané v časti TestyZ tohto vyplýva, že v test frameworku naraz beží pomerne veľké množstvo threadov. Preto musí byť u metód používajúcich zdieľané dáta zabezpečený bezpečný prístup k nim.
Test framework pre svoj beh nevyhnutne musí byť pripojený k serveru - bez toho odmietne bežať. V prípade správneho nastavenia sa v situácií keď server nebeží test framework pokúsi spustiť server sám, po 6 sekudách to ale v prípade neúspechu vzdá a skončí (server teda musí nabehnúť do 6 sekúnd, čo väčšinou nie je problém). Ak test framework server sám spustil, pri svojom ukončení sa ho takisto ukončí. Toto ukončenie môže byť jednoduché zničenie procesu, alebo sa môže za týmto účelom spustiť externý program, čo je potrebné na windows, kde server štandardným spôsobom nemožno ukončiť.
Okrem portu 3100, na ktorý posiela test framework serveru príkazy na manipuláciu so svetom (implementované v triede RobocupServer''
), sa testframework pripája aj na monitorovací port 3200. Tu dostáva kompletné informácie o celej simulácii, dosť podrobné na to aby sa z nich dala zrekonštruovať celá scéna. Tieto informácie sú však len vo forme popisu geometrických objektov, preto ich treba podľa určitých pravidiel správne priradiť k reálnym objektom (lopta, hráči). Toto je podrobnejšie popísané v sekcii Monitorovanie
Monitorovacie spojenie so serverom beží v samostatnom threade a je reprezentované triedou RobocupMonitor''
. Táto trieda síce podporuje spojenia k viacerým rôznym serverom naraz, toto však v lokálnej implementácii nemá príliš veľké využitie (a takisto na to nie je prispôsobené GUI). Spojenie ku konkrétnemu serveru sa z nej dá získať statickou metódou getMonitorInstance()''
.
Obe spojenia (riadiace - 3100 a monitorovacie - 3200) komunikujú so serverom pomocou textových S-výrazov, protokolom popísaným na stránkach SimSparku.
Test framework beží ako server (štandardne na porte 8000), ku ktorému sa majú pripájať agenti. Na tomto spojení získava test framework on agenta správy o jeho stave, toto spojenie teda slúži ako akýsi monitor agenta. Tento server je implementovaný triedou AgentMonitor''
(podobne ako u monitora serveru týchto inštancií môže byť viacero, no v lokálnej implementácii sa používa vždu len jedna), ktorá sa stará o prijímanie nových spojení od agentov. Každé jedno takéto spojenie je reprezentované triedou AgentMonitorThread''
, ktorá má na starosti spracovanie správ prichádzajúcich od agenta pomocou triedy AgentMonitorMessage''
.
Ďalšie spojenie medzi agentom a serverom je (nepovinný) TFTP server bežiaci na strane agenta. K tomuto sa pripája test framework a využíva ho na ovládanie agenta. Ak test framework pošle agentovi cez toto spojenie súbor s názvom ruby.exec
, agent vykoná ruby kód obsiahnutý v tomto súbore. To nie je zrovna najšťastnejšie riešenie, nakoľko to dosť hrubo porušuje enkapsuláciu (táto funkcionalita vnútri test frameworku závisí na veľmi špecifických detailoch implementácie vnútri agenta), ale nateraz to stačí. Používané ruby príkazy sa nachádzajú v metódach ktorých názov začína na invoke
v triede AgentJim''
.
Obe formy komunikácie z pohľadu agenta aj test frameworku sú podrobnejšie popísané v časti Komunikácia agenta s test frameworkom
Test framework teda môže pracovať s ľubovolnými agentami, ktorí sa pripoja na jeho hlavný port (štandardne 8000). Okrem toho že to môžu byť agenti spustení externe, dokáže si test framework agentov spúšťať aj sám. Okrem pohodlia je výhodou možnosť zobrazovať štandardný výstup agentov priamo v GUI test frameworku.
Agenti sú reprezentovaní objektami triedy AgentJim''
. Agentov ktorí sú pripojení k test frameworku spravuje trieda AgentManager''
. Dá sa od nej získať agent podľa čísla uniformy a názvu tímu, metódou getAgent''
. V prípade, že sa taký agent v hre nenachádza, môže byť spustený. Kombinácia čísla uniformy a názvu tímu tvorí jedinečný reťazec, podľa ktorého je každý agent identifikovaný. Aj keď AgentManager agenta spustí okamžite, začne ho spravovať (pridá do mapy runningAgents
) až po tom, čo sa tento agent pripojí k test frameworku. Na pripojenie agenta sa zvyčajne čaká (blokujúco) 15 sekúnd. Toto čakanie je možné zmeniť metódou setAgentWaitTime''
. V prípade nastavenia na nízku hodnotu ale treba rátať s tým, že getAgent
vráti null, a agent bude dostupný až niekedy neskôr, čo nie je vhodné napr. pre test casy. Táto hodnota by teda mala byť dostatočne veľká na zaručenie toho, že sa dovtedy agent pripojí.
Pre spustenie agenta asynchrónne, napr. z GUI, kde nemusí byť dostupný okamžite, je lepšie použiť metódu startAgent''
Trieda AgentManager
tiež môže ostatné triedy informovať o novo pripojených a odpojených agentoch pomocou rozhrania IAgentManagerListener''
. Toto sa využíva napríklad v triede AgentComboModel''
, ktorá zabezpečí aktuálnosť všetkých combo boxov v GUI obsahujúcich zoznam pripojených agentov.
Táto sekcia popisuje ako prebieha monitorovanie servera, plus kde získať a ako nakladať s aktuálnymi údajmi, ktoré sú jeho výsledkom. Jedná sa o pozíciu lopty a pozície agentov.