Loading [MathJax]/extensions/Safe.js

Lab 3: Friction Forces¶

Course: PHYS 216-503

Created Date: 9 March 2022

In [8]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

%load_ext autoreload

pd.options.display.float_format = '{:,.5f}'.format
pd.options.display.max_columns = 100
plt.style.use('seaborn-darkgrid')

# General Markdown Formatting Functions
from IPython.display import Markdown, display, HTML, JSON

def printmd(string: str, level: int=1):
    '''Display Markdown text with a default header value of 1.'''
    header_level = '#'*level + ' '
    display(Markdown(header_level + string))
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
In [9]:
%autoreload
import friction_experiment

# Initialize each experiment.
static_big = friction_experiment.FrictionExperiment(type='static', surface='big', trials=9)
static_small = friction_experiment.FrictionExperiment(type='static', surface='small', trials=9)
kinetic_big = friction_experiment.FrictionExperiment(type='kinetic', surface='big', trials=9)
kinetic_small = friction_experiment.FrictionExperiment(type='kinetic', surface='small', trials=9)

Theory¶

Angle of Decline $$\begin{aligned} \bar{r}_{\mathrm{Base}} &= \bar{r}_{\mathrm{Green}} - \bar{r}_{\mathrm{Orange}} \\ \bar{r}_{\mathrm{Ramp}} &= \bar{r}_{\mathrm{Pink}} - \bar{r}_{\mathrm{Orange}}\\ \theta &= \frac{ \bar{r}_{\mathrm{Base}} \cdot \bar{r}_{\mathrm{Ramp}} }{ \| \bar{r}_{\mathrm{Base}} \| \cdot \| \bar{r}_{\mathrm{Ramp}} \| } \end{aligned}$$

Static Friction Coefficient
$$\begin{aligned} \sum \bar{F} &= \bar{F_N} + \bar{F_f} + \bar{F_{g_{\parallel}}} + \bar{F_{g_{\perp}}} = 0 \\ \bar{F_f} &= \bar{F_{g_{\parallel}}} \\ \mu_s \bar{F_N} &= \bar{F_{g_{\parallel}}} \\ \mu_s m g \cos(\theta) &= m g \sin(\theta) \\ \mu_s &= \tan(\theta) \end{aligned}$$

Kinetic Friction Coefficient
$$\begin{aligned} m a &= \bar{F_{g_{\parallel}}} - \bar{F_f}\\ m a &= m g \sin(\theta) - \mu_k m g \cos(\theta)\\ \mu_k &= \frac{1}{\cos(\theta)} \times (\sin(\theta) - \frac{a}{g}) \end{aligned}$$

Data Analysis¶

In [10]:
# Show and summarize the contents of one of the trials.
printmd("Static Friction - Small Area: Trial 1 - Raw Data Collected", 3)
print('Units: timestamp (ms), px-(px), r-(m), v-(m/s), a-(m/s^2)')
display(static_small.trials[0].raw_data)
display(static_small.trials[0].raw_data.describe())

Static Friction - Small Area: Trial 1 - Raw Data Collected¶

Units: timestamp (ms), px-(px), r-(m), v-(m/s), a-(m/s^2)
frame_no timestamp size_px-darkorange position_px_x-darkorange position_px_y-darkorange rx-darkorange ry-darkorange vx-darkorange vy-darkorange ax-darkorange ay-darkorange size_px-green position_px_x-green position_px_y-green rx-green ry-green vx-green vy-green ax-green ay-green size_px-hotpink position_px_x-hotpink position_px_y-hotpink rx-hotpink ry-hotpink vx-hotpink vy-hotpink ax-hotpink ay-hotpink size_px-lightorange position_px_x-lightorange position_px_y-lightorange rx-lightorange ry-lightorange vx-lightorange vy-lightorange ax-lightorange ay-lightorange size_px-yellowneon position_px_x-yellowneon position_px_y-yellowneon rx-yellowneon ry-yellowneon vx-yellowneon vy-yellowneon ax-yellowneon ay-yellowneon
0 0 135.60000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.70000 4.92000 0.39000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 1 135.60000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.51000 0.50000 5.48000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 2 244.80000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.52000 0.50000 5.49000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 3 266.00000 0.15000 9.89000 0.64000 0.65547 0.04242 NaN NaN NaN NaN 0.14000 0.65000 0.78000 0.04308 0.05170 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.10000 2.14000 3.79000 0.14183 0.25119 NaN NaN NaN NaN
4 4 286.60000 0.15000 9.89000 0.65000 0.65547 0.04308 NaN NaN NaN NaN 0.14000 0.65000 0.78000 0.04308 0.05170 NaN NaN NaN NaN 0.14000 0.75000 3.39000 0.04971 0.22468 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.12000 2.12000 3.78000 0.14051 0.25052 NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
423 423 14,110.40000 0.15000 9.90000 0.64000 0.65613 0.04242 0.00000 0.00000 0.00000 0.00000 0.14000 0.66000 0.79000 0.04374 0.05236 -0.00331 0.00000 -0.06608 0.00000 0.14000 1.58000 5.25000 0.10472 0.34795 -0.00330 -0.00661 0.06595 -0.00013 NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.10000 9.98000 1.07000 0.66144 0.07092 0.00000 0.00000 0.00000 0.00000
424 424 14,142.20000 0.15000 9.90000 0.64000 0.65613 0.04242 0.00000 0.00000 0.00000 0.00000 0.14000 0.65000 0.78000 0.04308 0.05170 0.00000 -0.00005 0.00000 0.13189 0.14000 1.59000 5.25000 0.10538 0.34795 -0.00328 -0.00328 -0.06572 -0.06572 NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.09000 9.98000 1.06000 0.66144 0.07025 -0.00333 -0.00005 0.06618 0.13189
425 425 14,174.70000 0.15000 9.90000 0.64000 0.65613 0.04242 NaN NaN NaN NaN 0.14000 0.65000 0.78000 0.04308 0.05170 NaN NaN NaN NaN 0.14000 1.59000 5.25000 0.10538 0.34795 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.09000 9.98000 1.07000 0.66144 0.07092 NaN NaN NaN NaN
426 426 14,210.50000 0.15000 9.90000 0.64000 0.65613 0.04242 NaN NaN NaN NaN 0.14000 0.65000 0.79000 0.04308 0.05236 NaN NaN NaN NaN 0.14000 1.58000 5.24000 0.10472 0.34729 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.10000 9.98000 1.07000 0.66144 0.07092 NaN NaN NaN NaN
427 427 14,242.80000 0.15000 9.90000 0.64000 0.65613 0.04242 NaN NaN NaN NaN 0.14000 0.65000 0.79000 0.04308 0.05236 NaN NaN NaN NaN 0.15000 1.58000 5.24000 0.10472 0.34729 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.09000 9.98000 1.07000 0.66144 0.07092 NaN NaN NaN NaN

428 rows × 47 columns

frame_no timestamp size_px-darkorange position_px_x-darkorange position_px_y-darkorange rx-darkorange ry-darkorange vx-darkorange vy-darkorange ax-darkorange ay-darkorange size_px-green position_px_x-green position_px_y-green rx-green ry-green vx-green vy-green ax-green ay-green size_px-hotpink position_px_x-hotpink position_px_y-hotpink rx-hotpink ry-hotpink vx-hotpink vy-hotpink ax-hotpink ay-hotpink size_px-lightorange position_px_x-lightorange position_px_y-lightorange rx-lightorange ry-lightorange vx-lightorange vy-lightorange ax-lightorange ay-lightorange size_px-yellowneon position_px_x-yellowneon position_px_y-yellowneon rx-yellowneon ry-yellowneon vx-yellowneon vy-yellowneon ax-yellowneon ay-yellowneon
count 428.00000 428.00000 425.00000 425.00000 425.00000 425.00000 425.00000 419.00000 419.00000 419.00000 419.00000 425.00000 425.00000 425.00000 425.00000 425.00000 419.00000 419.00000 419.00000 419.00000 424.00000 424.00000 424.00000 424.00000 424.00000 418.00000 418.00000 418.00000 418.00000 3.00000 3.00000 3.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 377.00000 377.00000 377.00000 377.00000 377.00000 342.00000 342.00000 342.00000 342.00000
mean 213.50000 7,129.59089 0.15012 9.89927 0.64351 0.65608 0.04265 0.00008 -0.00017 -0.00085 -0.00327 0.14000 0.65273 0.78718 0.04326 0.05217 0.00005 0.00001 -0.00004 -0.00148 0.14901 1.11608 4.23733 0.07397 0.28083 0.00398 0.00857 -0.00024 0.00143 0.57667 1.97333 3.78667 NaN NaN NaN NaN NaN NaN 0.10780 3.66955 3.66095 0.24320 0.24263 0.03819 -0.01472 -0.04975 0.02968
std 123.69721 4,119.35752 0.00108 0.00372 0.00478 0.00025 0.00032 0.00184 0.00271 0.06685 0.10011 0.00000 0.00446 0.00451 0.00030 0.00030 0.00226 0.00283 0.08485 0.11249 0.00299 0.34986 0.77276 0.02319 0.05122 0.00547 0.01277 0.06274 0.15490 0.10693 2.55189 2.94160 NaN NaN NaN NaN NaN NaN 0.01415 2.80122 1.09493 0.18565 0.07257 0.11265 0.06286 1.10251 0.46623
min 0.00000 135.60000 0.15000 9.88000 0.64000 0.65481 0.04242 -0.00596 -0.02774 -0.43284 -1.02468 0.14000 0.65000 0.78000 0.04308 0.05170 -0.00568 -0.02774 -0.59464 -1.45751 0.14000 0.74000 3.36000 0.04904 0.22269 -0.00358 -0.05548 -0.19843 -2.04935 0.51000 0.50000 0.39000 NaN NaN NaN NaN NaN NaN 0.07000 2.10000 1.06000 0.13918 0.07025 -0.32207 -0.23483 -11.15104 -4.23883
25% 106.75000 3,566.27500 0.15000 9.90000 0.64000 0.65613 0.04242 0.00000 -0.00001 0.00000 0.00000 0.14000 0.65000 0.78000 0.04308 0.05170 -0.00004 -0.00003 -0.06458 -0.06590 0.15000 0.79000 3.51000 0.05236 0.23263 0.00000 0.00000 -0.06017 -0.06556 0.51500 0.50000 2.93500 NaN NaN NaN NaN NaN NaN 0.10000 2.16000 3.81000 0.14316 0.25251 0.00000 -0.00330 -0.06667 -0.06985
50% 213.50000 7,126.30000 0.15000 9.90000 0.64000 0.65613 0.04242 0.00000 0.00000 0.00000 0.00000 0.14000 0.65000 0.79000 0.04308 0.05236 0.00000 0.00000 0.00000 0.00000 0.15000 0.97000 3.99500 0.06429 0.26477 0.00009 0.00332 0.00000 0.00000 0.52000 0.50000 5.48000 NaN NaN NaN NaN NaN NaN 0.11000 2.19000 3.86000 0.14514 0.25583 0.00330 0.00327 0.00000 0.00000
75% 320.25000 10,689.85000 0.15000 9.90000 0.65000 0.65613 0.04308 0.00000 0.00000 0.00000 0.00000 0.14000 0.66000 0.79000 0.04374 0.05236 0.00007 0.00006 0.06616 0.05521 0.15000 1.52250 5.14250 0.10091 0.34082 0.00988 0.01944 0.00564 0.06581 0.61000 2.71000 5.48500 NaN NaN NaN NaN NaN NaN 0.12000 2.78000 4.23000 0.18425 0.28035 0.01043 0.01135 0.06676 0.11484
max 427.00000 14,242.80000 0.16000 9.91000 0.65000 0.65680 0.04308 0.01391 0.01134 0.53409 0.61988 0.14000 0.66000 0.79000 0.04374 0.05236 0.01180 0.01180 0.53409 0.61988 0.15000 1.63000 5.32000 0.10803 0.35259 0.01720 0.04470 0.19893 1.23975 0.70000 4.92000 5.49000 NaN NaN NaN NaN NaN NaN 0.13000 10.95000 5.27000 0.72572 0.34927 0.41459 0.04418 6.41353 3.12297

Plots of Static Friction Data¶

In [11]:
# Display a plot comparing the position of the block over time for each trial.
# Then, display a plot comparing the angle of the ramp over time for each trial.
static_big.plot_raw_data(legend=True)
static_big.plot_calculations(legend=True)

static_small.plot_raw_data(legend=True)
static_small.plot_calculations(legend=True)

Plots of Kinetic Friciton Data¶

In [12]:
# Display a plot comparing the position of the block over time for each trial.
# Then, display a plot comparing the acceleration of the block over time for each trial.
# Finally, display a plot comparing the angle of the ramp over time for each trial.
kinetic_big.plot_raw_data(legend=True)
kinetic_big.plot_raw_data(x='ax-yellowneon', y='ay-yellowneon', legend=True)
kinetic_big.plot_calculations(legend=True)

kinetic_small.plot_raw_data(legend=True)
kinetic_small.plot_raw_data(x='ax-yellowneon', y='ay-yellowneon', legend=True)
kinetic_small.plot_calculations(legend=True)

Results¶

In [13]:
# Tabulate the calculated friction coefficient of each trial in each experiment.
# Tabulate the mean and confidence interval of the friction coefficient in each experiment.
static_results = pd.DataFrame({
    'Large Area': static_big.mu,
    'Small Area': static_small.mu,
    'Trial': range(1, 10)
    }).set_index('Trial')

static_avg = pd.DataFrame({
    'Large Area': 
        [f"{static_big.mu_avg:.5f} ± {static_big.mu_error:.5f}",
        f"{static_big.mu_confidence_interval(.95)[0]:.5f} ≥ µ ≥ {static_big.mu_confidence_interval(.95)[1]:.5f}"],
    'Small Area': 
        [f"{static_small.mu_avg:.5f} ± {static_small.mu_error:.5f}",
        f"{static_small.mu_confidence_interval(.95)[0]:.5f} ≥ µ ≥ {static_small.mu_confidence_interval(.95)[1]:.5f}"]},
    index=['Average', '95% Conf']
    ).style.set_properties(**{'text-align': 'center'}
    ).set_table_styles([dict(selector='th', props=[('text-align', 'center')])])

