time interval of data recording

Typically: "How do I... ", "How can I... " questions
Post Reply
lwang87
Posts: 41
Joined: 24 May 2021, 16:47

time interval of data recording

Post by lwang87 »

Hello, I set a data recording file, the code is following:

Code: Select all

        y=os.date("%Y")
        m=os.date("%m")
        d=os.date("%d")
        h=os.date("%H")
        M=os.date("%M")
        S=os.date("%S")
        aa=y..'.'..m..'.'..d..' '..h..'--'..M..S
        fp=io.open('.\\temp\\data'..aa..'.csv',"a") 
        fp:write('Time',',','x',',','y',',','oriente',',','m_state',',','collide_T',',','Latency',',','map',',','clearance','\n')
and I want to record the model's state, such as forward, backward, turn right, turn left, wait...... the recording sentence is following:

Code: Select all

            fp:write(string.format('%.2f',simulationtime),',',string.format('%.2f',current_position[1]),',',string.format('%.2f',current_position[2]),',',string.format('%.2f',math.deg(current_orientation[3])),',',current_moving(m),',',collisionTimes,',',X[b][1],',',current_map(p),',',current_clearance(c),'\n')

but the time interval of recoding is inconsistent(it it randomly). At the "Simulation Setting" dialog, I've set dt=50.0ms(custom), Time step[s]0.05, and enabled the Real-time simulation, but it's not effective. I want the time interval of recording is consistent, Please help solve this problem, thanks you so much.

fferri
Posts: 1193
Joined: 09 Sep 2013, 19:28

Re: time interval of data recording

Post by fferri »

Hi,

if you put that code in the sysCall_sensing() function of some embedded script, at every timestep it will record the data; you should use sim.getSimulationTime() as source for your simulationtime field.

Your code is incomplete, can't tell exactly what is going on.

lwang87
Posts: 41
Joined: 24 May 2021, 16:47

Re: time interval of data recording

Post by lwang87 »

fferri wrote: 15 Jul 2021, 09:09 Hi,

if you put that code in the sysCall_sensing() function of some embedded script, at every timestep it will record the data; you should use sim.getSimulationTime() as source for your simulationtime field.

Your code is incomplete, can't tell exactly what is going on.
I did. I've used sim.getSimulationTime(). My code is included by function sysCall_threadmain(), and I wrote

Code: Select all

local simulationtime=sim.getSimulationTime()
before the controlling code of the model, Because I will record the simulation time. But the time step of my data is not recorded every second. For example, at 12.4s it recorded some data, the but the next recording time is 15.8s, and the third recording time is 20.9. The time step is not consistent.

fferri
Posts: 1193
Joined: 09 Sep 2013, 19:28

Re: time interval of data recording

Post by fferri »

You must have used a threaded script, which runs asynchronously.

Use a non-threaded script, instead; in that case sysCall_sensing() is called exactly once per timestep.

You can also achieve the same level of control in a threaded script by using sim.setThreadAutomaticSwitch() and sim.switchThread(), but it is going to be more complex than using a non-threaded script (in a nutshell: disable automatic thread switching, then explicitly switch thread each time you log new data)

lwang87
Posts: 41
Joined: 24 May 2021, 16:47

Re: time interval of data recording

Post by lwang87 »

fferri wrote: 15 Jul 2021, 16:17 You must have used a threaded script, which runs asynchronously.

Use a non-threaded script, instead; in that case sysCall_sensing() is called exactly once per timestep.

You can also achieve the same level of control in a threaded script by using sim.setThreadAutomaticSwitch() and sim.switchThread(), but it is going to be more complex than using a non-threaded script (in a nutshell: disable automatic thread switching, then explicitly switch thread each time you log new data)
Thanks for your answer. I did use threaded script. And I don't understand when should I use sim.setThreadAutomaticSwitch() and sim.switchThread() ??

coppelia
Site Admin
Posts: 10336
Joined: 14 Dec 2012, 00:25

Re: time interval of data recording

Post by coppelia »

A threaded script will automatically yield, after about 2ms. So if you have a threaded script with an infinite loop, CoppeliaSim will not block. Try following:

Infinite loop, not blocking (yielding after about 2ms by default):

Code: Select all

function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    while true do
        -- infinite loop
    end
end
You can control when the thread automatically yields via sim.setThreadSwitchTiming:

Infinite loop, not completely blocking (yielding after about 1000ms):

Code: Select all

function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    sim.setThreadSwitchTiming(1000) -- set automatic thread switch to 1000ms delay
    while true do
    end
end
You can also completely forbid automatic thread yields with sim.setThreadAutomaticSwitch(false). This is useful when you want to synchronize your thread with the simulation loop. Consider this first example:

Unsynchronized threaded script:

Code: Select all

function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    while true do
        print(string.format("Simulation time: %.3f[s]",sim.getSimulationTime()))
    end
end
You'll notice that the script will print several times the same simulation time. Sometimes more, sometimes less. You can now synchronize above example with the simulation loop with two additional commands: sim.setThreadAutomaticSwitch and sim.switchThread:

Synchronized threaded script:

Code: Select all

function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    local restoreLevel=sim.setThreadAutomaticSwitch(false) -- forbid automatic thread switches/yields
    while true do
        print(string.format("Simulation time: %.3f[s]",sim.getSimulationTime()))
        sim.switchThread() -- explicitely switch/yield!
    end
    sim.setThreadAutomaticSwitch(restoreLevel) -- restore previous 'forbid level'
end
Cheers

Post Reply