Merge pull request #751 from westphae/ahrs_warnings

AHRS Warnings and disable AHRS output when GPS not available, fixes #732.
pull/755/head
cyoung 2018-10-01 13:59:51 -04:00 zatwierdzone przez GitHub
commit 1756f77433
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
8 zmienionych plików z 180 dodań i 145 usunięć

Wyświetl plik

@ -1932,7 +1932,6 @@ func makeAHRSGDL90Report() {
palt := uint16(0xFFFF) palt := uint16(0xFFFF)
vs := int16(0x7FFF) vs := int16(0x7FFF)
if isAHRSValid() { if isAHRSValid() {
// AHRS invalid magic number is ahrs.Invalid.
if !isAHRSInvalidValue(mySituation.AHRSPitch) { if !isAHRSInvalidValue(mySituation.AHRSPitch) {
pitch = roundToInt16(mySituation.AHRSPitch * 10) pitch = roundToInt16(mySituation.AHRSPitch * 10)
} }
@ -2101,7 +2100,9 @@ func isGPSClockValid() bool {
} }
func isAHRSValid() bool { func isAHRSValid() bool {
return stratuxClock.Since(mySituation.AHRSLastAttitudeTime) < 1*time.Second // If attitude information gets to be over 1 second old, declare invalid. // If attitude information gets to be over 1 second old, declare invalid.
// If no GPS then we won't use or send attitude information.
return isGPSGroundTrackValid() && stratuxClock.Since(mySituation.AHRSLastAttitudeTime) < 1*time.Second
} }
func isTempPressValid() bool { func isTempPressValid() bool {

Wyświetl plik

@ -6,15 +6,16 @@
height: 100%; height: 100%;
background-color: #ABFF00; background-color: #ABFF00;
border-radius: 10%; border-radius: 10%;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px;
} }
.indicator.off { .indicator.off {
background-color: #F00; background-color: #F00;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #472001 0 -1px 9px, #FF4900 0 2px 12px;
} }
.indicator.on { .indicator.on {
background-color: #ABFF00; background-color: #ABFF00;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px;
} }
.indicator.blink { .indicator.blink {
@ -151,10 +152,10 @@
stroke-width: 2px; stroke-width: 2px;
} }
.error .errText { .msgText {
font-size: 16px; font-size: 16px;
font-family: sans-serif; font-family: sans-serif;
text-anchor: central; text-anchor: middle;
alignment-baseline: middle; alignment-baseline: middle;
stroke-width: 0px; stroke-width: 0px;
fill: red; fill: red;

Wyświetl plik

@ -1,35 +1,11 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="col-sm-6 hider">
<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; opacity:{{map_opacity}};">
<div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px', opacity: map_mark_opacity}">
<span class="fa fa-crosshairs"></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}} &plusmn; {{gps_horizontal_accuracy}} m <br>
{{gps_alt}} &plusmn; {{gps_vertical_accuracy}} ft @ {{gps_vert_speed}} ft/min</span>
<span class="col-xs-6 text-center">{{gps_track}}&deg; @ {{gps_speed}} KTS</span>
</div>
</div>
</div>
</div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><span ng-click="hideClick()" class="panel_label">AHRS</span></div> <div class="panel-heading">
<span ng-click="hideClick()" class="panel_label">AHRS</span>
<span ng-show="ConnectState == 'Connected'" class="label label-success">{{ConnectState}}</span>
<span ng-hide="ConnectState == 'Connected'" class="label label-danger">{{ConnectState}}</span>
</div>
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<span class="col-xs-12"> <span class="col-xs-12">
@ -48,7 +24,10 @@
<div class="col-xs-12"> <div class="col-xs-12">
<div class="separator"></div> <div class="separator"></div>
<div class="col-xs-3"> <div class="col-xs-3">
<a ng-click="AHRSCage()" class="btn btn-primary" ng-disabled="IsCaging()">Reset /<br>Level</a> <button class="btn btn-primary btn-block" ng-click="AHRSCage()"
ng-disabled="IsCaging || !IMU_Sensor_Enabled">Set Level</button>
<button class="btn btn-primary btn-block" ng-click="AHRSCalibrate()"
ng-disabled="IsCaging || !IMU_Sensor_Enabled">Zero Drift</button>
</div> </div>
<div class="col-xs-9"> <div class="col-xs-9">
<div class="row"> <div class="row">
@ -80,6 +59,36 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6 hider">
<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; opacity:{{map_opacity}};">
<div class="mark-position" ng-style="{left: map_mark_x+'px', top: map_mark_y+'px', opacity: map_mark_opacity}">
<span class="fa fa-crosshairs"></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}} &plusmn; {{gps_horizontal_accuracy}} m <br>
{{gps_alt}} &plusmn; {{gps_vertical_accuracy}} ft @ {{gps_vert_speed}} ft/min</span>
<span class="col-xs-6 text-center">{{gps_track}}&deg; @ {{gps_speed}} KTS</span>
</div>
</div>
</div>
</div>
</div> </div>
<div class="col-sm-12"> <div class="col-sm-12">
<div class="col-sm-6 hider"> <div class="col-sm-6 hider">

