Orbiter-Forum  

Go Back   Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK
Register Blogs Orbinauts List Social Groups FAQ Projects Mark Forums Read

Orbiter SDK Orbiter software developers post your questions and answers about the SDK, the API interface, LUA, meshing, etc.

Reply
 
Thread Tools
Old 02-28-2017, 06:04 PM   #1
indy91
Addon Developer
Default VESSEL::GetGlobalVel() and/or simdt oscillation

Next to this potential bug in Orbiter 2016 there is another problem with the implementation of accelerometers in NASSP.

Part of the acceleration calculation is taking the global velocity each timestep and use the difference to the previous timestep to get the global velocity difference per second.

First Timestep:

Code:
sat->GetGlobalVel(vel);
lastGlobalVel = vel;
All subsequent timesteps:

Code:
sat->GetGlobalVel(vel);
VECTOR3 dvel = (vel - lastGlobalVel) / simdt;
lastGlobalVel = vel;
This is only the few lines of code concerning the velocity. The problem is "dvel" seems to have a kind of oscillation in Orbiter 2016. It's not a steady change as in Orbiter 2010 and when the global velocity is changing a lot, like in Earth orbit, then this oscillation is severe enough to cause us some issues. Somewhere in cislunar space the global velocity doesn't change all that much per timestep and the effect is much weaker.

The code above is called in clbkPostStep and the "simdt" is from that function. Is simdt maybe not the exact time difference between the two velocities? In that case an oscillating framerate between e.g. 59.9 fps and 60.1 fps could already cause the issues.

The overall acceleration measurement seems to be fine. So the velocity change during a time period of let's say a minute is not really affected by the oscillation. But a few spacecraft systems have problems when there isn't a steadily measured acceleration.
indy91 is online now   Reply With Quote
Old 02-28-2017, 09:59 PM   #2
jarmonik
Beta Tester

Default

I had the same code used in IMFD to evaluate applied thrust in autoburn. It worked fine in 2010-P1 but failed in Orbiter 2016. It just couldn't get the remaining dV low enough and kept the vessel rotating aimlessly. Then I replaced the code with this one from LTMFD and it seems to be working fine. But why the original code failed in 2016 ? I have no idea.

PHP Code:
    theVessel->GetThrustVector(_NewThrust);

    
theVessel->GlobalRot(_NewThrust_NewThrust);
    
    
_dVS += (_NewThrust _OldThrust) * SimDT / (OldMass+NewMass); 
jarmonik is offline   Reply With Quote
Thanked by:
Old 02-28-2017, 10:46 PM   #3
indy91
Addon Developer
Default

Thanks for the reply! What you are describing is the same behavior that I have observed. The small acceleration oscillation is enough to confuse our Entry Monitoring System, which needs a steady 0.05G or more for 1 second until it recognizes the 0.05G event. But that doesn't really work until the acceleration is very high, because it will go below 0.05G every other timestep or so, because of this issue.

I have tested your implementation and it seems to work well. Now, the GetThrustVector() won't recognize atmospheric forces, which we also need to measure. But I guess adding GetDragVector() and GetLiftVector() to the force vector could work?

EDIT: No, the weight vector needs to be measured also, because the systems are already used on the launchpad. So simply adding lift, drag and thrust won't work.

Last edited by indy91; 02-28-2017 at 10:49 PM.
indy91 is online now   Reply With Quote
Old 03-01-2017, 03:43 AM   #4
martins
Orbiter Founder
Default

Quote:
Originally Posted by indy91 View Post
 Next to this potential bug in Orbiter 2016 there is another problem with the implementation of accelerometers in NASSP.

Part of the acceleration calculation is taking the global velocity each timestep and use the difference to the previous timestep to get the global velocity difference per second.

First Timestep:

Code:
sat->GetGlobalVel(vel);
lastGlobalVel = vel;
All subsequent timesteps:

Code:
sat->GetGlobalVel(vel);
VECTOR3 dvel = (vel - lastGlobalVel) / simdt;
lastGlobalVel = vel;
This is only the few lines of code concerning the velocity. The problem is "dvel" seems to have a kind of oscillation in Orbiter 2016. It's not a steady change as in Orbiter 2010 and when the global velocity is changing a lot, like in Earth orbit, then this oscillation is severe enough to cause us some issues. Somewhere in cislunar space the global velocity doesn't change all that much per timestep and the effect is much weaker.

The code above is called in clbkPostStep and the "simdt" is from that function. Is simdt maybe not the exact time difference between the two velocities? In that case an oscillating framerate between e.g. 59.9 fps and 60.1 fps could already cause the issues.

The overall acceleration measurement seems to be fine. So the velocity change during a time period of let's say a minute is not really affected by the oscillation. But a few spacecraft systems have problems when there isn't a steadily measured acceleration.
Does the oscillation still happen if you use the previous time interval, i.e.
Code:
// first step
sat->GetGlobalVel(vel);
lastGlobalVel = vel;
last_dt = simdt;

// All subsequent timesteps:

sat->GetGlobalVel(vel);
VECTOR3 dvel = (vel - lastGlobalVel) / last_dt;
lastGlobalVel = vel;
last_dt = simdt;
The thing is that the time step update point is located after the call to clbkPostStep. Let's say, at timestep n, clbkPreStep reports \mathrm{simt} = t_n, \mathrm{simdt} = t_{n+1}-t_n, and a call to GetGlobalVel returns v(t_n).
The subsequent clbkPostStep reports \mathrm{simt} = t_{n+1}, \mathrm{simdt} = t_{n+1}-t_n, and a call to GetGlobalVel still returns v(t_n). So in your code the time interval is one step ahead of the speed difference.

I am aware that this arrangement may be counterintuitive. The alternative would be to move the time synchronisation point ahead of clbkPostStep, such that a call to GetGlobalVel from clbkPostStep returns v(t_{n+1}). But then clbkPostStep is essentially redundant, since it returns the same state as the clbkPreStep in the next frame. The idea of clbkPostStep was essentially to have a hook into the simulation after Orbiter has done its internal update but before the updates have been propagated to the next time step.
martins is offline   Reply With Quote
Thanked by:
Old 03-01-2017, 09:05 AM   #5
indy91
Addon Developer
Default

Yeah, using the simdt from the previous timestep works. Awesome!

But I am not sure I follow your explanation. The global velocity returned by clbkPreStep and clbkPostStep of the same timestep is identical? It looks different in the Orbiter frame update loop figure from the API reference. If the "Render world at state s0" is updating GetGlobalVel, what is then the difference between clbkPreStep and clbkPostStep of the same timestep?

In NASSP we have explicitely been using clbkPostStep to access the updated states. So I guess we need to change a few things there, mostly the accelerometers. I hope using the previous simdt will fix most of these problems. So thanks for your answer!
indy91 is online now   Reply With Quote
Old 03-03-2017, 12:58 PM   #6
martins
Orbiter Founder
Default

You are right, the behaviour doesn't correspond to that schematic. I remember that I fiddled around with the callback sequence quite a bit at some point, and that I settled on the current behaviour for some compelling reason which completely eludes me now

In some sense the documented behaviour seems more logical. I might see if I can go back to that (or at least remind myself why I changed it). In the worst case I could introduce a third per-frame callback function after the synchronisation point.
martins is offline   Reply With Quote
Thanked by:
Old 03-03-2017, 01:11 PM   #7
indy91
Addon Developer
Default

Quote:
Originally Posted by martins View Post
 In the worst case I could introduce a third per-frame callback function after the synchronisation point.
Yeah, I thought about that, too. clbkMidStep or something like that and then clbkPostStep could have the old behavior.

But our accelerometers work good again now, except on the launchpad. There this problem is occuring: http://orbiter-forum.com/project.php?issueid=1318 And once that isn't an issue anymore there aren't many obstacles for NASSP to run pretty well in Orbiter 2016. Just staging can't be in clbkPostStep anymore, if I have been reading some of the posts here correctly. Anyway, thanks again for the help!
indy91 is online now   Reply With Quote
Old 03-03-2017, 04:10 PM   #8
martins
Orbiter Founder
Default

Ok, I think I more or less remember the reason behind this change now.

In a nutshell, it was to allow vessel state "Set" functions to be executed in clbkPostStep without introducing race conditions.

Let me explain:

Each vessel maintains its current state. This state is updated for all vessels simultaneously at the synchronisation point. Importantly, this is the _only_ point where this public state changes. Otherwise, the state should be considered read-only.

Prior to the synchronisation point, each vessel updates its state (applies forces, propagates the state across the current time step), by making a copy of its public state, and operating on this copy. This "update state" is where all "Set" operations should be directed at. This copy is created just before clbkPreStep, and it is merged back at the synchronisation point just after clbkPostStep.

If clbkPostStep was moved past the synchronisation point, any "Set" type API calls would operate on the public state, and thus introduce race conditions:
Let's say vessel A modifies its state in clbkPostStep (e.g. SetGlobalPos). Vessel B, in its own clbkPostStep, queries vessel A's state and does something based on that. This means that the state received by vessel B depends on the order in which orbiter calls the vessels' clbkPostStep function, hence a race condition. This would negate the whole rationale of the synchronisation point, where the entire simulation state is updated at once.

If I were to move clbkPostStep back past the synchronisation point (or add a new callback function there), no Set functions would be allowed to be called from there.

It should also be noted that each vessel's update state is private. No vessel should have access to another vessel's update state, again to prevent race conditions. (Ultimately, all vessel updates should be able to be executed in parallel on separate threads without inter-vessel communication).

Note that this strict separation between public "current" state and private "update" state is not completely enforced yet. There are numerous vessel callback functions taking place outside the vessel update phase, and orbiter doesn't yet prevent state changes in those functions. But clbkPreStep and clbkPostStep are the most critical.

Does this make sense? Please feel free to discuss this. Suggestions welcome!
martins is offline   Reply With Quote
Thanked by:
Old 03-03-2017, 04:47 PM   #9
Face
Beta Tester
 
Face's Avatar

Default

Synchronization makes a ton of sense, yes. I remember having many issues in OMP when using DefSetStateEx based on GetStatusEx willy-nilly in the receiver thread of clients. Random CTDs, jittering etc.

To compensate I've sent the state-vectors of all vessels in the scenario together with time-stamps to a cache on PostStep, so I have a global snapshot of each vessel that is kind of thread-safe. I've also experimented with double-buffering to implement the setter direction, but to my surprise it didn't matter whether it was there or not. I guess now I know why .
Face is offline   Reply With Quote
Reply

  Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK


Thread Tools

Posting Rules
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
Forum Jump


All times are GMT. The time now is 09:32 AM.

Quick Links Need Help?


About Us | Rules & Guidelines | TOS Policy | Privacy Policy

Orbiter-Forum is hosted at Orbithangar.com
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.
Copyright 2007 - 2017, Orbiter-Forum.com. All rights reserved.