Results 1 to 5 of 5

Thread: Some Basics in Simulation App - Ball Bouncing

  1. #1
    Join Date
    Sep 2004
    Posts
    1,905
    Rep Power
    21

    Default Some Basics in Simulation App - Ball Bouncing

    Some things I have said about a simulation app in a previous post, I hope to clarify here.

    This app comes from the specialist idea suggested in this post
    Specialized Learning vs General Learning

    This app is about simulating a rubber ball in free fall. The ball hits the ground and bounces back up into the air, and so on.

    The app was written a Windows 8 App in C#
    (Unfortunately, that is the only C# compiler I have access to at this time. I will try to port it to a Windows Form program whenever I get the chance)

    The objective of the app is to simulate a rubber ball bouncing as long as possible, while keeping each bounce as identical as possible.

    When you vary the sliders, sometimes a "floating point" variable goes to the high (or low) end with respect to the other floating point variables and this increases the error in floating point math.

    eg
    Code:
    1000000000000000 + .0000125 = 1000000000000000.000000087
    whereas adding in a more even range

    Code:
    10000000 + 1.25 = 10000001.25
    If the first step is done 1 million times then more error would be introduced and then accumulates

    These are just illustrative examples, not to be taken for exactness.

    In a simulation, you want to increase accuracy. You can play with the sliders in the app and see how the accuracy of the bouncing ball is affected.

    Another aspect of sim accuracy is doing an integration. Example, integrate x with respect to t, where in the code implementation, you would calculate dx using dt, then adjust x by adding dt, and then repeat. The accuracy of the integral increases as dt gets small, but sometimes when dt is sufficiently small, the sim would be accurate enough, and you can leave it at that. If you get too small with the floating point addition, you can have the problem described above.

    The equations used in the sim are:
    Code:
          dx = u dt + 1/2 dv dt
    
          v = u + dv
               
          dv = a dt
               
           v = u + a dt
    These are straight physics equation for distance x, acceleration a, and velocity v, where u is the initial velocity.
    Last edited by crosswire; Apr 3, 2018 at 07:45 PM.
    Let's act on what we agree on now, and argue later on what we don't.
    Black men leave Barbeque alone if Barbeque don't trouble you

  2. #2
    Join Date
    Sep 2004
    Posts
    1,905
    Rep Power
    21

    Default MainPage.xaml

    Uploaded!

    MainPage.xaml

    Code:
    <Page
        x:Class="Classical_Ball_Fall.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Classical_Ball_Fall"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Canvas HorizontalAlignment="Left" Height="500" Margin="106,79,0,0" VerticalAlignment="Top" Width="600" Background="DarkBlue" Name="Canvas01">
                <Rectangle Fill="#FFF4F4F5" Height="1" Canvas.Left="250" Stroke="Yellow" Canvas.Top="99" Width="100"/>
                <Ellipse Fill="#FFF4F4F5" Height="50" Canvas.Left="275" Stroke="Black" Canvas.Top="100" Width="50" Name="Ellipse01"/>
                <Rectangle Fill="#FFF4F4F5" Height="12" Canvas.Left="100" Stroke="Black" Canvas.Top="450" Width="400"/>
            </Canvas>
            <Button Content="Start" HorizontalAlignment="Left" Margin="710,150,0,0" VerticalAlignment="Top" Click="ButtonStart_Click" Name="buttonStart"/>
            <Button Content="Reset" HorizontalAlignment="Left" Margin="710,220,0,0" VerticalAlignment="Top" Click="ButtonReset_Click" Name="buttonReset"/>
            <Button Content="Close" HorizontalAlignment="Left" Margin="710,290,0,0" VerticalAlignment="Top" Click="ButtonClose_Click" Name="buttonClose"/>
            <Slider HorizontalAlignment="Left" Margin="713,380,0,0" VerticalAlignment="Top" Width="200" Name="Slider01" ValueChanged="Slider01_ValueChanged"/>
            <Slider HorizontalAlignment="Left" Margin="713,460,0,0" VerticalAlignment="Top" Width="200" Name="Slider02" ValueChanged="Slider02_ValueChanged"/>
            <Slider HorizontalAlignment="Left" Margin="713,540,0,0" VerticalAlignment="Top" Width="200" Name="Slider03" ValueChanged="Slider03_ValueChanged"/>
            <TextBlock HorizontalAlignment="Left" Height="48" Margin="713,350,0,0" TextWrapping="Wrap" Text="N Simulation calculation bewteen display frames. Higher is more accurate but uses more CPU power so it must be balanced. Also watch out for extreme conditions on very hi-end settings" VerticalAlignment="Top" Width="325"/>
            <TextBlock HorizontalAlignment="Left" Height="48" Margin="713,430,0,0" TextWrapping="Wrap" Text="
    A scale for the distance being dispayed but it can also be viewed as a scale for the time" VerticalAlignment="Top" Width="325"/>
            <TextBlock HorizontalAlignment="Left" Height="48" Margin="713,510,0,0" TextWrapping="Wrap" Text="
    
    Ball's Elasticity (Large is good but not too large)" VerticalAlignment="Top" Width="325"/>
        </Grid>
    </Page>
    Last edited by crosswire; Apr 3, 2018 at 06:56 PM. Reason: upload success
    Let's act on what we agree on now, and argue later on what we don't.
    Black men leave Barbeque alone if Barbeque don't trouble you

  3. #3
    Join Date
    Sep 2004
    Posts
    1,905
    Rep Power
    21

    Default MainPage.xaml.cs

    Uploaded!

    MainPage.xaml.cs

    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    using Windows.UI.Popups;
    
    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
    
    namespace Classical_Ball_Fall
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
    
    
    
        public class BallPhys
        {
            public static int nSimPerFrameDT;
            public static double nPixelsPerMeter;
            public static double elasticity;//big is good
    
            public const double mass = 28.0;
    
    
            //public static crosssectionalarea = 1.0; //for wind resistance - not implemented
            //public static double radius = 1.0f;
            //public static double height = 100.0f;
    
            /// <summary>
            /// Distance ball is squashed
            /// </summary>
            public static double compression = 0.0;
            /// <summary>
            /// Apparent Acceleration Due To Gravity
            /// </summary>
            public static double g = 9.98;
            /// <summary>
            /// Initial Velocity
            /// </summary>
            public static double u = 0;
            /// <summary>
            /// Final Velocity
            /// </summary>
            public static double v = 0;
            /// <summary>
            /// Incremental Time Interval
            /// </summary>
            public static int DT = 10; //10 milliseconds for each frame render
    
    
            public static double get_dx(bool bBallInContact)
            {
    
                double c = (elasticity * compression) / mass;
                /*
                Net Accelearation  on ball
                --------------------------
                           
                dx = u dt + 1/2 dv dt
                
                v = u + dv
               
                dv = a dt
               
                v = u + a dt
                
                */
    
                //Initialize u with initial v
                u = v;
    
                double dt = ((double)DT) / (1000.0 * nSimPerFrameDT); //convert from frame time to sim time. DT to dt. DT is time between displayed frames and dt is time in each sim. dt in seconds
                double dv = (g - c) * dt;
                double dx = (u * dt) + (0.5 * dv * dt);
    
                //Initialize final v;
                v = u + dv;
    
                return dx;
            }
    
    
            public static void reset()
            {
                u = 0;
                v = 0;
    
                //height = 100.0;
            }
        }
    
    
    
    
        public sealed partial class MainPage : Page
        {
    
            private DispatcherTimer timer = new DispatcherTimer();
    
            public MainPage()
            {
                this.InitializeComponent();
    
                //Initlize Timer
                timer.Tick += timer_Tick;
                timer.Interval = new TimeSpan(0, 0, 0, 0, BallPhys.DT); //DT is frame time in milliseconds
    
                //Allow user to change parameters of the sim
                //range 800 - 8000
                Slider01.Minimum = 350;
                Slider01.Maximum = 8000;
                Slider01.Value = 3800;//(double)(BallPhys.nSimPerFrameDT);
                //range 80 - 3000
                Slider02.Minimum = 80;
                Slider02.Maximum = 3000;
                Slider02.Value = 800.0;//(double)(BallPhys.nPixelsPerMeter);
                //range 20000 - 2000000
                Slider03.Minimum = 20000;
                Slider03.Maximum = 2000000;
                Slider03.Value = 240000.0;//(double)(BallPhys.elasticity);//big is good
    
            }
    
    
    
            /// <summary>
            /// Update state using N sim increments for each tick. Physics is simulated
            /// Display Frame
            /// </summary>
            void timer_Tick(object sender, object e)
            {
    
                //Do n  simulations per each frame
                int nSim = 0;
    
                while (nSim < BallPhys.nSimPerFrameDT)
                {
    
    
    
                    //Distance from canvas top Canvas.Top="122"
                    //Canvas.Top="450" 
                    //Ball heiht = Ellipse Height="50" 
    
                    BallPhys.compression = (50.0 - Ellipse01.Height) / BallPhys.nPixelsPerMeter;
    
                    //Fall the ball
                    //Move ball by dx
                    double DX = BallPhys.get_dx(true) * BallPhys.nPixelsPerMeter;
    
                    Canvas.SetTop(Ellipse01, Canvas.GetTop(Ellipse01) + DX);
    
    
                    //Is ball in contact
                    if ((Canvas.GetTop(Ellipse01) + Ellipse01.Height) >= (450))
                    {
                        //Compress ball
                        if ((Ellipse01.Height - ((Canvas.GetTop(Ellipse01) + Ellipse01.Height) - (450))) > 0)
                        {
                            Ellipse01.Height -= (Canvas.GetTop(Ellipse01) + Ellipse01.Height) - (450);
                        }
                        Ellipse01.Fill = new SolidColorBrush(Colors.DarkSlateGray);
    
                        //   timer.Stop();
                        // return;
                    }
                    else
                    {
                        //If ball is compressed
                        if (Ellipse01.Height < 50.0)
                        {
                            Ellipse01.Height = 450.0 - Canvas.GetTop(Ellipse01);
                        }
    
                        Ellipse01.Fill = new SolidColorBrush(Colors.White);
                    }
    
                    nSim++;
                }
            }
    
    
    
            private void ButtonStart_Click(object sender, RoutedEventArgs e)
            {
                if (timer.IsEnabled)
                {
                    //Stop timer
                    timer.Stop();
                    buttonStart.Content = "Start";
                }
                else
                {
                    //Start timer
                    timer.Start();
                    buttonStart.Content = "Pause";
                }
            }
    
            private void ButtonReset_Click(object sender, RoutedEventArgs e)
            {
                //Re-init timer / Stop timer
                if (timer.IsEnabled)
                {
                    //Stop timer
                    timer.Stop();
                    buttonStart.Content = "Start";
                }
    
                //Re-init positions
                Canvas.SetTop(Ellipse01, 100);
                Ellipse01.Height = 50;
                BallPhys.reset();
    
            }
    
            async private void ButtonClose_Click(object sender, RoutedEventArgs e)
            {
    
                MessageDialog msgDialog = new MessageDialog("Are you sure?", "Exit?");
    
                UICommand butOK = new UICommand("Yes", null, "YES");
                //butOK.Invoked = butOKClick;
                msgDialog.Commands.Add(butOK);
    
                UICommand butNo = new UICommand("No", null, "NO");
                //butNo.Invoked = butNoClick;
                msgDialog.Commands.Add(butNo);
    
                //Show message
                IUICommand op = await msgDialog.ShowAsync();
    
                //This below is oddly written so that it could be uploaded. Dont know why it was parsed and reject before
                if (op.Id.ToString().CompareTo("yes".ToUpper()) == 0)
                {
                    if (timer.IsEnabled)
                    {
                        //Stop timer
                        timer.Stop();
                    }
                    App.Current.Exit();
                }
            }
    
    
            private void Slider01_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                // public static int nSimPerFrameDT = 3800;
    
                BallPhys.nSimPerFrameDT = (int)(Slider01.Value);
    
                ButtonReset_Click(null, null);
                ButtonStart_Click(null, null);
            }
    
            private void Slider02_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                //public static double nPixelsPerMeter = 800;
    
                BallPhys.nPixelsPerMeter = (double)(Slider02.Value);
    
                ButtonReset_Click(null, null);
                ButtonStart_Click(null, null);
            }
    
            private void Slider03_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                //public static double elasticity = 240000.0;//big is good
    
                BallPhys.elasticity = (double)(Slider03.Value);
    
                ButtonReset_Click(null, null);
                ButtonStart_Click(null, null);
            }
        }
    
    }
    Last edited by crosswire; Apr 3, 2018 at 06:56 PM. Reason: upload success
    Let's act on what we agree on now, and argue later on what we don't.
    Black men leave Barbeque alone if Barbeque don't trouble you

  4. #4
    Join Date
    Sep 2004
    Posts
    1,905
    Rep Power
    21

    Default MainPage.xaml.cs (continued)

    Reserved for any future related uploads....
    Last edited by crosswire; Apr 3, 2018 at 07:51 PM.
    Let's act on what we agree on now, and argue later on what we don't.
    Black men leave Barbeque alone if Barbeque don't trouble you

  5. #5
    Join Date
    Sep 2004
    Posts
    1,905
    Rep Power
    21

    Default MainPage.xaml.cs (continued)

    Reserved for any future related uploads....
    Last edited by crosswire; Apr 3, 2018 at 07:50 PM.
    Let's act on what we agree on now, and argue later on what we don't.
    Black men leave Barbeque alone if Barbeque don't trouble you

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •