Dictionary ordered keys - python-3.7

grades = {}
while True:
k = input('enter input ')
val = input('enter input ')
grades[k] = val
In this scenario I want k to be a number that is given in order, not asked for by the user.
This will give the result of
grades = {1:'user input first', 2:'user input second') this repeats for all user inputs

How about:
grades = {}
k = 1
while True:
val = input('enter input ')
grades[str(k)] = val
k += 1

Related

Referencing value of an array based on the values of another

I have an array d = [0,1000,2000]. Based on this array, I compute the value of another array, let's say J = [0,5000,8000], where J = 3*d+2000.
Now, during iteration using a for loop, if d=0, I want to extract value of J(1); if d = 1000, then I want to extract values of J(1) and J(2); if d = 2000, I want to extract values of J(1),J(2) and J(3). What would be a generic way to cross-reference values of two arrays?
Assuming your values in d are unique and the length of d and J are identical, use MATLAB's find function, especially using this version with n = 1, and direction = 'first', like so:
idx = find(d == ii, 1, 'first')
Here, ii is the desired value, e.g. 0, 1000, and so on. You'll get the index of the (first) occurrence of the desired value in d. Then, just extract all values from J from 1 to idx:
J(1:idx)
Here's a small test script:
d = [0, 1000, 2000]
J = 3 * d + 2000
% If your counter variable only contains valid values from d
for ii = d
idx = find(d == ii, 1, 'first');
printf('d = %d\n', ii);
printf('Extracted values are: ');
printf('%d ', J(1:idx));
printf('\n \n');
end
% If your counter variable may contain any value
for ii = 0:2000
idx = find(d == ii, 1, 'first');
if (~isempty(idx))
printf('d = %d\n', ii);
printf('Extracted values are: ');
printf('%d ', J(1:idx));
printf('\n \n');
end
end
And, the output looks like this:
d =
0 1000 2000
J =
2000 5000 8000
d = 0
Extracted values are: 2000
d = 1000
Extracted values are: 2000 5000
d = 2000
Extracted values are: 2000 5000 8000
d = 0
Extracted values are: 2000
d = 1000
Extracted values are: 2000 5000
d = 2000
Extracted values are: 2000 5000 8000
Hope that helps!
P.S. I haven't thought about vectorization here, since the question states, that a for loop is used in any case.

Is there a way to store value of Matrix in a separate variable, in each loop of while loop so that I get all values of Matrix at the end at once

I want to save Matrix(Matrix is name of a matrix) value in a separate variable so that I collected all matrices at the end and then prints it all at once. my current code prints value in each loop while I want to get all values of matrices in the last loop.
syms num T1 T2 T3 T4 T3 T6 T7 T8 T9 T10 T5
%Getting data for Robot%
prompt = 'Enter the number of joints in your robot';
X = input(prompt);
num = 0;
while(num<X)
matrix_number = ['t ',num2str(num),'_', num2str(num+1)];
link_twist = ['Enter the value of twist(alpha) for the link number',num2str(num+1),' link e.g 10,80 etc'];
disp(link_twist)
al = input(prompt);
link_length = ['Enter the value of offset(d) for the link number',num2str(num+1),' link e.g 1,2,3,4 etc'];
disp(link_length)
prompt = '';
d = input(prompt);
link_offset = ['Enter the value of link length(a) for the link number',num2str(num+1),' link e.g 1,2,3,4 etc'];
disp(link_offset)
prompt = '';
a = input(prompt);
link_theta = ['Enter the value of theta for the link number ',num2str(num+1),' link e.g T1, T2 etc'];
disp(link_theta)
prompt = '';
theta = input(prompt);
Matrix = [cosd(theta) -sind(theta) 0 a;
sind(theta)*cos(al) cosd(theta)*cosd(al) -sind(al) -sind(al)*d; sind(theta)*sind(al) cosd(theta)*sind(al) cosd(al) cosd(al)*d;
0 0 0 1];
disp(matrix_number)
digits(2)
printed_matrix = vpa(Matrix);
pretty(printed_matrix)
num = num+1;
end
Use the cell array data type to store the entire matrix for each run.
Before your while loop you will want to preallocate the array Carray = cell([X,1])
Then you can index the array using your num value. You might choose to place this line immediately after you increment num
...
num = num+1
Carray{num} = Matrix
end
Now you can access the Matrix generated from each run by passing the index into the Carray.
Mat3 = Carray{3}

Differential part of PID and its low pass filter- time domain

I programmed PID in MATLAB:
classdef PID < handle
properties
Kp = 0
Ki = 0
Kd = 0
SetPoint = 1
Dt = 0.01
end
properties (Access = private)
IState = 0
PreErr = 0
end
methods
function obj = PID(Kp, Ki, Kd, SetPoint, Dt)
if nargin == 0
return;
end
obj.Kp = Kp;
obj.Ki = Ki;
obj.Kd = Kd;
obj.SetPoint = SetPoint;
obj.Dt = Dt;
end
function output = update(obj, measuredValue, t)
err = obj.SetPoint - measuredValue;
P = obj.getP(err);
I = obj.getI(err);
val = lowPass(obj,t);
D = obj.getD(err*val);
output = P + I + D;
end
function val = getP(obj, err)
val = obj.Kp*err;
end
function val = getI(obj, err)
obj.IState = obj.IState + err * obj.Dt;
val = obj.Ki * obj.IState;
end
function val = getD(obj, err)
val = obj.Kd * (err - obj.PreErr) / obj.Dt;
obj.PreErr = err;
end
function val = lowPass(obj,t)
N = 10;
val = 1-exp(-N*t);
end
end
end
And tested it using a random low pass filter as the plant:
function r = getResponse(t)
r = 1 - exp(-5*t);
end
The test code:
sr = 1e2; % sampling rate 100Hz
st = 10; % sampling time 10s
ss = st*sr+1; % sample size
t = 0:1/sr:st; % time
input = ones(1,ss)*100;
output = zeros(1,ss);
measured = 0;
pid = PID(0,1,1,input(1),t(2)-t(1));
for i = 2:ss
rPID(i) = pid.update(measured, t(i));
output(i) = rPID(i)*getResponse(t(i));
measured = output(i);
end
figure
plot(t,output)
hold on;
plot(t,input)
plot(t,rPID)
legend('Output','Input','PID')
Note that the parameters are set to kp=0;ki=1;kd=1;. I'm only testing the differential part here. The result is very wrong:
Notice the Y-axis is scaled by 10^307. It gets too big that after ~1.6s the PID value exceeds the range of double precision and therefore, the curve stops.
I have ensured that both P and I parts work well enough (see this question I asked a while ago).
From the curve for the D component (see figure below), one can clearly see that it starts to oscillate heavy from the very beginning; its value reaches >50k after the 5th timestamp at 0.04s:
I'm almost certain I must have made a mistake in implementing the low pass filter, but I also noticed that even with the low pass filter removed, the differential values still behave similarly.
To have some sort of reference and comparison, I also made a Simulink simulation of the same system, using the exact same PID gains (i.e. kp=0;ki=1;kd=1;). Below is the block diagram (left), figure for input and output (top right figure) and figure for PID values (bottom right)
Note that there is no top/lower limit in the gain blocks and the initial inputs/outputs are set to zeros.
These PID gains are nowhere near optimised but they give completely different results in the simulation and coded PID.
Therefore the big question is am I doing something wrong here? Why is there a difference between the two results?
The implementation of the low pass filter is not correct. The difference equation of a low pass filter is as shown:
The call of the getResponse function could look like this:
pid = PID(0,1,1,input(1),t(2)-t(1));
for i = 2:ss
rPID(i) = pid.update(measured, t(i));
alpha = getResponse(0.25,0.01);
output(i) = rPID(i)*alpha+(1-alpha)*output(i-1);
measured = output(i);
end
Thus getResponse is equivalent to alpha
function r = getResponse(wc,Ts)
r = 1 - exp(-wc*Ts);
end
Further you have to modify the lowPass function in the PID class.
function output = update(obj, measuredValue)
err = obj.SetPoint - measuredValue;
P = obj.getP(err);
I = obj.getI(err);
val = lowPass(obj,err,0.1,0.01);
D = obj.getD(val);
output = P + I + D;
end
% ...
function val = lowPass(obj,err,wc,Ts)
alpha = getResponse(wc,Ts);
output = err*alpha+(1-alpha)*obj.output_1;
obj.output_1 = output;
val = output;
end

