ROS on arm64 with Ubuntu Core
Previous Robot Operating System (ROS) releases only supported i386, amd64, and armhf. I even tried building ROS Indigo from source for arm64 about a year ago, but ran into dependency issues with a missing sbcl. Well, with surprisingly little fanfare, ROS Kinetic was released with support for arm64 in their prebuilt archive! I thought it might be time to take it for a spin with Ubuntu Core and its arm64 reference board, the DragonBoard 410c, and thought I'd take you along for the ride.
Step 1: Install Ubuntu Core
The first order of business is to install Ubuntu Core on the DragonBoard. Just follow the documentation. I want to mention two things for this step, though:
- I've never had good luck with wifi on the DragonBoard, it seems incredibly unstable. I recommend not even bothering with it and using a USB to ethernet adapter, since with Ubuntu Core at least your first login must be over SSH.
- There's a bug that causes the first boot wizard to take quite some time between entering your SSO password and finishing. Don't worry, just leave it alone, it'll finish (mine took about 7 minutes).
Step 2: Make sure it's up-to-date
SSH into the machine (or if you set a password, login locally, it doesn't matter), and run the following command to ensure everything is completely up-to-date:
$ sudo snap refresh
If it updated, you may need to reboot. Go ahead and do that now, we'll wait.
Step 3: Install Snapcraft
You may or may not be familiar with Ubuntu Core, but the first thing people typically notice is that it doesn't use Debian packages (.debs), it uses snaps (read up on them, they're pretty awesome). However, in this case, they don't give us what we need, which is a development environment. We need to build a ROS workspace into a snap, which means we'll need to utilize ROS's archive as well as the snap packaging tool, snapcraft. All of these are available as .debs. Fortunately, the environment we want is available as a snap:
$ snap install classic --edge --devmode
$ sudo classic
<unpacking stuff... snip>
The (classic) prompt modifier tells you that you're now in a classic shell. Now you can do familiar things such as update the package index and install Snapcraft, both of which you should do now:
(classic)kyrofa@localhost:~$ sudo apt update
(classic)kyrofa@localhost:~$ sudo apt install snapcraft
Step 4: Build your snap
Probably the most simple ROS workspace you can imagine is a single talker and a single listener. Snapcraft has exactly that as one of its demos, so for this example we'll just use that (you might consider reading that demo's walkthrough). First though, that means fetching the Snapcraft source code:
(classic)kyrofa@localhost:~$ sudo apt install git
(classic)kyrofa@localhost:~$ git clone https://github.com/snapcore/snapcraft
(classic)kyrofa@localhost:~$ cd snapcraft/demos/ros
The ROS demo in question will by default actually build for Indigo. But you're interested in arm64! You can't use Indigo. You need something newer... something shinier, and perhaps less purple. You need to use Kinetic. You tell Snapcraft this by utilizing the rosdistro property. Open up the snapcraft.yaml and edit the appropriate section to look like this (added text bolded):
Save that file and exit. Finally, it's time to run snapcraft and watch that workspace get built into a snap (this will take a bit, the DragonBoard is not a blazing workhorse; if you want something faster use the snap builders):
<snip pulling, building, staging>
In the end you have a snap. You should exit out of the classic shell at this point (e.g. ctrl+d).
Step 5: Install and run it!
Now it's time to install the snap you just built. Even though you've exited the classic shell, your $HOME remained the same, so you can install the snap like so:
$ cd snapcraft/demos/ros
$ sudo snap install --dangerous ros-example_1.0_arm64.snap
(remember the --dangerous flag is because you just built the snap locally, so snapd can't verify its publisher. You're telling it that's okay.)
Finally, run the application contained within the snap (it'll launch the talker/listener system):
* /rosdistro: kinetic
* /rosversion: 1.12.6
auto-starting new master
process[talker-2]: started with pid 
process[listener-3]: started with pid 
[ INFO] [1485394763.340461416]: Hello world 0
[ INFO] [1485394763.440354547]: Hello world 1
[ INFO] [1485394763.540334917]: Hello world 2
[ INFO] [1485394763.640330599]: Hello world 3
[ INFO] [1485394763.740335917]: Hello world 4
[ INFO] [1485394763.840366912]: Hello world 5
[ INFO] [1485394763.940342594]: Hello world 6
[ INFO] [1485394764.040321141]: Hello world 7
[ INFO] [1485394764.140323334]: Hello world 8
[ INFO] [1485394764.240328548]: Hello world 9
[ INFO] [1485394764.340319074]: Hello world 10
[INFO] [1485394764.341486]: I heard Hello world 10
[ INFO] [1485394764.440333194]: Hello world 11
[INFO] [1485394764.441476]: I heard Hello world 11
[ INFO] [1485394764.540333772]: Hello world 12
[INFO] [1485394764.541450]: I heard Hello world 12
I haven't yet pushed ROS's arm64 support very hard, but I'm thoroughly pleased that support is present. Particularly paired with snaps and Ubuntu Core, I think this opens the door to a lot of amazing robotic possibilities.