DCS export

From DCS World Wiki - Hoggitworld.com
Revision as of 18:46, 1 June 2018 by Jeremy Smitherman (talk | contribs) (Available Functions)


DCS allows for the export of data within the game world to be used by a wide variety of applications. Example include tacview, simple radio, and physical cockpits.

Luasocket

DCS supplies LuaSocket 2.0 Beta files in the Scripts\LuaSocket folder and in the DCS installation folder. You can use LuaSocket to establish standard network connection between the Export.lua script and your local or remote program. Look into the Scripts\LuaSocket folder and find Listener.lua and Talker.lua files. You can use them as stand alone examples for Lua script networking.

Export.lua

Initialization

At the top of Export.lua, there's some comments about it's use

-- Data export scripts 
-- Copyright (C) 2004, Eagle Dynamics.
-- …
The Lua language use two sequential dashes "--" to start the single-line comment to the end of line. If you need to comment several lines then use "--" and "--" brackets:

-- Uncomment this function to enable data export!
--[[ 
function LuaExportStart()
-- Works once just before mission start.

-- Make initializations of your files or connections here.
-- For example:
-- 1) File
--	local file = io.open("./Temp/Export.log", "w")
--	if file then
--	io.output(file)
--	end
-- 2) Socket
-- dofile "lua.lua"
-- socket = require("socket")
-- host = host or "localhost"
-- port = port or 8080
-- c = socket.try(socket.connect(host, port)) -- connect to the listener socket
-- c:setoption("tcp-nodelay",true) -- set immediate transmission mode 

end
--]]

DCS activates the Config\Export\Export.lua script at every mission start. You need to uncomment the function LuaExportStart to activate it and to activate all other functions. For that add the single "-" just before "--[[" opening multi-line comment to convert it to the single-line comment "---[[". So the closing multi-line comment bracket without opening one becomes the single-line comment too. If you want to disable exporting features then remove additional third dash to make the comment multi-line again.

DCS also prints to the Error.log file all other Lua error messages for the Export.lua script.

LuaExportStart and LuaExportStop

DCS calls script functions for every mission simulation. It calls the LuaExportStart function just before mission start to make user script initializations. For example, to open a log file:

local file = io.open("./Temp/Export.log", "w")
if file then
io.output(file)
end

or to establish a network connection:

dofile "lua.lua"
socket = require("socket")
host = host or "localhost"
port = port or 8080
c = socket.try(socket.connect(host, port)) -- connect to the listener socket
c:setoption("tcp-nodelay",true) -- set immediate transmission mode

DCS calls the LuaExportStop function just after mission quit to make user finishing actions. For example, to close the log file:

io.close()
or to unlink the network connection:

socket.try(c:send("quit")) -- to close the listener socket
c:close()

LuaExportBeforeNextFrame

DCS calls the function LuaExportBeforeNextFrame just before every simulation frame. So if you want to set some input control commands then you can do it here. For example:

LoSetCommand(3, 0.25) -- rudder 0.25 right 
LoSetCommand(64) -- increase thrust

There are discrete and analogous input control commands. The discrete command has code only:

LoSetCommand(64) -- increase thrust

The analogous command has code and value:

LoSetCommand(3, 0.25) -- rudder 0.25 right


LuaExportAfterNextFrame

DCS calls the function LuaExportAfterNextFrame every time the simulation frame finishes. So you need to code here your actions to get frame simulations results. For example:

local t = LoGetModelTime()
local name = LoGetPilotName()
local altBar = LoGetAltitudeAboveSeaLevel()
local altRad = LoGetAltitudeAboveGroundLevel()
local pitch, bank, yaw = LoGetADIPitchBankYaw()

Then you can send data to your file:

io.write(string.format("t = %.2f, name = %s, altBar = %.2f, altRad = %.2f, pitch = %.2f, bank = %.2f, yaw = 
%.2f\n", t, name, altBar, altRad, pitch, bank, yaw))

or to your receiving network program:

socket.try(c:send(string.format("t = %.2f, name = %s, altBar = %.2f, alrRad = %.2f, pitch = %.2f, bank = %.2f, 
yaw = %.2f\n", t, name, altRad, altBar, pitch, bank, yaw)))

Reducing Network Traffic

To reduce network traffic you may need to get data not after every frame but at some model time moments. You can use the LuaExportActivityNextEvent function to program the model time moment tNext of your next exporting event. The parameter t of this functions stands for current model time. If tNext doesn't increase it's value then the LuaExportActivityNextEvent function will not be called further in current simulation. For example, let's get objects data every simulation second and output them to our file:

local tNext = t 
local o = LoGetWorldObjects()
for k,v in pairs(o) do
io.write(string.format("t = %.2f, ID = %d, name = %s, country = %s(%s), LatLongAlt = (%f, %f, %f), heading = %f\n", t, k, v.Name, 
v.Country, v.Coalition, v.LatLongAlt.Lat, v.LatLongAlt.Long, v.LatLongAlt.Alt, v.Heading))
end
tNext = tNext + 1.0
return tNext

or to our network socket:

local tNext = t 
local o = LoGetWorldObjects()
for k,v in pairs(o) do
socket.try(c:send(string.format("t = %.2f, ID = %d, name = %s, country = %s(%s), LatLongAlt = (%f, %f, %f), heading = %f\n", t, k, 
v.Name, v.Country, v.Coalition, v.LatLongAlt.x, v.LatLongAlt.Long, v.LatLongAlt.Alt, v.Heading)))
end
tNext = tNext + 1.0
return tNext

Available Functions

You can use registered DCS internal data exporting functions in this script and in your scripts called from this script. All returned values are Lua numbers if other type is not pointed.

Coroutines

DCS supports Lua coroutines using internal function LoCreateCoroutineActivity() available from the exporting lua_State and using scripted function CoroutineResume() defined in the Config/Export/Export.lua file. Following are fragments from that file related to coroutines support:

Global coroutine table:

Coroutines = {}

Global last created coroutine index:

CoroutineIndex = 0

This function will be called by DCS model timer to resume coriutine and to get its status:

function CoroutineResume(index, tCurrent) coroutine.resume(Coroutines[index], tCurrent) return coroutine.status(Coroutines[index]) ~= 
"dead" end

Coroutine function sample using

coroutine.yield()

to suspend execution and for getting current model time value.

function f(t) local tNext = t local file = io.open("./Temp/Coroutine.log", "w") io.output(file) io.write(string.format("t = %f, 
started\n", tNext)) tNext = coroutine.yield() for i = 1,10 do io.write(string.format("t = %f, continued\n", tNext)) tNext = 
coroutine.yield() end io.write(string.format("t = %f, finished\n", tNext)) io.close() end

Create coroutine and save it in the coroutines table with corresponding index:

CoroutineIndex = CoroutineIndex + 1
Coroutines[CoroutineIndex] = coroutine.create(f)

Plan coroutine execution starting from 1.0 second with following periodic resumption with 3.0 seconds period:

LoCreateCoroutineActivity(CoroutineIndex, 1.0, 3.0)

Coroutine output results in the Temp/Coroutine.log file:

t = 1.000000, started
t = 4.000000, continued
t = 7.000000, continued
t = 10.000000, continued
t = 13.000000, continued
t = 16.000000, continued
t = 19.000000, continued
t = 22.000000, continued
t = 25.000000, continued
t = 28.000000, continued
t = 31.000000, continued
t = 34.000000, finished

So there is a possibility to use Lua scripts without visible stuttering specific for complex interpret programs. We can uniformly distribute Lua coroutine execution during simulation model time with given period.


Multiplayer

When playing the game in single player every command is available, however in multiplayer there are options to disable specific settings as desired by the server creator. There are three options as defined by the following:

Object

Allows for all objects to be accessible. For example this is how tacview knows and returns where every single object in the game is at.

 LoGetObjectById
 LoGetWorldObjects

Sensor

Exports sensor data from your aircraft.

 LoGetTWSInfo
 LoGetTargetInformation
 LoGetLockedTargetInformation
 LoGetF15_TWS_Contacts
 LoGetSightingSystemInfo
 LoGetWingTargets

Ownship

Exports data about your own aircraft. For example simple radio uses one of these to get the players current location and radio information.

 LoGetPlayerPlaneId
 LoGetIndicatedAirSpeed
 LoGetAngleOfAttack
 LoGetAngleOfSideSlip
 LoGetAccelerationUnits
 LoGetVerticalVelocity
 LoGetADIPitchBankYaw
 LoGetTrueAirSpeed
 LoGetAltitudeAboveSeaLevel
 LoGetAltitudeAboveGroundLevel
 LoGetMachNumber
 LoGetRadarAltimeter
 LoGetMagneticYaw
 LoGetGlideDeviation
 LoGetSideDeviation
 LoGetSlipBallPosition
 LoGetBasicAtmospherePressure
 LoGetControlPanel_HSI
 LoGetEngineInfo
 LoGetSelfData
 LoGetCameraPosition
 LoSetCameraPosition
 LoSetCommand
 LoGetMCPState
 LoGetRoute
 LoGetNavigationInfo
 LoGetPayloadInfo
 LoGetWingInfo
 LoGetMechInfo
 LoGetRadioBeaconsStatus
 LoGetVectorVelocity
 LoGetVectorWindVelocity
 LoGetSnares
 LoGetAngularVelocity
 LoGetHeightWithObjects
 LoGetFMData

Always

 LoGetPilotName
 LoGetAltitude
 LoGetNameByType
 LoGeoCoordinatesToLoCoordinates
 LoCoordinatesToGeoCoordinates
 LoGetVersionInfo
 LoGetWindAtPoint
 LoGetModelTime
 LoGetMissionStartTime