Matlab: return complete solution of inverse cosine (acos) - matlab

I have some Matlab code of the following form:
syms theta x
theta = acos(x)
This returns a single solution for theta. However, I want to return the complete solution (between some limits).
For example,
x = cos(theta)
would give x=0.5 for theta = 60 degrees, 120 degrees, 420 degrees, etc. Therefore, in my code above, I want theta to return all these possible values.
Does anyone know how to do this? I have been searching google for hours but I can't find how to do this!
Many thanks!

Here's a numerical solution; like Benoit_11 I don't see the point of doing it symbolically in this context.
There are two solutions within the interval [-pi, pi], the larger one being returned by acos:
% solution within [0, pi]
theta1 = acos(x);
% solution within [-pi, 0]
theta2 = -acos(x);
These solutions repeat at steps of 2 pi. The number of possible steps downwards and upwards can be determined by the integer part of the distance between the basic solution and the respective limit (lower and upper), in units of 2 pi. For theta1:
% repetitions in 2 pi intervals within limits
sd = floor((theta1 - lower) / (2 * pi));
su = floor((upper - theta1) / (2 * pi));
theta1 = (-sd : su) * 2 * pi + theta1
And the same for theta2:
% repetitions in 2 pi intervals within limits
sd = floor((theta2 - lower) / (2 * pi));
su = floor((upper - theta2) / (2 * pi));
theta2 = (-sd : su) * 2 * pi + theta2
If you'd like one combined list of solutions, excluding possible duplicates:
theta = unique([theta1, theta2])
and in degrees:
theta = theta / pi * 180;
Example:
x = 0.5;
lower = -10;
upper = 30;
gives
theta =
-7.3304 -5.2360 -1.0472 1.0472 5.2360 7.3304 11.5192 13.6136 17.8024 19.8968 24.0855 26.1799

You just have to use a loop:
for x = limit_inf:step:limit_sup
theta(x) = acos(x);
end
And also define your limits and the step between them.

Related

Calculate 3D cordinates from with camera matrix and know distance

I have been struggeling with this quiz question. This was part of FSG 2022 registration quiz and I can't figure out how to solve it
At first I thought that I can use extrinsic and intrinsic parameters to calculate 3D coordinates using equations described by Mathworks or in this article. Later I realized that the distance to the object is provided in camera frame, which means that this could be treat as a depth camera and convert depth info into 3d space as described in medium.com article
this article is using formula show below to calculate x and y coordinates and is very similar to this question, yet I can't get the correct solution.
One of my Matlab scripts attempting to solve it:
rot = eul2rotm(deg2rad([102 0 90]));
trans = [500 160 1140]' / 1000; % mm to m
t = [rot trans];
u = 795; % here was typo as pointed out by solstad.
v = 467;
cx = 636;
cy = 548;
fx = 241;
fy = 238;
z = 2100 / 1000 % mm to m
tmp_x = (u - cx) * z / fx;
tmp_y = (v - cy) * z / fy;
% attempt 1
tmp_cords = [tmp_x; tmp_y; z; 1]
linsolve(t', tmp_cords)'
% result is: 1.8913 1.8319 -0.4292
% attempt 2
tmp_cords = [tmp_x; tmp_y; z]
rot * tmp_cords + trans
% result is: 2.2661 1.9518 0.4253
If possible I would like to see the calculation process not any kind of a python code.
Correct answer is under the image.
Correct solution provided by the organisers were 2.030, 1.272, 0.228 m
The task states that the object's euclidean (straight-line) distance is 2.1 m. That doesn't mean its distance along z is 2.1 m. Those two only coincide if there is no x or y component in the object's translation to the camera frame.
The z component of the object's translation will be less than 2.1 meters.
You need to take a ray/vector for the screen space coordinates (normalized) and multiply that by the euclidean distance.
v_x = (u - cx) / fx;
v_y = (v - cy) / fy;
v_z = 1;
v = [v_x; v_y; v_z];
dist = 2.1;
tmp = v / norm(v) * dist;
The rotation may be an issue. Roll happens around X, then pitch happens around Y, and then yaw happens around Z. These operations are applied in that order, i.e. inner to outer.
R_Z * R_Y * R_X * v
My rotation matrix is
[[ 0. 0.20791 0.97815]
[ 1. 0. 0. ]
[ 0. 0.97815 -0.20791]]
That camera, taking the usual (X right, Y down, Z far) frame, would be looking, upside down, out the windshield, and slightly down.
Make sure that eul2rotm() does the right thing (specify axis order as 'XYZ') or that you use something else.
You can use rotvec2mat3d() to build individual rotation matrices from an axis-angle encoding.
Perhaps also review different MATLAB conventions regarding matrix multiplication: https://www.mathworks.com/help/images/migrate-geometric-transformations-to-premultiply-convention.html
I used Python and scipy.spatial.transform.Rotation.from_euler('xyz', [R_roll, R_pitch, R_yaw], degrees=True).as_matrix() to arrive at the sample solution.
Properly, the task should have specified a frame conversion step between vehicle and camera because the differing views are quite confusing, with a car having +X being forward and a camera having +Z being forward...
In addition to Christoph Rackwitz answer, which is correct and should get all the credited, here is a working Matlab script:
rot = eul2rotm(deg2rad([90 0 102]));
trans = [500 160 1140]' / 1000; % mm to m
u = 795;
v = 467;
cx = 636;
cy = 548;
fx = 241;
fy = 238;
v_x = (u - cx) / fx;
v_y = (v - cy) / fy;
v_z = 1;
v = [v_x; v_y; v_z];
dist = 2.1;
tmp = v / norm(v) * dist;
rot * tmp + trans

Neural Network not fitting XOR

I created an Octave script for training a neural network with 1 hidden layer using backpropagation but it can not seem to fit an XOR function.
x Input 4x2 matrix [0 0; 0 1; 1 0; 1 1]
y Output 4x1 matrix [0; 1; 1; 0]
theta Hidden / output layer weights
z Weighted sums
a Activation function applied to weighted sums
m Sample count (4 here)
My weights are initialized as follows
epsilon_init = 0.12;
theta1 = rand(hiddenCount, inputCount + 1) * 2 * epsilon_init * epsilon_init;
theta2 = rand(outputCount, hiddenCount + 1) * 2 * epsilon_init * epsilon_init;
Feed forward
a1 = x;
a1_with_bias = [ones(m, 1) a1];
z2 = a1_with_bias * theta1';
a2 = sigmoid(z2);
a2_with_bias = [ones(size(a2, 1), 1) a2];
z3 = a2_with_bias * theta2';
a3 = sigmoid(z3);
Then I compute the logistic cost function
j = -sum((y .* log(a3) + (1 - y) .* log(1 - a3))(:)) / m;
Back propagation
delta2 = (a3 - y);
gradient2 = delta2' * a2_with_bias / m;
delta1 = (delta2 * theta2(:, 2:end)) .* sigmoidGradient(z2);
gradient1 = delta1' * a1_with_bias / m;
The gradients were verified to be correct using gradient checking.
I then use these gradients to find the optimal values for theta using gradient descent, though using Octave's fminunc function yields the same results. The cost function converges to ln(2) (or 0.5 for a squared errors cost function) because the network outputs 0.5 for all four inputs no matter how many hidden units I use.
Does anyone know where my mistake is?
Start with a larger range when initialising weights, including negative values. It is difficult for your code to "cross-over" between positive and negative weights, and you probably meant to put * 2 * epsilon_init - epsilon_init; when instead you put * 2 * epsilon_init * epsilon_init;. Fixing that may well fix your code.
As a rule of thumb, I would do something like this:
theta1 = ( 0.5 * sqrt ( 6 / ( inputCount + hiddenCount) ) *
randn( hiddenCount, inputCount + 1 ) );
theta2 = ( 0.5 * sqrt ( 6 / ( hiddenCount + outputCount ) ) *
randn( outputCount, hiddenCount + 1 ) );
The multiplier is just some advice I picked up on a course, I think that it is backed by a research paper that compared a few different approaches.
In addition, you may need a lot of iterations to learn XOR if you run basic gradient descent. I suggest running for at least 10000 before declaring that learning isn't working. The fminunc function should do better than that.
I ran your code with 2 hidden neurons, basic gradient descent and the above initialisations, and it learned XOR correctly. I also tried adding momentum terms, and the learning was faster and more reliable, so I suggest you take a look at that next.
You need at least 3 neurons in the hidden layer and correct the initialization as the first answer suggest.
If the sigmoidGradient(z2) means a2.*(1-a2) all the rest of the code seems ok to me.
Best reggards,

How to set a max value for histogram [duplicate]

This question already has answers here:
How to normalize a histogram in MATLAB?
(7 answers)
Closed 8 years ago.
Image first:
As you can see, I have a set of normal distributions. Made for a presentation purpose, there was a feedback that those plots should be "normalized", for what I understood having the plot values set to some maximum value and the curvature of the plot set to fit this anyways. The goal is to make those plots easier to compare visually - I hope this makes sense. I'm using histfit for this plot.
Do you know of some method how can I possible make those graphs more comparable in that way?
EDIT:
As it was marked as a duplicate, it's not really the case. I'm not really looking for the probability density to fit the histogram, I want to set a maximum value for each probability density curve. I know about the market topics, I just couldn't find my anwser there.
EDIT2:
Those are exercpts from my code with the solutions they produce:
[f1,x1] = hist(data1);
[f2,x2] = hist(data2);
[f3,x3] = hist(data3);
avg = mean(data1);
stdev = std(data1);
VERT1 = sort(data1);
y1 = exp(- 0.5 * ((VERT1 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
y11 = y1/max(data1);
avg = mean(data2);
stdev = std(data2);
VERT2 = sort(data2);
y2 = exp(- 0.5 * ((VERT2 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
y22 = y2/max(data2);
%
avg = mean(data3);
stdev = std(data3);
VERT3 = sort(data3);
y3 = exp(- 0.5 * ((VERT3 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
y33 = y3/max(data3);
Direct link for clarity: http://i.imgur.com/YPrcM3R.jpg
From this explanation I get this:
[f1,x1] = hist(data1);
[f2,x2] = hist(data2);
[f3,x3] = hist(data3);
avg = mean(data1);
stdev = std(data1);
VERT1 = sort(data1);
y1 = exp(- 0.5 * ((VERT1 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
avg = mean(data2);
stdev = std(data2);
VERT2 = sort(data2);
y2 = exp(- 0.5 * ((VERT2 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
avg = mean(data3);
stdev = std(data3);
VERT3 = sort(data3);
y3 = exp(- 0.5 * ((VERT3 - avg) / stdev) .^ 2) / (stdev * sqrt(2 * pi));
h1 = bar(x1,f1/trapz(x1,f1));hold on;
h2 = bar(x2,f2/trapz(x2,f2),'r');hold on;
h3 = bar(x3,f3/trapz(x3,f3),'g');hold on;
plot(VERT1,y1,'b-');hold on;
plot(VERT2,y2,'r-');hold on;
plot(VERT3,y3,'g-');hold off;
Which results in:
Hope this explains everything.
What you have are two plots with non-zero means and non-unit standard deviations. Such distributions are hard to compare. What normalization means in this context (as far I think) is to make the mean of the fitted bell curve 0 and standard deviation 1. This can be achieved quite simply. Here is a toy example:
clf;
data1 = random('normal',300,30,100,1); %Randomly generated first dataset
data2 = random('normal',250,10,100,1); %Randomly generated second dataset
h1=histfit(data1); %Plot the data
hold on;
h2=histfit(data2);
delete(h1(1));
delete(h2(1));
set(h2(2),'color','b')
This yields:
To normalize, simply replace the data that you're fitting with normalized data as:
h1=histfit( (data1-mean(data1)) / std(data1) );
h2=histfit( (data2-mean(data2)) / std(data2) );
To yield:
making the comparison of the graphs much cleaner.

how to detect if one signal is increasing in amplitude and another in decreasing at the same window

I have to signals as shown below and I need to detect if one signal is increasing in amplitude and another in decreasing at the a specific time window and vice versa. I tried findpeaks function but it didn't detect the big peak shown below .. it detects all the small peaks which I don't need them.. any help?
using sign(diff(signal)) can help, you can use sgolayfilt for noise reduction.
L = 100;
Fs = 50;
t = (0 : L - 1) / Fs ;
n = .3 * rand([1 L]);
s1 = sin(2 * pi * .8 * t) + n;
s2 = cos(2 * pi * .8 * t) + n;
subplot(311)
plot(t,s1,'b'); hold on
plot(t,s2,'m');
subplot(312)
s1 = sgolayfilt(s1,3,13);
s2 = sgolayfilt(s1,3,13);
t(end) = [];
plot(t,sign(diff(s1)),'b')
ylim([-2 2])
subplot(313)
plot(t,sign(diff(s2)),'m')
ylim([-2 2])
If your signals are clean then the results will be better.
Compute the slopes for the period and see whether they have opposing sign.

For loop not working as desired

I am calculating the distance and velocity between GPS coordinates (lat,long,height) and it appears to work well when I used single values. However, I have a matrix of 79 GPS coordinates (3x79 matrix) and I want to find the distance and speed between each two consecutive points. When I try to use a for loop the output I get is all zeros apart from the first and last value (which are very high).
I am probably doing something silly but I can spot it...any suggestions are appreciated :)
for k=1:77
R=6378.1e3;
latDistance = copter_llh(1,k+1) - copter_llh(1,k);
lonDistance = copter_llh(2,k+1) - copter_llh(2,k);
a = sin(latDistance / 2) * sin(latDistance / 2) + cos(copter_llh(1,k))...
*cos(copter_llh(1,k+1)) * sin(lonDistance / 2) * sin(lonDistance / 2);
c = 2 *atan2(sqrt(a), sqrt(1 - a));
distance = R * c * 1000; % convert to meters
height = copter_llh(3,k+1) - copter_llh(3,k);
distance = sqrt((distance^ 2) + (height^2));
velocity = distance/0.1*60;
% stepsize =0.1min ___speed in m/s
distance(:,k)=(distance);
velocity(:,k)=(velocity);
end %-----
It looks like you are reusing your distance variable in an unintentional way, as well as your velocity variable at the end of your for loop. You're mutating the distance variable, and then trying to reshape it as a matrix. You'll need to change this variable, and then call where you want to store your matrix as something else. Also, distance and velocity look like they're single arrays, and so the : accessing for the first dimension is superfluous. As such, try doing this instead:
distance = zeros(1,77); %// NEW - Preallocate distance array
velocity = zeros(1,77); %// NEW - Preallocate velocity array
R=6378.1e3; %// NEW - Leave outside for loop. Constant at each iteration
for k=1:77
latDistance = copter_llh(1,k+1) - copter_llh(1,k);
lonDistance = copter_llh(2,k+1) - copter_llh(2,k);
a = sin(latDistance / 2) * sin(latDistance / 2) + cos(copter_llh(1,k))...
*cos(copter_llh(1,k+1)) * sin(lonDistance / 2) * sin(lonDistance / 2);
c = 2 *atan2(sqrt(a), sqrt(1 - a));
dist = R * c * 1000; %// convert to meters - NEW - change variable
height = copter_llh(3,k+1) - copter_llh(3,k);
%// stepsize =0.1min ___speed in m/s
distance(k) = sqrt((dist^ 2) + (height^2)); %// NEW - Assign directly to distance array
velocity(k) = distance/0.1*60; %// NEW - Assign directly to velocity array
end %-----
This code should now store 77 distances and velocities stored in distance and velocity respectively. Try that and let me know if it works!
Sidenote
You can compute this in a completely vectorized way without any for loops. You can use diff to compute those neighbouring distances for you. As such, you can actually do something like this:
R=6378.1e3;
latDistance = diff(copter_llh(1,:)); % // NEW
lonDistance = diff(copter_llh(2,:)); %// NEW
a = sin(latDistance / 2) .* sin(latDistance / 2) + cos(copter_llh(1,1:end-1))...
.*cos(copter_llh(1,2:end)) .* sin(lonDistance / 2) .* sin(lonDistance / 2);
c = 2 *atan2(sqrt(a), sqrt(1 - a));
dist = R * c * 1000; %// convert to meters - NEW - change variable
height = diff(copter_llh(3,:));
distance = sqrt((dist.^2) + (height.^2)); %// NEW
velocity = distance/0.1*60; %// NEW
The above code should be equivalent to your for loop method, but remember to always write code that makes sense to you first and works before you start doing any optimizations. That's the best way to code!