Skip to content

FTC 中常见的驱动控制模式​

约 1659 个字 157 行代码 预计阅读时间 7 分钟

1. 基本驱动控制模式​

POV 模式(视角控制)​

  • 使用左摇杆控制前进/后退,右摇杆控制转向

  • 更容易直线行驶

  • 更适合新手驾驶员

代码示例​

// 假设我们已经初始化了电机和游戏手柄

// 获取左摇杆和右摇杆的值
double drive = -gamepad1.left_stick_y;  // 前后移动,取反是因为在FTC编程中,向前推摇杆通常返回负值。
double turn  = gamepad1.right_stick_x;  // 左右转向

// 计算电机功率
double leftPower = Range.clip(drive + turn, -1.0, 1.0);  // 左电机功率
double rightPower = Range.clip(drive - turn, -1.0, 1.0); // 右电机功率

// 设置电机功率
leftDrive.setPower(leftPower);
rightDrive.setPower(rightPower);

运动示例​

  • 各种运动情况:前进​操作:将左摇杆向前推值:gamepad1.left_stick_y = -1, drive = -(-1) = 1(前进),turn = 0计算:leftPower = Range.clip(1 + 0, -1.0, 1.0) = 1rightPower = Range.clip(1 - 0, -1.0, 1.0) = 1结果:机器人向前移动,左电机的功率值为 1,右电机的功率值为 1后退​操作:将左摇杆向后推值:gamepad1.left_stick_y = 1, drive = -(1) = -1(后退),turn = 0计算:leftPower = Range.clip(-1 + 0, -1.0, 1.0) = -1rightPower = Range.clip(-1 - 0, -1.0, 1.0) = -1结果:机器人向后移动,左电机的功率值为-1,右电机的功率值为-1前进时左转​操作:将左摇杆向前推,右摇杆向左推值:gamepad1.left_stick_y = -1, drive = -(-1) = 1(前进),turn = -0.5(左转)计算:leftPower = Range.clip(1 + (-0.5), -1.0, 1.0) = 0.5rightPower = Range.clip(1 - (-0.5), -1.0, 1.0) = 1结果:机器人向前左转,左电机的功率值为 0.5,右电机的功率值为 1后退时右转​操作:将左摇杆向后推,右摇杆向右推值:gamepad1.left_stick_y = 1, drive = -(1) = -1(后退),turn = 0.5(右转)计算:leftPower = Range.clip(-1 + 0.5, -1.0, 1.0) = -0.5rightPower = Range.clip(-1 - 0.5, -1.0, 1.0) = -1结果:机器人向后右转,左电机的功率值为-0.5,右电机的功率值为-1

各种运动情况:

  • 操作:将左摇杆向前推

  • 值:gamepad1.left_stick_y = -1, drive = -(-1) = 1(前进),turn = 0

  • 计算:leftPower = Range.clip(1 + 0, -1.0, 1.0) = 1rightPower = Range.clip(1 - 0, -1.0, 1.0) = 1

  • leftPower = Range.clip(1 + 0, -1.0, 1.0) = 1

  • rightPower = Range.clip(1 - 0, -1.0, 1.0) = 1

  • 结果:机器人向前移动,左电机的功率值为 1,右电机的功率值为 1

  • 操作:将左摇杆向后推

  • 值:gamepad1.left_stick_y = 1, drive = -(1) = -1(后退),turn = 0

  • 计算:leftPower = Range.clip(-1 + 0, -1.0, 1.0) = -1rightPower = Range.clip(-1 - 0, -1.0, 1.0) = -1

  • leftPower = Range.clip(-1 + 0, -1.0, 1.0) = -1

  • rightPower = Range.clip(-1 - 0, -1.0, 1.0) = -1

  • 结果:机器人向后移动,左电机的功率值为-1,右电机的功率值为-1

  • 操作:将左摇杆向前推,右摇杆向左推

  • 值:gamepad1.left_stick_y = -1, drive = -(-1) = 1(前进),turn = -0.5(左转)

  • 计算:leftPower = Range.clip(1 + (-0.5), -1.0, 1.0) = 0.5rightPower = Range.clip(1 - (-0.5), -1.0, 1.0) = 1

  • leftPower = Range.clip(1 + (-0.5), -1.0, 1.0) = 0.5

  • rightPower = Range.clip(1 - (-0.5), -1.0, 1.0) = 1

  • 结果:机器人向前左转,左电机的功率值为 0.5,右电机的功率值为 1

  • 操作:将左摇杆向后推,右摇杆向右推

  • 值:gamepad1.left_stick_y = 1, drive = -(1) = -1(后退),turn = 0.5(右转)

  • 计算:leftPower = Range.clip(-1 + 0.5, -1.0, 1.0) = -0.5rightPower = Range.clip(-1 - 0.5, -1.0, 1.0) = -1

  • leftPower = Range.clip(-1 + 0.5, -1.0, 1.0) = -0.5

  • rightPower = Range.clip(-1 - 0.5, -1.0, 1.0) = -1

  • 结果:机器人向后右转,左电机的功率值为-0.5,右电机的功率值为-1

