Jump to content

Kerbin Mini Shuttle


helldiver

Recommended Posts

Foreword: There's been a lot of screenshots and pretty pictures in the development updates in this thread, but as well as the artwork there's a lot of coding that goes on behind the scenes to make it all work. Now that I have turned the prototype "hardcoded-everything" MFD plugin into something more suitable for release, I figured I would start doing some development update posts to give some insight into some of the new territory this mod is venturing into.


This update is about the graphical Multi-Function Displays (MFDs) used by the shuttle, specifically how I manage and abstract the differing layers of responsibility of rendering display components (such as a compass or altimeter) on each display. The key maintainability goal is to keep decisions about data that is specific to a display out of the plugin and strictly within the config file.

I have now got a usable scripting interface working for the MFD configuration files, after a long day of head-butting against Unity, Mono and Boo in (eventually successful) attempts to coerce everything into running correctly. This may at first glance not seem very relevant to the short term goals, but it is in fact desperately needed for this project to stay manageable, especially as the number of total different display components increases rapidly, as it will do soon. It saves a lot of time in the long run and cuts down on code bloat and the need to patch the plugin for any UI tweaks. The scripting interface means that I do not have to code an instrument renderer class for each possible flight statistic you would want to display (e.g. KIAS, EAS, TAS, and that's just for airspeed). For all of the prototype screenshots that have been posted so far the specific variables being sent to each instrument (e.g. airspeed, altitude etc.) were hardcoded into the application. If I let the project continue in this way it would result in a lot of redundant code that is specific to a particular use case, which is a headache to maintain and generally Bad software engineering. The introduction of a scripting interface means that the specification of the data to display is defined via code snippets in the configuration file, abstracting display-specific data manipulation away from the plugin itself1.

An example best illustrates the problem and the solution. I previously required classes in my code dedicated to each type of vertical tape instrument (e.g. altimeter, airspeed indicator, vertical speed indicator etc.), each specifying the slight difference that determines the value that is shown on the tape. You would then specify the individual class by name in the list of instruments in the config file (which, by the way, is written in YAML):


# An instance of the altitude tape class. This only shows the current altitude, in metres only.
- altitude_tape:
# these properties determine the location and appearance of the tape instrument
top_left: [363, 114]
background_tex: Altitude_tape_border
tape_tex: Altitude_tape
mask_tex: Altitude_tape_border_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
interval: 50


# An instance of the speed tape class. This only shows the current speed, in metres per second only.
- speed_tape:
top_left: [0, 114]
background_tex: Speed_tape_border
tape_tex: Speed_tape
mask_tex: Speed_tape_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
interval: 10

Similarly, I would have had to come up with code for every possible dynamic readout label (e.g. altitude, airspeed, G-force, main throttle, periapsis, apoapsis, ETA to periapsis, etc.), which would be inefficient and difficult to maintain and limit what can be shown on a display to what I can think of in advance.

The new system solves all of these problems. For example, vertical scrolling tapes are all covered by one class, which uses dynamically compiled script snippets to control the values it displays. Here's the config for the same two tapes from above rewritten using the new system:


# An instance of a generic vertical tape, with its behaviour set by script snippets to display the current altitude in feet.
- vertical_tape:
top_left: [363, 114]
background_tex: Altitude_tape_border
tape_tex: Altitude_tape
mask_tex: Altitude_tape_border_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
# local_defs - persistent variables/definitions used by update or value
# | is YAML code indicating a multi-line text block. It is not part of the script.
local_defs: |
static final FEET = 3.2808399f
unit = FEET
# value - a simple way to specify the expression value displayed by the tape - in this case
# the vessel altitude in feet, pulled straight from the KSP API via FlightGlobals.
value: FlightGlobals.ship_altitude * unit
interval: 50


# Another tape, controlled by the same class as above, but configured with different script
# snippets so that it displays the current speed in nautical miles per second in the current
# UI speed mode (Orbital, Surface, or Target).
- vertical_tape:
top_left: [0, 114]
background_tex: Speed_tape_border
tape_tex: Speed_tape
mask_tex: Speed_tape_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
local_defs: |
static final knots = 1.94384449f
unit = knots
# update - for more complex computation requiring more than just a single expression
# you can use this callback to change rendering properties every frame. These so far
# include the position on the tape (value) as well as the increment between tick marks (interval).
update: |
match FlightUIController.speedDisplayMode:
case FlightUIController.SpeedDisplayModes.Orbit:
value = FlightGlobals.ship_obtSpeed * unit
case FlightUIController.SpeedDisplayModes.Surface:
value = FlightGlobals.ship_srfSpeed * unit
case FlightUIController.SpeedDisplayModes.Target:
value = FlightGlobals.ship_tgtSpeed * unit
interval: 10

These config entries now include code snippets (in the optional properties local_defs, update and value_expr) that the plugin compiles to machine code2 when the game loads and runs in flight to determine the behaviour of each instrument. As you can see, this decouples the possible values that are shown on display components from the component renderering code itself, which cuts down on code I need to write, and allows other modders (once this is released) to come up with their own ways of displaying any data they like using the existing components. You could for example use this, in the case of the new vertical_tape components, to dynamically change the tape increment based on the current rate of change of the value so that the tape never moves too fast to read. Similarly other component properties can be customised by scripting, such as changing the ADI ground colours to shades of purple when you fly to Eve.

Of course, this scripting interface is just scratching the tip of the iceberg. All code snippets are written in Boo, a fully-fledged .NET language, and are given full access to just the KSP API. The natural extension of this project would be to create a generic programmable flight computer that runs Boo scripts. As an idea of how powerful this would be, most features from existing mods would be automatically made accessible to scripts, such as the thrust balancing features of my mod KerbCom Avionics (many of which are not controllable via the KCA GUI for usability reasons), the fuel balancing features of TAC, and control over the servos of Infernal Robotics. Then anyone could use the combined features of KSP and the mods they have installed to write a personalised control script for their crafts, such as a flight guidance computer for a shuttle.

Depending on how much interest there is, once the project is released I might do more posts explaining the other aspects of the project, such as the shader compilation and material management plugin and the upcoming acyclic attachment node plugin to be used on the shuttle EFT attachment points.

Sidenote: Boo has extensive support for metaprogramming that allows you to create new language variants within Boo (known as Domain Specific Languages). As an example, it is very likely that nearly all of the KOS scripting language could be reimplemented as macros in Boo, with the additional bonus of giving access to the entire KSP API.

P.P.S. Please note that all scripts using the system run just as fast as a plugin would - each script is compiled in memory when the script is first used (known as Just In Time compilation).

P.S. Security is not a concern, as .NET provides "sandboxes" for untrusted code (such as user-made scripts) to run in, restricting access to things like the filesystem or the internet.

[1] As the influential computer scientist Dr. David Wheeler (inventor of the infamous goto statement, amongst other things) succinctly observed - "All problems in computer science can be solved by another level of indirection.".

[2] Well, not actually machine code, but Common Intermediate Language - .NET bytecode, the same thing C# compiles to.

Edited by ZRM
Link to comment
Share on other sites


# An instance of a generic vertical tape, with its behaviour set by script snippets to display the current altitude in feet.
- vertical_tape:
top_left: [363, 114]
background_tex: Altitude_tape_border
tape_tex: Altitude_tape
mask_tex: Altitude_tape_border_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
# local_defs - persistent variables/definitions used by update or value
# | is YAML code indicating a multi-line text block. It is not part of the script.
local_defs: |
static final FEET = 3.2808399f
unit = FEET
# value - a simple way to specify the expression value displayed by the tape - in this case
# the vessel altitude in feet, pulled straight from the KSP API via FlightGlobals.
value: FlightGlobals.ship_altitude / unit
interval: 50


# Another tape, controlled by the same class as above, but configured with different script
# snippets so that it displays the current speed in nautical miles per second in the current
# UI speed mode (Orbital, Surface, or Target).
- vertical_tape:
top_left: [0, 114]
background_tex: Speed_tape_border
tape_tex: Speed_tape
mask_tex: Speed_tape_mask
char_atlas_tex: djvsm16
number_colour: [1, 1, 1]
tape_number_top_right: [59, -7]
needle_tip: [74, 141]
local_defs: |
static final knots = 1.94384449
unit = knots
# update - for more complex computation requiring more than just a single expression
# you can use this callback to change rendering properties every frame. These so far
# include the position on the tape (value) as well as the increment between tick marks (interval).
update: |
match FlightUIController.speedDisplayMode:
case FlightUIController.SpeedDisplayModes.Orbit:
value = FlightGlobals.ship_obtSpeed * knots
case FlightUIController.SpeedDisplayModes.Surface:
value = FlightGlobals.ship_srfSpeed * knots
case FlightUIController.SpeedDisplayModes.Target:
value = FlightGlobals.ship_tgtSpeed * knots
interval: 10

Wow. I really need to learn to code. Java, here I come!

Link to comment
Share on other sites

Whoah... as you point out, the possibilities with this are sweet. :)

