Orbiter-Forum  

Go Back   Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK
Register Blogs Orbinauts List Social Groups FAQ Projects Mark Forums Read

Orbiter SDK Orbiter software developers post your questions and answers about the SDK, the API interface, LUA, meshing, etc.

Reply
 
Thread Tools
Old 02-15-2020, 07:39 PM   #1
Observation
Orbinaut
Default LKEY usage

Hello everyone,

I am trying to develop an addon and am having trouble with the correct usage of the OAPI_LKEYs. The idea is to have thrus vectoring independent of RCS or AF control.
I tried:
Code:
if (KEYDOWN(kstate, OAPI_LKEY_RCSPitchDown)) {
    // do stuff ...
}
but it doesn't seem to work. The documentation doesn't say anything about usage either I believe.

Now of course, if there's an easier way of finding out pitch, yaw and roll commands, I'll gladly take it...
Observation is offline   Reply With Quote
Old 02-16-2020, 10:10 AM   #2
asbjos
tuanibrO
 
asbjos's Avatar
Default

For thrust vectoring, I found the easiest way to accomplish it was to create dummy RCS thrusters. Then I created control surfaces, which are automatically linked to the user numpad controls.
Finally, you can get the deflection from GetControlSurfaceLevel.
The benefit of this method is that you with the control surfaces get a realistic modeling of thruster delay and movement, without having to implement it yourself.
A drawback is that you have to define an airfoil for the control surfaces to work.

Here is the relevant code:
PHP Code:
// SetClassCaps:
// Dummy RCS for jet vanes and air rudders
th_rcsDummyBooster[0] = CreateThruster(_V(01, -1), _V(010), 0,    propellant_handle00);
th_rcsDummyBooster[1] = CreateThruster(_V(0, -1, -1), _V(0, -10), 0,    propellant_handle00);
th_rcsDummyBooster[2] = CreateThruster(_V(10, -1), _V(100), 0,    propellant_handle00);
th_rcsDummyBooster[3] = CreateThruster(_V(-10, -1), _V(-100), 0,    propellant_handle00);
th_rcsDummyBooster[4] = CreateThruster(_V(10, -1), _V(010), 0,    propellant_handle00);
th_rcsDummyBooster[5] = CreateThruster(_V(10, -1), _V(0, -10), 0,    propellant_handle00);
CreateThrusterGroup(&th_rcsDummyBooster[0], 1THGROUP_ATT_PITCHUP);
CreateThrusterGroup(&th_rcsDummyBooster[1], 1THGROUP_ATT_PITCHDOWN);
CreateThrusterGroup(&th_rcsDummyBooster[2], 1THGROUP_ATT_YAWLEFT);
CreateThrusterGroup(&th_rcsDummyBooster[3], 1THGROUP_ATT_YAWRIGHT);
CreateThrusterGroup(&th_rcsDummyBooster[4], 1THGROUP_ATT_BANKLEFT);
CreateThrusterGroup(&th_rcsDummyBooster[5], 1THGROUP_ATT_BANKRIGHT);

ClearAirfoilDefinitions(); // delete previous airfoils
SetRotDrag(_V(0.250.250.1)); // from BrianJ's Falcon 9
CreateAirfoil3(LIFT_VERTICAL_V(000.1), vliftNULL3.03.0 3.0 PI 4.01.0); // Width from Wikipedia
CreateAirfoil3(LIFT_HORIZONTAL_V(000.1), hliftNULL3.03.0 3.0 PI 4.01.0); // spherical symmetric
Verniers[0] = CreateControlSurface3(AIRCTRL_ELEVATOR0.515 20.0_V(0.00.0, -8.6), AIRCTRL_AXIS_XPOSrudderDelay); // rudder lift is zero, as they do not provide any lift. The foil area could maybe also be zero, but doesn't matter with zero lift anyaway.
Verniers[1] = CreateControlSurface3(AIRCTRL_RUDDER0.515 20.0_V(0.00.0, -8.6), AIRCTRL_AXIS_YPOSrudderDelay);
Verniers[2] = CreateControlSurface3(AIRCTRL_AILERON0.515 20.0_V(0.01.0, -8.6), AIRCTRL_AXIS_YPOSrudderDelay);


...