总结​

通过具体的 drive 和 turn 值,机器人能够实现不同的运动模式。Range.clip 方法确保电机功率在合理范围内,从而影响机器人的运动方向和速度。

思考?如果将电机的 Direction 互换,代码应该怎么修改?​

//DcMotor.Direction.FORWARD  // 正功率→正转,负功率→反转
//DcMotor.Direction.REVERSE  // 正功率→反转,负功率→正转
// 原来的设置
leftDrive.setDirection(DcMotor.Direction.REVERSE);   // 左电机反转
rightDrive.setDirection(DcMotor.Direction.FORWARD);  // 右电机正转

// 互换后的设置
leftDrive.setDirection(DcMotor.Direction.FORWARD);   // 左电机正转
rightDrive.setDirection(DcMotor.Direction.REVERSE);  // 右电机反转

让我举例说明互换后的运动情况:​

  • 操作:将左摇杆向前推

操作:将左摇杆向前推

  • 值:gamepad1.left_stick_y = -1, drive = -(-1) = 1

值:gamepad1.left_stick_y = -1, drive = -(-1) = 1

  • 计算:

计算:

  • leftPower = Range.clip(1 + 0, -1.0, 1.0) = 1

leftPower = Range.clip(1 + 0, -1.0, 1.0) = 1

  • rightPower = Range.clip(1 - 0, -1.0, 1.0) = 1

rightPower = Range.clip(1 - 0, -1.0, 1.0) = 1

  • 结果:

结果:

  • 左电机收到正功率 1.0,但因为是 FORWARD,所以正向转动

左电机收到正功率 1.0,但因为是 FORWARD,所以正向转动

  • 右电机收到正功率 1.0,但因为是 REVERSE,所以反向转动

右电机收到正功率 1.0,但因为是 REVERSE,所以反向转动

  • 机器人会原地打转,而不是前进!

机器人会原地打转,而不是前进!

  • 操作:将左摇杆向后推

操作:将左摇杆向后推

  • 值:gamepad1.left_stick_y = 1, drive = -(1) = -1

值:gamepad1.left_stick_y = 1, drive = -(1) = -1

  • 计算:

计算:

  • leftPower = Range.clip(-1 + 0, -1.0, 1.0) = -1

leftPower = Range.clip(-1 + 0, -1.0, 1.0) = -1

  • rightPower = Range.clip(-1 - 0, -1.0, 1.0) = -1

rightPower = Range.clip(-1 - 0, -1.0, 1.0) = -1

  • 结果:

结果:

  • 左电机收到负功率-1.0,但因为是 FORWARD,所以反向转动

左电机收到负功率-1.0,但因为是 FORWARD,所以反向转动

  • 右电机收到负功率-1.0,但因为是 REVERSE,所以正向转动

右电机收到负功率-1.0,但因为是 REVERSE,所以正向转动

  • 机器人同样会原地打转,方向与前进时相反!

机器人同样会原地打转,方向与前进时相反!

我们需要确保:

  • 我们需要两个轮子在给定相同功率时朝相同方向转动

我们需要两个轮子在给定相同功率时朝相同方向转动

  • 由于电机的物理安装是对称的,必须有一个电机设置为 REVERSE

由于电机的物理安装是对称的,必须有一个电机设置为 REVERSE

// 1. 修改电机方向设置
leftDrive.setDirection(DcMotor.Direction.FORWARD);   // 改为FORWARD
rightDrive.setDirection(DcMotor.Direction.REVERSE);  // 改为REVERSE

// 2. 修改功率计算公式
// 原来的计算
leftPower = Range.clip(drive + turn, -1.0, 1.0);
rightPower = Range.clip(drive - turn, -1.0, 1.0);

// 需要改为
leftPower = Range.clip(drive - turn, -1.0, 1.0);    // + 改为 -
rightPower = Range.clip(drive + turn, -1.0, 1.0);   // - 改为 +

坦克模式(双摇杆独立控制)​

  • 左摇杆直接控制左电机,右摇杆直接控制右电机

  • 更精确的转向控制

  • 需要更多练习掌握

/**
 * 坦克驱动模式
 * 左摇杆控制左侧电机,右摇杆控制右侧电机
 */
public void tankDrive() {
    double leftPower = -gamepad1.left_stick_y;   // 左侧电机
    double rightPower = -gamepad1.right_stick_y; // 右侧电机

    // 设置电机功率
    leftDrive.setPower(leftPower);
    rightDrive.setPower(rightPower);
}

2. 高级驱动控制模式​

弧形驱动(Arcade Drive)​

/**
 * 弧形驱动模式
 * 提供更平滑的转向控制
 */
