Návod/Monitorovanie
Z RoboCupTP wiki
Späť na Návod
Obsah |
Monitorovanie servera v test frameworku
Základy
Test framework je pripojený k serveru na porte 3200, odkiaľ od neho prijíma správy o aktuálnom stave kompletnej simulácie. Tieto správy sú podľa protokolu SimSparku S-výrazy obsahujúce niekoľko špecifických údajov a popisujúce graf scény. Test framework z tohto grafu vyberá pre seba zaujímavé informácie (poloha lopty, poloha hráčov).
Implementácia a použitie
Monitorovanie beží v samostatnom threade v triede RobocupMonitor
, ktorej inštancia sa dá získať metódou getMonitorInstance()
. Táto trieda sa pri každej príchodzej správe zo serveru pozrie do hlavičky správy, na základe čoho určí o aký typ správy sa jedná.
Celý stav simulácie - informácie z oboch typoch správ a kompletná scéna - je uložený v objekte triedy SimulationState
. Takýto objekt s aktuálnym stavom vlastní trieda RobocupMonitor
, ktorá ho priebežne updatuje na základe príchodzých správ. Dá sa z nej získať metódou getSimulationState
.
Takisto je možné sledovať všetky updaty týchto údajov zaregistrovaním observeru implementujúceho ISimulationStateObserver
v objekte triedy SimulationState
.
Parsovanie správ
Každá správa zo servera prijatá triedou RobocupMonitor
je najprv rozparsovaná
- environment message - obsahuje informácie o veľkosti ihriska, lopty a pod. (viď protokol), je parsovaná triedou
EnvironmentMessageParser
- game state message - obsahuje informácie o stave hry, napr. o skóre, čase a pod., je parsovaná triedou
GameStateMessageParser
Po oboch typoch správ vždy nasleduje graf scény, buď kompletný, alebo len čiastočný (vyjadrujúci zmenu oproti predchádzajúcemu stavu). Tento je rozparsovaný pomocou tried SceneGraphHeaderPartParser
a SceneGraphPartParser
Aplikovanie rozparsovaných údajov
Trieda RobocupMonitor
teda rozparsuje správy príslušným parserom do objektov podtried triedy Message
. Tieto dáta sú následne aplikované triedou MessageInterpreter
. Okrem informácií z environment správ a game state správ, ktoré sa uložia do aktuálneho stavu simulácie, je treba spracovať graf scény, čo sa deje vnútri triedy SceneUpdater
. Táto okrem vytvorenia celého grafu z neho vyberie uzol reprezentujúci loptu (uloží sa do jednoduchého 3D vektora Scene.ballLocation
) a uzly reprezentujúce hráčov (objekty triedy Player
), ktoré sú prepojené s objektami agentov AgentJim
. Toto prepojenie je popísané v nasledovnej podkapitole.
Ako už bolo uvedené, s týmito údajmi sa dá pracovať pomocou objektu triedy SimulationState
získanej volaním getSimulationState
z RobocupMonitor
. Zmeny je možné sledovať pomocou observeru ISimulationStateObserver
.
Pre jednoduchšiu prácu so stavmi simulácie v rôznych časoch možno použiť aj triedu MeasurableInformation
, ktorá si skopíruje aktuálny stav simulácie a neskôr možno dva takéto objekty porovnať.
Prepojenie grafu scény a objektov agentov
Server posiela graf scény len vo forme 3D objektov, informácia o tom ku ktorému pripojenému agentovi ktorý objekt patrí sa tam priamo nenachádza, treba ju teda získať iným spôsobom. Jedna z možností by možno (?) bola zistenie podľa materiálov (farba určí tím, číslo na drese hráča?). Ja sa však spolieham na fakt, že modely sú posielané v poradí, v akom sa hráči pripojili. Toto síce nie je priamo popísané v protokole, takže to možno nie je 100% spoľahlivé, no podľa mojich testov to v praxi funguje. TODO:: pridať poznámku do príslušnej časti kódu, že ak to prestane fungovať, treba overiť toto.
Na využitie týchto informácií je treba ukladať informácie o poradí pripojenia agentov. Toto je uložené v AgentManager.orderedAgents
. Pretože objekt grafu scény bude pri pripojení agenta vytvorený skôr než objekt AgentJim
, treba túto asociáciu vytvoriť oneskorene. To funguje tak že
- Pri vytvorení objektu grafu scény (trieda
Player
) sa do neho uloží jeho poradie. Ak príslušnýAgentJim
objekt už existuje, priradí sa mu (podľa poradia daného AgentJim objektu). V opačnom prípade sa zaradí do frontu v triedeAgentManager
, aby sa prepojenie vytvorilo pri vytvorení objektuAgentJim
- Po vytvorení
AgentJim
sa pozrie či sú nejakéPlayer
objekty vo fronte, ak áno, vyberie sa prvý a vytvorí sa asociácia.
Teoreticky to nemusí byť úplne spoľahlivé, hlavne keď sa pripojí viac agentov vo veľmi krátkom časovom úseku (prakticky naraz). V praxi to ale funguje relatívne dobre.
Objekt triedy Player sa dá z objektu triedy AgentJim získať pomocou metódy getSceneGraphPlayer
. Tá vráti poradie Player objektu v zozname vrátanom metódou getPlayers triedy Scene
. Objekt triedy Scene sa získa metódou getScene z objektu triedy SimulationState. V prípade, že prepojenie medzi agentom a objektom hráča v dátach z monitora ešte nebolo vytvorené, vráti getSceneGraphPlayer číslo -1.
Objekt triedy AgentJim sa z objektu triedy Player dá získať metódou getAssociatedAgent.
Podrobnosti o životnom cykle AgentJim
objektov sú v sekcii Spúšťanie a riadenie agentov.