Skip to article frontmatterSkip to article content

Krachten in twee dimensies

1. Inleiding (Spiderman en Spankrachten)

Spiderman hangt stil aan zijn elastische webben tussen een boot die uit elkaar valt.
Hoe zorgt de spankracht ervoor dat Spiderman stil hangt?
Wat gebeurt er met de richting van zijn webben als hij zwaarder wordt,
of als de boothelften verder uit elkaar staan?

In dit practicum gebruik jij natuurkunde om ‘science’-fiction beter te begrijpen.

Na afloop kun je:

  • De resultante kracht bepalen voor 2D-krachten
  • 2D-Krachten achterhalen door de rekenen met goniometrie.
  • Het verband tussen de hoek van het touw en de massa in het midden verklaren

Hieronder kan je een video bekijken van de situatie:

2. Theorie (voorbereiding)

Source
%pip install jupyterquiz
%pip install ipywidgets
Requirement already satisfied: jupyterquiz in c:\users\youri\anaconda3\lib\site-packages (2.9.6.2)
Note: you may need to restart the kernel to use updated packages.
Requirement already satisfied: ipywidgets in c:\users\youri\anaconda3\lib\site-packages (8.1.7)
Requirement already satisfied: jupyterlab_widgets~=3.0.15 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (3.0.15)
Requirement already satisfied: widgetsnbextension~=4.0.14 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (4.0.14)
Requirement already satisfied: traitlets>=4.3.1 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (5.14.3)
Requirement already satisfied: ipython>=6.1.0 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (7.31.1)
Requirement already satisfied: comm>=0.1.3 in c:\users\youri\anaconda3\lib\site-packages (from ipywidgets) (0.2.2)
Requirement already satisfied: matplotlib-inline in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (0.1.6)
Requirement already satisfied: setuptools>=18.5 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (63.4.1)
Requirement already satisfied: pickleshare in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (3.0.20)
Requirement already satisfied: colorama in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (0.4.5)
Requirement already satisfied: jedi>=0.16 in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (0.18.1)
Requirement already satisfied: pygments in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (2.11.2)
Requirement already satisfied: backcall in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (0.2.0)
Requirement already satisfied: decorator in c:\users\youri\anaconda3\lib\site-packages (from ipython>=6.1.0->ipywidgets) (5.1.1)
Requirement already satisfied: parso<0.9.0,>=0.8.0 in c:\users\youri\anaconda3\lib\site-packages (from jedi>=0.16->ipython>=6.1.0->ipywidgets) (0.8.3)
Requirement already satisfied: wcwidth in c:\users\youri\anaconda3\lib\site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=6.1.0->ipywidgets) (0.2.5)
Note: you may need to restart the kernel to use updated packages.

2.1 Krachten in één richting (1D)

In eerdere lessen heb je vooral gewerkt met krachten die in één richting werken,
bijvoorbeeld horizontaal of verticaal. Dit noemen we eendimensionale krachten (1D).

We gaan nu een voorbeeld situatie analyseren waarbij een auto weg rijd van een stop

Vraag 1

De 1e wet van Newton zegt dat een voorwerp waarop geen resulterende kracht (Fres=0 F_{res} = 0 ) werkt, in rust is of een eenparige snelheid heeft.
De 2e wet van Newton zegt dat een voorwerp waarop wél een resulterende kracht werkt, uit stilstand gaat bewegen of versnelt (Fres=ma F_{res} = ma ).

Source
from jupyterquiz import display_quiz

quiz1 = [
    {
        "question": "Welke 2 uitspraken kloppen?",
        "type": "many_choice",
        "answers": [
            {
                "answer": "A) In de horizontale richting geldt $ F_{res} = 0 $",
                "correct": False,
                "feedback": "Fout: de auto versnelt horizontaal, dus F_res ≠ 0."
            },
            {
                "answer": "B) In de horizontale richting geldt $ F_{res} = ma $",
                "correct": True,
                "feedback": "Correct: de auto versnelt, dus er is een resulterende kracht in horizontale richting."
            },
            {
                "answer": "C) In de verticale richting geldt $ F_{res} = 0 $",
                "correct": True,
                "feedback": "Correct: er is een krachtenevenwicht in verticale richting (normaalkracht = zwaartekracht)."
            },
            {
                "answer": "D) In de verticale richting geldt $ F_{res} = ma $",
                "correct": False,
                "feedback": "Fout: er is geen versnelling in de verticale richting."
            }
        ]
    }
]

display_quiz(quiz1)
Loading...

Vraag 2

De krachten die op de auto werken zijn:
de zwaartekracht Fz F_z , normaalkracht Fn F_n , aandrijfkracht Fauto F_{auto} en rolwrijving Fw F_w .

Source
quiz2 = [
    {
        "question": "Welke uitspraak is juist over de richtingen van de krachten?",
        "type": "multiple_choice",
        "answers": [
            {
                "answer": "A) Horizontaal: $ F_{auto}$, $ F_n $ & Verticaal: $ F_z $, $ F_w $",
                "correct": False,
                "feedback": "Fout: $ F_n $ is verticaal, en $ F_w $ is horizontaal."
            },
            {
                "answer": "B) Horizontaal: $ F_{auto}$, $ F_w $ & Verticaal: $ F_z $, $ F_n $",
                "correct": True,
                "feedback": "Correct: $ F_{auto}$ en $ F_w$ zijn horizontaal; $ F_z $ en $ F_n $ zijn verticaal."
            },
            {
                "answer": "C) Horizontaal: $ F_{auto} $ & Verticaal: $ F_z $",
                "correct": False,
                "feedback": "Fout: er missen krachten in deze beschrijving."
            }
        ]
    }
]

display_quiz(quiz2)
Loading...

Vraag 3

De resultante kracht Fres F_{res} ontstaat uit de som van de krachten in één richting.
In verticale richting is er evenwicht (Fy=0 \sum F_y = 0 ),
in horizontale richting is er versnelling (Fx=ma \sum F_x = ma ).

Beantwoord de volgende vergelijkingen:

  1. De zwaartekracht Fz F_z is ___ de normaalkracht Fn F_n .
  2. De aandrijfkracht Fauto F_{auto} van de auto is ___ de wrijvingskracht Fw F_w .
Source
quiz3 = [
    {
        "question": "1. De zwaartekracht $ F_z $ is ___ de normaalkracht $ F_n $ .",
        "type": "multiple_choice",
        "answers": [
            {
                "answer": "Groter dan",
                "correct": False,
                "feedback": "Fout: als de zwaartekracht groter was, zou de auto door de grond zakken."
            },
            {
                "answer": "Kleiner dan",
                "correct": False,
                "feedback": "Fout: dan zou de auto opstijgen of van de grond loskomen."
            },
            {
                "answer": "Gelijk aan",
                "correct": True,
                "feedback": "Correct: er is evenwicht in verticale richting, dus F_z = F_n."
            }
        ]
    },
    {
        "question": "2. De aandrijfkracht $ F_{auto} $ van de auto is ___ de wrijvingskracht $ F_w $ .",
        "type": "multiple_choice",
        "answers": [
            {
                "answer": "Groter dan",
                "correct": True,
                "feedback": "Correct: de auto versnelt, dus de aandrijfkracht is groter dan de rolweerstand."
            },
            {
                "answer": "Kleiner dan",
                "correct": False,
                "feedback": "Fout: dan zou de auto vertragen in plaats van versnellen."
            },
            {
                "answer": "Gelijk aan",
                "correct": False,
                "feedback": "Fout: als ze gelijk waren, zou er geen versnelling zijn."
            }
        ]
    }
]

display_quiz(quiz3)
Loading...

Verband massa en kracht

In de onderstaande situatie is kan je de massa veranderen. Je ziet dan dat de zwaartekracht omhoog gaat. Bij toename van massa is er dus een groterere reactie kracht nodig (in dit geval de normaal kracht) om te compenseren. Je kan ook de aandrijfkracht vergroten, dan zie je dat wrijvingskracht meer gecompenseert wordt door deze aandrijving en dus de resultante kracht groter moet worden.

Source
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact, FloatSlider

# Constanten
mu = 0.1  # wrijvingscoëfficiënt
g = 9.81  # gravitatieversnelling

def plot_krachten(m=1000, F_auto=2000):
    F_z = m * g
    F_n = F_z
    F_w = mu * F_n
    F_res_x = F_auto - F_w

    # Schaalfactor voor de krachten
    scale = 0.0002

    # Auto positie (center van het object)
    x0, y0 = 3, 0  # ← hier verhoog je de positie van de auto in de box

    # Box-afmetingen aanpassen:
    x_min, x_max = 0, 6
    y_min, y_max = -5, 5  # ← hier maak je de onderkant groter (-2 in plaats van 0)

    fig, ax = plt.subplots(figsize=(8, 6))
    ax.set_xlim(x_min, x_max)
    ax.set_ylim(y_min, y_max)
    ax.set_aspect('equal')
    ax.axis('off')

    # De box zelf (optioneel stippellijn rondom het zichtgebied)
    ax.plot([x_min, x_max, x_max, x_min, x_min],
            [y_min, y_min, y_max, y_max, y_min],
            'k--', linewidth=0.5)

    # Auto (als rechthoekje)
    car_width, car_height = 1.0, 0.4
    ax.add_patch(plt.Rectangle((x0 - car_width / 2, y0), car_width, car_height, color='gray'))

    # Assen pijlen
    ax.arrow(x_min + 0.5, y_min + 0.5, 0.7, 0, head_width=0.1, head_length=0.1, color='black')
    ax.arrow(x_min + 0.5, y_min + 0.5, 0, 0.7, head_width=0.1, head_length=0.1, color='black')
    ax.text(x_min + 1.3, y_min + 0.4, 'x', fontsize=12)
    ax.text(x_min + 0.4, y_min + 1.3, 'y', fontsize=12)

    # Helperfunctie om krachten te tekenen
    def draw_force(name, Fx, Fy, color, offset=(0, 0)):
        ax.arrow(
            x0 + offset[0], y0 + offset[1],
            Fx * scale, Fy * scale,
            head_width=0.08, head_length=0.15, color=color, length_includes_head=True
        )
        dx = Fx * scale
        dy = Fy * scale
        tx = x0 + dx * 1.1 + offset[0]
        ty = y0 + dy * 1.1 + offset[1]
        ax.text(tx, ty, name, fontsize=11, color=color,
                ha='left' if Fx >= 0 else 'right',
                va='bottom' if Fy >= 0 else 'top')

    # Krachten tekenen
    draw_force('F_z', 0, -F_z, 'blue', offset=(0, -0.1))
    draw_force('F_n', 0, F_n, 'green', offset=(0, 0.1))
    draw_force('F_w', -F_w, 0, 'orange', offset=(0, 0.3))
    draw_force('F_auto', F_auto, 0, 'red', offset=(0, 0.3))
    draw_force('F_res,x', F_res_x, 0, 'purple', offset=(0, 0.5))

    # Informatiebox
    ax.text(x_min + 8.3, y_max - 0.4,
            f'Massa = {m:.0f} kg\nF_auto = {F_auto:.0f} N\nF_res = {F_res_x:.0f} N',
            fontsize=11, bbox=dict(facecolor='white', edgecolor='black'))

    plt.title("Krachten op een versnellende auto", fontsize=14)
    plt.show()

