WaBis

walter.bislins.ch

Animation des Krüger-Flaps Mechanismus erklärt

Sonntag, 22. Mai 2016 - 12:33 | Autor: wabis | Themen: Wissen, Mechanik, Aviatik, Animation
Mit Hilfe einiger selbst programmierter Module habe ich eine interaktive Animation des Mechanismus der Krüger-Flaps (Krügerklappen) eines Flugzeugs programmiert. Ich erkläre hier, wie der Mechanismus aufgebaut ist und wie die Bewegung der einzelnen Hebel und Gelenke berechnet wird. Auch das JavaScript, welches die Grafik erzeugt, wird erklärt.

Was sind Krüger-Flaps?

Auftriebshilfen eines Flugzeugs

Bei den Krüger-Flaps oder Krügerklappen handelt es sich um Auftriebshilfen an den Vorderkanten der Tragflügel einiger Flugzeuge. Die Krüger-Flaps verbessern die Langsamflugeigenschaften. Sie sind eine Einrichtung, die sowohl die Flügelwölbung, als auch die Flügelfläche verändern.

Die Krüger-Flaps befinden sich an der vorderen Tragflächenunterseite und sind in ihrer Wirkung mit einem Vorflügel vergleichbar. Die beiden Auftriebshilfen werden auch kombiniert.

Der Krüger-Flaps Mechanismus

Die folgende interaktive Animation zeigt einen Querschnitt durch den Flügel mit dem Mechanismus der Krüger-Flaps. Der blaue Hebel wird mit einem Motor angetrieben. Alle anderen Hebel werden vom blauen Hebel direkt oder indirekt bewegt.

Mit dem Schieberegler unterhalb der Grafik lässt sich der Mechanismus von Hand bewegen. Ein Klick auf die Animation lässt die Bewegung automatisch ablaufen. Mit einem weiteren Klick wird die Animation angehalten.

In den folgenden Abschnitten wird erklärt, wie diese Animation programmiert worden ist.

Zerlegung des Mechanismus in seine Einzelteile

(Klick: Zoom)
ZoomHebeldarstellung des Krüger-Flaps-Mechanismus

Für alle nachfolgenden Berechnungen vereinfache ich die Hebel zu einfachen Stangen. Da der rote und grüne Hebel je drei Gelenke haben, bestehen diese aus je zwei Stangen, die in einem festen Winkel ω2 bei P2 bzw. ω3 bei P3 zueinander verbunden sind.

Die Gelenke bei Punkt P1 und P2 sind am Flügel fixiert. Der Antrieb des Mechanismus greift beim Gelenk P1 an. Alle anderen Gelenkpositionen sind abhängig vom Auslenkwinkel α (bei P1) des blauen Hebels und den jeweiligen Hebellängen. Diese Grössen definieren den Mechanismus vollständig und wir können alle Gelenkpositionen daraus in Abhängigkeit von α geometrisch bestimmen.

Sobald wir die Positionen aller Gelenke berechnet haben, ist das Zeichnen der Hebel eine einfache Angelegenheit.

Berechnung der Gelenkpositionen

Die folgende Animation veranschaulicht die geometrischen Zusammenhänge:

Wir brauchen für alle Berechnungen nur zwei Funktionen:

PointFromAngleLength( P0, Pref, Angle, Length )
Berechnet zunächst einen Referenzstrahl vom Punkt P0 aus durch den Punkt Pref. Dann wird der gesuchte Punkt mit Winkel Angle zum Referenzstrahl mit dem Abstand Length zum Punkt P0 berechnet.
Intersect2Circles( CenterA, RadiusA, CenterB, RadiusB )
Berechnet die Schnittpunkte Zweier Kreise A und B, welche durch ihre Zentren und Radien definiert sind. Bei dieser Berechnung fallen in der Regel zwei Schnittpunkte an. Der eine liegt links vom Strahl von CenterA durch CenterB, der andere rechts davon. Es muss aus der Geometrie der Hebel bestimmt werden, welcher Schnittpunkt jeweils der gesuchten Gelenkposition entspricht.

Berechnung von Punkt P3

Punkt P3 kann mit Hilfe der Funktion PointFromAngleLengt() berechnet werden. Die Position des Punktes P1 legt den Startpunkt des Referenzstrahls fest. Der Referenzpunkt liege auf der horizontalen X-Achse rechts vom Punkt P1 in einem beliebigen Abstand zu P1. Der Referenzpunkt Pref kann durch Addition eines Vektors ( 1, 0 ) zum Punkt P1 berechnet werden:

Pref = AddVectors( Model.P1, [ 1, 0 ] )

Der Winkel α wird nicht von diesem Referenzstrahl aus gemessen, sondern von einem Strahl aus, der um den Wert StartAngle im Gegenuhrzeigersinn um den Punkt P1 gedreht ist. Drehungen im Gegenuhrzeigersinn werden als positive Winkel angegeben. Der Winkel Angle berechnet sich also wiefolgt:

Angle = -( Model.Alpha - Model.StartAngle )

Alpha geht von 0 bis zu einem maximalen Winkel αmax. Negatives Vorzeichen, weil der Winkel α im Uhrzeigersinn von der Nullposition aus verläuft. Für Alpha = 0 erhalten wir einen Winkel Angle = StartAngle. StartAngle ist ein positiver Wert weil im Gegenuhrzeigersinn von der X-Achse aus gemessen. Für Alpha = StartAngle erhalten wir Angle = 0, der blaue Hebel liegt dann horizontal.

Mit dem Gelenkpunkt P1, dem Referenzpunkt Pref, dem Winkel Angle und der Hebellänge L13 kann der Punkt P3 mit der Funktion PointFromAngleLength() berechnet werden:

Model.P3 = PointFromAngleLength( P1, Pref, Angle, L13 )

Berechnung von Punkt P4

Aus der Grafik ist ersichtlich (wenn bei Hilfskreise ein Häckchen gesetzt ist), dass der Punkt P4 immer den Abstand L34 vom Punkt P3 und den Abstand L24 vom Punkt P2 hat. Punkt P4 liegt somit auf dem Schnittpunkt zweier Kreise mit den Zentren P3 und P2 und den Radien L34 und L24. Mit der Funktion Intersect2Circles kann der Punkt P4 berechnet werden:

Q = Intersect2Circles( Model.P2, Model.Len24, Model.P3, Model.Len34 )

Q ist ein Array von 0 bis 2 Punkten. In unserem Model gibt es immer zwei Schnittpunkte, Q enthält diese beiden Schnittpunkte Q[0] und Q[1]. Der erste Punkt in Q[0] liegt links bezüglich der Strecke P2 durch P3. Der gesuchte Punkt P4 liegt laut Skizze immer rechts dieser Strecke. Also gilt:

Model.P4 = Q[1]

Berechnung von Punkt P5 und P6

Der rote Hebel mit den Gelenken P2, P4 und P5 besteht aus zwei Teil-Hebeln, die den Punkt P2 gemeinsam haben und dort einen Winkel ω2 bilden. Der Punkt P5 kann mit der Funktion PointFromAngleLengt() aus dieser Geometrie einfach berechnet werden:

Model.P5 = PointFromAngleLength( Model.P2, Model.P4, Model.Omega2, Model.Len25 )

Analog kann der Punkt P6 des grünen Hebels berechnet werden:

Model.P6 = PointFromAngleLength( Model.P3, Model.P4, Model.Omega3, Model.Len36 );

Der Winkel Omega2 ist negativ, da der Hebel H26 im Uhrzeigersinn vom Hebel H24 aus gemessen wird. Der Winkel Omega3 hingegen ist positiv, da der Hebel H36 im Gegenuhrzeigersinn vom Hebel H34 aus gemessen wird.

Berechnung von Punkt P7

Analog wie bei der Berechnung von Punkt P4 ist aus der Grafik ersichtlich, dass der Punkt P7 immer den Abstand L57 vom Punkt P5 und den Abstand L67 vom Punkt P6 hat. Punkt P7 liegt somit auf dem Schnittpunkt zweier Kreise mit den Zentren P5 und P6 und den Radien L57 und L67. Mit der Funktion Intersect2Circles() kann der Punkt P7 berechnet werden:

Q = Intersect2Circles( Model.P5, Model.Len57, Model.P6, Model.Len67 )

Der erste Punkt in Q[0] liegt links bezüglich der Strecke P5 durch P6. Der gesuchte Punkt P7 liegt laut Skizze immer rechts dieser Strecke. Also gilt:

Model.P7 = Q[1]

JavaScript der Animation erklärt

Nachfolgend wird der wesentliche Teil des JavaScripts der Animation auf dieser Seite erklärt. Das komplette JavaScript kann unter der folgenden Seite eingesehen werden:

 Animation des Krüger-Flaps Mechanismus (JavaScript)

Die Animation verwendet das selbst programmierte Grafik-Modul Graph und das ebenfalls selbst programmierte Modul für Ein-/Ausgabeformulare ControlPanel für den Schieberegler.

Funktionsprinzip

Die Animation verwendet die folgenden 3 Objekte:

  • FlapsModel
  • FlapsModelGraph
  • FlapsModelSlider

Das Objekt FlapsModel enthält die Geometriedaten des Modells und hat eine Funktion Update, welche die Positionen P3 bis P7 berechnet (siehe Definition des Modells).

Das Objekt FlapsModelGraph erzeugt einen Zeichenbereich im Browserfenster und stellt Funktionen zum Zeichnen zur Verfügung (siehe Grafik-Objekt erzeugen und Zeichnen des Modells).

Das Objekt FlapsModelSlider erzeugt und verwaltet den Schieberegler (siehe Schieberegler erzeugen).

Im Objekt FlapsModelSlider wird die Funktion HandleFlapsModelChange() installiert. Der Schieberegler ist mit dem Property FlapsModel.Alpha verknüpft. Wenn der Schieberegler bewegt wird, wird Alpha entsprechend verändert und danach die Funktion HandleFlapsModelChange() gerufen.

Die Funktion HandleFlapsModelChange() ruft zunächst die Funktion Update des FlapsModel, um die Gelenkpositionen entsprechend dem neuen Alpha-Wert zu berechnen. Dann wird die Funktion Update() des FlapsModelSlider gerufen, um die Position des Schiebereglers entsprechend dem Alpha-Wert zu setzen (falls dieser nicht vom Schieberegler verändert wurde). Schliesslich wird die Funktion Redraw() des FlapsModelGraph gerufen, um die Grafik neu zu zeichnen.

Im FlapsModelGraph wird die Funktion DrawFlapsModel() installiert. Diese Funktion wird gerufen, wenn die Grösse des Browser-Fensters geändert wird oder wenn die Funktion Redraw() aufgerufen wird. DrawFlapsModel() greift beim Zeichnen auf die Daten des Objektes FlapsModel zu. Die Konturen der Hebel sind in den Zeichenfunktionen definiert (siehe Zeichnen der Hebel).

Hilfsfunktionen

Für die Berechnung der Gelenkpositionen werden die folgenden zwei Funktionen benötigt:

function PointFromAngleLength( P0, Pref, ang, len ) {
  // returns a point at distance len from P0 at angle ang from ray P0 to Pref
  var eref = JsgVect2.Norm( JsgVect2.Sub( Pref, P0 ) );
  var ep = JsgVect2.Rotate( eref, ang );
  return JsgVect2.Add( P0, JsgVect2.Scale( ep, len ) );
}

function Intersect2Circles( A, a, B, b ) {
  // A, B = [ x, y ]
  // return = [ Q1, Q2 ] or [ Q ] or [] where Q = [ x, y ]
  var AB0 = B[0] - A[0];
  var AB1 = B[1] - A[1];
  var c = Math.sqrt( AB0 * AB0 + AB1 * AB1 );
  if (c == 0) {
    // same center: A = B
    return [];
  }
  var x = (a*a + c*c - b*b) / (2*c);
  var y = a*a - x*x;
  if (y < 0) {
    // no intersection
    return [];
  }
  if (y > 0) y = Math.sqrt( y );
  // compute unit vectors ex and ey
  var ex0 = AB0 / c;
  var ex1 = AB1 / c;
  var ey0 = -ex1;
  var ey1 =  ex0;
  var Q1x = A[0] + x * ex0;
  var Q1y = A[1] + x * ex1;
  if (y == 0) {
    // one touch point
    return [ [ Q1x, Q1y ] ];
  } 
  // two intersections
  var Q2x = Q1x - y * ey0;
  var Q2y = Q1y - y * ey1;
  Q1x += y * ey0;
  Q1y += y * ey1;
  return [ [ Q1x, Q1y ], [ Q2x, Q2y ] ];
}

Definition des Modells

Alle Daten des Animation-Modells werden in der Klasse FlapsModelObject zusammengefasst. Diese Klasse besitzt eine Funktion Udate(), welche die Berechnung der Gelenkpositionen vornimmt.

function FlapsModelObject() {

  // Variable
  this.Alpha = 0;

  // Modell-Geometrie
  this.StartAngle = 10.2 / 180 * Math.PI;
  this.EndAngle = -133 / 180 * Math.PI;
  this.P1 = [ 0, 0 ];
  this.P2 = [ -200, -15 ];
  this.Omega2 = -0.32108;
  this.Omega3 = 0.056018;
  this.Len13 = 180.4;
  this.Len34 = 159.0;
  this.Len36 = 234.9;
  this.Len24 = 237.8;
  this.Len25 = 352.6;
  this.Len57 =  78.8;
  this.Len67 = 119.1;

  // Berechnete Punkte -> Update
  this.P3 = [ 0, 0 ];
  this.P4 = [ 0, 0 ];
  this.P5 = [ 0, 0 ];
  this.P6 = [ 0, 0 ];
  this.P7 = [ 0, 0 ];

  // Punkte P3 bis P7 jetzt berechnen
  this.Update();  
}

Die Funktion Update() berechnet die Positionen der Gelenke mithilfe der Hilfsfunktionen:

FlapsModelObject.prototype.Update = function() {

  // Berechnung von Punkt P3
  var Pref = JsgVect2.Add( this.P1, [ 1, 0 ] );
  this.P3 = PointFromAngleLength( this.P1, Pref, this.StartAngle-this.Alpha, this.Len13 );

  // Berechnung von Punkt P4
  var Q = Intersect2Circles( this.P2, this.Len24, this.P3, this.Len34 );
  // Abbruch, wenn Schnittpunkt nicht berechnet werden konnte
  if (Q.length < 2) return;
  this.P4 = Q[1];

  // Berechnung der Punkte P5 und P6
  this.P5 = PointFromAngleLength( this.P2, this.P4, this.Omega2, this.Len25 );
  this.P6 = PointFromAngleLength( this.P3, this.P4, this.Omega3, this.Len36 );

  // Berechnung von Punkt P7
  var Q = Intersect2Circles( this.P5, this.Len57, this.P6, this.Len67 );
  // Abbruch, wenn Schnittpunkt nicht berechnet werden konnte
  if (Q.length < 2) return;
  this.P7 = Q[1];
}

Zeichnen des Modells

Die Funktion zum Zeichnen des ganzen Modells ruft die Zeichenfunktionen der einzelnen Teile auf:

function DrawFlapsModel( g ) {
  // g: Grafik-Objekt

  g.SetAngleMeasure( 'rad' );
  g.SetWindow( -466.5, -492.1, 307.2, 163.3 );

  DrawWing( g, FlapsModel );
  DrawPart3( g, FlapsModel );
  DrawPart1( g, FlapsModel );
  DrawPart4( g, FlapsModel );
  DrawPart2( g, FlapsModel );
  DrawPart5( g, FlapsModel );
}

Mit SetAngleMeasure() werden die Winkeleinheiten auf Radian eingestellt. Mit SetWindow() wird die Abmessung des Modells dem Grafik-Objekt mitgeteilt.