// Pretty much stolen/borrowed from BrianJ's Falcon9
void rocket::vlift(VESSELvdouble aoadouble Mdouble Revoidcontextdoublecldoublecmdoublecd)
{
    static const 
double step RAD 22.5;
    static const 
double istep 1.0 step;
    static const 
int nabsc 17;
    static const 
double CL[nabsc] = { 00.10.20.100.10.20.10, -0.1, -0.2, -0.10, -0.1, -0.2, -0.1};


    
aoa += PI;
    
int idx max(0min(15, (int)(aoa istep)));
    
double d aoa istep idx;
    *
cl CL[idx] + (CL[idx 1] - CL[idx]) * d;
    *
cm 0.0;

    static const  
double mach[12] = {
        
0.00.500.70.901.001.151.52.03.05.07.09.6
    
};
    static const 
double cdp[12] = { // drag coeff at 0 AoA (tip first) for different mach numbers.
        
0.630.640.640.720.920.90.780.660.460.30.230.18
    
};

    
double aoastep 30.0 RAD;
    
idx max(0min(11, (int)(aoa aoastep)));
    
aoa aoastep idx;

    
int i 0;
    while (
14 && mach[i])
    {
        
i++;
    }

    if (
== 12)
    {
        *
cd cdp[11];
    }
    else if (
== 0)
    {
        *
cd cdp[0];
    }
    else
    {
        *
cd cdp[1] + (cdp[i] - cdp[1]) * (mach[1]) / (mach[i] - mach[1]);
    }

    *
cd *= 0.5;
}

void rocket::hlift(VESSELvdouble betadouble Mdouble Revoidcontextdoublecldoublecmdoublecd)
{
    static const 
double step RAD 22.5;
    static const 
double istep 1.0 step;
    static const 
int nabsc 17;
    static const 
double CL[nabsc] = { 00.10.20.100.10.20.10, -0.1, -0.2, -0.10, -0.1, -0.2, -0.1};

    
beta += PI;
    
int idx max(0min(15, (int)(beta istep)));
    
double d beta istep idx;
    *
cl CL[idx] + (CL[idx 1] - CL[idx]) * d;
    *
cm 0.0;

    static const  
double mach[12] = {
        
0.00.500.70.901.001.151.52.03.05.07.09.6
    
};
    static const 
double cdp[12] = { // drag coeff at 0 AoA (tip first) for different mach numbers.
        
0.630.640.640.720.920.90.780.660.460.30.230.18
    
};

    
double aoastep 30.0 RAD;
    
idx max(0min(11, (int)(beta aoastep)));
    
beta aoastep idx;

    
int i 0;
    while (
14 && mach[i])
    {
        
i++;
    }

    if (
== 12)
    {
        *
cd cdp[11];
    }
    else if (
== 0)
    {
        *
cd cdp[0];
    }
    else
    {
        *
cd cdp[1] + (cdp[i] - cdp[1]) * (mach[1]) / (mach[i] - mach[1]);
    }

    *
cd *= 0.5;
}


...


// PostStep:
SetADCtrlMode(7); // enable adc
double TotalPitch GetControlSurfaceLevel(AIRCTRL_ELEVATOR);
double TotalYaw GetControlSurfaceLevel(AIRCTRL_RUDDER);
double TotalRoll GetControlSurfaceLevel(AIRCTRL_AILERON);

VECTOR3 vernier1Directionvernier2Direction;
if (
TotalRoll != 0.0)
{
    
double deflRo = -TotalRoll 70.0 RAD// play with the sign to get correct direction
    
VECTOR3 t0 _V(VERNIER_EXHAUST_DIR.xVERNIER_EXHAUST_DIR.yVERNIER_EXHAUST_DIR.z);
    
vernier1Direction _V(t0.cos(deflRo) + t0.sin(deflRo), t0.y, -t0.sin(deflRo) + t0.cos(deflRo));
    
SetThrusterDir(th_vernier[0], vernier1Direction);
    
t0 FlipY(t0);
    
vernier2Direction _V(t0.cos(-deflRo) + t0.sin(-deflRo), t0.y, -t0.sin(-deflRo) + t0.cos(-deflRo));
    
SetThrusterDir(th_vernier[1], vernier2Direction);

    if (
VesselStatus == LAUNCH || VesselStatus == TOWERSEP// get help from the two booster engines
    
{
        
// Thrust gimbal of booster thrusters. Swiveled max 5 deg in pitch and yaw (19630012071 page 97(
        
VECTOR3 thrustDirection;
        
thrustDirection.cos(TotalRoll 5.0 RAD);
        
thrustDirection.sin(-TotalRoll 5.0 RAD); // negative because it was inverted
        
thrustDirection.0.0;
        
SetThrusterDir(th_booster[0], thrustDirection);
        
SetThrusterDir(th_booster[1], FlipY(thrustDirection));
    }
}
else
{
    
double deflPi TotalPitch 25.0 RAD;
    
double deflYa = -TotalYaw 70.0 RAD// play with the sign to get correct direction
    
VECTOR3 t0 VERNIER_EXHAUST_DIR;
    
vernier1Direction _V(t0.cos(deflYa) + (t0.cos(deflPi) + t0.sin(deflPi)) * sin(deflYa), t0.cos(deflPi) - t0.sin(deflPi), cos(deflYa) * (t0.sin(deflPi) + t0.cos(deflPi)) - t0.sin(deflYa));
    
SetThrusterDir(th_vernier[0], vernier1Direction);
    
t0 FlipY(t0);
    
vernier2Direction _V(t0.cos(deflYa) + (t0.cos(deflPi) + t0.sin(deflPi)) * sin(deflYa), t0.cos(deflPi) - t0.sin(deflPi), cos(deflYa) * (t0.sin(deflPi) + t0.cos(deflPi)) - t0.sin(deflYa));
    
SetThrusterDir(th_vernier[1], vernier2Direction);

    if (
VesselStatus == LAUNCH || VesselStatus == TOWERSEP// get help from the two booster engines
    
{
        
// Thrust gimbal of booster thrusters. Swiveled max 5 deg in pitch and yaw
        
t0 BOOSTER_EXHAUST_DIR;
        
deflPi TotalPitch 5.0 RAD;
        
deflYa = -TotalYaw 5.0 RAD// play with the sign to get correct direction
        
VECTOR3 booster1Direction _V(t0.cos(deflYa) + (t0.cos(deflPi) + t0.sin(deflPi)) * sin(deflYa), t0.cos(deflPi) - t0.sin(deflPi), cos(deflYa) * (t0.sin(deflPi) + t0.cos(deflPi)) - t0.sin(deflYa));
        
SetThrusterDir(th_booster[1], booster1Direction);
        
SetThrusterDir(th_booster[0], booster1Direction);
    }

    
// Thrust gimbal of core thruster. Swiveled max 3 deg in pitch and yaw
    
t0 CORE_EXHAUST_DIR;
    
deflPi TotalPitch 3.0 RAD;
    
deflYa = -TotalYaw 3.0 RAD// negative because it was inverted
    
VECTOR3 coreDirection _V(t0.cos(deflYa) + (t0.cos(deflPi) + t0.sin(deflPi)) * sin(deflYa), t0.cos(deflPi) - t0.sin(deflPi), cos(deflYa) * (t0.sin(deflPi) + t0.cos(deflPi)) - t0.sin(deflYa));
    
SetThrusterDir(th_maincoreDirection);

asbjos is offline   Reply With Quote
Old 02-16-2020, 11:09 AM   #3
Observation
Orbinaut
Default

That looks interesting, although it does not allow for other control surfaces to be turned off, as my vehicle has some. Creating fake RCS or AF requires at least one of them to be turned on, so if we want to have both off, we need to create another user command for switching between fake and real, without going through the default Orbiter interface, making it confusing / unclean (yes, I'm a perfectionist :-)).
Also, does it make a difference if we put all that control code in preStep or postStep other that knowing deltaT, eg. for thruster delay. Does it change anything on the Orbiter side?
Observation is offline   Reply With Quote
Old 02-16-2020, 12:18 PM   #4
asbjos
tuanibrO
 
asbjos's Avatar
Default

But if you then want thrust vectoring to be independent of your RCS and control surfaces, why do you need to consider that input at all?
If I understand your situation correctly, you want to control your craft manually, while the engine does some gimbaling magic at the same time. Or is that interpretation false?

Quote:
Originally Posted by Observation View Post
 Also, does it make a difference if we put all that control code in preStep or postStep other that knowing deltaT, eg. for thruster delay. Does it change anything on the Orbiter side?
If my understanding of the flowchart by martins is correct ( https://www.orbiter-forum.com/showth...01&postcount=7 ), it should not matter if you put it in PreStep or PostStep, as you then either use the data from last frame to edit the state in the current frame (pre), or use data from current frame to edit the state in the next frame (post).
So probably no big deal whatever you decide, but I could be wrong, though.
asbjos is offline   Reply With Quote
Thanked by:
Old 02-16-2020, 12:42 PM   #5
Observation
Orbinaut
Default

I would like to get pitch, yaw and roll input for engine gimballing while having both RCS and AF turned off.

Thanks for the explanation on preStep and postStep!
Observation is offline   Reply With Quote
Reply

  Orbiter-Forum > Orbiter Space Flight Simulator > Orbiter SDK


Thread Tools

Posting Rules
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
Forum Jump


All times are GMT. The time now is 11:09 PM.

Quick Links Need Help?


About Us | Rules & Guidelines | TOS Policy | Privacy Policy

Orbiter-Forum is hosted at Orbithangar.com
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.
Copyright 2007 - 2017, Orbiter-Forum.com. All rights reserved.