From e93fbf23868061fb4618f11cac8f7b7c65291a64 Mon Sep 17 00:00:00 2001 From: marcsello Date: Sun, 19 Dec 2021 19:22:44 +0100 Subject: [PATCH] Finishing touches --- drawio/birbnetes_super_simple_services | 1 - drawio/birbnetes_super_simple_services.drawio | 1 + .../{workload_move => workload_move.drawio} | 0 src/content/abstract.tex | 4 +-- src/content/birbnetes_impl.tex | 2 +- src/content/glossary.tex | 4 ++- src/content/measurements.tex | 2 +- src/content/overview.tex | 14 ++++---- src/content/ursim_impl.tex | 32 +++++++++--------- .../birbnetes_super_simple_services.pdf | Bin 18807 -> 19334 bytes src/figures/nagyon_simple_birbnetes.pdf | Bin 18437 -> 17666 bytes 11 files changed, 31 insertions(+), 29 deletions(-) delete mode 100644 drawio/birbnetes_super_simple_services create mode 100644 drawio/birbnetes_super_simple_services.drawio rename drawio/{workload_move => workload_move.drawio} (100%) diff --git a/drawio/birbnetes_super_simple_services b/drawio/birbnetes_super_simple_services deleted file mode 100644 index c54946e..0000000 --- a/drawio/birbnetes_super_simple_services +++ /dev/null @@ -1 +0,0 @@ -7VhNc5swEP01zLSHZAAZbB9t7CSdxmmm7jTJqaMaBRQL5BEi2Pz6ChAGIn/QpC7pTC+29kkrs2/fSos14ATrSwZX/oy6iGim7q41MNFM0wa6+MyATQFYfaMAPIbdAqoBc5wiCUo/L8YuihoLOaWE41UTXNAwRAvewCBjNGkue6Sk+asr6CEFmC8gUdE77HJfooauVxNXCHu+/OmBJScCWC6WQORDlyY1CEw14DBKeTEK1g4iGXclL4XfxZ7Z7YMxFPJWDnfO6Eeiz/1L5+neOosvv8TPZ3KXZ0hiGfAFIr7mWNpQTkV8U3IRJTggMBTWWLohxtF67/MY2yiFOhANEGcbsaR06EtipDLMnrSTimezpNmvUbwFocytt927Cl8MJAO/w4YaM3KFHKRJGfepR0NIphU6ZjQOXZRtqwurWnNN6UqAhgCfEOcbqW0YcyognwdEzqI15vfSPRs/ZOPzviXNybo2N9mURigCzr3OTau0H+qTlV9ulY5FhFlY+/N2QCkRjdkCHVjXl0UKmYcO7qfvVgdDBHL83Hy6P57pvqL7meYAbWRE1MXL7KAozBRH2WA8EtDsWjNtImIa/2Ri5GWjD87NzUdFNJUksvwmPuZovoI5bYk4JZvpb1dKe1Oyt77sZnlZanUZ5o7qsk9WXLrC+WecszxkvPheirsjH0Tvk1KjSakhKq9bTk2F0lvEUOAX4s3JHINU1FO2UfjIYMRZvOSFpBk88QkPhsdPeGOwgy8DnIqwnkLYlETldde66OffZ50VvXmY8ndW9EDh+xP9lt0/UbrMObbTE4vQaiNC+6+2GZZCyhUMPVbw4aW5CCe845MQHGTVbJIKutaZrVD6FcMo5fJS/ydI7P46GSg8ddb+tux+jUbre77thN/Q/Grt+lyZq6N9bm+3BFq3ubnriDG4qS1YURzyqLbzbQbUDr3By/p88W54bH3zXVIMiieopLUN5fVqG/5XW2u19Vqqrf9Gtb2twze7zKjxmozqnWW0fJc4mlL7NCkVZvXfU1HS1R94YPoL \ No newline at end of file diff --git a/drawio/birbnetes_super_simple_services.drawio b/drawio/birbnetes_super_simple_services.drawio new file mode 100644 index 0000000..1b71419 --- /dev/null +++ b/drawio/birbnetes_super_simple_services.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/drawio/workload_move b/drawio/workload_move.drawio similarity index 100% rename from drawio/workload_move rename to drawio/workload_move.drawio diff --git a/src/content/abstract.tex b/src/content/abstract.tex index 479be56..d08ef36 100644 --- a/src/content/abstract.tex +++ b/src/content/abstract.tex @@ -10,13 +10,13 @@ \chapter*{Kivonat}\addcontentsline{toc}{chapter}{Kivonat} -Napjainkban szinte alapvetőnek tekinthetők a felhőben üzemeltetett alkalmazások. Évről évre egyre nagyobb adoptációt érnek el, de mégis vannak még olyan területek, ahol még várat magára, hogy szélesebb körben is alkalmazzák. Ilyen területnek számítanak azok az alkalmazások, ahol a hálózati késleltetés egy kritikus tényező, vagy éppen a megfelelő sávszélesség nem áll rendelkezésre vagy túl költséges lenne a felhasználás helye és a felhő között. +Napjainkban szinte alapvetőnek tekinthetők a felhőben üzemeltetett alkalmazások. Évről évre egyre nagyobb adoptációt érnek el, de mégis vannak olyan területek, ahol még várat magára, hogy szélesebb körben is alkalmazzák. Ilyen területnek számítanak azok az alkalmazások, ahol a hálózati késleltetés egy kritikus tényező, vagy éppen a megfelelő sávszélesség nem áll rendelkezésre vagy túl költséges lenne a felhasználás helye és a felhő között. Ilyen és ehhez hasonló problémákra adhat megoldást a peremhálózati infrastruktúra használata. A megfelelő alkalmazások a peremhálózati infrastruktúra lehetőségeivel kiegészítve képesek lehetnek egyes komponensekkel csökkentett késleltetéssel és kedvezőbb sávszélesség feltételekkel kommunikálni. Peremhálózati rendszerek alkalmazásának rengeteg előnye ellenére még kevés olyan alkalmazás van, amely teljesen ki tudja használni azokat. Ennek oka az, hogy lévén viszonylag újkeletű technológia, még számos kérdés megoldatlan vele kapcsolatban. -A dolgozat célja, hogy konkrét alkalmazásokon keresztül mutassa be a azt, miképp lehet ezeknek a kérdéseknek egy részét megválaszolni és így sikeresen kihasználni a a peremhálózati infrastruktúra adta lehetőségeket, ezzel segítve ezen rendszerek adoptációjának további fejlődését. +A dolgozat célja, hogy konkrét alkalmazásokon keresztül mutassa be a azt, miképp lehet ezeknek a kérdéseknek egy részét megválaszolni és így sikeresen kihasználni a peremhálózati infrastruktúra adta lehetőségeket, ezzel segítve ezen rendszerek adoptációjának további fejlődését. A dolgozat első részében rövid áttekintést nyújt a felhő és a peremhálózati infrastruktúrák felépítésébe és működésébe. Bemutat néhány lehetséges keretrendszert, amelyek segítségével megoldható a peremhálózati infrastruktúra bevonása az alkalmazásunkba. Ezekből egyet kiválasztva mutatja be a peremhálózati szolgáltatás létesítését két konkrét alkalmazáson keresztül. diff --git a/src/content/birbnetes_impl.tex b/src/content/birbnetes_impl.tex index 7c7d0a7..137d3e8 100644 --- a/src/content/birbnetes_impl.tex +++ b/src/content/birbnetes_impl.tex @@ -8,7 +8,7 @@ A rendszer eredetileg a szőlővidékre telepített \acrfull{iot} eszközökből és a felhőben futó szoftverből áll. Kétszintű mesterséges intelligencia segítségével mind az eszközök, mind a felhő szoftver végez intelligens felismerést. Az eszköz maga egy egyszerűbb algoritmussal próbálja megállapítani, hogy a rögzített hangminta tartalmaz-e madárcsiripelést. Ha igen, továbbítja a mintát a felhőbe, ahol egy komolyabb számítási igényű mesterséges intelligencia osztályozza a mintát aszerint, hogy milyen madár hangját tartalmazza a minta. Ha a felismerés eredménye arra utal, hogy a cél madár hangját sikerült rögzíteni, akkor a rendszer megpróbálkozik a kérdéses madár elriasztásával hangminták lejátszásával a területen telepített eszközön. -A rendszer belső működéséről egy rövid összefoglaló található \aref{appendix:birbnetes}.\ függelékben. A fejezeten belül csak a permhálózati alkalmazásra való átalakítás szempontjából érintett részleteket vázolom. +A rendszer belső működéséről egy rövid összefoglaló található \aref{appendix:birbnetes}.\ függelékben. Ezen fejezeten belül csak a permhálózati alkalmazásra való átalakítás szempontjából érintett részleteket vázolom. Ez az alkalmazás a peremhálózati rendszerek adat aggregációs lehetőségeit hivatott kiaknázni. Azzal, hogy bevonjuk a peremhálózati rendszereket a működésbe, jelentős adatforgalmi és számítási kapacitásbeli megtakarításokat érhetünk el. diff --git a/src/content/glossary.tex b/src/content/glossary.tex index 9b85adc..ec3a7bf 100644 --- a/src/content/glossary.tex +++ b/src/content/glossary.tex @@ -156,4 +156,6 @@ \newacronym{oci}{OCI}{Open Container Initiative} \newacronym{raid}{RAID}{Redundant Array of Independent Disks} \newacronym{ssd}{SSD}{Solid State Drive} -\newacronym{icmp}{ICMP}{Internet Control Message Protocol} \ No newline at end of file +\newacronym{icmp}{ICMP}{Internet Control Message Protocol} +\newacronym{ntp}{NTP}{Network Time Protocol} +\newacronym{ptp}{PTP}{Precision Time Protocol} \ No newline at end of file diff --git a/src/content/measurements.tex b/src/content/measurements.tex index 353ef9f..433f732 100644 --- a/src/content/measurements.tex +++ b/src/content/measurements.tex @@ -58,7 +58,7 @@ Emellett feltűnő volt, hogy a rendszer nagyon lassan reagál a terhelésre és \subsection{Környezet} -Az alkalmazás teszteléséhez feltelepítettem az alkalmazást a felhő adatközpontot szimbolizáló klaszterbe. Ugyanebbe a klaszterbe telepítettem \aref{sec:scheduler}.\ alfejezetben ismertetett ütemező szoftver metrika gyűjtő komponenseit is, mivel itt nem volt szükség az ott ismertetett ütemező futtatására. +Az alkalmazás teszteléséhez feltelepítettem az alkalmazást a felhő adatközpontot szimbolizáló klaszterbe. Ugyanebbe a klaszterbe telepítettem \aref{sec:scheduler}.\ alfejezetben ismertetett ütemező szoftver metrika gyűjtő komponenseit is, mivel itt nem volt szükség az ott ismertetett ütemező futtatására. Meggyőződtem arról, hogy a pontos szinkronizáció eléréséhez, összes virtuális gépen helyesen jár a rendszer óra \acrshort{ntp} protokoll beállításával. A robotkarok szimulálására \aref{sec:ursim_simulator}.\ alfejezetben ismertetett \textit{DockURSim} szoftvert futtattam két példányban. Mivel a vezérlő szolgáltatások \acrshort{ip} cím alapján kapcsolódnak az egyes robotkarokhoz, így a klienseket emuláló virtuális gépnek felvettem két \acrshort{ip} címet, az egyik szimulátor portjait az egyik címhez a másikat a másikhoz rendeltem. Így képes voltam két robotkar szimulálására. diff --git a/src/content/overview.tex b/src/content/overview.tex index 7d6e797..7615eb0 100644 --- a/src/content/overview.tex +++ b/src/content/overview.tex @@ -72,7 +72,7 @@ Az egységek fejlesztése és tesztelése sokkal gyorsabb ütemben tud haladni a Mikroszolgáltatásokkal az alkalmazások skálázása is jelentősen leegyszerűsödik. Míg egy monolit rendszerben a teljes alkalmazást skálázni kellett, ha nagyobb teljesítményre volt szükség, itt -- feltéve, hogy tisztában vagyunk vele, hogy mely komponensek jelentik a szűk keresztmetszetet -- elég csak a megfelelő szolgáltatásokat. -A mikroszolgáltatásoknak további előnyös jellemzője, hogy az egyes komponensek teljesen egyedül kezelik a saját belső adatstruktúrájukat. Az egyetlen kompatibilitási réteg, amelyet biztosítaniuk kell, az az \acrfull{api} interfész. A mikroszolgáltatások teljesen szabadon változtathatják a belső struktúrájukat akár verziók között is. De nem csak az adatstruktúrával szemben van ekkora szabadságunk, hanem akár az alkalmazott programnyelv tekintetében is. +A mikroszolgáltatásoknak további előnyös jellemzője, hogy az egyes komponensek teljesen egyedül kezelik a saját belső adatstruktúrájukat. Az egyetlen kompatibilitási réteg, amelyet biztosítaniuk kell, az az \acrshort{api} interfész. A mikroszolgáltatások teljesen szabadon változtathatják a belső struktúrájukat akár verziók között is. De nem csak az adatstruktúrával szemben van ekkora szabadságunk, hanem akár az alkalmazott programnyelv tekintetében is. \section{Peremhálózati rendszerek} % Szóval itt felvezetem hogy van ez a perem meme \label{sec:peremhalozati_rendszerek} @@ -94,7 +94,7 @@ A fent vázolt problémákra megoldást ígér a peremhálózati rendszerek alka A peremhálózat pontos definiálása egyelőre nem teljesen tisztázott, mivel nem is egy egyszerű kérdés \cite{cureforedge, cloudflare_whatisedge}. Egyes források szerint a peremhálózati számítástechnika az magukon a \gls{vegeszkoz}ökön futtatott alkalmazások \cite{verge_whatisedge}, míg más források a felhő és a \gls{vegeszkoz}ök között elhelyezkedő számítási környezetre hivatkoznak így \cite{ibm_whatisedge}, illetve vannak források amelyek a határokat teljesen elmosva mindkettőt beleértik \cite{cb_whatisedge, dataplace_whatisedge}. -A fogalom -- és a kapcsolódó fogalmak -- tisztázására és egységesítésére a \textit{Linux Foundation} egy nyitott szójegyzéket hozott létre \enquote{\textit{Open Glossary of Edge Computing}} néven\footnote{\url{https://www.lfedge.org/openglossary/}}. Ezt a szabadon elérhető szójegyzéket egyre több gyártó ismeri el és használja \cite{openglossary}. +A fogalom -- és a kapcsolódó fogalmak -- tisztázására és egységesítésére a \textit{Linux Foundation} egy nyitott szójegyzéket hozott létre \enquote{\textit{Open Glossary of Edge Computing}}\footnote{\url{https://www.lfedge.org/openglossary/}} néven. Ezt a szabadon elérhető szójegyzéket egyre több gyártó ismeri el és használja \cite{openglossary}. A szójegyzék jelenlegi (2.0-ás verzió) kiadása alapján néhány fontosabb fogalmat az alábbiak szerint definiálhatunk: \begin{itemize} @@ -150,7 +150,7 @@ Számos olyan alkalmazás van, amelynél a peremhálózati és felhő rendszerek Jelenleg is már több alkalmazásnál is használják, vagy tervezik használni. Ilyenek például az önvezető járművek \cite{liu2019edge}, ipari rendszerek távfelügyelete \cite{hao2020cloud}, betegfelügyelet \cite{wang2020secure}, felhő alapú játék szolgáltatások \cite{edge_gaming}, okos otthonok és városok \cite{shi2016edge} és még sok minden más területen \cite{edge_companies}. -A dolgozatom részeként két konkrét alkalmazáson mutatom be a felhő és a peremhálózati rendszerek használatát. Ezek az alkalmazások korábban elkészült munkákon alapulnak, amelyeken jól demózhatóak az előnyök. Ezeknek a megvalósítását a \aref{chapter:birbnetes}.\ és \aref{chapter:ursim}.\ fejezetek részletezik. +A dolgozatom részeként két konkrét alkalmazáson mutatom be a felhő és a peremhálózati rendszerek használatát. Ezek az alkalmazások korábban elkészült munkákon alapulnak, amelyeken jól demonstrálhatóak az előnyök. Ezeknek a megvalósítását a \aref{chapter:birbnetes}.\ és \aref{chapter:ursim}.\ fejezetek részletezik. \section{Alkalmazás futtatási és fejlesztési keretrendszerek} \label{sec:frameworks} @@ -159,7 +159,7 @@ Ahhoz, hogy az alkalmazásunkat könnyen tudjuk egy felhő és peremhálózati k Egy ilyen keretrendszernél szükség van arra, hogy lehetőséget biztosítson egyes alkalmazás komponenseket a peremhálózati adatközpontban futtatni, másokat pedig a központi felhőben. Biztosítson valamilyen beavatkozható logikát arra, hogy egy alkalmazás mely adatközpontban kerül futtatásra és fedje el az egyes futtató adatközpontok sajátosságait. -A feladatom megvalósításához több ilyen keretrendszert is megvizsgáltam, ezeket az alábbiakban általánosságban részletezem. A feladat specifikus elvárásokat pedig \aref{chapter:dynamic_scheduling}.\ fejezetben fejtem ki. +A feladatom megvalósításához több ilyen keretrendszert is megvizsgáltam, ezeket az alábbiakban általánosságban részletezem. \subsection{EdgeX Foundry} @@ -178,7 +178,7 @@ A keretrendszert felépítő mikroszolgáltatások négy rétegbe sorolhatóak: \item \textit{Device Services Layer} (Eszköz szolgáltatások rétege): A rétegben elhelyezkedő szolgáltatások feladata a többi eszközzel, szenzorral való interfész megvalósítása. Egy szolgáltatás egy vagy több eszközt vagy szenzort kiszolgálhat, annak natív protokollját használva. A natív protokollon érkező, vagy arra küldendő adatokat ezeknek a szolgáltatásoknak a felelőssége átalakítani az \textit{EdgeX} többi rétegében használt közös formátumra. \end{itemize} -Mindezek mellett két további két rendszerszolgáltatást is tartalmaz, ezek a biztonságért és a rendszerfelügyeletért felelnek. +Mindezek mellett további két rendszerszolgáltatást is tartalmaz, ezek a biztonságért és a rendszerfelügyeletért felelnek. % TODO: Savazni @@ -206,11 +206,11 @@ Lévén ezek csak specifikációk és tervrajzok, az egyes kiadások nem szoftve \subsection{KubeEdge} -A \textit{KubeEdge} egy \textit{Kubernetes}re épülő rendszer, amely kiterjeszti annak képességeit peremhálózati rendszerek kezelésével \cite{kubeedge_docs}. Így lehetővé teszi a konténerizált alkalmazások futtatását a peremhálózaton. Architektúrája két részből épül fel, a központi felhőből és a peremhálózatól. +A \textit{KubeEdge} egy \textit{Kubernetesre} épülő rendszer, amely kiterjeszti annak képességeit peremhálózati rendszerek kezelésével \cite{kubeedge_docs}. Így lehetővé teszi a konténerizált alkalmazások futtatását a peremhálózaton. Architektúrája két részből épül fel, a központi felhőből és a peremhálózatól. A központi felhőben található fő komponensek a \textit{CloudHub} és az \textit{EdgeController}. Az előbbi egy kommunikációs interfész, amely a peremhálózatot megvalósító szervergépekkel kommunikál. Felelőssége megoldani, hogy az információ a lehető legnagyobb valószínűséggel eljusson azokhoz. Ennek érdekében egy átmeneti tárolót is fenntart a küldés alatt álló üzenetekhez. Az utóbbi magukért a szervergépek menedzselésért felel. -A peremhálózaton megtalálható a kommunikációs interfész párja \textit{Edged} néven. Emellett itt fut a \textit{KubeEdge} saját \textit{Pod} életciklus kezelője és meta adat tárolója. Emellett tartalmaz még egy \textit{EventBus} nevű komponenst is, amely a peremhálózaton belüli kommunikációért felel. +A peremhálózaton megtalálható a kommunikációs interfész párja \textit{Edged} néven. Illetve itt fut a \textit{KubeEdge} saját \textit{Pod} életciklus kezelője és meta adat tárolója. Emellett tartalmaz még egy \textit{EventBus} nevű komponenst is, amely a peremhálózaton belüli kommunikációért felel. Az alkalmazás komponensek ugyanúgy képesek kommunikálni egymással, mint egy \textit{Kubernetes} környezetben a perem és a központi felhő komponensek között. Ugyanazok a monitorozó, felügyeleti és ütemezős eszközök működnek mindkét oldalán a rendszernek. Ezáltal a \textit{KubeEdge} lehetővé teszi, hogy a hagyományos formában felépített mikroszolgáltatás alapú alkalmazások komponenseit kiszervezze a peremhálózatra. Viszont bizonyos helyzetekben az alkalmazásnak a felelőssége megoldani, hogy áthidalja az olyan helyzeteket, amikor nem áll rendelkezésre kapcsolat a központi felhővel. Ahhoz, hogy ezt megoldja, a \textit{Kubernetes} klaszteren belül használt hálózati plugin segítségével kiterjeszti és összekapcsolja a \textit{Pod} hálózatot. diff --git a/src/content/ursim_impl.tex b/src/content/ursim_impl.tex index 3bd772d..518b787 100644 --- a/src/content/ursim_impl.tex +++ b/src/content/ursim_impl.tex @@ -46,7 +46,7 @@ Az demonstráción használt \textit{Universal Robots} robotkarok többféle kom \item \textbf{Socket Communication}: Ez egy alacsony szintű \acrshort{tcp} alapú kommunikáció, amelyben a robot kliensként viselkedik és a szerver, amihez kapcsolódik, látja el utasításokkal. Természetesen ezen a protokollon is \textit{URScript} parancsokat adhatunk ki, ezekben segítő utasítások vannak a kapcsolat életciklusának kezelésére. - \item \textbf{\acrshort{xml}-\acrshort{rpc}}: Ez a protokol lehetőséget ad sokkal széles körűbb alkalmazásokra, mint az előbbiekben említett \textit{URScript}et használó protokollok. Hiszen a robotok egyes funkcióit a paraméterekkel együtt függvényhívás szerűen végezhetjük. Ezzel sokkal komplexebb programok készíthetőek. + \item \textbf{\acrshort{xml}-\acrshort{rpc}}: Ez a protokol lehetőséget ad sokkal széles körűbb alkalmazásokra, mint az előbbiekben említett \textit{URScriptet} használó protokollok. Hiszen a robotok egyes funkcióit a paraméterekkel együtt függvényhívás szerűen végezhetjük. Ezzel sokkal komplexebb programok készíthetőek. \item \textbf{\acrfull{rtde}}: Az \acrshort{rtde}-t egy robusztus megoldásnak tervezték, amely kiválthatja a \textit{Real-time} interfészt. Lehetővé teszi az \textit{UR} kontroller számára az egyéni státusz-adat és regiszter állapotok átvitelét. Ez az interfész valósidejű szinkronizációt tesz lehetővé akár 125Hz-es rátával (8ms/üzenet). \end{itemize} @@ -69,7 +69,7 @@ A robotokat 125Hz-es rátával kell vezérelni (azaz 8ms-ként kell utasítást A tanszéken található kettő robotkar természetesen nem áll mindig rendelkezésre. Más csapatok más-más projektekben is használják. A fejlesztés és a tesztelés megkönnyítésére több szimulátor is megvizsgálásra került a projekten korábban dolgozó csapat által. Végül a leghatékonyabban használhatónak a \textit{DockURSim}\footnote{\url{https://github.com/ahobsonsayers/DockURSim}} bizonyult. -Lényegében a \textit{DockURSim} a robotkarokat közvetlenül irányító, \textit{Control Box}on futó szoftver becsomagolva egy \textit{Docker} konténerbe. Konkrét robotkart nem irányít, de a kommunikációs interfészeket és azok funkcionalitását teljes mértékben implementálja. Lehetőségünk van a beépített \acrfull{rdp} szerveren keresztül grafikus felületet\footnote{Ez a grafikus felület a \textit{Teach Pendant}on grafikusan kezelhető felület.} kezelni és ott meg tudjuk figyelni a robotkar mozgását. +Lényegében a \textit{DockURSim} a robotkarokat közvetlenül irányító, \textit{Control Boxon} futó szoftver becsomagolva egy \textit{Docker} konténerbe. Konkrét robotkart nem irányít, de a kommunikációs interfészeket és azok funkcionalitását teljes mértékben implementálja. Lehetőségünk van a beépített \acrfull{rdp} szerveren keresztül grafikus felületet\footnote{Ez a grafikus felület a \textit{Teach Pendanton} grafikusan kezelhető felület.} kezelni és ott meg tudjuk figyelni a robotkar mozgását. Egyetlen hátránya ennek a megoldásnak, hogy a robotkarokat önállóan egy izolált környezetben tudja csak szimulálni, így a környezet fizikai hatásai, a gripperek működése és a robotkarok egymással való találkozását nem képes modellezni. @@ -102,7 +102,7 @@ gripper vezérlését \acrshort{rest} \acrshort{api}-n keresztül végzi. A két robotkar vezérlése két külön szálon van megvalósítva. Mindkettő szálon egymás után következnek az utasítások, a kritikus szinkronizációs részek egyszerű szál-szinkronizációs primitívekkel vannak megoldva. -A programban több futtatási mód is implementálva van. Egyrészt gyors és lassú végrehajtási sebesség között lehet választani. Ez a robotkarok mozgási sebességét befolyásolja. Emellett úgynevezett \enquote{Jogging} módban is lehet az alkalmazást futtatni. Ebben a módban a program minden mozdulat végrehajtása előtt várakozik egy gomb lenyomására a további parancsok kiadása előtt. Így lehetőség adódik az esetleges hibás mozgások hibakeresésére, illetve a program teljesen automatikus lefuttatása előtt manuális tesztelésre. +A programban több futtatási mód is implementálva van. Egyrészt gyors és lassú végrehajtási sebesség között lehet választani. Ez a robotkarok mozgási sebességét befolyásolja. Emellett úgynevezett \enquote{Jogging} módban is lehet az alkalmazást futtatni. Ebben a módban a program minden mozdulat végrehajtása előtt várakozik egy gomb lenyomására a további parancsok kiadása előtt. Így lehetőség adódik az esetleges hibás mozgások felderítésére, illetve a program teljesen automatikus lefuttatása előtt manuális tesztelésre. A program a konfigurációs beállításait egy \gls{ini} fájlban tárolja. Ezek a konfigurációs beállítások elsősorban a robotkarok és a hozzá tartozó gripperek hálózati címeit adja meg, illetve a konkrét sebesség módokhoz tartozó konfigurációs értékeket. @@ -140,7 +140,7 @@ A \enquote{középszintű} vezérlés feladata egy olyan absztrakciót adni az e A lépés sorozatoknál elvárás, hogy biztonságos állapotból indulnak és biztonságos állapotba érkeznek. Így a kettő lépés sorozat végrehajtása között eltelt idő nem befolyásolja károsan a rendszert. A lépés sorozatok engednek bizonyos fokú külső befolyást is, viszont ezeket szigorúan úgy kell implementálni, hogy itt se számítson a késleltetése a beavatkozásoknak. -A lépés sorozatokat \textit{Program}nak neveztem el. Egy ilyen \textit{program} lépéseinek végrehajtása a futtatás. A magasabb rétegek ilyen előre összeállított programokat képesek a peremhálózati rendszer felé küldeni, illetve annak futási állapotáról információkat kapni. +A lépés sorozatokat \textit{Programnak} neveztem el. Egy ilyen \textit{program} lépéseinek végrehajtása a futtatás. A magasabb rétegek ilyen előre összeállított programokat képesek a peremhálózati rendszer felé küldeni, illetve annak futási állapotáról információkat kapni. \subsubsection{Felhő réteg} @@ -155,7 +155,7 @@ Az adatok gyűjtése nem késleltetés érzékeny, ezért nem okoz problémát, \subsection{Peremhálózati szolgáltatások} % Peremhálózati rendszer basically \label{sec:single_robot_contoller_plans} -\Aref{sec:edge_layer_plans}.\ alfejezetben ismertetettek alapján terveztem meg a peremhálózati rendszerben futó mikroszolgáltatás halmazt. Jelenleg ez egyetlen egy mikroszolgáltatásból áll, ez a szolgáltatás a \textit{program}ok futtatását valósítja meg. +\Aref{sec:edge_layer_plans}.\ alfejezetben ismertetettek alapján terveztem meg a peremhálózati rendszerben futó mikroszolgáltatás halmazt. Jelenleg ez egyetlen egy mikroszolgáltatásból áll, ez a szolgáltatás a \textit{programok} futtatását valósítja meg. Egy program egyszerre csak egy robotkar működését írja le, így egy ilyen komponens egyszerre csak egy robotkarhoz kapcsolódik. A demonstráció végrehajtásához két komponensnek kell kapcsolódnia. @@ -164,7 +164,7 @@ Emellett meg kell oldania olyan problémákat is, amelyek \aref{sec:ursim_demo_c \subsubsection{Végrehajtási keretrendszer} \label{sec:ursim_execution_framework} -Annak érdekében, hogy a komponens absztrakt módon megoldást adjon a késleltetések áthidalására a felhő és a peremhálózati rendszerek között a robot mozgatásához szükséges lépéseket egy \textit{program}ba szedve kapja meg. Egy ilyen \textit{program} utasításokból épül fel, amelyet interpretáltan, imperatív módon hajt végre a komponens. +Annak érdekében, hogy a komponens absztrakt módon megoldást adjon a késleltetések áthidalására a felhő és a peremhálózati rendszerek között a robot mozgatásához szükséges lépéseket egy \textit{programba} szedve kapja meg. Egy ilyen \textit{program} utasításokból épül fel, amelyet interpretáltan, imperatív módon hajt végre a komponens. Szerettem volna egy olyan végrehajtási környezetet megalkotni, ahol könnyen lehet az egyes utasítások mögött cserélni a funkcionalitást. Ezzel lehetőség nyílik arra, hogy a programokat szinte módosítás nélkül újrahasznosítsuk. @@ -185,7 +185,7 @@ Alapos kutatás után sajnos nem találtam erre a problémára teljes, kész meg Mivel fontos, hogy a szinkronizáció pontos legyen minden komponensnél, ezért annak az ötletét, hogy hálózaton küldött üzenetek szolgáljanak a szinkronizáció alapjául, teljesen elvetettem. -Ezzel szemben lehetőség van a futtató környezetet adó fizikai számítógépek óráinak meglepően precíz szinkronizációjára. \Aref{append:timesync}.\ függelékben ezt részletesebben is tárgyalom. Ezt alapul véve kidolgoztam egy kellően precíz szinkronizációs protokollt. +Ezzel szemben lehetőség van a futtató környezetet adó fizikai számítógépek óráinak meglepően precíz szinkronizációjára Hálózati idő protokoll (\acrlong{ntp}; \acrshort{ntp}) vagy Precíz idő protokoll (\acrlong{ptp}; \acrshort{ptp}) használatával. Ezt alapul véve kidolgoztam egy megfelelően precíz szinkronizációs protokollt. Szinkronizáció gyanánt a résztvevők (Az egyes \textit{Single Robot Controller} példányok) \enquote{megegyeznek} abban, hogy mikor lesz az az időpont, amikor tovább haladnak a végrehajtással. Ehhez szükség van arra, hogy megbizonyosodjanak róla, hogy minden szolgáltatás elért a végrehajtással arra a pontra, ahonnan csak együtt léphetnek tovább. @@ -215,7 +215,7 @@ Azért ezt a megoldást választottam, mert a \acrshort{http} protokoll kellően Az \acrshort{api} két fontos és fix funkciót kell kiszolgáljon. Szükség esetén a program futását meg kell tudni szakítani (akár egy lépés végrehajtása közben is), emellett a program futásának állapotát is lekérhetővé teszi. -A \textit{plugin}ek további funkcionalitást regisztrálhatnak, amiket az \acrshort{api} használatával lehet elérni. Ennek segítségével meg lehet valósítani a \enquote{jogging} futtatást egy olyan \textit{plugin}nel, ami minden fő lépés után meghívásra kerül és várakozik az endpoint meghívására. +A \textit{pluginek} további funkcionalitást regisztrálhatnak, amiket az \acrshort{api} használatával lehet elérni. Ennek segítségével meg lehet valósítani a \enquote{jogging} futtatást egy olyan \textit{pluginnel}, ami minden fő lépés után meghívásra kerül és várakozik az endpoint meghívására. \subsection{Felhő szolgáltatások} \label{sec:cloud_layer_plans} @@ -227,7 +227,7 @@ A \textit{plugin}ek további funkcionalitást regisztrálhatnak, amiket az \acrs Az architektúra, melyet \aref{sec:edge_layer_plans}.\ alfejezetben bemutattam lehetővé teszi, hogy a felhőben futó komponensek bármilyen programot adjanak a peremhálózati réteg számára, legyen az automatikusan vagy részben automatikusan generált. -Mivel sem a demonstráció, sem a dolgozatom szempontjából nem lényeges, hogy milyen módon keletkeznek a \textit{program}ok magas szinten, ezért itt csak egy egyszerű, előre elkészített programokat tároló szolgáltatást terveztem. +Mivel sem a demonstráció, sem a dolgozatom szempontjából nem lényeges, hogy milyen módon keletkeznek a \textit{programok} magas szinten, ezért itt csak egy egyszerű, előre elkészített programokat tároló szolgáltatást terveztem. A szolgáltatásba fel lehet tölteni a felhasználó által megírt programot, illetve le lehet tölteni onnan egy egyszerű \acrshort{rest} \acrshort{api} használatával. @@ -289,15 +289,15 @@ A \textit{Program Service} esetén az eltárolt programokat egy dokumentum tárb % Esetleg pluginok felsorolással -\subsection{\textit{Single Robot Control} \textit{plugin}ek} +\subsection{\textit{Single Robot Control} \textit{pluginek}} -A \textit{Single Robot Control} komponens által, a \textit{programban} definiált utasítások implementációjára \textit{plugin}ek a programban osztályok csoportjaként kerültek megvalósításra. +A \textit{Single Robot Control} komponens által, a \textit{programban} definiált utasítások implementációjára \textit{pluginek} a programban osztályok csoportjaként kerültek megvalósításra. Minden \textit{plugin} egy különálló osztályban van megvalósítva. Ennek példányosításával lefut az adott \textit{plugin} inicializációja (például: csatlakozás a robotkarokhoz), majd regisztrálja a rendelkezésre álló utasítás osztályokat. A \textit{plugin} osztályok implementálnak egy \texttt{close} függvényt is, amely a foglalt erőforrások felszabadításáért felel. A beregisztrált utasítás osztályok lényegében egy \textit{factory} mintát valósítanak meg. Amikor a szolgáltatás betölt egy \textit{programot} akkor először minden lépését értelmezi azzal, hogy ezekkel a \textit{factory} osztályokkal példányosítja a konkrét utasítás objektumot. Ezen a ponton lehetőség van a bevitt adatok helyességének ellenőrzésére, hogy ez ne a futtatáskor történjen meg, ezzel futtatás közben spórolva a \acrshort{cpu} ciklusokkal és \textit{fail-early} megközelítés szerint még az előtt kiderülnek a problémák, hogy a program futtatásra kerülne. -Az értelmezett utasításokat listába szervezve készíti elő a futtatható \textit{program}ot a szolgáltatás. Ezek a példányosított utasítások implementálják \aref{sec:ursim_execution_framework}.\ alfejezetben említett három fő funkciót: \texttt{execute}, \texttt{abort} és \texttt{describe}. Az egyes paraméterek összerendelése ebben a lépésben történik meg az utasításokhoz. +Az értelmezett utasításokat listába szervezve készíti elő a futtatható \textit{programot} a szolgáltatás. Ezek a példányosított utasítások implementálják \aref{sec:ursim_execution_framework}.\ alfejezetben említett három fő funkciót: \texttt{execute}, \texttt{abort} és \texttt{describe}. Az egyes paraméterek összerendelése ebben a lépésben történik meg az utasításokhoz. Amikor egy program futtatásra kerül, akkor a komponens egyesével lépkedve a listán minden elemnek meghívja az \texttt{execute} függvényét. Ha meg kell szakítani a futást, akkor az éppen futó lépes \texttt{abort} függvényét meghívva, leállítja azt, és a következő parancsot már nem hajtja végre. @@ -331,10 +331,10 @@ Ennek a pluginnek a használatával megvalósítható, a demonstráció során i \subsubsection{Egyebek} -A fent vázolt \textit{plugin}ek mellett készítettem néhány egyszerűbbet is, amelyek egyszerűbb vagy csak hibakeresésnél használatos funkciókat implementálnak: +A fent vázolt \textit{pluginek} mellett készítettem néhány egyszerűbbet is, amelyek egyszerűbb vagy csak hibakeresésnél használatos funkciókat implementálnak: \begin{itemize} - \item \textbf{Log Plugin} Ezzel a \textit{plugin}nel a program futása közben előre definiált üzeneteket jeleníthetünk meg az alkalmazás naplójában. + \item \textbf{Log Plugin} Ezzel a \textit{pluginnel} a program futása közben előre definiált üzeneteket jeleníthetünk meg az alkalmazás naplójában. \item \textbf{Sleep} Ez a \textit{plugin} lehetővé teszi hogy meghatározott ideig szüneteltessük a végrehajtást. \end{itemize} @@ -345,7 +345,7 @@ A robotkarok vezérlésének lépései az általam tervezett formátumú \textit A \textit{program} leírása tartalmazza első sorban annak verzióját. Ez a későbbi kompatibilitási problémák megoldásának egyszerűsítésére lett bevezetve, jelenleg csak az \texttt{1}-es verzió létezik. Az a program, ahol ennek a mezőnek az értéke nem \texttt{1}, az érvénytelen. -A verzió mellett a leírás tartalmazza a program nevét, ennek nem kell egyedinek lennie, csak diagnosztikai céllal létezik, emellett a program létrehozásának időpontját és a betöltendő \textit{plugin}ek listáját is. +A verzió mellett a leírás tartalmazza a program nevét, ennek nem kell egyedinek lennie, csak diagnosztikai céllal létezik, emellett a program létrehozásának időpontját és a betöltendő \textit{pluginek} listáját is. A \textit{program} leírása opcionálisan tartalmazhat egy \texttt{id} vagy \texttt{\_id} mezőt, ezzel megkönnyítve a program kezelését. A beolvasásnál ennek a mezőnek a jelenléte nem okoz hibát. @@ -379,7 +379,7 @@ program: acceleration: 0.75 \end{lstlisting} -A program sémájának validálására a \textit{Marshmallow}\footnote{\url{https://github.com/marshmallow-code/marshmallow}} könyvtárat használtam. Ezzel deklaratív módon tudtam validációs sémákat írni, amelyet minden komponensnél használtam, amely érintkezik valamilyen szinten \textit{program}okkal. Így a lehető leghamarabb vissza tudja utasítani a rendszer a hibás programokat. +A program sémájának validálására a \textit{Marshmallow}\footnote{\url{https://github.com/marshmallow-code/marshmallow}} könyvtárat használtam. Ezzel deklaratív módon tudtam validációs sémákat írni, amelyet minden komponensnél használtam, amely érintkezik valamilyen szinten \textit{programokkal}. Így a lehető leghamarabb vissza tudja utasítani a rendszer a hibás programokat. Az eredeti szoftver által vezérelt mozgást futás időben fordítottam le az általam definiált \textit{program} struktúrára azáltal, hogy a program kódjában a \gls{python} által biztosított reflexiókat használva, az egyes lépéseket lecseréltem fájlba mentő funkciókra amely rögzíti az utasításokat és a paramétereiket. diff --git a/src/figures/birbnetes_super_simple_services.pdf b/src/figures/birbnetes_super_simple_services.pdf index d29bf953714e80fd33a62b71c9c47af73beb428b..82189df185705a4529f25966a086015112334cb4 100644 GIT binary patch delta 11157 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 delta 10644 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%0A~1 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 m{Z}5CicRulwLO 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