Calculate distance traveled by a vehicle in sumo with traCI4Matlab - matlab

I need some help: I'm trying to calculate the distance traveled by a vehicle I added in TRACI4Matlab in a SUMO scenario at the end of the simulation.
With my code I can calculate the distance but once passed the last node, since there is no more my vehicle in the SUMO scenario the error is thrown:
Error: Answered with error to command 0xa4: Vehicle 'prova' is not known.
this is my MATLAB code:
clear
close all
clc
import traci.constants
[scenarioPath,~,~] = fileparts(which(mfilename));
cd(scenarioPath);
traci.start('sumo-gui -c ./scenario1.sumocfg --start');
SIM_STEPS = [0 1000];
beginTime = SIM_STEPS(1);
duration = SIM_STEPS(2);
endTime = SIM_STEPS(1) + SIM_STEPS(2) - 1;
traci.vehicle.add('prova', 'percorso1', depart='100')
for i = 1 : duration
id{i}=(traci.vehicle.getIDList());
d1(i)=traci.vehicle.getDistance('prova');
traci.simulation.step();
end
traci.close()
How can I continue the simulation or avoid the error?

There is no way to get information via traci about a vehicle which is not in the simulation anymore. You could add a stop to the end of the route or just store the last distance you noticed. A different way of getting total route length would be to generate XML output for instance tripinfo and parse it.

Related

MATLAB how to make nlinfit() not quit out of loop and how to test distribution of results

Given some data (from the function 1/x), I solved for powers of a model function made of the sum of exponentials. I did this for several different samples of data and I want to plot the powers that I find and test to see what type of distribution they have.
My main problems are:
My loops are quitting when the nlinfit() function says the function gives -Inf values. I've tried playing around with initial conditions but can't see how to fix it. I know that I am working with the function 1/x, so there may not be a way around this problem. Is there at least a way to force the loop to keep going after getting this error? It only happens for some iterations. If I manually regenerate my sample data and run it again it works. So if I could force the loop to keep going it would be ideal. I have tried switching the for loop to a while loop and putting a try catch statement inside but this just seems to run endlessly.
I have code set to test how if the distribution of the resulting power is close to the exponential distribution. Is this the correct way to do this? When I add in the Monte Carlo tolerance ('MCTol') it has a drastic effect on p in some cases (going from 0.5 to 0.9). Do I have it set up correctly? Is there a way to also see empirically how far the curve is from the exponential distribution?
Are there better ways to fit this curve or do any of the above? I'm just learning so any suggestions are appreciated.
Here is my current code :
%Function that I use to fit curve and get error for each iteration
function[beta,error] = Fit_and_Calc_Error(T,X,modelfun, beta0)
opts = statset('nlinfit');
opts.RobustWgtFun = 'bisquare';
beta = nlinfit(T,X,modelfun,beta0,opts);
error = immse(X,modelfun(beta,T));
end
%Starting actual loop stuff
tracking_a = zeros();
tracking_error = zeros();
modelfun = #(a,x)(exp(-a(1)*x)+exp(-a(2)*x));
for i = 1:60
%make new random data
x = 20*rand(300,1)+1; %between 1 and 21 (Avoiding x=0)
X = sort(x);
Y = 1./(X);
%fit random data
beta0 = [max(X(:,1))/10;max(X(:,1))/10];
[beta,error]= Fit_and_Calc_Error(X,Y,modelfun, beta0);
%storing data found
tracking_a(i,1:length(beta)) = beta;
tracking_error(i) = error;
end
%Testing if first power found has exponential dist
pdN = fitdist(tracking_a(:,1),'Exponential');
histogram(tracking_a(:,1),10)
hold on
x_values2 = 0:0.001:5;
y2 = pdf(pdN,x_values2);
plot(x_values2,y2)
hold off
[h,p] = lillietest(tracking_a(:,1),'Distribution','exponential','MCTol',1e-4)
%Testing if second power found has exponential dist
pdN2 = fitdist(tracking_a(:,2),'Exponential');
histogram(tracking_a(:,2),10)
hold on
y3 = pdf(pdN2,x_values2);
plot(x_values2,y3)
hold off
[h2,p2] = lillietest(tracking_a(:,2),'Distribution','exponential','MCTol',1e-4)

How to design an observer to estimate all states from a single state?

