Pi Wars Week -23: CV Self assessment
With a little more tweaking of my line following code from the previous post, R3L14NT is now capable of following zigzaggy lines. How did we get to this point from the test code in the previous post?
What went right?
I'm fairly pleased with how well the code can detect a line and figure out its position and angle. Specifically, using an edge detect transform to turn the input image into a gradient map works well, seems to ignore distractions, and has the added bonus property of working with both dark lines on light backgrounds and light lines on dark ones. It still gets confused by the bright white cabinets where I was testing it, but a better course mockup might fix that.
Using the line's position and angle means I can do something akin to PID control. If the line is to the right of the bot, naively it would
just steer towards the line, but if the line is also pointing leftwards that means we're already driving towards it so don't need to turn.
The two measures are combined to decide which way the robot needs to drive, which seems to result in stable control.
What went wrong?
I realised my "are the points I've found roughly in a line?" algorithm didn't work because of a (silly) issue. I was testing whether the gradient between a given point and the first point on the line was within a percentage of the gradient I'd established the line had. This is a silly idea: if the line is close to vertical, the gradient is very small so the allowed deviation is tiny - I didn't realise this because I was testing with the bot stationary and not giving it different angles to identify. To remedy this I used atan() to convert the gradient to an angle, and allowed a consistent deviation of +/- 10 degrees, which should give sensible behaviour for lines in different positions.
My other big cause of headaches was doing silly things like reversing the array of point positions on the line but not the array of line widths, so I wasn't looking at the right data points when working out how far the straight line extended. Hungarian notation (the proper kind, where you name your variables according to what sort of data they contain, not the silly Microsoft lpsz_thingy sort that's just about data types) helps out here - if I'm looking at r_points but widths not r_widths, it's clear something is wrong.
Don't test an algorithm against a single test case and say "that works" - give it tough challenges it to make sure it's robust
Draw inspiration from other people's work, but don't blindly recreate it or you won't improve anything
Hungarian notation is great