Shop OBEX P1 Docs P2 Docs Learn Events
Getting angle value from sin/cos — Parallax Forums

Getting angle value from sin/cos

ErNaErNa Posts: 1,752
edited 2009-09-18 08:35 in Propeller 1
Having sin and cos as an input, I have to determine the appropriate angle value. Is there a simple way to do that? I now flip to the first octant and determine the angle by successive approximation searching the closest entry in the sine table?

PRI Angle (sinVal, cosVal) | octant, i, j, Phi, dPhi  ' There are 8 octants. Only 0-45° angles are determined, first transform to octant 0
                                     ' sin, cos   |sin| |cos|
                                     ' =>0   =>0       <       0
                                     ' =>0   =>0      =>       1
                                     ' =>0    <0      =>       2
                                     ' =>0    <0       <       3
                                     '  <0   =>0       <       4
                                     '  <0   =>0      =>       5
                                     '  <0    <0      =>       6
                                     '  <0    <0       <       7
                                     ' 
    octant  := 0     ' initialize variables  (may be redundant)
    i       := 0
    Phi     := 0
    dPhi    := 512
    
    if sinVal < 0        ' > 180°, invert sign to transform to <180°
      octant := 4
      sinVal *= -1
      cosVal *= -1
    if cosVal < 0        ' > 90°, transform to <90°
      octant += 2
      i      := sinVal
      sinVal := -cosVal
      cosVal := i
    if sinVal > cosVal   ' > 45°, transform to < 45°
      i      := sinVal
      sinVal := cosVal
      cosVal := i
      i      := -1
    ' now we are in the first octant, search angle by successive approximation via sinus table  (0-2047)
    
    Phi := dPhi

    repeat while dPhi > 0
      dPhi := dPhi~> 1
      j := sinVal - word[noparse][[/noparse]$E000 + Phi<<1]
      if j > 0
        j :=+1
      if j < 0
        j :=-1
  
      case  j ' search entry in table 
         0:   quit         ' found
        +1:                 ' sinVal was greater       
             Phi += dPhi
        -1:                 ' sinVal was less
             Phi -= dPhi

    if i < 0
      Phi := 2048 -Phi         
    Phi += octant << 10  
    return Phi    


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
Hello Rest Of The World
Hello Debris
Install a propeller and blow them away wink.gif

Post Edited (ErNa) : 9/13/2009 2:25:46 PM GMT

