2 * Copyright (C) 2016-2017 The LibrePilot Project
3 * Contact: http://www.librepilot.org
5 * This file is part of LibrePilot GCS.
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.
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.
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/>.
21 // ***************************
22 // Common javascript uav utils
23 // ***************************
28 .import UAVTalk.VtolPathFollowerSettings 1.0 as VtolPathFollowerSettings
31 .import UAVTalk.HomeLocation 1.0 as HomeLocation
32 .import UAVTalk.TakeOffLocation 1.0 as TakeOffLocation
35 .import UAVTalk.AuxMagSettings 1.0 as AuxMagSettings
36 .import UAVTalk.FlightBatterySettings 1.0 as FlightBatterySettings
39 .import UAVTalk.RevoSettings 1.0 as RevoSettings
42 .import UAVTalk.HwSettings 1.0 as HwSettings
43 .import UAVTalk.SystemSettings 1.0 as SystemSettings
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
54 .import UAVTalk.PathDesired 1.0 as PathDesired
55 .import UAVTalk.WaypointActive 1.0 as WaypointActive
58 .import UAVTalk.FlightBatteryState 1.0 as FlightBatteryState
59 .import UAVTalk.GPSPositionSensor 1.0 as GPSPositionSensor
60 .import UAVTalk.GPSSatellites 1.0 as GPSSatellites
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
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")
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:
125 return (homeLocation.set == HomeLocation.Set.True) ? homePosition() : defaultPosition();
129 function gpsPosition() {
131 gpsPositionSensor.longitude / 10000000.0,
132 gpsPositionSensor.latitude / 10000000.0,
133 gpsPositionSensor.altitude);
136 function homePosition() {
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);
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");
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";
194 return systemStats.cpuLoad;
198 return systemStats.cpuTemp;
201 function flightTimeValue() {
202 return Math.round(systemStats.flightTime / 1000)
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");
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");
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");
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");
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");
310 return oplmLinkStateText[opLinkStatus.linkState];
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)) {
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");
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");
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");
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");
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");
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");
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");
535 return armStatusColorText[flightStatus.armed];
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))