Skip to content

Commit f93fba9

Browse files
authored
Merge pull request #1988 from iNavFlight/dzikuvx-ltm-decoder
Decode LTM telemetry protocol
2 parents 781d0c5 + 542a307 commit f93fba9

8 files changed

+596
-2
lines changed

_locales/en/messages.json

+33
Original file line numberDiff line numberDiff line change
@@ -5603,5 +5603,38 @@
56035603
},
56045604
"ezTuneNote": {
56055605
"message": "<strong>Important</strong> Ez Tune is enabled. All settings on this tab are set and controlled by the Ez Tune. To use PID Tuning tab you have to disable Ez Tune. To do it, uncheck the <strong>Enabled</strong> checkbox on the Ez Tune tab."
5606+
},
5607+
"gsActivated": {
5608+
"message": "Ground station mode activated"
5609+
},
5610+
"gsDeactivated": {
5611+
"message": "Ground station mode deactivated"
5612+
},
5613+
"gsTelemetry": {
5614+
"message": "Telemetry"
5615+
},
5616+
"gsTelemetryLatitude": {
5617+
"message": "Latitude"
5618+
},
5619+
"gsTelemetryLongitude": {
5620+
"message": "Longitude"
5621+
},
5622+
"gsTelemetryAltitude": {
5623+
"message": "Altitude"
5624+
},
5625+
"gsTelemetryAltitudeShort": {
5626+
"message": "Alt"
5627+
},
5628+
"gsTelemetryVoltageShort": {
5629+
"message": "Vbat"
5630+
},
5631+
"gsTelemetrySats": {
5632+
"message": "Sats"
5633+
},
5634+
"gsTelemetryFix": {
5635+
"message": "Fix"
5636+
},
5637+
"gsTelemetrySpeed": {
5638+
"message": "Speed"
56065639
}
56075640
}

gulpfile.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ sources.css = [
5555
'./node_modules/openlayers/dist/ol.css',
5656
'./src/css/logic.css',
5757
'./src/css/defaults_dialog.css',
58+
'./src/css/groundstation.css',
5859
];
5960

6061
sources.js = [
@@ -139,7 +140,9 @@ sources.js = [
139140
'./js/libraries/plotly-latest.min.js',
140141
'./js/sitl.js',
141142
'./js/CliAutoComplete.js',
142-
'./node_modules/jquery-textcomplete/dist/jquery.textcomplete.js'
143+
'./node_modules/jquery-textcomplete/dist/jquery.textcomplete.js',
144+
'./js/ltmDecoder.js',
145+
'./js/groundstation.js'
143146
];
144147

145148
sources.receiverCss = [

js/groundstation.js

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
'use strict';
2+
3+
var helper = helper || {};
4+
5+
helper.groundstation = (function () {
6+
7+
let publicScope = {},
8+
privateScope = {};
9+
10+
privateScope.activated = false;
11+
privateScope.$viewport = null;
12+
privateScope.$gsViewport = null;
13+
privateScope.mapHandler = null;
14+
privateScope.mapLayer = null;
15+
privateScope.mapView = null;
16+
17+
privateScope.cursorStyle = null;
18+
privateScope.cursorPosition = null;
19+
privateScope.cursorFeature = null;
20+
privateScope.cursorVector = null;
21+
privateScope.cursorLayer = null;
22+
23+
privateScope.textGeometry = null;
24+
privateScope.textFeature = null;
25+
privateScope.textVector = null;
26+
privateScope.textSource = null;
27+
28+
privateScope.mapInitiated = false;
29+
30+
publicScope.isActivated = function () {
31+
return privateScope.activated;
32+
};
33+
34+
publicScope.activate = function ($viewport) {
35+
36+
if (privateScope.activated) {
37+
return;
38+
}
39+
40+
helper.interval.add('gsUpdateGui', privateScope.updateGui, 200);
41+
42+
privateScope.$viewport = $viewport;
43+
44+
privateScope.$viewport.find(".tab_container").hide();
45+
privateScope.$viewport.find('#content').hide();
46+
privateScope.$viewport.find('#status-bar').hide();
47+
privateScope.$viewport.find('#connectbutton a.connect_state').text(chrome.i18n.getMessage('disconnect')).addClass('active');
48+
49+
privateScope.$gsViewport = $viewport.find('#view-groundstation');
50+
privateScope.$gsViewport.show();
51+
privateScope.mapInitiated = false;
52+
53+
setTimeout(privateScope.initMap, 100);
54+
55+
privateScope.activated = true;
56+
GUI.log(chrome.i18n.getMessage('gsActivated'));
57+
}
58+
59+
privateScope.initMap = function () {
60+
61+
//initialte layers
62+
if (globalSettings.mapProviderType == 'bing') {
63+
privateScope.mapLayer = new ol.source.BingMaps({
64+
key: globalSettings.mapApiKey,
65+
imagerySet: 'AerialWithLabels',
66+
maxZoom: 19
67+
});
68+
} else if (globalSettings.mapProviderType == 'mapproxy') {
69+
privateScope.mapLayer = new ol.source.TileWMS({
70+
url: globalSettings.proxyURL,
71+
params: { 'LAYERS': globalSettings.proxyLayer }
72+
})
73+
} else {
74+
privateScope.mapLayer = new ol.source.OSM();
75+
}
76+
77+
//initiate view
78+
privateScope.mapView = new ol.View({
79+
center: ol.proj.fromLonLat([0, 0]),
80+
zoom: 3
81+
});
82+
83+
//initiate map handler
84+
privateScope.mapHandler = new ol.Map({
85+
target: document.getElementById('groundstation-map'),
86+
layers: [
87+
new ol.layer.Tile({
88+
source: privateScope.mapLayer
89+
})
90+
],
91+
view: privateScope.mapView
92+
});
93+
};
94+
95+
publicScope.deactivate = function () {
96+
97+
if (!privateScope.activated) {
98+
return;
99+
}
100+
101+
helper.interval.remove('gsUpdateGui');
102+
103+
if (privateScope.$viewport !== null) {
104+
privateScope.$viewport.find(".tab_container").show();
105+
privateScope.$viewport.find('#content').show();
106+
privateScope.$viewport.find('#status-bar').show();
107+
}
108+
109+
if (privateScope.$gsViewport !== null) {
110+
privateScope.$gsViewport.hide();
111+
}
112+
113+
privateScope.activated = false;
114+
GUI.log(chrome.i18n.getMessage('gsDeactivated'));
115+
}
116+
117+
privateScope.updateGui = function () {
118+
119+
let telemetry = helper.ltmDecoder.get();
120+
121+
if (telemetry.gpsFix && telemetry.gpsFix > 1) {
122+
123+
let lat = telemetry.latitude / 10000000;
124+
let lon = telemetry.longitude / 10000000;
125+
126+
//On first initiation, set zoom to 15
127+
if (!privateScope.mapInitiated) {
128+
129+
//Place UAV on the map
130+
privateScope.cursorStyle = new ol.style.Style({
131+
image: new ol.style.Icon(({
132+
anchor: [0.5, 0.5],
133+
opacity: 1,
134+
scale: 0.6,
135+
src: '../images/icons/icon_mission_airplane.png'
136+
}))
137+
});
138+
privateScope.cursorPosition = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
139+
140+
privateScope.cursorFeature = new ol.Feature({
141+
geometry: privateScope.cursorPosition
142+
});
143+
144+
privateScope.cursorFeature.setStyle(privateScope.cursorStyle);
145+
146+
privateScope.cursorVector = new ol.source.Vector({
147+
features: [privateScope.cursorFeature]
148+
});
149+
privateScope.cursorLayer = new ol.layer.Vector({
150+
source: privateScope.cursorVector
151+
});
152+
153+
privateScope.mapHandler.addLayer(privateScope.cursorLayer);
154+
155+
privateScope.mapView.setZoom(17);
156+
157+
privateScope.mapInitiated = true;
158+
}
159+
160+
//Update map center
161+
let position = ol.proj.fromLonLat([lon, lat]);
162+
privateScope.mapView.setCenter(position);
163+
164+
//Update position of cursor
165+
privateScope.cursorPosition.setCoordinates(position);
166+
//Update orientation of cursor
167+
privateScope.cursorStyle.getImage().setRotation((telemetry.heading / 360.0) * 6.28318);
168+
169+
170+
171+
//Update text
172+
privateScope.$viewport.find("#gs-telemetry-latitude").html(lat);
173+
privateScope.$viewport.find("#gs-telemetry-longitude").html(lon);
174+
}
175+
176+
privateScope.$viewport.find("#gs-telemetry-altitude").html(telemetry.altitude / 100.0 + 'm');
177+
privateScope.$viewport.find("#gs-telemetry-voltage").html(telemetry.voltage / 100.0 + 'V');
178+
privateScope.$viewport.find("#gs-telemetry-sats").html(telemetry.gpsSats);
179+
privateScope.$viewport.find("#gs-telemetry-speed").html(telemetry.groundSpeed * 100 + 'm/s');
180+
181+
let fixText = '';
182+
if (telemetry.gpsFix == 3) {
183+
fixText = '3D';
184+
} else if (telemetry.gpsFix == 2) {
185+
fixText = '2D';
186+
} else {
187+
fixText = 'No fix';
188+
}
189+
190+
privateScope.$viewport.find("#gs-telemetry-fix").html(fixText);
191+
};
192+
193+
return publicScope;
194+
})();

0 commit comments

Comments
 (0)