using aero.animation for video - matlab

I'm trying to use aero.animation to animate a missile motion in matlab.
When I use the following code it plays the video but saves only the first frame.
*data is in form of [time, x, y, angle] matrix where all time, x, y and angle are nx1 vectors which I calculated beforehand. In my case n = 1312 and I've taken x and y as zeros of column vectors. angle is the fifth column of SOLUTION which is a matrix of 1312x7, I had calculate before.
data = [time, zeros(length(time), 1), zeros(length(time), 1), SOLUTION(:, 5)];
h=Aero.Animation;
f=figure;
h.Figure=f;
h.initialize();
h.FramesPerSecond=10
h.TimeScaling = 5;
idx1=h.createBody('testrocket.ac','ac');
h.bodies{1}.TimeseriesSourceType='Array3DoF';
h.bodies{1}.timeseriesSource=data;
h.Camera.offset=[-150 -150 0];
h.show()
h.VideoRecord = 'on';
h.VideoQuality = 50;
h.VideoCompression = 'Motion JPEG AVI'
h.VideoFilename = 'astMotion_JPEG';
h.play()
h.VideoRecord='off';
The code looks like this now, yet the video still recording same image for few seconds insted of recording the actual video with the missile movment. ( when i play the record video it shows like frozen situation).
Thanks.

I have found a solution but you have to know the time duration of your animation.
Now your problem is caused by running h.VideoRecord = 'off'; command shortly after h.play command but h.VideoRecord = 'off'; command doesn' t wait for the previous command finish. Anyway you can use pause() function to avoid the problem.
% // ...
h.play()
pause(timeDurationOfAnimation) % // timeDurationOfAnimation -> time unit in seconds
h.VideoRecord = 'off';
EDIT: Time duration of animation/video depends on you specified values of FramesPerSecond and TimeScaling properties.
The combination of FramesPerSecond and TimeScaling property determine the time step of the simulation. Your settings result in a time step of approximately 0.5 s.
+++ More Explanation:
My data is 100x4 matrix means length of time vector is 100. Time resolution is 0.1 second so time vector like that Time = [0, 0.1, 0.2, 0.3, ..., 9.8, 9.9, 10]'. If I use your time set up which is FramesPerSecond = 10 and TimeScaling = 5, I get 2 seconds of video. Because TimeScaling = 5 means display 5 data pack in per second, but one data pack contains 10 frames so according to your set up animation displays 50 frame per second. My whole data contains 100 frames so 100/50 = 2 seconds so time duration of animation/video is 2 seconds. Remember TimeScaling is due to speeding up the animation and you record your animation as speeded up one.
My suggestion is that specify value of FramesPerSecond according to frequency of your Time update:
% // ...
h.FramesPerSecond = 1 / ( data(2, 1) - data(1, 1) ) % // According to my Time resolution that would be 10;
h.TimeScaling = 1;
% // ...
pause( data(end, 1) )
h.VideoRecord = 'off';

Related

How to increase time by 1s and replace old DT_i with the new one

I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end

What's wrong with my code in Matlab?

I want to play all frequencies given in matrix(FrTm) with its duration.The actual duration is one second but each frequency has to play for 3 of 1/18 and 6 of 1/18 seocnd such as given in matrix(FrTm).
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
t=0:1/18:1;
for i=1:length(FrTm),
M(i)=FrTm(i);
Z=M(i);
data= sin(2*pi*Z/Fs*t);
signal=[data;signal];
end
stem(Signal);
sound (Signal, 44100);
end
The classical way to make a sound with a given frequency (f) and sample frequency (Fs) is to make a time vector with step 1/Fs:
time = 0:1/Fs:D;
Where Dis the duration of the signal. The signal itself is then:
signal = sin(2*pi*f.*time)
In this case the total time is fixed, not the time of each signal. The total time is denoted with T, and the total time vector is made as
time = 0:1/Fs:T;
The sum of the second column is the total number of units the vector time needs to be divided in, e.g. 50, 3 means that a signal at 50 Hz needs to be played for 3 units. This means we only need a time vector of the length of 3 units:
t = time(1:floor(end*duration/s));
Where duration is the number of units for this part and s is the total number of units. The signal is then simply, as stated above,
data = sin(2*pi*f*t);
The data is then appended to the whole signal. The complete code, looks like this:
Fs = 44100; % sample frequency [Hz]
T = 3; % total duration [s]
time = 0:1/Fs:T;
% matrix with frequencies and duration
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
s = sum(FrTm(:,2));
[m, ~] = size(FrTm);
signal = [];
for i=1:m
freq = FrTm(i,1);
duration = FrTm(i,2);
t = time(1:floor(end*duration/s));
data = 10*sin(2*pi*freq.*t);
signal = [data signal];
end
stem(signal);
sound(signal, 44100);
Note instead of declaring time in the beginning, it is possible to make a new vector each time you run through the loop. In that case omit time = 0:1/Fs:T; and change t = time(1:floor(end*duration/s)); to t = 0:1/Fs:floor(end*duration/s);
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50 3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm),
%---------------------------------------------------
% complete the function
freq = FrTm(i,1);
duration = FrTm(i,2);
time =0:1/Fs:1; % change the 1 to change total duration
s = sum(FrTm(:,2));
t = time(1:floor(end*duration/s));
data = sin(2*pi*freq.*t);
Signal = [data Signal];
end
stem(Signal);
sound (Signal, 44100);
end
This is the exact code what i wanted ViG can you please remove this tak tak sound it just a noise actually how to use envelope function to remove thid tak tak sound in music code is following.
Fs=44100;
T=1/Fs;
M=zeros(1,88);
for I=7:88
M(I)=round(36.8*(2^(1/12))^(I-6));
end
signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm)
x=FrTm(i,1);
y=FrTm(i,2);
F=M(x);
time=0:1/Fs:y/18;
sinewave=sin(2*pi*F*time);
signal=[signal sinewave];
end
stem(signal)
sound(signal,Fs)

