Coding conventions

For the past month or so ive been reading the forums at least daily and i’ve notice one little problem in our programming corener over here; we need some base-line conventions for the ease of people just joining in and people new to programming. I would like to propose a few:

  1. If possible, replace pwmXX with some sort of macro throughout the program. That is, instead of putting pwm01 and pwm02, put R_MOTOR and L_MOTOR. Or at least state it at the beginning of your post. More than once, i’ve been readong code and said to my self, “What the heck does pwm03 do?”

  2. We should set down a base-line as to whether we should assume the flipped motor is later software corrected or not (a line at the end of the code somewhere along the lines of R_MOTOR=254-R_MOTOR;). I know last yaer we did just because the default code came with the reversal, but this year I’ve seen both (i.e. forward being both motors at 200 and assuming one will be flipped latter on and forward being one motor at 200 and one motor at 54)

  3. MACROS IN ALL CAPS, varables in all lowercase. Just for ease of mine and quick reference.

Does anyone have any other ideas? Would we like this sort of thing? Gimme your input. Thanks.

-Kesich

wonderful idea. i’d suggest agreeing on a certain point in the code to declare all variables. it’d also be nice to set up a standard for commenting code. what needs to be commented and how detailed and which details… i know i wouldn’t mind the extra guidance/rules, it would be good for my structure.

as far as you convention of wheel reversal pwm01 -= 254; is probaly one of the best methods and have not had a problem with it. Thats if you set your variable type to unsigned char.

I think the best conventions to use are the ones normally used in C/C++.

Variable names are such…

thisIsAVariable = 255;

Functions are…

ThisIsAFunction ();

Tabs and spaces should be used (I think normally a tab is eight spaces, but don’t quote me on that) for ease of reading. For instance…

ThisIsAFunction ()
 {
 		a = 0;
 		b = 255;
 
 		c = b - a;
 
 		return c;
 }
 

Something like that, which everyone should be used to be now, at least if they’ve taken any introductory course on C/C++ or Java.

If we want to add our own conventions, you have to set rather strict standards, and set them in the next 4 days, otherwise it’ll be too late, because as soon as people start coding for the robot, they won’t want to go in and change tiny things like making stuff all capitals, cause that’s just annoying (even with the searc/replace features in most text editors).

Just make sure there’s not too many little things to follow, otherwise it just gets annoying enough that no one will follow it. Holding down the shift key while typing half your program will get rather tedious :p.

Coding conventions are a dime a dozen. do we use K&R style with opening braces on the same line as the conditional? Do we use UpperCase to seperate words in variables or underscores? 5 space tabs, 8 space tabs, no tabs? Do we prefix variables with the type?

Coding conventions in a team are very valuable. However, it will never work on a massive scale like chiefdelphi. It should be fine as long as your code doesn’t look like this:http://www1.us.ioccc.org/2001/bellard.c. I do like your suggestions, though.

In fact, I would rather that the person asking the question take the extra 5 minutes to figure out what is happening then the person helping taking the extra 5 minutes to make their code look nice. But that’s just me.

ISO and ANSI standards do exist but are very costly for a school-based team (the original “standard” was LINT under UNIX).

I strongly suggest the “Indian Hill Style Guide” as a start. You can find it (and others) here: http://www.chris-lott.org/resources/cstyle/

BTW, I believe that 4 spaces to the tab (as used as default in the IDE editor) is a very acceptable standard. You will note that the IHSG does not specify the number of spaces but uses 4 spaces to the tab in their examples.

I agree- an 8-space tab is simply uncalled for. Conventions are absolutely needed within a team- especially because most teams have more than one programmer. And even if you do only have one programmer, what happens when he/she gets the flu four days before shipping and the mentor has to figure it all out? On the other hand, a FIRST-wide convention is almost impossible. Even if you examine the default code, you find sections of

ThisIsAFunction() {
}

and sections of
ThisIsDifferent()
{
}

and so on. I was going to suggest to my team that we follow the default code’s conventions, but it seems to fluctuate. This is an issue that will have to be worked out by each team individually.

While it doesn’t help with variable or function naming, there’s a great utility out called Artistic Style. It’s a free program available here. It runs under Windows or UNIX (it may need cygwin on windows, though). Anyway, it can reformat source code to follow certain specifications (such as put the braces on the same line as an “if” or on the next line, spaces around operators, indentation guidelines, whether or not to use tabs, etc). Works great for taking code written by a bunch of different people and making it follow one standard.

As a side note, most coding standards used by companies explicitly forbid the use of tabs in source code. While it is certainly up to you, I highly recommend you only use spaces to indent. It makes code so much easier to read when opened in another editor that uses a different number of spaces per tab. Any decent editor should allow you to have the tab key automatically insert the correct number of spaces instead of inserting a tab anyway, so it really shouldn’t be any harder to not use tabs.

ISO and ANSI standards do exist but are very costly for a school-based team (the original “standard” was LINT under UNIX).

Umm… Aren’t most C compilers ANSI C and ISO compliant? I didn’t think that their standards related to the way you formated text.

“The nice thing about standards is that there are so many to choose from.”

“The nice thing about standards is that there are so many to choose from.”

Why it appears the only standards that anyone should concern themselves with is ANSI and ISO.

whatever gets the job done…and what ever comments make it easier to read and understand to explain what gets the job done

All good suggestions, and i do understand that a FIRST-wide set of conventions simply cannot be done, but my one main problem was never addressed. Should motors be assumed to be later reversed (whether it be software or hardware), or should all motors be assumed to be unreversed?

wait, i dont think that works, but correct me if I’m wrong. Take pwm01=200. 200-254=0 with 54 more to roll over. So you then get 255-53, which then gives you 202, which is definately not what you are looking for. I, myself, have decided to stick to what I used in basic which was pwm01=254-pwm01.

It’s all about Hungarian notation. Microsoft makes all their new programmers go through courses on Hungarian before they ever touch a compiler. I don’t know if it deals with stuff like number of spaces or whatever, but it lays out the naming of variables. For instance:

lets say you have an integer storing average speed. An appropriate name might be nAvSpeed. The “n” prefixes the variable type, and all important parts of the name are capitalized.

chTest: character
sTest: structure (it think)
ptrsTest: pointer to a structure

Seems like to me this is a reason not to do it :smiley:

Seriously though, standardized coding conventions would help a lot, especially for teams that need programming help. Even if you just standardized within your team, it would be much better to be able to go back and forth between several years of robots and be able to use more of the same code with less editing. I think it’s a good idea, but will take someone who is really devoted to developing a good standard and sticking to it for it to work for the entire FIRST community. The best thing we can do is use plenty of comments and stay consistant at least in our own programs :slight_smile:

As for motor reversals: I believe that we should assume (when sharing code, at least) that to go forward


left_drive_motor = 254;
right_drive_motor = 254;

and all other movement can be inferred using this as a baseline. If a motor needs to be reversed, it is a simple matter for the team dealing with it to add the one line to thier code. Personally, I believe that this leads to code with maximum readability.

i agree completely, and i have done it the same way, well, forever, but i wasn’t sure what the general consesus was about it.

Most people probably use skid steering with two motors, like in this example. You’re probably also using the single joystick algorithm to mix the X and Y axis. Have you thought about modelling the robot to match that algorithm instead of setting the speed of the two motors? You would have a forward/reverse component and a rotational component. Something like:



//data types (from typelib.h, included for clarity)
typedef unsigned char uchar;
typedef unsigned int uint16;
typedef signed int sint16;

typedef struct {
    unsigned int cmdForward;  //range 0-255, 127=neutral, 127=forward
    unsigned int cmdRotate;    //range 0-255, 127=neutral, >127=clockwise
} robotModel;

//global robot variable
robotModel robot;

//map robot model commands to RC PWM outputs
void MapRobotOutputs()
{
    overlay sint16 temp;

    //set the left-hand drive motor
    temp = (sint16)robot.cmdForward + (sint16)robot.cmdRotate - 127; 
    pwm01 = NormalizePWM(temp);

    //set the right-hand drive motor
    //on our robot, the right-hand motor is mounted in reverse
    temp = (sint16)robot.cmdForward - (sint16)robot.cmdRotate + 127;
    pwm02 = 255 - NormalizePWM(temp);
}
 
//keep a pwm value between 0 and 255
uchar NormalizePWM(sint16 value)
{
    if (value < 0)
        return 0;
    else if (value > 255)
        return 255;
    else
        return (uchar) value;
}

If you only set the cmdForward and cmdRotate fields in the robot struct, and call MapRobotOutputs() during each program loop, then you have a standard API for both teleoperation and autonomous. Later you can close the loop on the rotational component by using the gyro within MapRobotOutputs() and add any scaling or filtering as you go. If you scale the values in that function then your autonomous code won’t have a big deadband in the middle as you step from 0-255 or vice versa. There is a whitepaper on IFI’s web site from last year describing how to do that.

From the teleoperation code you just set cmdForward = Y axis and cmdRotate = X axis. During autonomous you can rotate in place by keeping cmdForward = 127 and varying cmdRotate.

The point of my post was to say that lines of code such as this should not be included in short excerpts. The idea is that if a motor is to be reversed, it should only be done in one place in the code, preferably immediatly before output. When writing code, you can assume that if pwm02 (which, following convention 1 at the top of this thread should be R_MOTOR or some other macro) is full forward when it equals 255. Your code sets it to full forward at zero.

The point of my post was not to create a control algorithm, rather to define a convention for all FIRST programmers so that we can more easily communicate.

wow, this guy keeps stealing my wind. This is exactly what i had in mind.