Need help navigating "maze" with clawbot

I am trying to make a clawbot solve the simple “maze” (attached drawing).
I wrote the code, however it will sometimes work but sometimes veer off course at random. Its also a fight trying to guess how far it should be going.
How can I make the robot be able to go to start to end to start and repeat consistently enough that I could leave it on a loop and not have it fail?

Maybe something to do with the right hand rule (or whatever it’s called)? Basically if you keep your right hand on the wall of a maze at all times you will eventually get to the end. Similarly, you could use something like an ultrasound sensor to check that the robot is near a wall on the right side.

The “maze” is really just tape on the floor. The path is constant and can be preprogrammed. The problem is that the clawbot doesnt always do the same thing with the same code.

What specifically do you mean by this? For example, does the robot sometimes turn from the wrong position, throwing off the rest of its preprogrammed sequence?

1 Like

Are you using encoders and/or a gyro?

Yes, in a way. It gets to the right general area but the inaccuracies stack up and by the time it gets to the end it ends up crossing a line usually.

I’m using one encoder to determine distance.

Start by trying to move slower. Max your speed at say 65. The errors from compensating from the line sensor will be less. You won’t get as far off course.

One encoder can get you wheel rotations. However, if your robot veers off course, you are measuring the distance traveled on a curve, not a straight line. If your robot has to correct for the line sensor, then you get a larger reading as you move away but less as you come back. it should even out but only after the compensating move (if it actually happens; if you went in a circle you are waaay off now).

Using two encoders averaged together on left/right can help with this too. Adding in a gyro and figuring out the arc distance to have a true X and Y coordinate of the robot center is much more complex.

@Team80_Giraffes’ suggestions are a great starting point. If after implementing those you’re still going off course, you may want to look at using a PID controller to manage the error produced by the motors.

@Team80_Giraffes @hotel

Here’s the code I have currently. I’m new to programming so if you could help me out and suggest improvements that I can implement that would be very useful


#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, in1, leftLineFollower, sensorLineFollower)
#pragma config(Sensor, in2, centerLineFollower, sensorLineFollower)
#pragma config(Sensor, in3, rightLineFollower, sensorLineFollower)
#pragma config(Sensor, in5, gyro, sensorGyro)
#pragma config(Sensor, dgtl1, rightEncoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl4, leftEncoder, sensorQuadEncoder)
#pragma config(Sensor, dgtl6, touchSensor, sensorTouch)
#pragma config(Sensor, dgtl8, sonarSensor, sensorSONAR_cm)
#pragma config(Sensor, dgtl11, armEncoder, sensorQuadEncoder)
#pragma config(Sensor, I2C_1, rightIME, sensorQuadEncoderOnI2CPort, , AutoAssign )
#pragma config(Sensor, I2C_2, leftIME, sensorQuadEncoderOnI2CPort, , AutoAssign )
#pragma config(Sensor, I2C_3, armIME, sensorQuadEncoderOnI2CPort, , AutoAssign )
#pragma config(Motor, port2, rightMotor, tmotorVex393_MC29, openLoop, driveLeft, encoderPort, I2C_2)
#pragma config(Motor, port6, clawMotor, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port7, armMotor, tmotorVex393_MC29, openLoop, reversed, encoderPort, I2C_3)
#pragma config(Motor, port9, leftMotor, tmotorVex393_MC29, openLoop, reversed, driveRight, encoderPort, I2C_1)

int speedMult = 60;

void driveStraight (float distance){
	SensorValue(rightEncoder)=0; SensorValue(leftEncoder)=0;
	while(SensorValue(leftEncoder) < 600*distance){
		if(SensorValue(leftEncoder) == SensorValue(rightEncoder))
		{motor[leftMotor] = speedMult; motor[rightMotor] = speedMult;}
		if(SensorValue(leftEncoder) > SensorValue(rightEncoder))
		{motor[leftMotor] = speedMult; motor[rightMotor] = (speedMult+5);}
		if(SensorValue(leftEncoder) < SensorValue(rightEncoder))
		{motor[leftMotor] = (speedMult+5); motor[rightMotor] = speedMult;}
	}
	motor[leftMotor] = 0; motor[rightMotor] = 0;
	sleep(1000);
}
void turnRight (float distance){
	SensorValue(rightEncoder)=0; SensorValue(leftEncoder)=0;
	while(SensorValue(leftEncoder) < 270*distance){
		if(SensorValue(leftEncoder) == SensorValue(rightEncoder))
		{motor[leftMotor] = speedMult; motor[rightMotor] = -speedMult;}
		if(SensorValue(leftEncoder) > SensorValue(rightEncoder))
		{motor[leftMotor] = speedMult; motor[rightMotor] = -(speedMult+5);}
		if(SensorValue(leftEncoder) < SensorValue(rightEncoder))
		{motor[leftMotor] = (speedMult+5); motor[rightMotor] = -speedMult;}
	}
	motor[leftMotor] = 0; motor[rightMotor] = 0;
	sleep(1000);
}
void turnLeft (float distance){
	SensorValue(rightEncoder)=0; SensorValue(leftEncoder)=0;
	while(SensorValue(leftEncoder) > -270	*distance){
		if(SensorValue(leftEncoder) == SensorValue(rightEncoder))
		{motor[leftMotor] = -speedMult; motor[rightMotor] = speedMult;}
		if(SensorValue(leftEncoder) < -SensorValue(rightEncoder))
		{motor[leftMotor] = -speedMult; motor[rightMotor] = (speedMult+5);}
		if(SensorValue(leftEncoder) > -SensorValue(rightEncoder))
		{motor[leftMotor] = -(speedMult+5); motor[rightMotor] = speedMult;}
	}
	motor[leftMotor] = 0; motor[rightMotor] = 0;
	sleep(1000);
}
task control ()
{
	motor[leftMotor] = 0; motor[rightMotor] = 0;
	while(1 == 1)
	{
		motor[leftMotor] = vexRT[Ch3];
		motor[rightMotor] = vexRT[Ch2];
		if(vexRT[Btn5D] == 1)
		{
			turnLeft(1);
		}
		if(vexRT[Btn6D] == 1)
		{
			turnRight(1);
		}
	}

}
task auton ()
{
	while(1 == 1)
	{
		////////////////////
		driveStraight(1.8);
		////////////////////
		turnRight(1);
		driveStraight(0.9);
		turnRight(1);
		////////////////////
		driveStraight(2.1);
		////////////////////
		turnLeft(1);
		driveStraight(0.8);
		turnLeft(1);
		////////////////////
		driveStraight(1.7);
		////////////////////
		turnRight(1);
		driveStraight(0.8);
		turnRight(1);
		////////////////////
		driveStraight(2);
		////////////////////////////////////////
		turnRight(2);
		////////////////////////////////////////
		driveStraight(2.3);
		////////////////////
		turnLeft(1);
		driveStraight(1);
		turnLeft(1);
		////////////////////
		driveStraight(2.3);
		////////////////////
		turnRight(1);
		driveStraight(1);
		turnRight(1);
		////////////////////
		driveStraight(2.3);
		////////////////////
		turnLeft(1);
		driveStraight(1);
		turnLeft(1);
		////////////////////
		driveStraight(2.3);
		////////////////////
		turnRight(2);
	}
}
task main()
{
	startTask(control);
	while(1==1)
	{
		if(vexRT[Btn8D] == 1)
		{stopTask(control);startTask(auton);}
		if(vexRT[Btn8R] == 1)
		{stopTask(auton);startTask(control);}
		if(vexRT[Btn7D] == 1)
		{SensorValue(rightEncoder)=0; SensorValue(leftEncoder)=0;}
	}
}

That should work. Having a nice slow speed should help.

If both motors turn relatively at the same speed it should get you there and correct itself. However you are dependent upon the left encoder only. I would average the two together on the straight.

Averaging the absolute values of the turns is another way of ensuring one has not gone haywire. Or use just one encoder. Using the outside wheel encoder on the turns seems to have better luck for some reason. I am not sure if it is some scrubbing of the wheels or what.