neděle 30. prosince 2012

Převod quaternionu na Eulerovy úhly

V tomto příspěvku odvodím vztahy pro převod quaternionu na Elerovy úhly používané v letectví, tedy úhly, které postupně reprezentují rotaci okolo osy $z$ , $y$ a $x$. Tyto úhly značím postupně jako $\alpha$, $\beta$ a $\gamma$. Prvek matice $\mathbf{R}$ na řádku $i$ a ve sloupci $j$ značím jako $\mathbf{R}_{ij}$.

Nejprve převedeme quaternion na rotační matici a z té posléze získáme Eulerovy úhly. Rotační matici z quaternionu $\mathbf{q}=(q_w, q_x, q_y, q_z)$ získáme pomocí následujícího vztahu [1]:
$$
\mathbf{R}_q =

\begin{bmatrix}
    1 - 2 q_y^2 - 2 q_z^2 & 2 q_x q_y - 2 q_z q_w & 2 q_x q_z + 2 q_y q_w \\
    2 q_x q_y + 2 q_z q_w & 1 - 2 q_x^2 - 2 q_z^2 & 2 q_y q_z - 2 q_x q_w \\
    2 q_x q_z - 2 q_y q_w & 2 q_y q_z + 2 q_x q_w & 1 - 2 q_x^2 - 2 q_y^2
\end{bmatrix}
$$ Rotační matice pro Eulerovy úhly definované v úvodním odstavci při značení $\sin\!\left(\alpha\right)=s_\alpha$ (pro kosinus a další úhly analogicky) má následující podobu
$$ \mathbf{R}_E =
\begin{bmatrix} c_\alpha\, c_\beta & c_\alpha\, s_\beta\, s_\gamma - c_\gamma\, s_\alpha & s_\alpha\, s_\gamma + c_\alpha\, c_\gamma\, s_\beta\\ c_\beta\, s_\alpha & c_\alpha\, c_\gamma + s_\alpha\, s_\beta\, s_\gamma & c_\gamma\, s_\alpha\, s_\beta - c_\alpha\, s_\gamma\\ - s_\beta & c_\beta\, s_\gamma & c_\beta\, c_\gamma \end{bmatrix}
$$ Z matice $\mathbf{R}_E$ určíme nejprve úhel $\beta$ jako
$$ \beta = \mathrm{asin}\,\left(-\mathbf{R}_{31} \right).
$$ Dále se postup v závislosti na hodnotě prvku $\mathbf{R}_{31}$ dělí na tři případy.
  1. Pokud platí, že $\mathbf{R}_{31} = 1$, pak má rotační matice nutně následující podobu
$$
\mathbf{R}_E' =
\begin{bmatrix} 0 & -c_\alpha\, s_\gamma - c_\gamma\, s_\alpha & s_\alpha\, s_\gamma - c_\alpha\, c_\gamma\\
0 & c_\alpha\, c_\gamma - s_\alpha\,  s_\gamma & -c_\gamma\, s_\alpha\, - c_\alpha\, s_\gamma\\
1 & 0 & 0 \end{bmatrix}
=
\begin{bmatrix} 0 & -s_{\gamma + \alpha} & c_{\gamma + \alpha}\\
0 & c_{\gamma + \alpha} & -s_{\gamma + \alpha}\\
1 & 0 & 0 \end{bmatrix}.
$$ Řešení  pro úhly $\alpha$ a $\gamma$ je nekonečně mnoho. Je možné získat pouze součet těchto úhlů. Z nekonečně mnoha řešení tedy vybereme jedno. \begin{align*}
\alpha &= 0\\
\gamma &= \mathrm{atan2}\!\left( \mathrm{-\mathbf{R}_{12}}\mathrm{\mathbf{R}_{22}} \right)
\end{align*}
  1. Pokud platí, že $\mathbf{R}_{31} = -1$, pak má rotační matice nutně následující podobu
$$
\mathbf{R}_E' =
\begin{bmatrix} 0 & c_\alpha\, s_\gamma - c_\gamma\, s_\alpha & s_\alpha\, s_\gamma + c_\alpha\, c_\gamma\\
0 & c_\alpha\, c_\gamma + s_\alpha\,  s_\gamma & c_\gamma\, s_\alpha\, - c_\alpha\, s_\gamma\\
-1 & 0 & 0 \end{bmatrix}
=
\begin{bmatrix} 0 & s_{\gamma - \alpha} & c_{\gamma - \alpha}\\
0 & c_{\gamma - \alpha} & -s_{\gamma - \alpha}\\
-1 & 0 & 0 \end{bmatrix}.
$$ Obdobně jako v předchozím případě je řešení  pro úhly $\alpha$ a $\gamma$ nekonečně mnoho. Opět vybereme jedno řešení, které má například následující podobu \begin{align*}
\alpha &= 0,\\
\gamma &= \mathrm{atan2}\!\left( \mathrm{\mathbf{R}_{12}}, \mathrm{\mathbf{R}_{22}} \right).
\end{align*}
  1. Pro jiné hodnoty $\mathbf{R}_{31}$ určíme zbývající úhly podle následujících vztahů
\begin{align*} \alpha &= \mathrm{atan2}\!\left(\mathrm{\mathbf{R}_{21}}, \mathrm{\mathbf{R}_{11}} \right),\\
\gamma &= \mathrm{atan2}\!\left( \mathrm{\mathbf{R}_{32}}, \mathrm{\mathbf{R}_{33}} \right).
\end{align*} Rotační matici s konkrétními hodnotami jsme získali převodem z quaternionu a známe vztahy pro výpočet jednotlivých Eulerových úhlů z této matice, které jsme odvodili z obecného tvaru rotační matice pro tyto úhly. Již tedy zbývá jen do těchto vztahů dosadit. Pro jednoduchost zde uvádím jen dosazené vztahy pro poslední případ.\begin{align*} \alpha &= \mathrm{atan2}\!\left( 2 q_x q_y + 2 q_z q_w, 1 - 2 q_x^2 - 2 q_y^2 \right),\\
\beta &= \mathrm{asin}\,\left(2 q_y q_w - 2 q_x q_z\right),\\
\gamma &= \mathrm{atan2}\!\left( 2 q_y q_z + 2 q_x q_w, 1 - 2 q_y^2 - 2 q_z^2 \right).
\end{align*} Převod quaternionů na Eulerovy úhly implementovaný v programovacím jazyce C# vypadá následovně:
        public void ToEulerAngles(out double yaw, out double pitch, out double roll)
        {
            double test = q[1] * q[3] - q[0] * q[2];

            if (test > 0.49999)
            {
                roll = Math.Atan2(2 * q[1] * q[0] - 2 * q[2] * q[3], 2 * q[1] * q[3] + 2 * q[2] * q[0]);
                pitch = -Math.PI / 2;
                yaw = 0;
                return;
            }

            if (test < -0.49999)
            {
                roll = Math.Atan2(2 * q[2] * q[3] - 2 * q[1] * q[0], 2 * q[1] * q[3] + 2 * q[2] * q[0]);
                pitch = Math.PI / 2;
                yaw = 0;
                return;
            }

            double sqx = q[1] * q[1];
            double sqy = q[2] * q[2];
            double sqz = q[3] * q[3];

            roll = Math.Atan2(2 * q[2] * q[3] + 2 * q[0] * q[1], 1 - 2 * sqx - 2 * sqy);
            pitch = Math.Asin(-2 * test);
            yaw = Math.Atan2(2 * q[1] * q[2] + 2 * q[3] * q[0], 1 - 2 * sqy - 2 * sqz);
        }

Zdroje

Individuální projekt (2)

Vnější souřadnicová soustava

Vnější souřadnicová soustava nosiče vůči Zemi má počátek v hmotném středu nosiče, osa $x$ směřuje na sever, osa $z$ do středu Země a osa $y$ je orientována tak, aby byl souřadnicový systém pravotočivý.

Vnitřní souřadnicová soustava nosiče

Souřadnicová soustava nosiče je znázorněna na Obrázku 1. Jedná se o v letectví běžně používaný souřadnicový systém, kde počátek je ve středu nosiče (je tedy souhlasný s počátkem vnější souřad. soustavy), osa $x$ je orientována ve směru letu, osa $y$ prochází osou křídel a osa $z$ je orientována tak, aby směřovala směrem dolů a systém splňoval pravidlo pravotočivé souřadnicové soustavy.

Obrázek 1: Souřadnicová soustava nosiče


Poloha a orientace nosiče

Polohu nosiče získáme přímo z polohy určené GPS přijímačem v inerciální jednotce. Tato poloha sice neodpovídá poloze nosiče, jelikož je dána polohou antény, ale vzhledem k tomu, že rozdíl v těchto polohách je minimální vzhledem k ostatním uvažovaným vzdálenostem ve výpočtu přímé kinematické úlohy, lze tento rozdíl zanedbat, případně by byl kompenzován přímo v inerciální jednotce.

Orientaci nosiče získáme opět přímo z inerciální jednotky. Inerciální jednotka může být umístěna v rámci nosného objektu tak, že její orientace se neshoduje s orientací nosného objektu. Tato situace je však kompenzována přímo v inerciální jednotce. Orientace je v inerciální jednotce uchovávána v podobě quaternionů.

Popis samotné inerciálně stabilizované platformy

Samotná inerciálně stabilizovaná platforma má čtyři klouby. Dva zajišťují rotaci platformy v azimutální ose a zbylé dva v elevační ose. Pro rotaci okolo jedné osy jsou tedy vždy použity dva klouby. Jeden je schopen rotace o $n\cdot360^\circ$ a je vůči druhému relativně pomalý, druhý je schopen rotace jen ve velmi omezeném rozsahu, ale je velmi rychlý. Pro samotnou stabilizaci se tedy s výhodou využívají převážně ony rychlé klouby.

Pro naše účely je ale výhodnější reprezentovat kamerovou platformu jako otevřený kinematický řetězec s pouze dvěma klouby. Pro přímou kinematickou úlohu pouze přičteme k pomalému kloubu pro danou osu otočení rychlého kloubu. Pro inverzní kinematickou úlohu budeme uvažovat pouze pomalé klouby. Takovýto kinematický řetězec můžeme popsat například Denavit-Hartenbergovou notací. Pro náš případ je také výhodné, že v této notaci se bude shodovat osa kamery a dálkoměru s osou $x$ souřadnicové soustavy posledního kloubu.

Parametry Denavitovy-Hartenbergovy notace
$n$ $\theta_n$ $d_n$ $a_n$ $\alpha_n$
1 $q_1$ $d_1$ $0$ $\pi/2$
2 $q_2$ $0$ $0$ $0$
Parametry $q_1$ a $q_2$ jsou kloubové souřadnice robota, které odpovídají natočení azimutálního a elevačního kloubu. Tato natočení jsou vyčítána řídící jednotkou kamerové platformy z inkrementálních rotačních čítačů. Ty však bohužel nemají shodnou orientaci s kloubovými souřadnicemi. Na Obrázku 2 jsou znázorněny orientace jednotlivých čítačů. Z nich snadno získáme převodní vztah do kloubových souřadnic.

\begin{align*}
q_1 &= -(\beta_0 + \beta_1) + \pi \\
q_2 &= \alpha_0 + \alpha_1 - \pi/2
\end{align*}
Obrázek 2: Orientace kloubových úhlů


Individuální projekt (1)

Tato série příspěvků se bude věnovat úloze, kterou jsem řešil v rámci předmětu Individuální projekt (A3B35IND). Úloha se týká projektu inerciálně stabilizované kamerové platformy, tedy projektu, jehož se okrajově týkaly i předchozí příspěvky o inerciální jednotce. Podrobnější popis projektu inerciálně stabilizované kamerové platformy je na stránkách skupiny AA4CC.

Cílem práce je vyřešit přímou a inverzní kinematickou úlohu pro kamerovou hlavici na nějakém nosném objektu. Přímá část práce spočívá v určení místa na mapě, jenž je ve středu zorného pole kamery. Motivací pro tuto úlohu je fakt, že operátor kamerové hlavice má aktuálně k dispozici aplikaci, v níž je vykreslována pozice nosného objektu a obraz z kamery, bohužel však již nemá k dispozici informaci o tom, na jaké místo na mapě je kamerová hlavice zaměřena. Inverzní úloha spočívá v určení kloubových souřadnic kamerové platformy takových, aby zadané místo na mapě bylo v zorném poli kamery. Zde je motivace zřejmá. Místo nepohodlného ručního zaměřování určitého místa na mapě přenechat tuto úlohu řídícímu systému a celý tento proces tak zautomatizovat.

sobota 29. prosince 2012

C# třída pro práci s (transformačními) maticemi

Jelikož programovací jazyk C# nenabízí ve standardních třídách vhodnou třídu pro práci s maticemi, natož pak s transformačními maticemi, musel jsem si vytvořit vlastní třídu. Třída obsahuje mimo základní operace s maticemi, jako je sčítání, maticové násobení, násobení skalárem a transpozici i operace spojené s transformačními maticemi. Jmenovitě se jedná o generování rotačních matic okolo osy $x$, $y$ a $z$, rotační matice podle Eulerových úhlů v notaci $ZYX$, translační matice a transformační matice podle parametrů z Denavit-Hartnebergovy notace. Rotační matice jsou dimenze $4\times 4$, tedy v homogenních souřadnicích. Třída přetěžuje operátory sčítání, násobení a indexového přístupu pro maximálně intuitivní práci s jednotlivými instancemi třídy. Její aktuální verze s podrobnější dokumentací je přístupná na mém repositáři na githubu.

Seznam funkcí implementovaných ve třídě:
        public Matrix(int rows, int cols)
        public Matrix Copy()
        public static Matrix ZeroMatrix(int rows, int cols)
        public static Matrix IdentMatrix(int n)
        public override string ToString()
        public static Matrix Transpose(Matrix m)
        public static Matrix Multiply(Matrix m1, Matrix m2)
        private static Matrix ScalarMultiply(double n, Matrix m)
        private static Matrix Add(Matrix m1, Matrix m2)
        public static Matrix EulerRotaionMatrix(double yaw, double pitch, double roll)
        public static Matrix RotaionMatrixZ4(double angle)
        public static Matrix RotaionMatrixX4(double angle)
        public static Matrix RotaionMatrixY4(double angle)
        public static Matrix TranslationMatrix(double xTrans, double yTrans, double zTrans)
        public static Matrix DHTransMatrix(double[][] DHparams)

úterý 24. července 2012

Srovnání elektronických gyroskopů InvenSense ITG-3200 a ST L3G4200D

V dnešním článku srovnám elektronické gyroskopy InvenSense ITG-3200 a ST L3G4200D a to především podle šumu, teplotní závislosti offsetů a závislosti offsetů na tíhovém zrychlení.

Oba senzory měli při měření nastaveny obdobné parametry.
  • Oba: rozlišení 2000 °/s, vzorkovací frekvence 200 Hz
  • ITG-3200: dolnopropustní filtr 98 Hz
  • L3G4200dolnopropustní filtr 70 Hz

Popis senzorů

ITG-3200

Tento senzor jsem popsal již v tomto dřívějším článku.

L3G4200D

Elektronický gyroskop L3G4200D je 16 bitový tříosý mikromechanický senzor úhlové rychlosti. Senzor má  mimo jiné programové nastavitelné rozlišení (±250 °/s±500 °/s, ±2000 °/s), vzorkovací frekvenci a k dané vzorkovací frekvenci i dolnopropustní filtr. Dále má senzor v sobě integrován teploměr se vzorkovací frekvencí 1 Hz, 8 bitovým rozlišením s citlivostí 1 °C/LSB. Komunikace se senzorem je možná po sběrnici I2C nebo SPI. Výrobce se u tohoto senzoru chlubí výjimečnou stálostí offsetů.