MATLAB scrolling plot

I have an EEG data base that I would like to plot.
The database is a 19*1000*134 matrix, with:
19 being the number of channel. On a first approach, I'm working with only one channel.
1000 the size of a sample (1000 points for a sampling rate of 500 Hz, i.e. 2 sec of data)
134 the number of epochs (number of different 2 second experience)
The idea is to plot epoch n right after epoch n-1 on the same graph. The (X,Y) matrix used to plot this has a 134 000 * not_much size, and I would like to be able to scroll horizontally on the plot, to see individually each epoch.
My code right now, plotting only one channel:
fs = s_EEG.sampling_rate;
[channel, length, nb_epoch] = size(s_EEG.data)
display(s_EEG.data, fs, length, channel, nb_epoch)
function display(data, fs, length, channel, nb_epoch)
figure("Name", "Epoch display")
for j = 1:nb_epoch
time = 0.002+(2*j-2):1/fs:2*j;
epoch = data(1,:,j);
plot(time, epoch)
hold on
end
hold off
end
Current output:
I'm completely new to Matlab, and I don't use it well yet, but I would like to find a way to see on the same graph, individually, and at a correct visualization scale, all of my 134 epochs (one color = one epoch above).
Thanks !
This is very similar to something I already had so I tweaked it a bit for you. Basically pass plotData your data matrix. It will plot each of your items sequentially as you already have now.
Pressing the slider will change your x-limits so that you will step through 1 element (epochs) at a time. Clicking in the area will advance 2-epochs at a time. It currently just displays what you currently viewed "epoch" # is at the command line disp(['Current Epoch: ' num2str(viewI)]) However, it should be easy for you to redirect that to a text box on the figure to more readily know which you are viewing ... besides mentally dividing the x-limits by 2.
Use the list box to switch to a new channel which will reset the plot & x-limits.
Call it like this at the command line.
>> plotData( data )
CODE: Save everything below as plotData.m
function plotData( data )
% data = rand(19,1000,134);
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a = axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s = uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
'Min',1,'Max',size(data,3),'Value',1, 'Callback',{#sliderChange,a} );
l = uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
'String',cellstr(num2str([1:size(data,1)]')),'Callback',{#changeChannel,a,s,data} );
stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];
changeChannel(l,[],a,s,data)
function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.String{l.Value});
sR = 500; %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position
function sliderChange(s,evtData,a)
viewI = round(s.Value);
disp(['Current Epoch: ' num2str(viewI)])
xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])
Note: This uses implicit expansion so you need Matlab 2016b or higher.

glitch when I try to crossfade between two sinusoidal signals back and forth in Matlab

