The first time I ran the vehicle under its own control, it moved about two meters, turned sharply into a wall, and stopped. I had been so focused on getting it to move that I hadn't seriously thought about what would happen when it encountered something it wasn't expecting.
Looking back, this was entirely predictable. But at the time, I had convinced myself that the sensor readings were reliable enough to catch anything in the vehicle's path. They weren't.
The first wrong assumption
I assumed ultrasonic sensors produced clean, consistent distance readings. They don't. The readings I was getting varied by 15–30% depending on the angle at which the sound waves reflected off the object. At certain angles — particularly when approaching walls at less than 45 degrees — the sensor would return nothing at all, because the reflected wave never made it back to the receiver.
My decision logic was: if distance reading < threshold → turn. But if the reading is sometimes zero or wildly incorrect, the vehicle is making navigation decisions on noise. This is exactly what happened.
The second problem: timing
Even when the sensors were giving correct readings, there was a lag between the reading and the motor response. I hadn't measured this — I'd assumed it was negligible. It wasn't. At the speeds I was running, the vehicle was already 20–30cm past an obstacle by the time the motor control signal reached the wheels.
The fix was straightforward in principle: run slower, or reduce the sensor read / control loop latency. But it made me understand something important — in embedded systems, timing is not an afterthought. It's part of the design.
The third problem: lighting
The computer vision component of the system — path detection from the camera — worked fine indoors under fluorescent lights. When I moved the vehicle near a window, the contrast changes broke the edge detection entirely.
I had tested in one environment and assumed the system would generalize. It didn't. The model I'd built (however simple) was overfit to the conditions I'd tested it in.
What I actually changed
I slowed the vehicle down significantly. I added a moving average filter to the sensor readings to reduce noise. I added a minimum time delay before trusting a new sensor reading after a sudden change (to catch spurious reflections). And I added indoor-only mode constraints, acknowledging that the vision system wasn't ready for variable lighting.
Version two worked better. Not perfectly — but better in ways I could explain and measure. That felt like real progress.
What this taught me
The most useful lesson wasn't technical. It was this: testing reveals assumptions you didn't know you were making. Every failure in this project was caused by something I had assumed without realizing I'd assumed it.
The practice of asking "what am I assuming here?" before and after a test is now the most valuable debugging habit I have.