Close

Software Refactoring Progress

A project log for Ladon Project

A robot to sail around the world alone

pierce-nicholsPierce Nichols 12/07/2015 at 04:360 Comments

The big takeaway from our launch was that our software needs a major overhaul. Since we're not getting back in the water anytime in the next couple of months, this is what we are working on now.

Software Refactoring

I've taken the first cut at refactoring the Arduino code and defining a new REST API for the boat. The results can be seen in the doc/systems folder of the main repository.

One of the things I did was move all of the configuration and operational code into an Arduino library. This is largely to make it easier to write unit test code, since Arduino lacks any other reasonable way to compile multiple sketches off a single code base.

The way aREST handles variables and functions forced me to modify my original vision for the API a bit, but nothing too major. The state and REST tables reflect the changes, but the top level system description does not yet. I had to modify aREST along the way, adding the ability to turn direct pin access on and off. I also modified the handle() method to return a boolean indicating whether or not it had found a valid message. Once I've tested these functions adequately, I'll issue a pull request for it.

Last night, Jeremy, Wim, and I knocked around some ideas for software organization on the Beaglebone and some initial thoughts on what the UI is going to look like. Here's a shot of the whiteboard before we went home:

The map block will show the current location of the boat and the waypoints. Map data will come from Google Maps or a local store. Current position and waypoint list should be self-explanatory. The list of buttons to the right of the map block corresponds to the different boat states. The current state will be lit and the operator will press one to request a change. Below the waypoint list is a block to enter the desired course of the boat and a compass rose to show the current heading, current target course, and a draggable pointer to allow the user to set the course. The rudder block shows the current position of the rudder and, in the right boat state, allows the user to set it. The block to the right of this displays a bunch of boat health/state stuff. I listed some things that ought to be there, but that's not an exhaustive list.

The Beaglebone side is deceptively simple, but we sure talked about it a lot. Lighttpd should be self-explanatory -- it's a popular lightweight webserver for embedded applications. Having a running webserver makes it straightforward to serve back log files, camera images, and the like without a bunch of new UI. It also gives us access to existing authentication and SSL tools. That calls a REST handler on receipt of requests. That module can read and write from the Arduino via serial port. It can also read and write to a data store that it shares with the state machine module. The state machine module maintains the state of the Beaglebone, the waypoint list, and does the navigation.

Jeremy suggested something called microhttpd instead, which is a library designed to be statically compiled into the program in order to provide httpd functionality. I wasn't hugely in to it at the time, because I like the idea of being able to serve static stuff like log files directly. It also nicely separates functions into separately testable bits. However, thinking about the complexity required to make the data store part work, squishing this all into a single program sounds better and better. We can still have a regular httpd for everything else.

There's also an other shit box running into the state machine... that's other navigation data, which I'll get to in a bit.

A couple of things came out of this discussion...

  1. We're going to need some help on the Javascript front to do the UI in a way we can live with. Our thought so far is that it's going to be something with jQuery and some javascript widget library yet to be identified.
  2. The data store block in the Beaglebone code diagram to the left probably wants to be a database if we maintain separate programs.

Obstacle Avoidance

There is good open source digital map data... as long as we have a hard rule to remain a sufficient distance from shore, we should be fine. Some interesting local areas are pretty congested, with distances between adjacent islands as small as 50 - 60 meters. This will require some thought and perhaps on the ground measurement of tight areas to assure ourselves that the data is in fact good. The other problem is GPS accuracy -- GPS alone is not good enough to stay off the rocks in some areas.

A key element for any autonomous operation in in-shore waters is some way to avoid other traffic. Bigger ships (ferries, container ships, fishing vessels, some yachts) are kind enough to transmit their identity, location, speed, and heading via AIS. Dedicated AIS receivers run from $200 on up, but a little digging around shows that you can do it with an RTL-SDR dongle, and those cost about $20. Conveniently, the ships we most want to stay far away from, like ferries (aka imperial entanglements), are also the most rigorous about having functional, accurate AIS gear onboard. Since AIS users are using local GPS, systemic errors are likely to be constant between different users. Rocks, kayakers, and most smaller pleasure craft do not have AIS, however.

My intuition for the right way to sense obstacles is the same way I do -- stereoscopic vision. Invitingly, OpenCV has functions that just do this, and WiFi cameras are inexpensive. We have a baseline of a meter or so in the form of the forward solar panel. If we assume 60 degree field of view and a horizontal resolution of 640, this gives us a maximum theoretical range of about 300m... although somewhat less in practice due to noise etc.

Jeremy attended an autonomous sailboat talk at UW a few months back, and noted that they were trying a similar approach and having issues with it. In particular, they were having problems discriminating between actual obstacles and the water. I think we can avoid some of this by removing the water from the scene by determining the current position of the horizon relative to the boat and simply cutting it off. We already have pitch and roll sensors, so this ought to be straightforward. We'll see how it works in practice.

Discussions