Techna Pwn Code 2013

Hello all! We have been talking about doing this for a while, and are just now getting around to it. We decided to open our programming up to public criticism, and allow anyone who cares have access to our work. We also hope teams can find some of the material useful for learning some good and bad coding habits that we have picked up over the years, as well as maybe gain a new perspective on common problems. Please comment or ask questions and we will try to answer them to the best of our ability. Programming is an aspect of the game that we consider very important, and we hope this shows in the result of our work over the past two years.
Most of the credit goes to Josiah (Simmons2.0) and Joseph (JoeTpr).
Tecna Pwn Code (57.9 KB)

Before I download the code file and find out I can’t open it, easyC or ROBOTC?


The code is written in ROBOTC. It can be opened in notepad or any other text editor because .c files are stored in plain text.

Wow. The framework for the auton makes the modes really clean. I just spent a few minutes in the code and so far looks pretty nice.

Great work and thanks for your openness to help others learn different programming techniques !

Thanks guys! :slight_smile:
Also, the code is best viewed with tabs set to display as 4 characters wide.

I had read it already,and it truely inspired me a lot.Thank you!
I am a beginner of programming,and I have some questions on your code.Would you please explain some details for us?Thanks!

The most difficult part to understand for me is probably the DriveControl.

StkCos1 =		(float) StkDrvX/127.0;
	StkSin =		(float) StkDrvY/127.0;
	StkCos2	=		(float) StkDrvZ/127.0;
	StkTheta =		radiansToDegrees(atan2(StkSin, StkCos1));			

It seems you’re using the sine and cosine of the joystick direction instead of the analog value.I can understand the code above,but the following is hard for me.

StkEstPower =	137 - (cos(StkTheta * 4) * 10);
StkPower =	sqrt((StkCos1*StkCos1) + (StkCos2*StkCos2) + (StkSin*StkSin)) * (16129/StkEstPower);
MtrDrvFL =  ((StkSin*abs(StkSin)) + (StkCos2*abs(StkCos2)) + (StkCos1*abs(StkCos1))) * StkPower;
MtrDrvBL =  ((StkSin*abs(StkSin)) + (StkCos2*abs(StkCos2)) - (StkCos1*abs(StkCos1))) * StkPower;
MtrDrvFR =  ((StkSin*abs(StkSin)) - (StkCos2*abs(StkCos2)) - (StkCos1*abs(StkCos1))) * StkPower;
MtrDrvBR =  ((StkSin*abs(StkSin)) - (StkCos2*abs(StkCos2)) + (StkCos1*abs(StkCos1))) * StkPower;

What’s the use of StkPower?And as we all know,sin^2+cos^2=1,is the StkPower=sqrt(1+stkcos2stkcos2)(127*127/stkestpower)?I can’t understand the StkEstPower and the StkPower,and wonder about the motor output theory.Is it kind of cubic mapping?I so curious about your algorithm,would you please explain it?Thanks a lot!

Another thing is about the line followers.It seems that you installed 4 line followers,could you please tell me where did you put them?Your idea on establishing coordinate is really awesome.I don’t really understand your line following method,probably because I don’t know where is the line followers:p Do you have a way to reposition to parrallel the white line? I was trying this function these days.

I haven’t completely understand the autonomous structure.But the basic constructions is really unusual for me.Using arrays makes the tuning of autonomous more clearly,but the structure is not very easy to write.Do you suggest to using this kind of infrastructures?

Still thanks a lot! Your program made me learned a lot c-programming skills.I write my pid controller based on your code.That really helped me a lot.Thanks a lot!

They are using a direction and power type of driving.

X becomes Cos of drive angle
Y becomes Sin of drive angle.

The code then talks about the joystick not being a perfect circle (which I’m surprised at because it looks pretty circular to me, I need to check on that) so they do some “magic” compensation using “magic” numbers that don’t mean anything to readers of the code. Where did 137 and 16129 come from?

It looks like the code was originally arcade code and was then adapted for mecanum wheels.

16129 = 127^2

137 = 127 + 10

I’m guessing 137 has something to do with offset / threshold motor power to run the wheels, not completely sure.

As for the joystick not being complete circle, it’s probably not the “physical joystick” but the joystick mapping values since it has the corners (-127, -127) (127, -127) (-127, 127) and (127, 127). So when converting to polar coordinates, the magnitudes need to be scaled when operating outside of the radius 127 circle centered at (0, 0).

It is indeed arcade drive adapted for mecanum drive. The reasoning behind the use of

137 - (cos(StkTheta * 4) * 10);

is that we found that the joysticks are not circular. Our arcade drive is based on a unit circle but there was no circle to speak of; just a square with rounded edges. (I could upload the data from that test if anyone is interested)
So what we did is plot the sensor values on a graph and created a polar function to approximate the values at based on the angel of the joystick. The above function is the result. While this does not make a huge difference, it allows better control at 45 degree angles. Its not needed but it make it work just that much better.

P.S. And to be totally honest, we do not use sin and cos in their true meaning, we simply scale the raw values to between 1 and 0: it just happens to be the same thing.


Sorry I missed a few questions, I will try to answer them.

137 is the median value of the joystick’s edge (ranges from 127 at the axis to 147 at the corners) and 16129 is 127^2 we just saved the computer the trouble of calculating it every time.

Yes we use four line sensors, two in the front middle and one of each side halfway between the front and back wheel. This allows us to both follow and align on the white lines. This year was the first time we had done this with VEX, but previously we did it with NXT as seen here and here.
Hopefully that help a little bit.


I was curious so did a quick test. I had always assumed that because the physical joystick was constrained by a circular hole the values would make a circle if plotted. This was the data I found.


The red plot shows the ideal circular data, the black plot was data captured from a joystick, the green data is based on the equation you used.

StkEstPower =	137 - (cos(StkTheta * 4) * 10);

For the benefit of others, this uses a cosine with an amplitude of 10 to modify the data in each quadrant (the 4 in the equation gives one cos cycle for each quarter of the data).

This is useful information, thanks for finding this out (even if rather indirectly, thanks string).

FYI, ROBOTC is pretty good at optimizing constant calculations. For example,

        StkPower = sqrt((StkCos1*StkCos1) + (StkCos2*StkCos2) + (StkSin*StkSin)) * ((127*127)/StkEstPower);

ROBOTC will not calculate 127^2 each time, it replaces the 127^2 with a constant.

One comment on code style (and I guess this is subjective so you can choose to ignore). The code is hard to follow when all variables are global. DriveControl as a function uses several globals that are not used anywhere else, I would far prefer that they were declared in that function instead of another file. I assume you did this as it can make debugging in ROBOTC much easier, you can see everything in the globals window, however, once debugged better to make them local to the function.