Not Your Dad's Scala: Flying Objects and Proactive Streams

Jakob Odersky

April 18, 2016

Navigating a Drone with Scala

Initial Idea

  • Build a quadrotor
  • From scratch
    • hardware
    • software
  • Control with a joystick, no remote
  • ⇒ Project Condor

Two Parts

  1. The Quadrotor
  2. The Base Station

System Overview


1. The Quadrotor

(the flying object)
No Scala Here

Move on to the Scala parts →

See backstory ↓






Trifle Board
Trifle Board

Flight Stack

  • And then I found PX4, exactly what I was trying to build.

Alternative: PX4

  • Open Source Software
  • Developed by Computer Vision and Geometry Group, ETHZ
  • Uses open, wide-spread protocol MAVLink
  • Runs on free RTOS NuttX, available for AVR, ARM and more.

Pixhawk Hardware

  • Developed by the same group
  • Expensive
  • I already have a microcontroller and all sensors

NuttX (beginning 2015)

  • Our board uses the Teensy 3.1:
    • ARM Cortex M4
    • Freescale Kinetis K20 family
  • NuttX (beginning 2015) has support for K40 family

Let's port it!

  • Subtle differences in processor families, K20 != K40
  • I was never much involved with kernel development beforehand
  • Debugging microcontrollers is no fun
    • (without JTAG or other fancy equipment)

Fast-forward 2 months

Get the Pixhawk and move on

Quadrotor Take-Away:

  • A lot of work has gone into existing hardware platforms
  • ⇒ Use existing Pixhawk controller

2. The Base Station

  • Control drone with joystick/gamepad
  • Display live flight information
    • "virtual cockpit"
  • Underlying process: (proactive) message streaming


Requirement add Scala Area
Modern, portable UI Scala.js frontend
Web server Akka Http backend
Message streaming Akka Streams backend

Live Demo


Frontend: Scala.js

  • A JavaScript backend to the Scala compiler.
    • All the goodies from Scala: type safety, collections, etc
    • Outputs plain JavaScript
    • Can interface with plain JavaScript
  • Developed at EPFL by Sebastien Doeraene
  • Still in 0.x but totally usable!

Frontend: Design

  • One-page applications
  • Static scaffolding with Twirl (Play! templates)
  • Common launcher for all applications
  • Extensible "cake" pattern:
    • Providing web page environment
    • Reading messages
    • Displaying instruments
    • Laying out elements

Backend: Akka Streams

Streams as Graphs


Streams in Code

//Simple source
val src: Source[Int, _] = Source.tick[Int](100millis, 100millis, 1)

//Nested source
val inc: Source[Int, _] = src.scan(0)(_+_)

//A discrete flow
val flow = Flow[Int].map(_*2)

//Simple sink
val sink = Sink.foreach(println)

//Print all even numbers, ad infinitum
(inc via flow to sink).run()

More Streams

  • Arbitrary graphs
  • Feedback loops
  • Materialization
  • Much more...

Backend: Conceptual Model

Conceptual stream model
Conceptual stream model

Backend: Actual Model

Actual stream model
Actual stream model

Serial Backend

Serial().watch(Set("/dev/ttyUSB0")).runForeach{ port =>

  //replace backend on connection
  val multiplexer: Flow[Bytes, Bytes, NotUsed] = setBackend()

  //open actual connection to drone
  val uav: Flow[Bytes, Bytes, NotUsed] =
    Serial().open(port, serialSettings)

  (uav join multiplexer).run()

Web Sockets

path("/mavlink") {
  get {
    val fromWebSocket = Flow[Message].collect{
      case BinaryMessage.Strict(data) => data

    val toWebSocket = Flow[Bytes].map{bytes =>

    //request connection to multiplexer
    val backend: Flow[Bytes, Bytes, NotUsed] = Uav().connect()

    handleWebSocketMessages(fromWebSocket via backend via toWebSocket)
  • Akka Route DSL
  • Graph is run by Akka Http

Demo: Do a Barrel Roll

  • Define "unstable" message
  • Add extra UI element to notify user
  • Inject attitude messages


Add to dialect definition:

<message id="150" name="STABILITY">
    <description>Stability issues</description>
    <field type="uint8_t" name="stable">Is it stable?</field>

New UI element

  • Danger indicator
  • Illuminates on stability issues

Barrel Roll: Injection


Live Demo


  • git checkout demo1-before
  • git checkout demo1-after