Šum

Obrázek 1 zobrazuje graf s naměřeným hodnotami úhlových rychlostí pro stejnou osu z obou senzorů. Senzor L3G4200D měl nulový offset a naměřená data jsou tedy zobrazena bez jakýchkoliv úprav. U senzoru ITG-3200 byl pro lepší srovnání odečten nenulový offset, který nemá na šum vliv. Z grafu je zřejmé, že šum má v obou případech nulovou střední hodnotu. V tomto srovnán jasně vítězí senzor ITG-3200, neboť má násobně menší šum (v řádu několika málo LSB).
Obrázek 1: Srovnání šumu

Závislost offsetů na orientaci vektoru tíhového zrychlení

Tuto závislost jsem pro senzor ITG-3200 naměřil již dříve a publikoval v tomto článku. Zde již pouze uvedu, že závislost nebyla prokázána.
Naměřená data ze senzoru L3G4200D jsou zobrazena na Obrázku 2. Při měření byl senzor natočen do šesti poloh tak, aby vždy vektor tíhové zrychlení byl rovnoběžný z jednou z os senzoru. Offset je zřejmě nezávislý na orientaci senzoru vůči Zemi a tedy orientaci vektoru tíhového zrychlení.
Obrázek 2: Závislost offsetu senzoru L3G4200D na orientaci vůči Zemi

Závislost offsetů na teplotě

Senzory byly podchlazovány pomocí Peltierova článku M-TEC1-01708 a ohřívány pomocí horkovzdušné pistole. Teplota je měřena vždy čidlem teploty integrovaným přímo v pouzdře senzoru. 

L3G4200D

Závislost na teplotě je u senzoru L3G4200D zřejmá z grafu na Obrázku 3.  Na Obrázku 4 je zobrazen graf závislosti offsetu senzoru pro osu Z. Při změně teploty o cca 45 °C se offset změnil o cca 0,75 °/s. Nutno podotknout, že v obou grafech je teplota vynesena diferenčně tak, jak ji měří integrovaný teploměr.

Obrázek 3

ITG-3200

Podrobnější rozbor závislosti offsetu senzoru ITG-3200 jsem uvedl v tomto článku. Zde pouze publikuji grafy s naměřenými daty pro větší teplotní rozsah.


Závěr

Dle výše uvedených grafů považuji za vítěze tohoto srovnání elektronický gyroskop ITG-3200 od firmy InvenSnese. Má sice podstatně větší offset ve všech osách i mírně větší teplotní závislost offsetů, nicméně samotná velikost offsetu není zajímavá pokud je stabilní. Stabilní v tomto případě sice není, neboť je závislý na teplotě, ale díky velmi dobrému integrovanému teploměru, který má větší rozlišení i vzorkovací frekvenci než L3G4200D, je možné tuto závislost kompenzovat. Oproti svému konkurentovi navíc vyniká menším šumem.

sobota 14. července 2012

Teplotní charakteristiky offsetů senzorů

Samotný offset u senzoru nemusí znamenat nijak zásadní problém pokud je stálý. Pak jej stačí odečíst od naměřených dat a tím je jeho vliv eliminován. Mění-li se však v čase, s teplotou případně dokonce s orientací vzhledem k Zemi, není snadné jeho vliv minimalizovat.

Měření probíhalo ve velmi provizorních podmínkách. To je důvod proč je rozsah teplot poměrně nízký. Teplota byla měřena interním teploměrem v elektronickém gyroskopu a určitě se bude mírně lišit od teplot ostatních senzorů.

Akcelerometr Analog Devices ADXL345

Jak je vidět z následujících obrázků, tento konkrétní senzor zrychlení jednoznačně trpí závislostí offsetu na teplotě a to dokonce v každé ose jinak významně. Nejvíce je teplotně závislý offset osy Z a nejméně naopak offset osy X. Při změně teploty o 25 °C se změnil offset osy Z dokonce o cca 50 mg.

Obrázek 1: Graf závislosti offsetu akcelerometru na teplotě

Obrázek 2: Graf závislosti offsetu osy Z akcelerometru na teplotě

Elektronický gyroskop InvenSense ITG-3200

Změna offsetu elektronického gyroskopu je obzvláště kritická, jelikož integrací úhlové rychlosti se získávají úhly natočení tělesa. Pak je velmi nepříjemné, když elektronický gyroskop měří nenulovou úhlovou rychlost i pro neotáčející se těleso.

Závislost offsetu na orientaci vůči Zemi

Na Obrázku 3 je zobrazen graf naměřené úhlové rychlosti pro šest natočení senzoru. Změna natočení byla provedena vždy po 5-10 sekundách. Je zřejmé, že offset je stejný nezávisle na natočení senzoru. Závislost se tedy nepodařilo prokázat. Velmi podobně vypadají i grafy pro ostatní osy. Liší se pouze hodnotou samotného offsetu.
Obrázek 3: Graf závislosti offsetu senzoru ITG-3200 na orientaci vůči Zemi

