Drone V2.0

Drone V2.0
CreatorBaton008
CategoryFlying Machines
Size54 × 18 × 47 blocks
Blocks4,307
Minecraft1.21.X
Create6.0.10
ModsComputercraft, Createdeco, Createcasing, Interiors, Aeronautics, Create, Simulated, Copycats
Downloads375
Added2026-05-14

Schematic by Baton008, published on CreateMod.com. This page lists what it contains; download the file from the creator’s page.

Good Drone, need code for fly
H - Hover Mode
WASD - Move
Shift - down
Space - up
Q,E - Rotate
Code:



-- Инициализация датчиков, пульта и мониторов
local alt_front  = peripheral.wrap("altitude_sensor_0")
local alt_back   = peripheral.wrap("altitude_sensor_1")
local alt_left   = peripheral.wrap("altitude_sensor_2")
local alt_right  = peripheral.wrap("altitude_sensor_3")
local typewriter = peripheral.wrap("linked_typewriter_0")
local monitor    = peripheral.wrap("monitor_0")
local monitor_ah = peripheral.wrap("monitor_1")


if not (alt_front and alt_back and alt_left and alt_right and typewriter) then
    print("ERROR: Not all sensors or linked_typewriter_0 found!")
    return
end


if monitor then monitor.setTextScale(1.0) end


-- ================= НАСТРОЙКИ ПОЛЕТА =================
local CLUTCH_SIDE = "right"


local TILT_AMOUNT = 2.5
local YAW_SPEED   = 150
local LIFT_POWER  = 25  


-- Коэффициенты ПИД (Крен, Тангаж, Высота)
local Kp_roll = 1.2; local Ki_roll = 0.03; local Kd_roll = 8.0
local Kp_pitch = 1.5; local Ki_pitch = 0.05; local Kd_pitch = 15.0  
local Kp_alt = 2.0; local Ki_alt = 0.05; local Kd_alt = 10.0


local TRIM_PITCH = 10.0; local TRIM_ROLL  = 0.0  
local HOVER_SPEED = 45; local MIN_THROTTLE = 15; local MAX_SPEED = 256


-- Базовые переменные
local current_throttle = 0; local throttle_step = 0.5  
local prev_err_x, prev_err_z, prev_err_y = 0, 0, 0
local int_x, int_z, int_y = 0, 0, 0


-- Переменные Автопилота
local hover_mode = false
local autoland_mode = false
local target_altitude = 0
local prev_avg_alt = 0
local autoland_throttle = 0 -- НОВАЯ ПЕРЕМЕННАЯ ДЛЯ ПЛАВНОЙ ПОСАДКИ
local prev_keys = {}


-- ================= ФУНКЦИЯ ПАМЯТИ =================
local SAVE_FILE = "flight_data.txt"
local save_timer = os.clock()


local function saveState()
    local f = fs.open(SAVE_FILE, "w")
    if f then
        f.writeLine(tostring(current_throttle))
        f.writeLine(tostring(int_x))
        f.writeLine(tostring(int_z))
        f.close()
    end
end


local function loadState()
    if fs.exists(SAVE_FILE) then
        local f = fs.open(SAVE_FILE, "r")
        if f then
            local t = tonumber(f.readLine())
            local ix = tonumber(f.readLine())
            local iz = tonumber(f.readLine())
            if t and ix and iz then
                current_throttle = t; int_x = ix; int_z = iz
            end
            f.close()
        end
    end
end


local function resetState()
    current_throttle = 0; int_x = 0; int_z = 0; int_y = 0
    hover_mode = false; autoland_mode = false; autoland_throttle = 0
    saveState()
end


loadState()


-- ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ =================
local function clamp(v, min, max)
    return v < min and min or (v > max and max or v)
end


local function isPressed(keys_table, code)
    if not keys_table then return false end
    for _, k in ipairs(keys_table) do
        if k == code then return true end
    end
    return false
end


local function justPressed(keys_now, keys_prev, code)
    return isPressed(keys_now, code) and not isPressed(keys_prev, code)
end


local function osd_print(text)
    if monitor then
        local x, y = monitor.getCursorPos()
        monitor.write(text)
        monitor.setCursorPos(1, y + 1)
    else print(text) end
end


local function draw_artificial_horizon(mon, pitch_err, roll_err, alt)
    if not mon then return end
    mon.setTextScale(0.5)
    local w, h = mon.getSize()
    local cx = math.floor(w / 2); local cy = math.floor(h / 2)
    local pitch_offset = math.floor(-pitch_err * 2.0)
    local roll_slope = roll_err * 0.4


    for y = 1, h do
        local text_row, fg_row, bg_row = "", "", ""
        for x = 1, w do
            local horizon_y = cy + pitch_offset + (x - cx) * roll_slope
            if y < horizon_y - 0.5 then bg_row = bg_row .. "3"
            elseif math.abs(y - horizon_y) <= 0.5 then bg_row = bg_row .. "0"
            else bg_row = bg_row .. "c" end
            text_row = text_row .. " "; fg_row = fg_row .. "f"
        end
        mon.setCursorPos(1, y); mon.blit(text_row, fg_row, bg_row)
    end
    mon.setCursorPos(cx - 3, cy); mon.blit(" >-|-< ", "4444444", "7777777")
    mon.setCursorPos(2, 2); mon.setBackgroundColor(colors.black); mon.setTextColor(colors.white)
    mon.write(string.format(" ALT: %.1f ", alt))
    mon.setCursorPos(2, h - 1)
    mon.write(string.format(" P: %0.1f | R: %0.1f ", -pitch_err, -roll_err))
end


