diff --git a/web/css/ahrs.css b/web/css/ahrs.css index 10e1337e..400b3338 100644 --- a/web/css/ahrs.css +++ b/web/css/ahrs.css @@ -113,3 +113,34 @@ text-anchor: start; } +/* For attitude indicator */ +.ai .earth { + fill: chocolate; +} + +.ai .sky { + fill: deepskyblue; +} + +.ai .pointer { + stroke: goldenrod; + fill: yellow; +} + +.ai .pointerBG { + fill: goldenrod; +} + +.ai .marks { + fill: white; + stroke: white; + stroke-width: 2px; +} + +.ai .markText { + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + alignment-baseline: middle; + stroke-width: 0px; +} diff --git a/web/img/ai.svg b/web/img/ai.svg deleted file mode 100644 index c7a10079..00000000 --- a/web/img/ai.svg +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 80 - 80 - 90 - 90 - 80 - 80 - 70 - 70 - 60 - 60 - 50 - 50 - 40 - 40 - 30 - 30 - 20 - 20 - 10 - 10 - 10 - 10 - 20 - 20 - 30 - 30 - 40 - 40 - 50 - 50 - 60 - 60 - 70 - 70 - 80 - 80 - 90 - 90 - 80 - 80 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 270 - 300 - 330 - 0 - 30 - 60 - 90 - 120 - 150 - 180 - 210 - 240 - 270 - 300 - 330 - 0 - 30 - 60 - 90 - - - - - - - - - - - - - diff --git a/web/plates/gps.html b/web/plates/gps.html index b6c9e7f0..f47417d0 100644 --- a/web/plates/gps.html +++ b/web/plates/gps.html @@ -32,11 +32,7 @@
-
- - Please do a hard reload on your browser. - -
+
diff --git a/web/plates/js/ahrs.js b/web/plates/js/ahrs.js index 2fb8165f..09560a28 100644 --- a/web/plates/js/ahrs.js +++ b/web/plates/js/ahrs.js @@ -1,112 +1,115 @@ -function ahrsRenderer(location_id) { +function ahrsRenderer(locationId) { this.width = -1; this.height = -1; - this.locationID = location_id; - this.canvas = document.getElementById(location_id); - this.canvas_container = document.getElementById(location_id).parentElement; - - var ai = document.getElementById("attitude_indicator"), - _this = this; + this.locationId = locationId; + this.canvas = document.getElementById(locationId); + this.resize(); - this.ps = []; - this.rs = []; - this.hs = []; - this.ss = []; - - ai.onload = function() { - _this.ps = ai.contentDocument.getElementsByClassName("pitch"); - _this.rs = ai.contentDocument.getElementsByClassName("roll"); - _this.hs = ai.contentDocument.getElementsByClassName("heading"); - _this.ss = ai.contentDocument.getElementsByClassName("slipSkid"); - }; + // State variables + this.pitch = 0; + this.roll = 0; + this.heading = 0; + this.slipSkid = 0; + this.altitude = 0; + var ai = SVG(locationId).viewbox(-200, -200, 400, 400).group().addClass('ai'), + defs = ai.defs(), + earthClip = defs.rect(2400, 1200).x(-1200).y(0), + screenClip = defs.rect(400, 400).cx(0).cy(0); + this.pitchClip = defs.circle(320).cx(0).cy(0); + this.rollClip = defs.polygon('0,0 -200,-200 200,-200'); + + ai = ai.clipWith(screenClip).group(); + + // card is the earth+sky+pitch marks, moves with both pitch and roll. + this.card = ai.group(); + this.card.circle(2400).cx(0).cy(0).addClass('sky'); // Sky + this.card.line(-1200, 0, 1200, 0).addClass('marks'); // Horizon line + this.card.circle(2400).cx(0).cy(0).addClass('earth').clipWith(earthClip); // Earth + + var pitchMarks = this.card.group().addClass('marks').clipWith(this.pitchClip); + for (i = -1050; i <= 1050; i+=25) { + switch (i%100) { + case 0: + pitchMarks.line(-40, i, 40, i); + if (i!=0) { + pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(-55).cy(i).addClass('markText'); + pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(+55).cy(i).addClass('markText'); + } + break; + case 50: + pitchMarks.line(-20, i, 20, i); + break; + default: + pitchMarks.line(-10, i, 10, i); + } + } + + this.rollMarks = ai.group().addClass('marks').clipWith(this.rollClip); + for (i=-180; i<180; i+=10) { + if (i == 0) { + this.rollMarks.polygon('-10,-189 0,-175 10,-189').style('stroke-width', 0); + } + else if (i % 30 == 0) { + this.rollMarks.line(0, -175, 0, -195).rotate(i, 0, 0); + } else { + this.rollMarks.line(0, -175, 0, -189).rotate(i, 0, 0); + } + } + + var rollPointer = ai.group().addClass('marks'); + rollPointer.polygon('-10,-160 0,-174 10,-160').style('stroke-width', 0); + rollPointer.polygon('-10,+160 0,+174 10,+160').style('stroke-width', 0); + this.skidBar = ai.rect(20, 6).cx(0).y(-158).style('stroke-width', 0).addClass('marks'); + + var pointer = ai.group().addClass('pointer'); + pointer.polygon('-150,-3 -78,-3 -75,0 -78,3 -150,3'); + pointer.polygon('+150,-3 +78,-3 +75,0 +78,3 +150,3'); + pointer.polygon('-75,25 0,0 75,25 25,25 25,20 -25,20 -25,25').addClass('pointerBG'); + pointer.polygon('-75,25 0,0 75,25 0,10'); + pointer.line(0, 0, 0, 10); + + this.headingMarks = ai.group().addClass('marks'); + for (i=-200; i<=920; i+=20) { + if (i%60==0) { + this.headingMarks.line(i, 175, i, 178); + this.headingMarks.text((i<0 ? (i/2+360) : i/2).toString()).x(i).cy(185).addClass('markText'); + this.headingMarks.line(i, 192, i, 195); + } else { + this.headingMarks.line(i, 175, i, 195).style('stroke-width', 1); + } + } } ahrsRenderer.prototype = { constructor: ahrsRenderer, - init: function () { + resize: function () { + var canvasWidth = this.canvas.parentElement.offsetWidth - 12; - this.pitch = 0; - this.roll = 0; - this.heading = 0; - this.slipSkid = 0; + if (canvasWidth !== this.width) { + this.width = canvasWidth; + this.height = canvasWidth * 0.5; - this.resize(); - }, + this.canvas.width = this.width; + this.canvas.height = this.height; + } + }, - resize: function () { - var canvasWidth = this.canvas_container.offsetWidth - 12; // was (2*(this.canvas_container.offsetLeft)) // account for padding adjustments - - if (canvasWidth !== this.width) { - this.width = canvasWidth; - this.height = canvasWidth *0.5; - - this.canvas.width = this.width; - this.canvas.height = this.height; - } - }, - - orientation: function (pitch, roll, heading, slipSkid) { - // Assume we receive valid pitch, roll, heading - this.pitch = pitch; - this.roll = roll; - this.heading = heading; + update: function (pitch, roll, heading, slipSkid) { + this.pitch = pitch; + this.roll = roll; + this.heading = heading; this.slipSkid = slipSkid; - }, - animate: function (t, pitch, roll, heading, slipSkid) { - var FPS = 40; // we assume we can maintain a certain frame rate - var x_inc = ((pitch - this.pitch) / (FPS * t)); - var y_inc = ((roll - this.roll) / (FPS * t)); - if ((heading < this.heading) && (this.heading - heading) > 180) { - // let the animation wrap around gracefully clockwise - heading += 360; - } else if ((heading > this.heading) && (heading - this.heading) > 180) { - // let the animation wrap around gracefully counter clockwise - this.heading += 360; - } - var z_inc = ((heading - this.heading) / (FPS * t)); - var w_inc = ((slipSkid - this.slipSkid) / (FPS * t)); - var _this = this; - var frames = 0; - var f = function () { - _this.pitch += x_inc; - _this.roll += y_inc; - _this.heading += z_inc; - _this.slipSkid += w_inc; - if (frames < (FPS * t)) { - _this.draw(); - frames++; - window.requestAnimationFrame(f); // recurse - } else { - _this.orientation(pitch, roll, heading, slipSkid); - } - }; - f(); - }, - - draw: function() { - for (i=0; i