Závislost offsetu na teplotě

Některé dražší elektronické gyroskopy jsou teplotně stabilizované, ITG-3200 mezi ně bohužel nepatří. Výrobce však integroval do pouzdra senzoru alespoň teploměr a je tedy možné si jej teplotně stabilizovat softwarově. Jak je vidno z Obrázku 4, je nutné tuto stabilizaci provést. Offset na ose Z při změně teploty o 25 °C posunul dokonce o cca 1.75 °/s.
Obrázek 4: Graf závislosti offsetu senzoru ITG-3200 na teplotě

Sparkfun 9DOF modul - komunikace se senzory

První sada nově testovaných senzorů se dá zakoupit jako vývojový kit od firmy Sparkfun Electronics. Modul byl zakoupen již dříve a dnes se v nabídce obchodu už nenachází. Uvádím zde tedy alespoň odkaz na novější verzi tohoto modulu (9 Degrees of Freedom). Liší se pouze mírně modifikovanou verzí magnetometru. Modul se připojí ke stávající inerciální jednotce pomocí sběrnice I2C. Přímo na desce modulu jsou dokonce již osazeny i pull-up rezistory.
Novější varianta Sparkfun 9DOF modulu
Zdroj: http://www.sparkfun.com

Komunikace po sběrnici I2C

Implementace knihovny pro komunikaci po sběrnici je silně závislá na použitém mikrokontroléru. Já si napsal vlastní pro mikrokontrolér LPC2368. Její kód je příliš dlouhý na to, abych ho zde vypisoval, proto uvedu jen deklarace funkcí s velmi stručným popisem.