Wyświetl plik

@ -12,6 +12,7 @@ function AHRSRenderer(locationId) {
this.heading = 0; this.heading = 0;
this.slipSkid = 0; this.slipSkid = 0;
this.altitude = 0; this.altitude = 0;
this.messages = [];
var display = SVG(this.locationId).viewbox(-200, -200, 400, 400).group(); var display = SVG(this.locationId).viewbox(-200, -200, 400, 400).group();
@ -86,9 +87,11 @@ function AHRSRenderer(locationId) {
this.err.rect(400, 400).cx(0).cy(0); this.err.rect(400, 400).cx(0).cy(0);
this.err.line(-200, -200, 200, +200); this.err.line(-200, -200, 200, +200);
this.err.line(-200, +200, 200, -200); this.err.line(-200, +200, 200, -200);
this.errText = this.err.text("").cx(0).cy(0).addClass('errText');
var tb = this.errText.bbox(); this.message = display.group().cy(-85);
this.errTextBg = this.err.rect(tb.x, tb.y, tb.w, tb.h).stroke({'width': 1}).after(this.errText); this.msgText = this.message.text("").addClass('msgText').build(true);
var tb = this.msgText.bbox();
this.msgTextBg = this.message.rect(tb.x, tb.y, tb.w, tb.h).stroke({'width': 1}).after(this.msgText);
} }
AHRSRenderer.prototype = { AHRSRenderer.prototype = {
@ -117,6 +120,23 @@ AHRSRenderer.prototype = {
this.slipSkid = +10; this.slipSkid = +10;
} }
if (this.messages.length > 0) {
this.message.hide();
this.msgText.clear();
var msgs = this.messages;
this.msgText.text(function (add) {
for (var i = 0; i < msgs.length; i++) {
add.tspan(msgs[i]).center(0, 20 * i).newLine();
}
});
var tb = this.msgText.bbox();
this.msgTextBg.attr({x: tb.x - 3, y: tb.y - 2, width: tb.w + 6, height: tb.h + 4});
this.message.show();
} else {
this.message.hide();
this.msgText.clear();
}
this.pitchClip.translate(0, -10 * this.pitch * this.pitchScale); this.pitchClip.translate(0, -10 * this.pitch * this.pitchScale);
this.rollClip.rotate(this.roll, 0, 0); this.rollClip.rotate(this.roll, 0, 0);
this.card.rotate(0, 0, 0).translate(0, 10 * this.pitch * this.pitchScale); this.card.rotate(0, 0, 0).translate(0, 10 * this.pitch * this.pitchScale);
@ -129,13 +149,11 @@ AHRSRenderer.prototype = {
turn_on: function () { turn_on: function () {
this.err.hide(); this.err.hide();
this.ai.show(); this.ai.show();
this.errText.clear(); this.update(this.pitch, this.roll, this.heading, this.slipSkid);
}, },
turn_off: function(message) { turn_off: function () {
this.errText.text(message).center(0, 0); this.update(this.pitch, this.roll, this.heading, this.slipSkid);
var tb = this.errText.bbox();
this.errTextBg.attr({'x': tb.x, 'y': tb.y, 'width': tb.w, 'height': tb.h});
this.ai.hide(); this.ai.hide();
this.err.show(); this.err.show();
} }

Wyświetl plik

@ -1,6 +1,11 @@
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module controllers set angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module controllers set
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
const MSG_GROUND_TEST = ["GROUND TEST MODE - GPS REQUIRED", "DO NOT USE IN FLIGHT WITHOUT GPS"],
MSG_LEVELING = ["\n", "CALIBRATING", "FLY STRAIGHT AND DO NOT MOVE SENSOR"],
MSG_PSEUDO_AHRS = ["WARNING - USING GPS PSEUDO AHRS", "CONNECT AN AHRS BOARD TO USE TRUE AHRS"],
MSG_NO_AHRS = ["NO AHRS AVAILABLE", "MUST HAVE IMU AND/OR GPS FOR AHRS"];
// create our controller function with all necessary logic // create our controller function with all necessary logic
function GPSCtrl($rootScope, $scope, $state, $http, $interval) { function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.$parent.helppage = 'plates/gps-help.html'; $scope.$parent.helppage = 'plates/gps-help.html';
@ -116,14 +121,28 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.SolutionText = solutionText; $scope.SolutionText = solutionText;
$scope.gps_horizontal_accuracy = situation.GPSHorizontalAccuracy.toFixed(1); $scope.gps_horizontal_accuracy = situation.GPSHorizontalAccuracy.toFixed(1);
var msg_ix = ahrs.messages.indexOf(MSG_GROUND_TEST[0]);
if (msg_ix < 0 && $scope.IMU_Sensor_Enabled && $scope.gps_horizontal_accuracy >= 30) {
ahrs.messages = ahrs.messages.concat(MSG_GROUND_TEST);
} else if (msg_ix >= 0 && $scope.gps_horizontal_accuracy < 30) {
ahrs.messages.splice(msg_ix, MSG_GROUND_TEST.length);
}
var msg_ix = ahrs.messages.indexOf(MSG_NO_AHRS[0]);
if (msg_ix < 0 && !$scope.IMU_Sensor_Enabled && $scope.gps_horizontal_accuracy >= 30) {
ahrs.messages = ahrs.messages.concat(MSG_NO_AHRS);
ahrs.turn_off();
} else if (msg_ix >= 0 && ($scope.IMU_Sensor_Enabled || $scope.gps_horizontal_accuracy < 30)) {
ahrs.messages.splice(msg_ix, MSG_NO_AHRS.length);
ahrs.turn_on();
}
if ($scope.gps_horizontal_accuracy > 19999) { if ($scope.gps_horizontal_accuracy > 19999) {
$scope.gps_horizontal_accuracy = "\u221e"; $scope.gps_horizontal_accuracy = "\u221e";
$scope.gps_lat = "--"; $scope.gps_lat = "--";
$scope.gps_lon = "--"; $scope.gps_lon = "--";
$scope.gps_alt = "--";
$scope.gps_track = "--"; $scope.gps_track = "--";
$scope.gps_speed = "--"; $scope.gps_speed = "--";
$scope.gps_vert_speed = "--";
$scope.map_opacity = 0.2; $scope.map_opacity = 0.2;
$scope.map_mark_opacity = 0; $scope.map_mark_opacity = 0;
} else { } else {
@ -133,6 +152,8 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.gps_vertical_accuracy = (situation.GPSVerticalAccuracy*3.2808).toFixed(1); // accuracy is in meters, need to display in ft $scope.gps_vertical_accuracy = (situation.GPSVerticalAccuracy*3.2808).toFixed(1); // accuracy is in meters, need to display in ft
if ($scope.gps_vertical_accuracy > 9999) { if ($scope.gps_vertical_accuracy > 9999) {
$scope.gps_vertical_accuracy = "\u221e"; $scope.gps_vertical_accuracy = "\u221e";
$scope.gps_alt = "--";
$scope.gps_vert_speed = "--";
} }
@ -199,7 +220,7 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.ahrs_gload = situation.AHRSGLoad.toFixed(2); $scope.ahrs_gload = situation.AHRSGLoad.toFixed(2);
if ($scope.ahrs_gload > 360) { if ($scope.ahrs_gload > 360) {
$scope.ahrs_gload = "--"; $scope.ahrs_gload = "--";
} else { } else if (gMeter !== undefined) {
gMeter.update(situation.AHRSGLoad, situation.AHRSGLoadMin, situation.AHRSGLoadMax); gMeter.update(situation.AHRSGLoad, situation.AHRSGLoadMin, situation.AHRSGLoadMax);
} }
@ -241,6 +262,17 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
statusBMP.classList.add("off"); statusBMP.classList.add("off");
statusBMP.classList.remove("on"); statusBMP.classList.remove("on");
} }
if (situation.AHRSStatus & 0x08) {
statusCal.classList.add("blink");
statusCal.classList.remove("on");
statusCal.innerText = "Caging";
$scope.IsCaging = true;
} else {
statusCal.classList.remove("blink");
statusCal.classList.add("on");
statusCal.innerText = "Ready";
$scope.IsCaging = false;
}
if (situation.AHRSStatus & 0x10) { if (situation.AHRSStatus & 0x10) {
statusLog.classList.remove("off"); statusLog.classList.remove("off");
statusLog.classList.add("on"); statusLog.classList.add("on");
@ -248,16 +280,23 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
statusLog.classList.add("off"); statusLog.classList.add("off");
statusLog.classList.remove("on"); statusLog.classList.remove("on");
} }
if (situation.AHRSStatus & 0x08) {
statusCal.classList.add("blink"); msg_ix = ahrs.messages.indexOf(MSG_LEVELING[0]);
statusCal.classList.remove("on"); if (msg_ix < 0 && $scope.IsCaging) {
statusCal.innerText = "Caging"; ahrs.messages = ahrs.messages.concat(MSG_LEVELING);
} else { ahrs.turn_off();
statusCal.classList.remove("blink"); } else if (msg_ix >= 0 && !$scope.IsCaging) {
statusCal.classList.add("on"); ahrs.messages.splice(msg_ix, MSG_LEVELING.length);
statusCal.innerText = "Ready"; ahrs.turn_on();
}
$scope.IsPseudoAHRS = (!$scope.IMU_Sensor_Enabled && $scope.gps_horizontal_accuracy < 30);
msg_ix = ahrs.messages.indexOf(MSG_PSEUDO_AHRS[0]);
if (msg_ix < 0 && $scope.IsPseudoAHRS) {
ahrs.messages = ahrs.messages.concat(MSG_PSEUDO_AHRS);
} else if (msg_ix >= 0 && !$scope.IsPseudoAHRS) {
ahrs.messages.splice(msg_ix, MSG_PSEUDO_AHRS.length);
} }
// "LastAttitudeTime":"2015-10-11T16:47:03.534615187Z"
setGeoReferenceMap(situation.GPSLatitude, situation.GPSLongitude); setGeoReferenceMap(situation.GPSLatitude, situation.GPSLongitude);
} }
@ -342,6 +381,7 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
// GPS/AHRS Controller tasks go here // GPS/AHRS Controller tasks go here
var ahrs = new AHRSRenderer("ahrs_display"); var ahrs = new AHRSRenderer("ahrs_display");
ahrs.turn_on();
$scope.hideClick = function() { $scope.hideClick = function() {
$scope.isHidden = !$scope.isHidden; $scope.isHidden = !$scope.isHidden;
@ -360,23 +400,27 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
}; };
$scope.AHRSCage = function() { $scope.AHRSCage = function() {
if (!$scope.IsCaging()) { if (!$scope.IsCaging) {
$http.post(URL_AHRS_CAGE).then(function (response) { $http.post(URL_AHRS_CAGE).then(function (response) {
// do nothing
}, function (response) { }, function (response) {
// do nothing ahrs.messages = ahrs.messages.concat(response.data);
window.setTimeout(function() {
ahrs.messages.splice(ahrs.messages.indexOf(response.data), 1);
}, 1000);
}); });
} }
}; };
$scope.IsCaging = function() { $scope.AHRSCalibrate = function() {
var caging = statusCal.innerText === "Caging"; if (!$scope.IsCaging) {
if (caging) { $http.post(URL_AHRS_CAL).then(function (response) {
ahrs.turn_off("Calibrating. Fly straight and do not move sensor."); }, function (response) {
} else { ahrs.messages = ahrs.messages.concat(response.data);
ahrs.turn_on(); window.setTimeout(function() {
ahrs.messages.splice(ahrs.messages.indexOf(response.data), 1);
}, 1000);
});
} }
return caging;
}; };
$scope.GMeterReset = function() { $scope.GMeterReset = function() {
@ -392,6 +436,7 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) {
$http.get(URL_SETTINGS_GET). $http.get(URL_SETTINGS_GET).
then(function (response) { then(function (response) {
settings = angular.fromJson(response.data); settings = angular.fromJson(response.data);
$scope.IMU_Sensor_Enabled = settings.IMU_Sensor_Enabled;
if (settings.GLimits === "" || settings.GLimits === undefined) { if (settings.GLimits === "" || settings.GLimits === undefined) {
settings.GLimits = "-1.76 4.4"; settings.GLimits = "-1.76 4.4";
} }

Wyświetl plik

@ -257,18 +257,6 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
}); });
}; };
$scope.calibrateGyros = function() {
console.log("sending calibrate message.");
$http.post(URL_AHRS_CAL).then(function (response) {
console.log("Sent calibrate message.");
}, function (response) {
console.log(response.data);
$scope.Calibration_Failure_Message = response.data;
$scope.Ui.turnOff("modalCalibrateGyros");
$scope.Ui.turnOn("modalCalibrateGyrosFailed");
});
};
$scope.updateWiFi = function(action) { $scope.updateWiFi = function(action) {
$scope.WiFiErrors = { $scope.WiFiErrors = {
'WiFiSSID': '', 'WiFiSSID': '',

Wyświetl plik

@ -49,8 +49,10 @@ function TowersCtrl($rootScope, $scope, $state, $http, $interval) {
// Simple GET request example (note: responce is asynchronous) // Simple GET request example (note: responce is asynchronous)
$http.get(URL_TOWERS_GET). $http.get(URL_TOWERS_GET).
then(function (response) { then(function (response) {
$scope.ConnectState = "Connected";
loadTowers(response.data); loadTowers(response.data);
}, function (response) { }, function (response) {
$scope.ConnectState = "Disconnected";
$scope.raw_data = "error getting tower data"; $scope.raw_data = "error getting tower data";
}); });
}; };
@ -68,4 +70,4 @@ function TowersCtrl($rootScope, $scope, $state, $http, $interval) {
// stop any interval functions // stop any interval functions
$interval.cancel(updateTowers); $interval.cancel(updateTowers);
}; };
}; }

Wyświetl plik

@ -12,12 +12,6 @@
ng-disabled="!IMU_Sensor_Enabled">Set AHRS Sensor Orientation</button> ng-disabled="!IMU_Sensor_Enabled">Set AHRS Sensor Orientation</button>
</span> </span>
</div> </div>
<div class="form-group reset-flow">
<div class="col-xs-12">
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateGyros"
ng-disabled="!IMU_Sensor_Enabled">Calibrate Gyros</button>
</div>
</div>
<div class="form-group reset-flow"> <div class="form-group reset-flow">
<label class="control-label col-xs-3">G Limits</label> <label class="control-label col-xs-3">G Limits</label>
<form name="GLimitForm" ng-submit="updateGLimits()" novalidate> <form name="GLimitForm" ng-submit="updateGLimits()" novalidate>
@ -374,29 +368,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Gyro Calibration Modal -->
<div class="modal" ui-if="modalCalibrateGyros" ui-state="modalCalibrateGyros">
<div class="modal-overlay "></div>
<div class="vertical-alignment-helper center-block">
<div class="modal-dialog vertical-align-center">
<div class="modal-content">
<div class="modal-header">
<button class="close" ui-turn-off="modalCalibrateGyros"></button>
<h4 class="modal-title">Calibrate MPU Gyros</h4>
</div>
<div class="modal-body">
<p>Press <b>Calibrate</b> and keep the Stratux as stationary as possible for the next second.
You should only do this in calm air as turbulence will throw off the calibrations.</p>
</div>
<div class="modal-footer">
<a ui-turn-off="modalCalibrateGyros" class="btn btn-default">Cancel</a>
<a ng-click="calibrateGyros()" ui-turn-off="modalCalibrateGyros"
class="btn btn-default btn-primary">Calibrate</a>
</div>
</div>
</div>
</div>
</div>
<!-- WiFi Success Modal --> <!-- WiFi Success Modal -->
<div class="modal" ui-if="modalSuccessWiFi" ui-state="modalSuccessWiFi" id="WiFiSuccessModal"> <div class="modal" ui-if="modalSuccessWiFi" ui-state="modalSuccessWiFi" id="WiFiSuccessModal">
<div class="modal-overlay "></div> <div class="modal-overlay "></div>