Autonomous code causing bot to run momentarily then abruptly stop

Hello! We are currently working on the code for our kitbot. The bot works as expected in tele-op, but we are having issues running autonomously.
When we try to run autonomous mode, the wheels move momentarily before abruptly stopping. This is inconsistent with our written autonomous commands and occurs for all versions.
Here is our public github

This is a gif of what happened when I enabled, disabled, and then re-enabled autonomous mode.
IMG_9289

1 Like

how long does it run before stopping? It is hard to tell from the gif. If you have a programmer you could try running the code in debug mode or placing print statements.

also, make sure this is not a power or comms issue. there are some lights flashing on your Rio maybe that has something to do with it.

I believe the problem in your code causing this is that you have RobotContainer setting a default command on the CANDrivetrain system to use joystick inputs, but your code in your Autos class creates commands that do not specify any requirements. During autonomous, both commands then try to run at once which causes issues.
The immediate fix would be to put the drivetrain in as a requirement when you are creating the RunCommands, but a better solution might be to create a command factory method (Organizing Command-Based Robot Projects — FIRST Robotics Competition documentation) on your CANDrivetrain class with arguments for speed, rotation, and timeout.
Depending on how you fix that issue, you might also run into another problem with your autonomous because of the way that you have the parentheses when calling withTimeout. Essentially, in your exampleAuto, every time you call withTimeout, you are actually adding a timeout to the command composition created by .andThen() when you presumably only wanted the timeout for the individual RunCommands. You should make sure the additional steps are structured as .andThen(new RunCommand( ... ).withTimeout(1)), not .andThen(new RunCommand( ... )).withTimeout(1). You can read more about command compositions at the WPILib docs: Command Compositions — FIRST Robotics Competition documentation.

2 Likes

Literally milliseconds. The code calls for at minimum 1 full second, but in reality it does a slight jerk then stops. Not really running, more like it tries to run and halts itself. This happens with all 3 autonomous commands the same way

Joystick code however does work correctly with the same arcadeDrive calls. I looked at this briefly in person today but didn’t have enough time to investigate it fully. The motors are not fighting each other which was my first thought.

I don’t wanna speak for OP but I believe this is stemmed from the KitBot Java Code from FIRST

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.RunCommand;
import frc.robot.subsystems.PWMDrivetrain;

// import frc.robot.subsystems.CANDrivetrain;

public final class Autos {
  /** Example static factory for an autonomous command. */
  public static Command exampleAuto(PWMDrivetrain drivetrain) {
    /**
     * RunCommand is a helper class that creates a command from a single method, in this case we
     * pass it the arcadeDrive method to drive straight back at half power. We modify that command
     * with the .withTimeout(1) decorator to timeout after 1 second, and use the .andThen decorator
     * to stop the drivetrain after the first command times out
     */
    return new RunCommand(() -> drivetrain.arcadeDrive(-.5, 0))
        .withTimeout(1)
        .andThen(new RunCommand(() -> drivetrain.arcadeDrive(0, 0)));
  }

  private Autos() {
    throw new UnsupportedOperationException("This is a utility class!");
  }
}

This is from the KitBot Webpage and the Java zip file.

Looking at the code again, I believe the lack of requirements in the created RunCommand is a mistake in the Java code provided by FIRST (it appears correct in the C++ kitbot code). I’m not sure whether this is causing OP’s issue or if something different is going on, though.

2 Likes

We will be back in the lab tomorrow to try this fix. We will also post our findings because I’m sure if we followed the example and it was wrong others will too.

I’ve written this code to test.

public final class Autos {
  public static Command exampleRequirementAuto(CANDrivetrain drivetrain) {
    return new RunCommand(() -> drivetrain.arcadeDrive(-.5, 0), drivetrain).withTimeout(5)
        .andThen(new RunCommand(() -> drivetrain.arcadeDrive(0, 0), drivetrain).withTimeout(1))
        .andThen(new RunCommand(() -> drivetrain.arcadeDrive(0, 0.5), drivetrain).withTimeout(2))
        .andThen(new RunCommand(() -> drivetrain.arcadeDrive(0, 0), drivetrain)); 
  }

  public static Command exampleFactoryAuto(CANDrivetrain drivetrain) {
    return drivetrain.createArcadeDriveCommand(-.5, 0, 5)
            .andThen(drivetrain.createArcadeDriveCommand(0, 0, 1))
            .andThen(drivetrain.createArcadeDriveCommand(0, 0.5, 2))
            .andThen(drivetrain.createArcadeDriveCommand(0, 0, 1)); 
  }
  private Autos() {
    throw new UnsupportedOperationException("This is a utility class!");
  }
}

And in the CANDrivetrain subsystem, I have this method

public Command createArcadeDriveCommand(double speed, double rotation, double timeout) {
        return new RunCommand(() -> this.arcadeDrive(speed, rotation), this)
                .withTimeout(timeout);
    }

Worked perfectly! Thank you so much!

1 Like

I’m glad to have helped! If you haven’t done so already, it would be great if somebody on your team could contact FIRST and inform them about the issue.

Also, a few other tips on command-based code:

  1. Subsystems have methods to create commands which automatically require the subsystem. For instance you could implement your createArcadeDriveCommand command factory method as:
return run(() -> arcadeDrive(speed, rotation)).withTimeout(timeout);

(You might also use this.run to make it clear where run is coming from).

  1. Instead of repetitively using .andThen(), you can create a single SequentialCommandGroup or use the Commands.sequence method.
1 Like

In Team Update 05 they fixed this!

2 Likes

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