I am trying to design a Luenberger observer (or a full state feedback observer) such that with one sensor available I can estimate all the states. A good tutorial is shown here.
My system is 4th order:
num = [-0.00198 2];
den = [1 0.1201 12.22 0.4201 2];
sys = tf(num,den);
[A, B, C, D] = tf2ss(num,den);
First I have a row vector of poles to get my desired response:
poles = [-2.6 + 1i*2.39, -2.6 - 1i*2.39, -100, -120];
K = acker(A,B,poles)
rank(obsv(A,C)); % =4
Mo = rank([C;C*A;C*A^2;C*A^3]) % =4
I then proceed to calculate the plant poles and thus the poles I want for my observer should be around 3x faster.
plant = (A-B*K);
poles_cl = eig(plant)
poles = 3*poles_cl % THIS IS WRONG
des_poles = (min(real(poles_cl))*3)-(1:4); %This is better
des_poles =
-361.0000 -362.0000 -363.0000 -364.0000
I then proceed to use Ackermann's formula for pole placement using the new poles:
% design observer by placing poles of A-LC at des_poles
L=acker(A',C',poles_des)'
eig_obs = eig(A-L*C)
L =
1.0e+09 *
8.6121
0.1037
0.0005
0.0000
eig_obs =
-361.0000
-362.0000
-363.0000
-364.0000
And finally plot. For the observer (software) to give us all the states as output we need to set C = eye(4):
C = eye(4);
mysys=ss(A-L*C,[B L],C,0); %Not sure if this is correct
tf(mysys)
step(mysys)
Four outputs can be seen:
Following this model for a full state feedback observer:
I am then trying to verify the results on Simulink and am having issue with the block diagram. As can be seen I have two state space models, one for the real plant and one for the observer.
In the below diagram I am comparing state 1, which results in the second graph depicted below.
I am using the base workspace generated by the code above:
Upon running I get an output from the observer which does not track or follow the plant as expected:
Actual and Observer states when comparing state 4 through summing block:
Actual and Observer states when comparing state 1 through summing block:
Any suggestions on why the state I choose to compare via the summing block is effecting the observer estimations would be appreciated.
Observer Parameters:
Plant Parameters:
Why does the state which I am comparing, effect the observer response?
You are not using your closed loop system to determine your observer poles. You want to choose your observer poles faster than your closed loop poles.
Your closed loop A matrix becomes:
Ac = (A-B*K);
and then your closed loop poles become,
poles_cl = eig(Ac);
You can try to make your observer poles 3 or even 10 times faster then these poles, otherwise, and set them based on the (real of the) fastest pole:
factor = 3;
des_poles = (min(real(poles_cl))*factor)-(1:4);
L = place(A',C',des_poles)';
You can play around with the factor, in noisy conditions you may want to use slower poles (i.e. factor lower than 1, since it is based on the fastest pole), to not amplify your noise that much.

How to repeat random walk simulation and record end results in MatLab?

Hi I am working on my first random walk program. I was just able to figure out the random walk program itself. It is a simple 1d random walk, with 1000 steps. Here is what my code looks like so far:
stepslim = 1000;
rnew(1) = 0
r=0;
%Now we will set up the for loop
for isteps = 2:1:stepslim;
if rand <= 0.5 %The if-else statement will tell the walker
step = -1; %which direction it steps in
else
step = +1;
end
rnew(isteps) = rnew(isteps-1) + step; %This adds the new step
end
plot(rnew); %This will plot our random walk
This works just fine, and now I need to attempt a few more tasks:
Run this simulation X times to generate an ensemble. Record/store the final location of the walker at the end of each simulation in the ensemble.
Generate a histogram for the ending position of the walker for each simulation in the ensemble ▪ Adjust the bin-width to “make sense” of your results.
Repeat and plot results for X = [1000, 2000, 10000, 20000, 100000, 1000000]
I am not sure how to repeat the simulation and record the ending values into an ensemble. I would appreciate some help in accomplishing these tasks
Your method for generating the random walks is very, very, very slow... if you want to change your approach, I would suggest you yo use the following code instead:
steps = 1000;
rw = cumsum(-1 + 2 * round(rand(steps,1)),1);
Starting from that point, here is how you could run your simulation x times, record each result and retrieve the last step of every simulation:
iters = 10;
steps = 1000;
rws = NaN(steps,iters);
for i = 1:iters
rws(:,i) = cumsum(-1 + 2 * round(rand(steps,1)),1);
end
% retrieve the last step
last_steps = rws(end,:);
In order to plot an histogram of the last steps, you could use the histogram function which should be flexible enough to print something coherent enough with your data:
histogram(last_steps);
To use different step sizes, just enclose everything inside another for loop in which you cycle on every step size that you define within an array:
X = [1000, 2000, 10000, 20000, 100000, 1000000];
for j = 1:numel(X)
% previous code with variable "steps" replaced by X(j)
end

