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..
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 > 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 xtilt = inputs ytilt = inputs -- 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 * tiltcontrol yrot = yrot - inputs * 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 * 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 = left + zrot outputs = -right + zrot outputs = front + zrot outputs = -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