czech english

Paketová komunikace

po sériové lince

Tento článek se zabývá posíláním příkazů a zpráv mezi počítačem a jednočipem řídícím robota. Důraz bude kladen na obsah a především strukturu posílaných zpráv, nikoli na konkrétní implementaci na vybraném operačním systému a jednočipu. V tomto článku mluvím sice výhradně o sériové lince (myšleno RS232), podobné poznatky a principy však platí i o dalších podobných komunikačních sběrnicích.

Úvod

Až na nejjednodušší roboty řízené pouze jednočipem, nebo dokonce vůbec, byli snad všichni roboti, které naše robotická skupina na Matematicko-fyzikální fakultě Univerzity Karlovy používala (např. Dana, Daisy, Ester, roboti týmu MART, Mob2 …), sestaveni podle schématu na Obr. 1 nebo jeho blízké obdoby. Zdaleka se nejedná o světovou raritu. Stejným způsobem jsou uspořádáni také roboti Pioneer či tak mohou být řízené vysavače Roomba. Vyšší řízení robota, jako jsou např. lokalizace a plánování činnosti, běží na „výkonnějším” počítači, kterým může být třeba PDA, miniITX deska, nebo celý notebook. Nižší řízení, jako např. PID řízení motorů a čtení senzorů, jsou přenechány jednočipu, který je pro takovéto úlohy mnohem lépe uzpůsoben. Výměna informací a pokynů mezi počítačem a jednočipem pak probíhá po sériové lince. Sériová linka je implementačně jednoduchá a byla až donedávna přítomna skoro všude. V poslední době sice došlo k jejímu úplnému ústupu z počítačů a postupně mizí také z robotických desek, je ale nahrazována převodníky z USB na sériovou linku. Z pohledu operačního systému i jednočipu se tak nic nemění a obsah tohoto článku zůstává aktuálním. Jak zmiňuji dále, stává se možná dokonce ještě aktuálnějším, než dříve.
Během desetiletí práce s roboty se sériovou linkou jsme nasbírali různé zkušenosti, které nás vedou k následujícím východiskům při práci s ní:
  • Sériová linka je nespolehlivá. Posílané zprávy mohou dorazit neúplné, poničené a někdy možná dokonce vůbec. Místo nich může přijít komunikační šum (např. signál naindukovaný motory).
  • Sériová linka je pomalá.
Mnozí lidé se dušují, že ani jeden z vypsaných bodů není pravda. Naše pracně získaná zkušenost je ale takováto. A i v případě, kdy pracujete se skvělým robotem bez těchto neduhů, doporučuji pesimisticky problémy očekávat ("Better safe than sorry."). Beztak přijdou
Z čeho zmíněné potíže vychází? Nespolehlivost je sériové lince vlastní. Signálový kabel vedený kdekoli poblíž elektromotoru si o potíže přímo říká. Navíc, rozhodne-li se váš systém (ať už na počítači nebo na jednočipu), že zrovna nestíhá a musí řešit něco jiného, nemusí se příchozí zpráva vejít do bufferu a nestihnete ji přečíst, aniž byste o její část přišli.
Pomalost není ani tak vlastnost samotné sériové linky, jako jejích konkrétních provedení. Hvězdou tohoto nebe jsou právě různé USB<->RS232 převodníky. Podobně u převodníků přes bluetooth jsme pozorovali, že jim dělá velké potíže rychlé a časté přepínání směru komunikace. A to je přesně situace, která nastane na robotovi, kde posíláte řídící příkazy a očekáváte informace ze senzorů.
Různými řešeními popsaných problémů se zabývá tento článek.

Posílání struktur na robotech typu Daisy

Roboty typu Daisy rozumím především Daisy samotnou. Do této rodinky ale řadím také několik dalších robotů, především týmu Short Circuits, kteří dědí z tradice a zdrojových kódů Daisy a jejích předchůdců. Stejný kód, jak jsem zahlédl na posoutěžním workshopu, používají i další týmy v Robotour a možná i jinde. Jedná se o dlouho používaný a prověřený způsob komunikace.
O co jde? Princip je jednoduchý a je podrobně popsán v článku o atmega8-boardu, proto nepůjdu příliš do hloubky. Důležitá pro tento článek je především struktura posílaného datového balíčku (Obr. 2). Každý paket začíná start bytem 0xAB. Následuje byte s délkou zprávy, zpráva samotná a její checksum.
Kriticky důležitým prvkem je právě checksum na konci paketu. Ta umožňuje detekci poničených nebo šumových zpráv. Jedná se o implementačně jednoduchý doplněk k součtu bytů zprávy. Oprava poničeného paketu pomocí korekčních kódů není cílem a tedy ani možná. Nezbývá, než poničený paket zahodit a čekat na další.
Komunikace mezi počítačem a jednočipem probíhá plně synchronně: Počítač odešle jednu řídící zprávu (např. požadovanou rychlost) a očekává jednu odpověď (např. aktuální rychlost). Poté může dojít k další výměně zpráv (třeba jiného typu). Potíž nastane v okamžiku, kdy jednočip dostane řídící zprávu poničenou, nebo dokonce vůbec. V takové chvíli nemá jednočip na co odpovědět a počítač čeká na odpověď marně. Případně může dojít k neúplnému doručení odpovědi se stejným důsledkem. Proto musí být do komunikace zabudováno i zpracování timeoutu – pokud nepřijde odpověď v rozumném časovém intervalu, je komunikace považována za narušenou a musí dojít k její opětovné synchronizaci.
Pro synchronizaci aktérů se používá synchronizační byte 'D' (jako Daisy). Pokud čeká jednočip na začátek další zprávy a obdrží 'D', odpoví také 'D'. Pro opětovnou synchronizaci stačí posílat z PC 'D' tak dlouho, dokud jednočip neodpoví stejně. Několik prvních 'D' může být jednočipem považováno za konec předchozí (neplatné) zprávy a na první 'D' při čekání na začátek zprávy je odpovězeno. Tak se PC dozví, že jednočip už neočekává konec předchozí zprávy. Při této výměně dat musí PC pomocí timeoutů ošetřit situaci, kdy odesílá 'D', ale jednočip stále ještě neodpovídá (považuje zaslaná 'D' za konec předchozí zprávy).
Kvůli nešťastné kombinaci šumu a timeoutů může dojít k situaci, kdy robot citelně dlouho nedostává řídící pokyny. Tuto situaci je velmi snadné detekovat a bezpečně ošetřit (např. dočasným zastavením robota).
„Daisy protokol” byl původně navržený na posílání jediné řídící struktury obsahujících pokyny pro všechny aktuátory a příjem jediné informační struktury obsahující informace ze všech senzorů. To není u jednodušších robotů problém. Jak ale roste počet aktuátorů a senzorů robota, roste také délka obou zpráv. A s délkou zprávy klesá exponenciálně pravděpodobnost, že nebude při přenosu poničena. Postupně je navíc dosaženo velikosti bufferů na obou stranách linky, což může způsobit (a způsobí [Murphy]) potíže při jejich nedostatečně rychlém vyčítání. Proto současná verze protokolu počítá s tím, že prvním datovým bytem po délce zprávy je identifikátor jejího typu. Různé aktuátory a senzory tak mohou být zpracovávány nezávisle a délka zprávy opět klesne.

Roboti rodiny RobSys

Roboti z dílny RobSys se tradičně účastní soutěží Robotour (robot Explorer), Eurobot (robot Eduro) a jiných. Tato skupina robotů vznikla zcela nezávisle na vývojové větvi robota Daisy a tak řeší podobné problémy jiným způsobem. Pro pochopení důvodů, proč a jak vznikl komunikační protokol na těchto robotech je nutné vědět, jaká je jejich struktura (Obr. 3).
Každý senzor a aktuátor funguje jako zcela samostatný modul. Tyto moduly jsou navzájem spojeny sběrnicí CAN. Sběrnice CAN se často používá např. v automobilovém a leteckém průmyslu. Specifikace CAN pamatuje na robustnost přenosu dat a ukládá způsob, jakým je zaručeno bezchybné doručení všech zpráv. Robotik může použít snadno dostupné čipy, které implementují podstatnou část CAN protokolu. O takto obdržené zprávě je možné předpokládat, že je v pořádku a že žádná předchozí zpráva nebyla vynechána.
S počítačem je CAN spojen převodníkem (interně nazývaný „bridge”), který je připojen na jedné straně na CAN, na druhé straně na sériový port počítače. Z důvodu snadné implementace a úplné transparentnosti nezasahuje bridge do obsahu zpráv a nemusí jim rozumět. Zprávy z jedné strany jsou jednoduše přeposlány na stranu druhou a je na koncových zařízeních, aby se s obsahem zpráv vypořádala. Tím je dán formát zpráv: Je dán specifikací CAN. Složitost CAN zpráv, kdy jeden byte může obsahovat několik typů informace (i zároveň), mi neumožňuje nakreslit jednoduchý diagram.
Podle konstruktérů z dílny RobSys není u dobře vyrobené sériové linky problém s její (ne)spolehlivostí. Protože ale pracují jednotlivá zařízení na CAN sběrnici zcela nezávisle a asynchronně, může na straně přijímacího software nastat problém s bufferem sériové linky příliš malým na množství zasílaných zpráv a softwarem příliš pomalu vyčítajícím z tohoto bufferu příchozí data. (Je až pozoruhodné, jak se hardwaráři a softwaráři shodují, že problém je to druhé.) Jak o sběrnici CAN, tak o použité sériové lince se předpokládá, že jsou spolehlivé, a proto neobsahují v současné implementaci posílané zprávy žádnou checksum. Není proto možné snadno detekovat narušenou komunikaci a taková situace proto nesmí ani nastat. Problémům je předcházeno tím, že na robotech běží real-time varianta Linuxového jádra (Xenomai), jejíž ovladače sériové linky mají zaručit, že nebudou žádná data ztracena kvůli příliš malému bufferu a vše bude včas přečteno. Aktuální verze použitého Xenomai již na soutěži Field Robot Event netrpěla neduhy, které sužovaly robota Eduro na Robot Challenge a na Eurobotu.
Pro začátek komunikace počítače s bridgem, který již v době spuštění počítače může dávno běžet a posílat zprávy, je implementována synchronizace v principu velmi podobná Daisy synchronizaci. Počítač nejprve odešle desetkrát byte 0xFF. Protože maximální délka CAN zprávy je osm bytů a 0xFF je neplatný začátek zprávy, může bridge snadno detekovat, že se nejedná o platnou datovou zprávu a může odpovědět sérií deseti (anebo více) bytů 0xFF. Tuto synchronizaci může vyvolat řídící program i během činnosti robota, když dokáže (nějak) poznat, že přijímaná data jsou nesmyslná (např. díky neplatným identifikátorům zpráv).

Protokol Mobů

S nákupem robotických platforem Mob2 na naši fakultu (MFF UK) nastala potřeba implementace řízení nových robotů a příležitost zvážit dostupné komunikační postupy a případně omezit některé z potíží, které nastaly během let od robota Daisy na jiných robotech. Ačkoli jsme v té době měli zatím jen omezené zkušenosti s roboty s CANem z dílny RobSys, poznatky z jiného robota s touto sběrnicí dávaly tušit, že pouze synchronní komunikace zahrnutá v Daisy protokolu není dostatečná. Pro novou generaci robotů jsme chtěli použít novou generaci protokolu. Takovou, kterou budeme moct snadno přenést i na budoucí roboty. Nejprve jsme zvažovali rozsáhlejší používání timeoutů, které by umožnily lepší detekci narušené komunikace a její resetování. Protože ale naše roboty řídíme z různých operačních systémů, ukázal se tento přístup implementačně příliš náročný, ne-li dokonce nemožný. Pokus o přiučení se z jiných robotických systémů (např. iRobot Roomba Serial Command Interface) nepřinesl kýžené ovoce. Už Daisy protokol je navržen podstatně robustněji vzhledem k rušivým vlivům. Pro inspiraci jsme museli sáhnout do ještě vzdálenější historie komunikace po dnes již vlastně prehistorických sériových linkách.
V předethernetových dobách byly počítače běžně spojovány null-modemem, což není nic jiného, než vhodně překřížený kabel spojující RS232 porty počítače. Jedná se tedy o téměř stejnou situaci, ve které jsme s našimi roboty, a již v té době musel být přenos dat řešen. Pro naše potřeby se jeví velmi vhodným přenos paketů v Serial Line Internet Protokol (RFC1055, SLIP). SLIP řeší oddělení paketů (a tím i synchronizaci) vyhrazením speciálního bytu 0xC0. Tento byte je odeslán na konci každého přeneseného paketu a označuje jeho konec. Aby nedošlo ke špatné interpretaci stejného bytu v datové části, jsou datové byty s hodnotou 0xC0 nahrazeny speciální dvoubytovou sekvencí, ve které se 0xC0 nevyskytuje a která je u příjemce zpětně nahrazena původním 0xC0. Příjemce si tak může být jist, že 0xC0 ukončuje paket a následuje paket další. V případě ztracené značky konce paketů dojde k synchronizaci účastníků na příštím obdrženém 0xC0.
Drobným, ale podstatným, vylepšením je odeslání 0xC0 i na začátku paketu pro oddělení právě posílaného paketu od šumových dat, která se před ním mohla objevit na lince. V lepším případě se šumová data neobjevila a příjemce může vzniklý prázdný paket rovnou zahodit. V horším případě musí vyšší vrstva zpracování dat detekovat nekonzistenci paketu. Tuto kontrolu nekonzistence paketová vrstva neřeší a přenechává tuto úlohu vyšší, IP, vrstvě. V našem případě však nedochází k přenosu IP datagramů a proto si kontrolu konzistence musíme zařídit sami. V tomto konkrétním případě je na konci každé zprávy odeslán kontrolní součet, který je roven celkovému XOR předchozích byte zprávy. XOR celé zprávy včetně checksum tak nabývá hodnoty 0.
Další změnou oproti Daisy protokolu je asynchronnost nového protokolu. Řídící software musí očekávat, že může v libovolnou chvíli přijít zpráva od libovolného zařízení. Zároveň se nesmí spolehnout na to, že na poslaný řídící pokyn přijde odpověď. Každá strana komunikace musí sama detekovat situaci, kdy určitá zpráva nedorazila příliš dlouho, pokud to potřebuje (např. že nechodí řídící signál motorům – mohl vypadnout kabel nebo havarovat software). Program napsaný s ohledem na uvedené body nemusí tuhnout v timeoutech a čekat na odpověď, která možná nedorazí.
Popsaný protokol neřeší možnost zahlcení sériové linky. To musí být konkrétně řešeno podle robota a použitého počítače a operačního systému. Jednou z možností je real-time operační systém. U školních robotů však nemůžeme klást předpoklady a požadavky na operační systém, když roboty může řídit každý student z vlastního notebooku. Proto jsou mobi naprogramováni podle vzoru Daisy a pravidla „mluviti stříbro, mlčeti zlato.” Robot sám o sobě žádné informace neposílá. Až když dostane pokyn od počítače, odpovídá (ne ale nutně vždy, ne nutně jedinou zprávou). Pokud tedy řídící software posílá řídící pokyny s rozumnou kadencí, i odpovědi chodí ve zpracovatelném rytmu. Toto je už ale vlastnost konkrétního provedení v tomto okamžiku a ne komunikačního protokolu. Tímto sice ztratíme velmi přesný přehled o aktuální situaci robota, na druhou stranu se ale velmi zjednoduší implementace a odpadnou potíže s patchováním, vlastní kompilací a instalací nestandardního jádra. Přibývá možnost spustit řízení na libovolném počítači a systému. Data se senzorů běžně beztak obsahují chyby měření a řídící software se s nimi musí vypořádat. A když už se s chybou vypořádává, neměl by být takový problém, když je informace setinku sekundy stará. To je pro naše účely dostatečné.

Závěr

V tomto článku jsem popsal naše zkušenosti s přenosem robotických dat po sériové lince. Věřím, že uvedené poznatky a popsané postupy pomohou dalším robotikům v návrhu protokolu pro jejich roboty a ušetří jim spoustu práce, která by mohla vzniknout při použití špatného řešení. Pokud máte vlastní zkušenosti a návrhy, se kterými byste se rádi svěřili ostatním, neváhejte se ozvat pomocí kontaktního formuláře.