A program that recreates a driver run in autonomous

Does anyone know how a program that recreates a driver run in auton work?

1 Like

Yes… What programming environment are you using?

I use RobotC

If I understand correctly, you want to simulate a match with the starting and stopping of driver and auton. For this you need to make sure you are using the competition template in RobotC, and to switch between them you need a competition switch:

I believe there is also a way to do this within RobotC without the switch, but I’m not sure.

Yes I know. :slight_smile:

I believe there is also a way to do this within RobotC without the switch, but I’m not sure.

I think he is asking for a program that “records” what you did in the driver to then recreate it during auton.

Owen Marshall has a youtube video where he demonstrates this: [http://www.youtube.com/watch?v=h6qVm9rJR6I

Owen commented on the video and explained how it was done: “This was done by printing to the debug stream while the robot runs, then saving the code on a computer.”](http://www.youtube.com/watch?v=h6qVm9rJR6I)

The easiest way to do this would be to simply take motor power/joystick readings some number of times every second and plug that data into an array, then apply those powers back to the motors during the autonomous portion at the same time intervals.

A better way to do this would be to record encoder positions at certain time intervals, plug them into an array, and then use a PID control loop in order to try to replicate the movement.

The best way I can think of would be to use (x,y) position tracking code, and record points at certain time intervals, then use a PID control loop to play them back. However, I had some problems with this method. Although the (x,y) position tracking code worked flawlessly, I was having a lot of trouble with creating a calculation to determine left and right motor speeds to apply in order to reach a destination using (x,y) coordinates. Perhaps someone else has an idea for that?

~Jordan

I can understand how this would be helpful, however you have to consider a few things.

  1. There are little adjustments you make in drive control that you don’t want in Autonomous.

  2. If you mess-up the routine, you have to start over.

Decide for yourself, but this is why we don’t do this.

You can add sensors and use debugs to print those sensor values and then store those in a program.

Your right. It isn’t worth a second 15s try. Coding is so much faster. Why wouldn’t you want adjustments that are designed to perfectly line you up in your autonomous. Is your goal to miss?

I agree with the other statements here. I remember getting this to work last year as a side project, but never ended up using it. It’s much more effective to use sensors, even on a limited budget. I make no promises as to whether or not the code below currently works I haven’t compiled or ran it in quite some time. It should set you in the right direction. The code will print to the debug stream a copy-pastable autonomous routine ready to go (commands included).

I’m sure there are more elegant ways of achieving this (perhaps creating an array, or something similar), but this makes the most sense to me, at least at the time of writing the code. :smiley:

The code also uses 1 solenoid digital out, you should be able to spot it. I had to Find/Replace all of the variable names, so a couple of variable references might be broken. If you want to use this, please rewrite it so that you can better understand the code.

task main()
{
	string time;
	string motorPort1;
	string motorPort2;
	string motorPort3;
	string motorport4;
	string motorPort5;
	string motorPort6;
	string motorPort7;
	string motorPort8;
	string SVS;
	string motorPort9;
	string motorPort10;

	int PrevTime = 0;
	int PrevPort1 = 0;
	int PrevPort2 = 0;
	int PrevPort3 = 0;
	int PrevDRR = 0;
	int PrevPort5 = 0;
	int PrevSol = 0;
	int PrevPort9 = 0;
	int PrevPort10 = 0;

	// Initial motor values... just in case, or if you want to set servo or DigitalOut
	writeDebugStreamLine("motor[port1] = 0;");
	writeDebugStreamLine("motor[port2] = 0;");
	writeDebugStreamLine("motor[port3] = 0;");
	writeDebugStreamLine("motor[port4] = 0;");
	writeDebugStreamLine("motor[port5] = 0;");
	writeDebugStreamLine("motor[port6] = 0;");
	writeDebugStreamLine("motor[port7] = 0;");
	writeDebugStreamLine("motor[port8] = 0;");
	writeDebugStreamLine("SensorValue[solenoid] = 0;");
	writeDebugStreamLine("motor[port9] = 0;");
	writeDebugStreamLine("motor[port10] = 0;");

	string waitStatement;

	while (true)
	{
		/* Driver code goes here */

		wait1Msec(25);

		if (time10[T1] > PrevTime) { // Only check at staggered points
			if ((motor[port1] != PrevPort1) || (motor[port2] != PrevPort2) || (motor[port3] != PrevPort3) || (motor[DRR] != PrevDRR) || (motor[port5] != PrevPort5) || (SensorValue[solenoid] != PrevSol) || (motor[port9] != PrevPort9) || (motor[port10] != PrevPort10)) {
				// Check to see if any changes to motor values have been made. If so, print the time it took from last new print.
				sprintf(waitStatement, "%s%i%s", "wait1Msec(", time1[T1], ");");
				writeDebugStreamLine(waitStatement);
				time1[T1] = 0;
			}
			if (motor[port1] != PrevPort1) 
			{ // If Motor port1 has changed, print its new value. Same procedure below (shortened up for length just because)
				sprintf(motorPort1, "%s%d%s", "motor[port1] = ", motor[port1], ";"); 
				writeDebugStreamLine(motorPort1); 
				PrevPort1 = motor[port1]; 
			}
			if (motor[port2] != PrevPort2) { sprintf(motorPort2, "%s%d%s", "motor[port2] = ", motor[port2], ";"); writeDebugStreamLine(motorPort2); PrevPort2 = motor[port2]; }
			if (motor[port3] != PrevPort3) { sprintf(motorPort3, "%s%d%s", "motor[port3] = ", motor[port3], ";"); writeDebugStreamLine(motorPort3); PrevPort3 = motor[port3]; }
			if (motor[DRR] != PrevDRR) { sprintf(motorDRR, "%s%d%s", "motor[DRR] = ", motor[DRR], ";"); writeDebugStreamLine(motorDRR); PrevDRR = motor[DRR]; }
			if (motor[port5] != PrevPort5) {
				sprintf(motorPort5, "%s%d%s", "motor[port5] = ", motor[port5], ";"); sprintf(motorPort6, "%s%d%s", "motor[port6] = ", motor[port5], ";");
				sprintf(motorPort7, "%s%d%s", "motor[port7] = ", motor[port5], ";"); sprintf(motorPort8, "%s%d%s", "motor[port8] = ", motor[port5], ";");
				writeDebugStreamLine(motorPort5); writeDebugStreamLine(motorPort6); writeDebugStreamLine(motorPort7); writeDebugStreamLine(motorPort8); PrevPort5 = motor[port5];
			}
			if (SensorValue[solenoid] != PrevSol) { sprintf(SVS, "%s%d%s", "SensorValue[solenoid] = ", SensorValue[solenoid], ";"); writeDebugStreamLine(SVS); PrevSol = SensorValue[solenoid]; }
			if (motor[port9] != PrevPort9) { sprintf(motorPort9, "%s%d%s", "motor[port9] = ", motor[port9], ";"); writeDebugStreamLine(motorPort9); PrevPort9 = motor[port9]; }
			if (motor[port10] != PrevPort10) { sprintf(motorPort10, "%s%d%s", "motor[port10] = ", motor[port10], ";"); writeDebugStreamLine(motorPort10); PrevPort10 = motor[port10]; }
		}
		PrevTime = time10[T1];

	}
}

There are ways around this.

For example:
1 - Push a button on the joystick which writes the encoder values to the debug stream, and then resets the encoders and gyro.
1 - Or push a different button that writes the gyro value to the debug stream, and then resets the encoders and gyro.
2 - Then, drive wherever.
3 - Repeat.

There you have all your values ready and waiting for you to copy into your routine structure.
To make it really snazzy, have it spit out code into the debug stream, so you copy & paste the entire debug stream into a new file, and there you have your autonomous routine without any modification.

This only records the values at the end of each “step”, not the ones in the middle, so it is ok to make those “little adjustments” in driver control.

Thanks for the help guys! Programming it is a lot more accurate and faster but I usually never have time to do so because my team usually never gives me time to do so, and we end up having no auton or a really bad one so I just wanted something like this as a backup in case something goes wrong.