Minsta vinkel, vänster/höger?

Elektronik- och mekanikrelaterad mjukvara/litteratur. (T.ex schema-CAD, simulering, böcker, manualer mm. OS-problem hör inte hit!)
larsson
Inlägg: 188
Blev medlem: 9 juni 2007, 16:49:21
Ort: Göteborg

Minsta vinkel, vänster/höger?

Inlägg av larsson »

Jag programmerar just nu lite (i C) en snutt där jag behöver ta reda på skillnaden mellan nosens riktning och kompassriktning till ett objekt. Säg att jag står vänd rakt österut, dvs i 90°. I kompassriktning 80° ser jag det observerade objektet, dvs det ligger "tio grader till vänster". Inga problem här, 80-90 = -10.

Om jag istället kikar i riktning 5° och jag har ett objekt 10 grader till vänster så är dess bäring 355°. Nu är det inte så kul längre, 355-10 = 345. Samma elände även om det observerade objektet ligger till höger om mig, problemet ligger förstås i att man "passerar norr" på vägen. Det finns lite trick med att vända på tecknen, räkna kvadranter, och diverse tips jag hittat på nätet. För närvarande löser jag det med en härva if-satser, men jag anar att det finns en elegantare lösning/formel?

Kod: Markera allt

double relativ_baring(double nosriktn, double objektbaring)
{
     magic code here ;
     return answer;
}
Jag vill göra en funktion som ger svaret -10 oavsett om parametrarna är {90,80} eller {5,355} , eller förstås +10 om observatör och objekt "swappas". Negativa svar betyder vänster och positiva höger.

Hur löser man detta på ett mer sofistikerat sätt än med if-satser?
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Minsta vinkel, vänster/höger?

Inlägg av blueint »

Kanske ett sätt är att omdefiniera vinkeln från [0,360] till [-180,+180] ..?
Och sedan använda subtraktion på något lämpligt sätt.
Alternativt omdefiniera "nollpunkten" på något sätt.

Solklar och tydlig definition av ingående värden kan också vara bra.
larsson
Inlägg: 188
Blev medlem: 9 juni 2007, 16:49:21
Ort: Göteborg

Re: Minsta vinkel, vänster/höger?

Inlägg av larsson »

Ja, genom att ha nollan högst upp som en nordpol och sedan två "halvklot" som räknar åt varsitt håll så löser jag räkneproblemen när jag passerar norr. Men då är problemet istället flyttat till "sydpolen" där det blir ett hopp när +180° möter -180°.

Att skriva en snygg funktion (dvs utan if-satser eller loopar) som tar två godtyckliga vinklar och svarar med ± vinkelskillnad (närmsta vägen) var mycket svårare än jag kunde ana, problemet såg så enkelt ut...

If it ain't broken, don't fix it, så jag behåller nog mitt if-sats-härke.
limpan4all
Inlägg: 8444
Blev medlem: 15 april 2006, 18:57:29
Ort: Typ Nyköping

Re: Minsta vinkel, vänster/höger?

Inlägg av limpan4all »

Om svaret är mindre än 0, addera 360, sen teckenbyt ger väl det du önskar
larsson
Inlägg: 188
Blev medlem: 9 juni 2007, 16:49:21
Ort: Göteborg

Re: Minsta vinkel, vänster/höger?

Inlägg av larsson »

Ja det fungerar i exemplet ovan:
5-355 = -350, addera 360 och teckenbyt ==> -10°

Men byt plats på observatören och objektet så faller det:
355-5 = 350. (större än noll, så addera inte 360), teckenbyt ==> -350°

En if-sats till löser förstås problemet :-)
limpan4all
Inlägg: 8444
Blev medlem: 15 april 2006, 18:57:29
Ort: Typ Nyköping

Re: Minsta vinkel, vänster/höger?

Inlägg av limpan4all »

Gör ett hopp förbi rutinen om >0 så behövs inget mer.
Maalobs
Inlägg: 1304
Blev medlem: 3 februari 2005, 14:35:15
Ort: Stockholm

Re: Minsta vinkel, vänster/höger?

Inlägg av Maalobs »

En if-sats, ja...
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Minsta vinkel, vänster/höger?

Inlägg av blueint »

Kanske om problemet delas upp i fyra delproblem. Dvs 0-180° samt >180-360° för kompassriktning. Samt 0-180° och >180-360° för nosriktning. Det ger fyra fall, vilket borde vara hanterligt?
Det blir if satser, men kanske mer strukturerat?
Ev får ==0 eller ==180° bli två extra fall.

Glöm dock inte att man kan definiera gränser som mindre än 180°. Och lika med 180° och större.
Nerre
Inlägg: 27195
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Minsta vinkel, vänster/höger?

Inlägg av Nerre »

I exemplet så var A 5 grader och B 355 grader.

Om vi gör så att alla värden över 180 drar vi bort 360 från.

355 - 360 = - 5 grader.

