diff --git a/locales/en/messages.json b/locales/en/messages.json index 0c2d11da..b308cec8 100755 --- a/locales/en/messages.json +++ b/locales/en/messages.json @@ -830,14 +830,6 @@ "message": "Heading:", "description": "Heading shown on Setup tab" }, - "initialSetupPitch": { - "message": "Pitch:", - "description": "Pitch shown on Setup tab" - }, - "initialSetupRoll": { - "message": "Roll:", - "description": "Roll shown on Setup tab" - }, "initialSetupMixerHead": { "message": "Mixer Type" }, @@ -2783,7 +2775,8 @@ "description": "Show GPS position - Latitude / Longitude" }, "gpsHeading": { - "message": "Heading:" + "message": "Heading Mag / GPS:", + "description": "Show GPS heading - Magnetic / GPS course over ground" }, "gpsSpeed": { "message": "Speed:" @@ -4612,45 +4605,6 @@ "message": "GPS Rescue" }, - "failsafeGpsRescueItemAngle": { - "message": "Angle" - }, - "failsafeGpsRescueItemInitialAltitude": { - "message": "Initial altitude (meters)" - }, - "failsafeGpsRescueItemDescentDistance": { - "message": "Descent distance (meters)" - }, - "failsafeGpsRescueItemMinDth": { - "message": "Minimum distance to home (meters)" - }, - "failsafeGpsRescueItemMinDthHelp": { - "message": "The minimum distance to home needed for GPS rescue to activate" - }, - "failsafeGpsRescueItemGroundSpeed": { - "message": "Ground speed (meters/second)" - }, - "failsafeGpsRescueItemThrottleMin": { - "message": "Throttle minimum" - }, - "failsafeGpsRescueItemThrottleMax": { - "message": "Throttle maximum" - }, - "failsafeGpsRescueItemThrottleHover": { - "message": "Throttle hover" - }, - "failsafeGpsRescueItemAscendRate": { - "message": "Ascend rate (meters/second)" - }, - "failsafeGpsRescueItemDescendRate": { - "message": "Descend rate (meters/second)" - }, - "failsafeGpsRescueItemMinSats": { - "message": "Minimum satellites" - }, - "failsafeGpsRescueItemAllowArmingWithoutFix": { - "message": "Allow arming without fix - WARNING: the GPS Rescue will not be available" - }, "failsafeGpsRescueItemAltitudeMode": { "message": "Altitude mode" }, @@ -4663,6 +4617,70 @@ "failsafeGpsRescueItemAltitudeModeCurrentAlt": { "message": "Current altitude" }, + "failsafeGpsRescueInitialClimb": { + "message": "Initial climb (meters)" + }, + "failsafeGpsRescueInitialClimbHelp": { + "message": "The distance the quad will climb, above the current altitude, when a rescue is initiated and the altitude mode is set to CURRENT Altitude; also added when in MAX Altitude mode." + }, + "failsafeGpsRescueItemReturnAltitude": { + "message": "Return altitude (meters) - only applies in Fixed Altitude mode" + }, + "failsafeGpsRescueItemAscendRate": { + "message": "Ascend rate (meters/second)" + }, + "failsafeGpsRescueItemGroundSpeed": { + "message": "Return ground speed (meters/second)" + }, + "failsafeGpsRescueItemAngle": { + "message": "Maximum pitch angle" + }, + "failsafeGpsRescueAngleHelp": { + "message": "Higher maximum angles lead to more aggressive returns and higher forward speeds. May be useful for heavier, high-drag or low authority craft, or for use in stronger winds. WARNING: Rescue throttle usually needs to be increased if the max angle is increased! Otherwise the quad may lose altitude and crash!" + }, + "failsafeGpsRescueItemDescentDistance": { + "message": "Descent distance (meters)" + }, + "failsafeGpsRescueItemDescendRate": { + "message": "Descend rate (meters/second)" + }, + "failsafeGpsRescueDescendRateHelp": { + "message": "The initial descent rate is set to 3 times this value, decreasing to the set value at the landing altitude." + }, + "failsafeGpsRescueItemMinStartDistHelp" : { + "message": "If the rescue starts too close to home (within this minimum distance), the craft will fly away, on its current heading, until at least this distance from home, and then start normal rescue behaviour", + "description": "Updated help text for the minimum start distance needed for GPS rescue to activate" + }, + "failsafeGpsRescueItemThrottleMin": { + "message": "Throttle minimum" + }, + "failsafeGpsRescueItemThrottleMax": { + "message": "Throttle maximum" + }, + "failsafeGpsRescueThrottleMaxHelp": { + "message": "Should be increased for heavier, high-drag or low authority craft, if a return against strong winds is likely, or if the maximum pitch angle is increased." + }, + "failsafeGpsRescueItemThrottleHover": { + "message": "Throttle hover - IMPORTANT: set this value accurately" + }, + "failsafeGpsRescueThrottleHoverHelp": { + "message": "To find the right value, set the Failsafe switch action to Stage 2, set the Stage 2 Failsafe Procedure to Land, and adjust the Throttle value used while landing until the quad hovers or descends slowly. Then set GPS Rescue Throttle Hover, and the Stage 1 Channel Fallback value for Throttle to this value." + }, + "failsafeGpsRescueItemMinDth": { + "message": "Minimum distance to home (meters)" + }, + "failsafeGpsRescueItemMinDthHelp": { + "message": "The minimum distance to home needed for GPS rescue to activate" + }, + "failsafeGpsRescueItemMinSats": { + "message": "Minimum satellites" + }, + "failsafeGpsRescueItemAllowArmingWithoutFix": { + "message": "Allow arming without fix - WARNING: No fix = disarm on failsafe!" + }, + "failsafeGpsRescueArmWithoutFixHelp": { + "message": "Not recommended. Permits arming without a Home point being set, but the quad will disarm and crash with a true Rx loss failsafe. If tested with a switch, there is a short Do Nothing period before the disarm." + }, "failsafeGpsRescueItemSanityChecks": { "message": "Sanity checks" }, @@ -5107,7 +5125,7 @@ "message": "Custom image:" }, "osdSetupCustomLogoInfoImageSize": { - "message": "Size must be $t(logoWidthPx)×$t(logoHeightPx) pixels" + "message": "Size must be $t(logoWidthPx)x$t(logoHeightPx) pixels" }, "osdSetupCustomLogoInfoColorMap": { "message": "Must contain green, black and white pixels" @@ -5116,7 +5134,7 @@ "message": "Click $t(osdSetupUploadFont.message) to persist custom logo" }, "osdSetupCustomLogoImageSizeError": { - "message": "Invalid image size: {{width}}×{{height}} (expected $t(logoWidthPx)×$t(logoHeightPx))" + "message": "Invalid image size: {{width}}x{{height}} (expected $t(logoWidthPx)×$t(logoHeightPx))" }, "osdSetupCustomLogoColorMapError": { "message": "The image contains an invalid pixel: rgb({{valueR}}, {{valueG}}, {{valueB}}) at coordinates {{posX}}×{{posY}}" diff --git a/src/js/fc.js b/src/js/fc.js index 2dcc0f2c..9f4eecae 100644 --- a/src/js/fc.js +++ b/src/js/fc.js @@ -578,9 +578,9 @@ const FC = { this.GPS_RESCUE = { angle: 0, - initialAltitudeM: 0, + returnAltitudeM: 0, descentDistanceM: 0, - rescueGroundspeed: 0, + groundSpeed: 0, throttleMin: 0, throttleMax: 0, throttleHover: 0, @@ -590,7 +590,8 @@ const FC = { descendRate: 0, allowArmingWithoutFix: 0, altitudeMode: 0, - minRescueDth: 0, + minStartDistM: 0, + initialClimbM: 0, }; this.RXFAIL_CONFIG = []; diff --git a/src/js/msp/MSPHelper.js b/src/js/msp/MSPHelper.js index b80b7594..83d5088b 100644 --- a/src/js/msp/MSPHelper.js +++ b/src/js/msp/MSPHelper.js @@ -514,9 +514,9 @@ MspHelper.prototype.process_data = function(dataHandler) { break; case MSPCodes.MSP_GPS_RESCUE: FC.GPS_RESCUE.angle = data.readU16(); - FC.GPS_RESCUE.initialAltitudeM = data.readU16(); + FC.GPS_RESCUE.returnAltitudeM = data.readU16(); FC.GPS_RESCUE.descentDistanceM = data.readU16(); - FC.GPS_RESCUE.rescueGroundspeed = data.readU16(); + FC.GPS_RESCUE.groundSpeed = data.readU16(); FC.GPS_RESCUE.throttleMin = data.readU16(); FC.GPS_RESCUE.throttleMax = data.readU16(); FC.GPS_RESCUE.throttleHover = data.readU16(); @@ -529,7 +529,10 @@ MspHelper.prototype.process_data = function(dataHandler) { FC.GPS_RESCUE.altitudeMode = data.readU8(); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { - FC.GPS_RESCUE.minRescueDth = data.readU16(); + FC.GPS_RESCUE.minStartDistM = data.readU16(); + } + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { + FC.GPS_RESCUE.initialClimbM = data.readU16(); } break; case MSPCodes.MSP_RSSI_CONFIG: @@ -1797,9 +1800,9 @@ MspHelper.prototype.crunch = function(code, modifierCode = undefined) { break; case MSPCodes.MSP_SET_GPS_RESCUE: buffer.push16(FC.GPS_RESCUE.angle) - .push16(FC.GPS_RESCUE.initialAltitudeM) + .push16(FC.GPS_RESCUE.returnAltitudeM) .push16(FC.GPS_RESCUE.descentDistanceM) - .push16(FC.GPS_RESCUE.rescueGroundspeed) + .push16(FC.GPS_RESCUE.groundSpeed) .push16(FC.GPS_RESCUE.throttleMin) .push16(FC.GPS_RESCUE.throttleMax) .push16(FC.GPS_RESCUE.throttleHover) @@ -1813,7 +1816,10 @@ MspHelper.prototype.crunch = function(code, modifierCode = undefined) { .push8(FC.GPS_RESCUE.altitudeMode); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { - buffer.push16(FC.GPS_RESCUE.minRescueDth); + buffer.push16(FC.GPS_RESCUE.minStartDistM); + } + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { + buffer.push16(FC.GPS_RESCUE.initialClimbM); } break; case MSPCodes.MSP_SET_RSSI_CONFIG: diff --git a/src/js/tabs/failsafe.js b/src/js/tabs/failsafe.js index cacbeae4..2cb69b8e 100644 --- a/src/js/tabs/failsafe.js +++ b/src/js/tabs/failsafe.js @@ -269,9 +269,9 @@ failsafe.initialize = function (callback) { // Load GPS Rescue parameters $('input[name="gps_rescue_angle"]').val(FC.GPS_RESCUE.angle); - $('input[name="gps_rescue_initial_altitude"]').val(FC.GPS_RESCUE.initialAltitudeM); + $('input[name="gps_rescue_return_altitude"]').val(FC.GPS_RESCUE.returnAltitudeM); $('input[name="gps_rescue_descent_distance"]').val(FC.GPS_RESCUE.descentDistanceM); - $('input[name="gps_rescue_ground_speed"]').val((FC.GPS_RESCUE.rescueGroundspeed / 100).toFixed(2)); + $('input[name="gps_rescue_ground_speed"]').val((FC.GPS_RESCUE.groundSpeed / 100).toFixed(1)); $('input[name="gps_rescue_throttle_min"]').val(FC.GPS_RESCUE.throttleMin); $('input[name="gps_rescue_throttle_max"]').val(FC.GPS_RESCUE.throttleMax); $('input[name="gps_rescue_throttle_hover"]').val(FC.GPS_RESCUE.throttleHover); @@ -284,8 +284,8 @@ failsafe.initialize = function (callback) { $('#failsafeGpsRescueItemAltitudeSelect').sortSelect(); if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_43)) { - $('input[name="gps_rescue_ascend_rate"]').val((FC.GPS_RESCUE.ascendRate / 100).toFixed(2)); - $('input[name="gps_rescue_descend_rate"]').val((FC.GPS_RESCUE.descendRate / 100).toFixed(2)); + $('input[name="gps_rescue_ascend_rate"]').val((FC.GPS_RESCUE.ascendRate / 100).toFixed(1)); + $('input[name="gps_rescue_descend_rate"]').val((FC.GPS_RESCUE.descendRate / 100).toFixed(1)); $('input[name="gps_rescue_allow_arming_without_fix"]').prop('checked', FC.GPS_RESCUE.allowArmingWithoutFix > 0); $('select[name="gps_rescue_altitude_mode"]').val(FC.GPS_RESCUE.altitudeMode); } else { @@ -296,18 +296,36 @@ failsafe.initialize = function (callback) { } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { - if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { - $('input[name="gps_rescue_min_dth"]').attr("min", 10); - } else if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) { - $('input[name="gps_rescue_min_dth"]').attr("min", 20); - } - - $('input[name="gps_rescue_min_dth"]').val(FC.GPS_RESCUE.minRescueDth); + $('input[name="gps_rescue_min_start_dist"]').val(FC.GPS_RESCUE.minStartDistM); } else { - $('input[name="gps_rescue_min_dth"]').closest('.number').hide(); + $('input[name="gps_rescue_min_start_dist"]').closest('.number').hide(); } + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) { + $('input[name="gps_rescue_angle"]').attr("max", 80); + $('input[name="gps_rescue_return_altitude"]').attr({"min": 2, "max": 255}); + $('input[name="gps_rescue_descent_distance"]').attr("min", 5); + $('input[name="gps_rescue_min_start_dist"]').attr("min", 20); + $('input[name="gps_rescue_ground_speed"]').attr("min", 0.0); + $('input[name="gps_rescue_ascend_rate"]').attr("min", 0.5); + $('input[name="gps_rescue_descend_rate"]').attr("min", 0.3); + } + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { + $('input[name="gps_rescue_initial_climb"]').val(FC.GPS_RESCUE.initialClimbM); + } else { + $('input[name="gps_rescue_initial_climb"]').closest('.number').hide(); + } + + // Update attributes for API version 4.5 + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { + $('input[name="gps_rescue_angle"]').attr({"min": 30, "max": 60}); + $('input[name="gps_rescue_return_altitude"]').attr({"min": 5, "max": 1000}); + $('input[name="gps_rescue_descent_distance"]').attr("min", 10); + $('input[name="gps_rescue_min_start_dist"]').attr({"min": 10, "max": 30}) + .closest('.number').children('.helpicon').attr("i18n_title", i18n.getMessage("failsafeGpsRescueItemMinStartDistHelp")); + $('input[name="gps_rescue_descend_rate"]').attr({"min": 0.2, "max": 50.0}); + } $('a.save').click(function () { // gather data that doesn't have automatic change event bound @@ -334,9 +352,9 @@ failsafe.initialize = function (callback) { // Load GPS Rescue parameters FC.GPS_RESCUE.angle = $('input[name="gps_rescue_angle"]').val(); - FC.GPS_RESCUE.initialAltitudeM = $('input[name="gps_rescue_initial_altitude"]').val(); + FC.GPS_RESCUE.returnAltitudeM = $('input[name="gps_rescue_return_altitude"]').val(); FC.GPS_RESCUE.descentDistanceM = $('input[name="gps_rescue_descent_distance"]').val(); - FC.GPS_RESCUE.rescueGroundspeed = $('input[name="gps_rescue_ground_speed"]').val() * 100; + FC.GPS_RESCUE.groundSpeed = $('input[name="gps_rescue_ground_speed"]').val() * 100; FC.GPS_RESCUE.throttleMin = $('input[name="gps_rescue_throttle_min"]').val(); FC.GPS_RESCUE.throttleMax = $('input[name="gps_rescue_throttle_max"]').val(); FC.GPS_RESCUE.throttleHover = $('input[name="gps_rescue_throttle_hover"]').val(); @@ -351,7 +369,11 @@ failsafe.initialize = function (callback) { } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { - FC.GPS_RESCUE.minRescueDth = $('input[name="gps_rescue_min_dth"]').val(); + FC.GPS_RESCUE.minStartDistM = $('input[name="gps_rescue_min_start_dist"]').val(); + } + + if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { + FC.GPS_RESCUE.initialClimbM = $('input[name="gps_rescue_initial_climb"]').val(); } function save_failssafe_config() { diff --git a/src/js/tabs/gps.js b/src/js/tabs/gps.js index 1b366464..7c3c893a 100644 --- a/src/js/tabs/gps.js +++ b/src/js/tabs/gps.js @@ -185,8 +185,9 @@ gps.initialize = async function (callback) { const lat = FC.GPS_DATA.lat / 10000000; const lon = FC.GPS_DATA.lon / 10000000; const url = `https://maps.google.com/?q=${lat},${lon}`; - const heading = hasMag ? Math.atan2(FC.SENSOR_DATA.magnetometer[1], FC.SENSOR_DATA.magnetometer[0]) : undefined; - const headingDeg = heading === undefined ? 0 : heading * 180 / Math.PI; + const magHeading = hasMag ? Math.atan2(FC.SENSOR_DATA.magnetometer[1], FC.SENSOR_DATA.magnetometer[0]) : undefined; + const magHeadingDeg = magHeading === undefined ? 0 : magHeading * 180 / Math.PI; + const gpsHeading = FC.GPS_DATA.ground_course / 100; const gnssArray = ['GPS', 'SBAS', 'Galileo', 'BeiDou', 'IMES', 'QZSS', 'Glonass']; const qualityArray = ['gnssQualityNoSignal', 'gnssQualitySearching', 'gnssQualityAcquired', 'gnssQualityUnusable', 'gnssQualityLocked', 'gnssQualityFullyLocked', 'gnssQualityFullyLocked', 'gnssQualityFullyLocked']; @@ -199,8 +200,8 @@ gps.initialize = async function (callback) { const gspUnitText = i18n.getMessage('gpsPositionUnit'); $('.GPS_info td.alt').text(`${alt} m`); - $('.GPS_info td.latLon a').prop('href', url).text(`${lat.toFixed(4)} deg / ${lon.toFixed(4)} deg`); - $('.GPS_info td.heading').text(`${headingDeg.toFixed(4)} ${gspUnitText}`); + $('.GPS_info td.latLon a').prop('href', url).text(`${lat.toFixed(4)} / ${lon.toFixed(4)} ${gspUnitText}`); + $('.GPS_info td.heading').text(`${magHeadingDeg.toFixed(4)} / ${gpsHeading.toFixed(4)} ${gspUnitText}`); $('.GPS_info td.speed').text(`${FC.GPS_DATA.speed} cm/s`); $('.GPS_info td.sats').text(FC.GPS_DATA.numSat); $('.GPS_info td.distToHome').text(`${FC.GPS_DATA.distanceToHome} m`); @@ -296,7 +297,7 @@ gps.initialize = async function (callback) { action: 'center', lat: lat, lon: lon, - heading: heading, + heading: magHeading, }; frame = document.getElementById('map'); diff --git a/src/tabs/failsafe.html b/src/tabs/failsafe.html index f04cb6e2..9744a92e 100644 --- a/src/tabs/failsafe.html +++ b/src/tabs/failsafe.html @@ -118,33 +118,55 @@
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
-
- -
-
+
- -
-
-
-
-
+
@@ -152,22 +174,20 @@
+
- -
-
-
-
-
- +