├── .gitattributes ├── .gitignore ├── HeadingAPExample ├── HeadingAPExample.cpp ├── HeadingAPExample.vcxproj ├── HeadingAPExample.vcxproj.filters └── SimConnectInterface.h ├── README.md ├── RollFBWExample ├── RollFBWExample.filters ├── RollFBWExample.vcxproj ├── RollFBWExample.vcxproj.filters ├── SimConnectInterface.h └── main.cpp ├── SimConnect_FBW_Examples.sln ├── SimControlToolbox ├── SimControlToolbox.vcxproj └── SimControlToolbox.vcxproj.filters ├── doc └── AllowedRollRatesvsBank.png ├── inc ├── common │ ├── PIDController.h │ ├── siso_blocks.h │ └── util.h └── external │ └── SimConnect.h └── prebuilt_binaries └── roll_example.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | 263 | # The SimConnect.lib library (not sure if allowed to distribute) 264 | SimConnect.lib 265 | -------------------------------------------------------------------------------- /HeadingAPExample/HeadingAPExample.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The project simulates: 3 | * A simple aircraft lateral heading controller 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "external/SimConnect.h" 12 | 13 | #include "common/PIDController.h" 14 | #include "common/util.h" 15 | 16 | #include "SimConnectInterface.h" 17 | 18 | int quit = 0; 19 | HANDLE hSimConnect = NULL; 20 | 21 | /* Struct to hold the current status of all pilot inputs */ 22 | static struct PilotInputs { 23 | /* joystick axis readings are normalised into the range [-1, 1] */ 24 | double joystickX = 0; /* last known value of joystick's x-axis */ 25 | } pilotInputs; 26 | 27 | /* Actual aircraft status */ 28 | structAircraftPosition aircraft_status; 29 | 30 | /* Selected autopilot heading */ 31 | structAutopilotSelectedHeading ap_selected_heading; 32 | 33 | void setupDatadef() { 34 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_POSITION, "PLANE BANK DEGREES", "Radians")); 35 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_POSITION, "PLANE HEADING DEGREES TRUE", "Radians")); 36 | 37 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AUTOPILOT_SELECTED_HEADING, "AUTOPILOT HEADING LOCK DIR", "Degrees")); 38 | 39 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_ROLL_CONTROL, "AILERON POSITION", "Position")); 40 | } 41 | 42 | void setupInitialDataRequests() { 43 | /* Get position information for every sim frame */ 44 | ASSERT_SC_SUCCESS( 45 | SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AIRCRAFT_POSITION, 46 | DEFINITION_AIRCRAFT_POSITION, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SIM_FRAME, 0) 47 | ); 48 | 49 | /* Get autopilot heading only when it changes */ 50 | ASSERT_SC_SUCCESS( 51 | SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AUTOPILOT_HEADING, 52 | DEFINITION_AUTOPILOT_SELECTED_HEADING, SIMCONNECT_OBJECT_ID_USER, 53 | SIMCONNECT_PERIOD_SIM_FRAME, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED) 54 | ); 55 | 56 | } 57 | 58 | void UpdateControls() { 59 | /* 60 | Use PID control to generate target bank angle based on heading error 61 | */ 62 | 63 | /* Required bank per error in heading */ 64 | const double BANK_PER_DEGREE_HEADING_ERROR = radians(3); 65 | 66 | /* PID Controller for heading: finds target bank angle to achieve set heading, 67 | clamping at 33 degrees to prevent overbank 68 | */ 69 | static ClampedPIDController 70 | headingController(BANK_PER_DEGREE_HEADING_ERROR,0,0,-radians(20),radians(20)); 71 | 72 | /* Error between desired and actual heading */ 73 | double heading_error = ap_selected_heading.heading - degrees(aircraft_status.heading); 74 | 75 | /* Update PID controller */ 76 | double requested_bank = headingController.Update(heading_error, 1); 77 | 78 | /* Dump to screen: uncomment this to see desired roll calculations */ 79 | printf("HEADING: Req: %lf , Act: %lf , Err = %lf, Bank = %lf\n", 80 | ap_selected_heading.heading, degrees(aircraft_status.heading), 81 | heading_error, degrees(requested_bank)); 82 | 83 | /* Required aileron deflection per bank error */ 84 | const double AILERON_DEFL_PER_BANK_ERROR = 0.08 / radians(1); // 0.08 units per degree 85 | 86 | /* 87 | PID Controller for bank angle: bank towards the requested_bank 88 | */ 89 | static ClampedPIDController 90 | bankController(AILERON_DEFL_PER_BANK_ERROR, 0, 0, -1.0, 1.0); 91 | 92 | /* Error between requested and actual bank */ 93 | double bank_error = requested_bank - -aircraft_status.bank_rad; 94 | 95 | /* Update PID controller */ 96 | double aileron_defl = bankController.Update(bank_error, 1); 97 | 98 | /* Update FSX */ 99 | structAircraftRollControl rollControlSettings; 100 | rollControlSettings.aileronDeflect = aileron_defl; 101 | ASSERT_SC_SUCCESS( 102 | SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_AIRCRAFT_ROLL_CONTROL, 103 | SIMCONNECT_OBJECT_ID_USER, 0, 1, sizeof(rollControlSettings), &rollControlSettings)); 104 | 105 | /* Dump to screen: uncomment this to see aileron control calculations */ 106 | //printf("BANK: Req: %lf , Act: %lf , Err = %lf, Bank = %lf\n", 107 | // requested_bank, aircraft_status.bank_rad, bank_error, aileron_defl); 108 | } 109 | 110 | void CALLBACK SC_Dispatch_Handler(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext) 111 | { 112 | switch (pData->dwID) 113 | { 114 | case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: 115 | { 116 | SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = reinterpret_cast(pData); 117 | 118 | // Position data: 119 | if (pObjData->dwRequestID == REQUEST_AIRCRAFT_POSITION) { 120 | // update aircraft status struct 121 | aircraft_status = 122 | *reinterpret_cast(&pObjData->dwData); 123 | 124 | UpdateControls(); 125 | } 126 | // Autopilot settings 127 | else if (pObjData->dwDefineID == REQUEST_AUTOPILOT_HEADING) { 128 | // update autopilot heading struct 129 | ap_selected_heading = 130 | *reinterpret_cast(&pObjData->dwData); 131 | printf("New autopilot heading: %lf\n", ap_selected_heading.heading); 132 | } 133 | 134 | break; 135 | } 136 | case SIMCONNECT_RECV_ID_EVENT: 137 | { 138 | SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData; 139 | 140 | switch (evt->uEventID) 141 | { 142 | 143 | case EVENT_SIM_START: 144 | { 145 | } 146 | break; 147 | case EVENT_XAXIS: 148 | { 149 | /* raw data is unsigned, so need to convert to signed before double */ 150 | long int joystickIn = evt->dwData; 151 | pilotInputs.joystickX = static_cast(joystickIn) / 32768; 152 | } 153 | break; 154 | default: 155 | break; 156 | } 157 | break; 158 | } 159 | 160 | case SIMCONNECT_RECV_ID_QUIT: 161 | { 162 | quit = 1; 163 | break; 164 | } 165 | 166 | default: 167 | printf("\nReceived:%d", pData->dwID); 168 | break; 169 | } 170 | } 171 | 172 | void runHeadingControl() 173 | { 174 | // Establish connected to FSX 175 | while (SimConnect_Open(&hSimConnect, "Heading Autopilot", NULL, 0, 0, 0) != S_OK); 176 | 177 | printf("Connected...\b"); 178 | 179 | // Setup data definitons 180 | setupDatadef(); 181 | 182 | // Setup regular requests 183 | setupInitialDataRequests(); 184 | 185 | // Main loop 186 | while (0 == quit) { 187 | SimConnect_CallDispatch(hSimConnect, SC_Dispatch_Handler, NULL); 188 | } 189 | 190 | SimConnect_Close(hSimConnect); 191 | } 192 | 193 | int main(int argc, _TCHAR* argv[]) 194 | { 195 | runHeadingControl(); 196 | 197 | return 0; 198 | } -------------------------------------------------------------------------------- /HeadingAPExample/HeadingAPExample.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {DFA782D0-94C3-459E-A40D-49E3E1321E31} 24 | Win32Proj 25 | HeadingAPExample 26 | 10.0.15063.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | ../inc 93 | 94 | 95 | Console 96 | true 97 | SimConnect.lib %(AdditionalOptions) 98 | 99 | 100 | 101 | 102 | Use 103 | Level3 104 | Disabled 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Use 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Use 133 | Level3 134 | MaxSpeed 135 | true 136 | true 137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 138 | true 139 | 140 | 141 | Console 142 | true 143 | true 144 | true 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /HeadingAPExample/HeadingAPExample.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /HeadingAPExample/SimConnectInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMCONNECTINTERFACE_H 2 | #define SIMCONNECTINTERFACE_H 3 | 4 | /* This file contains all required enums, constants and structures required to 5 | exchange data with FS through the SimConnect interface. 6 | */ 7 | 8 | /* FSX Simulation phyiscs frames rate per second: this is actually variable 9 | but we don't currently make use of it. 10 | */ 11 | const double SIM_UPDATE_RATE = 30; 12 | 13 | /* Input Group IDs */ 14 | enum GROUP_ID { 15 | GROUP_0, 16 | }; 17 | 18 | enum INPUT_ID { 19 | INPUT_XAXIS, 20 | }; 21 | 22 | enum EVENT_ID { 23 | EVENT_SIM_START, 24 | EVENT_XAXIS, 25 | }; 26 | 27 | enum REQUEST_ID { 28 | REQUEST_AIRCRAFT_POSITION, 29 | REQUEST_AUTOPILOT_HEADING, 30 | }; 31 | 32 | /* Structure Definition ID's */ 33 | enum DATA_DEFINE_ID { 34 | DEFINITION_AIRCRAFT_POSITION, 35 | DEFINITION_AUTOPILOT_SELECTED_HEADING, 36 | DEFINITION_AIRCRAFT_ROLL_CONTROL, 37 | }; 38 | 39 | /* Start of Structure Definitions */ 40 | 41 | /* Struct used to get position from simulator */ 42 | struct structAircraftPosition { 43 | double bank_rad; // bank angle in radians 44 | double heading; // true aircraft heading in radians 45 | }; 46 | 47 | /* Struct used to get the heading from the autopilot panel */ 48 | struct structAutopilotSelectedHeading { 49 | double heading; // set heading in degrees 50 | }; 51 | 52 | /* Struct used to send controls to the simulator */ 53 | struct structAircraftRollControl { 54 | double aileronDeflect = 0; 55 | }; 56 | 57 | #endif 58 | 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimConnect_Examples 2 | 3 | This repository contains different examples of using the SimConnect API to control Microsoft Flight Simulator X (FSX) externally. 4 | 5 | Currently, there are two examples: 6 | 7 | ## Fly-By-Wire Roll 8 | 9 | Virtually all modern commercial airlines have a fly-by-wire based control system. This means that movement of the pilot's controls are processed electronically before the control surfaces are driven. 10 | 11 | The example given in this repository is an Airbus-style Fly-By-Wire control for the roll. In traditional aircraft, the ailerons are connected directly to the yoke. In an Airbus, however, the pilot flies the plane using a joystick. Under normal conditions, sideways deflection of the joystick commands a constant roll rate, irrespective of airspeed and configuration. The bank angle is also limited: letting go of the sidestick beyond 33 degrees bank will cause the aircraft to reduce it's bank angle to 33 degrees, and it is impossible to bank more than 67 degrees. 12 | 13 | See http://www.airbusdriver.net/airbus_fltlaws.htm for a description of the Airbus control laws. 14 | 15 | Files: 16 | * `main.cpp` - Main entry point. Majority of control processing is carried out here, as well as direct interfacing with SimConnect 17 | * `SimConnectInterface.h` - defines all structs, constants and enums used to communicate with SimConnect 18 | * `PIDController.h` - a generic PID controller class 19 | * `util.h` - Provides a set of useful functions and macros 20 | 21 | 22 | ### Example usage 23 | 24 | To see this example in action: 25 | * Start FSX 26 | * Choose the Default B737-800 27 | * Take off and achieve stable flight 28 | * Run roll_example.exe, provided in this repository under `prebuilt_binaries` 29 | * Try moving your joystick left and right. Also try letting go of the joystick and have a look at the response of the aircraft. You may notice that the aircraft seems more responsive than usual. 30 | * Try banking more than 33 degrees and then completely letting go of the joystick. The aircraft will reduce it's bank angle until it is 33 degrees. 31 | * Try to bank to greater than 67 degrees. You will notice that the roll rate decreases very quickly despite constant side-stick pressure around 60 degrees of bank - this is to prevent the aircraft from exceeding the 67 degree limit. 32 | 33 | ### How to build 34 | 35 | In order to build, you will require the SimConnect SDK. Copy the file `SimConnect.lib` from the SDK into the this directory, and make sure that `SimConnect.lib` is specified in Project Properties > Linker > Command Line > Additional Options. 36 | 37 | 38 | ### Description of control algorithm 39 | 40 | The control algorithm is heavily commented inside the source code. Have a look at the *`CalculateDesiredRollRate`* and *`UpdateControls`* functions inside `main.cpp`. 41 | 42 | ![Graph of roll rate behaviour](https://github.com/NicholasLindsay/SimConnect_Examples/blob/master/doc/AllowedRollRatesvsBank.png "Allowed Roll Rate vs Bank Angle") 43 | 44 | Brief description: 45 | 46 | The position of the joystick commands a roll rate directly proportional to the joystick's displacement. If the bank angle of the aircraft is less than 33 degrees, this roll rate is the setpoint for the PID controller. Otherwise: 47 | * If the bank angle is greater than 67 degrees, the FBW system commands a high rotation rate in the opposite direction to the bank angle 48 | * If the bank angle is between 60 and 67 degrees, the FBW system clamps the requested rotation rate if it is acting to increase the bank angle 49 | * If the bank angle is between 33 and 60 degrees, and the joystick is neutral in the roll axis, the FBW systems commands a rotation rate acting in the opposite direction to the bank angle 50 | 51 | See the above graph for a plot of allowed rotation rates vs bank angle. 52 | 53 | A PID controller is used to match the aircrafts actuall roll rate to the desired value. The input to the PID controller is the difference between the desired and actual rotation rate, and the output of the PID control is a number is the required deflection of the ailerons. 54 | 55 | By default, the dynamics of the aileron servos are not simulated and therefor the required deflection is immedietely reflected in the output. In reality, the aileron servos have a first order response with a typical time constant of 0.1s. Uncomment the indicated lines in the code to enable the simulation of this response. 56 | 57 | ### Limitations 58 | 59 | This is a simple and incomplete example. The FBW roll system does not function correctly under conditions of extreme pitch, yaw or speed. The control surfaces sometimes move instantaneously instead of gradually (this can be solved by enabling the aileron response in the code). The program is only tuned for the default Boeing 737-800. Nonetheless it is a useful proof-of-concept. 60 | 61 | ## Lateral autopilot 62 | 63 | This is an example of a simple nested PID control algorithm for the aircraft's heading. 64 | 65 | See code for documentation. 66 | 67 | *TODO: Improve documentation here * 68 | 69 | -------------------------------------------------------------------------------- /RollFBWExample/RollFBWExample.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /RollFBWExample/RollFBWExample.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9} 24 | Win32Proj 25 | AirbusControlLaw 26 | 10.0.15063.0 27 | RollFBWExample 28 | 29 | 30 | 31 | Application 32 | true 33 | v141 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v141 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v141 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v141 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | false 85 | 86 | 87 | 88 | NotUsing 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | ../inc;%(AdditionalIncludeDirectories) 94 | 95 | 96 | Console 97 | true 98 | SimConnect.lib %(AdditionalOptions) 99 | 100 | 101 | 102 | 103 | Use 104 | Level3 105 | Disabled 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | 109 | 110 | Console 111 | true 112 | 113 | 114 | 115 | 116 | Use 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | Use 134 | Level3 135 | MaxSpeed 136 | true 137 | true 138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | 141 | 142 | Console 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /RollFBWExample/RollFBWExample.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Header Files 6 | 7 | 8 | 9 | 10 | {3fed4a38-a2ab-4eb2-8cca-57554abc89b3} 11 | 12 | 13 | {0bba28bf-101c-401a-8f9a-6c9210a201e0} 14 | 15 | 16 | 17 | 18 | Source Files 19 | 20 | 21 | -------------------------------------------------------------------------------- /RollFBWExample/SimConnectInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMCONNECTINTERFACE_H 2 | #define SIMCONNECTINTERFACE_H 3 | 4 | /* This file contains all required enums, constants and structures required to 5 | exchange data with FS through the SimConnect interface. 6 | */ 7 | 8 | /* FSX Simulation phyiscs frames rate per second: this is actually variable 9 | but we don't currently make use of it. 10 | */ 11 | const double SIM_UPDATE_RATE = 30; 12 | 13 | /* Input Group IDs */ 14 | enum GROUP_ID { 15 | GROUP_0, 16 | }; 17 | 18 | enum INPUT_ID { 19 | INPUT_XAXIS, 20 | }; 21 | 22 | enum EVENT_ID { 23 | EVENT_SIM_START, 24 | EVENT_XAXIS, 25 | }; 26 | 27 | enum REQUEST_ID { 28 | REQUEST_AIRCRAFT_POSITION, 29 | }; 30 | 31 | /* Structure Definition ID's */ 32 | enum DATA_DEFINE_ID { 33 | DEFINITION_AIRCRAFT_POSITION, 34 | DEFINITION_AIRCRAFT_ROLL_CONTROL, 35 | }; 36 | 37 | /* Start of Structure Definitions */ 38 | 39 | /* Struct used to get position from simulator */ 40 | struct structAircraftPosition { 41 | double bank_rad; // bank angle in radians 42 | double rotation_vel_x_rad_s; // roll rate in radians/second 43 | }; 44 | 45 | /* Struct used to send controls to the simulator */ 46 | struct structAircraftRollControl { 47 | double aileronDeflect = 0; 48 | }; 49 | 50 | #endif 51 | 52 | 53 | -------------------------------------------------------------------------------- /RollFBWExample/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Airbus aircraft are controlled by so-called "control laws" when operating 3 | in standard flight. This means that under normal conditions inputs to the 4 | joystick do not correspond directly to deflections of the control surfaces. 5 | 6 | This project simulates: 7 | * Horizontal side-stick corresponds directly to roll angle 8 | * Bank angle protection mechanisms 9 | 10 | See http://www.airbusdriver.net/airbus_fltlaws.htm for overview of Airbus 11 | control laws. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "external/SimConnect.h" 20 | 21 | #include "common/PIDController.h" 22 | #include "common/util.h" 23 | 24 | #include "SimConnectInterface.h" 25 | 26 | int quit = 0; 27 | HANDLE hSimConnect = NULL; 28 | 29 | /* Struct to hold the current status of all pilot inputs */ 30 | static struct PilotInputs { 31 | /* joystick axis readings are normalised into the range [-1, 1] */ 32 | double joystickX = 0; /* last known value of joystick's x-axis */ 33 | } pilotInputs; 34 | 35 | /* Actual aircraft status */ 36 | structAircraftPosition aircraft_status; 37 | 38 | void setupEvents() 39 | { 40 | // Set up private events 41 | ASSERT_SC_SUCCESS(SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_XAXIS)); 42 | 43 | // Add private events to notification group (don't mask for now) 44 | ASSERT_SC_SUCCESS(SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_0, EVENT_XAXIS)); 45 | 46 | // Set highest priority so we recieve event before ESP 47 | ASSERT_SC_SUCCESS(SimConnect_SetNotificationGroupPriority(hSimConnect, GROUP_0, SIMCONNECT_GROUP_PRIORITY_HIGHEST)); 48 | 49 | // Map joystick event to this 50 | ASSERT_SC_SUCCESS(SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT_XAXIS, "joystick:0:XAxis", EVENT_XAXIS)); 51 | 52 | // Turn joystick events on 53 | ASSERT_SC_SUCCESS(SimConnect_SetInputGroupState(hSimConnect, INPUT_XAXIS, SIMCONNECT_STATE_ON)); 54 | } 55 | 56 | void setupDatadef() { 57 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_POSITION, "PLANE BANK DEGREES", "Radians")); 58 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_POSITION, "ROTATION VELOCITY BODY X", "Radians per second")); 59 | 60 | ASSERT_SC_SUCCESS(SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_AIRCRAFT_ROLL_CONTROL, "AILERON POSITION", "Position")); 61 | } 62 | 63 | void setupInitialDataRequests() { 64 | /* Get position information for every sim frame */ 65 | ASSERT_SC_SUCCESS( 66 | SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AIRCRAFT_POSITION, 67 | DEFINITION_AIRCRAFT_POSITION, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SIM_FRAME, 0) 68 | ); 69 | } 70 | 71 | /* 72 | Computes the desired roll rate, including applying protection 73 | */ 74 | 75 | double CalculateDesiredRollRate(double joystick_input) { 76 | /* Relationship between requested roll rate and joystick input */ 77 | const double RAD_S_PER_UNIT_DEFLECTION = 0.15; 78 | const double& MAX_REQUESTABLE_ROLL_RATE = RAD_S_PER_UNIT_DEFLECTION; 79 | 80 | double desired_roll_rate_rad_s = RAD_S_PER_UNIT_DEFLECTION * joystick_input; 81 | 82 | /* 83 | Apply roll protection here: if bank angle greater than 33 degrees, and no 84 | pressure on sidestick, request roll rate until bank angle is 33 degrees or 85 | less. Always prevent bank angle exceeding 67 degrees. 86 | */ 87 | 88 | /* The roll rate to command when roll protection activates */ 89 | const double RESTORING_ROLL_RATE = radians(5); // per second 90 | 91 | /* The bank angle at which clamping begins to prevent overbank */ 92 | const double BANK_CLAMPING_ANGLE = radians(60); 93 | 94 | /* The maximum bank angle allowed */ 95 | const double MAX_BANK_ANGLE = radians(67); 96 | 97 | /* The nominal bank angle: the usual bank angle for turns */ 98 | const double NOMINAL_BANK_ANGLE = radians(33); 99 | 100 | /* true if aircraft is rolling in direction of bank */ 101 | bool isRollingBankDir = (sign(aircraft_status.bank_rad) == -sign(desired_roll_rate_rad_s)); 102 | 103 | /* maximum bank angle is 67 degrees. to enforce this, aggressively reduce 104 | requested roll rate as 67 degrees is approached. 105 | */ 106 | if (abs(aircraft_status.bank_rad) >= MAX_BANK_ANGLE) { 107 | desired_roll_rate_rad_s = RESTORING_ROLL_RATE * sign(aircraft_status.bank_rad); 108 | } 109 | else if (abs(aircraft_status.bank_rad) > BANK_CLAMPING_ANGLE && isRollingBankDir && joystick_input != 0) { 110 | /* linearly reduce maximum allowable roll rate as maximum bank angle is approached */ 111 | double max_roll_rate = MAX_REQUESTABLE_ROLL_RATE + 112 | (abs(aircraft_status.bank_rad) - BANK_CLAMPING_ANGLE) * 113 | (0 - MAX_REQUESTABLE_ROLL_RATE) / (MAX_BANK_ANGLE - BANK_CLAMPING_ANGLE); 114 | 115 | /* clamp pre-computed desired_roll_rate to this value */ 116 | if (abs(desired_roll_rate_rad_s) > max_roll_rate) { 117 | desired_roll_rate_rad_s = max_roll_rate * sign(desired_roll_rate_rad_s); 118 | } 119 | } 120 | /* if no joystick input, restore aircraft to NOMINAL_BANK_ANGLE */ 121 | else if (abs(aircraft_status.bank_rad) > NOMINAL_BANK_ANGLE && joystick_input == 0) { 122 | desired_roll_rate_rad_s = RESTORING_ROLL_RATE * sign(aircraft_status.bank_rad); 123 | } 124 | 125 | return desired_roll_rate_rad_s; 126 | } 127 | 128 | void UpdateControls() { 129 | /* Relculate desired roll rate from joystick input and protections */ 130 | double desired_roll_rate = CalculateDesiredRollRate(pilotInputs.joystickX); 131 | 132 | /* Use a P-only controller for roll rate */ 133 | const double AILERON_DEFL_PER_RAD_S_ERROR = 10; 134 | static PIDController roll_rate_controller(AILERON_DEFL_PER_RAD_S_ERROR, 0, 0); 135 | auto output = roll_rate_controller.Update( 136 | desired_roll_rate - aircraft_status.rotation_vel_x_rad_s, SIM_UPDATE_RATE); 137 | 138 | /* Manually clamp controller output */ 139 | if (output > 1) { 140 | output = 1; 141 | } 142 | else if (output < -1) { 143 | output = -1; 144 | } 145 | 146 | /* Uncomment these lines to add a first order response to the ailerons. The 147 | selected time constant of 0.1s is typical for flight control surfaces. 148 | */ 149 | // static FirstOrderResponseBlock aileronResponse(0.1, 1); 150 | // output = aileronResponse.Update(output, 0.025); 151 | 152 | /* Send output to FSX */ 153 | structAircraftRollControl rollControlSettings; 154 | rollControlSettings.aileronDeflect = output; 155 | ASSERT_SC_SUCCESS( 156 | SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_AIRCRAFT_ROLL_CONTROL, 157 | SIMCONNECT_OBJECT_ID_USER, 0, 1, sizeof(rollControlSettings), &rollControlSettings)); 158 | } 159 | 160 | void CALLBACK SC_Dispatch_Handler(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext) 161 | { 162 | switch (pData->dwID) 163 | { 164 | case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: 165 | { 166 | SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = reinterpret_cast(pData); 167 | 168 | // Position data: 169 | if (pObjData->dwRequestID == REQUEST_AIRCRAFT_POSITION) { 170 | // update aircraft status struct 171 | aircraft_status = 172 | *reinterpret_cast(&pObjData->dwData); 173 | 174 | UpdateControls(); 175 | } 176 | 177 | break; 178 | } 179 | case SIMCONNECT_RECV_ID_EVENT: 180 | { 181 | SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData; 182 | 183 | switch (evt->uEventID) 184 | { 185 | 186 | case EVENT_SIM_START: 187 | { 188 | } 189 | break; 190 | case EVENT_XAXIS: 191 | { 192 | /* raw data is unsigned, so need to convert to signed before double */ 193 | long int joystickIn = evt->dwData; 194 | pilotInputs.joystickX = static_cast(joystickIn) / 32768; 195 | } 196 | break; 197 | default: 198 | break; 199 | } 200 | break; 201 | } 202 | 203 | case SIMCONNECT_RECV_ID_QUIT: 204 | { 205 | quit = 1; 206 | break; 207 | } 208 | 209 | default: 210 | printf("\nReceived:%d", pData->dwID); 211 | break; 212 | } 213 | } 214 | 215 | void runFBW() 216 | { 217 | // Establish connected to FSX 218 | while (SimConnect_Open(&hSimConnect, "Airbus Roll Control Law", NULL, 0, 0, 0) != S_OK); 219 | 220 | printf("Connected...\b"); 221 | 222 | // Setup events 223 | setupEvents(); 224 | 225 | // Setup data definitons 226 | setupDatadef(); 227 | 228 | // Setup regular requests 229 | setupInitialDataRequests(); 230 | 231 | // Main loop 232 | while (0 == quit) { 233 | SimConnect_CallDispatch(hSimConnect, SC_Dispatch_Handler, NULL); 234 | } 235 | 236 | SimConnect_Close(hSimConnect); 237 | } 238 | 239 | int main(int argc, _TCHAR* argv[]) 240 | { 241 | runFBW(); 242 | 243 | return 0; 244 | } -------------------------------------------------------------------------------- /SimConnect_FBW_Examples.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RollFBWExample", "RollFBWExample\RollFBWExample.vcxproj", "{CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HeadingAPExample", "HeadingAPExample\HeadingAPExample.vcxproj", "{DFA782D0-94C3-459E-A40D-49E3E1321E31}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonHeaders", "SimControlToolbox\SimControlToolbox.vcxproj", "{EA4F3284-F242-4559-9CEC-0CAB6E415601}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Debug|x64.ActiveCfg = Debug|x64 21 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Debug|x64.Build.0 = Debug|x64 22 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Debug|x86.ActiveCfg = Debug|Win32 23 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Debug|x86.Build.0 = Debug|Win32 24 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Release|x64.ActiveCfg = Release|x64 25 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Release|x64.Build.0 = Release|x64 26 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Release|x86.ActiveCfg = Release|Win32 27 | {CD13B049-8F66-4C14-90E3-4B6CB9CC68B9}.Release|x86.Build.0 = Release|Win32 28 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Debug|x64.ActiveCfg = Debug|x64 29 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Debug|x64.Build.0 = Debug|x64 30 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Debug|x86.ActiveCfg = Debug|Win32 31 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Debug|x86.Build.0 = Debug|Win32 32 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Release|x64.ActiveCfg = Release|x64 33 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Release|x64.Build.0 = Release|x64 34 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Release|x86.ActiveCfg = Release|Win32 35 | {DFA782D0-94C3-459E-A40D-49E3E1321E31}.Release|x86.Build.0 = Release|Win32 36 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Debug|x64.ActiveCfg = Debug|x64 37 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Debug|x64.Build.0 = Debug|x64 38 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Debug|x86.ActiveCfg = Debug|Win32 39 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Debug|x86.Build.0 = Debug|Win32 40 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Release|x64.ActiveCfg = Release|x64 41 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Release|x64.Build.0 = Release|x64 42 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Release|x86.ActiveCfg = Release|Win32 43 | {EA4F3284-F242-4559-9CEC-0CAB6E415601}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {8FEB68C7-847A-43D6-8EC5-1FD7B0EA76F5} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /SimControlToolbox/SimControlToolbox.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {EA4F3284-F242-4559-9CEC-0CAB6E415601} 24 | SimControlToolbox 25 | 10.0.15063.0 26 | CommonHeaders 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | MultiByte 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | MultiByte 41 | 42 | 43 | Application 44 | true 45 | v141 46 | MultiByte 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Level3 77 | Disabled 78 | true 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | 87 | 88 | 89 | 90 | Level3 91 | MaxSpeed 92 | true 93 | true 94 | true 95 | 96 | 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | MaxSpeed 105 | true 106 | true 107 | true 108 | 109 | 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /SimControlToolbox/SimControlToolbox.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/AllowedRollRatesvsBank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NicholasLindsay/SimConnect_Examples/65fab68e176d60ceb5168e6f224ad19350194877/doc/AllowedRollRatesvsBank.png -------------------------------------------------------------------------------- /inc/common/PIDController.h: -------------------------------------------------------------------------------- 1 | #ifndef PIDCONTROLLER_H 2 | #define PIDCONTROLLER_H 3 | 4 | #include "common\siso_blocks.h" 5 | 6 | /* 7 | Provides a simple and output clamped PID controller for use in simulations. 8 | */ 9 | 10 | /* Generic PID controller */ 11 | class PIDController : public SISOBlock 12 | { 13 | public: 14 | PIDController(double p_coeff, double d_coeff, double i_coeff) 15 | : p_coeff(p_coeff), d_coeff(d_coeff), i_coeff(i_coeff), last_error(0), error_integral(0) {} 16 | 17 | void SetPCoefficient(double val) { 18 | p_coeff = val; 19 | } 20 | void SetDCoefficient(double val) { 21 | d_coeff = val; 22 | } 23 | void SetICoefficient(double val) { 24 | i_coeff = val; 25 | } 26 | 27 | double GetPCoefficient() const { 28 | return p_coeff; 29 | } 30 | double GetDCoefficient() const { 31 | return d_coeff; 32 | } 33 | double GetICoefficient() const { 34 | return i_coeff; 35 | } 36 | 37 | protected: 38 | /* Internal PID calculation */ 39 | virtual double InternalUpdate(double new_error, double timestep) override { 40 | error_integral += new_error * timestep; 41 | double error_diff = (new_error - last_error) / timestep; 42 | 43 | double p = p_coeff * new_error; 44 | double i = i_coeff * error_integral; 45 | double d = d_coeff * error_diff; 46 | 47 | last_error = new_error; 48 | 49 | return p + i + d; 50 | } 51 | 52 | private: 53 | double p_coeff, d_coeff, i_coeff; 54 | 55 | double last_error; 56 | double error_integral; 57 | }; 58 | 59 | /* PID controller, with clamping */ 60 | class ClampedPIDController : public PIDController 61 | { 62 | public: 63 | ClampedPIDController(double p_coeff, double d_coeff, double i_coeff, double lowClamp, double highClamp) 64 | : PIDController(p_coeff, d_coeff, i_coeff), clampLow(lowClamp), clampHigh(highClamp) {}; 65 | 66 | /* Set the clamping limits */ 67 | void SetClampingLimits(double lower, double higher) { 68 | clampLow = lower; 69 | clampHigh = higher; 70 | } 71 | 72 | /* Return lower clamping limit */ 73 | double GetClampLowLimit() const { 74 | return clampLow; 75 | } 76 | 77 | /* Return higher clamping limit */ 78 | double GetClampHighLimit() const { 79 | return clampHigh; 80 | } 81 | 82 | protected: 83 | /* Update and clamp output */ 84 | virtual double InternalUpdate(double new_error, double timestep) override { 85 | double res = PIDController::InternalUpdate(new_error, timestep); 86 | if (res > clampHigh) { 87 | res = clampHigh; 88 | } 89 | else if (res < clampLow) { 90 | res = clampLow; 91 | } 92 | return res; 93 | } 94 | 95 | private: 96 | double clampLow, clampHigh; 97 | }; 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /inc/common/siso_blocks.h: -------------------------------------------------------------------------------- 1 | #ifndef SISO_BLOCKS_H 2 | #define SISO_BLOCKS_H 3 | 4 | /* 5 | This file contains a set of Single-Input Single-Output (SISO) blocks used for 6 | the simulation and control of systems. 7 | */ 8 | 9 | /* Simulates a Single-Input Single-Output block */ 10 | class SISOBlock 11 | { 12 | public: 13 | SISOBlock(double inital_output = 0) 14 | : last_output(inital_output) {}; 15 | 16 | /* Updates the output based on the input and time */ 17 | double Update(double input, double timestep) { 18 | last_output = InternalUpdate(input, timestep); 19 | return last_output; 20 | } 21 | 22 | /* Returns last computed output */ 23 | double Output() const { 24 | return last_output; 25 | } 26 | protected: 27 | virtual double InternalUpdate(double input, double timestep) = 0; 28 | private: 29 | double last_output; 30 | }; 31 | 32 | /* Simulates a First-Order response of the form a(dy/dt) + by = x */ 33 | class FirstOrderResponseBlock : public SISOBlock 34 | { 35 | public: 36 | FirstOrderResponseBlock(double a, double b) 37 | : a(a), b(b) {}; 38 | protected: 39 | virtual double InternalUpdate(double input, double timestep) { 40 | /* Get last output */ 41 | double y = Output(); 42 | 43 | /* Calculate time derivatives from response formula */ 44 | double ydot = (1 / a) * input - (b / a) * y; 45 | 46 | /* Apply Euler integration */ 47 | y = (1 - (timestep*b) / a) * y + (timestep / a)*input; 48 | 49 | return y; 50 | } 51 | private: 52 | double a, b; 53 | }; 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /inc/common/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | /* util.h defines a set of useful utility functions and macros */ 5 | 6 | #include 7 | 8 | /* macro for checking result of SimConnect operations */ 9 | #define ASSERT_SC_SUCCESS(expr) \ 10 | if (expr != S_OK) { \ 11 | printf("Error, " # expr " did not evaluate OK.\n"); \ 12 | abort(); \ 13 | } 14 | 15 | /* convert degrees to radians */ 16 | constexpr double radians(double degrees) { 17 | return degrees * 0.0174533; 18 | } 19 | 20 | /* convert radians to degrees */ 21 | constexpr double degrees(double rad) { 22 | return rad * 57.2958; 23 | } 24 | 25 | /* returns sign of a value */ 26 | constexpr double sign(double val) { 27 | return (val > 0) ? 1.0 : -1.0; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /inc/external/SimConnect.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2006 by Microsoft, all rights reserved 4 | // 5 | //----------------------------------------------------------------------------- 6 | 7 | #ifndef _SIMCONNECT_H_ 8 | #define _SIMCONNECT_H_ 9 | 10 | #pragma once 11 | 12 | #ifndef SIMCONNECT_H_NOMANIFEST 13 | #if _MSC_FULL_VER >= 140040130 14 | #ifdef _M_IX86 15 | #pragma comment(linker,"/manifestdependency:\"type='win32' " \ 16 | "name='" "Microsoft.FlightSimulator.SimConnect " "' " \ 17 | "version='" "10.0.60905.0" "' " \ 18 | "processorArchitecture='x86' " \ 19 | "publicKeyToken='" "67c7c14424d61b5b" "'\"") 20 | #endif 21 | #endif 22 | #endif //SIMCONNECT_H_NOMANIFEST 23 | 24 | #ifndef DWORD_MAX 25 | #define DWORD_MAX 0xFFFFFFFF 26 | #endif 27 | 28 | #include 29 | 30 | typedef DWORD SIMCONNECT_OBJECT_ID; 31 | 32 | //---------------------------------------------------------------------------- 33 | // Constants 34 | //---------------------------------------------------------------------------- 35 | 36 | static const DWORD SIMCONNECT_UNUSED = DWORD_MAX; // special value to indicate unused event, ID 37 | static const DWORD SIMCONNECT_OBJECT_ID_USER = 0; // proxy value for User vehicle ObjectID 38 | 39 | static const float SIMCONNECT_CAMERA_IGNORE_FIELD = FLT_MAX; //Used to tell the Camera API to NOT modify the value in this part of the argument. 40 | 41 | 42 | 43 | // Notification Group priority values 44 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority 45 | static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000; // highest priority that allows events to be masked 46 | static const DWORD SIMCONNECT_GROUP_PRIORITY_STANDARD = 1900000000; // standard priority 47 | static const DWORD SIMCONNECT_GROUP_PRIORITY_DEFAULT = 2000000000; // default priority 48 | static const DWORD SIMCONNECT_GROUP_PRIORITY_LOWEST = 4000000000; // priorities lower than this will be ignored 49 | 50 | //Weather observations Metar strings 51 | static const DWORD MAX_METAR_LENGTH = 2000; 52 | 53 | // Maximum thermal size is 100 km. 54 | static const float MAX_THERMAL_SIZE = 100000; 55 | static const float MAX_THERMAL_RATE = 1000; 56 | 57 | // SIMCONNECT_DATA_INITPOSITION.Airspeed 58 | static const DWORD INITPOSITION_AIRSPEED_CRUISE = -1; // aircraft's cruise airspeed 59 | static const DWORD INITPOSITION_AIRSPEED_KEEP = -2; // keep current airspeed 60 | 61 | //---------------------------------------------------------------------------- 62 | // Enum definitions 63 | //---------------------------------------------------------------------------- 64 | 65 | // Receive data types 66 | enum SIMCONNECT_RECV_ID { 67 | SIMCONNECT_RECV_ID_NULL, 68 | SIMCONNECT_RECV_ID_EXCEPTION, 69 | SIMCONNECT_RECV_ID_OPEN, 70 | SIMCONNECT_RECV_ID_QUIT, 71 | SIMCONNECT_RECV_ID_EVENT, 72 | SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE, 73 | SIMCONNECT_RECV_ID_EVENT_FILENAME, 74 | SIMCONNECT_RECV_ID_EVENT_FRAME, 75 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA, 76 | SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE, 77 | SIMCONNECT_RECV_ID_WEATHER_OBSERVATION, 78 | SIMCONNECT_RECV_ID_CLOUD_STATE, 79 | SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID, 80 | SIMCONNECT_RECV_ID_RESERVED_KEY, 81 | SIMCONNECT_RECV_ID_CUSTOM_ACTION, 82 | SIMCONNECT_RECV_ID_SYSTEM_STATE, 83 | SIMCONNECT_RECV_ID_CLIENT_DATA, 84 | 85 | }; 86 | 87 | 88 | 89 | // Data data types 90 | enum SIMCONNECT_DATATYPE { 91 | SIMCONNECT_DATATYPE_INVALID, // invalid data type 92 | SIMCONNECT_DATATYPE_INT32, // 32-bit integer number 93 | SIMCONNECT_DATATYPE_INT64, // 64-bit integer number 94 | SIMCONNECT_DATATYPE_FLOAT32, // 32-bit floating-point number (float) 95 | SIMCONNECT_DATATYPE_FLOAT64, // 64-bit floating-point number (double) 96 | SIMCONNECT_DATATYPE_STRING8, // 8-byte string 97 | SIMCONNECT_DATATYPE_STRING32, // 32-byte string 98 | SIMCONNECT_DATATYPE_STRING64, // 64-byte string 99 | SIMCONNECT_DATATYPE_STRING128, // 128-byte string 100 | SIMCONNECT_DATATYPE_STRING256, // 256-byte string 101 | SIMCONNECT_DATATYPE_STRING260, // 260-byte string 102 | SIMCONNECT_DATATYPE_STRINGV, // variable-length string 103 | 104 | SIMCONNECT_DATATYPE_INITPOSITION, // see SIMCONNECT_DATA_INITPOSITION 105 | SIMCONNECT_DATATYPE_MARKERSTATE, // see SIMCONNECT_DATA_MARKERSTATE 106 | SIMCONNECT_DATATYPE_WAYPOINT, // see SIMCONNECT_DATA_WAYPOINT 107 | SIMCONNECT_DATATYPE_LATLONALT, // see SIMCONNECT_DATA_LATLONALT 108 | SIMCONNECT_DATATYPE_XYZ, // see SIMCONNECT_DATA_XYZ 109 | 110 | SIMCONNECT_DATATYPE_MAX // enum limit 111 | }; 112 | 113 | // Exception error types 114 | enum SIMCONNECT_EXCEPTION { 115 | SIMCONNECT_EXCEPTION_NONE, 116 | 117 | SIMCONNECT_EXCEPTION_ERROR, 118 | SIMCONNECT_EXCEPTION_SIZE_MISMATCH, 119 | SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, 120 | SIMCONNECT_EXCEPTION_UNOPENED, 121 | SIMCONNECT_EXCEPTION_VERSION_MISMATCH, 122 | SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, 123 | SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, 124 | SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, 125 | SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, 126 | SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, 127 | SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, 128 | SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, 129 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, 130 | SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, 131 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, 132 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, 133 | SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, 134 | SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, 135 | SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, 136 | SIMCONNECT_EXCEPTION_DATA_ERROR, 137 | SIMCONNECT_EXCEPTION_INVALID_ARRAY, 138 | SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, 139 | SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED, 140 | SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, 141 | SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, 142 | SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, 143 | SIMCONNECT_EXCEPTION_INVALID_ENUM, 144 | SIMCONNECT_EXCEPTION_DEFINITION_ERROR, 145 | SIMCONNECT_EXCEPTION_DUPLICATE_ID, 146 | SIMCONNECT_EXCEPTION_DATUM_ID, 147 | SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, 148 | }; 149 | 150 | // Object types 151 | enum SIMCONNECT_SIMOBJECT_TYPE { 152 | SIMCONNECT_SIMOBJECT_TYPE_USER, 153 | SIMCONNECT_SIMOBJECT_TYPE_ALL, 154 | SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, 155 | SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER, 156 | SIMCONNECT_SIMOBJECT_TYPE_BOAT, 157 | SIMCONNECT_SIMOBJECT_TYPE_GROUND, 158 | }; 159 | 160 | // EventState values 161 | enum SIMCONNECT_STATE { 162 | SIMCONNECT_STATE_OFF, 163 | SIMCONNECT_STATE_ON, 164 | }; 165 | 166 | // Object Data Request Period values 167 | enum SIMCONNECT_PERIOD { 168 | SIMCONNECT_PERIOD_NEVER, 169 | SIMCONNECT_PERIOD_ONCE, 170 | SIMCONNECT_PERIOD_VISUAL_FRAME, 171 | SIMCONNECT_PERIOD_SIM_FRAME, 172 | SIMCONNECT_PERIOD_SECOND, 173 | }; 174 | 175 | 176 | enum SIMCONNECT_MISSION_END { 177 | SIMCONNECT_MISSION_FAILED, 178 | SIMCONNECT_MISSION_CRASHED, 179 | SIMCONNECT_MISSION_SUCCEEDED 180 | }; 181 | 182 | // bits for the Waypoint Flags field: may be combined 183 | typedef DWORD SIMCONNECT_WAYPOINT_FLAGS; 184 | 185 | static const DWORD SIMCONNECT_WAYPOINT_NONE = 0x00; 186 | static const DWORD SIMCONNECT_WAYPOINT_SPEED_REQUESTED = 0x04; // requested speed at waypoint is valid 187 | static const DWORD SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED = 0x08; // request a specific throttle percentage 188 | static const DWORD SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10; // compute vertical to speed to reach waypoint altitude when crossing the waypoint 189 | static const DWORD SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL = 0x20; // AltitudeIsAGL 190 | static const DWORD SIMCONNECT_WAYPOINT_ON_GROUND = 0x00100000; // place this waypoint on the ground 191 | static const DWORD SIMCONNECT_WAYPOINT_REVERSE = 0x00200000; // Back up to this waypoint. Only valid on first waypoint 192 | static const DWORD SIMCONNECT_WAYPOINT_WRAP_TO_FIRST = 0x00400000; // Wrap around back to first waypoint. Only valid on last waypoint. 193 | 194 | 195 | typedef DWORD SIMCONNECT_EVENT_FLAG; 196 | 197 | static const DWORD SIMCONNECT_EVENT_FLAG_DEFAULT = 0x00000000; 198 | static const DWORD SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001; // set event repeat timer to simulate fast repeat 199 | static const DWORD SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002; // set event repeat timer to simulate slow repeat 200 | static const DWORD SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010; // interpret GroupID parameter as priority value 201 | 202 | 203 | typedef DWORD SIMCONNECT_DATA_REQUEST_FLAG; 204 | 205 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; 206 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested data when value(s) change 207 | static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested data in tagged format 208 | 209 | 210 | typedef DWORD SIMCONNECT_DATA_SET_FLAG; // see SIMCONNECT_DATA_SET_FLAG_* definitions 211 | 212 | static const DWORD SIMCONNECT_DATA_SET_FLAG_DEFAULT = 0x00000000; // data is in tagged format 213 | static const DWORD SIMCONNECT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format 214 | 215 | 216 | typedef DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG; 217 | 218 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000; 219 | static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001; // permit only ClientData creator to write into ClientData 220 | 221 | 222 | typedef DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA; // dwData contains these flags for the "View" System Event 223 | 224 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001; // 2D Panels in cockpit view 225 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002; // Virtual (3D) panels in cockpit view 226 | static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004; // Orthogonal (Map) view 227 | 228 | 229 | typedef DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA; // dwData contains these flags for the "Sound" System Event 230 | 231 | static const DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001; // Sound Master 232 | 233 | 234 | 235 | 236 | //---------------------------------------------------------------------------- 237 | // User-defined enums 238 | //---------------------------------------------------------------------------- 239 | 240 | typedef DWORD SIMCONNECT_NOTIFICATION_GROUP_ID; //client-defined notification group ID 241 | typedef DWORD SIMCONNECT_INPUT_GROUP_ID; //client-defined input group ID 242 | typedef DWORD SIMCONNECT_DATA_DEFINITION_ID; //client-defined data definition ID 243 | typedef DWORD SIMCONNECT_DATA_REQUEST_ID; //client-defined request data ID 244 | 245 | typedef DWORD SIMCONNECT_CLIENT_EVENT_ID; //client-defined client event ID 246 | typedef DWORD SIMCONNECT_CLIENT_DATA_ID; //client-defined client data ID 247 | typedef DWORD SIMCONNECT_CLIENT_DATA_DEFINITION_ID; //client-defined client data definition ID 248 | 249 | 250 | //---------------------------------------------------------------------------- 251 | // Struct definitions 252 | //---------------------------------------------------------------------------- 253 | 254 | #pragma pack(push, 1) 255 | 256 | struct SIMCONNECT_RECV 257 | { 258 | DWORD dwSize; // record size 259 | DWORD dwVersion; // interface version 260 | DWORD dwID; // see SIMCONNECT_RECV_ID 261 | }; 262 | 263 | struct SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION 264 | { 265 | DWORD dwException; // see SIMCONNECT_EXCEPTION 266 | static const DWORD UNKNOWN_SENDID = 0; 267 | DWORD dwSendID; // see SimConnect_GetLastSentPacketID 268 | static const DWORD UNKNOWN_INDEX = DWORD_MAX; 269 | DWORD dwIndex; // index of parameter that was source of error 270 | }; 271 | 272 | struct SIMCONNECT_RECV_OPEN : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_OPEN 273 | { 274 | char szApplicationName[256]; 275 | DWORD dwApplicationVersionMajor; 276 | DWORD dwApplicationVersionMinor; 277 | DWORD dwApplicationBuildMajor; 278 | DWORD dwApplicationBuildMinor; 279 | DWORD dwSimConnectVersionMajor; 280 | DWORD dwSimConnectVersionMinor; 281 | DWORD dwSimConnectBuildMajor; 282 | DWORD dwSimConnectBuildMinor; 283 | DWORD dwReserved1; 284 | DWORD dwReserved2; 285 | }; 286 | 287 | struct SIMCONNECT_RECV_QUIT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_QUIT 288 | { 289 | }; 290 | 291 | struct SIMCONNECT_RECV_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT 292 | { 293 | static const DWORD UNKNOWN_GROUP = DWORD_MAX; 294 | DWORD uGroupID; 295 | DWORD uEventID; 296 | DWORD dwData; // uEventID-dependent context 297 | }; 298 | 299 | struct SIMCONNECT_RECV_EVENT_FILENAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 300 | { 301 | char szFileName[MAX_PATH]; // uEventID-dependent context 302 | DWORD dwFlags; 303 | }; 304 | 305 | struct SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME 306 | { 307 | SIMCONNECT_SIMOBJECT_TYPE eObjType; 308 | }; 309 | 310 | struct SIMCONNECT_RECV_EVENT_FRAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FRAME 311 | { 312 | float fFrameRate; 313 | float fSimSpeed; 314 | }; 315 | 316 | struct SIMCONNECT_RECV_SIMOBJECT_DATA : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA 317 | { 318 | DWORD dwRequestID; 319 | DWORD dwObjectID; 320 | DWORD dwDefineID; 321 | DWORD dwFlags; // SIMCONNECT_DATA_REQUEST_FLAG 322 | DWORD dwentrynumber; // if multiple objects returned, this is number out of . 323 | DWORD dwoutof; // note: starts with 1, not 0. 324 | DWORD dwDefineCount; // data count (number of datums, *not* byte count) 325 | DWORD dwData; // data begins here, dwDefineCount data items 326 | }; 327 | 328 | struct SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE 329 | { 330 | }; 331 | 332 | struct SIMCONNECT_RECV_CLIENT_DATA : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_CLIENT_DATA 333 | { 334 | }; 335 | 336 | struct SIMCONNECT_RECV_WEATHER_OBSERVATION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_WEATHER_OBSERVATION 337 | { 338 | DWORD dwRequestID; 339 | char szMetar[1]; // Variable length string whose maximum size is MAX_METAR_LENGTH 340 | }; 341 | 342 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH = 64; 343 | static const int SIMCONNECT_CLOUD_STATE_ARRAY_SIZE = SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH*SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH; 344 | 345 | struct SIMCONNECT_RECV_CLOUD_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_CLOUD_STATE 346 | { 347 | DWORD dwRequestID; 348 | DWORD dwArraySize; 349 | BYTE rgbData[1]; 350 | }; 351 | 352 | struct SIMCONNECT_RECV_ASSIGNED_OBJECT_ID : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID 353 | { 354 | DWORD dwRequestID; 355 | DWORD dwObjectID; 356 | }; 357 | 358 | struct SIMCONNECT_RECV_RESERVED_KEY : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY 359 | { 360 | char szChoiceReserved[30]; 361 | char szReservedKey[50]; 362 | }; 363 | 364 | struct SIMCONNECT_RECV_SYSTEM_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SYSTEM_STATE 365 | { 366 | DWORD dwRequestID; 367 | DWORD dwInteger; 368 | float fFloat; 369 | char szString[MAX_PATH]; 370 | }; 371 | 372 | struct SIMCONNECT_RECV_CUSTOM_ACTION : public SIMCONNECT_RECV_EVENT 373 | { 374 | GUID guidInstanceId; // Instance id of the action that executed 375 | DWORD dwWaitForCompletion; // Wait for completion flag on the action 376 | char szPayLoad[1]; // Variable length string payload associated with the mission action. 377 | }; 378 | 379 | 380 | 381 | 382 | // SIMCONNECT_DATATYPE_INITPOSITION 383 | struct SIMCONNECT_DATA_INITPOSITION 384 | { 385 | double Latitude; // degrees 386 | double Longitude; // degrees 387 | double Altitude; // feet 388 | double Pitch; // degrees 389 | double Bank; // degrees 390 | double Heading; // degrees 391 | DWORD OnGround; // 1=force to be on the ground 392 | DWORD Airspeed; // knots 393 | }; 394 | 395 | 396 | // SIMCONNECT_DATATYPE_MARKERSTATE 397 | struct SIMCONNECT_DATA_MARKERSTATE 398 | { 399 | char szMarkerName[64]; 400 | DWORD dwMarkerState; 401 | }; 402 | 403 | // SIMCONNECT_DATATYPE_WAYPOINT 404 | struct SIMCONNECT_DATA_WAYPOINT 405 | { 406 | double Latitude; // degrees 407 | double Longitude; // degrees 408 | double Altitude; // feet 409 | unsigned long Flags; 410 | double ktsSpeed; // knots 411 | double percentThrottle; 412 | }; 413 | 414 | // SIMCONNECT_DATA_LATLONALT 415 | struct SIMCONNECT_DATA_LATLONALT 416 | { 417 | double Latitude; 418 | double Longitude; 419 | double Altitude; 420 | }; 421 | 422 | // SIMCONNECT_DATA_XYZ 423 | struct SIMCONNECT_DATA_XYZ 424 | { 425 | double x; 426 | double y; 427 | double z; 428 | }; 429 | 430 | #pragma pack(pop) 431 | 432 | //---------------------------------------------------------------------------- 433 | // End of Struct definitions 434 | //---------------------------------------------------------------------------- 435 | 436 | 437 | #if !defined(SIMCONNECTAPI) 438 | #define SIMCONNECTAPI extern "C" HRESULT __stdcall 439 | #endif 440 | 441 | 442 | typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); 443 | 444 | 445 | SIMCONNECTAPI SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName = ""); 446 | SIMCONNECTAPI SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags); 447 | SIMCONNECTAPI SimConnect_SetSystemEventState(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_STATE dwState); 448 | SIMCONNECTAPI SimConnect_AddClientEventToNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable = FALSE); 449 | SIMCONNECTAPI SimConnect_RemoveClientEvent(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID); 450 | SIMCONNECTAPI SimConnect_SetNotificationGroupPriority(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); 451 | SIMCONNECTAPI SimConnect_ClearNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID); 452 | SIMCONNECTAPI SimConnect_RequestNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD dwReserved = 0, DWORD Flags = 0); 453 | SIMCONNECTAPI SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * DatumName, const char * UnitsName, SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); 454 | SIMCONNECTAPI SimConnect_ClearDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); 455 | SIMCONNECTAPI SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); 456 | SIMCONNECTAPI SimConnect_RequestDataOnSimObjectType(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, DWORD dwRadiusMeters, SIMCONNECT_SIMOBJECT_TYPE type); 457 | SIMCONNECTAPI SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); 458 | SIMCONNECTAPI SimConnect_MapInputEventToClientEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); 459 | SIMCONNECTAPI SimConnect_SetInputGroupPriority(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD uPriority); 460 | SIMCONNECTAPI SimConnect_RemoveInputEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition); 461 | SIMCONNECTAPI SimConnect_ClearInputGroup(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID); 462 | SIMCONNECTAPI SimConnect_SetInputGroupState(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD dwState); 463 | SIMCONNECTAPI SimConnect_RequestReservedKey(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * szKeyChoice1 = "", const char * szKeyChoice2 = "", const char * szKeyChoice3 = ""); 464 | SIMCONNECTAPI SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); 465 | SIMCONNECTAPI SimConnect_UnsubscribeFromSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); 466 | SIMCONNECTAPI SimConnect_WeatherRequestInterpolatedObservation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt); 467 | SIMCONNECTAPI SimConnect_WeatherRequestObservationAtStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 468 | SIMCONNECTAPI SimConnect_WeatherRequestObservationAtNearestStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon); 469 | SIMCONNECTAPI SimConnect_WeatherCreateStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO, const char * szName, float lat, float lon, float alt); 470 | SIMCONNECTAPI SimConnect_WeatherRemoveStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); 471 | SIMCONNECTAPI SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char * szMETAR); 472 | SIMCONNECTAPI SimConnect_WeatherSetModeServer(HANDLE hSimConnect, DWORD dwPort, DWORD dwSeconds); 473 | SIMCONNECTAPI SimConnect_WeatherSetModeTheme(HANDLE hSimConnect, const char * szThemeName); 474 | SIMCONNECTAPI SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect); 475 | SIMCONNECTAPI SimConnect_WeatherSetModeCustom(HANDLE hSimConnect); 476 | SIMCONNECTAPI SimConnect_WeatherSetDynamicUpdateRate(HANDLE hSimConnect, DWORD dwRate); 477 | SIMCONNECTAPI SimConnect_WeatherRequestCloudState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float minLat, float minLon, float minAlt, float maxLat, float maxLon, float maxAlt, DWORD dwFlags = 0); 478 | SIMCONNECTAPI SimConnect_WeatherCreateThermal(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt, float radius, float height, float coreRate = 3.0f, float coreTurbulence = 0.05f, float sinkRate = 3.0f, float sinkTurbulence = 0.2f, float coreSize = 0.4f, float coreTransitionSize = 0.1f, float sinkLayerSize = 0.4f, float sinkTransitionSize = 0.1f); 479 | SIMCONNECTAPI SimConnect_WeatherRemoveThermal(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID); 480 | SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); 481 | SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); 482 | SIMCONNECTAPI SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 483 | SIMCONNECTAPI SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char * szContainerTitle, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); 484 | SIMCONNECTAPI SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 485 | SIMCONNECTAPI SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); 486 | SIMCONNECTAPI SimConnect_AISetAircraftFlightPlan(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, const char * szFlightPlanPath, SIMCONNECT_DATA_REQUEST_ID RequestID); 487 | SIMCONNECTAPI SimConnect_ExecuteMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 488 | SIMCONNECTAPI SimConnect_CompleteCustomMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); 489 | SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect); 490 | SIMCONNECTAPI SimConnect_RetrieveString(SIMCONNECT_RECV * pData, DWORD cbData, void * pStringV, char ** pszString, DWORD * pcbString); 491 | SIMCONNECTAPI SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD * pdwError); 492 | SIMCONNECTAPI SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); 493 | SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); 494 | SIMCONNECTAPI SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData); 495 | SIMCONNECTAPI SimConnect_RequestResponseTimes(HANDLE hSimConnect, DWORD nCount, float * fElapsedSeconds); 496 | SIMCONNECTAPI SimConnect_InsertString(char * pDest, DWORD cbDest, void ** ppEnd, DWORD * pcbStringV, const char * pSource); 497 | SIMCONNECTAPI SimConnect_CameraSetRelative6DOF(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg); 498 | SIMCONNECTAPI SimConnect_MenuAddItem(HANDLE hSimConnect, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, DWORD dwData); 499 | SIMCONNECTAPI SimConnect_MenuDeleteItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID); 500 | SIMCONNECTAPI SimConnect_MenuAddSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID, DWORD dwData); 501 | SIMCONNECTAPI SimConnect_MenuDeleteSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID); 502 | SIMCONNECTAPI SimConnect_RequestSystemState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szState); 503 | SIMCONNECTAPI SimConnect_SetSystemState(HANDLE hSimConnect, const char * szState, DWORD dwInteger, float fFloat, const char * szString); 504 | SIMCONNECTAPI SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char * szClientDataName, SIMCONNECT_CLIENT_DATA_ID ClientDataID); 505 | SIMCONNECTAPI SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags); 506 | SIMCONNECTAPI SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwOffset, DWORD dwSize, DWORD dwReserved = SIMCONNECT_UNUSED); 507 | SIMCONNECTAPI SimConnect_ClearClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID); 508 | SIMCONNECTAPI SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwReserved1 = SIMCONNECT_UNUSED, DWORD dwReserved2 = 0); 509 | SIMCONNECTAPI SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwReserved, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); 510 | SIMCONNECTAPI SimConnect_FlightLoad(HANDLE hSimConnect, const char * szFileName); 511 | SIMCONNECTAPI SimConnect_FlightSave(HANDLE hSimConnect, const char * szFileName, const char * szDescription, DWORD Flags); 512 | SIMCONNECTAPI SimConnect_FlightPlanLoad(HANDLE hSimConnect, const char * szFileName); 513 | 514 | 515 | #endif // _SIMCONNECT_H_ 516 | -------------------------------------------------------------------------------- /prebuilt_binaries/roll_example.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NicholasLindsay/SimConnect_Examples/65fab68e176d60ceb5168e6f224ad19350194877/prebuilt_binaries/roll_example.exe --------------------------------------------------------------------------------