###### tags: `程式組教程`
# Chassis Controller Mode(X)
:::danger
The DifferentialDrive class contains three different default modes of driving your robot’s motors.
- **Tank Drive** ➨ which controls the left and right side independently.
- **Arcade Drive** ➨ which controls a forward and turn speed.
- ==**Curvature Drive**== ➨ a handle which control the velocity of the robot ,and another handle makes you follow a curved path turning.
:::
## TankDrive
Basically, Tank Drive is a method which controled by two different Axis independently on a joystick. And the difference of velocity outputs on each side can make robot move forward and turn.
Below begin with a example code which is not totally wrong.
:::spoiler Example Code
```java=
if(js1.getRawAxis(1) > 0 || js1.getRawAxis(1) < 0){
leftFront.set(ControlMode.PercentOutput, js1.getRawAxis(1));
//Motor.set(mode, value);
//leftFront the motor's velocity will according to the axisY
leftBack.set(ControlMode.PercentOutput, js1.getRawAxis(1));
//leftFront the motor's velocity will according to the percentagemovement of axisY
}else{
//If the detection result of the Y-axis does not move
leftFront.set(ControlMode.PercentOutput, 0 );
leftBack.set(ControlMode.PercentOutput, 0 );
//then set the vel of leftFront and leftBack as 0
}
if(js1.getRawAxis(5) > 0 || js1.getRawAxis(5) < 0){
rightFront.set(ControlMode.PercentOutput, js1.getRawAxis(5));
rightBack.set(ControlMode.PercentOutput, js1.getRawAxis(5));
}else{
rightFront.set(ControlMode.PercentOutput, 0 );
rightBack.set(ControlMode.PercentOutput, 0 );
}
```
:::
</br>
Alought the code above is exactly wrong, but it's too hard to read and understand. So it'll be much better after you rewrite in the way below.
:::spoiler Better Code
```java=
if(js1.getRawAxis(leftstick_Y) > 0 || js1.getRawAxis(leftstick_Y) < 0){
leftFront.set(ControlMode.PercentOutput, js1.getRawAxis(leftstick_Y));
leftBack.set(ControlMode.PercentOutput, js1.getRawAxis(leftstick_Y));
}else{
leftFront.set(ControlMode.PercentOutput, 0 );
leftBack.set(ControlMode.PercentOutput, 0 );
}
if(js1.getRawAxis(rightstick_Y) > 0 || js1.getRawAxis(rightstick_Y) < 0){
rightFront.set(ControlMode.PercentOutput, js1.getRawAxis(rightstick_Y));
rightBack.set(ControlMode.PercentOutput, js1.getRawAxis(rightstick_Y));
}else{
rightFront.set(ControlMode.PercentOutput, 0 );
rightBack.set(ControlMode.PercentOutput, 0 );
}
```
:::
</br>
what if we change into the method below it is much much more comfortable to program and even read and understand.
```java=
if(js1.getRawAxis(leftstick_Y)){
leftFront.set(ControlMode.PercentOutput, js1.getRawAxis(leftstick_Y));
leftBack.set(ControlMode.PercentOutput, js1.getRawAxis(leftstick_Y));
}
if(js1.getRawAxis(rightstick_Y)){
rightFront.set(ControlMode.PercentOutput, js1.getRawAxis(rightstick_Y));
rightBack.set(ControlMode.PercentOutput, js1.getRawAxis(rightstick_Y));
}
```
Alought we can just use the program above, in order to increase the programming speed we often use the function in WPILib just like below.
```java=
// Tank drive with a given left and right rates
Drive.tankDrive(js1.getRawAxis(leftstick_Y)*0.8, js1.getRawAxis(rightstick_Y)*0.8);
//前面取DifferentialDrive的名字.tankDrive(leftSpeed, rightSpeed);
```
## arcadeDrive
using one joysick to control the robot,import the wpi function directly。
> The Arcade Drive mode is used to control the drivetrain using speed/throttle and rotation rate. This is typically used either with two axes from a single joystick, or split across joysticks (often on a single gamepad) with the throttle coming from one stick and the rotation from another. This example shows how to use a single joystick with the Arcade mode.
```java=
// Arcade drive with a given forward and turn rate
Drive.arcadeDrive(js1.getRawAxis(leftStick_Y)*0.8,js1.getRawAxis(rightStick_X)*0.8);
//前面取DifferentialDrive的名字.arcadeDrive(Speed, Rotation);
```
## curvatureDrive
we won't use this
```java
// Curvature drive with a given forward and turn rate, as well as a quick-turn button
myDrive.curvatureDrive(-driveStick.getY(), driveStick.getX(), driveStick.getButton(1));
```
> Curvature Drive mode is used to control the drivetrain using speed/throttle and rotation rate. The difference is that the rotation control input controls the radius of curvature instead of rate of heading change, much like the steering wheel of a car. This mode also supports turning in place, which is enabled when the third boolean parameter is true.
## mecanumDrive
theory: Use the forward and reverse rotation of the four wheels to control the direction of movement


