Návod
Obsah |
Návod na použitie návodu
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).
Prehľad projektu
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.
Javadoc k všetkým projektom možno nájsť na našom serveri
Jim
Obsahuje samotného agenta - robota, ktorý sa pripojí k serveru a hrá futbal.
Beh agenta
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
- Načítavanie pohybov z XML súborov v adresári
moves
- Načítanie anotácií
- Spracovanie parametrov príkazového riadku
- Spustenie TFTP servera použitého pre komunikáciu s test frameworkom
- Prípadné vytvorenie GUI
- Spusteniu ruby skriptov
- Vstup do hlavného cyklu
Pohyby
Správanie agenta je riadené kódom, ktorý sa dá rozdeliť do viacerých vrstiev
- Na vrchu je plánovač, čo je v súčasnej verzii ruby skript spravovaný triedou
Planner
. Štruktúra a použitie týchto skriptov je podrobnejšie popísané v sekcii Plánovacie skripty. - Plánovač vytvára inštancie tzv. high skillov - vyšších pohybov tiež implementovaných v ruby, popísaných v časti Plánovanie a vykonávanie pohybov.
- High skilly počas svojho behu vyberajú, ktorý nižší pohyb, tzv. low skill sa má vykonať. Slovo "pohyb" vo väčšine dokumentácie označuje práve jeden z týchto low skillov. Toto je takisto popísané v sekcii Plánovanie a vykonávanie pohybov.
- Low skill je sám o sebe v podstate len skupina metadát, ktoré určujú jeho názov, ďalšie podobné informácie a počiatočnú fázu. Samotné jadro pohybu sa nachádza práve v týchto fázach, ktoré nie sú nijak pevne spojené s konkrétnymi low skillmi. Je ale zaužívaná konvencia, že väčšina fáz patrí k jednému konkrétnemu low skillu, čo je vyjadrené ich menom.
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.
Ďalšie čítanie
- Popis formátu XML súborov pohybov je na stránke XML súbory s pohybmi
- Popis súčasne existujúcich pohybov (asi neaktuálne) je na stránke Popis existujúcich pohybov.
GUI
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
Komunikácia so serverom a s testovacím frameworkom
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
Ďalšie čítanie
Časti odkazované zo sekcie Beh agenta.
RoboCupLibrary
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.
TestFramework
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.
Overview
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:
- Pripojenie k serveru
- Spustenie vlastného servera pre pripájanie agentov - popísané v sekcii Spojenia medzi agentmi a test frameworkom
- Spustenie GUI
- Popri behu ostatných častí na pozadí neustále prebieha spúšťanie test caseov z frontu
ProcessQueue
. Sem sa vkladajú test casy volaním metódyenqueueTestCase
. Toto je podrobnejšie popísané v časti Testy - Takisto má bežať spúšťanie trénovacích úloh z frontu TrainerQueue, tréner však v súčasnej dobe nie je implementovaný
Z 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.
Pripojenie k serveru
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.
Správa agentov
Spojenia medzi agentmi a test frameworkom
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
Spúšťanie a riadenie agentov
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.
Monitorovanie
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.