当前位置: 首页 > article >正文

matlab模拟小球平抛

% 需求:模拟小球平抛运动过程,考虑惯性、旋转和与地面的碰撞,直到能量足够少弹不起来为止,用动画形式展示
% TODO:调整动画窗口和坐标轴以完整显示动画,并将动画保存为视频

% 基础参数设置
x0 = 0;          % 初始水平位置
y0 = 10;         % 初始垂直位置(高度)
vx0 = 5;         % 初始水平速度
vy0 = 0;         % 初始垂直速度
g = -9.81;       % 重力加速度,单位:m/s^2
dt = 0.01;       % 时间步长,单位:秒
e = 0.8;         % 恢复系数(每次碰撞后的能量保留比例)
mu = 0.1;        % 地面与小球之间的摩擦系数
radius = 0.2;    % 小球半径,单位:米
mass = 0.5;      % 小球质量,单位:kg
I = (2/5)*mass*radius^2; % 小球的转动惯量

threshold_vy = 0.1; % 判定小球停止弹跳的垂直速度阈值
threshold_vx = 0.01; % 判定小球停止滚动的水平速度阈值

% 初始化变量
x = x0;
y = y0;
vx = vx0;
vy = vy0;
omega = 0;       % 初始角速度
t = 0;

% 用于存储轨迹数据
X = [];
Y = [];

% 设置动画
figure('Position', get(0, 'ScreenSize')); % 将窗口设置为全屏
hold on;
grid on;
xlabel('水平位置 (m)');
ylabel('垂直位置 (m)');
title('考虑惯性的小球平抛运动模拟(含能量损失)');

ball = plot(x, y, 'ro', 'MarkerSize', 15, 'MarkerFaceColor', 'r'); % 小球
trajectory = plot(NaN, NaN, 'b'); % 轨迹

% 初始化坐标轴范围
axis([x0-1 x0+10 0 y0+5]);

% 调整画面显示
set(gca, 'FontSize', 14); % 增大坐标轴字体

% 创建视频对象
video_filename = 'ball_motion.mp4'; % 视频文件名
video = VideoWriter(video_filename, 'MPEG-4');
video.FrameRate = 1/dt; % 设置帧率,与模拟时间步长匹配
open(video);

% 仿真循环
while true
    % 更新速度
    vy = vy + g * dt;
    
    % 更新位置
    x = x + vx * dt;
    y = y + vy * dt;
    
    % 存储数据
    X(end+1) = x;
    Y(end+1) = y;
    
    % 碰撞检测
    if y <= radius  % 考虑小球的半径
        y = radius;           % 确保小球不穿过地面
        vy = -e * vy;         % 垂直速度反向并考虑能量损失
        
        % 计算由于摩擦导致的水平速度变化和角速度变化
        Fn = mass * abs(g);   % 法向力
        Ff = mu * Fn;         % 摩擦力
        dv = (Ff / mass) * dt;     % 水平速度的变化量
        domega = (Ff * radius / I) * dt; % 角速度的变化量
        
        % 更新水平速度和角速度
        if vx > 0
            vx = vx - dv;
            omega = omega + domega;
            if vx < 0
                vx = 0;
            end
        elseif vx < 0
            vx = vx + dv;
            omega = omega - domega;
            if vx > 0
                vx = 0;
            end
        end
        
        % 判断是否停止弹跳
        if abs(vy) < threshold_vy
            vy = 0;
            % 检查是否需要继续滚动
            if abs(vx) < threshold_vx
                break; % 水平速度过小,结束仿真
            end
        end
    end
    
    % 当小球在地面上滚动时,考虑摩擦力减速
    if y == radius && vy == 0
        Fn = mass * abs(g);   % 法向力
        Ff = mu * Fn;         % 摩擦力
        dv = (Ff / mass) * dt;     % 水平速度的变化量
        domega = (Ff * radius / I) * dt; % 角速度的变化量
        
        % 更新水平速度和角速度
        if vx > 0
            vx = vx - dv;
            omega = omega + domega;
            if vx < 0
                vx = 0;
            end
        elseif vx < 0
            vx = vx + dv;
            omega = omega - domega;
            if vx > 0
                vx = 0;
            end
        end
        
        % 判断是否停止滚动
        if abs(vx) < threshold_vx
            break; % 水平速度过小,结束仿真
        end
    end
    
    % 更新动画
    set(ball, 'XData', x, 'YData', y);
    set(trajectory, 'XData', X, 'YData', Y);
    
    % 动态调整坐标轴范围
    axis([min(X)-1 max(X)+1 0 y0+5]);
    
    drawnow;
    
    % 捕获当前帧并写入视频
    frame = getframe(gcf);
    writeVideo(video, frame);
    
    % 更新时间
    t = t + dt;
end

% 关闭视频对象
close(video);

% 最后绘制完整轨迹
plot(X, Y, 'LineWidth', 2);

ball_motion


http://www.kler.cn/a/377274.html

相关文章:

  • 了解常见的反规范化技术手段
  • leetcode21:合并两个有序列表
  • P06_三数之和
  • 【浪潮商城-注册安全分析报告-无验证方式导致安全隐患】
  • [渲染层网络层错误] net::ERR_CONTENT_LENGTH_MISMATCH 问题解决
  • Qt的C++中实现一个文本转语音(TTS)系统
  • oracle insert忽略主键冲突,忽略重复记录
  • C++_day3
  • LeetCode3226题. 使两个整数相等的位更改次数(原创)
  • CSS 动画:网页设计的动态之美
  • ubuntu df -h分配的磁盘空间小于物理磁盘
  • mysql8 window 免安装
  • 【Qt聊天客户端-min_Bug】客户端请求失败分析
  • 杂货 | 每日资讯 | 2024.11.1
  • 使用Nginx作为反向代理和负载均衡器
  • RabbitMQ最全教程-Part2(高阶使用)
  • 【Linux系列】Linux 系统中的软连接管理
  • 科学教育与少儿编程:同向同行,共育新时代科技人才
  • RabbitMQ的解耦、异步、削峰是什么?
  • java医院绩效管理系统源码,采用B/S架构,开发工具:maven、Visual Studio Code,医院绩效管理系统数据流程解析
  • 使用 Docker Compose 将数据版 LobeChat 服务端部署
  • 无人机高山景区物资吊运技术及前景分析
  • 【OJ题解】C++实现反转字符串中的每个单词
  • 拿不到kafka消息可能是什么原因?
  • 图像压缩——图像压缩的保真度准则与压缩性能参数
  • 【那些年踩过的坑-前端篇- Mac版本】npm init vite 失败,报错`CERT_HAS_EXPIRED npm ERR