mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-20 23:05:13 +03:00
Offline missions (with FC disconnected) on file (#720)
* Offline missions (with FC disconnected) are now available for load and save to file. Supports XML file format, should be compatible enough with other software * removed default file name * removed code in early stage of future developments * code style and fc buttons * map resize handling
This commit is contained in:
parent
cec7997bfc
commit
3dcffdd292
6 changed files with 349 additions and 74 deletions
|
@ -2719,6 +2719,18 @@
|
|||
"saveEepromMissionButton": {
|
||||
"message": "Save Eeprom mission"
|
||||
},
|
||||
"loadFileMissionButton": {
|
||||
"message": "Load file"
|
||||
},
|
||||
"saveFileMissionButton": {
|
||||
"message": "Save file"
|
||||
},
|
||||
"missionSettingsSave": {
|
||||
"message": "Save"
|
||||
},
|
||||
"missionSettingsCancel": {
|
||||
"message": "Cancel"
|
||||
},
|
||||
"editPointHead": {
|
||||
"message": "Edit point"
|
||||
},
|
||||
|
|
|
@ -13,6 +13,7 @@ var GUI_control = function () {
|
|||
this.defaultAllowedTabsWhenDisconnected = [
|
||||
'landing',
|
||||
'firmware_flasher',
|
||||
'mission_control',
|
||||
'help'
|
||||
];
|
||||
this.defaultAllowedTabsWhenConnected = [
|
||||
|
|
|
@ -165,6 +165,7 @@
|
|||
title="Welcome"></a></li>
|
||||
<li class="tab_help"><a href="https://github.com/iNavFlight/inav/wiki" target="_blank" data-i18n="tabHelp" class="tabicon ic_help"
|
||||
title="Documentation & Support"></a></li>
|
||||
<li class="tab_mission_control"><a href="#" data-i18n="tabMissionControl" class="tabicon ic_mission" title="Mission Control"></a></li>
|
||||
<li class="tab_firmware_flasher"><a href="#" data-i18n="tabFirmwareFlasher" class="tabicon ic_flasher"
|
||||
title="Firmware Flasher"></a></li>
|
||||
</ul>
|
||||
|
|
|
@ -34,8 +34,10 @@
|
|||
"minimist": "^1.2.0",
|
||||
"nw": "^0.36.1-sdk",
|
||||
"nw-builder": "^3.5.7",
|
||||
"nw-dialog": "^1.0.7",
|
||||
"openlayers": "^4.6.5",
|
||||
"temp": "^0.8.3",
|
||||
"three": "0.72.0"
|
||||
"three": "0.72.0",
|
||||
"xml2js": "^0.4.19"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,17 @@
|
|||
</div>
|
||||
<div class="spacer">
|
||||
<div class="point">
|
||||
<label class="point-label" for="pointAlt">Alt (cm): </label>
|
||||
<label class="point-label" for="MPdefaultPointAlt">Alt (cm): </label>
|
||||
<input id="MPdefaultPointAlt" type="text" value="0" required>
|
||||
</div>
|
||||
<div class="point">
|
||||
<label class="point-label" for="pointSpeed">Speed (cm/s): </label>
|
||||
<label class="point-label" for="MPdefaultPointSpeed">Speed (cm/s): </label>
|
||||
<input id="MPdefaultPointSpeed" type="text" value="0" required>
|
||||
</div>
|
||||
<div>
|
||||
<div id="saveSettings" class="btn save_btn" style="padding-top: 10px; display: inline-block">
|
||||
<a class="save" href="#" data-i18n="editPointButtonSave" style="float: left">Save</a>
|
||||
<div class="btn save_btn" style="padding-top: 10px;">
|
||||
<a id="saveSettings" class="save" href="#" data-i18n="missionSettingsSave" style="float: left">Save</a>
|
||||
<a id="cancelSettings" class="save" href="#" data-i18n="missionSettingsCancel" style="float: right">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -33,15 +34,15 @@
|
|||
<div class="spacer_box_title i18n-replaced" data-i18n="missionTotalInformationHead">Total information</div>
|
||||
</div>
|
||||
<div class="spacer">
|
||||
<div style="padding-bottom: 2px;">
|
||||
<div id="infoMissionDistance" style="padding-bottom: 2px;">
|
||||
<span>Distance (m):</span>
|
||||
<span id="missionDistance"></span>
|
||||
</div>
|
||||
<div style="padding-bottom: 2px;">
|
||||
<div id="infoAvailablePoints" style="padding-bottom: 2px;">
|
||||
<span>Available Points</span>
|
||||
<span id="availablePoints">0/0</span>
|
||||
</div>
|
||||
<div style="padding-bottom: 2px;">
|
||||
<div id="infoMissionValid" style="padding-bottom: 2px;">
|
||||
<span>Mission valid</span>
|
||||
<div id="missionValid" style="display: inline-block"></div>
|
||||
</div>
|
||||
|
@ -57,6 +58,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="btn save_btn">
|
||||
<a id="loadFileMissionButton" class="save" href="#" data-i18n="loadFileMissionButton">Load file mission</a>
|
||||
<a id="saveFileMissionButton" class="save" href="#" data-i18n="saveFileMissionButton">Save file mission</a>
|
||||
</div>
|
||||
<div class="btn save_btn">
|
||||
<a id="loadMissionButton" class="save" href="#" data-i18n="loadMissionButton">Load mission from FC</a>
|
||||
<a id="saveMissionButton" class="save" href="#" data-i18n="saveMissionButton">Save mission to FC</a>
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
// MultiWii NAV Protocol
|
||||
var MWNP = MWNP || {};
|
||||
|
||||
// WayPoint type
|
||||
MWNP.WPTYPE = {
|
||||
WAYPOINT: 1,
|
||||
PH_UNLIM: 2,
|
||||
PH_TIME: 3,
|
||||
RTH: 4,
|
||||
SET_POI: 5,
|
||||
JUMP: 6,
|
||||
SET_HEAD: 7,
|
||||
LAND: 8
|
||||
};
|
||||
|
||||
|
||||
TABS.mission_control = {};
|
||||
TABS.mission_control.isYmapLoad = false;
|
||||
TABS.mission_control.initialize = function (callback) {
|
||||
|
@ -9,37 +25,46 @@ TABS.mission_control.initialize = function (callback) {
|
|||
googleAnalytics.sendAppView('Mission Control');
|
||||
}
|
||||
|
||||
if (CONFIGURATOR.connectionValid) {
|
||||
var loadChainer = new MSPChainerClass();
|
||||
loadChainer.setChain([
|
||||
mspHelper.getMissionInfo
|
||||
]);
|
||||
loadChainer.setExitPoint(loadHtml);
|
||||
loadChainer.execute();
|
||||
} else {
|
||||
|
||||
// FC not connected, load page anyway
|
||||
loadHtml();
|
||||
}
|
||||
|
||||
function updateTotalInfo() {
|
||||
if (CONFIGURATOR.connectionValid) {
|
||||
$('#availablePoints').text(MISSION_PLANER.countBusyPoints + '/' + MISSION_PLANER.maxWaypoints);
|
||||
$('#missionValid').html(MISSION_PLANER.isValidMission ? chrome.i18n.getMessage('armingCheckPass') : chrome.i18n.getMessage('armingCheckFail'));
|
||||
}
|
||||
}
|
||||
|
||||
function loadHtml() {
|
||||
$('#content').load("./tabs/mission_control.html", process_html);
|
||||
}
|
||||
|
||||
function process_html() {
|
||||
if (typeof require !== "undefined") {
|
||||
chrome.storage.local.get('missionPlanerSettings', function (result) {
|
||||
if (result.missionPlanerSettings) {
|
||||
$('#MPdefaultPointAlt').val(result.missionPlanerSettings.alt);
|
||||
$('#MPdefaultPointSpeed').val(result.missionPlanerSettings.speed);
|
||||
} else {
|
||||
chrome.storage.local.set({'missionPlanerSettings': {speed: 0, alt: 5000}});
|
||||
$('#MPdefaultPointAlt').val(5000);
|
||||
$('#MPdefaultPointSpeed').val(0);
|
||||
|
||||
// set GUI for offline operations
|
||||
if (!CONFIGURATOR.connectionValid) {
|
||||
$('#infoAvailablePoints').hide();
|
||||
$('#infoMissionValid').hide();
|
||||
$('#loadMissionButton').hide();
|
||||
$('#saveMissionButton').hide();
|
||||
$('#loadEepromMissionButton').hide();
|
||||
$('#saveEepromMissionButton').hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
initMap();
|
||||
if (typeof require !== "undefined") {
|
||||
loadSettings();
|
||||
// let the dom load finish, avoiding the resizing of the map
|
||||
setTimeout(initMap, 200);
|
||||
} else {
|
||||
$('#missionMap, #missionControls').hide();
|
||||
$('#notLoadMap').show();
|
||||
|
@ -54,6 +79,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
var map;
|
||||
var selectedMarker = null;
|
||||
var pointForSend = 0;
|
||||
var settings = { speed: 0, alt: 5000 };
|
||||
|
||||
function clearEditForm() {
|
||||
$('#pointLat').val('');
|
||||
|
@ -64,6 +90,25 @@ TABS.mission_control.initialize = function (callback) {
|
|||
$('#MPeditPoint').fadeOut(300);
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
chrome.storage.local.get('missionPlanerSettings', function (result) {
|
||||
if (result.missionPlanerSettings) {
|
||||
settings = result.missionPlanerSettings;
|
||||
}
|
||||
|
||||
refreshSettings();
|
||||
});
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
chrome.storage.local.set({'missionPlanerSettings': settings});
|
||||
}
|
||||
|
||||
function refreshSettings() {
|
||||
$('#MPdefaultPointAlt').val(settings.alt);
|
||||
$('#MPdefaultPointSpeed').val(settings.speed);
|
||||
}
|
||||
|
||||
function repaint() {
|
||||
var oldPos;
|
||||
for (var i in lines) {
|
||||
|
@ -122,16 +167,16 @@ TABS.mission_control.initialize = function (callback) {
|
|||
scale: 0.5,
|
||||
src: '../images/icons/cf_icon_position' + (isEdit ? '_edit' : '') + '.png'
|
||||
}))
|
||||
// text: new ol.style.Text({
|
||||
// text: '10',
|
||||
// offsetX: -1,
|
||||
// offsetY: -30,
|
||||
// overflow: true,
|
||||
// scale: 2,
|
||||
// fill: new ol.style.Fill({
|
||||
// color: 'black'
|
||||
// })
|
||||
// })
|
||||
/*
|
||||
text: new ol.style.Text({
|
||||
text: '10',
|
||||
offsetX: -1,
|
||||
offsetY: -30,
|
||||
overflow: true,
|
||||
scale: 2,
|
||||
fill: new ol.style.Fill({ color: 'black' })
|
||||
})
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -315,8 +360,8 @@ TABS.mission_control.initialize = function (callback) {
|
|||
return false;
|
||||
};
|
||||
|
||||
var lat = GPS_DATA.lat / 10000000;
|
||||
var lon = GPS_DATA.lon / 10000000;
|
||||
var lat = (GPS_DATA ? (GPS_DATA.lat / 10000000) : 0);
|
||||
var lon = (GPS_DATA ? (GPS_DATA.lon / 10000000) : 0);
|
||||
|
||||
let mapLayer;
|
||||
|
||||
|
@ -358,15 +403,26 @@ TABS.mission_control.initialize = function (callback) {
|
|||
|
||||
// Set the attribute link to open on an external browser window, so
|
||||
// it doesn't interfere with the configurator.
|
||||
var interval;
|
||||
interval = setInterval(function() {
|
||||
var anchor = $('.ol-attribution a');
|
||||
if (anchor.length) {
|
||||
anchor.attr('target', '_blank');
|
||||
clearInterval(interval);
|
||||
}
|
||||
setTimeout(function() {
|
||||
$('.ol-attribution a').attr('target', '_blank');
|
||||
}, 100);
|
||||
|
||||
// save map view settings when user moves it
|
||||
map.on('moveend', function (evt) {
|
||||
chrome.storage.local.set({'missionPlanerLastValues': {
|
||||
center: ol.proj.toLonLat(map.getView().getCenter()),
|
||||
zoom: map.getView().getZoom()
|
||||
}});
|
||||
});
|
||||
|
||||
// load map view settings on startup
|
||||
chrome.storage.local.get('missionPlanerLastValues', function (result) {
|
||||
if (result.missionPlanerLastValues && result.missionPlanerLastValues.center) {
|
||||
map.getView().setCenter(ol.proj.fromLonLat(result.missionPlanerLastValues.center));
|
||||
map.getView().setZoom(result.missionPlanerLastValues.zoom);
|
||||
}
|
||||
});
|
||||
|
||||
map.on('click', function (evt) {
|
||||
if (selectedMarker != null) {
|
||||
try {
|
||||
|
@ -392,14 +448,14 @@ TABS.mission_control.initialize = function (callback) {
|
|||
|
||||
selectedFeature.setStyle(getPointIcon(true));
|
||||
|
||||
$('#pointLon').val(coord[0]);
|
||||
$('#pointLat').val(coord[1]);
|
||||
$('#pointLon').val(Math.round(coord[0] * 10000000) / 10000000);
|
||||
$('#pointLat').val(Math.round(coord[1] * 10000000) / 10000000);
|
||||
$('#pointAlt').val(selectedMarker.alt);
|
||||
$('#pointType').val(selectedMarker.action);
|
||||
$('#pointSpeed').val(selectedMarker.speedValue);
|
||||
$('#MPeditPoint').fadeIn(300);
|
||||
} else {
|
||||
map.addLayer(addMarker(evt.coordinate, $('#MPdefaultPointAlt').val(), 1, $('#MPdefaultPointSpeed').val()));
|
||||
map.addLayer(addMarker(evt.coordinate, settings.alt, MWNP.WPTYPE.WAYPOINT, settings.speed));
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
|
@ -417,8 +473,15 @@ TABS.mission_control.initialize = function (callback) {
|
|||
}
|
||||
});
|
||||
|
||||
// handle map size on container resize
|
||||
setInterval(function () {
|
||||
let width = $("#missionMap canvas").width(), height = $("#missionMap canvas").height();
|
||||
if ((map.width_ != width) || (map.height_ != height)) map.updateSize();
|
||||
map.width_ = width; map.height_ = height;
|
||||
}, 200);
|
||||
|
||||
$('#removeAllPoints').on('click', function () {
|
||||
if (confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||
if (markers.length && confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||
removeAllPoints();
|
||||
}
|
||||
});
|
||||
|
@ -460,13 +523,28 @@ TABS.mission_control.initialize = function (callback) {
|
|||
}
|
||||
});
|
||||
|
||||
$('#loadMissionButton').on('click', function () {
|
||||
if (markers.length) {
|
||||
if (!confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||
return;
|
||||
}
|
||||
$('#loadFileMissionButton').on('click', function () {
|
||||
if (markers.length && !confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) return;
|
||||
removeAllPoints();
|
||||
var dialog = require('nw-dialog');
|
||||
dialog.setContext(document);
|
||||
dialog.openFileDialog(function(result) {
|
||||
loadMissionFile(result);
|
||||
})
|
||||
});
|
||||
|
||||
$('#saveFileMissionButton').on('click', function () {
|
||||
//if (!markers.length) return;
|
||||
var dialog = require('nw-dialog');
|
||||
dialog.setContext(document);
|
||||
dialog.saveFileDialog('', '.mission', function(result) {
|
||||
saveMissionFile(result);
|
||||
})
|
||||
});
|
||||
|
||||
$('#loadMissionButton').on('click', function () {
|
||||
if (markers.length && !confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) return;
|
||||
removeAllPoints();
|
||||
}
|
||||
$(this).addClass('disabled');
|
||||
GUI.log('Start get point');
|
||||
|
||||
|
@ -483,12 +561,8 @@ TABS.mission_control.initialize = function (callback) {
|
|||
});
|
||||
|
||||
$('#loadEepromMissionButton').on('click', function () {
|
||||
if (markers.length) {
|
||||
if (!confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||
return;
|
||||
}
|
||||
if (markers.length && !confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) return;
|
||||
removeAllPoints();
|
||||
}
|
||||
GUI.log(chrome.i18n.getMessage('eeprom_load_ok'));
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_WP_MISSION_LOAD, [0], getPointsFromEprom);
|
||||
|
@ -507,15 +581,25 @@ TABS.mission_control.initialize = function (callback) {
|
|||
});
|
||||
|
||||
$('#saveSettings').on('click', function () {
|
||||
chrome.storage.local.set({'missionPlanerSettings': {speed: $('#MPdefaultPointSpeed').val(), alt: $('#MPdefaultPointAlt').val()}});
|
||||
settings = { speed: $('#MPdefaultPointSpeed').val(), alt: $('#MPdefaultPointAlt').val() };
|
||||
saveSettings();
|
||||
closeSettingsPanel();
|
||||
});
|
||||
|
||||
$('#cancelSettings').on('click', function () {
|
||||
loadSettings();
|
||||
closeSettingsPanel();
|
||||
});
|
||||
|
||||
updateTotalInfo();
|
||||
}
|
||||
|
||||
function closeSettingsPanel() {
|
||||
$('#missionPlanerSettings').hide();
|
||||
$('#missionPalnerTotalInfo').fadeIn(300);
|
||||
if (selectedMarker !== null) {
|
||||
$('#MPeditPoint').fadeIn(300);
|
||||
}
|
||||
});
|
||||
|
||||
updateTotalInfo();
|
||||
}
|
||||
|
||||
function removeAllPoints() {
|
||||
|
@ -524,9 +608,179 @@ TABS.mission_control.initialize = function (callback) {
|
|||
}
|
||||
markers = [];
|
||||
clearEditForm();
|
||||
updateTotalInfo();
|
||||
$('#rthEndMission').prop('checked', false);
|
||||
$('#rthSettings').fadeOut(300);
|
||||
$('#rthLanding').prop('checked', false);
|
||||
repaint();
|
||||
}
|
||||
|
||||
function loadMissionFile(filename) {
|
||||
const fs = require('fs-extra');
|
||||
const xml2js = require('xml2js');
|
||||
|
||||
fs.readFile(filename, (err, data) => {
|
||||
if (err) {
|
||||
GUI.log('<span style="color: red">Error reading file</span>');
|
||||
return console.error(err);
|
||||
}
|
||||
|
||||
xml2js.Parser({ 'explicitChildren': true, 'preserveChildrenOrder': true }).parseString(data, (err, result) => {
|
||||
if (err) {
|
||||
GUI.log('<span style="color: red">Error parsing file</span>');
|
||||
return console.error(err);
|
||||
}
|
||||
|
||||
// parse mission file
|
||||
var mission = { points: [] };
|
||||
var node = null;
|
||||
var nodemission = null;
|
||||
for (var noderoot in result) {
|
||||
if (!nodemission && noderoot.match(/mission/i)) {
|
||||
nodemission = result[noderoot];
|
||||
if (nodemission.$$ && nodemission.$$.length) {
|
||||
for (var i = 0; i < nodemission.$$.length; i++) {
|
||||
node = nodemission.$$[i];
|
||||
if (node['#name'].match(/version/i) && node.$) {
|
||||
for (var attr in node.$) {
|
||||
if (attr.match(/value/i)) {
|
||||
mission.version = node.$[attr]
|
||||
}
|
||||
}
|
||||
} else if (node['#name'].match(/mwp/i) && node.$) {
|
||||
mission.center = {};
|
||||
for (var attr in node.$) {
|
||||
if (attr.match(/zoom/i)) {
|
||||
mission.center.zoom = parseInt(node.$[attr]);
|
||||
} else if (attr.match(/cx/i)) {
|
||||
mission.center.lon = parseFloat(node.$[attr]);
|
||||
} else if (attr.match(/cy/i)) {
|
||||
mission.center.lat = parseFloat(node.$[attr]);
|
||||
}
|
||||
}
|
||||
} else if (node['#name'].match(/missionitem/i) && node.$) {
|
||||
var point = {};
|
||||
for (var attr in node.$) {
|
||||
if (attr.match(/no/i)) {
|
||||
point.index = parseInt(node.$[attr]);
|
||||
} else if (attr.match(/action/i)) {
|
||||
if (node.$[attr].match(/WAYPOINT/i)) {
|
||||
point.action = MWNP.WPTYPE.WAYPOINT;
|
||||
} else if (node.$[attr].match(/PH_UNLIM/i) || node.$[attr].match(/POSHOLD_UNLIM/i)) {
|
||||
point.action = MWNP.WPTYPE.PH_UNLIM;
|
||||
} else if (node.$[attr].match(/PH_TIME/i) || node.$[attr].match(/POSHOLD_TIME/i)) {
|
||||
point.action = MWNP.WPTYPE.PH_TIME;
|
||||
} else if (node.$[attr].match(/RTH/i)) {
|
||||
point.action = MWNP.WPTYPE.RTH;
|
||||
} else if (node.$[attr].match(/SET_POI/i)) {
|
||||
point.action = MWNP.WPTYPE.SET_POI;
|
||||
} else if (node.$[attr].match(/JUMP/i)) {
|
||||
point.action = MWNP.WPTYPE.JUMP;
|
||||
} else if (node.$[attr].match(/SET_HEAD/i)) {
|
||||
point.action = MWNP.WPTYPE.SET_HEAD;
|
||||
} else if (node.$[attr].match(/LAND/i)) {
|
||||
point.action = MWNP.WPTYPE.LAND;
|
||||
} else {
|
||||
point.action = 0;
|
||||
}
|
||||
} else if (attr.match(/lat/i)) {
|
||||
point.lat = parseFloat(node.$[attr]);
|
||||
} else if (attr.match(/lon/i)) {
|
||||
point.lon = parseFloat(node.$[attr]);
|
||||
} else if (attr.match(/alt/i)) {
|
||||
point.alt = (parseInt(node.$[attr]) * 100);
|
||||
} else if (attr.match(/parameter1/i)) {
|
||||
point.p1 = parseInt(node.$[attr]);
|
||||
} else if (attr.match(/parameter2/i)) {
|
||||
point.p2 = parseInt(node.$[attr]);
|
||||
} else if (attr.match(/parameter3/i)) {
|
||||
point.p3 = parseInt(node.$[attr]);
|
||||
}
|
||||
}
|
||||
mission.points.push(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw actual mission
|
||||
removeAllPoints();
|
||||
for (var i = 0; i < mission.points.length; i++) {
|
||||
//if ([MWNP.WPTYPE.WAYPOINT,MWNP.WPTYPE.PH_UNLIM,MWNP.WPTYPE.PH_TIME,MWNP.WPTYPE.LAND].includes(mission.points[i].action)) {
|
||||
if (mission.points[i].action == MWNP.WPTYPE.WAYPOINT) {
|
||||
var coord = ol.proj.fromLonLat([mission.points[i].lon, mission.points[i].lat]);
|
||||
map.addLayer(addMarker(coord, mission.points[i].alt, mission.points[i].action, mission.points[i].p1));
|
||||
if (i == 0) {
|
||||
map.getView().setCenter(coord);
|
||||
map.getView().setZoom(16);
|
||||
}
|
||||
} else if (mission.points[i].action == MWNP.WPTYPE.RTH) {
|
||||
$('#rthEndMission').prop('checked', true);
|
||||
$('#rthSettings').fadeIn(300);
|
||||
if (mission.points[i].p1 > 0) {
|
||||
$('#rthLanding').prop('checked', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mission.center) {
|
||||
var coord = ol.proj.fromLonLat([mission.center.lon, mission.center.lat]);
|
||||
map.getView().setCenter(coord);
|
||||
if (mission.center.zoom) map.getView().setZoom(mission.center.zoom);
|
||||
}
|
||||
|
||||
repaint();
|
||||
updateTotalInfo();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function saveMissionFile(filename) {
|
||||
const fs = require('fs-extra');
|
||||
const xml2js = require('xml2js');
|
||||
|
||||
var center = ol.proj.toLonLat(map.getView().getCenter());
|
||||
var zoom = map.getView().getZoom();
|
||||
|
||||
var data = {
|
||||
'version': { $: { 'value': '2.3-pre8' } },
|
||||
'mwp': { $: { 'cx': (Math.round(center[0] * 10000000) / 10000000), 'cy': (Math.round(center[1] * 10000000) / 10000000), 'zoom': zoom } },
|
||||
'missionitem': []
|
||||
};
|
||||
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
var geometry = markers[i].getSource().getFeatures()[0].getGeometry();
|
||||
var coordinate = ol.proj.toLonLat(geometry.getCoordinates());
|
||||
var point = { $: {
|
||||
'no': (i + 1),
|
||||
'action': ((markers[i].action == MWNP.WPTYPE.WAYPOINT) ? 'WAYPOINT' : markers[i].action),
|
||||
'lon': (Math.round(coordinate[0] * 10000000) / 10000000),
|
||||
'lat': (Math.round(coordinate[1] * 10000000) / 10000000),
|
||||
'alt': (markers[i].alt / 100)
|
||||
} };
|
||||
if ((markers[i].action == MWNP.WPTYPE.WAYPOINT) && (markers[i].speedValue > 0)) point.$['parameter1'] = markers[i].speedValue;
|
||||
data.missionitem.push(point);
|
||||
}
|
||||
|
||||
// add last RTH point
|
||||
if ($('#rthEndMission').is(':checked')) {
|
||||
data.missionitem.push({ $: { 'no': (markers.length + 1), 'action': 'RTH', 'lon': 0, 'lat': 0, 'alt': (settings.alt / 100), 'parameter1': ($('#rthLanding').is(':checked') ? 1 : 0) } });
|
||||
}
|
||||
|
||||
var builder = new xml2js.Builder({ 'rootName': 'mission', 'renderOpts': { 'pretty': true, 'indent': '\t', 'newline': '\n' } });
|
||||
var xml = builder.buildObject(data);
|
||||
fs.writeFile(filename, xml, (err) => {
|
||||
if (err) {
|
||||
GUI.log('<span style="color: red">Error writing file</span>');
|
||||
return console.error(err);
|
||||
}
|
||||
GUI.log('File saved');
|
||||
});
|
||||
}
|
||||
|
||||
function getPointsFromEprom() {
|
||||
pointForSend = 0;
|
||||
MSP.send_message(MSPCodes.MSP_WP_GETINFO, false, false, getNextPoint);
|
||||
|
@ -551,10 +805,10 @@ TABS.mission_control.initialize = function (callback) {
|
|||
// console.log(MISSION_PLANER.bufferPoint.alt);
|
||||
// console.log(MISSION_PLANER.bufferPoint.action);
|
||||
if (MISSION_PLANER.bufferPoint.action == 4) {
|
||||
$('#rthEndMission').attr('checked', true);
|
||||
$('#rthEndMission').prop('checked', true);
|
||||
$('#rthSettings').fadeIn(300);
|
||||
if (MISSION_PLANER.bufferPoint.p1 > 0) {
|
||||
$('#rthLanding').attr('checked', true);
|
||||
$('#rthLanding').prop('checked', true);
|
||||
}
|
||||
} else {
|
||||
var coord = ol.proj.fromLonLat([MISSION_PLANER.bufferPoint.lon, MISSION_PLANER.bufferPoint.lat]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue