Automatic 2 Speed Drivetrain Shifting Code

I’ve been looking into automatic drivetrain shifting code. I’ve found this thread pretty helpful so far, specifically
apalrd’s post. I’ve basically been looking all over this search. I’ve also found 254’s driving code here and here, but I just don’t know enough C++ to understand exactly how it works (or if it even auto-shifts! - I was told that they do but I can’t find where it happens). Anyways, I’m just looking for some kind of rundown on how exactly you’d determine whether to shift up or down. So far I’ve come up with this:

    if (input > shiftersInputThreshhold && m.encoder.getRate() > shiftersSpeedThreshhold 
        // Make sure not to shift too much
        && (System.currentTimeMillis() - lastShift) > shiftersShiftTimeLimit * 1000) {
        lastShift = System.currentTimeMillis();
    } else {

Although I can’t think of them right now, I have a pretty strong feeling that there are a lot of things that this doesn’t account for. Just as much, I have no idea what to set “shiftersSpeedThreashhold” or “shiftersInputThreashhold”. It seems arbitrary to me. I’ve been told (and others in old threads have alluded to) that JVN has some kind of way to determine those kinds of threashholds. We’re using 2 CIMs and the super shifter gear box (from what I’m told). Is there anywhere you could point to for some ways for algorithms to shift gears?

My goal here is for it to shift when the robot is going fast enough that it needs to, and have enough torque to push others around.

Oh and one last thing, should shifting take turning into account? Right now that’s a little bit difficult to do with my code (for implementation reasons). What benefit would something like this

if(abs(turn) > 0) doNotShiftGears()

give me? Is it really necessary if we aren’t using tank drive?

Here is how we implemented auto shifting this year. It seemed to work well but we decided we wanted to be able to manually control our shifting due to interlocking that we implemented between the chassis and other systems.

We’ve never used one in competition, but I have a basic idea of how to get started. It’s helpful to have a simple functions that approximates the fps of each joystick value. You want to be continuously checking for certain parameters that would cause shifting, so set up code to measure the speed of the wheels and also the acceleration. You need to make sure that you wait 1 second between shifts, and that you don’t end up shifting while the driver is turning. The most useful is if somebody starts pushing you, and you need to shift to the slow gear to push them away. This can be detected if the actual speed of the robot is >10% away from where the joysticks are and if the average deceleration over the last second or so exceeds a certain amount. The problem with this is when the drivers hit a wall, it shifts into high gear and wears down the gear. Also, I’ve never tried it, but it may be possible to reach the max speed faster if you start in one gear, then shift up. If you want to try this, I would try starting with code that puts you in your slow gear when you are traveling slowly, and something that puts you in high gear if it detects that the driver has commanded a speed faster than a certain constant.

How did you determine Constants.AUTO_SHIFT_UP_THRESHOLD to be 0.9 and Constants.AUTO_SHIFT_DOWN_THRESHOLD to be 0.5? Just trial and error?

Also why did you multiply Constants.AUTO_SHIFT_DOWN_THRESHOLD.get() * Constants.CHASSIS_MAX_LOW_ENCODER_RATE.get() ?

The code makes sense, but I don’t think it does exactly what we’d like. Thanks for sharing though.

Yeah just trial and error. We have the ability to change variables without downloading code so that would help tweaking that. We never spent much time with the auto shift so we never got around to actually tweaking the 0.5 and 0.9 values.

We did that second part because our AUTO_SHIFT_THRESHOLD variables are meant to be percentages of our max low speed.

No problem. The way that we were able to distinguish between driving straight and rotating was by taking the average encoder rate. This way when you turn, rate will be around 0 and would shift to low gear.

Makes sense. I’m curious, how long / how many samples did you use for calculating the average?

I’ve not used Encoder.getRate() much. What kind of units would it return? (assuming default setup with the gear box and whatnot) How would I compare it to the joystick speed (-1 to +1)?

Also, is it bad to shift up if it is turning, but going forwards as well? (ie. +0.7 speed, -0.4 turn)

getRate returns encoder counts per second. one side of the drivetrain will be a negative value and the other side will be positive. To take the average, you’ll have to subtract one side from the other. If you successfully average both sides, the average rate should directly vary with the joystick setpoint.

About shifting up on a curve, it depends on how well your robot turns in high gear. Our robot doesn’t turn well in high gear so shifting up in the middle of a curve just results in the robot driving mostly straight.

We don’t auto shift. In fact we barely ever shift out of high gear in teleop. This year we are using low gear for autonomous and last year we used it to auto align to the goal, but these states were explicitly set.