aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2014-12-16 18:24:55 +0100
committerJakob Odersky <jodersky@gmail.com>2014-12-16 18:24:55 +0100
commit937bec66df1a3edfe819fb68e3ad85f60f92c1bb (patch)
tree031d9ee53834adb03afad8992c846a31d7619d04
parent458971f834a3af0dbf2fffe527352fa11e7d8168 (diff)
downloadmavigator-937bec66df1a3edfe819fb68e3ad85f60f92c1bb.tar.gz
mavigator-937bec66df1a3edfe819fb68e3ad85f60f92c1bb.tar.bz2
mavigator-937bec66df1a3edfe819fb68e3ad85f60f92c1bb.zip
add animations and reenable showing messages
-rw-r--r--concise.xml13
-rw-r--r--vfd-backend/public/images/instruments/altimeter.svg (renamed from vfd-backend/public/images/instruments/altitude.svg)0
-rw-r--r--vfd-backend/public/images/instruments/basic.svg313
-rw-r--r--vfd-backend/public/images/instruments/compass.svg (renamed from vfd-backend/public/images/instruments/heading.svg)0
-rw-r--r--vfd-backend/public/images/instruments/horizon.svg (renamed from vfd-backend/public/images/instruments/attitude.svg)28
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/Main.scala3
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala62
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Communication.scala27
-rw-r--r--vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Primary.scala12
-rw-r--r--vfd-uav/src/main/scala/vfd/uav/MockConnection.scala20
10 files changed, 430 insertions, 48 deletions
diff --git a/concise.xml b/concise.xml
index 9be16f7..4d8d174 100644
--- a/concise.xml
+++ b/concise.xml
@@ -66,6 +66,19 @@
<field type="uint8_t" name="target_system">System ID</field>
<field type="uint8_t" name="target_component">Component ID</field>
</message>
+ <message name="MOTOR" id="6">
+ <description>Status of motors</description>
+ <field type="uint8_t" name="m0">m0</field>
+ <field type="uint8_t" name="m1">m1</field>
+ <field type="uint8_t" name="m2">m2</field>
+ <field type="uint8_t" name="m3">m3</field>
+ </message>
+ <message id="30" name="ATTITUDE">
+ <description>The attitude in the aeronautical frame (right-handed, Z-down, X-front, Y-right).</description>
+ <field type="int16_t" name="roll">Roll angle</field>
+ <field type="int16_t" name="pitch">Pitch angle</field>
+ <field type="uint16_t" name="yaw">Yaw angle</field>
+ </message>
<message id="70" name="RC_CHANNELS_OVERRIDE">
<description>The RAW values of the RC channels sent to the MAV to override info received from the RC radio. A value of UINT16_MAX means no change to that channel. A value of 0 means control of that channel should be released back to the RC radio. The standard PPM modulation is as follows: 1000 microseconds: 0%, 2000 microseconds: 100%. Individual receivers/transmitters might violate this specification.</description>
<field type="uint8_t" name="target_system">System ID</field>
diff --git a/vfd-backend/public/images/instruments/altitude.svg b/vfd-backend/public/images/instruments/altimeter.svg
index 2bfb306..2bfb306 100644
--- a/vfd-backend/public/images/instruments/altitude.svg
+++ b/vfd-backend/public/images/instruments/altimeter.svg
diff --git a/vfd-backend/public/images/instruments/basic.svg b/vfd-backend/public/images/instruments/basic.svg
new file mode 100644
index 0000000..7712ece
--- /dev/null
+++ b/vfd-backend/public/images/instruments/basic.svg
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg:svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg4387"
+ version="1.1"
+ inkscape:version="0.48.5 r10040"
+ viewBox="-50 -50 100 100"
+ sodipodi:docname="thin.svg">
+ <svg:defs
+ id="defs4389">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 50 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="100 : 50 : 1"
+ inkscape:persp3d-origin="50 : 33.333333 : 1"
+ id="perspective5114" />
+ </svg:defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.6568542"
+ inkscape:cx="64.85138"
+ inkscape:cy="31.918663"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg4387"
+ showgrid="true"
+ showguides="false"
+ inkscape:snap-bbox="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1029"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:snap-grids="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4395"
+ units="px"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ spacingx="1px"
+ spacingy="1px" />
+ </sodipodi:namedview>
+ <svg:metadata
+ id="metadata4392">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </svg:metadata>
+ <svg:g
+ id="lower">
+ <svg:path
+ inkscape:transform-center-y="44.418149"
+ inkscape:transform-center-x="11.044759"
+ inkscape:connector-curvature="0"
+ id="path5010"
+ d="m -0.52403983,48.510133 0.0154511,-3.487667 C -7.2448512,44.942356 -13.911142,43.340039 -19.989534,40.326163 l -1.591395,3.126201 c 6.563792,3.254436 13.7823459,4.974145 21.05688917,5.057769 z"
+ style="fill:#00d400;fill-opacity:1;stroke:none" />
+ <svg:path
+ inkscape:transform-center-y="-24.174304"
+ inkscape:transform-center-x="39.074649"
+ inkscape:connector-curvature="0"
+ id="path5002"
+ d="m -45.973942,-15.488849 3.312195,1.092444 c 2.157808,-6.381812 5.741699,-12.226687 10.486391,-17.076243 l -2.481425,-2.479556 c -5.123476,5.236862 -8.989672,11.570695 -11.317161,18.463355 z"
+ style="fill:#00d400;fill-opacity:1;stroke:none" />
+ <svg:path
+ style="fill:#00d400;fill-opacity:1;stroke:none"
+ d="m -47.994872,7.0710673 3.447146,-0.5303303 c -0.974661,-6.66586045 -0.434908,-13.5007347 1.590991,-19.975766 l -3.336661,-1.082757 c -2.187565,6.9920876 -2.756871,14.39079041 -1.701476,21.5888533 z"
+ id="path5004"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-x="45.733006"
+ inkscape:transform-center-y="-3.7233588" />
+ <svg:path
+ inkscape:transform-center-y="17.810418"
+ inkscape:transform-center-x="42.280768"
+ inkscape:connector-curvature="0"
+ id="path5006"
+ d="m -39.553546,28.089583 2.830664,-2.037499 c -3.894666,-5.496838 -6.516711,-11.831799 -7.651224,-18.5208328 l -3.464548,0.5500689 c 1.225206,7.2231289 4.076892,14.0738809 8.285108,20.0082629 z"
+ style="fill:#00d400;fill-opacity:1;stroke:none" />
+ <svg:path
+ style="fill:#00d400;fill-opacity:1;stroke:none"
+ d="m -22.490063,42.984936 1.597135,-3.10052 c -5.965685,-3.129577 -11.177957,-7.583685 -15.225573,-13.0286 l -2.837209,2.062987 c 4.370899,5.879623 10.021946,10.68905 16.465647,14.066133 z"
+ id="path5008"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-x="29.924319"
+ inkscape:transform-center-y="34.920377" />
+ </svg:g>
+ <svg:g
+ id="dial">
+ <svg:path
+ transform="translate(-50,-50)"
+ id="path4401"
+ d="M 50,0 C 22.385763,0 0,22.385763 0,50 c 0,27.614237 22.385763,50 50,50 l 0,-1.5 C 23.21419,98.5 1.5,76.78581 1.5,50 1.5,23.21419 23.21419,1.5 50,1.5 76.78581,1.5 98.5,23.21419 98.5,50 l 1.5,0 C 100,22.385763 77.614237,0 50,0 z"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ inkscape:connector-curvature="0" />
+ <svg:rect
+ inkscape:transform-center-y="51.283333"
+ y="40.5"
+ x="-1"
+ height="8.5"
+ width="2"
+ id="rect4409"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none" />
+ <svg:rect
+ inkscape:transform-center-x="31.996582"
+ transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ id="rect4411"
+ width="2"
+ height="7.5"
+ x="-1"
+ y="41.5"
+ inkscape:transform-center-y="-31.996582" />
+ <svg:rect
+ y="41.5"
+ x="-1.0000002"
+ height="7.5"
+ width="2"
+ id="rect4413"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ transform="matrix(0,-1,1,0,0,0)"
+ inkscape:transform-center-x="-45.25" />
+ <svg:rect
+ inkscape:transform-center-x="21.110558"
+ transform="matrix(0.89100652,0.4539905,-0.4539905,0.89100652,0,0)"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ id="rect4961"
+ width="1"
+ height="5"
+ x="-0.5"
+ y="44"
+ inkscape:transform-center-y="41.431803" />
+ <svg:rect
+ inkscape:transform-center-y="27.332014"
+ y="44"
+ x="-0.49999985"
+ height="5"
+ width="1"
+ id="rect4963"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ transform="matrix(0.58778525,0.809017,-0.809017,0.58778525,0,0)"
+ inkscape:transform-center-x="37.61929" />
+ <svg:rect
+ inkscape:transform-center-x="45.927507"
+ transform="matrix(0.15643446,0.98768834,-0.98768834,0.15643446,0,0)"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ id="rect4965"
+ width="1"
+ height="5"
+ x="-0.49999964"
+ y="44"
+ inkscape:transform-center-y="7.2742025" />
+ <svg:rect
+ inkscape:transform-center-y="-14.36929"
+ y="44"
+ x="-0.49999928"
+ height="5"
+ width="1"
+ id="rect4967"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ transform="matrix(-0.309017,0.95105651,-0.95105651,-0.309017,0,0)"
+ inkscape:transform-center-x="44.224127" />
+ <svg:rect
+ inkscape:transform-center-x="14.36929"
+ transform="matrix(-0.95105652,0.30901699,-0.30901699,-0.95105652,0,0)"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ id="rect4969"
+ width="1"
+ height="5"
+ x="-0.49999872"
+ y="44"
+ inkscape:transform-center-y="-44.224128" />
+ <svg:rect
+ inkscape:transform-center-y="-45.927508"
+ y="44"
+ x="-0.49999878"
+ height="5"
+ width="1"
+ id="rect4971"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ transform="matrix(-0.98768834,-0.15643447,0.15643447,-0.98768834,0,0)"
+ inkscape:transform-center-x="-7.2742029" />
+ <svg:rect
+ inkscape:transform-center-x="-27.332015"
+ transform="matrix(-0.80901699,-0.58778526,0.58778526,-0.80901699,0,0)"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ id="rect4973"
+ width="1"
+ height="5"
+ x="-0.49999899"
+ y="44"
+ inkscape:transform-center-y="-37.619291" />
+ <svg:rect
+ inkscape:transform-center-y="-21.110559"
+ y="44"
+ x="-0.49999952"
+ height="5"
+ width="1"
+ id="rect4975"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ transform="matrix(-0.45399049,-0.89100653,0.89100653,-0.45399049,0,0)"
+ inkscape:transform-center-x="-41.431805" />
+ </svg:g>
+ <svg:g
+ id="upper">
+ <svg:path
+ inkscape:transform-center-y="-11.026553"
+ inkscape:transform-center-x="-44.430044"
+ inkscape:connector-curvature="0"
+ id="path4979"
+ d="m 43.460756,-21.556216 -3.114549,1.5696 c 2.986821,6.038424 4.585579,12.7055669 4.65973,19.48972598 l 3.507943,-0.001321 C 48.433702,-7.8240776 46.68882,-15.036587 43.460756,-21.556216 z"
+ style="fill:#ff0000;fill-opacity:1;stroke:none" />
+ <svg:path
+ style="fill:#ff0000;fill-opacity:1;stroke:none"
+ d="m 28.9375,-38.9375 -2.0625,2.8125 c 5.402664,4.024287 9.853987,9.238934 13,15.25 L 43,-22.46875 C 39.602688,-28.959745 34.773576,-34.593978 28.9375,-38.9375 z"
+ id="path5000"
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-x="-34.9375"
+ inkscape:transform-center-y="-29.90625" />
+ </svg:g>
+ <svg:g
+ id="labels">
+ <svg:text
+ xml:space="preserve"
+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+ x="40.52644"
+ y="3.5468256"
+ id="text5100"
+ sodipodi:linespacing="125%"><svg:tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Sans;-inkscape-font-specification:Sans"
+ sodipodi:role="line"
+ id="max"
+ x="40.52644"
+ y="3.5468256">100</svg:tspan></svg:text>
+ <svg:text
+ sodipodi:linespacing="125%"
+ id="text5102"
+ y="39.272289"
+ x="0.0016270902"
+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ xml:space="preserve"><svg:tspan
+ y="39.272289"
+ x="0.0016270902"
+ id="min"
+ sodipodi:role="line">0</svg:tspan></svg:text>
+ <svg:text
+ sodipodi:linespacing="125%"
+ id="text5104"
+ y="27.28607"
+ x="25.962608"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#1a1a1a;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ xml:space="preserve"><svg:tspan
+ y="27.28607"
+ x="25.962608"
+ id="value"
+ sodipodi:role="line">0</svg:tspan></svg:text>
+ <svg:text
+ sodipodi:linespacing="125%"
+ id="text5106"
+ y="38.902164"
+ x="25.957726"
+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+ xml:space="preserve"><svg:tspan
+ y="38.902164"
+ x="25.957726"
+ id="unit"
+ sodipodi:role="line">%</svg:tspan></svg:text>
+ <svg:text
+ sodipodi:linespacing="125%"
+ id="text5108"
+ y="-20.848358"
+ x="-28.750261"
+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#4d4d4d;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+ xml:space="preserve"><svg:tspan
+ y="-20.848358"
+ x="-28.750261"
+ id="med"
+ sodipodi:role="line"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;font-family:Sans;-inkscape-font-specification:Sans">50</svg:tspan></svg:text>
+ </svg:g>
+ <svg:g
+ id="hand">
+ <svg:path
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none"
+ d="m 48,50 c 0,13.34999 2,42 2,42 0,0 2,-28.65001 2,-42 0,-3 -4,-3 -4,0 z"
+ id="path5012"
+ inkscape:connector-curvature="0"
+ transform="translate(-50,-50)"
+ sodipodi:nodetypes="scss"/>
+ </svg:g>
+</svg:svg>
diff --git a/vfd-backend/public/images/instruments/heading.svg b/vfd-backend/public/images/instruments/compass.svg
index 83cf17b..83cf17b 100644
--- a/vfd-backend/public/images/instruments/heading.svg
+++ b/vfd-backend/public/images/instruments/compass.svg
diff --git a/vfd-backend/public/images/instruments/attitude.svg b/vfd-backend/public/images/instruments/horizon.svg
index 09464d1..363b962 100644
--- a/vfd-backend/public/images/instruments/attitude.svg
+++ b/vfd-backend/public/images/instruments/horizon.svg
@@ -20,17 +20,17 @@
id="defs4">
<clipPath
clipPathUnits="userSpaceOnUse"
- id="clipPath3999">
+ id="clipPath3055">
<path
- transform="translate(-55,-55)"
- d="M 105,55 A 50,50 0 1 1 5,55 50,50 0 1 1 105,55 z"
- sodipodi:ry="50"
- sodipodi:rx="50"
- sodipodi:cy="55"
- sodipodi:cx="55"
- id="path4002"
+ sodipodi:type="arc"
style="fill:#00ff00;fill-opacity:1;stroke:none"
- sodipodi:type="arc" />
+ id="path3057"
+ sodipodi:cx="55"
+ sodipodi:cy="55"
+ sodipodi:rx="50"
+ sodipodi:ry="50"
+ d="M 105,55 A 50,50 0 1 1 5,55 50,50 0 1 1 105,55 z"
+ transform="translate(-55,-55)" />
</clipPath>
</defs>
<sodipodi:namedview
@@ -41,7 +41,7 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
- inkscape:cx="-34.071266"
+ inkscape:cx="-19.222023"
inkscape:cy="22.322089"
inkscape:document-units="px"
inkscape:current-layer="layer1"
@@ -87,21 +87,21 @@
id="layer1">
<g
id="roll"
- clip-path="url(#clipPath3999)">
+ clip-path="url(#clipPath3055)">
<g
id="pitch">
<rect
style="fill:#2eccfa;fill-opacity:1;stroke:none"
id="rect3861"
width="100"
- height="100"
+ height="150"
x="-50"
- y="-100" />
+ y="-150" />
<rect
style="fill:#61380b;fill-opacity:1;stroke:none"
id="rect3863"
width="100"
- height="100"
+ height="150"
x="-50"
y="0" />
<rect
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/Main.scala b/vfd-frontend/src/main/scala/vfd/frontend/Main.scala
index 5c22a4b..446d56d 100644
--- a/vfd-frontend/src/main/scala/vfd/frontend/Main.scala
+++ b/vfd-frontend/src/main/scala/vfd/frontend/Main.scala
@@ -64,7 +64,8 @@ object Main {
socket.stats.packets,
socket.stats.crcErrors,
socket.stats.overflows,
- socket.stats.wrongIds))))))
+ socket.stats.wrongIds,
+ message))))))
env.root.appendChild(element.render)
}
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala b/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala
index a340c15..4c17ecf 100644
--- a/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala
+++ b/vfd-frontend/src/main/scala/vfd/frontend/ui/Components.scala
@@ -1,7 +1,6 @@
package vfd.frontend.ui
import org.scalajs.dom.HTMLElement
-
import rx.Obs
import rx.Rx
import rx.Rx
@@ -19,17 +18,6 @@ import vfd.frontend.util.Environment
object Components {
- def led(color: Rx[String], size: String)(implicit app: Environment) = {
- val elem = `object`(`type` := "image/svg+xml", "data".attr := app.asset("leds/led.svg"), width := size)(
- "Error loading image.").render
-
- Obs(color, skipInitial = true) {
- val svg = elem.contentDocument
- svg.getElementById("light").setAttribute("fill", color())
- }
- elem
- }
-
private def instrument(name: String)(implicit app: Environment) = {
val path = app.asset("images/instruments/" + name + ".svg")
`object`(`type` := "image/svg+xml", "data".attr := path, width := "100%")(
@@ -40,21 +28,34 @@ object Components {
div(style := s"width: $size; height: $size; display: inline-block;")(
elem)
}
+
+ def led(color: Rx[String], size: String)(implicit app: Environment) = {
+ val elem = `object`(`type` := "image/svg+xml", "data".attr := app.asset("leds/led.svg"), width := size)(
+ "Error loading image.").render
+
+ Obs(color, skipInitial = true) {
+ val svg = elem.contentDocument
+ svg.getElementById("light").setAttribute("fill", color())
+ }
+ elem
+ }
- def attitude(pitchRoll: Rx[(Double, Double)], size: String)(implicit app: Environment) = {
- val inst = instrument("attitude")
+ def horizon(pitchRoll: Rx[(Double, Double)], size: String)(implicit app: Environment) = {
+ val inst = instrument("horizon")
Obs(pitchRoll, skipInitial = true) {
val svg = inst.contentDocument
val pitch = svg.getElementById("pitch")
val roll = svg.getElementById("roll")
- pitch.setAttribute("transform", "translate(0, " + pitchRoll()._1 / math.Pi * 180 + ")");
- roll.setAttribute("transform", "rotate(" + pitchRoll()._2 / math.Pi * 180 + ")");
+ pitch.style.transition = "transform 250ms ease-out"
+ roll.style.transition = "transform 250ms ease-out"
+ pitch.style.transform = "translate(0px, " + pitchRoll()._1 + "px)"
+ roll.style.transform = "rotate(" + pitchRoll()._2 + "deg)"
}
frame(inst, size)
}
- def altitude(value: Rx[Double], size: String)(implicit app: Environment) = {
- val inst = instrument("altitude")
+ def altimeter(value: Rx[Double], size: String)(implicit app: Environment) = {
+ val inst = instrument("altimeter")
Obs(value, skipInitial = true) {
val svg = inst.contentDocument
// 36deg === 1m
@@ -63,14 +64,29 @@ object Components {
frame(inst, size)
}
- def heading(value: Rx[Double], size: String)(implicit app: Environment) = {
- val inst = instrument("heading")
+ def compass(value: Rx[Double], size: String)(implicit app: Environment) = {
+ val inst = instrument("compass")
Obs(value, skipInitial = true) {
val svg = inst.contentDocument
- // 1deg === 1deg
- svg.getElementById("heading").setAttribute("transform", "rotate(" + value() / math.Pi * 180 + ")");
+ val heading = svg.getElementById("heading")
+ heading.style.transition = "transform 250ms ease-out"
+ heading.style.transform = "rotate(" + value() + "deg)"
}
frame(inst, size)
}
+
+ def basic(value: Rx[Double], size: String)(implicit app: Environment) = {
+ val inst = instrument("basic")
+ Obs(value, skipInitial = true) {
+ val svg = inst.contentDocument
+ val hand = svg.getElementById("hand")
+ hand.style.transform = "rotate(" + value() * 270 / 100 + "deg)";
+ hand.style.transition = "transform 250ms ease-out"
+ svg.getElementById("unit").textContent = "%"
+ svg.getElementById("value").textContent = value().toString
+ }
+ frame(inst, size)
+ }
+
+}
-} \ No newline at end of file
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Communication.scala b/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Communication.scala
index b93ad27..ba0d490 100644
--- a/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Communication.scala
+++ b/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Communication.scala
@@ -15,10 +15,31 @@ import scalatags.JsDom.all.td
import scalatags.JsDom.all.tr
import vfd.frontend.util.Environment
import vfd.frontend.util.Framework.RxStr
+import vfd.frontend.ui.Components
+import rx.core.Var
+import rx.core.Obs
+import org.mavlink.messages._
object Communication {
- def apply(packets: Rx[Int], crcs: Rx[Int], overflows: Rx[Int], wrongIds: Rx[Int])(implicit app: Environment) = {
+ def apply(packets: Rx[Int], crcs: Rx[Int], overflows: Rx[Int], wrongIds: Rx[Int], message: Rx[Message])(implicit app: Environment) = {
+
+ val m0 = Var(0.0)
+ val m1 = Var(0.0)
+ val m2 = Var(0.0)
+ val m3 = Var(0.0)
+
+ Obs(message) {
+ message() match {
+ case Motor(_m0, _m1, _m2, _m3) =>
+ m0() = _m0
+ m1() = _m1
+ m2() = _m2
+ m3() = _m3
+ case _ => ()
+ }
+ }
+
div(
"Link Status",
table(`class` := "table table-condensed")(
@@ -42,7 +63,9 @@ object Communication {
td("OFLW"),
td(overflows),
td("BID"),
- td(wrongIds)))))
+ td(wrongIds)))),
+ div(
+ Components.basic(m0, "25%"),Components.basic(m1, "25%"),Components.basic(m2, "25%"),Components.basic(m3, "25%")))
}
} \ No newline at end of file
diff --git a/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Primary.scala b/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Primary.scala
index 738a84a..4517ea0 100644
--- a/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Primary.scala
+++ b/vfd-frontend/src/main/scala/vfd/frontend/ui/panels/Primary.scala
@@ -1,7 +1,6 @@
package vfd.frontend.ui.panels
-import org.mavlink.messages.Message
-
+import org.mavlink.messages._
import rx.core.Obs
import rx.core.Rx
import rx.core.Var
@@ -18,14 +17,17 @@ object Primary {
Obs(message) {
message() match {
+ case Attitude(roll, pitch, yaw) =>
+ pitchRoll() = (roll, pitch)
+ heading() = yaw
case _ => ()
}
}
div(
- Components.heading(heading, "33%"),
- Components.attitude(pitchRoll, "33%"),
- Components.altitude(altitude, "33%"))
+ Components.compass(heading, "33%"),
+ Components.horizon(pitchRoll, "33%"),
+ Components.altimeter(altitude, "33%"))
}
} \ No newline at end of file
diff --git a/vfd-uav/src/main/scala/vfd/uav/MockConnection.scala b/vfd-uav/src/main/scala/vfd/uav/MockConnection.scala
index 126fa9a..d427aef 100644
--- a/vfd-uav/src/main/scala/vfd/uav/MockConnection.scala
+++ b/vfd-uav/src/main/scala/vfd/uav/MockConnection.scala
@@ -1,15 +1,15 @@
package vfd.uav
import java.util.concurrent.TimeUnit.MILLISECONDS
-
import scala.concurrent.duration.FiniteDuration
import scala.util.Random
-
import Connection.Received
import akka.actor.Actor
import akka.actor.ActorLogging
import akka.actor.Props
import akka.util.ByteString
+import org.mavlink.messages._
+import org.mavlink.Packet
class MockConnection extends Actor with ActorLogging with Connection {
import Connection._
@@ -36,7 +36,21 @@ object MockConnection {
object MockPackets {
- def random() = Random.nextInt(2) match {
+ private implicit class RichMessage(val message: Message) extends AnyVal {
+ def bytes: Array[Byte] = {
+ val (id, payload) = Message.pack(message)
+ Packet(5, 42, 1, id, payload).toSeq.toArray
+ }
+ }
+
+ def random(): Array[Byte] = Random.nextInt(4) match {
+ case 0 => randomInvalid()
+ case 1 => Heartbeat(0).bytes
+ case 2 => Motor(Random.nextInt(101).toByte, Random.nextInt(101).toByte, Random.nextInt(101).toByte, Random.nextInt(101).toByte).bytes
+ case 3 => Attitude((Random.nextInt(160) - 80).toShort, (Random.nextInt(160) - 80).toShort.toShort, Random.nextInt(360).toShort).bytes
+ }
+
+ def randomInvalid() = Random.nextInt(2) match {
case 0 => invalidCrc
case 1 => invalidOverflow
}