docs: Update Kinematics.md document with "smooth pressure advance"

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-12-13 16:51:45 -05:00
parent 91bade5824
commit 1d05a34cd7
7 changed files with 169 additions and 410 deletions

View File

@ -264,35 +264,36 @@ through the nozzle orifice (as in
key idea is that the relationship between filament, pressure, and flow key idea is that the relationship between filament, pressure, and flow
rate can be modeled using a linear coefficient: rate can be modeled using a linear coefficient:
``` ```
stepper_position = requested_e_position + pressure_advance_coefficient * nominal_extruder_velocity pa_position = nominal_position + pressure_advance_coefficient * nominal_velocity
``` ```
See the [pressure advance](Pressure_Advance.md) document for See the [pressure advance](Pressure_Advance.md) document for
information on how to find this pressure advance coefficient. information on how to find this pressure advance coefficient.
Once configured, Klipper will push in an additional amount of filament The basic pressure advance formula can cause the extruder motor to
during acceleration. The higher the desired filament flow rate, the make sudden velocity changes. Klipper implements "smoothing" of the
more filament must be pushed in during acceleration to account for extruder movement to avoid this.
pressure. During head deceleration the extra filament is retracted
(the extruder will have a negative velocity).
![pressure-advance](img/pressure-advance.svg.png) ![pressure-advance](img/pressure-velocity.png)
One may notice that the pressure advance algorithm can cause the The above graph shows an example of two extrusion moves with a
extruder motor to make sudden velocity changes. This is tolerated non-zero cornering velocity between them. Note that the pressure
based on the idea that the majority of the inertia in the system is in advance system causes additional filament to be pushed into the
changing the extruder pressure. As long as the extruder pressure does extruder during acceleration. The higher the desired filament flow
not change rapidly the sudden changes in extruder motor velocity are rate, the more filament must be pushed in during acceleration to
tolerated. account for pressure. During head deceleration the extra filament is
retracted (the extruder will have a negative velocity).
One area where sudden velocity changes become problematic is during The "smoothing" is implemented by averaging the extruder position over
small changes in head speed due to cornering. a small time period (as specified by the
`pressure_advance_smooth_time` config parameter). This averaging can
span multiple g-code moves. Note how the extruder motor will start
moving prior to the nominal start of the first extrusion move and will
continue to move after the nominal end of the last extrusion move.
![pressure-cornering](img/pressure-cornering.svg.png) Key formula for "smoothed pressure advance":
```
To prevent this, the Klipper pressure advance code utilizes the move smooth_pa_position(t) =
look-ahead queue to detect intermittent speed changes. During a ( definitive_integral(pa_position, from=t-smooth_time/2, to=t+smooth_time/2)
deceleration event the code finds the maximum upcoming head speed / smooth_time )
within a configurable time window. The pressure is then only adjusted ```
to this found maximum. This can greatly reduce (or even completely
eliminate) pressure changes during cornering.

View File

@ -1,207 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="102.61139mm"
height="99.266594mm"
viewBox="0 0 363.58366 351.73204"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pressure-advance.svg"
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/pressure-advance.svg.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.97968464"
inkscape:cx="147.06528"
inkscape:cy="169.55487"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="419"
inkscape:window-y="273"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
showborder="false"
inkscape:snap-global="false"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid3436"
originx="17.089787"
originy="126.61899" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.13451,-140.19216)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 150.47693,249.82417 0.58688,123.9666 m 0,-21.42857 327.12765,-0.53192 -7.97871,5.85107"
id="path3347"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-334.86746"
y="122.91875"
id="text3353"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12816"
x="-334.86746"
y="122.91875">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12818"
x="-334.86746"
y="138.54375">velocity</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 150,250.23455 -5.31915,8.51063"
id="path3359"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 316.60647,311.78473 16.53759,62.00711 m -154.57776,-52.12767 16.05677,-60.94328 1.06383,29.78724 m 0,0 120.91957,-1.06383 0,22.34043"
id="path3361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-237.05733"
y="140.25932"
id="text3353-2"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12733-6"
x="-237.05733"
y="140.25932">head velocity</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 -5.31915,8.51063"
id="path3359-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 178.3809,241.67403 16.05679,-60.94329 120.91958,-1.06383 16.53759,62.00712"
id="path3361-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.78742969px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 331.74721,241.47248 16.72764,-63.00288 133.24332,0"
id="path3361-7-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="198.86868"
y="174.67674"
id="text12656-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12658-8"
x="198.86868"
y="174.67674">extrude move</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="355.25165"
y="173.61293"
id="text12660-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12662-2"
x="355.25165"
y="173.61293">non-extrude move</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 151.94226,384.0742 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-467.65732"
y="122.73453"
id="text3353-1"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12868"
x="-467.65732"
y="122.73453">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12870"
x="-467.65732"
y="138.35953">pressure</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 151.94226,384.0742 -5.31915,8.51063"
id="path3359-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 181.57239,485.29107 16.05679,-60.94329 120.91958,-1.06383 16.53759,62.00712"
id="path3361-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:100%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="438.03586"
y="499.53384"
id="text3349"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="438.03586"
y="499.53384">time</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,180 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="102.04809mm"
height="61.494076mm"
viewBox="0 0 361.58771 217.8924"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pressure-cornering.svg"
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/pressure-cornering.svg.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98"
inkscape:cx="110.74341"
inkscape:cy="35.715236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="656"
inkscape:window-y="0"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
showborder="false"
inkscape:snap-global="false"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid3436"
originx="17.089805"
originy="-7.2206491" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.13449,-140.19216)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 150,250.23455 1.06383,102.12765 327.12765,-0.53192 -7.97871,5.85107"
id="path3347"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-334.86746"
y="122.91875"
id="text3353"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12816"
x="-334.86746"
y="122.91875">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12818"
x="-334.86746"
y="138.54375">velocity</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 150,250.23455 -5.31915,8.51063"
id="path3359"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 178.5663,321.66417 16.05677,-60.94328 1.06383,29.78724 m 0,0 117.21969,-0.77616 5.99519,7.3871 5.9952,-6.89861 131.50541,-0.77616"
id="path3361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-237.05733"
y="140.25932"
id="text3353-2"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12733-6"
x="-237.05733"
y="140.25932">head velocity</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 -5.31915,8.51063"
id="path3359-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 178.3809,241.67403 16.05679,-60.94329 120.91958,-1.06383 4.29269,10.98671"
id="path3361-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 319.50231,193.5133 4.48274,-15.0437 133.24332,0"
id="path3361-7-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="198.86868"
y="174.67674"
id="text12656-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12891"
x="198.86868"
y="174.67674">first extrude</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="355.25165"
y="173.61293"
id="text12660-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12893"
x="355.25165"
y="173.61293">second extrude</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 2, 1, 2;stroke-dashoffset:0;stroke-opacity:1"
d="m 314.05288,288.86296 0,17.34694 5.10204,17.34694 -1.02041,-48.97959 7.14286,-17.34694 0,31.63265"
id="path12895"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:100%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="435.80841"
y="366.8262"
id="text3349"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="435.80841"
y="366.8262">time</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

