Getting angle value from sin/cos
ErNa
Posts: 1,752
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?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
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
Post Edited (ErNa) : 9/13/2009 2:25:46 PM GMT
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
Post Edited (ErNa) : 9/13/2009 2:25:46 PM GMT
Comments
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
best regards
Stefan
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.
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.
But I saw, i wrote "successive" "succesive" and that may have been critical
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
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
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
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
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
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
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