Hello All,
My simulation is interacting with a real world controller, and I'd like to bring the sim (virtual ) clock up as close to real time as I can get it. I won't go into those details here, as I think they'd just distract from the problem at hand.
I'm running 3.26 on an Ubuntu 16.04 machine, and haven't had any trouble getting realtime behavior to operate as intended. However, as we know, the virtual clock (RealtimeSimulatorImpl.m_currentTs) starts at 0, and discretely jumps upward as events are processed from the event queue. I'd like these discrete jumps to start at a realtime stamp to give the illusion of a real clock.
I see two broad strategies.
1.) Initialize m_currentTs to the value returned by WallClockSynchronizer.GetCurrentRealtime().
Benefit: Setting m_currentTs early like this takes advantage of the relative nature of the scheduler timing, ie i don't have to touch the behind the scenes scheduling, which I like since I don't fully understand what's being scheduled, how, when, etc.
Drawback: The time difference between m_currentTs and WallClockSynchronizer's m_realtimeOriginNano will be (based on my simulation code), a few hundred ms, with the origin time being ~200ms or so after m_currentTs. This is causing problems in synchronization, specifically in DoGetDrift, where I'm returning a monster negative, and thus spinwait forever.
Solution? I think my solution here would need to start with RealtimeSimulatorImpl's ProcessOneEvent function, specifically in setting tsNow. Since tsNow assumes the virtual clock was initialized to 0, I'm setting to GetCurrentRealtime() - the synchronizer's m_realtimeOriginNano (once I made that member variable public). This gets me past where I was, but eventually leads to an ASSERT when somebody tries to schedule an event that would occur in the past (after m_currentTs). So that's where I'm stuck. I'm not sure if the root of my issue that the origin timestamp is after the virtual clock's timestamp, if the sync module inherently assumes a virtual clock counting up from zero, or both. Probably both.
2.) Allow m_currentTs to be initialized to zero, but force it up to the sync's origin time right as the WallClockSynchronizer calls DoSetOrigin().
Benefit: This method would rid us of the ~200ms disparity between the origin timestamp ("timestamp", i know it's a 64bit int) and the m_currentTs virtual clock.
Drawback: Everything else. All of the scheduling done by the program would have to be redone, as it would have been done relative to a 0 containing clock. I can manually calculate when to schedule my application events, but there are something like 40 or 50 events in the event queue when the sim first begins running, and fewer than 10 of those are mine (application, end of simulation, etc). Further, I'll have a new problem with the origin time, described below.
Solution? If (A) I manually get the real time, set m_currentTs to it, reschedule everything, and then set the origin time, I'll have the same problem as method 1: an origin time that's further along the timeline than the virtual clock. This would effectively just decrease that ~200ms down to say 5ms and I'll have the same forever spinlock wait as above.
If (B) I set the origin time, then manually get the real time, set m_currentTs, reschedule everything, then begin processing the event queue, I'm increasing the disparity between the origin timestamp and the event queue checks.
So, I'd like to ask if anyone has been through this before and can point me in the right direction. Or if any of the devs/ those with a deeper understanding of NS3 would be willing to brainstorm a solution with me.
Thanks for your attention, I hope your own work is going well.
Stefan