Skip to main content
Mathematics LibreTexts

16.3: Odd Clock

  • Page ID
    67840
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Consider the clock depicted in the following image.

    The odd clock.
    Image from: Hackaday.

    Instead of a standard clock–which has independent hour and minute hands–this clock connects the minute hand at the end of the hour hand. Here is a video showing the sped-up clock motion:

    from IPython.display import YouTubeVideo
    YouTubeVideo("bowLiSlm_gA",width=640,height=360, mute=1)

    The following code is an animated traditional clock which uses the function as a trick to animate things in jupyter:

    %matplotlib inline
    import matplotlib.pylab as plt
    from IPython.display import display, clear_output
    import time
    def show_animation(delay=0.01):
        fig = plt.gcf();
        time.sleep(delay)       # Sleep for half a second to slow down the animation
        clear_output(wait=True) # Clear output for dynamic display
        display(fig)            # Reset display
        fig.clear()             # Prevent overlapping and layered plots

    Lets see a standard analog clock run at high speed

    import numpy as np
    '''
    Analog clock plotter with time input as seconds
    '''
    def analog_clock(tm=0):
    
        #Convert from time to radians
        a_minutes = -tm/(60*60) * np.pi * 2
        a_hours = -tm/(60*60*12) * np.pi * 2
    
        #Define clock hand sizees
        d_minutes = 4
        d_hours = 3 
        arrow_width=0.5
        arrow_length=1
    
        # Set up figure
        fig = plt.gcf()
        ax = fig.gca();
        ax.set_xlim([-15,15]);
        ax.set_ylim([-10,10]);
        ax.scatter(0,0, s=15000, color="navy"); #Background Circle
        plt.axis('off');
            
        # Calculation Minute hand transformation matrix
        J2 = np.matrix([[np.cos(a_minutes), -np.sin(a_minutes)], 
                        [np.sin(a_minutes), np.cos(a_minutes)]] )
        pm = np.matrix([[0,d_minutes], [-arrow_width,d_minutes], [0,arrow_length+d_minutes], [arrow_width,d_minutes], [0,d_minutes]] ).T;
        pm = np.concatenate((J2*pm, np.matrix([0,0]).T), axis=1 );
        ax.plot(pm[0,:].tolist()[0],(pm[1,:]).tolist()[0], color='cyan', linewidth=2);
    
        # Calculation Hour hand transformation matrix    
        J1 = np.matrix([[np.cos(a_hours), -np.sin(a_hours)], 
                        [np.sin(a_hours), np.cos(a_hours)]] )
        ph = np.matrix([[0,d_hours], [0,d_hours], [-arrow_width,d_hours], [0,arrow_length+d_hours], [arrow_width,d_hours], [0,d_hours]]).T;
        ph = np.concatenate((J1*ph, np.matrix([0,0]).T), axis=1 );
        ax.plot(ph[0,:].tolist()[0],(ph[1,:]).tolist()[0], color='yellow', linewidth=2);
    #Run the clock for about 5 hours at 100 times speed so we can see the hands move
    for tm in range(0,60*60*5, 100):
        analog_clock(tm);
        show_animation();
    # 'Run' this cell to see the animation

    For the following few questions, consider the transformation matrix \(J_1\) redefined below with an angle of 5 hours out of 12.

    import sympy as sym
    import numpy as np
    sym.init_printing(use_unicode=True)
    
    a_hours = 5/12 * 2 * np.pi
    J1 = np.matrix([[np.cos(a_hours), -np.sin(a_hours)], 
                    [np.sin(a_hours), np.cos(a_hours)]] )
    
    sym.Matrix(J1)
    Question

    Using code, show that the transpose of \(J_1\) is also the inverse of \(J_1\), then explain how the code demonstrates the answer.

    #Put your answer here
    Question

    Given the trigonometric identity \(cos^2(\theta) + sin^2(\theta) = 1\), prove by construction–using either Python or LaTeX/Markdown or sympy (if you are feeling adventurous)–that the transpose of the \(J_1\) matrix is also the inverse for ANY angle a_hours \(\in[0,2\pi]\).

    Now consider the following code which attempts to connect the hands on the clock together to make the Odd Clock shown in the video above.

    import numpy as np
    
    def odd_clock(tm=0):
    
        #Convert from time to radians
        #a_seconds = -tm/60 * np.pi * 2
        a_minutes = -tm/(60*60) * np.pi * 2
        a_hours = -tm/(60*60*12) * np.pi * 2
    
        #Define robot geomitry
        #d_seconds = 2.5  
        d_minutes = 2
        d_hours = 1.5 
        arrow_width=0.5
        arrow_length=1
    
        # Set up figure
        fig = plt.gcf()
        ax = fig.gca();
        ax.set_xlim([-15,15]);
        ax.set_ylim([-10,10]);
        plt.axis('off');
        
        #Define the arrow at the end of the last hand 
        #p = np.matrix([[0,d_minutes,1], [0,0,1]]).T
        p = np.matrix([[0,d_minutes,1], [-arrow_width,d_minutes,1], [0,arrow_length+d_minutes,1], [arrow_width,d_minutes,1 ], [0,d_minutes,1 ], [0,0,1]] ).T;
        
        # Calculation Second hand transformation matrix     
        J2 = np.matrix([[np.cos(a_minutes), -np.sin(a_minutes), 0 ], 
                        [np.sin(a_minutes), np.cos(a_minutes), d_hours ], 
                        [0, 0, 1]])
        p = np.concatenate((J2*p, np.matrix([0,0,1]).T), axis=1 )
        
        J1 = np.matrix([[np.cos(a_hours), -np.sin(a_hours), 0 ], 
                        [np.sin(a_hours), np.cos(a_hours), 0 ], 
                        [0, 0, 1]])
        p = np.concatenate((J1*p, np.matrix([0,0,1]).T), axis=1 )
    
        ax.scatter(0,0, s=20, facecolors='r', edgecolors='r')
        ax.plot(p[0,:].tolist()[0],(p[1,:]).tolist()[0])
    #Run the clock for about 5 hours at 100 times speed so we can see the hands move
    for tm in range(0,60*60*5, 100):
        odd_clock(tm);
        show_animation();
    # 'Run' this cell to see the animation
    Question

    Using the given point (\(p\)) written in “minutes” coordinates (on line 26 of the above code) and the above transformation matrices (\(J_1\),\(J_2\)), write down the equation to transform \(p\) into world coordinates \(p_w\).

    Question

    Notice the above odd_clock function has variables d_seconds and a_seconds commented out. Use these variables and modify the above code to add a “seconds” hand on the tip of the minute hand such that the seconds hand moves around the minute hand just like the minute hand moves around the hour hand. If you have trouble, use the following cell to explain your thought process and where you are getting stuck.


    This page titled 16.3: Odd Clock is shared under a CC BY-NC 4.0 license and was authored, remixed, and/or curated by Dirk Colbry via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.

    • Was this article helpful?