Mecanum Chassis tutorial#

The mecanum chassis serves as a transition between the KOP and swerve drivetrains. It offers greater driving flexibility with only a small amount of additional code compared to the KOP chassis.

Mecanum chassis image below:

Mecanum Chassis

You can also use the motors from the KOP here — now let’s check out the driving kinematics.

Because of the characteristics of the mecanum wheel, the robot can perform more complex movements, such as x-y panning and driving while rotating like the image below.

Mecanum Drive kinematics

Tip

If you want to know more about mecanum drive kinematics, you can check out this video.

This image demonstrates how the chassis responds to various wheel spin patterns. Each wheel’s motion can be described as:

FrontLeft = Vx + Vy + rotation
FrontRight = Vx - Vy - rotation
BackLeft = Vx - Vy + rotation
BackRight = Vx + Vy - rotation

and below the chassis code

OFFICAL METHOD

import com.revrobotics.spark.SparkMax;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.config.SparkMaxConfig;
import com.revrobotics.spark.config.SparkBaseConfig.IdleMode;

import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants.ChassisConstants;

public class NEOChassis extends SubsystemBase{
    public SparkMax LeftFrontMotor, RightFrontMotor, LeftBackMotor, RightBackMotor;
    public SparkMaxConfig LeftFrontConfig, RightFrontConfig, LeftBackConfig, RightBackConfig;

    public MecanumDrive drive;

    public NEOChassis(){
        LeftFrontMotor = new SparkMax(ChassisConstants.FrontLeftMotor, MotorType.kBrushless);
        RightFrontMotor = new SparkMax(ChassisConstants.FrontRightMotor, MotorType.kBrushless);
        LeftBackMotor = new SparkMax(ChassisConstants.BackLeftMotor, MotorType.kBrushless);
        RightBackMotor = new SparkMax(ChassisConstants.BackRightMotor, MotorType.kBrushless);

        LeftFrontConfig = new SparkMaxConfig();
        RightFrontConfig = new SparkMaxConfig();
        LeftBackConfig = new SparkMaxConfig();
        RightBackConfig = new SparkMaxConfig();

        LeftFrontConfig
            .idleMode(IdleMode.kBrake)
            .inverted(false);

        LeftBackConfig
            .idleMode(IdleMode.kBrake)
            .inverted(false);

        RightFrontConfig
            .idleMode(IdleMode.kBrake)
            .inverted(true);

        RightBackConfig
            .idleMode(IdleMode.kBrake)
            .inverted(true);

        drive = new MecanumDrive(LeftFrontMotor, LeftBackMotor, RightFrontMotor, RightBackMotor);
    }
}

SELF WRITTEN METHOD

import com.revrobotics.spark.SparkMax;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.config.SparkMaxConfig;
import com.revrobotics.spark.config.SparkBaseConfig.IdleMode;

import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants.ChassisConstants;

public class NEOChassis extends SubsystemBase{
    public SparkMax LeftFrontMotor, RightFrontMotor, LeftBackMotor, RightBackMotor;
    public SparkMaxConfig LeftFrontConfig, RightFrontConfig, LeftBackConfig, RightBackConfig;

    public NEOChassis(){
        LeftFrontMotor = new SparkMax(ChassisConstants.FrontLeftMotor, MotorType.kBrushless);
        RightFrontMotor = new SparkMax(ChassisConstants.FrontRightMotor, MotorType.kBrushless);
        LeftBackMotor = new SparkMax(ChassisConstants.BackLeftMotor, MotorType.kBrushless);
        RightBackMotor = new SparkMax(ChassisConstants.BackRightMotor, MotorType.kBrushless);

        LeftFrontConfig = new SparkMaxConfig();
        RightFrontConfig = new SparkMaxConfig();
        LeftBackConfig = new SparkMaxConfig();
        RightBackConfig = new SparkMaxConfig();

        LeftFrontConfig
            .idleMode(IdleMode.kBrake)
            .inverted(false);

        LeftBackConfig
            .idleMode(IdleMode.kBrake)
            .inverted(false);

        RightFrontConfig
            .idleMode(IdleMode.kBrake)
            .inverted(true);

        RightBackConfig
            .idleMode(IdleMode.kBrake)
            .inverted(true);

    }

    public void drive(double Vx, double Vy, double rotation){
        LeftFrontMotor.set(Vx+Vy+rotation);
        LeftBackMotor.set(Vx-Vy+rotation);
        RightFrontMotor.set(Vx-Vy-rotation);
        RightBackMotor.set(Vx+Vy-rotation);
    }
}

Note

Check out the references MecanumDrive