First quadcopter flight!

Wanting to try some more advanced form of motor control, I started toying around a bit with airborne balancing platforms, that get their lift and control their movements solely using turbines or propellers. The result from the turbine experiments was in the previous blog post (the Hovercraft Lab). You can see the results from the new propeller version in the following video. The code controlling both this and the hovercraft is very similar for both and you can see it further below in this post.

There are some obvious TODO’s, like in the quadcopter adding a control panel to adjust height and the heading of the copter. Right now I have to turn around and fly it backwards, to fly in the opposite direction… kind of annoying 🙂

It would be possible to add some manipulators hanging below the platform, to clamp and pick up stuff from the ground. Maybe abducting animals could be the next big project here..

Controller code

For reference, here below is the complete quadcopter control code put in the computer (or brain if you will).

All in-game computer code is in Lua, a very simple script-like language.

If you want to insert it into the game without having to enter it, copy and paste it into a text file named for example “user.vbrain.quadcopter.lua” and drop in the world directory in your installation (where the other saves go). When you edit a computer in the game for the first time, it will ask if you want to create it as new, as a shared code or a copy. Select shared or copy and select the quadcopter code in the list that pops up.


-- Mekside Quadcopter demo code v1.0
-- By Realitylabs Game Studios
-- Use/adapt however you want.

-- First some constants:
---------------------------------

-- Starting target height
desired_height = 0.0

-- Target height that can be toggled to with the on/off switch
on_height = 0.45

-- Proportional coefficient of the height PD-regulator
-- (how much we try to reduce errors in height)
hP = 20.0

-- Derivative coefficient of the height PD-regulator
-- (how much we dampen quick height-changes)
hD = 4.0

-- Same PD coefficients for the tilt regulator
rotP = 4.0
rotD = 2.0

tiltcap = 0.05

-- Amount of tilt the control panel input can add
tiltcontrol = 0.2

-- I/O doc
------------------------------------------

-- Outputs (thrusters):
-- 1: left
-- 2: right
-- 3: front
-- 4: back

-- Inputs:
-- 1: Barometer (height)
-- 2: X tilt (positive if the ship tilts "to the left")
-- 3: Y tilt (positive if the ship tilts "backwards")
-- 4: Toggle button panel, on / off
-- 5: Primary control panel x
-- 6: Primary control panel y
-- 7: Secondary control panel rotation input (x)

-- main thrust to use for lift
collective = 0

-- extra thrust to compensate for tilt in the X and Y directions
xrot = 0
yrot = 0

-- Start with -200 so we know it's invalid below on the first iteration
last_height = -200
last_xtilt = -200
last_ytilt = -200

-- This function is called each physics tick, that is 100 times per second
-----------------------------------------------------------

function tick()

    -- Check on/off control panel, just toggle the target height
    -- (TODO: make another control input to adjust height)
    if inputs[4] > 0.5 then
        if desired_height > 0 then
            desired_height = 0
        else
            desired_height = on_height
        end
    end

    -- Copy some inputs into better named variables internally
    height = inputs[1]
    xtilt = inputs[2]
    ytilt = inputs[3]

    -- The first iteration we have to set some last-variables
    if last_height < -100 then
       last_height = height
    end

    if last_xtilt < -100 then
        last_xtilt = xtilt
    end

    if last_ytilt < -100 then
        last_ytilt = ytilt
    end

    -- Get the height-change per second (input is 0 to 1 for the world height)
    zspeed = 100 * (height - last_height)

    -- Tilt speeds
    xtiltspeed = 100 * (xtilt - last_xtilt)
    ytiltspeed = 100 * (ytilt - last_ytilt)

    -- Deltas (velocities) in height and tilt
    dh = desired_height - height
    dxtilt = 0 - xtilt
    dytilt = 0 - ytilt

    -- Cap to sane values so we don't run away if the error is too large
    if dh > 0.05 then
        dh = 0.05
    elseif dh < -0.05 then
        dh = -0.05
    end

    if dxtilt > tiltcap then
        dxtilt = tiltcap
    elseif dxtilt < -tiltcap then
        dxtilt = -tiltcap
    end

    if dytilt > tiltcap then
        dytilt = tiltcap
    elseif dytilt < -tiltcap then
        dytilt = -tiltcap
    end

    -- PD regulator for height
    collective = hP * dh - hD * zspeed

    -- PD regulator for x tilt
    xrot = rotP * dxtilt - rotD * xtiltspeed

    if xrot < -0.2 then
       xrot = -0.2
    elseif xrot > 0.2 then
      xrot = 0.2
    end

    -- PD regulator for y tilt
    yrot = rotP * dytilt - rotD * ytiltspeed

    if yrot < -0.2 then
       yrot = -0.2
    elseif yrot > 0.2 then
      yrot = 0.2
    end

    -- Add in the control panel contribution, so we can tilt the vehicle a bit in each direction to
    -- make it travel there
    xrot = xrot - inputs[5] * tiltcontrol
    yrot = yrot - inputs[6] * tiltcontrol

    -- The secondary control panel x input controls the z-axis rotation
    -- by adjusting the total rotational momentum imposed by the
    -- counter-rotating rotors
    -- TODO: this does not work. Think out why.. 
    zrot = inputs[7] * 0.05

    -- Calculate the actual motor speeds for the 4 engines

    -- Positive xrot means we try to compensate for turing to the right,
    -- so then we should increase the thrust on the right side, and vice versa.

    left = math.min(1.0, math.max(0.0, collective - xrot))
    right = math.min(1.0, math.max(0.0, collective + xrot))
    front = math.min(1.0, math.max(0.0, collective + yrot))
    back = math.min(1.0, math.max(0.0, collective - yrot))

    -- Write to the outputs

    outputs[1] = left + zrot
    outputs[2] = -right + zrot
    outputs[3] = front + zrot
    outputs[4] = -back + zrot

    -- Prepare for the next tick so we can calculate deltas
    last_height = height
    last_xtilt = xtilt
    last_ytilt = ytilt

    -- End of physics tick
end
Share Button