Send only one value from a constant block - constants

I thought this should be fairly simple, I really have no idea what went wrong, been trying for a week, gosh!! so ashamed of myself.
I define the following at Workspace: I=[5 5.1 5.2 5.2]; V=[95 80 85 20];
I expect an output like this: at t=0, arr=20, at t=1, arr=30, at t=0, arr=40,
When I run the simulation, what I got is: at t=0, arr=20, 0, 0, 0, at t=1, arr=0, 10, 0, 0, at t=2, arr=0, 0, 10, 0,
There are few problems with this result: 1. I expect only one arr value at a particular time, but it came out four arr values at a time
I wonder why the arr never adds up to 30 and 40 etc
My system is as follow: http://imgur.com/nEKDqqS
The codes are here: http://imgur.com/Cipjbyn

You need to use a "From workspace" block. That will help you send different values at each time step. You can specify your data for the block as a parameter. The block dialog shows you the format for this parameter. If you have DSP System toolbox, using "Signal From workspace" block will make this even simpler. All you need is to provide a vector of data and one value will be picked up at each time step. The doc for these two blocks are at
http://www.mathworks.com/help/simulink/slref/fromworkspace.html
http://www.mathworks.com/help/dsp/ref/signalfromworkspace.html

If you don't want to input your values from the workspace and you want to stay in Simulink:
Use the Signal Builder source block. When you double-click on it you can create signals graphically.
For example:

Related

Loop live update Julia plot

