Merged in f5soh/librepilot/LP-575_fedora_package (pull request #491)
[librepilot.git] / ground / gcs / src / share / qml / js / uav.js
blob95489ec28a76f4cd87b6866b8d80c25ed9e7cdf1
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 batteryNbCells() {
322     return flightBatterySettings.nbCells;
325 function batteryVoltage() {
326     return flightBatteryState.voltage.toFixed(2);
329 function batteryCurrent() {
330     return flightBatteryState.current.toFixed(2);
333 function batteryConsumedEnergy() {
334     return flightBatteryState.consumedEnergy.toFixed(0);
337 function estimatedFlightTimeValue() {
338     return Math.round(flightBatteryState.estimatedFlightTime);
341 function batteryAlarmColor() {
342     //     Uninitialised, Ok,  Warning, Critical, Error
343     return ["#2c2929", "green", "orange", "red", "red"][systemAlarms.alarmBattery];
346 function estimatedTimeAlarmColor() {
347     return ((estimatedFlightTimeValue() <= 120) && (estimatedFlightTimeValue() > 60)) ? "orange" :
348            (estimatedFlightTimeValue() <= 60) ? "red" : batteryAlarmColor();
352  * Pathplan and Waypoints
355 function isPathPlanEnabled() {
356     return (flightStatus.flightMode == FlightStatus.FlightMode.PathPlanner);
359 function isPathPlanValid() {
360     return (systemAlarms.alarmPathPlan == SystemAlarms.Alarm.OK);
363 function isPathDesiredActive() {
364     return ((pathDesired.endEast != 0.0) || (pathDesired.endNorth != 0.0) || (pathDesired.endingVelocity != 0.0))
367 function isTakeOffLocationValid() {
368     return (takeOffLocation.status == TakeOffLocation.Status.Valid);
371 function pathModeDesired() {
372     var pathModeDesiredText = ["GOTO ENDPOINT","FOLLOW VECTOR","CIRCLE RIGHT","CIRCLE LEFT","FIXED ATTITUDE",
373                                "SET ACCESSORY","DISARM ALARM","LAND","BRAKE","VELOCITY","AUTO TAKEOFF"];
375     if (pathModeDesiredText.length != PathDesired.PathDesiredConstants.ModeCount) {
376         console.log("uav.js: pathModeDesired() do not match pathDesired.mode uavo");
377         return "FixMe"        
378     }
379     return pathModeDesiredText[pathDesired.mode];
382 function velocityDesiredDown() {
383     return velocityDesired.down;
386 function pathDesiredEndDown() {
387     return pathDesired.endDown;
390 function pathDesiredEndingVelocity() {
391     return pathDesired.endingVelocity;
394 function currentWaypointActive() {
395     return (waypointActive.index + 1);
398 function waypointCount() {
399     return pathPlan.waypointCount;
402 function homeHeading() {
403     return 180 / 3.1415 * Math.atan2(takeOffLocation.east - positionState.east, takeOffLocation.north - positionState.north);
406 function waypointHeading() {
407     return 180 / 3.1415 * Math.atan2(pathDesired.endEast - positionState.east, pathDesired.endNorth - positionState.north);
410 function homeDistance() {
411     return Math.sqrt(Math.pow((takeOffLocation.east - positionState.east), 2) +
412                      Math.pow((takeOffLocation.north - positionState.north), 2));
415 function waypointDistance() {
416     return Math.sqrt(Math.pow((pathDesired.endEast - positionState.east), 2) +
417                      Math.pow((pathDesired.endNorth - positionState.north), 2));
421  * FlightModes, Stabilization, Thrust modes
424 function isFlightModeManual() {
425     return (flightStatus.flightMode == FlightStatus.FlightMode.Manual);
428 function isFlightModeAssisted() {
429     return (flightStatus.flightMode > FlightStatus.FlightMode.Stabilized6);
432 function isVtolPathFollowerSettingsThrustAuto() {
433     return (vtolPathFollowerSettings.thrustControl == VtolPathFollowerSettings.ThrustControl.Auto);
436 function flightModeName() {
437     var flightModeNameText = ["MANUAL", "STAB 1", "STAB 2", "STAB 3", "STAB 4", "STAB 5", "STAB 6",
438                               "POS HOLD", "COURSELOCK", "VEL ROAM", "HOME LEASH", "ABS POS", "RTB",
439                               "LAND", "PATHPLAN", "POI", "AUTOCRUISE", "AUTOTAKEOFF", "AUTOTUNE"];
441     if (flightModeNameText.length != FlightStatus.FlightStatusConstants.FlightModeCount) {
442         console.log("uav.js: flightModeName() do not match flightStatus.flightMode uavo");
443         return "FixMe"        
444     }
445     return flightModeNameText[flightStatus.flightMode];
448 function flightModeColor() {
449     var flightModeColorText = ["gray", "green", "green", "green", "green", "green", "green",
450                                "cyan", "cyan", "cyan", "cyan", "cyan", "cyan",
451                                "cyan", "cyan", "cyan", "cyan", "cyan", "cyan"];
453     if (flightModeColorText.length != FlightStatus.FlightStatusConstants.FlightModeCount) {
454         console.log("uav.js: flightModeColor() do not match flightStatus.flightMode uavo");
455         return "gray"        
456     }
457     return flightModeColorText[flightStatus.flightMode];
460 function thrustMode() {
461     return !isFlightModeAssisted() ? stabilizationDesired.stabilizationModeThrust :
462            (isFlightModeAssisted() && isVtolOrMultirotor() && isVtolPathFollowerSettingsThrustAuto()) ?
463             StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount : (isFlightModeAssisted() && isFixedWing()) ?
464             StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount : 0;
467 function thrustModeName() {
468     // Lower case modes are never displayed/used for Thrust
469     var thrustModeNameText = ["MANUAL", "rate", "ratetrainer", "attitude", "axislock", "weakleveling", "virtualbar", "acro+ ", "rattitude",
470                               "ALT HOLD", "ALT VARIO", "CRUISECTRL", "systemident"];
472     // Last "Auto" Thrust mode is added to current UAVO enum list for display.
473     thrustModeNameText.push("AUTO");
475     if (thrustModeNameText.length != StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount + 1) {
476         console.log("uav.js: thrustModeName() do not match stabilizationDesired.StabilizationMode uavo");
477         return "FixMe"        
478     }
479     return thrustModeNameText[thrustMode()];
482 function thrustModeColor() {
483     var thrustModeColorText = ["green", "grey", "grey", "grey", "grey", "grey", "grey", "grey", "grey",
484                                "green", "green", "green", "grey"];
486     // Add the cyan color for AUTO
487     thrustModeColorText.push("cyan");
489     if (thrustModeColorText.length != StabilizationDesired.StabilizationDesiredConstants.StabilizationModeCount + 1) {
490         console.log("uav.js: thrustModeColor() do not match stabilizationDesired.StabilizationMode uavo");
491         return "gray"        
492     }
493     return thrustModeColorText[thrustMode()];
496 function armStatusName() {
497     var armStatusNameText = ["DISARMED","ARMING","ARMED"];
499     if (armStatusNameText.length != FlightStatus.FlightStatusConstants.ArmedCount) {
500         console.log("uav.js: armStatusName() do not match flightStatus.armed uavo");
501         return "FixMe"        
502     }
503     return armStatusNameText[flightStatus.armed];
506 function armStatusColor() {
507     var armStatusColorText = ["gray", "orange", "green"];
509     if (armStatusColorText.length != FlightStatus.FlightStatusConstants.ArmedCount) {
510         console.log("uav.js: armStatusColor() do not match flightStatus.armed uavo");
511         return "gray"        
512     }
513     return armStatusColorText[flightStatus.armed];
517  * Alarms
520 function autopilotStatusColor() {
521     return statusColor(systemAlarms.alarmGuidance)
524 function rcInputStatusColor() {
525     return statusColor(systemAlarms.alarmManualControl)
528 function statusColor(module) {
529     return ["gray", "green", "red", "red", "red"][module];
532 function masterCautionWarning() {
533     return ((systemAlarms.alarmBootFault > SystemAlarms.Alarm.OK) ||
534            (systemAlarms.alarmOutOfMemory > SystemAlarms.Alarm.OK) ||
535            (systemAlarms.alarmStackOverflow > SystemAlarms.Alarm.OK) ||
536            (systemAlarms.alarmCPUOverload > SystemAlarms.Alarm.OK) ||
537            (systemAlarms.alarmEventSystem > SystemAlarms.Alarm.OK))