Recording flights: aircraft variables - or events (example: flap position)?

Dear all,

This is more a design question - or “how to best use the SimConnect API” - rather than a specific question for some specific function.

I intend to record the flight (for playback). I receive the aircraft position (longitude, latitude, altitude) and attitude (pitch, bank, roll) “whenever data has changed”, naturally as simulation variables (with SimConnect_RequestDataOnSimObject(…, ::SIMCONNECT_DATA_REQUEST_FLAG_CHANGED).

That works well, as all of those variables are expected to change most of the time (whenever the aircraft is moving).

Now I understand I could record the aircraft main controls (flaps, rudder, ailerons, …) in the same way, as simulation variables.

But could we do better? Most of those variables (specifically flaps) are expected to change only rarely (compared to the entire flight), so I could also capture the events.

The SimConnect SDK example provides an example for receiving “brakes” events:

hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_BRAKES, "brakes");

So instead of constantly recording whether “brakes” (or in our example: “flap position”) are set or not (via the corresponding simulation variables) we could simply record the actual events, and during playback simply send the events (question to myself: with SimConnect_TransmitClientEvent?).

Advantage: minimisation of data that both needs to be stored and transmitted

Disadvantage:

  • for events that happen “frequently” (e.g. yoke position) sending events on top of the simulation variables might actually increase the traffic between client and FS 2020 (at least as far as the amount of request messages is concerned) → solution: record those events which happen frequently (e.g. for the yoke) as simulation variables instead
  • Added complexity when randomly selecting the “replay position”: the latest events that have happened just prior to the current timestamp need to be found and sent, in order to restore “the current state of the aircraft” → solution: a bit of algorithmic wizardry :wink:
  • Specifically for affecting the “flap position” there might be several events which affect it, e.g.
    • KEY_FLAPS_UP
    • KEY_FLAPS_1 … KEY_FLAPS_3
    • KEY_FLAPS_DOWN
    • (And possibly more events)
      so we would need to identify and record/playback all of those events (and we still might miss “custom events” that some hardware controllers might be using to alter the flap position → solution: try and error :confused:

Any other disadvantages of recording / sending events instead of simulation variables? Or is it simply not worth the effort?

Oh, and the use case here is merely that “it looks good”, that is, that when the aircraft is “played back” that it “visually behaves” just as the recorded one, so same flap/ailerons/rudder/gear/… positions. There is no need to “analyse the flight” (as in “when exactly were the flaps lowered” etc.)

Any thoughts or even experience to share here? :slight_smile:

Another way (and much simpler way) to do this is just nullify unchanged values, and you can simply ignore null during saving/transmitting. Basically a very simplified compression.

The largest problem with event are their wide variety of behaviors (e.g. set to an input value with or without internal mapping, set to a specific value, increase/decrease by 1/10, etc.) making converting from variable observations to events (or back) very difficult for replay purposes.

However, you’ll ended up with a mix regardless because there are unsettable SimConnect variables (so you must use event), and settable variables without corresponding Set event.

I have tackled some of those (including those you listed) in my free replay tool, if you want to have a look:

2 Likes

Hello,

The idea is clear, but how did you implement that? In your code I see that you seem to send the entire AircraftPosition record, in Connector.cs:

    public void Set(AircraftPositionSetStruct position)
    {
        simconnect.SetDataOnSimObject(DEFINITIONS.AircraftPositionSet, 0, SIMCONNECT_DATA_SET_FLAG.DEFAULT, position);
    }

(Just like I do currently, for that matter). I also noticed that you seem to - somehow - dynamically create (“generate”, e.g. in your ModelGenerator.cs) your request record (in ConnectorGenerator.cs), based on your annotated Structs.cs (annotated with the “SimConnectVariableAttribute”).

What I do not yet understand is wheter you have some logic to include/exclude simulation variables that have changed or not (“nullified”), and if so, whether you then dynamically register each combination of variables to be sent with SimConnect - but I just noticed that this would not work, as the number of combinations, given n variables, would be, uh n! (“n factorial”)? I don’t think you can even register that many request data structures with SimConnect.

So how exactly do you “prevent sending nullified variables”? Or are you even saying that the SimConnect client library itself “compresses” the outgoing request, by not sending NULL values?

I do understand how you send events, you only send them if the value has actually changed (or “different from the expected value”), in your TriggerEvents (generated in ConnectorGenerators.cs).

By the way I already noticed your announcement and project earlier. In fact, I made a reference to your project from mine already :wink:

GitHub - till213/SkyDolly: Sky Dolly connects with Flight Simulator 2020 and records the flight path and basic instruments for replay.

Under “Related Projects”. And I already… uh… copied one of your ideas, namely to “freeze” the latitute, longitude and altitude values during playback (because I noticed the same “micro-movements”, the simulation trying to “fight” my requested position values etc., especially when setting low sample/replay rates).

On the other hand you may want to have a look at my SkyMath.h (https://github.com/till213/SkyDolly/blob/main/src/Kernel/src/SkyMath.h) source, specifically with regards to “modulo 180|360” calculations related to interpolation. I actually tested your application quickly and noticed that during airplay your aircraft does a quick “visual glitch” whenever a 180 / 360 degree boundary is “crossed” (so e.g. heading from 359 to 0 - of course that is just a 1 degree difference, and not 359 degrees).

And I no Hermite cubic interpolation, not just linear (as I remember you do in your code). So feel free to “copy back” :wink:

Cheers

Yah haha I know that. Was just too busy to cramp everything in the first releases.

Ah when I talking about this, I was thinking about what you do after you get the data from SimConnect (e.g. storing the data), not about the communication between the tool and SimConnect. It’s like video codec where you can do all kind of compression on storage but still have to regenerate the full resolution on replay.
SimConnect is surprisingly fast if you bundle all your variables in a single request. Splitting into multiple request/definition is only needed if you have a crazy number of variables.

Ah, okay then. I was asking about the actual communication between client and server (= FS 2020), how to be able to minimise the traffic (while keeping the number of required messages to a minimum).

Yes, for simplicity I put all simulation variables into one record and send a single request message each time, including position, aircraft attitude and basic flight controls; mostly those which have the “greatest visual effect” (e.g. moving ailerons).

Just like you I noticed that some variables cannot be set, for one reason or another. Notably “lights” seem to be impossible to set via “setters” on the corresponding simulation variables: they are “read-only”, according to:

https://docs.flightsimulator.com/html/Programming_Tools/SimVars/Aircraft_Simulation_Variables.htm

No idea what the reasoning was (is) behind this: maybe “lights” were added “at a different implementaiton time” when setting variables was not foreseen? Who knows… anyway, sending events instead should work (and I saw in your code that you do exactly that).

Maybe in the future I will still define two distinct request records: one for the simulation variables mentioned above (positon, flight controls which are expected to change reasonably frequently), and “rarely used flight controls”, specifically the gear (" GEAR HANDLE POSITION"): the later group would then be sampled at a lower interval (1 second instead of each frame) and requested only once a second or so, too (if during the replay the gear lowers with a delay of a second then this might be acceptable).

But not sure yet whether that is worth the effort, for now I put every “settable” simulation variable into one record.

Thank you for your insights!