MATLAB实现弹道仿真源代码

弹道仿真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

使用方法

  1. 根据需要修改"参数设置"部分: 调整弹丸参数(质量、直径、阻力系数) 设置初始条件(位置、速度、角度) 选择数值积分方法和时间步长
  2. 运行代码后,将显示: 三维弹道轨迹图 高度和速度随时间变化曲线 命令行输出的关键参数
  3. 可通过修改初始条件模拟不同场景: 改变发射角度研究射程变化 调整弹丸参数研究空气动力学影响 修改发射位置研究地球曲率影响
相关推荐
2501_941877137 小时前
大规模系统稳定性建设方法论与工程实践分享
java·开发语言
2501_941820497 小时前
面向零信任安全与最小权限模型的互联网系统防护设计思路与多语言工程实践分享
开发语言·leetcode·rabbitmq
浩瀚地学7 小时前
【Java】面向对象进阶-接口
java·开发语言·经验分享·笔记·学习
2501_941802487 小时前
面向微服务限流、熔断与降级协同的互联网系统高可用架构与多语言工程实践分享
开发语言·python
2501_941875287 小时前
分布式系统中的安全权限与审计工程实践方法论经验总结与多语言示例解析分享
开发语言·rabbitmq
无限进步_7 小时前
【C语言】堆排序:从堆构建到高效排序的完整解析
c语言·开发语言·数据结构·c++·后端·算法·visual studio
雾岛听蓝7 小时前
STL 容器适配器:stack、queue 与 priority_queue
开发语言·c++
CSDN_RTKLIB7 小时前
【One Definition Rule】多编译单元定义同名全局变量
开发语言·c++
lang201509288 小时前
AQS共享锁的传播机制精髓
java·开发语言
云栖梦泽8 小时前
变量与数据类型:从“默认不可变”说起
开发语言