Postsnavigate_next

Reflecting on X-Plane Development Experience

Getting Started

While I had been a longtime X-Plane user, I had never ventured into the development aspect of the sim before contributing to the XB A318 project. While doing research on this niche area of programming, I realized just how difficult the pipeline is for new developers. Firstly, the iterative development process took a while for me to get used to, especially coming from iOS and web development. What I found was that although there was some SDK documentation written by Laminar Research themselves, code samples and examples were few and far between. My goal was to build a complex airliner for the platform, with it being as close to study level as possible but I soon realized this was going to be much more difficult than I initially thought. It seemed the best way to get started was by using the Lua programming language on top of the FlyWithLua framework which is a third party plugin written for X-Plane. By the end of my first day of experimentation, I had drawn a window and some shapes to the screen.

Understanding Datarefs

One of the most important concepts I had to learn when it came to development for the X-Plane platform was the use of datarefs, which are essentially variables that the SDK exposes to developers and lets us manipulate. Below is a general idea of how to access, read, and write a dataref using SASL.

The idea of datarefs was extremely powerful to me especially because you could essentially access global simulator properties from anywhere in your project, allowing you to develop complex functionality with very few lines of code. Because they aren't built into any one system, I was able to design my project architecture without thinking too much about how to access them. The ability to create my own datarefs was also extremely useful for the project in general as properties could be shared not just by different modules in the same project, but even across plugins running in the sim itself.

EFB Module

The first module I started on when I joined the XB team was the EFB which I thought was a great first step in understanding how SASL worked with X-Plane as it mixed UI work with some pretty heavy systems programming. While I was still getting to grips using Lua and SASL together, I spent time creating a 3D mockup of the EFB that A320 pilots are typically given by Airbus with the goal of having it imported into our virtual cockpit. This was a great experience for me as I hadn't done modeling in a few years and getting back to it was a fun challenge.

Architecture

Choosing what architecture to use on this module was a tricky decision initially, especially considering that SASL essentially requires you to build your own UI components if you want complex functionality. In the end, I ended up going with something loosely based on the traditional MVC architecture. I found this setup helped integrate datarefs, aircraft logic, and UI components in a way that was efficient and easy to read.

One great feature of Lua I came across was the ability to store functions in tables, which helped me reduce code complexity as I could store my draw functions from every page and simply do my draw calls based on the index of the page which was stored as a dataref. This allowed seamless transition between pages. I initially approached this with an object-oriented mindset where I could extend one 'page' object but this fell through as the pages really only share the required draw() and update() functions. I eventually used this feature of Lua in several different modules throughout the project.

Input and Custom Components

One particular challenge I had in this project was using SASL's basic input functionality to create my own custom UI components. These includes widgets such as buttons, checkboxes. This was tricky because SASL gives developers very basic functions for checking input. For mouse input, we get access to whether the left button is pressed along with the cursor's x and y coordinates. For keyboard input, I simply got access to a method that checks whether any key is being held. In order to pass input to the active page as required, I set up a system similar to the way draw calls work in which I store all page input functions in a table and then call by index. Because we need to store location data for every UI element in order to check whether the user interacts with the object, I thought using Lua's object oriented paradigm to be quite useful in creating custom UI components. These can also be stored in a table on the active page while component draw calls sit in the object itself.

MCDU Module

The most challenging part of this project for me was the MCDU module. Much of the difficulty here came from the sheer amount of data the MCDU is required to process as most major systems must be accessible to the pilot through the device. I settled on a similar architecture to the EFB in which page draws calls are essentially stored in tables and called by the index of the active page. Because the MCDU pages have many different variations and subpages, a file structure for the pages had to be built into the software to allow to transitions and data sharing between pages. The input system was reworked to allow input from the LS and RS keys on either side of the display as well as the keys from the MCDU keyboard itself which control not only letter input but also page flows.

Page Construction

Page construction for the MCDU was vastly different to construction for the EFB due to the rigid structure required. Much of the documentation I used was from an A320 MCDU emulator . This site helped me understand not just the structure of individual pages, but also how the Honeywell software is put together.

Once I had the file structure down, I found it easier to put that into a config file (a simplified sample of which can be seen above) which is then parsed by the MCDU software on initial startup to decide flows. Although this was probably a bit more complex than needed to be, it allowed for a lot more flexibility when deciding what pages to include and what version of the Honeywell software I wanted to replicate.

Networking and Communication

When I first started working on the MCDU, I didn't realize the full extent to which the device is connected to a vast array of sensors and other onboard computers which required simulation as well. As a result, I built two different network and communication layers in the backend of the operating system. The first layer was the most important as it helped with internal system communication between the MCDU and other modules such as the MFD, PFD, electronics, hydraulics, etc. This model was comprised of the various datarefs needed for pulling sensor data from the aircraft systems and from the simulator platform itself. The second layer connected the MCDU to the internet and allowed it to make requests to an API. In my opinion however, the most challenging aspect of this second layer was the live update system that I built from the ground up in which aircraft code files could be pulled from the internet and updated while the plane sat running in the sim itself (the first time this had been done for the X-Plane platform as far as I know). I will probably do an in-depth post about that part of the project at some point as it was one of the most interesting coding modules I've ever worked on. You can get a basic idea of the system (in very early progress) working below.

Performance

One aspect of the project I found difficult to get to grips to was making sure that performance was still optimal across all devices. The goal was to have the aircraft run smoothly with a minimum frame rate of 24 fps on rigs that meet X-Plane's minimum system requirements. Because we weren't meeting full study-level system depth in areas that pilots rarely use, a lot of lost performance could be recovered. For the systems we did simulate in-depth such as electrics and hydraulics, performance was not hugely impacted as much of it boiled down to circuit logic. However, with X-Plane being a graphics heavy program, the main way to improve performance besides reducing unnecessary draw calls was to cache and store data appropriately.

For example, I ran into many problems when starting the navigation and flight plan system for the MCDU as large navigational databases with millions of datapoints had to be parsed quite often in between update() calls. The quick solution for this was to use a simple binary tree structure (mostly because I was lazy and we had just gone over it in my Data Structures class) to create my own navigational database that could be accessed by several different modules throughout the entire project.

This implementation reduced the time needed to complete lookups in the navigation database to a fraction of a second when loaded and is one of my favorite examples for how performance was kept in mind when designing the system. A small demo can be seen below. It doesn't look like much but there is a lot happening behind the scenes.

Conclusion

Although I eventually had to leave the XB team to focus on school, I learned a lot about programming and software development in general. This was my first proper time working remotely and in a team environment where communication was done through Discord and code collaboration through Github. There was a tremendous amount of learning done on the job and the most rewarding part was planning a feature and watching it come to life in the aircraft cockpit. Knowing that hundreds of people were actively testing the pre-alpha version and thousands more were waiting for the final product was both nerve wracking and exciting. Having people review my work in YouTube videos and online forums also gave me a great source of positive feedback and constructive criticism. I do hope to eventually return to the XB A318 project when I have more time on my hands, especially because programming the MCDU module to completion would be a huge milestone in my career. For now I feel satisfied that I got to work on a project that aligned with my interests while also being able to learn a lot about development in large team environments.