|
|
@@ -55,34 +55,42 @@ Automatically generated HTML file from DocOnce source
|
|
|
'sketcher:ex:pendulum:basic',
|
|
|
'sketcher:ex:pendulum:basic'),
|
|
|
('The body diagram', 2, None, '___sec10'),
|
|
|
- ('Basic shapes', 1, None, '___sec11'),
|
|
|
- ('Axis', 2, None, '___sec12'),
|
|
|
- ('Distance with text', 2, None, '___sec13'),
|
|
|
- ('Rectangle', 2, None, '___sec14'),
|
|
|
- ('Triangle', 2, None, '___sec15'),
|
|
|
- ('Arc', 2, None, '___sec16'),
|
|
|
- ('Spring', 2, None, '___sec17'),
|
|
|
- ('Dashpot', 2, None, '___sec18'),
|
|
|
- ('Wavy', 2, None, '___sec19'),
|
|
|
- ('Stochastic curves', 2, None, '___sec20'),
|
|
|
- ('Inner workings of the Pysketcher tool', 1, None, '___sec21'),
|
|
|
+ ('Animated body diagram',
|
|
|
+ 2,
|
|
|
+ 'sketcher:ex:pendulum:anim',
|
|
|
+ 'sketcher:ex:pendulum:anim'),
|
|
|
+ ('Function for drawing the body diagram', 3, None, '___sec12'),
|
|
|
+ ('Equations for the motion and forces', 3, None, '___sec13'),
|
|
|
+ ('Numerical solution', 3, None, '___sec14'),
|
|
|
+ ('Animation', 3, None, '___sec15'),
|
|
|
+ ('Basic shapes', 1, None, '___sec16'),
|
|
|
+ ('Axis', 2, None, '___sec17'),
|
|
|
+ ('Distance with text', 2, None, '___sec18'),
|
|
|
+ ('Rectangle', 2, None, '___sec19'),
|
|
|
+ ('Triangle', 2, None, '___sec20'),
|
|
|
+ ('Arc', 2, None, '___sec21'),
|
|
|
+ ('Spring', 2, None, '___sec22'),
|
|
|
+ ('Dashpot', 2, None, '___sec23'),
|
|
|
+ ('Wavy', 2, None, '___sec24'),
|
|
|
+ ('Stochastic curves', 2, None, '___sec25'),
|
|
|
+ ('Inner workings of the Pysketcher tool', 1, None, '___sec26'),
|
|
|
('Example of classes for geometric objects',
|
|
|
2,
|
|
|
None,
|
|
|
- '___sec22'),
|
|
|
- ('Simple geometric objects', 3, None, '___sec23'),
|
|
|
- ('Class curve', 3, None, '___sec24'),
|
|
|
- ('Compound geometric objects', 3, None, '___sec25'),
|
|
|
- ('Adding functionality via recursion', 2, None, '___sec26'),
|
|
|
- ('Basic principles of recursion', 3, None, '___sec27'),
|
|
|
- ('Explaining recursion', 3, None, '___sec28'),
|
|
|
+ '___sec27'),
|
|
|
+ ('Simple geometric objects', 3, None, '___sec28'),
|
|
|
+ ('Class curve', 3, None, '___sec29'),
|
|
|
+ ('Compound geometric objects', 3, None, '___sec30'),
|
|
|
+ ('Adding functionality via recursion', 2, None, '___sec31'),
|
|
|
+ ('Basic principles of recursion', 3, None, '___sec32'),
|
|
|
+ ('Explaining recursion', 3, None, '___sec33'),
|
|
|
('Scaling, translating, and rotating a figure',
|
|
|
2,
|
|
|
'sketcher:scaling',
|
|
|
'sketcher:scaling'),
|
|
|
- ('Scaling', 3, None, '___sec30'),
|
|
|
- ('Translation', 3, None, '___sec31'),
|
|
|
- ('Rotation', 3, None, '___sec32')]}
|
|
|
+ ('Scaling', 3, None, '___sec35'),
|
|
|
+ ('Translation', 3, None, '___sec36'),
|
|
|
+ ('Rotation', 3, None, '___sec37')]}
|
|
|
end of tocinfo -->
|
|
|
|
|
|
<body>
|
|
|
@@ -101,6 +109,18 @@ MathJax.Hub.Config({
|
|
|
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
|
|
|
</script>
|
|
|
|
|
|
+<!-- newcommands.tex -->
|
|
|
+$$
|
|
|
+\newcommand{\half}{\frac{1}{2}}
|
|
|
+\newcommand{\tp}{\thinspace .}
|
|
|
+\newcommand{\rpos}{\boldsymbol{r}}
|
|
|
+\newcommand{\ii}{\boldsymbol{i}}
|
|
|
+\newcommand{\jj}{\boldsymbol{j}}
|
|
|
+\newcommand{\ir}{\boldsymbol{i}_r}
|
|
|
+\newcommand{\ith}{\boldsymbol{i}_{\theta}}
|
|
|
+$$
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
@@ -131,28 +151,33 @@ MathJax.Hub.Config({
|
|
|
<!-- navigation toc: --> <li><a href="#sketcher:ex:pendulum" style="font-size: 80%;"><b>A simple pendulum</b></a></li>
|
|
|
<!-- navigation toc: --> <li><a href="#sketcher:ex:pendulum:basic" style="font-size: 80%;"> The basic physics sketch</a></li>
|
|
|
<!-- navigation toc: --> <li><a href="#___sec10" style="font-size: 80%;"> The body diagram</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec11" style="font-size: 80%;"><b>Basic shapes</b></a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec12" style="font-size: 80%;"> Axis</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec13" style="font-size: 80%;"> Distance with text</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec14" style="font-size: 80%;"> Rectangle</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec15" style="font-size: 80%;"> Triangle</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec16" style="font-size: 80%;"> Arc</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec17" style="font-size: 80%;"> Spring</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec18" style="font-size: 80%;"> Dashpot</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec19" style="font-size: 80%;"> Wavy</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec20" style="font-size: 80%;"> Stochastic curves</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec21" style="font-size: 80%;"><b>Inner workings of the Pysketcher tool</b></a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec22" style="font-size: 80%;"> Example of classes for geometric objects</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec23" style="font-size: 80%;"> Simple geometric objects</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec24" style="font-size: 80%;"> Class curve</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec25" style="font-size: 80%;"> Compound geometric objects</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec26" style="font-size: 80%;"> Adding functionality via recursion</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec27" style="font-size: 80%;"> Basic principles of recursion</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec28" style="font-size: 80%;"> Explaining recursion</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="#sketcher:ex:pendulum:anim" style="font-size: 80%;"> Animated body diagram</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="#___sec12" style="font-size: 80%;"> Function for drawing the body diagram</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="#___sec13" style="font-size: 80%;"> Equations for the motion and forces</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="#___sec14" style="font-size: 80%;"> Numerical solution</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="#___sec15" style="font-size: 80%;"> Animation</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec16" style="font-size: 80%;"><b>Basic shapes</b></a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec17" style="font-size: 80%;"> Axis</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec18" style="font-size: 80%;"> Distance with text</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec19" style="font-size: 80%;"> Rectangle</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec20" style="font-size: 80%;"> Triangle</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec21" style="font-size: 80%;"> Arc</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec22" style="font-size: 80%;"> Spring</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec23" style="font-size: 80%;"> Dashpot</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec24" style="font-size: 80%;"> Wavy</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec25" style="font-size: 80%;"> Stochastic curves</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec26" style="font-size: 80%;"><b>Inner workings of the Pysketcher tool</b></a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec27" style="font-size: 80%;"> Example of classes for geometric objects</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec28" style="font-size: 80%;"> Simple geometric objects</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec29" style="font-size: 80%;"> Class curve</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec30" style="font-size: 80%;"> Compound geometric objects</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec31" style="font-size: 80%;"> Adding functionality via recursion</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec32" style="font-size: 80%;"> Basic principles of recursion</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec33" style="font-size: 80%;"> Explaining recursion</a></li>
|
|
|
<!-- navigation toc: --> <li><a href="._pysketcher005.html#sketcher:scaling" style="font-size: 80%;"> Scaling, translating, and rotating a figure</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec30" style="font-size: 80%;"> Scaling</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec31" style="font-size: 80%;"> Translation</a></li>
|
|
|
- <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec32" style="font-size: 80%;"> Rotation</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec35" style="font-size: 80%;"> Scaling</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec36" style="font-size: 80%;"> Translation</a></li>
|
|
|
+ <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec37" style="font-size: 80%;"> Rotation</a></li>
|
|
|
|
|
|
</ul>
|
|
|
</li>
|
|
|
@@ -174,7 +199,12 @@ MathJax.Hub.Config({
|
|
|
|
|
|
<p>
|
|
|
We now want to make a sketch of simple pendulum from physics, as shown
|
|
|
-in Figure <a href="#sketcher:ex:pendulum:fig1">8</a>. A suggested work flow is to
|
|
|
+in Figure <a href="#sketcher:ex:pendulum:fig1">8</a>. A body with mass \( m \) is attached
|
|
|
+to a massless, stiff rod, which can rotate about a point, causing the
|
|
|
+pendulum to oscillate.
|
|
|
+
|
|
|
+<p>
|
|
|
+A suggested work flow is to
|
|
|
first sketch the figure on a piece of paper and introduce a coordinate
|
|
|
system. A simple coordinate system is indicated in Figure
|
|
|
<a href="#sketcher:ex:pendulum:fig1wgrid">9</a>. In a code we introduce variables
|
|
|
@@ -206,13 +236,13 @@ Also note that we in this example let all lines be blue by default.
|
|
|
<center> <!-- figure -->
|
|
|
<hr class="figure">
|
|
|
<center><p class="caption">Figure 8: Sketch of a simple pendulum. <div id="sketcher:ex:pendulum:fig1"></div> </p></center>
|
|
|
-<p><img src="fig-tut/pendulum1.png" align="bottom" width=400></p>
|
|
|
+<p><img src="fig-tut/pendulum1.png" align="bottom" width=300></p>
|
|
|
</center>
|
|
|
|
|
|
<p>
|
|
|
<center> <!-- figure -->
|
|
|
<hr class="figure">
|
|
|
-<center><p class="caption">Figure 9: Sketch of a simple pendulum. <div id="sketcher:ex:pendulum:fig1wgrid"></div> </p></center>
|
|
|
+<center><p class="caption">Figure 9: Sketch with assisting coordinate system. <div id="sketcher:ex:pendulum:fig1wgrid"></div> </p></center>
|
|
|
<p><img src="fig-tut/pendulum1_wgrid.png" align="bottom" width=400></p>
|
|
|
</center>
|
|
|
|
|
|
@@ -253,13 +283,18 @@ Figure <a href="#sketcher:ex:pendulum:fig1">8</a> we see that we need
|
|
|
|
|
|
Pysketcher has objects for each of these elements in our sketch.
|
|
|
We start with the simplest element: the vertical line, going from
|
|
|
-<code>P</code> to <code>P</code> minus the length in \( y \) direction:
|
|
|
+<code>P</code> to <code>P</code> minus the length \( L \) in \( y \) direction:
|
|
|
|
|
|
<p>
|
|
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">vertical <span style="color: #666666">=</span> Line(P, P<span style="color: #666666">-</span>point(<span style="color: #666666">0</span>,L))
|
|
|
</pre></div>
|
|
|
+<p>
|
|
|
+The class <code>point</code> is very convenient: it turns its two coordinates into
|
|
|
+a vector with which we can compute, and is therefore one of the most
|
|
|
+widely used Pysketcher objects.
|
|
|
+
|
|
|
<p>
|
|
|
The path of the mass is an arc that can be made by
|
|
|
Pysketcher's <code>Arc</code> object:
|
|
|
@@ -271,7 +306,7 @@ Pysketcher's <code>Arc</code> object:
|
|
|
</pre></div>
|
|
|
<p>
|
|
|
The first argument <code>P</code> is the center point, the second is the
|
|
|
-radius (<code>L</code> here), the next arguments is the start angle, here
|
|
|
+radius (<code>L</code> here), the next argument is the start angle, here
|
|
|
it starts at -90 degrees, while the next argument is the angle of
|
|
|
the arc, here <code>a</code>.
|
|
|
For the path of the mass, we also need an arc object, but this
|
|
|
@@ -296,10 +331,11 @@ adjust spacings as one goes along.
|
|
|
The rod is simply a line from <code>P</code> to the mass. We can easily
|
|
|
compute the position of the mass from basic geometry considerations,
|
|
|
but it is easier and safer to look up this point in other objects
|
|
|
-if it is already computed. The <code>path</code> object stores its start and
|
|
|
+if it is already computed. In the present case,
|
|
|
+the <code>path</code> object stored its start and
|
|
|
end points, so <code>path.geometric_features()['end']</code> is the end point
|
|
|
of the path, which is the position of the mass. We can therefore
|
|
|
-create the rod simply as a line from <code>P</code> to this end point:
|
|
|
+create the rod simply as a line from <code>P</code> to this already computed end point:
|
|
|
|
|
|
<p>
|
|
|
|
|
|
@@ -351,6 +387,8 @@ length<span style="color: #666666">.</span>translate(L<span style="color: #66666
|
|
|
For this translation we need a unit vector in the normal direction
|
|
|
of the rod, which is from geometric considerations given by
|
|
|
\( (\cos a, \sin a) \), when \( a \) is the angle of the pendulum.
|
|
|
+Alternatively, we could have found the normal vector as a vector that
|
|
|
+is normal to <code>unit_rod_vec</code>: <code>point(-unit_rod_vec[1],unit_rod_vec[0])</code>.
|
|
|
|
|
|
<p>
|
|
|
The final object is the gravity force vector, which is so common
|
|
|
@@ -363,15 +401,15 @@ in physics sketches that Pysketcher has a ready-made object: <code>Gravity</code
|
|
|
</pre></div>
|
|
|
<p>
|
|
|
Since blue is the default color for
|
|
|
-lines, we want the dashed lines (<code>vertical</code> and <code>path</code>) to be black
|
|
|
-and dashed with linewidth 1. These properties can be set one by one,
|
|
|
-but we can also make a little helper function:
|
|
|
+lines, we want the dashed lines (for <code>vertical</code> and <code>path</code>) to be black
|
|
|
+and with linewidth 1. These properties can be set one by one for each
|
|
|
+object, but we can also make a little helper function:
|
|
|
|
|
|
<p>
|
|
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">set_dashed_thin_blackline</span>(<span style="color: #666666">*</span>objects):
|
|
|
- <span style="color: #BA2121; font-style: italic">"""Set linestyle of an object to dashed, black, width=1."""</span>
|
|
|
+ <span style="color: #BA2121; font-style: italic">"""Set linestyle of objects to dashed, black, width=1."""</span>
|
|
|
<span style="color: #008000; font-weight: bold">for</span> obj <span style="color: #AA22FF; font-weight: bold">in</span> objects:
|
|
|
obj<span style="color: #666666">.</span>set_linestyle(<span style="color: #BA2121">'dashed'</span>)
|
|
|
obj<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">'black'</span>)
|
|
|
@@ -412,7 +450,7 @@ coordinates.
|
|
|
<center> <!-- figure -->
|
|
|
<hr class="figure">
|
|
|
<center><p class="caption">Figure 10: Body diagram of a simple pendulum. <div id="sketcher:ex:pendulum:fig2wgrid"></div> </p></center>
|
|
|
-<p><img src="fig-tut/pendulum5_wgrid.png" align="bottom" width=400></p>
|
|
|
+<p><img src="fig-tut/pendulum5_wgrid.png" align="bottom" width=300></p>
|
|
|
</center>
|
|
|
|
|
|
<p>
|
|
|
@@ -431,9 +469,9 @@ We start by listing the objects in the sketch:
|
|
|
</ol>
|
|
|
|
|
|
The first object, \( (x_0,y_0) \), is simply a plain text where we have
|
|
|
-to experiment with the position. The unit vectors in polar coordinates
|
|
|
+to experiment with its position. The unit vectors in polar coordinates
|
|
|
may be drawn using the Pysketcher's <code>Force</code> object since it has an
|
|
|
-arrow with a text. The first three object can then be made as follows:
|
|
|
+arrow with a text. The first three objects can then be made as follows:
|
|
|
|
|
|
<p>
|
|
|
|
|
|
@@ -454,7 +492,7 @@ the tweaked displacement <code>point(-0.4,-0.1)</code> in terms of <code>W</code
|
|
|
The <code>text_spacing</code> values in the <code>Force</code> objects also use absolute
|
|
|
coordinates. Very often, this is much more convenient when adjusting
|
|
|
the objects, and global size parameters like <code>W</code> and <code>H</code> are in practice
|
|
|
-seldom changed.
|
|
|
+seldom changed, so the solution above is quite typical.
|
|
|
|
|
|
<p>
|
|
|
The vertical, dashed line, the dashed rod, and the arc for \( \theta \)
|
|
|
@@ -489,6 +527,11 @@ air_force <span style="color: #666666">=</span> Force(mass_pt, mass_pt <span sty
|
|
|
<span style="color: #BA2121">'$\sim|v|v$'</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>,
|
|
|
text_spacing<span style="color: #666666">=</span>(<span style="color: #666666">0.04</span>,<span style="color: #666666">0.005</span>))
|
|
|
</pre></div>
|
|
|
+<p>
|
|
|
+Note that the drag force from the air is directed perpendicular to
|
|
|
+the rod, so we construct a unit vector in this direction directly from
|
|
|
+the <code>rod_vec</code> vector.
|
|
|
+
|
|
|
<p>
|
|
|
All objects are in place, and we can compose a figure to be drawn:
|
|
|
|
|
|
@@ -511,7 +554,369 @@ dictionary, but (as in ordinary Python dictionaries) add new
|
|
|
elements later when desired.
|
|
|
|
|
|
<p>
|
|
|
-<!-- FIGURE: [fig-tut/pendulum1.png, width=400 frac=0.5] Sketch of a simple pendulum. <div id="sketcher:ex:pendulum:fig2"></div> -->
|
|
|
+<!-- FIGURE: [fig-tut/pendulum1.png, width=300 frac=0.5] Sketch of a simple pendulum. <div id="sketcher:ex:pendulum:fig2"></div> -->
|
|
|
+
|
|
|
+<h2 id="sketcher:ex:pendulum:anim">Animated body diagram</h2>
|
|
|
+
|
|
|
+<p>
|
|
|
+We want to make an animated body diagram so that we can see how forces
|
|
|
+develop in time according to the motion. This means that we must
|
|
|
+couple the sketch at each time level to a numerical solution for
|
|
|
+the motion of the pendulum.
|
|
|
+
|
|
|
+<h3 id="___sec12">Function for drawing the body diagram </h3>
|
|
|
+
|
|
|
+<p>
|
|
|
+The previous flat program for making sketches of the pendulum is not
|
|
|
+suitable when we want to make a sketch at a lot of different points
|
|
|
+in time, i.e., for a lot of different angles that the pendulum makes
|
|
|
+with the vertical. We therefore need to draw the body diagram in
|
|
|
+a function where the angle is a parameter. We also supply arrays
|
|
|
+containing the (numerically computed) values of the angle \( \theta \) and
|
|
|
+the forces at various time levels, plus the desired time point and level
|
|
|
+for this particular sketch:
|
|
|
+
|
|
|
+<p>
|
|
|
+
|
|
|
+<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
|
+<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">pysketcher</span> <span style="color: #008000; font-weight: bold">import</span> <span style="color: #666666">*</span>
|
|
|
+
|
|
|
+H <span style="color: #666666">=</span> <span style="color: #666666">15.</span>
|
|
|
+W <span style="color: #666666">=</span> <span style="color: #666666">17.</span>
|
|
|
+
|
|
|
+drawing_tool<span style="color: #666666">.</span>set_coordinate_system(xmin<span style="color: #666666">=0</span>, xmax<span style="color: #666666">=</span>W,
|
|
|
+ ymin<span style="color: #666666">=0</span>, ymax<span style="color: #666666">=</span>H,
|
|
|
+ axis<span style="color: #666666">=</span><span style="color: #008000">False</span>)
|
|
|
+
|
|
|
+<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">pendulum</span>(theta, S, mg, drag, t, time_level):
|
|
|
+
|
|
|
+ drawing_tool<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">'blue'</span>)
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">math</span>
|
|
|
+ a <span style="color: #666666">=</span> math<span style="color: #666666">.</span>degrees(theta[time_level])
|
|
|
+ L <span style="color: #666666">=</span> <span style="color: #666666">0.4*</span>H <span style="color: #408080; font-style: italic"># length</span>
|
|
|
+ P <span style="color: #666666">=</span> (W<span style="color: #666666">/2</span>, <span style="color: #666666">0.8*</span>H) <span style="color: #408080; font-style: italic"># rotation point</span>
|
|
|
+
|
|
|
+ vertical <span style="color: #666666">=</span> Line(P, P<span style="color: #666666">-</span>point(<span style="color: #666666">0</span>,L))
|
|
|
+ path <span style="color: #666666">=</span> Arc(P, L, <span style="color: #666666">-90</span>, a)
|
|
|
+ angle <span style="color: #666666">=</span> Arc_wText(<span style="color: #BA2121">r'$\theta$'</span>, P, L<span style="color: #666666">/4</span>, <span style="color: #666666">-90</span>, a, text_spacing<span style="color: #666666">=1/30.</span>)
|
|
|
+
|
|
|
+ mass_pt <span style="color: #666666">=</span> path<span style="color: #666666">.</span>geometric_features()[<span style="color: #BA2121">'end'</span>]
|
|
|
+ rod <span style="color: #666666">=</span> Line(P, mass_pt)
|
|
|
+
|
|
|
+ mass <span style="color: #666666">=</span> Circle(center<span style="color: #666666">=</span>mass_pt, radius<span style="color: #666666">=</span>L<span style="color: #666666">/20.</span>)
|
|
|
+ mass<span style="color: #666666">.</span>set_filled_curves(color<span style="color: #666666">=</span><span style="color: #BA2121">'blue'</span>)
|
|
|
+ rod_vec <span style="color: #666666">=</span> rod<span style="color: #666666">.</span>geometric_features()[<span style="color: #BA2121">'end'</span>] <span style="color: #666666">-</span> \
|
|
|
+ rod<span style="color: #666666">.</span>geometric_features()[<span style="color: #BA2121">'start'</span>]
|
|
|
+ unit_rod_vec <span style="color: #666666">=</span> unit_vec(rod_vec)
|
|
|
+ mass_symbol <span style="color: #666666">=</span> Text(<span style="color: #BA2121">'$m$'</span>, mass_pt <span style="color: #666666">+</span> L<span style="color: #666666">/10*</span>unit_rod_vec)
|
|
|
+
|
|
|
+ length <span style="color: #666666">=</span> Distance_wText(P, mass_pt, <span style="color: #BA2121">'$L$'</span>)
|
|
|
+ <span style="color: #408080; font-style: italic"># Displace length indication</span>
|
|
|
+ length<span style="color: #666666">.</span>translate(L<span style="color: #666666">/15*</span>point(cos(radians(a)), sin(radians(a))))
|
|
|
+ gravity <span style="color: #666666">=</span> Gravity(start<span style="color: #666666">=</span>P<span style="color: #666666">+</span>point(<span style="color: #666666">0.8*</span>L,<span style="color: #666666">0</span>), length<span style="color: #666666">=</span>L<span style="color: #666666">/3</span>)
|
|
|
+
|
|
|
+ <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">set_dashed_thin_blackline</span>(<span style="color: #666666">*</span>objects):
|
|
|
+ <span style="color: #BA2121; font-style: italic">"""Set linestyle of objects to dashed, black, width=1."""</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">for</span> obj <span style="color: #AA22FF; font-weight: bold">in</span> objects:
|
|
|
+ obj<span style="color: #666666">.</span>set_linestyle(<span style="color: #BA2121">'dashed'</span>)
|
|
|
+ obj<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">'black'</span>)
|
|
|
+ obj<span style="color: #666666">.</span>set_linewidth(<span style="color: #666666">1</span>)
|
|
|
+
|
|
|
+ set_dashed_thin_blackline(vertical, path)
|
|
|
+
|
|
|
+ fig <span style="color: #666666">=</span> Composition(
|
|
|
+ {<span style="color: #BA2121">'body'</span>: mass, <span style="color: #BA2121">'rod'</span>: rod,
|
|
|
+ <span style="color: #BA2121">'vertical'</span>: vertical, <span style="color: #BA2121">'theta'</span>: angle, <span style="color: #BA2121">'path'</span>: path,
|
|
|
+ <span style="color: #BA2121">'g'</span>: gravity, <span style="color: #BA2121">'L'</span>: length})
|
|
|
+
|
|
|
+ <span style="color: #408080; font-style: italic">#fig.draw()</span>
|
|
|
+ <span style="color: #408080; font-style: italic">#drawing_tool.display()</span>
|
|
|
+ <span style="color: #408080; font-style: italic">#drawing_tool.savefig('tmp_pendulum1')</span>
|
|
|
+
|
|
|
+ drawing_tool<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">'black'</span>)
|
|
|
+
|
|
|
+ rod_start <span style="color: #666666">=</span> rod<span style="color: #666666">.</span>geometric_features()[<span style="color: #BA2121">'start'</span>] <span style="color: #408080; font-style: italic"># Point P</span>
|
|
|
+ vertical2 <span style="color: #666666">=</span> Line(rod_start, rod_start <span style="color: #666666">+</span> point(<span style="color: #666666">0</span>,<span style="color: #666666">-</span>L<span style="color: #666666">/3</span>))
|
|
|
+ set_dashed_thin_blackline(vertical2)
|
|
|
+ set_dashed_thin_blackline(rod)
|
|
|
+ angle2 <span style="color: #666666">=</span> Arc_wText(<span style="color: #BA2121">r'$\theta$'</span>, rod_start, L<span style="color: #666666">/6</span>, <span style="color: #666666">-90</span>, a,
|
|
|
+ text_spacing<span style="color: #666666">=1/30.</span>)
|
|
|
+
|
|
|
+ magnitude <span style="color: #666666">=</span> <span style="color: #666666">1.2*</span>L<span style="color: #666666">/2</span> <span style="color: #408080; font-style: italic"># length of a unit force in figure</span>
|
|
|
+ force <span style="color: #666666">=</span> mg[time_level] <span style="color: #408080; font-style: italic"># constant (scaled eq: about 1)</span>
|
|
|
+ force <span style="color: #666666">*=</span> magnitude
|
|
|
+ mg_force <span style="color: #666666">=</span> Force(mass_pt, mass_pt <span style="color: #666666">+</span> force<span style="color: #666666">*</span>point(<span style="color: #666666">0</span>,<span style="color: #666666">-1</span>),
|
|
|
+ <span style="color: #BA2121">''</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>)
|
|
|
+ force <span style="color: #666666">=</span> S[time_level]
|
|
|
+ force <span style="color: #666666">*=</span> magnitude
|
|
|
+ rod_force <span style="color: #666666">=</span> Force(mass_pt, mass_pt <span style="color: #666666">-</span> force<span style="color: #666666">*</span>unit_vec(rod_vec),
|
|
|
+ <span style="color: #BA2121">''</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>,
|
|
|
+ text_spacing<span style="color: #666666">=</span>(<span style="color: #666666">0.03</span>, <span style="color: #666666">0.01</span>))
|
|
|
+ force <span style="color: #666666">=</span> drag[time_level]
|
|
|
+ force <span style="color: #666666">*=</span> magnitude
|
|
|
+ <span style="color: #408080; font-style: italic">#print('drag(%g)=%g' % (t, drag[time_level]))</span>
|
|
|
+ air_force <span style="color: #666666">=</span> Force(mass_pt, mass_pt <span style="color: #666666">-</span>
|
|
|
+ force<span style="color: #666666">*</span>unit_vec((rod_vec[<span style="color: #666666">1</span>], <span style="color: #666666">-</span>rod_vec[<span style="color: #666666">0</span>])),
|
|
|
+ <span style="color: #BA2121">''</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>,
|
|
|
+ text_spacing<span style="color: #666666">=</span>(<span style="color: #666666">0.04</span>,<span style="color: #666666">0.005</span>))
|
|
|
+
|
|
|
+ body_diagram <span style="color: #666666">=</span> Composition(
|
|
|
+ {<span style="color: #BA2121">'mg'</span>: mg_force, <span style="color: #BA2121">'S'</span>: rod_force, <span style="color: #BA2121">'air'</span>: air_force,
|
|
|
+ <span style="color: #BA2121">'rod'</span>: rod,
|
|
|
+ <span style="color: #BA2121">'vertical'</span>: vertical2, <span style="color: #BA2121">'theta'</span>: angle2,
|
|
|
+ <span style="color: #BA2121">'body'</span>: mass})
|
|
|
+
|
|
|
+ x0y0 <span style="color: #666666">=</span> Text(<span style="color: #BA2121">'$(x_0,y_0)$'</span>, P <span style="color: #666666">+</span> point(<span style="color: #666666">-0.4</span>,<span style="color: #666666">-0.1</span>))
|
|
|
+ ir <span style="color: #666666">=</span> Force(P, P <span style="color: #666666">+</span> L<span style="color: #666666">/10*</span>unit_vec(rod_vec),
|
|
|
+ <span style="color: #BA2121">r'$\boldsymbol{i}_r$'</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>,
|
|
|
+ text_spacing<span style="color: #666666">=</span>(<span style="color: #666666">0.015</span>,<span style="color: #666666">0</span>))
|
|
|
+ ith <span style="color: #666666">=</span> Force(P, P <span style="color: #666666">+</span> L<span style="color: #666666">/10*</span>unit_vec((<span style="color: #666666">-</span>rod_vec[<span style="color: #666666">1</span>], rod_vec[<span style="color: #666666">0</span>])),
|
|
|
+ <span style="color: #BA2121">r'$\boldsymbol{i}_{\theta}$'</span>, text_pos<span style="color: #666666">=</span><span style="color: #BA2121">'end'</span>,
|
|
|
+ text_spacing<span style="color: #666666">=</span>(<span style="color: #666666">0.02</span>,<span style="color: #666666">0.005</span>))
|
|
|
+
|
|
|
+ <span style="color: #408080; font-style: italic">#body_diagram['ir'] = ir</span>
|
|
|
+ <span style="color: #408080; font-style: italic">#body_diagram['ith'] = ith</span>
|
|
|
+ <span style="color: #408080; font-style: italic">#body_diagram['origin'] = x0y0</span>
|
|
|
+
|
|
|
+ drawing_tool<span style="color: #666666">.</span>erase()
|
|
|
+ body_diagram<span style="color: #666666">.</span>draw(verbose<span style="color: #666666">=0</span>)
|
|
|
+ <span style="color: #408080; font-style: italic">#drawing_tool.display('Body diagram')</span>
|
|
|
+ drawing_tool<span style="color: #666666">.</span>savefig(<span style="color: #BA2121">'tmp_</span><span style="color: #BB6688; font-weight: bold">%04d</span><span style="color: #BA2121">.png'</span> <span style="color: #666666">%</span> time_level, crop<span style="color: #666666">=</span><span style="color: #008000">False</span>)
|
|
|
+ <span style="color: #408080; font-style: italic"># No cropping: otherwise movies will be very strange</span>
|
|
|
+</pre></div>
|
|
|
+
|
|
|
+<h3 id="___sec13">Equations for the motion and forces </h3>
|
|
|
+
|
|
|
+<p>
|
|
|
+The modeling of the motion of a pendulum is most conveniently done in
|
|
|
+polar coordinates since then the unknown force in the rod is separated
|
|
|
+from the equation determining the motion \( \theta(t) \).
|
|
|
+The position vector for the mass is
|
|
|
+
|
|
|
+$$ \rpos = x_0\ii + y_0\jj + L\ir\tp$$
|
|
|
+
|
|
|
+The corresponding acceleration becomes
|
|
|
+
|
|
|
+$$ \ddot{\rpos} = L\ddot{\theta}{\ith} - L\dot{\theta^2}{\ir}\tp$$
|
|
|
+
|
|
|
+<!-- Note: the extra braces help to render the equation correctly in sphinx! -->
|
|
|
+
|
|
|
+<p>
|
|
|
+There are three forces on the mass: the gravity force
|
|
|
+\( mg\jj = mg(-\cos\theta\,\ir + \sin\theta\,\ith) \), the force in the rod
|
|
|
+\( -S\ir \), and the drag force because of air resistance:
|
|
|
+
|
|
|
+$$ -\half C_D \varrho \pi R^2 |v|v\,\ith,$$
|
|
|
+
|
|
|
+where \( C_D\approx 0.4 \) is the drag coefficient for a sphere, \( \varrho \)
|
|
|
+is the density of air, \( R \) is the radius of the mass, and \( v \) is the
|
|
|
+velocity (\( v=L\dot\theta \)). The drag force acts in \( -\ith \) direction
|
|
|
+when \( v>0 \).
|
|
|
+
|
|
|
+<p>
|
|
|
+Newton's second law of motion for the pendulum now becomes
|
|
|
+
|
|
|
+$$ mL\ddot\theta\ith - mL\dot\theta^2\ir = -mg(-\cos\theta\,\ir +
|
|
|
+\sin\theta\,\ith)
|
|
|
+-S\ir - \half C_D \varrho \pi R^2 L^2|\dot\theta|\dot\theta\ith,$$
|
|
|
+
|
|
|
+which gives two component equations
|
|
|
+
|
|
|
+$$
|
|
|
+\begin{align}
|
|
|
+mL\ddot\theta + \half C_D \varrho \pi R^2 L^2|\dot\theta|\dot\theta +
|
|
|
+mg\sin\theta &= 0,
|
|
|
+\tag{1}\\
|
|
|
+S &= mL\dot\theta^2 + mg\cos\theta
|
|
|
+\tag{2}\tp
|
|
|
+\end{align}
|
|
|
+$$
|
|
|
+
|
|
|
+<p>
|
|
|
+It is almost always convenient to scale such equations. Introducing
|
|
|
+the dimensionless time
|
|
|
+
|
|
|
+$$ \bar t = \frac{t}{t_c},\quad t_c = \sqrt{\frac{L}{g}},$$
|
|
|
+
|
|
|
+leads to
|
|
|
+
|
|
|
+$$
|
|
|
+\begin{align}
|
|
|
+\frac{d^2\theta}{d\bar t^2} +
|
|
|
+\alpha\left\vert\frac{d\theta}{d\bar t}\right\vert\frac{d\theta}{d\bar t} +
|
|
|
+\sin\theta &= 0,
|
|
|
+\tag{3}\\
|
|
|
+\bar S &= \left(\frac{d\theta}{d\bar t}\right)^2
|
|
|
++ \cos\theta,
|
|
|
+\tag{4}
|
|
|
+\end{align}
|
|
|
+$$
|
|
|
+
|
|
|
+where \( \alpha \) is a dimensionless drag coefficient
|
|
|
+
|
|
|
+$$ \alpha = \frac{C_D\varrho\pi R^2L}{2m},$$
|
|
|
+
|
|
|
+and \( \bar S \) is the scaled force
|
|
|
+
|
|
|
+$$ \bar S = \frac{S}{mg}\tp$$
|
|
|
+
|
|
|
+We see that \( \bar S = 1 \) for the equilibrium position \( \theta=0 \), so this
|
|
|
+scaling of \( S \) seems appropriate.
|
|
|
+
|
|
|
+<p>
|
|
|
+The parameter \( \alpha \) is about
|
|
|
+the ratio of the drag force and the gravity force:
|
|
|
+
|
|
|
+$$ \frac{|\half C_D\varrho \pi R^2 |v|v|}{|mg|}\sim
|
|
|
+\frac{C_D\varrho \pi R^2 L^2 t_c^{-2}}{mg}
|
|
|
+\left|\frac{d\bar\theta}{d\bar t}\right|\frac{d\bar\theta}{d\bar t}
|
|
|
+\sim \frac{C_D\varrho \pi R^2 L}{2m}\theta_0^2 = \alpha \theta_0^2\tp$$
|
|
|
+
|
|
|
+(We have that \( \theta(t)/d\theta_0 \) is in \( [-1,1] \), so we expect
|
|
|
+since \( \theta_0^{-1}d\bar\theta/d\bar t \) to be around unity.)
|
|
|
+
|
|
|
+<p>
|
|
|
+The next step is to write a numerical solver for
|
|
|
+<a href="#mjx-eqn-3">(3)</a>-<a href="#mjx-eqn-4">(4)</a>. To
|
|
|
+this end, we use the <a href="https://github.com/hplgit/odespy" target="_self">Odespy</a>
|
|
|
+package. The system of second-order ODEs must be expressed as a system
|
|
|
+of first-order ODEs. We realize that the unknown \( \bar S \) is decoupled
|
|
|
+from \( \theta \) in the sense that we can first use
|
|
|
+<a href="#mjx-eqn-3">(3)</a> to solve for \( \theta \) and
|
|
|
+then compute \( \bar S \) from <a href="#mjx-eqn-4">(4)</a>.
|
|
|
+The first-order ODEs become
|
|
|
+
|
|
|
+$$
|
|
|
+\begin{align}
|
|
|
+\frac{d\omega}{d\bar t} &= -\alpha\left\vert\omega\right\vert\omega
|
|
|
+- \sin\theta,
|
|
|
+\tag{5}\\
|
|
|
+\frac{d\theta}{d\bar t} &= \omega\tp
|
|
|
+\tag{6}
|
|
|
+\end{align}
|
|
|
+$$
|
|
|
+
|
|
|
+Then we compute
|
|
|
+
|
|
|
+$$
|
|
|
+\begin{equation}
|
|
|
+\bar S = \omega^2 + \cos\theta\tp
|
|
|
+\tag{7}
|
|
|
+\end{equation}
|
|
|
+$$
|
|
|
+
|
|
|
+The dimensionless air resistance force can also be computed:
|
|
|
+
|
|
|
+$$
|
|
|
+\begin{equation}
|
|
|
+-\alpha|\omega|\omega\tp
|
|
|
+\tag{8}
|
|
|
+\end{equation}
|
|
|
+$$
|
|
|
+
|
|
|
+Since we scaled the force \( S \) by \( mg \), \( mg \) is the natural force scale,
|
|
|
+and the \( mg \) force itself is then unity.
|
|
|
+
|
|
|
+<p>
|
|
|
+By updating \( \omega \) in the first equation, we can use an Euler-Cromer
|
|
|
+scheme on Odespy (all other schemes are independent of whether the
|
|
|
+\( \theta \) or \( \omega \) equation comes first).
|
|
|
+
|
|
|
+<h3 id="___sec14">Numerical solution </h3>
|
|
|
+
|
|
|
+<p>
|
|
|
+An appropriate solver is
|
|
|
+
|
|
|
+<p>
|
|
|
+
|
|
|
+<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
|
+<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">simulate_pendulum</span>(alpha, theta0, dt, T):
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">odespy</span>
|
|
|
+
|
|
|
+ <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">f</span>(u, t, alpha):
|
|
|
+ omega, theta <span style="color: #666666">=</span> u
|
|
|
+ <span style="color: #008000; font-weight: bold">return</span> [<span style="color: #666666">-</span>alpha<span style="color: #666666">*</span>omega<span style="color: #666666">*</span><span style="color: #008000">abs</span>(omega) <span style="color: #666666">-</span> sin(theta),
|
|
|
+ omega]
|
|
|
+
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
|
+ Nt <span style="color: #666666">=</span> <span style="color: #008000">int</span>(<span style="color: #008000">round</span>(T<span style="color: #666666">/</span><span style="color: #008000">float</span>(dt)))
|
|
|
+ t <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">0</span>, Nt<span style="color: #666666">*</span>dt, Nt<span style="color: #666666">+1</span>)
|
|
|
+ solver <span style="color: #666666">=</span> odespy<span style="color: #666666">.</span>RK4(f, f_args<span style="color: #666666">=</span>[alpha])
|
|
|
+ solver<span style="color: #666666">.</span>set_initial_condition([<span style="color: #666666">0</span>, theta0])
|
|
|
+ u, t <span style="color: #666666">=</span> solver<span style="color: #666666">.</span>solve(t,
|
|
|
+ terminate<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">lambda</span> u, t, n: <span style="color: #008000">abs</span>(u[n,<span style="color: #666666">1</span>]) <span style="color: #666666"><</span> <span style="color: #666666">1E-3</span>)
|
|
|
+ omega <span style="color: #666666">=</span> u[:,<span style="color: #666666">0</span>]
|
|
|
+ theta <span style="color: #666666">=</span> u[:,<span style="color: #666666">1</span>]
|
|
|
+ S <span style="color: #666666">=</span> omega<span style="color: #666666">**2</span> <span style="color: #666666">+</span> np<span style="color: #666666">.</span>cos(theta)
|
|
|
+ drag <span style="color: #666666">=</span> <span style="color: #666666">-</span>alpha<span style="color: #666666">*</span>np<span style="color: #666666">.</span>abs(omega)<span style="color: #666666">*</span>omega
|
|
|
+ <span style="color: #008000; font-weight: bold">return</span> t, theta, omega, S, drag
|
|
|
+</pre></div>
|
|
|
+
|
|
|
+<h3 id="___sec15">Animation </h3>
|
|
|
+
|
|
|
+<p>
|
|
|
+We can finally traverse the time array and draw a body diagram
|
|
|
+at each time level. The resulting sketches are saved to files
|
|
|
+<code>tmp_%04d.png</code>, and these files can be combined to videos:
|
|
|
+
|
|
|
+<p>
|
|
|
+
|
|
|
+<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
|
+<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">animate</span>():
|
|
|
+ <span style="color: #408080; font-style: italic"># Clean up old plot files</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">os</span><span style="color: #666666">,</span> <span style="color: #0000FF; font-weight: bold">glob</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">for</span> filename <span style="color: #AA22FF; font-weight: bold">in</span> glob<span style="color: #666666">.</span>glob(<span style="color: #BA2121">'tmp_*.png'</span>) <span style="color: #666666">+</span> glob<span style="color: #666666">.</span>glob(<span style="color: #BA2121">'movie.*'</span>):
|
|
|
+ os<span style="color: #666666">.</span>remove(filename)
|
|
|
+ <span style="color: #408080; font-style: italic"># Solve problem</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">math</span> <span style="color: #008000; font-weight: bold">import</span> pi, radians, degrees
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
|
|
+ alpha <span style="color: #666666">=</span> <span style="color: #666666">0.4</span>
|
|
|
+ period <span style="color: #666666">=</span> <span style="color: #666666">2*</span>pi
|
|
|
+ T <span style="color: #666666">=</span> <span style="color: #666666">12*</span>period
|
|
|
+ dt <span style="color: #666666">=</span> period<span style="color: #666666">/40</span>
|
|
|
+ a <span style="color: #666666">=</span> <span style="color: #666666">70</span>
|
|
|
+ theta0 <span style="color: #666666">=</span> radians(a)
|
|
|
+ t, theta, omega, S, drag <span style="color: #666666">=</span> simulate_pendulum(alpha, theta0, dt, T)
|
|
|
+ mg <span style="color: #666666">=</span> np<span style="color: #666666">.</span>ones(S<span style="color: #666666">.</span>size)
|
|
|
+ <span style="color: #408080; font-style: italic"># Visualize drag force 5 times as large</span>
|
|
|
+ drag <span style="color: #666666">*=</span> <span style="color: #666666">5</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'NOTE: drag force magnified 5 times!!'</span>)
|
|
|
+
|
|
|
+ <span style="color: #408080; font-style: italic"># Draw animation</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">time</span>
|
|
|
+ <span style="color: #008000; font-weight: bold">for</span> time_level, t_ <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">enumerate</span>(t):
|
|
|
+ pendulum(theta, S, mg, drag, t_, time_level)
|
|
|
+ time<span style="color: #666666">.</span>sleep(<span style="color: #666666">0.2</span>)
|
|
|
+
|
|
|
+ <span style="color: #408080; font-style: italic"># Make videos</span>
|
|
|
+ prog <span style="color: #666666">=</span> <span style="color: #BA2121">'ffmpeg'</span>
|
|
|
+ filename <span style="color: #666666">=</span> <span style="color: #BA2121">'tmp_</span><span style="color: #BB6688; font-weight: bold">%04d</span><span style="color: #BA2121">.png'</span>
|
|
|
+ fps <span style="color: #666666">=</span> <span style="color: #666666">6</span>
|
|
|
+ codecs <span style="color: #666666">=</span> {<span style="color: #BA2121">'flv'</span>: <span style="color: #BA2121">'flv'</span>, <span style="color: #BA2121">'mp4'</span>: <span style="color: #BA2121">'libx264'</span>,
|
|
|
+ <span style="color: #BA2121">'webm'</span>: <span style="color: #BA2121">'libvpx'</span>, <span style="color: #BA2121">'ogg'</span>: <span style="color: #BA2121">'libtheora'</span>}
|
|
|
+ <span style="color: #008000; font-weight: bold">for</span> ext <span style="color: #AA22FF; font-weight: bold">in</span> codecs:
|
|
|
+ lib <span style="color: #666666">=</span> codecs[ext]
|
|
|
+ cmd <span style="color: #666666">=</span> <span style="color: #BA2121">'</span><span style="color: #BB6688; font-weight: bold">%(prog)s</span><span style="color: #BA2121"> -i </span><span style="color: #BB6688; font-weight: bold">%(filename)s</span><span style="color: #BA2121"> -r </span><span style="color: #BB6688; font-weight: bold">%(fps)s</span><span style="color: #BA2121"> '</span> <span style="color: #666666">%</span> <span style="color: #008000">vars</span>()
|
|
|
+ cmd <span style="color: #666666">+=</span> <span style="color: #BA2121">'-vcodec </span><span style="color: #BB6688; font-weight: bold">%(lib)s</span><span style="color: #BA2121"> movie.</span><span style="color: #BB6688; font-weight: bold">%(ext)s</span><span style="color: #BA2121">'</span> <span style="color: #666666">%</span> <span style="color: #008000">vars</span>()
|
|
|
+ <span style="color: #008000; font-weight: bold">print</span>(cmd)
|
|
|
+ os<span style="color: #666666">.</span>system(cmd)
|
|
|
+</pre></div>
|
|
|
+<p>
|
|
|
+
|
|
|
+<div>
|
|
|
+<video loop controls width='640' height='365' preload='none'>
|
|
|
+ <source src='https://github.com/hplgit/pysketcher/raw/master/doc/pub/tutorial/mov-tut/pendulum/movie.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
|
|
|
+ <source src='https://github.com/hplgit/pysketcher/raw/master/doc/pub/tutorial/mov-tut/pendulum/movie.webm' type='video/webm; codecs="vp8, vorbis"'>
|
|
|
+ <source src='https://github.com/hplgit/pysketcher/raw/master/doc/pub/tutorial/mov-tut/pendulum/movie.ogg' type='video/ogg; codecs="theora, vorbis"'>
|
|
|
+</video>
|
|
|
+</div>
|
|
|
+<p><em>The drag force is magnified 5 times (compared to \( mg \) and \( S \)!</em></p>
|
|
|
+
|
|
|
+<!-- Issue warning if in a Safari browser -->
|
|
|
+<script language="javascript">
|
|
|
+if (!!(window.safari)) {
|
|
|
+ document.write("<div style=\"width: 95%%; padding: 10px; border: 1px solid #100; border-radius: 4px;\"><p><font color=\"red\">The above movie will not play in Safari - use Chrome, Firefox, or Opera.</font></p></div>")}
|
|
|
+</script>
|
|
|
|
|
|
<p>
|
|
|
<p>
|