adding the autopilot

master
Alexsandro Percy 2021-06-11 15:51:22 -03:00
parent d05e656b5e
commit a262544f03
6 changed files with 209 additions and 80 deletions

View File

@ -1,7 +1,8 @@
--global constants
hidroplane.last_time_command = 0
hidroplane.vector_up = vector.new(0, 1, 0)
hidroplane.ideal_step = 0.02
hidroplane.rudder_limit = 30
hidroplane.elevator_limit = 40
dofile(minetest.get_modpath("hidroplane") .. DIR_DELIM .. "hidroplane_utilities.lua")
@ -16,15 +17,41 @@ function hidroplane.check_node_below(obj)
return touching_ground, liquid_below
end
function hidroplane.powerAdjust(self,dtime,factor,dir,max_power)
local max = max_power or 100
local add_factor = factor
add_factor = add_factor * (dtime/hidroplane.ideal_step) --adjusting the command speed by dtime
local power_index = self._power_lever
if dir == 1 then
if self._power_lever < max then
self._power_lever = self._power_lever + add_factor
end
if self._power_lever > max then
self._power_lever = max
end
end
if dir == -1 then
if self._power_lever > 0 then
self._power_lever = self._power_lever - add_factor
if self._power_lever < 0 then self._power_lever = 0 end
end
if self._power_lever <= 0 then
self._power_lever = 0
end
end
if power_index ~= self._power_lever then
hidroplane.engineSoundPlay(self)
end
end
function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_drag,
later_speed, later_drag, accel, player, is_flying)
hidroplane.last_time_command = hidroplane.last_time_command + dtime
if hidroplane.last_time_command > 1 then hidroplane.last_time_command = 1 end
--if self.driver_name == nil then return end
local retval_accel = accel
local rudder_limit = 30
local elevator_limit = 40
local stop = false
-- player control
@ -36,6 +63,7 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
hidroplane.last_time_command = 0
if self._engine_running then
self._engine_running = false
self._autopilot = false
-- sound and animation
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
@ -46,10 +74,7 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
elseif self._engine_running == false and self._energy > 0 then
self._engine_running = true
-- sound and animation
self.sound_handle = minetest.sound_play({name = "hidroplane_engine"},
{object = self.object, gain = 2.0,
pitch = 0.5 + ((self._power_lever/100)/2),max_hear_distance = 32,
loop = true,})
hidroplane.engineSoundPlay(self)
self.engine:set_animation_frame_speed(60)
end
end
@ -60,32 +85,15 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
local engineacc = (self._power_lever * hidroplane.max_engine_acc) / 100;
self.engine:set_animation_frame_speed(60 + self._power_lever)
local add_factor = 1
add_factor = add_factor * (dtime/hidroplane.ideal_step) --adjusting the command speed by dtime
local factor = 1
--increase power lever
if ctrl.jump then
if self._power_lever < 100 then
self._power_lever = self._power_lever + add_factor
end
if self._power_lever > 100 then
self._power_lever = 100
engineacc = hidroplane.max_engine_acc
else
--sound
minetest.sound_stop(self.sound_handle)
self.sound_handle = minetest.sound_play({name = "hidroplane_engine"},
{object = self.object, gain = 2.0,
pitch = 0.5 + ((self._power_lever/100)/2),max_hear_distance = 32,
loop = true,})
end
hidroplane.powerAdjust(self, dtime, factor, 1)
end
--decrease power lever
if ctrl.sneak then
if self._power_lever > 0 then
self._power_lever = self._power_lever - add_factor
if self._power_lever < 0 then self._power_lever = 0 end
end
hidroplane.powerAdjust(self, dtime, factor, -1)
if self._power_lever <= 0 and is_flying == false then
--break
if longit_speed >= 0.1 then
@ -97,13 +105,6 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
if abs(longit_speed) < 0.1 then
stop = true
end
else
--sound
minetest.sound_stop(self.sound_handle)
self.sound_handle = minetest.sound_play({name = "hidroplane_engine"},
{object = self.object, gain = 2.0,
pitch = 0.5 + ((self._power_lever/100)/2),max_hear_distance = 32,
loop = true,})
end
end
--do not exceed
@ -128,21 +129,14 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
retval_accel=vector.add(retval_accel,hull_acc)
--pitch
local pitch_factor = 10
if ctrl.down then
self._elevator_angle = math.max(self._elevator_angle-pitch_factor*dtime,-elevator_limit)
elseif ctrl.up then
if self._angle_of_attack < 0 then pitch_factor = 1 end --lets reduce the command power to avoid accidents
self._elevator_angle = math.min(self._elevator_angle+pitch_factor*dtime,elevator_limit)
end
local pitch_cmd = 0
if ctrl.up then pitch_cmd = 1 elseif ctrl.down then pitch_cmd = -1 end
hidroplane.set_pitch(self, pitch_cmd, dtime)
-- yaw
local yaw_factor = 30
if ctrl.right then
self._rudder_angle = math.max(self._rudder_angle-yaw_factor*dtime,-rudder_limit)
elseif ctrl.left then
self._rudder_angle = math.min(self._rudder_angle+yaw_factor*dtime,rudder_limit)
end
local yaw_cmd = 0
if ctrl.right then yaw_cmd = 1 elseif ctrl.left then yaw_cmd = -1 end
hidroplane.set_yaw(self, yaw_cmd, dtime)
--I'm desperate, center all!
if ctrl.right and ctrl.left then
@ -152,19 +146,109 @@ function hidroplane.control(self, dtime, hull_direction, longit_speed, longit_dr
end
if longit_speed > 0 then
local factor = 1
if self._rudder_angle > 0 then factor = -1 end
local correction = (rudder_limit*(longit_speed/1000)) * factor
self._rudder_angle = self._rudder_angle + correction
factor = 1
--if self._elevator_angle > -1.5 then factor = -1 end --here is the "compensator" adjusto to keep it stable
if self._elevator_angle > 0 then factor = -1 end
correction = (elevator_limit/10) * factor * dtime
self._elevator_angle = self._elevator_angle + correction
hidroplane.rudder_elevator_auto_correction(self, longit_speed, dtime)
end
return retval_accel, stop
end
function hidroplane.set_pitch(self, dir, dtime)
local pitch_factor = 10
if dir == -1 then
self._elevator_angle = math.max(self._elevator_angle-pitch_factor*dtime,-hidroplane.elevator_limit)
elseif dir == 1 then
if self._angle_of_attack < 0 then pitch_factor = 1 end --lets reduce the command power to avoid accidents
self._elevator_angle = math.min(self._elevator_angle+pitch_factor*dtime,hidroplane.elevator_limit)
end
end
function hidroplane.set_yaw(self, dir, dtime)
local yaw_factor = 30
if dir == 1 then
self._rudder_angle = math.max(self._rudder_angle-yaw_factor*dtime,-hidroplane.rudder_limit)
elseif dir == -1 then
self._rudder_angle = math.min(self._rudder_angle+yaw_factor*dtime,hidroplane.rudder_limit)
end
end
function hidroplane.rudder_elevator_auto_correction(self, longit_speed, dtime)
local factor = 1
if self._rudder_angle > 0 then factor = -1 end
local correction = (hidroplane.rudder_limit*(longit_speed/1000)) * factor
self._rudder_angle = self._rudder_angle + correction
factor = 1
--if self._elevator_angle > -1.5 then factor = -1 end --here is the "compensator" adjusto to keep it stable
if self._elevator_angle > 0 then factor = -1 end
correction = (hidroplane.elevator_limit/10) * factor * dtime
self._elevator_angle = self._elevator_angle + correction
end
function hidroplane.engineSoundPlay(self)
--sound
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
self.sound_handle = minetest.sound_play({name = "hidroplane_engine"},
{object = self.object, gain = 2.0,
pitch = 0.5 + ((self._power_lever/100)/2),max_hear_distance = 32,
loop = true,})
end
function getAdjustFactor(curr_y, desired_y)
local max_difference = 0.1
local adjust_factor = 0.5
local difference = math.abs(curr_y - desired_y)
if difference > max_difference then difference = max_difference end
return (difference * adjust_factor) / max_difference
end
function hidroplane.autopilot(self, dtime, hull_direction,
longit_speed, longit_drag, later_speed, later_drag, accel, pilot, is_flying, curr_pos)
local retval_accel = accel
local max_autopilot_power = 85
local max_attack_angle = 1.8
self._acceleration = 0
if self._engine_running then
--engine acceleration calc
local engineacc = (self._power_lever * hidroplane.max_engine_acc) / 100;
self.engine:set_animation_frame_speed(60 + self._power_lever)
local factor = getAdjustFactor(curr_pos.y, self._auto_pilot_altitude)
--increase power lever
if self._auto_pilot_altitude < curr_pos.y then
hidroplane.powerAdjust(self, dtime, factor, -1)
end
--decrease power lever
if self._auto_pilot_altitude > curr_pos.y then
hidroplane.powerAdjust(self, dtime, factor, 1, max_autopilot_power)
end
--do not exceed
local max_speed = 6
if longit_speed > max_speed then
engineacc = engineacc - (longit_speed-max_speed)
if engineacc < 0 then engineacc = 0 end
end
self._acceleration = engineacc
end
local hull_acc = vector.multiply(hull_direction,self._acceleration)
retval_accel=vector.add(retval_accel,hull_acc)
--pitch
if self._angle_of_attack > max_attack_angle then
hidroplane.set_pitch(self, 1, dtime)
elseif self._angle_of_attack < max_attack_angle then
hidroplane.set_pitch(self, -1, dtime)
end
-- yaw
hidroplane.set_yaw(self, 0, dtime)
if longit_speed > 0 then
hidroplane.rudder_elevator_auto_correction(self, longit_speed, dtime)
end
return retval_accel
end

View File

@ -278,6 +278,8 @@ minetest.register_entity("hidroplane:hidro", {
_show_hud = false,
_instruction_mode = false, --flag to intruction mode
_command_is_given = false, --flag to mark the "owner" of the commands now
_autopilot = false,
_auto_pilot_altitude = 0,
get_staticdata = function(self) -- unloaded/unloads ... is now saved
return minetest.serialize({
@ -509,6 +511,7 @@ minetest.register_entity("hidroplane:hidro", {
else
--give the control to the pax
if self._passenger then
self._autopilot = false
hidroplane.transfer_control(self, true)
end
end

View File

@ -48,6 +48,7 @@ function hidroplane.consumptionCalc(self, accel)
end
if self._energy <= 0 and self._engine_running and accel ~= nil then
self._engine_running = false
self._autopilot = false
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
self.engine:set_animation_frame_speed(0)
end

View File

@ -12,3 +12,4 @@ HIDROPLANE_GAUGE_POWER_POSITION = {x=2.35,y=1.55,z=10.64}
HIDROPLANE_GAUGE_CLIMBER_POSITION = {x=-2.05,y=1.40,z=10.64}
HIDROPLANE_GAUGE_SPEED_POSITION = {x=-0.25,y=1.40,z=10.64}
hidroplane.last_time_command = 0

View File

@ -37,8 +37,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
"* Forward: go down flying - nose down \n",
"* Left/right: Turn to left/right, work on and out ground. \n",
"* Left and Right together: center all commands \n",
"* Sneak and Jump together: give/take the controls to/from \n",
" pilot student \n",
"* Sneak and Jump together (normal): activates de autopilot \n",
"* Sneak and Jump together (instruction mode): give/take the \n",
" controls to/from pilot student \n",
"* Up and Down together: enable/disable HUD"
}
local shortcut_form = table.concat({
@ -106,15 +107,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
"automatically extend. \n",
"When boarding the aircraft, centralize the commands (A \n",
"and D keys), press E to start the engine and hold Jump \n",
"until the power reaches maximum. When the speed \n",
"reaches the green range, lightly pull the stick using the S \n",
"key. Always keep the speed within the green range to \n",
"avoid stalling. To land, remove all power, but keep the \n",
"speed at the limit between the green and white range, \n",
"still in the green. When you are about to touch the soil or \n",
"water, lightly pull the stick to level and touch it gently. \n",
"It's possible to operate with an external camera, \n",
"activating the HUD. \n",
"until full power. When the speed reaches the green range, \n",
"lightly pull the stick using the S key. Always keep the \n",
"speed within the green range to avoid stalling. To land, \n",
"remove all power, but keep the speed at the limit \n",
"between the green and white range. \n",
"When you are about to touch the soil or water, lightly pull \n",
"the stick to level and touch it gently. It's possible to \n",
"operate with an external camera, activating the HUD. \n",
"The autopilot (jump and sneak) only keeps the airplane at the \n",
"activation level, limited by power and designed ceiling. \n",
"It's possible for a passenger to board the aircraft, just \n",
"click the right button on the floater. But the passenger \n",
"will only be able to enter if the pilot has already boarded."
@ -124,7 +126,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
"size[16,10]",
"background[-0.7,-0.5;17.5,11.5;hidroplane_manual_bg.png]",
"image[0.5,1.75;6,6;hidroplane_manual_side_view.png]",
"label[9.25,0.5;", table.concat(text, ""), "]",
"label[9.25,0.25;", table.concat(text, ""), "]",
}, "")
minetest.show_formspec(player:get_player_name(), "hidroplane:op", op_form)
end

View File

@ -356,6 +356,7 @@ function hidroplane.checkattachBug(self)
end
else
if self._passenger ~= nil and self._command_is_given == false then
self._autopilot = false
hidroplane.transfer_control(self, true)
end
end
@ -412,6 +413,14 @@ function hidroplane.transfer_control(self, status)
end
function hidroplane.flightstep(self)
local velocity = self.object:get_velocity()
--hack to avoid glitches
self.object:set_velocity(velocity)
local curr_pos = self.object:get_pos()
self.object:set_pos(curr_pos)
hidroplane.last_time_command = hidroplane.last_time_command + self.dtime
local player = nil
if self.driver_name then player = minetest.get_player_by_name(self.driver_name) end
local passenger = nil
@ -419,7 +428,9 @@ function hidroplane.flightstep(self)
if player then
local ctrl = player:get_player_control()
---------------------
-- change the driver
---------------------
if passenger and hidroplane.last_time_command >= 1 and self._instruction_mode == true then
if self._command_is_given == true then
if ctrl.sneak or ctrl.jump or ctrl.up or ctrl.down or ctrl.right or ctrl.left then
@ -435,7 +446,28 @@ function hidroplane.flightstep(self)
end
end
end
-----------
--autopilot
-----------
if self._instruction_mode == false and hidroplane.last_time_command >= 1 then
if self._autopilot == true then
if ctrl.sneak or ctrl.jump or ctrl.up or ctrl.down or ctrl.right or ctrl.left then
hidroplane.last_time_command = 0
self._autopilot = false
minetest.chat_send_player(self.driver_name," >>> Autopilot deactivated")
end
else
if ctrl.sneak == true and ctrl.jump == true then
hidroplane.last_time_command = 0
self._autopilot = true
self._auto_pilot_altitude = curr_pos.y
minetest.chat_send_player(self.driver_name,core.colorize('#00ff00', " >>> Autopilot on"))
end
end
end
----------------------------------
-- shows the hud for the player
----------------------------------
if ctrl.up == true and ctrl.down == true and hidroplane.last_time_command >= 1 then
hidroplane.last_time_command = 0
if self._show_hud == true then
@ -456,7 +488,6 @@ function hidroplane.flightstep(self)
if newroll > 360 then newroll = newroll - 360 end
if newroll < -360 then newroll = newroll + 360 end
local velocity = self.object:get_velocity()
local hull_direction = mobkit.rot_to_dir(rotation) --minetest.yaw_to_dir(yaw)
local nhdir = {x=hull_direction.z,y=0,z=-hull_direction.x} -- lateral unit vector
@ -471,11 +502,6 @@ function hidroplane.flightstep(self)
local accel = vector.add(longit_drag,later_drag)
local stop = false
--hack to avoid glitches
self.object:set_velocity(velocity)
local curr_pos = self.object:get_pos()
self.object:set_pos(curr_pos)
local node_bellow = mobkit.nodeatpos(mobkit.pos_shift(curr_pos,{y=-3}))
local is_flying = true
if node_bellow and node_bellow.drawtype ~= 'airlike' then is_flying = false end
@ -496,6 +522,8 @@ function hidroplane.flightstep(self)
self._elevator_angle = self._elevator_angle + 0.1
end --limiting the very high climb angle due to strange behavior]]--
--minetest.chat_send_all(self._angle_of_attack)
-- pitch
local speed_factor = 0
if longit_speed > hidroplane.min_speed then speed_factor = (velocity.y * math.rad(2)) end
@ -558,8 +586,6 @@ function hidroplane.flightstep(self)
---------------------------------
-- end roll
--accell calculation
--control
if not is_attached then
-- for some engine error the player can be detached from the machine, so lets set him attached again
hidroplane.checkattachBug(self)
@ -571,9 +597,18 @@ function hidroplane.flightstep(self)
else
self._command_is_given = false
end
------------------------------------------------------
--accell calculation block
------------------------------------------------------
if is_attached or passenger then
accel, stop = hidroplane.control(self, self.dtime, hull_direction,
longit_speed, longit_drag, later_speed, later_drag, accel, pilot, is_flying)
if self._autopilot ~= true then
accel, stop = hidroplane.control(self, self.dtime, hull_direction,
longit_speed, longit_drag, later_speed, later_drag, accel, pilot, is_flying)
else
accel = hidroplane.autopilot(self, self.dtime, hull_direction,
longit_speed, longit_drag, later_speed, later_drag, accel, pilot, is_flying, curr_pos)
end
end
--end accell
@ -605,6 +640,9 @@ function hidroplane.flightstep(self)
elseif stop == false then
self.object:set_velocity({x=0,y=0,z=0})
end
------------------------------------------------------
-- end accell
------------------------------------------------------
--self.object:get_luaentity() --hack way to fix jitter on climb