Special Aircraft Service

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1]   Go Down

Author Topic: Experimenting with imparting large, random control deflection with damage  (Read 460 times)

0 Members and 1 Guest are viewing this topic.

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040

I've been experimenting some more with controls damage code. Including the creation of a new method by which to randomly impart deflection to one or more of the ailerons, elevator and rudder, instead of always neutralizing them when damaged. This is in addition to the earlier work to inspire the bots to hit the silk more often, instead of so frequently riding their mount to their doom for no good reason.


Output of the controls damage events in log.lst (for testing only) for the plane illustrated here (I.D. "E"). In the image, note the downward elevator deflection (-76.5%) and the aileron deflection to impart a clockwise roll (+88.8%).

[2024-03-18 02:40:53.112]   dT: 3001   Ail_ctrl_hit  Ailerons:0.88807946 E
[2024-03-18 02:40:53.112]   dT:    0   Ail cut----bail, Rud_ctl?true E
[2024-03-18 02:40:53.112]   dT:    0   Elev_ctrl_hit  Elevators:-0.7649691 E
[2024-03-18 02:40:53.112]   dT:    0   Elev_no_BMP E
[2024-03-18 02:40:53.112]   dT:    0   Elev_cut----bail, VSI(m/s):12.484061129024585 E




My new method, Controls.anchorControl(). The existing method, Controls.resetControl() was always called from AircraftState() when a control was hit. It neutralizes the control deflection, but I wanted to sometimes impart a fairly large deflection. I now apply a randomness to call either this or my new method. At the moment the deflection is set to between 70% and 99%, with a 50% chance of being in one direction or the other.
Code: [Select]
public void resetControl(int i)
{
switch(i)
{
case 0: // '\0'
AileronControl = 0.0F;
Ailerons = 0.0F;
trimAileron = 0.0F;
break;

case 1: // '\001'
ElevatorControl = 0.0F;
Elevators = 0.0F;
trimElevator = 0.0F;
break;

case 2: // '\002'
RudderControl = 0.0F;
Rudder = 0.0F;
trimRudder = 0.0F;
break;
}
}

public void anchorControl(int i)
{
switch(i)
{
case 0: // '\0'
AileronControl = 0.0F;
Ailerons = TrueRandom.nextFloat (0.7F, 0.99F);
if(TrueRandom.nextFloat() < 0.5F)
Ailerons *= -1;
trimAileron = 0.0F;
break;

case 1: // '\001'
ElevatorControl = 0.0F;
Elevators = TrueRandom.nextFloat (0.7F, 0.99F);
if(TrueRandom.nextFloat() < 0.5F)
Elevators *= -1;
trimElevator = 0.0F;
break;

case 2: // '\002'
RudderControl = 0.0F;
Rudder = TrueRandom.nextFloat (0.7F, 0.99F);
if(TrueRandom.nextFloat() < 0.5F)
Rudder *= -1;
trimRudder = 0.0F;
break;
}
}


The stock AircraftState.doSetControlsDamage(). There are no invocations of bailouts to be found here, and so too many crew brainlessly stay with the plane as it plunges to earth.
Code: [Select]
private void doSetControlsDamage(int i, Actor actor1)
{
switch(i)
{
case 0: // '\0'
aircraft.FM.CT.resetControl(0);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasAileronControl)
HUD.log("FailedAroneAU");
aircraft.FM.CT.bHasAileronControl = false;
aircraft.FM.setCapableOfACM(false);
break;

case 1: // '\001'
aircraft.FM.CT.resetControl(1);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasElevatorControl)
HUD.log("FailedVatorAU");
aircraft.FM.CT.bHasElevatorControl = false;
aircraft.FM.setCapableOfACM(false);
if(Math.abs(aircraft.FM.Vwld.z) > 7D)
aircraft.FM.setCapableOfBMP(false, actor1);
break;

case 2: // '\002'
aircraft.FM.CT.resetControl(2);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasRudderControl)
HUD.log("FailedRudderAU");
aircraft.FM.CT.bHasRudderControl = false;
break;

default:
throw new RuntimeException("(" + aircraft.typedName() + ") A.S.: Corrupt data in (C.A.D./null)");
}
}


My modded AircraftState.doSetControlsDamage(). I have added new code to invoke a rather higher probability of AI bailouts, to greatly reduce the number of the little silicon bots calmly riding their damaged crate to destruction for no good reason. Here I randomly call my new method, Controls.anchorControl() instead of the usual resetControl(), in order to impart large control deflections for a more exciting plunge.   ;D
Code: [Select]
private void doSetControlsDamage(int i, Actor actor1)
{
switch(i)
{
case 0: // '\0'  //AILERON
if(TrueRandom.nextFloat() < 0.5F)
aircraft.FM.CT.resetControl(0);
else
aircraft.FM.CT.anchorControl(0);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasAileronControl)
HUD.log("FailedAroneAU");
aircraft.FM.CT.bHasAileronControl = false;
aircraft.FM.setCapableOfACM(false);
Aircraft.debugprintln(aircraft, "Aileron control damaged! ");
if((!(aircraft.FM.CT.bHasRudderControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3) || TrueRandom.nextInt(0, 99) < 50 + aircraft.FM.subSkill * 3)
{
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Aileron control cut, bailing out! ");
hitDaSilk();
}
break;


case 1: // '\001'  //ELEVATOR
if(TrueRandom.nextFloat() < 0.5F)
aircraft.FM.CT.resetControl(1);
else
aircraft.FM.CT.anchorControl(1);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasElevatorControl)
HUD.log("FailedVatorAU");
aircraft.FM.CT.bHasElevatorControl = false;
aircraft.FM.setCapableOfACM(false);
if(Math.abs(aircraft.FM.Vwld.z) > 7D)
{
aircraft.FM.setCapableOfBMP(false, actor1);
}
Aircraft.debugprintln(aircraft, "Elevator control damaged! ");
if(Math.abs(aircraft.FM.Vwld.z) < -21D || TrueRandom.nextInt(0, 99) < 75 + aircraft.FM.subSkill * 3)
{
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Elevator control cut, bailing out! ");
hitDaSilk();
}
break;


case 2: // '\002'  //RUDDER
if(TrueRandom.nextFloat() < 0.5F)
aircraft.FM.CT.resetControl(2);
else
aircraft.FM.CT.anchorControl(2);
if(aircraft.FM.isPlayers() && aircraft.FM.CT.bHasRudderControl)
HUD.log("FailedRudderAU");
aircraft.FM.CT.bHasRudderControl = false;
Aircraft.debugprintln(aircraft, "Rudder control damaged! ");
if((!(aircraft.FM.CT.bHasAileronControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3) || TrueRandom.nextInt(0, 99) < 10 + aircraft.FM.subSkill * 2)
{
aircraft.FM.setCapableOfACM(false);
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Rudder control cut, bailing out! ");
hitDaSilk();
}
break;


default:
throw new RuntimeException("(" + aircraft.typedName() + ") A.S.: Corrupt data in (C.A.D./null)");
}
}
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

Ol Willy

  • member
  • Offline Offline
  • Posts: 80

Interesting idea, but I have one comment.

WW2 aircraft usually had control surfaces connected to pilot controls directly trough cables, pulleys or rigid rods. No amplifiers or any "intermediaries", everything was moved purely by muscle power. Thus, if those connecting cables or rods were interrupted, control surfaces tended to just move around freely under the influence of the relative wind - which most often was to remain around default position.

But - if the pilot was killed, let's say, his body slums forward on the stick, plunging the plane downwards.

So, if realism is considered, I think this feature should be reserved only for the aircraft where pilot was killed and didn't bail out

Logged

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040

Such considerations were in front of mind.

The imparting of damage is necessarily simplistic. As implemented, damage to flight controls is always treated as full loss of control as though a linkage was severed. It's a fact that damage can cause a 'jamming' that impedes operation, leading to a control surface stuck in position.

Already simple randomization is widely applied, for all manner of actions. My approach is to add further variety to the manifestation of damage, hopefully within the bounds of the possible, and without necessarily introducing a degree of complexity that requires consideration of a host of  additional variables.

If a control can become stuck whether a pilot is present or not--dead or alive--then application of a simple randomness can have merit.

I can tune the frequency of occurrence, as well as apply one or both of a wider range of deflection and less severe deflection. This early stage is to verify that the concept is working as intended, by clearly seeing the result in action.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

Ol Willy

  • member
  • Offline Offline
  • Posts: 80

It's a fact that damage can cause a 'jamming' that impedes operation, leading to a control surface stuck in position.
Ahh, of course, a damaged piece of wing spar or other structural elements could be lodged in a way to jam the connecting cables or rods. I overlooked about such possibility

I gotta say this gonna be a very interesting addition for player too. It's one thing to try to get home with disabled control surfaces, but a different challenge if they are stuck in some position
Logged

SAS~Storebror

  • Editor
  • member
  • Offline Offline
  • Posts: 23933
  • Taking a timeout
    • STFU

I appreciate your perspective, however the likelihood of a control surface getting stuck due to damage to the cables, pulleys, or rods is quite low, perhaps around 5% at most.

There are a few scenarios that could potentially cause a control surface to get stuck, but each is quite rare:

  • Bent Control Rod: This could occur if there's adjacent damage that bends the rod but doesn't break it. There's only one known instance where I remember that this was happening.
  • Obstructed Gap: Parts of the plane could become damaged or loose and block the gap between a control surface and the attached wing or stabiliser edge. While this could theoretically happen, the specific circumstances required make it extremely unlikely.
  • Blocked Control Cable/Pulley: A control cable or pulley could get deflected or blocked by damaged parts of the plane's internal structure. However, there are no known instances of this occurring.

On the flip side, there are numerous accounts of incidents where the controls were damaged and yet remained in a neutral position afterwards. You can find more information about these incidents on https://en.wikipedia.org/wiki/Flight_with_disabled_controls.

In small airplanes, the control surfaces are usually of the simplest possible design, piano-hinged to the upper or lower skin and operated by cockpit controls of standardized size and travel. As airplanes get bigger and faster, their controls get harder to move and the design of unpowered control systems becomes more and more of a challenge.
In some old airplanes - again before the era of powered controls - the pilots’ yoke was actually connected to the servo tab (a mini control surface, also called a control tab), not to the main control surface. This type of pilot-controlled tab, which was first used to move the rudders of ships, is called a Flettner tab. Here too, if the pilot’s input to the servo tab was lost, the tab will go to zero deflection in the airflow due to static balance, and the main control surface will follow along and also go to zero deflection.
In case of power-operated control surfaces, the power-pack is so designed that severance of input will cause the actuator to bring the control to neutral.
These requirements are usually combined together in one mechanism named the "trim, centering, and feel" mechanism.

In conclusion, while it's important to be aware of the potential risks and to maintain the control systems properly, the probability of a control surface getting stuck due to damage to the cables, pulleys, or rods is very low.

More stuff to read on the topic:
https://www.aopa.org/news-and-media/all-news/2017/september/11/maintaining-flight-control-cables
https://www.aopa.org/news-and-media/all-news/2017/october/02/maintaining-flight-control-cables-part-3

]cheers[
Mike
Logged
Don't split your mentality without thinking twice.

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040

After some more tweaking...

I've set, for the moment, a 20% chance of a locked control. In my new method, aircraft.FM.CT.anchorControl(), I've expanded the randomized range of deflection from 0.7-0.99 to 0.33-0.99.

I also perform a check on whether the control has already been disabled (including locked), and if so do not again call methods aircraft.FM.CT.resetControl() and my new method, aircraft.FM.CT.anchorControl(), which would be redundant. Previously they would be called for every qualifying hit, thus only increasing the chance for my new method causing a locking of the control to a certain deflection.


My current AircraftState.doSetControlsDamage() (including the System.out commands for output to log.lst).
Code: [Select]
private void doSetControlsDamage(int i, Actor actor1)
{
switch(i)
{
case 0: // '\0'  //AILERON
if(aircraft.FM.CT.bHasAileronControl)  //does not get assessed after first setting of failed control
{
if(TrueRandom.nextFloat() < 0.8F)
aircraft.FM.CT.resetControl(0);  //normal action; sets Ailerons, AileronControl and trimAileron to 0
else
{
aircraft.FM.CT.anchorControl(0);  //NEW method to impart a 'jammed' control with a random deflection
bLockedAileron = true;
}
if(aircraft.FM.isPlayers())
HUD.log("FailedAroneAU");
aircraft.FM.CT.bHasAileronControl = false;
aircraft.FM.setCapableOfACM(false);
System.out.println("Ail_ctrl_hit, " + " Ailerons:" + aircraft.FM.CT.getAileron() + "   " + aircraft.typedName());
Aircraft.debugprintln(aircraft, "Aileron control damaged! ");
}
if(((!(aircraft.FM.CT.bHasRudderControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3)) || bLockedAileron || TrueRandom.nextInt(0, 99) < 50 + aircraft.FM.subSkill * 3)  //ace (3) more likely to bail
{
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Aileron control cut, bailing out! ");
System.out.println("Ail cut----bail, Rud_ctl?" + aircraft.FM.CT.bHasRudderControl + "  AilLock?" + bLockedAileron +  "   " + aircraft.typedName());
hitDaSilk();
}
break;


case 1: // '\001'  //ELEVATOR
if(aircraft.FM.CT.bHasElevatorControl)
{
if(TrueRandom.nextFloat() < 0.8F)
aircraft.FM.CT.resetControl(1);
else
{
aircraft.FM.CT.anchorControl(1);
bLockedElevator = true;
}
if(aircraft.FM.isPlayers())
HUD.log("FailedVatorAU");
aircraft.FM.CT.bHasElevatorControl = false;
aircraft.FM.setCapableOfACM(false);
System.out.println("Elev_ctrl_hit, " + " Elevators:" + aircraft.FM.CT.getElevator() + "   " + aircraft.typedName());
Aircraft.debugprintln(aircraft, "Elevator control damaged! ");
}
if(Math.abs(aircraft.FM.Vwld.z) > 7D)  //7m/s ~14kt, up or down; is assessed with each qualifying hit
{
aircraft.FM.setCapableOfBMP(false, actor1);
System.out.println("Elev_no_BMP " + aircraft.typedName());
}
if(aircraft.FM.Vwld.z < -21D || bLockedElevator || TrueRandom.nextInt(0, 99) < 75 + aircraft.FM.subSkill * 3)  //21m/s ~42kt, down only, is assessed with each qualifying hit
{
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Elevator control cut, bailing out! ");
System.out.println("Elev_cut----bail, VSI(m/s):" + aircraft.FM.Vwld.z + "  ElevLock?" + bLockedElevator +  "   " +aircraft.typedName());
hitDaSilk();
}
break;


case 2: // '\002'  //RUDDER
if(aircraft.FM.CT.bHasRudderControl)
{
if(TrueRandom.nextFloat() < 0.8F)
aircraft.FM.CT.resetControl(2);
else
{
aircraft.FM.CT.anchorControl(2);
bLockedRudder = true;
}
if(aircraft.FM.isPlayers())
HUD.log("FailedRudderAU");
aircraft.FM.CT.bHasRudderControl = false;
System.out.println("Rud_ctrl_hit, " + " Rudder:" + aircraft.FM.CT.getRudder() + "   " + aircraft.typedName());
}
Aircraft.debugprintln(aircraft, "Rudder control damaged! ");
if((!(aircraft.FM.CT.bHasAileronControl) && TrueRandom.nextInt(0, 99) < 80 + aircraft.FM.subSkill * 3) || bLockedRudder || TrueRandom.nextInt(0, 99) < 10 + aircraft.FM.subSkill * 2)
{
aircraft.FM.setCapableOfACM(false);
aircraft.FM.setCapableOfBMP(false, actor1);
aircraft.FM.setReadyToDie(true);
aircraft.FM.setTakenMortalDamage(true, actor1);
Voice.speakMayday(aircraft);
Aircraft.debugprintln(aircraft, "Rudder control cut, bailing out! ");
System.out.println("Rud_cut----bail, Ail_ctl?" + aircraft.FM.CT.bHasAileronControl + "  RudLock?" + bLockedRudder + "   " + aircraft.typedName());
hitDaSilk();
}
break;


default:
throw new RuntimeException("(" + aircraft.typedName() + ") A.S.: Corrupt data in (C.A.D./null)");
}
}


One mission result of taking down 12 P-40Bs, as recorded to log.lst. Out of seven chances for a locked control, such has occurred once. Again, the last character on each line is the plane's ID. Note particularly the greatly reduced number of qualifying events, due to not reduntantly calling the methods in Controls.class for every hit.


[2024-03-19 18:03:14.646]   dT: 1039   Rud_ctrl_hit,  Rudder:0.0   G

[2024-03-19 18:03:24.385]   dT:  325   Ail_ctrl_hit,  Ailerons:0.0   G
[2024-03-19 18:03:24.385]   dT:    0   Ail cut----bail,  Rud_ctl?false  AilLock?false   G

-----------------------------------------------------------------------------------------------

[2024-03-19 18:04:03.426]   dT: 1301   Elev_ctrl_hit,  Elevators:0.0   C
[2024-03-19 18:04:03.426]   dT:    0   Elev_cut----bail,  VSI(m/s):-6.065972568628225  ElevLock?false   C

-----------------------------------------------------------------------------------------------

[2024-03-19 18:06:36.231]   dT: 5093   Elev_ctrl_hit,  Elevators:-0.34874916   A
[2024-03-19 18:06:36.231]   dT:    0   Elev_no_BMP   A
[2024-03-19 18:06:36.231]   dT:    0   Elev_cut----bail,  VSI(m/s):24.28779131466929  ElevLock?true   A

[2024-03-19 18:06:50.999]   dT:  357   Ail cut----bail,  Rud_ctl?true  AilLock?false   A

-----------------------------------------------------------------------------------------------

[2024-03-19 18:07:30.614]   dT: 1322   Rud_ctrl_hit,  Rudder:0.0   L

[2024-03-19 18:07:33.075]   dT:   82   Rud_cut----bail,  Ail_ctl?true  RudLock?false   L

-----------------------------------------------------------------------------------------------

[2024-03-19 18:08:04.246]   dT: 1039   Elev_ctrl_hit,  Elevators:0.0   F
[2024-03-19 18:08:04.246]   dT:    0   Elev_no_BMP   F
[2024-03-19 18:08:04.247]   dT:    0   Elev_cut----bail,  VSI(m/s):41.93601136302307  ElevLock?false   F

[2024-03-19 18:08:04.565]   dT:   11   Elev_no_BMP   F

[2024-03-19 18:08:06.692]   dT:   71   Rud_ctrl_hit,  Rudder:0.74826646   F
[2024-03-19 18:08:06.692]   dT:    0   Rud_cut----bail,  Ail_ctl?true  RudLock?true   F

Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040

It's worth pointing out that my treatment of the determination for a bailout probability does not look at each control in total isolation.


- For disabled aileron control, if the rudder is also disabled the chance of a bailout is increased.
- Conversely, for a disabled rudder, if the aileron control is also disabled the chance of a bailout is increased.

And I've just added the check for a locked control. If any one of the three is locked, bailout always occurs.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040

I've added a conf.ini control, "DamagedControlLockProbability", where the probability for a control lock-up can be set as desired, between 0.0 to 0.99. If the control item is absent in the [Mods] section, the default is zero.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)
Pages: [1]   Go Up
 

Page created in 0.03 seconds with 24 queries.