六自由度外弹道计算程序一步到位版(含气动参数计算)

声明:

本程序仅用于PYTHON编程学习交流用途。

相关计算公式参考《弹箭外弹道学 第二版》;关于六自由度外弹道计算的相关知识,推荐参考《弹箭外弹道学 第二版》《导弹飞行力学》《外弹道学》这几本书。

程序中使用的弹箭的六自由度刚体弹道方程如下所示(参考《弹箭外弹道学 第二版》):

1. 程序介绍:

程序包含三个数据.csv文件用于输入计算数据并进行中转,此外包含一个SUPPORT文件夹用于存放气动参数计算软件(无界面版DATCOM),文件内容如下图所示:

 其中:

001.csv用于存放六月自由度外弹道相关计算基础输入参数,如下图所示:

002.csv用于存放 DATCOM计算出的气动参数结果,如下图所示:

003.csv用于存放 DATCOM气动计算的输入参数,如下图所示:

程序计算过程:

用户根据外弹道计算需求对001.csv和003.csv中的相关参数进行设定,此后运行程序,执行六自由度外弹道计算过程。

计算结束后,程序自动绘制出基本的弹丸飞行轨迹曲线,如下图所示:

并同时在程序目录下输出一个名为result.csv的文件用于存放计算过程中的所有相关变量,以便后续的数据处理及绘图,result.csv文件中的内容如下图所示:

 2. 程序代码实现:

2.1 基础内容设置

首先引入程序相关的库:

# 引入必要的库
#..........................................................................................
import math #数学计算库
from matplotlib import pyplot as plt #绘图库
import numpy as np #数值计算库
from scipy.integrate import solve_ivp #ODE求解库
from scipy.interpolate import interp1d, RectBivariateSpline #插值库
import pandas as pd #数据处理库
import chardet #编码检测库
import subprocess #子进程库
import os #操作系统库
import re #正则表达式库
#..........................................................................................

并定义用于检测文件编码的函数:

# 定义函数,用于检测文件编码
def detect_encoding(file_path):
    try:
        with open(file_path, 'rb') as f:
            rawdata = f.read()
        result = chardet.detect(rawdata)
        return result['encoding']
    except Exception as e:
        print(f"Error detecting encoding: {e}")
        return None

2.2 相关参数读取及气动参数计算

访问003.csv文件,读取用于进行气动计算的参数,并将其按照所需形式写入到DATCOM的运算输入文件中。

# 指定弹丸气动参数计算DATCOM软件的输入文件路径
csv_file_path_datcom_params = '003.csv'

# 尝试检测弹丸气动参数计算DATCOM软件的输入文件编码
detected_encoding = detect_encoding(csv_file_path_datcom_params)
if detected_encoding is None:
    print("Failed to detect encoding. Exiting.")
    exit()
else:
    try:
        # 读取CSV文件
        csv_reader = pd.read_csv(csv_file_path_datcom_params, encoding=detected_encoding, header=0)

        # 创建空列表来存储数据
        first_column_data = []
        second_column_data = []
        third_column_data = []

        # 遍历CSV文件的每一行
        for index, row in csv_reader.iterrows():
            first_column_data.append(row[0])
            second_column_data.append(row[1])
            third_column_data.append(row[2])

        data = list(zip(first_column_data, second_column_data, third_column_data))

        # 打印读取结果
        #print(data)

        # 赋值给变量
        XCG = second_column_data[0]
        LNOSE = second_column_data[1]
        DNOSE = second_column_data[2]
        BNOSE = second_column_data[3]
        LCENTR = second_column_data[4]
        DCENTR = second_column_data[5]
        LAFT = second_column_data[6]
        DAFT = second_column_data[7]

        # 打印弹丸气动参数
        print(f"XCG = {XCG}")
        print(f"LNOSE = {LNOSE}")
        print(f"DNOSE = {DNOSE}")
        print(f"BNOSE = {BNOSE}")
        print(f"LCENTR = {LCENTR}")
        print(f"DCENTR = {DCENTR}")
        print(f"LAFT = {LAFT}")
        print(f"DAFT = {DAFT}")

    except Exception as e:
        print(f"Error processing CSV file 003.csv: {e}")
        exit()

运行DATCOM程序并读取相关计算结果转存至002.csv中。

读取外弹道计算基础参数:

# 指定六自由度外弹道计算基础参数文件路径
basic_params_csv_file_path = '001.csv'

detected_encoding = detect_encoding(basic_params_csv_file_path)
if detected_encoding is None:
    print("Failed to detect encoding. Exiting.")
