Merge remote-tracking branch 'origin/master' into dzikuvx-new-mixer-approach
After Width: | Height: | Size: 4.9 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
function debugTraceOnLoad()
|
||||||
|
{
|
||||||
|
var output = document.getElementById('debug-trace');
|
||||||
|
setInterval(function() {
|
||||||
|
output.innerText = getDebugTrace();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = debugTraceOnLoad;
|
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 248 B |
After Width: | Height: | Size: 227 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 248 B |
After Width: | Height: | Size: 227 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 248 B |
@ -0,0 +1,127 @@
|
|||||||
|
.tab-mission-control .btn a {
|
||||||
|
/* common styles for content toolbar buttons */
|
||||||
|
/*margin-top: 0;*/
|
||||||
|
/*margin-bottom: 0;*/
|
||||||
|
/*margin-right: 20px;*/
|
||||||
|
background-color: #37a8db;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #3394b5;
|
||||||
|
color: #fff;
|
||||||
|
/*float: right;*/
|
||||||
|
font-family: 'open_sansbold', Arial, serif;
|
||||||
|
font-size: 12px;
|
||||||
|
text-shadow: 0 1px rgba(0, 0, 0, 0.25);
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
padding: 0 9px;
|
||||||
|
line-height: 28px;
|
||||||
|
margin: 5px;
|
||||||
|
float: left;
|
||||||
|
width: 130px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .btn a:hover {
|
||||||
|
background-color: #3394b5;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .btn a:active {
|
||||||
|
background-color: #37a8db;
|
||||||
|
transition: all ease 0.0s;
|
||||||
|
box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .btn a.disabled {
|
||||||
|
cursor: default;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #AFAFAF;
|
||||||
|
border: 1px solid #AFAFAF;
|
||||||
|
pointer-events: none;
|
||||||
|
text-shadow: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .btn-danger a {
|
||||||
|
background-color: #db250e;
|
||||||
|
border: 1px solid #b5480e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .btn-danger a:hover {
|
||||||
|
background-color: #b5480e;
|
||||||
|
transition: all ease 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .checksfail {
|
||||||
|
/*float: right;*/
|
||||||
|
margin-top: 3px;
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
background-image:url(../../../images/icons/nopass.svg);
|
||||||
|
background-size:contain;
|
||||||
|
background-position:center;
|
||||||
|
background-repeat:no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .content_wrapper {
|
||||||
|
display: flex;
|
||||||
|
/*height: 150px;*/
|
||||||
|
height: 90%;
|
||||||
|
/*width: 75%;*/
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#missionMap {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control input {
|
||||||
|
width: 115px;
|
||||||
|
padding-left: 3px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid silver;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control select {
|
||||||
|
width: 118px;
|
||||||
|
padding-left: 3px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid silver;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-mission-control .point {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.tab-mission-control .point-label {
|
||||||
|
width: 60px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mission-control-settings {
|
||||||
|
top: 65px;
|
||||||
|
left: .5em;
|
||||||
|
}
|
||||||
|
.ol-touch .mission-control-settings {
|
||||||
|
top: 80px;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Debug Trace</title>
|
||||||
|
<script type="text/javascript" src="/build/debug-trace.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre><code id="debug-trace"></code></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,119 @@
|
|||||||
|
<div class="tab-mission-control">
|
||||||
|
<div style="padding-top: 20px;padding-left: 20px; padding-right: 20px;position: relative;">
|
||||||
|
<div class="tab_title" data-i18n="tabMissionControl">Mission planer</div>
|
||||||
|
<div class="cf_doc_version_bt">
|
||||||
|
<a id="button-documentation" href="https://github.com/iNavFlight/inav/releases" target="_blank"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content_wrapper">
|
||||||
|
<div class="cf_column fourth" id="missionControls">
|
||||||
|
<div class="spacer_right">
|
||||||
|
<div id="missionPlanerSettings" class="gui_box grey" style="display: none">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title i18n-replaced" data-i18n="missionDefaultSettingsHead">Default settings</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer">
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointAlt">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>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="missionPalnerTotalInfo" class="gui_box grey">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title i18n-replaced" data-i18n="missionTotalInformationHead">Total information</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer">
|
||||||
|
<div style="padding-bottom: 2px;">
|
||||||
|
<span>Distance (m):</span>
|
||||||
|
<span id="missionDistance"></span>
|
||||||
|
</div>
|
||||||
|
<div style="padding-bottom: 2px;">
|
||||||
|
<span>Available Points</span>
|
||||||
|
<span id="availablePoints">0/0</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding-bottom: 2px;">
|
||||||
|
<span>Mission valid</span>
|
||||||
|
<div id="missionValid" style="display: inline-block"></div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div style="display: flex;">
|
||||||
|
<input type="checkbox" style="width: 18px;margin-left: 5px;" id="rthEndMission">
|
||||||
|
<label for="rthEndMission" style="padding: 2px;">RTH at the end of the mission</label>
|
||||||
|
</div>
|
||||||
|
<div id="rthSettings" style="display: none">
|
||||||
|
<div style="display: flex">
|
||||||
|
<input type="checkbox" id="rthLanding" style="width: 18px;margin-left: 5px;">
|
||||||
|
<label for="rthLanding" style="padding: 2px">Landing</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<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>
|
||||||
|
<a id="loadEepromMissionButton" class="save" href="#" data-i18n="loadEepromMissionButton">Load Eeprom mission</a>
|
||||||
|
<a id="saveEepromMissionButton" class="save" href="#" data-i18n="saveEepromMissionButton">Save Eeprom mission</a>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div id="removeAllPoints" class="btn btn-danger" style="padding-top: 10px; display: inline-block">
|
||||||
|
<a class="save" href="#" data-i18n="removeAllPointButtonSave" style="float: left">Remove all points</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gui_box grey" id="MPeditPoint" style="display: none">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title i18n-replaced" data-i18n="editPointHead">Edit point</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer">
|
||||||
|
<input type="hidden" name="pointNumber" value="">
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointType">Type: </label>
|
||||||
|
<select name="type" id="pointType">
|
||||||
|
<!--<option value="1">Home</option>-->
|
||||||
|
<option value="1">Waypoint</option>
|
||||||
|
<!--<option value="4">RTH</option>-->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointLat">Lat: </label>
|
||||||
|
<input id="pointLat" type="text" value="0.0" required>
|
||||||
|
</div>
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointLon">Lon: </label>
|
||||||
|
<input id="pointLon" type="text" value="0.0" required>
|
||||||
|
</div>
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointAlt">Alt (cm): </label>
|
||||||
|
<input id="pointAlt" type="text" value="0" required>
|
||||||
|
</div>
|
||||||
|
<div class="point">
|
||||||
|
<label class="point-label" for="pointSpeed">Speed (cm/s): </label>
|
||||||
|
<input id="pointSpeed" type="text" value="0" required>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id="savePoint" class="btn save_btn" style="padding-top: 10px; display: inline-block">
|
||||||
|
<a class="save" href="#" data-i18n="editPointButtonSave" style="float: left">Save</a>
|
||||||
|
</div>
|
||||||
|
<div id="removePoint" class="btn btn-danger" style="padding-top: 10px; display: inline-block;">
|
||||||
|
<a class="save" href="#" data-i18n="editPointButtonRemove" style="float: left">Remove</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cf_column threefourth_left">
|
||||||
|
<div id="missionMap"></div>
|
||||||
|
<div id="notLoadMap" data-i18n="useOnlyStandalone" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,602 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
TABS.mission_control = {};
|
||||||
|
TABS.mission_control.isYmapLoad = false;
|
||||||
|
TABS.mission_control.initialize = function (callback) {
|
||||||
|
|
||||||
|
if (GUI.active_tab != 'mission_control') {
|
||||||
|
GUI.active_tab = 'mission_control';
|
||||||
|
googleAnalytics.sendAppView('Mission Control');
|
||||||
|
}
|
||||||
|
|
||||||
|
var loadChainer = new MSPChainerClass();
|
||||||
|
loadChainer.setChain([
|
||||||
|
mspHelper.getMissionInfo
|
||||||
|
]);
|
||||||
|
loadChainer.setExitPoint(loadHtml);
|
||||||
|
loadChainer.execute();
|
||||||
|
|
||||||
|
function updateTotalInfo() {
|
||||||
|
$('#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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
initMap();
|
||||||
|
} else {
|
||||||
|
$('#missionMap, #missionControls').hide();
|
||||||
|
$('#notLoadMap').show();
|
||||||
|
}
|
||||||
|
localize();
|
||||||
|
|
||||||
|
GUI.content_ready(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
var markers = [];
|
||||||
|
var lines = [];
|
||||||
|
var map;
|
||||||
|
var selectedMarker = null;
|
||||||
|
var pointForSend = 0;
|
||||||
|
|
||||||
|
function clearEditForm() {
|
||||||
|
$('#pointLat').val('');
|
||||||
|
$('#pointLon').val('');
|
||||||
|
$('#pointAlt').val('');
|
||||||
|
$('#pointSpeed').val('');
|
||||||
|
$('[name=pointNumber]').val('');
|
||||||
|
$('#MPeditPoint').fadeOut(300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function repaint() {
|
||||||
|
var oldPos;
|
||||||
|
for (var i in lines) {
|
||||||
|
map.removeLayer(lines[i]);
|
||||||
|
}
|
||||||
|
lines = [];
|
||||||
|
$('#missionDistance').text(0);
|
||||||
|
|
||||||
|
map.getLayers().forEach(function (t) {
|
||||||
|
//feature.getGeometry().getType()
|
||||||
|
if (t instanceof ol.layer.Vector && typeof t.alt !== 'undefined') {
|
||||||
|
var geometry = t.getSource().getFeatures()[0].getGeometry();
|
||||||
|
if (typeof oldPos !== 'undefined') {
|
||||||
|
paintLine(oldPos, geometry.getCoordinates());
|
||||||
|
}
|
||||||
|
|
||||||
|
oldPos = geometry.getCoordinates();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function paintLine(pos1, pos2) {
|
||||||
|
var line = new ol.geom.LineString([pos1, pos2]);
|
||||||
|
|
||||||
|
var feature = new ol.Feature({
|
||||||
|
geometry: line
|
||||||
|
});
|
||||||
|
feature.setStyle(new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({
|
||||||
|
color: '#1497f1',
|
||||||
|
width: 3
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
var vectorSource = new ol.source.Vector({
|
||||||
|
features: [feature]
|
||||||
|
});
|
||||||
|
|
||||||
|
var vectorLayer = new ol.layer.Vector({
|
||||||
|
source: vectorSource
|
||||||
|
});
|
||||||
|
|
||||||
|
lines.push(vectorLayer);
|
||||||
|
|
||||||
|
var length = ol.Sphere.getLength(line) + parseFloat($('#missionDistance').text());
|
||||||
|
$('#missionDistance').text(length.toFixed(3));
|
||||||
|
|
||||||
|
map.addLayer(vectorLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointIcon(isEdit) {
|
||||||
|
return new ol.style.Style({
|
||||||
|
image: new ol.style.Icon(({
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
opacity: 1,
|
||||||
|
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'
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMarker(_pos, _alt, _action, _speed) {
|
||||||
|
var iconFeature = new ol.Feature({
|
||||||
|
geometry: new ol.geom.Point(_pos),
|
||||||
|
name: 'Null Island',
|
||||||
|
population: 4000,
|
||||||
|
rainfall: 500
|
||||||
|
});
|
||||||
|
|
||||||
|
iconFeature.setStyle(getPointIcon());
|
||||||
|
|
||||||
|
var vectorSource = new ol.source.Vector({
|
||||||
|
features: [iconFeature]
|
||||||
|
});
|
||||||
|
|
||||||
|
var vectorLayer = new ol.layer.Vector({
|
||||||
|
source: vectorSource
|
||||||
|
});
|
||||||
|
|
||||||
|
vectorLayer.alt = _alt;
|
||||||
|
vectorLayer.number = markers.length;
|
||||||
|
vectorLayer.action = _action;
|
||||||
|
vectorLayer.speedValue = _speed;
|
||||||
|
|
||||||
|
markers.push(vectorLayer);
|
||||||
|
|
||||||
|
return vectorLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMap() {
|
||||||
|
var app = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.interaction.Pointer}
|
||||||
|
*/
|
||||||
|
app.Drag = function () {
|
||||||
|
|
||||||
|
ol.interaction.Pointer.call(this, {
|
||||||
|
handleDownEvent: app.Drag.prototype.handleDownEvent,
|
||||||
|
handleDragEvent: app.Drag.prototype.handleDragEvent,
|
||||||
|
handleMoveEvent: app.Drag.prototype.handleMoveEvent,
|
||||||
|
handleUpEvent: app.Drag.prototype.handleUpEvent
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ol.Pixel}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.coordinate_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.cursor_ = 'pointer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ol.Feature}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.feature_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.previousCursor_ = undefined;
|
||||||
|
|
||||||
|
};
|
||||||
|
ol.inherits(app.Drag, ol.interaction.Pointer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.control.Control}
|
||||||
|
* @param {Object=} opt_options Control options.
|
||||||
|
*/
|
||||||
|
app.PlannerSettingsControl = function (opt_options) {
|
||||||
|
var options = opt_options || {};
|
||||||
|
var button = document.createElement('button');
|
||||||
|
|
||||||
|
button.innerHTML = ' ';
|
||||||
|
button.style = 'background: url(\'../images/CF_settings_white.svg\') no-repeat 1px -1px;background-color: rgba(0,60,136,.5);';
|
||||||
|
|
||||||
|
var handleShowSettings = function () {
|
||||||
|
$('#MPeditPoint, #missionPalnerTotalInfo').hide();
|
||||||
|
$('#missionPlanerSettings').fadeIn(300);
|
||||||
|
};
|
||||||
|
|
||||||
|
button.addEventListener('click', handleShowSettings, false);
|
||||||
|
button.addEventListener('touchstart', handleShowSettings, false);
|
||||||
|
|
||||||
|
var element = document.createElement('div');
|
||||||
|
element.className = 'mission-control-settings ol-unselectable ol-control';
|
||||||
|
element.appendChild(button);
|
||||||
|
element.title = 'MP Settings';
|
||||||
|
|
||||||
|
ol.control.Control.call(this, {
|
||||||
|
element: element,
|
||||||
|
target: options.target
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
ol.inherits(app.PlannerSettingsControl, ol.control.Control);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||||
|
* @return {boolean} `true` to start the drag sequence.
|
||||||
|
*/
|
||||||
|
app.Drag.prototype.handleDownEvent = function (evt) {
|
||||||
|
var map = evt.map;
|
||||||
|
|
||||||
|
var feature = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
function (feature, layer) {
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (feature) {
|
||||||
|
this.coordinate_ = evt.coordinate;
|
||||||
|
this.feature_ = feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!feature;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||||
|
*/
|
||||||
|
app.Drag.prototype.handleDragEvent = function (evt) {
|
||||||
|
var map = evt.map;
|
||||||
|
|
||||||
|
var feature = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
function (feature, layer) {
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
|
||||||
|
var deltaX = evt.coordinate[0] - this.coordinate_[0];
|
||||||
|
var deltaY = evt.coordinate[1] - this.coordinate_[1];
|
||||||
|
|
||||||
|
var geometry = /** @type {ol.geom.SimpleGeometry} */
|
||||||
|
(this.feature_.getGeometry());
|
||||||
|
geometry.translate(deltaX, deltaY);
|
||||||
|
|
||||||
|
this.coordinate_[0] = evt.coordinate[0];
|
||||||
|
this.coordinate_[1] = evt.coordinate[1];
|
||||||
|
repaint();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.MapBrowserEvent} evt Event.
|
||||||
|
*/
|
||||||
|
app.Drag.prototype.handleMoveEvent = function (evt) {
|
||||||
|
if (this.cursor_) {
|
||||||
|
var map = evt.map;
|
||||||
|
var feature = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
function (feature, layer) {
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
var element = evt.map.getTargetElement();
|
||||||
|
if (feature) {
|
||||||
|
if (element.style.cursor != this.cursor_) {
|
||||||
|
this.previousCursor_ = element.style.cursor;
|
||||||
|
element.style.cursor = this.cursor_;
|
||||||
|
}
|
||||||
|
} else if (this.previousCursor_ !== undefined) {
|
||||||
|
element.style.cursor = this.previousCursor_;
|
||||||
|
this.previousCursor_ = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||||
|
* @return {boolean} `false` to stop the drag sequence.
|
||||||
|
*/
|
||||||
|
app.Drag.prototype.handleUpEvent = function (evt) {
|
||||||
|
this.coordinate_ = null;
|
||||||
|
this.feature_ = null;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var lat = GPS_DATA.lat / 10000000;
|
||||||
|
var lon = GPS_DATA.lon / 10000000;
|
||||||
|
|
||||||
|
map = new ol.Map({
|
||||||
|
controls: ol.control.defaults({
|
||||||
|
attributionOptions: {
|
||||||
|
collapsible: false
|
||||||
|
}
|
||||||
|
}).extend([
|
||||||
|
new app.PlannerSettingsControl()
|
||||||
|
]),
|
||||||
|
interactions: ol.interaction.defaults().extend([new app.Drag()]),
|
||||||
|
layers: [
|
||||||
|
new ol.layer.Tile({
|
||||||
|
source: new ol.source.OSM()
|
||||||
|
})
|
||||||
|
],
|
||||||
|
target: document.getElementById('missionMap'),
|
||||||
|
view: new ol.View({
|
||||||
|
center: ol.proj.fromLonLat([lon, lat]),
|
||||||
|
zoom: 14
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
map.on('click', function (evt) {
|
||||||
|
if (selectedMarker != null) {
|
||||||
|
try {
|
||||||
|
selectedMarker.getSource().getFeatures()[0].setStyle(getPointIcon());
|
||||||
|
selectedMarker = null;
|
||||||
|
clearEditForm();
|
||||||
|
} catch (e) {
|
||||||
|
GUI.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedFeature = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
function (feature, layer) {
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
selectedMarker = map.forEachFeatureAtPixel(evt.pixel,
|
||||||
|
function (feature, layer) {
|
||||||
|
return layer;
|
||||||
|
});
|
||||||
|
if (selectedFeature) {
|
||||||
|
var geometry = selectedFeature.getGeometry();
|
||||||
|
var coord = ol.proj.toLonLat(geometry.getCoordinates());
|
||||||
|
|
||||||
|
selectedFeature.setStyle(getPointIcon(true));
|
||||||
|
|
||||||
|
$('#pointLon').val(coord[0]);
|
||||||
|
$('#pointLat').val(coord[1]);
|
||||||
|
$('#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()));
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// change mouse cursor when over marker
|
||||||
|
$(map.getViewport()).on('mousemove', function (e) {
|
||||||
|
var pixel = map.getEventPixel(e.originalEvent);
|
||||||
|
var hit = map.forEachFeatureAtPixel(pixel, function (feature, layer) {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (hit) {
|
||||||
|
map.getTarget().style.cursor = 'pointer';
|
||||||
|
} else {
|
||||||
|
map.getTarget().style.cursor = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#removeAllPoints').on('click', function () {
|
||||||
|
if (confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||||
|
removeAllPoints();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#removePoint').on('click', function () {
|
||||||
|
if (selectedMarker) {
|
||||||
|
|
||||||
|
var tmp = [];
|
||||||
|
for (var i in markers) {
|
||||||
|
if (markers[i] !== selectedMarker && typeof markers[i].action !== "undefined") {
|
||||||
|
tmp.push(markers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map.removeLayer(selectedMarker);
|
||||||
|
markers = tmp;
|
||||||
|
selectedMarker = null;
|
||||||
|
|
||||||
|
clearEditForm();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#savePoint').on('click', function () {
|
||||||
|
if (selectedMarker) {
|
||||||
|
map.getLayers().forEach(function (t) {
|
||||||
|
if (t === selectedMarker) {
|
||||||
|
var geometry = t.getSource().getFeatures()[0].getGeometry();
|
||||||
|
geometry.setCoordinates(ol.proj.fromLonLat([parseFloat($('#pointLon').val()), parseFloat($('#pointLat').val())]));
|
||||||
|
t.alt = $('#pointAlt').val();
|
||||||
|
t.action = $('#pointType').val();
|
||||||
|
t.speedValue = $('#pointSpeed').val();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
selectedMarker.getSource().getFeatures()[0].setStyle(getPointIcon());
|
||||||
|
selectedMarker = null;
|
||||||
|
clearEditForm();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#loadMissionButton').on('click', function () {
|
||||||
|
if (markers.length) {
|
||||||
|
if (!confirm(chrome.i18n.getMessage('confirm_delete_all_points'))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeAllPoints();
|
||||||
|
}
|
||||||
|
$(this).addClass('disabled');
|
||||||
|
GUI.log('Start get point');
|
||||||
|
|
||||||
|
pointForSend = 0;
|
||||||
|
getNextPoint();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#saveMissionButton').on('click', function () {
|
||||||
|
$(this).addClass('disabled');
|
||||||
|
GUI.log('Start send point');
|
||||||
|
|
||||||
|
pointForSend = 0;
|
||||||
|
sendNextPoint();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#loadEepromMissionButton').on('click', function () {
|
||||||
|
if (markers.length) {
|
||||||
|
if (!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, false, getPointsFromEprom);
|
||||||
|
});
|
||||||
|
$('#saveEepromMissionButton').on('click', function () {
|
||||||
|
GUI.log(chrome.i18n.getMessage('eeprom_saved_ok'));
|
||||||
|
MSP.send_message(MSPCodes.MSP_WP_MISSION_SAVE, false, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#rthEndMission').on('change', function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('#rthSettings').fadeIn(300);
|
||||||
|
} else {
|
||||||
|
$('#rthSettings').fadeOut(300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#saveSettings').on('click', function () {
|
||||||
|
chrome.storage.local.set({'missionPlanerSettings': {speed: $('#MPdefaultPointSpeed').val(), alt: $('#MPdefaultPointAlt').val()}});
|
||||||
|
$('#missionPlanerSettings').hide();
|
||||||
|
$('#missionPalnerTotalInfo').fadeIn(300);
|
||||||
|
if (selectedMarker !== null) {
|
||||||
|
$('#MPeditPoint').fadeIn(300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateTotalInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAllPoints() {
|
||||||
|
for (var i in markers) {
|
||||||
|
map.removeLayer(markers[i]);
|
||||||
|
}
|
||||||
|
markers = [];
|
||||||
|
clearEditForm();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointsFromEprom() {
|
||||||
|
pointForSend = 0;
|
||||||
|
MSP.send_message(MSPCodes.MSP_WP_GETINFO, false, false, getNextPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function endGetPoint() {
|
||||||
|
GUI.log('End get point');
|
||||||
|
$('#loadMissionButton').removeClass('disabled');
|
||||||
|
repaint();
|
||||||
|
updateTotalInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNextPoint() {
|
||||||
|
if (MISSION_PLANER.countBusyPoints == 0) {
|
||||||
|
endGetPoint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointForSend > 0) {
|
||||||
|
// console.log(MISSION_PLANER.bufferPoint.lon);
|
||||||
|
// console.log(MISSION_PLANER.bufferPoint.lat);
|
||||||
|
// console.log(MISSION_PLANER.bufferPoint.alt);
|
||||||
|
// console.log(MISSION_PLANER.bufferPoint.action);
|
||||||
|
if (MISSION_PLANER.bufferPoint.action == 4) {
|
||||||
|
$('#rthEndMission').attr('checked', true);
|
||||||
|
$('#rthSettings').fadeIn(300);
|
||||||
|
if (MISSION_PLANER.bufferPoint.p1 > 0) {
|
||||||
|
$('#rthLanding').attr('checked', true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var coord = ol.proj.fromLonLat([MISSION_PLANER.bufferPoint.lon, MISSION_PLANER.bufferPoint.lat]);
|
||||||
|
map.addLayer(addMarker(coord, MISSION_PLANER.bufferPoint.alt, MISSION_PLANER.bufferPoint.action, MISSION_PLANER.bufferPoint.p1));
|
||||||
|
if (pointForSend === 1) {
|
||||||
|
map.getView().setCenter(coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointForSend >= MISSION_PLANER.countBusyPoints) {
|
||||||
|
endGetPoint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MISSION_PLANER.bufferPoint.number = pointForSend;
|
||||||
|
|
||||||
|
pointForSend++;
|
||||||
|
|
||||||
|
MSP.send_message(MSPCodes.MSP_WP, mspHelper.crunch(MSPCodes.MSP_WP), false, getNextPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendNextPoint() {
|
||||||
|
var isRTH = $('#rthEndMission').is(':checked');
|
||||||
|
|
||||||
|
if (pointForSend >= markers.length) {
|
||||||
|
if (isRTH) {
|
||||||
|
MISSION_PLANER.bufferPoint.number = pointForSend + 1;
|
||||||
|
MISSION_PLANER.bufferPoint.action = 4;
|
||||||
|
MISSION_PLANER.bufferPoint.lon = 0;
|
||||||
|
MISSION_PLANER.bufferPoint.lat = 0;
|
||||||
|
MISSION_PLANER.bufferPoint.alt = 0;
|
||||||
|
MISSION_PLANER.bufferPoint.endMission = 0xA5;
|
||||||
|
MISSION_PLANER.bufferPoint.p1 = $('#rthLanding').is(':checked') ? 1 : 0;
|
||||||
|
MSP.send_message(MSPCodes.MSP_SET_WP, mspHelper.crunch(MSPCodes.MSP_SET_WP), false, endSendPoint);
|
||||||
|
} else {
|
||||||
|
endSendPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var geometry = markers[pointForSend].getSource().getFeatures()[0].getGeometry();
|
||||||
|
var coordinate = ol.proj.toLonLat(geometry.getCoordinates());
|
||||||
|
|
||||||
|
MISSION_PLANER.bufferPoint.number = pointForSend + 1;
|
||||||
|
MISSION_PLANER.bufferPoint.action = markers[pointForSend].action;
|
||||||
|
MISSION_PLANER.bufferPoint.lon = parseInt(coordinate[0] * 10000000);
|
||||||
|
MISSION_PLANER.bufferPoint.lat = parseInt(coordinate[1] * 10000000);
|
||||||
|
MISSION_PLANER.bufferPoint.alt = markers[pointForSend].alt;
|
||||||
|
MISSION_PLANER.bufferPoint.p1 = markers[pointForSend].speedValue;
|
||||||
|
pointForSend++;
|
||||||
|
if (pointForSend >= markers.length && !isRTH) {
|
||||||
|
MISSION_PLANER.bufferPoint.endMission = 0xA5;
|
||||||
|
} else {
|
||||||
|
MISSION_PLANER.bufferPoint.endMission = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MSP.send_message(MSPCodes.MSP_SET_WP, mspHelper.crunch(MSPCodes.MSP_SET_WP), false, sendNextPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function endSendPoint() {
|
||||||
|
GUI.log('End send point');
|
||||||
|
|
||||||
|
MSP.send_message(MSPCodes.MSP_WP_GETINFO, false, false, updateTotalInfo);
|
||||||
|
|
||||||
|
$('#saveMissionButton').removeClass('disabled');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TABS.mission_control.cleanup = function (callback) {
|
||||||
|
if (callback) callback();
|
||||||
|
};
|