--[[ script to prevent terrain impact in LOITER mode while flying copters in steep terrain --]] local PARAM_TABLE_KEY = 84 local PARAM_TABLE_PREFIX = "TERR_BRK_" local MODE_LOITER = 5 local MODE_BRAKE = 17 local MAV_SEVERITY = {EMERGENCY=0, ALERT=1, CRITICAL=2, ERROR=3, WARNING=4, NOTICE=5, INFO=6, DEBUG=7} -- add a parameter and bind it to a variable function bind_add_param(name, idx, default_value) assert(param:add_param(PARAM_TABLE_KEY, idx, name, default_value), string.format('could not add param %s', name)) return Parameter(PARAM_TABLE_PREFIX .. name) end -- setup script specific parameters assert(param:add_table(PARAM_TABLE_KEY, PARAM_TABLE_PREFIX, 14), 'could not add param table') --[[ // @Param: TERR_BRK_ENABLE // @DisplayName: terrain brake enable // @Description: terrain brake enable // @Values: 0:Disabled,1:Enabled // @User: Standard --]] local TERR_BRK_ENABLE = bind_add_param('ENABLE', 1, 1) --[[ // @Param: TERR_BRK_ALT // @DisplayName: terrain brake altitude // @Description: terrain brake altitude. The altitude above the ground below which BRAKE mode will be engaged if in LOITER mode. // @Range: 1 100 // @Units: m // @User: Standard --]] local TERR_BRK_ALT = bind_add_param('ALT', 2, 30) --[[ // @Param: TERR_BRK_HDIST // @DisplayName: terrain brake home distance // @Description: terrain brake home distance. The distance from home where the auto BRAKE will be enabled. When within this distance of home the script will not activate // @Range: 0 1000 // @Units: m // @User: Standard --]] local TERR_BRK_HDIST = bind_add_param('HDIST', 3, 100) --[[ // @Param: TERR_BRK_SPD // @DisplayName: terrain brake speed threshold // @Description: terrain brake speed threshold. Don't trigger BRAKE if both horizontal speed and descent rate are below this threshold. By setting this to a small value this can be used to allow the user to climb up to a safe altitude in LOITER mode. A value of 0.5 is recommended if you want to use LOITER to recover from an emergency terrain BRAKE mode change. // @Range: 0 5 // @Units: m/s // @User: Standard --]] local TERR_BRK_SPD = bind_add_param('SPD', 4, 0) local function sq(x) return x*x end local function run_checks() if TERR_BRK_ENABLE:get() ~= 1 then return end if not arming:is_armed() then return end if vehicle:get_mode() ~= MODE_LOITER then return end if not ahrs:home_is_set() then return end local home = ahrs:get_home() local pos = ahrs:get_location() if not pos then return end local home_dist = pos:get_distance(home) if home_dist <= TERR_BRK_HDIST:get() then return end --[[ get height above terrain with extrapolation --]] local hagl = terrain:height_above_terrain(true) if hagl >= TERR_BRK_ALT:get() then return end --[[ allow for climbing in LOITER mode if enabled --]] if TERR_BRK_SPD:get() > 0 then local spd = ahrs:get_velocity_NED() if spd ~= nil then local hspd = math.sqrt(sq(spd:x())+sq(spd:y())) local drate = spd:z() if hspd < TERR_BRK_SPD:get() and drate < TERR_BRK_SPD:get() then return end end end if vehicle:set_mode(MODE_BRAKE) then gcs:send_text(MAV_SEVERITY.EMERGENCY, string.format("Terrain %.1fm - BRAKE", hagl)) end end --[[ main update function, called at 1Hz --]] function update() run_checks() return update, 100 end if TERR_BRK_ENABLE:get() == 1 then gcs:send_text(MAV_SEVERITY.INFO, string.format("Loaded Loiter/Brake checker")) end -- start running update loop return update, 1000