else:
    try:
        # 读取CSV文件
        csv_reader = pd.read_csv(basic_params_csv_file_path, encoding=detected_encoding, header=0)

        # 创建空列表来存储数据
        first_column_data = []
        second_column_data = []
        third_column_data = []

        # 遍历CSV文件的每一行
        for index, row in csv_reader.iterrows():
            first_column_data.append(row[0])
            second_column_data.append(row[1])
            third_column_data.append(row[2])

        data = list(zip(first_column_data, second_column_data, third_column_data))

        # 打印读取结果
        print(data)

    except Exception as e:
        print(f"Error processing CSV file 001.csv: {e}")

读取外弹道计算气动参数:

# 指定六自由度外弹道气动基础参数文件路径
aero_params_csv_file_path = '002.csv'
detected_encoding = detect_encoding(aero_params_csv_file_path)

# 读取CSV文件
if detected_encoding is None:
    print("Failed to detect encoding. Exiting.")
else:
    try:
        # 读取CSV文件
        df = pd.read_csv(aero_params_csv_file_path, encoding=detected_encoding, header=0)

        # 创建一个字典来存储二维数组
        arrays = {}

        # 遍历DataFrame,提取每个二维数组
        current_array_name = None
        current_array = []

        for index, row in df.iterrows():
            array_name = row[0]
            if array_name != current_array_name:  # 判断二维数组的名字是否改变
                if current_array_name is not None:  # 如果当前二维数组的名字不为空,则将上一个二维数组添加到字典中
                    arrays[current_array_name] = current_array  # 添加到字典中
                current_array_name = array_name  # 更新当前二维数组的名字
                current_array = []  # 重置当前二维数组
            current_array.append(row[1:].tolist())  # 添加到当前二维数组中


        # 添加最后一个数组
        if current_array_name is not None:
            arrays[current_array_name] = current_array

        # 打印结果
   
        for array_name, array in arrays.items():
            print(f"{array_name}:")
            for row in array:
                print(row)
            print()
       

    except Exception as e:
        print(f"Error processing CSV file 002.csv: {e}")

2.3 六自由度外弹道计算

调用ode求解器,使用RK45方法求解微分方程组。

# 调用ode求解器,使用RK45方法求解微分方程组
def wrap_sdofmotion(t, mp, global_params):
    # 解包全局参数
    X_cm, tau, a, C, A, m, d, l, S, v_0, theta_a_0, psi_2_0, phi_a_0, phi_2_0, gamma_0, omiga_xi_0, omiga_eta_0, omiga_zeta_0, x_0, y_0, z_0, w, a_W, g, rou, beta_D_1, beta_D_2, Lambda, delta_f, delta_N, delta_M, gamma_0_1, gamma_0_2, Omiga_E, a_N, ma1, Delta, CA, CN, X_CP, CNA, CYPA, Cnp1, Cnp3, Cnp5= global_params
    
    return sdofmotion(t, mp, global_params)

# 设置初始条件和参数
t0 = 0.0
mp0 = np.array([v_0,theta_a_0,psi_2_0,omiga_xi_0,omiga_eta_0,omiga_zeta_0,phi_a_0,phi_2_0,gamma_0,x_0,y_0,z_0])  # 设置初始状态向量
t_end = t_estimation  # 设置积分终止时间

global_params = [X_cm, tau, a, C, A, m, d, l, S, v_0, theta_a_0, psi_2_0, phi_a_0, phi_2_0, gamma_0, 
                 omiga_xi_0, omiga_eta_0, omiga_zeta_0, x_0, y_0, z_0, w, a_W, g, rou, beta_D_1, beta_D_2, 
                 Lambda, delta_f, delta_N, delta_M, gamma_0_1, gamma_0_2, Omiga_E, a_N,
                 ma1, Delta, CA, CN, X_CP, CNA, CYPA, Cnp1, Cnp3, Cnp5]  # 设置全局参数列表

# 使用solve_ivp进行积分,指定方法为RK45并设置容差
sol = solve_ivp(wrap_sdofmotion, (t0, t_end), mp0, args=(global_params,), method='RK45', rtol=1e-7, atol=1e-7)

2.4 结果处理

将结果输出值result.csv文件,并绘制出基本外弹道飞行轨迹曲线。

# 处理结果
ts = sol.t # 时间序列
mps = sol.y.T # 状态向量序列
#..............................................................................................................................................
# 结果处理及导出
#..............................................................................................................................................
# 导出计算结果至外部csv文件中
df = pd.DataFrame(mps, columns=['v', 'theta_a', 'psi_2', 'omiga_xi', 'omiga_eta', 'omiga_zeta', 'phi_a', 'phi_2', 'gamma', 'x', 'y', 'z'])
df['t'] = ts
df.to_csv('result.csv', index=False)
print('The calculation result has been exported to the external csv file successfully!')

# 绘制结果图
fig, ax = plt.subplots(2, 2, figsize=(12, 10))

ax[0, 0].plot(ts, mps[:, 0], label='v')
ax[0, 0].set_xlabel('t')
ax[0, 0].set_ylabel('v')
ax[0, 0].legend()
ax[0, 0].set_title('Velocity')

ax[0, 1].plot(ts, mps[:, 9], label='X')
ax[0, 1].set_xlabel('t')
ax[0, 1].set_ylabel('X')
ax[0, 1].legend()
ax[0, 1].set_title('Position X') 

ax[1, 0].plot(ts, mps[:, 10], label='Y')
ax[1, 0].set_xlabel('t')
ax[1, 0].set_ylabel('Y')
ax[1, 0].legend()
ax[1, 0].set_title('Position Y')

ax[1, 1].plot(ts, mps[:, 11], label='Z')
ax[1, 1].set_xlabel('t')
ax[1, 1].set_ylabel('Z')
ax[1, 1].legend()
ax[1, 1].set_title('Position Z')

fig.suptitle('Time Series Analysis of Motion Data')
plt.tight_layout()  # 调整布局以防止标题重叠
plt.show()

3. 程序打包

通过pyinstller将程序内容打包为可直接运行的exe文件,用户在设置好相关输入参数后,可通过直接运行exe文件进行外弹道解算。

4. 总结

借助PYTHON,本程序能够方便地将第三方气动参数计算软件(本例中为DATCOM无界面版)整合进程序中,简化了整个计算过程中的工作量(无需再从006.dat文件中找寻相关结果并进行复制粘贴和重新读取)。通过pyinstller将程序打包为可直接运行的exe文件,使得程序无需相关环境准备在不同设备上的流畅运行成为了可能。有关外弹道计算和相关DATCOM气动参数计算软件的资料及手册,以及相关编程过程中遇到的问题和经验总结,欢迎感兴趣的读者和作者沟通交流,qq:3383016937。

对于自由度弹道问题,可以使用 Matlab 编写程序进行求解。下面给出一个简单的示例程序: ```matlab clc; clear; % 初始条件 v0 = 500; % 初速度 theta0 = pi/4; % 初角度 phi0 = 0; % 初方位角 x0 = 0; % 初位置 y0 = 0; % 初位置 z0 = 0; % 初位置 % 常数定义 g = 9.8; % 重力加速度 dt = 0.01; % 时间步长 t = 0; % 初始时间 m = 10; % 弹体质量 Cd = 0.3; % 阻力系数 A = 0.1; % 截面积 rho = 1.29; % 空气密度 % 初始化速度、加速度、位移等 v = v0*[sin(theta0)*cos(phi0), sin(theta0)*sin(phi0), cos(theta0)]; a = [0, 0, -g]; r = [x0, y0, z0]; path = r; while r(3) >= 0 % 弹体在地面上方时继续计算 v_mag = norm(v); % 计算速度大小 Fd = -0.5*rho*Cd*A*v_mag*v; % 计算阻力 a = [0, 0, -g] + Fd/m; % 计算加速度 v = v + a*dt; % 计算速度 r = r + v*dt; % 计算位移 path = [path; r]; % 记录弹道轨迹 t = t + dt; % 更新时间 end % 绘制弹道图 plot3(path(:,1), path(:,2), path(:,3)) xlabel('x (m)') ylabel('y (m)') zlabel('z (m)') ``` 在这个程序中,我们首先定义了初始条件,包括初始速度、初角度、初方位角以及初位置。然后定义了一些常数,如重力加速度、时间步长、弹体质量、阻力系数、截面积和空气密度。接着,我们初始化了速度、加速度和位移等变量,并进入一个循环,每一步计算弹体的运动状态,直到弹体落地为止。在每一步中,我们先计算速度大小,并根据速度大小计算阻力,然后计算加速度,再计算速度和位移,最后记录弹道轨迹。最后,我们使用 plot3 函数绘制弹道图。 需要注意的是,这个程序只是一个简单的示例,没有考虑很多实际问题,如空气动力学效应、地球曲率等。如果需要进行更精确的计算,需要考虑更多的因素。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值