James Kuszmaul | b13e13f | 2023-11-22 20:44:04 -0800 | [diff] [blame^] | 1 | from sympy import * |
| 2 | from sympy.logic.boolalg import * |
| 3 | |
| 4 | init_printing() |
| 5 | |
| 6 | U, A, B, t, x0, xf, v0, vf, c1, c2, v, V, kV, kA = symbols( |
| 7 | "U, A, B t, x0, xf, v0, vf, C1, C2, v, V, kV, kA" |
| 8 | ) |
| 9 | |
| 10 | x = symbols("x", cls=Function) |
| 11 | |
| 12 | # Exponential profiles are derived from a differential equation: ẍ - A * ẋ = B * U |
| 13 | diffeq = Eq(x(t).diff(t, t) - A * x(t).diff(t), B * U) |
| 14 | |
| 15 | x = dsolve(diffeq).rhs |
| 16 | dx = x.diff(t) |
| 17 | |
| 18 | x = x.subs( |
| 19 | [ |
| 20 | (c1, solve(Eq(x.subs(t, 0), x0), c1)[0]), |
| 21 | (c2, solve(Eq(dx.subs(t, 0), v0), c2)[0]), |
| 22 | ] |
| 23 | ) |
| 24 | |
| 25 | print(f"General Solution: {x}") |
| 26 | |
| 27 | # We need two specific solutions to this equation for an Exponential Profile: |
| 28 | # One that passes through (x0, v0) and has input U |
| 29 | # Another that passes through (xf, vf) and has input -U |
| 30 | |
| 31 | # x1 is for the accelerate step |
| 32 | x1 = x.subs({x0: x0, v0: v0, U: U}) |
| 33 | |
| 34 | dx1 = x1.diff(t) |
| 35 | t1_eqn = solve(Eq(dx1, v), t)[0] |
| 36 | # x1 in phase space (input v, output x) |
| 37 | x1_ps = x1.subs(t, t1_eqn) |
| 38 | |
| 39 | |
| 40 | # x2 is for the decelerate step |
| 41 | x2 = x.subs({x0: xf, v0: vf, U: -U}) |
| 42 | |
| 43 | dx2 = x2.diff(t) |
| 44 | t2_eqn = solve(Eq(dx2, v), t)[0] |
| 45 | # x2 in phase space (input v, output x) |
| 46 | x2_ps = x2.subs(t, t2_eqn) |
| 47 | |
| 48 | # The point at which we switch from input U to -U is the inflection point. |
| 49 | # In phase space, this is a point (x, v) where x1(v) = x2(v) |
| 50 | # For now, we will just solve for +U and assume inflection velocity is positive. |
| 51 | # The other possible solutions are -v_soln, and the solutions to v_equality.subs(U, -U) |
| 52 | equality = simplify(Eq(x1_ps, x2_ps).expand()).expand() |
| 53 | equality = Eq(equality.lhs - x0 + v0 / A - v / A, equality.rhs - x0 + v0 / A - v / A) |
| 54 | equality = Eq( |
| 55 | equality.lhs |
| 56 | - B * U * log(A * v / (A * vf - B * U) - B * U / (A * vf - B * U)) / A**2, |
| 57 | equality.rhs |
| 58 | - B * U * log(A * v / (A * vf - B * U) - B * U / (A * vf - B * U)) / A**2, |
| 59 | ) |
| 60 | equality = Eq(equality.lhs / (-B * U / A / A), equality.rhs / (-B * U / A / A)) |
| 61 | equality = Eq(exp(equality.lhs.simplify()), exp(equality.rhs.simplify())) |
| 62 | equality = Eq( |
| 63 | equality.lhs * (A * v0 + B * U) * (A * vf - B * U), |
| 64 | equality.rhs * (A * v0 + B * U) * (A * vf - B * U), |
| 65 | ) |
| 66 | equality = Eq(-equality.lhs.expand() + equality.rhs, 0) |
| 67 | |
| 68 | # This is a quadratic equation of the form ax^2 + c = 0 |
| 69 | v_equality = equality |
| 70 | |
| 71 | # solve, take positive result |
| 72 | v_soln = solve(v_equality, v)[0] |
| 73 | |
| 74 | # With this information, we can calculate the inflection point (x, v) |
| 75 | # and calculate the times that x1 and x2 reach the inflection point |
| 76 | inflection_x = x1_ps.subs(v, v_soln) |
| 77 | inflection_t1 = t1_eqn.subs(v, v_soln) |
| 78 | inflection_t2 = t2_eqn.subs(v, v_soln) |
| 79 | |
| 80 | # inflection_t2 < 0 because in order for the profile to get to |
| 81 | # the inflection point from the terminal state, it must go back in time. |
| 82 | totalTime = inflection_t1 - inflection_t2 |
| 83 | |
| 84 | print(f"x1: {expand(simplify(x1))}") |
| 85 | print(f"x2: {expand(simplify(x2))}") |
| 86 | print(f"dx1: {expand(simplify(dx1))}") |
| 87 | print(f"dx2: {expand(simplify(dx2))}") |
| 88 | print(f"t1: {expand(simplify(t1_eqn))}") |
| 89 | print(f"t2: {expand(simplify(t2_eqn))}") |
| 90 | print(f"x1 phase space: {expand(simplify(x1.subs(t, t1_eqn)))}") |
| 91 | print(f"x2 phase space: {expand(simplify(x2.subs(t, t2_eqn)))}") |
| 92 | print(f"vi equality: {v_equality}") |
| 93 | |
| 94 | |
| 95 | a, b, c, d = symbols("a, b, c, d") |
| 96 | |
| 97 | expression = SOPform([a, b, c, d], minterms=[0, 4, 5, 8, 10, 12, 13, 14]) |
| 98 | print(f"Truth Table Expression: {expression}") |