Jump to content

Recommended Posts

Posted

Hello All.  I have been working on a project to get items to export from DCS world using the local o = LoGetWorldObjects() and having great success for the most part.  What I have been wrapping my head around is to get exported is also the unit type>  AIRPLANE, SHIP, GROUND, HELICOPTER. to also be identified and exported.  Below is the lua that I have been using with all working well except when I try to get the unitType or Group. Now I see 'group' might quantify the total number of each and I am searching for each line of my CSV Export.log file to also include HELICOPTER or AIRPLANE, etc.  Please see lua.


--This Export.lua illustrates how to export multiple data in 30 second intervals lat/long and flight alt etc.

function LuaExportStart()

    -- create file object for writing
     default_output_file = io.open(lfs.writedir().."/Scripts/multiExportGS/Export.log", "w")
end
function LuaExportBeforeNextFrame()
end

function LuaExportAfterNextFrame()
end

function LuaExportStop()

     if default_output_file then
      default_output_file:close()
      default_output_file = nil
   end
   -- delete the Export.log file
    os.remove(lfs.writedir().."/Scripts/multiExportGS/Export.log")
end
function LuaExportActivityNextEvent(t)
    local tNext = t 
local o = LoGetWorldObjects()

for k,v in pairs(o) do

default_output_file:write(string.format("%.1f, %s, %f, %f, %f, %f, %s, %.1f\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition))

end
tNext = tNext + 30.0
return tNext

end

tNext = tNext + 30.0
return tNext
 

//

 

I have tried to use a v.Type with no success.  I have tried making some statements like this

function LuaExportActivityNextEvent(t)
    local tNext = t 
    local o = LoGetWorldObjects()

    for k,v in pairs(o) do
        print(v.Type)  -- add this line for debugging purposes
        local objectType = "unknown"
        if v.Type == "Ship" then
            objectType = "ship"
        elseif v.Type == "Helicopter" then
            objectType = "helicopter"
        elseif v.Type == "Airplane" then
            objectType = "airplane"
        else
            objectType = "ground"
        end
        default_output_file:write(string.format("%.1f, %s, %f, %f, %f, %f, %s, %s\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition, objectType))
    end

    tNext = tNext + 30.0
    return tNext
end
 

and the only thing that is output is 'ground' as it is not finding the type correctly.

Anyone have any ideas how i might be able to locate the level number or an ID 1,2,3,4 and I know what it is easily?

Any help is greatly appreciated.

Posted
16 hours ago, timothyboss said:

and the only thing that is output is 'ground' as it is not finding the type correctly.

You are receiving "ground" because your catchall 

else
	objectType = "ground"
end

masks the uninitialized state. You may want to change that to "elseif" and you'll likely receive "unknown". To find out what is really returned, output the type of v.Type, and go from there. I've only glanced at LoGetWorldObjects description, and it appears to be old indeed ("Lo" is from "LockOn" - a game ED published 20 years ago). Since you

16 hours ago, timothyboss said:

print(v.Type)  -- add this line for debugging purposes

already, what is the output? That should give you an indication what v.Type is.

 

  • Like 1
Posted

Hello cfrag.  Thanks for the reply.  I have been trying to get v.Type to output data but then the entire export.log is blank and nothing is written to it.  The output right now is "time, name of unit (i.e. F-18C_Hornet), Lat, Long, Altitude, Heading, enemy or allied"  lastly I am trying to determine if it is a ship, ground, airplane or helicopter, but with v.Type the output fails to write anything to my .log file.

Posted

with ground being catchall at the end I was hoping it would at least generate something, it did where the v.Type did not, but its not the right thing.  looking at the documentation i need to use something like getCategory or maybe getDesc and try to have that pull a class of the item from a table somewhere.

Posted (edited)
8 hours ago, timothyboss said:

I have been trying to get v.Type to output data but then the entire export.log is blank and nothing is written to it.

In that case, in all likelihood, v.Type is nil. Test for that, and set objectType = "NIL!" in that case, so know it's nil. If it's not nil, set objectType to the type that is returned, e.g. 

objectType = "type is <" .. type(v.Type) ..  ">"

and dump the table contents if type is equal to "table"

Or, try a different approach. If you know it's a unit, simpyl use Unit.GetByName, and then get its desc and type. Since you have the name of the unit, that should be possible. Nilcheck before you access desc/type so you don't crash.

 

Edited by cfrag
  • Like 1
Posted

I haven't had much luck.  I have a work around.  Get the name of the unit and just use a lookup function to compare and if criteria is met...it's a SHIP, HELICOPTER etc.  A little more work, but that's ok.  Thanks for your help.

 

  • 2 weeks later...
Posted

in case I still have followers in this post.  I did not have much luck in the previous posting so I instead used some info from the export and knowledge of units to have excel functions lookup and such.  anyhow thank you all for your inputs.  I do have a second question if anyone might have the answer (I will continue to search the forum too)

I have the Export.lua script in my saved games with the following call outs.

local wwtlfs=require('lfs');dofile(wwtlfs.writedir()..'Scripts/wwt/wwtExport.lua')

local FlightPlannerlfs = require('lfs');dofile(FlightPlannerlfs.writedir()..'Scripts/FlightPlanner/FlightPlanner.lua')

local multiExportGSlfs=require('lfs');dofile(multiExportGSlfs.writedir()..'Scripts/multiExportGS/latlongelev.lua')

dofile(lfs.writedir()..[[Scripts\DCS-BIOS\BIOS.lua]])

local Tacviewlfs=require('lfs');dofile(Tacviewlfs.writedir()..'Scripts/TacviewGameExport.lua')

local TheWayLfs=require('lfs');dofile(TheWayLfs.writedir()..'Scripts/TheWay.lua')

pcall(function() local dcsSr=require('lfs');dofile(dcsSr.writedir()..[[Mods\Services\DCS-SRS\Scripts\DCS-SimpleRadioStandalone.lua]]); end,nil)

Now my problem is that these two keep stepping on one another meaning which ever is in the bottom wins and thats is the lua that provides the output file.  when I swap these two around then the one on the bottom wins etc. and writes.

local FlightPlannerlfs = require('lfs');dofile(FlightPlannerlfs.writedir()..'Scripts/FlightPlanner/FlightPlanner.lua')

local multiExportGSlfs=require('lfs');dofile(multiExportGSlfs.writedir()..'Scripts/multiExportGS/latlongelev.lua')

so what are the two lua scripts it calls?  see below, in order of the above post.

function LuaExportStart()
    -- create file object for writing
    d_output_file = io.open(lfs.writedir().."/Scripts/FlightPlanner/data.json", "w")
    
    -- get the start time
    start_time = os.clock()

end

function LuaExportStop()
    -- close the file object
    if d_output_file then
        d_output_file:close()
        d_output_file = nil
    end
    
    -- delete the data.json file
    os.remove(lfs.writedir().."/Scripts/FlightPlanner/data.json")

end
function LuaExportActivityNextEvent(t)
    local currentTime = LoGetModelTime()
    if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        local o = LoGetWorldObjects()
        
        -- delete the data.json file before writing to it
        os.remove(lfs.writedir().."/Scripts/FlightPlanner/data.json")
        
        -- create file object for writing
        d_output_file = io.open(lfs.writedir().."/Scripts/FlightPlanner/data.json", "w")
        
        for k,v in pairs(o) do
            d_output_file:write(string.format("%.1f,%s,%f,%f,%.1f,%.1f,%s\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition))
        end
        
        -- close the file object
        if d_output_file then
            d_output_file:close()
            d_output_file = nil
        end
    end
end

and 

function startServer()
  local folderPath = "E:/Saved Games/DCS.openbeta/Scripts/multiExportGS" -- Replace this with the desired folder location
  local command = 'start "" powershell.exe -noexit -command "cd \'' .. folderPath .. '\'; node import.js"' -- Concatenate the command to change directory and start the server
  os.execute(command) -- Execute the command in the system shell
end
function LuaExportStart()
    -- create file object for writing
    default_output_file = io.open(lfs.writedir().."/Scripts/multiExportGS/FltPlannerGPS.log", "w")
    
    -- get the start time
    start_time = os.clock()

    -- Start the server upon LuaExportStart()
    startServer()
end

function LuaExportStop()
    -- close the file object
    if default_output_file then
        default_output_file:close()
        default_output_file = nil
    end
    
    -- delete the Export.log file
    os.remove(lfs.writedir().."/Scripts/multiExportGS/FltPlannerGPS.log")

    -- Close the server upon LuaExportStop()
    if os.getenv("OS") == "Windows_NT" then
        os.execute("taskkill /IM node.exe /F") -- Terminate the node.exe process
        os.execute("taskkill /IM powershell.exe /F") -- Terminate the PowerShell process
    else
        os.execute("pkill node") -- Terminate the node process on Unix-like systems
        os.execute("pkill powershell") -- Terminate the PowerShell process on Unix-like systems
    end
end

function LuaExportActivityNextEvent(t)
    local currentTime = LoGetModelTime()
    if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        local o = LoGetWorldObjects()
        for k,v in pairs(o) do
            default_output_file:write(string.format("%.1f,%s,%f,%f,%.1f,%.1f,%s\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition))
        end
    end
end

I suspect my problem is related to multiple calls to the same function at the same time, but I cannot wrap my head around it.  I am suspecting the function: 

function LuaExportActivityNextEvent(t)

is causing the binding or overwritten or stepping on issue.  Does anyone know how I might be able to run these two lua scripts separately and independent of one another while both performing as they are intended to function?

Thanks in advance. 

Posted

Interesting time to be playing with such scripts as I'm wondering if the multi-threading stuff might be impacting what you're doing. 

Have you thought of setting a global variable that the other routine refers to and won't execute until the first is finished it's LoGetWorldObjects call.

ie, something along the lines of:

In your first script:

 

  if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        while script1_is_running do
          -- do nothing but wait
        end
        script2_is_running = true
        local o = LoGetWorldObjects()
        script2_is_running = false
  ....

and

 

if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        while script2_is_running do
          -- do nothing
        end
        script1_is_running = true
        local o = LoGetWorldObjects()
        script1_is_running = false
        for k,v in pairs(o) do
            default_output_file:write(string.format("%.1f,%s,%f,%f,%.1f,%.1f,%s\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition))
        end

 

...Or better still maybe even if you just add an extra if condition to only run that code provided the other one isn't running, as it looks like you're just wanting this to run every 30 seconds anyway? 

  • Like 1
Posted
5 hours ago, timothyboss said:

Now my problem is that these two keep stepping on one another

Apologies, I'm having a slow brain day. Which two? I seem to see tons of dofile() in the script. I'm guessing "FlightPlannerlfs" and "multiExportGSlfs"

5 hours ago, timothyboss said:

which ever is in the bottom wins and thats is the lua that provides the output file.  when I swap these two around then the one on the bottom wins etc. and writes.

I suspect that this has a simple reason: overwrite. The sequentially second erases and then rewrites the first. If they have the same output file name, that is. Use 'a' instead of 'w' in open to append. What are the file names of the output files that you expect to be written? If it's an overwrite issue, open and create/erase the save file in the main script, then have both dependent scripts simply write. I'm suspecting that the invoked dependent scripts each io.open(filename, "w") to the save file, creating a new one each time.

Also (my brain is really hurting; yesterday evening was tremendously successful, I'm afraid) it seems to me that you redefine LuaExportStart() and LuaExportStop() in both scripts, so whatever you load last will win if they are invoked asynchronously (which the 'startServer' bit seems to imply).

Hope this helps,

-ch

Posted
4 hours ago, cfrag said:

Apologies, I'm having a slow brain day. Which two? I seem to see tons of dofile() in the script. I'm guessing "FlightPlannerlfs" and "multiExportGSlfs"

I suspect that this has a simple reason: overwrite. The sequentially second erases and then rewrites the first. If they have the same output file name, that is. Use 'a' instead of 'w' in open to append. What are the file names of the output files that you expect to be written? If it's an overwrite issue, open and create/erase the save file in the main script, then have both dependent scripts simply write. I'm suspecting that the invoked dependent scripts each io.open(filename, "w") to the save file, creating a new one each time.

Also (my brain is really hurting; yesterday evening was tremendously successful, I'm afraid) it seems to me that you redefine LuaExportStart() and LuaExportStop() in both scripts, so whatever you load last will win if they are invoked asynchronously (which the 'startServer' bit seems to imply).

Hope this helps,

-ch

Hello and thanks for your reply. you are correct in that the two files called by the export.lua are in fact "FlightPlannerlfs" and "multiExportGSlfs" and the "w" to "a" did nothing as the ..'Scripts/FlightPlanner/FlightPlanner.lua') is being blocked by ..'Scripts/multiExportGS/latlongelev.lua').  Im still at it, but a good head scratcher.  seems like I need to call on them separately, but having a heck of a time defining that process.

 

6 hours ago, Dangerzone said:

Interesting time to be playing with such scripts as I'm wondering if the multi-threading stuff might be impacting what you're doing. 

Have you thought of setting a global variable that the other routine refers to and won't execute until the first is finished it's LoGetWorldObjects call.

ie, something along the lines of:

In your first script:

 

  if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        while script1_is_running do
          -- do nothing but wait
        end
        script2_is_running = true
        local o = LoGetWorldObjects()
        script2_is_running = false
  ....

and

 

if not lastExportTime or (currentTime - lastExportTime) >= 30.0 then
        lastExportTime = currentTime
        while script2_is_running do
          -- do nothing
        end
        script1_is_running = true
        local o = LoGetWorldObjects()
        script1_is_running = false
        for k,v in pairs(o) do
            default_output_file:write(string.format("%.1f,%s,%f,%f,%.1f,%.1f,%s\n", t, v.Name, v.LatLongAlt.Lat, v.LatLongAlt.Long, 3.28084*v.LatLongAlt.Alt, 57.2958*v.Heading, v.Coalition))
        end

 

...Or better still maybe even if you just add an extra if condition to only run that code provided the other one isn't running, as it looks like you're just wanting this to run every 30 seconds anyway? 

That is correct.  I wan them to both be independent of one another an each run at a set time after executed.  they can be staggered, but I am going to attempt to go with your approach and see the outcome.  thank you for your input.  I let all know of the findings.

Posted

I'm thinking that maybe for this project... If I have to start or stop or pause and wait with if statements in the exporting of the same or similar data, then I might just try to build a master export Lua that writes to multiple locations in the format I need for both separate projects.  I should be able to set a global variable that starts say named function script1() and runs through the code in latlongelev.lua and then end with a continuation to function script2() run FlightPlannerGPS.lua end and then 30 seconds later repeat.  That way both files should be written, and ended so the other can be written and ended without being stepped on.  I will just have to start the server for node.js outside in a new global variable, remove the loops inside the independent Lua scripts so they complete and I should be good.  When the game closes, the server closes and the problem should be solved?  Maybe? Thoughts.  If only DCS Lua environ would allow multiple calls of the LuaExportActivityNextEvent () by affixing a 1,2,3.... To the end. Or I just need to get better...  The later.

Posted
2 hours ago, timothyboss said:

is that what you meant

I believe @Dangerzone was talking about a possible race condition between the two export scripts caused by two threads running concurrently that attempt to access the same resource, caused by the new multithreading ability in DCS. If that was the case, his kindly proposed solution is as likely to end in a deadlock as to resolve it, with both scripts waiting for the other to release the other scriptX_is_running, as Lua has no mutex or other semaphore to prevent this (the proposed lock-and-release solution is unsafe).

I don't think your issue is caused by a contention issue. Have you verified that your LuaExportStart() and LuaExportStop() methods can't overwrite each other, i.e. that their name space isn't shared? If they are loaded into the same context, one will overwrite the other.

Posted
20 minutes ago, cfrag said:

I believe @Dangerzone was talking about a possible race condition between the two export scripts caused by two threads running concurrently that attempt to access the same resource, caused by the new multithreading ability in DCS. If that was the case, his kindly proposed solution is as likely to end in a deadlock as to resolve it, with both scripts waiting for the other to release the other scriptX_is_running, as Lua has no mutex or other semaphore to prevent this (the proposed lock-and-release solution is unsafe).

I don't think your issue is caused by a contention issue. Have you verified that your LuaExportStart() and LuaExportStop() methods can't overwrite each other, i.e. that their name space isn't shared? If they are loaded into the same context, one will overwrite the other.

Good question.  I don't even see it reporting in the DCS.log file.  I might need to print to.  Should, normally, the Lua start / stop / exportActiveNextEvent function regardless if other scripts call the same functions?

Posted

I have a suspicion it is probably overwriting the other because of how the scripts were written at one test point.  The first (of two) dofile Lua's I am having issues with called the luaexportactivitynextevent() function and the second Lua actually performed the write to the location which confused me.  But the second Lua exportnextevent was renamed something else, so I feel there might need to be a pause or delay in the dofile if possible.  Maybe have a dofile that performs 1 script and then ends then performs the second then ends.  Maybe like a subroutine?

Posted

Maybe using the hooks is the way to go?  This is not the first time this issues has been brought up either.  There are some good talks across a couple forums of this same issue.  People get creating by refining global variables that end up calling on the LuaExportStart () / stop / before frame / after frame / next event.  

I just need to get smarter on that part.

Posted (edited)
10 hours ago, cfrag said:

I believe @Dangerzone was talking about a possible race condition between the two export scripts caused by two threads running concurrently that attempt to access the same resource, caused by the new multithreading ability in DCS. If that was the case, his kindly proposed solution is as likely to end in a deadlock as to resolve it, with both scripts waiting for the other to release the other scriptX_is_running, as Lua has no mutex or other semaphore to prevent this (the proposed lock-and-release solution is unsafe).

Thanks CFRAG for picking up on that problem. Sorry for misleading you @timothyboss, there's a lot more traps for me to learn about with lua it would seem. Thank goodness for the wealth of info shared in these forums. 

Would it be possible to set a lastran_x stamp instead. Then when starting a script you check to see if the 'other' script has been ran within the last 5 seconds and if it has you skip that instance and wait again. This way it may not end in a deadlock but rather uses timestamps so if something does go amiss - it would reset itself?

Edited by Dangerzone
Posted
13 hours ago, Dangerzone said:

Thanks CFRAG for picking up on that problem. Sorry for misleading you @timothyboss, there's a lot more traps for me to learn about with lua it would seem. Thank goodness for the wealth of info shared in these forums. 

Would it be possible to set a lastran_x stamp instead. Then when starting a script you check to see if the 'other' script has been ran within the last 5 seconds and if it has you skip that instance and wait again. This way it may not end in a deadlock but rather uses timestamps so if something does go amiss - it would reset itself?

 

@Dangerzone @cfrag what are your thoughts on the Export.lua making a call to a file that loads the two independently.  So for the FlightPlanner Lua I would have a LuaExportStart () start the server, start to write directory. Perform the task to export and end.  Start the write of the second Lua latlongelev.lua and just perform the script.  No need for the second script to start at the LuaExportStart ().  Once complete with the second Lua... Repeat until the game ends and then I can luaExportStop ().

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...