Dry Friction mockup

Libraries

In [1]:
%matplotlib widget

import matplotlib as mpl mpl.rc('text', usetex = True) mpl.rc('font', family = 'serif')

In [2]:
import time
In [3]:
from pysketcher import *
In [4]:
from ipywidgets import FloatSlider, AppLayout, Label, HBox, Button, Output
In [5]:
from IPython.display import HTML, SVG, display, clear_output
In [6]:
from math import tan, radians, sin, cos

Sketch container

In [7]:
myfig={}

Sketch yaml definition

In [9]:
head = """\
libraries: ["from math import tan, radians, sin, cos","from pysketcher import *"]
fontsize: 18
g: 9.81              # constant gravity
theta: 30.0          # inclined plane angle
L: 10.0              # sketch sizing parameter
a: 1.0               #
xmin: 0.0            # sketech min Abscissa
ymin: -3.0           # sketech min Ordinate     
rl: 2.0              # rectangle width
rL: 1.0              # rectangle length
setframe:            # sketch setup
    action: "drawing_tool.set_coordinate_system(xmin=xmin-L/5, xmax=xmin+1.5*L,ymin=ymin, ymax=ymin+1.5*L,instruction_file='tmp_mpl_friction.py')"
setblackline:        # default frame values and actions
    action: "drawing_tool.set_linecolor('black')"
B: point(a+L,0)                      # wall right end
A: point(a,tan(radians(theta))*L)    # wall left end
normal_vec: point(sin(radians(theta)),cos(radians(theta)))     # Vector normal to wall
tangent_vec: point(cos(radians(theta)),-sin(radians(theta)))   # Vector tangent to wall
help_line: Line(A,B)                 # wall line
x: a + 3*L/10.
y: help_line(x=x)    
contact: point(x, y)    
c: contact + rL/2*normal_vec
"""
In [11]:
body="""\
rectangle: 
    formula: Rectangle(contact, rl, rL)
    style:
        linecolor: blue
        filled_curves: blue
    transform: ["rotate(-theta, contact)",
                "translate(-rl/2*tangent_vec)"]
N: 
    formula: Force(contact - rl*normal_vec, contact, r'$N$', text_pos='start')
    style:
        linecolor: black
wheel: 
    formula: "Composition({'outer': rectangle})"   
    style:
        shadow: 1
mc:
    formula: Text(r'$c$', c)
body: 
    formula: "Composition({'wheel': wheel, 'N': N, 'mc': mc})"
    style:
        linecolor: black
"""        
In [15]:
plan="""\
mB:
    formula: Text(r'$B$',B)
mA:
    formula: Text(r'$A$', A)
wall: 
    formula: Wall(x=[A[0], B[0]], y=[A[1], B[1]], thickness=-0.25,transparent=False)
    style:
        linecolor: black    
x_const: 
    formula: Line(contact, contact + point(0,4))
    style:
        linestyle: dotted
    transform: rotate(-theta, contact)
x_axis: 
    formula: "Axis(start=contact+ 2*rl*normal_vec, length=2*rl,label='$x$', rotation_angle=-theta)"
plan: 
    formula: "Composition({'body': body, 'inclined wall': wall, 'x start': x_const, 'x axis': x_axis, 'mA': mA, 'mB': mB})"
"""
In [13]:
friction="""\
mg: 
    formula: Gravity(c, rl, text='$Mg$')
    style:
        linecolor: black
angle: 
    formula: "Arc_wText(r'$<bslash>theta$', center=B, radius=3, start_angle=180-theta, arc_angle=theta, fontsize=fontsize)"
    style:
        linecolor: black
        linewidth: 1
ground: 
     formula: Line((B[0]-L/10., 0), (B[0]-L/2.,0))
     stlye:
         linecolor: black
         linestyle: dashed
         linewidth: 1
friction: 
    formula: "Composition({'plan': plan, 'ground': ground, 'mg': mg, 'angle': angle})"
"""

Read yaml sketch definition, draw it

In [16]:
sketchParse(head,myfig)
sketchParse(body,myfig)
sketchParse(plan,myfig)
sketchParse(friction,myfig)
In [17]:
d = myfig['friction'].draw()
In [18]:
drawing_tool.display()
In [19]:
def doright(change):
    rotate(-5)
def doleft(change):
    rotate(5)
def rotate(theta):
    angle = myfig['theta']
    angle -= theta
    myfig['theta'] = angle
    drawing_tool.erase()
    x = myfig['plan']['body']['mc'].x
    y = myfig['plan']['body']['mc'].y
    myfig['plan'].rotate(theta,myfig['B'])
    xf = myfig['plan']['body']['mc'].x
    yf = myfig['plan']['body']['mc'].y
    trans = point(xf-x,yf-y)
    myfig['angle'].changeAngle(180-angle, angle)
    myfig['mg'].translate(trans)
    myfig['friction'].draw()
In [25]:
left = Button(
    description = '',
    icon = 'rotate-left',
)
left.on_click(doleft)
right = Button(
    description = '',
    icon = 'rotate-right',
)
right.on_click(doright)
output = Output()
In [26]:
applayout = AppLayout(
    center=output,
    footer=HBox([left,right]),
    pane_heights=[0, 6, 1]
)
#drawing_tool.mpl.ion()
In [27]:
applayout
In [28]:
with output:
    clear_output()
    display(drawing_tool.mpl.gcf().canvas)

Turn it interactiv

In [29]:
drawing_tool.mpl.ion()

Use left and right rotation button to rotate the sketch

Simulate sketch rotation

Using SVG

In [18]:
for i in range(0,10):
    doright(None)
    clear_output(wait=True)
    display(SVG(sketch2SVG()))
    time.sleep(0.01)
2020-08-03T13:05:15.684282 image/svg+xml Matplotlib v3.3.0, https://matplotlib.org/

Using PNG

In [19]:
for i in range(0,10):
    doright(None)
    clear_output(wait=True)
    display(sketch2PNG()) 
    time.sleep(0.01)

take a canvas snapshot

In [20]:
drawing_tool.mpl.gcf().canvas.print_png("friction.png")
from PIL import Image
img = Image.open("friction.png")
img
Out[20]:

Sketch composition

