Advertisement
575

Untitled

575
May 13th, 2025 (edited)
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.41 KB | None | 0 0
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3.  
  4. P1 = np.array([0.17,    0.0866])
  5. P2 = np.array([0.16933, 0.08586])
  6.  
  7. r0      = np.linalg.norm(P1 - P2)
  8. epsilon = r0 / 2
  9. theta0  = np.arctan2(P1[1] - P2[1], P1[0] - P2[0])
  10. Theta   = np.pi
  11.  
  12. theta_star = Theta * (1 - epsilon / r0)
  13. thetas     = np.linspace(0, theta_star, 500)
  14. rs         = r0 * (1 - thetas / Theta)
  15. angles     = theta0 + thetas
  16. xs_spiral  = P2[0] + rs * np.cos(angles)
  17. ys_spiral  = P2[1] + rs * np.sin(angles)
  18.  
  19. P_entry = np.array([xs_spiral[-1], ys_spiral[-1]])
  20. print("P_entry (вход в ε-окрестность):", P_entry)
  21.  
  22. v = P2 - P1
  23. L = np.linalg.norm(v)
  24. u = v / L
  25.  
  26. n = np.array([v[1], -v[0]])
  27. n = n / np.linalg.norm(n)
  28.  
  29. s2 = 1.0
  30. y_end = P2[1] - 1.5 * r0
  31. s_end = (y_end - P1[1]) / v[1]
  32.  
  33. a = 0.02 * r0
  34.  
  35. N = 400
  36. s_all = np.linspace(0.0, s_end, N)
  37.  
  38. xs_curve = np.zeros_like(s_all)
  39. ys_curve = np.zeros_like(s_all)
  40.  
  41. for i, s in enumerate(s_all):
  42.     base_pt = P1 + s * v
  43.     if s <= s2:
  44.         offset = 0.0
  45.     else:
  46.         offset = a * ((s - s2) / (s_end - s2))
  47.     xs_curve[i] = base_pt[0] + offset * n[0]
  48.     ys_curve[i] = base_pt[1] + offset * n[1]
  49.  
  50. idx_P2 = np.argmin(np.abs(s_all - s2))
  51. P2_from_curve = np.array([xs_curve[idx_P2], ys_curve[idx_P2]])
  52.  
  53. dists = np.sqrt((xs_curve - P_entry[0])**2 + (ys_curve - P_entry[1])**2)
  54.  
  55. target = 2 * epsilon
  56. idx_mark = np.argmin(np.abs(dists - target))
  57.  
  58. X_mark = xs_curve[idx_mark]
  59. Y_mark = ys_curve[idx_mark]
  60.  
  61. fig, ax = plt.subplots(figsize=(6, 6))
  62.  
  63. # 4.1. Спираль (черная)
  64. ax.plot(xs_spiral, ys_spiral, 'k-', linewidth=2)
  65. ax.scatter(*P1, color='k', s=50)
  66. ax.scatter(*P_entry, color='orange', s=50)
  67. ax.scatter(*P2, color='r', s=30)
  68. circle = plt.Circle(P2, epsilon, edgecolor='r', facecolor='none', linewidth=2)
  69. ax.add_patch(circle)
  70.  
  71. ax.plot(xs_curve, ys_curve, 'b--', linewidth=2)
  72.  
  73. ax.scatter(X_mark, Y_mark, color='magenta', s=60, marker='o')
  74.  
  75. ax.set_aspect('equal', 'box')
  76. ax.set_xlim(P2[0] - r0 * 1.1, P2[0] + r0 * 1.1)
  77. ax.set_ylim(P2[1] - r0 * 1.1, P2[1] + r0 * 1.1)
  78.  
  79. ax.set_xlabel('X (м)')
  80. ax.set_ylabel('Y (м)')
  81. ax.grid(True)
  82.  
  83. plt.show()
  84.  
  85. import sympy as sp
  86.  
  87. t = sp.symbols('t')
  88. v1, v2 = sp.Function('v1')(t), sp.Function('v2')(t)
  89. w1, w2 = sp.Function('w1')(t), sp.Function('w2')(t)
  90.  
  91. a2, k1, k2, m1, m2, g, Theta1 = sp.symbols('a2 k1 k2 m1 m2 g Theta1')
  92. dot_v1 = sp.diff(v1, t)
  93. dot_v2 = sp.diff(v2, t)
  94.  
  95. a11 = m1 * (k1 - a2)**2 + m2 * (k1**2 + 2 * k1 * k2 * sp.sin(v2))
  96. a12 = m2 * (k2**2 + k1 * k2 * sp.sin(v2))
  97. a22 = m2 * k2**2
  98. A = sp.Matrix([[a11, a12], [a12, a22]])
  99. v = sp.Matrix([dot_v1, dot_v2])
  100. T = sp.simplify((1/2) * v.T * A * v)[0]
  101.  
  102. P = g * (m1 * (k1 - a2) * sp.sin(v1) + m2 * (k1 * sp.sin(Theta1) - k2 * sp.cos(v1 + v2)))
  103.  
  104. L = sp.simplify(T - P)
  105.  
  106. dL_ddotv1 = sp.diff(L, dot_v1).simplify()
  107. ddt_dL_ddotv1 = sp.diff(dL_ddotv1, t).simplify()
  108. dL_dv1 = sp.diff(L, v1).simplify()
  109. EL_v1 = sp.simplify(ddt_dL_ddotv1 - dL_dv1)
  110.  
  111. dL_ddotv2 = sp.diff(L, dot_v2).simplify()
  112. ddt_dL_ddotv2 = sp.diff(dL_ddotv2, t).simplify()
  113. dL_dv2 = sp.diff(L, v2).simplify()
  114. EL_v2 = sp.simplify(ddt_dL_ddotv2 - dL_dv2)
  115.  
  116. print("Euler-Lagrange eq. for v1:")
  117. print(sp.latex(EL_v1))
  118. print("\nEuler-Lagrange eq. for v2:")
  119. print(sp.latex(EL_v2))
  120.  
  121. L1_dep, d1_dep, a1_dep, L2_dep, d2_dep, a2_dep = sp.symbols('L1_dep d1_dep a1_dep L2_dep d2_dep a2_dep')
  122.  
  123. B11 = sp.simplify(L1_dep*(d1_dep*sp.sin(w1 - v1) - a1_dep*sp.cos(v1)) / (d1_dep*(L1_dep*sp.sin(w1 - v1) - a1_dep*sp.cos(w1))))
  124. B22 = sp.simplify(L2_dep*(d2_dep*sp.sin(w2 - v2) - a2_dep*sp.cos(v2)) / (d2_dep*(L2_dep*sp.sin(w2 - v2) - a2_dep*sp.cos(w2))))
  125.  
  126. eq_w1 = sp.Eq(sp.diff(w1, t), B11 * dot_v1)
  127. eq_w2 = sp.Eq(sp.diff(w2, t), B22 * dot_v2)
  128.  
  129. print("\nKinematic constraint for w1:")
  130. sp.pprint(eq_w1)
  131. print("\nKinematic constraint for w2:")
  132. sp.pprint(eq_w2)
  133.  
  134.  
  135. b1, b2, i1, i2 = sp.symbols('b1 b2 i1 i2')
  136. k2_1, k2_2 = sp.symbols('k2_1 k2_2')
  137. Q_w1 = sp.simplify(-b1 * B11 * dot_v1 + k2_1 * i1)
  138. Q_w2 = sp.simplify(-b2 * B22 * dot_v2 + k2_2 * i2)
  139.  
  140. Q_s = sp.Matrix([Q_w1, Q_w2])
  141.  
  142. B_mat = sp.diag(B11, B22)
  143.  
  144. rhs_EL = sp.simplify(B_mat.T * Q_s)
  145.  
  146. eq_v1 = sp.Eq(EL_v1, rhs_EL[0])
  147. eq_v2 = sp.Eq(EL_v2, rhs_EL[1])
  148.  
  149. I1, R1, k11, I2, R2, k12 = sp.symbols('I1 R1 k11 I2 R2 k12')
  150.  
  151. e1, e2 = sp.symbols('e1 e2')
  152.  
  153. i1_func = sp.Function('i1')(t)
  154. i2_func = sp.Function('i2')(t)
  155.  
  156. eq_motor1 = sp.Eq(I1 * sp.diff(i1_func, t) + R1 * i1_func + k11 * B11 * dot_v1, e1)
  157. eq_motor2 = sp.Eq(I2 * sp.diff(i2_func, t) + R2 * i2_func + k12 * B22 * dot_v2, e2)
  158.  
  159. print("\nElectrical equation for motor 1:")
  160. sp.pprint(eq_motor1)
  161. print("\nElectrical equation for motor 2:")
  162. sp.pprint(eq_motor2)
  163.  
  164. import numpy as np
  165. from scipy.integrate import solve_ivp
  166. from scipy.linalg import solve_continuous_are, inv
  167. import matplotlib.pyplot as plt
  168.  
  169.  
  170. m1_val = 0.3
  171. m2_val = 0.1
  172. a1_val = 0.041
  173. a2_val = 0.041
  174. d1_val = 0.044
  175. d2_val = 0.037
  176. L1_val = 0.061
  177. L2_val = 0.05
  178. l1_val = 0.056
  179. l2_val = 0.06
  180. k1_val = 0.1
  181. k2_val = 0.12
  182.  
  183. k2_1_val = 0.02
  184. k2_2_val = 0.02
  185. k11_val = 0.017
  186. k12_val = 0.017
  187. I1_val = 0.02
  188. I2_val = 0.02
  189. R1_val = 10
  190. R2_val = 10
  191.  
  192. g_val = 9.81
  193.  
  194. v1_0_val = np.deg2rad(60)
  195. v2_0_val = np.deg2rad(30)
  196. w1_0_val = np.deg2rad(61 + 23/60)
  197. w2_0_val = np.deg2rad(10)
  198.  
  199. x0_val = 0.17
  200. y0_val = 0.0866
  201.  
  202.  
  203. B11_0 = L1_val*(d1_val*np.sin(w1_0_val - v1_0_val) - a1_val*np.cos(v1_0_val)) / \
  204.        (d1_val*(L1_val*np.sin(w1_0_val - v1_0_val) - a1_val*np.cos(w1_0_val)))
  205. B22_0 = L2_val*(d2_val*np.sin(w2_0_val - v2_0_val) - a2_val*np.cos(v2_0_val)) / \
  206.        (d2_val*(L2_val*np.sin(w2_0_val - v2_0_val) - a2_val*np.cos(w2_0_val)))
  207.  
  208. d_val = (m1_val*(k1_val - a2_val)**2 + m2_val*(k1_val**2 + 2*k1_val*k2_val*np.sin(v2_0_val)))*m2_val*k2_val**2 \
  209.         - m2_val**2*(k1_val*k2_val*np.sin(v2_0_val) + k2_val**2)**2
  210. b11_val = m2_val * k2_val**2 / d_val
  211. b12_val = -m2_val * (k1_val*k2_val*np.sin(v2_0_val) + k2_val**2) / d_val
  212. b22_val = (m1_val*(k1_val - a2_val)**2 + m2_val*(k1_val**2 + 2*k1_val*k2_val*np.sin(v2_0_val))) / d_val
  213.  
  214.  
  215. h11_val = -g_val*(m1_val*(k1_val - a2_val)*np.sin(v1_0_val) - m2_val*(k1_val*np.sin(v1_0_val) + k2_val*np.cos(v1_0_val + v2_0_val)))
  216. h21_val = -g_val*m2_val*k2_val*np.cos(v1_0_val + v2_0_val)
  217. h12_val = 1.0
  218. h15_val = 1.0
  219. h26_val = B22_0 * 0.1
  220. h13_val = -g_val*m2_val*np.cos(v1_0_val + v2_0_val)
  221. h22_val = 1.0
  222. b2_val = 0.5
  223. h24_val = -b2_val * B22_0**2
  224. h17_val = 0.5
  225. h28_val = 0.5
  226. h23_val = -g_val*m2_val*k2_val*np.cos(v1_0_val + v2_0_val)
  227.  
  228. p21 = b11_val*h11_val + b12_val*h21_val
  229. p22 = b11_val*h12_val
  230. p23 = b11_val*h12_val + b12_val*h22_val
  231. p24 = b11_val*h24_val
  232. p25 = b11_val*h15_val
  233. p26 = b12_val*h26_val
  234.  
  235. p41 = b12_val*h11_val + b22_val*h21_val
  236. p42 = b12_val*h12_val
  237. p43 = b12_val*h13_val + b22_val*h23_val
  238. p44 = b22_val*h24_val
  239. p45 = b12_val*h15_val
  240. p46 = b22_val*h26_val
  241.  
  242. p52 = 0.1
  243. p55 = 0.2
  244. p64 = 0.1
  245. p66 = 0.2
  246.  
  247. P_num = np.array([
  248.     [0,    1,   0,    0,   0,   0],
  249.     [p21, p22, p23, p24, p25, p26],
  250.     [0,    0,   0,    1,   0,   0],
  251.     [p41, p42, p43, p44, p45, p46],
  252.     [0,    p52, 0,    0,   p55, 0],
  253.     [0,    0,   0,    p64, 0,   p66]
  254. ])
  255.  
  256. Q_num = np.array([
  257.     [0, 0],
  258.     [0, 0],
  259.     [0, 0],
  260.     [0, 0],
  261.     [1, 0],
  262.     [0, 1]
  263. ])
  264.  
  265. Q_lqr = np.eye(6)
  266. R_lqr = np.eye(2)
  267.  
  268. S_care = solve_continuous_are(P_num, Q_num, Q_lqr, R_lqr)
  269. K = inv(R_lqr) @ Q_num.T @ S_care
  270.  
  271. A_cl = P_num - Q_num @ K
  272.  
  273. def grasp_position(x):
  274.     return np.array([x0_val + x[0], y0_val + x[2]])
  275.  
  276. delta_y = 0.05
  277. target = np.array([x0_val, y0_val - delta_y])
  278.  
  279. R_val = 0.1
  280. def brachistochrone(theta, x_start, y_start):
  281.     return np.array([x_start + R_val*(theta - np.sin(theta)),
  282.                      y_start - R_val*(1 - np.cos(theta))])
  283.  
  284. theta_target = 0.05
  285. target_brach = brachistochrone(theta_target, x0_val, y0_val)
  286.  
  287. distance_full = np.linalg.norm(target_brach - np.array([x0_val, y0_val]))
  288. epsilon = 0.5 * distance_full
  289.  
  290. print("Целевая точка (по брахистохроне):", target_brach)
  291. print("Радиус ε-окрестности:", epsilon)
  292.  
  293. x0_state = np.zeros(6)
  294. x0_state[0] = x0_val - target_brach[0]
  295. x0_state[2] = y0_val - target_brach[1]
  296.  
  297.  
  298. def closed_loop_ode(t, x):
  299.     return A_cl @ x
  300.  
  301. t_span = (0, 5)
  302. sol = solve_ivp(closed_loop_ode, t_span, x0_state, dense_output=True, max_step=0.01)
  303.  
  304. t_vals = sol.t
  305. x_traj = sol.y
  306.  
  307.  
  308. grasp_traj = np.array([grasp_position(x_traj[:, i]) for i in range(x_traj.shape[1])])
  309. distances = np.linalg.norm(grasp_traj - target_brach, axis=1)
  310.  
  311. idx = np.where(distances < epsilon)[0]
  312.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement