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./watch?v=FrYAD91eReY