Return a table from queueGameEngineLua

Discussion in 'Programming' started by bidwars, Jun 14, 2017.

  1. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    I am trying to get some wheel data to find out if the tire is spinning or the car is going to lose control. Does anyone have any suggestions.

    So I have the following command.
    vObj is the vehicle
    vObj:queueLuaCommand("obj:queueGameEngineLua('Test = ('..streams['wheelInfo']..')')")

    How can I get the system to return the table wheelInfo? Also does Test need to be a global variable or can we pass the table back to a local variable.
     
    #1 bidwars, Jun 14, 2017
    Last edited: Jun 14, 2017
  2. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    Maybe tcsData would be better then the stream data. How can I get the entire tcsData table from the command above into my scenario?
     
  3. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    So I changed the command to
    vObj:queueLuaCommand([[for i = 0, 3 do wheelData = wheels.wheels end]])
    This creates a global variable wheelData.

    But I still get an errors
    48.91718|E|libbeamng.lua.V|*** FATAL LUA ERROR: [string "string"]:1: attempt to index global 'wheelData' (a nil value)
    48.91723|E|libbeamng.lua.V|=============== Stack Traceback >> START >>
    48.91725|E|libbeamng.lua.V|(1) main chunk of [string "string"] at line 1
    48.91727|E|libbeamng.lua.V|--------------- << END <<
    48.91730|E|libbeamng.lua.V|*** while executing this line: for i = 0, 3 do wheelData = wheels.wheels end

    If I use the print operation on this it works fine.

    vObj:queueLuaCommand([[for i = 0, 3 do print(wheels.wheels.name) end]])
     
  4. Codeslasher

    Codeslasher
    Expand Collapse
    BeamNG Team

    Joined:
    Apr 12, 2016
    Messages:
    28
    Hi
    You can't concatenate tables. So, you have to extract the fields and send them across.
    You need to use a callback function that is setup to receive the fields.
    For example
    In your scenario have a function with the number of fields you need
    Code:
    local function wheelDataCallback(absActive)
      log('I','example', 'wheelDataCallback triggered....Data type is '..type(absActive))
    end
    Then just before you make the call to VLua, assign the callback to the active scenario (simplest method, but there are also others)
    Code:
    scenarios.getScenario().wheelDataCallback = wheelDataCallback
    local command = string.format("obj:queueGameEngineLua('scenarios.getScenario().wheelDataCallback('..tostring(wheels.wheels[0].absActive)..')')") 
    vObj:queueLuaCommand(command)
    Hope this helps.
     
    • Like Like x 1
  5. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    Thank you! I was thinking about doing this for each wheel and multiple fields. Would something like this work?

    Example:
    scenarios.getScenario().wheelDataCallback = wheelDataCallback

    vObj:queueLuaCommand("for i,v in pairs(wheels.wheels) do obj:queueGameEngineLua('scenarios.getScenario().wheelDataCallback('..tostring(v)..','..tostring(i)..')') end")
     
  6. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    I almost have this working. Can the function call return more than one variable at a time?

    Here is what I have:

    local function wheelDataCallback(n,value,i)
    log('I','example', 'wheelDataCallback triggered....Data type is '..type(n))
    log('I','example', 'wheelDataCallback triggered....Data type is '..type(value))
    log('I','example', 'wheelDataCallback triggered....Data type is '..type(i))
    end

    scenarios.getScenario().wheelDataCallback = wheelDataCallback

    vObj:queueLuaCommand([[for i,v in pairs(wheels.wheels) do for n,value in pairs(v) do if n == "name" then obj:queueGameEngineLua('scenarios.getScenario().wheelDataCallback('..tostring(n)..','..tostring(value)..','..tostring(i)..')') end end end]])

    It works except that I get
    n = nil
    value = nil
    i = numer: 3


    If I cause an error by removing type() in the log line I get more details. It looks like the function call is working because I can see "scenarios.getScenario().wheelDataCallback(name,FR,0)".

    38.68008|E|GameEngineLua|*** FATAL LUA ERROR: lua/scenario/derby_main.lua:383: attempt to concatenate local 'n' (a nil value)
    =============== Stack Traceback >> START >>
    (1) Lua field 'wheelDataCallback' at file 'lua/scenario/derby_main.lua:383'
    Local variables:
    n = nil
    value = nil
    i = number: 3
    (*temporary) = Lua function '?' (defined at line 13 of chunk "lua/ge/main.lua"])
    (*temporary) = string: "I"
    (*temporary) = string: "example"
    (*temporary) = string: "wheelDataCallback triggered....Data type is "
    (*temporary) = nil
    (*temporary) = string: "attempt to concatenate local 'n' (a nil value)"
    (2) main chunk of [string "line"] at line 1
    --------------- << END <<

    38.68012|E|GameEngineLua|*** while executing this line: scenarios.getScenario().wheelDataCallback(name,FR,3)
     
  7. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    This is working by changing the tostring to serialize. What does the serialize do?

    local command = string.format("obj:queueGameEngineLua('scenarios.getScenario().wheelDataCallback('..serialize(wheels.wheels[0].absActive)..')')")
     
  8. Codeslasher

    Codeslasher
    Expand Collapse
    BeamNG Team

    Joined:
    Apr 12, 2016
    Messages:
    28
    Hi,
    calling the callback once per field would be too slow.
    You can make the callback take more than 1 parameter, this allows you to access the directly using a named variable
    Code:
    local function wheelDataCallback(arg1, arg2, arg3)
      log('I','example', 'wheelDataCallback triggered....with '..arg1..','..arg2..','..arg3)
    end
    
    You could also make it take a variable number of arguments, but this is more complicated and requires processing
    Code:
    local function wheelDataCallback(...)
      -- here you'd have to process the ... to extract the arguments
    end
    
    In your case, you should send across a table with the fields you want
    Code:
    local command = "obj:queueGameEngineLua(string.format('scenario_scenarios.getScenario().wheelDataCallback(%s)', serialize({absActive=wheels.wheels[0].absActive, angularVelocity=wheels.wheels[0].angularVelocity, angularVelocityBrakeCouple=wheels.wheels[0].angularVelocityBrakeCouple})))"
    
    Then the callback should change to processing the table
    Code:
    local function wheelDataCallback(data)
      log('I','example', 'wheelDataCallback triggered....with ')
      dump(data)
      log('I','example', 'Abs is Active: '..tostring(data.absActive)) 
    end
    
    Good luck.
     
  9. bidwars

    bidwars
    Expand Collapse

    Joined:
    Sep 23, 2014
    Messages:
    171
    I was able to get the data callback to work. Thanks for your help!
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice