Sida 1 av 1

Beräkna vinkel från x och y

Postat: 23 september 2017, 22:29:10
av jesse
Jag håller på med ett litet projekt där många vinklar ska beräknas från sensordata.
Sensorer som accelerometrar och liknande ger ju ut data i form av treaxliga värden, x, y och z.

Vill man beräkna en rotationsvinkel utifrån x och y data finns ju en färdig formel:

v = arctan(x/y)

eller kanske

v = arcsin (x / sqr(x^2 + y^2))

(med reservation för att jag kanske har förväxlat x och y)

Detta är ju jobbigt och kräver en massa datakraft, särskilt om det är en applikation i en litet rörlig sak som snabbt ska ha reda på var den är nånstans och vart den är på väg.

Därför har jag hittat på ett sätt att approximera vinkel utifrån x och y data som bara kräver några enstaka beräkningar med de fyra räknesätten.

Ska man snabbt ta reda på ungefärlig vinkel använder man formeln v = x / (x+y) * 90 vilket blir förvånansvärt nära.
Vill man justera detta för ett mer exakt resultat lägger man till följande ekvation:

(V är beräknad vinkel enligt formeln ovan)

Kod: Markera allt

if (V < 45)
{
        int Vc = V-22,5;
        v = V+(Vc*Vc/128-4);
}
else
{
        int Vc = V - (22,5 + 45);
        v = V-(Vc*Vc/128-4);
}
Då kommer man väldigt nära korrekt värde.
vinkel_xy.png
Nu vill jag hitta något lika enkelt sätt att beräkna amplituden (längden) på en tvådimensionell vektor utifrån data (x,y) eller en tredimensionell vektor utifrån data (x, y, z).

Formlerna är enkla : a = sqr(x^2 + y^2) och a = sqr(x^2 + y^2 + z~2), men hur kan man förenkla den och approximera roten ur?

Jag kom att tänka på att sqr(2^n) = 2^(n/2).
Då kan man förenkla genom att kolla på vilken position högsta biten har i talet.

T.ex. beräkna sqr(10000).
MSB = bit 13. Det är en ojämn bit, så vi tar närmaste mindre jämna bit, dvs. bit 12.
sqr(2^12) = 2^6 dvs. 64.
ta bort 12 bitar och vi får talet (10000/4096) = 2,4414

Genom denna förenkling behöver vi bara beräkna roten ur ett tal melan 1 och 4.
Här kan vi t.ex. använda en tabell med 16 värden och interpolera fram ett svar.
Kan gå ruskigt snabbt, tar relativt lite minne och blir nog tillräckligt bra för beräkningar i realtid för farkoster som snabbt måste få reda på acceleration eller liknande.

Jag älskar såna här numeriska metoder. :mrgreen:
(EDIT: stavfel)

Re: Beräkna vinkel från x och y

Postat: 23 september 2017, 23:12:37
av kodar-holger

Re: Beräkna vinkel från x och y

Postat: 23 september 2017, 23:36:59
av lillahuset
Vad har du tänkt att använda för processor?
Har du övervägt att skippa flyttal och använda heltal?

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 00:17:34
av mankan
Vad har du för CPU egentligen? Skippa roten ur på amplituden är det mest uppenbara.

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 03:26:35
av baron3d
För positiva tal, A > B
L = A + B*0.4

Lite korrigering på detta...

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 13:34:38
av jesse
lillahuset skrev:Vad har du tänkt att använda för processor?
Har du övervägt att skippa flyttal och använda heltal?
Jag tänker generellt, alla microcontrollers från 8-bit Attiny till 32 bit.
Jag använder aldrig flyttal. 16 eller 32 bit heltal brukar duga alldeles utmärkt.
Formlerna ovan är inte anpassade för heltal eftersom man i så fall först måste veta saker som max amplitud och upplösning, så det beror ju på applikationen.
(Jag ser nu att jag skrivit 'int' i kodexemplet. Det funkar kanske inte så bra ihop med tal som 22,5 (dessutom med kommatecken! ), men det är tanken som räknas :)

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 14:54:08
av lillahuset
Om du läser kodar-holgers länkar kanske du tänker lite mindre generellt:
But the packages unfortunately isolate us from these grimy computational details, which can lead to significant performance penalties. A fast desktop with built-in floating point hardware can return a cosine in a few tens of nanoseconds. But the same function often takes many milliseconds on embedded systems.

Or even longer. Everyone recognizes that to do a double-precision trig function (as required by the C standard) would take about a week on an 8051, so most of those compilers cheat and return shorter floats.

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 15:17:39
av lillahuset
Kom just att tänka på att jag någonstans har en artikel från BYTE från 70-talet (?) om CORDIC som var rätt intressant. Passar bra för processorer utan multiplikator.
På nätet finns det en del artiklar om det. En av de första applikationerna i "modern tid" verkar ha varit att förbättra precisionen när man genom bombning jävlas med folk på marken. :(

https://en.wikipedia.org/wiki/CORDIC
https://dspguru.com/dsp/faqs/cordic/
https://duckduckgo.com/?q=cordic+algorithm&t=lm&ia=web

Re: Beräkna vinkel från x och y

Postat: 24 september 2017, 20:16:51
av Nerre
Har man klen datorkraft så är väl det normala att man använder tabeller för att få lämpliga approximationer. Man kan öka "upplösningen" genom att interpolera mellan två värden i tabellen med linjär interpolering.

Det bästa är antagligen att försöka eliminera steget att gå via vinkel. Vill man verkligen ha ut vinkeln så går det såklart inte, men om vinkeln ändå bara ska användas som ett mellansteg så kanske man kan förenkla bort den. Ta fram alla formler som behövs och förenkla dem algebraiskt bara.

Re: Beräkna vinkel från x och y

Postat: 25 september 2017, 18:48:45
av 4kTRB
För arctan finns några tips för de som håller på med DSP.

dsp TIPS&TRICKS
http://www-labs.iro.umontreal.ca/~migno ... nction.pdf

Re: Beräkna vinkel från x och y

Postat: 25 september 2017, 18:59:57
av lillahuset
Dessa approximationer är nog ännu intressantare för användare av "vanliga" processorer. Biblioteken för DSP brukar vara ganska väl optimerade. Men det är ju alltid intressant att lära sig mer. :)