blob: cc8fbc06ccab43ef786af46f555c7894079f429b [file] [log] [blame]
James Kuszmaulb13e13f2023-11-22 20:44:04 -08001from sympy import *
2from sympy.logic.boolalg import *
3
4init_printing()
5
6U, 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
10x = symbols("x", cls=Function)
11
12# Exponential profiles are derived from a differential equation: ẍ - A * ẋ = B * U
13diffeq = Eq(x(t).diff(t, t) - A * x(t).diff(t), B * U)
14
15x = dsolve(diffeq).rhs
16dx = x.diff(t)
17
18x = 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
25print(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
32x1 = x.subs({x0: x0, v0: v0, U: U})
33
34dx1 = x1.diff(t)
35t1_eqn = solve(Eq(dx1, v), t)[0]
36# x1 in phase space (input v, output x)
37x1_ps = x1.subs(t, t1_eqn)
38
39
40# x2 is for the decelerate step
41x2 = x.subs({x0: xf, v0: vf, U: -U})
42
43dx2 = x2.diff(t)
44t2_eqn = solve(Eq(dx2, v), t)[0]
45# x2 in phase space (input v, output x)
46x2_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)
52equality = simplify(Eq(x1_ps, x2_ps).expand()).expand()
53equality = Eq(equality.lhs - x0 + v0 / A - v / A, equality.rhs - x0 + v0 / A - v / A)
54equality = 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)
60equality = Eq(equality.lhs / (-B * U / A / A), equality.rhs / (-B * U / A / A))
61equality = Eq(exp(equality.lhs.simplify()), exp(equality.rhs.simplify()))
62equality = Eq(
63 equality.lhs * (A * v0 + B * U) * (A * vf - B * U),
64 equality.rhs * (A * v0 + B * U) * (A * vf - B * U),
65)
66equality = Eq(-equality.lhs.expand() + equality.rhs, 0)
67
68# This is a quadratic equation of the form ax^2 + c = 0
69v_equality = equality
70
71# solve, take positive result
72v_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
76inflection_x = x1_ps.subs(v, v_soln)
77inflection_t1 = t1_eqn.subs(v, v_soln)
78inflection_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.
82totalTime = inflection_t1 - inflection_t2
83
84print(f"x1: {expand(simplify(x1))}")
85print(f"x2: {expand(simplify(x2))}")
86print(f"dx1: {expand(simplify(dx1))}")
87print(f"dx2: {expand(simplify(dx2))}")
88print(f"t1: {expand(simplify(t1_eqn))}")
89print(f"t2: {expand(simplify(t2_eqn))}")
90print(f"x1 phase space: {expand(simplify(x1.subs(t, t1_eqn)))}")
91print(f"x2 phase space: {expand(simplify(x2.subs(t, t2_eqn)))}")
92print(f"vi equality: {v_equality}")
93
94
95a, b, c, d = symbols("a, b, c, d")
96
97expression = SOPform([a, b, c, d], minterms=[0, 4, 5, 8, 10, 12, 13, 14])
98print(f"Truth Table Expression: {expression}")