Die Funktion DrawFlapsModel() wird beim Erzeugen des Zeichbereichs mit NewGraph2D() im Grafik-Modul installiert. DrawFlapsModel() wird beim Verschieben des Schiebereglers in der Funktion HandleFlapsModelChange() beim Aufruf von FlapsModelGraph.Redraw() aufgerufen. Das Grafik-Modul ruft diese Funktion auch automatisch immer dann, wenn die Grösse des Browser-Fensters geändert wird.

Zeichnen der Hebel

Das verwendete Grafik-Modul stellt Transformations-Funktionen zur Verfügung. Mit TransRotate() lässt sich Grafik um einen Winkel rotieren und mit TransMove() an eine bestimmte Position verschieben. Die Grafik der Hebel kann so in einem vom Modell unabhängen Bezugssystem, dem Koordinatensystem eines Hebels, definiert werden. Ich habe jeweils den Nullpunkt des Bezugssystems so gewählt, dass er bei einem der Gelenke des Hebels zu liegen kommt.

Vor dem Zeichnen der Hebel muss der Rotationswinkel aus zwei Gelenkpositionen des Hebels berechnet werden. Dann wird mit einer entsprechende Rotations-Transformation der Hebel um diesen Winkel rotiert und mit einer Translations-Transformation der Nullpunkt des Hebels an die berechnete Position des entsprechenden Gelenkes verschoben.

Das sieht am Beispiel des blauen Hebels wiefolgt aus:

function DrawPart1( g, mod ) {
  // g: Grafik Objekt
  // mod: FlapsModel

  // Farben und Strichdicke für den Hebel setzen
  g.SetAreaAttr( '#aaf', '#00f', 2 );

  // Rotationswinkel des Hebels aus der Position von P1 und P3 berechnen
  // [ 0.0, 0.0 ] = Koordinaten des Punktes P1 bezüglich Koordinatensystems des Hebels
  // [ 179.7, 11.1 ] = Koordinaten des Punktes P3 bezüglich Koordinatensystems des Hebels
  // u = normierter Vektor von P1 nach P3 bezüglich Koordinatensystem des Hebels
  // v = normierter Vektor von P1 nach P3 bezüglich des Koordinatensystems des Modells
  var u = JsgVect2.Norm( JsgVect2.Sub( [ 179.7, 11.1 ], [ 0.0, 0.0 ] ) );
  var v = JsgVect2.Norm( JsgVect2.Sub( mod.P3, mod.P1 ) );
  var angle = JsgVect2.Angle( u, v );

  // Transformation setzen: Hebel um angle rotieren und verschieben zu P1
  g.TransRotate( angle );
  g.TransMove( mod.P1 );

  // Umriss des Hebels zeichnen
  // Alle Koordinaten bezüglich des Koordinatensystems des Hebels
  g.OpenPath();
  g.Line( 0, 33.9, 179.7, 33.9 );
  g.LineTo( 189.2, 16.1 );
  g.ArcTo( 172.4, 2.9, -11.1 );
  g.LineTo( 157.6, 16.1 );
  g.LineTo( 68.5, -8.1 );
  g.LineTo( 13.4, -31.2 );
  g.ArcTo( 0, 33.9, -33.9, true );
  g.Path( 3 );

  // Skelett-Linien zeichnen 
  g.Line( 146.3, 33.9, 157.6, 16.1 );
  g.Polygon( [ 24.6, 28.4, 143.8, 148.4, 65.7,  36.3,  31.9 ], 
             [ 23.2, 27.6,  27.6,  19.5, -1.8, -14.6, -12.2 ] );
  g.ArcPt( 31.9, -12.2, 24.6, 23.2, 33.9 );
  g.Circle( 0, 0, 16.1 );
  g.Circle( 0, 0, 27.6 );
  g.Circle( 179.7, 11.1, 8.0 );

  // Gelenke zeichnen
  g.SetBgColor( 'white' );
  g.Circle( 0, 0, 11.1, 3 );
  g.Circle( 179.7, 11.1, 5.0, 3 );

  // Transformation zurücksetzen
  g.ResetTrans();
}

