VectorLab šipky, které umí počítat

Tohle je statická kopie kapitoly pro vyhledávače. Interaktivní verze má animované obrázky, kontrolní otázky a tlačítka, která příklad načtou do kalkulačky.

Gram-Schmidt: jak se z hrubých směrů udělá rámec

Kapitola 8 skončila u toho, že ortonormální báze je pohodlná: souřadnice v ní vypadnou z pouhého skalárního součinu a čísla nerostou do nesmyslných hodnot. Zbývá otázka, jak se k takové bázi dostat, když člověk má jenom pár hrubých směrů — což je v praxi vždycky.

Odpověď je jeden opakovaný pohyb, který už znáte z kapitoly 5: odečti průmět.

xyabq₁q₂úhel a, b na vstupu50°w · q₁0,000000q₁ · q₂ (musí být 0)0,000000|q₁| = 1,000 , |q₂| = 1,000
  1. a, b — ani kolmé, ani jednotkové

    Vstup: dva směry, které někdo naměřil nebo odhadl. Chceme z nich udělat pravoúhlý rámec — a přitom co nejvíc respektovat, co bylo zadané.

  2. q₁ = a / |a|

    První směr se jenom znormalizuje a jinak se nechá být. To je vlastnost, na které v praxi hodně záleží: když je a osa, kolem které se opravdu otáčí, nesmí se pohnout.

  3. proj = (b·q₁)q₁ → délka 1,286

    Druhý vektor se rozloží podle kapitoly 5. Ta část, která míří podél q₁, je to, co b a a mají společné — a právě to musí pryč.

  4. w = b proj

    Zbytek. Celý Gram-Schmidt není nic jiného než tohle, jen opakovaně: vezmi další vektor, odečti z něj všechno, co už umí předchozí, a co zbude, je nový směr.

  5. w·q₁ = 0,000000

    Nemusí se to věřit — vynásobí se to a vyjde nula. To není náhoda: odečetli jsme právě tolik, aby nezbylo nic ve směru q₁.

  6. q₂ = w / |w| — rámec je hotový

    Zbývá zkrátit na jedničku. Ve třech rozměrech se stejný postup zopakuje s třetím vektorem, jen se odečítají dva průměty. A poslední směr se dá vzít i zkratkou: q₃ = q₁ × q₂.

Šest kroků a jenom jedna myšlenka: z každého dalšího vektoru odečti všechno, co už umí ty předchozí. Co zbude, je nový směr.
q₁ = a/|a|     w = b − (b·q₁)q₁     q₂ = w/|w|Gram-Schmidt, dva vektory

Ve třech rozměrech se totéž zopakuje potřetí, jen se odečítají dva průměty. A poslední směr se dá vzít zkratkou: q₃ = q₁ × q₂ je z definice kolmý na oba a rovnou jednotkový.

První směr zůstává — a proto se to používá

Ta nesymetrie není vada, je to celý smysl. V robotice se tímhle staví rámec nástroje: osa z je směr, kterým chapadlo opravdu míří a se kterým se hýbat nesmí; x je jen hrubé přání („zhruba podél stolu“), které se srovná do kolmého směru.

xyznápovědazxykontrola pravotočivostidet = 1,00000kolmost x·y, y·z, x·z0,0000 0,0000 0,0000z se dodrží PŘESNĚnápověda se jen narovná
x = (0,946, −0,093, −0,310)  ·  y = (0,000, 0,958, −0,287)  ·  z = (0,324, 0,272, 0,906)
Nakloň z kamkoli. Rámec se přizpůsobí, ale z se nehne — mění se jen nápověda. Otoč nápovědu tak, aby mířila skoro rovnoběžně s z, a přečti si, co se stane.

Nápověda rovnoběžná s osou je ta výjimka, na kterou se musí myslet. Když nápověda míří (skoro) stejně jako z, po odečtení průmětu nezbude nic — a normalizovat něco, co je jen zaokrouhlovací chyba, znamená dostat naprosto náhodný směr délky 1. Solver v takovém případě sáhne po náhradním kolmém směru, který si vyrobí sám (anyPerpendicular), a testy ověřují, že vyjde kolmý i pro vstupy ležící přesně na osách — což je zrovna to místo, kde naivní „vynásob to s x̂“ selže.

Vyhodit, ne znormalizovat

Když je vstupní vektor lineárně závislý na předchozích, zbytek po odečtení průmětů je nula (až na zaokrouhlení). Takový vektor se musí zahodit, ne znormalizovat. Znormalizovaný zbytek délky 10⁻¹⁷ je čistý šum, který se tváří jako plnohodnotný směr — a je to nejčastější způsob, jak tahle rutina tiše selže. Kalkulačka v téhle labce takový vektor vypíše jako vyhozený a řekne proč.

Kde se s tím ještě potkáte

  • QR rozklad je Gram-Schmidt zapsaný v maticích: Q jsou ty vzniklé kolmé směry, R jsou odečtené průměty. Používá ho každý slušný řešič nejmenších čtverců — viz OptiLab.
  • Ortogonalizace rotační matice: po tisících násobení se matice „rozjede“ a přestane být ortonormální. Gram-Schmidt ji srovná zpátky. Viz RotLab.
  • Kalibrace kamery hledá rámec z naměřených, tedy nepřesných směrů — a musí skončit s pravoúhlým. Viz VisionLab.

Numerická poznámka. Klasický Gram-Schmidt počítá všechny průměty proti původním vektorům a při skoro rovnoběžných vstupech ztrácí kolmost. Modifikovaná verze odečítá postupně proti už hotovým směrům a je výrazně stabilnější. Solver v téhle labce dělá modifikovanou variantu a navíc druhý průchod (reortogonalizace), což je standardní recept, jak držet kolmost na úrovni strojové přesnosti.

Vzorce v této kapitole

q₁ — první směr — jen normalizovaný
q₁ = a / |a| [—] kap. 9
q₂ — druhý směr — po odečtení průmětu
w = b − (b·q₁)q₁, q₂ = w / |w| [—] kap. 9
q₃ — třetí směr zkratkou
q₃ = q₁ × q₂ [—] kap. 6 + 9