I have been working on an air-breathing jet engine model for Orbiter, and have been using Kev33's Mirage2000 add-on model basically as a test bed to flight test that model. While doing so, I am trying to polish up some of the other functionality of that particular add-on, for self amusement if nothing else.
One thing I am trying to do is enable sensible steering and braking behavior while taxiing, which I know is a challenge with the current API tools. I've found that SetSurfaceFrictionCoeff, SetMaxWheelbrakeForce, and SetNosewheelSteering don't play well with each other at all.
As an example, if you set touchdown points and want to have them behave like a freely rotating wheel, you might set the friction coefficients like this example:
SetSurfaceFrictionCoeff(0.01, 1);
This makes resistance in the longitudinal direction small (rolling wheel), but high laterally (so the wheels don't scrub sideways).
This is all well and good, until you want to apply the brakes or steer. I've done some experimentation with SetMaxWheelbrakeForce, which the API reference says applies a specified brake force in Newtons, but it actually appears to be modified by the longitudinal friction coefficient set by SetSurfaceFrictionCoeff.
The Problems
Braking
So let's say you set the friction coefficients as I did above, and want to specify a braking force of 1000 N. You would think that SetMaxWheelbrakeForce(1000) would deliver 1000 N of braking force when SetWheelBrakeLevel to 1. But what you actually get is 1000 N * 0.01 = 10 N. It's roughly akin to locking up your car brakes on an icy road. So brakes are rendered effective.
Steering
You get the reverse problem when you attempt to use nose wheel steering with the SetNoseWheelSteering function. This applies a lateral steering force to the nose wheel in order to push it left or right based on yaw inputs. But if you specify the surface friction coefficients as I did above to prevent side slipping of the wheels, this actively opposes the nose steering forces. So nose wheel steering is rendered ineffective as well.
Potential Fixes
The braking issue by itself isn't too hard to fix - you could leave the longitudinal friction coefficient alone and just make your braking force 100 times higher (using my example numbers) to deliver the correct braking force. Most folks do this and call it a day.
But that still leaves you with steering problems. If you leave the lateral friction coefficient at 1 to prevent side slipping, it overwhelms the nose steering forces (which, as far as I can tell, are not possible to change or override like the brake forces).
What I am trying to do
So what I am trying to do to beat these issues is to implement differential braking and forgo the use of nose wheel steering, but change the surface friction coefficients when I apply the brakes to enable effective braking and steering. In SetClassCaps I have this entered:
This sets the friction coefficients to mimic a rolling wheel, and sets the brake force to a sensible nominal value. However, I know this won't work as-is for the above reasons. To fix this, in clbkConsumeBufferedKey I have modified the , and . keys to apply brakes like this:
Note that this increases the longitudinal friction coefficient to 1.0 (to enable full braking force application), but also reduces the lateral friction coefficient (to allow the nose wheel to slide sideways).
This works, but I need to restore the surface friction coefficients to their original values when I release the brake keys. Right now I am brute forcing it by this bit of code in clbkPreStep:
This works, but it's obviously clunky as the code has to keep resetting the coefficients each time step, whether needed or not.
The Question
So, the question is, is there a way that I can simply restore the surface coefficients once when I release a key? In pseudo code I'm dreaming for something like this:
Is there a way to use the key release as a trigger to resume the normal coefficients like this?
One thing I am trying to do is enable sensible steering and braking behavior while taxiing, which I know is a challenge with the current API tools. I've found that SetSurfaceFrictionCoeff, SetMaxWheelbrakeForce, and SetNosewheelSteering don't play well with each other at all.
As an example, if you set touchdown points and want to have them behave like a freely rotating wheel, you might set the friction coefficients like this example:
SetSurfaceFrictionCoeff(0.01, 1);
This makes resistance in the longitudinal direction small (rolling wheel), but high laterally (so the wheels don't scrub sideways).
This is all well and good, until you want to apply the brakes or steer. I've done some experimentation with SetMaxWheelbrakeForce, which the API reference says applies a specified brake force in Newtons, but it actually appears to be modified by the longitudinal friction coefficient set by SetSurfaceFrictionCoeff.
The Problems
Braking
So let's say you set the friction coefficients as I did above, and want to specify a braking force of 1000 N. You would think that SetMaxWheelbrakeForce(1000) would deliver 1000 N of braking force when SetWheelBrakeLevel to 1. But what you actually get is 1000 N * 0.01 = 10 N. It's roughly akin to locking up your car brakes on an icy road. So brakes are rendered effective.
Steering
You get the reverse problem when you attempt to use nose wheel steering with the SetNoseWheelSteering function. This applies a lateral steering force to the nose wheel in order to push it left or right based on yaw inputs. But if you specify the surface friction coefficients as I did above to prevent side slipping of the wheels, this actively opposes the nose steering forces. So nose wheel steering is rendered ineffective as well.
Potential Fixes
The braking issue by itself isn't too hard to fix - you could leave the longitudinal friction coefficient alone and just make your braking force 100 times higher (using my example numbers) to deliver the correct braking force. Most folks do this and call it a day.
But that still leaves you with steering problems. If you leave the lateral friction coefficient at 1 to prevent side slipping, it overwhelms the nose steering forces (which, as far as I can tell, are not possible to change or override like the brake forces).
What I am trying to do
So what I am trying to do to beat these issues is to implement differential braking and forgo the use of nose wheel steering, but change the surface friction coefficients when I apply the brakes to enable effective braking and steering. In SetClassCaps I have this entered:
C++:
SetSurfaceFrictionCoeff(0.01, 1.0);
SetMaxWheelbrakeForce(empty_mass * 2.0 * 9.81); //should provide ~2 G braking acceleration
This sets the friction coefficients to mimic a rolling wheel, and sets the brake force to a sensible nominal value. However, I know this won't work as-is for the above reasons. To fix this, in clbkConsumeBufferedKey I have modified the , and . keys to apply brakes like this:
C++:
case OAPI_KEY_COMMA: //Apply left wheel brake using Orbiter default brake key
{
//Increase longitudinal friction so brakes work, but lower lateral friction so nose turns
//Need to reset these coefficients when key is release to mimic rolling wheels.
SetSurfaceFrictionCoeff(1.0, 0.01);
//Apply the brake
SetWheelbrakeLevel(1, 1, false);
return 1;
}
case OAPI_KEY_PERIOD: //Apply right wheel brake using Orbiter default brake key
{
//Increase longitudinal friction so brakes work, but lower lateral friction so nose turns
//Need to reset these coefficients when key is release to mimic rolling wheels.
SetSurfaceFrictionCoeff(1.0, 0.01);
//Apply the brake
SetWheelbrakeLevel(1, 2, false);
return 1;
}
Note that this increases the longitudinal friction coefficient to 1.0 (to enable full braking force application), but also reduces the lateral friction coefficient (to allow the nose wheel to slide sideways).
This works, but I need to restore the surface friction coefficients to their original values when I release the brake keys. Right now I am brute forcing it by this bit of code in clbkPreStep:
C++:
if (GroundContact() == true)
{
SetSurfaceFrictionCoeff(0.01, 1.0);
}
This works, but it's obviously clunky as the code has to keep resetting the coefficients each time step, whether needed or not.
The Question
So, the question is, is there a way that I can simply restore the surface coefficients once when I release a key? In pseudo code I'm dreaming for something like this:
Code:
if (key pressed)
SetSurfaceFrictionCoeff(1.0, 0.01); //set up to brake and steer effectively
SetWheelBrakeForce(1,1); //I have this bit sorted out
if (key released)
SetSurfaceFrictionCoeff(0.01, 1.0); //resume free rolling wheel behavior
Is there a way to use the key release as a trigger to resume the normal coefficients like this?