Problem Sikorsky R4 in C++ (port from Lua)

Matias Saibene

Developing and CMakin'
Donator
Joined
Jul 7, 2012
Messages
1,519
Reaction score
1,542
Points
128
Location
Monte Hermoso - Argentina
Website
github.com
Preferred Pronouns
he/him
As you may know, we're working on converting the Lua Sikorsky R-4 helicopter to C++ to add UACS support.

The first step was converting every line of Lua programming to C++.
And now we're running into the problem: the mesh won't load.

I've tested it on my Windows 11 + OpenOrbiter2024 installation, and it fails to load the mesh. I also get this error in the Orbiter.log:
Code:
000054.798: ============================ ERROR: ===========================
000054.811: Could not load vessel module: R4 (code 126)
000054.823: [Vessel::LoadModule | D:\a\orbiter\orbiter\Src\Orbiter\Vessel.cpp | 5969]
000054.839: ===============================================================

This is the relevant code:

C++:
void R4::clbkPostCreation(){

    hfuselage = oapiLoadMeshGlobal(FUS_MESH_NAME);

    AddMesh(hfuselage);

    ShiftMesh(0, operator*(cg, -1));

    SetMeshVisibilityMode(0, MESHVIS_ALWAYS);



    if(floats == false){

        hgear = oapiLoadMeshGlobal(GEAR_MESH_NAME);

        AddMesh(hgear);

        ShiftMesh(1, operator*(cg, -1));

        SetMeshVisibilityMode(1, MESHVIS_ALWAYS);

        SetFeature_SetContactPointsWheels();

        MakeAnim_MainWheels();
       
        MakeAnim_TailWheel();

    } else if(floats == true){

        hfloats = oapiLoadMeshGlobal(FLOAT_MESH_NAME);

        AddMesh(hfloats);

        ShiftMesh(1, operator*(cg, -1));

        SetMeshVisibilityMode(1, MESHVIS_ALWAYS);

        SetFeature_MakeContactPointsFloats();
       
        SetTouchdownPoints(td_points_pontoon_land, ntdvtx_td_points_pontoon_land);
    }

}

https://github.com/MatiasSaibene/Sikorsky_R-4_Helicopter_for_Orbiter/blob/master/Src_Windows/R4.cpp
 

Attachments

I renamed mine blackhawk and complied But I get nothing in the log.
my cgf:
ClassName = NEWBLACKHAWK
Module = NEWBLACKHAWK
EditorModule=NEWBLACKHAWK


000023.285: Loading module LuaInline
000023.414: Module ShuttleA.dll .......... [Build 241231, API 241231]
000023.469: Module NEWBLACKHAWK.dll ...... [Build 250316, API 241231]
 

Attachments

  • blackhawkcpp.jpg
    blackhawkcpp.jpg
    76.1 KB · Views: 6
As you may know, we're working on converting the Lua Sikorsky R-4 helicopter to C++ to add UACS support.

The first step was converting every line of Lua programming to C++.
And now we're running into the problem: the mesh won't load.

I've tested it on my Windows 11 + OpenOrbiter2024 installation, and it fails to load the mesh. I also get this error in the Orbiter.log:
Code:
000054.798: ============================ ERROR: ===========================
000054.811: Could not load vessel module: R4 (code 126)
000054.823: [Vessel::LoadModule | D:\a\orbiter\orbiter\Src\Orbiter\Vessel.cpp | 5969]
000054.839: ===============================================================

This is the relevant code:

C++:
void R4::clbkPostCreation(){

    hfuselage = oapiLoadMeshGlobal(FUS_MESH_NAME);

    AddMesh(hfuselage);

    ShiftMesh(0, operator*(cg, -1));

    SetMeshVisibilityMode(0, MESHVIS_ALWAYS);



    if(floats == false){

        hgear = oapiLoadMeshGlobal(GEAR_MESH_NAME);

        AddMesh(hgear);

        ShiftMesh(1, operator*(cg, -1));

        SetMeshVisibilityMode(1, MESHVIS_ALWAYS);

        SetFeature_SetContactPointsWheels();

        MakeAnim_MainWheels();
      
        MakeAnim_TailWheel();

    } else if(floats == true){

        hfloats = oapiLoadMeshGlobal(FLOAT_MESH_NAME);

        AddMesh(hfloats);

        ShiftMesh(1, operator*(cg, -1));

        SetMeshVisibilityMode(1, MESHVIS_ALWAYS);

        SetFeature_MakeContactPointsFloats();
      
        SetTouchdownPoints(td_points_pontoon_land, ntdvtx_td_points_pontoon_land);
    }

}

https://github.com/MatiasSaibene/Sikorsky_R-4_Helicopter_for_Orbiter/blob/master/Src_Windows/R4.cpp
If it can't load the module, how can it load the mesh?
 
Yes. But on my it loaded the module. But the vessel is not seen and the save part isn't written. I put a break and ran the debug and it ignored it. So maybe a path or something is wrong?
uh60:NEWBLACKHAWK
STATUS Landed Earth
POS -80.6825910 28.5969190
HEADING 330.00
ALT 1.997
AROT 66.660 34.091 9.884
NAVFREQ 0 0
END
 

Attachments

  • uh60notloading.jpg
    uh60notloading.jpg
    88.4 KB · Views: 3
If you look at page 3 of the Orbiter Developer Manual.pdf there is a flowchart that shows the sequence of callbacks. It may be failing in SetClassCaps and not loading the meshes in PostCreation.

Perhaps you can try loading the fuselage mesh in SetClassCaps. That mesh gets loaded regardless. This might show if the problem is in SetClassCaps or in PostCreation.
 
Last edited:
If you look at page 3 of the Orbiter Developer Manual.pdf there is a flowchart that shows the sequence of callbacks. It may be failing in SetClassCaps and not loading the meshes in PostCreation.

Perhaps you can try loading the fuselage mesh in SetClassCaps. That mesh gets loaded regardless. This might show if the problem is in SetClassCaps or in PostCreation.
Thanks for the suggestion. The Orbiter Developer Manual is indeed new to me, and I've never seen it before.

I'll investigate and correct anything necessary.

The good news is that the mesh now loads and displays on screen, with some animation issues, but I think that's easy to fix.

The problem I need to address now is the fact that the motor isn't exerting any power.

I updated the code on GitHub.
 
Ok. I switched to 2022 VS. I updated my cpp an h.
Not sure about this:
github h: #include "HEADERS/DrawAPI.h"
and in mine
#include "DrawAPI.h"

I get issues with this also: the "format"
'format': is not a member of 'std'

if (color.a != 0) {

std::string col_fmt = std::format("r=%lf, g=%lf, b=%lf, a=%lf", color.r, color.g, color.b, color.a);
char* ch_col = new char[col_fmt.length() + 1];
std::strcpy(ch_col, col_fmt.c_str());

oapiWriteScenario_string(scn, ch_color, ch_col);
}

But now I get mesh can't be found. and the save state is missing.

============================ ERROR: ===========================
000006.097: Mesh not found: .\Meshes\R-4/Fuselage.msh
000006.097: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.097: ===============================================================
000006.098: ============================ ERROR: ===========================
000006.098: Mesh not found: .\Meshes\R-4/Fuselage.msh
000006.099: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.099: ===============================================================
000006.099: Finished initialising status
000006.099: Finished initialising camera
000006.100: Finished setting up render state
000006.101: ============================ ERROR: ===========================
000006.101: Mesh not found: .\Meshes\R-4/Gears.msh
000006.101: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.101: ===============================================================
000006.101: ============================ ERROR: ===========================
000006.101: Mesh not found: .\Meshes\R-4/Gears.msh
000006.101: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.101: ===============================================================
000006.109: Finished initialising panels
000006.130: ============================ ERROR: ===========================
000006.130: Mesh not found: .\Meshes\.msh
000006.130: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.130: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================

uh60:NEWBLACKHAWK
floats false
altitude_target 0.0
rpm 0.0
throttle_level 0.0
collective 0.0
cabin_light_level 1.0
instrument_light_level 0.0
END
 
Last edited:
Is the engine power actually 0, or is it not creating thrust? Those are different problems. Can you get values for power?
Now I can confirm that the engine is exerting a small thrust (2N) , and sometimes it's shot out of the solar system. So I need to correct the AddForce part.

2025-03-17 11_18_29-Greenshot.jpg

I also need to fix the animations.
2025-03-17 11_18_38-Greenshot.jpg


Ok. I switched to 2022 VS. I updated my cpp an h.
Not sure about this:
github h: #include "HEADERS/DrawAPI.h"
and in mine
#include "DrawAPI.h"

I get issues with this also: the "format"
'format': is not a member of 'std'

if (color.a != 0) {

std::string col_fmt = std::format("r=%lf, g=%lf, b=%lf, a=%lf", color.r, color.g, color.b, color.a);
char* ch_col = new char[col_fmt.length() + 1];
std::strcpy(ch_col, col_fmt.c_str());

oapiWriteScenario_string(scn, ch_color, ch_col);
}

But now I get mesh can't be found. and the save state is missing.

============================ ERROR: ===========================
000006.097: Mesh not found: .\Meshes\R-4/Fuselage.msh
000006.097: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.097: ===============================================================
000006.098: ============================ ERROR: ===========================
000006.098: Mesh not found: .\Meshes\R-4/Fuselage.msh
000006.099: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.099: ===============================================================
000006.099: Finished initialising status
000006.099: Finished initialising camera
000006.100: Finished setting up render state
000006.101: ============================ ERROR: ===========================
000006.101: Mesh not found: .\Meshes\R-4/Gears.msh
000006.101: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.101: ===============================================================
000006.101: ============================ ERROR: ===========================
000006.101: Mesh not found: .\Meshes\R-4/Gears.msh
000006.101: [MeshManager::LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1307]
000006.101: ===============================================================
000006.109: Finished initialising panels
000006.130: ============================ ERROR: ===========================
000006.130: Mesh not found: .\Meshes\.msh
000006.130: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.130: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================
000006.131: ============================ ERROR: ===========================
000006.131: Mesh not found: .\Meshes\.msh
000006.131: [LoadMesh | D:\a\orbiter\orbiter\Src\Orbiter\Mesh.cpp | 1341]
000006.131: ===============================================================

uh60:NEWBLACKHAWK
floats false
altitude_target 0.0
rpm 0.0
throttle_level 0.0
collective 0.0
cabin_light_level 1.0
instrument_light_level 0.0
END
I need to fix the code to place it in the Orbitersdk folder. And remember to use C++20.
Thank you all for reporting your findings.
 
Now I can confirm that the engine is exerting a small thrust (2N) , and sometimes it's shot out of the solar system. So I need to correct the AddForce part.

View attachment 42807

I also need to fix the animations.
View attachment 42808



