View previous topic :: View next topic |
Author |
Message |
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
cordic implementation |
Posted: Mon Apr 20, 2009 11:09 pm |
|
|
Trying to implement cordic32 routine provided in code library, on the following formula. Separate value of sin(), cos etc are ok but when used in formula, the result is weird. i.e.
Code: | tmp2 = cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(dLon); |
gives inappropiate result.
Any ideas .... ?
Regards... |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Apr 21, 2009 12:31 am |
|
|
You may want to tell example input and intermediate results of the individual terms to allow others to trace the problem. |
|
|
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
sample data |
Posted: Tue Apr 21, 2009 1:22 am |
|
|
Ok here is the sample data.
53.15055 is 531505500.
tmp = cos(531505500)*sin(532047200)-sin(531505500)*cos(532047200)*cos(17038888)
with calculator: tmp= -0.3445466179551353
cordic: tmp=-641923529
even breaking up the equation in multiple line doesnt work.
implemented in Borland C compiler for the time. |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 21, 2009 3:05 am |
|
|
Hint.
You have obviously got your calculator set to work in degrees, to give the result you are seeing. This is _not_ the angular format used in most languages (including C)...
Best Wishes |
|
|
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
|
Posted: Tue Apr 21, 2009 3:24 am |
|
|
Ttelmah wrote: | Hint.
You have obviously got your calculator set to work in degrees |
Calculator is set to radians. |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Tue Apr 21, 2009 6:53 am |
|
|
So cos(531505500) is taking the cosine of 8 1/2 revolutions? That strikes me as odd. What is the application?
53.51 radians = 3045 degrees = 8.4 revs (aprox) _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Apr 21, 2009 10:28 am |
|
|
The cordic library is using degrees, as far as I understand. |
|
|
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
|
Posted: Tue Apr 21, 2009 10:56 pm |
|
|
SherpaDoug wrote: | So cos(531505500) is taking the cosine of 8 1/2 revolutions? That strikes me as odd. What is the application?
|
You people took it wrong. Actually cordic library take the argument in degree. What I mentioned was that for calculator I converted it to radians. i.e given here 53.15055 (531505500) is in degress which gives 599714461 and calculator gives .5997144588 for Cosine, which is correct. But my question remains when multiple values of sines and cosine are multiplied the result gets wrong. I have even tried to break it up in multiple expressions.
The application is to calculate bearing from given latitude and longitude.
thanks... |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Apr 21, 2009 11:58 pm |
|
|
Quote: | But my question remains when multiple values of sines and cosine are multiplied the result gets wrong. I have even tried to break it up in multiple expressions. |
Yes, thus I previously suggested Quote: | to tell example input and intermediate results of the individual terms to allow others to trace the problem. |
This would have avoided also the degree/radians misunderstanding. Either an elementary Cordic function is giving wrong results, or it's another problem not directly related to Cordic. But no need to guess. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Wed Apr 22, 2009 12:10 am |
|
|
The purpose of the cordic is to avoid especially for the PIC the overhead of floating point and trig operations. I added the cordic to the library for that very reason. The cordic introduces the concept of binary notation in respect of angles. The tangent of 45 deg is represented by 1. then the tangent of 26.56 as 1/2 as binary 0.1 . Rotations then are performed using simple binary shift operations instead of multiplications . It is quadrant dependent and uses angles 0 to 90 degs and loses some precision as angles near 90 and 0. It could have been done in radians but wasn't. The cordic algorithm can have any precision. 32 bit was chosen since CCS provides for 32 bit binary storage and operations ( add subtract and rotate). Your calculation of a bearing in spherical geometry almost negates this purposed in that it uses
Quote: | tmp2 = cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(dLon); |
and is burdened by multiplication. 32 bit times 32 bit times 32 bits needs a 96 bit accumulator to maintain precision. If your two points on a sphere are within the same hemisphere set one pt as the center of a unit circle in a plane tangential to that point and project the other point onto it then rotate the co-ordinates using the cordic to the zero degree axis to get the angle. If you don't understand the mathematics then just do the whole thing in trig using the formula you have and accept the overhead.
Calculators use binary coded decimal and thus never leave decimal notation so they inherently will vary from pure binary notation used by the PIC and the CCS compiler. These are not errors just the expected variance between notations Ex 0.1 in decimal can't be notated in binary to arbitrary precision. |
|
|
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 22, 2009 1:05 am |
|
|
Quote: | If your two points on a sphere are within the same hemisphere set one pt as the center of a unit circle in a plane tangential to that point and project the other point onto it then rotate the co-ordinates using the cordic to the zero degree axis to get the angle.
|
It will be so nice of u if u elaborate a bit with an example.
BTW I have tried it on Borland C, regarding 96 bit accumulator issue.Its the same. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Apr 22, 2009 4:01 am |
|
|
@heli_potter: Basically, the cordic library uses a fixed point numeric representation. Fixed point numbers can't be multiplied without scaling the result during respectively after the multiply. As recently discussed in another thread, if you multiply two 32 bit integers to an int32 result, the upper 32 bits are discarded. That means, that a fractional number (representing -1..1) or most fixed point numbers must be downscaled before the multiply. Also, if your result has 64 or 96 bit resolution, a scaling or a shift after multiply is necessary.
@Douglas Kennedy: I must admit, that I don't see at first look, which number representation is used in the library. The 10e-7 scaling for degrees is clear, but the "length" or result scaling isn't. Mainly, because I didn't run the example code, I think. But it can be stated more clearly in the comments to my opinion. So in the below comment, what's the int32 value representing a "length" value of 0.607? Is it 1000000000 (0x3B9ACA00) or 607252935 (0x2431F1C7)? Or neither?
Quote: | /// so 1000000000 is 607252935 for 0.6072529350088813 |
Or, as another simple question, what's the int32 value representing tan(45°) respectively 1.0 |
|
|
heli_potter
Joined: 20 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 22, 2009 5:55 am |
|
|
You are right Fvm. I dont know what Mr. Douglas has to say. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Apr 22, 2009 6:15 am |
|
|
Quote: | I dont know what Mr. Douglas has to say. |
Well, the int32 * in32 point clearly says, why your code can't work. I only wondered about the correct scaling of the product. But it must be scaled, you didn't however.
P.S.: According to the results of the cordic.c example, the length values have a 1e9 scaling. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Wed Apr 22, 2009 5:04 pm |
|
|
As expected all numbers in the CCS compiler are binary and all operations by the cpu are binary. The compiler converts from decimal notation to binary when it sees numeric constants first they are decoded from ascii and then to binary and similarly various routines ex printf do the reverse. Within the storage requirement limitation on precision all operations are in binary and are exact in binary notation. Translation from binary to decimal notation produces differences that are often mislabeled as rounding errors especially when compared with a hand held calculator that never leaves decimal notation. Now when numerical values are scaled up so that integers represent what would otherwise be a fractional value higher correspondence between decimal and binary notation results. Now trig numbers are not rational numbers with the exception of certain values like cos(60) cos(0) cos(90) and no non rational number can be accurately represented in any notation except algebraic. Even rational numbers like 1/3 can't be expressed in decimal without some cut of point in precision. 32 bits puts the precision in the 9 significant decimal digit range. Iterations accumulate inaccuracies so the final result is likely to be accurate to 7or 8 significant digits. The CORDIC can be written to say 91 bit precision ( or any number of bits) but is cumbersome to implement unless the register sizes were also 91 bit. For CCS 16 bit precision is a bit low so the next most convenient size is 32 although 24 bit is fairly useful. As to heli_potter this is a self help board not a help yourself board. If the CORDIC isn't to your liking then don't help yourself to it. To define the help you get as not meeting your needs might come from the fact that you can't express your needs or maybe you don't understand your needs. |
|
|
|