--[[ -- -- -- -- -- -- -- -- -- -- -- -- Taxi_speed.lua v1.1 created by Mike Gromley December 2019 this script will maintain a taxi speed close to the speed set by the user by adjusting the throttle and brake to maintain speed. Revisions Version 1.1 Version 1.2 by RAJ 03/12/2022 to work for ToLiss A321 also works for JD A330, but not FF A350 1) Added disconnect master on toe brake press 2) Added BetterPushback commands if it is installed BetterPushback is the work of *Click on one of the two speed boxes to open/close BP panel 3) Fixed (hopefully) the throttle sticking on occasion Usage 1) set the speed you would like to taxi with the mouse wheel on Taxi Speed boxes. 2) Master has to be on 3) Park brake has to be off 4) It is disabled in the air 5) It is automatically disablled if you advance the throttles bast 45% 6) It doesn't hold the exact speed that is set but in the area, usually by 1-3 knots In this version you can arm taxi after landing, retract flaps, and retract spoilers in any combination. --Thanks to KAPTEJNLN for his autopilot script that taught me how to do the interface]] --print(string.format("############ Taxi_Speed - PLANE_ICAO: %s", PLANE_ICAO)) --============ USER CHANGABLE VARIABLES default values in ( ) local l_desired_speed = 15 -- default taxi speed (20) local l_max_taxi = 30 -- maximum selectable taxi speed (30) local l_flap_splr_speed = 45 -- ground speed spoilers and flaps are retracted if set to armed(45) local l_mstr_off_at = 0.45 -- throttle percent that turns off master 0.4 to 0.7 (0.45) local l_toebrake_ratio = 0.15 -- percentage of toebrake that turns off master 0.0 - 0.5(0.15) --** -- where to place the click text and subsequent rows **-- local l_x_pos = 25 -- distance from left edge (25) local l_y_pos = 10 -- distance up from bottom edge(10) --** change 0 to 1 to have these defaulted to on at startup 1 is on 0 is off **-- local ls_master_status = 0 -- Master switch local ls_brake_status = 1 -- Parking brake local ls_taxi_AL = 1 -- Arm taxi after landing local ls_flaps_AL = 0 -- Arm flaps up after landing local ls_spoilers_AL = 1 -- Arm retract spoilers at l_splrs_speed after landing local l_show_main = 1 -- Start with panel open local l_display_text = "Taxi" -- Displayed text when panels are not displayed -- Clickspot only works on first 4 characters --============ END of USER CHANGABLE VARIABLES --===================================== TEXT TABLES local ltx_status_txt = {[0] = "OFF", [1] = "ON", [2] = "ARMD", [3] = "TLS"} local ltx_colors = {[0] = "white", [1] = "green", [2] = "yellow", [3] = "red"} local ltx_AL_colors = {[0] = "white", [1] = "yellow"} --===================================== Misc local l_show_AL = 0 --arming row visible local l_show_BP = 0 local l_toliss = nil --the Toliss A319/21 is loaded local l_thrtl = 0.0 local l_brake = 0.0 local l_ground_speed = 0 local l_we_landed = 0 local l_we_took_off = 0 local l_counter = 0 local l_brake_counter = 0 local ls_armed_status = 0 local l_default_check = true local ls_home_status = 0 local ls_pre_master = 0 local l_check = false local l_debug = false -- 1 for debug info to screen local l_better_pb = 0 --===================================== Datarefs dataref("dr_ground_speed", "sim/flightmodel/position/groundspeed", "readonly") dataref("dr_on_ground", "sim/flightmodel/failures/onground_any", "readonly") dataref("dr_flap_ratio", "sim/cockpit2/controls/flap_ratio", "readonly") dataref("dr_speedbrake_ratio", "sim/cockpit2/controls/speedbrake_ratio", "readonly") dataref("dr_rbrake_ratio", "sim/cockpit2/controls/right_brake_ratio", "readonly") dataref("dr_lbrake_ratio", "sim/cockpit2/controls/left_brake_ratio", "readonly") dataref("dr_parkbrake_ratio", "sim/cockpit2/controls/parking_brake_ratio", "readonly") --==== modification of vSpeedsCallouts method ============================================================== function getAircraftName() local t = {} -- table to store the indices local i = 0 while true do i = string.find(AIRCRAFT_PATH, "/", i+1) -- find next "/" pattern in path if i == nil then break end table.insert(t, i) end aircraft = AIRCRAFT_PATH:sub(t[table.maxn(t)-1] + 1,AIRCRAFT_PATH.len(AIRCRAFT_PATH) - 1) logMsg("Taxi_Speed - aircraft type: "..aircraft) -- current version (V1p3p1+) has AIRCRAFT_PATH string as ToLissA321_V1p3p1 not ToLiss321_V1p3p1: if aircraft.lower(aircraft):match("tolissa3[12][019]") then l_toliss = 1 end t = nil i = nil end -- end function getAircraftName() --========================================================================================================== --Because toliss uses different datarefs: --original logic was: if PLANE_ICAO is NOT A319, then do [...], otherwise do [...] --if PLANE_ICAO ~= "A319" then // ~= is negation symbol in lua !!! --this seems confusing, and didn't work anyway for A321 (but amending A319 to A321 did work), so changed to using --vSpeedsCallouts method of determining if it's a ToLiss airbus [for non-ToLiss A319/21 see end of script for directions] getAircraftName() if l_toliss == 1 then logMsg("Taxi_Speed - loading ToLiss datarefs") dataref("dr_throttle", "AirbusFBW/throttle_input", "writable", 0) dataref("dr_throttle_1", "AirbusFBW/throttle_input", "writable", 1) dataref("dr_toliss_park_brake", "AirbusFBW/ParkBrake", "writable") else logMsg("Taxi_Speed - loading standard datarefs") dataref("dr_throttle", "sim/cockpit2/engine/actuators/throttle_ratio_all", "readonly") end --===================================== functions function f_set_controls(x_brake, x_throttle) if x_brake then -- logMsg("Taxi_Speed - x_brake: "..x_brake) set("sim/cockpit2/controls/parking_brake_ratio", x_brake) if l_toliss then set("sim/cockpit2/controls/left_brake_ratio", x_brake) set("sim/cockpit2/controls/right_brake_ratio", x_brake) dr_toliss_park_brake = x_brake end end if x_throttle then -- logMsg("Taxi_Speed - x_throttle: "..x_throttle) if l_toliss then dr_throttle = x_throttle dr_throttle_1 = x_throttle else set("sim/cockpit2/engine/actuators/throttle_ratio_all", x_throttle) end end end --============ Drawing function f_draw_TS() --if user changed brake via keyboard or cockpit if dr_on_ground == 1 then if ls_brake_status == 1 or ls_brake_status == 0 then if l_toliss then ls_brake_status = dr_toliss_park_brake else ls_brake_status = dr_parkbrake_ratio end end end glColor4f(0.5,0.5,0.5,1.0) if l_show_main == 0 then draw_string(l_x_pos, l_y_pos, l_display_text, ltx_colors[ls_home_status] ) else-- Show the main row glRectf(l_x_pos, l_y_pos - 9, l_x_pos + 400, l_y_pos + 10) draw_string(l_x_pos + 390, l_y_pos - 3, "X", ltx_colors[0] ) draw_string(l_x_pos + 157, l_y_pos - 3, "|Set:" .. l_desired_speed, "cyan") draw_string(l_x_pos + 205, l_y_pos - 3, "|Speed:" .. l_ground_speed, "black") draw_string(l_x_pos + 270, l_y_pos - 3, "|", "black") draw_string(l_x_pos + 275, l_y_pos - 3, " Arm on Landing |", ltx_AL_colors[ls_armed_status]) draw_string(l_x_pos, l_y_pos - 3, "Master: " .. ltx_status_txt[ls_home_status], ltx_colors[ls_home_status]) draw_string(l_x_pos + 80, l_y_pos - 3, "| Brake: " .. ltx_status_txt[math.floor(ls_brake_status)], ltx_colors[ls_brake_status]) -- Show the arm on landing options if l_show_AL + l_show_main == 2 then glRectf(l_x_pos + 270, l_y_pos + 10,l_x_pos + 400,l_y_pos + 30) draw_string(l_x_pos + 270, l_y_pos + 20, "| Taxi", ltx_AL_colors[ls_taxi_AL]) draw_string(l_x_pos + 315, l_y_pos + 20, "| Flaps", ltx_AL_colors[ls_flaps_AL]) draw_string(l_x_pos + 355, l_y_pos + 20, "| Splrs", ltx_AL_colors[ls_spoilers_AL]) draw_string(l_x_pos + 397, l_y_pos + 20, "|",ltx_AL_colors[ls_spoilers_AL]) end if (not l_default_check) and (l_better_pb + l_show_main + l_show_BP == 3) then glRectf(l_x_pos + 80, l_y_pos + 10,l_x_pos + 275,l_y_pos + 38) draw_string(l_x_pos + 80, l_y_pos + 17, "| -- Plan --" , "cyan") draw_string(l_x_pos + 108, l_y_pos + 30, " Better Pushback " , "cyan") draw_string(l_x_pos + 140, l_y_pos + 17, "|" , "cyan") draw_string(l_x_pos + 143, l_y_pos + 17, " -- Start --" , "cyan") draw_string(l_x_pos + 203, l_y_pos + 17, "| -- Stop --" , "cyan") draw_string(l_x_pos + 270, l_y_pos + 17, "|" , "cyan") end end if l_debug then draw_string(l_x_pos + 100, l_y_pos + 200, "l_counter "..l_counter, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 215, "l_brake_counter "..l_brake_counter, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 230, "l_check " .. tostring(l_check), "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 245, "ls_brake_status ".. ls_brake_status , "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 260, "ls_master_status " .. ls_master_status, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 275, "dr_flap_ratio " .. dr_flap_ratio , "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 290, "dr_parkbrake_ratio " .. dr_parkbrake_ratio , "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 310, "dr_rbrake_ratio " .. dr_rbrake_ratio , "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 325, "dr_lbrake_ratio " .. dr_lbrake_ratio, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 340, "dr_speedbrake_ratio " .. dr_speedbrake_ratio, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 355, "dr_throttle " .. dr_throttle, "yellow" ) draw_string(l_x_pos + 100, l_y_pos + 370, "l_better_pb " .. tostring(l_better_pb), "yellow" ) end end --============ Mouse function f_mouse_click_TS() --===================================== Close if l_show_main ~= 0 and MOUSE_X > l_x_pos + 380 and MOUSE_X < l_x_pos + 399 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then l_show_main = 0 return end --===================================== Open if l_show_main == 0 and MOUSE_X >= l_x_pos and MOUSE_X <= l_x_pos + 25 and MOUSE_Y >= l_y_pos and MOUSE_Y <= l_y_pos + 9 and MOUSE_STATUS == "down" then l_show_main = 1 return end --===================================== Master if l_show_main ~= 0 and MOUSE_X > l_x_pos and MOUSE_X < l_x_pos + 79 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then ls_master_status = 1 - ls_master_status ls_home_status = ls_master_status if ls_home_status ~= 1 then l_check = false l_brake_counter = 0 end f_change_armed_TS() return end --===================================== Brakes if l_show_main + dr_on_ground == 2 and MOUSE_X > l_x_pos + 80 and MOUSE_X < l_x_pos + 160 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then if dr_parkbrake_ratio == 1 or dr_parkbrake_ratio == 0 then ls_brake_status = 1 - ls_brake_status else ls_brake_status = 1 end if ls_brake_status == 1 then l_check = false l_brake_counter = 0 end f_set_controls(ls_brake_status,nil) return end --===================================== Arm/disarm all if in the air if l_show_main ~= 0 and MOUSE_X > l_x_pos + 275 and MOUSE_X < l_x_pos + 305 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then if dr_on_ground == 0 then --all are off or on so toggle if ls_taxi_AL + ls_flaps_AL + ls_spoilers_AL == 0 or ls_taxi_AL + ls_flaps_AL + ls_spoilers_AL == 3 then ls_taxi_AL = 1 - ls_taxi_AL ls_flaps_AL = 1 - ls_flaps_AL ls_spoilers_AL = 1 - ls_spoilers_AL ls_armed_status = 1 - ls_armed_status else --1 or more already set so enable all ls_spoilers_AL, ls_flaps_AL, ls_taxi_AL, ls_armed_status = 1, 1, 1, 1 end f_change_armed_TS() return else --on the ground use as arming arming screen toggle l_show_AL = 1 - l_show_AL --works like show arming screen return end end --===================================== Show Arming screen if l_show_main ~= 0 and MOUSE_X > l_x_pos + 306 and MOUSE_X < l_x_pos + 375 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then l_show_AL = 1 - l_show_AL return end --============ Arming form clicks --===================================== Taxi if l_show_main ~= 0 and MOUSE_X > l_x_pos + 270 and MOUSE_X < l_x_pos + 310 and MOUSE_Y > l_y_pos + 12 and MOUSE_Y < l_y_pos + 30 and MOUSE_STATUS == "down" then ls_taxi_AL = 1 - ls_taxi_AL f_change_armed_TS() return end --===================================== Flaps if l_show_main ~= 0 and MOUSE_X > l_x_pos + 313 and MOUSE_X < l_x_pos + 353 and MOUSE_Y > l_y_pos + 12 and MOUSE_Y < l_y_pos + 30 and MOUSE_STATUS == "down" then ls_flaps_AL = 1 - ls_flaps_AL f_change_armed_TS() return end --===================================== Spoilers if l_show_main ~= 0 and MOUSE_X > l_x_pos + 355 and MOUSE_X < l_x_pos + 395 and MOUSE_Y > l_y_pos + 12 and MOUSE_Y < l_y_pos + 30 and MOUSE_STATUS == "down" then ls_spoilers_AL = 1 - ls_spoilers_AL f_change_armed_TS() end --============ Open Better Pushback panel if installed if l_show_main + l_better_pb == 2 and MOUSE_X > l_x_pos + 162 and MOUSE_X < l_x_pos + 269 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 10 and MOUSE_STATUS == "down" then l_show_BP = 1 - l_show_BP --turn off master if BetterPushback is open if ls_master_status + l_show_BP == 2 then ls_master_status = 0 end end --============ better pushback form clicks --===================================== Plan if l_show_main + l_show_BP == 2 and MOUSE_X > l_x_pos + 80 and MOUSE_X < l_x_pos + 140 and MOUSE_Y > l_y_pos + 18 and MOUSE_Y < l_y_pos + 38 and MOUSE_STATUS == "down" then command_once("BetterPushback/start_planner") end --===================================== Start if l_show_main + l_show_BP == 2 and MOUSE_X > l_x_pos + 143 and MOUSE_X < l_x_pos + 203 and MOUSE_Y > l_y_pos + 18 and MOUSE_Y < l_y_pos + 38 and MOUSE_STATUS == "down" then command_once("BetterPushback/start") end --===================================== Stop if l_show_main + l_show_BP == 2 and MOUSE_X > l_x_pos + 206 and MOUSE_X < l_x_pos + 270 and MOUSE_Y > l_y_pos + 18 and MOUSE_Y < l_y_pos + 38 and MOUSE_STATUS == "down" then command_once("BetterPushback/stop") end end function f_change_armed_TS() if ls_brake_status == 1 or ls_master_status == 0 then l_check = false l_brake_counter = 0 end --get and save the current state of Master if it is not armed if ls_master_status < 2 then ls_pre_master = ls_master_status end --if anything is armed then change status if ls_flaps_AL + ls_spoilers_AL + ls_taxi_AL > 0 then ls_armed_status = 1 else ls_armed_status = 0 end --we are in the air and something is armed if l_we_took_off + ls_armed_status == 2 then ls_home_status = 2 else --we return to OFF or ON if we are no longer armed ls_master_status = ls_pre_master ls_home_status = ls_pre_master end end function f_mouse_wheel_TS() if l_show_main ~= 0 and MOUSE_X > l_x_pos + 162 and MOUSE_X < l_x_pos + 269 and MOUSE_Y > l_y_pos - 9 and MOUSE_Y < l_y_pos + 30 then --don't zoom RESUME_MOUSE_WHEEL = true l_desired_speed = l_desired_speed + MOUSE_WHEEL_CLICKS --stay within bounds if l_desired_speed < 0 then l_desired_speed = l_max_taxi elseif l_desired_speed > l_max_taxi then l_desired_speed = 0 end end end --============ Other function f_do_often_TS() --determines flow f_change_armed_TS() if l_default_check then f_first_run_TS() return end if (not l_check and ls_home_status == 1) and (dr_parkbrake_ratio < l_toebrake_ratio and l_brake_counter < 2) then l_brake_counter = l_brake_counter + 1 elseif l_brake_counter == 2 then l_check = true l_brake_counter = 0 end --convert meters/sec to knots l_ground_speed = math.floor(dr_ground_speed * 1.943) --we are flying now so move along nothing to see here if dr_on_ground == 0 and l_we_took_off == 1 then return end --we just took off so make sure we have been in the air at least 5 seconds if dr_on_ground == 0 and l_counter <= 5 then l_counter = l_counter + 1 return end --we should stay aloft now so clean up if dr_on_ground + l_we_took_off == 0 then l_we_took_off = 1 l_counter, ls_master_status = 0, 0 ls_brake_status = 0 f_set_controls(0,nil) end --cut the throttle if the user hit the parking brake while master is on if ls_master_status + ls_brake_status == 2 then f_set_controls(1,0.0) return end --check if we are on the ground and advanced the throttle too far turn off if dr_on_ground == 1 and dr_throttle >= l_mstr_off_at then ls_master_status, ls_home_status, ls_brake_status = 0, 0, 0 return end --we just landed make sure we are down for good if l_we_took_off + dr_on_ground == 2 and l_counter <= 3 then l_counter = l_counter + 1 return elseif l_we_took_off + dr_on_ground == 2 and l_counter > 3 then --definately not bouncing so set variables l_we_took_off = 0 l_we_landed = 1 l_counter = 0 end --we landed so do any armed functions if l_we_landed + ls_armed_status == 2 or l_we_landed + ls_armed_status + ls_master_status == 3 then f_after_landing_TS() end -- otherwise lets do things if the master is on if ls_master_status == 1 then f_decide_TS() end end function f_decide_TS() if not (l_check and f_check_TS()) then return end --do nothing if taxi speed is zero or exact if l_desired_speed == 0 or l_desired_speed == l_ground_speed then return end --we are too slow if l_ground_speed < l_desired_speed then f_increase_TS() else --we are too fast f_decrease_TS() end end function f_check_TS() --Check if user hit toe brake while master on if ((dr_lbrake_ratio + dr_rbrake_ratio) >= l_toebrake_ratio) then--or ((dr_parkbrake_ratio >= l_toebrake_ratio) and (dr_parkbrake_ratio <= 0.9)) then --cut throttle and turn off master ls_master_status = 0 f_set_controls(nil,0.0) f_change_armed_TS() return false else return true end end function f_increase_TS() --determines how much to adjust the throttle f_set_controls(0, nil) --a lot if l_ground_speed <= (l_desired_speed - 7) then l_thrtl = 0.375 --not so much elseif l_ground_speed <= (l_desired_speed - 5) then l_thrtl = 0.275 --some elseif l_ground_speed <= (l_desired_speed - 2) then l_thrtl = 0.2 --a bit else l_thrtl = 0.1 end f_set_controls(0, l_thrtl) end function f_decrease_TS() --determines how much to adjust the brake f_set_controls(0, 0.001) --a lot if l_ground_speed >= (l_desired_speed + 7) then l_brake = 0.4 --not so much elseif l_ground_speed >= (l_desired_speed + 5) then l_brake = 0.3 --some elseif l_ground_speed > (l_desired_speed + 2) then l_brake = 0.2 --a bit else l_brake = .1 end --Toliss brakes need more if l_toliss == 1 then l_brake = l_brake + 0.5 end f_set_controls(l_brake,0.001) end function f_first_run_TS() --First run through the script syncs thing f_set_controls(ls_brake_status,nil) f_check_better_pushback() l_default_check = nil end function f_after_landing_TS() if l_counter % 3 == 0.0 then --Retract flaps and spoilers when speed is under the set speed if l_ground_speed < l_flap_splr_speed then if ls_flaps_AL == 1 and dr_flap_ratio ~= 0.00 then command_once("sim/flight_controls/flaps_up") set("sim/cockpit2/controls/flap_ratio",0.00) end if ls_spoilers_AL == 1 then if dr_speedbrake_ratio ~= 0.00 or dr_speedbrake_ratio < 0 then command_once("sim/flight_controls/speed_brakes_up_all") set("sim/cockpit2/controls/speedbrake_ratio", 0.00) end end end end l_counter = l_counter + 1 --Engage the taxi hold if armed and within 10 knots if ls_taxi_AL == 1 and l_ground_speed < (l_desired_speed + 10) then ls_taxi_AL = 0 ls_master_status = 1 end if ls_flaps_AL == 1 and dr_flap_ratio == 0.00 and l_counter > 15 then ls_flaps_AL = 0 end if ls_spoilers_AL == 1 and dr_speedbrake_ratio == 0.00 and l_counter > 15 then ls_spoilers_AL = 0 end if ls_spoilers_AL + ls_flaps_AL + ls_taxi_AL == 0.00 then l_we_landed = 0 end end function f_check_better_pushback() file = io.open("Resources"..DIRECTORY_SEPARATOR.."plugins"..DIRECTORY_SEPARATOR.."BetterPushback"..DIRECTORY_SEPARATOR.. "64" ..DIRECTORY_SEPARATOR.. "win.xpl", "r") if file == nil then l_better_pb = 0 return else l_better_pb = 1 end file:close() end --============ FWLUA CALLS do_often("f_do_often_TS()") do_on_mouse_wheel("f_mouse_wheel_TS()") do_every_draw("f_draw_TS()") do_on_mouse_click("f_mouse_click_TS()") --[[ If you have an A319 that isn't from Toliss and uses standard datarefs then at top of script either place two hyphens/minus signs infront of the following lines to make the script look like this: (safest option if you later purchase the Toliss) --if PLANE_ICAO ~= "A319" then dataref("dr_throttle", "sim/cockpit2/engine/actuators/throttle_ratio_all", "readonly") dataref("dr_parkbrake_ratio", "sim/cockpit2/controls/parking_brake_ratio","readonly") l_toliss = nil --else --its an A319, hopefully toliss if its not a Toliss A319 the see end of script for directions -- dataref("dr_throttle", "AirbusFBW/throttle_input", "readonly", 0) -- dataref("dr_throttle_1", "AirbusFBW/throttle_input", "readonly", 1) -- dataref("dr_toliss_park_brake", "AirbusFBW/ParkBrake", "readonly") -- l_toliss = 1 --end OR: Delete those same lines so it looks like this dataref("dr_throttle", "sim/cockpit2/engine/actuators/throttle_ratio_all", "readonly") dataref("dr_parkbrake_ratio", "sim/cockpit2/controls/parking_brake_ratio","readonly") l_toliss = nil ]]