Изменение продолжительности / продолжительности времени, которое требуется объекту для завершения вращения в октаве / матлабе - PullRequest
0 голосов
/ 12 марта 2019

Я могу создать вращающуюся сферу, но как мне сделать так, чтобы она выполняла 2 вращения, 3,5 вращения или x вращений за определенное время, например 3 секунды, 25,4 секунды или x секунды?

Код ниже:

% Using rotate
clear all,clf reset,tic,clc, close all
figure
[x,y,z] = sphere(270);

s = surf(x,y,z,z,'EdgeColor','none');
axis vis3d
for ang = 1:360
    rotate(s,[1,1,1],1)
    str_1=strcat('Angle= ', sprintf('%02d',(ang)),'---------','Time in Seconds= ', sprintf('%02d',(toc)));
    title({str_1});

    xlabel('X-axis')
    ylabel('Y-axis')
    zlabel('Z-axis')
    drawnow
end

Rotating sphere

Ps: я использую Octave 5.1, который похож на Matlab

1 Ответ

1 голос
/ 12 марта 2019

Используйте timer

Как сказано в комментариях, единственный способ контролировать время в MATLAB - это использовать их класс timer. Даже если это ограничено, Mathworks прямо заявляет, что вы не можете ожидать точности до миллисекунды.

Следующий код приближается к тому, что вы просили. Он создает таймер, который запускает каждый period и выполняет функцию (которая будет вращать сферу).

Хитрость заключается в том, чтобы определить period (называемый TimeIncrement в коде) и шаг углового вращения, чтобы движение было плавным и достигалось за заданное время.

Даже с таймером, и особенно для малого целевого времени, он не будет точным с точностью до миллисекунды. Я установил minTimeIncrement (на основе моей машины), который используется для ослабления числа оборотов ( увеличение углового шага ) в случае, если TimeIncrement недостаточно для рендеринга одного поворота. Возможно, вам придется настроить его для вашей собственной машины.

%% Create and display the sphere
clear all,clf reset,clc, close all
figure
[x,y,z] = sphere(270) ;
s = surf(x,y,z,z,'EdgeColor','none');
axis vis3d
xlabel('X-axis')
ylabel('Y-axis')
zlabel('Z-axis')

%% Parameters
minTimeIncrement = 0.040 ;  % I worked that out on my machine.
                            % You may have to adjust for your

TotalRotationTime = 3.5 ;   % in second
Nangles = 360 ;             % number of angle rotations to complete a full turn

TimeIncrement    = TotalRotationTime / Nangles ; % Time step between each rotation
AngularIncrement = 360 / Nangles ;               % angle to rotate at each iteration

% Here we make sure to respect the timing. If the number of rotation
% increment does not fit into the total time allowed, the rotation increments
% are extended so they will be less of them.
if TimeIncrement < minTimeIncrement
    warning('Period too small, the angle increment will be adjusted')
    TimeIncrement = minTimeIncrement ;
    Nangles = TotalRotationTime / TimeIncrement ;
    AngularIncrement = 360 / Nangles ;               % angle to rotate at each iteration
end

%% Create the timer and start it
t = timer ;
t.ExecutionMode = 'fixedRate' ;
t.Period   = TimeIncrement ;
t.TimerFcn = @(htimer,evt) UpdateSphere(htimer,evt,s,AngularIncrement) ;
t.StopFcn  = 'delete(t)' ; % for self cleanup
start(t) ;

Редактировать: Извините, только что понял, что забыл опубликовать код для функции обратного вызова. Код для UpdateSphere.m:

function UpdateSphere( ht , evt , s , ang_increment )
%UpdateSphere Rotate the sphere and update the title display

%% Define a few persistent variables
persistent currentAngle ;
persistent StartTime ;

%% Initialise or update persistent variables
if isempty(currentAngle)
    currentAngle = 0 + ang_increment ;
% else
%     currentAngle = currentAngle + ang_increment ;
end
if isempty(StartTime)
    StartTime = tic ;
end

%% do the rotation
% To insure we will not go over 360 degrees
ang_increment = min(ang_increment , 360 - currentAngle) ;
currentAngle = currentAngle + ang_increment ;

rotate(s,[1,1,1],ang_increment)
strTitle = sprintf('Angle = %5.1f ° / Time = %7.3f s',currentAngle,toc(StartTime)) ;
title(strTitle);
drawnow

%% Stop the timer and reset counter if we reached a full rotation
if currentAngle >= 360
    currentAngle = 0 ;
    StartTime = [] ;
    stop(ht) ;
end

end

enter image description here

...