kinetic_results = pd.DataFrame({
    'Large Area': kinetic_big.mu,
    'Small Area': kinetic_small.mu,
    'Trial': range(1, 10)
    }).set_index('Trial')

kinetic_avg = pd.DataFrame({
    'Large Area': 
        [f"{kinetic_big.mu_avg:.5f} ± {kinetic_big.mu_error:.5f}",
        f"{kinetic_big.mu_confidence_interval(.95)[0]:.5f} ≥ µ ≥ {kinetic_big.mu_confidence_interval(.95)[1]:.5f}"],
    'Small Area': 
        [f"{kinetic_small.mu_avg:.5f} ± {kinetic_small.mu_error:.5f}",
        f"{kinetic_small.mu_confidence_interval(.95)[0]:.5f} ≥ µ ≥ {kinetic_small.mu_confidence_interval(.95)[1]:.5f}"]},
    index=['Average', '95% Conf']
    ).style.set_properties(**{'text-align': 'center'}
    ).set_table_styles([dict(selector='th', props=[('text-align', 'center')])])

printmd("Coefficient of Static Friction", 3)
display(static_results)
display(static_avg)

printmd("Coefficient of Kinetic Friction", 3)
display(kinetic_results)
display(kinetic_avg)

Coefficient of Static Friction¶

Large Area Small Area
Trial
1 0.55766 0.52844
2 0.51608 0.47587
3 0.56481 0.44508
4 0.65720 0.47697
5 0.66065 0.39673
6 0.49341 0.40580
7 0.58206 0.42013
8 0.55822 0.36181
9 0.52384 0.39870
  Large Area Small Area
Average 0.56821 ± 0.01831 0.43439 ± 0.01628
95% Conf 0.53232 ≥ µ ≥ 0.60410 0.40248 ≥ µ ≥ 0.46631

Coefficient of Kinetic Friction¶

Large Area Small Area
Trial
1 0.50014 0.46888
2 0.48944 0.49840
3 0.48735 0.52242
4 0.48492 0.50499
5 0.50084 0.51120
6 0.49464 0.49788
7 0.48225 0.49195
8 0.47826 0.49689
9 0.50031 0.47444
  Large Area Small Area
Average 0.49091 ± 0.00266 0.49634 ± 0.00525
95% Conf 0.48570 ≥ µ ≥ 0.49611 0.48604 ≥ µ ≥ 0.50664

Observations¶

In [14]:
# Plot the calculated coefficients and analyze any trends.
static_results['Large Area Rolling Mean'] = static_results['Large Area'].expanding(1).mean()
static_results['Small Area Rolling Mean'] = static_results['Small Area'].expanding(1).mean()
plt.plot('Large Area', '.', data = static_results, c='green', label='Static - Large Area')
plt.plot('Small Area', '.', data = static_results, c='red', label='Static - Small Area')

kinetic_results['Large Area Rolling Mean'] = kinetic_results['Large Area'].expanding(1).mean()
kinetic_results['Small Area Rolling Mean'] = kinetic_results['Small Area'].expanding(1).mean()
plt.plot('Large Area', '.', data = kinetic_results, c='lightgreen', label='Kinetic - Large Area')
plt.plot('Small Area', '.', data = kinetic_results, c='pink', label='Kinetic - Small Area')

plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)

plt.plot('Large Area Rolling Mean', data = static_results, c='green',)
plt.plot('Small Area Rolling Mean', data = static_results, c='red')

plt.plot('Large Area Rolling Mean', data = kinetic_results, c='lightgreen', label=None)
plt.plot('Small Area Rolling Mean', data = kinetic_results, c='pink')

plt.title('Coefficient of Friction of a Wood Block')
plt.xlabel('Trial #')
plt.ylabel('Coefficient of Friction')
plt.show()

The Kinetic - Large Area and Kinetic - Small Area values has a strong correlation, supporing the hypothesis that $\mu$ is not dependent on surface area, and it is only dependent on surface material and mass. These calculated values of $\mu_k$ trends towards a converging value.

The calculated values of $\mu_s$ in the Static - Large Area exeperiment indicates that $\mu_s$ is greater than $\mu_k$. The calculated values of $\mu_s$ in the Static - Small Area exeperiment, however, do not support this. Observing the plot above, these values of $\mu_s$ (red) are shown to get lower for each subsequent trial. As this trend line has a steady negative slope, it can be speculated that if more trials were taken in this way, the data would become even less accurate, before it improve.

This was likely caused a flaw in the experiment's execution, potentially due to human error.