Indeed. I can't wait to make the programmable computer plugin just to see what people would come up with. Imagine the auto-optimised launch trajectories, synchronised close proximity launches (with KerbTown for the extra launch pads), formation flying and aerial displays, autonomous space station/base construction, computer-controlled convoys of rovers following your rover, AI-controlled "opponents", etc.


Wow. I really need to learn to code. Java, here I come!

Java is a good starting point for beginners, but bearing in mind how similar it is to C#, and that KSP plugins are written in C#, you may want to start with C#. Both languages have thorough documentation and good tutorials available on the internet. Also note that the code you quoted is a combination of YAML, a markup language, and Boo, a Python-inspired .NET language (it runs using the same system as C#, just with different syntax). Python is also supposedly good for beginners, though I am concerned that due to its nature as a dynamic language once you learn Python you may find it difficult to migrate to other, more restrictive (but faster), static languages such as Java, C#, Boo, C, C++ etc. So overall I would recommend Java or C#.


A very interesting update, ZRM. It is nice to get an insight into the code running behind the MFD's. Does this mean that the MFD'S will also be released as a standalone plugin?

That is my intention. The plugin that powers the MFDs would be released separately (perhaps under the moniker "KerbCom Glass"), with helldiver hopefully giving permission (we have not discussed this yet) to release the shuttle MFD graphics as an example MFD set for the plugin release, as well as bundled with the shuttle.


Damn, this is amazing ZRM

Outstanding!

Thanks!

Link to comment
Share on other sites

The MFD can be removed easily

Let me know and I will send you the components.

Again, this is awesome.

I did not think of actually using the actual MFD model, but I guess that would be a handy addition for the plugin - otherwise people would not be able to use the plugin separately without making their own parts for it. Your MFD could be used as a prop in existing cockpits. Thanks for the offer. You don't need to send me the assets at the moment, but when you do, please could you make the MFD shallower than the MFD you previously sent me, so that it is better suited as a prop for placement in stock cockpits? It would then also look more like an LCD display.

Slowly but surely, everything is coming together.

Link to comment
Share on other sites

Any more progress since the forum went down? I'm really excited to hear about anything you guys have.

Yes, I've been waiting for the forums to come back online so that I can post a progress update and resume contact with helldiver.

Here is a screenshot of the PFD that is likely very close to what will be used for the first release:

nlUiJZ7.jpg

All of that display is functional, including the indicator labels ("RCS ON", "ENGINES 67%", etc.) and the directional markers on the heading tape and ADI (which include the normal complement of markers as you would find on the navball). A lot of the "display-specific" parts, like the values displayed on the labels and the indicator tapes, are script-powered, as explained in my previous post. None of their functionality is hard-coded into the plugin. Of all the dynamic elements in the display, only the ADI gimbal and heading indicator are unscripted, for the time being. There may be ways to extend their capabilities in the future with scripting.

So now I am waiting upon helldiver for more MFD mode designs. This first mode took a long time due to several corrections that had to be made to the way helldiver creates each asset so that it displays correctly without artefacts, as well as changes to the overall design due to usability concerns. I still had to recreate several parts from scratch using his designs as a reference so that they could actually be used in the display. His problems are mostly due to the limitations of Photoshop. Luckily I have Illustrator so that I can easily make the pixel-perfect versions of each asset. The idea for future display modes is that helldiver sends me his draft design, and then I create the final assets to the specifications I require in Illustrator. This should make the process a lot quicker, instead of slow back-and-forth PMs as each asset is corrected.

P.S. For the future of the MFD plugin I am thinking of recreating actual displays from real aircraft/spacecraft. First on my list is the newest Space Shuttle electronic PFD:

img_8013.jpg

This will be a bit of a challenge due the embedded 3D navball that will need to be rendered, however I have ideas for drawing this efficiently with high quality.

P.P.S. Yes, I know the heading indicator on the in-game PFD is missing the indicator notch. That will be added in due course.

Link to comment
Share on other sites

Personally, I'd rather see you spending time on developing a nice shuttle model with decent flight dynamics than bells and whistles in the cockpit. I have the feeling that not many people spend a lot of time IVA. I certainly hardly ever use it.

To each his own though...

Link to comment
Share on other sites

Personally, I'd rather see you spending time on developing a nice shuttle model with decent flight dynamics than bells and whistles in the cockpit. I have the feeling that not many people spend a lot of time IVA. I certainly hardly ever use it.

To each his own though...

regardless of how little time I might spend in IVA, the one time I do, I dont want to see a crappy IVA or worse, no IVA at all.

Link to comment
Share on other sites

Personally, I'd rather see you spending time on developing a nice shuttle model with decent flight dynamics than bells and whistles in the cockpit. I have the feeling that not many people spend a lot of time IVA. I certainly hardly ever use it.

To each his own though...

I actually looking forward to this IVA. Think the reason we do not use IVA that much, is that the uselessness of the Instrument. To have access to some of the information that is needed to do some of the navigation, you have to get outside where they are located. With this IVA instrument, we have a possibility to do all work in IVA.

Anariaq

Link to comment
Share on other sites

My apologies if this had already been addressed; will this shuttle have special fuel requirements, or will standard tanks work fine? I want to test out George Von Pragenau's proposed launch configuration when this bird becomes available. Thanks!

Link to comment
Share on other sites

Just finished reading all the back posts on this project. Looks outstanding!

Few personal notes:

-Outstanding choice of the Liquid boosters. That alone makes a successful ascent far more likely, as you can throttle down to make sure you don't exceed terminal velocity.

-The pairing of the absolutely beautiful interior and the sleek exterior with the new MFD system is one of the best features of this mod. I would still probably download the shuttle without the MFDs, but those are the final straw: this is number one on my "to download" list.

-Will this be compatible with MechJeb's ascent guidance mode?

-Once you have the flight dynamics balanced, can you include a small manual for flight ops? I don't think that MechJeb's landing guidance will play well with the winged design... You'd need to provide a couple of suggestions for timing the deorbit burn.

All in all, this is going to become one of the top addons (in terms of pushing the envelope) ever made for KSP.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...