% Demonstrate simple harmonic motion.
%
% Author: AdamTurner, 2021.04.
% Copyright reserved.
% Written in MATLAB R2018a.
function SimpleHarmonicMotion(cmd0)
persistent nShow nPeriod t dt tPeriod tShow x v m c k hFuncForce hFuncKinetic odeOption;
persistent hFigure hAxes hTimer;
if isempty(cmd0)
cmd0 = 'Init';
end % /* if isempty(cmd0) */
switch cmd0
case 'Init'
m = 1.000;
c = 0.000;
k = 10.000;
hFuncForce = @(t) (0.000);
hFuncKinetic = @(t, Y) ([Y(2); (hFuncForce(t) - c * Y(2) - k * Y(1)) / m]);
dt = 0.001;
tPeriod = 0.100;
tShow = 5.000;
nPeriod = round(tPeriod / dt) + 1;
nShow = round(tShow / dt) + 1;
t = zeros(nShow, 1);
t(:) = NaN;
x = t;
v = t;
t(end) = 0.000;
x(end) = 1.000;
v(end) = 0.000;
odeOption = ...
struct('AbsTol', 1.000e-4, ...
'RelTol', 1.000e-3);
hFigure = ...
figure('Name', 'Harmonic Motion', ...
'NumberTitle', 'off', ...
'Resize', 'off', ...
'Units', 'pixel', ...
'DeleteFcn', @DeleteFigure);
hAxes = ...
axes(hFigure, ...
'Box', 'on', ...
'NextPlot', 'add'博彩游戏, ...
'Units'博彩游戏, 'pixel', ...
'XLimMode', 'manual', 'XLim', [-1.000, tShow], ...
'YLimMode', 'manual', 'YLim', [-2.000, 2.000], ...
'XTickMode', 'manual', 'XTick', [], ...
'YTickMode', 'manual', 'YTick', [], ...
'XLabelMode', 'manual', 'XLabel', {}, ...
'YLabelMode', 'manual', 'YLabel', {});
hTimer = ...
timer('BusyMode', 'drop', ...
'ExecutionMode', 'fixedRate', ...
'Period', tPeriod, ...
'TasksToExecute', Inf, ...
'TimerFcn', @RunHarmonicMotion);
Render();
start(hTimer);
otherwise
error('Unknown command!');
end % /* switch cmd0 */
%% ========== Function(s) ========== %%
function DeleteFigure(source, event)
stop(hTimer);
delete(hTimer);
delete(source);
end % /* DeleteFigure */
function RunHarmonicMotion(source, event)
tSpan = (t(end) : dt : (t(end) + tPeriod)).';
Y0 = [x(end); v(end)];
[t1, Y1] = ...
ode45(hFuncKinetic, tSpan, Y0, odeOption);
t = [t((nPeriod) : (end - 1)); t1];
x = [x((nPeriod) : (end - 1)); Y1(:, 1)];
v = [v((nPeriod) : (end - 1)); Y1(:, 2)];
Render();
end % /* RunHarmonicMotion */
function Render()
% Plot the spring.
xySpring = ...
[0.000, x(end); ...
[[0.000; 0.250; -0.250; 0.250; -0.250; 0.250; -0.250; 0.250; -0.250; 0.000], ...
x(end) + 0.200 + [0; 1; 3; 5; 7; 9; 11; 13; 15; 16] * 0.062500 * (1.600 - x(end))]; ...
0.000, 2.000];
hSpring = findobj(hAxes, 'Tag', 'Spring');
if isempty(hSpring)
hSpring = ...
plot(hAxes, xySpring(:, 1), xySpring(:, 2), ...
'LineWidth', 1.500, 'LineStyle', '-', 'Color', 'black', ...
'Tag', 'Spring');
else
hSpring.XData = xySpring(:, 1);
hSpring.YData = xySpring(:, 2);
end % /* if isempty(hSpring) */
% Plot the trajectory.
hTrajectory = findobj(hAxes, 'Tag', 'Trajectory');
if isempty(hTrajectory)
hTrajectory = ...
plot(hAxes, t(end) - t, x, ...
'LineWidth', 1.500, 'LineStyle', '-', 'Color', 'blue', ...
'Tag', 'Trajectory');
else
hTrajectory.XData = t(end) - t;
hTrajectory.YData = x;
end % /* if isempty(hTrajectory) */
% Plot the vibrator.
hVibrator = findobj(hAxes, 'Tag', 'Vibrator');
if isempty(hVibrator)
hVibrator = ...
plot(hAxes, 0.000, x(end), ...
'LineStyle', 'none', ...
'Marker', 'o', 'MarkerSize', 16, 'MarkerFaceColor', 'white', 'MarkerEdgeColor', 'red', ...
'Tag', 'Vibrator');
else
hVibrator.YData = x(end);
end % /* if isempty(hVibrator) */
drawnow limitrate;
end % /* Render */
end % /* SimpleHarmonicMotion */