public void arcadeDrive() {
    double drive = -gamepad1.left_stick_y;
    double turn = gamepad1.right_stick_x;

    // 使用平方函数使控制更精确
    drive = Math.copySign(drive * drive, drive);
    turn = Math.copySign(turn * turn, turn);

    double leftPower = Range.clip(drive + turn, -1.0, 1.0);
    double rightPower = Range.clip(drive - turn, -1.0, 1.0);

    leftDrive.setPower(leftPower);
    rightDrive.setPower(rightPower);
}

麦克纳姆轮驱动​

/**
 * 麦克纳姆轮驱动模式
 * 支持全方向移动
 */
public void mecanumDrive() {
    double drive = -gamepad1.left_stick_y;   // 前进/后退
    double strafe = gamepad1.left_stick_x;   // 左右平移
    double turn = gamepad1.right_stick_x;    // 转向

    // 计算每个轮子的功率
    double frontLeftPower = drive + strafe + turn;
    double frontRightPower = drive - strafe - turn;
    double backLeftPower = drive - strafe + turn;
    double backRightPower = drive + strafe - turn;

    // 归一化功率值
    double maxPower = Math.max(Math.abs(frontLeftPower),
                     Math.max(Math.abs(frontRightPower),
                     Math.max(Math.abs(backLeftPower),
                     Math.abs(backRightPower))));

    if (maxPower > 1.0) {
        frontLeftPower /= maxPower;
        frontRightPower /= maxPower;
        backLeftPower /= maxPower;
        backRightPower /= maxPower;
    }

    // 设置电机功率
    frontLeft.setPower(frontLeftPower);
    frontRight.setPower(frontRightPower);
    backLeft.setPower(backLeftPower);
    backRight.setPower(backRightPower);
}

3. 精确控制功能​

速度控制​

/**
 * 速度控制模式
 * 提供不同的速度级别
 */
public class SpeedControl {
    private double speedMultiplier = 1.0;

    public void controlSpeed() {
        // 切换速度模式
        if (gamepad1.a) speedMultiplier = 1.0;    // 全速
        if (gamepad1.b) speedMultiplier = 0.5;    // 半速
        if (gamepad1.x) speedMultiplier = 0.25;   // 低速

        // 应用速度控制
        double drive = -gamepad1.left_stick_y * speedMultiplier;
        double turn = gamepad1.right_stick_x * speedMultiplier;

        // 设置电机功率...
    }
}

平滑加速​

/**
 * 平滑加速控制
 * 防止突然的功率变化
 */
public class SmoothControl {
    private double currentPower = 0.0;
    private static final double ACCELERATION_RATE = 0.1;

    public double smoothPower(double targetPower) {
        // 逐渐调整当前功率到目标功率
        if (currentPower < targetPower) {
            currentPower = Math.min(currentPower + ACCELERATION_RATE, targetPower);
        } else if (currentPower > targetPower) {
            currentPower = Math.max(currentPower - ACCELERATION_RATE, targetPower);
        }
        return currentPower;
    }
}

4. 驱动辅助功能​

直线修正​

/**
 * 直线驱动辅助
 * 使用陀螺仪保持直线行驶
 */
public class StraightDriveAssist {
    private IMU imu;
    private double targetHeading;

    public void driveStraight() {
        double drive = -gamepad1.left_stick_y;

        if (Math.abs(drive) > 0.1) {
            double currentHeading = imu.getAngularOrientation().firstAngle;
            double correction = (targetHeading - currentHeading) * 0.03;

            // 应用修正
            leftDrive.setPower(drive + correction);
            rightDrive.setPower(drive - correction);
        }
    }
}

注意事项​

  • 控制器死区:添加死区防止摇杆轻微抖动导致机器人移动通常设置 0.1 左右的死区值

控制器死区:

  • 添加死区防止摇杆轻微抖动导致机器人移动

  • 通常设置 0.1 左右的死区值

  • 功率限制:确保所有电机功率都在-1.0 到 1.0 范围内使用Range.clip()函数限制功率值

功率限制:

  • 确保所有电机功率都在-1.0 到 1.0 范围内

  • 使用Range.clip()函数限制功率值

  • 平滑控制:避免突然的功率变化实现渐进式加速和减速

平滑控制:

  • 避免突然的功率变化

  • 实现渐进式加速和减速

  • 安全考虑:添加紧急停止功能实现最大速度限制添加碰撞检测逻辑

安全考虑:

  • 添加紧急停止功能

  • 实现最大速度限制

  • 添加碰撞检测逻辑

  • 调试功能:使用遥测显示重要数据添加不同驱动模式的切换功能

调试功能:

  • 使用遥测显示重要数据

  • 添加不同驱动模式的切换功能

这些驱动控制模式可以根据具体的机器人设计和比赛策略进行组合和修改,以获得最佳的操控体验。

颜色主题调整