I need to fix the code to place it in the Orbitersdk folder. And remember to use C++20.
Thank you all for reporting your findings.
The 2N forces are the small vertical thruster forces applied to provide a 0-1 indications on the main and hover engine indicators with the dummy throttle setup. So your code is setting those thrusters (you can set the max thrust to 0 for both if these if you don't use the default main and hover engine indicators in the glass cockpit). They should be vertical through the CG and a Newton is about the weight of an apple, so it is effectively negligible either way.

Can you get text output of the engine power (variable was 'power' in my code)? That would tell you if it is calling the engine module properly. Similarly, getting output for the main_rotor_thrust would tell us if the propeller module is being called properly.
 
Note that the rotor thrust is implemented using add_force, not a thruster. The thruster definitions are just to take throttle and collective input from the user.
 
The 2N forces are the small vertical thruster forces applied to provide a 0-1 indications on the main and hover engine indicators with the dummy throttle setup. So your code is setting those thrusters (you can set the max thrust to 0 for both if these if you don't use the default main and hover engine indicators in the glass cockpit). They should be vertical through the CG and a Newton is about the weight of an apple, so it is effectively negligible either way.

Can you get text output of the engine power (variable was 'power' in my code)? That would tell you if it is calling the engine module properly. Similarly, getting output for the main_rotor_thrust would tell us if the propeller module is being called properly.
Thanks, I'm currently fixing the power variable, which was getting mixed up in the GetEngine_ReciprocatingPower and GetEngine_GasTurbinePower functions.

Sometimes I have trouble keeping track of Lua variables and tables in C++.
 
Thanks, I'm currently fixing the power variable, which was getting mixed up in the GetEngine_ReciprocatingPower and GetEngine_GasTurbinePower functions.
You use one or the other of those functions, not both. They are both provided so different engines can be accommodated.
 
Now I've fixed the functions, and it takes off and flies, but very violently. I need to adjust some variables.
What variables are you messing with? It should fly fine with the engine spec table as it is. If it isn't, something is wrong in your code.
 
What variables are you messing with? It should fly fine with the engine spec table as it is. If it isn't, something is wrong in your code.
I changed:
//Set engine power and rotor thrust

GetEngine_ReciprocatingPower(efficiency, main_fuel_tank, throttle_level);

To:

//Set engine power and rotor thrust

GetEngine_GasTurbinePower(efficiency, main_fuel_tank, throttle_level);

And then it took off. Before that, it wouldn't take off.

This is the updated code:

C++:
void R4::clbkPreStep (double simt, double simdt, double mjd){

    VECTOR3 airspd = _V(0, 0, 0);
    GetAirspeedVector(FRAME_LOCAL, airspd);

    //Get flight control inputs

    pitch = GetControlSurfaceLevel(AIRCTRL_ELEVATOR);

    roll = GetControlSurfaceLevel(AIRCTRL_AILERON);

    tail_rotor_dir = -GetControlSurfaceLevel(AIRCTRL_RUDDER);

    tail_rotor_spec.prop_eff = std::abs(tail_rotor_dir);

    throttle_level = GetThrusterGroupLevel(THGROUP_MAIN);

    main_rotor_spec.prop_eff = GetThrusterGroupLevel(THGROUP_HOVER);
    
    //Set engine power and rotor thrust

    GetEngine_ReciprocatingPower(efficiency, main_fuel_tank, throttle_level);

    double main_rotor_thrust = GetPropeller_Thrust_MainRotor(0.9 * power, airspd.y);

    oapiWriteLogV("%lf", power);

    main_rotor_thrust_vec = GetHelp_Rotate(_V(0, main_rotor_thrust, 0), pitch * 6 * RAD, 0, roll * 6 * RAD);

    AddForce(main_rotor_thrust_vec, operator-(main_rotor_axis, cg));

    //Main rotor axial torque (realistic, but hard to fly with keyboard)

    //main_rotor_torque = main_engine_torque/main_rotor_ratio

    //vi:add_force({x=0, y=0, z=-main_rotor_torque}, {x= 0.5, y=main_rotor_axis.y, z=main_rotor_axis.z})
    //vi:add_force({x=0, y=0, z= main_rotor_torque}, {x=-0.5, y=main_rotor_axis.y, z=main_rotor_axis.z})

    //Get tail rotor thrust and net torque
    double tail_rotor_thrust = GetPropeller_Thrust_TailRotor(0.1 * power, airspd.x);

    VECTOR3 tail_rotor_thrust_vec = _V(tail_rotor_dir * tail_rotor_thrust, 0, 0);

    VECTOR3 tail_rotor_torque = crossp(tail_rotor_thrust_vec, tail_rotor_axis);


    AddForce(_V(0, 0, tail_rotor_torque.y), _V(0.5, main_rotor_axis.y, main_rotor_axis.z));

    AddForce(_V(0, 0, -tail_rotor_torque.y), _V(-0.5, main_rotor_axis.y, main_rotor_axis.z));

    
    //Get drag force on fuselage

    GetPhysics_Drag();

    //Set altitude hold autopilot

    SetAutopilot_Altitude();

    //Set contact points if using floats on either land or water

    if(floats == true){

        SetFeature_CrashOrSplash();

    }

    //Set wheel forces and animations

    if(GroundContact()){

        if(floats == false){

            SetFeature_SetRollingWheels();

            SetFeature_ParkingBrake();

            SetAnim_MainWheels();

            SetAnim_TailWheel();

        } else if(floats == true){

            if(water == false){

                SetAngularVel(_V(0, 0, 0));

            }

        }

    }

    //Set animations

    SetAnim_MainRotor();
    SetAnim_TailRotor();
    SetAnim_AirspeedIndicator();
    SetAnim_Tachometer();
    SetAnim_Altimeter();
    SetAnim_Compass();
    SetAnim_VerticalSpeed();
    SetAnim_ArtificialHorizon();
    SetAnim_FuelIndicator();
    SetAnim_CollectiveIndicator();
    
    //Set lights
    SetPretty_StatusLights();

    if(lights_switched == true){

        SetPretty_NavLights(lights_on);

        SetPretty_SearchLight(lights_on);

    }

    if(light_level_switched == true){

        SetPretty_ClearWindows(); //control inner window reflections

        SetPretty_CabinLights();

        SetPretty_CockpitGlow();

        light_level_switched = false;

    }

}

C++:
void R4::GetEngine_ReciprocatingPower(double efficiency, PROPELLANT_HANDLE fuel_tank_handle, double throttle_level){
 
    //Determines power and torque based on efficiency for Otto and Diesel engines

    //Ambient air properties

    double air_density = GetAtmDensity();

    //Engine specs needed for power calculation
   
    int min_rpm = engine_spec.min_rpm;

    int max_rpm = engine_spec.max_rpm;

    double displacement = engine_spec.displacement;

    int n_stroke = engine_spec.n_stroke;

    double HV = engine_spec.HV;

    double AF = engine_spec.AF;

    if(engine_on == true){

        rpm_comm = min_rpm + throttle_level * (max_rpm - min_rpm);

    } else if(engine_on == false && GroundContact() == false){

        rpm_comm = 0.5 * engine_spec.max_rpm;

    } else if (engine_on == false && GroundContact()){

        rpm_comm = 0;

    }

    if(rpm == 0){

        rpm = rpm + 0.01 * (rpm_comm - rpm);

    } else {

        rpm = rpm_comm;

    }

    //Calculate engine speed (omega in rad/s)
    double omega = rpm * (2 * PI) / 60;

    if(engine_on == true){

        //Calculate air mass flow rate

        double mass_flow_air = air_density * displacement * (2 / n_stroke) * rpm * (1 / 60); //air flow in kg/s
        double mass_flow_fuel = mass_flow_air / AF; //fuel flow in kg/s

        //Update fuel mass in tank

        double fuel_level = GetPropellantMass(fuel_tank_handle) - mass_flow_fuel * oapiGetSimStep();

        SetPropellantMass(fuel_tank_handle, std::max(fuel_level, 0.0));

        if(fuel_level > 0 && throttle_level > 0){

            double QH = mass_flow_fuel * HV;
           
            power = efficiency * QH;
           
            torque = power / omega;

        } else if(fuel_level <= 0){

            engine_on = false;

        }

    } else {
       
        power = 0.0;

        torque = 0.0;

    }

}

void R4::GetEngine_GasTurbinePower(double efficiency, PROPELLANT_HANDLE fuel_tank_handle, double throttle_level){

    //Determines power and torque based on efficiency for Brayton cycle turboshaft engines

    //Ambient air properties

    double air_density = GetAtmDensity();

    double air_density_stp = ATMD; //air density at STP from Orbiter

    //Engine specs needed for power calculation

    int min_rpm = gas_turbine_engine_spec.min_rpm;
   
    int max_rpm = gas_turbine_engine_spec.max_rpm;

    double max_air_flow = gas_turbine_engine_spec.max_air_flow;

    double HV = gas_turbine_engine_spec.HV;

    double AF = gas_turbine_engine_spec.AF;

    VECTOR3 airspd = _V(0, 0, 0);
   
    GetAirspeedVector(FRAME_LOCAL, airspd);


    if(engine_on == true){

        rpm_comm = min_rpm + throttle_level * (max_rpm - min_rpm);

    } else if(engine_on == false && GroundContact() == false){
       

        rpm_comm = ((2*7*airspd.z) / main_rotor_spec.diameter) * (60 / (2 * PI));
        //rpm_comm = 0.5*engine_spec.max_rpm

    } else if(engine_on == false && GroundContact()){

        rpm_comm = 0;

    }

    if(rpm != 0){

        rpm = rpm + 0.002 * (rpm_comm - rpm);

    } else {
       
        rpm = rpm_comm;

    }

    //Calculate engine speed (omega in rad/s)

    double omega = rpm * (2 * PI) / 60;

    if(engine_on == true){

        //Calculate air mass flow rate based on spec air flow and corrected for density

        double mass_flow_air = max_air_flow * (air_density / air_density_stp) * (rpm / max_rpm);
        double mass_flow_fuel = mass_flow_air / AF;
       
        double fuel_level = GetPropellantMass(fuel_tank_handle) - mass_flow_fuel * oapiGetSimStep();

        SetPropellantMass(fuel_tank_handle, fuel_level);

        if(fuel_level > 0 && throttle_level > 0){

            double QH = mass_flow_fuel * HV;

            power = efficiency * QH;

            torque = power / omega;

        } else if(fuel_level <= 0){ //out of fuel

            engine_on = false;

        }

    } else {

        power = 0.0;

        torque = 0.0;

    }

}
 
I changed:
//Set engine power and rotor thrust

GetEngine_ReciprocatingPower(efficiency, main_fuel_tank, throttle_level);

To:

//Set engine power and rotor thrust

GetEngine_GasTurbinePower(efficiency, main_fuel_tank, throttle_level);

And then it took off. Before that, it wouldn't take off.

This is the updated code:

C++:
void R4::clbkPreStep (double simt, double simdt, double mjd){

    VECTOR3 airspd = _V(0, 0, 0);
    GetAirspeedVector(FRAME_LOCAL, airspd);

    //Get flight control inputs

    pitch = GetControlSurfaceLevel(AIRCTRL_ELEVATOR);

    roll = GetControlSurfaceLevel(AIRCTRL_AILERON);

    tail_rotor_dir = -GetControlSurfaceLevel(AIRCTRL_RUDDER);

    tail_rotor_spec.prop_eff = std::abs(tail_rotor_dir);

    throttle_level = GetThrusterGroupLevel(THGROUP_MAIN);

    main_rotor_spec.prop_eff = GetThrusterGroupLevel(THGROUP_HOVER);
   
    //Set engine power and rotor thrust

    GetEngine_ReciprocatingPower(efficiency, main_fuel_tank, throttle_level);

    double main_rotor_thrust = GetPropeller_Thrust_MainRotor(0.9 * power, airspd.y);

    oapiWriteLogV("%lf", power);

    main_rotor_thrust_vec = GetHelp_Rotate(_V(0, main_rotor_thrust, 0), pitch * 6 * RAD, 0, roll * 6 * RAD);

    AddForce(main_rotor_thrust_vec, operator-(main_rotor_axis, cg));

    //Main rotor axial torque (realistic, but hard to fly with keyboard)

    //main_rotor_torque = main_engine_torque/main_rotor_ratio

    //vi:add_force({x=0, y=0, z=-main_rotor_torque}, {x= 0.5, y=main_rotor_axis.y, z=main_rotor_axis.z})
    //vi:add_force({x=0, y=0, z= main_rotor_torque}, {x=-0.5, y=main_rotor_axis.y, z=main_rotor_axis.z})

    //Get tail rotor thrust and net torque
    double tail_rotor_thrust = GetPropeller_Thrust_TailRotor(0.1 * power, airspd.x);

    VECTOR3 tail_rotor_thrust_vec = _V(tail_rotor_dir * tail_rotor_thrust, 0, 0);

    VECTOR3 tail_rotor_torque = crossp(tail_rotor_thrust_vec, tail_rotor_axis);


    AddForce(_V(0, 0, tail_rotor_torque.y), _V(0.5, main_rotor_axis.y, main_rotor_axis.z));

    AddForce(_V(0, 0, -tail_rotor_torque.y), _V(-0.5, main_rotor_axis.y, main_rotor_axis.z));

   
    //Get drag force on fuselage

    GetPhysics_Drag();

    //Set altitude hold autopilot

    SetAutopilot_Altitude();

    //Set contact points if using floats on either land or water

    if(floats == true){

        SetFeature_CrashOrSplash();

    }

    //Set wheel forces and animations

    if(GroundContact()){

        if(floats == false){

            SetFeature_SetRollingWheels();

            SetFeature_ParkingBrake();

            SetAnim_MainWheels();

            SetAnim_TailWheel();

        } else if(floats == true){

            if(water == false){

                SetAngularVel(_V(0, 0, 0));

            }

        }

    }

    //Set animations

    SetAnim_MainRotor();
    SetAnim_TailRotor();
    SetAnim_AirspeedIndicator();
    SetAnim_Tachometer();
    SetAnim_Altimeter();
    SetAnim_Compass();
    SetAnim_VerticalSpeed();
    SetAnim_ArtificialHorizon();
    SetAnim_FuelIndicator();
    SetAnim_CollectiveIndicator();
   
    //Set lights
    SetPretty_StatusLights();

    if(lights_switched == true){

        SetPretty_NavLights(lights_on);

        SetPretty_SearchLight(lights_on);

    }

    if(light_level_switched == true){

        SetPretty_ClearWindows(); //control inner window reflections

        SetPretty_CabinLights();

        SetPretty_CockpitGlow();

        light_level_switched = false;

    }

}

C++:
void R4::GetEngine_ReciprocatingPower(double efficiency, PROPELLANT_HANDLE fuel_tank_handle, double throttle_level){
 
    //Determines power and torque based on efficiency for Otto and Diesel engines

    //Ambient air properties

    double air_density = GetAtmDensity();

    //Engine specs needed for power calculation
  
    int min_rpm = engine_spec.min_rpm;

    int max_rpm = engine_spec.max_rpm;

    double displacement = engine_spec.displacement;

    int n_stroke = engine_spec.n_stroke;

    double HV = engine_spec.HV;

    double AF = engine_spec.AF;

    if(engine_on == true){

        rpm_comm = min_rpm + throttle_level * (max_rpm - min_rpm);

    } else if(engine_on == false && GroundContact() == false){

        rpm_comm = 0.5 * engine_spec.max_rpm;

    } else if (engine_on == false && GroundContact()){

        rpm_comm = 0;

    }

    if(rpm == 0){

        rpm = rpm + 0.01 * (rpm_comm - rpm);

    } else {

        rpm = rpm_comm;

    }

    //Calculate engine speed (omega in rad/s)
    double omega = rpm * (2 * PI) / 60;

    if(engine_on == true){

        //Calculate air mass flow rate

        double mass_flow_air = air_density * displacement * (2 / n_stroke) * rpm * (1 / 60); //air flow in kg/s
        double mass_flow_fuel = mass_flow_air / AF; //fuel flow in kg/s

        //Update fuel mass in tank

        double fuel_level = GetPropellantMass(fuel_tank_handle) - mass_flow_fuel * oapiGetSimStep();

        SetPropellantMass(fuel_tank_handle, std::max(fuel_level, 0.0));

        if(fuel_level > 0 && throttle_level > 0){

            double QH = mass_flow_fuel * HV;
          
            power = efficiency * QH;
          
            torque = power / omega;

        } else if(fuel_level <= 0){

            engine_on = false;

        }

    } else {
      
        power = 0.0;

        torque = 0.0;

    }

}

void R4::GetEngine_GasTurbinePower(double efficiency, PROPELLANT_HANDLE fuel_tank_handle, double throttle_level){

    //Determines power and torque based on efficiency for Brayton cycle turboshaft engines

    //Ambient air properties

    double air_density = GetAtmDensity();

    double air_density_stp = ATMD; //air density at STP from Orbiter

    //Engine specs needed for power calculation

    int min_rpm = gas_turbine_engine_spec.min_rpm;
  
    int max_rpm = gas_turbine_engine_spec.max_rpm;

    double max_air_flow = gas_turbine_engine_spec.max_air_flow;

    double HV = gas_turbine_engine_spec.HV;

    double AF = gas_turbine_engine_spec.AF;

    VECTOR3 airspd = _V(0, 0, 0);
  
    GetAirspeedVector(FRAME_LOCAL, airspd);


    if(engine_on == true){

        rpm_comm = min_rpm + throttle_level * (max_rpm - min_rpm);

    } else if(engine_on == false && GroundContact() == false){
      

        rpm_comm = ((2*7*airspd.z) / main_rotor_spec.diameter) * (60 / (2 * PI));
        //rpm_comm = 0.5*engine_spec.max_rpm

    } else if(engine_on == false && GroundContact()){

        rpm_comm = 0;

    }

    if(rpm != 0){

        rpm = rpm + 0.002 * (rpm_comm - rpm);

    } else {
      
        rpm = rpm_comm;

    }

    //Calculate engine speed (omega in rad/s)

    double omega = rpm * (2 * PI) / 60;

    if(engine_on == true){

        //Calculate air mass flow rate based on spec air flow and corrected for density

        double mass_flow_air = max_air_flow * (air_density / air_density_stp) * (rpm / max_rpm);
        double mass_flow_fuel = mass_flow_air / AF;
      
        double fuel_level = GetPropellantMass(fuel_tank_handle) - mass_flow_fuel * oapiGetSimStep();

        SetPropellantMass(fuel_tank_handle, fuel_level);

        if(fuel_level > 0 && throttle_level > 0){

            double QH = mass_flow_fuel * HV;

            power = efficiency * QH;

            torque = power / omega;

        } else if(fuel_level <= 0){ //out of fuel

            engine_on = false;

        }

    } else {

        power = 0.0;

        torque = 0.0;

    }

}
You must be using the wrong engine specification table. You need to use the one for the reciprocating engine (the one in my code). If you tried guessing numbers and putting them into the gas turbine table that's the only way this would happen.
 
Back
Top