Mathematica 8: Convert from cartesian to spherical coordinates - math

I just started using Mathematica and came across a problem. I would like to solve more elegantly. I have measurement data in {x,y,z} form and want to transform these into sperical coordinates. I know how to do it using simple functions. But the code gets ugly.
I would like something like:
v={x,y,z}
TranformSpherical[v]
I have looked in the documentation and only found something for version 9, I am using 8 and it did not work when I tried it. Also I have not found a clear solution anywhere else. Hope someone here knows a simple solution to the probem.

The equations are given on Wikipedia and are simple function evaluations.
What's stopping you from simply computing them, and how does it get ugly?
Make sure to use ArcTan[x, y] in Mathematica, which computes the four-quadrant arctangent. For more information see the article about atan2.

In version 9
CoordinateTransformData["Cartesian" -> "Spherical", "Mapping", {x, y, z}]
gives you
{Sqrt[x^2 + y^2 + z^2], ArcTan[z, Sqrt[x^2 + y^2]], ArcTan[x, y]}
which expresses the three spherical coordinates in terms of {x,y,z}
CoordinateTransform["Cartesian" -> "Spherical", {x, y, z}]
will give you the same thing, but can also be used for conversion.
If you have a list {{x0,y0,z0},{x1,y1,z1},...} of Cartesian coordinates, you can apply CoordinateTransform like this
cartesianList = RandomReal[{0, 1}, {4, 3}];
CoordinateTransform["Cartesian" -> "Spherical", #] & /# cartesianList
In earlier versions
<< Calculus`VectorAnalysis`
SetCoordinates[Spherical]
There is a notebook at the mathworld.wolfram.com site page for Spherical Coordinates. Close to the beginning is an example for what you are doing.

Related

Get the trajectory of the rocket

I need to mathematically (or otherwise) get the 3D trajectory of the rocket. I have several variables: starting position, landing position, maximum altitude, flight angle. Here is a demo:
And yes, I don't use any popular game engine, I use the Lua language, on the MTA engine (MultiTheftAuto GTA SA). I want to get this trajectory mathematically. I need a set of points. Or if you are familiar with this engine, explain to me how to implement such a flight in the MTA. But you can also show me how this problem can be solved mathematically, or in any other languages ​​and even using the built-in functions of these engines, I will convert the code for Lua and find the implementation of your engine functions on the Internet. Thank you!
EDIT
And yes, I need to change exactly the Y coordinate (height) I have X and Z. I have a loop that every meter of the current trajectory goes through, in this cycle I have a variable X and Z , and I need to get Y based on these variables .
// float x = 0.0 - 1.0
y = sin(x * pi) ^ 0.6

Octave division of a binomial breaks plot

I am not sure if this is the correct stack exchange for this question. I normally use javascript and a canvas to graph an equation. I am trying out Octave. I am having trouble getting any function with the same variable on both sides of a division to render. Test equation:
x=0:1:512;
Vr=x/100;
clf;
plot((50*Vr.^2-200*Vr)/(Vr-3), 'k-', 'linewidth', 3.0);
axis([0 512 -256 256]);
It works just fine without the division:
plot((50*Vr.^2-200*Vr), 'k-', 'linewidth', 3.0);
Screenscrapes: https://imgur.com/a/nWkXstX
The third is the equation with the division rendered with javascript.
Does octave not support this rather basic arithmetic, or is there a syntax eccentricity that I'm missing?
As much as I hate to be the guy who answers his own question, I found the answer in octave's docs.
https://octave.org/doc/v4.2.1/Arithmetic-Ops.html
'/' Multiplies the left by the inverse of the right. Seemed right, as the opposite of the (Vr/3) sounds like what I wanted, until I read on. './' is "Element-by-element right division." So the plot function treats Vr as a matrix of all the coordinates and computes a matrix with one equation. That was not clear in any of the documentation I read. Seriously, this should have been in the top level help section.
So "syntax eccentricity" it is. The correct syntax for octave is:
plot((50*Vr.^2-200*Vr)./(Vr-3), 'k-', 'linewidth', 3.0)
This works. I think I'll stick to JS though, if only to avoid needing to transform my equations to and from octave's weird syntax. Still, it's nice to have a non-browser-dependent option handy, however eccentric.

Quaternion Component Interpolation

Im trying to optimize my skeletal animation system by using tracks (curve) instead of keyframe. Each curve take care of a specific component then (for now) I linearly interpolate the values. Work fine for my bone positions, however Im having a hard time getting rid of the "jagyness" of the quaternion component interpolation...
Basically I have 1 curve for each component (XY and Z) for each bones quaternion and I use the following code to interpolate the XY and Z curves independently:
// Simple lerp... (f is always a value between 0.0f and 1.0f)
return ( curve->data_array[ currentframe ].value * ( 1.0f - f ) ) +
( curve->data_array[ nextframe ].value * f );
When I interpolate the quaternion XYZ then I use the following code to rebuild the W component of the quaternion before normalizing it and affecting it to my bone before drawing:
Quaternion QuaternionW( const Quaternion q )
{
Quaternion t = { q.x, q.y, q.z };
float l = 1.0f - ( q.x * q.x ) - ( q.y * q.y ) - ( q.z * q.z );
t.w = ( l < 0.0f ) ? 0.0f : -sqrtf( l );
return t;
}
The drawing look fine at the exception that the bones become all jerky from time to time, would it be due to the floating point precision? Or the recalculation of the W component? Or there is absolutely no way I can linearly interpolate each component of a quaternion this way?
ps: On a side note, in my curve interpolation function if I replace the code above with:
return curve->data_array[ currentframe ].value;
instead or linearly interpolating, everything is fine... So the data is obviously correct... Im puzzled...
[ EDIT ]
After more research I found that the problem comes from the frame data... I got i.e. the following:
Frame0:
quat.x = 0.950497
Frame1:
quat.x = -0.952190
Frame2:
quat.x = 0.953192
This is what causes the inversion and jaggyness... I tried to detect this case and inverse the sign of the data but it still doesn't fix the problem fully as some frame now simply look weird (visually when drawing).
Any ideas how to properly fix the curves?
Your data are probably not wrong. Quaternion representations of orientation have the funny property of being 2x redundant. If you negate all four elements of a quaternion, you're left with the same orientation. It's easy to see this if you think of the quaternion as an axis/angle representation: Rotating by Θ around axis a, is the same as rotating by -Θ around axis -a.
So what should you do about it? As mentioned before, slerp is the right thing to do. Quaternion orientations exist on the unit hypersphere. If you linearly interpolate between points on a sphere, you leave the sphere. However, if the points are close by each other, it's often not a big deal (although you should still renormalize afterward). What you absolutely do need to make sure you do is check the inner-product of your two quaternions before interpolating them: e.g.,
k=q0[0]*q1[0] + q0[1]*q1[1] + q0[2]*q1[2] + q0[3]*q1[3];
If k<0, negate one of the quaternions: for (ii=0;ii<4;++ii) q1[ii]=-q1[ii]; This makes sure that you're not trying to interpolate the long way around the circle. This does mean, however, that you have to treat the quaternions as a whole, not in parts. Completely throwing away one component is particularly problematic because you need its sign to keep the quaternion from being ambiguous.
Naive considerations
Linear interpolation is fine for things that operate additively, i.e. that add something to something else every time you execute the corresponding operation. Queternions, however, are multiplicative: you multiply them to chain them.
For this reason, I originally suggested computing the following:
pow(secondQuaternion, f)*pow(firstQuaternion, 1. - f)
Wikipedia has a section on computing powers of quaternions, among other things. As your comment below states that this does not work, the above is for reference only.
Proper interpolation
Since writing this post, I've read a bit more about slerp (spherical linear interpolation) and found that wikipedia has a section on quaternion slerp. Your comment above suggests that the term is already familiar to you. The formula is a bit more complicated than what I wrote above, but it is still rather related due to the way it uses powers. I guess you'd do best by adapting or porting an available implementatin of that formula. This page for example comes with a bit of code.
Fixing data
As to your updated question
Any ideas how to properly fix the curves?
Fixing errors while maintaining correct data requires some idea of what kinds of errors do occur. So I'd start by trying to locate the source of that error, if at all possible. If that can be fixed to generate correct data, then good. If not, it should still give you a better idea of what to expect, and when.

Elliptical Arc Length

Given a point P on a 'canonical' ellipse defined by axes a, b, and an arc length s, how can I find a point Q, also on the ellipse, that is s clockwise along the elliptical curve from P — such that if I were to start at P and 'walk along' the elliptical curve for a distance of s, I would reach Q — programatically and without breaking the computational bank?
I have heard that this can be computed through some sort of elliptical integration, but I need to do this a bunch, and quickly. What I'm looking for is an easy to use, computationally inexpensive, and fairly accurate approximation method. Or at least a method that is one or two of those things. I will be implementing this in python.
Edit: alternatively, I might be forced to create a lookup table of position values around ellipses (I might only need in the 10s of dissimilar ellipses). How should I do this, and what method can I use to fill it?
You'll need to integrate the ellipse equation. It's not difficult, actually.
Take a look at the equations here:
Link
Since you're using python, the Runge-Kutta for integration is implemented in Python here (I don't know the license, though):
http://doswa.com/blog/2009/04/21/improved-rk4-implementation/
Just on step 3 and 4 of mathforum solution you already have a value for ds (the arc lenght) and you want dx.
After finding dx, use step 6 to find y.
You could use scipy.special.ellipeinc to calculate the arclengths. (More details are given by Roger Stafford here.)
If that isn't fast enough, you could wrap the arclength calculation in a function and use a memoize decorator to cache the result of previous (arclength) function calls.
Or, as you've mentioned, you could pre-calculate the values you need, and store them in a dict.
In order to solve the problems you need a conjeture:there is a circle in unit elipse
a=1, that it has the same perimeter han the elipse. That perim is 2πrp.your. perimeter is then P=2πrp x a