/*!
    \brief I2C single byte read routine
    \details
    \param devaddr 8 bit device address
    \param regaddr 8 bit register address
    \param data Pointer to address where readed byte will be stored
    \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL i21c_read(uint32_t devaddr, uint32_t regaddr, uint8_t * data);
BOOL i21c_read_seq(uint32_t devaddr, uint32_t regaddr, volatile uint8_t * data, uint32_t size);/*!
    \brief I2C single byte write routine
    \details
    \param devaddr 8 bit device address
    \param regaddr 8 bit register address
    \param data Byte to write
    \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL i21c_write(uint32_t devaddr, uint32_t regaddr, uint8_t data);
BOOL i21c_write_seq(uint32_t devaddr, uint32_t regaddr, uint8_t * data, uint32_t size);

Akcelerometr Analog Devices ADXL345

Senzor ADXL345 je tříosý akcelerometr s až 13 bitovým rozlišením a nastavitelným rozsahem až do ±16 g (nastavitelný rozsah je pouze pro 10 bitové rozlišení) [1]. Při maximálním 13 bitovém rozlišení má senzor citlivost  3.9 mg/LSB (LSB - least significant bit). Senzor komunikuje po sběrnici I2C a to buď rychlostí 100 kHz nebo 400 kHz a má adresu 0xA6. Poslední bit této adresy je určen logickou úrovní na pinu SDO/ALT ADDRESS (12). Možnosti využití senzoru jsou značně omezené díky tomu, že je z něj na modulu vyvedeno pouze rozhraní I2C a další piny jsou nedostupné. Mezi tyto nedostupné piny patří například rozhraní SPI či piny přerušení, které mimo jiné indikující volný pád nebo jednoduché či dvojité poklepání na senzor (viz datasheet).

Při inicializaci je nutné pouze nastavit Measure Bit v registru POWER_CTL pro probuzení senzoru ze standby módu do měřícího kontinuálního módu. Dále můžeme nastavit frekvenci s jakou bude senzor měřit a rozlišení.

#define ADXL345_DEV_ADDR  (0xA6)
#define ADXL345_DATA_ADDR  (0x32)
#define ADXL345_REGISTER_PWRCTL  (0x2D)
#define ADXL345_PWRCTL_MEASURE   (1 << 3)
#define ADXL345_REGISTER_BWRATE  (0x2C)
#define ADXL345_REGISTER_DATAFORMAT (0x31)
#define ADXL345_FULL_RES_BIT   (1 << 3)

typedef enum {
 adxl345_datarate_f100Hz = 0x0A,
 adxl345_datarate_f200Hz = 0x0B,
 adxl345_datarate_f400Hz = 0x0C,
 adxl345_datarate_f800Hz = 0x0D
} adxl345_data_rate;
typedef enum {
 adxl345_resolution_2g = 0x00,
 adxl345_resolution_4g = 0x01,
 adxl345_resolution_8g = 0x02,
 adxl345_resolution_16g = 0x03,
 adxl345_resolution_full = 0xFF
} adxl345_resolution;

/*! \brief Initialization of sensor
 \details

 \param freq Data rate of sensing
 \param res Resolution
 \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL init_adxl345(adxl345_data_rate freq, adxl345_resolution res) {
 BOOL result;

 //Set measure bit in PWR_CTL register to start measuring
 result = i21c_write(ADXL345_DEV_ADDR, ADXL345_REGISTER_PWRCTL, ADXL345_PWRCTL_MEASURE);

 //Set date rate to 200 Hz
 result &= i21c_write(ADXL345_DEV_ADDR, ADXL345_REGISTER_BWRATE, freq);

 //Set resolution
 if(res == 0xFF)
  // +-16 g resolution, 13 bit, 4 mg/LSB
  result &= i21c_write(ADXL345_DEV_ADDR, ADXL345_REGISTER_DATAFORMAT, ADXL345_FULL_RES_BIT);
 else
  result &= i21c_write(ADXL345_DEV_ADDR, ADXL345_REGISTER_DATAFORMAT, res);

 return result;
}
Čtení naměřených dat ze senzoru se provádí čtením šesti po sobě následující registrů, ve kterých je pro jednotlivé naměřené hodnoty pro dané osy uloženo vždy nejprve spodních 8 bitů a následně zbývající horní bity. Následující ukázka funkce pro čtení naměřených dat ze senzoru je jistě názornější než slovní popis.

/*! \brief Reading of sensor data
 \details Reads acceleration in all three axes os sensor and rotate them to coordinate system of inertial unit

 \param accelerometer_data[] Array where will be stored readed data (readed direct from register of sensor)
 \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL read_data_adxl345(int16_t accelerometer_data[]) {
 BOOL result;
 uint8_t readed_data[6];

 result = i21c_read_seq(ADXL345_DEV_ADDR, ADXL345_DATA_ADDR, readed_data, 6);

 accelerometer_data[0] = (int16_t)((readed_data[1]<<8) | readed_data[0]); // x 
 accelerometer_data[1] = (int16_t)((readed_data[3]<<8) | readed_data[2]); // y
 accelerometer_data[2] = (int16_t)((readed_data[5]<<8) | readed_data[4]); // z

 return result;
}

Elektronický gyroskop InvenSense ITG-3200

Elektronický gyroskop ITG-3200 je 16 bitový tříosý mikromechanický (MEMS) senzor úhlové rychlosti [2]. Rozlišení senzoru je neměnné a nabývá hodnoty ±2000 °/s při citlivosti 14.375 LSB/(°/s). Senzor má v sobě integrován digitální dolnopropustní filtr a teploměr. Podobně jako u akcelerometru senzor umožňuje i komunikaci po SPI, ale ne v případě tohoto modulu. Senzor opět umožňuje komunikaci po sběrnici I2C rychlostí 100 kHz, případně 400 kHz a má 8 bitovou adresu 0xD0. Připojením pinu AD0 na jinou logickou úroveň může být změněn LSB této adresy.

Inicializace senzoru spočívá pouze v nastavení dolnopropustního filtru a vzorkovací frekvence nebo přesněji nastavení děličky základní frekvence od níž je ta vzorkovací odvozena. Základní frekvence též závisí na nastavení dolnopropustního filtru. Pokud je dolnopropustní filtr nastaven na 256 Hz, je základní frekvence 8 kHz. Pro jiné hodnoty dolnopropustního filtru nabývá vždy základní frekvence hodnoty 1 kHz. Senzor funguje v kontinuálním měřícím režimu.

#define ITG3200_DEV_ADDR      (0xD0)
#define ITG3200_TEMP_ADDR      (0x1B)
#define ITG3200_DATA_ADDR      (0x1D)
#define ITG3200_REGISTER_DLPF_FS     (0x16)
#define ITG3200_FULLSCALE       (0x03 << 3)
#define ITG3200_REGISTER_SAMPLE_RATE_DIVIDER  (0x15)

typedef enum {
 itg3200_low_pass_f256Hz,
 itg3200_low_pass_f188Hz,
 itg3200_low_pass_f98Hz,
 itg3200_low_pass_f42Hz,
 itg3200_low_pass_f20Hz,
 itg3200_low_pass_f10Hz,
 itg3200_low_pass_f5Hz
} itg3200_low_pass_filter;

/*!
    \brief Initialize gyro sensor
    \details Sets low pass filter, frequence of sampling

 \param lp_freq Frequency of low pass filter
    \param divider Divide base sampling freqency. Base sample frequency is 8 kHz for 256 Hz lowpass filter and 1 kHz for others.
    \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL init_itg3200(itg3200_low_pass_filter lp_freq, DWORD divider) {
 BOOL result;

 // set divider of base sample frequency
 result = i21c_write(ITG3200_DEV_ADDR, ITG3200_REGISTER_SAMPLE_RATE_DIVIDER, divider);

 // set low pass filter and full scale resolution of 2000°/s (the only possible)
 result &= i21c_write(ITG3200_DEV_ADDR, ITG3200_REGISTER_DLPF_FS, ITG3200_FULLSCALE | lp_freq);

 return result;
}
Čtení je podobné jako v předchozím případě s jedním drobným rozdílem. Vzorkovací frekvence je odvozena od vnitřního oscilátoru, který má přesnost 2 %, což není mnoho. Pokud tedy nastavíme vzorkovací frekvenci na 200 Hz a čteme data ze senzoru také s frekvencí 200 Hz, stává se, že senzor ještě nemá nová data připravena a my načteme stejná data jako v minulé iteraci. To je důvod, proč je ve funkci pro čtení zahrnuta i čekací smyčka, která kontroluje příznak připravenosti nových dat v registrech senzoru.

/*! \brief Reading of sensor data
* \details Reads measured data from sensor in all three axes of sensor and rotate them to coordinate system of inertial unit
*
* \param gyro_data[] Array where will be stored readed data (readed direct from register of sensor)
* \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL read_data_itg3200(int16_t gyro_data[]) {
 BOOL result = 1;
 uint8_t readed_data[6];
 uint8_t new_data_available;

 // wait until new data is ready
 do {
  result &= i21c_read(ITG3200_DEV_ADDR, 26, &new_data_available);
 } while(new_data_available & 1);


 result &= i21c_read_seq(ITG3200_DEV_ADDR, ITG3200_DATA_ADDR, readed_data, 6);

 gyro_data[0] = -(int16_t)((readed_data[0]<<8) | readed_data[1]);  //x
 gyro_data[1] = (int16_t)((readed_data[2]<<8) | readed_data[3]);  //y
 gyro_data[2] = (int16_t)((readed_data[4]<<8) | readed_data[5]);  //z

 return result;
}

Magnetometr Honeywell HMC5843

Magnetometr HMC5843 je tříosý 12 bitový senzor magnetického pole (magnetické indukce) [3]. Zjednodušeně se dá říci, že převádí změnu rezistivity anizotropních magnetorezistorů na změnu magnetické indukce (anizotropní magnetorezistory mají závislou rezistivitu na magnetické indukci). Jako ostatní senzory osazené na modulu komunikuje po sběrnici I2C a má pevně danou adresu 0x3D. Opět podporuje rychlost komunikace 100 kHz i 400 kHz. Maximální rozlišení senzoru je ±4 gauss (±400 μT) a maximální vzorkovací frekvence je 50 Hz

Inicializace senzoru spočívá nastavení vzorkovací frekvence a kontinuálního měřícího módu. Senzor je totiž ve výchozím stavu nastaven na pouhé jedno měření po kterém přejde do sleep módu.
#define HMC5843_DEV_ADDR       (0x3C)
#define HMC5843_DATA_ADDR      (0x03)
#define HMC5843_REGISTER_CTRLA      (0x00)
#define HMC5843_REGISTER_MEASMODE     (0x02)
#define HMC5843_MEASMODE_CONT      (0x00)

typedef enum {
 hmc5843_datarate_05Hz,
 hmc5843_datarate_1Hz,
 hmc5843_datarate_2Hz,
 hmc5843_datarate_5Hz,
 hmc5843_datarate_10Hz,
 hmc5843_datarate_20Hz,
 hmc5843_datarate_50Hz
} hmc5843_datarate;

/*! \brief Initialization of sensor
 \details
 \param  data_rate Sampling rate
 \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL init_hmc5843(hmc5843_datarate data_rate) {
 BOOL result;

 //set up data rate
 result = i21c_write(HMC5843_DEV_ADDR, HMC5843_REGISTER_CTRLA, (data_rate << 2));

 //set up continuous measurement mode
 result &= i21c_write(HMC5843_DEV_ADDR, HMC5843_REGISTER_MEASMODE, HMC5843_MEASMODE_CONT);

 return result;
}
Čtení dat ze senzoru je opět skoro totožné s těmi předchozími.

/*! \brief Reading of sensor data
* \details Reads measured data from sensor in all three axes of sensor and rotate them to coordinate system of inertial unit
*
* \param magnetometer_data[] Array where will be stored readed data (readed direct from register of sensor)
* \return  Returns 0 in case of error in comunication with sensor, 1 otherwise
*/
BOOL read_data_hmc5843(int16_t magnetometer_data[]) {
 BOOL result;
 uint8_t readed_data[6];

 result = i21c_read_seq(HMC5843_DEV_ADDR, HMC5843_DATA_ADDR, readed_data, 6);

 magnetometer_data[0] = (int16_t)((readed_data[0]<<8) | readed_data[1]);  //x
 magnetometer_data[1] = (int16_t)((readed_data[2]<<8) | readed_data[3]);  //y
 magnetometer_data[2] = -(int16_t)((readed_data[4]<<8) | readed_data[5]);  //z

 return result;
}