# Sliders
interact(
    plot_krachten,
    m=FloatSlider(value=1000, min=500, max=2000, step=100, description='massa (kg)'),
    F_auto=FloatSlider(value=2000, min=0, max=5000, step=100, description='F_auto (N)')
)
Loading...

2.2 Krachten in meerdere richtingen (2D)

Zodra krachten niet meer netjes in dezelfde richting liggen,
hebben we te maken met tweedimensionale krachten (2D).

Kop staart methode

Stel je voor dat je van punt A naar B loopt (vector AB\vec{AB}),
en dan van B naar C (vector BC\vec{BC}).
De totale verplaatsing is dan van A naar C (vector AC\vec{AC}).
Dit is het idee achter het optellen van vectoren via de kop-staartmethode.

Source
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact, FloatSlider

# Interactieve functie om vectoren te tekenen
def plot_vector_kopstaart(Bx=2.0, By=2.0, Cx=4.0, Cy=1.0):
    # Vectoren berekenen
    A = np.array([0, 0])
    B = np.array([Bx, By])
    C = B + np.array([Cx, Cy])
    
    AB = B - A
    BC = C - B
    AC = C - A

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_xlim(-5, 9)
    ax.set_ylim(-5, 9)
    ax.set_aspect('equal')
    ax.grid(True)
    ax.set_title("Kop-staartmethode: Vectoroptelling in 2D", fontsize=14)

    # Vectors tekenen met kleur
    ax.arrow(*A, *AB, head_width=0.2, head_length=0.3, fc='blue', ec='blue', length_includes_head=True)
    ax.arrow(*B, *BC, head_width=0.2, head_length=0.3, fc='red', ec='red', length_includes_head=True)
    ax.arrow(*A, *AC, head_width=0.2, head_length=0.3, fc='purple', ec='purple', length_includes_head=True)

    # Labels van punten
    ax.text(*A - 0.3, "A", fontsize=12)
    ax.text(*B + 0.1, "B", fontsize=12)
    ax.text(*C + 0.1, "C", fontsize=12)

    # Vectornotaties in het midden van de pijlen
    def midpoint(p1, p2):
        return (p1 + p2) / 2

    AB_mid = midpoint(A, B)
    BC_mid = midpoint(B, C)
    AC_mid = midpoint(A, C)

    ax.text(*AB_mid + [0.2, 0.2], r'$\vec{AB}$', fontsize=14, color='blue')
    ax.text(*BC_mid + [0.2, 0.2], r'$\vec{BC}$', fontsize=14, color='red')
    ax.text(*AC_mid + [0.2, 0.2], r'$\vec{AC}$', fontsize=14, color='purple')

    plt.show()

# Sliders
interact(
    plot_vector_kopstaart,
    Bx=FloatSlider(value=4.0, min=-2.0, max=4.0, step=0.5, description='AB x'),
    By=FloatSlider(value=2.0, min=-2.0, max=4.0, step=0.5, description='AB y'),
    Cx=FloatSlider(value=0.5, min=-2.0, max=4.0, step=0.5, description='BC x'),
    Cy=FloatSlider(value=3.0, min=-2.0, max=4.0, step=0.5, description='BC y')
)
Loading...

In Figuur 2 zie je hoe dit werkt.
De parallellogrammethode is eigenlijk de kop-staartmethode,
maar dan twee keer toegepast.

We kunnen deze methode ook gebruiken om een kracht te ontbinden in twee richtingen:
bijvoorbeeld een schuine kracht splitsen in een horizontale en verticale component.

Dit is handig omdat we dan weer met eenvoudige 1D-vergelijkingen kunnen rekenen.

Source
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact, FloatSlider

def plot_vector_standaard_form(a_x=2.0, a_y=2.0, b_x=4.0, b_y=1.0):
    a = np.array([a_x, a_y])
    b = np.array([b_x, b_y])
    c = a + b

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_xlim(-5, 9)
    ax.set_ylim(-5, 9)
    ax.set_aspect('equal')
    ax.grid(True)
    ax.set_title("Vectoroptelling met standaardpositie (kop-staart via oorsprong)", fontsize=14)

    origin = np.array([0, 0])
    a_tip = a
    b_tip = b
    c_tip = c

    # Originele vector a (blauw)
    ax.arrow(*origin, *a, head_width=0.2, head_length=0.3, fc='blue', ec='blue', length_includes_head=True)
    ax.text(*(a / 2 + [0.2, 0.2]), r'$\vec{a}$', fontsize=14, color='blue')

    # Gestippelde vector b op de kop van a (rood gestippeld)
    ax.arrow(*a, *b, head_width=0.2, head_length=0.3, fc='red', ec='red', linestyle='dotted', length_includes_head=True)

    # Originele vector b vanuit oorsprong (rood)
    ax.arrow(*origin, *b, head_width=0.2, head_length=0.3, fc='red', ec='red', length_includes_head=True)
    ax.text(*(b / 2 + [0.2, 0.2]), r'$\vec{b}$', fontsize=14, color='red')

    # Gestippelde vector a op de kop van b (blauw gestippeld)
    ax.arrow(*b, *a, head_width=0.2, head_length=0.3, fc='blue', ec='blue', linestyle='dotted', length_includes_head=True)

    # Resultante vector c = a + b (paars)
    ax.arrow(*origin, *c, head_width=0.2, head_length=0.3, fc='purple', ec='purple', length_includes_head=True)
    ax.text(*(c / 2 + [0.2, 0.2]), r'$\vec{c} = \vec{a} + \vec{b}$', fontsize=14, color='purple')


    plt.show()

# Sliders
interact(
    plot_vector_standaard_form,
    a_x=FloatSlider(value=2.0, min=-2.0, max=4.0, step=0.5, description='a x'),
    a_y=FloatSlider(value=2.0, min=-2.0, max=4.0, step=0.5, description='a y'),
    b_x=FloatSlider(value=4.0, min=-2.0, max=4.0, step=0.5, description='b x'),
    b_y=FloatSlider(value=1.0, min=-2.0, max=4.0, step=0.5, description='b y')
)
Loading...

Vraag 4

In het onderstaande figuur zie je een vector a met lengte 3 en vector b met lengte 4. In het onderstaande figuur kan je de hoek tussen a en b varieren en zien wat voor impact dat maakt op de resultante vector

Source
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact, FloatSlider

def plot_vector_met_hoek(alpha_deg=60, b_length=4.0):
    # Constante vector a
    a = np.array([3.0, 0.0])

    # Vector b: lengte instelbaar, richting variabel
    alpha_rad = np.radians(alpha_deg)
    b = b_length * np.array([np.cos(alpha_rad), np.sin(alpha_rad)])

    # Resultante vector c
    c = a + b

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_xlim(-5, 8)
    ax.set_ylim(-1, 6)
    ax.set_aspect('equal')
    ax.grid(True)
    ax.set_title("Vectoroptelling met parallellogram en variabele hoek/lengte", fontsize=14)

    origin = np.array([0, 0])

    # Vector a (blauw)
    ax.arrow(*origin, *a, head_width=0.2, head_length=0.3, fc='blue', ec='blue', length_includes_head=True)
    ax.text(*(a / 2 + [0.2, 0.2]), r'$\vec{a}$', fontsize=14, color='blue')

    # Vector b (rood)
    ax.arrow(*origin, *b, head_width=0.2, head_length=0.3, fc='red', ec='red', length_includes_head=True)
    ax.text(*(b / 2 + [0.2, 0.2]), r'$\vec{b}$', fontsize=14, color='red')

    # Vector b vanaf a (rood gestippeld)
    ax.arrow(*a, *b, head_width=0.2, head_length=0.3, fc='red', ec='red', linestyle='dotted', length_includes_head=True)

    # Vector a vanaf b (blauw gestippeld)
    ax.arrow(*b, *a, head_width=0.2, head_length=0.3, fc='blue', ec='blue', linestyle='dotted', length_includes_head=True)

    # Resultante vector c (paars)
    ax.arrow(*origin, *c, head_width=0.2, head_length=0.3, fc='purple', ec='purple', length_includes_head=True)
    ax.text(*(c / 2 + [0.2, 0.2]), r'$\vec{c} = \vec{a} + \vec{b}$', fontsize=14, color='purple')

    # Hoek α tekenen
    arc_radius = 1.0
    arc = np.linspace(0, alpha_rad, 100)
    ax.plot(arc_radius * np.cos(arc), arc_radius * np.sin(arc), 'k')
    ax.text(arc_radius * np.cos(alpha_rad/2) + 0.2, arc_radius * np.sin(alpha_rad/2), r'$\alpha$', fontsize=14)

    # Grootte van vectoren tonen
    length_a = np.linalg.norm(a)
    length_b = np.linalg.norm(b)
    length_c = np.linalg.norm(c)

    ax.text(-4.5, 5.5, fr'$|\vec{{a}}| = {length_a:.2f}$', fontsize=12, color='blue')
    ax.text(-4.5, 5.0, fr'$|\vec{{b}}| = {length_b:.2f}$', fontsize=12, color='red')
    ax.text(-4.5, 4.5, fr'$|\vec{{c}}| = {length_c:.2f}$', fontsize=12, color='purple')

    plt.show()

# Interactieve sliders
interact(
    plot_vector_met_hoek,
    alpha_deg=FloatSlider(value=60, min=0, max=180, step=5, description='Hoek α (°)'),
    b_length=FloatSlider(value=4.0, min=2.0, max=4.0, step=0.5, description='|b|')
)

Beantwoord de volgende vragen voor b=4|\vec{{b}}| = 4 :

