1 from __future__
import division, absolute_import
5 from coordConv
import PVT
7 from .trapSlew
import trapSlew
9 def fullSlew(pA, vA, pB, vB, tJerk, vMax, aMax):
10 """!Compute a jerk-limited trapezoidal slew
13 @param[in] pA dp position of starting point at time t = 0 (deg)
14 @param[in] vA dp velocity of starting point at time t = 0 (deg/sec)
15 @param[in] pB dp position of ending point at time t = 0 (deg)
16 @param[in] vB dp velocity of ending point at time t = 0 (deg/sec)
17 @param[in] tJerk dp sets maximum allowed jerk and minimum slew duration (deg/sec^3)
18 (see Details for more information)
19 @param[in] vMax dp maximum allowed |velocity| (deg/sec)
20 @param[in] aMax dp maximum allowed |acceleration| (deg/sec^2)
22 @return pvtList: a list of approximately 8 PVTs; the time of the first one is 0
24 @throw RuntimeError if cannot compute a slew
26 @warning: |vA| must be <= vMax, |vB| must be some margin less than vMax.
27 See tcc.mov.trapSlew for details.
30 tJerk sets the maximum jerk and minimum duration of slew as follows:
32 - minimum duration of slew = tJerk
34 Here is how the subroutine works:
36 First a trapezoidal slew is computed, with several special characterstics:
37 - it begins a short time ("tJerk / 2") after 0
38 - the duration of its constant-velocity segment is at least "tJerk"
39 - the maximum possible acceleration ("aMax") is used for both constant
40 acceleration segments.
42 The resulting trapezoidal slew is then "rounded" to give jerk limiting,
44 - Rounding extends for a time (tJerk / 2) (or less if required)
45 symmetrically to both sides of each trapezoidal slew node.
46 - The rounded segments are paths of constant jerk.
47 This process does not affect the total area under the v vs. t curve,
48 hence the total distance travelled remains unchanged.
50 Trapezoidal slews, and possibly jerk-limiting, are discussed further
51 in my orange notebook.
53 Note: most of the equations used below are less algebraically
54 straightforward than is possible. They have been processed to
55 reduce accumulated error and limit the number of intermediate variables.
56 For example, expressions such as j = a / dt are used to eliminate
57 explicit reference to jerk.
60 2013-12-06 ROwen Converted from mov_fullSlew.for
62 def reportBug(msgStr):
63 """!Write a detailed message to stderr and raise RuntimeError"""
64 sys.stderr.write(msgStr +
"\n")
65 sys.stderr.write(
"fullSlew(pA=%s; pB=%s; vA=%s; vB=%s, tJerk=%s, vMax=%s; aMax=%s)\n" % \
66 (pA, pB, vA, vB, tJerk, vMax, aMax))
67 raise RuntimeError(msgStr)
73 rBAi = (pB + vB * tJerk / 2) - (pA + vA * tJerk / 2)
75 ts =
trapSlew(rBAi=rBAi, vA=vA, vB=vB, dt2min=tJerk, vMax=vMax, aMax=aMax)
80 t_end = tJerk + ts.dt1 + ts.dt2 + ts.dt3
81 p_end = pB + vB * t_end
83 t_cv1 = tJerk + ts.dt1
85 p_cv1 = pA + (tJerk + ts.dt1) * (vA + ts.vP) / 2
88 t_cv1 = tJerk + ts.dt1
89 t_cv2 = t_end - (tJerk + ts.dt3)
90 p_cv1 = pA + (tJerk + ts.dt1) * (vA + ts.vP) / 2
91 p_cv2 = p_end - (tJerk + ts.dt3) * (ts.vP + vB) / 2
93 reportBug(
"Bug! Trapezoidal constant-velocity segement too brief: ts.dt2=%s, tJerk=%s" % (ts.dt2, tJerk))
100 pvtList.append(PVT(pA, vA, 0))
108 ((pA + p_cv1) / 2) + ((tJerk + ts.dt1) * (vA - ts.vP) / 6),
114 pA + tJerk * (vA + tJerk * (ts.a1 / 6)),
115 vA + (tJerk / 2) * ts.a1,
119 p_cv1 - tJerk * (ts.vP - tJerk * (ts.a1 / 6)),
120 ts.vP - (tJerk / 2) * ts.a1,
152 ((p_cv2 + p_end) / 2) + ((tJerk + ts.dt3) * (ts.vP - vB) / 6),
158 p_cv2 + tJerk * (ts.vP + tJerk * (ts.a3 / 6)),
159 ts.vP + (tJerk / 2) * ts.a3,
163 p_end - tJerk * (vB - tJerk * (ts.a3 / 6)),
164 vB - (tJerk / 2) * ts.a3,
def trapSlew
Compute a trapezoidal slew.
def fullSlew
Compute a jerk-limited trapezoidal slew.