skyspy 0.11: Display glyph of GPS status
This adds another screen with graphical representation of GPS status, that can be used to quickly estimate when fix will be available and if user needs to move to get itmaster
parent
6cc628f173
commit
9f80ef1221
|
|
@ -3,3 +3,4 @@
|
|||
0.03: big rewrite, adding time-adjust and altitude-adjust functionality
|
||||
0.04: more refactoring, fix lat/lon display
|
||||
0.10: add screens with time to fixes and estimate of time to fix
|
||||
0.11: introduce graphical gps status
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{ "id": "skyspy",
|
||||
"name": "Sky Spy",
|
||||
"version": "0.10",
|
||||
"version": "0.11",
|
||||
"description": "Application for debugging GPS problems",
|
||||
"icon": "app.png",
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -200,10 +200,16 @@ let gps = {
|
|||
},
|
||||
};
|
||||
|
||||
/* ui library 0.1.5 */
|
||||
/* ui library 0.1.5, dirty, bad, revert! */
|
||||
let ui = {
|
||||
display: 0,
|
||||
numScreens: 2,
|
||||
clear: function() {
|
||||
g.reset()
|
||||
.setColor(g.theme.bg)
|
||||
.fillRect(0, this.wi, this.w, this.y2)
|
||||
.setColor(g.theme.fg);
|
||||
},
|
||||
drawMsg: function(msg) {
|
||||
g.reset().setFont("Vector", 35)
|
||||
.setColor(g.theme.bg)
|
||||
|
|
@ -296,11 +302,7 @@ let ui = {
|
|||
},
|
||||
};
|
||||
|
||||
function log2(x) {
|
||||
return Math.log(x) / Math.log(2);
|
||||
}
|
||||
|
||||
/* pie library v0.0.1 */
|
||||
/* pie library v0.0.4 */
|
||||
let pie = {
|
||||
radians: function(a) { return a*Math.PI/180; },
|
||||
|
||||
|
|
@ -310,77 +312,123 @@ let pie = {
|
|||
points.push(centerX, centerY); // Start at the center
|
||||
|
||||
// Step through angles to create points on the arc
|
||||
for (let angle = startAngle; angle <= endAngle; angle += 5) {
|
||||
const x = centerX + Math.cos(this.radians(angle)) * radius;
|
||||
const y = centerY + Math.sin(this.radians(angle)) * radius;
|
||||
for (let angle = startAngle; angle <= endAngle; angle += 15) {
|
||||
const x = centerX + Math.sin(this.radians(angle)) * radius;
|
||||
const y = centerY - Math.cos(this.radians(angle)) * radius;
|
||||
points.push(x, y);
|
||||
}
|
||||
|
||||
// Add the final point at the end angle
|
||||
points.push(centerX + Math.cos(this.radians(endAngle)) * radius);
|
||||
points.push(centerY + Math.sin(this.radians(endAngle)) * radius);
|
||||
points.push(centerX + Math.sin(this.radians(endAngle)) * radius);
|
||||
points.push(centerY - Math.cos(this.radians(endAngle)) * radius);
|
||||
|
||||
g.fillPoly(points); // Draw the arc as a polygon
|
||||
},
|
||||
|
||||
// Function to draw the pie chart
|
||||
drawPieChart1: function(g, centerX, centerY, radius, data, colors) {
|
||||
let startAngle = 0;
|
||||
let startAngle = data[0];
|
||||
|
||||
// Loop through the data to draw each segment
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
for (let i = 1; i < data.length; i++) {
|
||||
const angle = data[i]; // Get the angle for the current section
|
||||
const endAngle = startAngle + angle; // Calculate the end angle
|
||||
const endAngle = angle; // Calculate the end angle
|
||||
|
||||
g.setColor(colors[i]); // Set the fill color
|
||||
this.fillArc(g, centerX, centerY, radius, startAngle, endAngle, colors[i]); // Draw the arc
|
||||
startAngle = endAngle; // Update the start angle for the next segment
|
||||
startAngle = angle; // Update the start angle for the next segment
|
||||
}
|
||||
|
||||
g.flip(); // Update the screen
|
||||
},
|
||||
altDelta: function(centerX, centerY, radius, altitude, altChange) {
|
||||
// Altitude range and mapping to a logarithmic scale
|
||||
//const altitudeMin = -1000, altitudeMax = 1000;
|
||||
const altitudeLog = log2(Math.abs(altitude) + 1) * Math.sign(altitude); // Logarithmic scaling
|
||||
const altitudeAngle = E.clip((altitudeLog - log2(1)) / (log2(1001) - log2(1)), -1, 1) * 180;
|
||||
|
||||
// Altitude Change (linear scale)
|
||||
const altChangeMin = -30, altChangeMax = 30;
|
||||
const altChangeAngle = E.clip((altChange - altChangeMin) / (altChangeMax - altChangeMin), 0, 1) * 360;
|
||||
|
||||
this.twoPie(centerX, centerY, radius, altitudeAngle, altChangeAngle);
|
||||
},
|
||||
|
||||
twoPie: function(centerX, centerY, radius, altitudeAngle, altChangeAngle) {
|
||||
// Outer Ring (Altitude Change) - Draw a segment based on altitude change
|
||||
|
||||
g.setColor(0, 0, 0.5); // Set a color for the outer ring
|
||||
this.fillArc(g,
|
||||
centerX, centerY,
|
||||
radius, // Define the thickness of the outer ring
|
||||
0, altChangeAngle // Draw based on altitude change
|
||||
);
|
||||
|
||||
// Inner Ring (Altitude) - Draw a segment based on altitude angle
|
||||
const innerRadius = radius * 0.6; // Inner ring size
|
||||
g.setColor(0, 0.5, 0); // Set a color for the inner ring
|
||||
this.fillArc(g,
|
||||
centerX, centerY,
|
||||
innerRadius, // Define thickness of inner ring
|
||||
0, altitudeAngle // Draw based on altitude
|
||||
);
|
||||
|
||||
// Draw the baseline circle for reference
|
||||
g.setColor(0, 0, 0); // Gray for baseline
|
||||
g.drawCircle(centerX, centerY, innerRadius); // Inner circle (reference)
|
||||
g.drawCircle(centerX, centerY, radius); // Outer circle (reference)
|
||||
|
||||
// Render the chart
|
||||
g.flip();
|
||||
}
|
||||
};
|
||||
|
||||
let gpsg = {
|
||||
cx: ui.w/2,
|
||||
cy: ui.wi+ui.h/2,
|
||||
s: ui.h/2 - 1,
|
||||
sats: 4, /* Number of sats with good enough snr */
|
||||
sats_bad: 0, /* Sattelites visible but with low snr */
|
||||
view_t: getTime(), /* When sky became visible */
|
||||
start_t: getTime(), /* When we started acquiring fix */
|
||||
dalt: 30, /* Altitude error between barometer and gps */
|
||||
fix: {},
|
||||
|
||||
init : function() {
|
||||
},
|
||||
drawCorner(h, v) {
|
||||
let cx = this.cx;
|
||||
let cy = this.cy;
|
||||
let s = this.s;
|
||||
let st = 48;
|
||||
let a = [cx+h*s, cy+v*s, cx+h*s - h*st, cy+v*s, cx+h*s, cy+v*s - v*st];
|
||||
g.fillPoly(a);
|
||||
},
|
||||
clamp: function(low, v, high) {
|
||||
if (v < low)
|
||||
v = low;
|
||||
if (v > high)
|
||||
v = high;
|
||||
return [ low, v, high ];
|
||||
},
|
||||
draw : function() {
|
||||
let cx = this.cx;
|
||||
let cy = this.cy;
|
||||
let s = this.s;
|
||||
ui.clear();
|
||||
g.fillCircle(cx, cy, s);
|
||||
if (!this.fix.fix)
|
||||
this.drawCorner(1, -1);
|
||||
if (this.fix.hdop > 10)
|
||||
this.drawCorner(1, 1);
|
||||
if (this.fix.satellites < 4)
|
||||
this.drawCorner(-1, 1);
|
||||
if (this.sats < 4)
|
||||
this.drawCorner(-1, -1);
|
||||
|
||||
g.setColor(1, 1, 1);
|
||||
let t = getTime();
|
||||
if (this.fix.fix) { /* Have speed */
|
||||
let data = this.clamp(210, 210 + (360*this.fix.speed) / 20, 210+360);
|
||||
let colors = [ "ign", "#000", "#fff" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 1, data, colors);
|
||||
} else {
|
||||
let data = this.clamp(0, (360*(t - this.start_t)) / 600, 360);
|
||||
let colors = [ "ign", "#888", "#000" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 1, data, colors);
|
||||
}
|
||||
if (this.fix.fix) {
|
||||
let data = this.clamp(90, 90 + (360*this.dalt) / 200, 90+360);
|
||||
let colors = [ "ign", "#000", "#fff" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 0.6, data, colors);
|
||||
} else { /* Still waiting for fix */
|
||||
let data = this.clamp(0, (360*(t - this.view_t)) / 120, 360);
|
||||
let colors = [ "ign", "#888", "#000" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 0.6, data, colors);
|
||||
}
|
||||
if (this.fix.fix) {
|
||||
let slice = 360 / 8;
|
||||
let sats = this.fix.satellites;
|
||||
let data = this.clamp( 0, slice * sats, 360 );
|
||||
let colors = [ "ign", "#fff", "#000" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 0.3, data, colors);
|
||||
} else {
|
||||
let slice = 360 / 8;
|
||||
let sats = this.sats;
|
||||
let red = sats + this.sats_bad;
|
||||
if (sats > 8)
|
||||
sats = 8;
|
||||
if (red > 8)
|
||||
red = 8;
|
||||
let data = [ 0, slice * sats, slice * red, 360 ];
|
||||
let colors = [ "ign", "#888", "#800", "#000" ];
|
||||
pie.drawPieChart1(g, cx, cy, s * 0.3, data, colors);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function log2(x) {
|
||||
return Math.log(x) / Math.log(2);
|
||||
}
|
||||
|
||||
var debug = 0;
|
||||
var cur_altitude;
|
||||
var adj_time = 0, adj_alt = 0;
|
||||
|
|
@ -500,9 +548,17 @@ let quality = {
|
|||
let t = getTime();
|
||||
//print(t, this.fix_start);
|
||||
msg = "St: " + fmt.fmtTimeDiff(t-gps.gps_start) + "\n";
|
||||
msg += "Sky: " + fmt.fmtTimeDiff(t-sky.all.sky_start) + "\n";
|
||||
msg += "Sky: " + fmt.fmtTimeDiff(t-skys.sky_start) + "\n";
|
||||
msg += "2D: " + fmt.fmtTimeDiff(t-quality.fix_start) + "\n";
|
||||
msg += "3D: " + fmt.fmtTimeDiff(t-quality.f3d_start) + "\n";
|
||||
} else if (ui.display == 5) {
|
||||
gpsg.start_t = gps.gps_start;
|
||||
gpsg.view_t = skys.sky_start;
|
||||
gpsg.sats = skys.sats_used;
|
||||
gpsg.sats_bad = skys.sats_weak;
|
||||
gpsg.fix = fix;
|
||||
gpsg.dalt = Math.abs(adelta);
|
||||
gpsg.draw();
|
||||
}
|
||||
quality.step++;
|
||||
if (quality.step == 10) {
|
||||
|
|
@ -524,12 +580,18 @@ let skys = {
|
|||
sats: [],
|
||||
snum: 0,
|
||||
sats_used: 0,
|
||||
sats_weak: 0,
|
||||
sky_start: -1,
|
||||
/* 18.. don't get reliable fix in 40s */
|
||||
/* 25.. seems to be good limit for clear sky. ~60 seconds.
|
||||
.. maybe better 26? */
|
||||
snrLim: 25,
|
||||
|
||||
reset: function() {
|
||||
this.snum = 0;
|
||||
this.sats = [];
|
||||
this.sats_used = 0;
|
||||
this.sats_weak = 0;
|
||||
},
|
||||
parseSats: function(s) {
|
||||
let view = 1 * s[3];
|
||||
|
|
@ -542,6 +604,9 @@ let skys = {
|
|||
this.sats_used++;
|
||||
print(sat.id, sat.snr);
|
||||
}
|
||||
if (sat.snr > 0) {
|
||||
this.sats_weak++;
|
||||
}
|
||||
this.sats[this.snum++] = sat;
|
||||
}
|
||||
},
|
||||
|
|
@ -619,7 +684,7 @@ let skys = {
|
|||
},
|
||||
onEnd: function () {
|
||||
this.trackSatelliteVisibility();
|
||||
if (this.sats_used < 5)
|
||||
if (this.sats_used < 4)
|
||||
this.sky_start = getTime();
|
||||
this.reset();
|
||||
},
|
||||
|
|
@ -647,7 +712,7 @@ let sky = {
|
|||
this_usable: 0,
|
||||
debug: 0,
|
||||
all: skys, /* Sattelites from all systems */
|
||||
split: 1,
|
||||
split: 0,
|
||||
|
||||
init: function () {
|
||||
if (this.split) {
|
||||
|
|
@ -665,8 +730,6 @@ let sky = {
|
|||
ui.radCircle(1.0);
|
||||
},
|
||||
|
||||
/* 18.. don't get reliable fix in 40s */
|
||||
snrLim: 22,
|
||||
drawSat: function(s) {
|
||||
let a = s.azi / 360;
|
||||
let e = ((90 - s.ele) / 90);
|
||||
|
|
@ -675,7 +738,7 @@ let sky = {
|
|||
|
||||
if (s.snr == 0)
|
||||
g.setColor(1, 0.25, 0.25);
|
||||
else if (s.snr < this.snrLim)
|
||||
else if (s.snr < this.all.snrLim)
|
||||
g.setColor(0.25, 0.5, 0.25);
|
||||
else
|
||||
g.setColor(0, 0, 0);
|
||||
|
|
@ -885,18 +948,20 @@ function onMessage() {
|
|||
|
||||
|
||||
ui.init();
|
||||
ui.numScreens = 5;
|
||||
ui.numScreens = 6;
|
||||
/* 0.. sat drawing
|
||||
1.. position, basic data
|
||||
2.. fix quality esitmation
|
||||
3.. times from ...
|
||||
4.. time to fix experiment
|
||||
5.. gps graph
|
||||
*/
|
||||
gps.init();
|
||||
quality.resetAlt();
|
||||
fmt.init();
|
||||
sky.onMessageEnd = onMessage;
|
||||
sky.init();
|
||||
gpsg.init();
|
||||
|
||||
sky.decorate = () => {
|
||||
let p = 15;
|
||||
|
|
|
|||
Loading…
Reference in New Issue