Balloon string inverse kinematics [closed] - simulation

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have a simulation where I have balloons bouncing around the screen with a string attached to each one. it functions like a constraint. The string should obey gravity, such that if the balloon isn't max length, there should be slack hanging down.
In order to solve this, I represent the string with line segments. I have the string start hanging straight down, and then iterate over each segment, pointing it to the balloons, and then positioning it so it is connected. This gets the behavior very close to what I want, however in order to make sure that it doesn't leave the center, i translate it back to the place it is rooted in. The problem is that the end no longer is going to be connected. If i didn't have to reset the string to the vertical position this would work, but i have to in order to make sure the slack is calculated.
I added a temporary solution of iterating over it again to reconnect it, and the behavior is decent, but it definitely isn't realistic. An example can be seen here: http://www.mikerkoval.com/simulation/balloons
click to create balloons. I am unsure how to simulate gravity. Is there a better approach to make this more realistic?
-----EDIT----
I am strugglign to get my value solved for a in the catenary function.
I defined my function as:
var k = function (a){
return Math.pow((2 * a[0]*Math.sinh(h/(2 * a[0])) - sqrt(s*s- v*v)), 2)
}
however, when I call
var sol = numeric.uncmin(k, [1]);
it runs for a little then throws a Nan error. I am trying to figure out where the problem even is, but I am having very little success since I am struggling to learn what is going on with uncmin

I think what you want is to find the parameters for the catenary curve through two points p0 and p1, the positions of the anchor and balloon, which has given arc length s, which is the length of the string.
The equation of the curve is
y = a cosh (x / a)
where a is a parameter you need to determine. Let v = y1 - y0 and h = x1 - h0. With a bit of algebra you can show the value of a must satisfy
sqrt(s*s - v*v) = 2 * a * sinh(h / (2a))
This article a nice discussion of how to solve this for a iteratively with Newton's method. The author makes a substitution of variables b = a/h that make makes the solution space close to linear, so Newton will converge very quickly to a good answer.
Newton's method is a simple iteration that requires the explicit derivative of the curve and a starting point. The article above gives the derivative. Because the curve is so close to linear, you can pick any starting point on that linear portion - b = 0.2 will do. By converging quickly, I mean the number of correct significant digits doubles with each iteration. So in practice you're likely to have all the digits of a double precision floating point number in 6 iterations or less.
Once you have the parameter, it will be a simple patter to plot the explicit curve you need.
If Newton doesn't converge in 6 iterations or so, then the instance of the problem is a very ill-conditioned one. Here that means a curve that's very nearly a straight line. So just draw such a line between p0 and p1!
All this should be easily fast enough: less expensive than your current approximation.

Related

Why am I not getting slope of a horizontal line = 0?

I am trying to get the slope of my data in Matlab through "polyfit" command.
x = 1:38; y = -60*ones(1,38);
p_fit = polyfit(x,y,1);
slope = p_fit(1);
As per my knowledge, since y has constant values, I am expecting slope to be zero. But I am getting a value in 10^-16. So please help me in correcting myself.
The values of y is in dB domain. SO will this be any problem ? or any other reason.
Thanks
MATLAB runs on double precision floating point arithmetic if you don't tell it to do otherwise, and 10^-16 is reasonably well within the expected error.
If you want to get into the specifics (and you really should), have a look at "What every computer scientist should know about floating point arithmetic".
Update:
With regards to your comment, the boundaries you mention are at least 10 orders of magnitude bigger than the error you are seeing, so as long as this stays that way, you really need not worry about the small error.

atan(c*tan(x)) does not consider x>pi/2

The Problem:
I have a problem in Matlab with a part of a function that calculates the value of
atan(c*tan(x)).
For some real c and x where x is an angle. Usually this would return some values between -pi/2 and pi/2 but I want it to mind "how often the angle got around": For example with c=1 we get the same result for x=pi/2 and x=3*pi/2.
This is what I want to avoid, in this case I would want it to calculate for x=3*pi/2 the value 3*pi/2 (I know that for c=1 atan and tan would cancel out, but for arbitrary real c they do not).
In other words, I want to make atan(c*tan(x)) continuous on R in x.
How I tried to fix it:
I simply added a function that kept an eye on the argument of the tangens:
atan(c*tan(x))+pi.*(floor((x./pi)+(1/2)))
This works for values that are not too near to the poles of the tangent function, but once x lies !very! near it breaks down (jumps of heigh pi are observed). This is especially a problem for my calculations as x is near enough one of the poles all the time.
What still seems to be the problem:
Imho the problem is that the tangens has a "much higher resolution" near its poles than the "floor function" making its jump too early/late for the correcting function.
My question:
Is there another possibility to fix this problem that is not sensitive to x lying near the poles of the tangent ?
There are multiple possible solutions for this problem. A simple one would be to use a special case for x near pi + k*pi/2, letting atan(c*tan(x)) = +- pi/2 depending on whether x is slightly smaller, or slightly larger, than pi/2 respectively.
function Out = ContTangents(In,RidgeParam)
InOverPi = In./pi;
Rounded = round(InOverPi);
CloseRounded = round(InOverPi+1/2)-1/2;
ArctanResult = zeros(size(In));
IsCloseVal = abs(InOverPi - CloseRounded) < 0.00001;
CloseVal = sign(RidgeParam*(CloseRounded-InOverPi)) * pi/2;
NotCloseVal = atan(RidgeParam*tan(In));
ArctanResult(IsCloseVal) = CloseVal(IsCloseVal);
ArctanResult(~IsCloseVal) = NotCloseVal(~IsCloseVal);
Out = ArctanResult + pi*(Rounded + 1/2);
This solution appears to produce nice-looking curves, and as far as I can see it avoids discontinuities and singularities. At least, it seems nice when I run
figure, plot(ContTangents(-10:.001*pi:10,2))
Edit: Some parts of the function are modified. When running ContTangents(pi/2-exp(-36),2) (the problem value in the OP's example below), I found this very peculiar behavior. Is this a bug in Matlab?
K>> InOverPi<0.5
ans =
1
K>> round(InOverPi)
ans =
1
This could be worked around through redefining an own round function which doesn't fail at the point .5-eps(.25). In fact, due to the entertaining behavior of floating point at the limit, you can't even define that number as such, but you have to proceed as follows.
format hex
(pi/2-exp(-36))/pi
ans =
3fdfffffffffffff
-eps(.25)+.25+.25
ans =
3fdfffffffffffff

MATLAB - singularity warning [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
when my matlab code gets to the line:
vE(:,:,i)=(mY(:,:,i))\(-mA*(vIs-mG(:,:,i)*vVs));
The following warning comes up:
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate.
RCOND = 1.682710e-16.
Whats wrong?
Full code:
function [ vE, vV_node, vI_node ] = ...
node_analysis( vIs, vVs, mA, mG, mY )
[A,B,N]=size(mY);
vE=zeros(4,1,N);
for i=1:N
vE(:,:,i)=(mY(:,:,i))\(-mA*(vIs-mG(:,:,i)*vVs));
vV_node(:,:,i)=mA'*vE(:,:,i);
vI_node(:,:,i)=mG(:,:,i)*vV_node(:,:,i)+(vIs-mG(:,:,i)*vVs);
end
end
vE=mY^-1 * (-mA*(cIs-mG*vVs))
vE is (4x1xN) size
mY(4x4xN)
mA(4x9)
vIs(9x1)
mG(9x9xN)
vVs(9x1)
When you use the \ operator with a matrix, MATLAB will try and solve the least squares problem to estimate x given y in the equation y = A*x. Depending on the size and shape of A, solving this equation might be easy, hard, or impossible without additional information. It just depends on your particular problem.
As Oli mentioned the comments, this is because your matrix is close to singular or its singular values are close to zero. MATLAB is properly informing you that the MATRIX likely has either unknown information that is going to screw up the answer or that some of the information in the MATRIX is so small compared to other pieces that the small part is going to make solving for x almost impossible and error prone.
Depending on your math background, you might consider the following cod where I create create a matrix with one value very small. This will reproduce your error:
%% Make some data:
randn('seed', 1982);
n = 3;
A = zeros(n);
for ind = 1:n-1
v = randn(n,1);
A = A + v*v';
end
% Last bit is very tiny compared to the others:
A = A + 1e-14*randn(n,1)*randn(1,n);
%% Try and solve Ax=y for x= 1,2,3...
x = (1:n)';
y = A*x
x_est = A \ y
There are various ways to start trying to fix this, usually by reformulating the problem and/or adding some kind of regularization term. A good first try, though, is so add a simple Tikhonov regularization which bumps up all the small values to something reasonable that MATLAB can work with. This may mess up your data but you can plat with it.
Roughly, try this:
tikk = 1e-12;
x_est2 = (A + tikk * eye(n)) \ y
For larger or smaller values of tikk and you will see the error goes away but the solution is to some degree wrong. You might find this acceptable or not.
Note that in my example the answer is quite wrong because I used n=3. As you increase the problem size n you will be better results.
Finally, to begin exploring what is wrong with your matrix A ((-mA*(vIs-mG(:,:,i)*vVs))), you might consider seeing how fast the values s in s=svd(A) decay. Some of them should be quite close to zero. Also, you might look at Tihkonov regularization and what you can do by actually decomposing the matrix into the SVD and scaling things better.

GUI solving equations project

I have a Matlab project in which I need to make a GUI that receives two mathematical functions from the user. I then need to find their intersection point, and then plot the two functions.
So, I have several questions:
Do you know of any algorithm I can use to find the intersection point? Of course I prefer one to which I can already find a Matlab code for in the internet. Also, I prefer it wouldn't be the Newton-Raphson method.
I should point out I'm not allowed to use built in Matlab functions.
I'm having trouble plotting the functions. What I basically did is this:
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
cla % To clear axes when plotting new functions
ezplot(fun_f);
hold on
ezplot(fun_g);
axis ([-20 20 -10 10]);
The problem is that sometimes, the axes limits do not allow me to see the other function. This will happen, if, for example, I will have one function as log10(x) and the other as y=1, the y=1 will not be shown.
I have already tried using all the axis commands but to no avail. If I set the limits myself, the functions only exist in certain limits. I have no idea why.
3 . How do I display numbers in a static text? Or better yet, string with numbers?
I want to display something like x0 = [root1]; x1 = [root2]. The only solution I found was turning the roots I found into strings but I prefer not to.
As for the equation solver, this is the code I have so far. I know it is very amateurish but it seemed like the most "intuitive" way. Also keep in mind it is very very not finished (for example, it will show me only two solutions, I'm not so sure how to display multiple roots in one static text as they are strings, hence question #3).
function [Sol] = SolveEquation(handles)
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
f = inline(fun_f);
g = inline(fun_g);
i = 1;
Sol = 0;
for x = -10:0.1:10;
if (g(x) - f(x)) >= 0 && (g(x) - f(x)) < 0.01
Sol(i) = x;
i = i + 1;
end
end
solution1 = num2str(Sol(1));
solution2 = num2str(Sol(2));
set(handles.roots1,'string',solution1);
set(handles.roots2,'string',solution2);
The if condition is because the subtraction will never give me an absolute zero, and this seems to somewhat solve it, though it's really not perfect, sometimes it will give me more than two very similar solutions (e.g 1.9 and 2).
The range of x is arbitrary, chosen by me.
I know this is a long question, so I really appreciate your patience.
Thank you very much in advance!
Question 1
I think this is a more robust method for finding the roots given data at discrete points. Looking for when the difference between the functions changes sign, which corresponds to them crossing over.
S=sign(g(x)-f(x));
h=find(diff(S)~=0)
Sol=x(h);
If you can evaluate the function wherever you want there are more methods you can use, but it depends on the size of the domain and the accuracy you want as to what is best. For example, if you don't need a great deal of accurac, your f and g functions are simple to calculate, and you can't or don't want to use derivatives, you can get a more accurate root using the same idea as the first code snippet, but do it iteratively:
G=inline('sin(x)');
F=inline('1');
g=vectorize(G);
f=vectorize(F);
tol=1e-9;
tic()
x = -2*pi:.001:pi;
S=sign(g(x)-f(x));
h=find(diff(S)~=0); % Find where two lines cross over
Sol=zeros(size(h));
Err=zeros(size(h));
if ~isempty(h) % There are some cross-over points
for i=1:length(h) % For each point, improve the approximation
xN=x(h(i):h(i)+1);
err=1;
while(abs(err)>tol) % Iteratively improve aproximation
S=sign(g(xN)-f(xN));
hF=find(diff(S)~=0);
xN=xN(hF:hF+1);
[~,I]=min(abs(f(xN)-g(xN)));
xG=xN(I);
err=f(xG)-g(xG);
xN=linspace(xN(1),xN(2),15);
end
Sol(i)=xG;
Err(i)=f(xG)-g(xG);
end
else % No crossover points - lines could meet at tangents
[h,I]=findpeaks(-abs(g(x)-f(x)));
Sol=x(I(abs(f(x(I))-g(x(I)))<1e-5));
Err=f(Sol)-g(Sol)
end
% We also have to check each endpoint
if abs(f(x(end))-g(x(end)))<tol && abs(Sol(end)-x(end))>1e-12
Sol=[Sol x(end)];
Err=[Err g(x(end))-f(x(end))];
end
if abs(f(x(1))-g(x(1)))<tol && abs(Sol(1)-x(1))>1e-12
Sol=[x(1) Sol];
Err=[g(x(1))-f(x(1)) Err];
end
toc()
Sol
Err
This will "zoom" in to the region around each suspected root, and iteratively improve the accuracy. You can tweak the parameters to see whether they give better behaviour (the tolerance tol, the 15, number of new points to generate, could be higher probably).
Question 2
You would probably be best off avoiding ezplot, and using plot, which gives you greater control. You can vectorise inline functions so that you can evaluate them like anonymous functions, as I did in the previous code snippet, using
f=inline('x^2')
F=vectorize(f)
F(1:5)
and this should make plotting much easier:
plot(x,f(x),'b',Sol,f(Sol),'ro',x,g(x),'k',Sol,G(Sol),'ro')
Question 3
I'm not sure why you don't want to display your roots as strings, what's wrong with this:
text(xPos,yPos,['x0=' num2str(Sol(1))]);

Matlab: poor accuracy of optimizers/solvers

I am having difficulty achieving sufficient accuracy in a root-finding problem on Matlab. I have a function, Lik(k), and want to find the value of k where Lik(k)=L0. Basically, the problem is that various built-in Matlab solvers (fzero, fminbnd, fmincon) are not getting as close to the solution as I would like or expect.
Lik() is a user-defined function which involves extensive coding to compute a numerical inverse Laplace transform, etc., and I therefore do not include the full code. However, I have used this function extensively and it appears to work properly. Lik() actually takes several input parameters, but for the current step, all of these are fixed except k. So it is really a one-dimensional root-finding problem.
I want to find the value of k >= 165.95 for which Lik(k)-L0 = 0. Lik(165.95) is less than L0 and I expect Lik(k) to increase monotonically from here. In fact, I can evaluate Lik(k)-L0 in the range of interest and it appears to smoothly cross zero: e.g. Lik(165.95)-L0 = -0.7465, ..., Lik(170.5)-L0 = -0.1594, Lik(171)-L0 = -0.0344, Lik(171.5)-L0 = 0.1015, ... Lik(173)-L0 = 0.5730, ..., Lik(200)-L0 = 19.80. So it appears that the function is behaving nicely.
However, I have tried to "automatically" find the root with several different methods and the accuracy is not as good as I would expect...
Using fzero(#(k) Lik(k)-L0): If constrained to the interval (165.95,173), fzero returns k=170.96 with Lik(k)-L0=-0.045. Okay, although not great. And for practical purposes, I would not know such a precise upper bound without a lot of manual trial and error. If I use the interval (165.95,200), fzero returns k=167.19 where Lik(k)-L0 = -0.65, which is rather poor. I have been running these tests with Display set to iter so I can see what's going on, and it appears that fzero hits 167.19 on the 4th iteration and then stays there on the 5th iteration, meaning that the change in k from one iteration to the next is less than TolX (set to 0.001) and thus the procedure ends. The exit flag indicates that it successfully converged to a solution.
I also tried minimizing abs(Lik(k)-L0) using fminbnd (giving upper and lower bounds on k) and fmincon (giving a starting point for k) and ran into similar accuracy issues. In particular, with fmincon one can set both TolX and TolFun, but playing around with these (down to 10^-6, much higher precision than I need) did not make any difference. Confusingly, sometimes the optimizer even finds a k-value on an earlier iteration that is closer to making the objective function zero than the final k-value it returns.
So, it appears that the algorithm is iterating to a certain point, then failing to take any further step of sufficient size to find a better solution. Does anyone know why the algorithm does not take another, larger step? Is there anything I can adjust to change this? (I have looked at the list under optimset but did not come up with anything useful.)
Thanks a lot!
As you seem to have a 'wild' function that does appear to be monotone in the region, a fairly small range of interest, and not a very high requirement in precision I think all criteria are met for recommending the brute force approach.
Assuming it does not take too much time to evaluate the function in a point, please try this:
Find an upperbound xmax and a lower bound xmin, choose a preferred stepsize and evaluate your function at
xmin:stepsize:xmax
If required (and monotonicity really applies) you can get another upper and lower bound by doing this and repeat the process for better accuracy.
I also encountered this problem while using fmincon. Here is how I fixed it.
I needed to find the solution of a function (single variable) within an optimization loop (multiple variables). Because of this, I needed to provide a large interval for the solution of the single variable function. The problem is that fmincon (or fzero) does not converge to a solution if the search interval is too large. To get past this, I solve the problem inside a while loop, with a huge starting upperbound (1e200) with the constraint made on the fval value resulting from the solver. If the resulting fval is not small enough, I decrease the upperbound by a factor. The code looks something like this:
fval = 1;
factor = 1;
while fval>1e-7
UB = factor*1e200;
[x,fval,exitflag] = fminbnd(#(x)function(x,...),LB,UB,options);
factor = factor * 0.001;
end
The solver exits the while when a good solution is found. You can of course play also with the LB by introducing another factor and/or increase the factor step.
My 1st language isn't English so I apologize for any mistakes made.
Cheers,
Cristian
Why not use a simple bisection method? You always evaluate the middle of a certain interval and then reduce this to the right or left part so that you always have one bound giving a negative and the other bound giving a positive value. You can reduce to arbitrary precision very quickly. Since you reduce the interval in half each time it should converge very quickly.
I would suspect however there is some other problem with that function in that it has discontinuities. It seems strange that fzero would work so badly. It's a deterministic function right?