Go to Post NOOOOOOOOOOOOooooooo!!!!! I hate regolith. - apalrd [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rating: Thread Rating: 4 votes, 4.75 average. Display Modes
  #46   Spotlight this post!  
Unread 24-02-2007, 17:08
The Lucas's Avatar
The Lucas The Lucas is offline
CaMOElot, it is a silly place
AKA: My First Name is really "The" (or Brian)
FRC #0365 (The Miracle Workerz); FRC#1495 (AGR); FRC#4342 (Demon)
Team Role: Mentor
 
Join Date: Mar 2002
Rookie Year: 2001
Location: Dela-Where?
Posts: 1,564
The Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond repute
Send a message via AIM to The Lucas
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by Cuog View Post
You can use the LEDs on the OI and have them turn on when the joystick input is where you want it.(for info on this look at the bottom of default_routine() in the default code
Quote:
Originally Posted by Jake M View Post
Very true, but my whole reasoning for making such a circuit is not simply to let us see when the joysticks are trimmed or aren't, it's to let us do so without using up other OI features (such as the LEDs) which we could use for other feedback, concerning the actual driving of the robot. We can only acesss 8 of them, through the joystick ports and we could easily find 8 other uses for an LED.
I wrote a routine like this years ago and it goes into the code for both my teams every year. Here is what I use: ( I just added some defines for portability)

Code:
#define CALAXIS1	p1_y
#define CALAXIS2	p1_x
#define CALAXIS3	p3_y
#define CALAXIS4	p3_x


if (disabled_mode)
{
	//when joysticks are calibrated
	//all 8 LEDs will be on
	Pwm1_green = (CALAXIS1 >= 127);
	Pwm1_red = (CALAXIS1 <= 127);
	Pwm2_green = (CALAXIS2 >= 127);
	Pwm2_red = (CALAXIS2 <= 127);
	Relay1_green = (CALAXIS3 >= 127);
	Relay1_red = (CALAXIS3 <= 127);
	Relay2_green = (CALAXIS4 >= 127);
	Relay2_red = (CALAXIS4 <= 127);
}
else
{
	//whatever you normally do with the LEDs
}
It only uses the LEDs while the bot is disabled, since it should be calibrated before enabling. You are free to use the LEDs as you would during the match, just put that code in the else statement. Just make sure your LEDs are set every loop to avoid confusing the drivers with stray lights.

Basically you just have to play with the calibration trimmers until both red and green LEDs are ON for that axis. Might be tough at first but you will get the touch. All 8 LEDs ON = "Calibrated and ready to go".
__________________
Electrical & Programming Mentor ---Team #365 "The Miracle Workerz"
Programming Mentor ---Team #4342 "Demon Robotics"
Founding Mentor --- Team #1495 Avon Grove High School
2007 CMP Chairman's Award - Thanks to all MOE members (and others) past and present who made it a reality.
Robot Inspector
"I don't think I'm ever more ''aware'' than I am right after I burn my thumb with a soldering iron"

Last edited by The Lucas : 24-02-2007 at 17:44. Reason: spelling, Multiquote
  #47   Spotlight this post!  
Unread 24-02-2007, 21:23
JimGRobot JimGRobot is offline
Registered User
AKA: Jim
FRC #1388 (Eagle Robotics)
Team Role: Mentor
 
Join Date: Nov 2006
Rookie Year: 2005
Location: Arroyo Grande, CA
Posts: 29
JimGRobot is just really niceJimGRobot is just really niceJimGRobot is just really niceJimGRobot is just really nice
Re: Programming tricks (and former trade secrets)

Thanks for the note, this is a very good point...

We see the same behavior whenever we reset the RC.

Fortunately, our offsets are small, so the bot doesn't go nuts.

Thanks,
Jim
  #48   Spotlight this post!  
Unread 26-02-2007, 01:34
Dave K.'s Avatar
Dave K. Dave K. is offline
Engineer/Mentor
FRC #0930
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2005
Location: WI
Posts: 91
Dave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to behold
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by Alan Anderson View Post
Anyone else feel like sharing?
Streamlined, non-directional Encoder Tach code and added a ring buffer. This is used with 100 counts per revolution encoders on each wheel and provides good low speed resolution while still allowing the PID loop to compute new values every 26ms.

Some will recognize Kevin's interrupt framework, but everything else is different.

Here's the relevant portion of the interrupt routine:

Code:
volatile unsigned int Tach_Count[NUM_TACH];
unsigned char Old_Port_B = 0xFF;

void InterruptHandlerLow () {

	unsigned char Port_B;
	unsigned char Port_B_Delta;

  // other interrupt handler code removed for clarity.

	else if (INTCON3bits.INT2IF && INTCON3bits.INT2IE) { // encoder 1 interrupt?
		INTCON3bits.INT2IF = 0; // clear the interrupt flag
		Tach_Count[0]++;
	}
	else if (INTCON3bits.INT3IF && INTCON3bits.INT3IE) { // encoder 2 interrupt?
		INTCON3bits.INT3IF = 0; // clear the interrupt flag
		Tach_Count[1]++;
	}
	else if (INTCONbits.RBIF && INTCONbits.RBIE) { // encoder 3-6 interrupt?
		Port_B = PORTB; // remove the "mismatch condition" by reading port b            
		INTCONbits.RBIF = 0; // clear the interrupt flag
		Port_B_Delta = Port_B ^ Old_Port_B; // determine which bits have changed
		Old_Port_B = Port_B; // save a copy of port b for next time around
	 
		if(Port_B_Delta & 0x10) { // did external interrupt 3 change state?
			if (Port_B & 0x10) {
				Tach_Count[2]++;
			}
		}
		if(Port_B_Delta & 0x20) { // did external interrupt 4 change state?
			if (Port_B & 0x20) {
				Tach_Count[3]++;
			}
		}
	}
}

Initialization:

Code:
unsigned char i, j;

	for(i=0;i<NUM_TACH;i++) {
		TachHead[i] = 0;
		for(j=0;j<TACHBUFSIZE;j++) {
			TachBuf[i][j] = 0;
		}	
	}
And here's the foreground tach code that runs in the 26ms loop:

Code:
#define NUM_TACH 4
#define TACHBUFSIZE 4

extern unsigned int Tach_Count[];  // interrupt routine edge counter
unsigned char i, j;
unsigned int TachBuf[NUM_TACH][TACHBUFSIZE];  // ring buffer
unsigned char TachHead[NUM_TACH];  // TachBuf head pointer
unsigned int Tach[NUM_TACH];  // Tach result register.


			// disable tach interrupts, grab current count, and reset counter

			INTCON3bits.INT2IE = 0;		// Disable INT2 for tach 1
			INTCON3bits.INT3IE = 0;		// Disable INT3 for tach 2
			INTCONbits.RBIE = 0;		// Disable Port B change interrupt for tach 3&4

			// get current tach values into local var, then reset the counter
			for (i=0;i<NUM_TACH;i++) {
				TachBuf[i][TachHead[i]] = Tach_Count[i];	// place current tach count into ring buffer & inc buffer
				Tach_Count[i] = 0;
			}

			INTCON3bits.INT2IE = 1;		// INT2 on
			INTCON3bits.INT3IE = 1;		// INT3 on
			INTCONbits.RBIE = 1;		// Port B change interrupt on


			// sum up the tach counts in ring buffer into Tach[]
			for (i=0;i<NUM_TACH;i++) {
				Tach[i] = 0;
				for(j=0;j<TACHBUFSIZE;j++) {
					Tach[i] += TachBuf[i][j];
				}
				if (++TachHead[i] >= TACHBUFSIZE) {
					TachHead[i] = 0;
				}
			}

                        // Tach[] now contains the unsigned wheel speeds
__________________
--Dave
  #49   Spotlight this post!  
Unread 26-02-2007, 06:55
Alan Anderson's Avatar
Alan Anderson Alan Anderson is offline
Software Architect
FRC #0045 (TechnoKats)
Team Role: Mentor
 
Join Date: Feb 2004
Rookie Year: 2004
Location: Kokomo, Indiana
Posts: 9,113
Alan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond repute
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by Dave K. View Post
Streamlined, non-directional Encoder Tach code and added a ring buffer. This is used with 100 counts per revolution encoders on each wheel and provides good low speed resolution while still allowing the PID loop to compute new values every 26ms.
We did that for the shooter wheel last year, but with a twist. Recognizing that the buffer is essentially a filter that slows down the measurement response, we added the newest value from the buffer multiple times. The resolution stays high, but the sum more quickly represents a change in velocity.

I also came up with an interesting result when I figured how long it took to maintain the ring buffer. With as many as ten entries, it turned out to be faster to move all of the values every time than to index through an array. Array operations are convenient and make for easier coding in many cases, but they can be remarkably slow.
  #50   Spotlight this post!  
Unread 26-02-2007, 08:24
Joohoo's Avatar
Joohoo Joohoo is offline
Registered User
FRC #0340 (G.R.R.)
Team Role: Mentor
 
Join Date: Jun 2005
Rookie Year: 2005
Location: Rochester
Posts: 241
Joohoo is just really niceJoohoo is just really niceJoohoo is just really niceJoohoo is just really niceJoohoo is just really nice
Send a message via AIM to Joohoo Send a message via Yahoo to Joohoo
Re: Programming tricks (and former trade secrets)

we worked on writing a new scripting language for autonomous mode.

so easy to write new logic I had mechanical people writing some stuff.
  #51   Spotlight this post!  
Unread 26-02-2007, 13:37
Dave K.'s Avatar
Dave K. Dave K. is offline
Engineer/Mentor
FRC #0930
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2005
Location: WI
Posts: 91
Dave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to behold
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by Alan Anderson View Post
We did that for the shooter wheel last year, but with a twist. Recognizing that the buffer is essentially a filter that slows down the measurement response, we added the newest value from the buffer multiple times. The resolution stays high, but the sum more quickly represents a change in velocity.

I also came up with an interesting result when I figured how long it took to maintain the ring buffer. With as many as ten entries, it turned out to be faster to move all of the values every time than to index through an array. Array operations are convenient and make for easier coding in many cases, but they can be remarkably slow.
I agree that a weighted average approach can help. In this case, to get the resolution we needed, a sample window of about 4*26 (100ms) worked out about right, but only performing the PID calculations at that rate, made the loop somewhat hard to optimize and user response more sluggish.

I don't doubt that individual moves would be faster as it avoids one or more multiply operations to compute the array index.

Although the interrupt routines use an arrayed variable to store the tach counts, the use of an absolute index allows the compiler and linker to resolve this to a fixed memory location at build time.

The overall simplification of Kevin's code by reworking the logic to remove direction sensing as well as the overhead of function calls helps reduce the CPU loading where the impact is the greatest.

My primary point in sharing the idea was to provide a simpler example of how a velocity only interrupt could work, and to introduce the idea of using a sliding window for data values to improve resolution.


I chose to use arrayed variables in the 26ms loop for the tach code as well as all of the remaining PID code just to help with readability and to make it easy to change the size of the ring buffer, or add/delete motors.

Certainly if the CPU didn't have any idle time left, the arrays are one of the first things I'd go after.
__________________
--Dave
  #52   Spotlight this post!  
Unread 26-02-2007, 23:43
Jake M Jake M is offline
void* Jake;
FRC #1178 (DURT)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Missouri
Posts: 118
Jake M has a spectacular aura aboutJake M has a spectacular aura about
Re: Programming tricks (and former trade secrets)

[quote=The Lucas;585702]It only uses the LEDs while the bot is disabled, since it should be calibrated before enabling. You are free to use the LEDs as you would during the match, just put that code in the else statement. Just make sure your LEDs are set every loop to avoid confusing the drivers with stray lights.[quote]

Now, why didn't I think of that? Thanks for the tip.
__________________
Code:
void function(void)
 {
  function();
 }
  #53   Spotlight this post!  
Unread 27-02-2007, 10:32
PhilBot's Avatar
PhilBot PhilBot is offline
Get a life? This IS my life!
AKA: Phil Malone
FRC #1629 (GaCo: The Garrett Coalition)
Team Role: Mentor
 
Join Date: Jan 2006
Rookie Year: 2006
Location: Maryland
Posts: 756
PhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond reputePhilBot has a reputation beyond repute
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by WesleyC View Post
The code goes something like this:

output = (input * input / 127) * (input > 0) ? 1 : -1;
This is a great piece of math, but when I tried it, it didn't work...
It only served to reinforce my motto "when in doubt, add parenthesis".

It appears that the compiler gives greater precedence to * than it does to ?

So what the code was doing was this:

output = ((input * input / 127) * (input > 0)) ? 1 : -1;

not this:

output = (input * input / 127) * ((input > 0) ? 1 : -1);


As written, the code only returned +/- 1. With parenthesis added as in the second example, the code did what was intended.

The other cool by-product of this code is that it adds in a small dead-band to the joystick. Any offset less than 13 returns a zero after interger math truncation.
__________________
Phil Malone
Garrett Engineering And Robotics Society (GEARS) founder.
http://www.GEARSinc.org

FRC1629 Mentor, FTC2818 Coach, FTC4240 Mentor, FLL NeXTGEN Mentor
  #54   Spotlight this post!  
Unread 27-02-2007, 14:02
Dave K.'s Avatar
Dave K. Dave K. is offline
Engineer/Mentor
FRC #0930
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2005
Location: WI
Posts: 91
Dave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to behold
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by PhilBot View Post
This is a great piece of math, but when I tried it, it didn't work...
It only served to reinforce my motto "when in doubt, add parenthesis".

It appears that the compiler gives greater precedence to * than it does to ?

So what the code was doing was this:

output = ((input * input / 127) * (input > 0)) ? 1 : -1;

not this:

output = (input * input / 127) * ((input > 0) ? 1 : -1);
Operator precedence for Multiplicative and Additive instructions is relatively high, whereas the ternary operator is quite low, however the '?' forms a 'sequence point' and considers anything to the left, within the sequence, to be used as the scalar value.

Parenthesis is, of course, the correct way to create the desired association, and when using the ternary operator is a good habit to adopt.
__________________
--Dave
  #55   Spotlight this post!  
Unread 01-03-2007, 11:25
WesleyC WesleyC is offline
Registered User
FRC #1825
 
Join Date: Jan 2007
Location: Johnson County, KS
Posts: 16
WesleyC is on a distinguished road
Re: Programming tricks (and former trade secrets)

Thanks for the notes!

I'm coming from a PHP background--all math is given equal precedence in PHP; you use parenthesis to emphasize certain points to be performed first--also, all expressions are evaluated before math is performed.

Also, one thing you must be careful of when using this particular phrase is that the input variable must either be an int or typecast to an int before performing math. If "input" is a char, the math will overflow the size of the type, creating... shall we say, "undesirable" results.
  #56   Spotlight this post!  
Unread 01-03-2007, 15:22
Dave K.'s Avatar
Dave K. Dave K. is offline
Engineer/Mentor
FRC #0930
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2005
Location: WI
Posts: 91
Dave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to behold
Re: Programming tricks (and former trade secrets)

Quote:
Originally Posted by WesleyC View Post
Thanks for the notes!

I'm coming from a PHP background--all math is given equal precedence in PHP; you use parenthesis to emphasize certain points to be performed first--also, all expressions are evaluated before math is performed.

Also, one thing you must be careful of when using this particular phrase is that the input variable must either be an int or typecast to an int before performing math. If "input" is a char, the math will overflow the size of the type, creating... shall we say, "undesirable" results.
Without disagreeing with the comment about type casting...

If the compiler is really standards compliant, objects or expressions of rank less than int (such as unsigned char) are converted to int (if int can represent all values of the original type) or unsigned int (otherwise); this is known as integer promotion.

In the case of multiplying two unsigned chars, the the product of two values of unsigned type will be reduced according to the range of values for that type.

This is an area where compiler's behavior will sometimes vary, especially those targeted towards 8 bit native platforms (such as the PIC18) where math with 8 bit variables is not always evaluated as an integer (which in this case is 16 bits).

Not all compilers correctly perform integer promotion, and I've only run across one that did not behave any better when type casts were applied.

In the case of the PIC18 compiler it does understand integer promotions, however the default behavior is to not do it. The C compiler documentation covers this in section 2.7 (ISO DIVERGENCES).
__________________
--Dave
  #57   Spotlight this post!  
Unread 02-03-2007, 23:40
Snappel328's Avatar
Snappel328 Snappel328 is offline
Programmer
AKA: Chris Reins
FRC #1746 (Forsyth Alliance)
Team Role: Programmer
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Forsyth County
Posts: 33
Snappel328 will become famous soon enough
Re: Programming tricks (and former trade secrets)

Well, we've got some good things going on. I guess everyone else was either hurrying or something with their programming, because we managed to play quite a lot of Counter-Strike and still have a perfectly functional robot heh.
__________________
2006 Peachtree Regional Rookie All-Stars
2006 Championship Imagery Award Winners
2007 Peachtree Regional Imagery Award Winners
  #58   Spotlight this post!  
Unread 03-03-2007, 12:36
Qbranch Qbranch is offline
wow college goes fast.
AKA: Alex
FRC #1024 (Kil-A-Bytes)
Team Role: Alumni
 
Join Date: Apr 2006
Rookie Year: 2006
Location: Indianapolis
Posts: 1,174
Qbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond reputeQbranch has a reputation beyond repute
Re: Programming tricks (and former trade secrets)

*to the tune of California Dreamin'*

CCPs make me happy... when the skys are grey... when i have the pwm blues... on a winter's day... update rate ga-lore... when the skys are grey-hey....

keep on dreamin... and good luck in Rack N' Roll!

(by the way, low freq SDAR, team 1024's pet project, autonomous mode? we'll find out... *hint hint*)

-q
__________________
Electrical Engineer Illini
1024 | Programmer '06, '07, '08 | Driver '08
  #59   Spotlight this post!  
Unread 09-03-2007, 01:07
JohnC's Avatar
JohnC JohnC is offline
my other name is nigel
FRC #0360 (360 Revolution)
Team Role: Programmer
 
Join Date: Mar 2005
Rookie Year: 2005
Location: user_routines.c
Posts: 100
JohnC is a jewel in the roughJohnC is a jewel in the roughJohnC is a jewel in the roughJohnC is a jewel in the rough
Send a message via AIM to JohnC
Re: Programming tricks (and former trade secrets)

Our drive code was such that 3/54 teams approached us specifically asking how we get such fine control of our robot.

I know this is a lot of code, and it's not very advanced, but man does it work well.

Code:
int driveScaleFactor = 3;

void Left(int speed) {
  pwm03 = Safe_Values(speed);
}

void Right(int speed) {
  pwm04 = Safe_Values(254-speed);
}

int Safe_Values(int roughValue) {
  int toReturn = roughValue;

  if(toReturn> 254) {
    toReturn = 254;
  } else if(toReturn < 1) {
    toReturn = 1;
  }

  return toReturn;
}

int Scale_Offset(int roughValue, int scaleFactor) {
  int toReturn = roughValue;

  toReturn = ((toReturn-127)/scaleFactor) + 127;

  return toReturn;
}

//// later, in Process_Data_From_Master_uP()

if(p1_sw_trig && p2_sw_trig) {
  Left(p1_y);
  Right(p2_y);
} else {
  Left(Scale_Offset(p1_y,driveScaleFactor));
  Right(Scale_Offset(p2_y,driveScaleFactor));
}
The advantage of having a function to assign pwm values instead of assigning them inline, is, obviously, you can add other functions like the one I did. Let me know if you use this!

I will eventually post code that uses PD control with encoders to drive in a straight line autonomously.
__________________
What place are we at? ... TODAI!
  #60   Spotlight this post!  
Unread 09-03-2007, 01:38
AustinSchuh AustinSchuh is offline
Registered User
FRC #0971 (Spartan Robotics) #254 (The Cheesy Poofs)
Team Role: Engineer
 
Join Date: Feb 2005
Rookie Year: 1999
Location: Los Altos, CA
Posts: 803
AustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond reputeAustinSchuh has a reputation beyond repute
Re: Programming tricks (and former trade secrets)

We wrote our own sin() function.
It takes a degree measure in in "funnys", where there are 40 "funnys" per circle. We then directly map that angle to the table after correcting the sign of the number. We are using this to implement a feed forward controller with our PID controller. We will be adding in a function on Thursday that will take 2 angles and some other various data in from our double jointed arm, and output the torque that is being experienced on the "shoulder" joint and implement that into the PID controller for the shoulder.

I also wrote our drive code so that the steering wheel we use specifies the difference in motor power between the left and the right wheels. This even works when the throttle is full forward. The code calculates it out so that even though it would like to run one motor at over full power, it lowers the other motor's power further instead to retain this difference in power.

I like the reduced sensitivity code that I saw earlier. I think that I am going to implement a version of that using one of the buttons on our steering wheel to turn the mode on or off.

Our sin(x) function:
Code:
static const int8 sin_table[] = {0, 20, 39, 58, 75, 90, 103, 113, 121, 125, 127};
int sin(int x) {
        char negate = 0;
        int result; 

        // sin(-x) = -sin(x)
        if (x < 0) {
                x = -x;
                negate = 1;
        }

        // sin(x) = sin(x - 360 degrees)
        while (x >= 40) x -= 40;

        if (x > 30) { 
                x = 40 - x; 
                negate = !negate;
        } else if (x > 20) { 
                x = x - 20; 
                negate = !negate;
        } else if (x > 10) { 
                x = 20 - x; 
        }
        result = (int) sin_table[x];
        if (negate) result = -result;
        return result; 
}
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Former FIRST student and mentor dies in a tragic rocket attack in Iraq today. Munkaboo General Forum 48 19-04-2005 12:21
Off-season competetions and former teams Venkatesh Off-Season Events 5 10-12-2004 17:23
Harry Potter and the Chamber of Secrets Ryan Dognaux Chit-Chat 33 01-12-2002 19:57
scouting tips and tricks Rick Scouting 1 08-01-2002 00:52


All times are GMT -5. The time now is 09:14.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi