LP-574 Check if adc inputs are configured before displaying battery data on PFD
[librepilot.git] / ground / gcs / src / share / qml / js / uav.js
blobb81a2533f41cd992114cb71782c544d5c5040b61
1 /*
2  * Copyright (C) 2016-2017 The LibrePilot Project
3  * Contact: http://www.librepilot.org
4  *
5  * This file is part of LibrePilot GCS.
6  *
7  * LibrePilot GCS is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * LibrePilot GCS is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with LibrePilot GCS.  If not, see <http://www.gnu.org/licenses/>.
19  */
21 // ***************************
22 // Common javascript uav utils
23 // ***************************
25 // Settings
27 // Control
28 .import UAVTalk.VtolPathFollowerSettings 1.0 as VtolPathFollowerSettings
30 // Navigation
31 .import UAVTalk.HomeLocation 1.0 as HomeLocation
32 .import UAVTalk.TakeOffLocation 1.0 as TakeOffLocation
34 // Sensors
35 .import UAVTalk.AuxMagSettings 1.0 as AuxMagSettings
36 .import UAVTalk.FlightBatterySettings 1.0 as FlightBatterySettings
38 // State
39 .import UAVTalk.RevoSettings 1.0 as RevoSettings
41 // System
42 .import UAVTalk.HwSettings 1.0 as HwSettings
43 .import UAVTalk.SystemSettings 1.0 as SystemSettings
45 // Data
47 // Control
48 .import UAVTalk.FlightStatus 1.0 as FlightStatus
49 .import UAVTalk.ManualControlCommand 1.0 as ManualControlCommand
50 .import UAVTalk.StabilizationDesired 1.0 as StabilizationDesired
51 .import UAVTalk.VelocityDesired 1.0 as VelocityDesired
53 // Navigation
54 .import UAVTalk.PathDesired 1.0 as PathDesired
55 .import UAVTalk.WaypointActive 1.0 as WaypointActive
57 // Sensors
58 .import UAVTalk.FlightBatteryState 1.0 as FlightBatteryState
59 .import UAVTalk.GPSPositionSensor 1.0 as GPSPositionSensor
60 .import UAVTalk.GPSSatellites 1.0 as GPSSatellites
62 // State
63 .import UAVTalk.AttitudeState 1.0 as AttitudeState
64 .import UAVTalk.MagState 1.0 as MagState
65 .import UAVTalk.NedAccel 1.0 as NedAccel
66 .import UAVTalk.PositionState 1.0 as PositionState
67 .import UAVTalk.VelocityState 1.0 as VelocityState
69 // System
70 .import UAVTalk.OPLinkStatus 1.0 as OPLinkStatus
71 .import UAVTalk.ReceiverStatus 1.0 as ReceiverStatus
72 .import UAVTalk.SystemAlarms 1.0 as SystemAlarms
74 Qt.include("common.js")
76 // End Import
80  * State functions
81  *
84 function attitude() {
85     return Qt.vector3d(attitudeState.roll, attitudeState.pitch, attitudeState.yaw);
88 function attitudeRoll() {
89     return attitudeState.roll;
92 function attitudePitch() {
93     return attitudeState.pitch;
96 function attitudeYaw() {
97     return attitudeState.yaw;
100 function currentVelocity() {
101     return Math.sqrt(Math.pow(velocityState.north, 2) + Math.pow(velocityState.east, 2));
104 function positionStateDown() {
105     return positionState.down;
108 function velocityStateDown() {
109     return velocityState.down;
112 function nedAccelDown() {
113     return nedAccel.down;
116 function position() {
117     switch(gpsPositionSensor.status) {
118     case GPSPositionSensor.Status.Fix2D:
119     case GPSPositionSensor.Status.Fix3D:
120     case GPSPositionSensor.Status.Fix3DDGNSS:
121         return gpsPosition();
122     case GPSPositionSensor.Status.NoFix:
123     case GPSPositionSensor.Status.NoGPS:
124     default:
125         return (homeLocation.set == HomeLocation.Set.True) ? homePosition() : defaultPosition();
126     }
129 function gpsPosition() {
130     return Qt.vector3d(
131         gpsPositionSensor.longitude / 10000000.0,
132         gpsPositionSensor.latitude / 10000000.0,
133         gpsPositionSensor.altitude);
136 function homePosition() {
137     return Qt.vector3d(
138         homeLocation.longitude / 10000000.0,
139         homeLocation.latitude / 10000000.0,
140         homeLocation.altitude);
143 function defaultPosition() {
144     return Qt.vector3d(pfdContext.longitude, pfdContext.latitude, pfdContext.altitude);
148  * System
151 function isCC3D() {
152     // Hack: detect Coptercontrol with mem free
153     return (freeMemoryBytes() < 3096);
156 function frameType() {
157     var frameTypeText = ["FixedWing", "FixedWingElevon", "FixedWingVtail", "VTOL", "HeliCP", "QuadX", "QuadP",
158             "Hexa+", "Octo+", "Custom", "HexaX", "HexaH", "OctoV", "OctoCoaxP", "OctoCoaxX", "OctoX", "HexaCoax",
159             "Tricopter", "GroundCar", "GroundDiff", "GroundMoto", "GroundBoat", "GroundDiffBoat"];
161     if (frameTypeText.length != SystemSettings.SystemSettingsConstants.AirframeTypeCount) {
162         console.log("uav.js: frameType() do not match systemSettings.airframeType uavo");
163         return "FixMe"        
164     }
165     return frameTypeText[systemSettings.airframeType]
168 function isVtolOrMultirotor() {
169     return ((systemSettings.airframeType > SystemSettings.AirframeType.FixedWingVtail) &&
170            (systemSettings.airframeType < SystemSettings.AirframeType.GroundVehicleCar));
173 function isFixedWing() {
174     return (systemSettings.airframeType <= SystemSettings.AirframeType.FixedWingVtail);
177 function isGroundVehicle() {
178     return (systemSettings.airframeType >= SystemSettings.AirframeType.GroundVehicleCar);
181 function freeMemoryBytes() {
182     return systemStats.heapRemaining;
185 function freeMemoryKBytes() {
186     return (systemStats.heapRemaining / 1024).toFixed(2);
189 function freeMemory() {
190     return (freeMemoryBytes() > 1024) ? freeMemoryKBytes() + "Kb" : freeMemoryBytes() + "bytes";
193 function cpuLoad() {
194     return systemStats.cpuLoad;
197 function cpuTemp() {
198     return systemStats.cpuTemp;
201 function flightTimeValue() {
202     return Math.round(systemStats.flightTime / 1000)
206  * Sensors
209 function isAttitudeValid() {
210     return (systemAlarms.alarmAttitude == SystemAlarms.Alarm.OK);
213 function isAttitudeNotInitialised() {
214     return (systemAlarms.alarmAttitude == SystemAlarms.Alarm.Uninitialised);
217 function isGpsValid() {
218     return (systemAlarms.alarmGPS == SystemAlarms.Alarm.OK);
221 function isGpsNotInitialised() {
222     return (systemAlarms.alarmGPS == SystemAlarms.Alarm.Uninitialised);
225 function isGpsStatusFix3D() {
226     return ((gpsPositionSensor.status == GPSPositionSensor.Status.Fix3D) || (gpsPositionSensor.status == GPSPositionSensor.Status.Fix3DDGNSS));
229 function isOplmConnected() {
230     return (opLinkStatus.linkState == OPLinkStatus.LinkState.Connected);
233 function oplmRSSI() {
234     return (opLinkStatus.rssi > -13) ? -13 : opLinkStatus.rssi;
237 function oplmDeviceID() {
238     return opLinkStatus.deviceID;
241 function magSourceName() {
242     var auxMagTypeText = ["GPSv9", "Flexi", "I2C", "DJI"];
243     var magStateSourceText = ["Invalid", "OnBoard", "ExtMag"];
245     if ((auxMagTypeText.length != AuxMagSettings.AuxMagSettingsConstants.TypeCount) ||
246         (magStateSourceText.length != MagState.MagStateConstants.SourceCount)) {
247         console.log("uav.js: magSourceName() do not match magState.source or auxMagSettings.type uavo");
248         return "FixMe"        
249     }
250     return [magState.source == MagState.Source.Aux ? auxMagTypeText[auxMagSettings.type] + " " : ""] + magStateSourceText[magState.source];
253 function gpsSensorType() {
254     var gpsSensorTypeText = ["Unknown", "NMEA", "UBX", "UBX7", "UBX8", "DJI"];
256     if (gpsSensorTypeText.length != GPSPositionSensor.GPSPositionSensorConstants.SensorTypeCount) {
257         console.log("uav.js: gpsSensorType() do not match gpsPositionSensor.sensorType uavo");
258         return "FixMe"        
259     }
260     return gpsSensorTypeText[gpsPositionSensor.sensorType];
263 function gpsNumSat() {
264     return gpsPositionSensor.satellites;
267 function gpsSatsInView() {
268     return gpsSatellites.satsInView;
271 function gpsHdopInfo() {
272     return gpsPositionSensor.hdop.toFixed(2) + "/" + gpsPositionSensor.vdop.toFixed(2) + "/" + gpsPositionSensor.pdop.toFixed(2);
275 function gpsAltitude() {
276     return gpsPositionSensor.altitude.toFixed(2);
279 function gpsStatus() {
280     var gpsStatusText = ["NO GPS", "NO FIX", "2D", "3D", "3D"];
282     if (gpsStatusText.length != GPSPositionSensor.GPSPositionSensorConstants.StatusCount) {
283         console.log("uav.js: gpsStatus() do not match gpsPositionSensor.status uavo");
284         return "FixMe"        
285     }
286     return gpsStatusText[gpsPositionSensor.status];
289 function fusionAlgorithm() {
290     var fusionAlgorithmText = ["None", "Basic (No Nav)", "CompMag", "Comp+Mag+GPS", "EKFIndoor", "GPSNav (INS)", "GPSNav (INS+CF)", "Testing (INS Indoor+CF)"];
292     if (fusionAlgorithmText.length != RevoSettings.RevoSettingsConstants.FusionAlgorithmCount) {
293         console.log("uav.js: fusionAlgorithm() do not match revoSettings.fusionAlgorithm uavo");
294         return "FixMe"        
295     }
296     return fusionAlgorithmText[revoSettings.fusionAlgorithm];
299 function receiverQuality() {
300     return (receiverStatus.quality > 0) ? receiverStatus.quality + "%" : "?? %";
303 function oplmLinkState() {
304     var oplmLinkStateText = ["Disabled", "Enabled", "Binding", "Bound", "Disconnected", "Connecting", "Connected"];
306     if (oplmLinkStateText.length != OPLinkStatus.OPLinkStatusConstants.LinkStateCount) {
307         console.log("uav.js: oplmLinkState() do not match opLinkStatus.linkState uavo");
308         return "FixMe"        
309     }
310     return oplmLinkStateText[opLinkStatus.linkState];
314  * Battery
317 function batteryModuleEnabled() {
318     return (hwSettings.optionalModulesBattery == HwSettings.OptionalModules.Enabled);
321 function batteryModuleADCConfigured() {
322     if ((hwSettings.adcRoutingadc0 == HwSettings.ADCRouting.BatteryVoltage) || 
323         (hwSettings.adcRoutingadc0 == HwSettings.ADCRouting.BatteryCurrent) ||
324         (hwSettings.adcRoutingadc1 == HwSettings.ADCRouting.BatteryVoltage) || 
325         (hwSettings.adcRoutingadc1 == HwSettings.ADCRouting.BatteryCurrent) ||
326         (hwSettings.adcRoutingadc2 == HwSettings.ADCRouting.BatteryVoltage) || 
327         (hwSettings.adcRoutingadc2 == HwSettings.ADCRouting.BatteryCurrent) ||
328         (hwSettings.adcRoutingadc3 == HwSettings.ADCRouting.BatteryVoltage) || 
329         (hwSettings.adcRoutingadc3 == HwSettings.ADCRouting.BatteryCurrent) ||
330         (hwSettings.adcRoutingadc4 == HwSettings.ADCRouting.BatteryVoltage) || 
331         (hwSettings.adcRoutingadc4 == HwSettings.ADCRouting.BatteryCurrent) ||
332         (hwSettings.adcRoutingadc5 == HwSettings.ADCRouting.BatteryVoltage) || 
333         (hwSettings.adcRoutingadc5 == HwSettings.ADCRouting.BatteryCurrent) ||
334         (hwSettings.adcRoutingadc6 == HwSettings.ADCRouting.BatteryVoltage) || 
335         (hwSettings.adcRoutingadc6 == HwSettings.ADCRouting.BatteryCurrent) ||
336         (hwSettings.adcRoutingadc7 == HwSettings.ADCRouting.BatteryVoltage) || 
337         (hwSettings.adcRoutingadc7 == HwSettings.ADCRouting.BatteryCurrent)) {
338         return true;    
339     }
340     return false;
343 function batteryNbCells() {
344     return flightBatterySettings.nbCells;
347 function batteryVoltage() {
348     return flightBatteryState.voltage.toFixed(2);
351 function batteryCurrent() {
352     return flightBatteryState.current.toFixed(2);
355 function batteryConsumedEnergy() {
356     return flightBatteryState.consumedEnergy.toFixed(0);
359 function estimatedFlightTimeValue() {
360     return Math.round(flightBatteryState.estimatedFlightTime);
363 function batteryAlarmColor() {
364     //     Uninitialised, Ok,  Warning, Critical, Error
365     return ["#2c2929", "green", "orange", "red", "red"][systemAlarms.alarmBattery];
368 function estimatedTimeAlarmColor() {
369     return ((estimatedFlightTimeValue() <= 120) && (estimatedFlightTimeValue() > 60)) ? "orange" :
370            (estimatedFlightTimeValue() <= 60) ? "red" : batteryAlarmColor();
374  * Pathplan and Waypoints
377 function isPathPlanEnabled() {
378     return (flightStatus.flightMode == FlightStatus.FlightMode.PathPlanner);
381 function isPathPlanValid() {
382     return (systemAlarms.alarmPathPlan == SystemAlarms.Alarm.OK);
385 function isPathDesiredActive() {
386     return ((pathDesired.endEast != 0.0) || (pathDesired.endNorth != 0.0) || (pathDesired.endingVelocity != 0.0))
389 function isTakeOffLocationValid() {
390     return (takeOffLocation.status == TakeOffLocation.Status.Valid);
393 function pathModeDesired() {
394     var pathModeDesiredText = ["GOTO ENDPOINT","FOLLOW VECTOR","CIRCLE RIGHT","CIRCLE LEFT","FIXED ATTITUDE",
395                                "SET ACCESSORY","DISARM ALARM","LAND","BRAKE","VELOCITY","AUTO TAKEOFF"];
397     if (pathModeDesiredText.length != PathDesired.PathDesiredConstants.ModeCount) {
398         console.log("uav.js: pathModeDesired() do not match pathDesired.mode uavo");
399         return "FixMe"        
400     }
401     return pathModeDesiredText[pathDesired.mode];
404 function velocityDesiredDown() {
405     return velocityDesired.down;
408 function pathDesiredEndDown() {
409     return pathDesired.endDown;
412 function pathDesiredEndingVelocity() {
413     return pathDesired.endingVelocity;
416 function currentWaypointActive() {
417     return (waypointActive.index + 1);
420 function waypointCount() {
421     return pathPlan.waypointCount;
424 function homeHeading() {
425     return 180 / 3.1415 * Math.atan2(takeOffLocation.east - positionState.east, takeOffLocation.north - positionState.north);
428 function waypointHeading() {
429     return 180 / 3.1415 * Math.atan2(pathDesired.endEast - positionState.east, pathDesired.endNorth - positionState.north);
432 function homeDistance() {
433     return Math.sqrt(Math.pow((takeOffLocation.east - positionState.east), 2) +
434                      Math.pow((takeOffLocation.north - positionState.north), 2));
437 function waypointDistance() {
438     return Math.sqrt(Math.pow((pathDesired.endEast - positionState.east), 2) +
439                      Math.pow((pathDesired.endNorth - positionState.north), 2));
443  * FlightModes, Stabilization, Thrust modes
446 function isFlightModeManual() {
447     return (flightStatus.flightMode == FlightStatus.FlightMode.Manual);
450 function isFlightModeAssisted() {
451     return (flightStatus.flightMode > FlightStatus.FlightMode.Stabilized6);
454 function isVtolPathFollowerSettingsThrustAuto() {
455     return (vtolPathFollowerSettings.thrustControl == VtolPathFollowerSettings.ThrustControl.Auto);
458 function flightModeName() {
459     var flightModeNameText = ["MANUAL", "STAB 1", "STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
460                               "POS HOLD", "COURSELOCK", "VEL ROAM", "HOME LEASH", "ABS POS", "RTB",
461                               "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF", "AUTOTUNE"];
463     if (flightModeNameText.length != FlightStatus.FlightStatusConstants.FlightModeCount) {
464         console.log("uav.js: flightModeName() do not match flightStatus.flightMode uavo");
465         return "FixMe"        
466     }
467     return flightModeNameText[flightStatus.flightMode];
470 function flightModeColor() {
471     var flightModeColorText = ["gray", "green", "green", "green", "green", "green", "green",
472                                "cyan", "cyan", "cyan", "cyan", "cyan", "cyan",
473                                "cyan", "cyan", "cyan", "cyan", "cyan", "cyan"];
475     if (flightModeColorText.length != FlightStatus.FlightStatusConstants.FlightModeCount) {
476         console.log("uav.js: flightModeColor() do not match flightStatus.flightMode uavo");
477         return "gray"        
478     }
479     return flightModeColorText[flightStatus.flightMode];
482 function thrustMode() {
483     return !isFlightModeAssisted() ? stabilizationDesired.stabilizationModeThrust :
484            (isFlightModeAssisted() && isVtolOrMultirotor() && isVtolPathFollowerSettingsThrustAuto()) ?
485             StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount : (isFlightModeAssisted() && isFixedWing()) ?
486             StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount : 0;
489 function thrustModeName() {
490     // Lower case modes are never displayed/used for Thrust
491     var thrustModeNameText = ["MANUAL", "rate", "ratetrainer", "attitude", "axislock", "weakleveling", "virtualbar", "acro+ ", "rattitude",
492                               "ALT HOLD", "ALT VARIO", "CRUISECTRL", "systemident"];
494     // Last "Auto" Thrust mode is added to current UAVO enum list for display.
495     thrustModeNameText.push("AUTO");
497     if (thrustModeNameText.length != StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount + 1) {
498         console.log("uav.js: thrustModeName() do not match stabilizationDesired.StabilizationMode uavo");
499         return "FixMe"        
500     }
501     return thrustModeNameText[thrustMode()];
504 function thrustModeColor() {
505     var thrustModeColorText = ["green", "grey", "grey", "grey", "grey", "grey", "grey", "grey", "grey",
506                                "green", "green", "green", "grey"];
508     // Add the cyan color for AUTO
509     thrustModeColorText.push("cyan");
511     if (thrustModeColorText.length != StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount + 1) {
512         console.log("uav.js: thrustModeColor() do not match stabilizationDesired.StabilizationMode uavo");
513         return "gray"        
514     }
515     return thrustModeColorText[thrustMode()];
518 function armStatusName() {
519     var armStatusNameText = ["DISARMED","ARMING","ARMED"];
521     if (armStatusNameText.length != FlightStatus.FlightStatusConstants.ArmedCount) {
522         console.log("uav.js: armStatusName() do not match flightStatus.armed uavo");
523         return "FixMe"        
524     }
525     return armStatusNameText[flightStatus.armed];
528 function armStatusColor() {
529     var armStatusColorText = ["gray", "orange", "green"];
531     if (armStatusColorText.length != FlightStatus.FlightStatusConstants.ArmedCount) {
532         console.log("uav.js: armStatusColor() do not match flightStatus.armed uavo");
533         return "gray"        
534     }
535     return armStatusColorText[flightStatus.armed];
539  * Alarms
542 function autopilotStatusColor() {
543     return statusColor(systemAlarms.alarmGuidance)
546 function rcInputStatusColor() {
547     return statusColor(systemAlarms.alarmManualControl)
550 function statusColor(module) {
551     return ["gray", "green", "red", "red", "red"][module];
554 function masterCautionWarning() {
555     return ((systemAlarms.alarmBootFault > SystemAlarms.Alarm.OK) ||
556            (systemAlarms.alarmOutOfMemory > SystemAlarms.Alarm.OK) ||
557            (systemAlarms.alarmStackOverflow > SystemAlarms.Alarm.OK) ||
558            (systemAlarms.alarmCPUOverload > SystemAlarms.Alarm.OK) ||
559            (systemAlarms.alarmEventSystem > SystemAlarms.Alarm.OK))