How to numerically differentiate a set of unevenly time spaced quaternions in MATLAB - matlab

I have the time evolution (unevenly spaced) of around 1000 quaternions which provides the transformation from an inertial coordinate system to a body fixed. My goal is to obtain the angular velocity of the body, so for that I need the derivative of the quaternion (or at least I think so), and I am having trouble to obtain it.
So far I have tried first to use the gradient function
time_grad = gradient(time);
dquat(1,:) = gradient(quat(1,:)) ./ (time_grad);
dquat(2,:) = gradient(quat(2,:)) ./ (time_grad);
dquat(3,:) = gradient(quat(3,:)) ./ (time_grad);
dquat(4,:) = gradient(quat(4,:)) ./ (time_grad);
I have also tried using a Fornberg algorithm I found online, but I think I am not obtaining good results based on the final outcome (some computations using the angular velocity which should result in something very similar to some information I already have).
These quaternions could be easily converted to Direction Cosine Matrices if you know a better method to calculate angular velocity based on DCMs.

Related

cftool not fitting on custom fit

I'm trying to do a fit on cftool for a basic oscillator. The problem is that Matlab won't make a fit; it keeps drawing a straight line. I've been experimenting with the starting points and limits, but to no avail.
The problem is probably something trivial, but I can't figure out the problem.
Current fit:
You are using custom equation y = f(x) = a * exp(-b*x) * sin(dx+e) + c.
Matlab understands dx inside the sin above as a constant coefficient, so you have the sin of a constant, which is a constant number itself.
cftool is left then trying to approximate a sinusoidal motion with f(x), which at this point is a custom exponential function of the type const * exp(-const * x) + const, so the best it can do is to yield the mean value, that is, ~0.176.
In order to correct this, just substitute d*x for dx inside the sin in your custom function.
In addition to the pertinent answer from Lingo.
In practical use of non-linear regression sofware, a frequent cause of failure or of not good convergence is the initial setting of values of the parameters. The values of parameters given below would be very good to start a non-linear regression calculus.
Those values are probably more or less biaised because the data was not available on numerical form but only from the graph provided by the OP. "Substitue" data was obtained from scanning the graph. This isn't an accurate way.
NOTE : The linearised regression method used to compute the above approximate values is explained in https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales

Differentiating a Centred and Scaled Polyfit Fit

I have some data which I wish to model in order to be able to get relatively accurate values in the same range as the data.
To do this I used polyfit to fit a 6th order polynomial and due to my x-axis values it suggested I centred and scaled it to get a more accurate fit which I did.
However, now I want to find the derivative of this function in order to model the velocity of my model.
But I am not sure how the polyder function interacts with the scaled and fitted polyfit which I have produced. (I don't want to use the unscaled model as this is not very accurate).
Here is some code which reproduces my problem. I attempted to rescale the x values before putting them into the fit for the derivative but this still did no fix the problem.
x = 0:100;
y = 2*x.^2 + x + 1;
Fit = polyfit(x,y,2);
[ScaledFit,s,mu] = polyfit(x,y,2);
Deriv = polyder(Fit);
ScaledDeriv = polyder(ScaledFit);
plot(x,polyval(Deriv,x),'b.');
hold on
plot(x,polyval(ScaledDeriv,(x-mu(1))/mu(2)),'r.');
Here I have chosen a simple polynomial so that I could fit it accurate and produce the actual derivative.
Any help would be greatly appreciated thanks.
I am using Matlab R2014a BTW.
Edit.
Just been playing about with it and by dividing the resulting points for the differential by the standard deviation mu(2) it gave a very close result within the range -3e-13 to about 5e-13.
polyval(ScaledDeriv,(x-mu(1))/mu(2))/mu(2);
Not sure quite why this is the case, is there another more elegant way to solve this?
Edit2. Sorry for another edit but again was mucking around and found that for a large sample x = 1:1000; the deviation became much bigger up to 10. I am not sure if this is due to a bad polyfit even though it is centred and scaled or due to the funny way the derivative is plotted.
Thanks for your time
A simple application of the chain rule gives
Since by definition
it follows that
Which is exactly what you have verified numerically.
The lack of accuracy for large samples is due to the global, rather then local, Lagrange polynomial interpolation which you have done. I would suggest that you try to fit your data with splines, and obtain the derivative with fnder(). Another option is to apply the polyfit() function locally, i.e. to a moving small set of points, and then apply polyder() to all the fitted polynomials.

How long does it take for a curve too reach a specific x coordinate?

How do I calculate the time it takes for a curve to reach a specific x coordinate (in Matlab). Let's say we have:
dx/dt = x^2 + y^2 and dy/dt = 5.x.y and the curve starts at the point (a,b). With help from ode45 I was able to get the figure of the curve. I need too calculate the time it takes for the curve too reach x = c, (c>a). I've been told that this can be done by interpolation, but I have no idea how to write the code.
Depending on the behavior of your system around c, using data interpolation methods such as interp1 on the output may or may not work. The more rigorous way to solve this is either with events (see my answers here or here) or by using the single structure output argument form of ode45 in conjunction with deval and regular data interpolation methods. Both of these use polynomial interpolation methods designed to work with the underlying ODEs. Though more complicated, events are probably the best way to accuratly determine crossing times like your case.

Programming a 3 Body Problem using matlab

I am trying to program a 3 body problem using matlab. I was given the formula for the moon's trajectory in its rotational frame in space. It's basically the ydotdot, xdotdot=GM/(x^2+y^2)^3/2 formula. What the formula is, is not that important.
THe problem I am facing is that, I am supposed to code up a program that will numerically solve the moon's trajectory equation. I'm using ODE45 to compare with since my goal is to get the same results as ODE45. My ultimate problem is that, I want to iterate through time in terms of days so tspan= [0 365]. The thins is when I convert Gravitational constant to seconds and then do tspace= [0 365] I get a completely different result then If I were to do [0 365*3600*34] representing the seconds in a year and G= 6.67e-11. It seems that my units are very weird.
I was wondering if anyone can explain why this is happening when I use ODE 45. Why can't I convert seconds to days clearly using ODE45? Is there an extra step I have to do? The only other variables in my problem is radius, distance, and the mass of the 3 bodies.
Thank you so much. I've been working on this for a very very long time. Any help would be much appreciated.
That formula for gravitational acceleration along each axis isn't correct.
Put the earth, with mass M_e, at the origin, with the moon (mass M_m) at (x,y). Then
the earth-moon distance is given by:
R_em = sqrt(x^2 + y^2)
The total earth-moon force is given by:
F_em = G*M_e*M_m/R_em^2
The total acceleration due to Earth's gravity is given by:
a_em = F_em/M_m = G*M_e/R_em^2
and is directed toward the origin. The acceleration along
each axis is then:
xdotdot = -F_em*cos(theta) = -F_em*x/R_em = -G*M_e*x/R_em^(3/2)
ydotdot = -F_em*sin(theta) = -F_em*y/R_em = -G*M_e*y/R_em^(3/2)
Note the x and y factors, which are missing from the formula you stated.
I'm not sure what you mean by "converting the gravitational constant to seconds".
The value you're using for G has units of newton-meter^2/kg^2. So it's already
expressed in the MKS (meter-kilogram-second) system, and the accelerations calculated
using this value will have units of meters/sec^2.
With a third body (say, the sun) at (x_s, y_s), you compute a new R_s representing
the moon-sun distance, and compute new acceleration vectors as above, using the
sun's mass M_s (except the acceleration is now in the direction of (x_s, y_s), rather than (0,0)). The accelerations of the moon from the gravity of the earth and the sun just add component-wise, once everything is put into a common coordinate system (here,
geocentric coordinates -- although heliocentric might be a more convenient choice, if you're simulating the sun-earth-moon system). That, plus the initial positions and velocities, should be all you need to compute the positions and velocities at the next time step.

MATLAB's fminsearch function

I have two images I'm trying to co-register - ie, one could be of a ball in the centre of the picture, the other is of the same ball near the edge and I'm trying to find the numbed of pixels I have to move the second image so that the balls would be in the same place. (I'm actually using 3D MRI brain scans, but the principle is the same).
I've written a function that will move the ball left, right, up or down by a given number of pixels as well as another function that compares the correlation of the ball-in-the-centre image with the translated ball-at-the-edge image. When the two balls are in the same place the correlation function will return 0 and a number larger than 0 for other positions.
I'm trying to use fminsearch (documentation) to find the optimal translation for the correlation function's minimum (ie, the balls being in the same place) like so:
global reference_im unknown_im;
starting_trans = [0 0 0];
trans_vector = fminsearch(#correlate_images,starting_trans)
correlate_images.m:
function r = correlate_images(translate)
global reference_im unknown_im;
new_im = move_image(unknown_im,translate(1),translate(2),translate(3));
% This bit is unimportant to the question
% but you can see how I calculate my correlation
r = 1 - corr(reshape(new_im,[],1),reshape(reference_im,[],1));
There are two problems, firstly fminsearch insists on passing float values for the translation vector into the correlate_images function. Is there any way to inform it that only integers are necessary? (I would save a large number of cpu cycles!)
Secondly, when I run this program the resulting trans_vector is always the same as starting_trans - I assume this is because no minimum has been found, but is there another reason its just plain not working?
Many thanks!
EDIT
I've discovered what I think is the reason the output trans_vector is always the same as starting_trans. The fminsearch looks at the starting value, then a small increment in each direction from there, this small increment is always less than one, which means that the result from the correlation will be a perfect match (as the move_image will return the same as the input image for sub-pixel movements). I'm going to continue working on convincing matlab to only fminsearch over integer values!
First, I'd say that Matlab might not be the best tool for this problem. I'd look at Elastix, which is a pretty user-friendly wrapper around the registration functions in ITK. You get a variety of registration techniques, and the manuals for both programs do a good job of explaining the specifics of image registration.
Second, for this kind of simple translational registration, you can use the FFT. Forward transform both images, multiply the images together (pointwise! That is, use A .* B, not A * B, as those are different operations, and the first is what you want), and there should be a peak in the inverse transform whose offset from the origin is the translational amount you need. Numerical Recipes in C has a good explanation; here's a link to an index pdf. The speed difference between the FFT version and the direct correlation version is huge; the FFT is O(N log N), while the correlation method will be O (N * M), where M is the number of pixels in your search neighborhood. If you want to allow the entire image to be searched, then correlation becomes O (N*N), which will take much longer than the FFT version. Changing parameters from floats to integers won't solve the problem.
The reason the fminsearch function uses floats (if I can guess at the reasons behind the coders' decisions) is that for problems that aren't test problems (ie, spheres in a volume), you often need sub-pixel resolution to perform a correct registration. Take a look at the ITK documentation about the reasons behind this approach.
Third, I'd suggest that a good way to write this program in Matlab (if you still want to do so!) while still forcing integer correlations would be to avoid the fminsearch function, which will want to use floats. Try something like:
startXPos = -10; %these parameters dictate the size of your search neighborhood
startYPos = -10; %corresponds to M in the above explanation
endXPos = 10;
endYPos = 10;
optimalX = 0;
optimalY = 0;
maxCorrVal = 0;
for i=startXPos:endXPos
for j = startYPos:endYPos
%test the correlation of the two images here, where one image is shifted to another
currCorrVal = Correlate(image1, image2OffsetByiAndj);
if (currCorrVal > maxCorrVal)
maxCorrVal = currCorrVal;
optimalX = i;
optimalY = j;
end
end
end
From here, you just have to write the offset function. This way, you avoid the float problem, and you're also incrementing your translation vector (I don't see any way for that vector to move in your provided functions, which probably explains your lack of movement).
There is a very similar demo in the Image Processing Toolbox that uses the normalized cross-correlation function normxcorr2 to perform image registration. To avoid repeating the same thing, check out the demo directly:
Registering an Image Using Normalized Cross-Correlation