Problems with WPI robot characterization

We’ve recently begun working with WPI’s new characterization tool and have run into a few difficulties.

Here’s our code GitHub - Team5712/FRC_2020: Java code for FRC 2020 competition.

When we tried running this, our robot began to run backwards and didn’t seem to stop. The odometry and gyro seem to be working fine but we can’t seem to follow a trajectory. What’s also odd is that our left motor is inverted in our code but isn’t for the characterization tool.

Our graphs for the characterization are as follows. It doesn’t look like the accepted graph on WPI. It appears like it’s missing a side or something.

We would appreciate the help, thanks.

image

Here is our robot config file…

{
    # Class names of motor controllers used.
    # Options:
    # 'WPI_TalonSRX'
    # 'WPI_TalonFX' (for Falcon 500 motors)
    # 'WPI_VictorSPX'
    # Note: The first motor on each side should always be a Talon SRX/FX, as the
    # VictorSPX does not support encoder connections
    "rightControllerTypes": ["WPI_TalonSRX", "WPI_VictorSPX"],
    "leftControllerTypes": ["WPI_TalonSRX", "WPI_VictorSPX"],
    # Ports for the left-side motors
    "leftMotorPorts": [1, 2],
    # Ports for the right-side motors
    "rightMotorPorts": [5, 6],
    # Inversions for the left-side motors
    "leftMotorsInverted": [False, False],
    # Inversions for the right side motors
    "rightMotorsInverted": [False, False],
    # Wheel diameter (in units of your choice - will dictate units of analysis)
    "wheelDiameter": 0.1016,
    # If your robot has only one encoder, remove all of the right encoder fields
    # Encoder pulses-per-revolution (*NOT* cycles per revolution!)
    # This value should be the pulses per revolution *of the wheels*, and so
    # should take into account gearing between the encoder and the wheels
    "encoderPPR": 512,
    # Whether the left encoder is inverted
    "leftEncoderInverted": True,
    # Whether the right encoder is inverted:
    "rightEncoderInverted": False,
    # Your gyro type (one of "NavX", "Pigeon", "ADXRS450", "AnalogGyro", or "None")
    "gyroType": "NavX",
    # Whatever you put into the constructor of your gyro
    # Could be:
    # "SPI.Port.kMXP" (MXP SPI port for NavX or ADXRS450),
    # "I2C.Port.kOnboard" (Onboard I2C port for NavX)
    # "0" (Pigeon CAN ID or AnalogGyro channel),
    # "new WPI_TalonSRX(3)" (Pigeon on a Talon SRX),
    # "leftSlave" (Pigeon on the left slave Talon SRX/FX),
    # "" (NavX using default SPI, ADXRS450 using onboard CS0, or no gyro)
    "gyroPort": "SPI.Port.kMXP",
}
2 Likes

Your graphs look fine; it’s not “missing a side,” the characterization tool does not care about sensor inversion.

The DifferentialDrive class automatically inverts one side of the drive through its ordinary drive methods, which is probably why you are surprised by the inversion in code.

You’re using the odometry class incorrectly in your code; you are supposed to feed it the raw encoder positions, not the deltas from each iteration. Additionally, your unit scaling on your characterization graphs seems suspect; please check to make sure you’ve specified your encoder edges per rotation correctly.

1 Like

Sorry to hijack the thread, but does this mean we don’t have to call setInverted on talons if we’re using them in a DifferentialDrive?

1 Like

Yes

Wow, no wonder our bot wasn’t working. TiL

Lol, we learned the tough way when we started doing donuts. Lucky us that we put it on blocks because we don’t trust our programming

FWIW the automatic inversion was a horrible mistake and the whole WPILib team wishes we could change it, but alas, it is too late.

Fortunately, the DifferentialDriveKinematics class does not do any such automatic inversion, so you can always just use that instead.

2 Likes

Can you elaborate on unit scaling? Our graphs look similar, however with a much larger timescale. Acceleration and velocity are on the same order of magnitude as the OP. Distances that are output from the characterization tool look reasonable relative to actual distance traveled, and I believe edges per wheel rotation that I’ve provided the tool are accurate. I could be wrong though so a quick sanity check of the graph would be appreciated.

image

1 Like

Notice that your velocity is capping out at ~1 unit per second during your dynamic test. Assuming you used the default value of 6 volts, that would put your max speed at ~2 units per second.

Assuming you’re measuring in meters, this would correspond to a very slow robot. I could believe it for a shifting robot in low gear, but I’m skeptical for a single-speed bot.

We’ve also been having issues with getting RamseteCommand to work. I just noticed that the example for RamseteCommand uses a negated right output in tankDriveVolts, but doesn’t invert the right side speed controller.

My standard procedure for getting path following to work is to make sure that, 1. Positive power drives the robot forward (which usually means setting inverted on the right speed-controller) 2. Forward motion results in positive encoder output. 3. Gyro has positive output in the CCW direction (also negating in most cases). Keeping track of where we do and not have to add negatives to the output/inputs just makes me want to tear my hair out. So, when we added our SparkMaxes to it, it’s been driving off in weird directions and spinning, etc… I’m hoping that taking out the negation in that function fixes things.

Me to Builders: “The wood is across the shop, it will be fine!“
Me ten seconds later: SPACEBAR SPACEBAR SPACEBAR

Alas, this is a consequence of the aforementioned Bad Decision to make DifferentialDrive negate the right-side output.

FWIW, dealing with inversion issues is a constant and will never go away. It’s just one of those things that will always suck, and we’ll always have to deal with.

Sure, but what I’ve run into with student coders is a tendency to throw a negation into random functions in order to deal with it and then we’re spending hours trying to debug to find where things are going wrong. The only way to deal with it, sanely, is to minimize the number of places (Constants file or config) where they need to occur and then everything else can work off the same assumptions. Fortunately, we don’t use Differential Drive, so we can avoid that issue.

I love, by the way, the use of kGyroReversed in the example to switch the gyro where it is needed.
And the example code and tutorial have been terrific otherwise, so thank you for that work!

That is definitely the right approach to take. I’m glad you’ve liked the examples!

1 Like

Yes, we used the default step voltage of 6 volts. Given that our bot does indeed have both low and high gearing, and I used low gear, 2 meters per second at the top end would not be unreasonable. Thanks for taking a look and providing your feedback!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.