Letting ROBOTC write looped rerun program -- a cool idea

So a while ago, right before I left my robotics lab, I did a final little project about motor velocity mapping, PID velocity control and rerun program. The project is mainly successful as I did make the rerun work pretty well:

But I was never able to complete the final few steps – optimizing the output in debug stream. The method in the video is extremely tedious – print two lines of assign values and one line of delay every tenth of a second, and go as long as you want to. A 30 second record would take up 900 lines of code.

Well that’s not very nice, is it?

So today I had some time and decided to finish up one of the final steps of my little rerun project. Which is using an array to store the data and letting the debug stream print out a looped rerun program that has its identical independent data set as the recording. This way you can apply the recording to any motors on any cortex conveniently.

So, in summary, what I did was this:

https://vexforum.com/attachment.php?attachmentid=9447&stc=1&d=1434589985

[;
bool recording = false;

void initialize ();
void joystick_simulation ();
task LCD ();
task record_and_write ();
void writeReplayCode ();

task main()
{
initialize ();
while(true)
{
if (recording)
{
joystick_simulation();
recording=false;
}
wait1Msec(1);
}
}

//////////////////////////////////

void initialize_data_array ()
{
for(int i=0;i<150;i++)
{
data*=0;
}
}

void initialize ()
{
clearDebugStream();
initialize_data_array();
startTask(LCD);
startTask(record_and_write);
}

void visualize_joystick_simulation ()
{
writeDebugStreamLine(“%i”,joystick);
}

void joystick_simulation ()
{
for (int i=0; i<150;i++)
{
joystick = simulation_scale_factor*sin(i/PI);
wait1Msec(100);
//visualize_joystick_simulation();
}
}

task LCD ()
{
int count=1;
string time;
while(true)
{
if (nLCDButtons==2)
{
recording = true;
displayLCDString(0,0," recording “);
displayLCDString(1,0,” “);
while(count<15000)
{
count++;
sprintf(time,”%2.3f",count/1000.000);
displayLCDCenteredString(1,time);
wait1Msec(1);
}
}
displayLCDString(0,0," press to ");
displayLCDString(1,0,“start recording”);
wait1Msec(1);
}
}

void newLine ()
{
writeDebugStreamLine(“”);
}

void writeReplayCode ()
{
writeDebugStreamLine(“void replay ()”);
writeDebugStreamLine(“{”);
writeDebugStreamLine(" byte drive[150] = {“);
for(byte i=0;i<10;i++)
{
for (byte j=0;j<15;j++)
{
writeDebugStream(”%i,“,data[j+i15]);
}
newLine();
}
writeDebugStreamLine(“};”);
writeDebugStreamLine(" for(int i=0;i<150;i++)“);
writeDebugStreamLine(” {“);
writeDebugStreamLine(” motor[m] = drive
;”);
writeDebugStreamLine(" wait1Msec(100);“);
writeDebugStreamLine(” }“);
writeDebugStreamLine(” motor[m] = 0;“);
writeDebugStreamLine(”}");
}

task record_and_write ()
{
int count = 0;
bool write = false;
while(true)
{
while(recording&&count<150)
{
data[count]=joystick;
count++;
write=true;
wait1Msec(100);
}
if(write)
{
writeReplayCode();
write=false;
}
wait1Msec(1);
}
}

[/CODE]

Cheers,

MartinMaVEXForever**](Letting ROBOTC Write Programs For You ?!!!!!!!! - YouTube)
practicing smart printing program.c (2.48 KB)
printing out code.JPG

Supplemental explanatory stuff:

So essentially a rerun program is recording joystick values or button values every 100 ms or so, letting debug stream print out the data somehow, and then plug the data back to the motors. The accuracy issue can be improved with a PID velocity controller.

There’s a little programming trick I used in the program written above. When you’re declaring a user function, you usually have to declare it before you ever have to use it. Which is inconvenient if you declare a whole bunch of them. They push your main loop and autonomous routines, which are where you’re mainly gonna do your work, to the very bottom. You have to scroll down every time.

I found this trick when I’m trolling through ROBOTC’s competition template. Turned out, you can declare only the name of the user function at the top of the program and put a semicolon behind it, and then declare the full function somewhere below. ROBOTC, I assume, when sees the name, will search the entire program for the actual declaration and declare it. This way, you are kinda creating an index of all the user functions and variables you can use, while keeping the task main on the very top of the page.

Cool, hun? Or maybe you guys already know this very well and I just found it…

:stuck_out_tongue:

One last word:

I’ve been making some ROBOTC tutorial videos on my channel recently, addressing some of the problems that let me down when I had to learn robotc one error notice at a time. Primarily designed for newbies and programmers seeking to improve themselves but struggle with reading some of more advanced pieces of codes. However if you’re a veteran with ROBOTC, welcome to take a look and point out some things in my videos that I can improve.

I am by no means a top level ROBOTC programmer, and neither am I assuming I am standing on that position. I’m just one guy in the community who tries to show us some tricks in programming that you may or may not know. What I really hope is to clear out some questions you guys have about programming with ROBOTC in VEX competition.

Subscribe if you’re a VEX programmer and you wanna know every single corner about ROBOTC and make cool programs that let others go “WOWWWW”…

Haha…

Best,

MartinMaVEXForever

1 Like

Wow! Lot’s of good stuff. Maybe you should put “Vex” somewhere in the titles so kids might find them when doing searches on YouTube? And/or RobotC, etc. :slight_smile:

Okay so what you are alluding to is the difference between a function definition and a function declaration. Just saying


int MartinMa();

declares that you exist but doesn’t define the function. I can then later actually make the function definition. As long as the function is declared it can be referenced which is the benefit you are talking about. Just make sure you define the function eventually or you will have an error.

Here is a little background if you are interested