145
scripts/graph_extruder.py Executable file
View File

@ -0,0 +1,145 @@
#!/usr/bin/env python2
# Generate extruder pressure advance motion graphs
#
# Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import math, optparse, datetime
import matplotlib
SEG_TIME = .000100
INV_SEG_TIME = 1. / SEG_TIME
######################################################################
# Basic trapezoid motion
######################################################################
# List of moves: [(start_v, end_v, move_t), ...]
Moves = [
(0., 0., .200),
(0., 100., None), (100., 100., .200), (100., 60., None),
(60., 100., None), (100., 100., .200), (100., 0., None),
(0., 0., .300)
]
EXTRUDE_R = (.4 * .4 * .75) / (math.pi * (1.75 / 2.)**2)
ACCEL = 3000. * EXTRUDE_R
def gen_positions():
out = []
start_d = start_t = t = 0.
for start_v, end_v, move_t in Moves:
start_v *= EXTRUDE_R
end_v *= EXTRUDE_R
if move_t is None:
move_t = abs(end_v - start_v) / ACCEL
half_accel = 0.
if end_v > start_v:
half_accel = .5 * ACCEL
elif start_v > end_v:
half_accel = -.5 * ACCEL
end_t = start_t + move_t
while t <= end_t:
rel_t = t - start_t
out.append(start_d + (start_v + half_accel * rel_t) * rel_t)
t += SEG_TIME
start_d += (start_v + half_accel * move_t) * move_t
start_t = end_t
return out
def gen_deriv(data):
return [0.] + [(data[i+1] - data[i]) * INV_SEG_TIME
for i in range(len(data)-1)]
def time_to_index(t):
return int(t * INV_SEG_TIME + .5)
######################################################################
# Pressure advance
######################################################################
PA_HALF_SMOOTH_T = .040 / 2.
PRESSURE_ADVANCE = .045
def calc_pa_raw(t, positions):
pa = PRESSURE_ADVANCE * INV_SEG_TIME
i = time_to_index(t)
return positions[i] + pa * (positions[i+1] - positions[i])
def calc_pa_smooth(t, positions):
start_index = time_to_index(t - PA_HALF_SMOOTH_T) + 1
end_index = time_to_index(t + PA_HALF_SMOOTH_T)
pa = PRESSURE_ADVANCE * INV_SEG_TIME
pa_data = [positions[i] + pa * (positions[i+1] - positions[i])
for i in range(start_index, end_index)]
return sum(pa_data) / (end_index - start_index)
######################################################################
# Plotting and startup
######################################################################
MARGIN_TIME = 0.100
def plot_motion():
# Nominal motion
positions = gen_positions()
drop = int(MARGIN_TIME * INV_SEG_TIME)
times = [SEG_TIME * t for t in range(len(positions))][drop:-drop]
velocities = gen_deriv(positions[drop:-drop])
# Motion with pressure advance
pa_positions = [calc_pa_raw(t, positions) for t in times]
pa_velocities = gen_deriv(pa_positions)
# Smoothed motion
sm_positions = [calc_pa_smooth(t, positions) for t in times]
sm_velocities = gen_deriv(sm_positions)
# Build plot
shift_times = [t - MARGIN_TIME for t in times]
fig, ax1 = matplotlib.pyplot.subplots(nrows=1, sharex=True)
ax1.set_title("Extruder Velocity")
ax1.set_ylabel('Velocity (mm/s)')
pa_plot, = ax1.plot(shift_times, pa_velocities, 'r',
label='Pressure Advance', alpha=0.3)
nom_plot, = ax1.plot(shift_times, velocities, 'black', label='Nominal')
sm_plot, = ax1.plot(shift_times, sm_velocities, 'g', label='Smooth PA',
alpha=0.9)
fontP = matplotlib.font_manager.FontProperties()
fontP.set_size('x-small')
ax1.legend(handles=[nom_plot, pa_plot, sm_plot], loc='best', prop=fontP)
ax1.set_xlabel('Time (s)')
ax1.grid(True)
fig.tight_layout()
return fig
def setup_matplotlib(output_to_file):
global matplotlib
if output_to_file:
matplotlib.rcParams.update({'figure.autolayout': True})
matplotlib.use('Agg')
import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager
import matplotlib.ticker
def main():
# Parse command-line arguments
usage = "%prog [options]"
opts = optparse.OptionParser(usage)
opts.add_option("-o", "--output", type="string", dest="output",
default=None, help="filename of output graph")
options, args = opts.parse_args()
if len(args) != 0:
opts.error("Incorrect number of arguments")
# Draw graph
setup_matplotlib(options.output is not None)
fig = plot_motion()
# Show graph
if options.output is None:
matplotlib.pyplot.show()
else:
fig.set_size_inches(6, 2.5)
fig.savefig(options.output)
if __name__ == '__main__':
main()