Počas testovania sme nadobudli pocit, že Jim veľmi často padá. Môže to byť spôsobené zlými výpočtami Zero moment point a slabej stability hráča. Z toho dôvodu je potrebné analyzovať ako sa robot s touto problematikou vysporiada.
Zero moment point (ZMP) berie v úvahu efekty dynamických a statických síl v úvahu. Špecifikuje bod, v ktorom dynamická reakcia síl v kontakte s chodidlom a zemou neprodukujú žiadny moment v horizontálnom smere. Vo väčšine prípadov je za ZMP považovaný bod, kde celkový horizontálny vplyv a gravitačné sily sú rovné nule.
Stabilita počas kráčania vyžaduje ZMP vnútri podporného polygónu. Podporný polygón je vykreslený ako konvexný trup v okolí chodila a zeme.
Udržanie ZMP v podpornom polygón zabezpečuje stabilitu počas kráčania. V prípade, že sa ZMP dostane mimo podporného polygónu, veľmi rýchlo môže nastať jeho pád.
ZMP by sa mal v kóde vyskytovať hlavne v agentovi – highskill – move. Pri WalkFast sú vytvorené 3 súbory s názvom WaklFast, WaklFastZMP a WaklFastZMPOld. Podľa dokumentácie priamo v kóde ťažko určiť, ktorá z týchto tried je využívaná. V kóde je taktiež veľa zapoznámkovaných časti kódu, ku ktorým opäť často chýba popis a ťažko tak určiť dôvod zapoznámkovania. Nakoľko trieda WalkFast neobsahuje žiadne prvky stabilizácie je možné predpokladať, že ZMP nebol v Jimovi riešený vôbec. Naopak trieda WalkFastZMP obsahuje len stabilizačné metódy. Táto trieda je importovaná iba triedou DefaultTactic. WalkFastZMPOld je importovaná pri FastWalkTactic a StabilityWalkTactic. Táto trieda je aj zapoznámkovaná narozdiel od WalkFastZMP. V triede FastWalkTactic je možné pomocou boolean hodnoty určiť, či bude ZMP spustený – defaultná hodnota je TRUE. V tomto prípade je na prepočet používaná trieda WalkFastZMPOld.
AgentModel obsahuje hlavnú prácu so ZMP, kde sa updatujú podstatné metódy ako updateZeroMomentPoint(), updateCenterOfMass(), updateFeetForce(), atď.
Triedy v zložke move sú slabo zdokumentované a ťažko sa v nich orientuje. Nakoľko náš robot často padá na zem, bolo by vhodné hlbšie zanalyzovať tieto triedy a vyhľadať menej efektívne algoritmy.
Táto trieda je najpodstatnejšia pre ZMP, nakoľko v nej prebiehajú všetky výpočty spojené so ZMP. Obsahuje 3 podstatné metódy: updateZeroMomentPoint(), updateCenterOfMass() a setZMPallowed(boolean zmpAllowed).
Táto metóda počíta samotný ZMP. Síce sa na začiatku vytvoria premenné x, y, z s prednastavenou hodnotou 0, no z súradnica sa počas výpočtov vôbec nemení. Už v 2. riadku tejto metódy vidíme TODO na opravu stredu accelerometra. Vzorec použitý na výpočet xzmp a yzmp je:
Potom sa pomocou karteziánskeho súčinu vzniknutých x,y a z vypočíta hodnota ZMP a tá sa zapíše do LinkedListu obsahujúceho históriu vypočítaných ZMP. Následne sa ako ZMP vypočíta priemer posledných 5 vypočítaných ZMP hodnôt.
Na výpočet je použitý vzorec:
Kde n je počet súčiastok robota, p je poloha súčiastky, m je hmotnosť súčiastky. V cykle sa pre každú súčiastku pridáva do 3D vektora centerOfMass súčin pozície súčiastky a jej váha. Do celkovej hmotnosti totalMass sa postupne pripočítava hmotnosť aktuálnej súčiastky. Nakoniec sa vektor centerOfMass vydelí totalMass a vznikne z toho výsledný COM.
Táto trieda má za účel zapnutie a vypnutie ZMP. Taktiež prispôsobí minimálne hodnoty Thety na prednastavené hodnoty. Zaujímavé je, že hodnoty Theta sa využívajú len pri zisťovaní pádu a sú rozličné pri zapnutom a vypnutom ZMP. Taktiež nie je žiadne volanie, ktoré by zisťovalo či je ZMP zapnuté alebo nie. Túto metódu volajú s parametrom true dve triedy v balíčku sk.fiit.jim.agent.highskill.move WalkFastZMP a WalkFastZMPOld. Triedu WalkFastZMP využíva taktika DefaultTactic a triedu WalkFastZMPOld využívajú taktiky FastWalkTactic a StabilityWalkTactic.
Metóda updateZeroMomentPoint() vôbec nemení premennú z počas výpočtu a necháva ju rovnú 0 – preto je dôležité overiť a prípadne opraviť tento výpočet. Taktiež obsahuje TODO časť v komentári, ktorú poznačuje na možný nesprávny výpočet ZMP. Vo výpočte je používaný LinkedList a je prehľadávaný cyklom for – tento cyklus je neefektívny pre prehľadávanie LinkedListu a odporúčam optimalizovanie pomocou foreachu. Do histórie sa počas behu tejto metódy pridáva jeden prvok, preto by bolo vhodné namiesto while cyklu použiť jednoduchú if podmienku pri zisťovaní prekročenia maximálnej veľkosti a následnom vyprázdňovaní prvkov z LinkedListu. Maximálna veľkosť LinkedListu je nastavená na 1000 prvkov, no pracujeme len s 5-timi, preto je zbytočné udržiavať ostatných 955 prvkov v zozname.