I'm brand new to Julia (v1.7.1) and I've been using VSCode as an IDE. In VSCode (v1.64) I've installed the Julia Extension (v1.5.10). When plotting in VSCode, the plot shows up in the plot pane by default. I'm using the Plots (v1.25.7) package and the "gr" backend, as it's one of the "faster" options.
I'm trying to make a "live" time series plot, in which the series is updated in a loop. This seems to be a popular problem, as there are many questions addressing this, but I've found no "clean" solution yet. I should emphasize that I'm not trying to make an animation, which is fabricated upon termination of the loop. I want to update the plot as the loop is running. I've looked at SmoothLivePlot, but I think this requires that I know the series size before hand, which is not the case in my application. Then again, maybe I'm misinterpreting the package.
I'm going to present what I've done this far, with hopes for improvement. I first created a plotting function
function plt_update(p,time_series,var_series)
plot!(time_series, var_series,
label = "",
linecolor = :red)
display(p)
end
Then I initialized the plot
model_time = 100
p = plot([0.0],[0.0],
label = "",
linecolor = :red,
xlims = (0, model_time),
ylims = (0, 1),
display(p)
My loop is then called (NOTE: that all the code shown in this post is wrapped in a function and run in the RPEL, hence variables do not need to be defined with "global" inside the while loop. This is due to Julia's optimization and scope design...from what I've read. See another discussion on this for an example).
run_time = 0.0
time_series = [0.0]
var_series = [0.0]
while run_time < model_time
# Calculate new timestep
timestep = rand(Float64) # Be sure to add Random
run_time += timestep
# Computations
sleep(timestep/10)
# Build vector
push!(time_series,run_time)
push!(var_series,timestep)
# Live plots
plt_update(p,time_series,var_series)
end
I've encountered a few problems with this. First, I don't know if this is just an issue with VSCode or who to point the finger at, but putting display(p) inside the function to update the plot in the VSCode plot pane ends up creating a new plot for each iteration in the loop. Clearly this is not what is intended. I found that if I shut off the "plot in pane" option (File > Preferences > Settings > Extensions > Julia), then a single plot window is created. I'm not sure if "create new plot in pane" is expected or an issue (again, I'm new to this). Nevertheless, when plotting outside the VSCode, the above code works as I expected.
For the next issue, which I think is most important here, is that inside the plotting function, the call to plot! adds a new vector to p, while saving the previous one as well. In other words, p is not being updated with the new series, it is growing by appending a whole new vector. This is clear as the plotting comes to a grinding halt after many iterations. Also, if you remove the "color" attribute, you'll see the line changes color with each iteration. In effect, what is being plotted is many lines, all overlapping.
I then dove into p to look more closely at what is going on and made some changes to the plotting function
function plt_update(p,time_series,var_series)
push!(p.series_list[1].plotattributes[:x],time_series[:][end])
push!(p.series_list[1].plotattributes[:y],var_series[:][end])
display(p)
end
Above, instead of creating a new series_list (as was the case before w/ plot!), I'm now updating the series w/ the new data. This works much better than before and behaves as expected. While it's only a slight improvement, I've further modified the function and the function call by passing a scalar instead of a vecotr
function plt_update(p,run_time,variable)
push!(p.series_list[1].plotattributes[:x],run_time)
push!(p.series_list[1].plotattributes[:y],variable)
display(p)
end
in which the function call is now plt_update(p,run_time,timestep). As you can see, I sleep for a random time then divide that by 10, which I found to be about as much lag as I can afford before it loses it's "near realtime" appeal. Dividing by 100, for example, results in rather noticeable lag.
So my question is...is there a way to improve this, where the lag is reduced? Being new to Julia, I'm not aware of all the plotting options or how to access the "guts" to make improvements on my own.
EDIT:
I've just become aware of "Makie" and "Observables". I'm going to do a bit more research on those to see if this offers an improvement in the latency.
EDIT2:
In my research, I found a much cleaner way to express the last function (also see here for further confirmation of the approach)
function plt_update(p,run_time,variable)
push!(p,1,run_time,variable)
display(p)
end
The solution I found w/ Makie & observables is without a doubt the best! Between the YouTube video and code, I was able to apply it to my example above. Granted, my loop is only ~150 iterations, there is negligible lag (which was far from the case prior). Taking out the sleep function, the plot is instantaneous. I would encourage others to try this approach for "near real-time" plots.
The packages needed are
using GLMakie
using GeometryTypes
I'm not sure if GeometryTypes is needed explicitly (I thought GLMakie would bring in the necessary libs), but I was getting an error stating that Point2f0 was not found.
First, create the observable (note that it's a vector of type Point2f0)
pt_series = Observable([Point2f0(0, 0)])
Then initialize the plot
fig = Figure(); display(fig)
ax = Axis(fig[1,1])
lines!(ax, pt_series; linewidth = 4, color = :purple)
# Static elements
ax.title = "Time Series"
ax.xlabel = "Time (s)"
ax.ylabel = "Data"
xlims!(ax, 0, 100)
ylims!(ax, 0, 1)
Then run the loop
model_time = 100
run_time = 0.0
while run_time < model_time
# Calculate new timestep
timestep = rand(Float64)
run_time += timestep
# Computations
#sleep(timestep/1000)
# Live plots
push!(pt_series[], Point2f0(run_time, timestep))
pt_series[] = pt_series[]
end
As I stated in the question, all of the code above should be wrapped in a function to prevent scoping errors.

Store signal values, output as vector for function input

Im trying to do some calculations in a Matlab (R2015b) Simulink function block. I use a signal that gives discrete values in 1-minute intervals.
What i want to do is store the signal values of 1 day (1440 values), convert them into a vector and input it in my Matlab function for calculation (getting time between first and last value > x). All while the simulation is running.
Unit delay, and Transport delay blocks wont work because i need all the stored values at once.
Any ideas on this are much appreciated!
Thanks!
You need to add a "To Workspace" block to your simulink diagram. Setting the options as you wish will allow you to save all the outputs in a single vector. You can select the variable's name, and the default is "simout".
Then, after running the diagram, you have the variable you want in the workspace (as if you had typed it in the console). So next, you can call your function with the argument.

How to call simulink model(.slx) from script

I'm a super beginner in Simulink models and control systems.
I have .slx Simulink model for drone dynamics system.
It takes in two inputs (roll cmd, pitch cmd) and outputs velocity x, velocity y, position x, and position y.
From here, it seems like I can open the system by calling
open_system('myModel.slx', 'loadable');
But how do I put inputs and get output values?
Is there a way I can do this in a gui?
EDIT:
Here is the full layout of my model:
When I did
roll_CMD=10;
pitch_CMD=20;
I got a warning saying:
Input port 1 of 'SimpleDroneDynamics/...' is not connected.
How do I feed inputs using port numbers?
How do I get outputs with port numbers? I tried
[vx, vy, px, py] = sim('SimpleDroneDynamics.slx');
and got an error saying
Number of left-hand side argument doesn't match block diagram...
Is there a way to continuously feed inputs at every time step? This being controller module, I think I'm supposed to feed in different values based on output position and velocity.
EDIT2:
I'm using Matlab2017a
About the first two points of your question:
In simulink:
For the inputs you can use a constant block and when you double click the input block you can assign a value, which can be a workspace variable.
To get the outputs to your workspace you can use the simout block (make sure to put Save format to array).
Connect inputs to your simulink model
Connect outputs of your simulink model to the simout blocks.
MATLAB script
clc;
clear all;
roll = 10;
pitch = 20;
sim('/path_to_simulinkmodel.slx')
time = simout(:,1);
velocity_X = simout(:,2);
velocity_Y = simout(:,3);
position_X = simout(:,4);
position_Y = simout(:,5);
About the third point of your question
You can define the duration of your simulation in the block diagram editor. You can put a variable which is defined in the calling script. There are multiple ways of achieving time dependent input variables:
One option I personally don't recommend is using a for-loop and calling the simulink model with a different value of roll and pitch
for i = 1:numberOfTimesteps
roll = ...
...
sim('simulinkModel.slx')
end
A second and more efficient approach is changing the constant blocks to other source blocks like ramp signals or sinusoid signals
First of all Simulink model use main Matlab workspace. So you can change your variables values at command window (or just at your script) and run Simulink model.
There are several ways to initialize this constants for Simulink. One more useful way is to create script containing all your variables and load it at Simulink model starts. You can do it by adding script name in Simulink/Model Explorer/Callbacks. (There are different callbacks - on Loading, on Starting and etc.). Read more about this: here.
Now you can run your simulation using sim function:
sim('name_of_model')
name_of_model must contain path if model is not in the active MATLAB folder (active folder you can see in your matlab window just under the main menu).
There are different properties of sim function, read about them in help this can be useful for you. By the way: you can change some parameters of your model using sim. You even can find any block in your model and change it's properties. Read more about sim and about finding current blocks. Interesting that the last solution give you ability to change parameters during the simulation!
About getting output. After you run simulation you get tout variable in main workspace. It is an array of timesteps. But if you add outport block (like at my image) you also get another variable in workspace yout. yout is an Datasets. It contain all your outports values. For 2 outports for example:
yout
yout =
Simulink.SimulationData.Dataset
Package: Simulink.SimulationData
Characteristics:
Name: 'yout'
Total Elements: 2
Elements:
1 : ''
2 : ''
Get the values of any of outports:
yout.get(1).Values
it is a timeseries data type, so:
yout.get(1).Values.Time - give you times
yout.get(2).Values.Data - give you values of this outport at each time
We have one more method to take output values:
[t,x,y] = sim('model_name')
it returns double arrays. t- time array, y - matrix of all outports values (it already double and contain only values without times, but for each simulation time!)
So now you can create common Matlab GUI and work at this variables! There is no any difficulties. You can read more about GUI for Simulink here.

MATLAB - EEGLAB: surpress GUI for pop_eegfiltnew()

I am working on some scripts for which I use several functions from the EEGLAB package for matlab. Most of these functions make it possible to surpress the GUI from showing, for example using f( ... 'gui','off'), or by using a different version of the same function. However, I can not figure out how to do this for the function pop_eegfiltnew(). Two similar functions are eegfilt(), which seems to be an outdated version of the function, and firfilt() however, pop_eegfiltnew() has more arguments than these other two, so they are certainly not the same in functional terms.
Anyone knows how to get around this?
If you supply enough arguments to pop_eegfiltnew it does not pop up a GUI.
For example if you wanted to filter your signal 1 Hz highpass you would:
EEG = pop_eegfiltnew(EEG, 1, 0);
This is because the first argument of pop_eegfilt is EEG structure, the second is locutoff (lower edge of the passband) and the third is hicutoff (higher edge of the passband).

using from workspace block in simulink

how to use the "from workspace block in simulink" ?
I have tried using the from workspace block by given 10*2 matrix as input. it is appending some extra data along the data I have given .
and I have such 3 such blocks and want to know how I merge them.
Read the documentation. Simulink is time-based so the data in your From Workspace block must be as a function of time. Does your 10 x 2 matrix represent a signal as a function of time? If so, it needs to be as follows:
A two-dimensional matrix:
The first element of each matrix row is a
time stamp.
The rest of each row is a scalar or vector of signal
values.
The leftmost element of each row is the time stamp of the
value(s) in the rest of the row.
10 values isn't very much, it's likely that Simulink will need additional data points at intermediate times, if you have the Interpolate Data check box ticked. If not, "the current output equals the output at the most recent time for which data exists".
I think you may have a misunderstanding of the variables intended to be read by the FromWorkspace block.
The block expects a time series defining the value at various points in the simulation.
The From Workspace block help should point you in the right direction on this. Mathworks Help Documentation
I believe that something like the following would work for you:
>> WorkspaceVar.time=0;
>> WorkspaceVar.signals.values=zeros(10,2)
>> WorkspaceVar.signals.dimensions = [10,2]