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 Submit & Download to turn in your work and save a copy.

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 model 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 while loops 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
{
	long 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(1, -300);             // right wheel backward (pivot right)
	}
}
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). Turn takes two, separated by a comma — a direction and an angle:

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(1, -300);                           // right backward
		}
	}
	else if (direction == 'L' || direction == 'l')  // LEFT (either case)
	{
		cmpc(1);                                    // left pivot watches right wheel
		while (gmpc(1) < ticks)
		{
			mav(0, -300);
			mav(1, 300);
		}
	}
	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 printf 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?

When you are finished, press the button to turn in your work and save a copy.

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