-- ================= ГЛАВНЫЙ ЦИКЛ =================
while true do
    -- 1. Читаем высотомеры
    local ok_f, h_front = pcall(alt_front.getHeight)
    local ok_b, h_back  = pcall(alt_back.getHeight)
    local ok_l, h_left  = pcall(alt_left.getHeight)
    local ok_r, h_right = pcall(alt_right.getHeight)
   
    local err_x, err_z, avg_alt = 0, 0, 0
    if ok_f and ok_b and ok_l and ok_r then
        avg_alt = (h_front + h_back + h_left + h_right) / 4.0
    end


    local vertical_speed = (avg_alt - prev_avg_alt) / 0.05
    prev_avg_alt = avg_alt


    -- 2. Считываем пульт
    local keys = typewriter.getPressedKeyCodes() or {}
    local target_x, target_z, manual_throttle, yaw_cmd = 0, 0, 0, 0
    local is_turning = false
    local input_str = ""


    -- Переключатели режимов
    if justPressed(keys, prev_keys, 72) then
        hover_mode = not hover_mode
        if hover_mode then
            autoland_mode = false; target_altitude = avg_alt; int_y = 0
        end
    end


    if justPressed(keys, prev_keys, 76) then
        autoland_mode = not autoland_mode
        if autoland_mode then
            hover_mode = false
            autoland_throttle = 0 -- Сбрасываем счетчик давления газа при включении посадки
        end
    end


    -- ================= ЛОГИКА АВТОПОСАДКИ =================
    if autoland_mode then
        input_str = "[ AUTO-LAND ACTIVE ] "
        -- Каждые 0.05 сек дрон давит газ всё ниже и ниже (по -0.2 RPM за тик)
        autoland_throttle = autoland_throttle - 0.2
        manual_throttle = autoland_throttle


        -- КАК ПОНЯТЬ, ЧТО МЫ СЕЛИ:
        -- 1. Высота почти ноль (если датчики на пузе)
        -- 2. ИЛИ мы скинули газ уже очень сильно (-20 RPM), а дрон не двигается вниз (уперлись в землю)
        if avg_alt < 0.5 or (autoland_throttle < -20 and math.abs(vertical_speed) < 0.2) then
            resetState()
            peripheral.call("Create_RotationSpeedController_6", "setTargetSpeed", 0)
        end
    else
        -- Обычное управление
        if isPressed(keys, 87) then target_z = -TILT_AMOUNT; input_str = input_str .. "[W] " end              
        if isPressed(keys, 83) then target_z = TILT_AMOUNT; input_str = input_str .. "[S] " end              
        if isPressed(keys, 65) then target_x = -TILT_AMOUNT; input_str = input_str .. "[A] " end              
        if isPressed(keys, 68) then target_x = TILT_AMOUNT; input_str = input_str .. "[D] " end              
        if isPressed(keys, 81) then yaw_cmd = YAW_SPEED; is_turning = true; input_str = input_str .. "[Q] " end                
        if isPressed(keys, 69) then yaw_cmd = -YAW_SPEED; is_turning = true; input_str = input_str .. "[E] " end                  


        if hover_mode then
            input_str = "[HOVER] " .. input_str
            if isPressed(keys, 32) then target_altitude = target_altitude + 0.3; input_str = input_str .. "[UP] " end
            if isPressed(keys, 340) then target_altitude = target_altitude - 0.3; input_str = input_str .. "[DN] " end
        else
            if isPressed(keys, 32) then manual_throttle = LIFT_POWER; input_str = input_str .. "[SPC] " end      
            if isPressed(keys, 340) then manual_throttle = -LIFT_POWER; input_str = input_str .. "[SHF] " end    
        end
    end


    if input_str == "" then input_str = "IDLE" end
    prev_keys = keys


    -- УПРАВЛЕНИЕ СЦЕПЛЕНИЕМ
    if is_turning and not autoland_mode then
        redstone.setOutput(CLUTCH_SIDE, false)
        peripheral.call("Create_RotationSpeedController_6", "setTargetSpeed", yaw_cmd)
    else
        redstone.setOutput(CLUTCH_SIDE, true)  
    end


    -- 3. ПИД ВЫСОТЫ (Hover Mode)
    local pid_throttle = 0
    if hover_mode and not autoland_mode then
        local err_y = target_altitude - avg_alt
        int_y = clamp(int_y + err_y, -500, 500)
        pid_throttle = (Kp_alt * err_y) + (Ki_alt * int_y) + (Kd_alt * (err_y - prev_err_y))
        prev_err_y = err_y
    else
        int_y = 0; prev_err_y = 0
    end


    -- 4. Расчет газа
    local alt_cmd = -peripheral.call("Create_RotationSpeedController_5", "getTargetSpeed")
    local target_throttle = HOVER_SPEED + alt_cmd
   
    if hover_mode then target_throttle = target_throttle + pid_throttle
    else target_throttle = target_throttle + manual_throttle end
   
    target_throttle = clamp(target_throttle, MIN_THROTTLE, MAX_SPEED)


    if current_throttle < target_throttle then
        current_throttle = math.min(current_throttle + throttle_step, target_throttle)
    elseif current_throttle > target_throttle then
        current_throttle = math.max(current_throttle - (throttle_step * 2), target_throttle)
    end
    local throttle = current_throttle


    -- 5. ПИД Наклона
    err_z = target_z - (h_front - h_back)
    err_x = target_x - (h_left - h_right)


    if math.abs(err_x) < 0.1 and target_x == 0 then err_x = 0 end
    if math.abs(err_z) < 0.1 and target_z == 0 then err_z = 0 end


    if throttle <= MIN_THROTTLE + 5 then
        int_x = 0; int_z = 0
    else
        int_x = clamp(int_x + err_x, -500, 500)
        int_z = clamp(int_z + err_z, -500, 500)
    end


    local output_x = (Kp_roll * err_x) + (Ki_roll * int_x) + (Kd_roll * (err_x - prev_err_x)) - TRIM_ROLL
    local output_z = (Kp_pitch * err_z) + (Ki_pitch * int_z) + (Kd_pitch * (err_z - prev_err_z)) - TRIM_PITCH


    prev_err_x = err_x; prev_err_z = err_z


    -- Микшер
    local motor_1 = throttle + output_z + output_x
    local motor_2 = throttle + output_z - output_x
    local motor_4 = throttle - output_z + output_x
    local motor_3 = throttle - output_z - output_x


    motor_1 = clamp(motor_1, MIN_THROTTLE, MAX_SPEED); motor_2 = clamp(motor_2, MIN_THROTTLE, MAX_SPEED)
    motor_4 = clamp(motor_4, MIN_THROTTLE, MAX_SPEED); motor_3 = clamp(motor_3, MIN_THROTTLE, MAX_SPEED)


    peripheral.call("Create_RotationSpeedController_1", "setTargetSpeed", -motor_1)
    peripheral.call("Create_RotationSpeedController_2", "setTargetSpeed", -motor_2)
    peripheral.call("Create_RotationSpeedController_4", "setTargetSpeed", -motor_4)
    peripheral.call("Create_RotationSpeedController_3", "setTargetSpeed", -motor_3)


    -- === СИГНАЛИЗАЦИЯ GPWS ===
    local alarm_msg = nil
    if vertical_speed < -5.0 and avg_alt > 3.0 then
        alarm_msg = "!! PULL UP !!"
    elseif math.abs(err_x) > 6.0 or math.abs(err_z) > 6.0 then
        alarm_msg = "!! BANK ANGLE !!"
    end


    -- === ОБНОВЛЕНИЕ ГЛАВНОГО ЭКРАНА ===
    if monitor then
        monitor.clear(); monitor.setCursorPos(1,1)
        monitor.write("=== AERONAUTICS FLIGHT OS ===")
        monitor.setCursorPos(1,2)
        if hover_mode then monitor.write(string.format("PWR: %.1f | ALT: %.1f (Trgt: %.1f)", throttle, avg_alt, target_altitude))
        else monitor.write(string.format("PWR: %.1f | ALT: %.1f", throttle, avg_alt)) end
        monitor.setCursorPos(1,3); monitor.write("INPUT: " .. input_str)
        monitor.setCursorPos(1,4); monitor.write(string.format("PITCH: Trgt %4.1f | Err %5.2f", target_z, err_z))
        monitor.setCursorPos(1,5); monitor.write(string.format("ROLL : Trgt %4.1f | Err %5.2f", target_x, err_x))
       
        if alarm_msg then
            monitor.setCursorPos(1, 7)
            if math.floor(os.clock() * 6) % 2 == 0 then
                monitor.setBackgroundColor(colors.red); monitor.setTextColor(colors.white)
            else
                monitor.setBackgroundColor(colors.black); monitor.setTextColor(colors.red)
            end
            monitor.write(" " .. alarm_msg .. " ")
            monitor.setBackgroundColor(colors.black); monitor.setTextColor(colors.white)
        end


        monitor.setCursorPos(15, 10)
        monitor.setBackgroundColor(colors.red); monitor.setTextColor(colors.white)
        monitor.write("[ RESET ]")
        monitor.setBackgroundColor(colors.black)
    end


    if monitor_ah then draw_artificial_horizon(monitor_ah, err_z, err_x, avg_alt) end


    -- Сохранение состояния
    if os.clock() - save_timer > 1.0 then
        saveState(); save_timer = os.clock()
    end


    -- Ожидание и проверка тачскрина
    local timer = os.startTimer(0.05)
    while true do
        local event, p1, p2, p3 = os.pullEvent()
        if event == "monitor_touch" and p1 == "monitor_0" then
            if p2 >= 15 and p3 >= 10 then
                resetState()
                peripheral.call("Create_RotationSpeedController_6", "setTargetSpeed", 0)
            end
        elseif event == "timer" and p1 == timer then
            break
        end
    end
end
Materials · 45 types · 4,307 blocks
Industrial iron block2,748
Framed glass358
White symmetric sail355
Copycat vertical slope159
Copycat layer158
Cable98
Copycat board83
Fluid tank54
Shaft42
Copycat stairs37
Belt35
Industrial iron mesh fence34
Industrial iron encased shaft26
Redstone link17
Gearbox17
Blaze burner16
Monitor advanced16
Powered shaft14
Steam engine14
Yellow industrial iron lamp13
Wired modem full13
Industrial iron encased chain drive12
Fluid pipe8
Clutch6
Cogwheel6
Industrial iron gearbox6
Mechanical pump6
Rotation speed controller6
Lever6
Black floor chair5
Propeller bearing5
Industrial iron encased large cogwheel4
Analog transmission4
Altitude sensor4
Water3
Oak wall sign3
White nameplate3
Sequenced gearshift2
Mechanical bearing2
Oak button1
Linked typewriter1
Computer advanced1
Gearshift1
Rope winch1
Large cogwheel1

More in Flying Machines

See all