CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

atan error

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
louwi_138



Joined: 17 Nov 2012
Posts: 23

View user's profile Send private message

atan error
PostPosted: Tue Oct 08, 2013 12:20 pm     Reply with quote

Hello,
I need to calculate some angle by the use of atan but this one is not stabel always in fact after debuging I noteced that it's make for some input an error = 3° witch cause a huge bad effect on the result of my program.

so if some one have any code of atan more accurate then the one of the library math.h

this is what is writeen in the top of my library :
Code:
////////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2010 Custom Computer Services            ////
//// This source code may only be used by licensed users of the CCS C   ////
//// compiler.  This source code may only be distributed to other       ////
//// licensed users of the CCS C compiler.  No other use, reproduction  ////
//// or distribution is permitted without written permission.           ////
//// Derivative programs created using this software in object code     ////
//// form are not restricted in any way.                                ////
////////////////////////////////////////////////////////////////////////////
////                                                                    ////
//// History:                                                           ////
////  * 9/20/2001 :  Improvments are made to sin/cos code.              ////
////                 The code now is small, much faster,                ////
////                 and more accurate.                                 ////
////  * 2/21/2007 :  Compiler handles & operator differently and does   ////
////                 not return generic (int8 *) so type cast is done   ////
////  * 6/19/2010 :  Divisions by constants converted to multiplication ////
////                 by its inverse to improve computation speed        ////
////                                                                    ////
////////////////////////////////////////////////////////////////////////////
Ttelmah



Joined: 11 Mar 2010
Posts: 19347

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 1:15 pm     Reply with quote

Are you calculating back from a division?. If so, look at atan2. This performs better at the extreme values (0, and infinity).
Also for speed, I have posted a much faster approximation (a search for atan2, and my name should find it), which is within a fraction of a degree for the whole quadrant, and a lot faster.
Worth 'trying'.
However are you sure something is not giving the calculation the wrong value?. I ran the supplied atan function for a span of values and compared it with the values calculated on a PC, and it differed by only a tiny fraction of a degree. Correct value for converting degrees to radians?.

Best Wishes
louwi_138



Joined: 17 Nov 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 2:04 pm     Reply with quote

Ttelmah wrote:
Are you calculating back from a division?. If so, look at atan2. This performs better at the extreme values (0, and infinity).
Also for speed, I have posted a much faster approximation (a search for atan2, and my name should find it), which is within a fraction of a degree for the whole quadrant, and a lot faster.
Worth 'trying'.
However are you sure something is not giving the calculation the wrong value?. I ran the supplied atan function for a span of values and compared it with the values calculated on a PC, and it differed by only a tiny fraction of a degree. Correct value for converting degrees to radians?.

Best Wishes


Yes I'm using division. I tried atan2 and it's the same result. Here is my code:

I have an robot at position (x_r,y_r) with an initial angle "ang_r" % the axis of X. Tthe robot should go to the position (x_o,y_o).
So the first time I rotate the robot to be directly face to face with the object by the use of the function "rotate", then I make it go directly to the object.
If any error is made in the rotation angle it will make a big problem when I go to the objective, because it will cause a big offset when I go for a large distance like 4 meters. It cause an offset of 30 cm :/
Code:

void rotation(){
   //distance between robot and objective
      if(x_o > x_r){
         dx = x_o - x_r;
         sig = 0;
      }else{
         dx = x_r - x_o;
         sig = 1;
      }
      if (y_o > y_r) dy = y_o - y_r;
      else           dy = y_r - y_o;
   
   //angle of the vector (robot --> objective) % OX;
      ang_o = atan2(dy,dx);
      if (sig) ang_o += pi / 2;
   
   //compute error and correction
      if(ang_r > ang_o){
         ang = ang_r - ang_o;
         watch_variable0= (int16)(ang*180/pi);
         if (ang > pi)
            move(rot2_rad(2 * pi - ang),G2);
         else
            move(rot2_rad(ang),D2);
      }else{
         ang = ang_o - ang_r;
         watch_variable0= (int16)(ang*180/pi);
         if (ang > pi)
            move(rot2_rad(2 * pi - ang),D2);
         else
            move(rot2_rad(ang),G2);
      }
      ang_r = ang_o;
}
jeremiah



Joined: 20 Jul 2010
Posts: 1322

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 4:04 pm     Reply with quote

in the v4.1xx compiler somewhere, there used to be a bug using atan and atan2 directly from the h files for some chips (in my case it was a PIC24 chip). The bug would clobber a working register, making the output incorrect. I reported it but have no clue if they ever fixed it as I ended up not using the algorithm I started with.

The work around I used was to copy the function from the h file, paste it into one of my own files, rename it, and it worked fine without clobbering the working register.

Might be worth a try, but I think using a more optimized version (mentioned earlier) might be better anyways.
louwi_138



Joined: 17 Nov 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 7:34 pm     Reply with quote

It's work fine,
here is the solution for this problem I tested it and it work (it's the own of Ttelmah ) :

Code:
float angle(float X, float Y)
{
   //routine to give a fast solution for angle, from X/Y co-ordinates - result in degrees
   float AX,AY,ival,oval,aival;
   int8 quad;
   AX=fabs(X);
   AY=fabs(Y);
   //Now the approximation used works for tan from -1 to 1, so we have to keep the
   //values inside this range and adjust the input/output.
   //Four 'quadrants' are decoded -1 to 1, (315 to 45 degrees), then 45 to 135,
   //135 to 225, 225 to 315
   If (X >= 0) //Right hand half of the circle
   {
      If (AY > X)
      {
         If (Y < 0)
         {
             quad = 4;
             ival = -X / Y;
         }
         Else
         {
             quad = 2;
             ival = X / -Y;
         }
      }
      Else
      {
         If (AY > X)
         {
             quad = 4;
             ival = -Y / X;
         }
         else
         {
             quad = 1;
             ival = Y / X;
         }
      }
   }
   else
   {
      //Now the others
      If (Y > AX)
      {
         quad = 2;
         ival = X / -Y;
      }
      Else
      {
         If (AY > AX)
         {         
             quad = 4;
             ival = -X / Y;
         }
         Else
         {
             quad = 3;
             ival = -Y / -X;
         }
      }
   }
   //A lot of lines of code, but small and quick really.....
   //Now the solution
   //Now approximation for atan from -1 to +1, giving an answer in degrees.

   aival = fAbs(ival);
   oval = 45 * ival - ival * (aival - 1) * (14.02 + 3.79 * aival);
   
   //Now solve back to the final result
   If (quad != 1)
   {
      If (quad == 2)
          oval = oval + 90;
      Else
      {
          If (quad == 3)
              oval = oval + 180;
          Else
              oval = oval + 270;
      }
   }
   if (oval<0)
      oval+=360;
   return oval;
}   
Ttelmah



Joined: 11 Mar 2010
Posts: 19347

View user's profile Send private message

PostPosted: Wed Oct 09, 2013 12:34 am     Reply with quote

Glad my version worked. It is optimised for size/speed, but gave quite good results. Smile

Interesting the comment from Jeremiah. I had not seen this, using tests displaying the results, but it (of course) it'd only "rear it's head" if the same register was being used elsewhere, and then give screwy results. Might be what the original poster was seeing.... Ugh.

There was a 'historical' occasional behaviour like this when you used some functions in complex formulae, but it didn't tend to occur when you used the functions on their own. The original poster's code, doesn't do anything else in the line with the atan, so is unlikely to show this - I wonder if Jeremiah's problem could have been this one?. The fix is really 'odd', suggesting that CCS is treating their own code differently. I'd suspect it was just the function being 're-named', that actually fixed the behaviour, which is 'interesting'...

Best Wishes
jeremiah



Joined: 20 Jul 2010
Posts: 1322

View user's profile Send private message

PostPosted: Wed Oct 09, 2013 11:50 am     Reply with quote

Back then I didn't end up trying to rename the function in math.h (probably should have, but I usually keep those read only so I don't mess them up). For reference it was on the PIC24FJ256GA106. I want to say compiler rev 4.114, but this was a couple years ago, so not 100% on the compiler rev.

Back then, when I looked at the LST file, I didn't get 10 ASM lines into the function and one of the working registers got clobbered. Literally something put a value into a working register, and then, within a few lines, overwrote the same register without using the value from before or storing it else where (no push or move to W15 for the stack either as that had already occurred earlier).

After copy/paste/renaming the function from the CCS file to my own, the LST showed correct assembly and it worked. I reported it to CCS, so it may have been fixed and this could be a different problem.


Last edited by jeremiah on Thu Oct 10, 2013 12:26 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19347

View user's profile Send private message

PostPosted: Thu Oct 10, 2013 12:28 am     Reply with quote

The funny thing is that this is exactly what is happening on V5, with the problem on interrupts being left disabled after sprintf, running in another thread.
Here they save the INTCON register, then only a few lines later overwrite it with the value with the interrupt disabled, then when the code exits restore this wrong value. That on a basic PIC16....
There is a 'concept' hidden away here that the compiler/optimiser is treating the saving of registers in code flagged as 'their own', differently to the same task performed in 'user' code. With (perhaps) them specifying what register to use to save things, rather than using the automated behaviour. It then only takes somebody to get one setting wrong, and the same register gets re-used... Have to keep my 'eyes peeled' for similar behaviour elsewhere.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group