Source
quiz4 = [
  {
    "question": "1. De grootte van de resultante vector ___ naarmate de hoek tussen a en b toeneemt.",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "wordt groter",
        "correct": False,
        "feedback": "Fout: a en b werken steeds meer in de tegengestelde richting naar mate de hoek vergroot."
      },
      {
        "answer": "wordt kleiner",
        "correct": True,
        "feedback": "Correct: a en b werken steeds meer in de tegengestelde richting naar mate de hoek vergroot."
      },
      {
        "answer": "blijft gelijk",
        "correct": False,
        "feedback": "Fout: de grootte van de resultante verandert met de hoek."
      }
    ]
  },
  {
    "question": "2. Vector b is ___ vector a.",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "groter dan",
        "correct": True,
        "feedback": "Correct: vector b heeft een lengte van 4, vector a een lengte van 3."
      },
      {
        "answer": "kleiner dan",
        "correct": False,
        "feedback": "Fout: vector b is langer dan vector a."
      },
      {
        "answer": "even groot als",
        "correct": False,
        "feedback": "Fout: vector a en b hebben verschillende lengtes."
      }
    ]
  },
  {
    "question": "3. De resultante vector ligt ___ ten opzichte van vector a en b.",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "dichter bij a",
        "correct": False,
        "feedback": "Fout: Een grotere pijl naar links geeft een resultante die meer naar links hangt"
      },
      {
        "answer": "dichter bij b",
        "correct": True,
        "feedback": "Correct: de resultante ligt dichter bij vector b omdat b langer is dan a."
      },
      {
        "answer": "tussen a en b",
        "correct": False,
        "feedback": "De vectoren zijn geen spiegelbeeld van elkaar"
      }
    ]
  }
]


display_quiz(quiz4)

vraag 5

Nu zijn we benieuwd naar een speciaal geval; wat als de vectoren evengroot zijn? Stel de lengte van b in op 3 en beantwoord de volgend vragen

Source
quiz5 = [
  {
    "question": "1. De resultante vector ligt ___ ten opzichte van vector a en b.",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "dichter bij a",
        "correct": False,
        "feedback": "Fout: De vectoren zijn in dit geval even lang en de hoek is symmetrisch, dus de resultante ligt precies ertussenin."
      },
      {
        "answer": "tussen a en b",
        "correct": True,
        "feedback": "Correct: Door de symmetrie en gelijke lengte van de vectoren ligt de resultante precies tussen beide vectoren in."
      },
      {
        "answer": "dichter bij b",
        "correct": False,
        "feedback": "Fout: Alleen als b langer is dan a ligt de resultante dichter bij b."
      }
    ]
  },
  {
    "question": "2. De resultante kracht is 0 bij een hoek van ___ graden.",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "0°",
        "correct": False,
        "feedback": "Fout: Bij 0° werken beide krachten in dezelfde richting, dus versterken ze elkaar."
      },
      {
        "answer": "90°",
        "correct": False,
        "feedback": "Fout: Bij 90° staan de vectoren loodrecht op elkaar, dus ontstaat er nog steeds een duidelijke resultante."
      },
      {
        "answer": "180°",
        "correct": True,
        "feedback": "Correct: Bij 180° staan de krachten precies tegenover elkaar. Als ze even groot zijn, heffen ze elkaar volledig op."
      }
    ]
  },
  {
    "question": "3. Dit komt omdat...",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "de krachten dezelfde richting hebben",
        "correct": False,
        "feedback": "Fout: Bij 180° wijzen de vectoren juist in tegengestelde richting."
      },
      {
        "answer": "de vectoren elkaar versterken",
        "correct": False,
        "feedback": "Fout: Dat zou het geval zijn bij een hoek van 0°."
      },
      {
        "answer": "de krachten elkaar opheffen",
        "correct": True,
        "feedback": "Correct: Omdat de krachten precies even groot en tegenovergesteld zijn, is de netto kracht nul."
      }
    ]
  }
]

# Om te tonen met bijv. een display-functie
display_quiz(quiz5)

3. Opstelling en werkwijze

In dit experiment onderzoeken we de krachten in een touw dat aan beide uiteinden over katrollen is gespannen. Aan beide uiteinden hangen gelijke massa’s M1=M2=MM_1 = M_2 = M, waardoor het touw aanvankelijk horizontaal hangt. In het midden van het touw wordt een extra massa mm bevestigd. Door deze massa zakt het touw door in een V-vorm.

De spankracht FMF_M is overal in het touw gelijk, maar staat onder een hoek θ\theta ten opzichte van de horizontale richting. De som van de spankrachten aan beide zijden van het touw moet de zwaartekracht FmF_m van de toegevoegde massa compenseren. Deze krachtenbalans kan inzichtelijk gemaakt worden met de parallellogrammethode.

Benodigdheden

  • 2 statieven met katrollen
  • Een lang touw
  • 2 massa’s van M=5,0 gM = 5{,}0\ \text{g}
  • Set ophanggewichten voor m=[0,9] gm = [0, 9]\ \text{g}
  • Geodriehoek
Meetopstelling

Figuur 1: Meetopstelling met V-touw en hangende massa.

Werkwijze

  1. Stel de opstelling op zoals weergegeven in Figuur 1.
  2. Hang de massa’s MM aan beide uiteinden van het touw, zodat het touw zonder extra massa horizontaal hangt.
  3. Controleer de beginsituatie zonder massa mm; het touw moet recht hangen.
  4. Bevestig een massa mm in het midden van het touw en wacht tot het systeem in rust is.
  5. Meet de totale hoek α\alpha van de V-vorm met een geodriehoek en deel deze door 2 om θ\theta te verkrijgen.
  6. Noteer de gemeten hoek in Tabel 1.
  7. Herhaal stap 4 t/m 6 voor meerdere waarden van mm.

4. Resultaten

Source
import ipywidgets as widgets
from IPython.display import display, clear_output

# Aantal rijen
n_rows = 9

# Widgets maken voor m en α
m_widgets = [widgets.FloatText(value=0.0 if i == 0 else None,
                               layout=widgets.Layout(width='100px')) for i in range(n_rows)]
