API Question How can I program a precise burn in Lua?

Wishbone

Clueless developer
Addon Developer
Joined
Sep 12, 2010
Messages
2,420
Reaction score
2
Points
0
Location
Moscow
I used GetBurnTime from TransX to program burns in Lua.
In DG-XR1 "In orbit" scenario I type:
Code:
 run('testcode')
 pulse_dv('XR1-01', 10.0)
 pulse_dv('XR1-01', 20.0)
 pulse_dv('XR1-01', 30.0)

And the error seems to grow with the growth in commanded dV. As I understand, if it were the frame rate to blame for the error, the error would be more or less constant (with high Isp propellants mass depletion isn't a problem). The burns aren't long, so loss of velocity during the burn is not large either. So my guesses are:
a) TransX doesn't calculate burn time correctly (strange!)
or b) Lua proc.wait_simdt() isn't good
or c) something else (like Mr.Murphy stepping in and ruining the show).



the testcode.lua file:
Code:
function pulse(vessel_name, dt, thrustlevel)
	local v = vessel.get_interface(vessel_name)

	if v == nil then
    		term.out ('Could not find '..vessel_name..'. Aborting')
    		return
	end

        local tacc = oapi.get_tacc()
        oapi.set_tacc(1.0)

	v:set_thrustergrouplevel(THGROUP.MAIN, thrustlevel)
	proc.wait_simdt(dt)
	v:set_thrustergrouplevel(THGROUP.MAIN, 0.0)
	oapi.set_tacc(tacc)
end

-- from transX
function get_burntime(vessel_name, dV, thrustergroup, thrustlevel)
	local v = vessel.get_interface(vessel_name)

	if v == nil then
    		term.out ('Could not find '..vessel_name..'. Aborting')
    		return
	end
	-- Returns the time to burn to the required deltaV. Calculates via rocket equation
   local d_V = dV
	if(dV < 0) then
		d_V = -dV
	end
   local T = 0
   local isp = 0
   local numThrusters = v:get_groupthrustercount(thrustergroup)
   for i = 0, numThrusters-1 do 
		local thruster = v:get_groupthruster(thrustergroup,i)
		T = T+ v:get_thrustermax0(thruster)*thrustlevel
		isp = isp+ v:get_thrusterisp0(thruster)
   end
	return - (isp * v:get_mass() / T * (math.exp(-d_V / isp) - 1.0))
--	return - (isp * GetStackMass(vessel) / T * (exp(-d_V / isp) - 1.0))
end


function pulse_dv(vessel_name, dV)
    -- todo: add check for attitude! add thruster throttling before cutoff
 
	local v = vessel.get_interface(vessel_name)

	if v == nil then
    		term.out ('Could not find '..vessel_name..'. Aborting')
    		return
	end
        local tacc = oapi.get_tacc()
        oapi.set_tacc(1.0)
        local body = v:get_surfaceref()
        local currV = v:get_relativevel(body)
        local currVmod = vec.length(currV)
        local dt = get_burntime(vessel_name, dV, THGROUP.MAIN, 1.0)
        pulse(vessel_name, dt, 1.0)
        local newVmod = vec.length(v:get_relativevel(body))
        local dV_error = dV - (newVmod-currVmod)
        oapi.dbg_out(string.format("delta V error: %.4f", dV_error))
	oapi.set_tacc(tacc)
end
 
And the error seems to grow with the growth in commanded dV. As I understand, if it were the frame rate to blame for the error, the error would be more or less constant
That depends on how long the burns are with respect to the frame rate. If the burns so short to be completed within a small number of frames (or even a single frame) then it makes sense that the error is linear in dV, since you are not taking the granularity of the time steps into account.

Does the accuracy improve as you scale down the thrust level and scale up dt?
 
That depends on how long the burns are with respect to the frame rate. If the burns so short to be completed within a small number of frames (or even a single frame) then it makes sense that the error is linear in dV, since you are not taking the granularity of the time steps into account.

Does the accuracy improve as you scale down the thrust level and scale up dt?

Could you get around this by using a fixed timestep of a length of significantly smaller then your burn duration?
 
Will try both suggestions and set up a test suite. However, I did try acceleration of 0.1 and it did not help significantly.
 
All right, a host of problems appeared.

Now I understand why Apollo crews needed Houston's feedback during TLI. The setup has to be tested from a perfectly circular orbit OR I have to find a replacement for the homegrown dV error calculator that takes into account non-zero burn time and corresponding speed change due to radius change during the burn. Will sack and plunder the library to find the formulae for closed-loop cutoff guidance.

The next problem is that with Lua timing there is indeed a small (average) overtime (0.004 seconds on my computer) that can be deducted from the programmed time.

Third, the fixed step doesn't change much as far as timing accuracy is concerned. Would be nice to have an API function that would do burns with precise timing (OR I will have to code it with Windows high-perf timers in C myself, choose your poison, since my func will likely be unavailable to folks around here unless I find out how to do a Lua-accessible plugin).

Fourth, seems like closed loop cutoff control is the best (and pretty realistic) option.
 
Folks, I'll keep on reading Battin before posting anything else on this issue.
 
Back
Top