diff options
author | Jakob Odersky <jakob@odersky.com> | 2016-04-18 03:15:43 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2016-04-18 03:15:43 -0700 |
commit | 05f2776ccb9989dbc359276c5c36c46d8282fc8f (patch) | |
tree | 931bd6728602694ebefbc52351287d0b08657aba /mavigator-server | |
parent | ea468fe2af5dbc674c08e2f2c1d6766e6596f9a1 (diff) | |
download | mavigator-05f2776ccb9989dbc359276c5c36c46d8282fc8f.tar.gz mavigator-05f2776ccb9989dbc359276c5c36c46d8282fc8f.tar.bz2 mavigator-05f2776ccb9989dbc359276c5c36c46d8282fc8f.zip |
Implement serial backend
Diffstat (limited to 'mavigator-server')
-rw-r--r-- | mavigator-server/build.sbt | 45 | ||||
-rw-r--r-- | mavigator-server/src/main/resources/assets/images/hud/attitude.svg | 972 | ||||
-rw-r--r-- | mavigator-server/src/main/resources/assets/images/hud/horizon.svg | 51 | ||||
-rw-r--r-- | mavigator-server/src/main/scala/mavigator/Main.scala | 40 | ||||
-rw-r--r-- | mavigator-server/src/main/scala/mavigator/Router.scala | 120 |
5 files changed, 1059 insertions, 169 deletions
diff --git a/mavigator-server/build.sbt b/mavigator-server/build.sbt index 89bb0cd..10b59d0 100644 --- a/mavigator-server/build.sbt +++ b/mavigator-server/build.sbt @@ -7,7 +7,50 @@ MavigatorBuild.defaultSettings libraryDependencies ++= Seq( Dependencies.akkaHttp, Dependencies.akkaHttpCore, - Dependencies.akkaStream + Dependencies.akkaStream, + Dependencies.flowNative //FIXME runtime dependencies from uav are not included, is this an sbt bug? ) Js.dependsOnJs(MavigatorBuild.cockpit) + +fork in run := true +connectInput in run := true +cancelable in Global := true + + +/* + * Deployment configuration + */ +enablePlugins(UniversalPlugin, DebianPlugin, DockerPlugin) +enablePlugins(JavaServerAppPackaging) + + +name in Universal := "mavigator" +packageName in Universal := "mavigator" +executableScriptName in Universal := "mavigator" + +name in Linux := (name in Universal).value +packageName in Linux := (packageName in Universal).value +executableScriptName in Linux := (executableScriptName in Universal).value + +maintainer in Linux := "Jakob Odersky <jakob@odersky.com>" +packageSummary in Linux := "Virtual cockpit for drones." +packageDescription in Linux := "Compatible with devices using the MAVLink protocol." + +version in Debian := version.value +debianPackageDependencies in Debian ++= Seq( + "java8-runtime-headless", + "bash (>= 2.05a-11)" +) + +import com.typesafe.sbt.packager.archetypes.ServerLoader +serverLoading in Debian := ServerLoader.Systemd + + +name in Docker := "mavigator" +packageName in Docker := "mavigator" +executableScriptName := "mavigator" +maintainer in Docker := "Jakob Odersky <jakob@odersky.com>" + +dockerBaseImage := "java:8" +dockerExposedPorts += 8080 diff --git a/mavigator-server/src/main/resources/assets/images/hud/attitude.svg b/mavigator-server/src/main/resources/assets/images/hud/attitude.svg index eb7dd70..04d5c71 100644 --- a/mavigator-server/src/main/resources/assets/images/hud/attitude.svg +++ b/mavigator-server/src/main/resources/assets/images/hud/attitude.svg @@ -20,12 +20,13 @@ id="defs4"> <clipPath clipPathUnits="userSpaceOnUse" - id="clipPath4472"> + id="clipPath4744"> <circle - id="circle4474" - cx="0" + r="380" cy="0" - r="380" /> + cx="0" + id="circle4746" + style="fill:#000080" /> </clipPath> </defs> <sodipodi:namedview @@ -35,9 +36,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="415.60712" - inkscape:cy="547.77206" + inkscape:zoom="0.70710678" + inkscape:cx="229.45655" + inkscape:cy="461.66458" inkscape:document-units="px" inkscape:current-layer="svg2" showgrid="true" @@ -61,7 +62,7 @@ inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" - showguides="false"> + showguides="true"> <inkscape:grid type="xygrid" id="grid4686" /> @@ -84,7 +85,7 @@ clip-path="none"> <g id="g4476" - clip-path="url(#clipPath4472)"> + clip-path="url(#clipPath4744)"> <g id="pitch"> <path @@ -109,11 +110,6 @@ inkscape:connector-curvature="0" /> <path inkscape:connector-curvature="0" - id="path5032" - d="m -30,-350 60,0" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> - <path - inkscape:connector-curvature="0" id="path5034" d="m -50,-200 100,0" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> @@ -138,11 +134,6 @@ d="m -30,250 60,0" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m -30,350 60,0" - id="path5044" - inkscape:connector-curvature="0" /> - <path inkscape:connector-curvature="0" id="path5046" d="m -50,100 100,0" @@ -152,11 +143,6 @@ d="m -50,200 100,0" id="path5048" inkscape:connector-curvature="0" /> - <path - inkscape:connector-curvature="0" - id="path5050" - d="m -50,300 100,0" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" @@ -214,17 +200,6 @@ y="204.55017">20</tspan></text> <text xml:space="preserve" - style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - x="50" - y="304.55017" - id="text5078" - sodipodi:linespacing="125%"><tspan - sodipodi:role="line" - id="tspan5080" - x="50" - y="304.55017">30</tspan></text> - <text - xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="-50" y="-295.44983" @@ -278,17 +253,6 @@ id="tspan5100" x="-50" y="204.55017">20</tspan></text> - <text - xml:space="preserve" - style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - x="-50" - y="304.55017" - id="text5102" - sodipodi:linespacing="125%"><tspan - sodipodi:role="line" - x="-50" - y="304.55017" - id="tspan5106">30</tspan></text> <path inkscape:connector-curvature="0" id="path5110" @@ -397,26 +361,6 @@ d="m -10,-290 20,0" style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m -10,-340 20,0" - id="path4263" - inkscape:connector-curvature="0" /> - <path - inkscape:connector-curvature="0" - id="path4265" - d="m -10,-330 20,0" - style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> - <path - style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="m -10,-320 20,0" - id="path4267" - inkscape:connector-curvature="0" /> - <path - inkscape:connector-curvature="0" - id="path4269" - d="m -10,-310 20,0" - style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> - <path inkscape:connector-curvature="0" id="path4273" d="m -10,-170 20,0" @@ -578,24 +522,895 @@ inkscape:connector-curvature="0" /> <path inkscape:connector-curvature="0" - id="path4337" + id="path4369" + d="m -30,-350 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4371" + d="m -50,-400 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4373" + y="-395.44983" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-395.44983" + x="50" + id="tspan4375" + sodipodi:role="line">40</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4377" + y="-395.44983" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-395.44983" + x="-50" + id="tspan4379" + sodipodi:role="line">40</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-370 20,0" + id="path4381" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4383" + d="m -10,-380 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4385" + d="m -10,-360 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-340 20,0" + id="path4387" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4389" + d="m -10,-330 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-320 20,0" + id="path4391" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4393" + d="m -10,-310 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-390 20,0" + id="path4395" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,-450 60,0" + id="path4397" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,-500 100,0" + id="path4399" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="-495.44983" + id="text4401" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4403" + x="50" + y="-495.44983">50</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="-495.44983" + id="text4405" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4407" + x="-50" + y="-495.44983">50</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4409" + d="m -10,-470 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-480 20,0" + id="path4411" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-460 20,0" + id="path4413" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4415" + d="m -10,-440 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-430 20,0" + id="path4417" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4419" + d="m -10,-420 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-410 20,0" + id="path4421" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4423" + d="m -10,-490 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4425" + d="m -30,-550 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4427" + d="m -50,-600 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4429" + y="-595.44983" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-595.44983" + x="50" + id="tspan4431" + sodipodi:role="line">60</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4433" + y="-595.44983" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-595.44983" + x="-50" + id="tspan4435" + sodipodi:role="line">60</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-570 20,0" + id="path4437" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4439" + d="m -10,-580 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4441" + d="m -10,-560 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-540 20,0" + id="path4443" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4445" + d="m -10,-530 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-520 20,0" + id="path4447" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4449" + d="m -10,-510 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-590 20,0" + id="path4451" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,-650 60,0" + id="path4453" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,-700 100,0" + id="path4455" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="-695.44983" + id="text4457" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4459" + x="50" + y="-695.44983">70</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="-695.44983" + id="text4461" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4463" + x="-50" + y="-695.44983">70</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4465" + d="m -10,-670 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-680 20,0" + id="path4467" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-660 20,0" + id="path4469" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4471" + d="m -10,-640 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-630 20,0" + id="path4473" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4475" + d="m -10,-620 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-610 20,0" + id="path4477" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4479" + d="m -10,-690 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4481" + d="m -30,-750 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4483" + d="m -50,-800 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4485" + y="-795.44983" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-795.44983" + x="50" + id="tspan4487" + sodipodi:role="line">80</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4489" + y="-795.44983" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="-795.44983" + x="-50" + id="tspan4491" + sodipodi:role="line">80</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-770 20,0" + id="path4493" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4495" + d="m -10,-780 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4497" + d="m -10,-760 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-740 20,0" + id="path4499" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4501" + d="m -10,-730 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-720 20,0" + id="path4503" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4505" + d="m -10,-710 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-790 20,0" + id="path4507" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,-850 60,0" + id="path4509" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,-900 100,0" + id="path4511" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="-895.44983" + id="text4513" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4515" + x="50" + y="-895.44983">90</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="-895.44983" + id="text4517" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4519" + x="-50" + y="-895.44983">90</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4521" + d="m -10,-870 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-880 20,0" + id="path4523" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-860 20,0" + id="path4525" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4527" + d="m -10,-840 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-830 20,0" + id="path4529" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4531" + d="m -10,-820 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,-810 20,0" + id="path4533" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4535" + d="m -10,-890 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,350 60,0" + id="path4565" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4567" + d="m -50,300 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4569" + y="304.55017" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="304.55017" + x="50" + id="tspan4571" + sodipodi:role="line">30</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4573" + y="304.55017" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="304.55017" + x="-50" + id="tspan4575" + sodipodi:role="line">30</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4577" d="m -10,330 20,0" style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m -10,320 20,0" - id="path4339" + id="path4579" inkscape:connector-curvature="0" /> <path style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m -10,340 20,0" - id="path4341" + id="path4581" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4583" + d="m -10,360 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,370 20,0" + id="path4585" inkscape:connector-curvature="0" /> <path inkscape:connector-curvature="0" - id="path4351" + id="path4587" + d="m -10,380 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,390 20,0" + id="path4589" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4591" d="m -10,310 20,0" style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4593" + d="m -30,450 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,400 100,0" + id="path4595" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="404.55017" + id="text4597" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4599" + x="50" + y="404.55017">40</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="404.55017" + id="text4601" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4603" + x="-50" + y="404.55017">40</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,430 20,0" + id="path4605" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4607" + d="m -10,420 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4609" + d="m -10,440 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,460 20,0" + id="path4611" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4613" + d="m -10,470 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,480 20,0" + id="path4615" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4617" + d="m -10,490 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,410 20,0" + id="path4619" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,550 60,0" + id="path4621" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4623" + d="m -50,500 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4625" + y="504.55017" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="504.55017" + x="50" + id="tspan4627" + sodipodi:role="line">50</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4629" + y="504.55017" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="504.55017" + x="-50" + id="tspan4631" + sodipodi:role="line">50</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4633" + d="m -10,530 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,520 20,0" + id="path4635" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,540 20,0" + id="path4637" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4639" + d="m -10,560 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,570 20,0" + id="path4641" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4643" + d="m -10,580 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,590 20,0" + id="path4645" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4647" + d="m -10,510 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4649" + d="m -30,650 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,600 100,0" + id="path4651" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="604.55017" + id="text4653" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4655" + x="50" + y="604.55017">60</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="604.55017" + id="text4657" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4659" + x="-50" + y="604.55017">60</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,630 20,0" + id="path4661" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4663" + d="m -10,620 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4665" + d="m -10,640 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,660 20,0" + id="path4667" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4669" + d="m -10,670 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,680 20,0" + id="path4671" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4673" + d="m -10,690 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,610 20,0" + id="path4675" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -30,750 60,0" + id="path4677" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4679" + d="m -50,700 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4681" + y="704.55017" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="704.55017" + x="50" + id="tspan4683" + sodipodi:role="line">70</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4685" + y="704.55017" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="704.55017" + x="-50" + id="tspan4687" + sodipodi:role="line">70</tspan></text> + <path + inkscape:connector-curvature="0" + id="path4689" + d="m -10,730 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,720 20,0" + id="path4691" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,740 20,0" + id="path4693" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4695" + d="m -10,760 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,770 20,0" + id="path4697" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4699" + d="m -10,780 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,790 20,0" + id="path4701" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4703" + d="m -10,710 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4705" + d="m -30,850 60,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -50,800 100,0" + id="path4707" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="50" + y="804.55017" + id="text4709" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4711" + x="50" + y="804.55017">80</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="-50" + y="804.55017" + id="text4713" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4715" + x="-50" + y="804.55017">80</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,830 20,0" + id="path4717" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4719" + d="m -10,820 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path4721" + d="m -10,840 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,860 20,0" + id="path4723" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4726" + d="m -10,870 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,880 20,0" + id="path4728" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4730" + d="m -10,890 20,0" + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -10,810 20,0" + id="path4732" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path4734" + d="m -50,900 100,0" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + sodipodi:linespacing="125%" + id="text4736" + y="904.55017" + x="-50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="904.55017" + x="-50" + id="tspan4738" + sodipodi:role="line">90</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4740" + y="904.55017" + x="50" + style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="904.55017" + x="50" + id="tspan4742" + sodipodi:role="line">90</tspan></text> </g> </g> <text @@ -783,6 +1598,12 @@ <g id="static"> <path + sodipodi:nodetypes="cc" + inkscape:connector-curvature="0" + id="path4757" + style="fill:none;fill-rule:evenodd;stroke:#ffdd55;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 385,0 70,0" /> + <path inkscape:transform-center-y="-390" inkscape:transform-center-x="-0.0686585" sodipodi:nodetypes="cccc" @@ -807,9 +1628,16 @@ d="m -103.52762,-386.37033 -6.28209,22.3888 23.049582,-6.17612 z" style="fill:#fbff00;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> <path - d="M 30,0 150,0 M -30,0 -150,0 M 0,0 15,25 30,0 15,25 0,0 -15,25 -15,25 -30,0" + d="M 30,0 60,0 M -30,0 -60,0 M 0,0 15,15 30,0 15,15 0,0 -15,15 -15,15 -30,0" style="fill:none;fill-rule:evenodd;stroke:#ffdd55;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4991" - inkscape:connector-curvature="0" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccccc" /> + <path + d="m -455,0 70,0" + style="fill:none;fill-rule:evenodd;stroke:#ffdd55;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path4759" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> </g> </svg> diff --git a/mavigator-server/src/main/resources/assets/images/hud/horizon.svg b/mavigator-server/src/main/resources/assets/images/hud/horizon.svg index 8cf0150..36d0300 100644 --- a/mavigator-server/src/main/resources/assets/images/hud/horizon.svg +++ b/mavigator-server/src/main/resources/assets/images/hud/horizon.svg @@ -9,13 +9,13 @@ xmlns="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="1200" - height="1200" + width="1000" + height="1000" id="svg2" version="1.1" - inkscape:version="0.48.5 r10040" + inkscape:version="0.91 r13725" sodipodi:docname="horizon.svg" - viewBox="-600 -600 1200 1200" + viewBox="-500 -500 1000 1000" preserveAspectRatio="none"> <defs id="defs4" /> @@ -26,15 +26,15 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.35374999" - inkscape:cx="356.86783" - inkscape:cy="585.56122" + inkscape:zoom="0.176875" + inkscape:cx="417.16915" + inkscape:cy="602.15446" inkscape:document-units="px" - inkscape:current-layer="horizon" + inkscape:current-layer="svg2" showgrid="true" showborder="true" inkscape:window-width="1920" - inkscape:window-height="1033" + inkscape:window-height="1034" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1"> @@ -58,20 +58,23 @@ </rdf:RDF> </metadata> <g - id="horizon"> - <rect - style="fill:#c88f00;fill-opacity:1;stroke:none" - id="rect3000" - width="1800" - height="1200" - x="-900" - y="0" /> - <rect - y="-1200" - x="-900" - height="1200" - width="1800" - id="rect3770" - style="fill:#aaeeff;fill-opacity:1;stroke:none" /> + id="roll"> + <g + id="pitch"> + <rect + y="0" + x="-1000" + height="2000" + width="2000" + id="ground" + style="fill:#c88f00;fill-opacity:1;stroke:none" /> + <rect + style="fill:#aaeeff;fill-opacity:1;stroke:none" + id="sky" + width="2000" + height="2000" + x="-1000" + y="-2000" /> + </g> </g> </svg> diff --git a/mavigator-server/src/main/scala/mavigator/Main.scala b/mavigator-server/src/main/scala/mavigator/Main.scala index 6ea894e..3ad1460 100644 --- a/mavigator-server/src/main/scala/mavigator/Main.scala +++ b/mavigator-server/src/main/scala/mavigator/Main.scala @@ -1,11 +1,12 @@ package mavigator +import scala.concurrent.{Await, TimeoutException} +import scala.concurrent.duration._ + import akka.actor._ import akka.http.scaladsl._ -import akka.http.scaladsl.server._ import akka.stream._ -import scala.concurrent.Await -import scala.concurrent.duration.Duration +import mavigator.uav.Uav object Main { @@ -15,30 +16,33 @@ object Main { def main(args: Array[String]): Unit = { import system.dispatcher - system.log.info("System started.") + val route = Router.route - val router = Router.route + system.log.info(s"Initializing UAV connection backend...") + Uav().init() - system.log.info(s"Starting server") - val binding = Http(system).bindAndHandle(router, "0.0.0.0", 8080) + system.log.info(s"Starting server...") + val binding = Http(system).bindAndHandle(route, "::", 8080) for (b <- binding) { val addr = b.localAddress.getHostString() val port = b.localAddress.getPort() system.log.info(s"Server is listening on $addr:$port") } - - scala.io.StdIn.readLine() - - binding.flatMap{b => - system.log.info("Shutting down server...") - b.unbind() - }.onComplete{ _ => - system.log.info("Server shut down") - system.terminate() - } - Await.result(system.whenTerminated, Duration.Inf) + sys.addShutdownHook { stop() } + } + def stop() = { + system.log.info("Stopping server...") + system.terminate() + + try { + Await.result(system.whenTerminated, 2.seconds) + System.err.println("Bye.") + } catch { + case ex: TimeoutException => + System.err.println("Shutdown is taking too long, exiting now") + } } } diff --git a/mavigator-server/src/main/scala/mavigator/Router.scala b/mavigator-server/src/main/scala/mavigator/Router.scala index 389cb4d..226d6c1 100644 --- a/mavigator-server/src/main/scala/mavigator/Router.scala +++ b/mavigator-server/src/main/scala/mavigator/Router.scala @@ -1,80 +1,92 @@ package mavigator import akka.actor._ -import akka.stream._ -import akka.stream.scaladsl._ -import akka.http.scaladsl._ +import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} +import akka.http.scaladsl.model.MediaTypes._ import akka.http.scaladsl.model._ +import akka.http.scaladsl.model.Uri.Path import akka.http.scaladsl.model.ws._ import akka.http.scaladsl.server._ -import uav.Uav import akka.util._ - -import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} -import akka.http.scaladsl.model.MediaTypes._ -import akka.http.scaladsl.model.MediaType -import play.twirl.api.{ Xml, Txt, Html } +import akka.stream.scaladsl._ +import play.twirl.api.Html +import uav.Uav object Router { import Directives._ - val socketUrl = "ws://localhost:8080/mavlink" + final val SocketEndpoint = "mavlink" + + def withSocketUri: Directive1[Uri] = extractUri.map { uri => + uri.withScheme("ws").withPath(Path.Empty / SocketEndpoint) + } def route(implicit system: ActorSystem): Route = ( - path("cockpit" / IntNumber) { id => + path("whoami") { get { - val html = mavigator.views.html.app( - "Mavigator", - "mavigator_cockpit_Main", - Map( - "socketUrl" -> socketUrl, - "remoteSystemId" -> "0", - "systemId" -> "0", - "componentId" -> "0" - ) - ) - complete(html) + withSocketUri { sock => + complete(sock.toString) + } } } ~ - path("mavlink") { - get { - val fromWebSocket = Flow[Message].collect{ - case BinaryMessage.Strict(data) => data + path("cockpit" / IntNumber) { id => + get { + withSocketUri { socket => + val html = mavigator.views.html.app( + "Mavigator", + "mavigator_cockpit_Main", + Map( + "socketUrl" -> socket.toString, + "remoteSystemId" -> id.toString + ) + ) + complete(html) + } } + } ~ + path(SocketEndpoint) { + get { + val fromWebSocket = Flow[Message].collect{ + case BinaryMessage.Strict(data) => data + } - val toWebSocket = Flow[ByteString].map{bytes => - BinaryMessage(bytes) - } + val toWebSocket = Flow[ByteString].map{bytes => + BinaryMessage(bytes) + } - val backend = Uav().connect() + val backend = Uav().connect() - handleWebSocketMessages(fromWebSocket via backend via toWebSocket) - } - } ~ - pathPrefix("assets") { - get { - encodeResponse { - getFromResourceDirectory("assets") + handleWebSocketMessages(fromWebSocket via backend via toWebSocket) + } + } ~ + pathEndOrSingleSlash { + get { + withSocketUri { socket => + val html = mavigator.views.html.app( + "Index", + "mavigator_index_Main", + Map( + "socketUrl" -> socket.toString + ) + ) + complete(html) + } + } + } ~ + pathPrefix("assets") { + get { + encodeResponse { + getFromResourceDirectory("assets") + } } } - } ~ - pathEndOrSingleSlash { - get { - val html = mavigator.views.html.app( - "Index", - "mavigator_index_Main", - Map( - "socketUrl" -> socketUrl - ) - ) - complete(html) - } - } ) - implicit val twirlHtml : ToEntityMarshaller[Html] = Marshaller.StringMarshaller.wrap(`text/html`){(h: Html) => - h.toString - } - + /** Enables completing requests with html. */ + implicit val twirlHtml : ToEntityMarshaller[Html] = + Marshaller.StringMarshaller.wrap(`text/html`){ h: Html => + h.toString + } + } |