This commit is contained in:
2024-09-07 14:30:20 +08:00
parent caa0a9e2a1
commit ad195eca76
2 changed files with 108 additions and 40 deletions

View File

@@ -1,7 +1,7 @@
import mpmath as mp import mpmath as mp
import numba as nb import numba as nb
mp.dps = 25 # 设置精度为25位小数 mp.dps = 50 # 设置精度为50位小数
class Orbit: class Orbit:
def __init__(self): def __init__(self):

View File

@@ -3,6 +3,10 @@ import json
import numpy as np import numpy as np
import sys import sys
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import io
from PIL import Image
from matplotlib.patches import Rectangle
import multiprocessing
class GoodOrbit(Orbit): class GoodOrbit(Orbit):
@@ -18,10 +22,14 @@ class GoodOrbit(Orbit):
self.point_B_cartesian = (-self.kAlpha * self.kCriticalTheta * mp.cos(self.kCriticalTheta), self.point_B_cartesian = (-self.kAlpha * self.kCriticalTheta * mp.cos(self.kCriticalTheta),
-self.kAlpha * self.kCriticalTheta * mp.sin(self.kCriticalTheta)) -self.kAlpha * self.kCriticalTheta * mp.sin(self.kCriticalTheta))
self.kPhi = mp.atan(self.kCriticalTheta) self.kPhi = mp.atan(self.kCriticalTheta)
print(f"Phi={self.kPhi}", file=sys.stderr)
dx, dy = self.point_A_cartesian[0] - self.point_B_cartesian[0], self.point_A_cartesian[1] - self.point_B_cartesian[1] dx, dy = self.point_A_cartesian[0] - self.point_B_cartesian[0], self.point_A_cartesian[1] - self.point_B_cartesian[1]
self.angle = mp.atan2(dy, dx) self.angle = mp.atan2(dy, dx)
self.point_C1_cartesian = (self.point_A_cartesian[0] - 2 * self.r * dx, self.point_A_cartesian[1] - 2 * self.r * dy) print(f"angle={self.angle}", file=sys.stderr)
self.point_C2_cartesian = (self.point_B_cartesian[0] + 1 * self.r * dx, self.point_B_cartesian[1] + 1 * self.r * dy) self.point_C1_cartesian = (self.point_A_cartesian[0] + 2 * self.r * mp.cos(self.angle + 0.5 * mp.pi + self.kPhi),
self.point_A_cartesian[1] + 2 * self.r * mp.sin(self.angle + 0.5 * mp.pi + self.kPhi))
self.point_C2_cartesian = (self.point_B_cartesian[0] + 1 * self.r * mp.cos(self.angle - 0.5 * mp.pi + self.kPhi),
self.point_B_cartesian[1] + 1 * self.r * mp.sin(self.angle - 0.5 * mp.pi + self.kPhi))
self.radius_of_C1 = 2 * self.r self.radius_of_C1 = 2 * self.r
self.radius_of_C2 = 1 * self.r self.radius_of_C2 = 1 * self.r
self.arclength = 6 * self.r * self.kPhi self.arclength = 6 * self.r * self.kPhi
@@ -66,7 +74,31 @@ class GoodOrbit(Orbit):
return -self.kAlpha * 0.5 * (theta * tmp - mp.log(-theta + tmp)) + self.edge_raw_C - self.arclength return -self.kAlpha * 0.5 * (theta * tmp - mp.log(-theta + tmp)) + self.edge_raw_C - self.arclength
def Idx2Cartesian(self, idx): def Idx2Cartesian(self, idx):
return mp.matrix([mp.cos(idx), mp.sin(idx)]) if idx >= 0:
theta = idx + self.kCriticalTheta
return [self.kAlpha * theta * mp.cos(theta), self.kAlpha * theta * mp.sin(theta)]
elif idx >= -2 * self.kCriticalTheta:
c = self.Idx2C(idx) + self.arclength
# if c < 0 or c > self.arclength:
# raise Exception(f"idx={idx}, c={c}")
if c <= self.arclength / 3:
# In C2
delta_angle = c / self.radius_of_C2
actual_angle = self.angle + 0.5 * mp.pi + self.kPhi - delta_angle
return [
self.point_C2_cartesian[0] + self.radius_of_C2 * mp.cos(actual_angle),
self.point_C2_cartesian[1] + self.radius_of_C2 * mp.sin(actual_angle)
]
else:
delta_angle = (c - self.arclength / 3) / self.radius_of_C1
actual_angle = self.angle - 0.5 * mp.pi - self.kPhi + delta_angle
return [
self.point_C1_cartesian[0] + self.radius_of_C1 * mp.cos(actual_angle),
self.point_C1_cartesian[1] + self.radius_of_C1 * mp.sin(actual_angle)
]
else:
theta = -idx - self.kCriticalTheta
return [-self.kAlpha * theta * mp.cos(theta), -self.kAlpha * theta * mp.sin(theta)]
def C2Idx(self, C): def C2Idx(self, C):
@@ -75,48 +107,82 @@ class GoodOrbit(Orbit):
return mp.findroot(f, 0, solver='secant') return mp.findroot(f, 0, solver='secant')
def GenerateNextPointIdx(self, cur_point_idx, expected_distance): def GenerateNextPointIdx(self, cur_point_idx, expected_distance, guess=None):
return cur_point_idx + expected_distance if guess is None:
cur_point_C = self.Idx2C(cur_point_idx)
guess = self.C2Idx(cur_point_C + expected_distance)
cur_point_dot = self.Idx2Cartesian(cur_point_idx)
def f(idx):
test_point_dot = self.Idx2Cartesian(idx)
return mp.sqrt((cur_point_dot[0] - test_point_dot[0])**2 +
(cur_point_dot[1] - test_point_dot[1])**2) - expected_distance
return mp.findroot(f, guess, solver='secant')
def GenerateImg(self, node_list):
fig = plt.figure(figsize=(12, 12))
# 绘制轨道线
idx_list = np.linspace(-8 * 2 * np.pi, 8 * 2 * np.pi, 10000)
x = [float(self.Idx2Cartesian(t)[0]) for t in idx_list]
y = [float(self.Idx2Cartesian(t)[1]) for t in idx_list]
plt.plot(x, y, color='gray', linewidth=0.5)
# 绘制节点、连接线和木板
for i in range(len(node_list) - 1):
x1, y1 = [float(coord) for coord in node_list[i]["node"]]
x2, y2 = [float(coord) for coord in node_list[i + 1]["node"]]
# 绘制红色节点
plt.plot(x1, y1, 'ro', markersize=3)
# 绘制蓝色连接线
plt.plot([x1, x2], [y1, y2], 'b-', linewidth=0.5)
# 计算并绘制木板(长方形)
dx = x2 - x1
dy = y2 - y1
length = np.sqrt(dx**2 + dy**2)
angle = np.arctan2(dy, dx)
rect_length = length + 0.55 # 总长度加上两端各延伸的0.275m
rect_width = 0.3
# 计算长方形的中心点
center_x = (x1 + x2) / 2
center_y = (y1 + y2) / 2
# 计算长方形的左下角坐标
rect_x = center_x - rect_length / 2 * np.cos(angle) + rect_width / 2 * np.sin(angle)
rect_y = center_y - rect_length / 2 * np.sin(angle) - rect_width / 2 * np.cos(angle)
rect = Rectangle((rect_x, rect_y), rect_length, rect_width, angle=angle * 180 / np.pi, fill=False, edgecolor='g')
plt.gca().add_patch(rect)
# 绘制最后一个节点
x, y = [float(coord) for coord in node_list[-1]["node"]]
plt.plot(x, y, 'ro', markersize=3)
plt.axis('equal')
# 创建一个 BytesIO 对象来存储图像
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
# 清除当前图形,释放内存
plt.close(fig)
# 返回图像对象
return Image.open(buf)
orbit = GoodOrbit()
def f(x):
return float(orbit.Idx2C(x))
# 获取 kCriticalTheta
kCriticalTheta = float(orbit.kCriticalTheta)
print(f"kCriticalTheta={kCriticalTheta}")
# 定义范围 [-kCriticalTheta-1, kCriticalTheta +1]
start = -2.5 * kCriticalTheta - 1
end = 0.5 * kCriticalTheta + 1
# 生成范围内的点
x_vals = np.linspace(start, end, 1000)
# 计算 f(x) 的值
y_vals = [f(mp.mpf(x)) for x in x_vals]
# 绘制图像
plt.figure(figsize=(10, 6))
plt.plot(x_vals, y_vals, label='Idx2C(x)')
plt.title('Idx2C function plot')
plt.xlabel('Index (x)')
plt.ylabel('C Value')
plt.grid(True)
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.legend()
plt.show()
sys.exit()
if __name__ == "__main__": if __name__ == "__main__":
orbit = GoodOrbit() orbit = GoodOrbit()
loong = Loong(orbit, 224, mp.mpf("2.0"), mp.mpf("1e-8")) loong = Loong(orbit, 224, mp.mpf("2.0"), mp.mpf("1e-8"))
res_list = [] res_list = []
for ti in range(-100, 101): for ti in range(-10, 2):
print(f"calculating time_point={ti}") print(f"calculating time_point={ti}")
res_list.append(loong.CalcStatusListByTime(mp.mpf(ti))) res_list.append(loong.CalcStatusListByTime(mp.mpf(ti)))
# 转换成内置浮点数并保留6位 # 转换成内置浮点数并保留6位
@@ -131,3 +197,5 @@ if __name__ == "__main__":
} for node in res] for res in res_list] } for node in res] for res in res_list]
with open("A4_res.json", "w") as file: with open("A4_res.json", "w") as file:
json.dump(float_res_list, file, indent=4) json.dump(float_res_list, file, indent=4)
img_list = [orbit.GenerateImg(res) for res in res_list]
img_list[0].save("A4.gif", save_all=True, append_images=img_list[1:], duration=1000, loop=0)