Project Air Breathing Turbojet Engine Model for Orbiter

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
OK, I'm working on making a static library to allow add-on makers to implement the jet engine in their code. I've pulled out the functions that calculate the engine thrust and Isp into a static library project organized as follows:

C++:
// JetEngineLibrary.cpp

#include <cmath>
#include "JetEngineLibrary.h"

namespace JetEngineLibrary
{
    double JetEngine::GetJetEngineThrust(double throttle, bool afterburner, double M_0, double T_0, double P_0, double rho)
    {
        ...
        return thrust;
    }
 
    double JetEngine::GetJetEngineIsp(double throttle, double thrust)
    {
        ...
        return Isp;
    }
}

C++:
//JetEngineLibrary.h

namespace JetEngineLibrary
{
    class JetEngine
    {
    public:
       
        static double GetJetEngineThrust(double throttle, bool afterburner, double M_0, double T_0, double P_0, double rho);
        static double GetJetEngineIsp(double throttle, double thrust);

    };
}

The library compiled without problem, and I made a new add-on project for the Mirage2000 where I am attempting to implement it using the library, but I get errors 'GetJetEngineThrust': identifier not found and 'GetJetEngineIsp': identifier not found.

I put the library JetEngine.lib in the OrbiterSDK/lib directory, and that directory is linked in the project properties. I also added it as a source along with Orbiter.lib and OrbiterSDK.lib, but it doesn't seem to help.

This is how I've tried to call these functions in my add-on code:

C++:
void Mirage2000::clbkPostStep(double simt, double simdt, double mjd)
{
    //----JET ENGINE IMPLEMENTATION

    //Get throttle input from user from dummy thruster

    throttle = GetThrusterGroupLevel(thg_dummy);

    //determine afterburner status

    afterburner = false; //How is afterburner engaged in real jet?

    // Get local flight conditions from Orbiter

    M_0 = GetMachNumber();            //flight Mach number [-]
    T_0 = GetAtmTemperature();      //ambient static temperature [K]
    P_0 = GetAtmPressure();         //ambient static pressure [Pa absolute]
    rho = GetAtmDensity();             //ambient atmospheric density [kg/cubic meter]

    //Use inputs and flight conditions to calculate jet engine thrust and Isp

   thrust = JetEngine::GetJetEngineThrust(throttle, afterburner, M_0, T_0, P_0, rho); //doesn't work
   #thrust = GetJetEngineThrust(throttle, afterburner, M_0, T_0, P_0, rho); //doesn't work

    //Calculate Isp

    Isp = JetEngine::GetJetEngineIsp(throttle, thrust);  //doesn't work
    #Isp = GetJetEngineIsp(throttle, thrust);  //doesn't work

    //Update Isp and thrust of user-defined main engine

    SetThrusterIsp(th_main, Isp);

    SetThrusterGroupLevel(thg_main, abs(thrust)/(max_thrust*1000));

    //----END JET ENGINE IMPLEMENTATION
 
    ...
}

I'm really pushing my C++ capabilities here so I'm not quite sure what the problem is, or what's missing. Can anyone help me make sense of this? If I can get this to work this may be very close to ability to release it as an addon.
 
Last edited:

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
Wouldn't you have to prefix the namespace "JetEngineLibrary::" as well if your calling code is not in it already?
Possibly. I think I'm fundamentally confused by how the library is referenced. I thought it was sufficient to put the *.lib file in the additional libraries path, but apparently not. I'm now looking at this for guidance:


So I have a project directory for the library with JetEngineLibrary.h and JetEngineLibrary.lib. I put JetEngineLibrary.h in the OrbiterSDK/include directory and JetEngine.lib in the OrbiterSDK/lib directory.

I can now include JetEngineLibrary.h in my add-on code, with #include <JetEngineLibrary.h>, but I get mountains of linker 2019 errors.

Something is fundamentally borked in where I am locating things. Should the *lib and *h file simply go into the add-on project directory?
 
Last edited:

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,390
Reaction score
577
Points
153
Location
Vienna
On VS2017, I always had to name the library I wanted to be included as well. The additional libraries path is a search path where the linker tries to find the named library. AFAIK, you can alternatively also include the *.lib file as an element in the solution, but I'm not sure if this works for whatever VS version you are using.
 

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,842
Reaction score
2,105
Points
203
Location
between the planets
What face said: You always have to specifically note the library in "additional libraries", even if you already specified the library path. Next, be aware that you have different configurations for debug and release builds. Many a grey hair was grown trying to get stuff to work only to realise that I had been messing with the release configuration while trying to make a debug build.
And finally, you do not mention the header file in your post. I assume its path entered is in the additional include directories, and you're actually including it? (because you don't show your includes in your sample code).
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
Wouldn't you have to prefix the namespace "JetEngineLibrary::" as well if your calling code is not in it already?

I updated the calls to:

C++:
thrust = JetEngineLibrary::JetEngine::GetJetEngineThrust(throttle, afterburner, M_0, T_0, P_0, rho);
Isp = JetEngineLibrary::JetEngine::GetJetEngineIsp(throttle, thrust);

This seems to be correct (and is how it was presented in the MS tutorial), but I was not initially including the header file in my code. Now that I am and using this code I am now getting a pile of LNK2019 errors.

On VS2017, I always had to name the library I wanted to be included as well. The additional libraries path is a search path where the linker tries to find the named library. AFAIK, you can alternatively also include the *.lib file as an element in the solution, but I'm not sure if this works for whatever VS version you are using.
What face said: You always have to specifically note the library in "additional libraries", even if you already specified the library path.
I'm using VS2017. The library was placed in the OrbiterSDK/lib directory, and that path is provided in the linker Additional Library Directory in the add-on project properties.
Next, be aware that you have different configurations for debug and release builds. Many a grey hair was grown trying to get stuff to work only to realize that I had been messing with the release configuration while trying to make a debug build.
Yep, been there, done that. Both the library project and the addon project were/are set to Release.
And finally, you do not mention the header file in your post. I assume its path entered is in the additional include directories, and you're actually including it? (because you don't show your includes in your sample code).
The header file is located in OrbiterSDK\include, and that path is provided in the Additional Include Directory in the add-on project properties. I've included it in my add-on code with #include <JetEngineLibrary.h>

Now I am getting LNK2019 errors. I have gone over my project properties several times and I think it is configured correctly.
 

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,390
Reaction score
577
Points
153
Location
Vienna
I'm using VS2017. The library was placed in the OrbiterSDK/lib directory, and that path is provided in the linker Additional Library Directory in the add-on project properties.

Did you also add the file name in the "Input" section of the linker configuration into the "Additional Dependencies" field? If I am not including the file itself as "library" element in the solution tree, I always had to add the name there in addition to the "Additional Library Directory" entry.
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
Did you also add the file name in the "Input" section of the linker configuration into the "Additional Dependencies" field? If I am not including the file itself as "library" element in the solution tree, I always had to add the name there in addition to the "Additional Library Directory" entry.
No. If I do that or if I add the library to the solution tree, in addition to providing the library path, I get even more linker errors (LNK2005) indicating that a number of variables are already defined.
 

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,390
Reaction score
577
Points
153
Location
Vienna
No. If I do that or if I add the library to the solution tree, in addition to providing the library path, I get even more linker errors (LNK2005) indicating that a number of variables are already defined.
Aha. That suspiciously sounds like your library is defining globals that are already defined in your calling code. I'd investigate this configuration a bit more instead.
EDIT: the amount of linker errors is not always the best indicator of progress towards a compiling configuration. So even if you get more, you might be closer to a solution.
 
Last edited:

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
Aha. That suspiciously sounds like your library is defining globals that are already defined in your calling code.
All of the instances of those variables were removed from the main code and put into the library code. If I put the library path into Additional Library Directories, header path in the Additional Include Directories, AND either add the library to the solution tree I get the error saying they are already defined. It seems it is attempting to load it twice.

Could it be that you ran into a situation like described here: https://stackoverflow.com/questions...ned-error-in-case-of-two-static-libraries-tha ?
I don't think so? I only have the one static library.

I'm in agreement that it is something to do with the project configuration as it seems I've seen these linker errors before. It's some mundane thing (I hope). I am going through my old projects to verify the configuration.

EDIT: I'm not seeing any problem with the project configuration.
 
Last edited:

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
Can someone explain to me why addon modules (.dlls) and the static libraries (*.lib) needs to be compiled under the multithreaded (/MT) runtime library? For dlls I keep trying to throw intuition at it and assume it's a multithreaded DLL (/MD) but apparently that is not so. I always seem to screw that up. I did so in my library AND in my addon. Grrr....

Anyway, I restored the OrbiterSDK lib and include folder contents to the default Orbiter files, and I recompiled the jet engine library and am now just adding the jet engine library and header to the add-on solution tree. That compiles and the add-on works.

I'm going to stitch together a quick document with instructions on how to use the library to add a jet engine to an add-on and will probably post here for beta testing. Stay tuned!
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
I'm learning a few more things about the thruster implementation. In making the thruster instance, I have to use the user-supplied maximum thrust of the engine, which may not exactly match the maximum thrust calculated by the model. This basically limits the engine thrust to the specified maximum, which isn't terrible if the model is predicting performance correctly.

Another issue is how to implement afterburning. I had initially thought it was sufficient to specify the maximum thrust on the main engine to be equal to the maximum thrust with afterburning, but that maps the throttle range incorrectly. It looks like another thruster needs to be specified which will deliver the thrust difference due to afterburning.

Anyway, had some fun flying the Mirage2000. I've finally got a half-decent aerodynamic model into it and it flies nicely. I could get it up to Mach 0.75 at about 32,000 ft before running out of fuel (25 minutes at full throttle without afterburning). Probably could get it higher and faster with more fuel, but the engine is hungry.

1659716307828.png
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
I'm getting a strange "runaway" effect at high speed and altitude when using afterburner. Drag decreases, so speed increases, but then thrust increases (?) and it acts like some sort of crazy ramjet. I'll have to dive into the model and see what is happening. I improved the afterburner model by limiting the heat release due to combustion when starved of air, but that didn't seem to be the problem.
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
There is something deeply borked in the model and I'm going to have to investigate it. If the throttle is reduced to zero while flying at any speed relative to the air, that should make the exhaust velocity go to zero, and the change in air momentum should be negative (i.e. the engine doesn't provide any thrust, and in fact is causing drag). This model isn't doing this, and I don't believe the Orbiter thruster implementation can deal with a negative thrust anyway.

I'm taking down the library I posted the other day; this isn't ready at all. Stay tuned.
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
I've gone back to my Python code to sort out the issues with the model. One of my assumptions on the maximum volume flow rate of air through the engine was a little too quick and dirty, and I have a better model for variation of air density at the engine inlet. This will require the user to supply the inlet diameter of the engine in addition to the other required engine parameters, but I think that isn't unreasonable. It should now model ram compression/expansion in the inlet appropriately accounting for the difference in air velocity from freestream to the inlet. If the inlet velocity is less than flight velocity, inlet air density increases due to ram compression; if it is greater, inlet density decreases.

I've also updated the handling of the afterburner to account for available air for combustion accounting for the oxygen consumed in the combustor. This will reduce afterburning thrust with altitude which I believe was the cause of the "runaway" behavior I was seeing.

I need to update the library module and test fly some more, but I think we're getting there. Progress!
 

Thunder Chicken

Fine Threads since 2008
Donator
Joined
Mar 22, 2008
Messages
4,327
Reaction score
3,246
Points
138
Location
Massachusetts
OK, now I'm much happier with it. I've posted the updated libraries and a quick start guide on my original thread starting post and attached to this post. If someone could give it a shot in one of their add-ons and provide some feedback I'd greatly appreciate it. After I get the documentation fully fleshed out I'll release it through OH.

Enjoy!

 
Last edited:
Top