alpha_widgets = [widgets.FloatText(layout=widgets.Layout(width='100px')) for _ in range(n_rows)]
theta_outputs = [widgets.Label(value='', layout=widgets.Layout(width='100px')) for _ in range(n_rows)]

# Updatefunctie voor θ = α / 2
def update_theta(change=None):
    for i in range(n_rows):
        alpha = alpha_widgets[i].value
        if alpha is not None:
            try:
                theta = alpha / 2
                theta_outputs[i].value = f"{theta:.2f}"
            except:
                theta_outputs[i].value = ""
        else:
            theta_outputs[i].value = ""

# Observe α-velden
for widget in alpha_widgets:
    widget.observe(update_theta, names='value')

# Toon interactieve tabel
def display_table():
    header = widgets.HBox([
        widgets.Label("n", layout=widgets.Layout(width='40px')),
        widgets.Label("m (kg)", layout=widgets.Layout(width='100px')),
        widgets.Label("α (°)", layout=widgets.Layout(width='100px')),
        widgets.Label("θ = α / 2 (°)", layout=widgets.Layout(width='120px'))
    ])
    
    rows = []
    for i in range(n_rows):
        row = widgets.HBox([
            widgets.Label(str(i), layout=widgets.Layout(width='40px')),
            m_widgets[i],
            alpha_widgets[i],
            theta_outputs[i]
        ])
        rows.append(row)
    
    display(widgets.VBox([header] + rows))

# Activeer de initiële waarden
update_theta()
display_table()
Loading...

5. Verwerkingsvragen

vraag 6

Ga terug naar vraag 1 en bekijk figuur 1. We weten dat het object stilhangt dus er geld: Fres=0 F_{res} = 0 . De zwaartekracht Fz F_z moet dus gecompenseert worden door een even grote kracht in de tegengestelde richting. Waaruit is deze reactie kracht ontstaan?

Source
quiz6 = [
  {
    "question": "6. Waaruit is deze reactiekracht ontstaan?",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "Deze reactiekracht is de som van de spankrachten.",
        "correct": True,
        "feedback": "Correct: De reactiekracht die de zwaartekracht compenseert is inderdaad het resultaat van de twee spankrachten die samenwerken om het object in evenwicht te houden."
      },
      {
        "answer": "Deze reactiekracht is de normaalkracht.",
        "correct": False,
        "feedback": "Fout: De normaalkracht speelt hier geen rol, omdat het object hangt en niet op een ondergrond rust."
      },
      {
        "answer": "De reactiekracht is een component van de span- en zwaartekracht.",
        "correct": False,
        "feedback": "Fout: Dit klopt niet. De zwaartekracht wordt juist volledig gecompenseerd door de resultante van de spankrachten – niet door een component daarvan."
      }
    ]
  }
]

display_quiz(quiz6)
Loading...

vraag 7

Nu we weten dat de som van de spankrachten de reactie kracht is op de zwaartekracht kunnen we meerdere uitspraken doen over de 2d situatie.

Source
quiz7 = [
  {
    "question": "7. De massa m hangt in het midden van het touw. Zijn de hoeken tussen de spankrachten en de zwaartekracht gelijk?",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "Ja, want het systeem is symmetrisch en de spankrachten zijn even groot.",
        "correct": True,
        "feedback": "Correct: De massa hangt in het midden, en het touw is via katrollen gespannen met gelijke massa's aan beide zijden."
      },
      {
        "answer": "Nee, want spankracht 1 werkt anders dan spankracht 2.",
        "correct": False,
        "feedback": "Fout: De massa’s aan beide zijden zijn gelijk, dus ook de krachten zijn gelijk."
      },
      {
        "answer": "Ja, want op het plaatje ziet het er symetrisch uit.",
        "correct": False,
        "feedback": "Fout: Dat is waar, maar je moet zoeken naar de waarom en niet aannames nemen."
      },
      {
        "answer": "Nee, want de spankrachten trekken in verschillende richtingen.",
        "correct": False,
        "feedback": "Fout: De richtingen verschillen, maar richting en grootte samen bepaald de resultante"
      }
    ]
  },
  {
    "question": "8. Wat gebeurt er met de hoek θ als je een grotere massa m in het midden hangt?",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "De hoek θ wordt kleiner, want de spankrachten moet meer samenwerken om een grotere reactiekracht te leveren.",
        "correct": True,
        "feedback": "Correct: Meer gewicht in het midden betekent dat het touw meer doorhangt, dus θ wordt kleiner (de V wordt scherper)."
      },
      {
        "answer": "De hoek θ blijft gelijk, want de massa hangt in het midden.",
        "correct": False,
        "feedback": "Fout: De  horizontale positie van de massa verandert niet, maar de grootte van de kracht wel — en dat beïnvloedt de hoek."
      },
      {
        "answer": "De hoek θ wordt groter, want de spankrachten nemen toe.",
        "correct": False,
        "feedback": "Fout: De spankrachten nemen inderdaad toe, maar de hoek θ is wat anders dan de grootte van de kracht."
      },
      {
        "answer": "De hoek θ wordt 90°, want het touw hangt dan recht naar beneden.",
        "correct": False,
        "feedback": "Fout: Dat zou pas gebeuren als het touw volledig doorzakt zonder zijwaartse component — dat is hier niet het geval."
      }
    ]
  },
  {
    "question": "9. Waarom hangt het touw in de beginsituatie (zonder massa m) horizontaal?",
    "type": "multiple_choice",
    "answers": [
      {
        "answer": "Omdat er geen verticale kracht in het midden is die het touw naar beneden trekt.",
        "correct": True,
        "feedback": "Correct: Zonder massa m werkt er alleen spankracht aan de uiteinden, en die zijn horizontaal gespiegeld, dus het midden zakt niet."
      },
      {
        "answer": "Omdat de zwaartekracht op het touw nul is.",
        "correct": False,
        "feedback": "Fout: De zwaartekracht van het touw zelf is niet nul, maar de invloed is verwaarloosbaar t.o.v. m."
      },
      {
        "answer": "Omdat de spankrachten elkaar opheffen.",
        "correct": False,
        "feedback": "Fout: De spankrachten trekken aan beide zijden, maar dat voorkomt juist beweging; ze heffen de zwaartekracht in het midden niet op (die is er niet zonder m)."
      },
      {
        "answer": "Omdat het touw stijf is.",
        "correct": False,
        "feedback": "Fout: Het touw is soepel — het blijft horizontaal door de afwezigheid van kracht in het midden, niet door stijfheid."
      }
    ]
  }
]


