diff --git a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/10_loops-and-immelman.lua b/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/10_loops-and-immelman.lua deleted file mode 100644 index 9627cc0cc9..0000000000 --- a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/10_loops-and-immelman.lua +++ /dev/null @@ -1,324 +0,0 @@ --- loops and returns on switch - -TRICK_NUMBER = 10 -- selector number recognized to execute trick, change as desired --- number of loops controlled by AERO_RPT_COUNT, if 0 it will do an immelman instead, trick returns control after executing even if trick id remains 10 - -local target_vel -- trick specific global variables -local loop_stage - -------------------------------------------------------------------- --- do not change anything unless noted - -local running = false -local not_bound = true -local initial_yaw_deg = 0 -local initial_height = 0 -local repeat_count - --- constrain a value between limits -function constrain(v, vmin, vmax) - if v < vmin then - v = vmin - end - if v > vmax then - v = vmax - end - return v -end - - -function wrap_360(angle) --function returns positive angle modulo360, -710 in returns 10, -10 returns +350 - local res = math.fmod(angle, 360.0) - if res < 0 then - res = res + 360.0 - end - return res -end - -function wrap_180(angle) - local res = wrap_360(angle) - if res > 180 then - res = res - 360 - end - return res -end - --- roll angle error 180 wrap to cope with errors while in inverted segments -function roll_angle_error_wrap(roll_angle_error) - if math.abs(roll_angle_error) > 180 then - if roll_angle_error > 0 then - roll_angle_error = roll_angle_error - 360 - else - roll_angle_error= roll_angle_error +360 - end - end - return roll_angle_error -end - ---roll controller to keep wings level in earth frame. if arg is 0 then level is at only 0 deg, otherwise its at 180/-180 roll also for loops -function earth_frame_wings_level(arg) - local roll_deg = math.deg(ahrs:get_roll()) - local roll_angle_error = 0.0 - if (roll_deg > 90 or roll_deg < -90) and arg ~= 0 then - roll_angle_error = 180 - roll_deg - else - roll_angle_error = - roll_deg - end - return roll_angle_error_wrap(roll_angle_error)/(RLL2SRV_TCONST:get()) -end - --- constrain rates to rate controller call -function _set_target_throttle_rate_rpy(throttle,roll_rate, pitch_rate, yaw_rate) - local r_rate = constrain(roll_rate,-RATE_MAX:get(),RATE_MAX:get()) - local p_rate = constrain(pitch_rate,-RATE_MAX:get(),RATE_MAX:get()) - vehicle:set_target_throttle_rate_rpy(throttle, r_rate, p_rate, yaw_rate) -end - --- a PI controller implemented as a Lua object -local function PI_controller(kP,kI,iMax) - -- the new instance. You can put public variables inside this self - -- declaration if you want to - local self = {} - - -- private fields as locals - local _kP = kP or 0.0 - local _kI = kI or 0.0 - local _kD = kD or 0.0 - local _iMax = iMax - local _last_t = nil - local _I = 0 - local _P = 0 - local _total = 0 - local _counter = 0 - local _target = 0 - local _current = 0 - - -- update the controller. - function self.update(target, current) - local now = millis():tofloat() * 0.001 - if not _last_t then - _last_t = now - end - local dt = now - _last_t - _last_t = now - local err = target - current - _counter = _counter + 1 - - local P = _kP * err - _I = _I + _kI * err * dt - if _iMax then - _I = constrain(_I, -_iMax, iMax) - end - local I = _I - local ret = P + I - - _target = target - _current = current - _P = P - _total = ret - return ret - end - - -- reset integrator to an initial value - function self.reset(integrator) - _I = integrator - end - - function self.set_I(I) - _kI = I - end - - function self.set_P(P) - _kP = P - end - - function self.set_Imax(Imax) - _iMax = Imax - end - - -- log the controller internals - function self.log(name, add_total) - -- allow for an external addition to total - logger:write(name,'Targ,Curr,P,I,Total,Add','ffffff',_target,_current,_P,_I,_total,add_total) - end - -- return the instance - return self -end - -local function height_controller(kP_param,kI_param,KnifeEdge_param,Imax) - local self = {} - local kP = kP_param - local kI = kI_param - local KnifeEdge = KnifeEdge_param - local PI = PI_controller(kP:get(), kI:get(), Imax) - - function self.update(target) - local target_pitch = PI.update(initial_height, ahrs:get_position():alt()*0.01) - local roll_rad = ahrs:get_roll() - local ke_add = math.abs(math.sin(roll_rad)) * KnifeEdge:get() - target_pitch = target_pitch + ke_add - PI.log("HPI", ke_add) - return constrain(target_pitch,-45,45) - end - - function self.reset() - PI.reset(math.max(math.deg(ahrs:get_pitch()), 3.0)) - PI.set_P(kP:get()) - PI.set_I(kI:get()) - end - - return self -end - --- a controller to target a zero pitch angle and zero heading change, used in a roll --- output is a body frame pitch rate, with convergence over time tconst in seconds -function pitch_controller(target_pitch_deg, target_yaw_deg, tconst) - local roll_deg = math.deg(ahrs:get_roll()) - local pitch_deg = math.deg(ahrs:get_pitch()) - local yaw_deg = math.deg(ahrs:get_yaw()) - - -- get earth frame pitch and yaw rates - local ef_pitch_rate = (target_pitch_deg - pitch_deg) / tconst - local ef_yaw_rate = wrap_180(target_yaw_deg - yaw_deg) / tconst - - local bf_pitch_rate = math.sin(math.rad(roll_deg)) * ef_yaw_rate + math.cos(math.rad(roll_deg)) * ef_pitch_rate - local bf_yaw_rate = math.cos(math.rad(roll_deg)) * ef_yaw_rate - math.sin(math.rad(roll_deg)) * ef_pitch_rate - return bf_pitch_rate, bf_yaw_rate -end - --- a controller for throttle to account for pitch -function throttle_controller() - local pitch_rad = ahrs:get_pitch() - local thr_ff = THR_PIT_FF:get() - local throttle = TRIM_THROTTLE:get() + math.sin(pitch_rad) * thr_ff - return constrain(throttle, TRIM_THROTTLE:get(), 100.0) -end -function bind_param(name) - local p = Parameter() - if p:init(name) then - not_bound = false - return p - else - not_bound = true - end -end - --- recover entry altitude -function recover_alt() - local target_pitch = height_PI.update(initial_height) - local pitch_rate, yaw_rate = pitch_controller(target_pitch, initial_yaw_deg, PITCH_TCONST:get()) - throttle = throttle_controller() - return throttle, pitch_rate, yaw_rate -end ----------------------------------------------------------------------------------------------- ---every trick needs an init, change as needed...to bind the AERO params it uses(which will depend on the trick), and setup PID controllers used by script - -function init() - HGT_P = bind_param("AERO_HGT_P") -- height P gain, required for height controller - HGT_I = bind_param("AERO_HGT_I") -- height I gain, required for height controller - HGT_KE_BIAS = bind_param("AERO_HGT_KE_BIAS") -- height knifeedge addition for pitch - THR_PIT_FF = bind_param("AERO_THR_PIT_FF") -- throttle FF from pitch - TRIM_THROTTLE = bind_param("TRIM_THROTTLE") --usually required for any trick - TRIM_ARSPD_CM = bind_param("TRIM_ARSPD_CM") --usually required for any trick - RATE_MAX = bind_param("AERO_RATE_MAX") - RLL2SRV_TCONST = bind_param("RLL2SRV_TCONST") --usually required for any trick - PITCH_TCONST = bind_param("PTCH2SRV_TCONST") --usually required for any trick - TRICK_ID = bind_param("AERO_TRICK_ID") --- required for any trick - TRICK_RAT = bind_param("AERO_TRICK_RAT") --usually required for any trick - RPT_COUNT = bind_param("AERO_RPT_COUNT") --repeat count for trick -if not_bound then - gcs:send_text(0,string.format("Not bound yet")) - return init, 100 -else - gcs:send_text(0,string.format("Params bound,Trick %.0f loaded", TRICK_NUMBER)) - height_PI = height_controller(HGT_P, HGT_I, HGT_KE_BIAS, 20.0) -- this trick needs this height PID controller setup to hold height during the trick - loop_stage = 0 - return update, 50 -end -end ------------------------------------------------------------------------------------------------ ---every trick will have its own do_trick function to perform the trick...this will change totally for each different trick - -function do_loop(arg1) - -- do one loop with controllable pitch rate arg1 is pitch rate, arg2 number of loops, 0 indicates 1/2 cuban8 reversa - local throttle = throttle_controller() - local pitch_deg = math.deg(ahrs:get_pitch()) - local roll_deg = math.deg(ahrs:get_roll()) - local vel = ahrs:get_velocity_NED():length() - local pitch_rate = arg1 - local yaw_rate = 0 - pitch_rate = pitch_rate * (1+ 2*((vel/target_vel)-1)) --increase/decrease rate based on velocity to round loop - pitch_rate = constrain(pitch_rate,.5 * arg1, 3 * arg1) - if loop_stage == 0 then - if pitch_deg > 60 then - loop_stage = 1 - end - elseif loop_stage == 1 then - if (math.abs(roll_deg) < 90 and pitch_deg > -5 and pitch_deg < 5 and repeat_count > 0) then - -- we're done with loop - gcs:send_text(0, string.format("Finished loop p=%.1f", pitch_deg)) - loop_stage = 2 --now recover stage - repeat_count = repeat_count - 1 - elseif (math.abs(roll_deg) > 90 and pitch_deg > -5 and pitch_deg < 5 and repeat_count <= 0) then - gcs:send_text(0, string.format("Finished return p=%.1f", pitch_deg)) - loop_stage = 2 --now recover stage - repeat_count = repeat_count - 1 - initial_yaw_deg = math.deg(ahrs:get_yaw()) - end - elseif loop_stage == 2 then - -- recover alt if above or below start and terminate - - if repeat_count > 0 then - --yaw_rate = 0 - loop_stage = 0 - elseif math.abs(ahrs:get_position():alt()*0.01 - initial_height) > 3 then - - throttle, pitch_rate, yaw_rate = recover_alt() - else - running = false - gcs:send_text(0, string.format("Recovered entry alt")) - TRICK_ID:set(0) - return - end - end - throttle = throttle_controller() - if loop_stage == 2 or loop_stage == 0 then level_type = 0 else level_type = 1 end - if math.abs(pitch_deg) > 85 and math.abs(pitch_deg) < 95 then - roll_rate = 0 - else - roll_rate = earth_frame_wings_level(level_type) - end - _set_target_throttle_rate_rpy(throttle, roll_rate, pitch_rate, yaw_rate) -end - -------------------------------------------------------------------------------------------- ---trick should noramlly only have to change the notification text in this routine,initialize trick specific variables, and any parameters needing to be passed to do_trick(..) - -function update() - if (TRICK_ID:get() == TRICK_NUMBER) then - local current_mode = vehicle:get_mode() - if arming:is_armed() and running == false then - if not vehicle:nav_scripting_enable(current_mode) then - return update, 50 - end - running = true - initial_height = ahrs:get_position():alt()*0.01 - initial_yaw_deg = math.deg(ahrs:get_yaw()) - height_PI.reset() - repeat_count = RPT_COUNT:get() - -----------------------------------------------trick specific - loop_stage = 0 - target_vel = ahrs:get_velocity_NED():length() - gcs:send_text(0, string.format("Loop/Return")) --change announcement as appropriate for trick - ------------------------------------------------------- - elseif running == true then - do_loop(TRICK_RAT:get()) -- change arguments as appropriate for trick - end - else - running = false - end - return update, 50 -end - -return init,1000 - diff --git a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/5_knifedges.lua b/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/5_knifedges.lua deleted file mode 100644 index 5aa317f5b3..0000000000 --- a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/5_knifedges.lua +++ /dev/null @@ -1,243 +0,0 @@ --- knife edge on switch - -TRICK_NUMBER = 5 -- selector number recognized to execute trick, change as desired --- knife-edge angle set by AERO_TRICK_ANG, active for as long as trick id = 5 -------------------------------------------------------------------- --- do not change anything below unless noted - -local running = false -local not_bound = true -local initial_yaw_deg = 0 -local initial_height = 0 -local repeat_count - --- constrain a value between limits -function constrain(v, vmin, vmax) - if v < vmin then - v = vmin - end - if v > vmax then - v = vmax - end - return v -end - - -function wrap_360(angle) --function returns positive angle modulo360, -710 in returns 10, -10 returns +350 - local res = math.fmod(angle, 360.0) - if res < 0 then - res = res + 360.0 - end - return res -end - -function wrap_180(angle) - local res = wrap_360(angle) - if res > 180 then - res = res - 360 - end - return res -end - --- a PI controller implemented as a Lua object -local function PI_controller(kP,kI,iMax) - -- the new instance. You can put public variables inside this self - -- declaration if you want to - local self = {} - - -- private fields as locals - local _kP = kP or 0.0 - local _kI = kI or 0.0 - local _kD = kD or 0.0 - local _iMax = iMax - local _last_t = nil - local _I = 0 - local _P = 0 - local _total = 0 - local _counter = 0 - local _target = 0 - local _current = 0 - - -- update the controller. - function self.update(target, current) - local now = millis():tofloat() * 0.001 - if not _last_t then - _last_t = now - end - local dt = now - _last_t - _last_t = now - local err = target - current - _counter = _counter + 1 - - local P = _kP * err - _I = _I + _kI * err * dt - if _iMax then - _I = constrain(_I, -_iMax, iMax) - end - local I = _I - local ret = P + I - - _target = target - _current = current - _P = P - _total = ret - return ret - end - - -- reset integrator to an initial value - function self.reset(integrator) - _I = integrator - end - - function self.set_I(I) - _kI = I - end - - function self.set_P(P) - _kP = P - end - - function self.set_Imax(Imax) - _iMax = Imax - end - - -- log the controller internals - function self.log(name, add_total) - -- allow for an external addition to total - logger:write(name,'Targ,Curr,P,I,Total,Add','ffffff',_target,_current,_P,_I,_total,add_total) - end - -- return the instance - return self -end - -local function height_controller(kP_param,kI_param,KnifeEdge_param,Imax) - local self = {} - local kP = kP_param - local kI = kI_param - local KnifeEdge = KnifeEdge_param - local PI = PI_controller(kP:get(), kI:get(), Imax) - - function self.update(target) - local target_pitch = PI.update(initial_height, ahrs:get_position():alt()*0.01) - local roll_rad = ahrs:get_roll() - local ke_add = math.abs(math.sin(roll_rad)) * KnifeEdge:get() - target_pitch = target_pitch + ke_add - PI.log("HPI", ke_add) - return constrain(target_pitch,-45,45) - end - - function self.reset() - PI.reset(math.max(math.deg(ahrs:get_pitch()), 3.0)) - PI.set_P(kP:get()) - PI.set_I(kI:get()) - end - - return self -end - --- a controller to target a zero pitch angle and zero heading change, used in a roll --- output is a body frame pitch rate, with convergence over time tconst in seconds -function pitch_controller(target_pitch_deg, target_yaw_deg, tconst) - local roll_deg = math.deg(ahrs:get_roll()) - local pitch_deg = math.deg(ahrs:get_pitch()) - local yaw_deg = math.deg(ahrs:get_yaw()) - - -- get earth frame pitch and yaw rates - local ef_pitch_rate = (target_pitch_deg - pitch_deg) / tconst - local ef_yaw_rate = wrap_180(target_yaw_deg - yaw_deg) / tconst - - local bf_pitch_rate = math.sin(math.rad(roll_deg)) * ef_yaw_rate + math.cos(math.rad(roll_deg)) * ef_pitch_rate - local bf_yaw_rate = math.cos(math.rad(roll_deg)) * ef_yaw_rate - math.sin(math.rad(roll_deg)) * ef_pitch_rate - return bf_pitch_rate, bf_yaw_rate -end - --- a controller for throttle to account for pitch -function throttle_controller() - local pitch_rad = ahrs:get_pitch() - local thr_ff = THR_PIT_FF:get() - local throttle = TRIM_THROTTLE:get() + math.sin(pitch_rad) * thr_ff - return constrain(throttle, TRIM_THROTTLE:get(), 100.0) -end - -function bind_param(name) - local p = Parameter() - if not p:init(name) then - not_bound = true - end - return p -end ----------------------------------------------------------------------------------------------- ---every trick needs an init, change as needed...to bind the AERO params it uses(which will depend on the trick), and setup PID controllers used by script - -function init() - not_bound = false - HGT_P = bind_param("AERO_HGT_P") -- height P gain, required for height controller - HGT_I = bind_param("AERO_HGT_I") -- height I gain, required for height controller - HGT_KE_BIAS = bind_param("AERO_HGT_KE_BIAS") -- height knifeedge addition for pitch - THR_PIT_FF = bind_param("AERO_THR_PIT_FF") -- throttle FF from pitch - TRIM_THROTTLE = bind_param("TRIM_THROTTLE") --usually required for any trick - TRIM_ARSPD_CM = bind_param("TRIM_ARSPD_CM") --usually required for any trick - RLL2SRV_TCONST = bind_param("RLL2SRV_TCONST") --usually required for any trick - PITCH_TCONST = bind_param("PTCH2SRV_TCONST") --usually required for any trick - KE_ANG = bind_param("AERO_TRICK_ANG") --this particulat trick needs a target angle for the knife-edge its doing - TRICK_ID = bind_param("AERO_TRICK_ID") --- required for any trick - RPT_COUNT = bind_param("AERO_RPT_COUNT") -- if trick can repeat -if not_bound then - gcs:send_text(0,string.format("Not bound yet")) - return init, 100 -else - gcs:send_text(0,string.format("Params bound,Trick %.0f loaded", TRICK_NUMBER)) - height_PI = height_controller(HGT_P, HGT_I, HGT_KE_BIAS, 20.0) -- this trick needs this height PID controller setup to hold height during the trick - return update, 1000 -end -end ------------------------------------------------------------------------------------------------ ---every trick will have its own do_trick function to perform the trick...this will change totally for each different trick - -function do_trick(arg1) - -- arg1 is angle +/-180 - local roll_deg = math.deg(ahrs:get_roll()) - local roll_angle_error = (arg1 - roll_deg) - if math.abs(roll_angle_error) > 180 then - if roll_angle_error > 0 then - roll_angle_error = roll_angle_error - 360 - else - roll_angle_error= roll_angle_error +360 - end - end - local roll_rate = roll_angle_error/(RLL2SRV_TCONST:get()) - local target_pitch = height_PI.update(initial_height) - local pitch_rate, yaw_rate = pitch_controller(target_pitch, initial_yaw_deg, PITCH_TCONST:get()) - local throttle = throttle_controller() - vehicle:set_target_throttle_rate_rpy(throttle, roll_rate, pitch_rate, yaw_rate) - return -end -------------------------------------------------------------------------------------------- ---trick should noramlly only have to change the notification text in this routine,initialize trick specific variables, and any parameters needing to be passed to do_trick(..) - -function update() - if (TRICK_ID:get() == TRICK_NUMBER) then - local current_mode = vehicle:get_mode() - if arming:is_armed() and running == false then - if not vehicle:nav_scripting_enable(current_mode) then - return update, 50 - end - running = true - initial_height = ahrs:get_position():alt()*0.01 - initial_yaw_deg = math.deg(ahrs:get_yaw()) - height_PI.reset() - repeat_count = RPT_COUNT:get() --not used in this trick, knife-edge on as long as mode does not change or sw is not lowered - -----------------------------------------------trick specific - gcs:send_text(0, string.format("%d Knife edge", KE_ANG:get())) --change announcement as appropriate for trick - ---------------------------------------------------------- - elseif running == true then - do_trick(KE_ANG:get()) -- change arguments as appropriate for trick - end - else - running = false - end - return update, 50 -end - -return init,1000 - diff --git a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/README b/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/README deleted file mode 100644 index ced2455b85..0000000000 --- a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/README +++ /dev/null @@ -1,22 +0,0 @@ -Aerobatics via an RC switch -=========================== - -this requires the lua_trick_selector.lua script -additional individual trick scripts can then be selectively executed via a switch - -RCx_OPTION switch 300 is the activations switch to execute a trick -RCx_OPTION switch 301 selects a trick from up to 10 trick scripts to execute - -included as templates are two tricks: any angle knife-edge and a loop/return - -activation switch when high will start the trick, which may self terminate (loop/return example), or continue indefinitely (knige-edge) until switch is low, when switched from low to mid and held for 0.5 second, the trick number selected by the selection channel is announced - -trick is aborted if: -- activation switch is returned low -- flight mode changes -- script hangs, ie does not call the set_target_throttle_rpy(..) function every 50ms -- trick selection is moved to 0 (low) - -Only modes defined in the nav_scripting_enable(mode) function call can enable scripting control and current flight mode must match the "mode" argument - -Note: for tricks like knifedges which normally are indefinite(could modify this trick for a fixed duration, instead, though) until activation switch is set back low or mode is changed, the exit is totally dependent upon the mode being re-entered....for example, returning to FBWA can result in a change of heading as FBWA re-establishes level depending on knife-edge angle (90 deg has worst heading shift upon FBWA recovery), ACRO shows no change of attitude,CRUISE will re-establish track to last CRUISE target update, etc. diff --git a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/lua_trick_selector.lua b/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/lua_trick_selector.lua deleted file mode 100644 index e67a1f188c..0000000000 --- a/libraries/AP_Scripting/examples/Aerobatics/Via_Switch/lua_trick_selector.lua +++ /dev/null @@ -1,59 +0,0 @@ --- master control script for selecting aerobatics scripts --- the two rc channels below must be assigned - -local scripting_rc_activation = assert(rc:find_channel_for_option(300), 'no sw assigned for trick activation') -- trick script selection channel -local scripting_rc_selection = assert(rc:find_channel_for_option(301), 'no switch assigned for trick selection') -- trick script activation channel (low:off/stop, mid:report trick ID to GCS, high:do trick - -local trick_id = 0 --current trick ID, 0 means no trick, placing any number into the AERO_TRICK_ID param below means execute a script that recognizes it as its trick ID - -local sw_current = scripting_rc_activation:norm_input() --current position of scripting_rc_activation switch -1 to 1 -local sw_last = sw_current -- last position of scripting scripting_rc_activation switch - --- setup param block for aerobatics, reserving 30 params beginning with AERO_ -local PARAM_TABLE_KEY = 72 -assert(param:add_table(PARAM_TABLE_KEY, "AERO_", 30), 'could not add param table') - --- this control script uses AERO_TRICK_ID to report the selected trick number from the scripting_rc_selection rc channel -assert(param:add_param(PARAM_TABLE_KEY, 1, 'TRICK_ID', 0), 'could not add param1') -- trick IDs for switch activation -assert(param:add_param(PARAM_TABLE_KEY, 2, 'RPT_COUNT', 0), 'could not add param2') -- trick repeats -assert(param:add_param(PARAM_TABLE_KEY, 3, 'RATE_MAX', 120), 'could not add param3') -- max rates applied to axes(like ACRO rate param) -assert(param:add_param(PARAM_TABLE_KEY, 4, 'HGT_P', 1), 'could not add param4') -- height P gain -assert(param:add_param(PARAM_TABLE_KEY, 5, 'HGT_I', 2), 'could not add param5') -- height I gain -assert(param:add_param(PARAM_TABLE_KEY, 6, 'HGT_KE_BIAS', 20), 'could not add param6') --height knife-edge addition for pitch -assert(param:add_param(PARAM_TABLE_KEY, 7, 'THR_PIT_FF', 80), 'could not add param67') --throttle FF from pitch -assert(param:add_param(PARAM_TABLE_KEY, 8, 'SPD_P', 5), 'could not add param8') -- speed P gain -assert(param:add_param(PARAM_TABLE_KEY, 9, 'SPD_I', 25), 'could not add param9') -- speed I gain -assert(param:add_param(PARAM_TABLE_KEY, 10, 'TRICK_ANG', 90), 'could not add param10') -- knife-edge angle,etc. -assert(param:add_param(PARAM_TABLE_KEY, 11, 'TRICK_RAT', 90), 'could not add param11') -- used for trick loop rate, axial roll rates, etc - - -local trick_id = Parameter("AERO_TRICK_ID") -local sw_last = 0 -local sw_current = 0 -local last_selection = 0 -function update() - local trick_selection = math.floor(5 * (scripting_rc_selection:norm_input_ignore_trim() +1)) -- produces range of 0 to 10 for selecting trick ID - if trick_selection == 0 then -- anytime trick selection is zero force trick ID to 0, another way to terminate tricks - trick_id:set(trick_selection) - end - sw_current = scripting_rc_activation:norm_input_ignore_trim() - if sw_current == sw_last then - if sw_current > -0.25 and sw_current < 0.75 and last_selection ~= trick_selection then - gcs:send_text(0, string.format("Current trick ID = %.0f",trick_selection)) - last_selection = trick_selection - end - return update, 500 - else - if sw_current < -0.25 then - trick_id:set(0) - elseif sw_current > 0.75 and arming:is_armed() then --setting trick ID to non-zero should be recognized by trick with that ID to init and execute - trick_id:set(trick_selection) - elseif sw_last < -0.25 and sw_current > -0.25 and sw_current < 0.75 then - gcs:send_text(0, string.format("Current trick ID = %.0f",trick_selection)) - end - sw_last = sw_current - return update, 500 - end -end - -return update, 50