Rodney Dunning's Home Page | Research and Scholarship | VPython | Simultaneity
Introduction
Suppose two firecrackers at different locations explode at the same time, with their positions and the time of the explosions determined by clocks and meter sticks which are at rest relative to you. An observer moving relative to you will claim the firecrackers did not explode simultaneously, i.e., one exploded before the other. Physically, this claim is just as correct as your observation.
Einstein's special theory of relativity predicts that events which are simultaneous in one reference frame will not be simultaneous in another reference frame, unless the events occur at the same location.
This animation was inspired by Figures 3-2 and 3-3 in Lewis C. Epstein, Relativity Visualized, (Insight Press, San Francisco, 1985), pp. 35-36.
Description
The animation shows three rockets. The flag ship, in the center, is piloted by and labeled "Alice." The lead ship is labeled "Bob," and the rear ship is labeled "Claire." Each rocket has a flag that will raise at a predetermined event.
Alice's rocket sends a light signal that reaches both Claire and Bob. The signal appears as a ring. When the signal reaches Claire and Bob, as measured in Alice's reference frame, Alice raises her flag. Claire and Bob each raise their flag when the signal from Alice is received.
A sequence of five events takes place:
- Event A: Alice sends a signal to both Claire and Bob.
- Event B: Bob receives the signal from Alice, rasies his flag, and sends a response signal to Alice.
- Event C: Claire receives the signal from Alice, rasies her flag, and sends a response signal to Alice.
- Event D: Alice raises her flag at the time she calculates Bob and Claire to have received her signal. In Alice's reference frame, events B, C, and D occur simultaneously.
- Event E: Alice receives the response signals from Bob and Claire.
If the sequence of events is viewed with the rockets at rest, events B, C, and D occur simultaneously. If the sequence of events is viewed with the rockets moving to the right (with Bob in the lead), event C occurs before event D, which occurs before event B.
When you execute the program, you are prompted for the speed of the Other Frame, attached to the rockets, relative to the Home Frame, attached to the animation window.
Screen Shots
The rockets are viewed in a frame in which they are at rest. The light
signal from Alice (the largest circle) reaches Claire and Bob at the
same time.
The rockets are viewed in a frame in which they move to the right at 50%
of the speed of light. The signal from Alice (the largest circle), reaches
Claire before it reached Bob.
Suggested Use
What I did:
- First run the program with zero speed for the Other Frame. This allows students to view the events from within the Other Frame, which is attached to the ships. Ask the students to observe whether the flags are raised simultaneously.
- Run the program with the ships moving at 50% of the speed of light. (Enter 0.5 for the speed of the Other Frame.) Ask the students to observe whether the flags are raised simultaneously.
- Use the mouse coordinates and the clock to determine event coordinates in the Other Frame, attached to the rocket, and the Home Frame, attached to the animation window. Verify that the animation's results are consistent with the Lorentz transformation equations. I show some sample calculations below.
Hints:
- Stress that in each animation, students are viewing the same sequence of events that Alice herself views, at rest in the Other Frame. Events that occur simultaneously in a reference frame attached to Alice's ship do not occur simultaneously in other reference frames.
- Point out the Lorentz contraction of the ships and the separation distances between them.
- Click anywhere in the animation scene to pause the animation. Click again to restart the animation.
- Run the animation with different speeds for the Other Frame. With a very low speed, the flags are raised nearly simultaneously.
Recall the Lorentz transformation equations:
t = γ(t' + βx')
x = γ(x' + βt')
The Other Frame is attached to the rockets. The Home Frame is attached to the animation window. Suppose the Other Frame speed relative to the Home Frame is β = 0.5. Then γ = 1.1547.
Event A: Alice sends the signal. The Other Frame coordinates are t = 0, x = 0. The Home Frame coordinates should be t' = 0 and x' = 0.
Event B: Bob, in the lead ship, receives Alice's signal. The Other Frame coordinates are t' = 100 s, x' = 100 s. The Home Frame coordinates should be t = 173.2 s, x = 173.2 s.
Event C: Claire, in the rear ship, receives Alice's signal. The Other Frame coordinates are t' = 100 s, x' = -100 s. The Home Frame coordinates should be t = 57.7 s, x = 57.7 s.
You can use the animation to confirm that the Home Frame coordinates are correct for each of these events.
Source Code
The source code appears between the bars below. Copy and paste the code into the Python IDLE environment, and hit F5 to run the code.
from visual import *
from __future__ import division
"""
Rodney Dunning
Assistant Professor of Physics
Longwood University
See Figures 3-2 and 3-3 in Epstein's
"Relativity Visualized," pp. 35-36.
The Other Frame is attached to the ships. The
Home Frame is attached to the animation window.
User enters the speed of the Other Frame
relative to his own frame, the Home Frame.
The ships are spaced 100 light-seconds
apart. At t = 0.0 seconds in the Home
Frame and Other Frame, a signal is sent from the
central ship to the lead and rear ships. Upon
reception of the signal, each ship sends a
signal back to the central ship.
"""
#----------------------------
# The clock class
#----------------------------
class clock:
def __init__(self,
t = 0.0,
dt = 0.01,
t_max = 1000.0):
self.t = t
self.dt = dt
self.t_max = t_max
self.label = label(pos=(0,0,0),
text="Clock")
def tick(self):
self.t += self.dt
def full_time(self):
return self.t >= self.t_max
def set_time(self,t):
self.t = t
def reset(self):
self.t = 0
#----------------------------------
# The ship class
#----------------------------------
class ship:
def __init__(self,
pos = vector(0,0,0), # position
vel = vector(0,0,0), # velocity
acc = vector(0,0,0), # acceleration
force = vector(0,0,0), # force
mass = 1.0, # common mass of the ships
L = 25.0, # common length of the ships
W = 10.0, # common width of the ships
H = 5.0, # common height of the ships
fL = 25.0/7.0, #flag length
fW = 10.0/20.0, # flag width
fH = 5.0, #flag height
pR = 0.5, # common radius of the flag poles
theta = 0, # initial angle of the flag
d_theta = 0.01, #step size for rotating the flag
label_text = "Ship"):
self.Lproper = L
self.ship = frame(pos=pos,
vel=vel,
acc=acc,
mass=mass,
force=force)
self.body = box(frame=self.ship,
length = L,
width = W,
height = H)
self.flag = frame(frame=self.ship,
angle=0,
step=d_theta)
self.pole = cylinder(frame=self.flag,
axis=(L/1.25,0,0),
radius = pR,
color = color.green)
self.cloth = box(frame=self.flag,
height = fH,
width = fW,
length = fL,
pos = (L/1.25 - H/2, H/2,0), #within the frame!
color=color.red)
self.label = label(frame = self.ship,
pos = vector(0,-1.5*H,0), #within the frame!
box = 0,
text = label_text)
def move(self,dt): # moves the ship foward one step
self.ship.pos += self.ship.vel * dt
def rotate_flag(self):
pi = acos(-1.0) #3.14159....
self.flag.rotate(angle=self.flag.step,
axis=(0,0,1))
self.flag.angle += self.flag.step
#----------------------------------------
# The light signal class.
#----------------------------------------
class light_signal:
def __init__(self,
pos = vector(0,0,0), # initial position
thickness = 0.5, # thickness of the ring
radius = 0, # initial radius
rate = 1.0 # speed of light
):
self.body = ring(pos=pos, # initial position
thickness = thickness,
axis=(0,0,1),
radius = radius,
rate = rate,
color = color.white)
def propagate(self,dt):
self.body.radius += self.body.rate * dt
#-------------------------
# The labels class
#-------------------------
class labels:
def __init__(self,
list = [] #empty list of labels
):
self.list = list
def toggle(self):
for x in self.list:
x.visible = abs(1 - x.visible)
#----------------------------
# Useful quantities
#
# SR units throughout
#----------------------------
ship_separation = vector(100,0,0)
flag_delay = mag(ship_separation)
c = 1 # speed of light
signal_time = 0.0 # signal time; part of the origin event
# in the Home and Other Frames.
#--------------------------------------------
# The user enters the speed of the Home Frame
# relative to his own frame.
#--------------------------------------------
user_finished = 0 # set to 1 when finished
while(not user_finished):
beta = input("Enter the Other Frame speed relative to you: ")
print " " # spacer
if(0 <= beta and beta < 1):
user_finished = 1
gamma = 1 / sqrt(1 - beta**2)
ship_separation /= gamma
signal_time*=gamma
else:
print " " #spacer
print "Input error. Please enter a value between 0 and 1."
print " " # spacer
print "beta = ",beta
print "gamma = ",gamma
print "ship separation is ",ship_separation.x
print " " # spacer
print "Thank you. Please find the animation window."
#----------------------------------------
# Specify the scene attributes
#----------------------------------------
scene.title = "The Relativity of Simultaneity"
scene.x = 0
scene.y = 0
scene.width = 800
scene.height = 600
scene.range = (200,200,200)
scene.autoscale = 0 ##0 means autoscaling is OFF
scene.userzoom = 1 ##0 means user cannot zoom
scene.userspin = 1 ##0 means user cannot spin
scene.lights = [vector(0,0,1)]
scene.ambient = 0.5
scene.label = label(visible=0,
pos=(0,0,0),
xoffset = 0,
yoffset = 0,
text = ("Click to begin.\n"))
scene.mouse_label = label(visible=1,
pos=(0,0,0),
text="Mouse position")
def return_mouse_pos(scene):
scene.mouse_label.text = ("mouse\n x: %3.2f y: %3.2f"
%(scene.mouse.pos.x, scene.mouse.pos.y))
def check_for_pause(scene): #checks for pause request
if scene.mouse.clicked:
scene.mouse.getclick()
pause(scene)
def pause(scene): #pauses the animation
while 1:
return_mouse_pos(scene)
if scene.mouse.clicked:
scene.mouse.getclick()
break
scene.mouse_label.pos = vector(beta*scene.range.x,100,0)
""" We shift the center of the scene to keep all the events
in the animation window, but the origin event in both
Home and Other Frame is the initial signal sent by
the flag ship.
"""
if(beta > 0):
scene.center = vector(beta*scene.range.x,0,0)
#----------------------------------------
# Create a clock.
#----------------------------------------
master_clock = clock()
master_clock.t = -5.0
master_clock.t_max = 1000.0
master_clock.label.pos.x = beta*scene.range.x
master_clock.label.pos.y = -100
master_clock.label.text = "Master Clock"
#--------------------------------------
# Create three ships: the flag ship,
# the rear ship, and the lead ship.
#--------------------------------------
flag_ship = ship(pos=vector(0,0,0),
vel=vector(beta*c,0,0),
acc=vector(0,0,0),
label_text="Alice")
rear_ship = ship(pos=flag_ship.ship.pos - ship_separation,
vel=vector(beta*c,0,0),
acc=vector(0,0,0),
label_text="Claire")
lead_ship = ship(pos=flag_ship.ship.pos + ship_separation,
vel=vector(beta*c,0,0),
acc=vector(0,0,0),
label_text="Bob")
flag_ship.body.length = flag_ship.Lproper / gamma
rear_ship.body.length = flag_ship.Lproper / gamma
lead_ship.body.length = flag_ship.Lproper / gamma
#-----------------------------------------------
# Create a list of labels to toggle on and off
#-----------------------------------------------
label_list = labels(list=(master_clock.label,
scene.label,
scene.mouse_label,
lead_ship.label,
flag_ship.label,
rear_ship.label))
#---------------------------------------
# Animate the scene
#---------------------------------------
ready = 0
label_list.toggle()
while(not ready):
ready = scene.mouse.getclick()
label_list.toggle()
center_signal = 0 # set to 1 when the signal is created
rear_signal = 0 # set to 1 when signal is created
lead_signal = 0 # set to 1 when signal is created
center_flag = 0 # set to 1 when center flag is raised
rear_flag = 0 # set to 1 when signal is received
lead_flag = 0 # set to 1 when signal is received
while(not master_clock.full_time()):
## rate(1000) # change this number to change the animation speed
check_for_pause(scene)
return_mouse_pos(scene)
master_clock.tick()
master_clock.label.text = "Clock t= %3.2f" %master_clock.t
flag_ship.move(master_clock.dt)
rear_ship.move(master_clock.dt)
lead_ship.move(master_clock.dt)
if(master_clock.t > signal_time and not center_signal): #create a light signal
signal_from_center = light_signal(pos=flag_ship.ship.pos)
center_signal = 1
if(rear_flag and not rear_signal): #create a rear signal
signal_from_rear = light_signal(pos=rear_ship.ship.pos)
rear_signal = 1
if(lead_flag and not lead_signal): #create a lead signal
signal_from_lead = light_signal(pos=lead_ship.ship.pos)
lead_signal = 1
if(rear_signal):
signal_from_rear.propagate(master_clock.dt)
if(lead_signal):
signal_from_lead.propagate(master_clock.dt)
if(center_signal):
signal_from_center.propagate(master_clock.dt)
"""
The following block of code rotates the center ship
flag when, the in the reference frame of the center
ship, its signals reach the front and rear ships.
(These events occur simultaneously in the center
ship's reference frame.)
The master clock keeps the time in the Home Frame,
the frame attached to the animation window.
The Other Frame is attached to the ships.
These frames will coincide if you entered zero for
the speed of the Home Frame.
"""
if( (signal_time + flag_delay*gamma) < master_clock.t
and flag_ship.flag.angle < pi/2):
flag_ship.rotate_flag()
if(not center_flag): center_flag = 1
"""
In the following blocks of code, the flags on the rear
and lead ships are rotated when the radius of the signal
sent from the flag ship exceeds the rear-flag or lead-flag
separation distance.
"""
if(mag(rear_ship.ship.pos - signal_from_center.body.pos) <
signal_from_center.body.radius
and
rear_ship.flag.angle < pi/2):
if(not rear_flag): rear_flag = 1
rear_ship.rotate_flag()
if(mag(lead_ship.ship.pos - signal_from_center.body.pos) <
signal_from_center.body.radius
and
lead_ship.flag.angle < pi/2):
if(not lead_flag): lead_flag = 1
lead_ship.rotate_flag()
scene.label.text = ("Finished. Close the window and\n"
"reopen the file to view the\n"
"animation again.\n"
"" #spacer
"Copyright, 2006. Rodney Dunning.")
label_list.toggle()