diff options
Diffstat (limited to 'presentation/index.html')
-rw-r--r-- | presentation/index.html | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/presentation/index.html b/presentation/index.html new file mode 100644 index 0000000..b4679ea --- /dev/null +++ b/presentation/index.html @@ -0,0 +1,504 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + + <title>Not Your Dad's Scala: Flying Objects and Proactive Streams</title> + + <meta name="description" content="Not Your Dad's Scala: Flying Objects and Proactive Streams"> + + <meta name="author" content="Jakob Odersky" /> + + <meta name="apple-mobile-web-app-capable" content="yes" /> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> + + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + + <link rel="stylesheet" href="revealjs/css/reveal.css"> + <link rel="stylesheet" href="revealjs/css/theme/league.css" id="theme"> + + + <!-- For syntax highlighting --> + <link rel="stylesheet" href="revealjs/lib/css/zenburn.css"> + + <!-- If the query includes 'print-pdf', use the PDF print sheet --> + <script> + var link = document.createElement( 'link' ); + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = window.location.search.match( /print-pdf/gi ) ? 'revealjs/css/print/pdf.css' : 'revealjs/css/print/paper.css'; + document.getElementsByTagName( 'head' )[0].appendChild( link ); + </script> + + <!--[if lt IE 9]> + <script src="lib/js/html5shiv.js"></script> + <![endif]--> + </head> + + <body> + + <div class="reveal"> + + <!-- Any section element inside of this container is displayed as a slide --> + <div class="slides"> + + <section> + <h2>Not Your Dad's Scala: Flying Objects and Proactive Streams</h2> + <h5>Jakob Odersky</h5> + <h5> + <a href="https://github.com/jodersky">@jodersky</a> + </h5> + <p> + <h4>April 18, 2016</h4> + </p> + </section> + + + <section id="or-navigating-a-drone-with-scala" class="level2"> +<h2>Or, <br/> Navigating a Drone with Scala</h2> +</section> +<section id="initial-idea" class="level2"> +<h2>Initial Idea</h2> +<ul> +<li>Build a quadrotor</li> +<li>From scratch +<ul> +<li>hardware</li> +<li>software</li> +</ul></li> +<li>Control with a joystick, no remote</li> +<li>⇒ Project Condor</li> +</ul> +</section> +<section id="two-parts" class="level2"> +<h2>Two Parts</h2> +<ol type="1"> +<li>The Quadrotor</li> +<li>The Base Station</li> +</ol> +</section> +<section id="system-overview" class="level2"> +<h2>System Overview</h2> +<figure> +<img src="images/functional.svg" alt="overview" /><figcaption>overview</figcaption> +</figure> +</section> +<section id="the-quadrotor" class="level2"> +<h2>1. The Quadrotor</h2> +<section id="the-flying-object-no-scala-here" class="level3"> +<h3><em>(the flying object)</em> <br/> No Scala Here</h3> +<p>Move on to the Scala parts →</p> +<p>See backstory ↓</p> +</section> +<section id="frame" class="level3"> +<h3>Frame</h3> +<figure> +<img src="images/structure.png" alt="Structure" /><figcaption>Structure</figcaption> +</figure> +</section> +<section id="frame-1" class="level3"> +<h3>Frame</h3> +<figure> +<img src="images/prototype.jpg" alt="Unit" /><figcaption>Unit</figcaption> +</figure> +</section> +<section id="electronics" class="level3"> +<h3>Electronics</h3> +<figure> +<img src="images/trifle.jpg" alt="Trifle Board" /><figcaption>Trifle Board</figcaption> +</figure> +</section> +<section id="flight-stack" class="level3"> +<h3>Flight Stack</h3> +<ul> +<li>And then I found PX4, exactly what I was trying to build.</li> +</ul> +</section> +<section id="alternative-px4" class="level3"> +<h3>Alternative: PX4</h3> +<ul> +<li>Open Source Software</li> +<li>Developed by Computer Vision and Geometry Group, ETHZ</li> +<li>Uses open, wide-spread protocol MAVLink</li> +<li>Runs on free RTOS <a href="http://nuttx.org/">NuttX</a>, available for AVR, ARM and more.</li> +</ul> +</section> +<section id="pixhawk-hardware" class="level3"> +<h3>Pixhawk Hardware</h3> +<ul> +<li>Developed by the same group</li> +<li>Expensive</li> +<li>I already have a microcontroller and all sensors</li> +</ul> +<figure> +<img src="images/pixhawk.jpg" alt="Pixhawk" /><figcaption>Pixhawk</figcaption> +</figure> +</section> +<section id="nuttx-beginning-2015" class="level3"> +<h3>NuttX (beginning 2015)</h3> +<ul> +<li>Our board uses the Teensy 3.1: +<ul> +<li>ARM Cortex M4</li> +<li>Freescale Kinetis K20 family</li> +</ul></li> +<li>NuttX (beginning 2015) has support for K40 family</li> +</ul> +</section> +<section id="lets-port-it" class="level3"> +<h3>Let's port it!</h3> +<ul> +<li>Subtle differences in processor families, K20 != K40</li> +<li>I was never much involved with kernel development beforehand</li> +<li>Debugging microcontrollers is no fun +<ul> +<li>(without JTAG or other fancy equipment)</li> +</ul></li> +</ul> +</section> +<section id="fast-forward-2-months" class="level3"> +<h3>Fast-forward 2 months</h3> +</section> +<section id="get-the-pixhawk-and-move-on" class="level3"> +<h3>Get the Pixhawk and move on</h3> +</section> +</section> +<section id="quadrotor-take-away" class="level2"> +<h2>Quadrotor Take-Away:</h2> +<ul> +<li>A lot of work has gone into existing hardware platforms</li> +<li>⇒ Use existing Pixhawk controller</li> +</ul> +<figure> +<img src="images/pixhawk.jpg" alt="Pixhawk" /><figcaption>Pixhawk</figcaption> +</figure> +</section> +<section id="the-base-station" class="level2"> +<h2>2. The Base Station</h2> +<ul> +<li>Control drone with joystick/gamepad</li> +<li>Display live flight information +<ul> +<li>"virtual cockpit"</li> +</ul></li> +<li>Underlying process: <em>(proactive)</em> message streaming</li> +</ul> +</section> +<section id="mavlink-protocol" class="level2"> +<h2>MAVLink Protocol</h2> +<ul> +<li>Wide-spread use, including the PX4</li> +<li>Published 2009 by Lorenz Meier, ETHZ</li> +<li>Very simple and extensible</li> +</ul> +</section> +<section id="mavlink-frame" class="level2"> +<h2>MAVLink Frame</h2> +<ul> +<li>Header-only structure</li> +<li>Every entity on network has 2-byte address</li> +<li>Low overhead: 6 bytes</li> +</ul> +<pre class="scala"><code>+-----+-----+-----+-------+--------+-------+---------+-----+ +| Stx | Len | Seq | SysID | CompID | MsgID | Payload | CRC | ++-----+-----+-----+-------+--------+-------+---------+-----+ +| 1 | 1 | 1 | 1 | 1 | 1 | n | 2 | ++-----+-----+-----+-------+--------+-------+---------+-----+</code></pre> +</section> +<section id="mavlink-messages" class="level2"> +<h2>MAVLink Messages</h2> +<ul> +<li>Message consists of: +<ul> +<li>ID/name</li> +<li>collection of fields (name, value) pairs</li> +</ul></li> +<li><p>Common message definitions in XML</p></li> +<li><p><a href="https://github.com/mavlink/mavlink">Official repository</a> contains bindings for various languages</p></li> +</ul> +<pre class="xml"><code><message id="0" name="HEARTBEAT"> + <description>Description...</description> + <field type="uint8_t" name="type">...</field> + <field type="uint8_t" name="autopilot">...</field> + <field type="uint8_t" name="base_mode">...</field> + <field type="uint32_t" name="custom_mode">...</field> + <field type="uint8_t" name="system_status">...</field> +</message></code></pre> +</section> +<section id="mavlink-via-the-base-station" class="level2"> +<h2>MAVLink via the Base Station</h2> +<ul> +<li>Send movement messages to drone: +<ul> +<li>standalone program</li> +<li>⇒ <a href="https://github.com/project-condor/maverick">Maverick</a></li> +</ul></li> +<li>View and send non-movement messages: +<ul> +<li>⇒ <a href="https://github.com/project-condor/mavigator">Mavigator</a> (rest of this presentation)</li> +</ul></li> +</ul> +</section> +<section id="mavigator" class="level2"> +<h2>Mavigator</h2> +<table> +<thead> +<tr class="header"> +<th style="text-align: left;">Requirement</th> +<th style="text-align: left;">add Scala</th> +<th style="text-align: left;">Area</th> +</tr> +</thead> +<tbody> +<tr class="odd"> +<td style="text-align: left;">Modern, portable UI</td> +<td style="text-align: left;">Scala.js</td> +<td style="text-align: left;">frontend</td> +</tr> +<tr class="even"> +<td style="text-align: left;">Web server</td> +<td style="text-align: left;">Akka Http</td> +<td style="text-align: left;">backend</td> +</tr> +<tr class="odd"> +<td style="text-align: left;">Message streaming</td> +<td style="text-align: left;">Akka Streams</td> +<td style="text-align: left;">backend</td> +</tr> +</tbody> +</table> +</section> +<section id="live-demo" class="level2"> +<h2>Live Demo</h2> +<section id="alternatives" class="level4"> +<h4>Alternatives</h4> +<ul> +<li>online: <a href="http://mavigator.jodersky.ch" class="uri">http://mavigator.jodersky.ch</a></li> +<li>run locally: <code>sbt mavigator-server/run</code></li> +</ul> +</section> +</section> +<section id="frontend-scala.js" class="level2"> +<h2>Frontend: Scala.js</h2> +<ul> +<li>A JavaScript backend to the Scala compiler. +<ul> +<li>All the goodies from Scala: type safety, collections, etc</li> +<li>Outputs plain JavaScript</li> +<li>Can interface with plain JavaScript</li> +</ul></li> +<li>Developed at EPFL by Sebastien Doeraene</li> +<li>Still in 0.x but totally usable!</li> +</ul> +</section> +<section id="frontend-design" class="level2"> +<h2>Frontend: Design</h2> +<ul> +<li>One-page applications</li> +<li>Static scaffolding with <a href="https://github.com/playframework/twirl">Twirl</a> (Play! templates)</li> +<li>Common launcher for all applications</li> +<li>Extensible "cake" pattern: +<ul> +<li>Providing web page environment</li> +<li>Reading messages</li> +<li>Displaying instruments</li> +<li>Laying out elements</li> +</ul></li> +</ul> +</section> +<section id="backend-akka-streams" class="level2"> +<h2>Backend: Akka Streams</h2> +<ul> +<li>Compatible with Reactive Streams +<ul> +<li>standard for aynchronous, non-blocking, back-pressures streaming</li> +<li><a href="http://www.reactive-streams.org/" class="uri">http://www.reactive-streams.org/</a></li> +</ul></li> +<li>"Natural" Streaming API</li> +</ul> +</section> +<section id="streams-as-graphs" class="level2"> +<h2>Streams as Graphs</h2> +<figure> +<img src="images/stream-graphs.svg" alt="overview" /><figcaption>overview</figcaption> +</figure> +</section> +<section id="streams-in-code" class="level2"> +<h2>Streams in Code</h2> +<figure> +<img src="images/counter.svg" /> +</figure> +<pre class="scala"><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() +</code></pre> +</section> +<section id="more-streams" class="level2"> +<h2>More Streams</h2> +<ul> +<li>Arbitrary graphs</li> +<li>Feedback loops</li> +<li>Materialization</li> +<li>Much more...</li> +</ul> +<p><a href="http://akka.io" class="uri">http://akka.io</a></p> +</section> +<section id="backend-conceptual-model" class="level2"> +<h2>Backend: Conceptual Model</h2> +<figure> +<img src="images/model.svg" alt="Conceptual stream model" /><figcaption>Conceptual stream model</figcaption> +</figure> +</section> +<section id="backend-actual-model" class="level2"> +<h2>Backend: Actual Model</h2> +<figure> +<img src="images/core.svg" alt="Actual stream model" /><figcaption>Actual stream model</figcaption> +</figure> +</section> +<section id="serial-backend" class="level2"> +<h2>Serial Backend</h2> +<pre class="scala"><code>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() +}</code></pre> +<ul> +<li><code>Serial()</code> is a custom Akka extension</li> +<li>See <a href="https://www.jodersky.ch/flow" class="uri">https://www.jodersky.ch/flow</a> for implementation</li> +</ul> +</section> +<section id="web-sockets" class="level2"> +<h2>Web Sockets</h2> +<pre class="scala"><code>path("/mavlink") { + get { + val fromWebSocket = Flow[Message].collect{ + case BinaryMessage.Strict(data) => data + } + + val toWebSocket = Flow[Bytes].map{bytes => + BinaryMessage(bytes) + } + + //request connection to multiplexer + val backend: Flow[Bytes, Bytes, NotUsed] = Uav().connect() + + handleWebSocketMessages(fromWebSocket via backend via toWebSocket) + } +}</code></pre> +<ul> +<li>Akka Route DSL</li> +<li>Graph is run by Akka Http</li> +</ul> +</section> +<section id="mavlink-codegen" class="level2"> +<h2>MAVLink CodeGen</h2> +<ul> +<li><a href="https://github.com/project-condor/sbt-mavlink">sbt-mavlink</a>: +<ul> +<li>generates data parser and assembler</li> +<li>message maps to case class</li> +</ul></li> +</ul> +<pre class="scala"><code>case class Attitude( + timeBootMs: Int, + roll: Float, pitch: Float, yaw: Float, + rollspeed: Float, pitchspeed: Float, yawspeed: Float) + extends Message</code></pre> +</section> +<section id="demo-do-a-barrel-roll" class="level2"> +<h2>Demo: Do a Barrel Roll</h2> +<ul> +<li>Define "unstable" message</li> +<li>Add extra UI element to notify user</li> +<li>Inject attitude messages</li> +</ul> +</section> +<section id="message" class="level2"> +<h2>Message</h2> +<p>Add to dialect definition:</p> +<pre class="xml"><code><message id="150" name="STABILITY"> + <description>Stability issues</description> + <field type="uint8_t" name="stable">Is it stable?</field> +</message></code></pre> +</section> +<section id="new-ui-element" class="level2"> +<h2>New UI element</h2> +<ul> +<li>Danger indicator</li> +<li>Illuminates on stability issues</li> +</ul> +</section> +<section id="barrel-roll-injection" class="level2"> +<h2>Barrel Roll: Injection</h2> +<figure> +<img src="images/core-new.svg" alt="overview" /><figcaption>overview</figcaption> +</figure> +</section> +<section id="live-demo-1" class="level2"> +<h2>Live Demo</h2> +<section id="alternatives-1" class="level4"> +<h4>Alternatives</h4> +<ul> +<li><code>git checkout demo1-before</code></li> +<li><code>git checkout demo1-after</code></li> +</ul> +</section> +</section> +<section id="references" class="level2"> +<h2>References</h2> +<ul> +<li><p>Mavigator repository:</p> +<p><a href="https://github.com/project-condor/mavigator" class="uri">https://github.com/project-condor/mavigator</a></p></li> +<li><p>Project website:</p> +<p><a href="https://project-condor.github.io" class="uri">https://project-condor.github.io</a></p></li> +</ul> +</section> + </div> + + <script src="revealjs/lib/js/head.min.js"></script> + <script src="revealjs/js/reveal.js"></script> + + <script> + // Full list of configuration options available here: + // https://github.com/hakimel/reveal.js#configuration + Reveal.initialize({ + controls: true, + progress: true, + history: true, + center: false, + // available themes are in /css/theme + theme: Reveal.getQueryHash().theme || 'league', + // default/cube/page/concave/zoom/linear/fade/none + transition: Reveal.getQueryHash().transition || 'default', + // Optional libraries used to extend on reveal.js + dependencies: [ + { src: 'revealjs/lib/js/classList.js', condition: function() { return !document.body.classList; } }, + { src: 'revealjs/plugin/markdown/showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, + { src: 'revealjs/plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } }, + //{ src: 'revealjs/plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } } + // { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } } + ] + }); + </script> + + </body> +</html> |