Why Does This Robot Need Two Brains?
A genuine question I had before I understood the answer: the Pi already runs Linux and ROS2. Why bolt on a whole separate microcontroller too?
I was ready to blame the servo. The model had been telling me it was something else for two days.

I was ready to blame the servo. The model had been telling me it was something else for two days.*
Here's the question I actually had, unfiltered, the first time I felt the wiggle on straight sections at speed: after Hung's steering geometry upgrade gave MentorPi-A1 eleven extra degrees of lock, the robot handled beautifully at walking pace and did something faintly unsettling at higher speed instead. New geometry, more torque demand at the extreme — isn't the servo the obvious suspect? It's new hardware doing more work than before. Why wouldn't I just swap it for a stronger one and call it a day?
The way I actually worked through this wasn't by ordering a new servo first — it was by imagining what a struggling servo would actually look like if I could see inside the control loop instead of just feeling the wheel wiggle from the outside. Torque demand exceeding what it could deliver. Response lagging further and further behind as speed increased. A clean story: new geometry, harder job, servo can't keep up, buy a bigger one.
The trouble was I couldn't actually see any of that just by watching the robot. All I had was a wiggle at speed and a plausible-sounding suspect. I was two days into being ready to blame the servo on a story I hadn't actually checked against anything.
[CHÈN ẢNH INLINE TẠI ĐÂY]
So I built the model I should have built before touching anything. A bicycle-model representation of the steering geometry, coupled to the actual servo dynamics — not an idealized instant-response actuator, but one with the real measured delay and rate limit — fed with the same commanded-speed and commanded-angle profile we were sending the real robot. If the servo really was the problem, the model should show it: torque demand exceeding what the servo could deliver, response lagging further behind at speed.
It didn't show that. The servo, in the model, was keeping up fine. What the model showed instead was a steering-loop gain that had been tuned for the old geometry's turning radius and never revisited after the mechanical change — at low speed, forgiving; at higher speed, just underdamped enough to produce exactly the small rhythmic oscillation we were seeing on the bench. Two days of watching that mismatch between what I believed and what the model kept insisting was genuinely uncomfortable. I trust hardware problems. They feel more real than a coefficient in a block diagram.
I retuned the gain to the value the model suggested, loaded it onto the real robot, and ran the same speed profile. The wiggle was gone. No new part, no swapped servo — just a control parameter that should have been touched the moment the mechanical geometry changed, and wasn't, because nobody had a way to see the consequence of that gap until there was a model sitting between the geometry change and the control loop.
This is the whole argument for Model-Based Design, and it's easy to lose track of on a project this size, where "just try it" usually works fine. It doesn't always. Sometimes the part that's wrong is invisible until you build the thing that can disagree with you — and then you find out the disagreement was the useful part all along.