View Single Post
  #2   Spotlight this post!  
Unread 24-11-2005, 22:18
Astronouth7303's Avatar
Astronouth7303 Astronouth7303 is offline
Why did I come back?
AKA: Jamie Bliss
FRC #4967 (That ONE Team)
Team Role: Mentor
 
Join Date: Jan 2004
Rookie Year: 2004
Location: Grand Rapids, MI
Posts: 2,071
Astronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud ofAstronouth7303 has much to be proud of
Re: Programming Organization

Everything said so far is good. Here is my list of the important stuff:

Use a standard formatting style. This includes how to position braces ({ and }), spacing between arguments, amount of indent (2 spaces, 4 spaces, or a tab), line overflow, etc. I believe the de facto standard of C is like this:
Code:
// You should use more descriptive names for everything
void AFunctionName(int an_argument, int other_argument)
{
	int retval = DoSomething(other_argument, an_argument + 1);
	int n = 0;
	for (int i = 0; i < retval; i++)
	{
		// So, do something here...
		n = an_argument * i;
	}
}
Use a versioning system. CVS and Subversion are the best (only) free ones I've heard of. Do some googling as to how to use them/set them up. If used appropriately, this can also cover changelogs. (Write a descriptive commit message! I prefer many commits with specific changes to few large commits that can't have a good description.)

Document. I find doxygen works well for API-type documentation (Which functions do what, and what arguments they take). For logic documentation, nothing beats good ol' comments.

Create functions for conceptual reasons. A function should perform a specific task, and that task should be fairly clear from the name. (And having clearly named functions with unambiguous purposes also helps with self-documenting code, if you believe in such a thing.)

I agree entirely with teaching basic OOP concepts, since that includes ideas of abstraction and encapsulation (not to mention a few other things), concepts I consider important to writing clear code that works.

Code reuse. Last year, I used a system much like the autonomous scripting to handle motor control (control loops). This was a great boon for me, because when part of the robot didn't work, I could say, "It's not the code. The same code works on the other joint." (This is greatly undervalued. Definately going to do something similar again.)

Many files are good. You should actually reduce the number of functions in user_routines.c and user_routines_fast.c. Have a file devouted to translating human input, another one for driving, and several for autonomous. (I consider autonomous a 95-10 situation: 95% of your work goes into 10% of the match.)

In 2004 (code) and in 2005, I organized code based on function on the robot. All the hardware interaction went through abstraction macros/functions. This ment higher-level code would do things like:
Code:
 //user_routines.c, line 175
 //Map Joysticks to drive train
 Drive_Joystick(OI_Left, OI_Right);
While code farther in would be doing:
Code:
// Drive.c, line 51
void Drive_Joystick(char Left, char Right)
{
	if(Left > 127)
	{
		Left_CIM = Left_Drill =  (128 + JOYSTICK_SMOOTHING[Left - 127]);
	}
	else
	{
		Left_CIM = Left_Drill = (127 - JOYSTICK_SMOOTHING[127 - Left]);
    }
    
//	Right_CIM = Right_Drill = Right;
   	if(Right > 127)
	{
		Right_CIM = Right_Drill =  (128 + JOYSTICK_SMOOTHING[Right - 127]);
	}
	else
	{
		Right_CIM = Right_Drill = (127 - JOYSTICK_SMOOTHING[127 - Right]);
    }
}
(These same routines were used for autonomous, as well.)
This is a simplistic sample. The Hand_*() functions in Grabber.c (which maybe should have been broken up) are the most complex, due to the current-limiting sensor. BTW, this example is not from the year I used doxygen, so the functions themselves are poorly documented. *_Check() functions compared the input value to the current value and reacted appropriately (except the drive code, which just mapped input to output without feedback).