Unit 4 · Big Idea 3 — The Turn Model
KIPR · Botball Explorer
Activity Sections

Unit 4 · Big Idea 3

The Turn Model

Student Lab · Turn Any Angle, in Either Direction

Unit Guiding Question
How can a machine know where it is and where it is going?
Big Idea
One Smart Can Handle Many Cases
AI Literacy Thread
Models are best-fit approximations — never perfect, but good enough to act on.
CS1 Concepts
char Type · · Multiple · · Defensive Code
Game Context
One Turn function for every angle your missions need
What You Need
Explorer robot · open floor · protractor or angle marks · this lab sheet
Before you start: type your PIN in the box at the top of the page. Your teacher gave you this number. When you finish, press Download to save a local copy of your answers. This does not turn in your work automatically; give the downloaded file to your teacher.

Overview

Your turns right now are stuck at 90°. But missions need all kinds of angles — 45°, 180°, whatever the field demands. Today you’ll build one flexible function, Turn, that takes a direction and an angle and handles them all. Along the way you’ll meet four new tools: a new type for letters, a new kind of loop, functions that take more than one input, and functions that hand a value back. And you’ll discover something real engineers live with every day: a is never perfect — it’s the best fit you can find.

Core Insight

A model like “ per degree” lets one function turn any angle. But the real world fights back — and friction mean no single number is perfect. You find the one that fits best.

By the end of this activity you will be able to:

  • Use a char to store a single letter like 'R' or 'L'.
  • Use a for loop to repeat an action a set number of times.
  • Write a function that takes two parameters and returns a value.
  • Build a ticks_per_degree model and a flexible Turn function.

Phase 1 — New Tool: The char Type

A char holds one single character

You’ve used int and double for numbers. A char holds a single character — one letter, written in single quotes:

char direction = 'R';   // one character, in SINGLE quotes

This is perfect for telling the robot which way to turn: 'R' for right, 'L' for left.

What is a char, and how is 'R' different from "R"? Why is a char a good fit for a turn direction?

Phase 2 — New Tool: The for Loop

A for loop repeats a set number of times

You’ve used that run until something changes. A for loop is for when you know exactly how many times to repeat. It counts for you:

for (int i = 0; i < 4; i++)  // run 4 times: i = 0, 1, 2, 3
{
	// ...do this each time...
}

Three parts in the parentheses: start (int i = 0), keep going while (i < 4), and each time, do this (i++, which adds 1 to i). When i reaches 4, it stops — so the body ran exactly 4 times.

How is a for loop different from the while loops you’ve used? When would you reach for a for loop instead?

Phase 3 — Calibrate: Find ticks_per_degree

Just like ticks_per_inch told you ticks-to-inches, you now need ticks_per_degree: how many ticks make one degree of turning. The clever way to measure it: make the robot spin all the way around — a full 360° — counting ticks, then divide.

The turning model

ticks_per_degree = total ticks for a full spin ÷ 360

Here’s where the for loop shines. A full 360° spin can be built three different ways — and they should all equal 360°:

The for loopTotal turn
Afor (i=0; i<4; i++) → 90° each4 × 90° = 360°
Bfor (i=0; i<8; i++) → 45° each8 × 45° = 360°
Cfor (i=0; i<2; i++) → 180° each2 × 180° = 360°
A test spin built with a for loop (uses mav)

This example pivots in chunks using a for loop. Notice it uses mav, not motor — control is smoother for turning. Use a slow speed so the robot doesn’t from its own momentum.

cmpc(0);                          // clear the counter once, before the spin
for (int i = 0; i < 4; i++)       // four chunks = one full 360 degree spin
{
	int target = (i + 1) * CHUNK_TICKS;   // how far we should be after this chunk
	while (gmpc(0) < target)
	{
		mav(0, 300);              // SLOW velocity: left wheel forward
		mav(3, -300);             // right wheel backward (pivot right)
        msleep(10);
	}
}
motor(0,0); motor(3,0); msleep(50);   // brake-settle
printf("total ticks = %d\n", gmpc(0));

Run all three versions (A, B, C). After each full spin, read the total ticks and compute ticks_per_degree. Mark the robot’s start so you can see how close it lands to a true 360°.

Data

Run each version — all should be 360°
VersionTotal ticks for 360°ticks ÷ 360 = ticks_per_degree
A — four 90° turns
B — eight 45° turns
C — two 180° turns

They won't perfectly agree --- and that's the lesson

You’ll find it’s incredibly hard to make all three land on a perfect 360°. Every time the robot starts and stops a chunk, inertia carries it a little extra, and friction varies. More chunks (eight 45s) means more start-stops and more error pile-up. There is no single perfect ticks_per_degree — your job is to find the value that fits your robot best across the cases you care about.

Did your three ticks_per_degree values come out the same? Why might the eight-turn version (B) drift more than the two-turn version (C)?

Which ticks_per_degree value will you use as your model, and why did you pick it?

Phase 4 — Build: The Turn Function

Now build Turn — and it introduces two more new ideas at once: it takes two parameters (a char and a double), and it returns a value to report whether it worked.

Two parameters, two different types

Until now your functions took one input (or none). In the definition of Turn, direction and angle are the two named parameters. In each call below, values such as 'R' and 90.0 are the arguments supplied to those parameters:

Turn('R', 90.0);    // turn right 90 degrees
Turn('L', 45.0);    // turn left 45 degrees
An int function that returns success or failure

Every function you’ve built has been void — it did something but handed nothing back. Turn is an int function: it returns a number that reports what happened. We’ll use 1 for success and 0 for failure (a bad direction). return also immediately exits the function — so a bad input never reaches the turning code.

Defensive: forgive upper OR lower case

A good function is easy to use and hard to break. Instead of demanding a capital 'R', accept either case with the OR operator || — true if either side is true. That way a user who types 'r' still succeeds — one less thing to remember.

if (direction == 'R' || direction == 'r') // either capital or lowercase
{
}
// Unit 4, Big Idea 3: The Turn Model
// Name: _______________________   Date: ___________

#include <kipr/wombat.h>

#include <yourname.h>

double ticks_per_degree = ____;   // YOUR best value from Phase 3

int Turn(char direction, double angle);   // PROTOTYPE (note: returns an int)

int main()
{
	Turn('R', 90.0);      // right 90
	Turn('l', 45.0);      // left 45: lowercase works too!
	return 0;
}

int Turn(char direction, double angle)
{
	int ticks = angle * ticks_per_degree;   // PREDICT ticks from the model

	if (direction == 'R' || direction == 'r')     // RIGHT (either case)
	{
		cmpc(0);                                    // right pivot watches left wheel
		while (gmpc(0) < ticks)
		{
			mav(0, 300);                            // slow velocity, left forward
			mav(3, -300);                           // right backward
			msleep(10);
		}
	}
	else if (direction == 'L' || direction == 'l')  // LEFT (either case)
	{
		cmpc(1);                                    // left pivot watches right wheel
		while (gmpc(1) < ticks)
		{
			mav(0, -300);
			mav(3, 300);
			msleep(10);
		}
	}
	else                                             // not R/r or L/l: bad input!
	{
		printf("Invalid direction! Use 'R' or 'L'.\n");
		return 0;                                   // report FAILURE and stop here
	}

	motor(0, 0); motor(3, 0); msleep(50);           // brake-settle (your usual stop)
	return 1;                                       // report SUCCESS
}

Test Turn('R', 90.0) and Turn('l', 90.0). Did both work, even with the lowercase L? Why does accepting both cases make your function easier for someone else to use?

Now try a bad input like Turn('X', 90.0). What did the robot do, what got printed, and what did the function return?

Phase 5 — Test Your Model on Real Angles

Your model should now turn any angle. Test a range, both directions, and measure how close each lands. Remember: it’s a best-fit, so expect small errors — especially on bigger angles.

Ask for an angle, measure what you got
TryTurn callActual angle turned (degrees)
1Turn(‘R’, 90.0)
2Turn(‘L’, 45.0)
3
4

How close were your turns to the angles you asked for? Were small angles or big angles more accurate? Why might that be?

Phase 6 — Add to & Connect

Add ticks_per_degree and your Turn function to your library. Now any mission can turn any angle, either direction, with one readable call — and you can retire the old fixed 90° turns.

AI Literacy Thread

Models are best-fit approximations — never perfect, but good enough to act on.

Your three calibration runs disagreed, and no single ticks_per_degree was perfect. That’s not failure — that’s how models work everywhere in AI. A weather model, a self-driving car’s physics, a language model’s predictions: none are exactly right. They’re the best fit to messy real-world data, good enough to act on while never being flawless. The skill isn’t finding a perfect model — it’s finding one that fits well enough and knowing its limits.

Read each scenario. Think it through, then write your answer.

Why is it impossible to find one ticks_per_degree that turns every angle perfectly? Connect this to why real AI models are never 100% accurate.

Your Turn function returns 1 for success and 0 for failure. Why is it useful for a function to report back whether it worked?

Phase 7 — Individual Reflection

Complete this section on your own.

1. What is a char, and why must 'R' use single quotes?

2. Explain the three parts of a for loop, using your calibration spin as the example.

3. Your Turn takes two parameters and returns a value. What are the two inputs, and what does the return value tell you?

4. Complete in 2–3 sentences: “Models are best-fit approximations, never perfect. This means that when my robot turns, I should expect…”

Extension Challenges

Finished early? Try one or more of these.

Extension A — Slow vs. Fast

  • Recalibrate at a faster mav speed. Does the robot overshoot more from inertia? How does that change your best ticks_per_degree?

Extension B — A Full Circle Test

  • Use a for loop to call Turn('R', 90.0) four times. Does the robot return to its start? Compare to your old fixed turns.

Extension C — Check the Return Value

  • Store the return: int ok = Turn('X', 90.0); then whether it succeeded. How could a mission use that to react to a failed turn?

Extension D — Retire the Old Turns

  • Find an old program that used turn_left()/turn_right() and replace them with Turn. Is the new version easier to read and change?

Extension E — The Recursive Version

  • Extension B used a for loop to call Turn('R', 90.0) four times. A recursive function could do the same thing by calling itself: a function that turns once, then calls itself again with one fewer turn remaining, until it hits zero.
  • Sketch (in words or ) what that recursive version would look like. Why might a loop be the more natural choice than recursion for this particular task?

Download saves a local copy of your answers. It does not turn in your work automatically; give the downloaded file to your teacher.

KIPR · Botball Explorer · Unit 4 Big Idea 3 — Student Lab