In [21]:
myfig['friction'].graphviz_dot('friction')
graphviz [('Composition:\\nfriction', 'Composition:\\nplan'), ('Composition:\\nplan', 'Composition:\\nbody'), ('Composition:\\nbody', 'Composition:\\nwheel'), ('Composition:\\nwheel', 'Rectangle:\\nouter'), ('Rectangle:\\nouter', 'Curve:\\nrectangle'), ('Composition:\\nbody', 'Force:\\nN'), ('Force:\\nN', 'Line:\\narrow'), ('Line:\\narrow', 'Curve:\\nline'), ('Force:\\nN', 'Text:\\ntext'), ('Composition:\\nbody', 'Text:\\nmc'), ('Composition:\\nplan', 'Wall:\\ninclined wall'), ('Wall:\\ninclined wall', 'Curve:\\nwall'), ('Composition:\\nplan', 'Line:\\nx start'), ('Line:\\nx start', 'Curve:\\nline'), ('Composition:\\nplan', 'Axis:\\nx axis'), ('Axis:\\nx axis', 'Arrow3:\\narrow'), ('Arrow3:\\narrow', 'Line:\\nline'), ('Line:\\nline', 'Curve:\\nline'), ('Arrow3:\\narrow', 'Line:\\nhead left'), ('Line:\\nhead left', 'Curve:\\nline'), ('Arrow3:\\narrow', 'Line:\\nhead right'), ('Line:\\nhead right', 'Curve:\\nline'), ('Axis:\\nx axis', 'Text:\\nlabel'), ('Composition:\\nplan', 'Text:\\nmA'), ('Composition:\\nplan', 'Text:\\nmB'), ('Composition:\\nfriction', 'Line:\\nground'), ('Line:\\nground', 'Curve:\\nline'), ('Composition:\\nfriction', 'Gravity:\\nmg'), ('Gravity:\\nmg', 'Line:\\narrow'), ('Line:\\narrow', 'Curve:\\nline'), ('Gravity:\\nmg', 'Text:\\ntext'), ('Composition:\\nfriction', 'Arc_wText:\\nangle'), ('Arc_wText:\\nangle', 'Arc:\\narc'), ('Arc:\\narc', 'Curve:\\narc'), ('Arc_wText:\\nangle', 'Text:\\ntext')] defaultdict(<function Shape.graphviz_dot.<locals>.<lambda> at 0x0000026E4E9629D0>, {'Composition:\\nplan': 1, 'Composition:\\nfriction': 0, 'Composition:\\nbody': 1, 'Composition:\\nwheel': 1, 'Rectangle:\\nouter': 1, 'Curve:\\nrectangle': 1, 'Force:\\nN': 1, 'Line:\\narrow': 2, 'Curve:\\nline': 7, 'Text:\\ntext': 3, 'Text:\\nmc': 1, 'Wall:\\ninclined wall': 1, 'Curve:\\nwall': 1, 'Line:\\nx start': 1, 'Axis:\\nx axis': 1, 'Arrow3:\\narrow': 1, 'Line:\\nline': 1, 'Line:\\nhead left': 1, 'Line:\\nhead right': 1, 'Text:\\nlabel': 1, 'Text:\\nmA': 1, 'Text:\\nmB': 1, 'Line:\\nground': 1, 'Gravity:\\nmg': 1, 'Arc_wText:\\nangle': 1, 'Arc:\\narc': 1, 'Curve:\\narc': 1})
[('Composition:\\nfriction', 'Composition:\\nplan'), ('Composition:\\nplan', 'Composition:\\nbody'), ('Composition:\\nbody', 'Composition:\\nwheel'), ('Composition:\\nwheel', 'Rectangle:\\nouter'), ('Rectangle:\\nouter', 'Curve:\\nrectangle'), ('Composition:\\nbody', 'Force:\\nN'), ('Force:\\nN', 'Line:\\narrow (1)'), ('Line:\\narrow (1)', 'Curve:\\nline (1)'), ('Force:\\nN', 'Text:\\ntext (1)'), ('Composition:\\nbody', 'Text:\\nmc'), ('Composition:\\nplan', 'Wall:\\ninclined wall'), ('Wall:\\ninclined wall', 'Curve:\\nwall'), ('Composition:\\nplan', 'Line:\\nx start'), ('Line:\\nx start', 'Curve:\\nline (2)'), ('Composition:\\nplan', 'Axis:\\nx axis'), ('Axis:\\nx axis', 'Arrow3:\\narrow'), ('Arrow3:\\narrow', 'Line:\\nline'), ('Line:\\nline', 'Curve:\\nline (3)'), ('Arrow3:\\narrow', 'Line:\\nhead left'), ('Line:\\nhead left', 'Curve:\\nline (4)'), ('Arrow3:\\narrow', 'Line:\\nhead right'), ('Line:\\nhead right', 'Curve:\\nline (5)'), ('Axis:\\nx axis', 'Text:\\nlabel'), ('Composition:\\nplan', 'Text:\\nmA'), ('Composition:\\nplan', 'Text:\\nmB'), ('Composition:\\nfriction', 'Line:\\nground'), ('Line:\\nground', 'Curve:\\nline (6)'), ('Composition:\\nfriction', 'Gravity:\\nmg'), ('Gravity:\\nmg', 'Line:\\narrow (2)'), ('Line:\\narrow (2)', 'Curve:\\nline (7)'), ('Gravity:\\nmg', 'Text:\\ntext (2)'), ('Composition:\\nfriction', 'Arc_wText:\\nangle'), ('Arc_wText:\\nangle', 'Arc:\\narc'), ('Arc:\\narc', 'Curve:\\narc'), ('Arc_wText:\\nangle', 'Text:\\ntext (3)')]
Run dot -Tpng -o friction.png friction.dot
In [22]:
!dot -Tpng -o dotfriction.png friction.dot
from PIL import Image
img = Image.open("dotfriction.png")
img
Out[22]:
In [ ]: