Commit 6cd87dbd authored by Sergej Pozdnyakov's avatar Sergej Pozdnyakov
Browse files

add first version mission planer

parent a058f0a9
......@@ -2319,5 +2319,29 @@
},
"downloadUpdatesBtn": {
"message": "Download new app"
},
"tabMissionControl": {
"message": "Mission Control"
},
"loadMissionButton": {
"message": "Load mission"
},
"saveMissionButton": {
"message": "Save mission"
},
"editPointHead": {
"message": "Edit point"
},
"editPointButtonSave": {
"message": "Save"
},
"editPointButtonRemove": {
"message": "Remove"
},
"removeAllPointButtonSave": {
"message": "Remove all points"
},
"missionTotalInformationHead": {
"message": "Total information"
}
}
......@@ -38,7 +38,8 @@ var GUI_control = function () {
'setup',
'osd',
'profiles',
'advanced_tuning'
'advanced_tuning',
'mission_control'
];
this.allowedTabs = this.defaultAllowedTabsWhenDisconnected;
......
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link type="text/css" rel="stylesheet" href="./build/styles.css" media="all"/>
<script type="text/javascript" src="./build/script.js"></script>
<link type="text/css" rel="stylesheet" href="./build/map.css" media="all"/>
<script type="text/javascript" src="./build/map.js"></script>
<title></title>
</head>
<body>
......@@ -14,7 +16,8 @@
<div class="modal__text" data-i18n="appUpdateNotificationDescription"></div>
</div>
<div class="modal__buttons modal__buttons--upbottom">
<a href="https://github.com/iNavFlight/inav-configurator/releases" target="_blank" id="update-notification-download" class="modal__button modal__button--main modal__button--main--inline" data-i18n="downloadUpdatesBtn"></a>
<a href="https://github.com/iNavFlight/inav-configurator/releases" target="_blank" id="update-notification-download"
class="modal__button modal__button--main modal__button--main--inline" data-i18n="downloadUpdatesBtn"></a>
<a id="update-notification-close" class="modal__button modal__button--main modal__button--main--inline" data-i18n="closeUpdateBtn"></a>
</div>
</div>
......@@ -185,6 +188,7 @@
<li class="tab_servos"><a href="#" data-i18n="tabServos" class="tabicon ic_servo" title="Servos"></a>
</li>
<li class="tab_gps"><a href="#" data-i18n="tabGPS" class="tabicon ic_gps" title="GPS"></a></li>
<li class="tab_mission_control"><a href="#" data-i18n="tabMissionControl" class="tabicon ic_mission" title="Mission Control"></a></li>
<li class="tab_motors"><a href="#" data-i18n="tabMotorTesting" class="tabicon ic_motor"
title="Motors"></a></li>
<li class="tab_osd"><a href="#" data-i18n="tabOSD" class="tabicon ic_osd" title="OSD"></a></li>
......@@ -199,7 +203,6 @@
title="Onboard Logging"></a></li>
<li class="tab_cli"><a href="#" data-i18n="tabCLI" class="tabicon ic_cli" title="CLI"></a></li>
<!--<li class=""><a href="#" class="tabicon ic_mission">Mission (spare icon)</a></li>-->
<!--<li class=""><a href="#" class="tabicon ic_advanced">Advanced (spare icon)</a></li>-->
<!--<li class=""><a href="#" class="tabicon ic_wizzard">Wizzard (spare icon)</a></li>-->
</ul>
......
......@@ -189,6 +189,9 @@ $(document).ready(function () {
case 'gps':
TABS.gps.initialize(content_ready);
break;
case 'mission_control':
TABS.mission_control.initialize(content_ready);
break;
case 'motors':
TABS.motors.initialize(content_ready);
break;
......
This diff is collapsed.
.tab-calibration .content_toolbar {
height: 100px;
}
.tab-mission-control .waypoint {
padding-left: 19px;
padding-right: 19px;
padding-bottom: 10px;
}
.tab-mission-control .waypoint-left {
width: 54%;
float: left;
padding-right: 5px;
}
.tab-mission-control .waypoint-right{
width: 40%;
float: right;
}
.tab-mission-control .content_wrapper {
height: calc(100% - 150px);
}
.tab-mission-control .content_toolbar {
height: 150px;
}
.tab-mission-control input {
width: 157px;
padding-left: 3px;
height: 20px;
line-height: 20px;
text-align: left;
border: 1px solid silver;
border-radius: 3px;
margin-left: 11px;
font-size: 12px;
font-weight: normal;
}
.tab-mission-control .point {
display: inline-block;
margin-bottom: 5px;
}
.tab-mission-control .point-label {
}
@media (max-width: 1236px) {
.tab-mission-control .waypoint-left {
width: 96%;
}
.tab-mission-control .waypoint-right{
width: 96%;
float: left;
padding-right: 19px;
}
.tab-mission-control .content_toolbar {
height: 240px;
}
.tab-mission-control .content_wrapper {
height: calc(100% - 240px);
}
}
\ No newline at end of file
<div class="tab-mission-control toolbar_fixed_bottom">
<div class="content_wrapper">
<div id="missionMap"></div>
</div>
<div class="content_toolbar">
<div class="waypoint waypoint-left">
<div class="gui_box" style="padding-bottom: 10px">
<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="pointLat">Lat: </label>
<input id="pointLat" type="text" required>
</div>
<div class="point">
<label class="point-label" for="pointLon">Lon: </label>
<input id="pointLon" type="text" required>
</div>
<div class="point">
<label class="point-label" for="pointAlt">Alt: </label>
<input id="pointAlt" 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 save_btn" style="padding-top: 10px; display: inline-block;">
<a class="save" href="#" data-i18n="editPointButtonRemove" style="float: left">Remove</a>
</div>
<div id="removeAllPoints" class="btn save_btn" 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>
</div>
<div class="waypoint waypoint-right">
<div class="gui_box" style="padding-bottom: 10px">
<div class="gui_box_titlebar">
<div class="spacer_box_title i18n-replaced" data-i18n="missionTotalInformationHead">Total information</div>
</div>
<div class="spacer">
<div>
<span>Distance (m):</span>
<span id="missionDistance"></span>
</div>
<div>
<span>Available Points</span>
</div>
<div class="btn save_btn">
<a class="save" href="#" data-i18n="loadMissionButton">Load mission</a>
<a class="save" href="#" data-i18n="saveMissionButton">Save mission</a>
</div>
</div>
</div>
</div>
</div>
</div>
'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');
}
function load_html() {
$('#content').load("./tabs/mission_control.html", process_html);
}
load_html();
function process_html() {
initMap();
localize();
GUI.content_ready(callback);
}
var markers = [];
var lines = [];
var map;
var selectedMarker;
function clearEditForm() {
$('#pointLat').val('');
$('#pointLon').val('');
$('#pointAlt').val('');
$('[name=pointNumber]').val('')
}
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 addMarker(pos) {
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(pos),
name: 'Null Island',
population: 4000,
rainfall: 500
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 1],
opacity: 1,
scale: 0.5,
src: '../images/icons/cf_icon_position.png'
}))
// text: new ol.style.Text({
// text: '10',
// offsetX: -1,
// offsetY: -30,
// overflow: true,
// scale: 2,
// fill: new ol.style.Fill({
// color: 'black'
// })
// })
});
iconFeature.setStyle(iconStyle);
var vectorSource = new ol.source.Vector({
features: [iconFeature]
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
vectorLayer.alt = 0;
vectorLayer.number = markers.length;
markers.push(vectorLayer);
return vectorLayer;
}
function initMap() {
// var center = ol.proj.fromLonLat([e.data.lon, e.data.lat]);
//
// mapView.setCenter(center);
// iconGeometry.setCoordinates(center);
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);
/**
* @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({
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: 10
})
});
map.on('click', function (evt) {
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());
$('#pointLat').val(coord[0]);
$('#pointLon').val(coord[1]);
$('#pointAlt').val(selectedMarker.alt);
} else {
map.addLayer(addMarker(evt.coordinate));
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 () {
for (var i in markers) {
map.removeLayer(markers[i]);
}
markers = [];
clearEditForm();
repaint();
});
$('#removePoint').on('click', function () {
if (selectedMarker) {
map.removeLayer(selectedMarker);
var tmp = [];
for (var i in markers) {
if (markers[i] !== selectedMarker) {
tmp.push(markers[i]);
}
}
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($('#pointLat').val()), parseFloat($('#pointLon').val())]));
t.alt = $('#pointAlt').val();
}
});
selectedMarker = null;
clearEditForm();
repaint();
}
});
}
};
TABS.mission_control.cleanup = function (callback) {
if (callback) callback();
};
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment