kopia lustrzana https://github.com/cyoung/stratux
new gps / ahrs page with both data details and graphical representation using image for gps location and webgl for ahrs
rodzic
8769ced73e
commit
6e84557616
5
Makefile
5
Makefile
|
@ -15,10 +15,13 @@ www:
|
|||
mkdir -p /var/www/css
|
||||
cp web/css/*.css /var/www/css
|
||||
mkdir -p /var/www/js
|
||||
cp web/js/*.js /var/www/js
|
||||
cp web/js/main.js /var/www/js
|
||||
cp web/js/addtohomescreen.min.js /var/www/js
|
||||
cp web/js/j3di-all.min.js /var/www/js
|
||||
mkdir -p /var/www/img
|
||||
cp web/img/logo*.png /var/www/img
|
||||
cp web/img/screen*.png /var/www/img
|
||||
cp web/img/world.png /var/www/img
|
||||
mkdir -p /var/www/maui
|
||||
mkdir -p /var/www/maui/js
|
||||
cp web/maui/js/angular-ui-router.min.js /var/www/maui/js
|
||||
|
|
|
@ -6,16 +6,48 @@
|
|||
|
||||
.weather-page {}
|
||||
|
||||
.gps_page {}
|
||||
|
||||
.map-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.world-map {
|
||||
background-image: url(../img/world.png);
|
||||
background-position: 1186px 591px;
|
||||
margin-bottom: 4px;
|
||||
/* this will be set dynamically to center map at gps location */
|
||||
/*
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
*/
|
||||
}
|
||||
|
||||
.mark-position {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.washout {
|
||||
background-color: rgba(255, 255, 255, 0.65);
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.section_invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.text-normal {
|
||||
font-weight:100;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
.reset-flow {
|
||||
clear:both;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.separator {
|
||||
|
@ -86,20 +118,23 @@
|
|||
}
|
||||
|
||||
.flight_condition_VFR {
|
||||
background-color:forestgreen;
|
||||
color:white;
|
||||
background-color: forestgreen;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.flight_condition_MVFR {
|
||||
background-color:blue;
|
||||
color:white;
|
||||
background-color: blue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.flight_condition_IFR {
|
||||
background-color:crimson;
|
||||
color:white;
|
||||
background-color: crimson;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.flight_condition_LIFR {
|
||||
background-color:darkorchid;
|
||||
color:white;
|
||||
background-color: darkorchid;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.traffic-style1 {
|
||||
|
@ -129,16 +164,18 @@
|
|||
}
|
||||
|
||||
.bar_container {
|
||||
display:inline-block;
|
||||
border:1px solid #cccccc;
|
||||
display: inline-block;
|
||||
border: 1px solid #cccccc;
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
font-size: 0.75em;
|
||||
border-radius: 2px;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.bar_display {
|
||||
padding: 1px 2px 1px 3px;
|
||||
}
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
everything below this comment represents tweeks to the mobile-angular-uis CSS
|
||||
*************************************************************************** */
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 58 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 117 KiB |
|
@ -39,9 +39,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="css/addtohomescreen.css">
|
||||
<script src="js/addtohomescreen.min.js"></script>
|
||||
<script>
|
||||
addToHomescreen({
|
||||
displayPace: 480
|
||||
});
|
||||
addToHomescreen({ displayPace: 480 });
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="maui/css/mobile-angular-ui-base.min.css" />
|
||||
|
@ -57,12 +55,14 @@
|
|||
|
||||
<!-- TODO: combine and minify the following javascript -->
|
||||
<script src="js/main.js"></script>
|
||||
<script src="plates/js/gps.js"></script>
|
||||
<script src="plates/js/logs.js"></script>
|
||||
<script src="plates/js/settings.js"></script>
|
||||
<script src="plates/js/status.js"></script>
|
||||
<script src="plates/js/traffic.js"></script>
|
||||
<script src="plates/js/weather.js"></script>
|
||||
<script src="js/j3di-all.min.js"></script>
|
||||
<script src="plates/js/ahrs.js"></script>
|
||||
<script src="plates/js/gps.js"></script>
|
||||
</head>
|
||||
|
||||
<body ng-app="stratux" ng-controller="MainCtrl" ui-prevent-touchmove-defaults>
|
||||
|
|
Plik diff jest za duży
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,11 @@
|
|||
// application constants
|
||||
var URL_HOST_BASE = window.location.hostname;
|
||||
var URL_SETTINGS_GET = "http://" + URL_HOST_BASE + "/getSettings";
|
||||
var URL_SETTINGS_SET = "http://" + URL_HOST_BASE + "/setSettings";
|
||||
|
||||
|
||||
var URL_HOST_BASE = window.location.hostname;
|
||||
var URL_SETTINGS_GET = "http://" + URL_HOST_BASE + "/getSettings";
|
||||
var URL_SETTINGS_SET = "http://" + URL_HOST_BASE + "/setSettings";
|
||||
var URL_GPS_GET = "http://" + URL_HOST_BASE + "/getSituation";
|
||||
var URL_STATUS_WS = "ws://" + URL_HOST_BASE + "/status"
|
||||
var URL_TRAFFIC_WS = "ws://" + URL_HOST_BASE + "/traffic";
|
||||
var URL_WEATHER_WS = "ws://" + URL_HOST_BASE + "/weather";
|
||||
|
||||
// define the module with dependency on mobile-angular-ui
|
||||
//var app = angular.module('stratux', ['ngRoute', 'mobile-angular-ui', 'mobile-angular-ui.gestures', 'appControllers']);
|
||||
|
@ -13,12 +15,42 @@ var appControllers = angular.module('appControllers', []);
|
|||
|
||||
app.config(function ($stateProvider, $urlRouterProvider) {
|
||||
$stateProvider
|
||||
.state('home', { url: '/', templateUrl: 'plates/status.html', controller: 'StatusCtrl', reloadOnSearch: false })
|
||||
.state('weather', { url: '/weather', templateUrl: 'plates/weather.html', controller: 'WeatherCtrl', reloadOnSearch: false })
|
||||
.state('traffic', { url: '/traffic', templateUrl: 'plates/traffic.html', controller: 'TrafficCtrl', reloadOnSearch: false })
|
||||
.state('gps', { url: '/gps', templateUrl: 'plates/gps.html', controller: 'GPSCtrl', reloadOnSearch: false })
|
||||
.state('logs', { url: '/logs', templateUrl: 'plates/logs.html', controller: 'LogsCtrl', reloadOnSearch: false })
|
||||
.state('settings', { url: '/settings', templateUrl: 'plates/settings.html',controller: 'SettingsCtrl', reloadOnSearch: false });
|
||||
.state('home', {
|
||||
url: '/',
|
||||
templateUrl: 'plates/status.html',
|
||||
controller: 'StatusCtrl',
|
||||
reloadOnSearch: false
|
||||
})
|
||||
.state('weather', {
|
||||
url: '/weather',
|
||||
templateUrl: 'plates/weather.html',
|
||||
controller: 'WeatherCtrl',
|
||||
reloadOnSearch: false
|
||||
})
|
||||
.state('traffic', {
|
||||
url: '/traffic',
|
||||
templateUrl: 'plates/traffic.html',
|
||||
controller: 'TrafficCtrl',
|
||||
reloadOnSearch: false
|
||||
})
|
||||
.state('gps', {
|
||||
url: '/gps',
|
||||
templateUrl: 'plates/gps.html',
|
||||
controller: 'GPSCtrl',
|
||||
reloadOnSearch: false
|
||||
})
|
||||
.state('logs', {
|
||||
url: '/logs',
|
||||
templateUrl: 'plates/logs.html',
|
||||
controller: 'LogsCtrl',
|
||||
reloadOnSearch: false
|
||||
})
|
||||
.state('settings', {
|
||||
url: '/settings',
|
||||
templateUrl: 'plates/settings.html',
|
||||
controller: 'SettingsCtrl',
|
||||
reloadOnSearch: false
|
||||
});
|
||||
$urlRouterProvider.otherwise('/');
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<div class="section text-left help-page">
|
||||
<p>The <strong>GPS / AHRS</strong> page provides a view on the current status of GPS data and AHRS orientation. The Satellite count is located on the <strong>Status</strong> page.</p>
|
||||
<p>The <strong>GPS</strong> reports position with estimated accuracy, ground track, ground speed, and GPS derived altitude are displayed along with the location depicted on a world map.</p>
|
||||
<p>The <strong>AHRS</strong> reports magnetic heading, pressure altitude, pitch and roll are displayed along with a graphical representation of movement.</p>
|
||||
<p class="text-warning">NOTE: This page is for reference only and must not be used for flight operations.</p>
|
||||
</div>
|
|
@ -1,13 +1,66 @@
|
|||
<div class="list-group text-center">
|
||||
<div class="list-group-item list-group-item-home">
|
||||
<h2>GPS Status</h2>
|
||||
</div>
|
||||
<div class="list-group-item list-group-item-home">
|
||||
<div>
|
||||
<i class="fa fa-globe feature-icon text-primary"></i>
|
||||
</div>
|
||||
<div>
|
||||
this space reserved to display GPS/AHRS status
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><span class="panel_label">GPS</span></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<span class="col-xs-12">
|
||||
<div class="map-container">
|
||||
<div id="map_display" class="world-map" ng-attr-style="background-position:{{map_pos_x + 'px ' + map_pos_y + 'px'}}; width:{{map_width}}px; height:{{map_height}}px;">
|
||||
<div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px'}">
|
||||
<span class="fa fa-crosshairs icon-red"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="row">
|
||||
<strong class="col-xs-6 text-center">Location:</strong>
|
||||
<strong class="col-xs-6 text-center">Track:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="col-xs-6 text-center">{{gps_lat}}, {{gps_lon}} ± {{gps_accuracy}} m</span>
|
||||
<span class="col-xs-6 text-center">{{gps_track}}° @ {{gps_speed}}KTS @ {{gps_alt}} ft</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><span class="panel_label">AHRS</span></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<span class="col-xs-12">
|
||||
<canvas id="ahrs_display">
|
||||
your web browser doesn't support the <canvas>> element.
|
||||
</canvas>
|
||||
</span>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="row">
|
||||
<strong class="col-xs-3 text-center">Heading:</strong>
|
||||
<strong class="col-xs-3 text-center">Pitch:</strong>
|
||||
<strong class="col-xs-3 text-center">Roll:</strong>
|
||||
<strong class="col-xs-3 text-center">P-Alt:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="col-xs-3 text-center">{{ahrs_heading}}°</span>
|
||||
<span class="col-xs-3 text-center">{{ahrs_pitch}}°</span>
|
||||
<span class="col-xs-3 text-center">{{ahrs_roll}}°</span>
|
||||
<span class="col-xs-3 text-center">{{ahrs_alt}}°</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Raw GPS / AHRS Data</div>
|
||||
<div class="panel-body">
|
||||
<pre>{{raw_data}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
|
@ -0,0 +1,207 @@
|
|||
function ahrsRenderer(location_id) {
|
||||
this.gcontext = {}; // globals
|
||||
this.gl = null;
|
||||
|
||||
this.width = -1;
|
||||
this.height = -1;
|
||||
|
||||
this.locationID = location_id;
|
||||
this.canvas = document.getElementById(location_id);
|
||||
this.canvas_container = document.getElementById(location_id).parentElement;
|
||||
}
|
||||
|
||||
ahrsRenderer.prototype = {
|
||||
constructor: ahrsRenderer,
|
||||
|
||||
_init_canvas: function () {
|
||||
var gl = initWebGL(this.locationID);
|
||||
if (!gl)
|
||||
return;
|
||||
this.gl = gl;
|
||||
|
||||
vertex_shader = 'uniform mat4 u_modelViewProjMatrix; uniform mat4 u_normalMatrix; uniform vec3 lightDir; attribute vec3 vNormal; attribute vec4 vColor; attribute vec4 vPosition; varying float v_Dot; varying vec4 v_Color; void main() { gl_Position = u_modelViewProjMatrix * vPosition; v_Color = vColor; vec4 transNormal = u_normalMatrix * vec4(vNormal, 1); v_Dot = max(dot(transNormal.xyz, lightDir), 0.0); }';
|
||||
fragment_shader = 'precision mediump float; varying float v_Dot; varying vec4 v_Color; void main() { gl_FragColor = vec4(v_Color.xyz * v_Dot, v_Color.a * 0.95); }';
|
||||
|
||||
var vertexShader = loadShaderVertexScript(gl, vertex_shader);
|
||||
var fragmentShader = loadShaderFragmentScript(gl, fragment_shader);
|
||||
|
||||
var program = gl.createProgram();
|
||||
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
|
||||
// Bind attributes
|
||||
gl.bindAttribLocation(program, 0, "vNormal");
|
||||
gl.bindAttribLocation(program, 1, "vColor");
|
||||
gl.bindAttribLocation(program, 2, "vPosition");
|
||||
|
||||
gl.linkProgram(program);
|
||||
|
||||
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||
if (!linked && !gl.isContextLost()) {
|
||||
// something went wrong with the link
|
||||
var error = gl.getProgramInfoLog(program);
|
||||
log("Error in program linking:" + error);
|
||||
gl.deleteProgram(program);
|
||||
gl.deleteProgram(fragmentShader);
|
||||
gl.deleteProgram(vertexShader);
|
||||
} else {
|
||||
gl.useProgram(program);
|
||||
gl.clearColor(0, 0, 0, 0) // rgba for background color
|
||||
gl.clearDepth(10000); //??
|
||||
|
||||
if (false /* funcky blending */ ) {
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.depthFunc(gl.LESS);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
||||
} else {
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
this.gcontext.program = program;
|
||||
}
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._init_canvas(); // init the canvas
|
||||
g = this.gcontext;
|
||||
gl = this.gl;
|
||||
|
||||
if (gl === null)
|
||||
return;
|
||||
|
||||
// Set up a uniform variable for the shaders
|
||||
gl.uniform3f(gl.getUniformLocation(g.program, "lightDir"), 0, 1, -1);
|
||||
|
||||
// Create a box. On return 'gl' contains a 'box' property with
|
||||
// the BufferObjects containing the arrays for vertices,
|
||||
// normals, texture coords, and indices.
|
||||
// g.box = makeBox(gl);
|
||||
g.box = makePaperAirplane(gl);
|
||||
|
||||
// Create some matrices to use later and save their locations in the shaders
|
||||
g.mvMatrix = new J3DIMatrix4();
|
||||
g.u_normalMatrixLoc = gl.getUniformLocation(g.program, "u_normalMatrix");
|
||||
g.normalMatrix = new J3DIMatrix4();
|
||||
g.u_modelViewProjMatrixLoc =
|
||||
gl.getUniformLocation(g.program, "u_modelViewProjMatrix");
|
||||
g.mvpMatrix = new J3DIMatrix4();
|
||||
|
||||
// Enable all of the vertex attribute arrays.
|
||||
gl.enableVertexAttribArray(0);
|
||||
gl.enableVertexAttribArray(1);
|
||||
gl.enableVertexAttribArray(2);
|
||||
// Set up all the vertex attributes for vertices, normals and colors
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.vertexObject);
|
||||
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.normalObject);
|
||||
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.colorObject);
|
||||
gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
|
||||
|
||||
// Bind the index array
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, g.box.indexObject);
|
||||
|
||||
this.pitch = 0;
|
||||
this.roll = 0;
|
||||
this.heading = 0;
|
||||
|
||||
this.resize();
|
||||
},
|
||||
|
||||
resize: function () {
|
||||
gl = this.gl;
|
||||
g = this.gcontext;
|
||||
if (gl === null)
|
||||
return;
|
||||
|
||||
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;
|
||||
// Set the viewport and projection matrix for the scene
|
||||
gl.viewport(0, 0, this.width, this.height);
|
||||
g.perspectiveMatrix = new J3DIMatrix4();
|
||||
g.perspectiveMatrix.perspective(30, this.width / this.height, 1, 10000);
|
||||
g.perspectiveMatrix.lookat( 0, 0, 4, // eye location
|
||||
0, 0, 0, // focal point
|
||||
0, 1, 0); // up vector
|
||||
}
|
||||
},
|
||||
|
||||
orientation: function (x, y, z) {
|
||||
if (x > 360) x -= 360;
|
||||
if (y > 360) y -= 360;
|
||||
if (z > 360) z -= 360;
|
||||
this.pitch = x; // need to reorient to level
|
||||
this.roll = y;
|
||||
this.heading = z;
|
||||
},
|
||||
|
||||
animate: function (t, x, y, z) {
|
||||
var FPS = 24; // we assume we can maintain a certain frame rate
|
||||
var x_inc = ((x - this.pitch) / (FPS * t));
|
||||
var y_inc = ((y - this.roll) / (FPS * t));
|
||||
// let the animation wrap aroung gracefully
|
||||
if ((z < this.heading) && (this.heading - z) > 180)
|
||||
z += 360;
|
||||
var z_inc = ((z - this.heading) / (FPS * t));
|
||||
var _this = this;
|
||||
//console.log(z_inc);
|
||||
var frames = 0;
|
||||
var f = function () {
|
||||
_this.pitch += x_inc;
|
||||
_this.roll += y_inc;
|
||||
_this.heading += z_inc;
|
||||
if (frames < (FPS * t)) {
|
||||
_this.draw();
|
||||
frames++
|
||||
window.requestAnimationFrame(f, _this.canvas); // recurse
|
||||
} else {
|
||||
_this.orientation(x, y, z);
|
||||
}
|
||||
};
|
||||
f();
|
||||
},
|
||||
|
||||
draw: function () {
|
||||
this.resize();
|
||||
gl = this.gl;
|
||||
g = this.gcontext;
|
||||
if (gl === null)
|
||||
return;
|
||||
|
||||
// Clear the canvas
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
// Make a model/view matrix.
|
||||
g.mvMatrix.makeIdentity();
|
||||
|
||||
g.mvMatrix.rotate(15, 1, 0, 0); // adjust viewing angle slightly by pitching the airplane up
|
||||
|
||||
g.mvMatrix.rotate(-this.pitch, 1, 0, 0);
|
||||
g.mvMatrix.rotate(-this.roll, 0, 0, 1);
|
||||
g.mvMatrix.rotate(-this.heading, 0, 1, 0);
|
||||
|
||||
// Construct the normal matrix from the model-view matrix and pass it in
|
||||
g.normalMatrix.load(g.mvMatrix);
|
||||
g.normalMatrix.invert();
|
||||
g.normalMatrix.transpose();
|
||||
g.normalMatrix.setUniform(gl, g.u_normalMatrixLoc, false);
|
||||
|
||||
// Construct the model-view * projection matrix and pass it in
|
||||
g.mvpMatrix.load(g.perspectiveMatrix);
|
||||
g.mvpMatrix.multiply(g.mvMatrix);
|
||||
g.mvpMatrix.setUniform(gl, g.u_modelViewProjMatrixLoc, false);
|
||||
|
||||
// Draw the object
|
||||
gl.drawElements(gl.TRIANGLES, g.box.numIndices, gl.UNSIGNED_BYTE, 0);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,125 @@
|
|||
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set
|
||||
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http']; // Inject my dependencies
|
||||
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
|
||||
|
||||
// create our controller function with all necessary logic
|
||||
function GPSCtrl($rootScope, $scope, $state, $http) {
|
||||
function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
|
||||
$scope.$parent.helppage = 'plates/gps-help.html';
|
||||
|
||||
/*
|
||||
$state.get('weather').onEnter = function () {
|
||||
};
|
||||
$state.get('weather').onExit = function () {
|
||||
};
|
||||
*/
|
||||
var status = {};
|
||||
var display_area_size = -1;
|
||||
|
||||
function sizeMap() {
|
||||
var width = 0;
|
||||
var el = document.getElementById("map_display").parentElement;
|
||||
width = el.offsetWidth; // was (- (2 * el.offsetLeft))
|
||||
if (width !== display_area_size) {
|
||||
display_area_size = width;
|
||||
$scope.map_width = width;
|
||||
$scope.map_height = width *0.5;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
function setGeoReferenceMap(la, lo) {
|
||||
// Mercator projection
|
||||
// var map = "img/world.png";
|
||||
var map_width = 3929;
|
||||
var map_height = 2184;
|
||||
var map_zero_x = 1868;
|
||||
var map_zero_y = 1412;
|
||||
var font_size = 18; // size of font used for marker
|
||||
|
||||
sizeMap();
|
||||
var div_width = $scope.map_width;
|
||||
var div_height = $scope.map_height;
|
||||
|
||||
|
||||
// longitude: just scale and shift
|
||||
var x = (map_width * (180 + lo) / 360) - (map_width/2 - map_zero_x); // longitude_shift;
|
||||
|
||||
// latitude: using the Mercator projection
|
||||
la_rad = la * Math.PI / 180; // convert from degrees to radians
|
||||
merc_n = Math.log(Math.tan((la_rad / 2) + (Math.PI / 4))); // do the Mercator projection (w/ equator of 2pi units)
|
||||
var y = (map_height / 2) - (map_width * merc_n / (2 * Math.PI)) - (map_height/2 - map_zero_y); // fit it to our map
|
||||
|
||||
// dot = '<div style="position:absolute; width:' + dot_size + 'px; height:' + dot_size + 'px; top:' + y + 'px; left:' + x + 'px; background:#ff7f00;"></div>';
|
||||
// <img src="map-world-medium.png" style="position:absolute;top:0px;left:0px">
|
||||
$scope.map_pos_x = map_width - Math.round(x - (div_width / 2));
|
||||
$scope.map_pos_y = map_height - Math.round(y - (div_height / 2));
|
||||
|
||||
$scope.map_mark_x = Math.round((div_width - (font_size * 0.85)) / 2);
|
||||
$scope.map_mark_y = Math.round((div_height - font_size) / 2);
|
||||
};
|
||||
|
||||
|
||||
function loadStatus(data) {
|
||||
status = angular.fromJson(data);
|
||||
// consider using angular.extend()
|
||||
$scope.raw_data = angular.toJson(data, true); // makes it pretty
|
||||
|
||||
/* not currently used
|
||||
$scope.gps_satellites = status.Satellites;
|
||||
*/
|
||||
$scope.gps_accuracy = Math.round(status.Accuracy);
|
||||
|
||||
// NACp should be an integer value in the range of 0 .. 11
|
||||
// var accuracies = ["≥ 10 NM", "< 10 NM", "< 4 NM", "< 2 NM", "< 1 NM", "< 0.5 NM", "< 0.3 NM", "< 0.1 NM", "< 100 m", "< 30 m", "< 10 m", "< 3 m"];
|
||||
// $scope.gps_accuracy = accuracies[status.NACp];
|
||||
// "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z"
|
||||
|
||||
$scope.gps_lat = status.Lat.toPrecision(6); // result is string
|
||||
$scope.gps_lon = status.Lng.toPrecision(6); // result is string
|
||||
$scope.gps_alt = Math.round(status.Alt);
|
||||
$scope.gps_track = status.TrueCourse;
|
||||
$scope.gps_speed = status.GroundSpeed;
|
||||
// "LastGroundTrackTime":"0001-01-01T00:00:00Z"
|
||||
|
||||
/* not currently used
|
||||
$scope.ahrs_temp = status.Temp;
|
||||
*/
|
||||
$scope.ahrs_alt = Math.round(status.Pressure_alt);
|
||||
|
||||
$scope.ahrs_heading = Math.round(status.Gyro_heading);
|
||||
// pitch and roll are in degrees
|
||||
$scope.ahrs_pitch = Math.round(status.Pitch);
|
||||
$scope.ahrs_roll = Math.round(status.Roll);
|
||||
// "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z"
|
||||
|
||||
setGeoReferenceMap(status.Lat, status.Lng);
|
||||
|
||||
// $scope.$apply();
|
||||
};
|
||||
|
||||
function getStatus() {
|
||||
// Simple GET request example (note: responce is asynchronous)
|
||||
$http.get(URL_GPS_GET).
|
||||
then(function (response) {
|
||||
loadStatus(response.data);
|
||||
ahrs.animate(1, $scope.ahrs_pitch, $scope.ahrs_roll, $scope.ahrs_heading);
|
||||
// $scope.$apply();
|
||||
}, function (response) {
|
||||
$scope.raw_data = "error getting gps / ahrs status";
|
||||
});
|
||||
};
|
||||
|
||||
var updateStatus = $interval(function () {
|
||||
// refresh GPS/AHRS status once each second (aka polling)
|
||||
getStatus();
|
||||
}, (1 * 1000), 0, false);
|
||||
|
||||
$state.get('gps').onEnter = function () {
|
||||
// everything gets handled correctly by the controller
|
||||
};
|
||||
|
||||
$state.get('gps').onExit = function () {
|
||||
// stop polling for gps/ahrs status
|
||||
$interval.cancel(updateStatus);
|
||||
};
|
||||
|
||||
|
||||
// GPS/AHRS Controller tasks go here
|
||||
var ahrs = new ahrsRenderer("ahrs_display");
|
||||
ahrs.init();
|
||||
ahrs.orientation(0, 0, 0);
|
||||
|
||||
// Weather Controller tasks go here
|
||||
};
|
|
@ -11,7 +11,7 @@ function StatusCtrl($rootScope, $scope, $state, $http) {
|
|||
return; // we are getting called once after clicking away from the status page
|
||||
|
||||
if (($scope.socket === undefined) || ($scope.socket === null)) {
|
||||
socket = new WebSocket('ws://' + URL_HOST_BASE + '/status');
|
||||
socket = new WebSocket(URL_STATUS_WS);
|
||||
$scope.socket = socket; // store socket in scope for enter/exit usage
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
return; // we are getting called once after clicking away from the status page
|
||||
|
||||
if (($scope.socket === undefined) || ($scope.socket === null)) {
|
||||
socket = new WebSocket('ws://' + URL_HOST_BASE + '/traffic');
|
||||
socket = new WebSocket(URL_TRAFFIC_WS);
|
||||
$scope.socket = socket; // store socket in scope for enter/exit usage
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ function WeatherCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
return; // we are getting called once after clicking away from the status page
|
||||
|
||||
if (($scope.socket === undefined) || ($scope.socket === null)) {
|
||||
socket = new WebSocket('ws://' + URL_HOST_BASE + '/weather');
|
||||
socket = new WebSocket(URL_WEATHER_WS);
|
||||
$scope.socket = socket; // store socket in scope for enter/exit usage
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
</div>
|
||||
|
||||
<!--
|
||||
ssh<div class="col-sm-12">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Raw Configuration</div>
|
||||
<div class="panel-body">
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
<div class="row" ng-class="{'section_invisible': !visible_uat}">
|
||||
<span class="col-xs-1"></span>
|
||||
<label class="col-xs-3">UAT:</label>
|
||||
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style2" ng-attr-style="width:{{100*UAT_messages_last_minute / UAT_messages_max}}%">{{UAT_messages_last_minute}}</div></div></span>
|
||||
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style2" ng-attr-style="width:{{UAT_messages_max ? 100*UAT_messages_last_minute / UAT_messages_max : 0}}%">{{UAT_messages_last_minute}}</div></div></span>
|
||||
<span class="col-xs-2 text-right">{{UAT_messages_max}}</span>
|
||||
</div>
|
||||
<div class="row" ng-class="{'section_invisible': !visible_es}">
|
||||
<span class="col-xs-1"></span>
|
||||
<label class="col-xs-3">1090ES:</label>
|
||||
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style1" ng-attr-style="width:{{100*ES_messages_last_minute / ES_messages_max}}%;">{{ES_messages_last_minute}}</div></div></span>
|
||||
<span class="col-xs-6"><div class="bar_container"><div class="bar_display traffic-style1" ng-attr-style="width:{{ES_messages_max ? 100*ES_messages_last_minute / ES_messages_max : 0}}%;">{{ES_messages_last_minute}}</div></div></span>
|
||||
<span class="col-xs-2 text-right">{{ES_messages_max}}</span>
|
||||
</div>
|
||||
<!--
|
||||
|
|
Ładowanie…
Reference in New Issue