Y-BH

half_cycle_model

May 13th, 2020
3,988
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 5.11 KB | None | 0 0
  1. % 质点离开竖直光滑半圆轨道的轨迹
  2. % 如运行有问题,建议使用R2020a或较新版本
  3. % R2016a或较旧版本请将微分方程函数、事件函数单独存为脚本函数
  4. % 如需转载此脚本请注明出处:
  5. % @YBH、ssrs@bilibili - https://space.bilibili.com/9943102
  6. clc;clear
  7. close all
  8. path=char('.\pic_seqs\');% 生成的图片序列所在文件夹
  9. if exist(path,'dir')==7
  10.     rmdir(path,'s')% 删除旧文件
  11. end
  12. mkdir(path)
  13. dpi=1.25;% 系统缩放125%
  14. scr=[1920 1080];% 屏幕分辨率
  15. res=[1280 720];% 图像分辨率
  16. R=1;%轨道半径
  17. L=4*R;%水平轨长
  18. g=10;%重力加速度
  19. vu=sqrt(g*R);%单位速度
  20. tu=sqrt(R/g);%单位时间
  21. T=100*tu;%模拟时间上限
  22. %半圆轨道
  23. tht=-0.5*pi:0.01:0.5*pi;
  24. xc=R*cos(tht);yc=R+R*sin(tht);
  25. %圆轨道
  26. tht=-pi:0.01:pi;
  27. xo=R*cos(tht);yo=R+R*sin(tht);
  28. % 此脚本目的为生成演示动画,
  29. % 常见视频分辨率为1920x1080或1280x720等等
  30. % 一个像素点以下的误差几乎不能察觉,故精度在1e-3即可
  31. % 考虑到误差积累,保守起见至少设为1e-4 /
  32. % 实测至少x_0=0 --> 1e-5;x_0=-L --> 1e-6
  33. odest=odeset('RelTol',1e-7,'AbsTol',1e-7,'NormControl','on',...
  34.     'MaxStep',tu*1e-2,'InitialStep',tu*1e-2,...
  35.     'Stats','off','Events',@(t,y) luodi_evns(t,y,R));
  36. v1=sqrt(2);%恰好到达圆轨道半高的速度
  37. v2=sqrt(5);%恰好经过圆轨道顶点的速度
  38. v3=sqrt(7/2);%恰好落在圆轨道底部的速度
  39. % 恰好通过最高点轨迹
  40. v=v2*vu;
  41. [~,yd] = ode45(@(t,y) half_c(t,y,g,R),[0 T],[0 0 -0.5*pi v v 0]',odest);
  42. % 恰好落至圆轨道底部轨迹
  43. v=v3*vu;
  44. [~,yb] = ode45(@(t,y) half_c(t,y,g,R),...
  45.     [0 T],[0 0 -0.5*pi v v 0]',odest);
  46. sizem=0;tmax=0;
  47. N1=1;N=16;%小球个数
  48. % 微分方程数值计算
  49. for ii=N1:N
  50.     v0=sqrt(ii/2)*vu;%初速度
  51.     eval(['[t,y',num2str(ii),']',...
  52.         ' = ode45(@(t,y) half_c(t,y,g,R),',...
  53.         '[0 T],[0 0 -0.5*pi v0 v0 0]'',odest);']);
  54.     eval(['t',num2str(ii), ' = t;']);
  55.     tmax=max(tmax,max(t));%终止模拟时间
  56.     sizem=max(sizem,size(t,1));%最大数组长度
  57. end
  58. % 最大数组不一定对应最大时间!!!
  59. % 数组填充对齐/与最大的数组对齐
  60. tmaxp=tmax*1.1;sizemp=fix(1.1*sizem);
  61. for ii=N1:N
  62.     % 计算每个size(y_ii,1)=sizei
  63.     eval(['sizei=size(y',num2str(ii),',1);']);
  64.     % 计算每个max(t_ii)=tim
  65.     eval(['tim=max(t',num2str(ii),');']);
  66.     % t对齐t-->tf / 线性填充
  67.     eval(['tf',num2str(ii),'=[t',num2str(ii),...
  68.         '(1:sizei-1);linspace(tim,tmaxp,sizemp-sizei+1)''];']);
  69.     % y对齐y-->yf / 拖尾填充
  70.     eval(['yf',num2str(ii),'=[y',num2str(ii),...
  71.         ';zeros(sizemp-sizei,6)+y',num2str(ii),'(sizei,:)];']);
  72. end
  73. % 按基准时间线插值
  74. fps=120;%帧率
  75. frames=fix(fps*tmaxp);%总帧数
  76. ti=linspace(0,tmaxp,frames)';% 等间隔的基准时间线
  77. % yi=interp1(tf,yf,ti)
  78. for ii=N1:N
  79.     eval(['yi',num2str(ii),'=interp1(tf',num2str(ii),...
  80.         ',yf',num2str(ii),',ti,''linear'');']);
  81. end
  82. % 模型绘图
  83. for n=1:frames
  84.     %半圆轨道
  85.     plot(xc,yc,'Color','k','LineWidth',4)
  86.     hold on
  87.     axis equal
  88.     axis tight
  89. %     axis off
  90.     % 圆轨道
  91.     plot(xo,yo,'-.','Color','k','LineWidth',0.5)
  92.     %水平轨道
  93.     line([-L 0],[0 0],'linestyle','-','Color','k','LineWidth',4)
  94.     % 小球位置及运动轨迹
  95.     for kk=N:-1:N1
  96.         eval(['plot(yi',num2str(kk),'(n,1),yi',num2str(kk),...
  97.             '(n,2),''.'',''markersize'',40)'])% 小球位置
  98.         eval(['plot(yi',num2str(kk),'(1:n,1),yi',num2str(kk),...
  99.             '(1:n,2),''-'',''LineWidth'',2)'])% 小球轨迹
  100.     end
  101.     % 恰好通过最高点轨迹
  102.     pd=plot(yd(:,1),yd(:,2),...
  103.         '--','Color','#444444','LineWidth',1.5);
  104.     % 恰好落至圆轨道底部轨迹
  105.     pb=plot(yb(:,1),yb(:,2),...
  106.         '-','Color','#444444','LineWidth',1);
  107.     legend([pd,pb],{'恰好通过最高点轨迹','恰好落至圆轨道底部轨迹'},...
  108.         'FontSize',16,'FontName','黑体','Location','northwest');
  109.     legend('boxoff')
  110.     hold off
  111.     set(gcf,'Color','w');% 设置白色背景
  112.     fig=gcf;
  113.     fig.Units = 'pixel';
  114.     fig.Position = [(scr-res)/2,res]/dpi;% 居中显示
  115.     m(n)=getframe(fig);% 获取当前图像
  116.     imwrite(m(n).cdata,[path,num2str(n),'.png']);% 保存图像为png
  117. end
  118. % 微分方程
  119. function dydt = half_c(~,y,g,R)
  120. a=y(4)^2/R;% 向心加速度
  121. if y(2)==0 && y(1)<0
  122.     dx=y(4);
  123.     dy=0;
  124.     dtheta=0;
  125.     dv=0;
  126.     dvx=0;
  127.     dvy=0;
  128. else
  129.     if y(1)>=0 && g*sin(y(3))<a
  130.         dx=-y(4)*sin(y(3));
  131.         dy=y(4)*cos(y(3));
  132.         dtheta=y(4)/R;
  133.         dv=-g*cos(y(3));
  134.         dvx=-a*cos(y(3))-dv*sin(y(3));
  135.         dvy=-a*sin(y(3))+dv*cos(y(3));
  136.     else
  137.         dx=y(5);
  138.         dy=y(6);
  139.         dtheta=0;%记录脱离时角度,同dv=0
  140.         dv=0;%不再计算v,v保持脱离时的速度,同dtheta=0
  141.         dvx=0;
  142.         dvy=-g;
  143.     end
  144. end
  145. dydt=[dx dy dtheta dv dvx dvy]';% 需为列向量
  146. end
  147. % 事件函数
  148. function [position,isterminal,direction] = luodi_evns(~,y,R)
  149. if y(1)>0 && y(2)<R && y(3)>0
  150.     position = y(2)+sqrt(R^2-y(1)^2)-R;% 落在圆轨道
  151. else
  152.     position = y(2);% 落回水平面
  153. end
  154. isterminal = 1;
  155. direction = -1;
  156. end
Add Comment
Please, Sign In to add comment