A reflector is fixed to a bicycle wheel at a distance r metres from the hub. The wheel turns rev revolutions per second, anticlockwise as the camera sees it, and the camera takes fs frames per second. At frame k (time t = k / fs seconds) the reflector has turned through the angle
angle = phase + 2 * pi * rev * k / fs (radians)
where phase is its angle at frame 0, measured anticlockwise from the right.
A complex number is a natural way to store such a position. Python writes the imaginary unit as 1j, and cmath.exp(1j * angle) is the arrow of length 1 pointing at angle: its real part is cos(angle) and its imaginary part is sin(angle). Multiplying by r stretches it to length r. So the reflector is at z = r * cmath.exp(1j * angle), with x = z.real to the right of the hub and y = z.imag above it. (abs(z) gives the length back, and cmath.phase(z) the angle.) This turning arrow is the building block of frequency analysis: the discrete Fourier transform compares a signal with arrows like it.
Write reflector_track(r, rev, fs, phase, n) that returns a list of n pairs (x, y), the reflector's position in the first n frames. Press Run with plot([p[0] for p in track], [p[1] for p in track], kind="scatter") to see the dots on a circle.
Examples
Input: r = 0.3, rev = 1, fs = 4, phase = 0, n = 5
Output: [(0.3, 0.0), (0.0, 0.3), (-0.3, 0.0), (0.0, -0.3), (0.3, 0.0)]
Explanation: four frames per turn, so the reflector moves a quarter turn per frame:
right, top, left, bottom, and back to the right.
Input: r = 2, rev = 0, fs = 10, phase = 1.5707963267948966, n = 2
Output: [(0.0, 2.0), (0.0, 2.0)]
Explanation: a wheel standing still with the reflector at the top (a quarter turn, pi / 2).
Values like 1.8e-17 where the exact answer is 0 count as correct.
Constraints
- answers are compared with a tolerance of
1e-6; do not round
Goals
- Use a complex number as an arrow: its real part is x, its imaginary part is y
- Build a turning arrow with cmath.exp(1j * angle)
- Sample a rotation at a frame rate, like sampling a signal