Animated plot of infectious disease spread with for loop (Matlab)

I'm a beginner in Matlab and I'm trying to model the spread of an infectious disease using Matlab. However, I encounter some problems.
At first, I define the matrices that need to be filled and their initial status:
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix=zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.0001; % Rate of spread
Now, I want to make a plot where the spread of the disease is shown, using a for loop. But i'm stuck here...
for t=1:365
Zneighboursum=zeros(size(diseasematrix));
out_ZT = calc_ZT(Zneighboursum, diseasematrix);
infectionmatrix(t) = round((Rate).*(out_ZT));
diseasematrix(t) = diseasematrix(t-1) + infectionmatrix(t-1);
healthymatrix(t) = healthymatrix(t-1) - infectionmatrix(t-1);
imagesc(diseasematrix(t));
title(sprintf('Day %i',t));
drawnow;
end
This basically says that the infectionmatrix is calculated based upon the formula in the loop, the diseasematrix is calculated by adding up the sick people of the previous timestep with the infected people of the previous time. The healthy people that remain are calculated by substracting the healthy people of the previous time step with the infected people. The variable out_ZT is a function I made:
function [ZT] = calc_ZT(Zneighboursum, diseasematrix)
Zneighboursum = Zneighboursum + circshift(diseasematrix,[1 0]);
Zneighboursum = Zneighboursum + circshift(diseasematrix,[0 1]);
ZT=Zneighboursum;
end
This is to quantify the number of sick people around a central cell.
However, the result is not what I want. The plot does not evolve dynamically and the values don't seem to be right. Can anyone help me?
Thanks in advance!
There are several problems with the code:
(Rate).*(out_ZT) is wrong. Because first one is a scalar and
second is a matrix, while .* requires both to be matrices of the
same size. so a single * would work.
The infectionmatrix,
diseasematrix, healthymatrix are all 2 dimensional matrices and
in order to keep them in memory you need to have a 3 dimensional
matrix. But since you don't use the things you store later you can
just rewrite on the old one.
You store integers in the
infectionmatrix, because you calculate it with round(). That
sets the result always to zero.
The value for Rate was too low to see any result. So I increased it to 0.01 instead
(just a cautionary point) you haven't used healthymatrix in your code anywhere.
The code for the function is fine, so after debugging according to what I perceived, here's the code:
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix=zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.01;
for t=1:365
Zneighboursum=zeros(size(diseasematrix));
out_ZT = calc_ZT(Zneighboursum, diseasematrix);
infectionmatrix = (Rate*out_ZT);
diseasematrix = diseasematrix + infectionmatrix;
healthymatrix = healthymatrix - infectionmatrix;
imagesc(diseasematrix);
title(sprintf('Day %i',t));
drawnow;
end
There is several problems:
1) If you want to save a 3D matrix you will need a 3D vector:
so you have to replace myvariable(t) by myvariable(:,:,t);
2) Why did you use round ? if you round a value < 0.5 the result will be 0. So nothing will change in your loop.
3) You need to define the boundary condition (t=1) and then start your loop with t = 2.
diseasematrix=zeros(20,20);
inirow=10;
inicol=10;
diseasematrix(inirow,inicol)=1; % The first place where a sick person is
infectionmatrix =zeros(20,20); % Infected people, initially all 0
healthymatrix=round(rand(20,20)*100); % Initial healthy population (randomly)
Rate=0.01; % Rate of spread
for t=2:365
Zneighboursum=zeros(size(diseasematrix,1),size(diseasematrix,2));
out_ZT = calc_ZT(Zneighboursum, diseasematrix(:,:,t-1));
infectionmatrix(:,:,t) = (Rate).*(out_ZT);
diseasematrix(:,:,t) = diseasematrix(:,:,t-1) + infectionmatrix(:,:,t-1);
healthymatrix(:,:,t) = healthymatrix(:,:,t-1) - infectionmatrix(:,:,t-1);
imagesc(diseasematrix(:,:,t));
title(sprintf('Day %i',t));
drawnow;
end
IMPORTANT: circshift clone your matrix in order to deal with the boundary effect.

