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
and len() · · 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 len() to confirm a string is exactly one letter long.
  • 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: Checking Length With len()

A string can hold any number of letters --- including just one

Python doesn’t have a separate type for “one letter” — a single character is just a string that happens to be one letter long:

direction = 'R'   # a string, one letter long

This is perfect for telling the robot which way to turn: 'R' for right, 'L' for left. But because Python doesn’t enforce a length for you, nothing stops someone from typing 'Right' by mistake — so you need a way to check.

len() tells you how many characters are in a string

len() returns the number of characters in a string. Use it to confirm you actually got a single letter before you trust it:

print(len('R'))        # 1
print(len('Right'))    # 5
print(len('R') == 1)   # True confirms that this is a single letter.

And remember: 'R' and 'r' are still different strings to the computer — capitalization matters.

What does len() tell you about a string? Why is checking len(direction) == 1 a useful safeguard when Python doesn’t have a separate type just for single letters?

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 with range() is for when you know exactly how many times to repeat. It counts for you:

for i in range(4):   # run 4 times: i = 0, 1, 2, 3
    # ...do this each time...

range(4) counts 0, 1, 2, 3 — four values, even though it stops before reaching 4. Each time through, i holds the next number, and the loop keeps going until range() runs out.

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 in range(4) → 90° each4 × 90° = 360°
Bfor i in range(8) → 45° each8 × 45° = 360°
Cfor i in range(2) → 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.

k.cmpc(0)                         # clear the counter once, before the spin
for i in range(4):                # Four chunks make one full 360-degree spin.
    target = (i + 1) * CHUNK_TICKS   # how far we should be after this chunk
    while k.gmpc(0) < target:
        k.mav(0, 300)              # Use a SLOW velocity while the left wheel moves forward.
        k.mav(1, -300)             # right wheel backward (pivot right)
k.motor(0,0); k.motor(3,0); k.msleep(50)   # brake-settle
print(f"total ticks = {k.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 direction and an angle), 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
A function that returns True or False for success or failure

Every function you’ve built so far hasn’t handed anything back. Turn is different: it returns a value that reports what happened. Python has a real type for exactly this — , which are just True and False. We’ll return True for success and False 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 keyword or — true if either side is true. That way a user who types 'r' still succeeds — one less thing to remember.

if direction == 'R' or direction == 'r':   # either capital or lowercase
#!/usr/bin/python3

# Unit 4, Big Idea 3: The Turn Model

# Name: _______________________   Date: ___________

import os, sys
sys.path.append("/usr/lib")
import _kipr as k
from yourname import *

ticks_per_degree = ____   # YOUR best value from Phase 3

def main():
    Turn('R', 90.0)      # right 90
    Turn('l', 45.0)      # Turn left 45 degrees. Lowercase works too!

def Turn(direction, angle):
    if len(direction) != 1:                          # defensive: must be a single letter
        print("Invalid direction! Use 'R' or 'L'.")
        return False                                  # report FAILURE and stop here

    ticks = round(angle * ticks_per_degree)   # PREDICT ticks from the model

    if direction == 'R' or direction == 'r':      # RIGHT (either case)
        k.cmpc(0)                                 # right pivot watches left wheel
        while k.gmpc(0) < ticks:
            k.mav(0, 300)                          # slow velocity, left forward
            k.mav(1, -300)                         # right backward
    elif direction == 'L' or direction == 'l':    # LEFT (either case)
        k.cmpc(1)                                 # left pivot watches right wheel
        while k.gmpc(1) < ticks:
            k.mav(0, -300)
            k.mav(1, 300)
    else:                                          # Any value other than R/r or L/l is invalid input.
        print("Invalid direction! Use 'R' or 'L'.")
        return False                                # report FAILURE and stop here

    k.motor(0, 0); k.motor(3, 0); k.msleep(50)      # brake-settle (your usual stop)
    return True                                     # report SUCCESS

main()

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 True for success and False 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. Why doesn’t Python need a separate type just for single letters, and what does len(direction) == 1 check for that Python won’t guarantee on its own?

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: ok = Turn('X', 90.0) then print() 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