display_quiz(quiz7)
Loading...

Vraag 8 – Controleer je metingen

In onderstaande tabel zie je per situatie:

  • De berekende kracht (F = m·g)
  • De gemeten lengte van de vector in cm
  • De massa waarmee is gewerkt

We weten dat de spankracht van FMF_M bij 0,005 kg (5 g) gelijk is aan de zwaartekracht die we berekenen met FM=Mg F_M = Mg . Omdat bijde vectoren FMF_M even groot zijn kunnen we het figuur bij vraag 4 aflezen. We zien daar een lengte van 3 cm.:
F_M = 0,049 N → lengte = 3,0 cm, dus schaal = 0,049 / 3,0 = 0,0163 N/cm.

Voor de overige situaties geldt:

  1. Bereken de verwachte kracht op basis van de gemeten lengte en de schaal.
  2. Vergelijk deze met de kracht uit F = m·g.
  3. Kijk of de afwijking binnen de 5% valt.

De resultaten worden hieronder getoond.

Source
import pandas as pd
import ipywidgets as widgets
from IPython.display import display, clear_output

# Referentieschaal
schaal_ref = 0.049 / 3.0  # N/cm ≈ 0.0163

# Situaties
situaties = ["F_M", "F_m (α=145°)", "F_m (α=120°)", "F_m (α=90°)"]

# Invoervelden
velden = []
for _ in situaties:
    kracht = widgets.FloatText(description="F (N):", value=0.0, step=0.001, layout=widgets.Layout(width="150px"))
    lengte = widgets.FloatText(description="L (cm):", value=0.0, step=0.1, layout=widgets.Layout(width="150px"))
    massa  = widgets.FloatText(description="m (kg):", value=0.0, step=0.001, layout=widgets.Layout(width="150px"))
    velden.append((kracht, lengte, massa))

# Knop + output
knop = widgets.Button(description="Controleer antwoorden", button_style="primary")
output = widgets.Output()

def controleer(b):
    with output:
        clear_output()
        resultaten = []
        for i, (kracht, lengte, massa) in enumerate(velden):
            F = kracht.value
            L = lengte.value
            m = massa.value
            if L == 0:
                resultaten.append(["-", "-", "-", "-", "-", "Geen lengte ingevoerd"])
                continue
            F_schat = L * schaal_ref
            afwijking = abs(F_schat - F) / F * 100 if F != 0 else 0
            beoordeling = "✓ correct" if afwijking < 5 else "✗ > 5% afwijking"
            resultaten.append([
                situaties[i], round(F, 4), round(L, 2), round(m, 4), round(F_schat, 4), round(afwijking, 2), beoordeling
            ])

        df = pd.DataFrame(resultaten, columns=[
            "Situatie", "F (N)", "L (cm)", "m (kg)", "F uit schaal (N)", "Afwijking (%)", "Beoordeling"
        ])
        display(df)

knop.on_click(controleer)

# Interface tonen
rijen = []
for i, (kracht, lengte, massa) in enumerate(velden):
    rij = widgets.HBox([widgets.Label(value=situaties[i], layout=widgets.Layout(width="130px")),
                        kracht, lengte, massa])
    rijen.append(rij)

display(widgets.VBox(rijen))
display(knop, output)
Loading...

6. Ontbinden van vectoren

Wanneer we naar de meetgegevens kijken kunnen we een verband bepalen tussen m m en de hoek theta.

Ontbinden van vectoren

Ontbinden in vectoren

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import ipywidgets as widgets
from IPython.display import display, clear_output
from scipy.optimize import curve_fit

# Selecteer regressietype
regressie_keuze = widgets.Dropdown(
    options=["Geen regressie", "Regressie: y = a + b·x²", "Regressie: y = a·cos(x)"],
    value="Geen regressie",
    description="Regressie:",
    style={'description_width': 'initial'},
    layout=widgets.Layout(width='300px')
)

# Uitvoer voor grafiek en analyse
grafiek_button = widgets.Button(description="Toon grafiek", button_style="success")
grafiek_output = widgets.Output()

def plot_grafiek(b):
    with grafiek_output:
        clear_output()

        # Verzamel gegevens
        m_values = []
        theta_values = []
        for m_widget, alpha_widget in zip(m_widgets, alpha_widgets):
            try:
                m = m_widget.value
                alpha = alpha_widget.value
                if m is not None and alpha is not None:
                    m_values.append(m)
                    theta_values.append(alpha / 2)
            except:
                continue

        if not theta_values:
            print("Geen geldige gegevens om te plotten.")
            return

        theta_array = np.array(theta_values)
        m_array = np.array(m_values)

        # Plot basis
        fig, ax = plt.subplots(figsize=(8, 6))
        ax.scatter(theta_array, m_array, color='blue', label="Meetpunten")

        # Regressietype
        keuze = regressie_keuze.value
        regressie_label = ""

        if keuze == "Regressie: y = a + b·x²":
            def model(x, a, b):
                return a + b * x**2

            popt, pcov = curve_fit(model, theta_array, m_array)
            a, b = popt
            a_std, b_std = np.sqrt(np.diag(pcov))
            x_fit = np.linspace(0, 90, 200)
            y_fit = model(x_fit, *popt)

            ax.plot(x_fit, y_fit, 'r-', label=f"y = {a:.3f} ± {a_std:.3f} + ({b:.3f} ± {b_std:.3f})·x²")

        elif keuze == "Regressie: y = a·cos(x)":
            def model(x, a):
                return a * np.cos(np.radians(x))

            popt, pcov = curve_fit(model, theta_array, m_array)
            a = popt[0]
            a_std = np.sqrt(np.diag(pcov))[0]
            x_fit = np.linspace(0, 90, 200)
            y_fit = model(x_fit, *popt)

            ax.plot(x_fit, y_fit, 'r-', label=f"y = ({a:.3f} ± {a_std:.3f})·cos(x)")

        # Assenlimieten en labels
        ax.set_xlim(0, 90)
        ax.set_ylim(0, 0.45)
        ax.set_xlabel("θ (°)", fontsize=12)
        ax.set_ylabel("m (kg)", fontsize=12)
        ax.set_title("Grafiek van θ versus massa m")
        ax.grid(True, linestyle='--', alpha=0.6)

        # Komma als decimaalscheiding
        ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
        ax.yaxis.set_major_locator(ticker.MultipleLocator(0.1))
        ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, _: f"{x:.1f}".replace('.', ',')))
        ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y, _: f"{y:.1f}".replace('.', ',')))

        ax.legend()
        plt.show()

grafiek_button.on_click(plot_grafiek)

# Toon interactie
display(widgets.VBox([regressie_keuze, grafiek_button, grafiek_output]))
Loading...
Source
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact, FloatSlider

def plot_eenheidscirkel(theta_deg=45):
    # Hoek en componenten
    theta_rad = np.radians(theta_deg)
    cos_t = np.cos(theta_rad)
    sin_t = np.sin(theta_rad)
    F = np.array([cos_t, sin_t])
    Fx = np.array([F[0], 0])
    Fy = np.array([0, F[1]])

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_xlim(-0.2, 1.2)
    ax.set_ylim(-0.2, 1.2)
    ax.set_aspect('equal')
    ax.grid(True)
    ax.set_title("Ontbinden van een vector op de eenheidscirkel", fontsize=14)

    origin = np.array([0, 0])

    # Eenheidscirkel (eerste kwadrant)
    circle = plt.Circle(origin, 1, color='lightgray', fill=False, linestyle='dashed')
    ax.add_patch(circle)

    # Vector F (paars)
    ax.arrow(*origin, *F, head_width=0.03, head_length=0.05, fc='purple', ec='purple', length_includes_head=True)
    ax.text(*(F * 0.55), r'$\vec{F}$', fontsize=14, color='purple')

    # Componenten
    ax.arrow(*origin, *Fx, head_width=0.03, head_length=0.05, fc='red', ec='red', length_includes_head=True)
    ax.arrow(*origin, *Fy, head_width=0.03, head_length=0.05, fc='blue', ec='blue', length_includes_head=True)

    # Labels met berekende projecties
    ax.text(*(Fx * 0.6 + [0.02, -0.05]),
            fr'$\vec{{F}}_x = {cos_t:.2f} \cdot F$', fontsize=14, color='red')
    ax.text(*(Fy * 0.6 + [-0.1, 0.02]),
            fr'$\vec{{F}}_y = {sin_t:.2f} \cdot F$', fontsize=14, color='blue')

    # Gestippelde hulplijnen met omgewisselde kleuren
    ax.plot([F[0], F[0]], [0, F[1]], 'b--', linewidth=1)  # verticaal: blauw
    ax.plot([0, F[0]], [F[1], F[1]], 'r--', linewidth=1)  # horizontaal: rood

    # Hoek theta tekenen
    angle_radius = 0.2
    angle = np.linspace(0, theta_rad, 100)
    ax.plot(angle_radius * np.cos(angle), angle_radius * np.sin(angle), 'k')
    ax.text(angle_radius * 1.05, 0.04, r'$\theta$', fontsize=14)

    # Legenda
    from matplotlib.lines import Line2D
    legend_elements = [
        Line2D([0], [0], color='purple', lw=2, label=r'$\vec{F}$'),
        Line2D([0], [0], color='red', lw=2, label=r'$\vec{F}_x$'),
        Line2D([0], [0], color='blue', lw=2, label=r'$\vec{F}_y$')
    ]
    ax.legend(handles=legend_elements, loc='upper right', fontsize=12)

    plt.show()

# Interactieve slider
interact(
    plot_eenheidscirkel,
    theta_deg=FloatSlider(value=45, min=0, max=90, step=1, description='θ (graden)')
)
Loading...