Sign in to follow this  
Guest bartels

Couple of questions regarding controlling update rate

Recommended Posts

How often are macro callbacks happening? 18 times/second?For example, if you use a MAKE_ICON macro and callback for it, how often is that callback running?I know the gauges callback is updating and drawing 18 times per second, so if one wants to go easy on frame rates and say only check for changes once per second what is generally the best way to approach this?I am guessing (partly from memory of previous readings) that one would use the main gauge callback to update a counter, and use that to determine if you are going to perform some action. Maybe in a multi-gauge environment, use one gauge to update various variables for the others to use in such tests.Does it increase performance to avoid using a gauge callback, and doing everything in the macro's callback, or perhaps a mouse callback?What have you discovered?Thanks for your thoughts.

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

The proverbial answer is: it depends. The standard rate for "regular" fired events is about 18 times per second.Some callbacks are triggered - you mention mouse as an example. You can also have callbacks that are not FS driven (keyboard or directX hooks for example).Not all events are fired all the time either, and the order fired can sometimes be interesting as well. Most of it is trial an error but this can be a source of insidious bugs.Some events fire once, when you need them to fire multiple times.I've found that if you intend to have something happen at a known regular interval, don't rely on the FS callbacks at all. Instead, setup a timer using the win32 API and trigger on that. You use the FS trigger event to setup the timer, and once this is setup, you're on your own little thread. You can cleanup the timer when FS tells you your window is closed. The only thing to do is to sync up with various FS callbacks when it decides to fire them. This allows you to do the work outside of the FS "framework", which helps a lot with FPS. You can use multiple timers for different update rates as well. Another thing: having your code do something at every callback may not be necessary either. For example, reading a fuel value for display at every callback isn't going to change much from one call to the next. Yet, reading that value with each callback will use CPU cycles and impact the frame rate quite a bit.Painting is the only callback where you have to do something, but in my other post, I stated there are ways you can cache the image too so you only paint the pre-rendered image.Of all the callbacks, I think the paint events are the most consistent, even though they can catch their own tail too. Ancient FS proverb: "don't trust anything to occur in a particular order and use semaphores to block code just in case".EM

Share this post


Link to post
Share on other sites

You wrote:>I've found that if you intend to have something happen at a>known regular interval, don't rely on the FS callbacks at all.> Instead, setup a timer using the win32 API and trigger on>that. You use the FS trigger event to setup the timer, and>once this is setup, you're on your own little thread. So probably create a "hidden" gauge to do timer and out-side the FS framework stuff and in there use this stuff: [DllImport("kernel32")] static extern "C" bool QueryPerformanceFrequency(ref long PerformanceFrequency); [DllImport("kernel32")] static extern "C" bool QueryPerformanceCounter(ref long PerformanceCount);or maybe get fancy and work in .NET 2.0's new stopwatch from SYSTEM.DIAGNOSTICS.>You can>cleanup the timer when FS tells you your window is closed. >The only thing to do is to sync up with various FS callbacks>when it decides to fire them. This allows you to do the work>outside of the FS "framework", which helps a lot with FPS. >You can use multiple timers for different update rates as>well. When you say "snyc up", are you saying have those callbacks pass you stuff? Can you illustrate with a conceptual example?>Another thing: having your code do something at every callback>may not be necessary either. For example, reading a fuel>value for display at every callback isn't going to change much>from one call to the next. Yet, reading that value with each>callback will use CPU cycles and impact the frame rate quite a>bit.So the work-around is to basically do next to nothing in the callbacks, and then have a separate gauge trigger all the real work?Patrick

Share this post


Link to post
Share on other sites

While you could create a hidden gauge to do this or use a separate FS module file placed in the modules folder, but this is not needed. One gauge will likely be a lot simpler.If you create simple timers using the windows 32 API (lookup http://www.codeproject.com/system/timers_intro.asp), you can have a set of routines in your gauge code called by the operating system at a regular intervals of your choosing. You can create the timers in the window open event, and destroy them in the window close event. Different timers can be used for different update rates, completely outside the default 18 cycles FS provides on some events.I like timers like this because it allows my gauge code to update states using my own timing, no matter what FS is doing. I save the state in memory and when the event fires from FS, I just pickup the saved state and do whatever update is needed then (paint a cached image mostly).The Windows API is not one that is referenced often in the gauge code aside perhaps from the GDI+ system, but it is a very rich environment and opens quite a few possibilities for your gauge.EM

Share this post


Link to post
Share on other sites

For completeness: all drawing element callbacks are called at 18Hz. Depending on the return value of these callbacks the FS engine decides on drawing the element. The call of the image element callbacks starts after the gauge callback is called with PANEL_SERVICE_PRE_UPDATE, it starts with the "root" of the image element tree and goes up to the "leaves", after the tree is worked through, the gauge callback is called again with PANEL_SERVICE_POST_UPDATE. Therefore it doesn't make a difference if you use an image callback or the gauge callback. I often use the variable TICK18 to introduce a non 18Hz frequency, but a divider of 18Hz often simply 1Hz (e.g. RadarGauge in C or XML).You can also use timers of course, either start and stop via the gauge callback at PANEL_SERVICE_CONNECT_TO_WINDOW (aircraft loading) and PANEL_SERVICE_DISCONNECT (aircraft unloading) or modify DllMain or module_init() module_deinit() (dll functions) in the ...gauges.h for your purpose.In all cases take care that callback functions are really callbacks, meaning that they return fast enough, since hooking in any callback or timer callback with too long excersizing will stall the complete system effectively. If you plan something really heavy in terms of processing think about threads.Instead of gauges you can also use module dlls in the modules folder. There again you can modify the dll functions to introduce timers/threads (always loaded) or build a XML<->C interface (example code in the library) where you have methods called a specific times in FS (e.g. FS loading,aircraft loading ,panel loading, 18Hz update cycle, draw cycle). Actually it is almost the same as for gauge callbacks, which isn't surprising, we're talking about the gauge engine which isn't too different between XML and C if you have a close look.

Share this post


Link to post
Share on other sites

Yes Arne, last night, I happened to go through your traffic gauge again (I pick up more each time), and noticed again the TICK18 stuff, but this time really saw what it was doing.So, seems like for doing things slower than 18 Hz, this is the way to go, and if there is a need to do things faster than 18 Hz (like maybe an autopilot I suppose) then go with timers.>The call of the image element callbacks starts after the gauge >callback is called with PANEL_SERVICE_PRE_UPDATE, it starts with >the "root" of the image element tree and goes up to the "leaves", >after the tree is worked through, the gauge callback is called >again with PANEL_SERVICE_POST_UPDATE. Therefore it doesn't make a >difference if you use an image callback or the gauge callback.So, the sequence is: gauge callback - PANEL_SERVICE_PRE_UPDATE image element callbacks gauge callback - PANEL_SERVICE_POST_UPDATEExplains the PRE / POST thing.This is all really coming together. Thanks.

Share this post


Link to post
Share on other sites

Ok, almost. You can't get higher with timers on old systems like Win98 and older, the highest frequency for timers then is 18Hz. All NT system and later (XP,2000,...) can go higher in update frequency for timers. But for FS it doesn't pay off, FS even uses a slower update frequency in the background, a lot of the vars for APs (speed,alt,attitude,etc.) are evaluated at an even slower rate around 3-4Hz. You get the effect that a lot of vars are actually constant over a couple of update cycles, extremely annoying if you need time derivates (the D in PID regulators).

Share this post


Link to post
Share on other sites

I see, so we only need to go faster than 18 Hz when we need to do something that is not dependent on FS VARS.So, how do you do something like an AP that makes many adjustments?I see you hint at using a PID. Found this interesting article too: http://www.e.kth.se/~vivek/news.htmlPatrick

Share this post


Link to post
Share on other sites

I use the 18Hz of the gauge callback. If I can't avoid D regulators, I have to work a bit to cirumvent the problems, by doing a bit of exponential averaging (low pass filtering) the D part.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this