---
# System prepended metadata

title: 底盤控制模式
tags: [程式組教程]

---

# 底盤控制模式

:::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 subset of Arcade Drive, which makes your robot handle like a car with constant-curvature turns.
:::


## tankDrive
簡單來說，就是一個搖桿控制一邊的馬達，藉由兩個搖桿並利用兩邊的速度差進行直走和轉彎。
> The Tank Drive mode is used to control each side of the drivetrain independently (usually with an individual joystick axis controlling each). This example shows how to use the Y-axis of two separate joysticks to run the drivetrain in Tank mode. 

```java=
if(js1.getRawAxis(1) > 0 || js1.getRawAxis(1) < 0){

    leftFront.set(ControlMode.PercentOutput, js1.getRawAxis(1));
    //馬達名字.set(mode, value);
    //leftFront馬達的控制轉速方視為根據左方搖桿感測到的Y軸移動的百分比

    leftBack.set(ControlMode.PercentOutput, js1.getRawAxis(1));
    //leftBack馬達的控制轉速方視為根據左方搖桿感測到的Y軸移動的百分比

}else{

    //若偵測結果並未在Y軸方向移動
    leftFront.set(ControlMode.PercentOutput, 0 );
    leftBack.set(ControlMode.PercentOutput, 0 );
    //則將leftFront和leftBack馬達設定轉速為0

}
if(js1.getRawAxis(5) > 0 || js1.getRawAxis(5) < 0){

    rightFront.set(ControlMode.PercentOutput, js1.getRawAxis(5));
    //rightFront馬達的控制轉速方視為根據左方搖桿感測到的Y軸移動的百分比

    rightBack.set(ControlMode.PercentOutput, js1.getRawAxis(5));
    //rightBack馬達的控制轉速方視為根據左方搖桿感測到的Y軸移動的百分比

}else{

    //若偵測結果並未在Y軸方向移動//
    rightFront.set(ControlMode.PercentOutput, 0 );
    rightBack.set(ControlMode.PercentOutput, 0 );
    //則將rightFront和rightBack馬達設定轉速為0(0是根據前面設定的百分比控制模式)
    
    }
```
上面寫的是對的，可是程式缺乏可讀性，若更改成下面那樣會更好
```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 );
}
```

更改成下面那樣，寫起來更加輕鬆。

```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));
}
```

我們也可以使用 WPI 中內建的函式，讓我們程式寫得好棒棒。
```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
使用一個搖桿控制前後左右，直接導入內建函式。
> 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

沒用過...後續
```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

沒用過...後續

![](https://i.imgur.com/OwBVdXl.jpg)
> 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 帥柏豪寫的
``` 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 使用官方函式庫
```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
###### tags: `程式組教程`

