WaBis

walter.bislins.ch

Sim: Demo

Klicke in das Bild um die Simulation zu stoppen bzw. neu zu starten.

d1: Lineare Dämpfung, enstpricht Reibung im Lager

d2: Quadratische Dämpfung, enstpricht dem Luftwiderstand

v0: Start-Winkelgeschwindigkeit

g: Gravitationsbeschleunigung, Erde = 9,81 m/s2

Speed: Simulations-Geschwindigkeit: > 1 für Timelaps, < 1 für Zeitlupe

Code

var PendulumModel = {
  v0: 4,    // start speed
  a: 0,     // current angle 
  da: 0,    // current angular speed
  dda: 0,   // current angular acceleration
  d1: 0,    // linear damping
  d2: 0.1,  // quadratic damping
  m: 1,     // pendulum mass
  l: 1,     // pendulum length
  g: 9.81,  // gravitational acceleration
  Fl: 0,    // current string force
  Fg: 0,    // current gravity force
  Fd: 0,    // current damping force
  Ft: 0,    // current total force
  graph: null,
  sim: null,

  Create: function( sim ) {
    this.sim = sim;
    var me = this;
    this.graph = NewGraph2D( {
      Id: 'PendulumModel-Graph',
      Width: '100%',
      Height: '60%',
      DrawFunc: function(){ me.Draw(); },
      OnClick: function(){ sim.Pause(true); },
      AutoReset: false,
      AutoClear: false,
    } );
  },

  Reset: function() {
    this.a = 0;
    this.da = this.v0;
    this.dda = 0;
  },

  Update: function() {
    // is called from sim to compute next time step values

    // compute all forces
    this.Fg = this.m * this.g;
    this.Fl = this.Fg * Math.cos( this.a );
    this.Fd = this.d1 * Math.abs( this.da ) + this.d2 * this.da * this.da;
    var vdir = this.da >= 0 ? -1 : 1;
    this.Ft = -this.Fg * Math.sin( this.a ) + vdir * this.Fd;

    // compute new acceleration, speed and position by simple numerical integration
    this.dda = this.Ft / this.m;
    this.da += this.dda * this.sim.DeltaTime;
    this.a += this.da * this.sim.DeltaTime;
  },

  Draw: function() {
    // is called from sim once per frame to draw pendulum

    var g = this.graph;

    g.Reset();
    g.MapWindow( 0, 0.5, 2.2, 0, 0 );

    // compute pendulum position
    var x = this.l * Math.sin( this.a );
    var y = -this.l * Math.cos( this.a ) + 1;
  
    // draw pendulum
    g.SetLineAttr( 'black', 2 );
    g.Line( 0, 1, x, y );
    g.SetMarkerAttr( 'Circle', 20, 'black', 'yellow', 2 );
    g.Marker( x, y );

    // draw zero marker
    g.SetMarkerAttr( 'ArrowUp', 10, 'black', 'white', 1 );
    g.Marker( 0, -0.04 );

    // draw Ft
    var ax = 0.025 * this.Ft * Math.cos( this.a );
    var ay = 0.025 * this.Ft * Math.sin( this.a );
    g.SetMarkerAttr( 'Arrow1', 8, 'black', 'red', 1 )
    g.Arrow( x, y, x+ax, y+ay, 1, 3 );

    // display sim values
    var sim = this.sim;
    var txtpos = 0;
    g.SelectTrans( 'viewport' );
    g.SetTextAttr( 'Arial', 16, 'black', 'normal', 'normal', 'left', 'top', 4 );
    var cpuDrawMax = sim.CpuLoadFrameMax - sim.CpuLoadSimMax;
    if (cpuDrawMax < 0) cpuDrawMax = 0;
    var cpuDrawAvg = sim.CpuLoadFrameAvg - sim.CpuLoadSimAvg;
    if (cpuDrawAvg < 0) cpuDrawAvg = 0;
    g.Text( 'FPS max = ' + sim.FpsMax.toFixed(0), 0, 20*txtpos++ );
    g.Text( 'CPU sim max = ' + sim.CpuLoadSimMax.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'CPU draw max = ' + cpuDrawMax.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'CPU frame max = ' + sim.CpuLoadFrameMax.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'FPS avg = ' + sim.FpsAvg.toFixed(0), 0, 20*txtpos++ );
    g.Text( 'CPU sim avg = ' + sim.CpuLoadSimAvg.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'CPU draw avg = ' + cpuDrawAvg.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'CPU frame avg = ' + sim.CpuLoadFrameAvg.toFixed(3), 0, 20*txtpos++ );
    g.Text( 'RealTime = ' + sim.RealTime.toFixed(1), 0, 20*txtpos++ );
    g.Text( 'SimTime = ' + sim.SimulTime.toFixed(1), 0, 20*txtpos++ );

    // display pendulum valus
    g.Text( 'a = ' + this.a.toFixed(2), 0, 20*txtpos++ );  
    g.Text( 'da = ' + this.da.toFixed(2), 0, 20*txtpos++);
    g.Text( 'dda = ' + this.dda.toFixed(2), 0, 20*txtpos++);
    g.Text( 'Ft = ' + this.Ft.toFixed(2), 0, 20*txtpos++);
  },

};

var PendulumSim = new Sim( {
  EnableStatistics: true,
  TimeStep:      0.0005,
  TimeSpeed:     1,
  SimObj:        PendulumModel,
  ResetFuncs:    function(sim) { sim.SimObj.Reset(); },
  TimeStepFuncs: function(sim) { sim.SimObj.Update(); },
  FrameFuncs:    function(sim) { sim.SimObj.Draw(); },
} );

PendulumModel.Create( PendulumSim );
PendulumSim.Run( true );

function UpdateAll() {
  ControlPanels.Update();
}

PendulumSim.AddResetFunc( UpdateAll );

ControlPanels.NewSliderPanel( { 
  Name: 'SliderPanel',
  ModelRef: 'PendulumModel',
  NCols: 1, 
  ValuePos: 'left',
  OnModelChange: UpdateAll, 
  Format: 'fix0', 
  Digits: 2,
  ReadOnly: true, 
  PanelFormat: 'InputShortWidth'

} ).AddValueSliderField( {
  Name: 'd1',
  Min: 0,
  Max: 2,

} ).AddValueSliderField( {
  Name: 'd2',
  Min: 0,
  Max: 2,

} ).AddValueSliderField( {
  Name: 'v0',
  Color: 'green',
  Min: -20,
  Max: 20,

} ).AddValueSliderField( {
  Name: 'g',
  Color: 'blue',
  Min: 0,
  Max: 20,

} ).AddValueSliderField( {
  Name: 'PendulumSim.TimeSpeed',
  Color: 'black',
  Label: 'Speed',
  Min: 0.25,
  Max: 4,

} ).Render();

UpdateAll();

Weitere Infos zur Seite
Erzeugt Dienstag, 10. Oktober 2017
von wabis
Zum Seitenanfang
Geändert Dienstag, 10. Oktober 2017
von wabis