In the past, we’ve used Python and C++ for our robots but this year we switched to Go. Why the change? It seemed like a good idea at the time
To be honest, the main reason was that I signed up to lead the coding effort this year. I haven’t had much C++/Qt experience (so it wasn’t easy for me to pick up last year’s code) but I’ve been working in Go in my day job for a couple of years; I enjoy working with Go and the language has some features that are appealing for building robots:
“Naturally” written Go is just plain faster than “naturally” written Python (by some margin).
Go can take advantage of more than one core by running multiple goroutines at once (and the computer scientist in me can’t resist a bit of CSP). The normal Python interpreter is limited to one core.
It felt like a good choice because it sits at the right level, giving access to low-level primitives (like pointers and structs) for interfacing with C and hardware while also offering garbage collection and other modern features for rapid development.
I have found Go to be a good language to program a bot. The biggest downside was that the library ecosystem is a bit less mature than Python or C(++). That meant that getting the hardware driver layer of the bot together required quite some work:
We found that the Go wrapper for OpenCV (gocv) required a patch to work on the Pi. (I found the patch in a forum post but I can’t dig it out to link to.)
We didn’t find a working Go driver for the VL53L0X time-of-flight sensors, so (after some false starts) we took the existing C-wrapper that GitHub user cassou had already ported for the Pi and wrapped it in a Go library using CGo (Go’s C function call interface).
We ported a Python sample joystick driver for the DS4 to Go. The Linux joystick interface turned out to be easy to access.
There were a few i2c libraries without a clear winner. We ended up using golang.org/x/exp/io/i2c.
While it made some work, I find the low-level bit banging quite fun so it wasn’t much of a downside 🙂
We spend a big chunk of last weekend trying to track down an issue with our motor driving logic. The problem was that sometimes a fast change of direction would cause the i2c bus to die; writes from the Pi would fail and the bot would go crazy as result.
We knew it was likely to be one of a couple of factors:
High current draw from the quick change in direction causing a brownout.
Motor switching causing interference/voltage spikes.
Unfortunately, not owning an oscilloscope, it was hard to pinpoint the exact cause so we resorted to magic capacitive pixie dust and software changes:
We added large reservoir capacitors to the power inputs of the various boards to provide a store of charge in case the power rail momentarily dropped.
We added small decoupling capacitors too to help filter any noise.
Those changes did seem to help but they didn’t eliminate the problem completely. An extra layer of software changes seems to have done the trick:
We changed the i2c driver code to close and reopen the device file after a failure. The hope is that that resets the bus more thoroughly than simply retrying the write.
After John mentioned that he’d seen issues with it in the past, we took control of the GPIO pin that is attached to the propeller’s reset pin and started actively driving it rather than letting it be weakly pulled up with a resistor.
We beefed up our retry loop, with escalation. If it fails enough times, it resets the propeller and reflashes it. That takes about a second but it might just save us on the day!
We implemented a maximum ramp rate for the motors so that we change their speed a little slower.
We put the motor PWMs out-of-phase so that they don’t all start and stop on the same clock cycle.
With all those changes in place, we’ve seen a few retries but it’s hasn’t escalated to a reset yet so, fingers crossed, the problem is fixed enough.
Panic panic panic, must pull my head up out of the code and start blogging!
It’s been an eventful 18 months for the Metabot team. The balance of the team moved from our old home at Metaswitch to a new company, Tigera. We couldn’t resist a name change so I’d like to introduce Tigerbot….
(It’ll be orange and black striped by the big day, we promise!)
The picture above shows the bot’s bare bones before we added the motor drivers and power circuitry. Lance’s new 3D printer has been getting a good workout, churning out the new chassis, wheels and attachments.
Just in case there are any PiWars organiser’s reading, the bot’s a lot further along by now, of course! Not long after the above photo, Lance had the bot to “remote control car” stage:
This is the traditional point for him to lose interest move on to building whizzy attachments while the code monkeys on the team get to work.
Joking aside, “remote control car” is a huge milestone:
power electronics in place to drive the motors, Pi and sensors
Propeller hat mounted on the Pi; this little board gives us a fast little micro-controller to do hard real time motor speed and servo position control; a big hat tip to John who wrote all the Propeller spin code for Metabot II, which we’re using largely unaltered
interconnect board soldered up, exposing the I2C bus, which we use talking to the Propeller and sensors
remote control connected; we’re using a DualShock 4 controller again paired over Bluetooth
It’s a bot! IT WORKS!!
Now, the rest is “just code”…