> MecanumDrive is a method provided for the control of holonomic drivetrains with Mecanum wheels, such as the Kit of Parts chassis with the mecanum drive upgrade kit, as shown above.
:::spoiler the code
``` java
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends TimedRobot {
private static final String kDefaultAuto = "Default";
private static final String kCustomAuto = "My Auto";
private String m_autoSelected;
private final SendableChooser<String> m_chooser = new SendableChooser<>();
public final int kFrontLeftChannel = 3;
public final int kRearLeftChannel = 4;
public final int kFrontRightChannel = 1;
public final int kRearRightChannel = 2;
public final int leftStick_X = 0;
public final int leftStick_Y = 1;
public final int rightStick_X = 4;
public final int rightStick_Y = 5;
public final int trigger_L = 2;
public final int trigger_R = 3;
public final int Btn_A = 1;
public final int Btn_B = 2;
public final int Btn_X = 3;
public final int Btn_Y = 4;
public final int Btn_LB = 5;
public final int Btn_RB = 6;
public final int Btn_LS = 9;
public final int Btn_RS = 10;
double ySpeed;
double xSpeed;
double zRotation;
WPI_TalonSRX LeftFront = new WPI_TalonSRX(kFrontLeftChannel);
WPI_TalonSRX LeftRear = new WPI_TalonSRX(kRearLeftChannel);
WPI_TalonSRX RightFront = new WPI_TalonSRX(kFrontRightChannel);
WPI_TalonSRX RightRear = new WPI_TalonSRX(kRearRightChannel);
Joystick joystick = new Joystick(0);
@Override
public void robotInit() {
RightFront.setInverted(true);
RightRear.setInverted(true);
LeftFront.setInverted(false);
LeftRear.setInverted(false);
}
@Override
public void robotPeriodic() {
}
@Override
public void autonomousInit() {
}
@Override
public void autonomousPeriodic() {
}
@Override
public void teleopInit() {
}
@Override
public void teleopPeriodic() {
ySpeed = -joystick.getRawAxis(leftStick_Y) * -0.5;
xSpeed = joystick.getRawAxis(leftStick_X)* -0.5;
zRotation = joystick.getRawAxis(rightStick_X)* 0.5;
LeftFront.set(ySpeed + xSpeed + zRotation);
RightFront.set(ySpeed - xSpeed - zRotation);
LeftRear.set(ySpeed - xSpeed + zRotation);
RightRear.set(ySpeed + xSpeed - zRotation);
}
@Override
public void disabledInit() {
}
@Override
public void disabledPeriodic() {
}
@Override
public void testInit() {
}
@Override
public void testPeriodic() {
}
}
```
:::
:::spoiler using official function
```java=
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends TimedRobot {
private static final String kDefaultAuto = "Default";
private static final String kCustomAuto = "My Auto";
private String m_autoSelected;
private final SendableChooser<String> m_chooser = new SendableChooser<>();
public final int kFrontLeftChannel = 3;
public final int kRearLeftChannel = 4;
public final int kFrontRightChannel = 1;
public final int kRearRightChannel = 2;
public final int leftStick_X = 0;
public final int leftStick_Y = 1;
public final int rightStick_X = 4;
public final int rightStick_Y = 5;
public final int trigger_L = 2;
public final int trigger_R = 3;
public final int Btn_A = 1;
public final int Btn_B = 2;
public final int Btn_X = 3;
public final int Btn_Y = 4;
public final int Btn_LB = 5;
public final int Btn_RB = 6;
public final int Btn_LS = 9;
public final int Btn_RS = 10;
public MecanumDrive m_Drive;
double ySpeed;
double xSpeed;
double zRotation;
double chassisPower;
WPI_TalonSRX m_frontLeft = new WPI_TalonSRX(kFrontLeftChannel);
WPI_TalonSRX m_rearLeft = new WPI_TalonSRX(kRearLeftChannel);
WPI_TalonSRX m_frontRight = new WPI_TalonSRX(kFrontRightChannel);
WPI_TalonSRX m_rearRight = new WPI_TalonSRX(kRearRightChannel);
Joystick joystick = new Joystick(0);
WPI_TalonSRX LeftFront = new WPI_TalonSRX(0);
WPI_TalonSRX LeftRear = new WPI_TalonSRX(1);
SpeedControllerGroup LeftMotor = new SpeedControllerGroup(LeftFront, LeftRear);
WPI_TalonSRX RightFront = new WPI_TalonSRX(2);
WPI_TalonSRX RightRear = new WPI_TalonSRX(3);
SpeedControllerGroup RightMotor = new SpeedControllerGroup(RightFront, RightRear);
@Override
public void robotInit() {
double chassisPower = 0.5;
m_Drive = new MecanumDrive(LeftFront, LeftRear, RightFront, RightRear);
}
@Override
public void robotPeriodic() {
}
@Override
public void autonomousInit() {
}
@Override
public void autonomousPeriodic() {
}
@Override
public void teleopInit() {
}
@Override
public void teleopPeriodic() {
if (joystick.getRawButton(6) || joystick.getRawButton(5)){
chassisPower = 1;
} else {
chassisPower = 0.5;
}
ySpeed = -joystick.getRawAxis(leftStick_Y) * chassisPower;
xSpeed = joystick.getRawAxis(leftStick_X) * chassisPower;
zRotation = joystick.getRawAxis(rightStick_X) * chassisPower;
m_Drive.driveCartesian(ySpeed, -xSpeed, zRotation);
}
@Override
public void disabledInit() {
}
@Override
public void disabledPeriodic() {
}
@Override
public void testInit() {
}
@Override
public void testPeriodic() {
}
}
```
:::
資料來源:https://docs.wpilib.org/en/stable/docs/software/actuators/wpi-drive-classes.html