MATLAB Morse Code diff and find functions

We are trying to write a function that takes arr and counts how many 0's and 1's appear in sequence. The output should be a 2D array where column 1 is how many appear in sequence and column 2 is which token it is (0 or 1).  Our function below
function [token] = tokenizeSignal(arr)
matA = diff(find(diff([log_vector;-1])));
addA = zeros(size(matA, 1),1);
matA = [matA, addA];
matB = diff(find(diff([log_vector;0])));
addB = ones(size(matB, 1), 1);
matB = [matB, addB];
[nRowsA, nCols] = size(matA);
nRowsB = size(matB, 1);
AB = zeros(nRowsA + nRowsB, nCols);
AB(1:2:end, :) = matA;
AB(2:2:end, :) = matB;
token = AB;
works with
arr = [0; 0; 0; 1; 1; 1; 0];
but nothing else because it adds random integers into the matrix. Why does it do this and how can I fix it?
Here is code that takes any array arr and produces what you want:
% input checking/processing
% ... convert the input into a column vector
arr = arr(:);
% ... check that the input is nonempty and numeric
if ~isnumeric(arr), error('Bad input'); end
if isempty(arr), error('Bad input'); end
% determine the starting indices of each sequence in arr
I = [1 ; find(diff(arr)) + 1];
% determine the values of each of these sequences
values = arr(I);
% determine the length of each of these sequences
value_counts = [diff(I) ; length(arr) - max(I) + 1];
% produce the output
token = [value_counts, values];

How to Create Autocorrelation Function without any buit-in functions like xcorr

I want to auto-correlate a random noise vector with out any built-in MATLAB functions.
My auto correlation equation that is given is:
Rxx[L] = ∑ from n = 1 to N-1 [x(n)*x(n+L)]
L = [0:200]
I have written the code below but the plot Rxx vs L plot is not what I am expecting.
I am expecting my plot to start at some maximum at L = 0 or L = 1 since MATLAB starts its index at 1. Then exponentially decrease and saturates at a min of zero.
clc
clear all
randn('seed',2496132);
n = randn(1,1024);
upperbound = numel(n)-1;
for L = 1:200
for j = 1 : upperbound
n1(j) = n(j)+L;
Rxx(j) = (n(j)*n1(j));
end
Rxx_sum(L) = sum(Rxx);
Rxx = 0;
end
plot([1:200], Rxx_sum)
You have error in inner loop: you need to use n1(j) = n(j+L); instead n1(j) = n(j)+L;. E.g. you need add L to index instead value.
Second error is following: if you want to use upperbound = numel(n)-1 than you should use L equal to 0 or 1 only. E.g. you outer loop will be
for L = 0:1
...
Rxx_sum(L+1) = sum(Rxx);
...
Instead of this you can also correct upperbound value:
upperbound = numel(n) - maxL;
There maxL is maximal value of L that will used in next loop.
One more tip: it is possible to increase calculation speed if you replace inner loop with scalar product, e.g.
for L = 1:200
Rxx_sum(L) = n(1:upperbound) * n(1+L:upperbound+L)';
end
I ended up fixing my script with the help of the above code.
clc
clear all
randn('seed',2496132);
z = randn(1,1024);
n = [z zeros(1,200)];
upperbound = numel(z)-1;
for L = 0:200
for j = 1 : upperbound
Rxx(j) = (n(j)*n(j+L));
>end
Rxx_sum(L+1) = sum(Rxx);
Rxx = 0;
end
plot([0:200],Rxx_sum)