5 - (-)5 = 10 grader är vinkeln mellan dem.

Å andra sidan vet vi redan att vi ska subtrahera. Det blir ju

5 - (355 - 360) = 5 - 355 + 360. Det är då kanske enklare att addera 360 till alla värden som är mindre än 180.
larsson
Inlägg: 188
Blev medlem: 9 juni 2007, 16:49:21
Ort: Göteborg

Re: Minsta vinkel, vänster/höger?

Inlägg av larsson »

> addera 360 till alla värden som är mindre än 180.

Fungerar ju på exempeltalet. Men om den ena vinkeln är
175° och den andra 185° så blir det pannkaka. Det behövs
en if-sats till. Så här ser koden ut idag, det är en snutt jag hittade
på nätet för ett par veckor sedan:

Kod: Markera allt

offset = bearing - heading ;

if (offset > 180)
        offset -= 360;

if (offset < -180)
        offset += 360;
Alltså en subtraktion och två if-satser som kan ge upphov till
ytterligare subtraktion eller addition. Fungerar bra med de tal jag
testat. Men det skulle varit mer elegant med nåt i den här
stilen:

angular_diff = sin(angle1) * sqrt(angle2) / arctan2(angle1+angle2 - whatever(pi) ;

Nån sån oneliner verkar inte stå att finna. Allltnog, det funkar som det är och
jag är i grunden en förnöjsam man!
Nerre
Inlägg: 27195
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Minsta vinkel, vänster/höger?

Inlägg av Nerre »

Trignometriska funktioner drar ju massor med mer kraft än några IF-satser.
Användarvisningsbild
ToB
Inlägg: 678
Blev medlem: 22 februari 2004, 10:32:58
Skype: tobias_bjork
Ort: Sollentuna

Re: Minsta vinkel, vänster/höger?

Inlägg av ToB »

En lösning är ju (a ? b : c)
Det blir ju kanske snyggare och kortare kod men jag vet inte hur det påverkar prestandan.

Kod: Markera allt

#include <stdio.h>

int main(){
  int nos, obj, diff;

  for (nos=0; nos<360; nos+=45){
    for (obj=0; obj<360; obj+=45){
      diff = obj - nos;
      diff = (diff > 180) ? diff-360 : diff;
      printf("nos = %3d, objekt = %3d, diff = %4d\n",nos ,obj, diff);
    }
  }
  return 0;
}
Del av utskriften från körningen.

Kod: Markera allt

nos =   0, objekt =   0, diff =    0
nos =   0, objekt =  45, diff =   45
nos =   0, objekt =  90, diff =   90
nos =   0, objekt = 135, diff =  135
nos =   0, objekt = 180, diff =  180
nos =   0, objekt = 225, diff = -135
nos =   0, objekt = 270, diff =  -90
nos =   0, objekt = 315, diff =  -45
nos =  45, objekt =   0, diff =  -45
nos =  45, objekt =  45, diff =    0
nos =  45, objekt =  90, diff =   45
nos =  45, objekt = 135, diff =   90
nos =  45, objekt = 180, diff =  135
nos =  45, objekt = 225, diff =  180
nos =  45, objekt = 270, diff = -135
nos =  45, objekt = 315, diff =  -90
...

EDIT:
Kom på att koden ovan inte fungerar riktigt när nosens riktning är större än 180 grader. Det kräver i så fall en sats till.
Principen som jag ville visa borde ändå framgå.

EDIT 2:
Inser just att detta är egentligen samma sak som larsson föreslog.
haklu
Inlägg: 36
Blev medlem: 7 augusti 2008, 16:32:33
Ort: Örebro

Re: Minsta vinkel, vänster/höger?

Inlägg av haklu »

Om man vet att argumenten alltid håller sig inom 0 till 360 kan man köra med:

Kod: Markera allt

#include <math.h>

double relativ_baring(double nosriktn, double objektbaring)
{
    return fmod(objektbaring - nosriktn + 540.0, 360.0) - 180.0;
}
Är man osäker på argumenten bör man ta det säkra före det osäkra:

Kod: Markera allt

#include <math.h>

double relativ_baring(double nosriktn, double objektbaring)
{
    double diff = objektbaring - nosriktn + 180.0;
    while (diff < 0)
    {
        diff += 360.0;
    }
    return fmod(diff, 360.0) - 180.0;
}
Användarvisningsbild
Icecap
Inlägg: 26632
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Minsta vinkel, vänster/höger?

Inlägg av Icecap »

Och att börja blanda in flytande komma-tal är då verkligen att sänka prestanda.
Användarvisningsbild
JonasJ
Inlägg: 653
Blev medlem: 11 september 2007, 16:02:26
Ort: Kinna
Kontakt:

Re: Minsta vinkel, vänster/höger?

Inlägg av JonasJ »

Är det en modern PC programmet körs på lär den knappast ha några problem med varken trigonometriska beräkningar eller flyttal....
Skriv svar