Zdroje

[1] Datasheet (ADXL345)
[2] Datasheet (ITG-3200)
[3] Datasheet (HMC5883L)

pondělí 25. června 2012

Princip určování orientace v prostoru inerciální měřící jednotkou

Ve zjednodušené verzi se používají k určování orientace 3 senzory a to elektronický gyroskop, akcelerometr a magnetometr. Proč nestačí pouze elektronický gyroskop, který měří úhlovou rychlost, jejíž integrací přeci získáme kýžené úhly?


Orientace jednotlivých úhlů
Problém je v tom, že mikromechanický (MEMS) elektronický gyroskop, který se za tímto účelem kvůli své dostupnosti využívá, trpí velkým offsetem. To by nemusel být zásadní problém, pokud by však byl tento offset neměnný, ale on je často závislý na teplotě či dokonce na orientaci samotného senzoru vůči Zemi a tedy na tíhové síle. Při integraci samozřejmě nadělá takový offset velkou paseku, protože senzor udává nenulovou úhlovou rychlost i pro neotáčející se objekt. Velkou výhodou těchto senzorů je však rychlost. Moderní elektronické gyroskopy jsou schopné snímat úhlovou rychlost až do ±2000 °/s.

Za účelem eliminace offsetu elektronického gyroskopu se používají ještě další dva senzory (akcelerometr a magnetometr). Uvažujeme-li těleso pohybující se bez zrychlení, akcelerometr měří pouze tíhové zrychlení g. Jelikož vektor tíhového zrychlení míří do středu Země, snadno  určíme orientaci senzoru z naměřeného vektoru zrychlení (vyjma natočení okolo naměřeného vektoru tíhového zrychlení - azimutálního úhlu). Pomocí magnetometru se měří magnetické pole země a z toho lze určit azimutální úhel (velmi podobně jako u kompasu) [1]. Nevýhoda magnetometru je v porovnání s elektronickým gyroskopem jeho malá vzorkovací frekvence a tedy i šířka pásma.

