In Part 1, I discussed how I had to drop rosserial in favor of a homespun solution to create a ROS node for Sparki. I developed a communication protocol to talk between a ROS node on a PC written in python and Sparki's microcontroller. I created a slimmed-down version for the micro for SparkiSLAM.
Now, I'll discuss the development of the python side of things. The way this node should work is that it is constantly sending out sensor data to various ROS topics as the data is received from Sparki and it should be listening to various command topics, such as robot linear and angular velocity commands, which it should transmit to Sparki.
As is recommended, I created a python class for communicating with Sparki that does not depend ROS. This class needs to provide methods for sending commands such as motor speeds or to actuate the gripper. It also needs to read in messages from Sparki and process that data. The first part, sending commands is trivial: just format the message and send it over the serial connection. The second part is harder. I first considered using pyserial to handle the serial comms. It, however, does not do asynchronous reading of the data on the port. One must continuous poll the port to check if data is available. This isn't ideal, as nearly all data transfer in ROS is asynchronous. To simulate that with polling could be processor intensive.
Some quick googling led me to the twisted library. It took a bit of learning but I figured out that I could create a custom protocol for twisted's serial port that would allow me to trigger a callback function whenever a line ending in '\n' was received on the port. Every message in my protocol ends with that delimiter so this suited my needs perfectly. I added functionality such that a user can add their own callback functions for whenever a specific type of message is received. I.e. when accelerometer data is received, print it and when distance data is received, send it over a ROS topic.
This almost got me where I needed to be, with one problem. Twisted requires a reactor to be running to process its event queue and ROS also requires its spin() function it run to process its event queue. Time for some threading. After a bit of trial and error, I managed to get the twisted reactor to run on its own thread without interfering with the ROS functionality.
I setup the appropriate ROS publishers and subscribers in the ROS node file and now we're on our way.
Currently, the node only has enough functionality for the SLAM project but it's designed to very easily expend to support all of Sparki's functionality. Once I do that, I'll release it into the ROS ecosystem.
You can check out a demo of the node running in my first update video: https://www.youtube.com/watch?v=FrYAD91eReY