Preventing Creep with Breaks Set and Allowing Idle Taxi

#1
Hey folks,

Just thought I'd share this. The code below is what we used in the 717 to prevent creeping with the brakes (either parking brake or toe brakes) with high thrust to allow static takeoffs. It also allows the aircraft to continue rolling after picking up some speed taxiing, giving it a more natural idle taxi effect. It also reads the surface type to determine whether or not it is reasonable to be able to idle taxi/glide (i.e. not so much on grass, etc.). It's by no means perfect, but it does the trick.

How it Works
Brake Creep Prevention: It reads thrust and brakes and conditionally sets the velocity to 0.
Idle Taxi/Friction Reduction: It uses the basic F=MA (force equals mass times acceleration) rule of physics combined with aircraft specific tuners to determine speeds and blends smoothly up until built-in acceleration can take over.

Note: To use this, you will need a basic understanding of SimConnect and C++, as it must be part of a C++ gauge.

C++:
//scdata is a SimConnect data struct
//relevant pieces of it are shown below

//on_ground
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "SIM ON GROUND", "bool");
//ground_speed
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "GROUND VELOCITY", "knots");
//l_brake
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "BRAKE LEFT POSITION", "percent");
//r_brake
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "BRAKE RIGHT POSITION", "percent");
//park_brake_indicator
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "BRAKE PARKING INDICATOR", "bool");
//l_thrust
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "TURB ENG JET THRUST:1", "pounds");
//r_thrust
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "TURB ENG JET THRUST:2", "pounds");
//total_weight
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "TOTAL WEIGHT", "pounds");
//surface_type
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "SURFACE TYPE", "number");
//vel_body_z
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_READ, "RELATIVE WIND VELOCITY BODY Z", "knots");


//the definition of SIM_DEFINITION_DATA_WRITE_Z_VELOCITY is this
SimConnect_AddToDataDefinition(hSimConn, SIM_DEFINITION_DATA_WRITE_Z_VELOCITY, "VELOCITY BODY Z", "feet per second");

//first_simconnect_frame_handled is just a flag set after the first time scdata is updated to ensure we're not using bad/default data - may not apply to all cases

//force_mod, mass_mod, and accel_mod can be used to tweak the behavior of the aircraft.

if (scdata->on_ground == TRUE && scdata->ground_speed <= 40 && first_simconnect_frame_handled == true) {
        double brake = ((scdata->l_brake + scdata->r_brake) / 200.0);
        brake = max(scdata->park_brake_indicator, brake);
        brake = min(brake, 1.0);

        double speed = 0;
        bool use_accel = brake < 0.1 && scdata->l_thrust >= 0 && scdata->r_thrust >= 0;
        switch ((int)scdata->surface_type) {
        case 1: //grass
        case 2: //water
        case 3: //grass_bumpy
        case 5: //short grass
        case 6: //long grass
        case 7: //hard turf
        case 8: //snow
        case 10: //urban
        case 14: //gravel
        case 21: //sand
            use_accel = false;
            break;
        }

        if (use_accel == true) {
            //F = M*A
            //A = F/M
            //F = thrust
            //M = total weight
           
            static double force_mod = 20.0;
            static double mass_mod = 1.0;
            static double accel_mod = 1.0;

            double force = (scdata->l_thrust + scdata->r_thrust) * force_mod;
            double mass = scdata->total_weight * mass_mod;
            double accel = (force / mass) * accel_mod;      

            if (accel > 0) {
                accel *= 0.592484; //feet per second per second
                speed = scdata->vel_body_z + (accel * sctimediff);
               
                SimConnect_SetDataOnSimObject(hSimConn, SIM_DEFINITION_DATA_WRITE_Z_VELOCITY, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(double), &speed);
            }
        }
        else {
            if (fabs(scdata->vel_body_z) < 1.0 && brake > 0.8) {
                SimConnect_SetDataOnSimObject(hSimConn, SIM_DEFINITION_DATA_WRITE_Z_VELOCITY, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(double), &speed);
            }
        }
    }
 

DragonflightDesign

Resource contributor
#2
Just a thought... what if you modified the code so that force_mod, mass_mod and accel_mod were read from the panel.cfg as parameters? It would save a bit (probably not much!) time between tweaks as you wouldn't have to recompile the project.
 

Heretic

Resource contributor
#3
Yep, a separate config file would be a nice idea (not the panel.cfg though).

I figure that all of this can also be done in XML via XMLTools, albeit at the 18Hz update rate used by 2D gauges.
 

rcbarend

Resource contributor
#5
I don't think it would work as well at 18hz... just my thought.
IMO that depends on the update rate at which SimConnect is commanded.
If the VelocityZ calculations are done at 18 Hz and the commanding of SimConnect is done at actual framerate, I think it will work as intended.
Not sure though, if XMLtools commands SimConnect at 18 Hz or at actual frame rate.

And to the OP:
Since I'm an XML programmer, I don't fully understand the C++ code.
But the idea of making the ground-acceleration dependant on surface-type, really is a good one. And thanks for sharing...

But as a sidenote: if I see texts like "Ground Velocity" and " SIM_DEFINITION_DATA_WRITE_Z_VELOCITY"
I assume you are overwriting the FS-FDE-calculated value of VELOCITY BODY Z. Right ?
If so:

Not sure what you mean by "static takeoffs".
If you mean "takeoff on static (== non-moving) surfaces: Ok.
But if not:
it doesn't work on for takeoffs /"creeping" on moving surfaces, like on a deck of a moving aircraft carrier.
Since overwiting VELOCITY BODY Z is commanding speed relative to the earth surface, not relative to the speed of the carrier.

Hence, my confusion on what you mean with the term "static takeoff".
Since anticipating takeoff of a Boeing-717 off an aircraft carrier isn't very likely ... LoL

Best regards,

Rob
 

Heretic

Resource contributor
#6
Static takeoff: Brakes set, engines spooled, brakes released, starting roll.
Rolling takeoff: No brakes, engines spooling while rolling.
 

Roy Holmes

Resource contributor
#7
This all assumes you have the correct idle thrust. It can simply be adjusted in the .air file.
The chain for idle thrust is:
Idle CN2% is set in Record 1503
1502 gives the CN1% idle from the 1503 CN2% idle
Idle thrust comes from static thrust (aircraft.cfg) times the scalar in 1506 for the CN1% idle.
So to reduce idle thrust you can reduce the CN1 scalar in 1506. Not too much because that could affect combustion on start-up.
As a fast jet operator I'm rather surprised that you could have take-off power set without the brakes slipping.
And how often does a 717 taxi on anything other than a hard surface?
Roy
 
#8
@Heretic and @DragonflightDesign I left it as a static variable so I can easily edit it in a debugger but a user can't tweak it. In my opinion, that isn't an "option", it's an essential parameter to be setup by the developers.
@rcbarend Agreed - I didn't think about carriers. As you said, carriers really aren't a thought for airliners...lol. Yes, it overwrites (or, "alters") the default calculated airspeed. It will gradually release control back to the sim as you accelerate to avoid jumpiness.
@Roy Holmes The problem with doing it solely with idle thrust is that default ground friction is WAY too high, so setting idle thrust low enough to match descent profiles means it's a brick on the ground. And yes, static takeoffs do happen somewhat often and the aircraft does not move very far (if at all) down the runway. The surface type is just for completeness, should you ever land on a dirt strip, taxi in the grass, whatever it may be. These may not be ideal situations, but I wanted to do a thorough job on this (especially if it is to be reused in other aircraft).
 

Heretic

Resource contributor
#9
@Heretic and @DragonflightDesign I left it as a static variable so I can easily edit it in a debugger but a user can't tweak it. In my opinion, that isn't an "option", it's an essential parameter to be setup by the developers.
Cue users complaining that the values are unrealistic and inquiring how they can be tweaked.
Believe me, it'd be less work for you in the long run to simply set it up like that and, more importantly, it'll avoid lengthy discussions.
 
#10
At this point, I'm used to being complained at; it's part of the job... lol. That said, yes, you could modify it to read from another location if that's the way the project needs to be setup.
 

Roy Holmes

Resource contributor
#12
The problem with doing it solely with idle thrust is that default ground friction is WAY too high, so setting idle thrust low enough to match descent profiles means it's a brick on the ground.
If idle thrust that just gets the airplane moving (assuming that is what actually happens for that specific airplane) is too low in the descent , it means one of two things.
1. The CN2 idle value from 1504 which is Mach dependent is too high because the table was incorrectly constructed or
2. You have insufficient drag.
Roy
 
Top