Startcompetition() error

I’m getting this error in the driver station. does anyone know what this is about I can’t fix it.

ERROR  1  Unhandled exception: java.lang.NullPointerException  frc.robot.subsystems.DriveTrain.<init>(DriveTrain.java:20) 
ERROR  1  The startCompetition() method (or methods called by it) should have handled the exception above.  

this is my drive train:

package frc.robot.subsystems;

import com.revrobotics.CANSparkMax;
import com.revrobotics.RelativeEncoder;
import com.revrobotics.SparkMaxPIDController;

import edu.wpi.first.wpilibj.ADXRS450_Gyro;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants;

public class DriveTrain extends SubsystemBase {

    CANSparkMax leftLeader;
    CANSparkMax rightLeader;
    
    CANSparkMax leftFollower;
    CANSparkMax rightFollower;

    RelativeEncoder leftEncoder = leftLeader.getEncoder();
    RelativeEncoder rightEncoder = rightLeader.getEncoder();

    SparkMaxPIDController leftController = leftLeader.getPIDController();
    SparkMaxPIDController rightController = rightLeader.getPIDController();

    DifferentialDrive drive = new DifferentialDrive(leftLeader, rightLeader);

    ADXRS450_Gyro gyro = new ADXRS450_Gyro();
    
    double setpoint;
    double leftEncoderPosition;
    double rightEncoderPosition;

    public DriveTrain() {
        leftFollower.follow(leftLeader);
        rightFollower.follow(rightLeader);
        gyro.reset();
        gyro.calibrate();
        leftController.setP(Constants.kP);
        leftController.setI(Constants.kI);
        leftController.setD(Constants.kD);
        rightController.setP(Constants.kP);
        rightController.setI(Constants.kI);
        rightController.setD(Constants.kD);
        leftController.setOutputRange(-1, 1);
        rightController.setOutputRange(-1, 1);
    }

    public void drive(double f, double t) {
        drive.arcadeDrive(f, t);
    }

    public void drivePID(double s) {
        setpoint = s;
        leftController.setReference(setpoint, CANSparkMax.ControlType.kPosition);
        rightController.setReference(setpoint, CANSparkMax.ControlType.kPosition);
        drive.feed();
    }

    public void angleCorrect(double angle) {
        if (gyro.getAngle() < angle) {
            drive.arcadeDrive(0, 0.5);
        } else if (gyro.getAngle() > angle) {
            drive.arcadeDrive(0, -0.5);
        }
    }

    public void resetGyro() {
        gyro.reset();
    }

    public void calibrateGyro() {
        gyro.calibrate();
    }

    public boolean leftAtSetpoint() {
        if ((leftEncoderPosition == Math.abs(setpoint + 2)) || (leftEncoderPosition == Math.abs(setpoint - 2))) {
            return true;
        } else {
            return false;
        }
    }

    public boolean rightAtSetpoint() {
        if ((rightEncoderPosition == setpoint + 2) || (rightEncoderPosition == setpoint - 2)) {
            return true;
        } else {
            return false;
        }
    }
    public double getleftVelocity() {
        return leftEncoder.getVelocity();
    }
    public double getRightVelocity() {
        return rightEncoder.getVelocity();
    }

    public double getVelocity() {
        return (getleftVelocity() + getRightVelocity()) / 2;
    }

    public boolean atSetpoint() {
        if (leftAtSetpoint() && rightAtSetpoint()) {
            return true;
        } else {
            return false;
        }
    }

    public void update() {
        leftEncoderPosition = leftEncoder.getPosition();
        rightEncoderPosition = rightEncoder.getPosition();
    }
}

When you initialize the encoders, you’re telling the system to get the encoder from leftLeader. But at time point in time leftLeader doesn’t point to anything because it hasn’t yet been initialized. Before you call a function on something you need to set that something to a value, not just declare it’s existence. You’ll also run into the same issue where you’re initializing the PIDControllers, potentially with the DifferentialDrive, and when making the follower calls in the DriveTrain constructor.

So to resolve this you need to initialize the CANSparkMax objects to a valid object.

2 Likes

omg you’re totally right. I’ve been way to tired to code lately :wink: thanks!!!

Something I do to avoid these errors is make my member variables final. For instance, your program would not compile if you had something like this instead:

public class DriveTrain extends SubsystemBase {

    final CANSparkMax leftLeader;
    final CANSparkMax rightLeader;
    
    final CANSparkMax leftFollower;
    final CANSparkMax rightFollower;

    ...

    public DriveTrain() {
        ...
    }
    ...
}

I like to catch as many errors before compiling as possible. final will help catch some mistakes, but not all.

1 Like

Lots of ways to skin the cat, but on top of making the member variables final, you can also just take the norm of not instantiating the member variables until the constructor’s body.

That will also give the same compilation errors as just making them final, but enforces the standard of the constructor initialization of member variables just as policy.

1 Like

The general way to investigate these errors is to remove/comment out code ‘till the error doesn’t happen, then add back code in small pieces ‘till it comes back.

1 Like

Thanks everyone! I appreciate all the help!

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