Orientaci inerciální jednotky určíme prvotně integrací úhlových rychlostí elektronického gyroskopu. "Ujíždění" úhlů způsobené integrací offsetu kompenzujeme úhly vypočtenými z naměřených hodnot akcelerometrem a magnetometrem. To však nelze vždy, neboť u akcelerometru jsme v předchozím odstavci zavedli nepříjemnou podmínku a to ohledně pohybu tělesa se zrychlením. Tělesa se běžně pohybují se zrychlením a to například i když jen zatáčejí, protože pak na ně působí dostředivé zrychlení. V takovém případě je nutné kompenzaci vypnout. Detekce těchto případů se provádí kontrolou velikosti naměřeného vektoru zrychlení. Pokud se významně liší od velikosti tíhového zrychlení, kompenzaci vypneme.  


Zdroje
[1] Jan Kříž. Inerciální měřicí jednotka v počítačovém modulu Gumstix Overo. Diplomová práce, ČVUT v Praze, 2011.

Motivace

Již pěknou řádku let se snažím každé letní prázdniny řádně využít a to jak pracovně, tak aktivním odpočinkem. Při výběru práce (brigády) jsem vždy dbal nejen na finanční ohodnocení, ale i na přínos pro mě do budoucna. Vždy pro mě bylo velmi přínosné pohybovat se v kolektivu zkušenějších lidí. Je pro mě obrovskou motivací snažit se v takovém kolektivu nezapadnout a být dobrý (snad podle hesla "Dohnat a předehnat!" :-)). V tomto ohledu otevírá studium na vysoké škole velké možnosti a to především v rámci pracovních stáží na katedrách napříč celou fakultou. Přeci právě ve výzkumných týmech na jednotlivých katedrách musí být takovýchto kolektivů velmi mnoho. Dále předpokládám, že se v rámci takového týmu dostanu k zajímavým problémům, které je potřeba vyřešit.

Jelikož studuji na Kybernetice a robotice obor Systémy a řízení, kterýžto spadá pod Katedru řídící techniky, byla by letní stáž na této katedře logickou volbou. Samozřejmě mě k tomuto kroku nevedl jen tento banální důvod. Končím druhý ročník, těžko mohu hodnotit kvalitu či výsledky jednotlivých kateder, přesto však na mne zapůsobila Katedra řídící techniky zdaleka nejvíce a to nejen velmi zajímavým výzkumem a jeho výsledky, ale i stylem výuky a náročností předmětů, které pod tuto katedru spadají. Právě podle oněch předmětů jsem předpokládal, že stáž na této katedře na mě sice bude klást vyšší nároky, ale za to mi nabídne o to více zkušeností a znalostí. Navíc vzhledem k tomu, že řízení je obecně interdisciplinární oblast, určitě si rozšířím vědomosti i do dalších oborů. 

Na katedře působí více výzkumných oddělení. Osobně mě nejvíce zaujalo Oddělení pokročilých algoritmů pro řízení a komunikace (AA4CC) . Mají velmi mnoho zajímavých výzkumných aktivit, z nichž mně byla nejbližší ta, zabývající se inerciálně stabilizovanou kamerovou hlavicí. Snad protože se v tomto projektu setkává robotika, mikroprocesorová technika a řízení, což jsou všechno oblasti, které mě velmi zajímají, a velmi rád si v nich rozšířím rozhledy.

Po domluvě s vedoucím tohoto projektu Ing. Zdeňkem Hurákem, Ph.D. a dalšími členy týmu mi byla nabídnuta práce na inerciální jednotce, která sleduje polohu a natočení základny kamerové hlavice, tedy v podstatě polohu a natočení nosného objektu, na kterém je hlavice přimontovaná. První fáze spočívá v nalezení, otestování a proměření menší verze gyra než je momentálně v jednotce použita. Gyro je označení, které se vžilo pro elektronický gyroskop. Důvodem hledání menší verze gyra je především snaha o miniaturizaci samotné jednotky. Vzhledem k tomu, že aktuální veze gyro senzoru má v sobě integrován i magnetometr a akcelerometr, bude nutné najít adekvátní náhrada i za ně. Cíl další fáze je zatím otevřený.

neděle 24. června 2012

Úvodem

Letošní prázdniny budu trávit na letní stáži na Katedře řídící techniky v rámci Oddělení pokročilých algoritmů pro řízení a komunikace (AA4CC) na Elektrotechnické fakultě ČVUT v Praze. Konkrétně budu pracovat ve skupině vyvíjející inerciálně stabilizovanou kamerovou hlavici. Bližší informace o této skupině je možné získat zde. Na tomto blogu budu popisovat průběh této letní stáže.