Wie man sieht, werden alle Zeichenfunktionen für jeden Winkel Alpha mit denselben Koordinaten gerufen. Durch die Transformations-Funktionen werden die Hebel aber an verschiedenen Positionen und Lagen gezeichnet.

Die JsgVect2 Vektor-Funktionen werden vom Grafik-Modul zur Verfügung gestellt.

Modell erzeugen und Update-Funktion

Flaps-Modell erzeugen und Funktion, welche beim Ändern des Winkels α durch den Schieberegler gerufen wird. HandleFlapsModelChange() veranlasst das Berechnen der Modell-Gelenke, setzt den Schieberegler auf den Wert von FlapsModel.Alpha und veranlasst das Neuzeichnen der Grafik.

var FlapsModel = new FlapsModelObject();

function HandleFlapsModelChange() {
  // FlapsModel.Alpha wurde geändert (z.B. durch den Schieberegler)

  // Gelenkpositionen des Modells neu berechnen
  FlapsModel.Update();

  // Schieberegler auf die Position FlapsModel.Alpha nachführen
  FlapsModelSlider.Update();

  // Neuzeichnen der Grafik veranlassen (ruft die Funktion DrawFlapsModel)
  FlapsModelGraph.Redraw();
}

Grafik-Objekt erzeugen

Mit dem Modul Graph können Grafiken auf der Webseite erzeugt und gezeichnet werden.

Das Grafik-Objekt FlapsModelGraph erzeugt die Zeichenfläche der Grösse Width × Height auf der Webseite. Über DrawFunc wird die Funktion DrawFlapsModel() installiert, welche bei einem Resize des Browser-Fensters oder beim Aufruf der Funktion Redraw() des FlapsModelGraph gerufen wird, siehe HandleFlapsModelChange().

var FlapsModelGraph = NewGraph2D( {
  
  // relative Grösse des Zeichenbereichs
  Width: '100%',
  Height: '84.71%',
  
  // Funktion, die beim Resize des Browser-Fensters gerufen werden soll
  DrawFunc: DrawFlapsModel,

  // Weitere Einstellungen...
  AutoReset: true,
  ScaleRef: 800,
  AutoScalePix: true

} );

Schieberegler erzeugen

Mit dem Modul ControlPanel können Eingabeformulare auf einer Website erstellt werden, welche unter anderem auch Schieberegler enthalten können.

Das Objekt FlapsModelSlider, welches einem solchen Eingabeformular entspricht, wird über ModelRef mit dem FlapsModel verknüpf. Über OnModelChange wird die Funktion HandleFlapsModelChange() installiert. Diese wird bei jeder Änderung des Modells durch das Eingabeformular, d.h. durch Bewegen des Schiebereglers, aufgerufen.

Der Schieberegler wird bei AddSliderField über Name mit dem Property Alpha des FlapsModel verknüpft.

var FlapsModelSlider = ControlPanels.NewPanel( { 
  Name: 'FlapsSetting',
  ModelRef: 'FlapsModel',
  OnModelChange: HandleFlapsModelChange
} );

FlapsModelSlider.AddSliderField( {
  Name: 'Alpha', 
  Label: 'Position',
  Min: 0, 
  Max: -(FlapsModel.EndAngle - FlapsModel.StartAngle)
} );

FlapsModelSlider.Render();

Dein Kommentar zu diesem Artikel
Name
Email optional; wird nicht angezeigt
Kommentar
  • Name wird bei deinem Kommentar angezeigt.
  • Email ist nur für den Administrator, sie wird nicht angezeigt.
  • Du kannst deine Kommentare eine Zeit lang editieren oder löschen.
  • Du kannst Formatierungen im Kommentar verwenden, z.B: Code, Formeln, usw.
  • Externen Links und Bilder werden nicht angezeigt, bis sie der Admin freischaltet.
Weitere Infos zur Seite
Erzeugt Sonntag, 22. Mai 2016
von wabis
Zum Seitenanfang
Geändert Freitag, 18. November 2016
von wabis