- Field: 8 ft × 4 ft = 244 cm × 122 cm
- One "block" = 27 cm.
CutebotPro.runBlockCnt(n)drives exactlyn × 27 cm, then stops. → distance in cm ÷ 27 = block count (round to the nearest whole number). - The golden rule: the kick goes the way the bot is FACING. Finish your launch behind the ball, aimed straight down the field.
- Measure first. Before coding, use a tape measure: how far forward is the ball (
a)? how far to the side (b)? Those two numbers drive the math.
(0, 0), with the x-axis running forward toward the goal (distance a) and the y-axis running sideways (distance b). The ball's location is the point (a, b). Every strategy below is a different path from (0, 0) to (a, b).
Heads-up: in algebra class, x usually runs horizontally and y vertically. On a real field, "forward" looks vertical — so in this lesson, x = forward. Different convention, same math.
Command cheat-sheet
CutebotPro.runBlockCnt(n) // drive n × 27 cm, then stop (best for geometry) CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 45) // spin left 45° in place CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 90) // spin right 90° in place CutebotPro.pwmCruiseControl(left, right) // drive wheels (use currentPower) CutebotPro.stopImmediately(CutebotProMotors.ALL) // stop basic.pause(500) // wait 0.5 s
Students often struggle more with picking a strategy than with executing one. Use this tree as a 60-second warm-up: read the ball position, follow the matching row. Strategy 3 always works as the general solution — the rows below are just the easier match for common geometries.
a ≈ b.a ≈ b.a ≠ b. The general case.runBlockCnt available (older bot, blocks editor).Ten launch strategies, but only one model. The lesson is fundamentally about modeling a point in space — measure the ball's location, represent it as a coordinate, compute the path, convert the path to robot commands. Everything else is a special case, a comparison, or an application.
The modeling cycle
a, sideways distance b.(0, 0). Ball at the point (a, b). The field is now a coordinate plane.c = √(a² + b²). Launch angle θ = tan⁻¹(b ÷ a). The general solution.c ÷ 27 blocks. Turn θ° in place. Run the code. Compare prediction to reality.How the ten strategies relate
Once you see the modeling cycle, the ten cards stop looking like ten unrelated recipes:
c = √(a² + b²), θ = tan⁻¹(b ÷ a). Works for any ball position (a, b). Every other strategy in this guide is either a simplification of this one or a comparison against it.- Strategy 1 · Straight Shot — when
b = 0(ball dead ahead). No turn needed;θ = 0°. - Strategy 2 · 45° Diagonal — when
a = bon the left.θ = 45°;c = a√2. - Strategy 7 · Mirror Diagonal — when
a = bon the right. Strategy 2 reflected across the x-axis.
- Strategy 4 · L-Path — comparison. Two legs vs one diagonal. Triangle inequality lives here.
- Strategy 5 · Midpoint Hold — application. Coordinate midpoint when the ball's position is unknown.
- Strategy 6 · Swing Wide — application. Arc geometry (
L = rθ) to get behind the ball. - Strategy 8 · Sniper Hold — baseline. Tiny nudge; let the sensors run the model.
- Strategy 9 · Time-Based Diagonal — implementation variant of Strategy 2, using time instead of distance.
- Strategy 10 · Arc Launch — implementation variant. Curve in one motion instead of turn-drive-turn.
Color stripe = difficulty (green easy · amber medium · red challenge). Strategy 3 is highlighted as the core — every other strategy is a simplification, comparison, or implementation variant. Code is a starting point; students tune the numbers to their own field.
// Ball is dead ahead. Drive straight at it; // the locked code finishes the kick. // 81 cm to the ball -> 81 / 27 = 3 blocks. CutebotPro.runBlockCnt(3) basic.pause(150)
a = b) has a 45° angle; its hypotenuse is a × 1.41.// Turn 45° toward the ball, drive the diagonal, // then turn back 45° to face the goal. CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 45) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) // Hypotenuse: each leg ≈ 81 cm -> diagonal ≈ 115 cm ≈ 4 blocks. CutebotPro.runBlockCnt(4) basic.pause(150) CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 45) basic.pause(150)
(0, 0) to (a, b). The hypotenuse and the launch angle are both given by the coordinates.a and to the side b, NOT equal.a = b (giving θ = 45°). Strategy 1 is the special case where b = 0 (giving θ = 0°). Once students see this, the earlier strategies become shortcuts — not separate moves to memorize.// Example: a = 120 cm forward, b = 60 cm left. // angle = atan(60 / 120) ≈ 27° // c = √(120² + 60²) ≈ 134 cm -> 134 / 27 ≈ 5 blocks CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 27) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) CutebotPro.runBlockCnt(5) basic.pause(150) CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 27) basic.pause(150)
a + b is always longer than √(a² + b²) (the triangle inequality).a, to the side b.// Leg 1: forward toward the ball's depth. CutebotPro.runBlockCnt(3) // ~81 cm forward (a) basic.pause(150) // Turn to face the ball's side. CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 90) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) // Leg 2: across to the ball. CutebotPro.runBlockCnt(2) // ~54 cm sideways (b) basic.pause(150) // Re-face the goal. CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 90) basic.pause(150)
(122, 0) in cm. Posting up here minimizes the worst-case distance to wherever the ball ends up. Coverage-area optimization.// Drive to the midpoint of the field (forward axis). // Field is 244 cm long; midpoint = 122 cm = 4–5 blocks // from your goal line. CutebotPro.runBlockCnt(4) basic.pause(150) // Why post here? From (122, 0), the worst-case ball position // is the far corner: √(122² + 122²) = 122√2 ≈ 173 cm. // Compare to (0, 0), where the far corner is √(244² + 122²) // ≈ 273 cm. The midpoint cuts the worst case by ~37%.
((x₁+x₂)/2, (y₁+y₂)/2) applied to a real field. Optimization framing: a fixed position that minimizes maximum distance to a moving target. Compare with a forward rush — when does each one win?r and a sweep angle θ (in radians); the arc length is L = r × θ.r (~30–50 cm is typical) — bigger r is more forgiving, smaller r is quicker but more error-prone.r first and then derive L are doing real engineering.// Curve out and past the ball, then come back in // lined up with the goal. CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 30) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) CutebotPro.runBlockCnt(3) // drive out and past the ball basic.pause(150) CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 30) basic.pause(150)
L = rθ), and the relationship between sweep angle and distance traveled — the same math that connects to circles, tangent lines, and inverse kinematics later on.CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 45) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) CutebotPro.runBlockCnt(4) basic.pause(150) CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 45) basic.pause(150)
// Short nudge forward; let the sensors find, // aim, and kick on their own. CutebotPro.runBlockCnt(1) // ~27 cm basic.pause(150)
powerScale makes the distance come out the same on fast and slow bots.runBlockCnt available).CutebotPro.trolleySteering(CutebotProTurn.LeftInPlace, 45) basic.pause(300) CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) CutebotPro.pwmCruiseControl(currentPower, currentPower) basic.pause(Math.round(1500 * powerScale)) // tune the 1500 until it reaches the ball CutebotPro.stopImmediately(CutebotProMotors.ALL); basic.pause(150) CutebotPro.trolleySteering(CutebotProTurn.RightInPlace, 45) basic.pause(150)
powerScale is for. Have them race a fast build vs a slow build and watch the difference shrink with powerScale.// Left wheel slower than right -> the bot arcs LEFT // toward the center line. CutebotPro.pwmCruiseControl(Math.round(currentPower * 0.6), currentPower) basic.pause(Math.round(1400 * powerScale)) // tune time for your field CutebotPro.stopImmediately(CutebotProMotors.ALL) basic.pause(150)
0.6 (sharper vs gentler arc). Swap the wheel values to arc right.Once students can run the strategies, switch the question from "did it work?" to "how efficient was it?" The L-Path (Strategy 4) and the Measured Diagonal (Strategy 3) reach the same point. They don't travel the same distance.
(a, b) — and decide whether the savings are worth the extra turning math.
Extensions you can run with this:
- For which
(a, b)values does the diagonal save the most? Hint: the percentage advantage shrinks as one leg becomes much larger than the other — but the absolute savings in cm don't always shrink. Have students check both. - If turning takes time too, when does the L-Path actually win on total seconds — even though it loses on distance?
- Plot path-length vs. ball position on graph paper. The triangle-inequality result is suddenly a visible curve.
- Everyone starts with #8 (Sniper Hold) — get a baseline, see the bot play.
- Measure the ball: record
(a, b)in your data table before anything else. Have students point at the origin (0, 0) and the ball (a, b) before they touch the code. - Pick a strategy using the decision tree in Section 02.
- Predict, then test. Before running, write the predicted distance, angle, and time-to-ball in the data table. After running, record what the bot actually did. The gap between prediction and actual is the lesson — much more than the result itself.
- Iterate: the numbers in every example (
runBlockCnt(3),45°,1500) are starting points — students tune them to their own field and bot. Each tune is a new row in the data table. - Compare strategies: which scores fastest from the same ball position? Which had the smallest prediction error? They're different questions, and the data table makes both answerable.
Match log · data collection
Hand teams this table at the start of the lesson. One row per run. Three rows minimum before they're allowed to claim "this strategy works."
| Strategy | (a, b) | Predicted distance | Predicted time | Actual time | Error = Actual − Predicted | Goal? | Tune for next run |
|---|---|---|---|---|---|---|---|
| 1 · Straight | _____ | _____ cm | _____ s | _____ s | _____ s | Y / N | _____________ |
| __ | _____ | _____ cm | _____ s | _____ s | _____ s | Y / N | _____________ |
| __ | _____ | _____ cm | _____ s | _____ s | _____ s | Y / N | _____________ |
| __ | _____ | _____ cm | _____ s | _____ s | _____ s | Y / N | _____________ |
A positive error means the bot took longer than predicted (most common — friction, wheel slip, battery drain). A negative error means it beat your prediction. After a few rows, students can spot whether their errors are systematic (always positive, always negative) or noisy. Systematic error → tune the formula. Noisy error → tune the bot.
After the optimization comparison (Section 04) and a few rows of real data, change the question one more time. Not "did it score?" Not "which distance was shortest?" Not "which turn count was lowest?" — but: which strategy reliably gets the ball into the goal in the fewest total seconds, averaged over multiple runs?
~300 ms per pivot, plus settling time. A 45° diagonal that takes two turns may lose to a longer L-Path that takes zero turns at speed if the field is short.- Average successful time =
(sum of successful run times) ÷ (number of successful runs). Speed when the strategy works. - Reliability =
(number of successful runs) ÷ 3. Probability the strategy works at all.
The winner is whichever strategy has the lowest average successful time AND reliability ≥ 2/3. A 1.2 s strategy that succeeds 1 of 3 times loses to a 1.6 s strategy that succeeds 3 of 3. Defend your pick with the data table — not the highlight reel.
This is the question engineers actually answer in the real world: not "what's possible in the best case?", but "what wins on average, accounting for failure?" Bring the data table forward — every row a team filled in becomes evidence for or against their final pick.
trolleySteering (dead-reckoned by degrees), and drives can be distance-based (runBlockCnt) or time-based (pwmCruiseControl + pause). Distance-based is more repeatable — push students toward it for anything that depends on geometry.