How to interpolate rotations?

I have two vectors describing rotations; a start rotation A and a target rotation B. How would I best go about interpolating A by a factor F to approach B?
Using a simple lerp on the vectors fails to work when more than one dimension needs to be interpolated (i.e. produces undesirable rotations). Maybe building quaternions from the rotation vectors and using slerp is the way to go. But how, then, could I extract a vector describing the new rotation from the resulting quaternion?
Thanks in advance.
Since I don't seem to understand your question, here is a little SLERP implementation in python using numpy. I plotted the results using matplotlib (v.99 for Axes3D).
I don't know if you can use python, but does look like your SLERP implementation? It seems to me to give fine results ...
from numpy import *
from numpy.linalg import norm
def slerp(p0, p1, t):
omega = arccos(dot(p0/norm(p0), p1/norm(p1)))
so = sin(omega)
return sin((1.0-t)*omega) / so * p0 + sin(t*omega)/so * p1
# test code
if __name__ == '__main__':
pA = array([-2.0, 0.0, 2.0])
pB = array([0.0, 2.0, -2.0])
ps = array([slerp(pA, pB, t) for t in arange(0.0, 1.0, 0.01)])
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
f = figure()
ax = Axes3D(f)
ax.plot3D(ps[:,0], ps[:,1], ps[:,2], '.')
show()
A simple LERP (and renormalizing) only works fine when the vectors are very close together, but will result in unwanted results when the vectors are further apart.
There are two options:
Simple cross-products:
Determine the axis n that is orthogonal to both A and B using a cross product (take care when the vectors are aligned) and calculate the angle a between A and B using a dot product. Now you can simply approach B by letting a go from 0 to a (this will be aNew and applying the rotation of aNew about axis n on A.
Quaternions:
Calculate the quaternion q that moves A to B, and interpolate q with the identity quaternion I using SLERP. The resulting quaternion qNew can then be applied on A.
Well, your slerp approach would work and is probably computationally most efficient (even though it's a bit tough to understand). To get back from the quaternions to the vector, you'll need to use a set of formulas you can find here.
There's also a bit of relevant code here, although I don't know if it corresponds to the way you have your data represented.
If you have decided to go with Quaternions (which will slerp very nicely), see my answer here on resources for implementing Quaternions:
Rotating in OpenGL relative to the viewport
You should find plenty of examples in the links in that post.

Resources