Python Tutorial 4: Simulating Change

Tutorial Objectives and Overview

It is time to learn about coding repetitive calculations - what is known as iterative calculations. This is essential before moving on to simulating motion.

  • Learn how change the value of a variable each frame.

  • Learn how to use the built in variables of t and dt to represent time.

  • Learn how to scale calculations from frame rate time in Tychos to seconds using dt.

Real Time vs Virtual Time

Before we begin discussing how to simulate motion in two dimensions, we have to talk about time. All motion presupposes the existence of time, and so we must define the concept of time in our simulation tool.

Click on the link below to open the Tychos scenario in a new browser tab where you can follow along:

Python Tutorial: Executing Repetitive Calculations

In our simulated universe, time progresses as a function of what is known as the frame rate. This is the rate at which the universe recalculates the positions of all objects in the universe and then updates (or "refreshes") the universe. Each frame represents an individual calculation and "still frame" of the universe. It is a "step" in the evolution of the universe. Tychos uses a number of variables that each represent time in slightly different ways. Understanding each one is important to understanding how Tychos works.

Type the following into the Calculations Pane:

# The time interval
print("dt", dt)

# The number of elapsed frames
print("frame count", frame_count)

# Time elapsed in seconds
print("time", t)

When you start the simulation, you should see in the Console, the values for each variable printed for each frame in the animation, and should look something like this:

time 3
frame count 60
dt 0.05
time 2.95
frame count 59
dt 0.05
time 2.9
frame count 58
dt 0.05
time 2.85
frame count 57
dt 0.05
time 2.8
frame count 56
dt 0.05
frame count 60
dt 0.05
...

To slow down the numbers that are changing, you can click the Step button at the bottom of the simulation world window. Each time you click this button, you should see some of the numbers change.

Notice that dt does not change. This is the interval time - the segment of time between each frame. It is the "time step", or "delta time" that is used to calculate the amount of change that occurs from frame to frame. The smaller the value of dt, then the more frames per second that will be calculated for the animation. This will result in a smoother animation.

Note: If the rate is too high, the computer might not have enough time to execute the code, and so the simulation will appear to slow down. This delay will depend on the complexity of the code that is executed each frame as well as the speed of your computer.

You will see that the value of the next two variables are changing quickly. They are both increasing. The frame_count is the number of frames that have elapsed since you pressed the start button. This value represents the number of time intervals that have elapsed, and thus the number of times the simulation has been updated. The variable t is actually the time in seconds (simulated) that have elapsed since you pressed the start button. Type the following line of code into the Calculations pane:

print("sim time", frame_count * dt)

This demonstrates that the elapsed time in seconds is equal to the number of frames so far in the animation multiplied by the time interval between each frame. Each frame represents the state of our simulation at that moment in time and the simulation rate is the rate at which our simulated universe evolves.

You can modify the rate at which your universe evolves, and how smoothy or accurately it evolves. This is done by going to the Settings Pane and adjusting the step rate.

Setting the interval duration (dt) too low can result in slow animations because the number of times the universe has to be updated increases for each second, but setting it too high can cause the animation to "jump" and become less accurate. Change this setting and watch how the variable frame_count and dt change.

Repeating Calculations

One of the powerful aspects of computers is their ability to repeat calculations, and also to use a previous calculation as an input for the next calculation. For example, we can ask the computer to continually add one to a variable, thus increasing its value every time a new frame passes. In the Initial State pane, let's create a new variable:

x = 1

Then in the Calculations pane, type the following line of code:

x = x + 1
print("x is:", x)

This might seem like an odd line of code.

A very important point needs to be made here. The above line of code is not saying that "x" is equal to "x" plus one. That would be impossible mathematically because if "x" were 2, then how could 2 = 2 + 1?! In most computer programming languages though, the "=" sign is not a statement of equality, but rather a way to assign a new value to a variable - it's an assignment operator. So the code actually is saying this:

"Assign a new value to x that is the old value of x plus one".

When you run the simulation, take a look in the Console tab, and you will notice what is happening to the varaible x.

The value of of the calculation is changing because with every frame, the value of x has changed from the previous calculation. This is because we aren't just doing a calculation, but we are also reassigning the value of x to the value of the old "x" plus 1. So if "x" were 2, then the next frame "x" will be now 3 - its old value of 2 plus 1, making its new value 3.

There are a couple of goals you should try to achieve in the scenario just to make sure that you get how this works:

  • Create a variable called y whose initial value is 100 but that decreases by 1 each frame.

  • Create a variable called z whose initial value is 0 but whose value is always the result of y divided by x.

Recurring Vector Calculations

Just like normal variables, vector variables can be involved in recurring calculations. It is very similar, you just need to remember to perform the calculations as well as reassigning the result back to the original variable. There are several ways to do this, but let's look at the easiest to understand.

First create this new vector variable called v1 in the Initial State Pane:

v1 = vec(0, 0)

We are gong to use the incrementing value for x that we used before. Now assign the first element in the vector to the value of x. This is done in the Calculations pane:

x = x + 1
v1.x = x
print("vector 1", v1) 

When you run your simulation you should notice that the value of the x component of the vector changes.

You could also simply add an incremental vector - a "change" vector like this:

v1 = v1 + vec(1, 1)

Just like with a single value, the vector v1 will change in value by (1, 1) so each of the components in the vector will increment by 1 every step of the animation.

Try creating some vectors whose values change each step by achieving the next two goals:

  • Create a variable called v2 whose initial value is (100, 100) but that decreases by (1, 1) each animation step.

  • Create a variable called v3 whose initial value is (0, 0) but whose value is always the result of v1 + v2.

Using Meters To Display Variable Values

Tychos provides a way for you to more easily see in the simulated world a variable's value. This tool is called a meter. A meter is a numeric display that you create in the Initial State Pane and then you specify the data to display in the Calculations Pane. Each meter that is created will appear on the left side of the World View (though you can change that to align it to the right side of the window). Your program needs to tell the Meter what value it needs to display by using the read command.

To create a meter , you first need to write this line of code in the Initial State Pane:

my_meter = meter("Value for x")

This tells Tychos to create a new display box in the World View with the title "Value for x".

To get the meter to actually display data, you need to specify a numeric variable's value to display . This line of code would need to be written in the Calculations Pane:

my_meter.display(x)

This would then allow the meter to read the value of the variable x and display it on the screen. You can only display a single numerical value on a meter, so if you want to display a vector value you can only display one component of the vector using this notation:

# Display x component of v1 
my_meter.display(v1.x)

Scaling Time to Seconds

This next point is very important to understand. So far all of our calculations were scaled to the step rate, which is a unit of time. The unit of time that we use in our experiments is the second. In order for our simulations to be scaled to this "real time" in seconds, we need to do a scaling calculation.

This point can be demonstrated. Let's suppose that you wanted to change a variable's value by a certain amount each second, rather than each frame. For example, we wanted to change the value of a new variable, let's call it s, and we want to change the value of s by 10 each second. Create the variables in the Initial State Pane:

s = 0

Now try this in the Calculations Pane:

s = s + 10
my_meter.display(s)

What you should see is that the value of s is increasing way too quickly! That's because it is increasing by 10 every step of the animation, not 10 every second! If the animation rate were 50 steps per second, then the value of s would already be 500 by the end of the first second!

Remember that each step represents a time duration for the existence of the simulated universe - a "step" in its evolution. The time interval is represented by the variable dt and its value is based on the number of steps that pass each second. If the animation rate were 50 steps per second, then the value of dt would be .02 because:

We can use this important variable to scale our calculation to a time based on seconds rather than a time based on steps. We are going to define a new variable called ds that will represent how much we want to change s each frame:

ds = 10 * dt

The value of ds is:

So if we perform this calculation for increasing s:

s = s + ds

You will see that the value of s will increase by .2 each step, and because there 50 steps in a given second, then we can see that the value of s after a single second should increase by 10 because it increased by 0.2 fifty times in one second:

This allows us to perform calculations based on seconds rather than having to figure out how much to change our variables based on the animation rate. This is really good, because now, if we change the animation rate, the calculations do not have to be rescaled and thus our code does not have to change. You can test this out by changing the interval duration time in the Settings tab and you will see that the rate of change to s remains the same. The only difference is how much it changes each frame, but not each second.

Once again, the larger the animation rate, then the greater the number of animation steps, which can result in a more "accurate" animation due to the fact that you are telling Tychos to make more calculations every second based on smaller time intervals...but this can also result in slower animations when they are played in the viewer.

Try these goals to see if you fully understand this:

  • Create a variable called s2 whose initial value is 100 but decreases by a value of 10 each second.

  • Create a variable called m4 whose initial value is [0, 0] but whose value changes by [10, -5] each second.

We are now ready to start talking about how to simulate motion...

Last updated