Living Museum of Learning

Where real moments become exhibits
← Prev Next →
When the Pedals Hit the Ground

When the Pedals Hit the Ground

A 300-line bicycle, a tiny s, and a surprisingly physical lesson in abstraction

Situation

Enning had been building a 3D bicycle in p5.js piece by piece. By this point, the bike had grown into a substantial program: wheels, rear forks, lower bars, seat bar, seat, triangle frame, front fork, handlebars, coordinate axes, and now pedals.

The pedal itself had already become a reusable tool. Following the same idea she had used earlier for her bike seat, Enning changed drawBikePedal() so that it accepted a scale factor:

drawBikePedal(s)

This seemed simple enough. But for a beginner, the little s opened another world of confusion. Donald had already explained many times that the s inside one function had nothing to do with an s somewhere else.

“This s has nothing to do with that s.”

The sentence had been repeated dozens of times.

There was s here, s there, then t here, t there. Enning's head could spin.

But she was getting better. She had already experienced the idea with the bike seat: one simple function call could produce a complete, properly sized object.

Now the pedal needed to become the same kind of tool.

Turning Point

Enning experimented with the new scale parameter.

At one point she discovered something neither of us had planned for: negative scale.

Donald thought he had a clever solution.

“If we use -1 for both, we change both pedals. So it still works, right?”

Enning agreed and put -1 into both function calls.

Then she started enjoying the strange new result.

Donald looked closer.

“Wait a minute. Does it really work?”

It didn't.

The two pedals, which were supposed to sit outside the two pedal arms, had suddenly appeared between the arms.

We both started laughing, and we recorded the moment.

The experiment had made something important visible: the scale factor was not simply a “size number.” A negative value also changed the orientation of the geometry.

Enning then put 1, and later 0.7, back into the pedal calls and was ready to ship the pedal tool.

But there was one more refinement.

Donald noticed that the axis connecting the two pedal arms was not following the same scale factor. As the pedal changed size, the axis quickly went out of sync.

Enning moved the axis-drawing code inside drawBikePedal() so it could use the same s.

The pedal was now a proper reusable component.

Emergence

Then came the exciting moment: mounting the pedal onto the bicycle.

After more than 300 lines of code had built the bike, Enning needed only two lines to add her new component:

translate(0, 15, 0)
drawBikePedal(0.3)

The huge program suddenly became wonderfully simple at the point of use.

Hundreds of lines described how to build the whole bicycle.

One function call described the pedal that belongs on the bicycle.

And the 0.3 told that function how large the pedal should be.

But the first mounted pedal was still hilariously wrong.

Enning looked at her own bicycle and said:

“Something isn't quite right~”

Of course something was quite wrong. 😂

Even at 0.7, the pedal was enormous compared with the tiny wheels. As the crank rotated, the pair of pedal pieces swept down far enough to touch the ground twice every revolution.

The code was working perfectly.

The bicycle was physically ridiculous.

Donald came to the rescue:

“Your pedal is still too big even with 0.7 scale.”

Enning woke up, changed the argument to:

drawBikePedal(0.3)

and suddenly the bicycle began to look like a bicycle.

The demo she recorded was already wonderful.

Then, near the end of class, Enning looked again.

“Our wheels are too small.”

She had found the next physical problem herself.

The wheel code hadn't originally been designed with flexible scaling, and there wasn't enough time to redesign it properly.

“Yes, we can make them bigger. But we'll do that later.”

And that was a perfect place to stop.

The bicycle was not finished.

But the learning was very much alive.

Enning's 3D Bike with Pedals:

Learning

Enning experienced several layers of abstraction without having to learn them as isolated programming vocabulary.

She saw that a function can package a complicated object behind a simple call:

drawBikePedal(0.3)

She continued wrestling with the difference between a formal parameter and an actual argument. The s in

function drawBikePedal(s)

is simply the local name the function uses for whatever value is supplied when it is called.

So:

drawBikePedal(0.3)

means that, for this particular call, the function's s becomes 0.3.

This distinction is easy to say and surprisingly hard for a beginner to internalize. Enning didn't need another definition. She needed another experience.

The pedal gave her several.

She also discovered that abstraction is not merely about making code shorter. Once the pedal became a component, all of its geometry had to obey the same parameter. The pedal arms, pedal pieces, and connecting axis needed to scale together.

And then the completed component could be moved into the much larger bicycle with just two lines.

Most importantly, Enning learned to look at her program's output with the eyes of a person who understands the thing being modeled.

A syntactically correct bicycle can still have pedals that hit the ground.

And a bicycle can be beautifully modeled and still have wheels that are too small.

The computer executes the code.

The learner has to decide whether the world it creates makes sense.