This example is interactive. Click the play button on any cell to execute it, or run all cells in sequence.

Bouncing Ball

Simulation of a bouncing ball using PathSim's event handling system.

You can also find this example as a single file in the GitHub repository.

schematic of a bouncing ball

Systems like this require the location and resolution of discrete events within the timestep and are not easily solved with standard numerical ODE solvers. PathSim implements an event management system that can track the system state and locate and resolve specified events.

We can translate the dynamics of the system into a block diagram. Note the event manager that watches the state of the integrator for the position and can act on both integrator states:

block diagram of the bouncing ball system

Import and Setup

To simulate the bouncing ball, let's start by importing the required blocks from the block library. In this case integrators and a constant for gravity.

And of course the ZeroCrossing event manager from the event library.

Python
Loading...

System Parameters

Then define the system parameters:

Python
Loading...

System Definition

Now we can construct the system by instantiating the blocks we need (from the block diagram above) with their corresponding parameters and collect them together in a list:

Python
Loading...

Event Handling

Now the continuous system dynamics are defined. Without any additions, the ball would just accelerate indefinitely even past the floor. To implement the bounce, we need to define a zero crossing event tracker that watches the position and can detect when it changes its sign.

In PathSim events are defined by their type and an event function that is evaluated to determine whether an event has occurred and how close to the timestep it is and an action function that gets called to resolve the event once it is located to sufficient accuracy.

Here the event function just watches the state of the integrator Ix, i.e. the position and if it crosses the origin, the action function flips the sign of the velocity, i.e. the state of integrator Iv multiplied by the elasticity constant (loses some energy at the bounce):

Python
Loading...

Simulation Setup and Execution

Now the hybrid dynamical system consisting of the blocks, connections and discrete events is fully defined. Next, we can initialize the simulation and set some tolerances.

We use an adaptive timestep ODE solver RKBS32 (it's essentially the same as MATLAB's ode23) so the event management system can use backtracking to accurately locate the events. Finally we can run the simulation for some duration.

Python
Loading...
12:43:14 - INFO - LOGGING (log: True)
12:43:14 - INFO - BLOCKS (total: 4, dynamic: 2, static: 2, eventful: 0)
12:43:14 - INFO - GRAPH (nodes: 4, edges: 3, alg. depth: 1, loop depth: 0, runtime: 0.045ms)
12:43:14 - INFO - STARTING -> TRANSIENT (Duration: 10.00s)
12:43:14 - INFO - --------------------   1% | 0.0s<0.1s | 2488.7 it/s
12:43:14 - INFO - ####----------------  20% | 0.0s<0.1s | 2722.6 it/s
12:43:14 - INFO - ########------------  40% | 0.1s<0.0s | 3913.4 it/s
12:43:14 - INFO - ############--------  60% | 0.1s<0.0s | 3361.1 it/s
12:43:14 - INFO - ################----  80% | 0.2s<0.0s | 3525.3 it/s
12:43:14 - INFO - #################### 100% | 0.2s<--:-- | 3280.8 it/s
12:43:14 - INFO - FINISHED -> TRANSIENT (total steps: 415, successful: 363, runtime: 187.25 ms)

Results

Due to the object-oriented and decentralized architecture of PathSim, the scope block holds the time series data directly. Reading the recorded data is as easy as:

Python
Loading...

And plotting the results in an external matplotlib window is also straightforward:

Python
Loading...
Output

We can also add the detected events to the plot by just iterating the event instance:

Python
Loading...
Output

Timestep Evolution

For educational purposes it might be interesting to have a look at the evolution of the timestep.

We can clearly see how the adaptive integrator in combination with the event handling system approaches the event location with smaller steps and once located takes larger steps again until the next event is in sight. And so on.

Python
Loading...
Output