Replay motions -- how do you really want this to work?

In the “Robot C” wish list is the request of “replay”. I’m really wondering how you want this to work.

In a brute world, there would be a snapshot at 22ms intervals of all the motor speeds stuffed away. The playback program would just pull a record, set the motor speeds. Lather, rinse, repeat, WIN(?!?)

How do you plan for variations in robot battery, floor tiles, initial positioning, game element placements, differences in field setups, etc.

We all know that timed motion doesn’t work.

All of the computer systems that I use/see have some levels of sensors. A playback scheme would need to have sensors in it somehow.

So how would you want the playback to work?

When I was writing a playback method (before it crashed and burned) was to record the controller and use PIDs everywhere, which is not a perfect solution, but I think it would be more effective than just setting motor values.

Time might (emphasis on might) work in starstruck because the scoring zones are so large and do not require extreme precision. Sensors will always be more reliable.

Of course. What @Foster is complaining about is that everyone wants a general built in recording system. They want that system to work out of the box for every robot with every mechanism. These are mechanisms without tuned PID values or without sensors at all. The request is pretty insane. Every mechanism on every robot in controlled and sensed in a different way.

I am with Foster, its a silly ask.

I’m trying to make a playback method that’s sensor based so more accurate (still less than a pid though) but it’ll need a free day or two with my robot which I won’t get for a while… the base code goes like:
If(motor[arm]!=motorValueArmOneLoopAgo)
{
WriteToDebugStream(“while(abs(sensorValue[arm])<%d”,sensorValue[arm]);
WriteToDebugStream(“)motor[arm]=%d”,motorValueArmOneLoopAgo);
WriteToDebugStreamLine(“;”);
SensorValue[arm]=0;
}
After you drive it to do what you want with this if statement running in the background for all your motors, you can copy and paste the debugger stream straight into your autonomous… in theory…

Building a general purpose recording software would be really hard. Just in the last few minutes I think I figured out how it would have to be done but the issue is every mechanism would need a its own update control loop function that took in parameters from the playback system and then would need a get goal value function. The goal value function would be called during recording and then those values would be fed into the update control loop function during playback. The issue is that a good general system would be decently complicated for a user to use.(good handful of pointers etc) Less general programs could just assume everything.

Something like this library


pos_PID_SetTargetPosition(&myPID, 100);

A line like this would be called for every mechanism you gave the recorder every time step. So each mechanism would need to be initialized and exist in an abstract enough way. Then a user would have to make lots of different types of controllers. Maybe Bang Bang, something for piston control, a controller that just sets power to the input value for the mechanisms that don’t have sensors(trivial).

Every trivial mechanism would need a struct and 2 functions created for it. I imagine a noob programmer would find the code required to work with a well written general purpose recording software above their level.

1 Like

@MayorMonty – This, like your electronic notebook, is a learning experience. It’s OK to ask for something, but when the go “OK, how does it work” you need some details about how the interaction would work.

@tabor473 – Thanks for your support. It may not be a silly ask, or it may be. Lets see what they want it to do. Both you and I are predisposed to one way to look at it, there may be another way. As you know “No Requirements = No Code” is the first thing they teach in programming class (or it should be).

@tabor473 @Foster I’m not disagreeing with you, there’s no way you could “solve” autonomous programming with one cleverly written script. Perhaps, in the future, the best way to do autonomous runs is to download some script and customize it to your robot, but there will be no “one and done” system that you could include in ROBOTC, because it would need intimate knowledge of your Robot that could not adequately provide. When I was writing that system, I wasn’t designing it to be something someone might be to package into ROBOTC (I was actually using PROS, but that’s beside the point), I wanted a solution I could use. Maybe I’ll revisit it, but like @tabor473 said, making such a general purpose recording mechanism would require unimaginable complexity for it to be general enough to work on ALL robots.

I am fully in agreement about sensor based programming being the proper solution, but expect that the people asking for this playback feature are looking for (or would accept) a brute-force record of a human controlling the robot for 15 seconds.

If that premise is correct, then wouldn’t you want to record the signals from the controller at x frequency, then call a function that holds all the signal and runs the same code they use in their user control task?

I am not much of a programmer, but something like this:


int C1, C2, C3, C4, B5D, B5U, B6D, B6U, B7D, B7U, B7L, B7R, B8D, B8U, B8L, B8R;

// paste this function above the pre-autonomous task in your competition template code
void replayVexRT(int C1, int C2, int C3, int C4, int B5D, int B5U, int B6D, int B6U, int B7D, int B7U, int B7L, int B7R, int B8D, int B8U, int B8L, int B8R)
{
	// paste your user control code here, replacing all the vexRT] statements with the corresponding variable
	// if your button code is written as a boolean test for true or false, change true to 1 and false to 0
	wait1Msec(50);
}

task recordVexRT()
{
	while(true)
	{
		C1 = vexRT[Ch1];
		C2 = vexRT[Ch2];
		C3 = vexRT[Ch3];
		C4 = vexRT[Ch4];
		B5D = vexRT[Btn5D];
		B5U = vexRT[Btn5U];
		B6D = vexRT[Btn6D];
		B6U = vexRT[Btn6U];
		B7D = vexRT[Btn7D];
		B7U = vexRT[Btn7U];
		B7L = vexRT[Btn7L];
		B7R = vexRT[Btn7R];
		B8D = vexRT[Btn8D];
		B8U = vexRT[Btn8U];
		B8L = vexRT[Btn8L];
		B8R = vexRT[Btn8R];

		writeDebugStreamLine("replayVexRT(", C1, ",%d", C2, ",%d", C3, ",%d", C4, ",%d", B5D, ",%d", B5U, ",%d", B6D, ",%d", B6U, ",%d", B7D, ",%d", B7U, ",%d", B7L, ",%d", B7R, ",%d", B8D, ",%d", B8U, ",%d", B8L, ",%d", B8R, ");");

		wait1Msec(50);
	}
}


task main()
{
	writeDebugStreamLine("Begin recording in: 3");
	wait1Msec(1000);
	writeDebugStreamLine("Begin recording in: 2");
	wait1Msec(1000);
	writeDebugStreamLine("Begin recording in: 1");
	wait1Msec(1000);

	startTask (recordVexRT);
	writeDebugStreamLine("BEGIN AUTON RECORDING");

	writeDebugStreamLine("// Copy the following lines into your autonomous task:");

	clearTimer(T1);
	while (time1[T1] < 15000)
	{
		// paste user control code here
	}

	stopTask (recordVexRT);
	writeDebugStreamLine("//END AUTON RECORDING");

	// stop all motors
	motor[port1] = motor[port2] = motor[port3] = motor[port4] = motor[port5] = motor[port6] = motor[port7] = motor[port8] = motor[port9] = motor[port10] = 0;
}

1 Like

This actually looks like it should work. Nice job. It’s pretty simple too. Thank you for this(I may try it out when i get the time).
:slight_smile:

YW. I’ve been playing with it a bit since I posted (not with a bot, just in code) and added a line to the record that lists the battery voltage at the time of the recording. It might be possible to modify the frequency of the playback based on the difference in recorded battery voltage and the voltage at the time of playback.

Nice on the recording side. Need to remember that teams use dual controls.

Anyone up for taking the output, stripping out the not used actions and creating a RobotC player?

Post back ASAP after testing! We’re all very eager to see if it works!

Well my team decided to do an intake rebuild so it’s going to be awhile before I can find time to take out all the unnecessary controls and add in the ones i need as well as test it on our robot. I may try and add something in that records the encoder counts as well(for convenience) but that will just make it take longer because I’m not much of a programmer myself :stuck_out_tongue:

As what I can tell, it will be hard to differentiate when the robot stops because the program won’t know if the robot is either using encoders, time, or maybe something else to find the distance the robot has gone. So does the recording code add a certain amount of time whenever nothing is pressed or before any change in movement?

It doesn’t record the robot movement at all. It records joystick movement and controller button values and displays them in order. Everything in the code will only operate within a 15 second time limit and after that it will shut off.

@CATaclysm Delta_II @Joseph W(182 C)

Aye, that’s the rub. If you are using just the joystick entries, then you need to have a way for the replay to use the code that was used to record the events. A little tricky, how would you make that happen so the input values get fed back into the code to make use of the sensors. You don’t need to write the code here, talk about how to make it work.

Just recording the motor values may work, but need to remember to do digital ports for people with pneumatics. And the battery issue.

I understand the code here (kinda) but how are you guys planning to record this information so you can make it the atounimous later. Will it all be recorded on the lcd screen?

If you had sensors on everything, you could only display a command to the debug stream when the joystick input changed. For example, Btn5U controls the lift up. When Btn5U is no longer pressed, the lift potentiometer reads 1000. Write to debug stream “liftUpUntil(1000);”.

That’d be a bit harder to do with the drive, because it’s analog, but it should work for everything else.

oops, reread, and noticed I responded in error.