Comments

  • StefanL38StefanL38 Posts: 2,292
    edited 2009-09-13 13:44
    Hello ErNa,

    I did not analyse your code in detail.

    How about using the "take the half"-method or maybe I can describe it as take the middle of the upper/lower-half next time ?

    f.e. your your-Sin-val is 0.0.573576436 (corresponds with angle 35°)

    start at the middle of the first quadrant 90° / 2 = 45° sin(45°)=0.707106781

    compare your-Sin-val=0.573576436 with 0.707106781

    your-Sin-val is smaller than 0.707106781 so next value to compare against is

    so next compare-value is (0 + 0.707106781) / 2 = 0.35355339

    compare your-Sin-val=0.573576436 with compare-value 0.35355339

    your-Sin-val is bigger than compare-value

    next compare-value is (0.707106781 + 0.35355339) / 2 = 0.530330085

    compare your-Sin-val=0.573576436 with 0.530330085

    your-Sin-val is bigger than compare-value

    so next compare-value is (0.707106781 + 0.530330085) / 2 = 0.618718433

    compare your-Sin-val=0.573576436 with 0.618718433

    compare your-Sin-val is smaller than compare-value

    so next compare-value is (0.618718433 + 0.530330085) / 2 = 0.574524259

    compare your-Sin-val=0.573576436 with 0.574524259

    so after only 5 iterations the difference went down on 0.000947823
    or in ° ASin(0.573576436) -ASin(0.574524259) = -0.066322592

    this is the basic priniciple. With the sine-table you have to calculate the next tableindex of the value you want to compare with
    maybe your algorithm is already doing that. I didn't analysed it in detail

    So if you search through the first quadrat and the values are 0-2047
    first tableindex of value to compare against is (0 + 2047)/ 2 = 1023

    if your-value is bigger than compare-value so next tableindex is (1023 + 2047) / 2 = 1535 (1023, 2047) upper half of the interval

    if your-value is smaller than compare-value so next tableindex is (0 + 1023) / 2 = 511 (0, 1023) lowwer half of the interval

    you always have the compare-value from the last comparison and the actual compare-value

    etc. etc.

    maybe in a char-grafic it is better to understand

                                             first compare-value
    x<-lower half interval-------------------------->x<--------------upper half interval--------------->
             10        20        30        40        50        60        70        80        90        100
    1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
    
    
    
    your value is 32
    
    first compare-value (0 + 100) = 50
    
    32 is smaller than 50 so next compare-value is (0 + 50) / 2 = 25
    
                                             first compare-value
                                                     x
    <-lower half interval-->x<-upper half intervak-->x
                            x
                      2nd compare-value              x
             10        20   x    30        40        50        60        70        80        90        100
    1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
    
    
    32 is bigger than 25 so next compare-value is (25 + 50) / 2 = 37 
    
    
    
    
                                             first compare-value
                                                     x
                                                     x
                      2nd compare-value              x
                            x                        x
                            x<-L->x<-U->x            x
                            x     3rd compare-value  x
             10        20   x    30     x  40        50        60        70        80        90        100
    1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
    
    32 is smaller than 37 so next compare-value is (25 + 37) / 2 = 31
    
    and after just 3 iterations we are really close the the right value 
    
    



    best regards

    Stefan
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-09-13 14:08
    ErNa,

    You might try this thread to use the 'binary successive approximation' method that StefanL38 describes.

    http://forums.parallax.com/forums/default.aspx?f=25&m=188818

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • ErNaErNa Posts: 1,752
    edited 2009-09-13 14:34
    Reinventing the wheel may be simpler than finding the right one.
    Indeed, I use a successive approximation as I wrote in the code.
    The program has two parts: first, limiting the search space to the first octant. The sine function having a starting slope of 1, going down to zero a 90° is sufficiently increasing until 45° are reached. So I limit the search to the sinus table.
    Then I do succ app by starting in the middle of the table and going forward or backward if I not already have a hit.
    So, I have to compare two sources to the mine, what comes out to be some burden. wink.gif
    But I saw, i wrote "successive" "succesive" and that may have been critical wink.gif

    Thanks, ErNa

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
    Hello Rest Of The World
    Hello Debris
    Install a propeller and blow them away wink.gif
  • MGreimMGreim Posts: 114
    edited 2009-09-13 15:45
    Hi,

    in a more general way, i would say you are looking for an atan2 algorithm. You may google for it or search here in the forum.
    The most common way to calculate it is the so called Cordic algorithm.

    I have ported it into Spin this morning, and i just try to translate it in Propeller ASM.
    If its running i will post the code here

    Markus
  • TimmooreTimmoore Posts: 1,031
    edited 2009-09-13 16:33
    You could look at the atan2 in http://obex.parallax.com/objects/501/ I use this and it gives accurate answers.
  • ErNaErNa Posts: 1,752
    edited 2009-09-13 17:29
    Thanks to all. Important to know where to find or to find someone who knows! You all are knowing angles! And with atan2 we know the angle wink.gif We will see, what comes out.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
    Hello Rest Of The World
    Hello Debris
    Install a propeller and blow them away wink.gif
  • Peter NachtweyPeter Nachtwey Posts: 9
    edited 2009-09-13 18:25
    I would use Newton's method. This covergers very quickly around 0.
    x(n+1)=x(n)-f(x(n))/f`(x(n))
    In this case
    f(x)=sin(x)-A // A is the number your are trying to find the asin() of
    f`(x)=cos(x)
    make a good gues for x(0) =A*PI/2
    You just need to look up sin(x) and cos(x) a few times.
    When the angle gets close to PI/2 the cos(x) approaches 0 which will cause problems if this case is not tested for or enough resolition used. You could try rotating around PI/4
  • MGreimMGreim Posts: 114
    edited 2009-09-18 08:35
    Hi

    after implementing a cordic algorithm in SPIN quite easily, i was fighting
    with Propasm for some days to port this algorithm to assembler.
    In the source code i have written my opinion about some Propasm constructs wink.gif

    I have tested the algorithm against the atan2() of Perl.
    As input i used x := (cos(fi) <<10) and y := (sin(fi) << 10) from the Propeller.
    I f i did no mistake the deviation is less then +/- 2.5E-6 degrees, but a cross check would be helpful.

    Markus Greim
Sign In or Register to comment.