# Algorithm/Chords
V této sekci se definují tětivy a souřadnice referenčního bodu vozíku. Tětivy jsou dále používány např. procesory [Chord-Versine3][], [Chord-Multiply][] nebo [Corrugation-D1][]..[Corrugation-D4]
## Referenční bod zařízení (vozíku, měřicího vozu, měřicí soustavy)
Každé měřicí zařízení musí mít v podélné souřadnici (ve směru jízdy po kolejích) definovaný tzv. **referenční bod**. Lokalizace měření a tedy i odměřených dat je dána právě polohou referenčního bodu během měření.
**Referenční bod** se typicky volí do zvláštního místa na vozíku, např. do osy kolečka tětivy na vozících Krab. V principu ale může být zvolen kdekoliv. Referenční bod zařízení bychom měli chápat velmi obecně, jako domluvené místo (v 1D prostoru), které souhlasí (kryje se) s místem na trati, kde chceme mít počátek dráhové souřadnice měřených signálů. Reference vůbec nemusí ležet na daném vozíku: představme si, že spřáhneme dva vozíky (např. Krab je vzadu a T-vozík vpředu). Na Krabovi je GPK, na T-vozíku kamery profilů kolejnic. Referenci dáme do profilů (třeba proto, že se nám líbí, že lasery kamer hezky ukazují místo na trati, od kterého chceme začít měřit.)
## Umístění snímačů na voze (topologie)
Měřicí vůz je obvykle osazen řadou snímačů, které snímají veličiny z různé podélné souřadnice vozíku. Jejich podélné umístění na voze vztahujeme k tzv. **referenčnímu bodu vozu**/vozíku. Ten je pro každé měřicí zařízení unikátní.
**Poznámka: Fyzické umístění snímače vs. místo snímané veličiny** *Nejde o fyzické umístění snímačů, ale o místo, ke kterému se vztahuje signál, který měří. To není stejné: Například inklinometr na Krabovi může být namontovaný kdekoli na rámu a poleze z něho ve všech případech stejný signál, který se z geometrických důvodů vztahuje ke středu vozíku. Další příklad je gyro na MMD Finsko: IMU může být kdekoli na trojúhelníkovém podvozku a na výsledku to vůbec nepoznáme. Ještě ilustrativnější je to u inklinometru MMD Finsko: ten je v černé krabici poblíž středu vozíku, kam jsme umístili referenci, ale jeho signál se vztahuje k přední ose vozíku, protože kopíruje její náklon. Proto jsme mu dali Displacement=-1.25 m*
Abychom se vyhnuli ad hoc definicím parametrů měřicích algoritmů (přenosových funkcí, symetrie, orientace, umístění tětiv-nejen 3-bodových, kompenzace zpoždění jejich signálů…), vznikla představa, že
- umístění snímačů se zakótuje na 2D obrázku vozu v systému 1D kót, kóty jednotlivých bodů se zapíší v `cfg_das` do sekce `Algorithm/Constants`
- navazující definice tětiv, [Displacement](#displacement)ů, a procesorů vyžadujících znalost polohy těchto bodů se budou odkazovat na tyto body.
Ne všude už to je tak implementované, ale postupně k tomu směřujeme, viz issue [#400](https://gitlab.com/kzv/doc/-/issues/400).
K tomu účelu je vhodné zavést pojem *počátku souřadnicového systému (počátek kót)*. Tento počátek lze zvolit libovolně, protože vše navazující musí být k jeho volbě invariantní. Důležitá je orientace souřadnicového systému. Hodnoty kót bodů na vozíku rostou ve směru správného postavení. Z orientace plynou znaménka kót, pojmy přední/zadní atd. Dobrý nápad je malovat 2D obrázek tak, aby orientace kót byla kladná směrem doprava. Za tohoto předpokladu je předek vozu na pravé straně obrázku.
Nejdůležitější souřadnice je poloha *referenčního bodu vozu* `ReferencePoint`. Tuto hodnotu je v `cfg_das` zapotřebí definovat vždy, když se dále vyskytuje nějaká definice tětiv(y), nebo pokud chceme tuto hodnotu použít pro výpočet [Displacement](#displacement)u některého snímače relativně k *referenčnímu bodu*.
Pokud se *počátek kót* zvolí tak, že se kryje s polohou *referenčního bodu*, je kóta *referenčního bodu* nulová: `ReferencePoint = 0`. Nevýhodou takové volby je ovšem např. to, že kóty zadních snímačů (snímačů ve směru nesprávného postavení) mají záporné hodnoty.
## Definice měřicích tětiv
Vůz může být vybavený řadou obecně umístěných měřicích tětiv. Každá tětiva je v `cfg_das` konfigurovaná
1. kótami tří bodů `a`, `b`, `c` v sekci `Algorithm/Constants`
2. definicí samotné tětivy odkazem na tyto tři body v sekci `Algorithm/Chords`. `a` je kóta zadního, `b` středního a `c` předního bodu. Zadní/střední/přední je dáno orientací systému souřadnic (kót), kóty rostou ve směru správného postavení. Pokud se měří v opačném postavení, příslušné procesory si tětivu interně otočí.
Příklad definice dvou tětiv `Corrugation.DirRS_Left` a `Corrugation.DirRL_Left` pro výpočet vlnkovitosti:
```xml
<CFGDASvNET>
<Algorithm Version="1.0.0">
<Constants>
<!-- Počátek kót jsme zvolili 2000 mm nalevo od referenčního bodu,
jeho kóta na výkresu je tedy +2000 mm. Tu sem uvedeme. -->
<Constant Name="ReferencePoint" Unit="mm">2000</Constant>
<!-- Snímače vlnkovitosti jsou nalevo od referenčního bodu -->
<Constant Name="PointR0" Unit="mm">1688</Constant>
<Constant Name="PointR1" Unit="mm">1767</Constant>
<Constant Name="PointR2" Unit="mm">1802</Constant>
<Constant Name="PointR3" Unit="mm">1828</Constant>
</Constants>
<Chords>
<Chord Name="Corrugation.DirRS_Left" Pa="PointR1" Pb="PointR2" Pc="PointR3"/>
<Chord Name="Corrugation.DirRL_Left" Pa="PointR0" Pb="PointR1" Pc="PointR3"/>
</Chords>
</Algorithm>
</CFGDASvNET>
```

V tomto případě si např. procesor [Corrugation-D1][] z definice tětivy spočte
- `c1 = b - a` ... délka zadního úseku tětivy
- `c2 = c - b` ... délka předního úseku tětivy
- `Delay = ReferencePoint - b` ... posun tětivy vzhledem k *referenčnímu bodu*
které se dále použijí ve výpočtu přenosové funkce procesoru.
## *Delay* tětivy - její posun vůči *referenčnímu bodu*, a vztah k [Displacement](#displacement)u snímačů {#chord-delay}
Každá tětiva může být obecně posunutá mimo *referenční bod vozíku*. Toto posunutí se nazývá *Delay* a má hodnotu `Delay = ReferencePoint - b`, je to tedy posunutí prostředního bodu tětivy `b` vůči *referenčnímu bodu vozíku*.
Výsledné signály počítané a ukládané z tětivy chceme mít vztažené k *referenčnímu bodu vozíku*, potřebujeme tedy *Delay* nějak kompenzovat. V principu jsou dvě cesty, jak toho docílit, a každá má své opodstatnění.
Před popisem obou cest je důležité vysvětlit, jak spolu interagují [Displacement](#displacement) snímačů a *Delay* tětiv. [Displacement](#displacement) je podrobně zdokumentován v [samostatné kapitole](#displacement). Nyní je důležité vědět, že
- snímače se vždy vyčítají v časové doméně bez použití [Displacement](#displacement)u. Ten se aplikuje až v resampleru z času do dráhy - převzorkované dráhové vzorky už jsou podle příslušného [Displacement](#displacement)u posunuté do *referenčního bodu*.
- když použiji např. procesor [Chord-Versine3][] počítající vzepětí na tříbodové tětivě z *dráhových* vzorků tří snímačů, které mají definovaný nějaký (stejný) [Displacement](#displacement), výsledné vzepětí bude také o tento [Displacement](#displacement) posunuté, zde je to zřejmé.
- Když použiji ten samý procesor [Chord-Versine3][] na vstupy v *časové* doméně, které mají stejný nenulový [Displacement](#displacement), vzepětí se sice bude počítat z neposunutých vzorků (v čase se žádné posouvání neděje), ale výstupnímu signálu bude přiřazen ten samý [Displacement](#displacement) jako je na vstupech (vlastnost [Synchronních procesorů](#processor-synchronicity-synchronous)), a při převzorkování do dráhy tedy bude vzepětí také o tento [Displacement](#displacement) posunuto.
- Není možné (selže při kontrole při startu programu) omylem ani záměrně na vstup [Chord-Versine3][] přivést *časové* snímače s různým [Displacement](#displacement)em (vlastnost [Synchronních procesorů](#processor-synchronicity-synchronous))
Vyzbrojeni těmito znalostmi můžeme popsat dvě cesty, jak kompenzovat tětivu posunutou mimo *referenční bod*.
### 1. Kompenzace *Delay* v dráhové doméně
Tradiční cesta, používaná nyní např. u výpočtu vlnkovitosti, je následující:
1. nejprve se spočítá vzepětí pomocí procesoru [Chord-Versine3][], který *Delay* ignoruje. Snímače vlnkovitosti mají nulový [Displacement](#displacement). V principu není zásadní rozdíl mezi tím, jestli se vzepětí počítá v čase a poté převzorkuje do dráhy, nebo jestli se počítá rovnou v dráze z převzorkovaných dráhových vstupů. První možnost pravděpodobně poskytne o něco přesnější výsledky v případě, že délka tětivy není soudělná se vzorkovacím krokem.
2. na vzepětí v dráze navazuje procesor [Corrugation-D1][], který teprve v dráhové doméně *Delay* kompenzuje pomocí FFT přenosové funkce.
*Poznámka*: Zde je mj. vidět, že záleží na každém procesoru, jakou informaci z definice tětivy použije. Některý procesor *Delay* použije, některý ho ignoruje. Způsob použití tětivy je zdokumentován u každého procesoru zvlášť.
### 2. Kompenzace *Delay* pomocí [Displacement](#displacement)u při převzorkování do dráhy.
*Tato cesta se zatím nepoužívala, a v některých případech nemusí jít použít, dokud nebude naimplementována možnost aplikace [Displacement](#displacement)-u na libovolný signál v časové doméně, viz issue [#399](https://gitlab.com/kzv/doc/-/issues/399). Přesto myslím, že do budoucna může jít v některých případech o užitečný způsob.*
Představme si, že chceme počítat výšku `VK` z tětivy tvorené třemi 3D kamerami (Wenglory), a tato tětiva má nenulový *Delay* (prostřední bod tětivy je tedy mimo *referenční bod vozu*)
Pokud bychom k tomu chtěli přistoupit podobně jako v případě cesty 1., kamery bychom pomocí [Displacement](#displacement)u nijak neposouvali, spočítali bychom si z poloh kolejnice podle jednotlivých kamer vzepětí (`VK`), a to poté posunuli v dráze pomocí FFT.
Cesta 2 je však u *všech* kamer nastavit takový (stejný) [Displacement](#displacement), aby se prostřední kamera posunula do *referenčního bodu*, tedy
`Displacement="GC_PointRailProfileMiddle - GC_ReferencePoint"`
Tím se celé tětivové měření posune do *referenčního bodu*. Fungovat to bude ať už se vzepětí počítá v čase z časových vzorků (protože na spočtené časové vzepětí se aplikuje stejný [Displacement](#displacement) jako je na vstupech, vzepětí se pak při převzorkování do dráhy posune), nebo v dráze z dráhových vzorků (protože dráhové vstupy už mají [Displacement](#displacement) aplikovaný z resampleru). Počítání v čase možná bude o trochu přesnější, pokud není délka tětivy soudělná se vzorkovacím krokem.
Výhodou tohoto přístupu je, že nepotřebujeme žádné posouvací FFT, a tedy máme k dispozici výsledný směr téměř okamžitě, což může být praktické např. pro vykreslování grafů během měření.
## Interakce zpoždění (*Delay*) tětivy s posunutím ([Displacement](#displacement)) snímačů
**POZOR na posunutí [Displacement](#displacement)em i *Delay*em zároveň!** Je třeba být opatrný, pokud mám na snímačích nenulový [Displacement](#displacement), neměl bych si zařazovat do výpočtového řetězu procesor, který kompenzuje posunutí tětivy, např. [Corrugation-D1][], aby se mi hodnoty neposouvaly dvakrát!
**POZOR na souběžné použití snímačů pro tětivu a jiné měření!** Jednotlivé body tětiv jsou realizované snímači, které mohou být víceúčelové. Například 3D kamera umístěná mimo *referenční bod vozu* může měřit
1. Profil/ojetí/úklon kolejnice. Ukládání profilu, ojetí atp. chceme posunout do *referenčního bodu*, k tomu slouží atribut `Displacement` u příslušného snímače (v tomto případě kamery)
2. Výšku/směr kolejnice v daném bodě nějaké tětivy. U tětivových výpočtů potřebujeme přinejmenším krajní snímače vyčítat navzájem odlehlé v jednotlivých bodech tětivy, tedy **ne**posunuté do *referenčního bodu*.
Pokud se tedy taková situace vícerého využití jednoho snímače vyskytuje, je třeba jeho hodnotu mít několikrát s různým [Displacement](#displacement)em. To je aktuálně rozdělané, viz issue [#399](https://gitlab.com/kzv/doc/-/issues/399).