3D Robotics

3689678881?profile=original

I had so much fun playing around with DroneKit Python over the last month or so, that I thought I would try my hand at DroneKit Android. Specifically, I was interested in building a customized version of Tower. As always, this blog post is cross posted on my blog with a little nicer formatting here.

 

The DIY Drones community is probably well aware of Tower’s expansive capabilities as a mobile ground control station, specifically with regards the built in autonomous mapping and scanning modes. Some tens of thousands of users are currently leveraging Tower to control their Pixhawk-powered drones, many of these for small business or large enterprise. However, these commercial users are stuck with a multitool when all they need is a knife. Tower has so many features and functions that it can be quite overwhelming for first time users to create even simple survey. Furthermore, it is fairly easy for even advanced users to make simple mistakes like accidentally pushing the drone into ACRO using the drop down menu up top.

 

For my first DroneKit Android project, I set out to create an Agribotix branded GCS for Solo AGCO Edition. This isn’t any kind of official AGCO product, but just a fun project I thought would help me learn about DK-Android.

 

Key features I wanted to explore in DroneKit Android were how to:

  • Change styling, colors, and logos

  • Remove unnecessary flight modes

  • Fix camera settings

  • Remove hobby oriented settings

  • Force a UDP connection

 

While this project is obviously mostly an exercise in deletion, it served as a great introduction to what functions are available in DroneKit Android, how code is split between Tower and 3DR Services, and how a basic Android app is structured. Prior to this undertaking, I had never touched a line of Java or Kotlin or worked with an Android app, so I will assume the reader hails from a similar background.

 

I hope this guide inspires/enables some of you to create your own custom versions of Tower! My example apk is available here and my my source code is here.

Step 1: Get ready

 

If you aren’t already familiar with SITL, DroneKit, git, and the various developer tools I’ll mention here, head over to my Idiot’s Guide to DK-Python: A Journey to WHOZ CHILLIN and give it a quick read. You will be using many of the tools and concepts discussed previously to debug and test your custom version of Tower.

 

Note: DK-Python is fairly simple and well documented. DK-Android is not. If you are interested in an easier journey to a custom GCS, it may make sense to work in Python.

 

Next, download Android Studio. Google has built an incredible Integrated Development Environment (IDE) for building Android apps and you will be using it to do all of your work on Tower.

 

The Tower source code comes next. Because Tower is open source, all of its source code can be downloaded from the DroidPlanner GitHub account. Run

 

git clone https://github.com/DroidPlanner/Tower.git

 

from the terminal in the directory where you’d like to work on your version of Tower. Git will automatically download all of the files you will need.

 

Next open Tower in Android Studio. Alternatively you can use the VCS ⇒ Checkout from Version Control ⇒ GitHub flow to automatically import Tower into Android Studio.

 

Android Studio will then attempt to build the Gradle, which must succeed before you can do anything. If you just installed Android Studio, it will fail because you will need to install both the latest Android SDK and BuildTools. Wait for the Gradle build to fail and follow Android Studio’s instructions to get both of these items installed.

 

Finally, it’s possible to test your app on either a simulated device or a real one. On my computer, the simulated device runs very slowly, so I prefer to debug using a real tablet. To do this, you must plug your tablet into your computer’s USB and set it to developer mode. Briefly, find the Android Build Number section in settings and tap it seven times. After the seventh tap, you will see Developer Mode enabled and you will be able to run your code on the connected tablet.

Step 2: Build Tower

 

Now that you’re ready to roll, try building Tower yourself. First, click Run ‘Android’ under the Run menu. Assuming you’ve followed all the instructions in Step 1 successfully, Android Studio should compile the Tower source code and spin up a copy of Tower on your connected device. Cool! Now you never need to download compiled .apks of open source projects. You can just compile them yourself.

 

Go ahead and start up an instance of SITL and connect your compiled version of Tower, which should be called Tower debug on your tablet. You should be able to control your virtual copter just like the you can using the production version of Tower available in the app store.

 

Running your program is great for quickly testing your changes, but you will need to compile your own .apk for distribution. Try clicking Build APK under the Build menu, building your own version of Tower, and installing it on an Android device. Easy!

 

Step 3: Android app basics

 

I am definitely not the most qualified person to write this section and likely will have some errors in my assumptions, but I think my basic understanding is generally sound. If any of the Android wizards out here have improvements or corrections, I would love to roll them in. However, having spent some time bumbling through Tower’s structure without any background in Android applications, I hope I can provide a more accessible view into how to start digging in.

 

When you open Tower in Android Studio, you’ll notice two high level menus: Android and Gradle Scripts. Android is where most of the meat lives, but some of the files found within Gradle Scripts are responsible for very high level functions like the app name.

 

2016-01-18 04.59.32 pm.png

 

Within Android, you’ll see manifests, java, and res. manifests dictates what types of devices are compatible with our app. When you open the xml file within manifests, you’ll notice most of the file is concerned with various hardware configurations. For this project, we don’t care about hardware, but you might imagine that for your custom version of Tower, you might want to restrict users to connecting over Bluetooth and thus would like to throw up an error if a user tried to run your app on a tablet that did not have Bluetooth capability.

 

The java folder contains, not surprisingly, all of the java files that provide the structure of the app. However, in an Android application, the java files in many cases only serve as a general framework into which content is populated from the xml files found in the res folder. This will become abundantly clear as we walk through the tutorial, but Tower is a delicate dance between the java files in the java folder and the xml files in the res folder.


Take a minute to scan through the java and res folders with Tower open by your side and see what you recognize. I certainly was pretty amazed by how much I was able to understand by just generally scanning the code while poking through Tower. If there is a specific feature you are interested in, try Find in Path, Shift+Command+F on a Mac, and you generally can see where in the code base a specific feature resides.
 

Step 4: Let’s try some easy stuff

 

So you think Tower is a boring name? Me, too. Within Android Studio, open the Gradle Scripts/build.gradle (Module Android) file. Head down to lines 140, 148, and 154. You’ll notice that you can replace Tower with a name of your choosing. I used Agribotix for my example, but let your creative juices flow.

 

Don’t like the Tower logo? Replace the ic_launcher.png logos found in res/drawable/ic_launcher with your own. The different files are for different resolution icons that are displayed on different size devices. If you want to be really fancy, you can use an online tool like this one to automatically generate all of these files from a vector image.

Screenshot_2016-01-18-16-58-24.png

 

Want to establish some branding within the app? The sidebar seems like a good place to start. Head to res/layout/nav_header_main.xml. You’ll see something like the image below. The screen is split between Android Studio’s best guess as to how nav_header_main.xml will appear on an device and the actual .xml file. If you CMD + click on some of the elements, you can see how they are linked to the rest of the code. Try it and see. After playing around for a few minutes, it should be fairly obvious what’s going on inside this .xml file.

 

2016-01-18 05.02.23 pm.png

 

Now, let’s get to your custom branding. You can either do things the hard way or the easy way. The hard way is scan through the text and identify which lines of code likely correspond to which design element. Here, is is fairly obvious that android:text= specifies what the text in the header will say, but that’s not always to case. However, Android Studio is pretty amazing. You can simply click on the item of interest, say the text, and Android Studio will highlight what code is responsible for that element. Go ahead and change the background color, logo, and text to match your branding.

 

Screenshot_2016-01-18-16-58-47.png

Great, now you should understand the basics of how Tower, and Android apps in general for that matter, is structured from a design perspective. I just identified a few specific touch points here, but with some pretty straightforward digging, you should now be able to completely own the style and design of Tower.

 

After you’ve tinkered to your heart’s content, go ahead and Run ‘Android’ or build an APK and see how it looks.

 

Step 5: Let’s dive a little deeper

 

Now that you own the design, let’s start to own the functionality. One of my biggest issues with Tower, especially when showing it off to a commercial user interested in mapping, is the 15 flight modes available from the telemetry bar. It is far too easy for a user interested in autonomous flight to accidentally kick the copter into ACRO mode and cause a crash. Let’s fix that.

 

Screenshot_2016-01-18-17-15-24.png

This is the first time where we will be working at the intersection of Tower and 3DR Services. You’ll notice that if you navigate res/layout/fragment_action_bar_telem.xml, you’ll find the design responsible for this feature. However, what you will not find is the ability to add or remove menu items using a simple .xml file. Rather, you will see a reference to android:id="@+id/bar_flight_mode" when you click on the flight mode piece of the telemetry bar. If you search your app for that string, you will find a java file called ActionBarTelemFragment.java.

 

If you stare at this file for long enough, you will realize that the menu of options in the telemetry drop down is populated by FlightModeAdapter.

 

2016-01-18 05.26.01 pm.png

 

If you CMD + click on FlightModeAdapter, Android Studio will take you to a file called FlightModeAdapter.kt, which is written in a language called Kotlin, which is similar to Java. It may be worthwhile to stop at this point and download the Kotlin plugin for Android Studio to make your code look a little more beautiful. Inside FlightModeAdapter.kt, you will see that there is another layer to the onion.

 

2016-01-18 05.28.13 pm.png

 

Tower is pulling the flightModes from a variable called VehicleMode. CMD + click on VehicleMode and you’ll notice that Android Studio takes you to the locked VehicleMode.java. This file is locked because it is not actually part of Tower, but rather 3DR Services, which provides many of the functions called by Tower and DroneKit-Android apps. While you certainly could modify that file and compile a new version of 3DR Services, it is easier to step out a layer and try to address all of our changes from the Tower level.

 

To do this, reopen FlightModeAdapter.kt and put on your Java hat. flightModes is simply an array populated by 3DR Service’s VehicleMode variable. To remove elements from the array, we use the Java remove command. For example, to remove ACRO from your version of Tower, include  

 

flightModes.remove(VehicleMode.COPTER_ACRO)

 

underneath flightModes. For my app, I removed every flight mode aside from RTL, Auto, and Guided.

 

2016-01-18 05.36.12 pm.png

 

Great. Now build your app and make sure everything still works.

 

Screenshot_2016-01-18-17-37-04.png



Step 6: Like Solo? Let’s make Tower connect automatically over WiFi (UDP).

 

Solo AGCO Edition users obviously are only interested in flying Solo. Bluetooth, USB, and TCP connections are painful for the uninitiated to understand and totally unnecessary. To force a UDP connection, open java/DroidPlannerApp.java. You can see that this file handles all kinds of connectivity-related functionality.


Around line 300, you’ll see

 

final int connectionType = dpPrefs.getConnectionParameterType();

 

If you look at the code carefully, you’ll see that we can cheat and short circuit the whole connection type selection process by just hard coding in a UDP connection. You’ll notice that the connectionType variable in an integer. If you do a little CMD + click digging, you’ll learn that that integer is 0 for USB, 1 for UDP, 2 for TCP, and 3 for Bluetooth. To force a UDP connection, we can just go behind all of the logic and menus and replace

 

dpPrefs.getConnectionParameterType()

 

with

 

1

 

Easy.

 

2016-01-18 05.46.44 pm.png

 

This cheat will not remove any of the UI, but no matter what connection type you specific, Tower will look for a vehicle over UDP. Which brings us to...

 

Step 7: Remove unnecessary menus

 

Now that we’ve hardcoded a UDP connection, we should remove all of the connectivity menus. And, while we’re at it, let’s get rid of everything else we find distracting. Personally, I don’t like the Flight History or Checklist top level menus and think the user is exposed to way too many settings.

 

Go ahead and open up res/menu/navigation_drawer_items.xml to clean up the navigation drawer and res/xml/preferences.xml to get rid of the preferences you don’t like.

 

You may find that with some of the xml items that you remove, you may have to find the associated Java reference and comment it out as well. This should be fairly straightforward to work through, but feel free to look to the Agribotix app for specific examples.

 

In this general vein, I also removed Dronie, Follow, and Land from the top level menus and everything aside from Spline Survey from the Editor screen, because the Solo AGCO Edition owners are essentially only interested in building maps. You can see how I did this by looking at what I commented out in java/org.droidplanner.android/fragments/control/CopterFlightControlFragment.java and /res/layout/fragment_editor_tools.xml

 

Step 8: Simplify the Editor screen for the optimal survey

 

Solo AGCO Edition customers use the editor screen to do only one thing: spline survey. They also user only one camera, GoPro, and should never have to play with sidelap or overlap. The mapping workflow can be dramatically simplified by hardcoding all of these values in, which is possible in java/org.droidplanner.android/proxy/mission/item/fragments/MissionSurveyFragment.java.

 

I started to get a little sloppy here (you’ll notice that I didn’t change the camera UI, although the camera is hardcoded to GoPro in the backend), but I hardcoded the camera to Hero 4 Black, the sidelap to 70%, and the overlap to 85%.

 

Screenshot_2016-01-18-18-12-43.png

 

Step 9: Profit?

Whew! That was a lot of work, but in the end we created a custom version of Tower that is built to address specific user needs and reinforce a platform partner’s branding. Tower is a very extensible base for a huge variety of custom mobile GCSs, so I hope this guide makes modification a little more accessible for all of the 3DR platform partners out there doing great things with Pixhawk.

 

E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • Can't run project gradle configuration issue 

  • Just an update the cause of this was when I imported the tower project into AS it put all the compile statements in the dependancies onto the same line. Seperating these to individual lines allows me to now build the project.

  • @Daniel Nice job on the writeup. What version of Android Studio are you using? When I try builing Tower using Android Studio 2.1.2 on windows 10 I get errors:

    Firstly I get MissingTranslation errors

    - This can be fixed by adding "disable 'MissingTranslation'" to lint options in the module gradle

    Then I get android:validatereleasesigning errro

    - Fixed this by creating a keystore

    Now I get the following error:

    Error:(7, 1) A problem occurred evaluating project ':Android'.
    > Could not find method compile() for arguments [com.google.android.gms:play-services-location:8.4.0] on DefaultExternalModuleDependency{group='com.google.android.gms', name='play-services-maps', version='8.4.0', configuration='default'}.

    Any suggestions? Am I doing something wrong?

  • Developer

    Thanks for posting this Daniel.  I do want to mention that Tower is GPL licensed https://github.com/DroidPlanner/Tower/commit/6a2c55bf204d5ff2640a5f... and people are encouraged to both adapt the software and they are obligated to publish their changes and pass the license on to their users.  Acknowledging the dev team working on Tower and making pull requests back to the project are really appreciated as well.

    Adding the GPLv3 license · DroidPlanner/Tower@6a2c55b
    Ground Control Station for Android Devices. Contribute to DroidPlanner/Tower development by creating an account on GitHub.
  • T3

    I also think it is good to have more tutorials like this.

    However, in this specific case (Tower) it would be good to implement a mechanism to easily customize the GUI by users. As in the above example a Dronie is not required for mapping. But for non-Solo surveys the hard-coded UDP is not a good idea. So more options is the preferences would be perfect.

    For sure anyone can fork Tower and tweak it but this will lead to diversification and most probably incompatibility issues when 3DR Services is (automatically) updated - and thus to potential crashes. 

    So I hope tutorials like this will foster the development in general - and specifically in the case of Tower where the  software development process slowed down dramatically since Arthur left the project more than a year ago.

  • If this were something other than a 3DR aligned project, I can guarantee you the wrath of @chris_anderson would descend upon this thread. :)  You used terms like "hard coded UDP", as well as expect the user to understand Java, and the list goes on. The humanity! Nice tutorial. It will be interesting to see if this approach might become a product support issue for `Tower` and possibly, trigger a bit more engineering effort to make these kinds of UI config options better integrated. 

  • MR60

    Excellent as always! Keep these series of tutorials going.

  • 3D Robotics

    @Thorsten. You are right! My changes should up now.

  • Absolutely 1st rate stuff from 3DR, I can't tell you how excited I am to get going with this... for those who need to get up to speed with Python I recommend the course over at codecademy: https://www.codecademy.com/learn/python

  • Developer

    Yeah, txs for sharing!  very cool.

This reply was deleted.