mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-24 00:35:20 +03:00
Init
This commit is contained in:
parent
25a73085ab
commit
e1195dd0ee
11 changed files with 770 additions and 182 deletions
|
@ -3241,6 +3241,52 @@
|
||||||
"fixedWingNavigationConfiguration": {
|
"fixedWingNavigationConfiguration": {
|
||||||
"message": "Fixed Wing Navigation Settings"
|
"message": "Fixed Wing Navigation Settings"
|
||||||
},
|
},
|
||||||
|
"fixedWingLandingConfiguration": {
|
||||||
|
"message": "Fixed Wing Landing Settings"
|
||||||
|
},
|
||||||
|
|
||||||
|
"fwLandApproachLength" : {
|
||||||
|
"message": "Final approach length"
|
||||||
|
},
|
||||||
|
"fwLandApproachLengthHelp": {
|
||||||
|
"message": "Length of the final approach, also includes the glide and intercept phase. This is the length from the safe home point to the final turn point."
|
||||||
|
},
|
||||||
|
"fwLandFinalApproachPitch2throttle": {
|
||||||
|
"message": "Modifier for pitch to throttle ratio at final approach"
|
||||||
|
},
|
||||||
|
"fwLandFinalApproachPitch2throttleHelp": {
|
||||||
|
"message": "This value is multiplied by the \"pitch to throttle ratio\" value during the final approach. Allows the velocity to be reduced."
|
||||||
|
},
|
||||||
|
"fwLandGlideAlt" : {
|
||||||
|
"message": "Initial altitude of the glide phase"
|
||||||
|
},
|
||||||
|
"fwLandGlideAltHelp" : {
|
||||||
|
"message": "At this altitude (measured from the altitude of the landing point) the engine is switched off and the aircraft glides from here."
|
||||||
|
},
|
||||||
|
"fwLandFlareAlt" : {
|
||||||
|
"message": "Initial altitude of the flare phase"
|
||||||
|
},
|
||||||
|
"fwLandFlareAltHelp" : {
|
||||||
|
"message": "At this altitude (measured from the altitude of the landing point) the last phase of landing is executed."
|
||||||
|
},
|
||||||
|
"fwLandGlidePitch" : {
|
||||||
|
"message": "Pitch value for glide phase"
|
||||||
|
},
|
||||||
|
"fwLandGlidePitchHelp" : {
|
||||||
|
"message": "This pitch angle is held during the glide phase."
|
||||||
|
},
|
||||||
|
"fwLandFlarePitch" : {
|
||||||
|
"message": "Pitch value for flare phase"
|
||||||
|
},
|
||||||
|
"fwLandFlarePitchHelp" : {
|
||||||
|
"message": "This pitch angle is held during the flare phase."
|
||||||
|
},
|
||||||
|
"fwLandMaxTailwind": {
|
||||||
|
"message": "Max. tailwind"
|
||||||
|
},
|
||||||
|
"fwLandMaxTailwindHelp": {
|
||||||
|
"message": "This value is used when no headwind landing is possible and wind speeds below this value are ignored (inaccuracies in INAV wind measurement)."
|
||||||
|
},
|
||||||
"osd_unsupported_msg1": {
|
"osd_unsupported_msg1": {
|
||||||
"message" : "Your flight controller isn't responding to OSD commands. This probably means that it does not have an integrated OSD."
|
"message" : "Your flight controller isn't responding to OSD commands. This probably means that it does not have an integrated OSD."
|
||||||
},
|
},
|
||||||
|
@ -4072,6 +4118,12 @@
|
||||||
"missionSafehomeHead": {
|
"missionSafehomeHead": {
|
||||||
"message": "Safe Home manager"
|
"message": "Safe Home manager"
|
||||||
},
|
},
|
||||||
|
"missionSafehomeAvailableSafehomes" : {
|
||||||
|
"message": "Available Safehomes:"
|
||||||
|
},
|
||||||
|
"missionSafehomeMaxSafehomesReached": {
|
||||||
|
"message": "Maximum number of safehomes reached."
|
||||||
|
},
|
||||||
"missionMultiMissionHead": {
|
"missionMultiMissionHead": {
|
||||||
"message": "Multi Missions"
|
"message": "Multi Missions"
|
||||||
},
|
},
|
||||||
|
|
|
@ -274,7 +274,7 @@ gulp.task('apps', gulp.series('dist', function(done) {
|
||||||
version: get_nw_version(),
|
version: get_nw_version(),
|
||||||
zip: false
|
zip: false
|
||||||
});
|
});
|
||||||
builder.on('log', console.log);
|
//builder.on('log', console.log);
|
||||||
builder.build(function (err) {
|
builder.build(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("Error building NW apps:" + err);
|
console.log("Error building NW apps:" + err);
|
||||||
|
|
1
js/fc.js
1
js/fc.js
|
@ -1268,6 +1268,7 @@ var FC = {
|
||||||
35: "AGL status [0/1]",
|
35: "AGL status [0/1]",
|
||||||
36: "AGL [cm]",
|
36: "AGL [cm]",
|
||||||
37: "Rangefinder [cm]",
|
37: "Rangefinder [cm]",
|
||||||
|
38: "FW Land State"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
3: {
|
3: {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*global $*/
|
/*global $*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const { ColorManagement } = require("three");
|
||||||
|
|
||||||
function checkChromeRuntimeError() {
|
function checkChromeRuntimeError() {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error(
|
console.error(
|
||||||
|
@ -65,3 +67,51 @@ function scaleRangeInt(x, srcMin, srcMax, destMin, destMax) {
|
||||||
let b = srcMax - srcMin;
|
let b = srcMax - srcMin;
|
||||||
return Math.round((a / b) + destMin);
|
return Math.round((a / b) + destMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function distanceOnLine(start, end, distance)
|
||||||
|
{
|
||||||
|
var vx = end[0] - start[0];
|
||||||
|
var vy = end[1] - start[1];
|
||||||
|
var mag = Math.sqrt(vx * vx + vy * vy);
|
||||||
|
vx /= mag;
|
||||||
|
vy /= mag;
|
||||||
|
|
||||||
|
var px = start[0] + vx * (mag + distance);
|
||||||
|
var py = start[1] + vy * (mag + distance);
|
||||||
|
|
||||||
|
return [px, py];
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrap_360(angle)
|
||||||
|
{
|
||||||
|
if (angle >= 360)
|
||||||
|
angle -= 360;
|
||||||
|
if (angle < 0)
|
||||||
|
angle += 360;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rad2Deg(rad)
|
||||||
|
{
|
||||||
|
return rad * (180 / Math.PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deg2Rad(deg)
|
||||||
|
{
|
||||||
|
return deg * (Math.PI / 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculate_new_cooridatnes(coord, bearing, distance)
|
||||||
|
{
|
||||||
|
var lat = deg2Rad(coord.lat);
|
||||||
|
var lon = deg2Rad(coord.lon);
|
||||||
|
bearing = deg2Rad(bearing);
|
||||||
|
var delta = distance / 637100000; // Earth radius in cm
|
||||||
|
|
||||||
|
var latNew = Math.asin(Math.sin(lat) * Math.cos(delta) + Math.cos(lat) * Math.sin(delta) * Math.cos(bearing));
|
||||||
|
var lonNew = lon + Math.atan2(Math.sin(bearing) * Math.sin(delta) * Math.cos(lat), Math.cos(delta) - Math.sin(lat) * Math.sin(lat));
|
||||||
|
return {
|
||||||
|
lat: rad2Deg(latNew),
|
||||||
|
lon: rad2Deg(lonNew),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1521,12 +1521,27 @@ var mspHelper = (function (gui) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSPCodes.MSP2_INAV_SAFEHOME:
|
case MSPCodes.MSP2_INAV_SAFEHOME:
|
||||||
SAFEHOMES.put(new Safehome(
|
let safehome = new Safehome(
|
||||||
data.getUint8(0),
|
|
||||||
data.getUint8(1),
|
data.getUint8(1),
|
||||||
data.getInt32(2, true),
|
data.getInt32(2, true),
|
||||||
data.getInt32(6, true)
|
data.getInt32(6, true),
|
||||||
));
|
data.getInt32(10, true),
|
||||||
|
data.getInt32(14, true),
|
||||||
|
data.getUint8(18, true),
|
||||||
|
data.getInt16(19, true),
|
||||||
|
data.getInt16(21, true),
|
||||||
|
data.getUint8(23, true),
|
||||||
|
data.getUint8(0, true),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (safehome.getEnabled()) {
|
||||||
|
(async () => {
|
||||||
|
const elevation = await safehome.getElevationFromServer(globalSettings) * 100;
|
||||||
|
safehome.setElevation(elevation);
|
||||||
|
SAFEHOMES.put(safehome);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MSPCodes.MSP2_INAV_SET_SAFEHOME:
|
case MSPCodes.MSP2_INAV_SET_SAFEHOME:
|
||||||
console.log('Safehome points saved');
|
console.log('Safehome points saved');
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*global $*/
|
/*global $*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const ApproachDirection = Object.freeze({
|
||||||
|
LEFT: 0,
|
||||||
|
RIGHT: 1,
|
||||||
|
})
|
||||||
|
|
||||||
let Safehome = function (number, enabled, lat, lon) {
|
let Safehome = function (enabled, lat, lon, approachAltAsl = 0, landAltAsl = 0, approachDirection = 0, landHeading1 = 0, landHeading2 = 0, isSeaLevelRef = 0, elevation = 0, number = 0) {
|
||||||
|
|
||||||
var self = {};
|
var self = {};
|
||||||
|
|
||||||
|
@ -49,7 +53,63 @@ let Safehome = function (number, enabled, lat, lon) {
|
||||||
self.setEnabled = function (data) {
|
self.setEnabled = function (data) {
|
||||||
enabled = data;
|
enabled = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.getApproachAltAsl = function () {
|
||||||
|
return approachAltAsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setApproachAltAsl = function (data) {
|
||||||
|
approachAltAsl = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getLandAltAsl = function () {
|
||||||
|
return landAltAsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setLandAltAsl = function (data) {
|
||||||
|
landAltAsl = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getApproachDirection = function () {
|
||||||
|
return approachDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setApproachDirection = function (data) {
|
||||||
|
approachDirection = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getLandHeading1 = function () {
|
||||||
|
return landHeading1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setLandHeading1 = function (data) {
|
||||||
|
landHeading1 = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getLandHeading2 = function () {
|
||||||
|
return landHeading2;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setLandHeading2 = function (data) {
|
||||||
|
landHeading2 = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getIsSeaLevelRef = function () {
|
||||||
|
return isSeaLevelRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setIsSeaLevelRef = function (data) {
|
||||||
|
isSeaLevelRef = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getElevation = function() {
|
||||||
|
return elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setElevation = function (data) {
|
||||||
|
elevation = data;
|
||||||
|
}
|
||||||
|
|
||||||
self.cleanup = function () {
|
self.cleanup = function () {
|
||||||
number = 0;
|
number = 0;
|
||||||
enabled = 0;
|
enabled = 0;
|
||||||
|
@ -57,5 +117,24 @@ let Safehome = function (number, enabled, lat, lon) {
|
||||||
lat = 0;
|
lat = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.getElevationFromServer = async function (globalSettings) {
|
||||||
|
let elevation = "N/A";
|
||||||
|
if (globalSettings.mapProviderType == 'bing') {
|
||||||
|
let elevationEarthModel = $('#elevationEarthModel').prop("checked") ? "sealevel" : "ellipsoid";
|
||||||
|
|
||||||
|
const response = await fetch('http://dev.virtualearth.net/REST/v1/Elevation/List?points='+self.getLatMap()+','+self.getLonMap()+'&heights='+elevationEarthModel+'&key='+globalSettings.mapApiKey);
|
||||||
|
const myJson = await response.json();
|
||||||
|
elevation = myJson.resourceSets[0].resources[0].elevations[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+self.getLatMap()+','+self.getLonMap());
|
||||||
|
const myJson = await response.json();
|
||||||
|
if (myJson.status == "OK" && myJson.results[0].elevation != null) {
|
||||||
|
elevation = myJson.results[0].elevation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elevation;
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
|
@ -15,6 +15,7 @@ let SafehomeCollection = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.put = function (element) {
|
self.put = function (element) {
|
||||||
|
element.setNumber(data.length);
|
||||||
data.push(element);
|
data.push(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,85 +31,68 @@ let SafehomeCollection = function () {
|
||||||
data = [];
|
data = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
self.inflate = function () {
|
self.isEmpty = () => {
|
||||||
while (self.hasFreeSlots()) {
|
return data.length == 0;
|
||||||
self.put(new Safehome(data.length, 0, 0, 0));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.hasFreeSlots = function () {
|
self.safehomeCount = () => {
|
||||||
return data.length < self.getMaxSafehomeCount();
|
return data.length;
|
||||||
};
|
|
||||||
|
|
||||||
self.isSafehomeConfigured = function(safehomeId) {
|
|
||||||
|
|
||||||
for (let safehomeIndex in data) {
|
|
||||||
if (data.hasOwnProperty(safehomeIndex)) {
|
|
||||||
let safehome = data[safehomeIndex];
|
|
||||||
|
|
||||||
if (safehome.getNumber() == safehomeId && safehome.isUsed()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.getNumberOfConfiguredSafehome = function () {
|
|
||||||
let count = 0;
|
|
||||||
for (let i = 0; i < self.getMaxSafehomeCount(); i ++) {
|
|
||||||
if (self.isSafehomeConfigured(i)) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.getUsedSafehomeIndexes = function () {
|
|
||||||
let out = [];
|
|
||||||
|
|
||||||
for (let safehomeIndex in data) {
|
|
||||||
if (data.hasOwnProperty(safehomeIndex)) {
|
|
||||||
let safehome = data[safehomeIndex];
|
|
||||||
out.push(safehome.getNumber());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let unique = [...new Set(out)];
|
|
||||||
|
|
||||||
return unique.sort(function(a, b) {
|
|
||||||
return a-b;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.getSafehome = function(safehomeId) {
|
self.drop = (idx) => {
|
||||||
for (let safehomeIndex in data) {
|
data.forEach(safehome => {
|
||||||
if (data.hasOwnProperty(safehomeIndex)) {
|
if (safehome.getNumber() >= idx) {
|
||||||
let safehome = data[safehomeIndex];
|
safehome.setNumber(safehome.getNumber() - 1);
|
||||||
if (safehome.getNumber() == safehomeId ) {
|
|
||||||
return safehome;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
data.splice(idx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.insert = (safehome, idx) => {
|
||||||
|
data.forEach(s => {
|
||||||
|
if (s.getNumber() >= idx) {
|
||||||
|
s.setNumber(s.getNumber() + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
data.splice(idx, 0, safehome);
|
||||||
|
}
|
||||||
|
|
||||||
self.updateSafehome = function(newSafehome) {
|
self.updateSafehome = function(newSafehome) {
|
||||||
data[newSafehome.getNumber()] = newSafehome;
|
data[newSafehome.getNumber()] = newSafehome;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.extractBuffer = function(safehomeId) {
|
self.extractBuffer = function(safehomeId) {
|
||||||
let buffer = [];
|
let buffer = [];
|
||||||
let safehome = self.getSafehome(safehomeId);
|
let safehome = data[safehomeId];
|
||||||
buffer.push(safehome.getNumber()); // sbufReadU8(src); // number
|
if (safehomeId < self.safehomeCount()) {
|
||||||
buffer.push(safehome.getEnabled()); // sbufReadU8(src); // action
|
buffer.push(safehome.getNumber()); // sbufReadU8(src); // number
|
||||||
buffer.push(specificByte(safehome.getLat(), 0)); // sbufReadU32(src); // lat
|
buffer.push(1);
|
||||||
buffer.push(specificByte(safehome.getLat(), 1));
|
buffer.push(specificByte(safehome.getLat(), 0)); // sbufReadU32(src); // lat
|
||||||
buffer.push(specificByte(safehome.getLat(), 2));
|
buffer.push(specificByte(safehome.getLat(), 1));
|
||||||
buffer.push(specificByte(safehome.getLat(), 3));
|
buffer.push(specificByte(safehome.getLat(), 2));
|
||||||
buffer.push(specificByte(safehome.getLon(), 0)); // sbufReadU32(src); // lon
|
buffer.push(specificByte(safehome.getLat(), 3));
|
||||||
buffer.push(specificByte(safehome.getLon(), 1));
|
buffer.push(specificByte(safehome.getLon(), 0)); // sbufReadU32(src); // lon
|
||||||
buffer.push(specificByte(safehome.getLon(), 2));
|
buffer.push(specificByte(safehome.getLon(), 1));
|
||||||
buffer.push(specificByte(safehome.getLon(), 3));
|
buffer.push(specificByte(safehome.getLon(), 2));
|
||||||
|
buffer.push(specificByte(safehome.getLon(), 3));
|
||||||
|
buffer.push(specificByte(safehome.getApproachAltAsl(), 0));
|
||||||
|
buffer.push(specificByte(safehome.getApproachAltAsl(), 1));
|
||||||
|
buffer.push(specificByte(safehome.getApproachAltAsl(), 2));
|
||||||
|
buffer.push(specificByte(safehome.getApproachAltAsl(), 3));
|
||||||
|
buffer.push(specificByte(safehome.getLandAltAsl(), 0));
|
||||||
|
buffer.push(specificByte(safehome.getLandAltAsl(), 1));
|
||||||
|
buffer.push(specificByte(safehome.getLandAltAsl(), 2));
|
||||||
|
buffer.push(specificByte(safehome.getLandAltAsl(), 3));
|
||||||
|
buffer.push(safehome.getApproachDirection());
|
||||||
|
buffer.push(specificByte(safehome.getLandHeading1(), 0));
|
||||||
|
buffer.push(specificByte(safehome.getLandHeading1(), 1));
|
||||||
|
buffer.push(specificByte(safehome.getLandHeading2(), 0));
|
||||||
|
buffer.push(specificByte(safehome.getLandHeading2(), 1));
|
||||||
|
buffer.push(safehome.getIsSeaLevelRef());
|
||||||
|
} else {
|
||||||
|
buffer = Array(24).fill(0);
|
||||||
|
buffer[0] = safehomeId;
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,10 +236,17 @@
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-mission-control .point-label {
|
.tab-mission-control .point-label {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .point-label-safehome {
|
||||||
|
width: 120px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-mission-control .point-radio input{
|
.tab-mission-control .point-radio input{
|
||||||
width: 25px;
|
width: 25px;
|
||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
|
@ -511,7 +518,6 @@
|
||||||
|
|
||||||
.tab-mission-control .fill{
|
.tab-mission-control .fill{
|
||||||
border:none;
|
border:none;
|
||||||
border-bottom:5px dotted #88CC3E;
|
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
width:20px;
|
width:20px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,49 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="config-section gui_box grey">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title" data-i18n="fixedWingLandingConfiguration"></div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandApproachLength" type="number" data-unit="cm" data-setting="nav_fw_land_approach_length" data-setting-multiplier="1" step="1" min="100" max="100000" />
|
||||||
|
<label for="fwLandApproachLength"><span data-i18n="fwLandApproachLength"></span></label>
|
||||||
|
<div for="fwLandApproachLength" class="helpicon cf_tip" data-i18n_title="fwLandApproachLengthHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandFinalApproachPitch2throttle" type="number" data-unit="percent" data-setting="nav_fw_land_final_approach_pitch2throttle_mod" data-setting-multiplier="1" step="1" min="100" max="400" />
|
||||||
|
<label for="fwLandFinalApproachPitch2throttle"><span data-i18n="fwLandFinalApproachPitch2throttle"></span></label>
|
||||||
|
<div for="fwLandFinalApproachPitch2throttle" class="helpicon cf_tip" data-i18n_title="fwLandFinalApproachPitch2throttleHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandGlideAlt" type="number" data-unit="cm" data-setting="nav_fw_land_glide_alt" data-setting-multiplier="1" step="1" min="100" max="5000" />
|
||||||
|
<label for="fwLandGlideAlt"><span data-i18n="fwLandGlideAlt"></span></label>
|
||||||
|
<div for="fwLandGlideAlt" class="helpicon cf_tip" data-i18n_title="fwLandGlideAltHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandFlareAlt" type="number" data-unit="cm" data-setting="nav_fw_land_flare_alt" data-setting-multiplier="1" step="1" min="0" max="10000" />
|
||||||
|
<label for="fwLandFlareAlt"><span data-i18n="fwLandFlareAlt"></span></label>
|
||||||
|
<div for="fwLandFlareAlt" class="helpicon cf_tip" data-i18n_title="fwLandFlareAltHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandGlidePitch" type="number" data-unit="deg" data-setting="nav_fw_land_glide_pitch" data-setting-multiplier="1" step="1" min="0" max="45" />
|
||||||
|
<label for="fwLandGlidePitch"><span data-i18n="fwLandGlidePitch"></span></label>
|
||||||
|
<div for="fwLandGlidePitch" class="helpicon cf_tip" data-i18n_title="fwLandGlidePitchHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandFlarePitch" type="number" data-unit="deg" data-setting="nav_fw_land_flare_pitch" data-setting-multiplier="1" step="1" min="0" max="45" />
|
||||||
|
<label for="fwLandFlarePitch"><span data-i18n="fwLandFlarePitch"></span></label>
|
||||||
|
<div for="fwLandFlarePitch" class="helpicon cf_tip" data-i18n_title="fwLandFlarePitchHelp"></div>
|
||||||
|
</div>
|
||||||
|
<div class="number">
|
||||||
|
<input id="fwLandMaxTailwind" type="number" data-unit="cms" data-setting="nav_fw_land_max_tailwind" data-setting-multiplier="1" step="1" min="0" max="3000" />
|
||||||
|
<label for="fwLandMaxTailwind"><span data-i18n="fwLandMaxTailwind"></span></label>
|
||||||
|
<div for="fwLandMaxTailwind" class="helpicon cf_tip" data-i18n_title="fwLandMaxTailwindHelp"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="config-section gui_box grey">
|
<div class="config-section gui_box grey">
|
||||||
<div class="gui_box_titlebar">
|
<div class="gui_box_titlebar">
|
||||||
<div class="spacer_box_title" data-i18n="powerConfiguration"></div>
|
<div class="spacer_box_title" data-i18n="powerConfiguration"></div>
|
||||||
|
|
|
@ -180,35 +180,34 @@
|
||||||
<a id="cancelSafehome" class="ic_cancel" href="#" title="Cancel"></a>
|
<a id="cancelSafehome" class="ic_cancel" href="#" title="Cancel"></a>
|
||||||
<a id="saveEepromSafehomeButton" class="ic_save2Eprom" href="#" title="Save Eeprom Safehome"></a>
|
<a id="saveEepromSafehomeButton" class="ic_save2Eprom" href="#" title="Save Eeprom Safehome"></a>
|
||||||
<a id="loadEepromSafehomeButton" class="ic_loadFromEprom" href="#" title="Load Eeprom Safehome"></a>
|
<a id="loadEepromSafehomeButton" class="ic_loadFromEprom" href="#" title="Load Eeprom Safehome"></a>
|
||||||
|
<a id="addSafehome" class="ic_add" href="#" title="Add Safehome"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="spacer" id="SafehomeContent">
|
<div class="spacer" id="SafehomeContent">
|
||||||
<div>
|
<div>
|
||||||
<table class="safehomesTable">
|
<div style="padding-bottom: 2px;">
|
||||||
<thead>
|
<span class="i18n-replaced" data-i18n="missionSafehomeAvailableSafehomes">Available Safehomes:</span>
|
||||||
<tr>
|
<span id="availableSafehomes"></span>
|
||||||
<th style="width: 40px" data-i18n="SafehomeSelected"></th>
|
</div>
|
||||||
<th style="width: 40px" data-i18n="SafehomeId"></th>
|
<div id="SafehomeContentBox">
|
||||||
<th style="width: 60px" data-i18n="SafehomeEnabled"></th>
|
</div>
|
||||||
<th style="width: 140px" data-i18n="SafehomeLat"></th>
|
|
||||||
<th style="width: 140px" data-i18n="SafehomeLon"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="safehomesTableBody">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<hr>
|
<hr>
|
||||||
<div class="spacer" id="safehomeLegend">
|
<div class="spacer" id="safehomeLegend">
|
||||||
<span><b>Legend : </b></span>
|
<span><b>Legend : </b></span>
|
||||||
<div class="legendItem">
|
<div class="legendItem">
|
||||||
<span class="fill" style="border-bottom-color:#900C3F"></span>
|
<span class="fill" style="border-bottom:5px dotted #900C3F;"></span>
|
||||||
<span class="textLegend">Max distance (m):</span>
|
<span class="textLegend">Max distance (m):</span>
|
||||||
<span id="safeHomeMaxDistance" class="valueLegend"></span>
|
<span id="safeHomeMaxDistance"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="legendItem">
|
<div class="legendItem">
|
||||||
<span class="fill"></span>
|
<span class="fill" style="border-bottom:5px dotted #88CC3E;"></span>
|
||||||
<span class="textLegend">Safe Radius (m):</span>
|
<span class="textLegend">Safe Radius (m):</span>
|
||||||
<span id="SafeHomeSafeDistance" class="valueLegend"></span>
|
<span id="SafeHomeSafeDistance"></span>
|
||||||
|
</div>
|
||||||
|
<div class="legendItem">
|
||||||
|
<span class="fill" style="border-bottom:5px solid #f78a05;"></span>
|
||||||
|
<span class="textLegend">FW Approach</span>
|
||||||
|
<span id="SafeHomeSafeDistance"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -79,6 +79,8 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
var textGeom;
|
var textGeom;
|
||||||
let isOffline = false;
|
let isOffline = false;
|
||||||
let rthUpdateInterval = 0;
|
let rthUpdateInterval = 0;
|
||||||
|
let selectedSafehome = -1;
|
||||||
|
let settings = { speed: 0, alt: 5000, safeRadiusSH : 50, maxDistSH : 0, fwApproachLength: 0};
|
||||||
|
|
||||||
if (GUI.active_tab != 'mission_control') {
|
if (GUI.active_tab != 'mission_control') {
|
||||||
GUI.active_tab = 'mission_control';
|
GUI.active_tab = 'mission_control';
|
||||||
|
@ -90,7 +92,17 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
loadChainer.setChain([
|
loadChainer.setChain([
|
||||||
mspHelper.getMissionInfo,
|
mspHelper.getMissionInfo,
|
||||||
//mspHelper.loadWaypoints,
|
//mspHelper.loadWaypoints,
|
||||||
//mspHelper.loadSafehomes
|
mspHelper.loadSafehomes,
|
||||||
|
function (callback) {
|
||||||
|
mspHelper.getSetting("nav_fw_land_approach_length").then((data) => {
|
||||||
|
settings.fwApproachLength = parseInt(data.value);
|
||||||
|
}).then(callback);
|
||||||
|
},
|
||||||
|
function (callback) {
|
||||||
|
mspHelper.getSetting("safehome_max_distance").then((data) => {
|
||||||
|
settings.maxDistSH = parseInt(data.value) / 100;
|
||||||
|
}).then(callback);
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
loadChainer.setExitPoint(loadHtml);
|
loadChainer.setExitPoint(loadHtml);
|
||||||
loadChainer.execute();
|
loadChainer.execute();
|
||||||
|
@ -117,8 +129,7 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
isOffline = true;
|
isOffline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$safehomesTable = $('.safehomesTable');
|
$safehomeContentBox = $('#SafehomeContentBox');
|
||||||
$safehomesTableBody = $('#safehomesTableBody');
|
|
||||||
$waypointOptionsTable = $('.waypointOptionsTable');
|
$waypointOptionsTable = $('.waypointOptionsTable');
|
||||||
$waypointOptionsTableBody = $('#waypointOptionsTableBody');
|
$waypointOptionsTableBody = $('#waypointOptionsTableBody');
|
||||||
|
|
||||||
|
@ -126,6 +137,17 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
loadSettings();
|
loadSettings();
|
||||||
// let the dom load finish, avoiding the resizing of the map
|
// let the dom load finish, avoiding the resizing of the map
|
||||||
setTimeout(initMap, 200);
|
setTimeout(initMap, 200);
|
||||||
|
if (!isOffline) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (SAFEHOMES.safehomeCount() >= 1) {
|
||||||
|
selectedSafehome = 0;
|
||||||
|
} else {
|
||||||
|
selectedSafehome = -1;
|
||||||
|
}
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
updateSafehomeInfo();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$('#missionMap, #missionControls').hide();
|
$('#missionMap, #missionControls').hide();
|
||||||
$('#notLoadMap').show();
|
$('#notLoadMap').show();
|
||||||
|
@ -364,24 +386,8 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// define & init parameters for default Settings
|
// define & init parameters for default Settings
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
var vMaxDistSH = 0;
|
|
||||||
var settings = {};
|
|
||||||
if (CONFIGURATOR.connectionValid) {
|
|
||||||
mspHelper.getSetting("safehome_max_distance").then(function (s) {
|
|
||||||
if (s) {
|
|
||||||
vMaxDistSH = Number(s.value)/100;
|
|
||||||
settings = { speed: 0, alt: 5000, safeRadiusSH : 50, maxDistSH : vMaxDistSH};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vMaxDistSH = 0;
|
|
||||||
settings = { speed: 0, alt: 5000, safeRadiusSH : 50, maxDistSH : vMaxDistSH};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vMaxDistSH = 0;
|
|
||||||
settings = { speed: 0, alt: 5000, safeRadiusSH : 50, maxDistSH : vMaxDistSH};
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// define & init Waypoints parameters
|
// define & init Waypoints parameters
|
||||||
|
@ -468,67 +474,267 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSafehomesTable() {
|
function renderSafehomesTable() {
|
||||||
/*
|
|
||||||
* Process safehome table UI
|
$safehomeContentBox.find("*").remove();
|
||||||
*/
|
|
||||||
let safehomes = SAFEHOMES.get();
|
if (selectedSafehome < 0) {
|
||||||
$safehomesTableBody.find("*").remove();
|
return;
|
||||||
for (let safehomeIndex in safehomes) {
|
|
||||||
if (safehomes.hasOwnProperty(safehomeIndex)) {
|
|
||||||
const safehome = safehomes[safehomeIndex];
|
|
||||||
|
|
||||||
$safehomesTableBody.append('\
|
|
||||||
<tr>\
|
|
||||||
<td><div id="viewSafomePoint" class="btnTable btnTableIcon"> \
|
|
||||||
<a class="ic_center" data-role="safehome-center" href="#" title="move to center view"></a> \
|
|
||||||
</div>\
|
|
||||||
</td> \
|
|
||||||
<td><span class="safehome-number"/></td>\
|
|
||||||
<td class="safehome-enabled"><input type="checkbox" class="togglesmall safehome-enabled-value"/></td> \
|
|
||||||
<td><input type="number" class="safehome-lat" /></td>\
|
|
||||||
<td><input type="number" class="safehome-lon" /></td>\
|
|
||||||
</tr>\
|
|
||||||
');
|
|
||||||
|
|
||||||
const $row = $safehomesTableBody.find('tr:last');
|
|
||||||
|
|
||||||
$row.find(".safehome-number").text(safehome.getNumber()+1);
|
|
||||||
|
|
||||||
$row.find(".safehome-enabled-value").prop('checked',safehome.isUsed()).change(function () {
|
|
||||||
safehome.setEnabled((($(this).prop('checked')) ? 1 : 0));
|
|
||||||
SAFEHOMES.updateSafehome(safehome);
|
|
||||||
cleanSafehomeLayers();
|
|
||||||
renderSafehomesOnMap();
|
|
||||||
});
|
|
||||||
|
|
||||||
$row.find(".safehome-lon").val(safehome.getLonMap()).change(function () {
|
|
||||||
safehome.setLon(Math.round(Number($(this).val()) * 10000000));
|
|
||||||
SAFEHOMES.updateSafehome(safehome);
|
|
||||||
cleanSafehomeLayers();
|
|
||||||
renderSafehomesOnMap();
|
|
||||||
});
|
|
||||||
|
|
||||||
$row.find(".safehome-lat").val(safehome.getLatMap()).change(function () {
|
|
||||||
safehome.setLat(Math.round(Number($(this).val()) * 10000000));
|
|
||||||
SAFEHOMES.updateSafehome(safehome);
|
|
||||||
cleanSafehomeLayers();
|
|
||||||
renderSafehomesOnMap();
|
|
||||||
});
|
|
||||||
|
|
||||||
$row.find("[data-role='safehome-center']").attr("data-index", safehomeIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$("#missionPlannerSafehome").is(":visible")) {
|
||||||
|
$("#missionPlannerSafehome").fadeIn(300);
|
||||||
|
$('#safeHomeMaxDistance').text(settings.maxDistSH);
|
||||||
|
$('#SafeHomeSafeDistance').text(settings.safeRadiusSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
const safehome = SAFEHOMES.get()[selectedSafehome];
|
||||||
|
|
||||||
|
$safehomeContentBox.append('\
|
||||||
|
<div class="gui_box grey missionPlannerSafehomeBox"> \
|
||||||
|
<div class="gui_box_titlebar"> \
|
||||||
|
<div class="spacer_box_title">Edit Safehome </div> \
|
||||||
|
<div class="btnMenu btnMenuIcon"> \
|
||||||
|
<div class="btnMenu-danger"> \
|
||||||
|
<a id="deleteSafehome" class="ic_removeAll" href="#" title="Delete"></a> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
<div class="spacer" id="safehomeSingelContent"> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safeHomeLatitude">Latitude:</label> \
|
||||||
|
<input type="number" id="safehomeLatitude"></input> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeLongitude">Longitude:</label> \
|
||||||
|
<input type="number" id="safehomeLongitude"></input> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<span style="font-weight: bold">Fixed Wing landing settings:</span> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeSeaLEvelRef">Sea level ref:</label> \
|
||||||
|
<input id="safehomeSeaLevelRef" type="checkbox" value="0" class="togglemedium" required> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeApproachAlt">Approach Alt: (cm):</label> \
|
||||||
|
<input type="number" id="safehomeApproachAlt"></input> \
|
||||||
|
<span id="safehomeApproachAltM"></span> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeLandAlt">Land Alt: (cm):</label> \
|
||||||
|
<input type="number" id="safehomeLandAlt"></input> \
|
||||||
|
<span id="safehomeLandAltM"></span> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeElevation">Elevation: (m):</label> \
|
||||||
|
<span id="safehomeElevation"></span> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="geozoneApproachDirection">Approach direction:</label> \
|
||||||
|
<select name="zoneAction" id="geozoneApproachDirection"> \
|
||||||
|
<option value="0">Left</option> \
|
||||||
|
<option value="1">Right</option> \
|
||||||
|
</select> \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeLandHeading1">Heading 1: (deg):</label> \
|
||||||
|
<input type="number" id="safehomeLandHeading1"></input> \
|
||||||
|
<input id="safehomeLandHeading1Excl" type="checkbox" value="0" class="togglemedium" required> Excl. \
|
||||||
|
</div> \
|
||||||
|
<div class="point"> \
|
||||||
|
<label class="point-label-safehome" for="safehomeLandHeading2">Heading 2: (deg):</label> \
|
||||||
|
<input type="number" id="safehomeLandHeading2"></input> \
|
||||||
|
<input id="safehomeLandHeading2Excl" type="checkbox" value="0" class="togglemedium" required> Excl. \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
');
|
||||||
|
|
||||||
|
const $safehomeBox = $safehomeContentBox.find('.missionPlannerSafehomeBox:last-child');
|
||||||
|
$safehomeBox.find('.spacer_box_title').append(safehome.getNumber() + 1);
|
||||||
|
|
||||||
|
$safehomeBox.find('#deleteSafehome').on('click', () => {
|
||||||
|
SAFEHOMES.drop(safehome.getNumber());
|
||||||
|
selectedSafehome = SAFEHOMES.safehomeCount() - 1;
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
renderSafehomesTable();
|
||||||
|
updateSafehomeInfo();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLatitude').val(safehome.getLatMap()).on('change', event => {
|
||||||
|
safehome.setLat(Math.round(Number($(event.currentTarget).val()) * 1e7));
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLongitude').val(safehome.getLonMap()).on('change', event => {
|
||||||
|
safehome.setLon(Math.round(Number($(event.currentTarget).val()) * 1e7));
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find($('#safehomeSeaLevelRef')).prop('checked', safehome.getIsSeaLevelRef()).change(event => {
|
||||||
|
|
||||||
|
let isChecked = $(event.currentTarget).prop('checked') ? 1 : 0;
|
||||||
|
safehome.setIsSeaLevelRef(isChecked);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const elevation = await safehome.getElevationFromServer(globalSettings) * 100;
|
||||||
|
safehome.setElevation(elevation);
|
||||||
|
|
||||||
|
$('#safehomeElevation').text(elevation / 100);
|
||||||
|
$approachAlt = $safehomeBox.find('#safehomeApproachAlt');
|
||||||
|
$landAlt = $safehomeBox.find('#safehomeLandAlt');
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
safehome.setApproachAltAsl(safehome.getApproachAltAsl() + elevation)
|
||||||
|
$approachAlt.val(safehome.getApproachAltAsl());
|
||||||
|
safehome.setLandAltAsl(safehome.getLandAltAsl() + elevation)
|
||||||
|
$landAlt.val(safehome.getLandAltAsl());
|
||||||
|
} else {
|
||||||
|
safehome.setApproachAltAsl(safehome.getApproachAltAsl() - elevation)
|
||||||
|
$approachAlt.val(safehome.getApproachAltAsl());
|
||||||
|
safehome.setLandAltAsl(safehome.getLandAltAsl() - elevation)
|
||||||
|
$landAlt.val(safehome.getLandAltAsl());
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#safehomeLandAltM').text(safehome.getLandAltAsl() / 100 + " m");
|
||||||
|
$('#safehomeApproachAltM').text( safehome.getApproachAltAsl() / 100 + " m");
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeApproachAlt').val(safehome.getApproachAltAsl()).on('change', event => {
|
||||||
|
|
||||||
|
let altitude = Number($(event.currentTarget).val());
|
||||||
|
if (checkSafhomeAltitude(altitude, $safehomeBox.find('#safehomeSeaLevelRef').prop('checked'), Number($('#safehomeElevation').text()))) {
|
||||||
|
safehome.setApproachAltAsl(Number($(event.currentTarget).val()));
|
||||||
|
$('#safehomeApproachAltM').text( safehome.getApproachAltAsl() / 100 + " m");
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
renderHomeTable();
|
||||||
|
}
|
||||||
|
$safehomeBox.find('#safehomeApproachAlt').val(safehome.getApproachAltAsl());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLandAlt').val(safehome.getLandAltAsl()).on('change', event => {
|
||||||
|
|
||||||
|
let altitude = Number($(event.currentTarget).val());
|
||||||
|
if (checkSafhomeAltitude(altitude, $safehomeBox.find('#safehomeSeaLevelRef').prop('checked'), Number($('#safehomeElevation').text()))) {
|
||||||
|
safehome.setLandAltAsl(altitude);
|
||||||
|
$('#safehomeLandAltM').text(safehome.getLandAltAsl() / 100 + " m");
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
renderHomeTable();
|
||||||
|
} else {
|
||||||
|
$safehomeBox.find('#safehomeLandAlt').val(safehome.getLandAltAsl());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#geozoneApproachDirection').val(safehome.getApproachDirection()).on('change', event => {
|
||||||
|
safehome.setApproachDirection($(event.currentTarget).val());
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLandHeading1Excl').prop('checked', safehome.getLandHeading1() < 0).change(event => {
|
||||||
|
safehome.setLandHeading1(safehome.getLandHeading1() * -1);
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLandHeading1').val(Math.abs(safehome.getLandHeading1())).on('change', event => {
|
||||||
|
let val = Number($(event.currentTarget).val());
|
||||||
|
if (val < -360 || val > 360) {
|
||||||
|
$safehomeBox.find('#safehomeLandHeading1').val(safehome.getLandHeading1());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
safehome.setLandHeading1(val);
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLandHeading2Excl').prop('checked', safehome.getLandHeading2() < 0).change(event => {
|
||||||
|
safehome.setLandHeading2(safehome.getLandHeading2() * -1);
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$safehomeBox.find('#safehomeLandHeading2').val(Math.abs(safehome.getLandHeading2())).on('change', event => {
|
||||||
|
let val = Number($(event.currentTarget).val());
|
||||||
|
if (val < -360 || val > 360) {
|
||||||
|
$safehomeBox.find('#safehomeLandHeading2').val(safehome.getLandHeading2());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
safehome.setLandHeading2(val);
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#safehomeLandAltM').text(safehome.getLandAltAsl() / 100 + " m");
|
||||||
|
$('#safehomeApproachAltM').text(safehome.getApproachAltAsl() / 100 + " m");
|
||||||
|
|
||||||
|
if (safehome.getElevation() != "NaN")
|
||||||
|
$('#safehomeElevation').text(safehome.getElevation() / 100 + " m");
|
||||||
|
|
||||||
GUI.switchery();
|
GUI.switchery();
|
||||||
localize();
|
localize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkSafhomeAltitude(altitude, isSeaLevelRef, sealevel) {
|
||||||
|
|
||||||
|
if (isSeaLevelRef && altitude - sealevel < 0) {
|
||||||
|
alert(chrome.i18n.getMessage('MissionPlannerAltitudeChangeReset'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSafehomeInfo(){
|
||||||
|
let freeSamehomes = SAFEHOMES.getMaxSafehomeCount() - SAFEHOMES.safehomeCount()
|
||||||
|
$('#availableSafehomes').text(freeSamehomes + '/' + SAFEHOMES.getMaxSafehomeCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSafehome(){
|
||||||
|
if (SAFEHOMES.safehomeCount() + 1 > SAFEHOMES.getMaxSafehomeCount()){
|
||||||
|
alert(chrome.i18n.getMessage('missionSafehomeMaxSafehomesReached'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mapCenter = map.getView().getCenter();
|
||||||
|
let midLon = Math.round(ol.proj.toLonLat(mapCenter)[0] * 1e7);
|
||||||
|
let midLat = Math.round(ol.proj.toLonLat(mapCenter)[1] * 1e7);
|
||||||
|
var safehome = new Safehome(1, midLat, midLon);
|
||||||
|
safehome.setNumber(SAFEHOMES.safehomeCount());
|
||||||
|
SAFEHOMES.put(safehome);
|
||||||
|
selectedSafehome = SAFEHOMES.safehomeCount() - 1;
|
||||||
|
|
||||||
|
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
renderSafehomesTable();
|
||||||
|
updateSafehomeInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderSafehomesOnMap() {
|
function renderSafehomesOnMap() {
|
||||||
/*
|
/*
|
||||||
* Process safehome on Map
|
* Process safehome on Map
|
||||||
*/
|
*/
|
||||||
SAFEHOMES.get().forEach(function (safehome) {
|
|
||||||
map.addLayer(addSafeHomeMarker(safehome));
|
SAFEHOMES.get().forEach(safehome => {
|
||||||
|
addSafehomeCircles(safehome);
|
||||||
|
addSafeHomeMarker(safehome);
|
||||||
|
});
|
||||||
|
SAFEHOMES.get().forEach(safehome => {
|
||||||
|
addFwApproach(safehome);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +771,105 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSafeHomeMarker(safehome) {
|
function paintApproachLine(pos1, pos2, color)
|
||||||
|
{
|
||||||
|
var line = new ol.geom.LineString([pos1, pos2]);
|
||||||
|
|
||||||
|
var feature = new ol.Feature({
|
||||||
|
geometry: line
|
||||||
|
});
|
||||||
|
|
||||||
|
var styles = [ new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({
|
||||||
|
color: color,
|
||||||
|
width: 3,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
var geometry = feature.getGeometry();
|
||||||
|
geometry.forEachSegment(function (start, end) {
|
||||||
|
var dx = end[0] - start[0];
|
||||||
|
var dy = end[1] - start[1];
|
||||||
|
var rotation = Math.atan2(dy, dx);
|
||||||
|
|
||||||
|
styles.push(new ol.style.Style({
|
||||||
|
geometry: new ol.geom.Point(distanceOnLine(start, end, -8)),
|
||||||
|
image: new ol.style.RegularShape({
|
||||||
|
fill: new ol.style.Fill({color}),
|
||||||
|
points: 3,
|
||||||
|
radius: 8,
|
||||||
|
rotation: -rotation,
|
||||||
|
angle: Math.PI / 2 // rotate -90°
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
feature.setStyle(styles);
|
||||||
|
|
||||||
|
var vectorSource = new ol.source.Vector({
|
||||||
|
features: [feature]
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var vectorLayer = new ol.layer.Vector({
|
||||||
|
source: vectorSource
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vectorLayer.kind = "approachline";
|
||||||
|
vectorLayer.selection = false;
|
||||||
|
|
||||||
|
safehomeMarkers.push(vectorLayer);
|
||||||
|
map.addLayer(vectorLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function paintApproach(landCoord, approachLength, bearing, approachDirection) {
|
||||||
|
var coords = new Array(4);
|
||||||
|
coords[3] = landCoord;
|
||||||
|
coords[2] = calculate_new_cooridatnes(coords[3], bearing, approachLength);
|
||||||
|
let direction;
|
||||||
|
if (approachDirection == ApproachDirection.LEFT) {
|
||||||
|
direction = wrap_360(bearing + 90);
|
||||||
|
} else {
|
||||||
|
direction = wrap_360(bearing - 90);
|
||||||
|
}
|
||||||
|
coords[1] = calculate_new_cooridatnes(coords[2], direction, approachLength / 2);
|
||||||
|
coords[0] = calculate_new_cooridatnes(coords[3], direction, approachLength / 2);
|
||||||
|
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
let pos1 = ol.proj.fromLonLat([coords[i].lon, coords[i].lat]);
|
||||||
|
let pos2 = ol.proj.fromLonLat([coords[i + 1].lon, coords[i + 1].lat]);
|
||||||
|
paintApproachLine(pos1, pos2, '#f78a05');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFwApproach(safehome)
|
||||||
|
{
|
||||||
|
if (safehome.getLandHeading1() != 0) {
|
||||||
|
let bearing = wrap_360(Math.abs(safehome.getLandHeading1()) + 180);
|
||||||
|
paintApproach({lat: safehome.getLatMap(), lon: safehome.getLonMap()}, settings.fwApproachLength, bearing, safehome.getApproachDirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safehome.getLandHeading1() > 0) {
|
||||||
|
let direction = safehome.getApproachDirection() == ApproachDirection.LEFT ? ApproachDirection.RIGHT : ApproachDirection.LEFT;
|
||||||
|
paintApproach({lat: safehome.getLatMap(), lon: safehome.getLonMap()}, settings.fwApproachLength, safehome.getLandHeading1(), direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safehome.getLandHeading2() != 0) {
|
||||||
|
paintApproach({lat: safehome.getLatMap(), lon: safehome.getLonMap()}, settings.fwApproachLength, Math.abs(safehome.getLandHeading2()), safehome.getApproachDirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safehome.getLandHeading2() > 0) {
|
||||||
|
let bearing = wrap_360(safehome.getLandHeading2() + 180);
|
||||||
|
let direction = safehome.getApproachDirection() == ApproachDirection.LEFT ? ApproachDirection.RIGHT : ApproachDirection.LEFT;
|
||||||
|
paintApproach({lat: safehome.getLatMap(), lon: safehome.getLonMap()}, settings.fwApproachLength, bearing, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSafehomeCircles(safehome) {
|
||||||
/*
|
/*
|
||||||
* add safehome on Map
|
* add safehome on Map
|
||||||
*/
|
*/
|
||||||
|
@ -620,8 +924,32 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
vectorLayer.selection = false;
|
vectorLayer.selection = false;
|
||||||
|
|
||||||
safehomeMarkers.push(vectorLayer);
|
safehomeMarkers.push(vectorLayer);
|
||||||
|
map.addLayer(vectorLayer);
|
||||||
|
}
|
||||||
|
|
||||||
return vectorLayer;
|
function addSafeHomeMarker(safehome) {
|
||||||
|
|
||||||
|
let coord = ol.proj.fromLonLat([safehome.getLonMap(), safehome.getLatMap()]);
|
||||||
|
var iconFeature = new ol.Feature({
|
||||||
|
geometry: new ol.geom.Point(coord),
|
||||||
|
name: 'safehome'
|
||||||
|
});
|
||||||
|
|
||||||
|
var vectorLayer = new ol.layer.Vector({
|
||||||
|
source: new ol.source.Vector({
|
||||||
|
features: [iconFeature]
|
||||||
|
}),
|
||||||
|
style : function(iconFeature) {
|
||||||
|
return [getSafehomeIcon(safehome)];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
vectorLayer.kind = "safehome";
|
||||||
|
vectorLayer.number = safehome.getNumber();
|
||||||
|
vectorLayer.selection = true;
|
||||||
|
|
||||||
|
safehomeMarkers.push(vectorLayer);
|
||||||
|
map.addLayer(vectorLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProjectedRadius(radius) {
|
function getProjectedRadius(radius) {
|
||||||
|
@ -1599,6 +1927,10 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
* @param {ol.MapBrowserEvent} evt Map browser event.
|
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||||
*/
|
*/
|
||||||
app.Drag.prototype.handleDragEvent = function (evt) {
|
app.Drag.prototype.handleDragEvent = function (evt) {
|
||||||
|
if (tempMarker.kind == "safehomecircle") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var map = evt.map;
|
var map = evt.map;
|
||||||
|
|
||||||
var feature = map.forEachFeatureAtPixel(evt.pixel,
|
var feature = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
@ -1606,7 +1938,7 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
return feature;
|
return feature;
|
||||||
});
|
});
|
||||||
|
|
||||||
var deltaX = evt.coordinate[0] - this.coordinate_[0];
|
var deltaX = evt.coordinate[0] - this.coordinate_[0];
|
||||||
var deltaY = evt.coordinate[1] - this.coordinate_[1];
|
var deltaY = evt.coordinate[1] - this.coordinate_[1];
|
||||||
|
|
||||||
var geometry = /** @type {ol.geom.SimpleGeometry} */
|
var geometry = /** @type {ol.geom.SimpleGeometry} */
|
||||||
|
@ -1615,7 +1947,7 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
geometry.translate(deltaX, deltaY);
|
geometry.translate(deltaX, deltaY);
|
||||||
this.coordinate_[0] = evt.coordinate[0];
|
this.coordinate_[0] = evt.coordinate[0];
|
||||||
this.coordinate_[1] = evt.coordinate[1];
|
this.coordinate_[1] = evt.coordinate[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let coord = ol.proj.toLonLat(geometry.getCoordinates());
|
let coord = ol.proj.toLonLat(geometry.getCoordinates());
|
||||||
if (tempMarker.kind == "waypoint") {
|
if (tempMarker.kind == "waypoint") {
|
||||||
|
@ -1630,12 +1962,17 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
repaintLine4Waypoints(mission);
|
repaintLine4Waypoints(mission);
|
||||||
}
|
}
|
||||||
else if (tempMarker.kind == "safehome") {
|
else if (tempMarker.kind == "safehome") {
|
||||||
let tempSH = SAFEHOMES.getSafehome(tempMarker.number);
|
let tmpSafehome = SAFEHOMES.get()[tempMarker.number];
|
||||||
tempSH.setLon(Math.round(coord[0] * 10000000));
|
tmpSafehome.setLon(Math.round(coord[0] * 1e7));
|
||||||
tempSH.setLat(Math.round(coord[1] * 10000000));
|
tmpSafehome.setLat(Math.round(coord[1] * 1e7));
|
||||||
SAFEHOMES.updateSafehome(tempSH);
|
|
||||||
$safehomesTableBody.find('tr:nth-child('+String(tempMarker.number+1)+') > td > .safehome-lon').val(Math.round(coord[0] * 10000000) / 10000000);
|
$('#safeHomeLongitude').val(Math.round(coord[0] * 1e7));
|
||||||
$safehomesTableBody.find('tr:nth-child('+String(tempMarker.number+1)+') > td > .safehome-lat').val(Math.round(coord[1] * 10000000) / 10000000);
|
$('#safeHomeLatitude').val(Math.round(coord[1] * 1e7));
|
||||||
|
selectedSafehome = tempMarker.number;
|
||||||
|
|
||||||
|
cleanSafehomeLayers();
|
||||||
|
renderSafehomesOnMap();
|
||||||
|
renderSafehomesTable();
|
||||||
}
|
}
|
||||||
else if (tempMarker.kind == "home") {
|
else if (tempMarker.kind == "home") {
|
||||||
HOME.setLon(Math.round(coord[0] * 10000000));
|
HOME.setLon(Math.round(coord[0] * 10000000));
|
||||||
|
@ -1692,6 +2029,21 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
plotElevation();
|
plotElevation();
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
else if (tempMarker.kind == "safehome") {
|
||||||
|
(async () => {
|
||||||
|
let safehome = SAFEHOMES.get()[tempMarker.number];
|
||||||
|
const elevation = await safehome.getElevationFromServer(globalSettings) * 100;
|
||||||
|
$('#safehomeElevation').text(elevation / 100 + " m");
|
||||||
|
if (safehome.getIsSeaLevelRef()) {
|
||||||
|
if ( safehome.getElevation() != 0) {
|
||||||
|
safehome.setApproachAltAsl(safehome.getApproachAltAsl() - safehome.getElevation() + elevation);
|
||||||
|
safehome.setLandAltAsl(safehome.getLandAltAsl() - safehome.getElevation() + elevation);
|
||||||
|
}
|
||||||
|
safehome.setElevation(elevation);
|
||||||
|
renderSafehomesTable();
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
this.coordinate_ = null;
|
this.coordinate_ = null;
|
||||||
this.feature_ = null;
|
this.feature_ = null;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1883,12 +2235,8 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (selectedFeature && tempMarker.kind == "safehome" && tempMarker.selection) {
|
else if (selectedFeature && tempMarker.kind == "safehome" && tempMarker.selection) {
|
||||||
selectedMarker = SAFEHOMES.getSafehome(tempMarker.number);
|
selectedSafehome = tempMarker.number;
|
||||||
var geometry = selectedFeature.getGeometry();
|
renderSafehomesTable();
|
||||||
var coord = ol.proj.toLonLat(geometry.getCoordinates());
|
|
||||||
$safehomesTableBody.find('tr:nth-child('+String(tempMarker.number+1)+') > td > .safehome-enabled-value').val(selectedMarker.isUsed());
|
|
||||||
$safehomesTableBody.find('tr:nth-child('+String(tempMarker.number+1)+') > td > .safehome-lon').val(Math.round(coord[0] * 10000000) / 10000000);
|
|
||||||
$safehomesTableBody.find('tr:nth-child('+String(tempMarker.number+1)+') > td > .safehome-lat').val(Math.round(coord[1] * 10000000) / 10000000);
|
|
||||||
}
|
}
|
||||||
else if (selectedFeature && tempMarker.kind == "home" && tempMarker.selection) {
|
else if (selectedFeature && tempMarker.kind == "home" && tempMarker.selection) {
|
||||||
selectedMarker = HOME;
|
selectedMarker = HOME;
|
||||||
|
@ -1926,10 +2274,14 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
$(map.getViewport()).on('mousemove', function (e) {
|
$(map.getViewport()).on('mousemove', function (e) {
|
||||||
var pixel = map.getEventPixel(e.originalEvent);
|
var pixel = map.getEventPixel(e.originalEvent);
|
||||||
|
var name = "";
|
||||||
var hit = map.forEachFeatureAtPixel(pixel, function (feature, layer) {
|
var hit = map.forEachFeatureAtPixel(pixel, function (feature, layer) {
|
||||||
|
if (feature) {
|
||||||
|
name = feature.getProperties().name;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (hit) {
|
if (hit && name != "safehomeDist" && name != "safehomeSafe") {
|
||||||
map.getTarget().style.cursor = 'pointer';
|
map.getTarget().style.cursor = 'pointer';
|
||||||
} else {
|
} else {
|
||||||
map.getTarget().style.cursor = '';
|
map.getTarget().style.cursor = '';
|
||||||
|
@ -2242,6 +2594,7 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
// Callback for SAFEHOMES Table
|
// Callback for SAFEHOMES Table
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
/*
|
||||||
$safehomesTableBody.on('click', "[data-role='safehome-center']", function (event) {
|
$safehomesTableBody.on('click', "[data-role='safehome-center']", function (event) {
|
||||||
let mapCenter = map.getView().getCenter();
|
let mapCenter = map.getView().getCenter();
|
||||||
let tmpSH = SAFEHOMES.getSafehome($(event.currentTarget).attr("data-index"));
|
let tmpSH = SAFEHOMES.getSafehome($(event.currentTarget).attr("data-index"));
|
||||||
|
@ -2252,6 +2605,11 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
cleanSafehomeLayers();
|
cleanSafehomeLayers();
|
||||||
renderSafehomesOnMap();
|
renderSafehomesOnMap();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
$('#addSafehome').on('click', () => {
|
||||||
|
addSafehome();
|
||||||
|
});
|
||||||
|
|
||||||
$('#cancelSafehome').on('click', function () {
|
$('#cancelSafehome').on('click', function () {
|
||||||
closeSafehomePanel();
|
closeSafehomePanel();
|
||||||
|
@ -2265,6 +2623,7 @@ TABS.mission_control.initialize = function (callback) {
|
||||||
renderSafehomesTable();
|
renderSafehomesTable();
|
||||||
cleanSafehomeLayers();
|
cleanSafehomeLayers();
|
||||||
renderSafehomesOnMap();
|
renderSafehomesOnMap();
|
||||||
|
updateSafehomeInfo();
|
||||||
GUI.log('End of getting Safehome points');
|
GUI.log('End of getting Safehome points');
|
||||||
$('#loadEepromSafehomeButton').removeClass('disabled');
|
$('#loadEepromSafehomeButton').removeClass('disabled');
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue