Base Mission
11 points Final judgedBotguy is the Loading Zone.
Unit 5 · Big Idea 2
Student Lab · Driving Like a Car, Not a Light Switch
Student PIN:
Every Drive() you’ve written so far does the same thing the whole way: full speed, then slam to a stop the instant the count is reached. That works, but think about how a car actually drives — it eases onto the gas, cruises, then eases onto the brake well before the stop sign. It never slams from 60 to 0 in one instant. Today you rebuild Drive() to do the same thing: ease on for the first few ticks, cruise in the middle, and ease off for the last several hundred ticks before the target — using a new tool, the else if chain, to decide which of those three zones the robot is in right now.
The Big Idea of This Unit
A robust system doesn’t treat “far from the goal” and “about to arrive” the same way. It measures how close it is and adjusts its behavior smoothly — proportional response instead of all-or-nothing.
else if chain does and when it’s the right tool versus separate if .Drive() so it accelerates, cruises, and decelerates instead of running at one fixed speed.The run
Today’s goal is just the base mission: moving Botguy into the loading zone.
Mission 18
Botguy is the Loading Zone.
Botguy is the Loading Zone AND at least one Traffic Cone is the Loading Zone.
Botguy is the Loading Zone AND both Traffic Cones are the Loading Zone.
Here’s why this mission is a perfect fit for today: Botguy isn’t fixed to the floor. If your robot arrives at full speed and slams to a stop, the impact can shove Botguy off target in the last instant — the exact moment accuracy matters most. A robot that eases off its speed as it approaches is far less likely to the zone or knock Botguy out of position on contact.
Say the mission back in your own words. Why would a sudden stop right at the end be especially risky for this mission compared to, say, just driving to an empty spot on the floor?
You already know if and else. An else if chain adds one or more extra checks in between, for when there are more than two possible situations:
if (condition_1)
{
// runs only if condition_1 is true
}
else if (condition_2)
{
// runs only if condition_1 was false AND condition_2 is true
}
else
{
// runs only if BOTH conditions above were false
}The chain is checked top to bottom, and the instant one is true, its runs and every condition below it is skipped — even if one of them would also have been true. Only one block in the whole chain ever runs.
Good fit: when the situations are mutually exclusive zones — a value falls into exactly one of them, never more than one. A speed limit that’s 20 mph in a school zone, 35 in a residential zone, and 55 on the highway is a perfect else if chain: any one location is in exactly one zone.
Poor fit: when the conditions are independent — more than one could be true at the same time, and you need to react to each one separately. “It’s raining” and “it’s nighttime” can both be true at once. Chaining them with else if would silently skip the nighttime check whenever it’s already raining — that’s a bug, not a design choice. Two separate if statements are correct there.
In your own words: what does an else if chain do differently from writing separate if statements? Give one example (robot or not) where else if is the right tool, and one where it would cause a bug.
A car doesn’t drive at one constant speed and then slam the brakes. It eases onto the gas leaving a stop sign, cruises once it’s up to speed, and eases onto the brake well before the next stop. Your Drive() is going to do the same thing, split into three zones based on tick position:
Exactly one of these zones applies at any instant while the robot is driving — which makes this a textbook if / else if / else chain.
In the deceleration zone, speed isn’t fixed — it depends on how many ticks are left to travel. The fewer ticks remaining, the slower you want to go. That relationship is a straight line, exactly like y = mx + b from math class:
Here, ticks_remaining is your x, motor_speed is your y, m is how steeply speed drops as you get closer, and b is a small base speed so the robot never fully stalls before it actually reaches the target. A starting point to test:
where desired_ticks - current_ticks is exactly ticks_remaining. The acceleration zone works the same way, just measuring from the start instead of the end — speed ramps up as current_ticks grows from 0 toward 50.
Why does deceleration speed depend on ticks remaining rather than ticks already driven? What would go wrong if you used the wrong one?
Replace your single fixed-speed loop with the three-zone if / else if / else chain. This checks the zone every trip through the loop, so speed updates continuously as ticks change.
void Drive(double inches)
{
int desired_ticks = inches * ticks_per_inch;
int current_ticks;
int motor_speed;
cmpc(0);
current_ticks = gmpc(0);
while (current_ticks < desired_ticks)
{
current_ticks = gmpc(0);
if (current_ticks < 50)
{
// ACCELERATION ZONE: ramp speed UP from a slow start
motor_speed = current_ticks * 12 + 150;
}
else if ((desired_ticks - current_ticks) < 500)
{
// DECELERATION ZONE: ramp speed DOWN as ticks remaining shrinks
motor_speed = (desired_ticks - current_ticks) * 2 + 150;
}
else
{
// CRUISE ZONE: full speed, neither ramp applies
motor_speed = 750;
}
mav(0, motor_speed);
mav(1, motor_speed);
}
mav(0, 0); mav(1, 0); msleep(50); // brake
}Walk through the three branches in your own words: what triggers each one, and what does each one do to motor_speed?
Test your new Drive() on a medium-to-long distance (24+ inches works well, so all three zones actually get used). Watch the robot closely as it drives — does it visibly ease on, cruise, then ease off? Or does something look off?
⚠ Something to watch for
The cruise speed in the skeleton is 750. Plug ticks_remaining = 500 (the instant deceleration begins) into the decel formula: 500 × 2 + 150 = 1150. That’s faster than cruise speed — the robot would speed up right as it’s supposed to start slowing down. Watch for this when you test. If you see it, that’s not a mistake in the lab — it’s your m and b constants not yet matching your cruise speed.
| Constant | Starting value | Your tuned value | Why you changed it |
|---|---|---|---|
| Accel slope (m) | 12 | ||
| Accel base (b) | 150 | ||
| Decel slope (m) | 2 | ||
| Decel base (b) | 150 | ||
| Cruise speed | 750 |
Did you hit the speed-jump problem described above? How did you change your constants so decel speed at 500 ticks remaining lines up with your cruise speed instead of exceeding it?
Using your tuned Drive(), drive to Botguy and move him into the loading zone. Run it several times.
| Run | Botguy fully in the loading zone? | Did the stop feel smooth, or still abrupt? |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
Compare this to a flat-speed Drive() from Unit 4. Was Botguy’s final position more consistent with easing on/off? Why would a reliability engineer care about that consistency more than raw speed?
AI Literacy Thread
Reliable systems respond proportionally to how close they are to a goal, instead of acting the same way right up until they suddenly stop.
This idea shows up everywhere intelligent systems need to be trusted with something delicate. A self-driving car doesn’t brake at one constant rate regardless of following distance — it eases harder the closer it gets to a stopped car ahead. A robotic arm placing a fragile part slows dramatically in its last few millimeters of travel. Even a thermostat easing a heater’s output as room temperature approaches the target, instead of blasting full heat until the exact instant it’s satisfied, is the same pattern: proportional response near the goal, not all-or-nothing action right up to it.
Complete the reflection on your own.
1. What does an else if chain do that separate if statements don’t, and why did the three speed zones need one?
2. Explain the decel formula motor_speed = ticks_remaining × m + b the way you’d explain y = mx + b to a friend who hasn’t seen this lab.
3. Why does tuning constants by testing beat guessing a value and hoping it works?
4. Complete in 2–3 sentences: “Reliable systems respond proportionally instead of all-or-nothing. This means that near a goal, a system should…”
Finished early? Try one or more of these.
Turn(). Does a turn need as large a deceleration zone as a long drive? Why or why not?Drive() on a very short distance (6 inches) and a very long one (48+ inches). Does the same accel/decel zone size work well for both? What would you change if not?else as an explicit else if that checks both bounds of the cruise zone directly. Was else if necessary? What did plain else save you from writing?motor_speed calculation with round() so it’s always a whole number (motors don’t understand fractional ticks/sec anyway). You’ll need #include <math.h>.abs() on the difference between your tuned decel speed at 500 ticks remaining and your cruise speed — how close did your tuning actually get them?When you are finished, press the button to turn in your work and save a copy.
KIPR · Botball Explorer · Unit 5 Big Idea 2