private static final CANSparkMax leftFrontSpark = new CANSparkMax(LEFT_FRONT_DRIVE_CAN_ID, MotorType.kBrushless);
The above constructor call fails silently, for each our Spark Max’s. This causes NullPointerExceptions when they are referenced. we’ve included the vendor json and updated their Spark’s firmware, both pointing to version 1.5.1.
Could you try making them not final or static and trying? And put the number straight into the constructor rather than the variable just to make sure there’s no issue there. Check the console and see if it reports any errors.
I do not think making these variables not final will help things. Some one else made the suggestion that perhaps they should not be static, as that inits them with the rest of the drive class (and before our drive object ). No console errors are reported, save for the NullPointers when the Spark’s are referenced. I have chosen to pre-empt this by including null checks in our drive’s constructor.
Thankfully, we are most definetely using 2020 Rio image and Wpilib. Lib installed yesterday under $PUBLIC/wpilib/2020, and we imaged our Rio several times by accident.
Are you inserting these spark max’s into either a SpeedControllerGroup or some other type of drive input, like differential drive? Because of how Java works, variables get initialized in order from top to bottom, but will not error if you pass a variable declared below the initialization line to a constructor declared above. Make sure everything you are initializing is in order from top to bottom, and not trying to access anything below it.
I’ve copied all references to the Spark objects in our class. This is not the whole class. We are not passing the SparkMax objects around. We’ve opted to instead use the Spark.follow(Spark) methods and solely use the leaders. As you can see, we’re kinda-sorta using the singleton pattern. NOTE: Methods/Code that doesn’t use the sparks has been omitted.
public class DriveBase extends Subsystem {
public static final DriveBase drives = new DriveBase();
private static final int LEFT_FRONT_DRIVE_CAN_ID = 1;
// Other ID variables here
private static final CANSparkMax leftFrontSpark = new CANSparkMax(LEFT_FRONT_DRIVE_CAN_ID, MotorType.kBrushless);
// Other spark objects here
private DriveBase() {
rightBackSpark.follow(rightFrontSpark);
leftBackSpark.follow(leftFrontSpark);
}
public void setSpeed(double leftSpeed, double rightSpeed) {
leftFrontSpark.set(leftSpeed);
rightFrontSpark.set(rightSpeed);
}
}
That code is still causing things to go out of order. Calling the follow method in the constructor is actually happening before the static variables for the individual motors are constructed, since the DriveBase() constructor is called before the sparks are initialized. If you move the DriveBase object below the CANSparkMax objects, this error should go away.
Although, since you are using a singleton, the spark maxes don’t need to be static, and removing static from those would also solve this issue.
You were correct! Both making the sparks instance / moving the singleton to the bottom solved the issue. Though I knew about init blocks, I never though about this potential “grey area” when instance init is run in class init. Anyways, Kotlin implements the singleton pattern with the object keyword. Maybe you’ll see us running kotlin soon!