If Statement within for loop - Matlab

Him I am working on modelling a wind turbine using turbine specific parameters from three manufacturers
My code is
Site_speed = xlsread('test.xlsx','Sheet1'); % Wind speed data recorded on site
air_density = xlsread('test.xlsx','Sheet2'); % Air density data recorded on site
Turbine_parameters = xlsread('windparameters.xlsx'); % Wind turbine unit database
Ref_wind_speed = Turbine_parameters(:,1); % Wind speed from wind turbine unit database file Turbine_parameters
Ref_output = Turbine_parameters(:,2:4); % Power output from wind turbine unit database file Turbine_parameters
Density_correct = (air_density./air_density_ref);
for K = 1 : size(Ref_output, 2)
power_out(:,:,K) = Density_correct.* interp1( Ref_wind_speed, Ref_output(:,K), Site_speed, 'nearest');
% xlswrite('this_file2.xlsx', power_out(:,:,1), 'sheet1');
% xlswrite('this_file2.xlsx', power_out(:,:,2), 'sheet2');
% xlswrite('this_file2.xlsx', power_out(:,:,3), 'sheet3');
%% WIND TURBINE FINANCIAL ANALYSIS + OPERATIONAL EMISSIONS
Array_supply(:,:,K) = (1-Losses) .* power_out(:,:,K) .* Turbines;
Total_array(:,:,K) = sum(Array_supply(:));
Array_OM_cost(:,:,K) = sum(sum(Total_array(:,:,K) * Wind_OM));
% % Grid connected system with internal load
end
for K = 1 : size(Array_supply,3)
Demand = xlsread('demandtest.xlsx');
if Demand >= Array_supply(:,:,K)
Grid(:,:,K) = Demand - Array_supply(:,:,K)
Income(:,:,K)= (Array_supply(:,:,K)*FIT_wind) + Array_supply(:,:,K)*Grid_cost);
Expences(:,:,K) = (Array_OM_cost(:,:,K)) + sum(sum((Grid(:,:,K)*Grid_cost)));
Profit(:,:,K) = sum(sum(Income(:,:,K))) - sum(sum(Expences(:,:,K)));
else
Income(:,:,K) = (Demand*FIT_wind) + (Demand*Xe_wind)+(Demand*Grid_cost);
Expences(:,:,K) = Array_OM_cost(:,:,K);
Profit(:,:,K) = sum(sum(Income(:,:,K))) - sum(sum(Expences(:,:,K)));
end
end
I have shown all of the code above, but I think that the mistakes start at the line -
for K = 1 : size(Array_supply,3)
The results I get when the program runs is a set of three matrices (as expected) where the first two are populated with zeros only (incorrect).
Also the Grid, Income and Expenses should be 365x 24 matrices (as are the Demand and Array_supply)
When I try and just run the Grid(:,:,K), an error appears saying Matlab cant find it!!
Does anyone have any idea where I might have gone wrong?
Thanks
First of all, it is always best practice in Matlab to pre-allocate your arrays. If ou know that Grid, Income, Expenses, and Profit are all going to be a 365x24x3 matrix, then you should put this before the loop, and doing likewise for the other variables.
Grid=zeros(365,24,3);
As for your problem, it seems likely that you aren't computing this correctly. Put a break point after the Demand=xlsread(...) statement. Does demand look right? Demand must be a single variable, if it is a matrix, then that is your problem. If it is a matrix, you need to loop through every variable. There are more elegant solutions involving logical masks, feel free to look up the concept if you want to. I'm going to suggest that at least for the time being, you just loop through the whole Demand loop.
Also, I don't think you are using your profit statements correctly. It is only storing a single variable per loop, but you are storing it for the entire matrix... It seems like Profit would be just as well served as a 3x1 matrix, referencing it like Profit(f) instead of Profit(:,:,f).
Oh, and a very minor point, it's Expenses, not Expences...