Guide for Developers

By reading this guide, you can expect to learn about the architecture of the server and the client and everything around it, the inner workings of each module, and the ‘why’ behind major design decisions.

Server

Server is an application designed to run on an on-board computer (e.g. ODroid) and allow clients to upload and download files to and from the on-board computer. For example, you might use this server to upload camera configuration files and download images that the camera has captured.

HTTP The reason we went the HTTP server route for exchanging files between ground and UAV computers is that most of it is already implemented in a standard library (read: not written and maintained by us) and as a result it’s very easy to use. We didn’t build a server but instead wrote the logic for what should happen when a client makes a specific HTTP request. Everything from establishing and managing connections to parsing and validating requests is handled by the library.

An obvious downside to using a HTTP server library is the overhead that it adds. Especially for a simple task such as ours, where most of the time we will have a single connected client downloading every image stored on a server, using a lightweight socket would make more sense. However, using a socket means we operate on a byte level and we have to implement any control codes and checksums that we need to validate the integrity of the data, which will take a lot of time and will still have a lot of bugs. The HTTP library does all of that for us - it has been developed and tested for a long time, it had very experienced people working on it, and it likely had been optimized as much as possible. Lastly, the overhead that this library adds barely affects the performance in our and many other cases, so it’s a good choice for us that ended up saving a lot of time.

Docker First of all, Docker is a really neat program, so go look up some videos on YouTube that explain what it is and why it’s used so often. If you find it confusing - that’s okay, I don’t fully understand it either. Docker is powerful because of how sophisticated it is - it takes time and probably some specialized knowledge to wrap your head around it, so take in as much information as you can and carry on.

Docker isn’t used when you’re developing your application. Instead, Docker comes in when you’re ready to “release” your app and begin using it - Docker provides an easy way to deploy your code and a few other convenient features, some of which we will talk about as they are the reason we chose to use it.

When you work on a project, over time you write the code and build the environment in which the code runs (side note: if you’re using Python, use virtual environments or, better yet, pipenv). Once you are ready to release your code, you would want to record the environment in which the app runs and come up with a way to replicate that environment on another computer. One way to do this is to write a shell script that will install all the packages you need. There are two problems with that: first, things you install using that script will be installed system-wide, meaning that you might run into the problem of conflicting package versions if you have multiple apps requiring different versions; second, if your development operating system (OS) is different from the OS on which you run your app (e.g. you have Ubuntu 18.04 on your laptop, but the ODroid is still running Ubuntu 16.04 for compatibility reasons), packages with the same name might have changed between OS releaases, and your app might not work as you expect.

Enter Docker. Docker achieves two things, namely it isolates an application and its dependencies and it also makes sure it can run anywhere (where Docker engine is present, read: where you can install Docker like you did for running the server). If you put your application and your dependencies into a Docker container, then you can run multiple apps on the same system without worrying about their dependencies conflicting. Moreover, because OS libraries are also packaged in a Docker image (a container is an instance of an image), you don’t have to worry so much about the host OS on which your application will run - as long as you can install Docker engine on it, you’re good. In other words, if your application must run on Ubuntu 18.04, but you are stuck with using Ubuntu 16.04 on your host, as long as you can install Docker on the 16.04, you should be good because everything that you need from 18.04 will be included in the image.