API Question intercepting users thrusterlevel control

Mindblast

Donator
Donator
Joined
Aug 29, 2008
Messages
171
Reaction score
0
Points
16
Location
Berlin
Website
www.nestadlinn.de
I'm trying to simulate a Turbofan-like airbreathing engine and what i would like to do is simulate up- and downramping of the fan rotation speed. So i was looking for a way to intercept the thrust level set by user interaction (joystick throttle, +- buttons) to get the thrust level the user was aiming for and then slowly ramping the actual thrust level towards this value. I thought i had found a way to do this using SetThrusterLevel_SingleStep but unfortunately there is a bug with that.
One other way i could imagine is to set a main thruster with almost no thrust, read the users thrust value from that and apply it to an internal thruster. But that would prevent MFDs like IMFD from reading out the max thrustlevel of my ship.

I wonder if anybody has found a good way of doing this ?
 

Tommy

Well-known member
Joined
Aug 14, 2008
Messages
2,021
Reaction score
84
Points
48
Location
Here and now
Assuming you'll also have normal rocket engines for orbital and interplanetary flight, I'd define them as the "main" thrusters. The Turbofan mode would be a seperate thruster as far as the code is concerned. When you are in Turbofan mode you should be able to use the throttle setting to regulate the Turbofan. The Rocket is another matter. You could assign it to an empty propellant resource, but then I'm not sure you can intercept throttle settings, I think Orbiter will automatically zero the throttle every step if the prop resource is empty. A more complicated solution would be to do the following when in Turbofan mode:

Change the main engin exhaust texture to a transparent texture. Change the main engine sound to a custom sound (silence), and apply a force equal to the main engines thrust opposite the main engines thrust vector (cancelling out the main engin thrust). This should be allow IMFD to read the max thrust and make it's course predictions, etc.
 

EtherDragon

Addon Developer
Addon Developer
Joined
Mar 20, 2008
Messages
106
Reaction score
0
Points
0
Location
Ellensburg
Don't muck around with counter forces and the like...

Make a single thruster in your MAIN group with very small force. (like 0.01kn or something) and control another USER group of thrusters respond in your call-back prestep;

double userThrottle = GetThrusterGroupLevel(THGROUP_MAIN);
... do some stuff to figure out how much to increase the thrust of ...
SetThrusterGroupLevel(THGROUP_USER, outputThrottle);
 

francisdrake

Addon Developer
Addon Developer
Joined
Mar 23, 2008
Messages
798
Reaction score
207
Points
58
Website
francisdrakex.deviantart.com
This is how I ramp the thrust level down and up again:

Time t is the control parameter (elapsed time since liftoff).
Until 20 sec full thrust is applied.
Between 20 and 50 sec the thrust is reduced and then held at a minimum level.
Between 50 and 85 sec the thrust is increased again.

int t = (int) (simt - t_start);
...
if (t < 20) {
SetThrusterLevel( th_main, 1); // SRB full throttle at start
return;
}
if (t < 50) {
if (GetThrusterGroupLevel(THGROUP_MAIN) > 0.82 ) // throttle back for maxQ
IncThrusterGroupLevel( THGROUP_MAIN, -0.0006);
return;
}
if (t < 85) {
if (GetThrusterGroupLevel(THGROUP_MAIN) < 0.93 ) // throttle up
IncThrusterGroupLevel( THGROUP_MAIN, 0.0004);
return;
}

There is one slight disadvantage to it:
If the user moves the throttle, the thrust 'jumps' to the throttle setting, and starts then to be adjusted again. I never bothered intercepting this. The message is simple: Apply full thrust (with the throttle) and then let the auto-engine regime do its job.

Maybe you could intercept the trottle setting and use it as the target level to adjust the thrust to.

And maybe you should not use "clbkPostStep" for the loop, but intercept the throttle before the timestep is executed (with "clbkPreStep")
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,632
Reaction score
2
Points
0
If the user moves the throttle, the thrust 'jumps' to the throttle setting, and starts then to be adjusted again. I never bothered intercepting this. The message is simple: Apply full thrust (with the throttle) and then let the auto-engine regime do its job.
This would be a relatively easy thing to fix: remember what the thrust was last time and set it to that before adjusting it further.
 

EtherDragon

Addon Developer
Addon Developer
Joined
Mar 20, 2008
Messages
106
Reaction score
0
Points
0
Location
Ellensburg
That's a good thought, actually... no need for a THGROUP_USER at all.

In callbackprestep the thruster level for the engine has been set by Orbiter, but not applied to the physics engine. If you compare that to some variable you stored previously, then you could see if the user wants to throttle up or down - and spool accordingly.

Something like... (written in c# for shorthand you can convert it to C++ easily)
Assume:
previousThrottle is a class level variable
throttleChangePerSecond is a class level variable = 0.1 (10 seconds from 0.0 to 1.0)

double requestThrottle = GetThrusterGroupLevel(THGROUP_MAIN);
double throttleChangePerTick = throttleChangePerSecond * oapiGetTimeStep();
double newThrottle = previousThrottle;

if (requestThrottle > previousThrottle)
{
double newThrottle = previousThrottle + throttleChangePerTick;
SetThrusterGroupLevel(THGROUP_MAIN, newThrottle > requestThrottle ? requestThrottle : newThrottle);
}
else
{
double newThrottle = previousThrottle - throttleChangePerTick;
SetThrusterGroupLevel(THGROUP_MAIN, newThrottle < requestThrottle ? requestThrottle : newThrottle);
}
 
Last edited:

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,632
Reaction score
2
Points
0
That's a good thought, actually... no need for a THGROUP_USER at all.

In callbackprestep the thruster level for the engine has been set by Orbiter, but not applied to the physics engine. If you compare that to some variable you stored previously, then you could see if the user wants to throttle up or down - and spool accordingly.

Something like... (written in c# for shorthand you can convert it to C++ easily)
Assume:
previousThrottle is a class level variable
throttleChangePerSecond is a class level variable = 0.1 (10 seconds from 0.0 to 1.0)

double requestThrottle = GetThrusterGroupLevel(THGROUP_MAIN);
double throttleChangePerTick = throttleChangePerSecond * oapiGetTimeStep();
double newThrottle = previousThrottle;

if (requestThrottle > previousThrottle)
{
double newThrottle = previousThrottle + throttleChangePerTick;
SetThrusterGroupLevel(THGROUP_MAIN, newThrottle > requestThrottle ? requestThrottle : newThrottle);
}
else
{
double newThrottle = previousThrottle - throttleChangePerTick;
SetThrusterGroupLevel(THGROUP_MAIN, newThrottle < requestThrottle ? requestThrottle : newThrottle);
}
- You're never setting previousthrottle to anything
- Once you've set the thrustergrouplevel once, you'll override the user input setting until the move the joystick again, so "requestthrottle" will just be whatever you set last step.

When you detect that the throttle has moved through some means other than your code, set that as your "target throttle" and then spool toward that.
 

Mindblast

Donator
Donator
Joined
Aug 29, 2008
Messages
171
Reaction score
0
Points
16
Location
Berlin
Website
www.nestadlinn.de
I tried something along those lines a while back:

double thrusterLevel = this->pVessel->GetThrusterLevel(this->th);
if(thrusterLevel != this->curThrustLevel)
{
this->userThrustLevel = thrusterLevel;
}

if(this->userThrustLevel != this->curThrustLevel)
{
double thrustLvlDif = this->curThrustLevel - this->userThrustLevel;
double thrustChangeSign = this->curThrustLevel < this->userThrustLevel?1:-1;
this->curThrustLevel += thrustChangeSign * min(simdt * 0.2, abs(thrustLvlDif));
this->pVessel->SetThrusterLevel(this->th, this->curThrustLevel);
}

This was a quick hack and worked a bit clumsy though, especially when using a Joystick throttle i had some problems. I guess I'll look into it again now but i think the counterforce approach is quite nice too.
 
Top