综合挑战 Combined Challenge
5.1 挑战目标 5.1 Challenge Goal
在 Level 1,你学会了用时间控制机器人直走和转弯。现在,用你在 Level 3 学到的传感器知识,重写那段代码 。 In Level 1, you learned to make the robot drive and turn using time control. Now, use the sensor knowledge from Level 3 to rewrite that code .
任务 Task
让机器人完成以下动作: Make the robot complete these actions:
向前走 600 度 (用编码器控制) Drive forward 600 degrees (using encoder)
右转 90 度 (用 IMU 控制) Turn right 90 degrees (using IMU)
再向前走 400 度 (用编码器控制) Drive forward another 400 degrees (using encoder)
停下 Stop
5.2 要求 5.2 Requirements
不能用时间控制 No time control allowed (不能用 wait(X, seconds) 来控制距离或角度) (don't use wait(X, seconds) for distance or angle control)
直走用编码器 ,转弯用 IMU Use encoders for driving straight, IMU for turning
不给框架——从空白开始自己写 No starter code -- write it from scratch
需要包含:电机声明、IMU 声明和校准、编码器重置 Must include: motor declarations, IMU declaration and calibration, encoder resets
5.3 思路提示 5.3 Hints
不知道怎么开始?点开看提示: Not sure where to start? Open the hints below:
提示 1:整体结构 Hint 1: Overall Structure
展开 Expand
代码的大致顺序: The general order of the code:
声明电机和 IMU Declare motors and IMU
校准 IMU(等校准完成) Calibrate the IMU (wait for it to finish)
第一段直走(重置编码器 → 开始走 → while 循环等到位 → 停) First straight drive (reset encoder -> start driving -> while loop until target -> stop)
右转 90 度(开始转 → while 循环等 IMU 到 90 → 停) Turn right 90 degrees (start turning -> while loop until IMU reads 90 -> stop)
第二段直走(重置编码器 → 开始走 → while 循环等到位 → 停) Second straight drive (reset encoder -> start driving -> while loop until target -> stop)
提示 2:编码器直走的模板 Hint 2: Encoder Driving Template
展开 Expand
每次直走前,记得重置编码器 ,否则它会从上次的值继续计数。 Before each straight drive, remember to reset the encoder , otherwise it will continue counting from the previous value.
C++ (VEXcode)
// 重置 → 启动 → 等待 → 停止
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 目标度数) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
C++ (VS Code)
// 重置 → 启动 → 等待 → 停止
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 目标度数) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
C++ (PROS)
// 重置 → 启动 → 等待 → 停止
left_motor.set_zero_position(0);
left_motor.move(80);
right_motor.move(80);
while (left_motor.get_position() < 目标度数) {
pros::delay(20);
}
left_motor.move(0);
right_motor.move(0);
提示 3:IMU 转弯的模板 Hint 3: IMU Turning Template
展开 Expand
C++ (VEXcode)
// 右转:左轮前进,右轮后退
LeftMotor.spin(forward);
RightMotor.spin(reverse);
while (IMU.heading(degrees) < 90) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
C++ (VS Code)
// 右转:左轮前进,右轮后退
LeftMotor.spin(forward);
RightMotor.spin(reverse);
while (IMU.heading(degrees) < 90) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
C++ (PROS)
// 右转:左轮前进,右轮后退
left_motor.move(80);
right_motor.move(-80);
while (imu.get_heading() < 90) {
pros::delay(20);
}
left_motor.move(0);
right_motor.move(0);
5.4 参考答案 5.4 Reference Answer
自己写完了再看! Write your own code first before looking!
完整参考代码 Complete Reference Code
展开参考答案 Show Reference Answer
C++ (VEXcode)
复制
// 声明电机和 IMU
motor LeftMotor = motor(PORT1, ratio18_1, false);
motor RightMotor = motor(PORT2, ratio18_1, true);
inertial IMU = inertial(PORT10);
int main() {
// 1. 校准 IMU
IMU.calibrate();
while (IMU.isCalibrating()) {
wait(50, msec);
}
// 2. 第一段直走:600 度
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 600) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
// 3. 右转 90 度
LeftMotor.spin(forward);
RightMotor.spin(reverse);
while (IMU.heading(degrees) < 90) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
// 4. 第二段直走:400 度
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 400) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
return 0;
}
C++ (VS Code)
复制
// 声明电机和 IMU
motor LeftMotor = motor(PORT1, ratio18_1, false);
motor RightMotor = motor(PORT2, ratio18_1, true);
inertial IMU = inertial(PORT10);
int main() {
// 1. 校准 IMU
IMU.calibrate();
while (IMU.isCalibrating()) {
wait(50, msec);
}
// 2. 第一段直走:600 度
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 600) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
// 3. 右转 90 度
LeftMotor.spin(forward);
RightMotor.spin(reverse);
while (IMU.heading(degrees) < 90) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
// 4. 第二段直走:400 度
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
RightMotor.spin(forward);
while (LeftMotor.position(degrees) < 400) {
wait(20, msec);
}
LeftMotor.stop();
RightMotor.stop();
return 0;
}
C++ (PROS)
复制
// 声明电机和 IMU
pros::Motor left_motor(1);
pros::Motor right_motor(2, true); // true = 反转
pros::Imu imu(10);
void autonomous() {
// 1. 校准 IMU
imu.reset();
// reset() 会等校准完成
// 2. 第一段直走:600 度
left_motor.set_zero_position(0);
left_motor.move(80);
right_motor.move(80);
while (left_motor.get_position() < 600) {
pros::delay(20);
}
left_motor.move(0);
right_motor.move(0);
// 3. 右转 90 度
left_motor.move(80);
right_motor.move(-80);
while (imu.get_heading() < 90) {
pros::delay(20);
}
left_motor.move(0);
right_motor.move(0);
// 4. 第二段直走:400 度
left_motor.set_zero_position(0);
left_motor.move(80);
right_motor.move(80);
while (left_motor.get_position() < 400) {
pros::delay(20);
}
left_motor.move(0);
right_motor.move(0);
}
注意几个关键点: Key points to note:
每次直走前都重置编码器 ,否则第二段会接着第一段的度数继续算 Reset the encoder before each straight drive, otherwise the second segment will continue counting from the first
IMU 校准在最前面,只校准一次 IMU calibration goes at the very beginning, only once
while 循环里别忘了 wait/delay,否则会占满 CPU Don't forget wait/delay inside while loops, or it will max out the CPU
下面的代码有一个 Bug。机器人先走了 600 度,然后想再走 400 度,但第二段直走不动了。为什么? The code below has a bug. The robot drives 600 degrees first, then tries to drive 400 more degrees, but the second drive doesn't move. Why?
C++ (VEXcode)
// 第一段
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
while (LeftMotor.position(degrees) < 600) {
wait(20, msec);
}
LeftMotor.stop();
// 第二段(Bug 在这里!)
LeftMotor.spin(forward);
while (LeftMotor.position(degrees) < 400) {
wait(20, msec);
}
LeftMotor.stop();
C++ (VS Code)
// 第一段
LeftMotor.setPosition(0, degrees);
LeftMotor.spin(forward);
while (LeftMotor.position(degrees) < 600) {
wait(20, msec);
}
LeftMotor.stop();
// 第二段(Bug 在这里!)
LeftMotor.spin(forward);
while (LeftMotor.position(degrees) < 400) {
wait(20, msec);
}
LeftMotor.stop();
C++ (PROS)
// 第一段
left_motor.set_zero_position(0);
left_motor.move(80);
while (left_motor.get_position() < 600) {
pros::delay(20);
}
left_motor.move(0);
// 第二段(Bug 在这里!)
left_motor.move(80);
while (left_motor.get_position() < 400) {
pros::delay(20);
}
left_motor.move(0);
A. 第二段忘了写 spin/move A. The second segment is missing spin/move
B. 第二段没有重置编码器,位置已经是 600,永远大于 400 B. The second segment didn't reset the encoder -- position is already 600, which is always greater than 400
C. while 循环写反了 C. The while loop condition is backwards
D. 电机坏了 D. The motor is broken
正确!第一段走完后,编码器的值已经是 600。第二段没有重置编码器,所以 while 条件 "position < 400" 一上来就是 false(600 > 400),循环直接跳过,电机马上停了。修复方法:第二段前加上 setPosition(0, degrees) 或 set_zero_position(0)。 Correct! After the first drive, the encoder value is already 600. The second segment didn't reset the encoder, so the while condition "position < 400" is immediately false (600 > 400), the loop is skipped, and the motor stops right away. Fix: add setPosition(0, degrees) or set_zero_position(0) before the second segment.
通过