# 底盤控制模式 :::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: `程式組教程`