PROS Okapilib ChassisControllerPID major issues

After switching from Okapilib’s chassis controller integrated to chassis controller PID (By declaring withgains), the robot can no longer even drive straight, moving forward slightly before veering sharply off in a swing turn infinitely (anti-clockwise, or counter-clockwise for you Americans) when the moveDistance function is called. The PID gains aren’t tuned well yet though so don’t judge the code too much, its very much a test. The odometry reads the correct position after a translation, the same code was used but with .withgains commented and it worked fine (integrated PID controller). Here is the code:

#include "main.h"
#include "okapi/api.hpp"
using namespace okapi;

std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()

.withMotors({1, -2}, {-4, 3})
.withDimensions(AbstractMotor::gearset::green, {{3.25_in, 393_mm}, 540})
.withSensors
(
	ADIEncoder{'A', 'B'},
	ADIEncoder{'E', 'F'},
	ADIEncoder{'C', 'D', true}
)
.withGains({0.002, 0, 0.00003}, {0.001, 0, 0.00003}, {0.001, 0, 0.00003})
//.withClosedLoopControllerTimeUtil(50, 5, 200_ms)
.withOdometry({{2.75_in, 212_mm, 120_mm, 2.75_in}, quadEncoderTPR})
.buildOdometry();

Just to make it clear, I am pretty sure that this is not an issue with chassis scales/dimensions or quad encoders being inverted, I am unsure, therefore, having little okapi PID or odometry experience, about why this issue is occurring.

Ok, so after some more testing, it turns out that my original post incorrectly stated that the robot could drive in a straight line, however I have now identified that it fails to even achieve this! I have updated the original post and title accordingly with the updated issue.
I would greatly appreciate a response on this thread as I have no idea about solving this issue, being inexperienced in Okapilib.

The behavior you describe does seem like one side’s encoders are reversed, though you also indicate that you’ve checked for that.

Could you post your full code, including the turnAngle or turnToAngle calls?

Certainly for the moveDistance calls, the Integrated Chassis Controller does not use the odometry wheels for “course correction” (while the tracking wheels are used for “course correction” in the PID Chassis Controller), so it is plausible that your ADIEncoder declaration for one of the encoders should be flipped. That said, the chassis’ odometry functionality should use them.

Printing out the OdometryState before and after the movement might be instructional and help debugging. I’d suggest starting with the turn movements first.

Also of note, the convention for OkapiLib’s odmetry is for positive Y to be “North” and positive X to be “East” in terms of compass headings.

1 Like

I did try reading the OdomState, and this, oddly, seems to yield the correct coordinates! Here is the full code:

#include "main.h"
#include "okapi/api.hpp"
using namespace okapi;

std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()

.withMotors({1, -2}, {-4, 3})
.withDimensions(AbstractMotor::gearset::green, {{3.25_in, 393_mm}, 540})
.withSensors
(
	ADIEncoder{'A', 'B'},
	ADIEncoder{'E', 'F'},
	ADIEncoder{'C', 'D', true}
)
.withGains({0.002, 0, 0.00003}, {0.001, 0, 0.00003}, {0.001, 0, 0.00003})
//.withClosedLoopControllerTimeUtil(50, 5, 200_ms)
.withOdometry({{2.75_in, 212_mm, 120_mm, 2.75_in}, quadEncoderTPR})
.buildOdometry();

void initialize() {}


void disabled() {}


void competition_initialize() {}


void autonomous()
{
	chassis->setMaxVelocity(50);
	chassis->setState({0_in, 0_in, 0_deg});
	chassis->moveDistance(10_in);
	printf("%s\n", chassis->getState().str().c_str());
	chassis->moveDistance(10_in);
	printf("%s\n", chassis->getState().str().c_str());
	chassis->turnAngle(90_deg);
	printf("%s\n", chassis->getState().str().c_str());
}

This simply gives the result explained in the original post (moves a few inches forward before moving in a swing turn to the left - right moves much faster than left)

What is the output of the 3 output lines for each run (PID vs Integrated)? Does the physical robot face “West” (e.g. anti-clockwise 90) with the withGains in while the physical robot faces “East” with withGains removed?

Chassis controller integrated:
image
Chassis controller PID:
[never made it past the first moveDistance]
It just moved in a continuous left hand turn until I stopped it.

Additional tests to run

  • Take out the 3rd tracking wheel from .withSensors
  • Flip one of the 2 ADISensors to reversed
  • Take out withSensors entirely (e.g. just a .withOdometry() with no arguments) so that the odometry just uses the built-in motor controllers

You should be able to run scenarios above with both Integrated and PID chassis

1 Like

On your output for the Integrated run, I find that first line to be somewhat concerning that the theta value is not zero…

I agree, on looking at the odomstate output, I am equally concerned! Does it have anything to do with:
image
at the start of some runs?

First test:
#include “main.h”
#include “okapi/api.hpp”
using namespace okapi;

std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()

.withMotors({1, -2}, {-4, 3})
.withDimensions(AbstractMotor::gearset::green, {{3.25_in, 393_mm}, 540})
.withSensors
(
	ADIEncoder{'A', 'B'},
	ADIEncoder{'E', 'F'}//,
	//ADIEncoder{'C', 'D', true}
)
.withGains({0.002, 0, 0.00003}, {0.001, 0, 0.00003}, {0.001, 0, 0.00003})
//.withClosedLoopControllerTimeUtil(50, 5, 200_ms)
//.withOdometry({{2.75_in, 212_mm, 120_mm, 2.75_in}, quadEncoderTPR})
.withOdometry()
.buildOdometry();

produced the same infinite turn for some reason?!

Possibly. You may what to add a short delay after setting the odometry state initially. Is your chassis externally geared? I’m not sure what the 540 number means as an argument to withDimensions

The 540 is the TPR because, as you guessed, the chassis is geared 36:60.
I thought that the set state function blocked until it had set things up, but I will try a delay now with the original (non-integrated) PID controller

I am no longer getting the tick diff warnings with a delay, however the main issue still persists. I will continue the tests. Thanks for the help so far!

We can come back to the 540 number and the external gearing later. My team ran into similar issues and there’s a patch to OkapiLib due soon to account for it.

Lets at least get to the point where it turns in the correct direction under both Integrated and PID chassis controllers first.

I’m assuming if you manually drive the robot with the motors declared this way, that it drives properly? Just trying to rule out whether the motors should be reversed…

1 Like

Well the autonamous worked fine without withgains (integrated controller) so I assume this rules out most of those kind of issues.

With this in mind, I can only assume that the issue must be with the PID controller setup as the odometry worked fine for adjusting the target for each movement when using the integrated controller and driveToPoint seemed to work fine, it seems that simply specifying the non-integrated controller through withgains has somehow messed it all up.

Ok, so after reversing one encoder (I had accidently removed the reverse parameter on one of them somehow), the moveDistance commands appear to work fine, but when given the turnAngle(90_deg) command, the robot rotates approximately 195 degrees clockwise!

image

Yeah, so now you’re where my kids are at. You have the following options:

  • Not use the PID chassis controller and stick with the Integrated one
  • Wait for the OkapiLib patch

The options aren’t mutually exclusive. You could use the Integrated chassis for now, get your auton routines coded, and switch to PID when the patch comes out.

1 Like

What exactly is the patch and do you know when it may arrive? Thanks for the help btw.