Odometry less accurate with third tracking wheel okapilib

My odometry is pretty accurate when I have two tracking wheels. However, when I add in the middle one it becomes much less accurate. I would like to have this third tracking wheel for accuracy, but if I can’t have it so be it. I made sure that my measurements for the third wheel were accurate and they are. Here’s my code.

#include "main.h"
using namespace okapi;
Motor frontLeftMotor(1, false, AbstractMotor::gearset::green, AbstractMotor::encoderUnits::degrees);
Motor frontRightMotor(2, true, AbstractMotor::gearset::green, AbstractMotor::encoderUnits::degrees);
Motor backRightMotor(3, true, AbstractMotor::gearset::green, AbstractMotor::encoderUnits::degrees);
Motor backLeftMotor(4, false, AbstractMotor::gearset::green, AbstractMotor::encoderUnits::degrees);

ADIEncoder leftEncoder('A', 'B', true);
ADIEncoder rightEncoder('C', 'D');
ADIEncoder middleEncoder('E', 'F', true);

pros::Imu Inertial(5);

std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()
.withMotors(frontLeftMotor, frontRightMotor, backRightMotor, backLeftMotor)
.withMaxVelocity(150)
.withSensors(leftEncoder, rightEncoder, middleEncoder)
.withGains(
		{0.0035, 0, 0}, // Distance controller gains
		{0.006, 0, 0}, // Turn controller gains
		{0.002, 0, 0.00006}  // Angle controller gains (helps drive straight)
)
.withDimensions(AbstractMotor::gearset::green, {{2.75_in, 10_in, 3_in, 2.75_in}, quadEncoderTPR})//gearset, diameter, track, ticks
.withOdometry()
.buildOdometry(); // build an odometry chassis

std::shared_ptr<okapi::XDriveModel> driveTrain = std::dynamic_pointer_cast<XDriveModel>(chassis->getModel());

Controller master;

void initialize() {//runs when program starts
	pros::lcd::initialize();
}

void disabled() {
	chassis->moveDistance(0_in);
}//runs when disabled

void competition_initialize() {}//after initialize before auton

void autonomous() {//after start comp
	chassis->setState({0_in, 0_in, 0_deg});
	chassis->driveToPoint({1_ft, 1_ft});
	chassis->turnToPoint({0_ft, 0_ft});
	chassis->driveToPoint({0_ft, 0_ft});
	chassis->turnToAngle(0_deg);
}
void opcontrol() {//after auton
	chassis->moveDistance(0_in);
	driveTrain->setBrakeMode(AbstractMotor::brakeMode::coast);
	while (true) {
			driveTrain->xArcade(master.getAnalog(ControllerAnalog::leftX),
	   	master.getAnalog(ControllerAnalog::leftY),
	    master.getAnalog(ControllerAnalog::rightX),
			0.3);

    pros::delay(20);
	}
}

There is nothing wrong with the okapi math. Either your encoder is broken, your tracking wheels are badly built, or something else on your end is messing with the tracking. Having good tracking is mostly dependent on the hardware.

That being said, your middle encoder is three inches behind the center of rotation?

What do you mean by less accurate? Usually your chassis width needs to be tuned to a few decimals of precision. Using a third encoder is probably just bringing out the incorrect tuning.

11 Likes

Thank you, I made the measurements more precise and it’s doing better. Sometimes the robot turns 270 degrees instead of 90 when using odometry. Do you know why that is?

Its currently an unfixed limitation of okapi, that it won’t take the shortest path. You can work around it by wrapping the odometry angle yourself, but honestly why can’t you make your own movement functions.

2 Likes

I think I’ll making my own movement functions. How do I get the x and the y of where I am? I did chassis->getState().x and it is a variable qlength. I cannot find a way to get the qlength to be a double. Any ideas? Should I just use the encoder values?

To convert a dimensioned unit to a value, use .convert(unit).
For example, use x.convert(inch).

1 Like

This has been giving me an output that is massive.

You should not start the odometry until the sensors have a chance to initialize.

2 Likes

I have a somewhat related question. I’m running position tracking and motion control on vexcode. After any maneuver larger than a simple straight line or turn, when I have the robot return to the origin, it ends around 2 inches off of where it should be, in one or both directions.

I know the issue is not with the motion control, as I’m outputting values to the brain screen, and they are correct. Is there anything I should try to increase the accuracy of my position tracking? (using a three wheel setup on x-drive)

I wait two seconds in the initialize. Then I used this code

pros::lcd::print(0, "%d", chassis->getState().x.convert(inch));

This is what outputs.

Make sure that your tracking wheels are making good contact with the ground and that all of your measurements are accurate. This helped me the most and I’m using a mecanum drive with three tracking wheels.

Alright, thanks. I’m thinking of adding more rubber bands, that might do the trick.

Nevermind, I had to use %f instead of %d. That fixed it.

1 Like