弹道仿真MATLAB实现,包含坐标系转换、运动学计算和可视化功能。该代码模拟了弹丸在重力、空气阻力和地球自转影响下的飞行轨迹。
matlab
%% 弹道仿真系统 - 完整MATLAB实现
% 描述: 模拟弹丸在重力、空气阻力和地球自转影响下的飞行轨迹
% 包含坐标系转换、运动学计算和三维可视化
clear all; close all; clc;
%% 参数设置
% 地球参数
earth.radius = 6371000; % 地球半径 (m)
earth.gravity = 9.80665; % 重力加速度 (m/s²)
earth.rotation = 7.292115e-5; % 地球自转角速度 (rad/s)
earth.atmosphere = struct(...
'density', @(h) 1.225 * exp(-h/8500), ... % 大气密度模型 (kg/m³)
'speed_of_sound', 340); % 声速 (m/s)
% 弹丸参数
projectile.mass = 10; % 质量 (kg)
projectile.diameter = 0.1; % 直径 (m)
projectile.drag_coeff = 0.3; % 阻力系数
projectile.area = pi*(projectile.diameter/2)^2; % 横截面积 (m²)
% 初始条件
initial.position = [0, 0, 0]; % 发射点位置 (经度, 纬度, 高度) (度, 度, m)
initial.velocity = 800; % 初始速度大小 (m/s)
initial.elevation = 45; % 发射仰角 (度)
initial.azimuth = 45; % 发射方位角 (度, 正北为0)
% 仿真参数
sim.time_step = 0.01; % 时间步长 (s)
sim.duration = 200; % 最大仿真时间 (s)
sim.method = 'rk4'; % 数值积分方法 ('euler', 'rk4')
%% 坐标系转换函数
% 经纬高转地心笛卡尔坐标 (ECEF)
lla2ecef = @(lat, lon, alt) [...
(earth.radius + alt) .* cosd(lat) .* cosd(lon); ...
(earth.radius + alt) .* cosd(lat) .* sind(lon); ...
(earth.radius + alt) .* sind(lat)];
% 地心笛卡尔坐标转经纬高 (ECEF to LLA)
ecef2lla = @(x, y, z) [...
atand(z, sqrt(x^2 + y^2)); ... % 纬度
atan2d(y, x); ... % 经度
sqrt(x^2 + y^2 + z^2) - earth.radius]; % 高度
% 局部坐标系转换 (ENU)
lla2enu = @(ref_lat, ref_lon, lat, lon, alt) [...
(lon - ref_lon) * cosd(ref_lat) * (pi/180) * (earth.radius + alt); ... % 东
(lat - ref_lat) * (pi/180) * (earth.radius + alt); ... % 北
alt]; % 上
%% 初始化状态变量
% 初始位置 (经纬高)
lat0 = initial.position(1);
lon0 = initial.position(2);
alt0 = initial.position(3);
% 初始速度向量 (ECEF坐标系)
elev_rad = deg2rad(initial.elevation);
azim_rad = deg2rad(initial.azimuth);
vx0 = initial.velocity * cos(elev_rad) * sin(azim_rad);
vy0 = initial.velocity * cos(elev_rad) * cos(azim_rad);
vz0 = initial.velocity * sin(elev_rad);
% 初始ECEF位置
pos0 = lla2ecef(lat0, lon0, alt0);
% 初始ECEF速度
vel0 = [vx0; vy0; vz0];
% 状态向量: [x, y, z, vx, vy, vz]
state = [pos0; vel0];
% 存储轨迹
trajectory.time = 0;
trajectory.position_ecef = pos0';
trajectory.position_lla = [lat0, lon0, alt0];
trajectory.velocity = norm(vel0);
%% 主仿真循环
t = 0;
while t < sim.duration
% 获取当前状态
pos = state(1:3);
vel = state(4:6);
% 计算当前经纬高
[lat, lon, alt] = ecef2lla(pos(1), pos(2), pos(3));
% 计算空气动力
rho = earth.atmosphere.density(alt); % 大气密度
v_rel = norm(vel); % 相对速度大小
drag_force = 0.5 * rho * v_rel^2 * projectile.drag_coeff * projectile.area;
drag_acc = drag_force / projectile.mass;
% 计算重力加速度 (随高度变化)
gravity = earth.gravity * (earth.radius/(earth.radius+alt))^2;
% 计算科里奥利加速度 (地球自转效应)
omega = [0; 0; earth.rotation]; % 地球自转角速度矢量
coriolis_acc = -2 * cross(omega, vel);
% 计算加速度
acc_gravity = -gravity * pos / norm(pos); % 重力 (指向地心)
acc_drag = -drag_acc * vel / v_rel; % 阻力 (与速度反向)
acc_total = acc_gravity + acc_drag + coriolis_acc;
% 数值积分
if strcmp(sim.method, 'euler')
new_state = state + sim.time_step * [vel; acc_total];
elseif strcmp(sim.method, 'rk4')
k1 = sim.time_step * [vel; acc_total];
k2_state = state + 0.5*k1;
k2_vel = k2_state(4:6);
[lat_k2, lon_k2, alt_k2] = ecef2lla(k2_state(1), k2_state(2), k2_state(3));
rho_k2 = earth.atmosphere.density(alt_k2);
v_rel_k2 = norm(k2_vel);
drag_force_k2 = 0.5 * rho_k2 * v_rel_k2^2 * projectile.drag_coeff * projectile.area;
drag_acc_k2 = drag_force_k2 / projectile.mass;
acc_gravity_k2 = -gravity * (earth.radius/(earth.radius+alt_k2))^2 * k2_state(1:3)/norm(k2_state(1:3));
acc_drag_k2 = -drag_acc_k2 * k2_vel / v_rel_k2;
acc_coriolis_k2 = -2 * cross(omega, k2_vel);
acc_total_k2 = acc_gravity_k2 + acc_drag_k2 + acc_coriolis_k2;
k2 = sim.time_step * [k2_vel; acc_total_k2];
k3_state = state + 0.5*k2;
k3_vel = k3_state(4:6);
[lat_k3, lon_k3, alt_k3] = ecef2lla(k3_state(1), k3_state(2), k3_state(3));
rho_k3 = earth.atmosphere.density(alt_k3);
v_rel_k3 = norm(k3_vel);
drag_force_k3 = 0.5 * rho_k3 * v_rel_k3^2 * projectile.drag_coeff * projectile.area;
drag_acc_k3 = drag_force_k3 / projectile.mass;
acc_gravity_k3 = -gravity * (earth.radius/(earth.radius+alt_k3))^2 * k3_state(1:3)/norm(k3_state(1:3));
acc_drag_k3 = -drag_acc_k3 * k3_vel / v_rel_k3;
acc_coriolis_k3 = -2 * cross(omega, k3_vel);
acc_total_k3 = acc_gravity_k3 + acc_drag_k3 + acc_coriolis_k3;
k3 = sim.time_step * [k3_vel; acc_total_k3];
k4_state = state + k3;
k4_vel = k4_state(4:6);
[lat_k4, lon_k4, alt_k4] = ecef2lla(k4_state(1), k4_state(2), k4_state(3));
rho_k4 = earth.atmosphere.density(alt_k4);
v_rel_k4 = norm(k4_vel);
drag_force_k4 = 0.5 * rho_k4 * v_rel_k4^2 * projectile.drag_coeff * projectile.area;
drag_acc_k4 = drag_force_k4 / projectile.mass;
acc_gravity_k4 = -gravity * (earth.radius/(earth.radius+alt_k4))^2 * k4_state(1:3)/norm(k4_state(1:3));
acc_drag_k4 = -drag_acc_k4 * k4_vel / v_rel_k4;
acc_coriolis_k4 = -2 * cross(omega, k4_vel);
acc_total_k4 = acc_gravity_k4 + acc_drag_k4 + acc_coriolis_k4;
k4 = sim.time_step * [k4_vel; acc_total_k4];
new_state = state + (k1 + 2*k2 + 2*k3 + k4)/6;
end
% 更新状态
state = new_state;
t = t + sim.time_step;
% 存储轨迹
trajectory.time(end+1) = t;
trajectory.position_ecef(end+1,:) = state(1:3)';
[lat, lon, alt] = ecef2lla(state(1), state(2), state(3));
trajectory.position_lla(end+1,:) = [lat, lon, alt];
trajectory.velocity(end+1) = norm(state(4:6));
% 检查是否落地 (高度低于0)
if alt < 0
disp(['弹丸在 t = ', num2str(t), ' s 时落地']);
disp(['落点位置: 纬度=', num2str(lat), '°, 经度=', num2str(lon), '°, 高度=', num2str(alt), 'm']);
break;
end
end
%% 结果可视化
% 创建图形窗口
figure('Position', [100, 100, 1200, 800], 'Name', '弹道仿真结果');
% 三维轨迹图
subplot(2,2,[1,3]);
plot3(trajectory.position_lla(:,2), trajectory.position_lla(:,1), trajectory.position_lla(:,3)/1000, 'b-', 'LineWidth', 2);
hold on;
plot3(initial.position(2), initial.position(1), initial.position(3)/1000, 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
if min(trajectory.position_lla(:,3)) < 0
idx = find(trajectory.position_lla(:,3) < 0, 1);
plot3(trajectory.position_lla(idx,2), trajectory.position_lla(idx,1), 0, 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
end
xlabel('经度 (°)');
ylabel('纬度 (°)');
zlabel('高度 (km)');
title('弹道三维轨迹');
grid on;
legend('弹道轨迹', '发射点', '落地点', 'Location', 'best');
view(45, 30);
% 高度随时间变化
subplot(2,2,2);
plot(trajectory.time, trajectory.position_lla(:,3)/1000, 'b-', 'LineWidth', 2);
xlabel('时间 (s)');
ylabel('高度 (km)');
title('高度随时间变化');
grid on;
% 速度随时间变化
subplot(2,2,4);
plot(trajectory.time, trajectory.velocity, 'r-', 'LineWidth', 2);
xlabel('时间 (s)');
ylabel('速度 (m/s)');
title('速度随时间变化');
grid on;
% 添加地球曲面
[X, Y, Z] = sphere(50);
X = X * earth.radius/1000;
Y = Y * earth.radius/1000;
Z = Z * earth.radius/1000;
hold on;
surf(X, Y, Z, 'FaceAlpha', 0.1, 'EdgeColor', 'none');
colormap('gray');
%% 输出关键参数
fprintf('\n===== 弹道仿真结果 =====\n');
fprintf('发射点: 纬度=%.4f°, 经度=%.4f°, 高度=%.1f m\n', ...
initial.position(1), initial.position(2), initial.position(3));
fprintf('初始速度: %.1f m/s, 仰角=%.1f°, 方位角=%.1f°\n', ...
initial.velocity, initial.elevation, initial.azimuth);
if min(trajectory.position_lla(:,3)) < 0
idx = find(trajectory.position_lla(:,3) < 0, 1);
fprintf('落点: 纬度=%.4f°, 经度=%.4f°, 高度=%.1f m\n', ...
trajectory.position_lla(idx,1), trajectory.position_lla(idx,2), trajectory.position_lla(idx,3));
fprintf('飞行时间: %.2f s\n', trajectory.time(idx));
fprintf('射程: %.2f km\n', ...
distance(initial.position(1), initial.position(2), ...
trajectory.position_lla(idx,1), trajectory.position_lla(idx,2))/1000);
else
fprintf('最大飞行时间: %.2f s\n', trajectory.time(end));
fprintf('最大高度: %.2f km\n', max(trajectory.position_lla(:,3))/1000);
end
fprintf('最大速度: %.1f m/s\n', max(trajectory.velocity));
fprintf('最小速度: %.1f m/s\n', min(trajectory.velocity));
%% 辅助函数:计算两点间距离 (Haversine公式)
function d = distance(lat1, lon1, lat2, lon2)
R = 6371000; % 地球半径 (m)
phi1 = deg2rad(lat1);
phi2 = deg2rad(lat2);
delta_phi = deg2rad(lat2 - lat1);
delta_lambda = deg2rad(lon2 - lon1);
a = sin(delta_phi/2)^2 + cos(phi1)*cos(phi2)*sin(delta_lambda/2)^2;
c = 2*atan2(sqrt(a), sqrt(1-a));
d = R * c; % 距离 (m)
end
代码功能说明
1. 物理模型
- 重力模型:随高度变化的重力加速度
- 空气阻力:基于大气密度和弹丸参数的阻力模型
- 地球自转:科里奥利力效应
- 坐标系转换:经纬高(LLH) ↔ 地心地固(ECEF) ↔ 东北天(ENU)
2. 数值积分方法
- 欧拉法:简单但精度较低
- 龙格-库塔4阶(RK4):高精度数值积分方法(默认)
3. 可视化功能
- 三维弹道轨迹图(包含地球曲面)
- 高度随时间变化曲线
- 速度随时间变化曲线
- 关键参数输出(发射点、落点、飞行时间等)
4. 关键参数计算
- 飞行时间
- 射程(使用Haversine公式计算大圆距离)
- 最大高度
- 最大/最小速度
参考代码 利用MATLAB进行弹道仿真源代码 www.3dddown.com/csa/82761.html
使用方法
- 根据需要修改"参数设置"部分: 调整弹丸参数(质量、直径、阻力系数) 设置初始条件(位置、速度、角度) 选择数值积分方法和时间步长
- 运行代码后,将显示: 三维弹道轨迹图 高度和速度随时间变化曲线 命令行输出的关键参数
- 可通过修改初始条件模拟不同场景: 改变发射角度研究射程变化 调整弹丸参数研究空气动力学影响 修改发射位置研究地球曲率影响