I'm trying to create some functions in Matlab that is going to record a tone and then play it back semi-continuous. For example I want the user to be able to whistle for 2 seconds and the whistle to be dragged out to 10 seconds. I want to avoid using fancy time stretch algorithms but just use this through repetitions. I know there's issues with this but I'm doing this for experiment.
To do this, I need to crossfade the beginning and end of the sound to make it seem continuous. I have written a crossfade function that takes two signals and fades between them.
The idea is to have a sigmoid volume function that goes from 1 to 0 for the old sound and 0 to 1 for the new. I then just multiply the signal by this volume function and add the result. My understanding of the sigmoid function is that the resulting volume should be an average of the two input signals, with weight slowly moving from input signal a to input signal b, and the output amplitude should be the same as the input ones.
When I try this with two simple sinusoid input signals, however, and go back and forth between a low and high tone, I get a small "glitch" in the section just where it transfers from a low-to-high section, to a high-to-low sliding section. Where does this come from? I'm also not sure if this is only on my speakers, and I tried watching the plotted waveforms in time domain, but couldn't see anything weird happening at the specific time.
The end of the first section, and beginning of the last should have exactly the same frequency component, and nothing is moved in time, so I'm not sure where this glitch comes from.
Sample code:
(SLIGHT WARNING: This output some tones, one of which is a little bit high pitch, so maybe not play this with earphones on or with full volume).
function test()
Fs=44100;
x=1:1/Fs:2;
x=x'; %time vector
freq1 = 440; %low tone
freq2 = freq1*2^(7/12) % high tone (harmonic fifth)
Fs=44100;
x=1:1/Fs:2;
x=x'; %time vector
freq1 = 440; %low tone
freq2 = freq1*2^(7/12); % high tone (harmonic fifth)
y1 = sin(2*pi*x*freq1)
y2 = sin(2*pi*x*freq2)
res = stitchandrepeat(y1,y2, Fs);
end
function [out] = stitchandrepeat(in, in2, Fs)
lowtohigh = crossfade(in,in2,1);
hightolow = crossfade(in2,in,1);
out = [lowtohigh;hightolow];
out = [out;out];
out = [out;out];
out = [out;out];
end
function [out] = crossfade(a, b, sigmoid)
if not(size(a) == size(b))
error('Different sizes');
end
index = (1:size(a,1))';
factor = index/size(a,1);
if(sigmoid)
steepness = 5;
factor = logsig((factor-0.5)*steepness*2);
end
plot(index, factor, 'o');
out = bsxfun(#times, a, 1-factor)+bsxfun(#times, b, factor);
end
I even tried doing a second crossfade where I stitched together the end and beginning of the first and second signal, but it still sounded a little bit weird just in the transition. Any idea on how to make the transition smooth?
function [out] = stitchandrepeat2(in, in2, Fs)
lowtohigh = crossfade(in,in2,1);
hightolow = crossfade(in2,in,1);
secstofade = 0.1;
len = size(lowtohigh,1);
partsize = secstofade*Fs;
lthpart = lowtohigh((len-partsize+1):len,:);
htlpart = hightolow(1:partsize,:);
lthcropped = lowtohigh(1:len-partsize,:);
htlcropped = hightolow(partsize+1:len,:);
highfade = crossfade(htlpart, lthpart,1);
out = [lthcropped;highfade;htlcropped];
out = [out;out];
out = [out;out];
out = [out;out];
end
And how come I don't get this glitch sound in the low part of the sound? (Two different sound waves are also just concatenated there.)

creating fast successive beeps in matlab/psychtoolbox

I have to create beep arrays of differing numerosity. I determine how many beeps will be
played, the duration of each individual beep and the inter-beep duration online. However,
these all have to be played really fast, both the intervals and the durations will be in between 0.01secs-0.2secs. The sound function of matlab does not allow you to take very small breaks in between as even if you play two sound functions one after each other without putting a small break by a timer, it takes longer than the timing I need. Any ideas? I would really appreciate any help...
To guarantee a given spacing, I think that you need to assemble the waveform. I suspect a lot of variation in the time it takes to startup the sound function.
As an example, the function below should give you a good start:
function beep_series(specs)
%BEEP_SERIES Create a series of beeps
% BEEP_SERIES([FREQ_HZ, VOL, DUR_SEC, PAUSE_SEC]) creates a series of
% beeps from an N-by-4 spec matrix, where the colums represent:
% frequency
% volumne (0-1)
% beep duration
% pause duration,
freq = specs(:,1);
volume = specs(:,2);
duration = specs(:,3);
trailingGap = specs(:,4);
SAMPLE_FREQ = 8192;
totalTime = sum(duration) + sum(trailingGap);
x = zeros(ceil(totalTime*SAMPLE_FREQ),1);
curBeepStartTime = 0;
for ix = 1:length(freq)
numSamples = round(duration(ix)*SAMPLE_FREQ);
x( round(curBeepStartTime*SAMPLE_FREQ + (1:numSamples)) ) = ...
volume(ix) * sin( (1:numSamples) * (2*pi*freq(ix)/SAMPLE_FREQ) );
curBeepStartTime = curBeepStartTime + duration(ix) + trailingGap(ix);
end
sound(x, SAMPLE_FREQ)